summaryrefslogtreecommitdiffstats
path: root/PrmPkg
diff options
context:
space:
mode:
Diffstat (limited to 'PrmPkg')
-rw-r--r--PrmPkg/Include/Library/PrmModuleDiscoveryLib.h60
-rw-r--r--PrmPkg/Include/Library/PrmPeCoffLib.h111
-rw-r--r--PrmPkg/Include/PrmModuleImageContext.h28
-rw-r--r--PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c382
-rw-r--r--PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf41
-rw-r--r--PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h27
-rw-r--r--PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c411
-rw-r--r--PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf32
-rw-r--r--PrmPkg/PrmLoaderDxe/PrmLoader.h51
-rw-r--r--PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c600
-rw-r--r--PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf5
-rw-r--r--PrmPkg/PrmPkg.dec8
-rw-r--r--PrmPkg/PrmPkg.dsc13
13 files changed, 1133 insertions, 636 deletions
diff --git a/PrmPkg/Include/Library/PrmModuleDiscoveryLib.h b/PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
new file mode 100644
index 0000000000..fe3a42586a
--- /dev/null
+++ b/PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
@@ -0,0 +1,60 @@
+/** @file
+
+ The PRM Module Discovery library provides functionality to discover PRM modules installed by platform firmware.
+
+ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_MODULE_DISCOVERY_LIB_H_
+#define PRM_MODULE_DISCOVERY_LIB_H_
+
+#include <Base.h>
+#include <PrmContextBuffer.h>
+#include <PrmModuleImageContext.h>
+#include <Uefi.h>
+
+/**
+ Gets the next PRM module discovered after the given PRM module.
+
+ @param[in,out] ModuleImageContext A pointer to a pointer to a PRM module image context structure.
+
+ @retval EFI_SUCCESS The next PRM module was found successfully.
+ @retval EFI_INVALID_PARAMETER The given ModuleImageContext structure is invalid or the pointer is NULL.
+ @retval EFI_NOT_FOUND The next PRM module was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextPrmModuleEntry (
+ IN OUT PRM_MODULE_IMAGE_CONTEXT **ModuleImageContext
+ );
+
+/**
+ Discovers all PRM Modules loaded during boot.
+
+ Each PRM Module discovered is placed into a linked list so the list can br processsed in the future.
+
+ @param[out] ModuleCount An optional pointer parameter that, if provided, is set to the number
+ of PRM modules discovered.
+ @param[out] HandlerCount An optional pointer parameter that, if provided, is set to the number
+ of PRM handlers discovered.
+
+ @retval EFI_SUCCESS All PRM Modules were discovered successfully.
+ @retval EFI_INVALID_PARAMETER An actual pointer parameter was passed as NULL.
+ @retval EFI_NOT_FOUND The gEfiLoadedImageProtocolGuid protocol could not be found.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory resources to allocate the new PRM Context
+ linked list nodes.
+ @retval EFI_ALREADY_STARTED The function was called previously and already discovered the PRM modules
+ loaded on this boot.
+
+**/
+EFI_STATUS
+EFIAPI
+DiscoverPrmModules (
+ OUT UINTN *ModuleCount OPTIONAL,
+ OUT UINTN *HandlerCount OPTIONAL
+ );
+
+#endif
diff --git a/PrmPkg/Include/Library/PrmPeCoffLib.h b/PrmPkg/Include/Library/PrmPeCoffLib.h
new file mode 100644
index 0000000000..4698a94776
--- /dev/null
+++ b/PrmPkg/Include/Library/PrmPeCoffLib.h
@@ -0,0 +1,111 @@
+/** @file
+
+ The PRM PE/COFF library provides functionality to support additional PE/COFF functionality needed to use
+ Platform Runtime Mechanism (PRM) modules.
+
+ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_PECOFF_LIB_H_
+#define PRM_PECOFF_LIB_H_
+
+#include <Base.h>
+#include <PrmExportDescriptor.h>
+#include <IndustryStandard/PeImage.h>
+#include <Library/PeCoffLib.h>
+
+/**
+ Gets a pointer to the export directory in a given PE/COFF image.
+
+ @param[in] ImageExportDirectory A pointer to an export directory table in a PE/COFF image.
+ @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
+ PE/COFF image context for the Image containing the PRM Module Export
+ Descriptor table.
+ @param[out] ExportDescriptor A pointer to a pointer to the PRM Module Export Descriptor table found
+ in the ImageExportDirectory given.
+
+ @retval EFI_SUCCESS The PRM Module Export Descriptor table was found successfully.
+ @retval EFI_INVALID_PARAMETER A required parameter is NULL.
+ @retval EFI_NOT_FOUND The PRM Module Export Descriptor table was not found in the given
+ ImageExportDirectory.
+
+**/
+EFI_STATUS
+GetPrmModuleExportDescriptorTable (
+ IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
+ OUT PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT **ExportDescriptor
+ );
+
+/**
+ Gets a pointer to the export directory in a given PE/COFF image.
+
+ @param[in] Image A pointer to a PE32/COFF image base address that is loaded into memory
+ and already relocated to the memory base address. RVAs in the image given
+ should be valid.
+ @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
+ PE/COFF image context for the Image given.
+ @param[out] ImageExportDirectory A pointer to a pointer to the export directory found in the Image given.
+
+ @retval EFI_SUCCESS The export directory was found successfully.
+ @retval EFI_INVALID_PARAMETER A required parameter is NULL.
+ @retval EFI_UNSUPPORTED The PE/COFF image given is not supported as a PRM Module.
+ @retval EFI_NOT_FOUND The image export directory could not be found for this image.
+
+**/
+EFI_STATUS
+GetExportDirectoryInPeCoffImage (
+ IN VOID *Image,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
+ OUT EFI_IMAGE_EXPORT_DIRECTORY **ImageExportDirectory
+ );
+
+/**
+ Returns the image major and image minor version in a given PE/COFF image.
+
+ @param[in] Image A pointer to a PE32/COFF image base address that is loaded into memory
+ and already relocated to the memory base address. RVAs in the image given
+ should be valid.
+ @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
+ PE/COFF image context for the Image given.
+ @param[out] ImageMajorVersion A pointer to a UINT16 buffer to hold the image major version.
+ @param[out] ImageMinorVersion A pointer to a UINT16 buffer to hold the image minor version.
+
+ @retval EFI_SUCCESS The image version was read successfully.
+ @retval EFI_INVALID_PARAMETER A required parameter is NULL.
+ @retval EFI_UNSUPPORTED The PE/COFF image given is not supported.
+
+**/
+EFI_STATUS
+GetImageVersionInPeCoffImage (
+ IN VOID *Image,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
+ OUT UINT16 *ImageMajorVersion,
+ OUT UINT16 *ImageMinorVersion
+ );
+
+/**
+ Gets the address of an entry in an image export table by ASCII name.
+
+ @param[in] ExportName A pointer to an ASCII name string of the entry name.
+ @param[in] ImageBaseAddress The base address of the PE/COFF image.
+ @param[in] ImageExportDirectory A pointer to the export directory in the image.
+ @param[out] ExportPhysicalAddress A pointer that will be updated with the address of the address of the
+ export entry if found.
+
+ @retval EFI_SUCCESS The export entry was found successfully.
+ @retval EFI_INVALID_PARAMETER A required pointer argument is NULL.
+ @retval EFI_NOT_FOUND An entry with the given ExportName was not found.
+
+**/
+EFI_STATUS
+GetExportEntryAddress (
+ IN CONST CHAR8 *ExportName,
+ IN EFI_PHYSICAL_ADDRESS ImageBaseAddress,
+ IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory,
+ OUT EFI_PHYSICAL_ADDRESS *ExportPhysicalAddress
+ );
+
+#endif
diff --git a/PrmPkg/Include/PrmModuleImageContext.h b/PrmPkg/Include/PrmModuleImageContext.h
new file mode 100644
index 0000000000..10146a272b
--- /dev/null
+++ b/PrmPkg/Include/PrmModuleImageContext.h
@@ -0,0 +1,28 @@
+/** @file
+
+ Definitions used internal to the PrmPkg implementation for PRM module image context.
+
+ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_MODULE_IMAGE_CONTEXT_H_
+#define PRM_MODULE_IMAGE_CONTEXT_H_
+
+#include <IndustryStandard/PeImage.h>
+#include <Library/PeCoffLib.h>
+
+#include <PrmExportDescriptor.h>
+
+#pragma pack(push, 1)
+
+typedef struct {
+ PE_COFF_LOADER_IMAGE_CONTEXT PeCoffImageContext;
+ EFI_IMAGE_EXPORT_DIRECTORY *ExportDirectory;
+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *ExportDescriptor;
+} PRM_MODULE_IMAGE_CONTEXT;
+
+#pragma pack(pop)
+
+#endif
diff --git a/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c b/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
new file mode 100644
index 0000000000..6977799aa8
--- /dev/null
+++ b/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
@@ -0,0 +1,382 @@
+/** @file
+
+ The PRM Module Discovery library provides functionality to discover PRM modules installed by platform firmware.
+
+ Copyright (c) Microsoft Corporation
+ Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+#include <Protocol/MmAccess.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrmModuleDiscoveryLib.h>
+#include <Library/PrmPeCoffLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/LoadedImage.h>
+
+#include "PrmModuleDiscovery.h"
+
+#define _DBGMSGID_ "[PRMMODULEDISCOVERYLIB]"
+
+LIST_ENTRY mPrmModuleList;
+
+/**
+ Gets the next PRM module discovered after the given PRM module.
+
+ @param[in,out] ModuleImageContext A pointer to a pointer to a PRM module image context structure.
+ ModuleImageContext should point to a pointer that points to NULL to
+ get the first PRM module discovered.
+
+ @retval EFI_SUCCESS The next PRM module was found successfully.
+ @retval EFI_INVALID_PARAMETER The given ModuleImageContext structure is invalid or the pointer is NULL.
+ @retval EFI_NOT_FOUND The next PRM module was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextPrmModuleEntry (
+ IN OUT PRM_MODULE_IMAGE_CONTEXT **ModuleImageContext
+ )
+{
+ LIST_ENTRY *CurrentLink;
+ LIST_ENTRY *ForwardLink;
+ PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *CurrentListEntry;
+ PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *ForwardListEntry;
+
+ DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+ if (ModuleImageContext == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*ModuleImageContext == NULL) {
+ ForwardLink = GetFirstNode (&mPrmModuleList);
+ } else {
+ CurrentListEntry = NULL;
+ CurrentListEntry = CR (*ModuleImageContext, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY, Context, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE);
+ if (CurrentListEntry == NULL || CurrentListEntry->Signature != PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CurrentLink = &CurrentListEntry->Link;
+ ForwardLink = GetNextNode (&mPrmModuleList, CurrentLink);
+
+ if (ForwardLink == &mPrmModuleList) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ ForwardListEntry = BASE_CR (ForwardLink, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY, Link);
+ if (ForwardListEntry->Signature == PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE) {
+ *ModuleImageContext = &ForwardListEntry->Context;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Creates a new PRM Module Image Context linked list entry.
+
+ @retval PrmModuleImageContextListEntry If successful, a pointer a PRM Module Image Context linked list entry
+ otherwise, NULL is returned.
+
+**/
+STATIC
+PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *
+CreateNewPrmModuleImageContextListEntry (
+ VOID
+ )
+{
+ PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *PrmModuleImageContextListEntry;
+
+ DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+ PrmModuleImageContextListEntry = AllocateZeroPool (sizeof (*PrmModuleImageContextListEntry));
+ if (PrmModuleImageContextListEntry == NULL) {
+ return NULL;
+ }
+ DEBUG ((
+ DEBUG_INFO,
+ " %a %a: Allocated PrmModuleImageContextListEntry at 0x%x of size 0x%x bytes.\n",
+ _DBGMSGID_,
+ __FUNCTION__,
+ (UINTN) PrmModuleImageContextListEntry,
+ sizeof (*PrmModuleImageContextListEntry)
+ ));
+
+ PrmModuleImageContextListEntry->Signature = PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE;
+
+ return PrmModuleImageContextListEntry;
+}
+
+/**
+ Check whether the address is within any of the MMRAM ranges.
+
+ @param[in] Address The address to be checked.
+ @param[in] MmramRanges Pointer to MMRAM descriptor.
+ @param[in] MmramRangeCount MMRAM range count.
+
+ @retval TRUE The address is in MMRAM ranges.
+ @retval FALSE The address is out of MMRAM ranges.
+**/
+BOOLEAN
+EFIAPI
+IsAddressInMmram (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN EFI_MMRAM_DESCRIPTOR *MmramRanges,
+ IN UINTN MmramRangeCount
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < MmramRangeCount; Index++) {
+ if ((Address >= MmramRanges[Index].CpuStart) &&
+ (Address < (MmramRanges[Index].CpuStart + MmramRanges[Index].PhysicalSize)))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Discovers all PRM Modules loaded during boot.
+
+ Each PRM Module discovered is placed into a linked list so the list can br processsed in the future.
+
+ @param[out] ModuleCount An optional pointer parameter that, if provided, is set to the number
+ of PRM modules discovered.
+ @param[out] HandlerCount An optional pointer parameter that, if provided, is set to the number
+ of PRM handlers discovered.
+
+ @retval EFI_SUCCESS All PRM Modules were discovered successfully.
+ @retval EFI_INVALID_PARAMETER An actual pointer parameter was passed as NULL.
+ @retval EFI_NOT_FOUND The gEfiLoadedImageProtocolGuid protocol could not be found.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory resources to allocate the new PRM Context
+ linked list nodes.
+ @retval EFI_ALREADY_STARTED The function was called previously and already discovered the PRM modules
+ loaded on this boot.
+
+**/
+EFI_STATUS
+EFIAPI
+DiscoverPrmModules (
+ OUT UINTN *ModuleCount OPTIONAL,
+ OUT UINTN *HandlerCount OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ PRM_MODULE_IMAGE_CONTEXT TempPrmModuleImageContext;
+ PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *PrmModuleImageContextListEntry;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+ UINTN PrmHandlerCount;
+ UINTN PrmModuleCount;
+ EFI_MM_ACCESS_PROTOCOL *MmAccess;
+ UINTN Size;
+ EFI_MMRAM_DESCRIPTOR *MmramRanges;
+ UINTN MmramRangeCount;
+
+ DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+ PrmHandlerCount = 0;
+ PrmModuleCount = 0;
+
+ if (!IsListEmpty (&mPrmModuleList)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiLoadedImageProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) && (HandleCount == 0)) {
+ DEBUG ((DEBUG_ERROR, "%a %a: No LoadedImageProtocol instances found!\n", _DBGMSGID_, __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ MmramRanges = NULL;
+ MmramRangeCount = 0;
+ Status = gBS->LocateProtocol (
+ &gEfiMmAccessProtocolGuid,
+ NULL,
+ (VOID **)&MmAccess
+ );
+ if (Status == EFI_SUCCESS) {
+ //
+ // Get MMRAM range information
+ //
+ Size = 0;
+ Status = MmAccess->GetCapabilities (MmAccess, &Size, NULL);
+ if ((Status == EFI_BUFFER_TOO_SMALL) && (Size != 0)) {
+ MmramRanges = (EFI_MMRAM_DESCRIPTOR *)AllocatePool (Size);
+ if (MmramRanges != NULL) {
+ Status = MmAccess->GetCapabilities (MmAccess, &Size, MmramRanges);
+ if (Status == EFI_SUCCESS) {
+ MmramRangeCount = Size / sizeof (EFI_MMRAM_DESCRIPTOR);
+ }
+ }
+ }
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImageProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (IsAddressInMmram ((EFI_PHYSICAL_ADDRESS)(UINTN)(LoadedImageProtocol->ImageBase), MmramRanges, MmramRangeCount)) {
+ continue;
+ }
+
+ ZeroMem (&TempPrmModuleImageContext, sizeof (TempPrmModuleImageContext));
+ TempPrmModuleImageContext.PeCoffImageContext.Handle = LoadedImageProtocol->ImageBase;
+ TempPrmModuleImageContext.PeCoffImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+
+ Status = PeCoffLoaderGetImageInfo (&TempPrmModuleImageContext.PeCoffImageContext);
+ if (EFI_ERROR (Status) || TempPrmModuleImageContext.PeCoffImageContext.ImageError != IMAGE_ERROR_SUCCESS) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a %a: ImageHandle 0x%016lx is not a valid PE/COFF image. It cannot be considered a PRM module.\n",
+ _DBGMSGID_,
+ __FUNCTION__,
+ (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImageProtocol->ImageBase
+ ));
+ continue;
+ }
+ if (TempPrmModuleImageContext.PeCoffImageContext.IsTeImage) {
+ // A PRM Module is not allowed to be a TE image
+ continue;
+ }
+
+ // Attempt to find an export table in this image
+ Status = GetExportDirectoryInPeCoffImage (
+ LoadedImageProtocol->ImageBase,
+ &TempPrmModuleImageContext.PeCoffImageContext,
+ &TempPrmModuleImageContext.ExportDirectory
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ // Attempt to find the PRM Module Export Descriptor in the export table
+ Status = GetPrmModuleExportDescriptorTable (
+ TempPrmModuleImageContext.ExportDirectory,
+ &TempPrmModuleImageContext.PeCoffImageContext,
+ &TempPrmModuleImageContext.ExportDescriptor
+ );
+ if (EFI_ERROR (Status) || TempPrmModuleImageContext.ExportDescriptor == NULL) {
+ continue;
+ }
+ // A PRM Module Export Descriptor was successfully found, this is considered a PRM Module.
+
+ //
+ // Create a new PRM Module image context node
+ //
+ PrmModuleImageContextListEntry = CreateNewPrmModuleImageContextListEntry ();
+ if (PrmModuleImageContextListEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (
+ &PrmModuleImageContextListEntry->Context,
+ &TempPrmModuleImageContext,
+ sizeof (PrmModuleImageContextListEntry->Context)
+ );
+ InsertTailList (&mPrmModuleList, &PrmModuleImageContextListEntry->Link);
+ PrmHandlerCount += TempPrmModuleImageContext.ExportDescriptor->Header.NumberPrmHandlers;
+ PrmModuleCount++;
+ DEBUG ((DEBUG_INFO, "%a %a: New PRM Module inserted into list to be processed.\n", _DBGMSGID_, __FUNCTION__));
+ }
+
+ if (HandlerCount != NULL) {
+ *HandlerCount = PrmHandlerCount;
+ }
+ if (ModuleCount != NULL) {
+ *ModuleCount = PrmModuleCount;
+ }
+
+ if (MmramRanges != NULL) {
+ FreePool (MmramRanges);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The destructor function for this library instance.
+
+ Frees global resources allocated by this library instance.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The destructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+PrmModuleDiscoveryLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NextLink;
+ PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *ListEntry;
+
+ if (IsListEmpty (&mPrmModuleList)) {
+ return EFI_SUCCESS;
+ }
+
+ Link = GetFirstNode (&mPrmModuleList);
+ while (!IsNull (&mPrmModuleList, Link)) {
+ ListEntry = CR (Link, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY, Link, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE);
+ NextLink = GetNextNode (&mPrmModuleList, Link);
+
+ RemoveEntryList (Link);
+ FreePool (ListEntry);
+
+ Link = NextLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The constructor function for this library instance.
+
+ Internally initializes data structures used later during library execution.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+PrmModuleDiscoveryLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ InitializeListHead (&mPrmModuleList);
+
+ return EFI_SUCCESS;
+}
diff --git a/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf b/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
new file mode 100644
index 0000000000..1115df3a34
--- /dev/null
+++ b/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
@@ -0,0 +1,41 @@
+## @file
+# PRM Module Discovery Library
+#
+# Provides functionality to discover PRM modules loaded in the system boot.
+#
+# Copyright (c) Microsoft Corporation
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxePrmModuleDiscoveryLib
+ FILE_GUID = 95D3893F-4CBA-4C20-92C1-D24BFE3CE7B9
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PrmModuleDiscoveryLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = PrmModuleDiscoveryLibConstructor
+ DESTRUCTOR = PrmModuleDiscoveryLibDestructor
+
+[Sources]
+ PrmModuleDiscovery.h
+ DxePrmModuleDiscoveryLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ PrmPeCoffLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid
+ gEfiMmAccessProtocolGuid
diff --git a/PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h b/PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
new file mode 100644
index 0000000000..79058d1531
--- /dev/null
+++ b/PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
@@ -0,0 +1,27 @@
+/** @file
+
+ Definitions internally used for Platform Runtime Mechanism (PRM) module discovery.
+
+ Copyright (c) Microsoft Corporation
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_MODULE_DISCOVERY_H_
+#define PRM_MODULE_DISCOVERY_H_
+
+#include <PrmModuleImageContext.h>
+
+#define PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE SIGNATURE_32('P','R','M','E')
+
+#pragma pack(push, 1)
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ PRM_MODULE_IMAGE_CONTEXT Context;
+} PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY;
+
+#pragma pack(pop)
+
+#endif
diff --git a/PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c b/PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
new file mode 100644
index 0000000000..d760d137dc
--- /dev/null
+++ b/PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
@@ -0,0 +1,411 @@
+/** @file
+
+ This file contains implementation for additional PE/COFF functionality needed to use
+ Platform Runtime Mechanism (PRM) modules.
+
+ Copyright (c) Microsoft Corporation
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/PeImage.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeCoffLib.h>
+
+#include <PrmExportDescriptor.h>
+#include <PrmModuleImageContext.h>
+
+#define _DBGMSGID_ "[PRMPECOFFLIB]"
+
+/**
+ Gets a pointer to the export directory in a given PE/COFF image.
+
+ @param[in] ImageExportDirectory A pointer to an export directory table in a PE/COFF image.
+ @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
+ PE/COFF image context for the Image containing the PRM Module Export
+ Descriptor table.
+ @param[out] ExportDescriptor A pointer to a pointer to the PRM Module Export Descriptor table found
+ in the ImageExportDirectory given.
+
+ @retval EFI_SUCCESS The PRM Module Export Descriptor table was found successfully.
+ @retval EFI_INVALID_PARAMETER A required parameter is NULL.
+ @retval EFI_NOT_FOUND The PRM Module Export Descriptor table was not found in the given
+ ImageExportDirectory.
+
+**/
+EFI_STATUS
+GetPrmModuleExportDescriptorTable (
+ IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
+ OUT PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT **ExportDescriptor
+ )
+{
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS CurrentImageAddress;
+ UINT16 PrmModuleExportDescriptorOrdinal;
+ CONST CHAR8 *CurrentExportName;
+ UINT16 *OrdinalTable;
+ UINT32 *ExportNamePointerTable;
+ UINT32 *ExportAddressTable;
+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *TempExportDescriptor;
+
+ DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+ if (ImageExportDirectory == NULL ||
+ PeCoffLoaderImageContext == NULL ||
+ PeCoffLoaderImageContext->ImageAddress == 0 ||
+ ExportDescriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ExportDescriptor = NULL;
+
+ DEBUG ((
+ DEBUG_INFO,
+ " %a %a: %d exported names found in this image.\n",
+ _DBGMSGID_,
+ __FUNCTION__,
+ ImageExportDirectory->NumberOfNames
+ ));
+
+ //
+ // The export name pointer table and export ordinal table form two parallel arrays associated by index.
+ //
+ CurrentImageAddress = PeCoffLoaderImageContext->ImageAddress;
+ ExportAddressTable = (UINT32 *) ((UINTN) CurrentImageAddress + ImageExportDirectory->AddressOfFunctions);
+ ExportNamePointerTable = (UINT32 *) ((UINTN) CurrentImageAddress + ImageExportDirectory->AddressOfNames);
+ OrdinalTable = (UINT16 *) ((UINTN) CurrentImageAddress + ImageExportDirectory->AddressOfNameOrdinals);
+
+ for (Index = 0; Index < ImageExportDirectory->NumberOfNames; Index++) {
+ CurrentExportName = (CONST CHAR8 *) ((UINTN) CurrentImageAddress + ExportNamePointerTable[Index]);
+ DEBUG ((
+ DEBUG_INFO,
+ " %a %a: Export Name[0x%x] - %a.\n",
+ _DBGMSGID_,
+ __FUNCTION__,
+ Index,
+ CurrentExportName
+ ));
+ if (
+ AsciiStrnCmp (
+ PRM_STRING(PRM_MODULE_EXPORT_DESCRIPTOR_NAME),
+ CurrentExportName,
+ AsciiStrLen (PRM_STRING(PRM_MODULE_EXPORT_DESCRIPTOR_NAME))
+ ) == 0) {
+ PrmModuleExportDescriptorOrdinal = OrdinalTable[Index];
+ DEBUG ((
+ DEBUG_INFO,
+ " %a %a: PRM Module Export Descriptor found. Ordinal = %d.\n",
+ _DBGMSGID_,
+ __FUNCTION__,
+ PrmModuleExportDescriptorOrdinal
+ ));
+ if (PrmModuleExportDescriptorOrdinal >= ImageExportDirectory->NumberOfFunctions) {
+ DEBUG ((DEBUG_ERROR, "%a %a: The PRM Module Export Descriptor ordinal value is invalid.\n", _DBGMSGID_, __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ TempExportDescriptor = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *) ((UINTN) CurrentImageAddress + ExportAddressTable[PrmModuleExportDescriptorOrdinal]);
+ if (TempExportDescriptor->Header.Signature == PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE) {
+ *ExportDescriptor = TempExportDescriptor;
+ DEBUG ((DEBUG_INFO, " %a %a: PRM Module Export Descriptor found at 0x%x.\n", _DBGMSGID_, __FUNCTION__, (UINTN) ExportDescriptor));
+ } else {
+ DEBUG ((
+ DEBUG_INFO,
+ " %a %a: PRM Module Export Descriptor found at 0x%x but signature check failed.\n",
+ _DBGMSGID_,
+ __FUNCTION__,
+ (UINTN) TempExportDescriptor
+ ));
+ }
+ DEBUG ((DEBUG_INFO, " %a %a: Exiting export iteration since export descriptor found.\n", _DBGMSGID_, __FUNCTION__));
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Gets a pointer to the export directory in a given PE/COFF image.
+
+ @param[in] Image A pointer to a PE32/COFF image base address that is loaded into memory
+ and already relocated to the memory base address. RVAs in the image given
+ should be valid.
+ @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
+ PE/COFF image context for the Image given.
+ @param[out] ImageExportDirectory A pointer to a pointer to the export directory found in the Image given.
+
+ @retval EFI_SUCCESS The export directory was found successfully.
+ @retval EFI_INVALID_PARAMETER A required parameter is NULL.
+ @retval EFI_UNSUPPORTED The PE/COFF image given is not supported as a PRM Module.
+ @retval EFI_NOT_FOUND The image export directory could not be found for this image.
+
+**/
+EFI_STATUS
+GetExportDirectoryInPeCoffImage (
+ IN VOID *Image,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
+ OUT EFI_IMAGE_EXPORT_DIRECTORY **ImageExportDirectory
+ )
+{
+ UINT16 Magic;
+ UINT32 NumberOfRvaAndSizes;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION OptionalHeaderPtrUnion;
+ EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
+ EFI_IMAGE_EXPORT_DIRECTORY *ExportDirectory;
+
+ if (Image == NULL || PeCoffLoaderImageContext == NULL || ImageExportDirectory == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DirectoryEntry = NULL;
+ ExportDirectory = NULL;
+
+ //
+ // NOTE: For backward compatibility, use the Machine field to identify a PE32/PE32+
+ // image instead of using the Magic field. Some systems might generate a PE32+
+ // image with PE32 magic.
+ //
+ switch (PeCoffLoaderImageContext->Machine) {
+ case EFI_IMAGE_MACHINE_IA32:
+ //
+ // Assume PE32 image with IA32 Machine field.
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ break;
+ case EFI_IMAGE_MACHINE_X64:
+ case EFI_IMAGE_MACHINE_AARCH64:
+ //
+ // Assume PE32+ image with X64 Machine field
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ break;
+ default:
+ //
+ // For unknown Machine field, use Magic in optional header
+ //
+ DEBUG ((
+ DEBUG_WARN,
+ "%a %a: The machine type for this image is not valid for a PRM module.\n",
+ _DBGMSGID_,
+ __FUNCTION__
+ ));
+ return EFI_UNSUPPORTED;
+ }
+
+ OptionalHeaderPtrUnion.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (
+ (UINTN) Image +
+ PeCoffLoaderImageContext->PeCoffHeaderOffset
+ );
+
+ //
+ // Check the PE/COFF Header Signature. Determine if the image is valid and/or a TE image.
+ //
+ if (OptionalHeaderPtrUnion.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "%a %a: The PE signature is not valid for the current image.\n", _DBGMSGID_, __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use the PE32 offset to get the Export Directory Entry
+ //
+ NumberOfRvaAndSizes = OptionalHeaderPtrUnion.Pe32->OptionalHeader.NumberOfRvaAndSizes;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHeaderPtrUnion.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT]);
+ } else if (OptionalHeaderPtrUnion.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ //
+ // Use the PE32+ offset get the Export Directory Entry
+ //
+ NumberOfRvaAndSizes = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT]);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_EXPORT || DirectoryEntry->VirtualAddress == 0) {
+ //
+ // The export directory is not present
+ //
+ return EFI_NOT_FOUND;
+ } else if (((UINT32) (~0) - DirectoryEntry->VirtualAddress) < DirectoryEntry->Size) {
+ //
+ // The directory address overflows
+ //
+ DEBUG ((DEBUG_ERROR, "%a %a: The export directory entry in this image results in overflow.\n", _DBGMSGID_, __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ } else {
+ DEBUG ((DEBUG_INFO, "%a %a: Export Directory Entry found in the image at 0x%x.\n", _DBGMSGID_, __FUNCTION__, (UINTN) OptionalHeaderPtrUnion.Pe32));
+ DEBUG ((DEBUG_INFO, " %a %a: Directory Entry Virtual Address = 0x%x.\n", _DBGMSGID_, __FUNCTION__, DirectoryEntry->VirtualAddress));
+
+ ExportDirectory = (EFI_IMAGE_EXPORT_DIRECTORY *) ((UINTN) Image + DirectoryEntry->VirtualAddress);
+ DEBUG ((
+ DEBUG_INFO,
+ " %a %a: Export Directory Table found successfully at 0x%x. Name address = 0x%x. Name = %a.\n",
+ _DBGMSGID_,
+ __FUNCTION__,
+ (UINTN) ExportDirectory,
+ ((UINTN) Image + ExportDirectory->Name),
+ (CHAR8 *) ((UINTN) Image + ExportDirectory->Name)
+ ));
+ }
+ *ImageExportDirectory = ExportDirectory;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns the image major and image minor version in a given PE/COFF image.
+
+ @param[in] Image A pointer to a PE32/COFF image base address that is loaded into memory
+ and already relocated to the memory base address. RVAs in the image given
+ should be valid.
+ @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
+ PE/COFF image context for the Image given.
+ @param[out] ImageMajorVersion A pointer to a UINT16 buffer to hold the image major version.
+ @param[out] ImageMinorVersion A pointer to a UINT16 buffer to hold the image minor version.
+
+ @retval EFI_SUCCESS The image version was read successfully.
+ @retval EFI_INVALID_PARAMETER A required parameter is NULL.
+ @retval EFI_UNSUPPORTED The PE/COFF image given is not supported.
+
+**/
+EFI_STATUS
+GetImageVersionInPeCoffImage (
+ IN VOID *Image,
+ IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
+ OUT UINT16 *ImageMajorVersion,
+ OUT UINT16 *ImageMinorVersion
+ )
+{
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION OptionalHeaderPtrUnion;
+ UINT16 Magic;
+
+ DEBUG ((DEBUG_INFO, " %a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+ if (Image == NULL || PeCoffLoaderImageContext == NULL || ImageMajorVersion == NULL || ImageMinorVersion == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // NOTE: For backward compatibility, use the Machine field to identify a PE32/PE32+
+ // image instead of using the Magic field. Some systems might generate a PE32+
+ // image with PE32 magic.
+ //
+ switch (PeCoffLoaderImageContext->Machine) {
+ case EFI_IMAGE_MACHINE_IA32:
+ //
+ // Assume PE32 image
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ break;
+ case EFI_IMAGE_MACHINE_X64:
+ case EFI_IMAGE_MACHINE_AARCH64:
+ //
+ // Assume PE32+ image
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ break;
+ default:
+ //
+ // For unknown Machine field, use Magic in optional header
+ //
+ DEBUG ((
+ DEBUG_WARN,
+ "%a %a: The machine type for this image is not valid for a PRM module.\n",
+ _DBGMSGID_,
+ __FUNCTION__
+ ));
+ return EFI_UNSUPPORTED;
+ }
+
+ OptionalHeaderPtrUnion.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (
+ (UINTN) Image +
+ PeCoffLoaderImageContext->PeCoffHeaderOffset
+ );
+ //
+ // Check the PE/COFF Header Signature. Determine if the image is valid and/or a TE image.
+ //
+ if (OptionalHeaderPtrUnion.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "%a %a: The PE signature is not valid for the current image.\n", _DBGMSGID_, __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Use the PE32 offset to get the Export Directory Entry
+ //
+ *ImageMajorVersion = OptionalHeaderPtrUnion.Pe32->OptionalHeader.MajorImageVersion;
+ *ImageMinorVersion = OptionalHeaderPtrUnion.Pe32->OptionalHeader.MinorImageVersion;
+ } else {
+ //
+ // Use the PE32+ offset to get the Export Directory Entry
+ //
+ *ImageMajorVersion = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.MajorImageVersion;
+ *ImageMinorVersion = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.MinorImageVersion;
+ }
+
+ DEBUG ((DEBUG_INFO, " %a %a - Image Major Version: 0x%02x.\n", _DBGMSGID_, __FUNCTION__, *ImageMajorVersion));
+ DEBUG ((DEBUG_INFO, " %a %a - Image Minor Version: 0x%02x.\n", _DBGMSGID_, __FUNCTION__, *ImageMinorVersion));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets the address of an entry in an image export table by ASCII name.
+
+ @param[in] ExportName A pointer to an ASCII name string of the entry name.
+ @param[in] ImageBaseAddress The base address of the PE/COFF image.
+ @param[in] ImageExportDirectory A pointer to the export directory in the image.
+ @param[out] ExportPhysicalAddress A pointer that will be updated with the address of the address of the
+ export entry if found.
+
+ @retval EFI_SUCCESS The export entry was found successfully.
+ @retval EFI_INVALID_PARAMETER A required pointer argument is NULL.
+ @retval EFI_NOT_FOUND An entry with the given ExportName was not found.
+
+**/
+EFI_STATUS
+GetExportEntryAddress (
+ IN CONST CHAR8 *ExportName,
+ IN EFI_PHYSICAL_ADDRESS ImageBaseAddress,
+ IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory,
+ OUT EFI_PHYSICAL_ADDRESS *ExportPhysicalAddress
+ )
+{
+ UINTN ExportNameIndex;
+ UINT16 CurrentExportOrdinal;
+ UINT32 *ExportAddressTable;
+ UINT32 *ExportNamePointerTable;
+ UINT16 *OrdinalTable;
+ CONST CHAR8 *ExportNameTablePointerName;
+
+ if (ExportName == NULL || ImageBaseAddress == 0 || ImageExportDirectory == NULL || ExportPhysicalAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *ExportPhysicalAddress = 0;
+
+ ExportAddressTable = (UINT32 *) ((UINTN) ImageBaseAddress + ImageExportDirectory->AddressOfFunctions);
+ ExportNamePointerTable = (UINT32 *) ((UINTN) ImageBaseAddress + ImageExportDirectory->AddressOfNames);
+ OrdinalTable = (UINT16 *) ((UINTN) ImageBaseAddress + ImageExportDirectory->AddressOfNameOrdinals);
+
+ for (ExportNameIndex = 0; ExportNameIndex < ImageExportDirectory->NumberOfNames; ExportNameIndex++) {
+ ExportNameTablePointerName = (CONST CHAR8 *) ((UINTN) ImageBaseAddress + ExportNamePointerTable[ExportNameIndex]);
+
+ if (AsciiStrnCmp (ExportName, ExportNameTablePointerName, PRM_HANDLER_NAME_MAXIMUM_LENGTH) == 0) {
+ CurrentExportOrdinal = OrdinalTable[ExportNameIndex];
+
+ ASSERT (CurrentExportOrdinal < ImageExportDirectory->NumberOfFunctions);
+ if (CurrentExportOrdinal >= ImageExportDirectory->NumberOfFunctions) {
+ DEBUG ((DEBUG_ERROR, " %a %a: The export ordinal value is invalid.\n", _DBGMSGID_, __FUNCTION__));
+ break;
+ }
+
+ *ExportPhysicalAddress = (EFI_PHYSICAL_ADDRESS) ((UINTN) ImageBaseAddress + ExportAddressTable[CurrentExportOrdinal]);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf b/PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
new file mode 100644
index 0000000000..f139d5380b
--- /dev/null
+++ b/PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
@@ -0,0 +1,32 @@
+## @file
+# PRM PE/COFF Library
+#
+# Provides functionality to support additional PE/COFF functionality needed to use Platform Runtime Mechanism (PRM)
+# modules.
+#
+# Copyright (c) Microsoft Corporation
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxePrmPeCoffLib
+ FILE_GUID = 0B9AEEAC-D79A-46A5-A784-84BDBC6291B5
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PrmPeCoffLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+[Sources]
+ DxePrmPeCoffLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PeCoffLib
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoader.h b/PrmPkg/PrmLoaderDxe/PrmLoader.h
deleted file mode 100644
index 1356c7a0c9..0000000000
--- a/PrmPkg/PrmLoaderDxe/PrmLoader.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/** @file
-
- Definitions specific to the Platform Runtime Mechanism (PRM) loader.x
-
- Copyright (c) Microsoft Corporation
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef PRM_LOADER_H_
-#define PRM_LOADER_H_
-
-#include <IndustryStandard/PeImage.h>
-#include <Library/PeCoffLib.h>
-
-#include <PrmExportDescriptor.h>
-
-#define _DBGMSGID_ "[PRMLOADER]"
-#define PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE SIGNATURE_32('P','R','M','E')
-
-#pragma pack(push, 1)
-
-typedef struct {
- PE_COFF_LOADER_IMAGE_CONTEXT PeCoffImageContext;
- EFI_IMAGE_EXPORT_DIRECTORY *ExportDirectory;
- PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *ExportDescriptor;
-} PRM_MODULE_IMAGE_CONTEXT;
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
- PRM_MODULE_IMAGE_CONTEXT *Context;
-} PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY;
-
-#pragma pack(pop)
-
-//
-// Iterate through the double linked list. NOT delete safe.
-//
-#define EFI_LIST_FOR_EACH(Entry, ListHead) \
- for(Entry = (ListHead)->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink)
-
-//
-// Iterate through the double linked list. This is delete-safe.
-// Don't touch NextEntry.
-//
-#define EFI_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead) \
- for(Entry = (ListHead)->ForwardLink, NextEntry = Entry->ForwardLink;\
- Entry != (ListHead); Entry = NextEntry, NextEntry = Entry->ForwardLin
-
-#endif
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index 6416e388a6..407c482574 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -10,7 +10,6 @@
**/
#include "PrmAcpiTable.h"
-#include "PrmLoader.h"
#include <IndustryStandard/Acpi.h>
#include <Library/BaseLib.h>
@@ -18,581 +17,20 @@
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PrmContextBufferLib.h>
+#include <Library/PrmModuleDiscoveryLib.h>
+#include <Library/PrmPeCoffLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/AcpiTable.h>
-#include <Protocol/LoadedImage.h>
#include <Protocol/PrmConfig.h>
#include <PrmContextBuffer.h>
#include <PrmMmio.h>
-LIST_ENTRY mPrmModuleList;
+#define _DBGMSGID_ "[PRMLOADER]"
-// Todo: Potentially refactor mPrmHandlerCount and mPrmModuleCount into localized structures
-// in the future.
-UINT32 mPrmHandlerCount;
-UINT32 mPrmModuleCount;
-
-/**
- Gets a pointer to the export directory in a given PE/COFF image.
-
- @param[in] ImageExportDirectory A pointer to an export directory table in a PE/COFF image.
- @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
- PE/COFF image context for the Image containing the PRM Module Export
- Descriptor table.
- @param[out] ExportDescriptor A pointer to a pointer to the PRM Module Export Descriptor table found
- in the ImageExportDirectory given.
-
- @retval EFI_SUCCESS The PRM Module Export Descriptor table was found successfully.
- @retval EFI_INVALID_PARAMETER A required parameter is NULL.
- @retval EFI_NOT_FOUND The PRM Module Export Descriptor table was not found in the given
- ImageExportDirectory.
-
-**/
-EFI_STATUS
-GetPrmModuleExportDescriptorTable (
- IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory,
- IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
- OUT PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT **ExportDescriptor
- )
-{
- UINTN Index;
- EFI_PHYSICAL_ADDRESS CurrentImageAddress;
- UINT16 PrmModuleExportDescriptorOrdinal;
- CONST CHAR8 *CurrentExportName;
- UINT16 *OrdinalTable;
- UINT32 *ExportNamePointerTable;
- UINT32 *ExportAddressTable;
- PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *TempExportDescriptor;
-
- DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
-
- *ExportDescriptor = NULL;
-
- if (ImageExportDirectory == NULL ||
- PeCoffLoaderImageContext == NULL ||
- PeCoffLoaderImageContext->ImageAddress == 0 ||
- ExportDescriptor == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- DEBUG ((
- DEBUG_INFO,
- " %a %a: %d exported names found in this image.\n",
- _DBGMSGID_,
- __FUNCTION__,
- ImageExportDirectory->NumberOfNames
- ));
-
- //
- // The export name pointer table and export ordinal table form two parallel arrays associated by index.
- //
- CurrentImageAddress = PeCoffLoaderImageContext->ImageAddress;
- ExportAddressTable = (UINT32 *) ((UINTN) CurrentImageAddress + ImageExportDirectory->AddressOfFunctions);
- ExportNamePointerTable = (UINT32 *) ((UINTN) CurrentImageAddress + ImageExportDirectory->AddressOfNames);
- OrdinalTable = (UINT16 *) ((UINTN) CurrentImageAddress + ImageExportDirectory->AddressOfNameOrdinals);
-
- for (Index = 0; Index < ImageExportDirectory->NumberOfNames; Index++) {
- CurrentExportName = (CONST CHAR8 *) ((UINTN) CurrentImageAddress + ExportNamePointerTable[Index]);
- DEBUG ((
- DEBUG_INFO,
- " %a %a: Export Name[0x%x] - %a.\n",
- _DBGMSGID_,
- __FUNCTION__,
- Index,
- CurrentExportName
- ));
- if (
- AsciiStrnCmp (
- PRM_STRING(PRM_MODULE_EXPORT_DESCRIPTOR_NAME),
- CurrentExportName,
- AsciiStrLen (PRM_STRING(PRM_MODULE_EXPORT_DESCRIPTOR_NAME))
- ) == 0) {
- PrmModuleExportDescriptorOrdinal = OrdinalTable[Index];
- DEBUG ((
- DEBUG_INFO,
- " %a %a: PRM Module Export Descriptor found. Ordinal = %d.\n",
- _DBGMSGID_,
- __FUNCTION__,
- PrmModuleExportDescriptorOrdinal
- ));
- if (PrmModuleExportDescriptorOrdinal >= ImageExportDirectory->NumberOfFunctions) {
- DEBUG ((DEBUG_ERROR, "%a %a: The PRM Module Export Descriptor ordinal value is invalid.\n", _DBGMSGID_, __FUNCTION__));
- return EFI_NOT_FOUND;
- }
- TempExportDescriptor = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *) ((UINTN) CurrentImageAddress + ExportAddressTable[PrmModuleExportDescriptorOrdinal]);
- if (TempExportDescriptor->Header.Signature == PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE) {
- *ExportDescriptor = TempExportDescriptor;
- DEBUG ((DEBUG_INFO, " %a %a: PRM Module Export Descriptor found at 0x%x.\n", _DBGMSGID_, __FUNCTION__, (UINTN) ExportDescriptor));
- } else {
- DEBUG ((
- DEBUG_INFO,
- " %a %a: PRM Module Export Descriptor found at 0x%x but signature check failed.\n",
- _DBGMSGID_,
- __FUNCTION__,
- (UINTN) TempExportDescriptor
- ));
- }
- DEBUG ((DEBUG_INFO, " %a %a: Exiting export iteration since export descriptor found.\n", _DBGMSGID_, __FUNCTION__));
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Gets a pointer to the export directory in a given PE/COFF image.
-
- @param[in] Image A pointer to a PE32/COFF image base address that is loaded into memory
- and already relocated to the memory base address. RVAs in the image given
- should be valid.
- @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
- PE/COFF image context for the Image given.
- @param[out] ImageExportDirectory A pointer to a pointer to the export directory found in the Image given.
-
- @retval EFI_SUCCESS The export directory was found successfully.
- @retval EFI_INVALID_PARAMETER A required parameter is NULL.
- @retval EFI_UNSUPPORTED The PE/COFF image given is not supported as a PRM Module.
- @retval EFI_NOT_FOUND The image export directory could not be found for this image.
-
-**/
-EFI_STATUS
-GetExportDirectoryInPeCoffImage (
- IN VOID *Image,
- IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
- OUT EFI_IMAGE_EXPORT_DIRECTORY **ImageExportDirectory
- )
-{
- UINT16 Magic;
- UINT32 NumberOfRvaAndSizes;
- EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION OptionalHeaderPtrUnion;
- EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
- EFI_IMAGE_EXPORT_DIRECTORY *ExportDirectory;
- EFI_IMAGE_SECTION_HEADER *SectionHeader;
-
- if (Image == NULL || PeCoffLoaderImageContext == NULL || ImageExportDirectory == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- DirectoryEntry = NULL;
- ExportDirectory = NULL;
-
- //
- // NOTE: For backward compatibility, use the Machine field to identify a PE32/PE32+
- // image instead of using the Magic field. Some systems might generate a PE32+
- // image with PE32 magic.
- //
- switch (PeCoffLoaderImageContext->Machine) {
- case EFI_IMAGE_MACHINE_IA32:
- // Todo: Add EFI_IMAGE_MACHINE_ARMT
- //
- // Assume PE32 image with IA32 Machine field.
- //
- Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
- break;
- case EFI_IMAGE_MACHINE_X64:
- //
- // Assume PE32+ image with X64 Machine field
- //
- Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
- break;
- default:
- //
- // For unknown Machine field, use Magic in optional header
- //
- DEBUG ((
- DEBUG_WARN,
- "%a %a: The machine type for this image is not valid for a PRM module.\n",
- _DBGMSGID_,
- __FUNCTION__
- ));
- return EFI_UNSUPPORTED;
- }
-
- OptionalHeaderPtrUnion.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (
- (UINTN) Image +
- PeCoffLoaderImageContext->PeCoffHeaderOffset
- );
-
- //
- // Check the PE/COFF Header Signature. Determine if the image is valid and/or a TE image.
- //
- if (OptionalHeaderPtrUnion.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
- DEBUG ((DEBUG_ERROR, "%a %a: The PE signature is not valid for the current image.\n", _DBGMSGID_, __FUNCTION__));
- return EFI_UNSUPPORTED;
- }
-
- SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
- (UINTN) Image +
- PeCoffLoaderImageContext->PeCoffHeaderOffset +
- sizeof (UINT32) +
- sizeof (EFI_IMAGE_FILE_HEADER) +
- PeCoffLoaderImageContext->SizeOfHeaders
- );
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
- //
- // Use the PE32 offset to get the Export Directory Entry
- //
- NumberOfRvaAndSizes = OptionalHeaderPtrUnion.Pe32->OptionalHeader.NumberOfRvaAndSizes;
- DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHeaderPtrUnion.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT]);
- } else if (OptionalHeaderPtrUnion.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
- //
- // Use the PE32+ offset get the Export Directory Entry
- //
- NumberOfRvaAndSizes = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
- DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT]);
- } else {
- return EFI_UNSUPPORTED;
- }
-
- if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_EXPORT || DirectoryEntry->VirtualAddress == 0) {
- //
- // The export directory is not present
- //
- return EFI_NOT_FOUND;
- } else if (((UINT32) (~0) - DirectoryEntry->VirtualAddress) < DirectoryEntry->Size) {
- //
- // The directory address overflows
- //
- DEBUG ((DEBUG_ERROR, "%a %a: The export directory entry in this image results in overflow.\n", _DBGMSGID_, __FUNCTION__));
- return EFI_UNSUPPORTED;
- } else {
- DEBUG ((DEBUG_INFO, "%a %a: Export Directory Entry found in the image at 0x%x.\n", _DBGMSGID_, __FUNCTION__, (UINTN) OptionalHeaderPtrUnion.Pe32));
- DEBUG ((DEBUG_INFO, " %a %a: Directory Entry Virtual Address = 0x%x.\n", _DBGMSGID_, __FUNCTION__, DirectoryEntry->VirtualAddress));
-
- ExportDirectory = (EFI_IMAGE_EXPORT_DIRECTORY *) ((UINTN) Image + DirectoryEntry->VirtualAddress);
- DEBUG ((
- DEBUG_INFO,
- " %a %a: Export Directory Table found successfully at 0x%x. Name address = 0x%x. Name = %a.\n",
- _DBGMSGID_,
- __FUNCTION__,
- (UINTN) ExportDirectory,
- ((UINTN) Image + ExportDirectory->Name),
- (CHAR8 *) ((UINTN) Image + ExportDirectory->Name)
- ));
- }
- *ImageExportDirectory = ExportDirectory;
-
- return EFI_SUCCESS;
-}
-
-/**
- Returns the image major and image minor version in a given PE/COFF image.
-
- @param[in] Image A pointer to a PE32/COFF image base address that is loaded into memory
- and already relocated to the memory base address. RVAs in the image given
- should be valid.
- @param[in] PeCoffLoaderImageContext A pointer to a PE_COFF_LOADER_IMAGE_CONTEXT structure that contains the
- PE/COFF image context for the Image given.
- @param[out] ImageMajorVersion A pointer to a UINT16 buffer to hold the image major version.
- @param[out] ImageMinorVersion A pointer to a UINT16 buffer to hold the image minor version.
-
- @retval EFI_SUCCESS The image version was read successfully.
- @retval EFI_INVALID_PARAMETER A required parameter is NULL.
- @retval EFI_UNSUPPORTED The PE/COFF image given is not supported.
-
-**/
-EFI_STATUS
-GetImageVersionInPeCoffImage (
- IN VOID *Image,
- IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext,
- OUT UINT16 *ImageMajorVersion,
- OUT UINT16 *ImageMinorVersion
- )
-{
- EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION OptionalHeaderPtrUnion;
- UINT16 Magic;
-
- DEBUG ((DEBUG_INFO, " %a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
-
- if (Image == NULL || PeCoffLoaderImageContext == NULL || ImageMajorVersion == NULL || ImageMinorVersion == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // NOTE: For backward compatibility, use the Machine field to identify a PE32/PE32+
- // image instead of using the Magic field. Some systems might generate a PE32+
- // image with PE32 magic.
- //
- switch (PeCoffLoaderImageContext->Machine) {
- case EFI_IMAGE_MACHINE_IA32:
- // Todo: Add EFI_IMAGE_MACHINE_ARMT
- //
- // Assume PE32 image with IA32 Machine field.
- //
- Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
- break;
- case EFI_IMAGE_MACHINE_X64:
- //
- // Assume PE32+ image with X64 Machine field
- //
- Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
- break;
- default:
- //
- // For unknown Machine field, use Magic in optional header
- //
- DEBUG ((
- DEBUG_WARN,
- "%a %a: The machine type for this image is not valid for a PRM module.\n",
- _DBGMSGID_,
- __FUNCTION__
- ));
- return EFI_UNSUPPORTED;
- }
-
- OptionalHeaderPtrUnion.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) (
- (UINTN) Image +
- PeCoffLoaderImageContext->PeCoffHeaderOffset
- );
- //
- // Check the PE/COFF Header Signature. Determine if the image is valid and/or a TE image.
- //
- if (OptionalHeaderPtrUnion.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
- DEBUG ((DEBUG_ERROR, "%a %a: The PE signature is not valid for the current image.\n", _DBGMSGID_, __FUNCTION__));
- return EFI_UNSUPPORTED;
- }
-
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
- //
- // Use the PE32 offset to get the Export Directory Entry
- //
- *ImageMajorVersion = OptionalHeaderPtrUnion.Pe32->OptionalHeader.MajorImageVersion;
- *ImageMinorVersion = OptionalHeaderPtrUnion.Pe32->OptionalHeader.MinorImageVersion;
- } else {
- //
- // Use the PE32+ offset to get the Export Directory Entry
- //
- *ImageMajorVersion = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.MajorImageVersion;
- *ImageMinorVersion = OptionalHeaderPtrUnion.Pe32Plus->OptionalHeader.MinorImageVersion;
- }
-
- DEBUG ((DEBUG_INFO, " %a %a - Image Major Version: 0x%02x.\n", _DBGMSGID_, __FUNCTION__, *ImageMajorVersion));
- DEBUG ((DEBUG_INFO, " %a %a - Image Minor Version: 0x%02x.\n", _DBGMSGID_, __FUNCTION__, *ImageMinorVersion));
-
- return EFI_SUCCESS;
-}
-
-/**
- Creates a new PRM Module Image Context linked list entry.
-
- @retval PrmModuleImageContextListEntry If successful, a pointer a PRM Module Image Context linked list entry
- otherwise, NULL is returned.
-
-**/
-STATIC
-PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *
-CreateNewPrmModuleImageContextListEntry (
- VOID
- )
-{
- PRM_MODULE_IMAGE_CONTEXT *PrmModuleImageContext;
- PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *PrmModuleImageContextListEntry;
-
- DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
-
- PrmModuleImageContext = AllocateZeroPool (sizeof (*PrmModuleImageContext));
- if (PrmModuleImageContext == NULL) {
- return NULL;
- }
- DEBUG ((
- DEBUG_INFO,
- " %a %a: Allocated PrmModuleImageContext at 0x%x of size 0x%x bytes.\n",
- _DBGMSGID_,
- __FUNCTION__,
- (UINTN) PrmModuleImageContext,
- sizeof (*PrmModuleImageContext)
- ));
-
- PrmModuleImageContextListEntry = AllocateZeroPool (sizeof (*PrmModuleImageContextListEntry));
- if (PrmModuleImageContextListEntry == NULL) {
- FreePool (PrmModuleImageContext);
- return NULL;
- }
- DEBUG ((
- DEBUG_INFO,
- " %a %a: Allocated PrmModuleImageContextListEntry at 0x%x of size 0x%x bytes.\n",
- _DBGMSGID_,
- __FUNCTION__,
- (UINTN) PrmModuleImageContextListEntry,
- sizeof (*PrmModuleImageContextListEntry)
- ));
-
- PrmModuleImageContextListEntry->Signature = PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE;
- PrmModuleImageContextListEntry->Context = PrmModuleImageContext;
-
- return PrmModuleImageContextListEntry;
-}
-
-/**
- Discovers all PRM Modules loaded during the DXE boot phase.
-
- Each PRM Module discovered is placed into a linked list so the list can br processsed in the future.
-
- @retval EFI_SUCCESS All PRM Modules were discovered successfully.
- @retval EFI_NOT_FOUND The gEfiLoadedImageProtocolGuid protocol could not be found.
- @retval EFI_OUT_OF_RESOURCES Insufficient memory resources to allocate the new PRM Context
- linked list nodes.
-
-**/
-EFI_STATUS
-DiscoverPrmModules (
- VOID
- )
-{
- EFI_STATUS Status;
- PRM_MODULE_IMAGE_CONTEXT TempPrmModuleImageContext;
- PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *PrmModuleImageContextListEntry;
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
-
- DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
-
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiLoadedImageProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (EFI_ERROR (Status) && (HandleCount == 0)) {
- DEBUG ((DEBUG_ERROR, "%a %a: No LoadedImageProtocol instances found!\n", _DBGMSGID_, __FUNCTION__));
- return EFI_NOT_FOUND;
- }
-
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiLoadedImageProtocolGuid,
- (VOID **) &LoadedImageProtocol
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- ZeroMem (&TempPrmModuleImageContext, sizeof (TempPrmModuleImageContext));
- TempPrmModuleImageContext.PeCoffImageContext.Handle = LoadedImageProtocol->ImageBase;
- TempPrmModuleImageContext.PeCoffImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
-
- Status = PeCoffLoaderGetImageInfo (&TempPrmModuleImageContext.PeCoffImageContext);
- if (EFI_ERROR (Status) || TempPrmModuleImageContext.PeCoffImageContext.ImageError != IMAGE_ERROR_SUCCESS) {
- DEBUG ((
- DEBUG_WARN,
- "%a %a: ImageHandle 0x%016lx is not a valid PE/COFF image. It cannot be considered a PRM module.\n",
- _DBGMSGID_,
- __FUNCTION__,
- (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImageProtocol->ImageBase
- ));
- continue;
- }
- if (TempPrmModuleImageContext.PeCoffImageContext.IsTeImage) {
- // A PRM Module is not allowed to be a TE image
- continue;
- }
-
- // Attempt to find an export table in this image
- Status = GetExportDirectoryInPeCoffImage (
- LoadedImageProtocol->ImageBase,
- &TempPrmModuleImageContext.PeCoffImageContext,
- &TempPrmModuleImageContext.ExportDirectory
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- // Attempt to find the PRM Module Export Descriptor in the export table
- Status = GetPrmModuleExportDescriptorTable (
- TempPrmModuleImageContext.ExportDirectory,
- &TempPrmModuleImageContext.PeCoffImageContext,
- &TempPrmModuleImageContext.ExportDescriptor
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
- // A PRM Module Export Descriptor was successfully found, this is considered a PRM Module.
-
- //
- // Create a new PRM Module image context node
- //
- PrmModuleImageContextListEntry = CreateNewPrmModuleImageContextListEntry ();
- if (PrmModuleImageContextListEntry == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- CopyMem (
- PrmModuleImageContextListEntry->Context,
- &TempPrmModuleImageContext,
- sizeof (*(PrmModuleImageContextListEntry->Context))
- );
- InsertTailList (&mPrmModuleList, &PrmModuleImageContextListEntry->Link);
- mPrmHandlerCount += TempPrmModuleImageContext.ExportDescriptor->Header.NumberPrmHandlers;
- mPrmModuleCount++; // Todo: Match with global variable refactor change in the future
- DEBUG ((DEBUG_INFO, "%a %a: New PRM Module inserted into list to be processed.\n", _DBGMSGID_, __FUNCTION__));
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Gets the address of an entry in an image export table by ASCII name.
-
- @param[in] ExportName A pointer to an ASCII name string of the entry name.
- @param[in] ImageBaseAddress The base address of the PE/COFF image.
- @param[in] ImageExportDirectory A pointer to the export directory in the image.
- @param[out] ExportPhysicalAddress A pointer that will be updated with the address of the address of the
- export entry if found.
-
- @retval EFI_SUCCESS The export entry was found successfully.
- @retval EFI_INVALID_PARAMETER A required pointer argument is NULL.
- @retval EFI_NOT_FOUND An entry with the given ExportName was not found.
-
-**/
-EFI_STATUS
-GetExportEntryAddress (
- IN CONST CHAR8 *ExportName,
- IN EFI_PHYSICAL_ADDRESS ImageBaseAddress,
- IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory,
- OUT EFI_PHYSICAL_ADDRESS *ExportPhysicalAddress
- )
-{
- UINTN ExportNameIndex;
- UINT16 CurrentExportOrdinal;
- UINT32 *ExportAddressTable;
- UINT32 *ExportNamePointerTable;
- UINT16 *OrdinalTable;
- CONST CHAR8 *ExportNameTablePointerName;
-
- if (ExportName == NULL || ImageBaseAddress == 0 || ImageExportDirectory == NULL || ExportPhysicalAddress == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- *ExportPhysicalAddress = 0;
-
- ExportAddressTable = (UINT32 *) ((UINTN) ImageBaseAddress + ImageExportDirectory->AddressOfFunctions);
- ExportNamePointerTable = (UINT32 *) ((UINTN) ImageBaseAddress + ImageExportDirectory->AddressOfNames);
- OrdinalTable = (UINT16 *) ((UINTN) ImageBaseAddress + ImageExportDirectory->AddressOfNameOrdinals);
-
- for (ExportNameIndex = 0; ExportNameIndex < ImageExportDirectory->NumberOfNames; ExportNameIndex++) {
- ExportNameTablePointerName = (CONST CHAR8 *) ((UINTN) ImageBaseAddress + ExportNamePointerTable[ExportNameIndex]);
-
- if (AsciiStrnCmp (ExportName, ExportNameTablePointerName, PRM_HANDLER_NAME_MAXIMUM_LENGTH) == 0) {
- CurrentExportOrdinal = OrdinalTable[ExportNameIndex];
-
- ASSERT (CurrentExportOrdinal < ImageExportDirectory->NumberOfFunctions);
- if (CurrentExportOrdinal >= ImageExportDirectory->NumberOfFunctions) {
- DEBUG ((DEBUG_ERROR, " %a %a: The export ordinal value is invalid.\n", _DBGMSGID_, __FUNCTION__));
- break;
- }
-
- *ExportPhysicalAddress = (EFI_PHYSICAL_ADDRESS) ((UINTN) ImageBaseAddress + ExportAddressTable[CurrentExportOrdinal]);
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
+UINTN mPrmHandlerCount;
+UINTN mPrmModuleCount;
/**
Processes a list of PRM context entries to build a PRM ACPI table.
@@ -616,9 +54,8 @@ ProcessPrmModules (
{
EFI_IMAGE_EXPORT_DIRECTORY *CurrentImageExportDirectory;
PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *CurrentExportDescriptorStruct;
- LIST_ENTRY *Link;
PRM_ACPI_DESCRIPTION_TABLE *PrmAcpiTable;
- PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *TempListEntry;
+ PRM_MODULE_IMAGE_CONTEXT *CurrentPrmModuleImageContext;
CONST CHAR8 *CurrentExportDescriptorHandlerName;
ACPI_PARAMETER_BUFFER_DESCRIPTOR *CurrentModuleAcpiParamDescriptors;
@@ -640,13 +77,12 @@ ProcessPrmModules (
if (PrmAcpiDescriptionTable == NULL) {
return EFI_INVALID_PARAMETER;
}
- Link = NULL;
*PrmAcpiDescriptionTable = NULL;
DEBUG ((DEBUG_INFO, " %a %a: %d total PRM modules to process.\n", _DBGMSGID_, __FUNCTION__, mPrmModuleCount));
DEBUG ((DEBUG_INFO, " %a %a: %d total PRM handlers to process.\n", _DBGMSGID_, __FUNCTION__, mPrmHandlerCount));
- PrmAcpiDescriptionTableBufferSize = (OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure) +
+ PrmAcpiDescriptionTableBufferSize = (UINT32) (OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure) +
(OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) * mPrmModuleCount) +
(sizeof (PRM_HANDLER_INFORMATION_STRUCT) * mPrmHandlerCount)
);
@@ -667,18 +103,20 @@ ProcessPrmModules (
PrmAcpiTable->Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
PrmAcpiTable->Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
PrmAcpiTable->PrmModuleInfoOffset = OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure);
- PrmAcpiTable->PrmModuleInfoCount = mPrmModuleCount;
+ PrmAcpiTable->PrmModuleInfoCount = (UINT32) mPrmModuleCount;
//
// Iterate across all PRM Modules on the list
//
CurrentModuleInfoStruct = &PrmAcpiTable->PrmModuleInfoStructure[0];
- EFI_LIST_FOR_EACH(Link, &mPrmModuleList)
- {
- TempListEntry = CR(Link, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY, Link, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE);
- CurrentImageAddress = TempListEntry->Context->PeCoffImageContext.ImageAddress;
- CurrentImageExportDirectory = TempListEntry->Context->ExportDirectory;
- CurrentExportDescriptorStruct = TempListEntry->Context->ExportDescriptor;
+ for (
+ CurrentPrmModuleImageContext = NULL, Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext);
+ !EFI_ERROR (Status);
+ Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext)) {
+
+ CurrentImageAddress = CurrentPrmModuleImageContext->PeCoffImageContext.ImageAddress;
+ CurrentImageExportDirectory = CurrentPrmModuleImageContext->ExportDirectory;
+ CurrentExportDescriptorStruct = CurrentPrmModuleImageContext->ExportDescriptor;
CurrentModuleAcpiParamDescriptors = NULL;
DEBUG ((
@@ -703,7 +141,7 @@ ProcessPrmModules (
CurrentModuleInfoStruct->MinorRevision = 0;
Status = GetImageVersionInPeCoffImage (
(VOID *) (UINTN) CurrentImageAddress,
- &TempListEntry->Context->PeCoffImageContext,
+ &CurrentPrmModuleImageContext->PeCoffImageContext,
&CurrentModuleInfoStruct->MajorRevision,
&CurrentModuleInfoStruct->MinorRevision
);
@@ -863,9 +301,7 @@ PrmLoaderEndOfDxeNotification (
DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
- InitializeListHead (&mPrmModuleList);
-
- Status = DiscoverPrmModules ();
+ Status = DiscoverPrmModules (&mPrmModuleCount, &mPrmHandlerCount);
ASSERT_EFI_ERROR (Status);
Status = ProcessPrmModules (&PrmAcpiDescriptionTable);
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
index 4d959ccd35..554d49685e 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
@@ -22,7 +22,6 @@
[Sources]
PrmAcpiTable.h
- PrmLoader.h
PrmLoaderDxe.c
[Packages]
@@ -39,8 +38,9 @@
DebugLib
MemoryAllocationLib
PcdLib
- PeCoffLib
PrmContextBufferLib
+ PrmModuleDiscoveryLib
+ PrmPeCoffLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
@@ -54,7 +54,6 @@
[Protocols]
gEfiAcpiTableProtocolGuid
- gEfiLoadedImageProtocolGuid
gPrmConfigProtocolGuid
[Depex]
diff --git a/PrmPkg/PrmPkg.dec b/PrmPkg/PrmPkg.dec
index ff681d423d..785e2c24c2 100644
--- a/PrmPkg/PrmPkg.dec
+++ b/PrmPkg/PrmPkg.dec
@@ -36,6 +36,14 @@
#
PrmContextBufferLib|Include/Library/PrmContextBufferLib.h
+ ## @libraryclass Provides functionality to discover PRM modules installed by platform firmware
+ #
+ PrmModuleDiscoveryLib|Include/Library/PrmModuleDiscoveryLib.h
+
+ ## @libraryclass Provides additional PE/COFF functionality needed to support the Platform Runtime Mechanism (PRM) loader driver.
+ #
+ PrmPeCoffLib|Include/Library/PrmPeCoffLib.h
+
[Protocols]
## PRM Configuration Protocol
#
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index 19b996eb3a..e876f2053a 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -55,6 +55,9 @@
# PRM Package
#
PrmContextBufferLib|$(PLATFORM_PACKAGE)/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
+ PrmModuleDiscoveryLib|$(PLATFORM_PACKAGE)/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
+ PrmPeCoffLib|$(PLATFORM_PACKAGE)/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
+
###################################################################################################
#
@@ -73,6 +76,16 @@
$(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
#
+ # PRM Module Discovery Library
+ #
+ $(PLATFORM_PACKAGE)/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
+
+ #
+ # PRM PE/COFF Library
+ #
+ $(PLATFORM_PACKAGE)/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
+
+ #
# PRM Configuration Driver
#
$(PLATFORM_PACKAGE)/PrmConfigDxe/PrmConfigDxe.inf {