diff --git a/OvmfPkg/AcpiPlatformDxe/Qemu.c b/OvmfPkg/AcpiPlatformDxe/Qemu.c index 70f3ff6426..ef2ba114b6 100644 --- a/OvmfPkg/AcpiPlatformDxe/Qemu.c +++ b/OvmfPkg/AcpiPlatformDxe/Qemu.c @@ -517,272 +517,6 @@ QemuInstallAcpiTable ( } -/** - Check if an array of bytes starts with an RSD PTR structure. - - Checksum is ignored. - - @param[in] Buffer The array to check. - - @param[in] Size Number of bytes in Buffer. - - @param[out] RsdpSize If the function returns EFI_SUCCESS, this parameter - contains the size of the detected RSD PTR structure. - - @retval EFI_SUCCESS RSD PTR structure detected at the beginning of - Buffer, and its advertised size does not exceed - Size. - - @retval EFI_PROTOCOL_ERROR RSD PTR structure detected at the beginning of - Buffer, but it has inconsistent size. - - @retval EFI_NOT_FOUND RSD PTR structure not found. - -**/ - -STATIC -EFI_STATUS -CheckRsdp ( - IN CONST VOID *Buffer, - IN UINTN Size, - OUT UINTN *RsdpSize - ) -{ - CONST UINT64 *Signature; - CONST EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp1; - CONST EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp2; - - if (Size < sizeof *Signature) { - return EFI_NOT_FOUND; - } - Signature = Buffer; - - if (*Signature != EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) { - return EFI_NOT_FOUND; - } - - // - // Signature found -- from this point on we can only report - // EFI_PROTOCOL_ERROR or EFI_SUCCESS. - // - if (Size < sizeof *Rsdp1) { - return EFI_PROTOCOL_ERROR; - } - Rsdp1 = Buffer; - - if (Rsdp1->Reserved == 0) { - // - // ACPI 1.0 doesn't include the Length field - // - *RsdpSize = sizeof *Rsdp1; - return EFI_SUCCESS; - } - - if (Size < sizeof *Rsdp2) { - return EFI_PROTOCOL_ERROR; - } - Rsdp2 = Buffer; - - if (Size < Rsdp2->Length || Rsdp2->Length < sizeof *Rsdp2) { - return EFI_PROTOCOL_ERROR; - } - - *RsdpSize = Rsdp2->Length; - return EFI_SUCCESS; -} - -// -// We'll be saving the keys of installed tables so that we can roll them back -// in case of failure. 128 tables should be enough for anyone (TM). -// -#define INSTALLED_TABLES_MAX 128 - -/** - Download one ACPI table data file from QEMU and interpret it. - - @param[in] FwCfgFile The NUL-terminated name of the fw_cfg file to - download and interpret. - - @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 keys of the ACPI tables - that the function has installed from the fw_cfg - file. The array reflects installed tables even - if the function returns with an error. - - @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 updated to the new cumulative count - of the keys stored in InstalledKey; the value - reflects installed tables even if the function - returns with an error. - - @retval EFI_INVALID_PARAMETER NumInstalled is outside the allowed range on - input. - - @retval EFI_UNSUPPORTED Firmware configuration is unavailable. - - @retval EFI_NOT_FOUND The host doesn't export the requested fw_cfg - file. - - @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or no more room in - InstalledKey. - - @retval EFI_PROTOCOL_ERROR Found truncated or invalid ACPI table header - in the fw_cfg contents. - - @return Status codes returned by - AcpiProtocol->InstallAcpiTable(). - -**/ - -STATIC -EFI_STATUS -InstallQemuLinkedTables ( - IN CONST CHAR8 *FwCfgFile, - IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, - IN OUT UINTN InstalledKey[INSTALLED_TABLES_MAX], - IN OUT INT32 *NumInstalled - ) -{ - EFI_STATUS Status; - FIRMWARE_CONFIG_ITEM TablesFile; - UINTN TablesFileSize; - UINT8 *Tables; - UINTN Processed; - - if (*NumInstalled < 0 || *NumInstalled > INSTALLED_TABLES_MAX) { - return EFI_INVALID_PARAMETER; - } - - Status = QemuFwCfgFindFile (FwCfgFile, &TablesFile, &TablesFileSize); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "%a: \"%a\" unavailable: %r\n", __FUNCTION__, - FwCfgFile, Status)); - return Status; - } - - Tables = AllocatePool (TablesFileSize); - if (Tables == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - QemuFwCfgSelectItem (TablesFile); - QemuFwCfgReadBytes (TablesFileSize, Tables); - - Processed = 0; - while (Processed < TablesFileSize) { - UINTN Remaining; - UINTN RsdpSize; - EFI_ACPI_DESCRIPTION_HEADER *Probe; - - Remaining = TablesFileSize - Processed; - - // - // See if we're looking at an RSD PTR structure. - // - RsdpSize = 0; - Status = CheckRsdp (Tables + Processed, Remaining, &RsdpSize); - if (Status == EFI_PROTOCOL_ERROR) { - // - // RSD PTR found but its size is inconsistent; abort processing. (Note - // that "RSD PTR found" excludes the NUL-padding case by definition.) - // - break; - } - if (!EFI_ERROR (Status)) { - // - // Consistent RSD PTR found, skip it. - // - DEBUG ((EFI_D_VERBOSE, "%a: \"%a\" offset 0x%016Lx: RSD PTR " - "Length=0x%08x\n", __FUNCTION__, FwCfgFile, (UINT64)Processed, - (UINT32)RsdpSize)); - Processed += RsdpSize; - continue; - } - ASSERT (Status == EFI_NOT_FOUND); - - // - // What we're looking at is not an RSD PTR structure; attempt to parse it - // as an ACPI table. - // - if (Remaining < sizeof *Probe) { - Status = EFI_PROTOCOL_ERROR; - break; - } - - Probe = (EFI_ACPI_DESCRIPTION_HEADER *) (Tables + Processed); - if (Remaining < Probe->Length || Probe->Length < sizeof *Probe) { - Status = EFI_PROTOCOL_ERROR; - break; - } - - DEBUG ((EFI_D_VERBOSE, "%a: \"%a\" offset 0x%016Lx:" - " Signature=\"%-4.4a\" Length=0x%08x\n", - __FUNCTION__, FwCfgFile, (UINT64) Processed, - (CONST CHAR8 *) &Probe->Signature, Probe->Length)); - - // - // skip automatically handled "root" tables: RSDT, XSDT - // - if (Probe->Signature != - EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE && - Probe->Signature != - EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { - if (*NumInstalled == INSTALLED_TABLES_MAX) { - DEBUG ((EFI_D_ERROR, "%a: can't install more than %d tables\n", - __FUNCTION__, INSTALLED_TABLES_MAX)); - Status = EFI_OUT_OF_RESOURCES; - break; - } - - Status = AcpiProtocol->InstallAcpiTable (AcpiProtocol, Probe, - Probe->Length, &InstalledKey[*NumInstalled]); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, - "%a: failed to install table \"%-4.4a\" at \"%a\" offset 0x%Lx: " - "%r\n", __FUNCTION__, (CONST CHAR8 *)&Probe->Signature, FwCfgFile, - (UINT64) Processed, Status)); - break; - } - - ++*NumInstalled; - } - - Processed += Probe->Length; - } - - // - // NUL-padding at the end is accepted - // - if (Status == EFI_PROTOCOL_ERROR) { - UINTN ErrorLocation; - - ErrorLocation = Processed; - while (Processed < TablesFileSize && Tables[Processed] == '\0') { - ++Processed; - } - if (Processed < TablesFileSize) { - DEBUG ((EFI_D_ERROR, "%a: truncated or invalid ACPI table header at " - "\"%a\" offset 0x%Lx\n", __FUNCTION__, FwCfgFile, - (UINT64)ErrorLocation)); - } - } - - if (Processed == TablesFileSize) { - Status = EFI_SUCCESS; - } else { - ASSERT (EFI_ERROR (Status)); - } - - FreePool (Tables); - return Status; -} - /** Download all ACPI table data files from QEMU and interpret them. @@ -809,75 +543,5 @@ InstallAllQemuLinkedTables ( IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol ) { - UINTN *InstalledKey; - INT32 Installed; - EFI_STATUS Status; - FIRMWARE_CONFIG_ITEM LoaderItem; - UINTN LoaderSize; - UINT8 *Loader; - QEMU_LOADER_ENTRY *Entry, *End; - - InstalledKey = AllocatePool (INSTALLED_TABLES_MAX * sizeof *InstalledKey); - if (InstalledKey == NULL) { - return EFI_OUT_OF_RESOURCES; - } - Installed = 0; - - Status = QemuFwCfgFindFile ("etc/table-loader", &LoaderItem, &LoaderSize); - if (EFI_ERROR (Status)) { - goto FreeInstalledKey; - } - if (LoaderSize % sizeof *Entry != 0) { - Status = EFI_PROTOCOL_ERROR; - goto FreeInstalledKey; - } - - Loader = AllocatePool (LoaderSize); - if (Loader == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto FreeInstalledKey; - } - - QemuFwCfgSelectItem (LoaderItem); - QemuFwCfgReadBytes (LoaderSize, Loader); - - Entry = (QEMU_LOADER_ENTRY *)Loader; - End = (QEMU_LOADER_ENTRY *)(Loader + LoaderSize); - while (Entry < End) { - if (Entry->Type == QemuLoaderCmdAllocate) { - QEMU_LOADER_ALLOCATE *Allocate; - - Allocate = &Entry->Command.Allocate; - if (Allocate->File[sizeof Allocate->File - 1] != '\0') { - Status = EFI_PROTOCOL_ERROR; - break; - } - - Status = InstallQemuLinkedTables ((CHAR8 *)Allocate->File, AcpiProtocol, - InstalledKey, &Installed); - if (EFI_ERROR (Status)) { - ASSERT (Status != EFI_INVALID_PARAMETER); - break; - } - } - ++Entry; - } - - FreePool (Loader); - - if (EFI_ERROR (Status)) { - // - // Roll back partial installation. - // - while (Installed > 0) { - --Installed; - AcpiProtocol->UninstallAcpiTable (AcpiProtocol, InstalledKey[Installed]); - } - } else { - DEBUG ((EFI_D_INFO, "%a: installed %d tables\n", __FUNCTION__, Installed)); - } - -FreeInstalledKey: - FreePool (InstalledKey); - return Status; + return EFI_NOT_FOUND; }