summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2021-05-26 22:14:16 +0200
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2021-06-04 16:01:50 +0000
commit4115840c282660b071dbd53c08516e437df1ad0b (patch)
treeedd0a498bc9d3d63ac9a234249638d63a2e6608c
parenta31fcb509684c45d173919d8b980c013df300cb5 (diff)
downloadedk2-4115840c282660b071dbd53c08516e437df1ad0b.tar.gz
edk2-4115840c282660b071dbd53c08516e437df1ad0b.tar.bz2
edk2-4115840c282660b071dbd53c08516e437df1ad0b.zip
OvmfPkg/XenAcpiPlatformDxe: remove the QEMU ACPI linker/loader client
The root of the QEMU ACPI linker/loader client in XenAcpiPlatformDxe is the InstallQemuFwCfgTables() function. This function always fails on Xen, due to its top-most QemuFwCfgFindFile() call. Remove the InstallQemuFwCfgTables() function call from XenAcpiPlatformDxe, along with all dependencies that now become unused. Cc: Anthony Perard <anthony.perard@citrix.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Julien Grall <julien@xen.org> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2122 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20210526201446.12554-14-lersek@redhat.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
-rw-r--r--OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c2
-rw-r--r--OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h51
-rw-r--r--OvmfPkg/XenAcpiPlatformDxe/BootScript.c269
-rw-r--r--OvmfPkg/XenAcpiPlatformDxe/PciDecoding.c194
-rw-r--r--OvmfPkg/XenAcpiPlatformDxe/QemuFwCfgAcpi.c1196
-rw-r--r--OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf6
6 files changed, 1 insertions, 1717 deletions
diff --git a/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c b/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c
index 2b2dc57675..9c8b1e0fcf 100644
--- a/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c
+++ b/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c
@@ -256,7 +256,7 @@ InstallAcpiTables (
if (XenDetected ()) {
Status = InstallXenTables (AcpiTable);
} else {
- Status = InstallQemuFwCfgTables (AcpiTable);
+ Status = EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status)) {
diff --git a/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h
index 6259697c4b..d35143a00d 100644
--- a/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h
+++ b/OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h
@@ -11,14 +11,6 @@
#define ACPI_PLATFORM_H_
#include <Protocol/AcpiTable.h> // EFI_ACPI_TABLE_PROTOCOL
-#include <Protocol/PciIo.h> // EFI_PCI_IO_PROTOCOL
-
-typedef struct {
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINT64 PciAttributes;
-} ORIGINAL_ATTRIBUTES;
-
-typedef struct S3_CONTEXT S3_CONTEXT;
EFI_STATUS
EFIAPI
@@ -51,52 +43,9 @@ InstallXenTables (
EFI_STATUS
EFIAPI
-InstallQemuFwCfgTables (
- IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
- );
-
-EFI_STATUS
-EFIAPI
InstallAcpiTables (
IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
);
-VOID
-EnablePciDecoding (
- OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
- OUT UINTN *Count
- );
-
-VOID
-RestorePciDecoding (
- IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
- IN UINTN Count
- );
-
-EFI_STATUS
-AllocateS3Context (
- OUT S3_CONTEXT **S3Context,
- IN UINTN WritePointerCount
- );
-
-VOID
-ReleaseS3Context (
- IN S3_CONTEXT *S3Context
- );
-
-EFI_STATUS
-SaveCondensedWritePointerToS3Context (
- IN OUT S3_CONTEXT *S3Context,
- IN UINT16 PointerItem,
- IN UINT8 PointerSize,
- IN UINT32 PointerOffset,
- IN UINT64 PointerValue
- );
-
-EFI_STATUS
-TransferS3ContextToBootScript (
- IN S3_CONTEXT *S3Context
- );
-
#endif
diff --git a/OvmfPkg/XenAcpiPlatformDxe/BootScript.c b/OvmfPkg/XenAcpiPlatformDxe/BootScript.c
deleted file mode 100644
index 14d1e68694..0000000000
--- a/OvmfPkg/XenAcpiPlatformDxe/BootScript.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/** @file
- Append an ACPI S3 Boot Script fragment from the QEMU_LOADER_WRITE_POINTER
- commands of QEMU's fully processed table linker/loader script.
-
- Copyright (C) 2017-2021, Red Hat, Inc.
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include <Library/BaseLib.h> // CpuDeadLoop()
-#include <Library/DebugLib.h> // DEBUG()
-#include <Library/MemoryAllocationLib.h> // AllocatePool()
-#include <Library/QemuFwCfgS3Lib.h> // QemuFwCfgS3ScriptSkipBytes()
-
-#include "AcpiPlatform.h"
-
-
-//
-// Condensed structure for capturing the fw_cfg operations -- select, skip,
-// write -- inherent in executing a QEMU_LOADER_WRITE_POINTER command.
-//
-typedef struct {
- UINT16 PointerItem; // resolved from QEMU_LOADER_WRITE_POINTER.PointerFile
- UINT8 PointerSize; // copied as-is from QEMU_LOADER_WRITE_POINTER
- UINT32 PointerOffset; // copied as-is from QEMU_LOADER_WRITE_POINTER
- UINT64 PointerValue; // resolved from QEMU_LOADER_WRITE_POINTER.PointeeFile
- // and QEMU_LOADER_WRITE_POINTER.PointeeOffset
-} CONDENSED_WRITE_POINTER;
-
-
-//
-// Context structure to accumulate CONDENSED_WRITE_POINTER objects from
-// QEMU_LOADER_WRITE_POINTER commands.
-//
-// Any pointers in this structure own the pointed-to objects; that is, when the
-// context structure is released, all pointed-to objects must be released too.
-//
-struct S3_CONTEXT {
- CONDENSED_WRITE_POINTER *WritePointers; // one array element per processed
- // QEMU_LOADER_WRITE_POINTER
- // command
- UINTN Allocated; // number of elements allocated for
- // WritePointers
- UINTN Used; // number of elements populated in
- // WritePointers
-};
-
-
-//
-// Scratch buffer, allocated in EfiReservedMemoryType type memory, for the ACPI
-// S3 Boot Script opcodes to work on.
-//
-#pragma pack (1)
-typedef union {
- UINT64 PointerValue; // filled in from CONDENSED_WRITE_POINTER.PointerValue
-} SCRATCH_BUFFER;
-#pragma pack ()
-
-
-/**
- Allocate an S3_CONTEXT object.
-
- @param[out] S3Context The allocated S3_CONTEXT object is returned
- through this parameter.
-
- @param[in] WritePointerCount Number of CONDENSED_WRITE_POINTER elements to
- allocate room for. WritePointerCount must be
- positive.
-
- @retval EFI_SUCCESS Allocation successful.
-
- @retval EFI_OUT_OF_RESOURCES Out of memory.
-
- @retval EFI_INVALID_PARAMETER WritePointerCount is zero.
-**/
-EFI_STATUS
-AllocateS3Context (
- OUT S3_CONTEXT **S3Context,
- IN UINTN WritePointerCount
- )
-{
- EFI_STATUS Status;
- S3_CONTEXT *Context;
-
- if (WritePointerCount == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- Context = AllocateZeroPool (sizeof *Context);
- if (Context == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Context->WritePointers = AllocatePool (WritePointerCount *
- sizeof *Context->WritePointers);
- if (Context->WritePointers == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto FreeContext;
- }
-
- Context->Allocated = WritePointerCount;
- *S3Context = Context;
- return EFI_SUCCESS;
-
-FreeContext:
- FreePool (Context);
-
- return Status;
-}
-
-
-/**
- Release an S3_CONTEXT object.
-
- @param[in] S3Context The object to release.
-**/
-VOID
-ReleaseS3Context (
- IN S3_CONTEXT *S3Context
- )
-{
- FreePool (S3Context->WritePointers);
- FreePool (S3Context);
-}
-
-
-/**
- Save the information necessary to replicate a QEMU_LOADER_WRITE_POINTER
- command during S3 resume, in condensed format.
-
- This function is to be called from ProcessCmdWritePointer(), after all the
- sanity checks have passed, and before the fw_cfg operations are performed.
-
- @param[in,out] S3Context The S3_CONTEXT object into which the caller wants
- to save the information that was derived from
- QEMU_LOADER_WRITE_POINTER.
-
- @param[in] PointerItem The FIRMWARE_CONFIG_ITEM that
- QEMU_LOADER_WRITE_POINTER.PointerFile was resolved
- to, expressed as a UINT16 value.
-
- @param[in] PointerSize Copied directly from
- QEMU_LOADER_WRITE_POINTER.PointerSize.
-
- @param[in] PointerOffset Copied directly from
- QEMU_LOADER_WRITE_POINTER.PointerOffset.
-
- @param[in] PointerValue The base address of the allocated / downloaded
- fw_cfg blob that is identified by
- QEMU_LOADER_WRITE_POINTER.PointeeFile, plus
- QEMU_LOADER_WRITE_POINTER.PointeeOffset.
-
- @retval EFI_SUCCESS The information derived from
- QEMU_LOADER_WRITE_POINTER has been successfully
- absorbed into S3Context.
-
- @retval EFI_OUT_OF_RESOURCES No room available in S3Context.
-**/
-EFI_STATUS
-SaveCondensedWritePointerToS3Context (
- IN OUT S3_CONTEXT *S3Context,
- IN UINT16 PointerItem,
- IN UINT8 PointerSize,
- IN UINT32 PointerOffset,
- IN UINT64 PointerValue
- )
-{
- CONDENSED_WRITE_POINTER *Condensed;
-
- if (S3Context->Used == S3Context->Allocated) {
- return EFI_OUT_OF_RESOURCES;
- }
- Condensed = S3Context->WritePointers + S3Context->Used;
- Condensed->PointerItem = PointerItem;
- Condensed->PointerSize = PointerSize;
- Condensed->PointerOffset = PointerOffset;
- Condensed->PointerValue = PointerValue;
- DEBUG ((DEBUG_VERBOSE, "%a: 0x%04x/[0x%08x+%d] := 0x%Lx (%Lu)\n",
- __FUNCTION__, PointerItem, PointerOffset, PointerSize, PointerValue,
- (UINT64)S3Context->Used));
- ++S3Context->Used;
- return EFI_SUCCESS;
-}
-
-
-/**
- FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION provided to QemuFwCfgS3Lib.
-**/
-STATIC
-VOID
-EFIAPI
-AppendFwCfgBootScript (
- IN OUT VOID *Context, OPTIONAL
- IN OUT VOID *ExternalScratchBuffer
- )
-{
- S3_CONTEXT *S3Context;
- SCRATCH_BUFFER *ScratchBuffer;
- UINTN Index;
-
- S3Context = Context;
- ScratchBuffer = ExternalScratchBuffer;
-
- for (Index = 0; Index < S3Context->Used; ++Index) {
- CONST CONDENSED_WRITE_POINTER *Condensed;
- RETURN_STATUS Status;
-
- Condensed = &S3Context->WritePointers[Index];
-
- Status = QemuFwCfgS3ScriptSkipBytes (Condensed->PointerItem,
- Condensed->PointerOffset);
- if (RETURN_ERROR (Status)) {
- goto FatalError;
- }
-
- ScratchBuffer->PointerValue = Condensed->PointerValue;
- Status = QemuFwCfgS3ScriptWriteBytes (-1, Condensed->PointerSize);
- if (RETURN_ERROR (Status)) {
- goto FatalError;
- }
- }
-
- DEBUG ((DEBUG_VERBOSE, "%a: boot script fragment saved\n", __FUNCTION__));
-
- ReleaseS3Context (S3Context);
- return;
-
-FatalError:
- ASSERT (FALSE);
- CpuDeadLoop ();
-}
-
-
-/**
- Translate and append the information from an S3_CONTEXT object to the ACPI S3
- Boot Script.
-
- The effects of a successful call to this function cannot be undone.
-
- @param[in] S3Context The S3_CONTEXT object to translate to ACPI S3 Boot
- Script opcodes. If the function returns successfully,
- the caller must set the S3Context pointer -- originally
- returned by AllocateS3Context() -- immediately to NULL,
- because the ownership of S3Context has been transferred.
-
- @retval EFI_SUCCESS The translation of S3Context to ACPI S3 Boot Script
- opcodes has been successfully executed or queued. (This
- includes the case when S3Context was empty on input and
- no ACPI S3 Boot Script opcodes have been necessary to
- produce.)
-
- @return Error codes from underlying functions.
-**/
-EFI_STATUS
-TransferS3ContextToBootScript (
- IN S3_CONTEXT *S3Context
- )
-{
- RETURN_STATUS Status;
-
- if (S3Context->Used == 0) {
- ReleaseS3Context (S3Context);
- return EFI_SUCCESS;
- }
-
- Status = QemuFwCfgS3CallWhenBootScriptReady (AppendFwCfgBootScript,
- S3Context, sizeof (SCRATCH_BUFFER));
- return (EFI_STATUS)Status;
-}
diff --git a/OvmfPkg/XenAcpiPlatformDxe/PciDecoding.c b/OvmfPkg/XenAcpiPlatformDxe/PciDecoding.c
deleted file mode 100644
index 00fc57eb13..0000000000
--- a/OvmfPkg/XenAcpiPlatformDxe/PciDecoding.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/** @file
- Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
- regenerates the ACPI tables.
-
- Copyright (C) 2016-2021, Red Hat, Inc.
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include <Library/DebugLib.h> // DEBUG()
-#include <Library/MemoryAllocationLib.h> // AllocatePool()
-#include <Library/UefiBootServicesTableLib.h> // gBS
-
-#include "AcpiPlatform.h"
-
-
-/**
- Collect all PciIo protocol instances in the system. Save their original
- attributes, and enable IO and MMIO decoding for each.
-
- This is a best effort function; it doesn't return status codes. Its
- caller is supposed to proceed even if this function fails.
-
- @param[out] OriginalAttributes On output, a dynamically allocated array of
- ORIGINAL_ATTRIBUTES elements. The array lists
- the PciIo protocol instances found in the
- system at the time of the call, plus the
- original PCI attributes for each.
-
- Before returning, the function enables IO and
- MMIO decoding for each PciIo instance it
- finds.
-
- On error, or when no such instances are
- found, OriginalAttributes is set to NULL.
-
- @param[out] Count On output, the number of elements in
- OriginalAttributes. On error it is set to
- zero.
-**/
-VOID
-EnablePciDecoding (
- OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
- OUT UINTN *Count
- )
-{
- EFI_STATUS Status;
- UINTN NoHandles;
- EFI_HANDLE *Handles;
- ORIGINAL_ATTRIBUTES *OrigAttrs;
- UINTN Idx;
-
- *OriginalAttributes = NULL;
- *Count = 0;
-
- if (PcdGetBool (PcdPciDisableBusEnumeration)) {
- //
- // The platform downloads ACPI tables from QEMU in general, but there are
- // no root bridges in this execution. We're done.
- //
- return;
- }
-
- Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid,
- NULL /* SearchKey */, &NoHandles, &Handles);
- if (Status == EFI_NOT_FOUND) {
- //
- // No PCI devices were found on either of the root bridges. We're done.
- //
- return;
- }
-
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_WARN, "%a: LocateHandleBuffer(): %r\n", __FUNCTION__,
- Status));
- return;
- }
-
- OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
- if (OrigAttrs == NULL) {
- DEBUG ((DEBUG_WARN, "%a: AllocatePool(): out of resources\n",
- __FUNCTION__));
- goto FreeHandles;
- }
-
- for (Idx = 0; Idx < NoHandles; ++Idx) {
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINT64 Attributes;
-
- //
- // Look up PciIo on the handle and stash it
- //
- Status = gBS->HandleProtocol (Handles[Idx], &gEfiPciIoProtocolGuid,
- (VOID**)&PciIo);
- ASSERT_EFI_ERROR (Status);
- OrigAttrs[Idx].PciIo = PciIo;
-
- //
- // Stash the current attributes
- //
- Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0,
- &OrigAttrs[Idx].PciAttributes);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationGet: %r\n",
- __FUNCTION__, Status));
- goto RestoreAttributes;
- }
-
- //
- // Retrieve supported attributes
- //
- Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupported, 0,
- &Attributes);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationSupported: %r\n",
- __FUNCTION__, Status));
- goto RestoreAttributes;
- }
-
- //
- // Enable IO and MMIO decoding
- //
- Attributes &= EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY;
- Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable,
- Attributes, NULL);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationEnable: %r\n",
- __FUNCTION__, Status));
- goto RestoreAttributes;
- }
- }
-
- //
- // Success
- //
- FreePool (Handles);
- *OriginalAttributes = OrigAttrs;
- *Count = NoHandles;
- return;
-
-RestoreAttributes:
- while (Idx > 0) {
- --Idx;
- OrigAttrs[Idx].PciIo->Attributes (OrigAttrs[Idx].PciIo,
- EfiPciIoAttributeOperationSet,
- OrigAttrs[Idx].PciAttributes,
- NULL
- );
- }
- FreePool (OrigAttrs);
-
-FreeHandles:
- FreePool (Handles);
-}
-
-
-/**
- Restore the original PCI attributes saved with EnablePciDecoding().
-
- @param[in] OriginalAttributes The array allocated and populated by
- EnablePciDecoding(). This parameter may be
- NULL. If OriginalAttributes is NULL, then the
- function is a no-op; otherwise the PciIo
- attributes will be restored, and the
- OriginalAttributes array will be freed.
-
- @param[in] Count The Count value stored by EnablePciDecoding(),
- the number of elements in OriginalAttributes.
- Count may be zero if and only if
- OriginalAttributes is NULL.
-**/
-VOID
-RestorePciDecoding (
- IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
- IN UINTN Count
- )
-{
- UINTN Idx;
-
- ASSERT ((OriginalAttributes == NULL) == (Count == 0));
- if (OriginalAttributes == NULL) {
- return;
- }
-
- for (Idx = 0; Idx < Count; ++Idx) {
- OriginalAttributes[Idx].PciIo->Attributes (
- OriginalAttributes[Idx].PciIo,
- EfiPciIoAttributeOperationSet,
- OriginalAttributes[Idx].PciAttributes,
- NULL
- );
- }
- FreePool (OriginalAttributes);
-}
diff --git a/OvmfPkg/XenAcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/XenAcpiPlatformDxe/QemuFwCfgAcpi.c
deleted file mode 100644
index 521c06cf54..0000000000
--- a/OvmfPkg/XenAcpiPlatformDxe/QemuFwCfgAcpi.c
+++ /dev/null
@@ -1,1196 +0,0 @@
-/** @file
- OVMF ACPI support using QEMU's fw-cfg interface
-
- Copyright (C) 2012-2021, Red Hat, Inc.
- Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <IndustryStandard/Acpi.h> // EFI_ACPI_DESCRIPTION_HEADER
-#include <IndustryStandard/QemuLoader.h> // QEMU_LOADER_FNAME_SIZE
-#include <Library/BaseLib.h> // AsciiStrCmp()
-#include <Library/BaseMemoryLib.h> // CopyMem()
-#include <Library/DebugLib.h> // DEBUG()
-#include <Library/MemoryAllocationLib.h> // AllocatePool()
-#include <Library/OrderedCollectionLib.h> // OrderedCollectionMin()
-#include <Library/QemuFwCfgLib.h> // QemuFwCfgFindFile()
-#include <Library/QemuFwCfgS3Lib.h> // QemuFwCfgS3Enabled()
-#include <Library/UefiBootServicesTableLib.h> // gBS
-
-#include "AcpiPlatform.h"
-
-//
-// The user structure for the ordered collection that will track the fw_cfg
-// blobs under processing.
-//
-typedef struct {
- UINT8 File[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated name of the fw_cfg
- // blob. This is the ordering / search
- // key.
- UINTN Size; // The number of bytes in this blob.
- UINT8 *Base; // Pointer to the blob data.
- BOOLEAN HostsOnlyTableData; // TRUE iff the blob has been found to
- // only contain data that is directly
- // part of ACPI tables.
-} BLOB;
-
-
-/**
- Compare a standalone key against a user structure containing an embedded key.
-
- @param[in] StandaloneKey Pointer to the bare key.
-
- @param[in] UserStruct Pointer to the user structure with the embedded
- key.
-
- @retval <0 If StandaloneKey compares less than UserStruct's key.
-
- @retval 0 If StandaloneKey compares equal to UserStruct's key.
-
- @retval >0 If StandaloneKey compares greater than UserStruct's key.
-**/
-STATIC
-INTN
-EFIAPI
-BlobKeyCompare (
- IN CONST VOID *StandaloneKey,
- IN CONST VOID *UserStruct
- )
-{
- CONST BLOB *Blob;
-
- Blob = UserStruct;
- return AsciiStrCmp (StandaloneKey, (CONST CHAR8 *)Blob->File);
-}
-
-
-/**
- Comparator function for two user structures.
-
- @param[in] UserStruct1 Pointer to the first user structure.
-
- @param[in] UserStruct2 Pointer to the second user structure.
-
- @retval <0 If UserStruct1 compares less than UserStruct2.
-
- @retval 0 If UserStruct1 compares equal to UserStruct2.
-
- @retval >0 If UserStruct1 compares greater than UserStruct2.
-**/
-STATIC
-INTN
-EFIAPI
-BlobCompare (
- IN CONST VOID *UserStruct1,
- IN CONST VOID *UserStruct2
- )
-{
- CONST BLOB *Blob1;
-
- Blob1 = UserStruct1;
- return BlobKeyCompare (Blob1->File, UserStruct2);
-}
-
-
-/**
- Comparator function for two opaque pointers, ordering on (unsigned) pointer
- value itself.
- Can be used as both Key and UserStruct comparator.
-
- @param[in] Pointer1 First pointer.
-
- @param[in] Pointer2 Second pointer.
-
- @retval <0 If Pointer1 compares less than Pointer2.
-
- @retval 0 If Pointer1 compares equal to Pointer2.
-
- @retval >0 If Pointer1 compares greater than Pointer2.
-**/
-STATIC
-INTN
-EFIAPI
-PointerCompare (
- IN CONST VOID *Pointer1,
- IN CONST VOID *Pointer2
- )
-{
- if (Pointer1 == Pointer2) {
- return 0;
- }
- if ((UINTN)Pointer1 < (UINTN)Pointer2) {
- return -1;
- }
- return 1;
-}
-
-
-/**
- Comparator function for two ASCII strings. Can be used as both Key and
- UserStruct comparator.
-
- This function exists solely so we can avoid casting &AsciiStrCmp to
- ORDERED_COLLECTION_USER_COMPARE and ORDERED_COLLECTION_KEY_COMPARE.
-
- @param[in] AsciiString1 Pointer to the first ASCII string.
-
- @param[in] AsciiString2 Pointer to the second ASCII string.
-
- @return The return value of AsciiStrCmp (AsciiString1, AsciiString2).
-**/
-STATIC
-INTN
-EFIAPI
-AsciiStringCompare (
- IN CONST VOID *AsciiString1,
- IN CONST VOID *AsciiString2
- )
-{
- return AsciiStrCmp (AsciiString1, AsciiString2);
-}
-
-
-/**
- Release the ORDERED_COLLECTION structure populated by
- CollectAllocationsRestrictedTo32Bit() (below).
-
- This function may be called by CollectAllocationsRestrictedTo32Bit() itself,
- on the error path.
-
- @param[in] AllocationsRestrictedTo32Bit The ORDERED_COLLECTION structure to
- release.
-**/
-STATIC
-VOID
-ReleaseAllocationsRestrictedTo32Bit (
- IN ORDERED_COLLECTION *AllocationsRestrictedTo32Bit
-)
-{
- ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
-
- for (Entry = OrderedCollectionMin (AllocationsRestrictedTo32Bit);
- Entry != NULL;
- Entry = Entry2) {
- Entry2 = OrderedCollectionNext (Entry);
- OrderedCollectionDelete (AllocationsRestrictedTo32Bit, Entry, NULL);
- }
- OrderedCollectionUninit (AllocationsRestrictedTo32Bit);
-}
-
-
-/**
- Iterate over the linker/loader script, and collect the names of the fw_cfg
- blobs that are referenced by QEMU_LOADER_ADD_POINTER.PointeeFile fields, such
- that QEMU_LOADER_ADD_POINTER.PointerSize is less than 8. This means that the
- pointee blob's address will have to be patched into a narrower-than-8 byte
- pointer field, hence the pointee blob must not be allocated from 64-bit
- address space.
-
- @param[out] AllocationsRestrictedTo32Bit The ORDERED_COLLECTION structure
- linking (not copying / owning) such
- QEMU_LOADER_ADD_POINTER.PointeeFile
- fields that name the blobs
- restricted from 64-bit allocation.
-
- @param[in] LoaderStart Points to the first entry in the
- linker/loader script.
-
- @param[in] LoaderEnd Points one past the last entry in
- the linker/loader script.
-
- @retval EFI_SUCCESS AllocationsRestrictedTo32Bit has been
- populated.
-
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
-
- @retval EFI_PROTOCOL_ERROR Invalid linker/loader script contents.
-**/
-STATIC
-EFI_STATUS
-CollectAllocationsRestrictedTo32Bit (
- OUT ORDERED_COLLECTION **AllocationsRestrictedTo32Bit,
- IN CONST QEMU_LOADER_ENTRY *LoaderStart,
- IN CONST QEMU_LOADER_ENTRY *LoaderEnd
-)
-{
- ORDERED_COLLECTION *Collection;
- CONST QEMU_LOADER_ENTRY *LoaderEntry;
- EFI_STATUS Status;
-
- Collection = OrderedCollectionInit (AsciiStringCompare, AsciiStringCompare);
- if (Collection == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) {
- CONST QEMU_LOADER_ADD_POINTER *AddPointer;
-
- if (LoaderEntry->Type != QemuLoaderCmdAddPointer) {
- continue;
- }
- AddPointer = &LoaderEntry->Command.AddPointer;
-
- if (AddPointer->PointerSize >= 8) {
- continue;
- }
-
- if (AddPointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] != '\0') {
- DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__));
- Status = EFI_PROTOCOL_ERROR;
- goto RollBack;
- }
-
- Status = OrderedCollectionInsert (
- Collection,
- NULL, // Entry
- (VOID *)AddPointer->PointeeFile
- );
- switch (Status) {
- case EFI_SUCCESS:
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: restricting blob \"%a\" from 64-bit allocation\n",
- __FUNCTION__,
- AddPointer->PointeeFile
- ));
- break;
- case EFI_ALREADY_STARTED:
- //
- // The restriction has been recorded already.
- //
- break;
- case EFI_OUT_OF_RESOURCES:
- goto RollBack;
- default:
- ASSERT (FALSE);
- }
- }
-
- *AllocationsRestrictedTo32Bit = Collection;
- return EFI_SUCCESS;
-
-RollBack:
- ReleaseAllocationsRestrictedTo32Bit (Collection);
- return Status;
-}
-
-
-/**
- Process a QEMU_LOADER_ALLOCATE command.
-
- @param[in] Allocate The QEMU_LOADER_ALLOCATE command to
- process.
-
- @param[in,out] Tracker The ORDERED_COLLECTION tracking the
- BLOB user structures created thus
- far.
-
- @param[in] AllocationsRestrictedTo32Bit The ORDERED_COLLECTION populated by
- the function
- CollectAllocationsRestrictedTo32Bit,
- naming the fw_cfg blobs that must
- not be allocated from 64-bit address
- space.
-
- @retval EFI_SUCCESS An area of whole AcpiNVS pages has been
- allocated for the blob contents, and the
- contents have been saved. A BLOB object (user
- structure) has been allocated from pool memory,
- referencing the blob contents. The BLOB user
- structure has been linked into Tracker.
-
- @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name has been found in
- Allocate, or the Allocate command references a
- file that is already known by Tracker.
-
- @retval EFI_UNSUPPORTED Unsupported alignment request has been found in
- Allocate.
-
- @retval EFI_OUT_OF_RESOURCES Pool allocation failed.
-
- @return Error codes from QemuFwCfgFindFile() and
- gBS->AllocatePages().
-**/
-STATIC
-EFI_STATUS
-EFIAPI
-ProcessCmdAllocate (
- IN CONST QEMU_LOADER_ALLOCATE *Allocate,
- IN OUT ORDERED_COLLECTION *Tracker,
- IN ORDERED_COLLECTION *AllocationsRestrictedTo32Bit
- )
-{
- FIRMWARE_CONFIG_ITEM FwCfgItem;
- UINTN FwCfgSize;
- EFI_STATUS Status;
- UINTN NumPages;
- EFI_PHYSICAL_ADDRESS Address;
- BLOB *Blob;
-
- if (Allocate->File[QEMU_LOADER_FNAME_SIZE - 1] != '\0') {
- DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__));
- return EFI_PROTOCOL_ERROR;
- }
-
- if (Allocate->Alignment > EFI_PAGE_SIZE) {
- DEBUG ((DEBUG_ERROR, "%a: unsupported alignment 0x%x\n", __FUNCTION__,
- Allocate->Alignment));
- return EFI_UNSUPPORTED;
- }
-
- Status = QemuFwCfgFindFile ((CHAR8 *)Allocate->File, &FwCfgItem, &FwCfgSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: QemuFwCfgFindFile(\"%a\"): %r\n", __FUNCTION__,
- Allocate->File, Status));
- return Status;
- }
-
- NumPages = EFI_SIZE_TO_PAGES (FwCfgSize);
- Address = MAX_UINT64;
- if (OrderedCollectionFind (
- AllocationsRestrictedTo32Bit,
- Allocate->File
- ) != NULL) {
- Address = MAX_UINT32;
- }
- Status = gBS->AllocatePages (AllocateMaxAddress, EfiACPIMemoryNVS, NumPages,
- &Address);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Blob = AllocatePool (sizeof *Blob);
- if (Blob == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto FreePages;
- }
- CopyMem (Blob->File, Allocate->File, QEMU_LOADER_FNAME_SIZE);
- Blob->Size = FwCfgSize;
- Blob->Base = (VOID *)(UINTN)Address;
- Blob->HostsOnlyTableData = TRUE;
-
- Status = OrderedCollectionInsert (Tracker, NULL, Blob);
- if (Status == RETURN_ALREADY_STARTED) {
- DEBUG ((DEBUG_ERROR, "%a: duplicated file \"%a\"\n", __FUNCTION__,
- Allocate->File));
- Status = EFI_PROTOCOL_ERROR;
- }
- if (EFI_ERROR (Status)) {
- goto FreeBlob;
- }
-
- QemuFwCfgSelectItem (FwCfgItem);
- QemuFwCfgReadBytes (FwCfgSize, Blob->Base);
- ZeroMem (Blob->Base + Blob->Size, EFI_PAGES_TO_SIZE (NumPages) - Blob->Size);
-
- DEBUG ((DEBUG_VERBOSE, "%a: File=\"%a\" Alignment=0x%x Zone=%d Size=0x%Lx "
- "Address=0x%Lx\n", __FUNCTION__, Allocate->File, Allocate->Alignment,
- Allocate->Zone, (UINT64)Blob->Size, (UINT64)(UINTN)Blob->Base));
- return EFI_SUCCESS;
-
-FreeBlob:
- FreePool (Blob);
-
-FreePages:
- gBS->FreePages (Address, NumPages);
-
- return Status;
-}
-
-
-/**
- Process a QEMU_LOADER_ADD_POINTER command.
-
- @param[in] AddPointer The QEMU_LOADER_ADD_POINTER command to process.
-
- @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user
- structures created thus far.
-
- @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name(s) have been found in
- AddPointer, or the AddPointer command references
- a file unknown to Tracker, or the pointer to
- relocate has invalid location, size, or value, or
- the relocated pointer value is not representable
- in the given pointer size.
-
- @retval EFI_SUCCESS The pointer field inside the pointer blob has
- been relocated.
-**/
-STATIC
-EFI_STATUS
-EFIAPI
-ProcessCmdAddPointer (
- IN CONST QEMU_LOADER_ADD_POINTER *AddPointer,
- IN CONST ORDERED_COLLECTION *Tracker
- )
-{
- ORDERED_COLLECTION_ENTRY *TrackerEntry, *TrackerEntry2;
- BLOB *Blob, *Blob2;
- UINT8 *PointerField;
- UINT64 PointerValue;
-
- if (AddPointer->PointerFile[QEMU_LOADER_FNAME_SIZE - 1] != '\0' ||
- AddPointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] != '\0') {
- DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__));
- return EFI_PROTOCOL_ERROR;
- }
-
- TrackerEntry = OrderedCollectionFind (Tracker, AddPointer->PointerFile);
- TrackerEntry2 = OrderedCollectionFind (Tracker, AddPointer->PointeeFile);
- if (TrackerEntry == NULL || TrackerEntry2 == NULL) {
- DEBUG ((DEBUG_ERROR, "%a: invalid blob reference(s) \"%a\" / \"%a\"\n",
- __FUNCTION__, AddPointer->PointerFile, AddPointer->PointeeFile));
- return EFI_PROTOCOL_ERROR;
- }
-
- Blob = OrderedCollectionUserStruct (TrackerEntry);
- Blob2 = OrderedCollectionUserStruct (TrackerEntry2);
- if ((AddPointer->PointerSize != 1 && AddPointer->PointerSize != 2 &&
- AddPointer->PointerSize != 4 && AddPointer->PointerSize != 8) ||
- Blob->Size < AddPointer->PointerSize ||
- Blob->Size - AddPointer->PointerSize < AddPointer->PointerOffset) {
- DEBUG ((DEBUG_ERROR, "%a: invalid pointer location or size in \"%a\"\n",
- __FUNCTION__, AddPointer->PointerFile));
- return EFI_PROTOCOL_ERROR;
- }
-
- PointerField = Blob->Base + AddPointer->PointerOffset;
- PointerValue = 0;
- CopyMem (&PointerValue, PointerField, AddPointer->PointerSize);
- if (PointerValue >= Blob2->Size) {
- DEBUG ((DEBUG_ERROR, "%a: invalid pointer value in \"%a\"\n", __FUNCTION__,
- AddPointer->PointerFile));
- return EFI_PROTOCOL_ERROR;
- }
-
- //
- // The memory allocation system ensures that the address of the byte past the
- // last byte of any allocated object is expressible (no wraparound).
- //
- ASSERT ((UINTN)Blob2->Base <= MAX_ADDRESS - Blob2->Size);
-
- PointerValue += (UINT64)(UINTN)Blob2->Base;
- if (AddPointer->PointerSize < 8 &&
- RShiftU64 (PointerValue, AddPointer->PointerSize * 8) != 0) {
- DEBUG ((DEBUG_ERROR, "%a: relocated pointer value unrepresentable in "
- "\"%a\"\n", __FUNCTION__, AddPointer->PointerFile));
- return EFI_PROTOCOL_ERROR;
- }
-
- CopyMem (PointerField, &PointerValue, AddPointer->PointerSize);
-
- DEBUG ((DEBUG_VERBOSE, "%a: PointerFile=\"%a\" PointeeFile=\"%a\" "
- "PointerOffset=0x%x PointerSize=%d\n", __FUNCTION__,
- AddPointer->PointerFile, AddPointer->PointeeFile,
- AddPointer->PointerOffset, AddPointer->PointerSize));
- return EFI_SUCCESS;
-}
-
-
-/**
- Process a QEMU_LOADER_ADD_CHECKSUM command.
-
- @param[in] AddChecksum The QEMU_LOADER_ADD_CHECKSUM command to process.
-
- @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user
- structures created thus far.
-
- @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name has been found in
- AddChecksum, or the AddChecksum command
- references a file unknown to Tracker, or the
- range to checksum is invalid.
-
- @retval EFI_SUCCESS The requested range has been checksummed.
-**/
-STATIC
-EFI_STATUS
-EFIAPI
-ProcessCmdAddChecksum (
- IN CONST QEMU_LOADER_ADD_CHECKSUM *AddChecksum,
- IN CONST ORDERED_COLLECTION *Tracker
- )
-{
- ORDERED_COLLECTION_ENTRY *TrackerEntry;
- BLOB *Blob;
-
- if (AddChecksum->File[QEMU_LOADER_FNAME_SIZE - 1] != '\0') {
- DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__));
- return EFI_PROTOCOL_ERROR;
- }
-
- TrackerEntry = OrderedCollectionFind (Tracker, AddChecksum->File);
- if (TrackerEntry == NULL) {
- DEBUG ((DEBUG_ERROR, "%a: invalid blob reference \"%a\"\n", __FUNCTION__,
- AddChecksum->File));
- return EFI_PROTOCOL_ERROR;
- }
-
- Blob = OrderedCollectionUserStruct (TrackerEntry);
- if (Blob->Size <= AddChecksum->ResultOffset ||
- Blob->Size < AddChecksum->Length ||
- Blob->Size - AddChecksum->Length < AddChecksum->Start) {
- DEBUG ((DEBUG_ERROR, "%a: invalid checksum range in \"%a\"\n",
- __FUNCTION__, AddChecksum->File));
- return EFI_PROTOCOL_ERROR;
- }
-
- Blob->Base[AddChecksum->ResultOffset] = CalculateCheckSum8 (
- Blob->Base + AddChecksum->Start,
- AddChecksum->Length
- );
- DEBUG ((DEBUG_VERBOSE, "%a: File=\"%a\" ResultOffset=0x%x Start=0x%x "
- "Length=0x%x\n", __FUNCTION__, AddChecksum->File,
- AddChecksum->ResultOffset, AddChecksum->Start, AddChecksum->Length));
- return EFI_SUCCESS;
-}
-
-
-/**
- Process a QEMU_LOADER_WRITE_POINTER command.
-
- @param[in] WritePointer The QEMU_LOADER_WRITE_POINTER command to process.
-
- @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user
- structures created thus far.
-
- @param[in,out] S3Context The S3_CONTEXT object capturing the fw_cfg actions
- of successfully processed QEMU_LOADER_WRITE_POINTER
- commands, to be replayed at S3 resume. S3Context
- may be NULL if S3 is disabled.
-
- @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name(s) have been found in
- WritePointer. Or, the WritePointer command
- references a file unknown to Tracker or the
- fw_cfg directory. Or, the pointer object to
- rewrite has invalid location, size, or initial
- relative value. Or, the pointer value to store
- does not fit in the given pointer size.
-
- @retval EFI_SUCCESS The pointer object inside the writeable fw_cfg
- file has been written. If S3Context is not NULL,
- then WritePointer has been condensed into
- S3Context.
-
- @return Error codes propagated from
- SaveCondensedWritePointerToS3Context(). The
- pointer object inside the writeable fw_cfg file
- has not been written.
-**/
-STATIC
-EFI_STATUS
-ProcessCmdWritePointer (
- IN CONST QEMU_LOADER_WRITE_POINTER *WritePointer,
- IN CONST ORDERED_COLLECTION *Tracker,
- IN OUT S3_CONTEXT *S3Context OPTIONAL
- )
-{
- RETURN_STATUS Status;
- FIRMWARE_CONFIG_ITEM PointerItem;
- UINTN PointerItemSize;
- ORDERED_COLLECTION_ENTRY *PointeeEntry;
- BLOB *PointeeBlob;
- UINT64 PointerValue;
-
- if (WritePointer->PointerFile[QEMU_LOADER_FNAME_SIZE - 1] != '\0' ||
- WritePointer->PointeeFile[QEMU_LOADER_FNAME_SIZE - 1] != '\0') {
- DEBUG ((DEBUG_ERROR, "%a: malformed file name\n", __FUNCTION__));
- return EFI_PROTOCOL_ERROR;
- }
-
- Status = QemuFwCfgFindFile ((CONST CHAR8 *)WritePointer->PointerFile,
- &PointerItem, &PointerItemSize);
- PointeeEntry = OrderedCollectionFind (Tracker, WritePointer->PointeeFile);
- if (RETURN_ERROR (Status) || PointeeEntry == NULL) {
- DEBUG ((DEBUG_ERROR,
- "%a: invalid fw_cfg file or blob reference \"%a\" / \"%a\"\n",
- __FUNCTION__, WritePointer->PointerFile, WritePointer->PointeeFile));
- return EFI_PROTOCOL_ERROR;
- }
-
- if ((WritePointer->PointerSize != 1 && WritePointer->PointerSize != 2 &&
- WritePointer->PointerSize != 4 && WritePointer->PointerSize != 8) ||
- (PointerItemSize < WritePointer->PointerSize) ||
- (PointerItemSize - WritePointer->PointerSize <
- WritePointer->PointerOffset)) {
- DEBUG ((DEBUG_ERROR, "%a: invalid pointer location or size in \"%a\"\n",
- __FUNCTION__, WritePointer->PointerFile));
- return EFI_PROTOCOL_ERROR;
- }
-
- PointeeBlob = OrderedCollectionUserStruct (PointeeEntry);
- PointerValue = WritePointer->PointeeOffset;
- if (PointerValue >= PointeeBlob->Size) {
- DEBUG ((DEBUG_ERROR, "%a: invalid PointeeOffset\n", __FUNCTION__));
- return EFI_PROTOCOL_ERROR;
- }
-
- //
- // The memory allocation system ensures that the address of the byte past the
- // last byte of any allocated object is expressible (no wraparound).
- //
- ASSERT ((UINTN)PointeeBlob->Base <= MAX_ADDRESS - PointeeBlob->Size);
-
- PointerValue += (UINT64)(UINTN)PointeeBlob->Base;
- if (WritePointer->PointerSize < 8 &&
- RShiftU64 (PointerValue, WritePointer->PointerSize * 8) != 0) {
- DEBUG ((DEBUG_ERROR, "%a: pointer value unrepresentable in \"%a\"\n",
- __FUNCTION__, WritePointer->PointerFile));
- return EFI_PROTOCOL_ERROR;
- }
-
- //
- // If S3 is enabled, we have to capture the below fw_cfg actions in condensed
- // form, to be replayed during S3 resume.
- //
- if (S3Context != NULL) {
- EFI_STATUS SaveStatus;
-
- SaveStatus = SaveCondensedWritePointerToS3Context (
- S3Context,
- (UINT16)PointerItem,
- WritePointer->PointerSize,
- WritePointer->PointerOffset,
- PointerValue
- );
- if (EFI_ERROR (SaveStatus)) {
- return SaveStatus;
- }
- }
-
- QemuFwCfgSelectItem (PointerItem);
- QemuFwCfgSkipBytes (WritePointer->PointerOffset);
- QemuFwCfgWriteBytes (WritePointer->PointerSize, &PointerValue);
-
- //
- // Because QEMU has now learned PointeeBlob->Base, we must mark PointeeBlob
- // as unreleasable, for the case when the whole linker/loader script is
- // handled successfully.
- //
- PointeeBlob->HostsOnlyTableData = FALSE;
-
- DEBUG ((DEBUG_VERBOSE, "%a: PointerFile=\"%a\" PointeeFile=\"%a\" "
- "PointerOffset=0x%x PointeeOffset=0x%x PointerSize=%d\n", __FUNCTION__,
- WritePointer->PointerFile, WritePointer->PointeeFile,
- WritePointer->PointerOffset, WritePointer->PointeeOffset,
- WritePointer->PointerSize));
- return EFI_SUCCESS;
-}
-
-
-/**
- Undo a QEMU_LOADER_WRITE_POINTER command.
-
- This function revokes (zeroes out) a guest memory reference communicated to
- QEMU earlier. The caller is responsible for invoking this function only on
- such QEMU_LOADER_WRITE_POINTER commands that have been successfully processed
- by ProcessCmdWritePointer().
-
- @param[in] WritePointer The QEMU_LOADER_WRITE_POINTER command to undo.
-**/
-STATIC
-VOID
-UndoCmdWritePointer (
- IN CONST QEMU_LOADER_WRITE_POINTER *WritePointer
- )
-{
- RETURN_STATUS Status;
- FIRMWARE_CONFIG_ITEM PointerItem;
- UINTN PointerItemSize;
- UINT64 PointerValue;
-
- Status = QemuFwCfgFindFile ((CONST CHAR8 *)WritePointer->PointerFile,
- &PointerItem, &PointerItemSize);
- ASSERT_RETURN_ERROR (Status);
-
- PointerValue = 0;
- QemuFwCfgSelectItem (PointerItem);
- QemuFwCfgSkipBytes (WritePointer->PointerOffset);
- QemuFwCfgWriteBytes (WritePointer->PointerSize, &PointerValue);
-
- DEBUG ((DEBUG_VERBOSE,
- "%a: PointerFile=\"%a\" PointerOffset=0x%x PointerSize=%d\n", __FUNCTION__,
- WritePointer->PointerFile, WritePointer->PointerOffset,
- WritePointer->PointerSize));
-}
-
-
-//
-// 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
-
-/**
- Process a QEMU_LOADER_ADD_POINTER command in order to see if its target byte
- array is an ACPI table, and if so, install it.
-
- This function assumes that the entire QEMU linker/loader command file has
- been processed successfully in a prior first pass.
-
- @param[in] AddPointer The QEMU_LOADER_ADD_POINTER command to process.
-
- @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user
- structures.
-
- @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 key of the ACPI table that
- the function has installed, if the AddPointer
- command identified an ACPI table that is
- different from RSDT and XSDT.
-
- @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 incremented if the AddPointer
- command identified an ACPI table that is
- different from RSDT and XSDT.
-
- @param[in,out] SeenPointers The ORDERED_COLLECTION tracking the absolute
- target addresses that have been pointed-to by
- QEMU_LOADER_ADD_POINTER commands thus far. If a
- target address is encountered for the first
- time, and it identifies an ACPI table that is
- different from RDST and XSDT, the table is
- installed. If a target address is seen for the
- second or later times, it is skipped without
- taking any action.
-
- @retval EFI_INVALID_PARAMETER NumInstalled was outside the allowed range on
- input.
-
- @retval EFI_OUT_OF_RESOURCES The AddPointer command identified an ACPI
- table different from RSDT and XSDT, but there
- was no more room in InstalledKey.
-
- @retval EFI_SUCCESS AddPointer has been processed. Either its
- absolute target address has been encountered
- before, or an ACPI table different from RSDT
- and XSDT has been installed (reflected by
- InstalledKey and NumInstalled), or RSDT or
- XSDT has been identified but not installed, or
- the fw_cfg blob pointed-into by AddPointer has
- been marked as hosting something else than
- just direct ACPI table contents.
-
- @return Error codes returned by
- AcpiProtocol->InstallAcpiTable().
-**/
-STATIC
-EFI_STATUS
-EFIAPI
-Process2ndPassCmdAddPointer (
- IN CONST QEMU_LOADER_ADD_POINTER *AddPointer,
- IN CONST ORDERED_COLLECTION *Tracker,
- IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
- IN OUT UINTN InstalledKey[INSTALLED_TABLES_MAX],
- IN OUT INT32 *NumInstalled,
- IN OUT ORDERED_COLLECTION *SeenPointers
- )
-{
- CONST ORDERED_COLLECTION_ENTRY *TrackerEntry;
- CONST ORDERED_COLLECTION_ENTRY *TrackerEntry2;
- ORDERED_COLLECTION_ENTRY *SeenPointerEntry;
- CONST BLOB *Blob;
- BLOB *Blob2;
- CONST UINT8 *PointerField;
- UINT64 PointerValue;
- UINTN Blob2Remaining;
- UINTN TableSize;
- CONST EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
- CONST EFI_ACPI_DESCRIPTION_HEADER *Header;
- EFI_STATUS Status;
-
- if (*NumInstalled < 0 || *NumInstalled > INSTALLED_TABLES_MAX) {
- return EFI_INVALID_PARAMETER;
- }
-
- TrackerEntry = OrderedCollectionFind (Tracker, AddPointer->PointerFile);
- TrackerEntry2 = OrderedCollectionFind (Tracker, AddPointer->PointeeFile);
- Blob = OrderedCollectionUserStruct (TrackerEntry);
- Blob2 = OrderedCollectionUserStruct (TrackerEntry2);
- PointerField = Blob->Base + AddPointer->PointerOffset;
- PointerValue = 0;
- CopyMem (&PointerValue, PointerField, AddPointer->PointerSize);
-
- //
- // We assert that PointerValue falls inside Blob2's contents. This is ensured
- // by the Blob2->Size check and later checks in ProcessCmdAddPointer().
- //
- Blob2Remaining = (UINTN)Blob2->Base;
- ASSERT(PointerValue >= Blob2Remaining);
- Blob2Remaining += Blob2->Size;
- ASSERT (PointerValue < Blob2Remaining);
-
- Status = OrderedCollectionInsert (
- SeenPointers,
- &SeenPointerEntry, // for reverting insertion in error case
- (VOID *)(UINTN)PointerValue
- );
- if (EFI_ERROR (Status)) {
- if (Status == RETURN_ALREADY_STARTED) {
- //
- // Already seen this pointer, don't try to process it again.
- //
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: PointerValue=0x%Lx already processed, skipping.\n",
- __FUNCTION__,
- PointerValue
- ));
- Status = EFI_SUCCESS;
- }
- return Status;
- }
-
- Blob2Remaining -= (UINTN) PointerValue;
- DEBUG ((DEBUG_VERBOSE, "%a: checking for ACPI header in \"%a\" at 0x%Lx "
- "(remaining: 0x%Lx): ", __FUNCTION__, AddPointer->PointeeFile,
- PointerValue, (UINT64)Blob2Remaining));
-
- TableSize = 0;
-
- //
- // To make our job simple, the FACS has a custom header. Sigh.
- //
- if (sizeof *Facs <= Blob2Remaining) {
- Facs = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)PointerValue;
-
- if (Facs->Length >= sizeof *Facs &&
- Facs->Length <= Blob2Remaining &&
- Facs->Signature ==
- EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
- DEBUG ((DEBUG_VERBOSE, "found \"%-4.4a\" size 0x%x\n",
- (CONST CHAR8 *)&Facs->Signature, Facs->Length));
- TableSize = Facs->Length;
- }
- }
-
- //
- // check for the uniform tables
- //
- if (TableSize == 0 && sizeof *Header <= Blob2Remaining) {
- Header = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)PointerValue;
-
- if (Header->Length >= sizeof *Header &&
- Header->Length <= Blob2Remaining &&
- CalculateSum8 ((CONST UINT8 *)Header, Header->Length) == 0) {
- //
- // This looks very much like an ACPI table from QEMU:
- // - Length field consistent with both ACPI and containing blob size
- // - checksum is correct
- //
- DEBUG ((DEBUG_VERBOSE, "found \"%-4.4a\" size 0x%x\n",
- (CONST CHAR8 *)&Header->Signature, Header->Length));
- TableSize = Header->Length;
-
- //
- // Skip RSDT and XSDT because those are handled by
- // EFI_ACPI_TABLE_PROTOCOL automatically.
- if (Header->Signature ==
- EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE ||
- Header->Signature ==
- EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
- return EFI_SUCCESS;
- }
- }
- }
-
- if (TableSize == 0) {
- DEBUG ((DEBUG_VERBOSE, "not found; marking fw_cfg blob as opaque\n"));
- Blob2->HostsOnlyTableData = FALSE;
- return EFI_SUCCESS;
- }
-
- if (*NumInstalled == INSTALLED_TABLES_MAX) {
- DEBUG ((DEBUG_ERROR, "%a: can't install more than %d tables\n",
- __FUNCTION__, INSTALLED_TABLES_MAX));
- Status = EFI_OUT_OF_RESOURCES;
- goto RollbackSeenPointer;
- }
-
- Status = AcpiProtocol->InstallAcpiTable (AcpiProtocol,
- (VOID *)(UINTN)PointerValue, TableSize,
- &InstalledKey[*NumInstalled]);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: InstallAcpiTable(): %r\n", __FUNCTION__,
- Status));
- goto RollbackSeenPointer;
- }
- ++*NumInstalled;
- return EFI_SUCCESS;
-
-RollbackSeenPointer:
- OrderedCollectionDelete (SeenPointers, SeenPointerEntry, NULL);
- return Status;
-}
-
-
-/**
- Download, process, and install ACPI table data from the QEMU loader
- interface.
-
- @param[in] AcpiProtocol The ACPI table protocol used to install tables.
-
- @retval EFI_UNSUPPORTED Firmware configuration is unavailable, or QEMU
- loader command with unsupported parameters
- has been found.
-
- @retval EFI_NOT_FOUND The host doesn't export the required fw_cfg
- files.
-
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed, or more than
- INSTALLED_TABLES_MAX tables found.
-
- @retval EFI_PROTOCOL_ERROR Found invalid fw_cfg contents.
-
- @return Status codes returned by
- AcpiProtocol->InstallAcpiTable().
-
-**/
-EFI_STATUS
-EFIAPI
-InstallQemuFwCfgTables (
- IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
- )
-{
- EFI_STATUS Status;
- FIRMWARE_CONFIG_ITEM FwCfgItem;
- UINTN FwCfgSize;
- QEMU_LOADER_ENTRY *LoaderStart;
- CONST QEMU_LOADER_ENTRY *LoaderEntry, *LoaderEnd;
- CONST QEMU_LOADER_ENTRY *WritePointerSubsetEnd;
- ORIGINAL_ATTRIBUTES *OriginalPciAttributes;
- UINTN OriginalPciAttributesCount;
- ORDERED_COLLECTION *AllocationsRestrictedTo32Bit;
- S3_CONTEXT *S3Context;
- ORDERED_COLLECTION *Tracker;
- UINTN *InstalledKey;
- INT32 Installed;
- ORDERED_COLLECTION_ENTRY *TrackerEntry, *TrackerEntry2;
- ORDERED_COLLECTION *SeenPointers;
- ORDERED_COLLECTION_ENTRY *SeenPointerEntry, *SeenPointerEntry2;
-
- Status = QemuFwCfgFindFile ("etc/table-loader", &FwCfgItem, &FwCfgSize);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (FwCfgSize % sizeof *LoaderEntry != 0) {
- DEBUG ((DEBUG_ERROR, "%a: \"etc/table-loader\" has invalid size 0x%Lx\n",
- __FUNCTION__, (UINT64)FwCfgSize));
- return EFI_PROTOCOL_ERROR;
- }
-
- LoaderStart = AllocatePool (FwCfgSize);
- if (LoaderStart == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- EnablePciDecoding (&OriginalPciAttributes, &OriginalPciAttributesCount);
- QemuFwCfgSelectItem (FwCfgItem);
- QemuFwCfgReadBytes (FwCfgSize, LoaderStart);
- RestorePciDecoding (OriginalPciAttributes, OriginalPciAttributesCount);
- LoaderEnd = LoaderStart + FwCfgSize / sizeof *LoaderEntry;
-
- AllocationsRestrictedTo32Bit = NULL;
- Status = CollectAllocationsRestrictedTo32Bit (
- &AllocationsRestrictedTo32Bit,
- LoaderStart,
- LoaderEnd
- );
- if (EFI_ERROR (Status)) {
- goto FreeLoader;
- }
-
- S3Context = NULL;
- if (QemuFwCfgS3Enabled ()) {
- //
- // Size the allocation pessimistically, assuming that all commands in the
- // script are QEMU_LOADER_WRITE_POINTER commands.
- //
- Status = AllocateS3Context (&S3Context, LoaderEnd - LoaderStart);
- if (EFI_ERROR (Status)) {
- goto FreeAllocationsRestrictedTo32Bit;
- }
- }
-
- Tracker = OrderedCollectionInit (BlobCompare, BlobKeyCompare);
- if (Tracker == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto FreeS3Context;
- }
-
- //
- // first pass: process the commands
- //
- // "WritePointerSubsetEnd" points one past the last successful
- // QEMU_LOADER_WRITE_POINTER command. Now when we're about to start the first
- // pass, no such command has been encountered yet.
- //
- WritePointerSubsetEnd = LoaderStart;
- for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) {
- switch (LoaderEntry->Type) {
- case QemuLoaderCmdAllocate:
- Status = ProcessCmdAllocate (
- &LoaderEntry->Command.Allocate,
- Tracker,
- AllocationsRestrictedTo32Bit
- );
- break;
-
- case QemuLoaderCmdAddPointer:
- Status = ProcessCmdAddPointer (&LoaderEntry->Command.AddPointer,
- Tracker);
- break;
-
- case QemuLoaderCmdAddChecksum:
- Status = ProcessCmdAddChecksum (&LoaderEntry->Command.AddChecksum,
- Tracker);
- break;
-
- case QemuLoaderCmdWritePointer:
- Status = ProcessCmdWritePointer (&LoaderEntry->Command.WritePointer,
- Tracker, S3Context);
- if (!EFI_ERROR (Status)) {
- WritePointerSubsetEnd = LoaderEntry + 1;
- }
- break;
-
- default:
- DEBUG ((DEBUG_VERBOSE, "%a: unknown loader command: 0x%x\n",
- __FUNCTION__, LoaderEntry->Type));
- break;
- }
-
- if (EFI_ERROR (Status)) {
- goto RollbackWritePointersAndFreeTracker;
- }
- }
-
- InstalledKey = AllocatePool (INSTALLED_TABLES_MAX * sizeof *InstalledKey);
- if (InstalledKey == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto RollbackWritePointersAndFreeTracker;
- }
-
- SeenPointers = OrderedCollectionInit (PointerCompare, PointerCompare);
- if (SeenPointers == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto FreeKeys;
- }
-
- //
- // second pass: identify and install ACPI tables
- //
- Installed = 0;
- for (LoaderEntry = LoaderStart; LoaderEntry < LoaderEnd; ++LoaderEntry) {
- if (LoaderEntry->Type == QemuLoaderCmdAddPointer) {
- Status = Process2ndPassCmdAddPointer (
- &LoaderEntry->Command.AddPointer,
- Tracker,
- AcpiProtocol,
- InstalledKey,
- &Installed,
- SeenPointers
- );
- if (EFI_ERROR (Status)) {
- goto UninstallAcpiTables;
- }
- }
- }
-
- //
- // Translating the condensed QEMU_LOADER_WRITE_POINTER commands to ACPI S3
- // Boot Script opcodes has to be the last operation in this function, because
- // if it succeeds, it cannot be undone.
- //
- if (S3Context != NULL) {
- Status = TransferS3ContextToBootScript (S3Context);
- if (EFI_ERROR (Status)) {
- goto UninstallAcpiTables;
- }
- //
- // Ownership of S3Context has been transferred.
- //
- S3Context = NULL;
- }
-
-UninstallAcpiTables:
- if (EFI_ERROR (Status)) {
- //
- // roll back partial installation
- //
- while (Installed > 0) {
- --Installed;
- AcpiProtocol->UninstallAcpiTable (AcpiProtocol, InstalledKey[Installed]);
- }
- } else {
- DEBUG ((DEBUG_INFO, "%a: installed %d tables\n", __FUNCTION__, Installed));
- }
-
- for (SeenPointerEntry = OrderedCollectionMin (SeenPointers);
- SeenPointerEntry != NULL;
- SeenPointerEntry = SeenPointerEntry2) {
- SeenPointerEntry2 = OrderedCollectionNext (SeenPointerEntry);
- OrderedCollectionDelete (SeenPointers, SeenPointerEntry, NULL);
- }
- OrderedCollectionUninit (SeenPointers);
-
-FreeKeys:
- FreePool (InstalledKey);
-
-RollbackWritePointersAndFreeTracker:
- //
- // In case of failure, revoke any allocation addresses that were communicated
- // to QEMU previously, before we release all the blobs.
- //
- if (EFI_ERROR (Status)) {
- LoaderEntry = WritePointerSubsetEnd;
- while (LoaderEntry > LoaderStart) {
- --LoaderEntry;
- if (LoaderEntry->Type == QemuLoaderCmdWritePointer) {
- UndoCmdWritePointer (&LoaderEntry->Command.WritePointer);
- }
- }
- }
-
- //
- // Tear down the tracker infrastructure. Each fw_cfg blob will be left in
- // place only if we're exiting with success and the blob hosts data that is
- // not directly part of some ACPI table.
- //
- for (TrackerEntry = OrderedCollectionMin (Tracker); TrackerEntry != NULL;
- TrackerEntry = TrackerEntry2) {
- VOID *UserStruct;
- BLOB *Blob;
-
- TrackerEntry2 = OrderedCollectionNext (TrackerEntry);
- OrderedCollectionDelete (Tracker, TrackerEntry, &UserStruct);
- Blob = UserStruct;
-
- if (EFI_ERROR (Status) || Blob->HostsOnlyTableData) {
- DEBUG ((DEBUG_VERBOSE, "%a: freeing \"%a\"\n", __FUNCTION__,
- Blob->File));
- gBS->FreePages ((UINTN)Blob->Base, EFI_SIZE_TO_PAGES (Blob->Size));
- }
- FreePool (Blob);
- }
- OrderedCollectionUninit (Tracker);
-
-FreeS3Context:
- if (S3Context != NULL) {
- ReleaseS3Context (S3Context);
- }
-
-FreeAllocationsRestrictedTo32Bit:
- ReleaseAllocationsRestrictedTo32Bit (AllocationsRestrictedTo32Bit);
-
-FreeLoader:
- FreePool (LoaderStart);
-
- return Status;
-}
diff --git a/OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf b/OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf
index 379b5d56d5..72132e397d 100644
--- a/OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf
+++ b/OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf
@@ -24,11 +24,8 @@
[Sources]
AcpiPlatform.c
AcpiPlatform.h
- BootScript.c
EntryPoint.c
- PciDecoding.c
Qemu.c
- QemuFwCfgAcpi.c
Xen.c
[Packages]
@@ -43,10 +40,8 @@
DebugLib
DxeServicesTableLib
MemoryAllocationLib
- OrderedCollectionLib
PcdLib
QemuFwCfgLib
- QemuFwCfgS3Lib
UefiBootServicesTableLib
UefiDriverEntryPoint
XenPlatformLib
@@ -54,7 +49,6 @@
[Protocols]
gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
- gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
[Guids]
gRootBridgesConnectedEventGroupGuid