]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/XenAcpiPlatformDxe: remove the QEMU ACPI linker/loader client
authorLaszlo Ersek <lersek@redhat.com>
Wed, 26 May 2021 20:14:16 +0000 (22:14 +0200)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 4 Jun 2021 16:01:50 +0000 (16:01 +0000)
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>
OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.c
OvmfPkg/XenAcpiPlatformDxe/AcpiPlatform.h
OvmfPkg/XenAcpiPlatformDxe/BootScript.c [deleted file]
OvmfPkg/XenAcpiPlatformDxe/PciDecoding.c [deleted file]
OvmfPkg/XenAcpiPlatformDxe/QemuFwCfgAcpi.c [deleted file]
OvmfPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.inf

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