If the PcdAcpiTestSupport Feature PCD is set, allocate and fill the
ACPI_TEST_SUPPORT structure at a 1MB boundary.

This feature is a best-effort development / unit test helper, so even if
it is enabled at build time, and fails at boot time, it will not prevent
AcpiPlatformDxe from doing its job. For the same reason, error messages
are only logged at the DEBUG_WARN level.

Cc: Anthony Perard <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: Drew Jones <[email protected]>
Cc: Igor Mammedov <[email protected]>
Cc: Jordan Justen <[email protected]>
Cc: Julien Grall <[email protected]>
Cc: Philippe Mathieu-Daudé <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <[email protected]>
---
 OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf          |  4 +
 OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf |  4 +
 OvmfPkg/AcpiPlatformDxe/AcpiTestSupport.c            | 89 ++++++++++++++++++++
 3 files changed, 97 insertions(+)

diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf 
b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
index 9c5bfe767981..11ae3e2a1ac1 100644
--- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -66,6 +66,10 @@ [Protocols]
   gEfiPciIoProtocolGuid                         # PROTOCOL SOMETIMES_CONSUMED
 
 [Guids]
+  gAcpiTestSupportGuid
+  gEfiAcpi10TableGuid
+  gEfiAcpi20TableGuid
+  gEfiEventReadyToBootGuid
   gEfiXenInfoGuid
   gRootBridgesConnectedEventGroupGuid
 
diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf 
b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf
index b2501fea9ca4..062f4d2fc50c 100644
--- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf
+++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf
@@ -58,6 +58,10 @@ [Protocols]
   gEfiPciIoProtocolGuid                         # PROTOCOL SOMETIMES_CONSUMED
 
 [Guids]
+  gAcpiTestSupportGuid
+  gEfiAcpi10TableGuid
+  gEfiAcpi20TableGuid
+  gEfiEventReadyToBootGuid
   gRootBridgesConnectedEventGroupGuid
 
 [Pcd]
diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiTestSupport.c 
b/OvmfPkg/AcpiPlatformDxe/AcpiTestSupport.c
index 462c8e64a4fd..26dd26cdc439 100644
--- a/OvmfPkg/AcpiPlatformDxe/AcpiTestSupport.c
+++ b/OvmfPkg/AcpiPlatformDxe/AcpiTestSupport.c
@@ -15,16 +15,105 @@
 
 #include "AcpiPlatform.h"
 
+#include <Guid/Acpi.h>
+#include <Guid/AcpiTestSupport.h>
+#include <Guid/EventGroup.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+STATIC volatile ACPI_TEST_SUPPORT *mAcpiTestSupport;
+STATIC EFI_EVENT                  mAcpiTestSupportEvent;
+
+STATIC
+VOID
+EFIAPI
+AcpiTestSupportOnReadyToBoot (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  )
+{
+  VOID                          *Pages;
+  CONST VOID                    *Rsdp10;
+  CONST VOID                    *Rsdp20;
+  CONST EFI_CONFIGURATION_TABLE *ConfigTable;
+  CONST EFI_CONFIGURATION_TABLE *ConfigTablesEnd;
+  volatile EFI_GUID             *InverseSignature;
+  UINTN                         Idx;
+
+  Pages = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof *mAcpiTestSupport),
+            SIZE_1MB);
+  if (Pages == NULL) {
+    DEBUG ((DEBUG_WARN, "%a: AllocateAlignedPages() failed\n", __FUNCTION__));
+    UnregisterAcpiTestSupport ();
+    return;
+  }
+
+  //
+  // Locate both gEfiAcpi10TableGuid and gEfiAcpi20TableGuid config tables in
+  // one go.
+  //
+  Rsdp10 = NULL;
+  Rsdp20 = NULL;
+  ConfigTable = gST->ConfigurationTable;
+  ConfigTablesEnd = gST->ConfigurationTable + gST->NumberOfTableEntries;
+  while ((Rsdp10 == NULL || Rsdp20 == NULL) && ConfigTable < ConfigTablesEnd) {
+    if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi10TableGuid)) {
+      Rsdp10 = ConfigTable->VendorTable;
+    } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi20TableGuid)) {
+      Rsdp20 = ConfigTable->VendorTable;
+    }
+    ++ConfigTable;
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "%a: AcpiTestSupport=%p Rsdp10=%p Rsdp20=%p\n",
+    __FUNCTION__, Pages, Rsdp10, Rsdp20));
+
+  //
+  // Store the RSD PTR address(es) first, then the signature second.
+  //
+  mAcpiTestSupport = Pages;
+  mAcpiTestSupport->Rsdp10 = (UINTN)Rsdp10;
+  mAcpiTestSupport->Rsdp20 = (UINTN)Rsdp20;
+
+  MemoryFence();
+
+  InverseSignature = &mAcpiTestSupport->InverseSignatureGuid;
+  InverseSignature->Data1  = gAcpiTestSupportGuid.Data1;
+  InverseSignature->Data1 ^= MAX_UINT32;
+  InverseSignature->Data2  = gAcpiTestSupportGuid.Data2;
+  InverseSignature->Data2 ^= MAX_UINT16;
+  InverseSignature->Data3  = gAcpiTestSupportGuid.Data3;
+  InverseSignature->Data3 ^= MAX_UINT16;
+  for (Idx = 0; Idx < sizeof InverseSignature->Data4; ++Idx) {
+    InverseSignature->Data4[Idx]  = gAcpiTestSupportGuid.Data4[Idx];
+    InverseSignature->Data4[Idx] ^= MAX_UINT8;
+  }
+
+  UnregisterAcpiTestSupport ();
+}
+
 VOID
 RegisterAcpiTestSupport (
   VOID
   )
 {
+  EFI_STATUS Status;
+
+  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+                  AcpiTestSupportOnReadyToBoot, NULL /* Context */,
+                  &gEfiEventReadyToBootGuid, &mAcpiTestSupportEvent);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "%a: CreateEventEx(): %r\n", __FUNCTION__, Status));
+  }
 }
 
 VOID
 UnregisterAcpiTestSupport (
   VOID
   )
 {
+  if (mAcpiTestSupportEvent != NULL) {
+    gBS->CloseEvent (mAcpiTestSupportEvent);
+    mAcpiTestSupportEvent = NULL;
+  }
 }
-- 
2.19.1.3.g30247aa5d201

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to