**/\r
\r
#include "AcpiPlatform.h"\r
+#include "QemuLoader.h"\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/QemuFwCfgLib.h>\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
+ @retval EFI_PROTOCOL_ERROR Found invalid fw_cfg contents.\r
\r
@return Status codes returned by\r
AcpiProtocol->InstallAcpiTable().\r
UINTN *InstalledKey;\r
INT32 Installed;\r
EFI_STATUS Status;\r
+ FIRMWARE_CONFIG_ITEM LoaderItem;\r
+ UINTN LoaderSize;\r
+ UINT8 *Loader;\r
+ QEMU_LOADER_ENTRY *Entry, *End;\r
\r
InstalledKey = AllocatePool (INSTALLED_TABLES_MAX * sizeof *InstalledKey);\r
if (InstalledKey == NULL) {\r
}\r
Installed = 0;\r
\r
- Status = InstallQemuLinkedTables ("etc/acpi/tables", AcpiProtocol,\r
- InstalledKey, &Installed);\r
+ Status = QemuFwCfgFindFile ("etc/table-loader", &LoaderItem, &LoaderSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeInstalledKey;\r
+ }\r
+ if (LoaderSize % sizeof *Entry != 0) {\r
+ Status = EFI_PROTOCOL_ERROR;\r
+ goto FreeInstalledKey;\r
+ }\r
+\r
+ Loader = AllocatePool (LoaderSize);\r
+ if (Loader == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto FreeInstalledKey;\r
+ }\r
+\r
+ QemuFwCfgSelectItem (LoaderItem);\r
+ QemuFwCfgReadBytes (LoaderSize, Loader);\r
+\r
+ Entry = (QEMU_LOADER_ENTRY *)Loader;\r
+ End = (QEMU_LOADER_ENTRY *)(Loader + LoaderSize);\r
+ while (Entry < End) {\r
+ if (Entry->Type == QemuLoaderCmdAllocate) {\r
+ QEMU_LOADER_ALLOCATE *Allocate;\r
+\r
+ Allocate = &Entry->Command.Allocate;\r
+ if (Allocate->File[sizeof Allocate->File - 1] != '\0') {\r
+ Status = EFI_PROTOCOL_ERROR;\r
+ break;\r
+ }\r
+\r
+ Status = InstallQemuLinkedTables ((CHAR8 *)Allocate->File, AcpiProtocol,\r
+ InstalledKey, &Installed);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (Status != EFI_INVALID_PARAMETER);\r
+ break;\r
+ }\r
+ }\r
+ ++Entry;\r
+ }\r
+\r
+ FreePool (Loader);\r
+\r
if (EFI_ERROR (Status)) {\r
- ASSERT (Status != EFI_INVALID_PARAMETER);\r
//\r
// Roll back partial installation.\r
//\r
DEBUG ((EFI_D_INFO, "%a: installed %d tables\n", __FUNCTION__, Installed));\r
}\r
\r
+FreeInstalledKey:\r
FreePool (InstalledKey);\r
return Status;\r
}\r
--- /dev/null
+/** @file\r
+ Command structures for the QEMU FwCfg table loader interface.\r
+\r
+ Copyright (C) 2014, Red Hat, Inc.\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __QEMU_LOADER_H__\r
+#define __QEMU_LOADER_H__\r
+\r
+#include <Include/Base.h>\r
+#include <Library/QemuFwCfgLib.h>\r
+\r
+//\r
+// The types and the documentation reflects the SeaBIOS interface. In OVMF we\r
+// use a minimal subset of it.\r
+//\r
+#define QEMU_LOADER_FNAME_SIZE QEMU_FW_CFG_FNAME_SIZE\r
+\r
+//\r
+// We only look at the Allocate command, and only to get FwCfg filenames.\r
+//\r
+typedef enum {\r
+ QemuLoaderCmdAllocate = 1,\r
+ QemuLoaderCmdAddPointer,\r
+ QemuLoaderCmdAddChecksum\r
+} QEMU_LOADER_COMMAND_TYPE;\r
+\r
+typedef enum {\r
+ QemuLoaderAllocHigh = 1,\r
+ QemuLoaderAllocFSeg\r
+} QEMU_LOADER_ALLOC_ZONE;\r
+\r
+#pragma pack (1)\r
+//\r
+// QemuLoaderCmdAllocate: download the fw_cfg file named File, to a buffer\r
+// allocated in the zone specified by Zone, aligned at a multiple of Alignment.\r
+//\r
+typedef struct {\r
+ UINT8 File[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated\r
+ UINT32 Alignment; // power of two\r
+ UINT8 Zone; // QEMU_LOADER_ALLOC_ZONE values\r
+} QEMU_LOADER_ALLOCATE;\r
+\r
+//\r
+// QemuLoaderCmdAddPointer: the bytes at\r
+// [PointerOffset..PointerOffset+PointerSize) in the file PointerFile contain a\r
+// relative pointer (an offset) into PointeeFile. Increment the relative\r
+// pointer's value by the base address of where PointeeFile's contents have\r
+// been placed (when QemuLoaderCmdAllocate has been executed for PointeeFile).\r
+//\r
+typedef struct {\r
+ UINT8 PointerFile[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated\r
+ UINT8 PointeeFile[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated\r
+ UINT32 PointerOffset;\r
+ UINT8 PointerSize; // one of 1, 2, 4, 8\r
+} QEMU_LOADER_ADD_POINTER;\r
+\r
+//\r
+// QemuLoaderCmdAddChecksum: calculate the UINT8 checksum (as per\r
+// CalculateChecksum8()) of the range [Start..Start+Length) in File. Store the\r
+// UINT8 result at ResultOffset in the same File.\r
+//\r
+typedef struct {\r
+ UINT8 File[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated\r
+ UINT32 ResultOffset;\r
+ UINT32 Start;\r
+ UINT32 Length;\r
+} QEMU_LOADER_ADD_CHECKSUM;\r
+\r
+typedef struct {\r
+ UINT32 Type; // QEMU_LOADER_COMMAND_TYPE values\r
+ union {\r
+ QEMU_LOADER_ALLOCATE Allocate;\r
+ QEMU_LOADER_ADD_POINTER AddPointer;\r
+ QEMU_LOADER_ADD_CHECKSUM AddChecksum;\r
+ UINT8 Padding[124];\r
+ } Command;\r
+} QEMU_LOADER_ENTRY;\r
+#pragma pack ()\r
+\r
+#endif\r