-\r
-\r
-//\r
-// We'll be saving the keys of installed tables so that we can roll them back\r
-// in case of failure. 128 tables should be enough for anyone (TM).\r
-//\r
-#define INSTALLED_TABLES_MAX 128\r
-\r
-/**\r
- Download one ACPI table data file from QEMU and interpret it.\r
-\r
- @param[in] FwCfgFile The NUL-terminated name of the fw_cfg file to\r
- download and interpret.\r
-\r
- @param[in] AcpiProtocol The ACPI table protocol used to install tables.\r
-\r
- @param[in,out] InstalledKey On input, an array of INSTALLED_TABLES_MAX UINTN\r
- elements, allocated by the caller. On output,\r
- the function will have stored (appended) the\r
- AcpiProtocol-internal keys of the ACPI tables\r
- that the function has installed from the fw_cfg\r
- file. The array reflects installed tables even\r
- if the function returns with an error.\r
-\r
- @param[in,out] NumInstalled On input, the number of entries already used in\r
- InstalledKey; it must be in [0,\r
- INSTALLED_TABLES_MAX] inclusive. On output, the\r
- parameter is updated to the new cumulative count\r
- of the keys stored in InstalledKey; the value\r
- reflects installed tables even if the function\r
- returns with an error.\r
-\r
- @retval EFI_INVALID_PARAMETER NumInstalled is outside the allowed range on\r
- input.\r
-\r
- @retval EFI_UNSUPPORTED Firmware configuration is unavailable.\r
-\r
- @retval EFI_NOT_FOUND The host doesn't export the requested fw_cfg\r
- file.\r
-\r
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or no more room in\r
- InstalledKey.\r
-\r
- @retval EFI_PROTOCOL_ERROR Found truncated or invalid ACPI table header\r
- in the fw_cfg contents.\r
-\r
- @return Status codes returned by\r
- AcpiProtocol->InstallAcpiTable().\r
-\r
-**/\r
-\r
-STATIC\r
-EFI_STATUS\r
-InstallQemuLinkedTables (\r
- IN CONST CHAR8 *FwCfgFile,\r
- IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,\r
- IN OUT UINTN InstalledKey[INSTALLED_TABLES_MAX],\r
- IN OUT INT32 *NumInstalled\r
- )\r
-{\r
- EFI_STATUS Status;\r
- FIRMWARE_CONFIG_ITEM TablesFile;\r
- UINTN TablesFileSize;\r
- UINT8 *Tables;\r
- UINTN Processed;\r
-\r
- if (*NumInstalled < 0 || *NumInstalled > INSTALLED_TABLES_MAX) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = QemuFwCfgFindFile (FwCfgFile, &TablesFile, &TablesFileSize);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: \"%a\" unavailable: %r\n", __FUNCTION__,\r
- FwCfgFile, Status));\r
- return Status;\r
- }\r
-\r
- Tables = AllocatePool (TablesFileSize);\r
- if (Tables == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- QemuFwCfgSelectItem (TablesFile);\r
- QemuFwCfgReadBytes (TablesFileSize, Tables);\r
-\r
- Processed = 0;\r
- while (Processed < TablesFileSize) {\r
- UINTN Remaining;\r
- EFI_ACPI_DESCRIPTION_HEADER *Probe;\r
-\r
- Remaining = TablesFileSize - Processed;\r
- if (Remaining < sizeof *Probe) {\r
- Status = EFI_PROTOCOL_ERROR;\r
- break;\r
- }\r
-\r
- Probe = (EFI_ACPI_DESCRIPTION_HEADER *) (Tables + Processed);\r
- if (Remaining < Probe->Length || Probe->Length < sizeof *Probe) {\r
- Status = EFI_PROTOCOL_ERROR;\r
- break;\r
- }\r
-\r
- DEBUG ((EFI_D_VERBOSE, "%a: \"%a\" offset 0x%016Lx:"\r
- " Signature=\"%-4.4a\" Length=0x%08x\n",\r
- __FUNCTION__, FwCfgFile, (UINT64) Processed,\r
- (CONST CHAR8 *) &Probe->Signature, Probe->Length));\r
-\r
- //\r
- // skip automatically handled "root" tables: RSDT, XSDT\r
- //\r
- if (Probe->Signature !=\r
- EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE &&\r
- Probe->Signature !=\r
- EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {\r
- if (*NumInstalled == INSTALLED_TABLES_MAX) {\r
- DEBUG ((EFI_D_ERROR, "%a: can't install more than %d tables\n",\r
- __FUNCTION__, INSTALLED_TABLES_MAX));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- break;\r
- }\r
-\r
- Status = AcpiProtocol->InstallAcpiTable (AcpiProtocol, Probe,\r
- Probe->Length, &InstalledKey[*NumInstalled]);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR,\r
- "%a: failed to install table \"%-4.4a\" at \"%a\" offset 0x%Lx: "\r
- "%r\n", __FUNCTION__, (CONST CHAR8 *)&Probe->Signature, FwCfgFile,\r
- (UINT64) Processed, Status));\r
- break;\r
- }\r
-\r
- ++*NumInstalled;\r
- }\r
-\r
- Processed += Probe->Length;\r
- }\r
-\r
- //\r
- // NUL-padding at the end is accepted\r
- //\r
- if (Status == EFI_PROTOCOL_ERROR) {\r
- UINTN ErrorLocation;\r
-\r
- ErrorLocation = Processed;\r
- while (Processed < TablesFileSize && Tables[Processed] == '\0') {\r
- ++Processed;\r
- }\r
- if (Processed < TablesFileSize) {\r
- DEBUG ((EFI_D_ERROR, "%a: truncated or invalid ACPI table header at "\r
- "\"%a\" offset 0x%Lx\n", __FUNCTION__, FwCfgFile,\r
- (UINT64)ErrorLocation));\r
- }\r
- }\r
-\r
- if (Processed == TablesFileSize) {\r
- Status = EFI_SUCCESS;\r
- } else {\r
- ASSERT (EFI_ERROR (Status));\r
- }\r
-\r
- FreePool (Tables);\r
- return Status;\r
-}\r
-\r
-/**\r
- Download all ACPI table data files from QEMU and interpret them.\r
-\r
- @param[in] AcpiProtocol The ACPI table protocol used to install tables.\r
-\r
- @retval EFI_UNSUPPORTED Firmware configuration is unavailable.\r
-\r
- @retval EFI_NOT_FOUND The host doesn't export the required fw_cfg\r
- files.\r
-\r
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or more than\r
- INSTALLED_TABLES_MAX tables found.\r
-\r
- @retval EFI_PROTOCOL_ERROR Found truncated or invalid ACPI table header\r
- in the fw_cfg contents.\r
-\r
- @return Status codes returned by\r
- AcpiProtocol->InstallAcpiTable().\r
-\r
-**/\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-InstallAllQemuLinkedTables (\r
- IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol\r
- )\r
-{\r
- UINTN *InstalledKey;\r
- INT32 Installed;\r
- EFI_STATUS Status;\r
-\r
- InstalledKey = AllocatePool (INSTALLED_TABLES_MAX * sizeof *InstalledKey);\r
- if (InstalledKey == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- Installed = 0;\r
-\r
- Status = InstallQemuLinkedTables ("etc/acpi/tables", AcpiProtocol,\r
- InstalledKey, &Installed);\r
- if (EFI_ERROR (Status)) {\r
- ASSERT (Status != EFI_INVALID_PARAMETER);\r
- //\r
- // Roll back partial installation.\r
- //\r
- while (Installed > 0) {\r
- --Installed;\r
- AcpiProtocol->UninstallAcpiTable (AcpiProtocol, InstalledKey[Installed]);\r
- }\r
- } else {\r
- DEBUG ((EFI_D_INFO, "%a: installed %d tables\n", __FUNCTION__, Installed));\r
- }\r
-\r
- FreePool (InstalledKey);\r
- return Status;\r
-}\r