]> git.proxmox.com Git - mirror_edk2.git/commitdiff
PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option
authorMichael Kubacki <michael.kubacki@microsoft.com>
Mon, 13 Apr 2020 23:38:19 +0000 (16:38 -0700)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Tue, 5 Apr 2022 00:42:38 +0000 (00:42 +0000)
There's currently two approaches being considered for how to allocate the
context buffer passed to PRM handlers:

1. The context buffer is allocated and populated in firmware. As such, the
   FW converts all pointers internal to the buffer to virtual memory
   addresses at the virtual address change event. A single context buffer
   pointer is given to the OS via the PRM ACPI table and the OS converts
   this single physical address to a virtual address when it passes the
   context buffer as a pointer to PRM handlers.

2. The context buffer is allocated and populated in the OS. The OS gets
   all the information needed to populate the context buffer from other
   pre-existing resources (mainly physical addresses in the PRM ACPI
   table). The OS converts all the physical addresses to virtual addresses,
   allocates the context buffer instances, and fills in the information.
   The OS passes the context buffer virtual address to PRM handlers.

The prior behavior was (1). The current POR behavior has moved to (2).
Until (2) is used more widely, it can be kept around with fairly minimal
overhead via a build flag in a few places.

So the default behavior is now (2) (the expected permanent behavior) with
(1) easily enabled by defining "ALLOCATE_CONTEXT_BUFFER_IN_FW" in the
compiler defined macros. A DSC define was added in PrmPkg.dsc to set this
compiler macro in the package  build.

At some point in the future, all code (and some peripheral code)
surrounded with this build flag can be removed if (2) is fully
decided upon.

Cc: Andrew Fish <afish@apple.com>
Cc: Kang Gao <kang.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Michael Kubacki <michael.kubacki@microsoft.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Benjamin You <benjamin.you@intel.com>
Cc: Liu Yun <yun.y.liu@intel.com>
Cc: Ankit Sinha <ankit.sinha@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Acked-by: Michael D Kinney <michael.d.kinney@intel.com>
Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
Acked-by: Leif Lindholm <quic_llindhol@quicinc.com>
Reviewed-by: Ankit Sinha <ankit.sinha@intel.com>
PrmPkg/PrmConfigDxe/PrmConfigDxe.c
PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
PrmPkg/PrmPkg.dsc
PrmPkg/Readme.md
PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c

index cb38146bc9e092a5ed62857e63e7bbed23653450..7215c2e1dc6f11a921065c18770e39640a741ec4 100644 (file)
@@ -28,8 +28,8 @@
 STATIC  UINTN                     mMaxRuntimeMmioRangeCount;\r
 STATIC  UINTN                     mMaxStaticDataBufferCount;\r
 \r
