diff options
-rw-r--r-- | OvmfPkg/AcpiPlatformDxe/Qemu.c | 54 | ||||
-rw-r--r-- | OvmfPkg/AcpiPlatformDxe/QemuLoader.h | 90 |
2 files changed, 139 insertions, 5 deletions
diff --git a/OvmfPkg/AcpiPlatformDxe/Qemu.c b/OvmfPkg/AcpiPlatformDxe/Qemu.c index 5a96d76a1f..70f3ff6426 100644 --- a/OvmfPkg/AcpiPlatformDxe/Qemu.c +++ b/OvmfPkg/AcpiPlatformDxe/Qemu.c @@ -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;
}
diff --git a/OvmfPkg/AcpiPlatformDxe/QemuLoader.h b/OvmfPkg/AcpiPlatformDxe/QemuLoader.h new file mode 100644 index 0000000000..b8f6147ceb --- /dev/null +++ b/OvmfPkg/AcpiPlatformDxe/QemuLoader.h @@ -0,0 +1,90 @@ +/** @file
+ Command structures for the QEMU FwCfg table loader interface.
+
+ Copyright (C) 2014, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __QEMU_LOADER_H__
+#define __QEMU_LOADER_H__
+
+#include <Include/Base.h>
+#include <Library/QemuFwCfgLib.h>
+
+//
+// The types and the documentation reflects the SeaBIOS interface. In OVMF we
+// use a minimal subset of it.
+//
+#define QEMU_LOADER_FNAME_SIZE QEMU_FW_CFG_FNAME_SIZE
+
+//
+// We only look at the Allocate command, and only to get FwCfg filenames.
+//
+typedef enum {
+ QemuLoaderCmdAllocate = 1,
+ QemuLoaderCmdAddPointer,
+ QemuLoaderCmdAddChecksum
+} QEMU_LOADER_COMMAND_TYPE;
+
+typedef enum {
+ QemuLoaderAllocHigh = 1,
+ QemuLoaderAllocFSeg
+} QEMU_LOADER_ALLOC_ZONE;
+
+#pragma pack (1)
+//
+// QemuLoaderCmdAllocate: download the fw_cfg file named File, to a buffer
+// allocated in the zone specified by Zone, aligned at a multiple of Alignment.
+//
+typedef struct {
+ UINT8 File[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated
+ UINT32 Alignment; // power of two
+ UINT8 Zone; // QEMU_LOADER_ALLOC_ZONE values
+} QEMU_LOADER_ALLOCATE;
+
+//
+// QemuLoaderCmdAddPointer: the bytes at
+// [PointerOffset..PointerOffset+PointerSize) in the file PointerFile contain a
+// relative pointer (an offset) into PointeeFile. Increment the relative
+// pointer's value by the base address of where PointeeFile's contents have
+// been placed (when QemuLoaderCmdAllocate has been executed for PointeeFile).
+//
+typedef struct {
+ UINT8 PointerFile[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated
+ UINT8 PointeeFile[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated
+ UINT32 PointerOffset;
+ UINT8 PointerSize; // one of 1, 2, 4, 8
+} QEMU_LOADER_ADD_POINTER;
+
+//
+// QemuLoaderCmdAddChecksum: calculate the UINT8 checksum (as per
+// CalculateChecksum8()) of the range [Start..Start+Length) in File. Store the
+// UINT8 result at ResultOffset in the same File.
+//
+typedef struct {
+ UINT8 File[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated
+ UINT32 ResultOffset;
+ UINT32 Start;
+ UINT32 Length;
+} QEMU_LOADER_ADD_CHECKSUM;
+
+typedef struct {
+ UINT32 Type; // QEMU_LOADER_COMMAND_TYPE values
+ union {
+ QEMU_LOADER_ALLOCATE Allocate;
+ QEMU_LOADER_ADD_POINTER AddPointer;
+ QEMU_LOADER_ADD_CHECKSUM AddChecksum;
+ UINT8 Padding[124];
+ } Command;
+} QEMU_LOADER_ENTRY;
+#pragma pack ()
+
+#endif
|