From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg0-x243.google.com (mail-pg0-x243.google.com [IPv6:2607:f8b0:400e:c05::243]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 2CF42208F7A03 for ; Wed, 29 Mar 2017 00:50:34 -0700 (PDT) Received: by mail-pg0-x243.google.com with SMTP id 79so1680686pgf.0 for ; Wed, 29 Mar 2017 00:50:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=philjordan-eu.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=jqcT2uI0HPi3g0jvuJ/ZdE1vZ7lFQ42R30aqnBhVOKw=; b=sOBzj8AE9Tmqq2bNlu+gnDTyR8Pcvu3m+SrrU+HdOABwDWDvJyflVLO9ZPbkV7b2z3 hBjwmoGmi6LS3QxtdRf8nFaC4/UoRtYGHKCv9Tx6LGI44fgJUr2r92ZExisKJ+TgcLga j5AxgrDP26ZblrBjj4Qs/w2gbSbF9B8Fhy070qlPdoDTAKiEh+y2lJNn6Mfp0bg3u21Q 4tcGRKaFo83D/vfAzbIOwEbE8GHDuUlHS52m/ZWqHhqGClPUTyYTKjFHXLLmtHHEwl1p Hf1PRzSgOuXpDOxfjmElCc/vOnCuGaUc7AW4nnqyedIRTHYHRJNjfsxFtvJcHO6xYDwn e3bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jqcT2uI0HPi3g0jvuJ/ZdE1vZ7lFQ42R30aqnBhVOKw=; b=b7vvRAPnxPTsGMlE9z4xMNsyPLxp7CpUyOWwBYA+/q5riv5hBDX54clrCEfjNe2Bot MvHx72NMs6QDFkT+eORAeBE9nvfNNkLyPDQ4O4ZVcJxfqPj1Cn8KmHh9a8r/qjPf2yu1 +0nsx0yXxCXI+wnjXPf1M8E5BrN9Wd+5pecytAsQ8s9+d/DQaJl7vDm/JLO70TnooJ5E u5S6wadnxi/UesCjSedAstWxTeXSZrQZE5j8w+L9uRumm9Wg+RzrS+L+Mw6guSVm7Dex GxUZFH762xO4U6jjvqGodM/CJhDSh25BPDv6O3xEZT0Llupz/3uUgDOS6KBd+CXVIqgF yAew== X-Gm-Message-State: AFeK/H0s8V/ozNuU4ez9i2z6shezPmMay6/fK4KqfQhGXqY+I5HNqs7746iBl0kn1sUTBQ== X-Received: by 10.99.224.69 with SMTP id n5mr33778807pgj.113.1490773833711; Wed, 29 Mar 2017 00:50:33 -0700 (PDT) Received: from localhost.localdomain ([118.82.182.58]) by smtp.gmail.com with ESMTPSA id q23sm11629946pfg.63.2017.03.29.00.50.29 (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 29 Mar 2017 00:50:33 -0700 (PDT) From: Phil Dennis-Jordan To: edk2-devel@lists.01.org Cc: Phil Dennis-Jordan Date: Wed, 29 Mar 2017 20:50:12 +1300 Message-Id: <1490773812-23839-2-git-send-email-lists@philjordan.eu> X-Mailer: git-send-email 2.3.2 (Apple Git-55) In-Reply-To: <1490773812-23839-1-git-send-email-lists@philjordan.eu> References: <1490773812-23839-1-git-send-email-lists@philjordan.eu> Subject: [PATCH v1 1/1] OvmfPkg: Allow multiple add-pointer linker commands to same ACPI table X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Mar 2017 07:50:34 -0000 From: Phil Dennis-Jordan ACPI tables may contain multiple pointer fields to the same destination table. For example, in some revisions, the FADT contains both DSDT and X_DSDT fields, and they may both point to the DSDT. Indeed, some operating systems demand this to be the case. Previously, if Qemu created "add pointer" linker commands for both fields, the linking process would fail, as AcpiProtocol->InstallAcpiTable() may only be called once for each destination table and otherwise returns an error. This change adds a memoisation data structure which tracks the table pointers that have already been installed; even if the same pointer is encountered multiple times, it is only installed once. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Phil Dennis-Jordan --- OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c | 109 ++++++++++++++++---- 1 file changed, 89 insertions(+), 20 deletions(-) diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c index 7bb2e3f21821..cffa838623cc 100644 --- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c +++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c @@ -100,6 +100,39 @@ BlobCompare ( /** + Comparator function for two opaque pointers, ordering on pointer value + itself. + Can be used as both Key and UserStruct comparator. + + @param[in] Pointer1 First pointer. + + @param[in] Pointer2 Second pointer. + + @retval <0 If Pointer1 compares less than Pointer2. + + @retval 0 If Pointer1 compares equal to Pointer2. + + @retval >0 If Pointer1 compares greater than Pointer2. +**/ +STATIC +INTN +EFIAPI +PointerCompare ( + IN CONST VOID *Pointer1, + IN CONST VOID *Pointer2 + ) +{ + if (Pointer1 == Pointer2) { + return 0; + } else if ((INTN)Pointer1 < (INTN)Pointer2) { + return -1; + } else { + return 1; + } +} + + +/** Process a QEMU_LOADER_ALLOCATE command. @param[in] Allocate The QEMU_LOADER_ALLOCATE command to process. @@ -535,27 +568,32 @@ UndoCmdWritePointer ( This function assumes that the entire QEMU linker/loader command file has been processed successfully in a prior first pass. - @param[in] AddPointer The QEMU_LOADER_ADD_POINTER command to process. + @param[in] AddPointer The QEMU_LOADER_ADD_POINTER command to process. - @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user - structures. + @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user + structures. - @param[in] AcpiProtocol The ACPI table protocol used to install tables. + @param[in] AcpiProtocol The ACPI table protocol used to install tables. - @param[in,out] InstalledKey On input, an array of INSTALLED_TABLES_MAX UINTN - elements, allocated by the caller. On output, - the function will have stored (appended) the - AcpiProtocol-internal key of the ACPI table that - the function has installed, if the AddPointer - command identified an ACPI table that is - different from RSDT and XSDT. + @param[in,out] InstalledKey On input, an array of INSTALLED_TABLES_MAX UINTN + elements, allocated by the caller. On output, + the function will have stored (appended) the + AcpiProtocol-internal key of the ACPI table that + the function has installed, if the AddPointer + command identified an ACPI table that is + different from RSDT and XSDT. - @param[in,out] NumInstalled On input, the number of entries already used in - InstalledKey; it must be in [0, - INSTALLED_TABLES_MAX] inclusive. On output, the - parameter is incremented if the AddPointer - command identified an ACPI table that is - different from RSDT and XSDT. + @param[in,out] NumInstalled On input, the number of entries already used in + InstalledKey; it must be in [0, + INSTALLED_TABLES_MAX] inclusive. On output, the + parameter is incremented if the AddPointer + command identified an ACPI table that is + different from RSDT and XSDT. + + @param[in,out] InstalledTables The ORDERED_COLLECTION tracking the ACPI tables + which have already been installed. If a new + table is encountered by the function, it is + added; existing ones will not be installed again. @retval EFI_INVALID_PARAMETER NumInstalled was outside the allowed range on input. @@ -584,7 +622,8 @@ Process2ndPassCmdAddPointer ( IN CONST ORDERED_COLLECTION *Tracker, IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, IN OUT UINTN InstalledKey[INSTALLED_TABLES_MAX], - IN OUT INT32 *NumInstalled + IN OUT INT32 *NumInstalled, + IN OUT ORDERED_COLLECTION *InstalledTables ) { CONST ORDERED_COLLECTION_ENTRY *TrackerEntry; @@ -679,6 +718,21 @@ Process2ndPassCmdAddPointer ( return EFI_SUCCESS; } + Status = OrderedCollectionInsert ( + InstalledTables, NULL, (VOID *)(UINTN)PointerValue); + if (EFI_ERROR (Status)) { + if (Status == RETURN_ALREADY_STARTED) { + // + // Already installed this table, don't try to do so again. + // + DEBUG ((DEBUG_VERBOSE, "%a: AcpiProtocol->InstallAcpiTable reports table " + "already installed, skipping. PointerValue=0x%Lx\n", + __FUNCTION__, PointerValue)); + Status = EFI_SUCCESS; + } + return Status; + } + if (*NumInstalled == INSTALLED_TABLES_MAX) { DEBUG ((EFI_D_ERROR, "%a: can't install more than %d tables\n", __FUNCTION__, INSTALLED_TABLES_MAX)); @@ -739,6 +793,8 @@ InstallQemuFwCfgTables ( UINTN *InstalledKey; INT32 Installed; ORDERED_COLLECTION_ENTRY *TrackerEntry, *TrackerEntry2; + ORDERED_COLLECTION *InstalledTables; + ORDERED_COLLECTION_ENTRY *InstalledTableEntry; Status = QemuFwCfgFindFile ("etc/table-loader", &FwCfgItem, &FwCfgSize); if (EFI_ERROR (Status)) { @@ -827,14 +883,21 @@ InstallQemuFwCfgTables ( goto RollbackWritePointersAndFreeTracker; } + InstalledTables = OrderedCollectionInit (PointerCompare, PointerCompare); + if (InstalledTables == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto FreeKeys; + } + // // second pass: identify and install ACPI tables // Installed = 0; for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) { if (LoaderEntry->Type == QemuLoaderCmdAddPointer) { - Status = Process2ndPassCmdAddPointer (&LoaderEntry->Command.AddPointer, - Tracker, AcpiProtocol, InstalledKey, &Installed); + Status = Process2ndPassCmdAddPointer ( + &LoaderEntry->Command.AddPointer, Tracker, AcpiProtocol, + InstalledKey, &Installed, InstalledTables); if (EFI_ERROR (Status)) { goto UninstallAcpiTables; } @@ -870,6 +933,12 @@ UninstallAcpiTables: DEBUG ((EFI_D_INFO, "%a: installed %d tables\n", __FUNCTION__, Installed)); } + while (((InstalledTableEntry = OrderedCollectionMax(InstalledTables))) != NULL) { + OrderedCollectionDelete (InstalledTables, InstalledTableEntry, NULL); + } + OrderedCollectionUninit (InstalledTables); + +FreeKeys: FreePool (InstalledKey); RollbackWritePointersAndFreeTracker: -- 2.3.2 (Apple Git-55)