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