OvmfPkg: AcpiPlatformDxe: don't rely on unstable QEMU interface

The fw_cfg file "etc/acpi/tables" is not a stable guest interface -- QEMU
could rename it in the future, and/or introduce additional fw_cfg files
with ACPI payload. Only the higher-level "etc/table-loader" file is
considered stable, which contains a sequence of commands to assist
firmware with reading QEMU ACPI tables from the FwCfg interface.

Because edk2 provides publishing support for ACPI tables, OVMF only uses
the Allocate command to find the names of FwCfg files to read and publish
as ACPI tables.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15574 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Laszlo Ersek
2014-06-19 06:13:29 +00:00
committed by jljusten
parent 374df8fc59
commit a618eaa1f4
2 changed files with 139 additions and 5 deletions

View File

@@ -16,6 +16,7 @@
**/
#include "AcpiPlatform.h"
#include "QemuLoader.h"
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/QemuFwCfgLib.h>
@@ -795,8 +796,7 @@ InstallQemuLinkedTables (
@retval EFI_OUT_OF_RESOURCES Memory allocation failed, or more than
INSTALLED_TABLES_MAX tables found.
@retval EFI_PROTOCOL_ERROR Found truncated or invalid ACPI table header
in the fw_cfg contents.
@retval EFI_PROTOCOL_ERROR Found invalid fw_cfg contents.
@return Status codes returned by
AcpiProtocol->InstallAcpiTable().
@@ -812,6 +812,10 @@ InstallAllQemuLinkedTables (
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) {
@@ -819,10 +823,49 @@ InstallAllQemuLinkedTables (
}
Installed = 0;
Status = InstallQemuLinkedTables ("etc/acpi/tables", AcpiProtocol,
InstalledKey, &Installed);
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)) {
ASSERT (Status != EFI_INVALID_PARAMETER);
//
// Roll back partial installation.
//
@@ -834,6 +877,7 @@ InstallAllQemuLinkedTables (
DEBUG ((EFI_D_INFO, "%a: installed %d tables\n", __FUNCTION__, Installed));
}
FreeInstalledKey:
FreePool (InstalledKey);
return Status;
}