-STATIC  PRM_RUNTIME_MMIO_RANGES   **mRuntimeMmioRanges;\r
-STATIC  PRM_DATA_BUFFER           ***mStaticDataBuffers;\r
+GLOBAL_REMOVE_IF_UNREFERENCED STATIC  PRM_RUNTIME_MMIO_RANGES   **mRuntimeMmioRanges;\r
+GLOBAL_REMOVE_IF_UNREFERENCED STATIC  PRM_DATA_BUFFER           ***mStaticDataBuffers;\r
 \r
 /**\r
   Converts the runtime memory range physical addresses to virtual addresses.\r
@@ -178,37 +178,41 @@ StoreVirtualMemoryAddressChangePointers (
   )\r
 {\r
   EFI_STATUS                  Status;\r
-  UINTN                       BufferIndex;\r
   UINTN                       HandleCount;\r
   UINTN                       HandleIndex;\r
   UINTN                       RangeIndex;\r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
+  UINTN                       BufferIndex;\r
   UINTN                       StaticDataBufferIndex;\r
+  PRM_CONTEXT_BUFFER          *CurrentContextBuffer;\r
+#endif\r
   EFI_HANDLE                  *HandleBuffer;\r
   PRM_CONFIG_PROTOCOL         *PrmConfigProtocol;\r
-  PRM_CONTEXT_BUFFER          *CurrentContextBuffer;\r
 \r
   DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));\r
 \r
   RangeIndex = 0;\r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
   StaticDataBufferIndex = 0;\r
 \r
-  mRuntimeMmioRanges = AllocateRuntimeZeroPool (sizeof (*mRuntimeMmioRanges) * mMaxRuntimeMmioRangeCount);\r
-  if (mRuntimeMmioRanges == NULL && mMaxRuntimeMmioRangeCount > 0) {\r
+  mStaticDataBuffers = AllocateRuntimeZeroPool (sizeof (*mStaticDataBuffers) * mMaxStaticDataBufferCount);\r
+  if (mStaticDataBuffers == NULL && mMaxStaticDataBufferCount > 0) {\r
     DEBUG ((\r
       DEBUG_ERROR,\r
-      "  %a %a: Memory allocation for runtime MMIO pointer array failed.\n",\r
+      "  %a %a: Memory allocation for PRM static data buffer pointer array failed.\n",\r
       _DBGMSGID_,\r
       __FUNCTION__\r
       ));\r
     ASSERT (FALSE);\r
     return;\r
   }\r
+#endif\r
 \r
-  mStaticDataBuffers = AllocateRuntimeZeroPool (sizeof (*mStaticDataBuffers) * mMaxStaticDataBufferCount);\r
-  if (mStaticDataBuffers == NULL && mMaxStaticDataBufferCount > 0) {\r
+  mRuntimeMmioRanges = AllocateRuntimeZeroPool (sizeof (*mRuntimeMmioRanges) * mMaxRuntimeMmioRangeCount);\r
+  if (mRuntimeMmioRanges == NULL && mMaxRuntimeMmioRangeCount > 0) {\r
     DEBUG ((\r
       DEBUG_ERROR,\r
-      "  %a %a: Memory allocation for PRM static data buffer pointer array failed.\n",\r
+      "  %a %a: Memory allocation for runtime MMIO pointer array failed.\n",\r
       _DBGMSGID_,\r
       __FUNCTION__\r
       ));\r
@@ -236,6 +240,7 @@ StoreVirtualMemoryAddressChangePointers (
         continue;\r
       }\r
 \r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
       for (BufferIndex = 0; BufferIndex < PrmConfigProtocol->ModuleContextBuffers.BufferCount; BufferIndex++) {\r
         CurrentContextBuffer = &(PrmConfigProtocol->ModuleContextBuffers.Buffer[BufferIndex]);\r
 \r
@@ -256,6 +261,7 @@ StoreVirtualMemoryAddressChangePointers (
           mStaticDataBuffers[StaticDataBufferIndex++] = &CurrentContextBuffer->StaticDataBuffer;\r
         }\r
       }\r
+#endif\r
       if (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges != NULL) {\r
         if (RangeIndex >= mMaxRuntimeMmioRangeCount) {\r
           Status = EFI_BUFFER_TOO_SMALL;\r
@@ -280,6 +286,7 @@ StoreVirtualMemoryAddressChangePointers (
       __FUNCTION__,\r
       RangeIndex\r
       ));\r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
     DEBUG ((\r
       DEBUG_INFO,\r
       "  %a %a: %d static buffers saved for future virtual memory conversion.\n",\r
@@ -287,6 +294,7 @@ StoreVirtualMemoryAddressChangePointers (
       __FUNCTION__,\r
       StaticDataBufferIndex\r
       ));\r
+#endif\r
   }\r
 }\r
 \r
@@ -388,12 +396,14 @@ PrmConfigVirtualAddressChangeEvent (
 {\r
   UINTN   Index;\r
 \r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
   //\r
   // Convert static data buffer pointers\r
   //\r
   for (Index = 0; Index < mMaxStaticDataBufferCount; Index++) {\r
     gRT->ConvertPointer (0x0, (VOID **) mStaticDataBuffers[Index]);\r
   }\r
+#endif\r
 \r
   //\r
   // Convert runtime MMIO ranges\r
@@ -484,7 +494,7 @@ PrmConfigEndOfDxeNotification (
       if (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges != NULL) {\r
         DEBUG ((\r
           DEBUG_INFO,\r
-          "    %a %a: Found %d PRM runtime MMIO ranges to convert.\n",\r
+          "    %a %a: Found %d PRM runtime MMIO ranges.\n",\r
            _DBGMSGID_,\r
            __FUNCTION__,\r
            PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges->Count\r
@@ -541,6 +551,13 @@ PrmConfigEntryPoint (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  DEBUG ((DEBUG_INFO, "  %a %a: Context buffers will be allocated in ", _DBGMSGID_, __FUNCTION__));\r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
+  DEBUG ((DEBUG_INFO, "firmware.\n"));\r
+#else\r
+  DEBUG ((DEBUG_INFO, "the operating system.\n"));\r
+#endif\r
+\r
   //\r
   // Register a notification function for virtual address change\r
   //\r
index 6b9099ca7ba76df6ede5a954deaf0f55dcf06126..8a9c82347d93b5df814926ea4c8284a9cba6040d 100644 (file)
@@ -30,8 +30,10 @@ typedef struct {
   UINT16                              StructureLength;            ///< Length in bytes of this structure\r
   GUID                                Identifier;                 ///< GUID of the PRM handler for this structure\r
   UINT64                              PhysicalAddress;            ///< Physical address of this PRM handler\r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
   UINT64                              PrmContextBuffer;           ///< Physical address of the context buffer for this\r
                                                                   ///< PRM handler (PRM_CONTEXT_BUFFER *)\r
+#else\r
   UINT64                              StaticDataBuffer;           ///< Physical address of the static data buffer for\r
                                                                   ///< this PRM handler (PRM_DATA_BUFFER *)\r
   UINT64                              AcpiParameterBuffer;        ///< Physical address of the parameter buffer\r
@@ -39,6 +41,8 @@ typedef struct {
                                                                   ///< that is only used in the case of _DSM invocation.\r
                                                                   ///< If _DSM invocation is not used, this value is\r
                                                                   ///< ignored.\r
+#endif\r
+\r
 } PRM_HANDLER_INFORMATION_STRUCT;\r
 \r
 typedef struct {\r
index b43e6d6bf0782452d01d9afbab6a0f1d3c9f6708..85fffdcbd9f1ba9ce79b155c43340f56e58845b2 100644 (file)
@@ -755,7 +755,11 @@ ProcessPrmModules (
                   &CurrentContextBuffer\r
                   );\r
       if (!EFI_ERROR (Status)) {\r
-        CurrentHandlerInfoStruct->PrmContextBuffer = (UINT64) CurrentContextBuffer;\r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
+        CurrentHandlerInfoStruct->PrmContextBuffer = (UINT64) (UINTN) CurrentContextBuffer;\r
+#else\r
+        CurrentHandlerInfoStruct->StaticDataBuffer = (UINT64) (UINTN) CurrentContextBuffer->StaticDataBuffer;\r
+#endif\r
       }\r
 \r
       Status =  GetExportEntryAddress (\r
index a0237d1fe059eed23c0eeee86f2b2daa3aad408d..1a0ddc6ac1815214127bb458b9fe2d6517b80fce 100644 (file)
 [BuildOptions]\r
 # Force deprecated interfaces off\r
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES\r
+\r
+# Append package-specific build settings\r
+!ifdef $(ALLOCATE_CONTEXT_BUFFER_IN_FW)\r
+  *_*_*_CC_FLAGS = -D ALLOCATE_CONTEXT_BUFFER_IN_FW\r
+!endif\r
index b67b3a391e371e8c31f7308664f2b1b10191a828..00ef41bc5f42ac0d001fc0be70c517fc1873452b 100644 (file)
@@ -68,6 +68,18 @@ record (POR) configuration.
 The following list are the currently defined build flags (if any) that may be passed to the `build` command\r
 (e.g. -D FLAG=VALUE).\r
 \r
+* `ALLOCATE_CONTEXT_BUFFER_IN_FW` - Allocates the context buffer for each PRM handler in the firmware instead of\r
+   the operating system (OS).\r
+\r
+   Additional detail: The context buffer structure is defined in [PrmContextBuffer.h](PrmPkg/Include/PrmContextBuffer.h).\r
+   This structure can be instantiated by either firmware with a physical pointer to the buffer placed in the\r
+   `PRM_HANDLER_INFORMATION_STRUCT` for each handler wherein the OS would convert that physical pointer and pass it\r
+   as a virtual address pointer to each PRM handler. Alternatively, the context buffer can be allocated and populated\r
+   by the OS where it would get all the information to populate the context buffer from other structures.\r
+\r
+   The default is for the OS to allocate and populate the buffer. The alternative option of the firmware doing this\r
+   work is kept in the source code until broader OS testing is completed.\r
+\r
 ## Overview\r
 At a high-level, PRM can be viewed from three levels of granularity:\r
 \r
index 3bf5beba7d4a46c7d5b0706b5871b1f732c9c592..b0b12c012a41ca45b1627508b7e3efed66be580b 100644 (file)
@@ -151,10 +151,26 @@ ContextBufferModuleConfigLibConstructor (
   //\r
   // Allocate and populate the context buffer\r
   //\r
+#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW\r
+  //\r
+  // The context buffer allocated in FW will continue being used at OS runtime so it must\r
+  // be a runtime services data buffer.\r
+  //\r
   // This sample module uses a single context buffer for all the handlers\r
   // Todo: This can be done more elegantly in the future. Likely though a library service.\r
   //\r
   PrmContextBuffer = AllocateRuntimeZeroPool (sizeof (*PrmContextBuffer));\r
+#else\r
+  //\r
+  // This context buffer is not actually used by PRM handler at OS runtime. The OS will allocate\r
+  // the actual context buffer passed to the PRM handler.\r
+  //\r
+  // This context buffer is used internally in the firmware to associate a PRM handler with a\r
+  // a static data buffer and a runtime MMIO ranges array so those can be placed into the\r
+  // PRM_HANDLER_INFORMATION_STRUCT and PRM_MODULE_INFORMATION_STRUCT respectively for the PRM handler.\r
+  //\r
+  PrmContextBuffer = AllocateZeroPool (sizeof (*PrmContextBuffer));\r
+#endif\r
   ASSERT (PrmContextBuffer != NULL);\r
   if (PrmContextBuffer == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r