public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v1 00/41] Add PrmPkg
@ 2022-03-22 16:19 Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 01/41] PrmPkg: Add package and include headers Michael Kubacki
                   ` (40 more replies)
  0 siblings, 41 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

This patch series adds a new package called PrmPkg. An RFC was sent
to the edk2 mailing list on January 28, 2022 detailing the proposal,
see https://edk2.groups.io/g/devel/message/86181.

Platform Runtime Mechanism (PRM) is a new firmware solution that has
been developed in edk2-staging/PlatformRuntimeMechanism.

This patch series has been organized to greatly condense the history
from the edk2-staging branch but to preserve important decisions and
changes in history that help establish context of changes and will
serve as valuable references for future development.

Interest in PRM has increased across various vendors and we believe
it is beneficial to make the source code more widely available for
the following reasons:

  1. PRM specification adoption
  2. Feature completeness
  3. Overall validation coverage
  4. Interest from the community and future collaboration

The technical details of PRM are covered in the PRM Specification
in addition to the Readme.md file located in the root of PrmPkg
in this patch series.

1. PRM specification adoption

Intel and Microsoft have worked together to standardize PRM in the
ACPI Specification and the PRM Specification hosted on uefi.org.

  * ACPI 6.4 Specification:
  https://uefi.org/node/4149

  * PRM Specification:
  https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mechanism%20-%20with%20legal%20notice.pdf

2. Feature completeness

PrmPkg implements the full firmware functionality described in the
PRM Specification and there are no significant changes to
functionality planned at this time.

Though we are very much interested in evolving PRM based on
feedback.

3. Overall validation coverage

PrmPkg has been integrated and tested on client and server systems
in addition to virtual platforms (OvmfPkg/QEMU).

Platform integration is simple and a demonstration of this
integration for OvmfPkg is available in the following branch:
https://github.com/makubacki/edk2/tree/ovmf_prmpkg_integration

The code has been built with:
  * MSFT VS2015, VS2017, and VS2019
  * GCC5 (see https://bugzilla.tianocore.org/show_bug.cgi?id=3802)
  * iASL compiler (20200528 - https://acpica.org/node/181)

The Linux kernel currently includes the following PRM support:
  * _OSC PRM bit - allows FW to know determine the OS is
    PRM-capable and can redirect _DSM method from alternate
    triggers (such as SMI) to PRM.
  * PRM invocation via _DSM, includes PRM module and handler parsing
    from ACPI PRMT table, and also the PRM operation region handler
    for runtime PRM service invocation.
  * An OS configuration for PRM enabling, PRM support can be
    disabled during OS image build.

Note that upstream Linux does not currently support the following:
  * Ability for the OS driver to call a PRM handler directly,
    it has to be via ACPI _DSM.
  * Run time update PRM module and handler via PE/COFF PRM image.

This commit provides additional context of the changes in Linux:
https://github.com/torvalds/linux/commit/cefc7ca46235f01d5233e3abd4b79452af01d9e9

Windows 11 (https://www.microsoft.com/software-download/windows11)
and Windows Server 2022 (https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk)
include the PRM functionality noted above in addition to PRM direct
call and PRM runtime updates.

PRM has been tested on IA32, X64, and AARCH64 targets.

4. Interest from the community and future collaboration

PRM has been presented at several industry conferences:

* OSFC 2020 - "PRM: SMM Goes on a Diet"
  https://cfp.osfc.io/osfc2020/talk/MCJASB/

* OCP Summit 2019 - "Case Study Alternatives for SMM Usage in
  Intel Platforms"
  https://www.youtube.com/watch?v=mu3DRLM1dPA
  
In addition, Microsoft plans to publish the Windows PRM driver
interface and a WDF sample driver that uses the interface to the
Windows Driver Samples GitHub repository
(https://github.com/microsoft/Windows-driver-samples).

We believe a PrmPkg in edk2 can increase accessibility to PRM and
ease collaboration.

PrmPkg
------
PrmPkg contains the common functionality needed to enable PRM on
any system. It does not contain platform-specific code such as PRM
modules (and by extension PRM handlers). Other than sample modules,
PrmPkg will only contain code needed to provide PRM feature
functionality as defined in the PRM Specification.

PrmPkg is scoped to continue to only contain platform-agnostic
functionality in the future.

The proposed maintainers of PrmPkg are:
* Michael Kubacki <mikuback@linux.microsoft.com>
* Nate DeSimone <nathaniel.l.desimone@intel.com>

The proposed reviewers of PrmPkg are:
* Ankit Sinha <ankit.sinha@intel.com>

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>

Liu (2):
  PrmPkg: Publish PRM operation region to support PRM ACPI _DSM
    invocation
  PrmPkg: Export major/minor version in PRM module PE COFF header

Liu Yun Y (1):
  PrmPkg: Update PRM OpRegion

Michael Kubacki (38):
  PrmPkg: Add package and include headers
  PrmPkg: Add PrmConfig protocol interface
  PrmPkg/PrmContextBufferLib: Add initial library instance
  PrmPkg/PrmConfigDxe: Add initial driver
  PrmPkg: Add initial PrmSamplePrintModule
  PrmPkg: Add initial PrmSampleMemoryAllocationModule
  PrmPkg: Add initial PrmSampleHardwareAccessModule
  PrmPkg: Add initial PrmSampleContextBufferModule
  PrmPkg: Add initial package DSC file
  Readme.md: Add initial content
  PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option
  PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro
  PrmPkg: Add initial PrmSsdtInstallDxe module
  PrmPkg: Remove PRM Module Update Lock
  PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag
  PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures
  PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support
  PrmPkg/PrmSampleContextBufferModule: Remove OS debug print requirement
  PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM handlers
  PrmPkg/SampleAcpiParameterBufferModule: Add initial module
  PrmPkg/HardwareAccessModuleConfigLib: Add initial library
  PrmPkg/Samples/Readme.md: Add initial file
  PrmPkg: Refactor some PrmLoaderDxe functionality into libraries
  PrmPkg/Application/PrmInfo: Add initial application
  PrmPkg: Enforce stricter types
  PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file
  PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib
  PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests
  PrmPkg/DxePrmModuleDiscoveryLib: Add initial host-based unit tests
  PrmPkg: Add PlatformGuid
  Readme.md: Add iASL note and QEMU sample link
  PrmPkg: Replace PcdPrmPlatformGuid with EDKII_DSC_PLATFORM_GUID
  PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule
  PrmPkg/Samples: Remove PrmSamplePrintModule
  PrmPkg: Remove the concept of OS services
  Readme.md: Add a link to PRM Specification
  PrmPkg: Changes for edk2 repo transition
  PrmPkg: Apply uncrustify changes

 PrmPkg/Application/PrmInfo/PrmInfo.c                                                                                                      |  732 +++++++++
 PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c                                                                            |  199 +++
 PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTest.c                                                           |  649 ++++++++
 PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c                                                                        |  386 +++++
 PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTest.c                                                       |  210 +++
 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c                                                                                          |  417 +++++
 PrmPkg/PrmConfigDxe/PrmConfigDxe.c                                                                                                        |  512 ++++++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c                                                                                                        |  377 +++++
 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c                                                                                              |  110 ++
 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c   |  127 ++
 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.c                                                    |   78 +
 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c                     |  218 +++
 PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c                                                                |   84 +
 PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c                  |  108 ++
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c                                                              |  335 ++++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.c                                          |  119 ++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestEventTimer.c                                |  180 +++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestImage.c                                     |  163 ++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMemory.c                                    |  145 ++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMisc.c                                      |  198 +++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.c                                  | 1650 ++++++++++++++++++++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestTpl.c                                       |   43 +
 .azurepipelines/templates/pr-gate-build-job.yml                                                                                           |    2 +-
 .pytool/CISettings.py                                                                                                                     |    1 +
 Maintainers.txt                                                                                                                           |    8 +
 PrmPkg/Application/PrmInfo/PrmInfo.h                                                                                                      |   49 +
 PrmPkg/Application/PrmInfo/PrmInfo.inf                                                                                                    |   66 +
 PrmPkg/Application/PrmInfo/PrmInfo.uni                                                                                                    |   11 +
 PrmPkg/Application/PrmInfo/PrmInfoExtra.uni                                                                                               |   12 +
 PrmPkg/Application/PrmInfo/PrmInfoStrings.uni                                                                                             |  132 ++
 PrmPkg/Include/Library/PrmContextBufferLib.h                                                                                              |   99 ++
 PrmPkg/Include/Library/PrmModuleDiscoveryLib.h                                                                                            |   60 +
 PrmPkg/Include/Library/PrmPeCoffLib.h                                                                                                     |  111 ++
 PrmPkg/Include/Prm.h                                                                                                                      |   46 +
 PrmPkg/Include/PrmContextBuffer.h                                                                                                         |  171 ++
 PrmPkg/Include/PrmDataBuffer.h                                                                                                            |   50 +
 PrmPkg/Include/PrmExportDescriptor.h                                                                                                      |  109 ++
 PrmPkg/Include/PrmMmio.h                                                                                                                  |   45 +
 PrmPkg/Include/PrmModule.h                                                                                                                |   47 +
 PrmPkg/Include/PrmModuleImageContext.h                                                                                                    |   28 +
 PrmPkg/Include/Protocol/PrmConfig.h                                                                                                       |   31 +
 PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf                                                                          |   35 +
 PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTestHost.inf                                                     |   46 +
 PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf                                                                      |   41 +
 PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h                                                                              |   39 +
 PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTestHost.inf                                                 |   39 +
 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf                                                                                        |   32 +
 PrmPkg/PrmConfigDxe/PrmConfigDxe.inf                                                                                                      |   48 +
 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h                                                                                                        |   96 ++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf                                                                                                      |   61 +
 PrmPkg/PrmPkg.ci.yaml                                                                                                                     |  110 ++
 PrmPkg/PrmPkg.dec                                                                                                                         |   67 +
 PrmPkg/PrmPkg.dsc                                                                                                                         |  142 ++
 PrmPkg/PrmPkg.uni                                                                                                                         |   10 +
 PrmPkg/PrmSsdtInstallDxe/Prm.asl                                                                                                          |  115 ++
 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf                                                                                            |   52 +
 PrmPkg/Readme.md                                                                                                                          |  264 ++++
 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf |   39 +
 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf                                                  |   41 +
 PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h                                                                          |   24 +
 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf                   |   39 +
 PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf                                                              |   44 +
 PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h                                                                                       |  108 ++
 PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf                |   39 +
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf                                                            |   43 +
 PrmPkg/Samples/Readme.md                                                                                                                  |  146 ++
 PrmPkg/Test/PrmPkgHostTest.dsc                                                                                                            |   39 +
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibTest.uni                                            |   12 +
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.h                                          | 1042 ++++++++++++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf                                        |   46 +
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.h                                  |  120 ++
 71 files changed, 11096 insertions(+), 1 deletion(-)
 create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.c
 create mode 100644 PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
 create mode 100644 PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTest.c
 create mode 100644 PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
 create mode 100644 PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTest.c
 create mode 100644 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
 create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.c
 create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
 create mode 100644 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
 create mode 100644 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c
 create mode 100644 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.c
 create mode 100644 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
 create mode 100644 PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c
 create mode 100644 PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
 create mode 100644 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.c
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestEventTimer.c
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestImage.c
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMemory.c
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMisc.c
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.c
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestTpl.c
 create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.h
 create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.inf
 create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.uni
 create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
 create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
 create mode 100644 PrmPkg/Include/Library/PrmContextBufferLib.h
 create mode 100644 PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
 create mode 100644 PrmPkg/Include/Library/PrmPeCoffLib.h
 create mode 100644 PrmPkg/Include/Prm.h
 create mode 100644 PrmPkg/Include/PrmContextBuffer.h
 create mode 100644 PrmPkg/Include/PrmDataBuffer.h
 create mode 100644 PrmPkg/Include/PrmExportDescriptor.h
 create mode 100644 PrmPkg/Include/PrmMmio.h
 create mode 100644 PrmPkg/Include/PrmModule.h
 create mode 100644 PrmPkg/Include/PrmModuleImageContext.h
 create mode 100644 PrmPkg/Include/Protocol/PrmConfig.h
 create mode 100644 PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
 create mode 100644 PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTestHost.inf
 create mode 100644 PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
 create mode 100644 PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
 create mode 100644 PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTestHost.inf
 create mode 100644 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
 create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
 create mode 100644 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
 create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
 create mode 100644 PrmPkg/PrmPkg.ci.yaml
 create mode 100644 PrmPkg/PrmPkg.dec
 create mode 100644 PrmPkg/PrmPkg.dsc
 create mode 100644 PrmPkg/PrmPkg.uni
 create mode 100644 PrmPkg/PrmSsdtInstallDxe/Prm.asl
 create mode 100644 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
 create mode 100644 PrmPkg/Readme.md
 create mode 100644 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
 create mode 100644 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf
 create mode 100644 PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
 create mode 100644 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
 create mode 100644 PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
 create mode 100644 PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
 create mode 100644 PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
 create mode 100644 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
 create mode 100644 PrmPkg/Samples/Readme.md
 create mode 100644 PrmPkg/Test/PrmPkgHostTest.dsc
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibTest.uni
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.h
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
 create mode 100644 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.h

-- 
2.28.0.windows.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v1 01/41] PrmPkg: Add package and include headers
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 02/41] PrmPkg: Add PrmConfig protocol interface Michael Kubacki
                   ` (39 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

Adds a new package to maintain Platform Runtime Mechanism (PRM)
support.

This package is intended to include generic code that provides a
common infrastructure to support PRM in firmware and a collection
of sample PRM modules that demonstrate how to use the interfaces
and other package resources to author a PRM module.

The following initial headers are included in this commit:

* Prm.h - Includes common content for PRM with no dependencies on
  other PRM header files.

* PrmContextBuffer.h - Includes definitions for PRM context buffers.

  Context buffers are standardized structures that point to various
  resources available to a PRM handler during its execution.

* PrmDataBuffer.h - Includes definitions for PRM data buffers.

  Within the context of PRM, these data buffers are composed of a
  generic header followed by a variable length blob of arbitrary
  data.

* PrmExportDescriptor.h - Includes definitions for  creating PRM
  export descriptors.

  A PRM export descriptor is a structure referenced in the export
  table of PRM module that contains PRM-specific metadata about the
  module.

* PrmMmio.h - Includes definitions for describing MMIO ranges uses
  by PRM modules.

* PrmModule.h - Includes definitions commonly used by PRM module
  authors.

  This file is provided to serve as a convenient include for PRM
  module authors.

* PrmOsServices.h - Includes content specific to PRM OS services.

  OS Services will not planned to be present in the final version
  of PRM. The OS Services have been reduced to a simple debug print
  function. So this is currently planned to be a temporary file to
  support debugging during PRM development.

Note: Modules built for the UEFI environment can be built by Visual
      Studio and non-Visual Studio toolchains. However, PRM modules
      are currently only supported on Visual Studio toolchain due to
      usage of export tables.

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>
---
 PrmPkg/Include/Prm.h                 |  46 +++++++
 PrmPkg/Include/PrmContextBuffer.h    | 131 ++++++++++++++++++++
 PrmPkg/Include/PrmDataBuffer.h       |  50 ++++++++
 PrmPkg/Include/PrmExportDescriptor.h |  87 +++++++++++++
 PrmPkg/Include/PrmMmio.h             |  45 +++++++
 PrmPkg/Include/PrmModule.h           |  68 ++++++++++
 PrmPkg/Include/PrmModuleUpdate.h     |  46 +++++++
 PrmPkg/Include/PrmOsServices.h       |  45 +++++++
 PrmPkg/PrmPkg.dec                    |  49 ++++++++
 PrmPkg/PrmPkg.uni                    |  10 ++
 10 files changed, 577 insertions(+)

diff --git a/PrmPkg/Include/Prm.h b/PrmPkg/Include/Prm.h
new file mode 100644
index 000000000000..0e3ccfffa333
--- /dev/null
+++ b/PrmPkg/Include/Prm.h
@@ -0,0 +1,46 @@
+/** @file
+
+  Common Platform Runtime Mechanism (PRM) definitions.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_H_
+#define PRM_H_
+
+#include <Uefi.h>
+#include <PrmContextBuffer.h>
+
+#if defined(_MSC_VER)
+  #define PRM_EXPORT_API                          __declspec(dllexport)
+#else
+  #define PRM_EXPORT_API
+#endif
+
+#define PRM_HANDLER_NAME_MAXIMUM_LENGTH           128
+
+#define PRM_STRING_(x)                            #x
+#define PRM_STRING(x)                             PRM_STRING_(x)
+
+/**
+  A Platform Runtime Mechanism (PRM) handler function.
+
+  @param[in]  ParameterBuffer             A pointer to a buffer with arbitrary data that is allocated and populated
+                                          by the PRM handler caller.
+  @param[in]  ContextBuffer               A pointer to a buffer with arbitrary data that is allocated in the firmware
+                                          boot environment.
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI PRM_HANDLER) (
+  IN VOID                 *ParameterBuffer  OPTIONAL,
+  IN PRM_CONTEXT_BUFFER   *ContextBuffer  OPTIONAL
+  );
+
+#endif
diff --git a/PrmPkg/Include/PrmContextBuffer.h b/PrmPkg/Include/PrmContextBuffer.h
new file mode 100644
index 000000000000..8f8144545e64
--- /dev/null
+++ b/PrmPkg/Include/PrmContextBuffer.h
@@ -0,0 +1,131 @@
+/** @file
+
+  Definitions for the Platform Runtime Mechanism (PRM) context buffer structures.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_CONTEXT_BUFFER_H_
+#define PRM_CONTEXT_BUFFER_H_
+
+#include <PrmDataBuffer.h>
+#include <PrmMmio.h>
+#include <Uefi.h>
+
+#define PRM_CONTEXT_BUFFER_SIGNATURE          SIGNATURE_32('P','R','M','C')
+#define PRM_CONTEXT_BUFFER_INTERFACE_VERSION  1
+
+#pragma pack(push, 1)
+
+//
+// This is the context buffer structure that is passed to a PRM handler.
+//
+// At OS runtime, the OS will allocate and populate this structure and
+// place virtual addresses in the pointer fields.
+//
+// It is also reused internally in FW (in the PRM_MODULE_CONTEXT_BUFFERS structure)
+// to track context buffers within a given PRM module. In that internal usage,
+// the addresses will be physical addresses.
+//
+typedef struct {
+  ///
+  /// Signature of this interface.
+  ///
+  UINT32                                  Signature;
+
+  ///
+  /// Version of this interface.
+  ///
+  UINT16                                  Version;
+
+  ///
+  /// Reserved field.
+  ///
+  UINT16                                  Reserved;
+
+  ///
+  /// The GUID of the PRM handler represented by this context instance.
+  ///
+  EFI_GUID                                HandlerGuid;
+
+  ///
+  /// A virtual address pointer to the static data buffer allocated for
+  /// the PRM handler represented by this context instance.
+  ///
+  /// The static buffer is intended to be populated in the PRM module
+  /// configuration library and treated as read-only data at OS runtime.
+  ///
+  /// This pointer may be NULL if a static data buffer is not needed.
+  ///
+  PRM_DATA_BUFFER                         *StaticDataBuffer;
+
+  ///
+  /// A virtual address pointer to an array of PRM_RUNTIME_MMIO_RANGE
+  /// structures that describe MMIO physical address ranges mapped to
+  /// virtual memory addresses for access at OS runtime.
+  ///
+  /// This pointer is ignored in firmware internal usage of this structure
+  /// as this field is present to allow a PRM handler to get the list
+  /// of MMIO ranges described as accessible by its PRM module.
+  ///
+  /// The module list of MMIO ranges is specified by the PRM configuration
+  /// code as a single array in PRM_MODULE_CONTEXT_BUFFERS.
+  ///
+  /// The OS is responsible for ensuring the pointer to the array in this
+  /// structure is converted to a virtual address during construction of
+  /// of the context buffer in the OS.
+  ///
+  /// This pointer may be NULL if runtime memory ranges are not needed.
+  ///
+  PRM_RUNTIME_MMIO_RANGES                 *RuntimeMmioRanges;
+} PRM_CONTEXT_BUFFER;
+
+//
+// A firmware internal data structure used to track context buffer and
+// runtime MMIO range usage across a PRM module.
+//
+typedef struct
+{
+  ///
+  /// The GUID of the PRM module.
+  ///
+  EFI_GUID                                ModuleGuid;
+
+  ///
+  /// The number of PRM context buffers in ContextBuffers[].
+  /// This count should equal the number of PRM handlers in the module being configured.
+  ///
+  UINTN                                   BufferCount;
+
+  ///
+  /// A pointer to an array of PRM context buffers
+  ///
+  PRM_CONTEXT_BUFFER                      *Buffer;
+
+  /// The MMIO ranges are defined in the firmware boot environment.
+  /// The addresses within the PRM_RUNTIME_MMIO_RANGES structure will
+  /// be converted to virtual addresses by firmware.
+
+  ///
+  /// A physical address pointer to an array of PRM_RUNTIME_MMIO_RANGE
+  /// structures that describe memory ranges that need to be mapped to
+  /// virtual memory addresses for access at OS runtime.
+  ///
+  /// This is a consolidated array of MMIO ranges accessed by any PRM
+  /// handler in the PRM module at OS runtime. The MMIO range physical
+  /// addresses registered here will automatically be converted to the
+  /// corresponding virtual address in the structure by PRM infrastructure
+  /// code. No action is required to convert MMIO range base physical
+  /// addresses to virtual addresses by either the PRM configuration code
+  /// or the OS.
+  ///
+  /// This pointer may be NULL if runtime memory ranges are not needed.
+  ///
+  PRM_RUNTIME_MMIO_RANGES                 *RuntimeMmioRanges;
+} PRM_MODULE_CONTEXT_BUFFERS;
+
+#pragma pack(pop)
+
+#endif
diff --git a/PrmPkg/Include/PrmDataBuffer.h b/PrmPkg/Include/PrmDataBuffer.h
new file mode 100644
index 000000000000..70d690ca5446
--- /dev/null
+++ b/PrmPkg/Include/PrmDataBuffer.h
@@ -0,0 +1,50 @@
+/** @file
+
+  Definitions for the Platform Runtime Mechanism (PRM) data buffer structures.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_DATA_BUFFER_H_
+#define PRM_DATA_BUFFER_H_
+
+#include <Uefi.h>
+
+#define PRM_DATA_BUFFER_HEADER_SIGNATURE      SIGNATURE_32('P','R','M','D')
+
+#pragma pack(push, 1)
+
+///
+/// A generic header that describes the PRM data buffer.
+///
+typedef struct {
+  ///
+  /// PRM Data Buffer signature.
+  ///
+  UINT32                                  Signature;
+  ///
+  /// Length of the entire data buffer, including the size of the header.
+  ///
+  UINT32                                  Length;
+} PRM_DATA_BUFFER_HEADER;
+
+///
+/// A PRM data buffer is a generic header followed by variable length arbitrary data.
+///
+typedef struct {
+  ///
+  /// The header is required at the beginning of every PRM data buffer.
+  ///
+  PRM_DATA_BUFFER_HEADER                  Header;
+
+  ///
+  /// The beginning of data immediately follows the header.
+  ///
+  UINT8                                   Data[1];
+} PRM_DATA_BUFFER;
+
+#pragma pack(pop)
+
+#endif
diff --git a/PrmPkg/Include/PrmExportDescriptor.h b/PrmPkg/Include/PrmExportDescriptor.h
new file mode 100644
index 000000000000..95198cef659c
--- /dev/null
+++ b/PrmPkg/Include/PrmExportDescriptor.h
@@ -0,0 +1,87 @@
+/** @file
+
+  Definitions for the Platform Runtime Mechanism (PRM) export descriptor structures.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_EXPORT_DESCRIPTOR_H_
+#define PRM_EXPORT_DESCRIPTOR_H_
+
+#include <Prm.h>
+
+#define PRM_MODULE_EXPORT_DESCRIPTOR_NAME         PrmModuleExportDescriptor
+#define PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE    SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'E', 'D', 'T')
+#define PRM_MODULE_EXPORT_REVISION                0x0
+
+//
+// Platform Runtime Mechanism (PRM) Export Descriptor Structures
+//
+#pragma pack(push, 1)
+
+typedef struct {
+  GUID                                  PrmHandlerGuid;
+  CHAR8                                 PrmHandlerName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];
+} PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT;
+
+typedef struct {
+  UINT64                                Signature;
+  UINT16                                Revision;
+  UINT16                                NumberPrmHandlers;
+  GUID                                  ModuleGuid;
+  PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT  PrmHandlerExportDescriptors[3];
+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;
+
+#pragma pack(pop)
+
+/**
+  A macro that declares a PRM Handler Export Descriptor for a PRM Handler.
+
+  This macro is intended to be used once per PRM Handler to describe the handler when the
+  module description is defined. It should be provided as an argument to PRM_MODULE_EXPORT.
+
+  @param  Guid    The GUID of the PRM Handler being exported.
+
+  @param  Name    The name of the PRM Handler being exported. This string should exactly
+                  match the function name.
+
+**/
+#define PRM_HANDLER_EXPORT_ENTRY(Guid, Name)  \
+      {                                       \
+        Guid,                                 \
+        PRM_STRING_(Name)                     \
+      }                                       \
+
+/**
+  A macro that returns the count of the number of variable-length arguments given.
+
+  @param  VariableArgumentList  A variable argument list of elements that will be included
+                                in the return value of the list count.
+**/
+#define VA_ARG_COUNT(...)  (sizeof((PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT[]){__VA_ARGS__})/sizeof(PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT))
+
+/**
+  A macro that declares the PRM Module Export Descriptor for a PRM Module.
+
+  This macro is intended to be used once in a PRM Module after all of the PRM Handler definitions
+  to describe the PRM Handlers being exported in the module.
+
+  @param  PrmHandlerExportEntries   A variable argument list of PRM_HANDLER_EXPORT_ENTRY values.
+                                    This list should include all PRM Handlers being exported by
+                                    this module.
+
+**/
+#define PRM_MODULE_EXPORT(...)                                                              \
+  PRM_EXPORT_API PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT PRM_MODULE_EXPORT_DESCRIPTOR_NAME = {               \
+    {                                                                                                     \
+      PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE,                                                             \
+      PRM_MODULE_EXPORT_REVISION,                                                                         \
+      VA_ARG_COUNT(__VA_ARGS__),                                                                          \
+      EFI_CALLER_ID_GUID                                                                                  \
+    },                                                                                                    \
+    { __VA_ARGS__ }                                                                                       \
+  }                                                                                                       \
+
+#endif
diff --git a/PrmPkg/Include/PrmMmio.h b/PrmPkg/Include/PrmMmio.h
new file mode 100644
index 000000000000..fb216c27e8e3
--- /dev/null
+++ b/PrmPkg/Include/PrmMmio.h
@@ -0,0 +1,45 @@
+/** @file
+
+  Definitions for the Platform Runtime Mechanism (PRM) MMIO elements.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_MMIO_H_
+#define PRM_MMIO_H_
+
+#include <Uefi.h>
+
+#pragma pack(push, 1)
+
+///
+/// Describes a memory range that needs to be made accessible at OS runtime.
+///
+/// The memory range with the given base address and length will be marked as EFI_MEMORY_RUNTIME.
+///
+typedef struct {
+  EFI_PHYSICAL_ADDRESS                    PhysicalBaseAddress;
+  EFI_PHYSICAL_ADDRESS                    VirtualBaseAddress;
+  UINT32                                  Length;
+} PRM_RUNTIME_MMIO_RANGE;
+
+///
+/// Describes a buffer with an array of PRM module
+/// config runtime memory ranges.
+///
+typedef struct {
+  ///
+  /// The number of runtime memory range elements in this buffer.
+  ///
+  UINT64                                  Count;
+  ///
+  /// The beginning of the runtime memory range data.
+  ///
+  PRM_RUNTIME_MMIO_RANGE                  Range[1];
+} PRM_RUNTIME_MMIO_RANGES;
+
+#pragma pack(pop)
+
+#endif
diff --git a/PrmPkg/Include/PrmModule.h b/PrmPkg/Include/PrmModule.h
new file mode 100644
index 000000000000..f40fb42a2b4f
--- /dev/null
+++ b/PrmPkg/Include/PrmModule.h
@@ -0,0 +1,68 @@
+/** @file
+
+  Common definitions needed for Platform Runtime Mechanism (PRM) modules.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_MODULE_H_
+#define PRM_MODULE_H_
+
+#include <Prm.h>
+#include <PrmContextBuffer.h>
+#include <PrmDataBuffer.h>
+#include <PrmExportDescriptor.h>
+#include <PrmMmio.h>
+#include <PrmModuleUpdate.h>
+#include <PrmOsServices.h>
+
+/**
+  Macro that provides a condensed form of a PRM Handler.
+
+  This macro can be used to define a PRM Handler that uses the standard PRM Handle
+  signature. It is simply provided for convenience.
+
+**/
+#define PRM_HANDLER_EXPORT(Name)                                                  \
+  STATIC_ASSERT (sizeof (PRM_STRING_(Name)) <= PRM_HANDLER_NAME_MAXIMUM_LENGTH, "The PRM handler exceeds the maximum allowed size of 128.");  \
+                                                                                  \
+/**                                                                               \
+  A Platform Runtime Mechanism (PRM) handler.                                     \
+                                                                                  \
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer   \
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer     \
+                                                                                  \
+  @retval EFI_STATUS              The PRM handler executed successfully.          \
+  @retval Others                  An error occurred in the PRM handler.           \
+                                                                                  \
+**/                                                                               \
+  EFI_STATUS                                    \
+  PRM_EXPORT_API                                \
+  EFIAPI                                        \
+  Name (                                        \
+    IN VOID                 *ParameterBuffer,   \
+    IN PRM_CONTEXT_BUFFER   *ContextBuffer      \
+    )                                           \
+
+/**
+  A macro that declares the PRM Module Update Lock Descriptor for a PRM Module.
+
+  This macro is intended to be used once in a PRM Module so the module update lock descriptor is
+  exported for the module.
+
+**/
+#define PRM_MODULE_UPDATE_LOCK_EXPORT                                                           \
+  PRM_EXPORT_API PRM_MODULE_UPDATE_LOCK_DESCRIPTOR PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_NAME = {   \
+    PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_SIGNATURE,                                                \
+    PRM_MODULE_UPDATE_LOCK_REVISION,                                                            \
+    { 0 }                                                                                       \
+  }                                                                                             \
+
+//
+// A PRM module is required to export the PRM Module Update Lock
+//
+PRM_MODULE_UPDATE_LOCK_EXPORT;
+
+#endif
diff --git a/PrmPkg/Include/PrmModuleUpdate.h b/PrmPkg/Include/PrmModuleUpdate.h
new file mode 100644
index 000000000000..fde97eff0462
--- /dev/null
+++ b/PrmPkg/Include/PrmModuleUpdate.h
@@ -0,0 +1,46 @@
+/** @file
+
+  Definition for the Platform Runtime Mechanism (PRM) module update structures.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_MODULE_UPDATE_H_
+#define PRM_MODULE_UPDATE_H_
+
+#include <Uefi.h>
+
+#define PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_NAME        PrmModuleUpdateLock
+#define PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_SIGNATURE   SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'U', 'L', '_')
+#define PRM_MODULE_UPDATE_LOCK_REVISION               0x0
+
+#pragma pack(push, 1)
+
+///
+/// Maintains the PRM Module Update Lock state
+///
+typedef union {
+  ///
+  /// Individual bit fields
+  ///
+  struct {
+    UINT8 Acquired          : 1;  ///< [0] - If 1 lock is acquired. If 0 lock is released.
+    UINT8 Reserved          : 7;  ///< [7:1] - Reserved
+  } Bits;
+  ///
+  /// All bit fields as an 8-bit value
+  ///
+  UINT8 Uint8;
+} PRM_MODULE_UPDATE_LOCK;
+
+typedef struct {
+  UINT64                                Signature;
+  UINT16                                Revision;
+  PRM_MODULE_UPDATE_LOCK                Lock;
+} PRM_MODULE_UPDATE_LOCK_DESCRIPTOR;
+
+#pragma pack(pop)
+
+#endif
diff --git a/PrmPkg/Include/PrmOsServices.h b/PrmPkg/Include/PrmOsServices.h
new file mode 100644
index 000000000000..62dfa0018787
--- /dev/null
+++ b/PrmPkg/Include/PrmOsServices.h
@@ -0,0 +1,45 @@
+/** @file
+
+  Definitions for the Platform Runtime Mechanism (PRM) OS Services.
+
+  Note: OS Services have been removed from POR. This file has been reduced to just debug print
+        OS Service for use during PRM enabling.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_OS_SERVICES_H_
+#define PRM_OS_SERVICES_H_
+
+#include <Uefi.h>
+
+typedef struct _PRM_OS_SERVICES PRM_OS_SERVICES;
+
+//
+// PRM OS Services function signatures
+//
+typedef
+VOID
+(EFIAPI *PRM_OS_SERVICE_DEBUG_PRINT) (
+  IN  CONST CHAR8           *String
+  );
+
+#pragma pack(push, 1)
+
+//
+// PRM OS Services table
+//
+struct _PRM_OS_SERVICES {
+    // Structure information
+    UINT16                                MajorVersion;
+    UINT16                                MinorVersion;
+
+    // OS Services
+    PRM_OS_SERVICE_DEBUG_PRINT            DebugPrint;
+};
+
+#pragma pack(pop)
+
+#endif
diff --git a/PrmPkg/PrmPkg.dec b/PrmPkg/PrmPkg.dec
new file mode 100644
index 000000000000..ff681d423d30
--- /dev/null
+++ b/PrmPkg/PrmPkg.dec
@@ -0,0 +1,49 @@
+## @file  PrmPkg.dec
+# This package provides support for the Platform Runtime Mechanism (PRM).
+#
+# The following key elements of PRM are maintained in this package:
+#
+# 1. PRM interfaces - Comprised of interfaces shared with the operating system such as ACPI table structures
+#                     in addition to internal firmware interfaces such as protocols and library interfaces.
+#
+# 2. PRM generic drivers - EDK II drivers that implement generic functionality such that a platform can quickly
+#                          and reliably adopt PRM.
+#
+# 3. PRM module - An independently updatable PE/COFF binary that conforms to the unique requirements of a PRM module.
+#                 PRM modules expose functions for operating system invocation referred to as PRM handlers.
+#
+# 4. PRM handler - A function in a PRM module. The function is identified through PRM interfaces in the OS by a GUID.
+#
+# Copyright (c) Microsoft Corporation<BR>
+## SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = PrmPkg
+  PACKAGE_UNI_FILE               = PrmPkg.uni
+  PACKAGE_GUID                   = 3D22F66E-9090-46CE-B260-1836070AFA5E
+  PACKAGE_VERSION                = 0.1
+
+[Includes]
+  Include
+
+[Guids]
+  gPrmPkgTokenSpaceGuid = { 0x46f56acc, 0x600b, 0x450f, { 0xa5, 0x9c, 0x3a, 0x1a, 0x4a, 0xd4, 0x35, 0x3e }}
+
+[LibraryClasses]
+  ## @libraryclass Provides a general abstraction for PRM context buffer management
+  #
+  PrmContextBufferLib|Include/Library/PrmContextBufferLib.h
+
+[Protocols]
+  ## PRM Configuration Protocol
+  #
+  gPrmConfigProtocolGuid = { 0x4e5b4fea, 0x936a, 0x45bc, { 0xac, 0x6a, 0x2f, 0x8f, 0x14, 0xa6, 0xc2, 0x9e }}
+
+[PcdsFixedAtBuild]
+  ## Flash base address of a PRM firmware volume
+  gPrmPkgTokenSpaceGuid.PcdFlashFvPrmBase|0x00000000|UINT32|0x00000001
+
+  ## Size in bytes of a PRM firmware volume
+  gPrmPkgTokenSpaceGuid.PcdFlashFvPrmSize|0x00000000|UINT32|0x00000002
diff --git a/PrmPkg/PrmPkg.uni b/PrmPkg/PrmPkg.uni
new file mode 100644
index 000000000000..3575b3505213
--- /dev/null
+++ b/PrmPkg/PrmPkg.uni
@@ -0,0 +1,10 @@
+// /** @file
+//
+// Copyright (c) Microsoft Corporation
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+// **/
+
+
+#string STR_PACKAGE_ABSTRACT            #language en-US "This package provides support for the Platform Runtime Mechanism (PRM)."
+
+#string STR_PACKAGE_DESCRIPTION         #language en-US "Provides infrastructure support code and sample PRM modules for PRM authors."
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 02/41] PrmPkg: Add PrmConfig protocol interface
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 01/41] PrmPkg: Add package and include headers Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 03/41] PrmPkg/PrmContextBufferLib: Add initial library instance Michael Kubacki
                   ` (38 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

The PRM Configuration protocol is used by PRM module configuration
libraries to describe their resources so that a generic PRM Configuration
DXE driver can prepare those resources for OS runtime.

Therefore, multiple instances are expected in the system per boot with
approximately one instance per PRM module. All PRM Configuration Protocol
instances must be installed prior to end of DXE.

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>
---
 PrmPkg/Include/Protocol/PrmConfig.h | 32 ++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/PrmPkg/Include/Protocol/PrmConfig.h b/PrmPkg/Include/Protocol/PrmConfig.h
new file mode 100644
index 000000000000..d90fe5a0dd73
--- /dev/null
+++ b/PrmPkg/Include/Protocol/PrmConfig.h
@@ -0,0 +1,32 @@
+/** @file
+
+  PRM Configuration protocol
+
+  PRM Configuration protocol is used by PRM module configuration libraries to
+  describe their resources so that a generic PRM Configuration DXE driver can prepare those
+  resources for OS runtime.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_CONFIG_H_
+#define PRM_CONFIG_H_
+
+#include <PrmContextBuffer.h>
+#include <Uefi.h>
+
+typedef struct _PRM_CONFIG_PROTOCOL PRM_CONFIG_PROTOCOL;
+
+#define PRM_CONFIG_PROTOCOL_SIGNATURE   SIGNATURE_32('P','M','C','P')
+#define PRM_CONFIG_PROTOCOL_VERSION     1
+
+struct _PRM_CONFIG_PROTOCOL
+{
+  PRM_MODULE_CONTEXT_BUFFERS            ModuleContextBuffers;
+};
+
+extern EFI_GUID gPrmConfigProtocolGuid;
+
+#endif
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 03/41] PrmPkg/PrmContextBufferLib: Add initial library instance
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 01/41] PrmPkg: Add package and include headers Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 02/41] PrmPkg: Add PrmConfig protocol interface Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 04/41] PrmPkg/PrmConfigDxe: Add initial driver Michael Kubacki
                   ` (37 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

This library is introduced to add  a general abstraction for PRM context
buffer management.

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>
---
 PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c   | 196 ++++++++++++++++++++
 PrmPkg/Include/Library/PrmContextBufferLib.h                     |  99 ++++++++++
 PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf |  35 ++++
 3 files changed, 330 insertions(+)

diff --git a/PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c b/PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
new file mode 100644
index 000000000000..1a1a15b5cdbb
--- /dev/null
+++ b/PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
@@ -0,0 +1,196 @@
+/** @file
+
+  The PRM Buffer Context library provides a general abstraction for context buffer management.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrmContextBufferLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/PrmConfig.h>
+
+#define _DBGMSGID_        "[PRMCONTEXTBUFFERLIB]"
+
+/**
+  Finds a PRM context buffer for the given PRM handler GUID.
+
+  Note: PRM_MODULE_CONTEXT_BUFFERS is at the PRM module level while PRM_CONTEXT_BUFFER is at the PRM handler level.
+
+  @param[in]  HandlerGuid                 A pointer to the PRM handler GUID.
+  @param[in]  ModuleContextBuffers        A pointer to the PRM context buffers structure for the PRM module.
+  @param[out] PrmModuleContextBuffer      A pointer to a pointer that will be set to the PRM context buffer
+                                          if successfully found.
+
+  @retval EFI_SUCCESS                     The PRM context buffer was found.
+  @retval EFI_INVALID_PARAMETER           A required parameter pointer is NULL.
+  @retval EFI_NOT_FOUND                   The context buffer for the given PRM handler GUID could not be found.
+
+**/
+EFI_STATUS
+FindContextBufferInModuleBuffers (
+  IN  CONST EFI_GUID                      *HandlerGuid,
+  IN  CONST PRM_MODULE_CONTEXT_BUFFERS    *ModuleContextBuffers,
+  OUT CONST PRM_CONTEXT_BUFFER            **ContextBuffer
+  )
+{
+  UINTN                                   Index;
+
+  DEBUG ((DEBUG_INFO, "    %a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  if (HandlerGuid == NULL || ModuleContextBuffers == NULL || ContextBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  for (Index = 0; Index < ModuleContextBuffers->BufferCount; Index++) {
+    if (CompareGuid (&ModuleContextBuffers->Buffer[Index].HandlerGuid, HandlerGuid)) {
+      *ContextBuffer = &ModuleContextBuffers->Buffer[Index];
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Returns a PRM context buffers structure for the given PRM search type.
+
+  This function allows a caller to get the context buffers structure for a PRM module with either the PRM module
+  GUID or the GUID for a PRM handler in the module.
+
+  Note: PRM_MODULE_CONTEXT_BUFFERS is at the PRM module level while PRM_CONTEXT_BUFFER is at the PRM handler level.
+
+  @param[in]  GuidSearchType              The type of GUID passed in the Guid argument.
+  @param[in]  Guid                        A pointer to the GUID of a PRM module or PRM handler. The actual GUID type
+                                          will be interpreted based on the value passed in GuidSearchType.
+  @param[out] PrmModuleContextBuffers     A pointer to a pointer that will be set to the PRM context buffers
+                                          structure if successfully found.
+
+  @retval EFI_SUCCESS                     The PRM context buffers structure was found.
+  @retval EFI_INVALID_PARAMETER           A required parameter pointer is NULL.
+  @retval EFI_NOT_FOUND                   The context buffers for the given GUID could not be found.
+
+**/
+EFI_STATUS
+GetModuleContextBuffers (
+  IN  PRM_GUID_SEARCH_TYPE                GuidSearchType,
+  IN  CONST EFI_GUID                      *Guid,
+  OUT CONST PRM_MODULE_CONTEXT_BUFFERS    **PrmModuleContextBuffers
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       HandleCount;
+  UINTN                       Index;
+  EFI_HANDLE                  *HandleBuffer;
+  PRM_CONFIG_PROTOCOL         *PrmConfigProtocol;
+  CONST PRM_CONTEXT_BUFFER    *PrmContextBuffer;
+
+  DEBUG ((DEBUG_INFO, "    %a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  if (Guid == NULL || PrmModuleContextBuffers == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  *PrmModuleContextBuffers = NULL;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gPrmConfigProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (!EFI_ERROR (Status)) {
+    for (Index = 0; Index < HandleCount; Index++) {
+      Status = gBS->HandleProtocol (
+                      HandleBuffer[Index],
+                      &gPrmConfigProtocolGuid,
+                      (VOID **) &PrmConfigProtocol
+                      );
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR (Status) || PrmConfigProtocol == NULL) {
+        continue;
+      }
+
+      if (GuidSearchType == ByModuleGuid) {
+        if (CompareGuid (&PrmConfigProtocol->ModuleContextBuffers.ModuleGuid, Guid)) {
+          DEBUG ((
+            DEBUG_INFO,
+            "      %a %a: Found a PRM configuration protocol for PRM module %g.\n",
+            _DBGMSGID_,
+            __FUNCTION__,
+            Guid
+            ));
+
+          *PrmModuleContextBuffers = &PrmConfigProtocol->ModuleContextBuffers;
+          return EFI_SUCCESS;
+        }
+      } else {
+        Status = FindContextBufferInModuleBuffers (Guid, &PrmConfigProtocol->ModuleContextBuffers, &PrmContextBuffer);
+        if (!EFI_ERROR (Status)) {
+          *PrmModuleContextBuffers = &PrmConfigProtocol->ModuleContextBuffers;
+          return EFI_SUCCESS;
+        }
+      }
+    }
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "      %a %a: Could not locate a PRM configuration protocol for PRM handler %g.\n",
+    _DBGMSGID_,
+    __FUNCTION__,
+    Guid
+    ));
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Returns a PRM context buffer for the given PRM handler.
+
+  @param[in]  PrmHandlerGuid              A pointer to the GUID for the PRM handler.
+  @param[in]  PrmModuleContextBuffers     A pointer to a PRM_MODULE_CONTEXT_BUFFERS structure. If this optional
+                                          parameter is provided, the handler context buffer will be searched for in this
+                                          buffer structure which saves time by not performing a global search for the
+                                          module buffer structure.
+  @param[out] PrmContextBuffer            A pointer to a pointer that will be set to the PRM context buffer
+                                          if successfully found.
+
+  @retval EFI_SUCCESS                     The PRM context buffer was found.
+  @retval EFI_INVALID_PARAMETER           A required parameter pointer is NULL.
+  @retval EFI_NOT_FOUND                   The context buffer for the PRM handler could not be found.
+
+**/
+EFI_STATUS
+GetContextBuffer (
+  IN  CONST EFI_GUID                      *PrmHandlerGuid,
+  IN  CONST PRM_MODULE_CONTEXT_BUFFERS    *PrmModuleContextBuffers  OPTIONAL,
+  OUT CONST PRM_CONTEXT_BUFFER            **PrmContextBuffer
+  )
+{
+  EFI_STATUS                              Status;
+  CONST PRM_MODULE_CONTEXT_BUFFERS        *ContextBuffers;
+
+  DEBUG ((DEBUG_INFO, "    %a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  if (PrmHandlerGuid == NULL || PrmContextBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  *PrmContextBuffer = NULL;
+
+  if (PrmModuleContextBuffers == NULL) {
+    Status = GetModuleContextBuffers (ByHandlerGuid, PrmHandlerGuid, &ContextBuffers);
+    if (EFI_ERROR (Status)) {
+      return EFI_NOT_FOUND;
+    }
+  } else {
+    ContextBuffers = PrmModuleContextBuffers;
+  }
+  Status = FindContextBufferInModuleBuffers (PrmHandlerGuid, ContextBuffers, PrmContextBuffer);
+
+  return Status;
+}
diff --git a/PrmPkg/Include/Library/PrmContextBufferLib.h b/PrmPkg/Include/Library/PrmContextBufferLib.h
new file mode 100644
index 000000000000..93dcd1e76642
--- /dev/null
+++ b/PrmPkg/Include/Library/PrmContextBufferLib.h
@@ -0,0 +1,99 @@
+/** @file
+
+  The PRM Buffer Context library provides a general abstraction for context buffer management.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_CONTEXT_BUFFER_LIB_H_
+#define PRM_CONTEXT_BUFFER_LIB_H_
+
+#include <Base.h>
+#include <PrmContextBuffer.h>
+#include <Uefi.h>
+
+typedef enum {
+  ///
+  /// Search by the PRM module GUID
+  ///
+  ByModuleGuid,
+  ///
+  /// Search by the PRM handler GUID
+  ///
+  ByHandlerGuid
+} PRM_GUID_SEARCH_TYPE;
+
+/**
+  Finds a PRM context buffer for the given PRM handler GUID.
+
+  Note: PRM_MODULE_CONTEXT_BUFFERS is at the PRM module level while PRM_CONTEXT_BUFFER is at the PRM handler level.
+
+  @param[in]  HandlerGuid                 A pointer to the PRM handler GUID.
+  @param[in]  ModuleContextBuffers        A pointer to the PRM context buffers structure for the PRM module.
+  @param[out] PrmModuleContextBuffer      A pointer to a pointer that will be set to the PRM context buffer
+                                          if successfully found.
+
+  @retval EFI_SUCCESS                     The PRM context buffer was found.
+  @retval EFI_INVALID_PARAMETER           A required parameter pointer is NULL.
+  @retval EFI_NOT_FOUND                   The context buffer for the given PRM handler GUID could not be found.
+
+**/
+EFI_STATUS
+FindContextBufferInModuleBuffers (
+  IN  CONST EFI_GUID                      *HandlerGuid,
+  IN  CONST PRM_MODULE_CONTEXT_BUFFERS    *ModuleContextBuffers,
+  OUT CONST PRM_CONTEXT_BUFFER            **ContextBuffer
+  );
+
+/**
+  Returns a PRM context buffers structure for the given PRM search type.
+
+  This function allows a caller to get the context buffers structure for a PRM module with either the PRM module
+  GUID or the GUID for a PRM handler in the module.
+
+  Note: PRM_MODULE_CONTEXT_BUFFERS is at the PRM module level while PRM_CONTEXT_BUFFER is at the PRM handler level.
+
+  @param[in]  GuidSearchType              The type of GUID passed in the Guid argument.
+  @param[in]  Guid                        A pointer to the GUID of a PRM module or PRM handler. The actual GUID type
+                                          will be interpreted based on the value passed in GuidSearchType.
+  @param[out] PrmModuleContextBuffers     A pointer to a pointer that will be set to the PRM context buffers
+                                          structure if successfully found.
+
+  @retval EFI_SUCCESS                     The PRM context buffers structure was found.
+  @retval EFI_INVALID_PARAMETER           A required parameter pointer is NULL.
+  @retval EFI_NOT_FOUND                   The context buffers for the given GUID could not be found.
+
+**/
+EFI_STATUS
+GetModuleContextBuffers (
+  IN  PRM_GUID_SEARCH_TYPE                GuidSearchType,
+  IN  CONST EFI_GUID                      *Guid,
+  OUT CONST PRM_MODULE_CONTEXT_BUFFERS    **PrmModuleContextBuffers
+  );
+
+/**
+  Returns a PRM context buffer for the given PRM handler.
+
+  @param[in]  PrmHandlerGuid              A pointer to the GUID for the PRM handler.
+  @param[in]  PrmModuleContextBuffers     A pointer to a PRM_MODULE_CONTEXT_BUFFERS structure. If this optional
+                                          parameter is provided, the handler context buffer will be searched for in this
+                                          buffer structure which saves time by not performing a global search for the
+                                          module buffer structure.
+  @param[out] PrmContextBuffer            A pointer to a pointer that will be set to the PRM context buffer
+                                          if successfully found.
+
+  @retval EFI_SUCCESS                     The PRM context buffer was found.
+  @retval EFI_INVALID_PARAMETER           A required parameter pointer is NULL.
+  @retval EFI_NOT_FOUND                   The context buffer for the PRM handler could not be found.
+
+**/
+EFI_STATUS
+GetContextBuffer (
+  IN  CONST EFI_GUID                      *PrmHandlerGuid,
+  IN  CONST PRM_MODULE_CONTEXT_BUFFERS    *PrmModuleContextBuffers  OPTIONAL,
+  OUT CONST PRM_CONTEXT_BUFFER            **PrmContextBuffer
+  );
+
+#endif
diff --git a/PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf b/PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
new file mode 100644
index 000000000000..16ed1edfe36a
--- /dev/null
+++ b/PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
@@ -0,0 +1,35 @@
+## @file
+#  PRM Context Buffer Library
+#
+#  Provides a general abstraction for PRM context buffer management.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION         = 0x00010005
+  BASE_NAME           = DxePrmContextBufferLib
+  FILE_GUID           = 49828E93-29FA-4665-B8B1-19BA4059D140
+  MODULE_TYPE         = DXE_DRIVER
+  VERSION_STRING      = 1.0
+  LIBRARY_CLASS       = PrmContextBufferLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+[Sources]
+  DxePrmContextBufferLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[Protocols]
+  gPrmConfigProtocolGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  UefiBootServicesTableLib
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 04/41] PrmPkg/PrmConfigDxe: Add initial driver
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (2 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 03/41] PrmPkg/PrmContextBufferLib: Add initial library instance Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 05/41] PrmPkg: Add initial PrmSamplePrintModule Michael Kubacki
                   ` (36 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

This driver serves as a generic PRM configuration driver. Its primary
role is to prepare PRM resources published by PRM module configuration
libraries for OS runtime. As such, it locates all PRM Configuration
Protocol instances and consumes the information to ready those resources.

For example, set runtime memory attributes on MMIO ranges and convert
physical addresses to virtual addresses in PRM buffers.

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>
---
 PrmPkg/PrmConfigDxe/PrmConfigDxe.c   | 559 ++++++++++++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c   | 925 ++++++++++++++++++++
 PrmPkg/PrmConfigDxe/PrmConfigDxe.inf |  48 +
 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h   |  97 ++
 PrmPkg/PrmLoaderDxe/PrmLoader.h      |  51 ++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf |  59 ++
 6 files changed, 1739 insertions(+)

diff --git a/PrmPkg/PrmConfigDxe/PrmConfigDxe.c b/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
new file mode 100644
index 000000000000..cb38146bc9e0
--- /dev/null
+++ b/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
@@ -0,0 +1,559 @@
+/** @file
+
+  This file contains the implementation for a Platform Runtime Mechanism (PRM) configuration driver.
+
+  Copyright (c) Microsoft Corporation
+  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <PiDxe.h>
+#include <PrmContextBuffer.h>
+#include <PrmDataBuffer.h>
+#include <PrmMmio.h>
+#include <Protocol/PrmConfig.h>
+
+#define _DBGMSGID_                "[PRMCONFIG]"
+
+STATIC  UINTN                     mMaxRuntimeMmioRangeCount;
+STATIC  UINTN                     mMaxStaticDataBufferCount;
+
+STATIC  PRM_RUNTIME_MMIO_RANGES   **mRuntimeMmioRanges;
+STATIC  PRM_DATA_BUFFER           ***mStaticDataBuffers;
+
+/**
+  Converts the runtime memory range physical addresses to virtual addresses.
+
+  @param[in]  RuntimeMmioRanges   A pointer to a PRM_RUNTIME_MMIO_RANGES buffer.
+
+**/
+VOID
+ConvertRuntimeMemoryRangeAddresses (
+  IN  PRM_RUNTIME_MMIO_RANGES     *RuntimeMmioRanges
+  )
+{
+  UINTN   Index;
+
+  if (RuntimeMmioRanges == NULL || RuntimeMmioRanges->Count == 0) {
+    return;
+  }
+
+  for (Index = 0; Index < (UINTN) RuntimeMmioRanges->Count; Index++) {
+    RuntimeMmioRanges->Range[Index].VirtualBaseAddress = RuntimeMmioRanges->Range[Index].PhysicalBaseAddress;
+    gRT->ConvertPointer (0x0, (VOID **) &(RuntimeMmioRanges->Range[Index].VirtualBaseAddress));
+  }
+}
+
+/**
+  Sets the runtime memory range attributes.
+
+  The EFI_MEMORY_RUNTIME attribute is set for each PRM_RUNTIME_MMIO_RANGE present
+  in the buffer provided.
+
+  @param[in]  RuntimeMmioRanges     A pointer to a PRM_RUNTIME_MMIO_RANGES buffer.
+
+**/
+VOID
+SetRuntimeMemoryRangeAttributes (
+  IN  PRM_RUNTIME_MMIO_RANGES       *RuntimeMmioRanges
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_STATUS                        Status2;
+  UINTN                             Index;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR   Descriptor;
+
+  DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  if (RuntimeMmioRanges == NULL || RuntimeMmioRanges->Count == 0) {
+    return;
+  }
+
+  for (Index = 0; Index < (UINTN) RuntimeMmioRanges->Count; Index++) {
+    DEBUG ((
+      DEBUG_INFO, "      %a %a: Runtime MMIO Range [%d].\n", _DBGMSGID_, __FUNCTION__, Index));
+    DEBUG ((
+      DEBUG_INFO,
+      "      %a %a: Physical address = 0x%016x. Length = 0x%x.\n",
+      _DBGMSGID_,
+      __FUNCTION__,
+      RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
+      RuntimeMmioRanges->Range[Index].Length
+      ));
+
+    // Runtime memory ranges should cover ranges on a page boundary
+    ASSERT ((RuntimeMmioRanges->Range[Index].PhysicalBaseAddress & EFI_PAGE_MASK) == 0);
+    ASSERT ((RuntimeMmioRanges->Range[Index].Length & EFI_PAGE_MASK) == 0);
+
+    Status2 = EFI_NOT_FOUND;
+    Status = gDS->GetMemorySpaceDescriptor (RuntimeMmioRanges->Range[Index].PhysicalBaseAddress, &Descriptor);
+    if (!EFI_ERROR (Status) &&
+      (
+        (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo && Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) ||
+        ((Descriptor.Length & EFI_PAGE_MASK) != 0)
+        )
+      ) {
+      Status2 =  gDS->RemoveMemorySpace (
+                        RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
+                        Descriptor.Length
+                        );
+    }
+
+    if (Status == EFI_NOT_FOUND || !EFI_ERROR (Status2)) {
+      Status = gDS->AddMemorySpace (
+                      EfiGcdMemoryTypeMemoryMappedIo,
+                      RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
+                      (UINT64) RuntimeMmioRanges->Range[Index].Length,
+                      EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+                      );
+      ASSERT_EFI_ERROR (Status);
+
+      Status = gDS->AllocateMemorySpace (
+                      EfiGcdAllocateAddress,
+                      EfiGcdMemoryTypeMemoryMappedIo,
+                      0,
+                      (UINT64) RuntimeMmioRanges->Range[Index].Length,
+                      &RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
+                      gImageHandle,
+                      NULL
+                      );
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    Status = gDS->GetMemorySpaceDescriptor (RuntimeMmioRanges->Range[Index].PhysicalBaseAddress, &Descriptor);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "      %a %a: Error [%r] finding descriptor for runtime memory range 0x%016x.\n",
+        _DBGMSGID_,
+        __FUNCTION__,
+        Status,
+        RuntimeMmioRanges->Range[Index].PhysicalBaseAddress
+        ));
+      continue;
+    }
+    if ((Descriptor.Attributes & EFI_MEMORY_RUNTIME) != 0) {
+      continue;
+    }
+
+    Status = gDS->SetMemorySpaceAttributes (
+                    RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
+                    (UINT64) RuntimeMmioRanges->Range[Index].Length,
+                    Descriptor.Attributes | EFI_MEMORY_RUNTIME
+                    );
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "      %a %a: Error [%r] setting descriptor for runtime memory range 0x%016x.\n",
+        _DBGMSGID_,
+        __FUNCTION__,
+        Status,
+        RuntimeMmioRanges->Range[Index].PhysicalBaseAddress
+        ));
+    } else {
+      DEBUG ((DEBUG_INFO, "      %a %a: Successfully set runtime attribute for the MMIO range.\n", _DBGMSGID_, __FUNCTION__));
+    }
+  }
+}
+
+/**
+  Stores pointers or pointer to resources that should be converted in the virtual address change event.
+
+**/
+VOID
+StoreVirtualMemoryAddressChangePointers (
+  VOID
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       BufferIndex;
+  UINTN                       HandleCount;
+  UINTN                       HandleIndex;
+  UINTN                       RangeIndex;
+  UINTN                       StaticDataBufferIndex;
+  EFI_HANDLE                  *HandleBuffer;
+  PRM_CONFIG_PROTOCOL         *PrmConfigProtocol;
+  PRM_CONTEXT_BUFFER          *CurrentContextBuffer;
+
+  DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  RangeIndex = 0;
+  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 ((
+      DEBUG_ERROR,
+      "  %a %a: Memory allocation for PRM static data buffer pointer array failed.\n",
+      _DBGMSGID_,
+      __FUNCTION__
+      ));
+    ASSERT (FALSE);
+    return;
+  }
+
+  HandleBuffer = NULL;
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gPrmConfigProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (!EFI_ERROR (Status)) {
+    for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+      Status = gBS->HandleProtocol (
+                      HandleBuffer[HandleIndex],
+                      &gPrmConfigProtocolGuid,
+                      (VOID **) &PrmConfigProtocol
+                      );
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR (Status) || PrmConfigProtocol == NULL) {
+        continue;
+      }
+
+      for (BufferIndex = 0; BufferIndex < PrmConfigProtocol->ModuleContextBuffers.BufferCount; BufferIndex++) {
+        CurrentContextBuffer = &(PrmConfigProtocol->ModuleContextBuffers.Buffer[BufferIndex]);
+
+        if (CurrentContextBuffer->StaticDataBuffer != NULL) {
+          if (StaticDataBufferIndex >= mMaxStaticDataBufferCount) {
+            Status = EFI_BUFFER_TOO_SMALL;
+            DEBUG ((
+              DEBUG_ERROR,
+              "  %a %a: Index out of bounds - Actual count (%d) of PRM data buffers exceeds maximum count (%d).\n",
+              _DBGMSGID_,
+              __FUNCTION__,
+              StaticDataBufferIndex + 1,
+              mMaxStaticDataBufferCount
+              ));
+            ASSERT_EFI_ERROR (Status);
+            return;
+          }
+          mStaticDataBuffers[StaticDataBufferIndex++] = &CurrentContextBuffer->StaticDataBuffer;
+        }
+      }
+      if (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges != NULL) {
+        if (RangeIndex >= mMaxRuntimeMmioRangeCount) {
+          Status = EFI_BUFFER_TOO_SMALL;
+          DEBUG ((
+            DEBUG_ERROR,
+            "  %a %a: Index out of bounds - Actual count (%d) of runtime MMIO ranges exceeds maximum count (%d).\n",
+            _DBGMSGID_,
+            __FUNCTION__,
+            RangeIndex + 1,
+            mMaxRuntimeMmioRangeCount
+            ));
+          ASSERT_EFI_ERROR (Status);
+          return;
+        }
+        mRuntimeMmioRanges[RangeIndex++] = PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges;
+      }
+    }
+    DEBUG ((
+      DEBUG_INFO,
+      "  %a %a: %d MMIO ranges buffers saved for future virtual memory conversion.\n",
+      _DBGMSGID_,
+      __FUNCTION__,
+      RangeIndex
+      ));
+    DEBUG ((
+      DEBUG_INFO,
+      "  %a %a: %d static buffers saved for future virtual memory conversion.\n",
+      _DBGMSGID_,
+      __FUNCTION__,
+      StaticDataBufferIndex
+      ));
+  }
+}
+
+/**
+  Validates a data buffer for a PRM module.
+
+  Verifies the buffer header signature is valid and the length meets the minimum size.
+
+  @param[in]  PrmDataBuffer         A pointer to the data buffer for this PRM module.
+
+  @retval EFI_SUCCESS               The data buffer was validated successfully.
+  @retval EFI_INVALID_PARAMETER     The pointer given for PrmDataBuffer is NULL.
+  @retval EFI_NOT_FOUND             The data buffer signature is not valid.
+  @retval EFI_BUFFER_TOO_SMALL      The buffer size is too small.
+
+**/
+EFI_STATUS
+ValidatePrmDataBuffer (
+  IN  CONST PRM_DATA_BUFFER         *PrmDataBuffer
+  )
+{
+  if (PrmDataBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (PrmDataBuffer->Header.Signature != PRM_DATA_BUFFER_HEADER_SIGNATURE) {
+    DEBUG ((DEBUG_ERROR, "  %a %a: The PRM data buffer signature is invalid. PRM module.\n", _DBGMSGID_, __FUNCTION__));
+    return EFI_NOT_FOUND;
+  }
+  if (PrmDataBuffer->Header.Length < sizeof (PRM_DATA_BUFFER_HEADER)) {
+    DEBUG ((DEBUG_ERROR, "  %a %a: The PRM data buffer length is invalid.\n", _DBGMSGID_, __FUNCTION__));
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Validates a PRM context buffer.
+
+  Verifies the buffer header signature is valid and the GUID is set to a non-zero value.
+
+  @param[in]  PrmContextBuffer      A pointer to the context buffer for this PRM handler.
+
+  @retval EFI_SUCCESS               The context buffer was validated successfully.
+  @retval EFI_INVALID_PARAMETER     The pointer given for ContextBuffer is NULL.
+  @retval EFI_NOT_FOUND             The proper value for a field was not found.
+
+**/
+EFI_STATUS
+ValidatePrmContextBuffer (
+  IN  CONST PRM_CONTEXT_BUFFER      *PrmContextBuffer
+  )
+{
+  if (PrmContextBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (PrmContextBuffer->Signature != PRM_CONTEXT_BUFFER_SIGNATURE) {
+    DEBUG ((DEBUG_ERROR, "  %a %a: The PRM context buffer signature is invalid.\n", _DBGMSGID_, __FUNCTION__));
+    return EFI_NOT_FOUND;
+  }
+
+  if (IsZeroGuid (&PrmContextBuffer->HandlerGuid)) {
+    DEBUG ((DEBUG_ERROR, "  %a %a: The PRM context buffer GUID is zero.\n", _DBGMSGID_, __FUNCTION__));
+    return EFI_NOT_FOUND;
+  }
+
+  if (PrmContextBuffer->StaticDataBuffer != NULL && EFI_ERROR (ValidatePrmDataBuffer (PrmContextBuffer->StaticDataBuffer))) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "    %a %a: Error in static buffer for PRM handler %g.\n",
+      _DBGMSGID_,
+      __FUNCTION__,
+      &PrmContextBuffer->HandlerGuid
+      ));
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+  This is notification function converts any registered PRM_RUNTIME_MMIO_RANGE
+  addresses to a virtual address.
+
+  @param[in]  Event        Event whose notification function is being invoked.
+  @param[in]  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+PrmConfigVirtualAddressChangeEvent (
+  IN EFI_EVENT                            Event,
+  IN VOID                                 *Context
+  )
+{
+  UINTN   Index;
+
+  //
+  // Convert static data buffer pointers
+  //
+  for (Index = 0; Index < mMaxStaticDataBufferCount; Index++) {
+    gRT->ConvertPointer (0x0, (VOID **) mStaticDataBuffers[Index]);
+  }
+
+  //
+  // Convert runtime MMIO ranges
+  //
+  for (Index = 0; Index < mMaxRuntimeMmioRangeCount; Index++) {
+    ConvertRuntimeMemoryRangeAddresses (mRuntimeMmioRanges[Index]);
+  }
+}
+
+/**
+  The PRM Config END_OF_DXE protocol notification event handler.
+
+  Finds all of the PRM_CONFIG_PROTOCOL instances installed at end of DXE and
+  marks all PRM_RUNTIME_MMIO_RANGE entries as EFI_MEMORY_RUNTIME.
+
+  @param[in]  Event           Event whose notification function is being invoked.
+  @param[in]  Context         The pointer to the notification function's context,
+                              which is implementation-dependent.
+
+  @retval EFI_SUCCESS         The function executed successfully
+
+**/
+EFI_STATUS
+EFIAPI
+PrmConfigEndOfDxeNotification (
+  IN  EFI_EVENT               Event,
+  IN  VOID                    *Context
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       HandleCount;
+  UINTN                       BufferIndex;
+  UINTN                       HandleIndex;
+  EFI_HANDLE                  *HandleBuffer;
+  PRM_CONTEXT_BUFFER          *CurrentContextBuffer;
+  PRM_CONFIG_PROTOCOL         *PrmConfigProtocol;
+
+  DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  HandleBuffer = NULL;
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gPrmConfigProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (!EFI_ERROR (Status)) {
+    for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+      Status = gBS->HandleProtocol (
+                      HandleBuffer[HandleIndex],
+                      &gPrmConfigProtocolGuid,
+                      (VOID **) &PrmConfigProtocol
+                      );
+      ASSERT_EFI_ERROR (Status);
+      if (EFI_ERROR (Status) || PrmConfigProtocol == NULL) {
+        continue;
+      }
+
+      DEBUG ((
+        DEBUG_INFO,
+        "  %a %a: Found PRM configuration protocol for PRM module %g.\n",
+         _DBGMSGID_,
+         __FUNCTION__,
+         &PrmConfigProtocol->ModuleContextBuffers.ModuleGuid
+         ));
+
+      DEBUG ((DEBUG_INFO, "      %a %a: Validating module context buffers...\n", _DBGMSGID_, __FUNCTION__));
+      for (BufferIndex = 0; BufferIndex < PrmConfigProtocol->ModuleContextBuffers.BufferCount; BufferIndex++) {
+        CurrentContextBuffer = &(PrmConfigProtocol->ModuleContextBuffers.Buffer[BufferIndex]);
+
+        Status =  ValidatePrmContextBuffer (CurrentContextBuffer);
+        if (EFI_ERROR (Status)) {
+          DEBUG ((
+            DEBUG_ERROR,
+            "        %a %a: Context buffer validation failed for PRM handler %g.\n",
+            _DBGMSGID_,
+            __FUNCTION__,
+            CurrentContextBuffer->HandlerGuid
+            ));
+        }
+        if (CurrentContextBuffer->StaticDataBuffer != NULL) {
+          mMaxStaticDataBufferCount++;
+        }
+      }
+      DEBUG ((DEBUG_INFO, "      %a %a: Module context buffer validation complete.\n", _DBGMSGID_, __FUNCTION__));
+
+      if (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges != NULL) {
+        DEBUG ((
+          DEBUG_INFO,
+          "    %a %a: Found %d PRM runtime MMIO ranges to convert.\n",
+           _DBGMSGID_,
+           __FUNCTION__,
+           PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges->Count
+           ));
+        SetRuntimeMemoryRangeAttributes (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges);
+        mMaxRuntimeMmioRangeCount++;
+      }
+    }
+
+    StoreVirtualMemoryAddressChangePointers ();
+  }
+
+  if (HandleBuffer != NULL) {
+    gBS->FreePool (HandleBuffer);
+  }
+  gBS->CloseEvent(Event);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The entry point for this module.
+
+  @param[in]  ImageHandle     The firmware allocated handle for the EFI image.
+  @param[in]  SystemTable     A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS         The entry point is executed successfully.
+  @retval Others              An error occurred when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+PrmConfigEntryPoint (
+  IN EFI_HANDLE               ImageHandle,
+  IN EFI_SYSTEM_TABLE         *SystemTable
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_EVENT                   Event;
+
+  DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  //
+  // Register a notification function to change memory attributes at end of DXE
+  //
+  Event = NULL;
+  Status = gBS->CreateEventEx(
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  PrmConfigEndOfDxeNotification,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register a notification function for virtual address change
+  //
+  Event = NULL;
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  PrmConfigVirtualAddressChangeEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
new file mode 100644
index 000000000000..b43e6d6bf078
--- /dev/null
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -0,0 +1,925 @@
+/** @file
+
+  This file contains the implementation for a Platform Runtime Mechanism (PRM)
+  loader driver.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PrmAcpiTable.h"
+#include "PrmLoader.h"
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrmContextBufferLib.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>
+#include <PrmModuleUpdate.h>
+
+LIST_ENTRY          mPrmModuleList;
+
+// 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->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->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;
+}
+
+/**
+  Processes a list of PRM context entries to build a PRM ACPI table.
+
+  The ACPI table buffer is allocated and the table structure is built inside this function.
+
+  @param[out]  PrmAcpiDescriptionTable    A pointer to a pointer to a buffer that is allocated within this function
+                                          and will contain the PRM ACPI table. In case of an error in this function,
+                                          *PrmAcpiDescriptorTable will be NULL.
+
+  @retval EFI_SUCCESS                     All PRM Modules were processed to construct the PRM ACPI table successfully.
+  @retval EFI_INVALID_PARAMETER           THe parameter PrmAcpiDescriptionTable is NULL.
+  @retval EFI_OUT_OF_RESOURCES            Insufficient memory resources to allocate the PRM ACPI table boot services
+                                          memory data buffer.
+
+**/
+EFI_STATUS
+ProcessPrmModules (
+  OUT PRM_ACPI_DESCRIPTION_TABLE          **PrmAcpiDescriptionTable
+  )
+{
+  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;
+  CONST CHAR8                             *CurrentExportDescriptorHandlerName;
+
+  PRM_CONTEXT_BUFFER                      *CurrentContextBuffer;
+  PRM_MODULE_CONTEXT_BUFFERS              *CurrentModuleContextBuffers;
+  PRM_MODULE_INFORMATION_STRUCT           *CurrentModuleInfoStruct;
+  PRM_HANDLER_INFORMATION_STRUCT          *CurrentHandlerInfoStruct;
+
+  EFI_STATUS                              Status;
+  EFI_PHYSICAL_ADDRESS                    CurrentImageAddress;
+  UINTN                                   HandlerIndex;
+  UINT32                                  PrmAcpiDescriptionTableBufferSize;
+
+  UINT64                                  HandlerPhysicalAddress;
+
+  DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  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) +
+                                        (OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) *  mPrmModuleCount) +
+                                        (sizeof (PRM_HANDLER_INFORMATION_STRUCT) * mPrmHandlerCount)
+                                        );
+  DEBUG ((DEBUG_INFO, "  %a %a: Total PRM ACPI table size: 0x%x.\n", _DBGMSGID_, __FUNCTION__, PrmAcpiDescriptionTableBufferSize));
+
+  PrmAcpiTable = AllocateZeroPool ((UINTN) PrmAcpiDescriptionTableBufferSize);
+  if (PrmAcpiTable == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  PrmAcpiTable->Header.Signature        = PRM_TABLE_SIGNATURE;
+  PrmAcpiTable->Header.Length           = PrmAcpiDescriptionTableBufferSize;
+  PrmAcpiTable->Header.Revision         = PRM_TABLE_REVISION;
+  PrmAcpiTable->Header.Checksum         = 0x0;
+  CopyMem (&PrmAcpiTable->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (PrmAcpiTable->Header.OemId));
+  PrmAcpiTable->Header.OemTableId       = PcdGet64 (PcdAcpiDefaultOemTableId);
+  PrmAcpiTable->Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
+  PrmAcpiTable->Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
+  PrmAcpiTable->Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+  PrmAcpiTable->PrmModuleInfoOffset     = OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure);
+  PrmAcpiTable->PrmModuleInfoCount      = 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;
+
+    DEBUG ((
+      DEBUG_INFO,
+      "  %a %a: PRM Module - %a with %d handlers.\n",
+      _DBGMSGID_,
+      __FUNCTION__,
+      (CHAR8 *) ((UINTN) CurrentImageAddress + CurrentImageExportDirectory->Name),
+      CurrentExportDescriptorStruct->NumberPrmHandlers
+      ));
+
+    CurrentModuleInfoStruct->StructureRevision = PRM_MODULE_INFORMATION_STRUCT_REVISION;
+    CurrentModuleInfoStruct->StructureLength = (
+                                             OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) +
+                                             (CurrentExportDescriptorStruct->NumberPrmHandlers * sizeof (PRM_HANDLER_INFORMATION_STRUCT))
+                                             );
+    CopyGuid (&CurrentModuleInfoStruct->Identifier, &CurrentExportDescriptorStruct->ModuleGuid);
+    CurrentModuleInfoStruct->HandlerCount       = (UINT32) CurrentExportDescriptorStruct->NumberPrmHandlers;
+    CurrentModuleInfoStruct->HandlerInfoOffset  = OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure);
+
+    CurrentModuleInfoStruct->MajorRevision = 0;
+    CurrentModuleInfoStruct->MinorRevision = 0;
+    Status =  GetImageVersionInPeCoffImage (
+                (VOID *) (UINTN) CurrentImageAddress,
+                &TempListEntry->Context->PeCoffImageContext,
+                &CurrentModuleInfoStruct->MajorRevision,
+                &CurrentModuleInfoStruct->MinorRevision
+                );
+    ASSERT_EFI_ERROR (Status);
+
+    Status =  GetExportEntryAddress (
+                PRM_STRING (PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_NAME),
+                CurrentImageAddress,
+                CurrentImageExportDirectory,
+                (EFI_PHYSICAL_ADDRESS *) &(CurrentModuleInfoStruct->ModuleUpdateLock)
+                );
+    ASSERT_EFI_ERROR (Status);
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((
+        DEBUG_INFO,
+        "    %a %a: Found PRM module update lock physical address at 0x%016x.\n",
+        _DBGMSGID_,
+        __FUNCTION__,
+        CurrentModuleInfoStruct->ModuleUpdateLock
+        ));
+    }
+
+    // It is currently valid for a PRM module not to use a context buffer
+    Status = GetModuleContextBuffers (
+              ByModuleGuid,
+              &CurrentModuleInfoStruct->Identifier,
+              &CurrentModuleContextBuffers
+              );
+    ASSERT (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND);
+    if (!EFI_ERROR (Status) && CurrentModuleContextBuffers != NULL) {
+      CurrentModuleInfoStruct->RuntimeMmioRanges = (UINT64) (UINTN) CurrentModuleContextBuffers->RuntimeMmioRanges;
+    }
+
+    //
+    // Iterate across all PRM handlers in the PRM Module
+    //
+    for (HandlerIndex = 0; HandlerIndex < CurrentExportDescriptorStruct->NumberPrmHandlers; HandlerIndex++) {
+      CurrentHandlerInfoStruct = &(CurrentModuleInfoStruct->HandlerInfoStructure[HandlerIndex]);
+
+      CurrentHandlerInfoStruct->StructureRevision = PRM_HANDLER_INFORMATION_STRUCT_REVISION;
+      CurrentHandlerInfoStruct->StructureLength = sizeof (PRM_HANDLER_INFORMATION_STRUCT);
+      CopyGuid (
+        &CurrentHandlerInfoStruct->Identifier,
+        &CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerGuid
+        );
+
+      CurrentExportDescriptorHandlerName = (CONST CHAR8 *) CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerName;
+
+      Status =  GetContextBuffer (
+                  &CurrentHandlerInfoStruct->Identifier,
+                  CurrentModuleContextBuffers,
+                  &CurrentContextBuffer
+                  );
+      if (!EFI_ERROR (Status)) {
+        CurrentHandlerInfoStruct->PrmContextBuffer = (UINT64) CurrentContextBuffer;
+      }
+
+      Status =  GetExportEntryAddress (
+                  CurrentExportDescriptorHandlerName,
+                  CurrentImageAddress,
+                  CurrentImageExportDirectory,
+                  &HandlerPhysicalAddress
+                  );
+      ASSERT_EFI_ERROR (Status);
+      if (!EFI_ERROR (Status)) {
+        CurrentHandlerInfoStruct->PhysicalAddress = HandlerPhysicalAddress;
+        DEBUG ((
+          DEBUG_INFO,
+          "    %a %a: Found %a handler physical address at 0x%016x.\n",
+          _DBGMSGID_,
+          __FUNCTION__,
+          CurrentExportDescriptorHandlerName,
+          CurrentHandlerInfoStruct->PhysicalAddress
+          ));
+      }
+    }
+    CurrentModuleInfoStruct = (PRM_MODULE_INFORMATION_STRUCT *) ((UINTN) CurrentModuleInfoStruct + CurrentModuleInfoStruct->StructureLength);
+  }
+  *PrmAcpiDescriptionTable = PrmAcpiTable;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Publishes the PRM ACPI table (PRMT).
+
+  @param[in]  PrmAcpiDescriptionTable     A pointer to a buffer with a completely populated and valid PRM
+                                          ACPI description table.
+
+  @retval EFI_SUCCESS                     The PRM ACPI was installed successfully.
+  @retval EFI_INVALID_PARAMETER           THe parameter PrmAcpiDescriptionTable is NULL or the table signature
+                                          in the table provided is invalid.
+  @retval EFI_NOT_FOUND                   The protocol gEfiAcpiTableProtocolGuid could not be found.
+  @retval EFI_OUT_OF_RESOURCES            Insufficient memory resources to allocate the PRM ACPI table buffer.
+
+**/
+EFI_STATUS
+PublishPrmAcpiTable (
+  IN  PRM_ACPI_DESCRIPTION_TABLE          *PrmAcpiDescriptionTable
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_ACPI_TABLE_PROTOCOL                 *AcpiTableProtocol;
+  UINTN                                   TableKey;
+
+  if (PrmAcpiDescriptionTable == NULL || PrmAcpiDescriptionTable->Header.Signature != PRM_TABLE_SIGNATURE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
+  if (!EFI_ERROR (Status)) {
+    TableKey = 0;
+    //
+    // Publish the PRM ACPI table. The table checksum will be computed during installation.
+    //
+    Status = AcpiTableProtocol->InstallAcpiTable (
+                                  AcpiTableProtocol,
+                                  PrmAcpiDescriptionTable,
+                                  PrmAcpiDescriptionTable->Header.Length,
+                                  &TableKey
+                                  );
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO, "%a %a: The PRMT ACPI table was installed successfully.\n", _DBGMSGID_, __FUNCTION__));
+    }
+  }
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  The PRM Loader END_OF_DXE protocol notification event handler.
+
+  All PRM Modules that are eligible for dispatch should have been loaded the DXE Dispatcher at the
+  time of this function invocation.
+
+  The main responsibilities of the PRM Loader are executed from this function which include 3 phases:
+    1.) Disover PRM Modules - Find all PRM modules loaded during DXE dispatch and insert a PRM Module
+        Context entry into a linked list to be handed off to phase 2.
+    2.) Process PRM Modules - Build a GUID to PRM handler mapping for each module that is described in the
+        PRM ACPI table so the OS can resolve a PRM Handler GUID to the corresponding PRM Handler physical address.
+    3.) Publish PRM ACPI Table - Publish the PRM ACPI table with the information gathered in the phase 2.
+
+  @param[in]  Event                       Event whose notification function is being invoked.
+  @param[in]  Context                     The pointer to the notification function's context,
+                                          which is implementation-dependent.
+
+  @retval EFI_SUCCESS                     The function executed successfully
+
+**/
+EFI_STATUS
+EFIAPI
+PrmLoaderEndOfDxeNotification (
+  IN  EFI_EVENT                           Event,
+  IN  VOID                                *Context
+  )
+{
+  EFI_STATUS                              Status;
+  PRM_ACPI_DESCRIPTION_TABLE              *PrmAcpiDescriptionTable;
+
+  DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  InitializeListHead (&mPrmModuleList);
+
+  Status = DiscoverPrmModules ();
+  ASSERT_EFI_ERROR (Status);
+
+  Status = ProcessPrmModules (&PrmAcpiDescriptionTable);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = PublishPrmAcpiTable (PrmAcpiDescriptionTable);
+  ASSERT_EFI_ERROR (Status);
+
+  if (PrmAcpiDescriptionTable != NULL) {
+    FreePool (PrmAcpiDescriptionTable);
+  }
+  gBS->CloseEvent (Event);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The entry point for this module.
+
+  @param  ImageHandle    The firmware allocated handle for the EFI image.
+  @param  SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS    The entry point is executed successfully.
+  @retval Others         An error occurred when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+PrmLoaderEntryPoint (
+  IN EFI_HANDLE                           ImageHandle,
+  IN EFI_SYSTEM_TABLE                     *SystemTable
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_EVENT                               EndOfDxeEvent;
+
+  DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  //
+  // Discover and process installed PRM modules at the End of DXE
+  // The PRM ACPI table is published if one or PRM modules are discovered
+  //
+  Status = gBS->CreateEventEx(
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  PrmLoaderEndOfDxeNotification,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a %a: EndOfDxe callback registration failed! %r.\n", _DBGMSGID_, __FUNCTION__, Status));
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/PrmConfigDxe/PrmConfigDxe.inf b/PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
new file mode 100644
index 000000000000..88613c146a0b
--- /dev/null
+++ b/PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
@@ -0,0 +1,48 @@
+## @file
+#  PRM Configuration Driver
+#
+#  This driver configures PRM Module settings during the boot services environment.
+#
+#  Copyright (c) Microsoft Corporation
+#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION           = 0x00010005
+  BASE_NAME             = PrmConfigDxe
+  FILE_GUID             = 18D93D57-0B00-4213-B0A2-A2FF5EC214E4
+  MODULE_TYPE           = DXE_RUNTIME_DRIVER
+  VERSION_STRING        = 1.0
+  ENTRY_POINT           = PrmConfigEntryPoint
+
+[Sources]
+  PrmConfigDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid
+  gEfiEventVirtualAddressChangeGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  DxeServicesTableLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiRuntimeServicesTableLib
+  UefiLib
+
+[Protocols]
+  gPrmConfigProtocolGuid
+
+[Depex]
+  TRUE
diff --git a/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
new file mode 100644
index 000000000000..6b9099ca7ba7
--- /dev/null
+++ b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
@@ -0,0 +1,97 @@
+/** @file
+
+  Definition for the Platform Runtime Mechanism (PRM) ACPI table (PRMT).
+
+  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRMT_ACPI_TABLE_H_
+#define PRMT_ACPI_TABLE_H_
+
+#include <Base.h>
+#include <IndustryStandard/Acpi10.h>
+
+#define PRM_TABLE_SIGNATURE                       SIGNATURE_32 ('P', 'R', 'M', 'T')
+
+#define PRM_TABLE_REVISION                        0x0
+#define PRM_MODULE_INFORMATION_STRUCT_REVISION    0x00
+#define PRM_HANDLER_INFORMATION_STRUCT_REVISION   0x00
+
+#pragma pack(push, 1)
+
+//
+// Platform Runtime Mechanism (PRM) ACPI Table (PRMT) structures
+//
+typedef struct {
+  UINT16                              StructureRevision;          ///< Revision of this structure
+  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
+  UINT64                              PrmContextBuffer;           ///< Physical address of the context buffer for this
+                                                                  ///< PRM handler (PRM_CONTEXT_BUFFER *)
+  UINT64                              StaticDataBuffer;           ///< Physical address of the static data buffer for
+                                                                  ///< this PRM handler (PRM_DATA_BUFFER *)
+  UINT64                              AcpiParameterBuffer;        ///< Physical address of the parameter buffer
+                                                                  ///< for this PRM handler (PRM_DATA_BUFFER *)
+                                                                  ///< that is only used in the case of _DSM invocation.
+                                                                  ///< If _DSM invocation is not used, this value is
+                                                                  ///< ignored.
+} PRM_HANDLER_INFORMATION_STRUCT;
+
+typedef struct {
+  UINT16                              StructureRevision;          ///< Revision of this structure
+  UINT16                              StructureLength;            ///< Length in bytes of this structure including the
+                                                                  ///< variable length PRM Handler Info array
+  GUID                                Identifier;                 ///< GUID of the PRM module for this structure
+  UINT16                              MajorRevision;              ///< PRM module major revision
+  UINT16                              MinorRevision;              ///< PRM module minor revision
+  UINT16                              HandlerCount;               ///< Number of entries in the Handler Info array
+  UINT32                              HandlerInfoOffset;          ///< Offset in bytes from the beginning of this
+                                                                  ///< structure to the Handler Info array
+  UINT64                              ModuleUpdateLock;           ///< Physical address of the PRM Module Update Lock
+                                                                  ///< descriptor (PRM_MODULE_UPDATE_LOCK_DESCRIPTOR *)
+  UINT64                              RuntimeMmioRanges;          ///< Physical address of the PRM MMIO Ranges
+                                                                  ///< structure (PRM_MODULE_RUNTIME_MMIO_RANGES *)
+  PRM_HANDLER_INFORMATION_STRUCT      HandlerInfoStructure[1];
+} PRM_MODULE_INFORMATION_STRUCT;
+
+typedef struct {
+  EFI_ACPI_DESCRIPTION_HEADER         Header;                     ///< Standard ACPI description header
+  UINT32                              PrmModuleInfoOffset;        ///< Offset in bytes from the beginning of this
+                                                                  ///< structure to the PRM Module Info array
+  UINT32                              PrmModuleInfoCount;         ///< Number of entries in the PRM Module Info array
+  PRM_MODULE_INFORMATION_STRUCT       PrmModuleInfoStructure[1];
+} PRM_ACPI_DESCRIPTION_TABLE;
+
+#pragma pack(pop)
+
+//
+// Helper macros to build PRM Information structures
+//
+// Todo: Revisit whether to use; currently both macros are not used
+//
+#define PRM_MODULE_INFORMATION_STRUCTURE(ModuleGuid, ModuleRevision, HandlerCount, PrmHanderInfoStructureArray) {                       \
+    {                                                                                                                                   \
+      PRM_MODULE_INFORMATION_STRUCT_REVISION,                              /* UINT16    StructureRevision;   */                         \
+      (OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) + (HandlerCount * sizeof (PRM_HANDLER_INFORMATION_STRUCT)))   /* UINT16    StructureLength;     */ \
+      ModuleGuid,                                                          /* GUID      ModuleGuid;          */                         \
+      ModuleRevision,                                                      /* UINT16    ModuleRevision       */                         \
+      HandlerCount,                                                        /* UINT16    HandlerCount         */                         \
+      OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoOffset),        /* UINT32    HandlerInfoOffset    */                         \
+      PrmHanderInfoStructureArray                                          /* PRM_HANDLER_INFORMATION_STRUCT HandlerInfoStructure */    \
+    } \
+  }
+
+#define PRM_HANDLER_INFORMATION_STRUCTURE(HandlerGuid, PhysicalAddress) {                                                   \
+    {                                                                                                                              \
+      PRM_HANDLER_INFORMATION_STRUCT_REVISION,                             /* UINT16                  StructureRevision;      */   \
+      sizeof (PRM_HANDLER_INFORMATION_STRUCT),                             /* UINT16                  StructureLength;        */   \
+      HandlerGuid,                                                         /* GUID                    HandlerGuid;            */   \
+      PhysicalAddress,                                                     /* UINT64                  PhysicalAddress         */   \
+    } \
+  }
+
+#endif // _PRMT_ACPI_TABLE_H_
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoader.h b/PrmPkg/PrmLoaderDxe/PrmLoader.h
new file mode 100644
index 000000000000..1356c7a0c923
--- /dev/null
+++ b/PrmPkg/PrmLoaderDxe/PrmLoader.h
@@ -0,0 +1,51 @@
+/** @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.inf b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
new file mode 100644
index 000000000000..643e1a7989f2
--- /dev/null
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
@@ -0,0 +1,59 @@
+## @file
+#  PRM Loader Driver
+#
+#  This driver discovers PRM Modules loaded in memory and places those modules and the
+#  PRM handlers within those modules into a PRMT ACPI table such that the handlers are
+#  made available for invocation in the OS.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PrmLoaderDxe
+  FILE_GUID                      = 226A500A-E14F-414A-A956-40E5762D3D1E
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PrmLoaderEntryPoint
+
+[Sources]
+  PrmAcpiTable.h
+  PrmLoader.h
+  PrmLoaderDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  PeCoffLib
+  PrmContextBufferLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId            ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId       ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision      ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId        ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision  ## CONSUMES
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid
+  gEfiLoadedImageProtocolGuid
+  gPrmConfigProtocolGuid
+
+[Depex]
+  TRUE
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 05/41] PrmPkg: Add initial PrmSamplePrintModule
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (3 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 04/41] PrmPkg/PrmConfigDxe: Add initial driver Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 06/41] PrmPkg: Add initial PrmSampleMemoryAllocationModule Michael Kubacki
                   ` (35 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

Adds a simple sample PRM module that demonstrates:
  1. How to write a PRM module
  2. How to use multiple PRM handlers in a module
  3. How to use a basic PRM OS service

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>
---
 PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.c   | 157 ++++++++++++++++++++
 PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf |  39 +++++
 2 files changed, 196 insertions(+)

diff --git a/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.c b/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.c
new file mode 100644
index 000000000000..85e8eb28a231
--- /dev/null
+++ b/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.c
@@ -0,0 +1,157 @@
+/** @file
+
+  A sample PRM Module implementation. This PRM Module provides 3 PRM handlers that simply take a DEBUG print
+  function from the OS and invoke it with a debug message internal the PRM handler.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PrmModule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+
+//
+// PRM Handler GUIDs
+//
+
+// {d5f2ad5f-a347-4d3e-87bc-c2ce63029cc8}
+#define PRM_HANDLER_1_GUID {0xd5f2ad5f, 0xa347, 0x4d3e, {0x87, 0xbc, 0xc2, 0xce, 0x63, 0x02, 0x9c, 0xc8}}
+
+// {a9e7adc3-8cd0-429a-8915-10946ebde318}
+#define PRM_HANDLER_2_GUID  {0xa9e7adc3, 0x8cd0, 0x429a, {0x89, 0x15, 0x10, 0x94, 0x6e, 0xbd, 0xe3, 0x18}}
+
+// {b688c214-4081-4eeb-8d26-1eb5a3bcf11a}
+#define PRM_HANDLER_N_GUID {0xb688c214, 0x4081, 0x4eeb, {0x8d, 0x26, 0x1e, 0xb5, 0xa3, 0xbc, 0xf1, 0x1a}}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler currently uses the OS_SERVICES to write a debug message
+  indicating this is PRM handler 1.
+
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+EFI_STATUS
+PRM_EXPORT_API
+EFIAPI
+PrmHandler1 (
+  IN VOID                         *ParameterBuffer,
+  IN PRM_CONTEXT_BUFFER           *ContextBUffer
+  )
+{
+  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
+
+  if (ParameterBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
+  if (OsServiceDebugPrint == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  OsServiceDebugPrint ("PRM1 handler sample message!\n");
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler currently uses the OS_SERVICES to write a debug message
+  indicating this is PRM handler 2.
+
+  @param[in]  ParameterBuffer    A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer      A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS             The PRM handler executed successfully.
+  @retval Others                 An error occurred in the PRM handler.
+
+**/
+EFI_STATUS
+PRM_EXPORT_API
+EFIAPI
+PrmHandler2 (
+  IN VOID                         *ParameterBuffer,
+  IN PRM_CONTEXT_BUFFER           *ContextBUffer
+  )
+{
+  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
+
+  if (ParameterBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
+  if (OsServiceDebugPrint == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  OsServiceDebugPrint ("PRM2 handler sample message!\n");
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler currently uses the OS_SERVICES to write a debug message
+  indicating this is PRM handler N.
+
+  @param[in]  ParameterBuffer    A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer      A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS             The PRM handler executed successfully.
+  @retval Others                 An error occurred in the PRM handler.
+
+**/
+EFI_STATUS
+PRM_EXPORT_API
+EFIAPI
+PrmHandlerN (
+  IN VOID                         *ParameterBuffer,
+  IN PRM_CONTEXT_BUFFER           *ContextBUffer
+  )
+{
+  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
+
+  if (ParameterBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
+  if (OsServiceDebugPrint == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  OsServiceDebugPrint ("PRMN handler sample message!\n");
+
+  return EFI_SUCCESS;
+}
+
+//
+// Register the PRM export information for this PRM Module
+//
+PRM_MODULE_EXPORT (
+  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_1_GUID, PrmHandler1),
+  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_2_GUID, PrmHandler2),
+  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_N_GUID, PrmHandlerN)
+  );
+
+EFI_STATUS
+EFIAPI
+PrmSamplePrintModuleInit (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  EFI_SYSTEM_TABLE            *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf b/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
new file mode 100644
index 000000000000..d685bf888a1c
--- /dev/null
+++ b/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
@@ -0,0 +1,39 @@
+## @file
+#  Sample PRM Driver
+#
+#  This driver simply uses an OS-provided debug message print service to write
+#  a debug message. Three PRM handlers are provided that each print a unique
+#  debug message.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PrmSamplePrintModule
+  FILE_GUID                      = 1652B3C2-A7A1-46AC-AF93-DD6DEE446669
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PrmSamplePrintModuleInit
+
+[Sources]
+  PrmSamplePrintModule.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Depex]
+  TRUE
+
+[BuildOptions.common]
+  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 06/41] PrmPkg: Add initial PrmSampleMemoryAllocationModule
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (4 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 05/41] PrmPkg: Add initial PrmSamplePrintModule Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 07/41] PrmPkg: Add initial PrmSampleHardwareAccessModule Michael Kubacki
                   ` (34 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

DEPRECATED: This module is no longer relevant since OS Services that
allow memory allocation have been removed. It is still present in the
source tree in the event dynamic memory allocation at OS runtime is
needed again.

  Adds a sample PRM module that demonstrates:
  1. How to write a PRM module
  2. How to use a basic PRM OS service
  3. How to dynamically allocate memory at OS runtime

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>
---
 PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.c   | 115 ++++++++++++++++++++
 PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf |  41 +++++++
 2 files changed, 156 insertions(+)

diff --git a/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.c b/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.c
new file mode 100644
index 000000000000..f1245664ab9c
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.c
@@ -0,0 +1,115 @@
+/** @file
+
+  A sample PRM Module implementation. This PRM Module provides 3 PRM handlers that simply take a DEBUG print
+  function from the OS and invoke it with a debug message internal the PRM handler.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PrmModule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+
+//
+// PRM Handler GUIDs
+//
+
+// {149a5cb3-6a9c-403f-940a-156abf63938a}
+#define PRM_HANDLER_1_GUID {0x149a5cb3, 0x6a9c, 0x403f, {0x94, 0x0a, 0x15, 0x6a, 0xbf, 0x63, 0x93, 0x8a}}
+
+// Note: If the signature size is modified, the PRM Handler test code in this module needs to be updated.
+#define MEMORY_ALLOCATION_TEST_DATA_SIGNATURE     SIGNATURE_32('T','E','S','T')
+#define MEMORY_ALLOCATION_TEST_DATA_SIZE          sizeof(UINT32)
+#define MEMORY_ALLOCATION_TEST_DATA_BUFFER_SIZE   256
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler currently uses the OS_SERVICES to write a debug message
+  indicating this is PRM handler 1.
+
+  @param[in]  ParameterBuffer    A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBuffer      A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+EFI_STATUS
+PRM_EXPORT_API
+EFIAPI
+PrmHandler1 (
+  IN VOID                         *ParameterBuffer,
+  IN PRM_CONTEXT_BUFFER           *ContextBUffer
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           Index;
+  VOID                            *NonPagedPool;
+  CHAR8                           DebugMessage[256];
+
+  if (OsServices == NULL || OsServices->DebugPrint == NULL || OsServices->AllocateMemory == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OsServices->DebugPrint ("Memory Allocation PrmHandler1 entry.\n");
+  OsServices->DebugPrint ("  Requesting allocation of a 256 byte non-paged pool...\n");
+
+  NonPagedPool = NULL;
+  NonPagedPool = OsServices->AllocateMemory (MEMORY_ALLOCATION_TEST_DATA_BUFFER_SIZE, FALSE);
+  if (NonPagedPool == NULL) {
+    OsServices->DebugPrint ("  NULL was returned from AllocateMemory()...\n");
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  Buffer address returned from AllocateMemory() = 0x%016lx.\n",
+    (UINTN) NonPagedPool
+    );
+  OsServices->DebugPrint (&DebugMessage[0]);
+
+  // Write the test data
+  OsServices->DebugPrint ("  Beginning memory buffer write and read back test...\n");
+  SetMem32 (NonPagedPool, MEMORY_ALLOCATION_TEST_DATA_BUFFER_SIZE, MEMORY_ALLOCATION_TEST_DATA_SIGNATURE);
+
+  // Read back and verify the test data is valid
+  for (Index = 0, Status = EFI_SUCCESS; Index < (MEMORY_ALLOCATION_TEST_DATA_BUFFER_SIZE / MEMORY_ALLOCATION_TEST_DATA_SIZE); Index++) {
+    if (((UINT32 *) NonPagedPool)[Index] != MEMORY_ALLOCATION_TEST_DATA_SIGNATURE) {
+      Status = EFI_DEVICE_ERROR;
+      break;
+    }
+  }
+  if (EFI_ERROR (Status)) {
+    OsServices->DebugPrint ("    Memory write & read test failed.\n");
+  } else {
+    OsServices->DebugPrint ("    Memory write & read test passed.\n");
+  }
+
+  OsServices->DebugPrint ("Memory Allocation PrmHandler1 exit.\n");
+
+  return EFI_SUCCESS;
+}
+
+//
+// Register the PRM export information for this PRM Module
+//
+PRM_MODULE_EXPORT (
+  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_1_GUID, PrmHandler1)
+  );
+
+EFI_STATUS
+EFIAPI
+PrmSampleMemoryAllocationModuleInit (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  EFI_SYSTEM_TABLE            *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf b/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
new file mode 100644
index 000000000000..e6798afe19e8
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
@@ -0,0 +1,41 @@
+## @file
+#  Sample PRM Driver
+#
+#  This driver simply uses an OS-provided debug message print service to write
+#  a debug message. Three PRM handlers are provided that each print a unique
+#  debug message.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PrmSampleMemoryAllocationModule
+  FILE_GUID                      = C6B3E74A-12E3-4364-8FB4-8C8B34DD153B
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PrmSampleMemoryAllocationModuleInit
+
+[Sources]
+  PrmSampleMemoryAllocationModule.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  PrintLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Depex]
+  TRUE
+
+[BuildOptions.common]
+  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 07/41] PrmPkg: Add initial PrmSampleHardwareAccessModule
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (5 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 06/41] PrmPkg: Add initial PrmSampleMemoryAllocationModule Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 08/41] PrmPkg: Add initial PrmSampleContextBufferModule Michael Kubacki
                   ` (33 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

Adds a sample PRM module that demonstrates:
  1. How to write a PRM module
  2. How to use multiple PRM handlers in a module
  3. How to use a basic PRM OS service
  4. MSR access at OS runtime

Note: This module contains a PRM handler to read from the HPET MMIO
      range but the memory map changes needed for this to succeed
      are currently not implemented. These will be implemented in a
      future change.

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>
---
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c   | 537 ++++++++++++++++++++
 PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h                            | 105 ++++
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf |  42 ++
 3 files changed, 684 insertions(+)

diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
new file mode 100644
index 000000000000..87fe9cafc912
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
@@ -0,0 +1,537 @@
+/** @file
+
+  A sample PRM Module implementation. This PRM Module provides PRM handlers that perform various types
+  of hardware access. This is simply meant to demonstrate hardware access capabilities from a PRM handler.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PrmModule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+
+#include <Register/Intel/ArchitecturalMsr.h>
+#include <Register/Intel/Cpuid.h>
+
+#include "Hpet.h"
+
+//
+// PRM Handler GUIDs
+//
+
+// {2120cd3c-848b-4d8f-abbb-4b74ce64ac89}
+#define MSR_ACCESS_MICROCODE_SIGNATURE_PRM_HANDLER_GUID {0x2120cd3c, 0x848b, 0x4d8f, {0xab, 0xbb, 0x4b, 0x74, 0xce, 0x64, 0xac, 0x89}}
+
+// {ea0935a7-506b-4159-bbbb-48deeecb6f58}
+#define MSR_ACCESS_MTRR_DUMP_PRM_HANDLER_GUID {0xea0935a7, 0x506b, 0x4159, {0xbb, 0xbb, 0x48, 0xde, 0xee, 0xcb, 0x6f, 0x58}}
+
+// {1bd1bda9-909a-4614-9699-25ec0c2783f7}
+#define MMIO_ACCESS_HPET_PRM_HANDLER_GUID {0x1bd1bda9, 0x909a, 0x4614, {0x96, 0x99, 0x25, 0xec, 0x0c, 0x27, 0x83, 0xf7}}
+
+#define HPET_BASE_ADDRESS 0xFED00000
+
+//
+// BEGIN: MtrrLib internal library globals and function prototypes here for testing
+//
+extern CONST CHAR8        *mMtrrMemoryCacheTypeShortName[];
+
+/**
+  Initializes the valid bits mask and valid address mask for MTRRs.
+
+  This function initializes the valid bits mask and valid address mask for MTRRs.
+
+  @param[out]  MtrrValidBitsMask     The mask for the valid bit of the MTRR
+  @param[out]  MtrrValidAddressMask  The valid address mask for the MTRR
+
+**/
+VOID
+MtrrLibInitializeMtrrMask (
+  OUT UINT64 *MtrrValidBitsMask,
+  OUT UINT64 *MtrrValidAddressMask
+  );
+
+/**
+  Convert variable MTRRs to a RAW MTRR_MEMORY_RANGE array.
+  One MTRR_MEMORY_RANGE element is created for each MTRR setting.
+  The routine doesn't remove the overlap or combine the near-by region.
+
+  @param[in]   VariableSettings      The variable MTRR values to shadow
+  @param[in]   VariableMtrrCount     The number of variable MTRRs
+  @param[in]   MtrrValidBitsMask     The mask for the valid bit of the MTRR
+  @param[in]   MtrrValidAddressMask  The valid address mask for MTRR
+  @param[out]  VariableMtrr          The array to shadow variable MTRRs content
+
+  @return      Number of MTRRs which has been used.
+
+**/
+UINT32
+MtrrLibGetRawVariableRanges (
+  IN  MTRR_VARIABLE_SETTINGS  *VariableSettings,
+  IN  UINTN                   VariableMtrrCount,
+  IN  UINT64                  MtrrValidBitsMask,
+  IN  UINT64                  MtrrValidAddressMask,
+  OUT MTRR_MEMORY_RANGE       *VariableMtrr
+  );
+
+/**
+  Apply the fixed MTRR settings to memory range array.
+
+  @param Fixed             The fixed MTRR settings.
+  @param Ranges            Return the memory range array holding memory type
+                           settings for all memory address.
+  @param RangeCapacity     The capacity of memory range array.
+  @param RangeCount        Return the count of memory range.
+
+  @retval RETURN_SUCCESS          The memory range array is returned successfully.
+  @retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity.
+**/
+RETURN_STATUS
+MtrrLibApplyFixedMtrrs (
+  IN     MTRR_FIXED_SETTINGS  *Fixed,
+  IN OUT MTRR_MEMORY_RANGE    *Ranges,
+  IN     UINTN                RangeCapacity,
+  IN OUT UINTN                *RangeCount
+  );
+
+/**
+  Apply the variable MTRR settings to memory range array.
+
+  @param VariableMtrr      The variable MTRR array.
+  @param VariableMtrrCount The count of variable MTRRs.
+  @param Ranges            Return the memory range array with new MTRR settings applied.
+  @param RangeCapacity     The capacity of memory range array.
+  @param RangeCount        Return the count of memory range.
+
+  @retval RETURN_SUCCESS          The memory range array is returned successfully.
+  @retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity.
+**/
+RETURN_STATUS
+MtrrLibApplyVariableMtrrs (
+  IN     CONST MTRR_MEMORY_RANGE *VariableMtrr,
+  IN     UINT32                  VariableMtrrCount,
+  IN OUT MTRR_MEMORY_RANGE       *Ranges,
+  IN     UINTN                   RangeCapacity,
+  IN OUT UINTN                   *RangeCount
+  );
+
+//
+// END: MtrrLib internal library function prototypes here for testing
+//
+
+/**
+  Prints all MTRR values including architectural and variable MTTRs.
+
+**/
+VOID
+EFIAPI
+PrintAllMtrrs (
+  IN PRM_OS_SERVICE_DEBUG_PRINT   OsServiceDebugPrint
+  )
+{
+  MTRR_SETTINGS                   LocalMtrrs;
+  MTRR_SETTINGS                   *Mtrrs;
+  UINTN                           Index;
+  UINTN                           RangeCount;
+  UINT64                          MtrrValidBitsMask;
+  UINT64                          MtrrValidAddressMask;
+  UINT32                          VariableMtrrCount;
+  BOOLEAN                         ContainVariableMtrr;
+  CHAR8                           DebugMessage[256];
+
+  MTRR_MEMORY_RANGE Ranges[
+    MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * ARRAY_SIZE (Mtrrs->Variables.Mtrr) + 1
+    ];
+  MTRR_MEMORY_RANGE RawVariableRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)];
+
+  if (OsServiceDebugPrint == NULL || !IsMtrrSupported ()) {
+    return;
+  }
+
+  VariableMtrrCount = GetVariableMtrrCount ();
+
+  MtrrGetAllMtrrs (&LocalMtrrs);
+  Mtrrs = &LocalMtrrs;
+
+  //
+  // Dump RAW MTRR contents
+  //
+  OsServiceDebugPrint ("  MTRR Settings:\n");
+  OsServiceDebugPrint ("  =============\n");
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  MTRR Default Type: %016lx\n",
+    Mtrrs->MtrrDefType
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  Fixed MTRR[%02d]   : %016lx\n",
+      Index,
+      Mtrrs->Fixed.Mtrr[Index]
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
+  }
+  ContainVariableMtrr = FALSE;
+  for (Index = 0; Index < VariableMtrrCount; Index++) {
+    if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {
+      //
+      // If mask is not valid, then do not display range
+      //
+      continue;
+    }
+    ContainVariableMtrr = TRUE;
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
+      Index,
+      Mtrrs->Variables.Mtrr[Index].Base,
+      Mtrrs->Variables.Mtrr[Index].Mask
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
+  }
+  if (!ContainVariableMtrr) {
+    OsServiceDebugPrint ("  Variable MTRR    : None.\n");
+  }
+  OsServiceDebugPrint ("\n");
+
+  //
+  // Dump MTRR setting in ranges
+  //
+  OsServiceDebugPrint ("  Memory Ranges:\n");
+  OsServiceDebugPrint ("  ====================================\n");
+  MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
+  Ranges[0].BaseAddress = 0;
+  Ranges[0].Length      = MtrrValidBitsMask + 1;
+  Ranges[0].Type        = MtrrGetDefaultMemoryType ();
+  RangeCount = 1;
+
+  MtrrLibGetRawVariableRanges (
+    &Mtrrs->Variables, VariableMtrrCount,
+    MtrrValidBitsMask, MtrrValidAddressMask, RawVariableRanges
+    );
+  MtrrLibApplyVariableMtrrs (
+    RawVariableRanges, VariableMtrrCount,
+    Ranges, ARRAY_SIZE (Ranges), &RangeCount
+    );
+
+  MtrrLibApplyFixedMtrrs (&Mtrrs->Fixed, Ranges, ARRAY_SIZE (Ranges), &RangeCount);
+
+  for (Index = 0; Index < RangeCount; Index++) {
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  %a:%016lx-%016lx\n",
+      mMtrrMemoryCacheTypeShortName[Ranges[Index].Type],
+      Ranges[Index].BaseAddress, Ranges[Index].BaseAddress + Ranges[Index].Length - 1
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
+  }
+}
+
+/**
+  Reads a HPET MMIO register.
+
+  Reads the 64-bit HPET MMIO register specified by Address.
+
+  This function must guarantee that all MMIO read and write
+  operations are serialized.
+
+  If Address is not aligned on a 64-bit boundary, zero will be returned.
+
+  @param  Offset                  Specifies the offset of the HPET register to read.
+
+  @return                         The value read.
+
+**/
+UINT64
+EFIAPI
+HpetRead (
+  IN  UINTN                       Offset
+  )
+{
+  UINTN                           Address;
+  UINT64                          Value;
+
+  Address = HPET_BASE_ADDRESS + Offset;
+
+  if ((Address & 7) == 0) {
+    return 0;
+  }
+
+  MemoryFence ();
+  Value = *(volatile UINT64*)Address;
+  MemoryFence ();
+
+  return Value;
+}
+
+/**
+  Prints HPET configuration information.
+
+**/
+VOID
+EFIAPI
+PrintHpetConfiguration (
+  IN PRM_OS_SERVICE_DEBUG_PRINT           OsServiceDebugPrint
+  )
+{
+  UINTN                                   TimerIndex;
+  HPET_GENERAL_CAPABILITIES_ID_REGISTER   HpetGeneralCapabilities;
+  HPET_GENERAL_CONFIGURATION_REGISTER     HpetGeneralConfiguration;
+  CHAR8                                   DebugMessage[256];
+
+  if (OsServiceDebugPrint == NULL) {
+    return;
+  }
+
+  HpetGeneralCapabilities.Uint64  = HpetRead (HPET_GENERAL_CAPABILITIES_ID_OFFSET);
+  HpetGeneralConfiguration.Uint64 = HpetRead (HPET_GENERAL_CONFIGURATION_OFFSET);
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  HPET Base Address = 0x%08x\n",
+    HPET_BASE_ADDRESS
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  HPET_GENERAL_CAPABILITIES_ID  = 0x%016lx\n",
+    HpetGeneralCapabilities
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  HPET_GENERAL_CONFIGURATION    = 0x%016lx\n",
+    HpetGeneralConfiguration.Uint64
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  HPET_GENERAL_INTERRUPT_STATUS = 0x%016lx\n",
+    HpetRead (HPET_GENERAL_INTERRUPT_STATUS_OFFSET)
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  HPET_MAIN_COUNTER             = 0x%016lx\n",
+    HpetRead (HPET_MAIN_COUNTER_OFFSET)
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  HPET Main Counter Period      = %d (fs)\n",
+    HpetGeneralCapabilities.Bits.CounterClockPeriod
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  for (TimerIndex = 0; TimerIndex <= HpetGeneralCapabilities.Bits.NumberOfTimers; TimerIndex++) {
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  HPET_TIMER%d_CONFIGURATION     = 0x%016lx\n",
+      TimerIndex,
+      HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + TimerIndex * HPET_TIMER_STRIDE)
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
+
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  HPET_TIMER%d_COMPARATOR        = 0x%016lx\n",
+      TimerIndex,
+      HpetRead (HPET_TIMER_COMPARATOR_OFFSET    + TimerIndex * HPET_TIMER_STRIDE)
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
+
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  HPET_TIMER%d_MSI_ROUTE         = 0x%016lx\n",
+      TimerIndex,
+      HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET     + TimerIndex * HPET_TIMER_STRIDE)
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
+  }
+}
+
+/**
+  Prints the microcode update signature as read from architectural MSR 0x8B.
+
+**/
+VOID
+EFIAPI
+PrintMicrocodeUpdateSignature (
+  IN PRM_OS_SERVICE_DEBUG_PRINT   OsServiceDebugPrint
+  )
+{
+  MSR_IA32_BIOS_SIGN_ID_REGISTER  BiosSignIdMsr;
+  CHAR8                           DebugMessage[256];
+
+  if (OsServiceDebugPrint == NULL) {
+    return;
+  }
+
+  AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
+  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
+  BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  Signature read = 0x%x.\n",
+    BiosSignIdMsr.Bits.MicrocodeUpdateSignature
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler attempts to read the microcode update signature MSR and print the result to a debug message.
+
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+PRM_HANDLER_EXPORT (MsrAccessMicrocodeSignaturePrmHandler)
+{
+  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
+
+  if (ParameterBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
+  if (OsServiceDebugPrint == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OsServiceDebugPrint ("Hardware Access MsrAccessMicrocodeSignaturePrmHandler entry.\n");
+  OsServiceDebugPrint ("  Attempting to read the Microcode Update Signature MSR (0x8B)...\n");
+  PrintMicrocodeUpdateSignature (OsServiceDebugPrint);
+  OsServiceDebugPrint ("Hardware Access MsrAccessMicrocodeSignaturePrmHandler exit.\n");
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler attempts to read the current MTRR settings and print the result to a debug message.
+
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+PRM_HANDLER_EXPORT (MsrAccessMtrrDumpPrmHandler)
+{
+  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
+
+  if (ParameterBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
+  if (OsServiceDebugPrint == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OsServiceDebugPrint ("Hardware Access MsrAccessMtrrDumpPrmHandler entry.\n");
+  OsServiceDebugPrint ("  Attempting to dump MTRR values:\n");
+  PrintAllMtrrs (OsServiceDebugPrint);
+  OsServiceDebugPrint ("Hardware Access MsrAccessMtrrDumpPrmHandler exit.\n");
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler attempts to read from a HPET MMIO resource and print the result to a debug message.
+
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+PRM_HANDLER_EXPORT (MmioAccessHpetPrmHandler)
+{
+  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
+
+  if (ParameterBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
+  if (OsServiceDebugPrint == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OsServiceDebugPrint ("Hardware Access MmioAccessHpetPrmHandler entry.\n");
+  OsServiceDebugPrint ("  Attempting to read HPET configuration...\n");
+  PrintHpetConfiguration (OsServiceDebugPrint);
+  OsServiceDebugPrint ("Hardware Access MmioAccessHpetPrmHandler exit.\n");
+
+  return EFI_SUCCESS;
+}
+
+//
+// Register the PRM export information for this PRM Module
+//
+PRM_MODULE_EXPORT (
+  PRM_HANDLER_EXPORT_ENTRY (MSR_ACCESS_MICROCODE_SIGNATURE_PRM_HANDLER_GUID, MsrAccessMicrocodeSignaturePrmHandler),
+  PRM_HANDLER_EXPORT_ENTRY (MSR_ACCESS_MTRR_DUMP_PRM_HANDLER_GUID, MsrAccessMtrrDumpPrmHandler),
+  PRM_HANDLER_EXPORT_ENTRY (MMIO_ACCESS_HPET_PRM_HANDLER_GUID, MmioAccessHpetPrmHandler)
+  );
+
+/**
+  Module entry point.
+
+  @param[in]   ImageHandle     The image handle.
+  @param[in]   SystemTable     A pointer to the system table.
+
+  @retval  EFI_SUCCESS         This function always returns success.
+
+**/
+EFI_STATUS
+EFIAPI
+PrmSampleHardwareAccessModuleInit (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  EFI_SYSTEM_TABLE            *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h b/PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
new file mode 100644
index 000000000000..c7eb0cbfa747
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
@@ -0,0 +1,105 @@
+/** @file
+  HPET register definitions from the IA-PC HPET (High Precision Event Timers)
+  Specification, Revision 1.0a, October 2004.
+
+  PRM Module Note:
+  This specific header was copied from PcAtChipsetPkg to avoid a module dependency on the package
+  just for this header. This is done for temporary testing purposes of the PRM module.
+
+  Copyright (c) Microsoft Corporation
+  Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef HPET_REGISTER_H_
+#define HPET_REGISTER_H_
+
+///
+/// HPET General Register Offsets
+///
+#define HPET_GENERAL_CAPABILITIES_ID_OFFSET   0x000
+#define HPET_GENERAL_CONFIGURATION_OFFSET     0x010
+#define HPET_GENERAL_INTERRUPT_STATUS_OFFSET  0x020
+
+///
+/// HPET Timer Register Offsets
+///
+#define HPET_MAIN_COUNTER_OFFSET              0x0F0
+#define HPET_TIMER_CONFIGURATION_OFFSET       0x100
+#define HPET_TIMER_COMPARATOR_OFFSET          0x108
+#define HPET_TIMER_MSI_ROUTE_OFFSET           0x110
+
+///
+/// Stride between sets of HPET Timer Registers
+///
+#define HPET_TIMER_STRIDE         0x20
+
+#pragma pack(1)
+
+///
+/// HPET General Capabilities and ID Register
+///
+typedef union {
+  struct {
+    UINT32  Revision:8;
+    UINT32  NumberOfTimers:5;
+    UINT32  CounterSize:1;
+    UINT32  Reserved0:1;
+    UINT32  LegacyRoute:1;
+    UINT32  VendorId:16;
+    UINT32  CounterClockPeriod:32;
+  } Bits;
+  UINT64  Uint64;
+} HPET_GENERAL_CAPABILITIES_ID_REGISTER;
+
+///
+/// HPET General Configuration Register
+///
+typedef union {
+  struct {
+    UINT32  MainCounterEnable:1;
+    UINT32  LegacyRouteEnable:1;
+    UINT32  Reserved0:30;
+    UINT32  Reserved1:32;
+  } Bits;
+  UINT64  Uint64;
+} HPET_GENERAL_CONFIGURATION_REGISTER;
+
+///
+/// HPET Timer Configuration Register
+///
+typedef union {
+  struct {
+    UINT32  Reserved0:1;
+    UINT32  LevelTriggeredInterrupt:1;
+    UINT32  InterruptEnable:1;
+    UINT32  PeriodicInterruptEnable:1;
+    UINT32  PeriodicInterruptCapability:1;
+    UINT32  CounterSizeCapability:1;
+    UINT32  ValueSetEnable:1;
+    UINT32  Reserved1:1;
+    UINT32  CounterSizeEnable:1;
+    UINT32  InterruptRoute:5;
+    UINT32  MsiInterruptEnable:1;
+    UINT32  MsiInterruptCapability:1;
+    UINT32  Reserved2:16;
+    UINT32  InterruptRouteCapability;
+  } Bits;
+  UINT64  Uint64;
+} HPET_TIMER_CONFIGURATION_REGISTER;
+
+///
+/// HPET Timer MSI Route Register
+///
+typedef union {
+  struct {
+    UINT32  Value:32;
+    UINT32  Address:32;
+  } Bits;
+  UINT64  Uint64;
+} HPET_TIMER_MSI_ROUTE_REGISTER;
+
+#pragma pack()
+
+#endif
diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
new file mode 100644
index 000000000000..302183c576f9
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
@@ -0,0 +1,42 @@
+## @file
+#  Sample PRM Driver
+#
+#  A sample PRM Module implementation. This PRM Module provides PRM handlers that perform various types
+#  of hardware access. This is simply meant to demonstrate hardware access capabilities from a PRM handler.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PrmSampleHardwareAccessModule
+  FILE_GUID                      = 0EF93ED7-14AE-425B-928F-B85A6213B57E
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PrmSampleHardwareAccessModuleInit
+
+[Sources]
+  Hpet.h
+  PrmSampleHardwareAccessModule.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  MtrrLib
+  PrintLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Depex]
+  TRUE
+
+[BuildOptions.common]
+  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 08/41] PrmPkg: Add initial PrmSampleContextBufferModule
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (6 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 07/41] PrmPkg: Add initial PrmSampleHardwareAccessModule Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 09/41] PrmPkg: Add initial package DSC file Michael Kubacki
                   ` (32 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

Adds a sample PRM module that demonstrates:
  1. How to write a PRM module
  2. How to use a basic PRM OS services
  3. How to use a basic PRM module configuration library
  4. How to use a context buffer during PRM handler execution

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>
---
 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c   | 203 ++++++++++++++++++++
 PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c                                              | 182 ++++++++++++++++++
 PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h                                                        |  24 +++
 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf |  39 ++++
 PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf                                            |  42 ++++
 5 files changed, 490 insertions(+)

diff --git a/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
new file mode 100644
index 000000000000..3bf5beba7d4a
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
@@ -0,0 +1,203 @@
+/** @file
+
+  The boot services environment configuration library for the Context Buffer Sample PRM module.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/PrmConfig.h>
+#include <Samples/PrmSampleContextBufferModule/Include/StaticData.h>
+
+#include <PrmContextBuffer.h>
+#include <PrmDataBuffer.h>
+
+STATIC EFI_HANDLE  mPrmConfigProtocolHandle;
+
+// {5a6cf42b-8bb4-472c-a233-5c4dc4033dc7}
+STATIC CONST EFI_GUID mPrmModuleGuid = {0x5a6cf42b, 0x8bb4, 0x472c, {0xa2, 0x33, 0x5c, 0x4d, 0xc4, 0x03, 0x3d, 0xc7}};
+
+// {e1466081-7562-430f-896b-b0e523dc335a}
+STATIC CONST EFI_GUID mDumpStaticDataBufferPrmHandlerGuid = {0xe1466081, 0x7562, 0x430f, {0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a}};
+
+/**
+  Populates the static data buffer for this PRM module.
+
+  @param[out] StaticDataBuffer  A pointer to the static data buffer.
+
+  @retval EFI_SUCCESS           The static data buffer was populated successfully.
+  @retval EFI_INVALID_PARAMETER The StaticDataBuffer pointer argument is NULL.
+
+**/
+EFI_STATUS
+PopulateStaticDataBuffer (
+  OUT STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE  *StaticDataBuffer
+  )
+{
+  if (StaticDataBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Note: In a real-world module these values would likely come from somewhere
+  // like a Setup menu option, PCD, binary data, runtime device info, etc. Ideally,
+  // this configuration library would be provided an API to get what it needs (the data)
+  // and not be concerned with how the data is provided. This makes the PRM module more
+  // portable across systems.
+  //
+  StaticDataBuffer->Policy1Enabled = TRUE;
+  StaticDataBuffer->Policy2Enabled = FALSE;
+  SetMem (StaticDataBuffer->SomeValueArray, ARRAY_SIZE (StaticDataBuffer->SomeValueArray), 'D');
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Allocates and populates the static data buffer for this PRM module.
+
+  @param[out] StaticDataBuffer  A pointer to a pointer to the static data buffer.
+
+  @retval EFI_SUCCESS           The static data buffer was allocated and filled successfully.
+  @retval EFI_INVALID_PARAMETER The StaticDataBuffer pointer argument is NULL.
+  @retval EFI_OUT_OF_RESOURCES  Insufficient memory resources to allocate the static data buffer.
+
+**/
+EFI_STATUS
+GetStaticDataBuffer (
+  OUT PRM_DATA_BUFFER         **StaticDataBuffer
+  )
+{
+  EFI_STATUS                  Status;
+  PRM_DATA_BUFFER             *DataBuffer;
+  UINTN                       DataBufferLength;
+
+  if (StaticDataBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  *StaticDataBuffer = NULL;
+
+  //
+  // Length of the data buffer = Buffer Header Size + Buffer Data Size
+  //
+  DataBufferLength = sizeof (PRM_DATA_BUFFER_HEADER) + sizeof (STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE);
+
+  DataBuffer = AllocateRuntimeZeroPool (DataBufferLength);
+  if (DataBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the data buffer header
+  //
+  DataBuffer->Header.Signature = PRM_DATA_BUFFER_HEADER_SIGNATURE;
+  DataBuffer->Header.Length = (UINT32) DataBufferLength;
+
+  Status = PopulateStaticDataBuffer ((STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE *) &DataBuffer->Data[0]);
+  ASSERT_EFI_ERROR (Status);
+
+  *StaticDataBuffer = DataBuffer;
+  return EFI_SUCCESS;
+}
+
+/**
+  Constructor of the PRM configuration library.
+
+  @param[in] ImageHandle        The image handle of the driver.
+  @param[in] SystemTable        The EFI System Table pointer.
+
+  @retval EFI_SUCCESS           The shell command handlers were installed successfully.
+  @retval EFI_UNSUPPORTED       The shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ContextBufferModuleConfigLibConstructor (
+  IN  EFI_HANDLE              ImageHandle,
+  IN  EFI_SYSTEM_TABLE        *SystemTable
+  )
+{
+  EFI_STATUS                  Status;
+  PRM_CONTEXT_BUFFER          *PrmContextBuffer;
+  PRM_DATA_BUFFER             *StaticDataBuffer;
+  PRM_CONFIG_PROTOCOL         *PrmConfigProtocol;
+
+  PrmContextBuffer = NULL;
+  StaticDataBuffer = NULL;
+  PrmConfigProtocol = NULL;
+
+  /*
+    In this sample PRM module, the protocol describing this sample module's resources is simply
+    installed in the constructor.
+
+    However, if some data is not available until later, this constructor could register a callback
+    on the dependency for the data to be available (e.g. ability to communicate with some device)
+    and then install the protocol. The requirement is that the protocol is installed before end of DXE.
+  */
+
+  //
+  // Allocate and populate the static data buffer
+  //
+  Status = GetStaticDataBuffer (&StaticDataBuffer);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status) || StaticDataBuffer == NULL) {
+    goto Done;
+  }
+
+  //
+  // Allocate and populate the context 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));
+  ASSERT (PrmContextBuffer != NULL);
+  if (PrmContextBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CopyGuid (&PrmContextBuffer->HandlerGuid, &mDumpStaticDataBufferPrmHandlerGuid);
+  PrmContextBuffer->Signature = PRM_CONTEXT_BUFFER_SIGNATURE;
+  PrmContextBuffer->Version = PRM_CONTEXT_BUFFER_INTERFACE_VERSION;
+  PrmContextBuffer->StaticDataBuffer = StaticDataBuffer;
+
+  PrmConfigProtocol = AllocateZeroPool (sizeof (*PrmConfigProtocol));
+  ASSERT (PrmConfigProtocol != NULL);
+  if (PrmConfigProtocol == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CopyGuid (&PrmConfigProtocol->ModuleContextBuffers.ModuleGuid, &mPrmModuleGuid);
+  PrmConfigProtocol->ModuleContextBuffers.BufferCount = 1;
+  PrmConfigProtocol->ModuleContextBuffers.Buffer = PrmContextBuffer;
+
+  //
+  // Install the PRM Configuration Protocol for this module. This indicates the configuration
+  // library has completed resource initialization for the PRM module.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mPrmConfigProtocolHandle,
+                  &gPrmConfigProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID *) PrmConfigProtocol
+                  );
+
+Done:
+  if (EFI_ERROR (Status)) {
+    if (StaticDataBuffer != NULL) {
+      FreePool (StaticDataBuffer);
+    }
+    if (PrmContextBuffer != NULL) {
+      FreePool (PrmContextBuffer);
+    }
+    if (PrmConfigProtocol != NULL) {
+      FreePool (PrmConfigProtocol);
+    }
+  }
+
+  return Status;
+}
diff --git a/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c b/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c
new file mode 100644
index 000000000000..074552d0c07e
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c
@@ -0,0 +1,182 @@
+/** @file
+
+  This PRM Module demonstrates how to configure the module data resources in the firmware boot environment
+  and access those resources in a PRM handler at OS runtime.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PrmModule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+
+#include <Samples/PrmSampleContextBufferModule/Include/StaticData.h>
+
+//
+// PRM Handler GUIDs
+//
+
+// {e1466081-7562-430f-896b-b0e523dc335a}
+#define DUMP_STATIC_DATA_BUFFER_PRM_HANDLER_GUID {0xe1466081, 0x7562, 0x430f, {0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a}}
+
+/**
+  Dumps the contents of a given buffer.
+
+  @param[in]  OsServiceDebugPrint   A pointer to the debug print OS service.
+  @param[in]  Buffer                A pointer to the buffer that should be dumped.
+  @param[in]  BufferSize            The size of Buffer in bytes.
+
+**/
+STATIC
+VOID
+DumpBuffer (
+  IN PRM_OS_SERVICE_DEBUG_PRINT OsServiceDebugPrint,
+  IN CONST VOID                 *Buffer,
+  IN UINTN                      BufferSize
+  )
+{
+  UINTN Count;
+  CONST UINT8 *Char = Buffer;
+  CHAR8 DebugMessage[16];
+
+  if (OsServiceDebugPrint == NULL || Buffer == NULL) {
+    return;
+  }
+
+  OsServiceDebugPrint ("    ");
+  for (Count = 0; Count < BufferSize; Count++)
+  {
+    if (Count && !(Count % 16)) {
+      OsServiceDebugPrint ("\n    ");
+    }
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "%02X ",
+      Char[Count]
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
+  }
+  OsServiceDebugPrint ("\n\n");
+}
+
+/**
+  Prints the contents of this PRM module's static data buffer.
+
+  @param[in]  OsServiceDebugPrint   A pointer to the debug print OS service.
+  @param[in]  StaticDataBuffer      A pointer to the static buffer.
+
+**/
+VOID
+EFIAPI
+PrintStaticDataBuffer (
+  IN PRM_OS_SERVICE_DEBUG_PRINT                       OsServiceDebugPrint,
+  IN CONST STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE   *StaticDataBuffer
+  )
+{
+  CHAR8 DebugMessage[256];
+
+  if (OsServiceDebugPrint == NULL || StaticDataBuffer == NULL) {
+    return;
+  }
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  Policy1Enabled = 0x%x.\n",
+    StaticDataBuffer->Policy1Enabled
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  AsciiSPrint (
+    &DebugMessage[0],
+    ARRAY_SIZE (DebugMessage),
+    "  Policy2Enabled = 0x%x.\n",
+    StaticDataBuffer->Policy2Enabled
+    );
+  OsServiceDebugPrint (&DebugMessage[0]);
+
+  OsServiceDebugPrint ("  Dumping SomeValueArray:\n");
+  DumpBuffer (
+    OsServiceDebugPrint,
+    (CONST VOID *) &StaticDataBuffer->SomeValueArray[0],
+    ARRAY_SIZE (StaticDataBuffer->SomeValueArray)
+    );
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler attempts to read the contents of the static data buffer that were configured
+  during the firmware boot environment and print those contents at OS runtime.
+
+  @param[in]  OsServices          An array of pointers to OS provided services for PRM handlers
+  @param[in]  Context             Handler context info
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+PRM_HANDLER_EXPORT (DumpStaticDataBufferPrmHandler)
+{
+  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
+
+  if (ContextBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
+  if (OsServiceDebugPrint == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OsServiceDebugPrint ("Context Buffer DumpStaticDataBufferPrmHandler entry.\n");
+
+  if (ContextBuffer->StaticDataBuffer == NULL) {
+    OsServiceDebugPrint ("The static buffer is not allocated!\n");
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OsServiceDebugPrint ("  Printing the contents of the static data buffer:\n");
+
+  //
+  // Verify PRM data buffer signature is valid
+  //
+  if (
+    ContextBuffer->Signature != PRM_CONTEXT_BUFFER_SIGNATURE ||
+    ContextBuffer->StaticDataBuffer->Header.Signature != PRM_DATA_BUFFER_HEADER_SIGNATURE) {
+    OsServiceDebugPrint ("  A buffer signature is invalid!\n");
+    return EFI_NOT_FOUND;
+  }
+
+  PrintStaticDataBuffer (
+    OsServiceDebugPrint,
+    (CONST STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE *) &(ContextBuffer->StaticDataBuffer->Data[0])
+    );
+
+  OsServiceDebugPrint ("Context Buffer DumpStaticDataBufferPrmHandler exit.\n");
+
+  return EFI_SUCCESS;
+}
+
+//
+// Register the PRM export information for this PRM Module
+//
+PRM_MODULE_EXPORT (
+  PRM_HANDLER_EXPORT_ENTRY (DUMP_STATIC_DATA_BUFFER_PRM_HANDLER_GUID, DumpStaticDataBufferPrmHandler)
+  );
+
+EFI_STATUS
+EFIAPI
+PrmSampleContextBufferModuleInit (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  EFI_SYSTEM_TABLE            *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h b/PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
new file mode 100644
index 000000000000..8fe3cf901fad
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
@@ -0,0 +1,24 @@
+/** @file
+  PRM Module Static Data
+
+  Defines the structure of the static data buffer for the PRM Sample Context Buffer module.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE_H_
+#define PRM_STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE_H_
+
+#include <Base.h>
+
+#define   SOME_VALUE_ARRAY_MAX_VALUES   16
+
+typedef struct {
+  BOOLEAN       Policy1Enabled;
+  BOOLEAN       Policy2Enabled;
+  UINT8         SomeValueArray[SOME_VALUE_ARRAY_MAX_VALUES];
+} STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE;
+
+#endif
diff --git a/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
new file mode 100644
index 000000000000..db604680e91e
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
@@ -0,0 +1,39 @@
+## @file
+#  Sample PRM Configuration Library Instance
+#
+#  The PRM configuration library instance is responsible for initializing and setting the corresponding
+#  PRM module's configuration in the boot environment.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION         = 0x00010005
+  BASE_NAME           = DxeContextBufferModuleConfigLib
+  FILE_GUID           = FFB56F09-65E3-4462-A799-2F0D1930D38C
+  MODULE_TYPE         = DXE_DRIVER
+  VERSION_STRING      = 1.0
+  LIBRARY_CLASS       = NULL |DXE_DRIVER
+  CONSTRUCTOR         = ContextBufferModuleConfigLibConstructor
+
+[Sources]
+  DxeContextBufferModuleConfigLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[Protocols]
+  gPrmConfigProtocolGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
diff --git a/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf b/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
new file mode 100644
index 000000000000..4dd77f526116
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
@@ -0,0 +1,42 @@
+## @file
+#  Sample PRM Driver
+#
+#  A sample PRM Module implementation. This PRM Module includes a PRM Module configuration library instance
+#  that applies the configuration for the PRM context data in the boot environment. A PRM handler
+#  is provided that accesses the context buffer resources and prints their value at OS runtime.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION         = 0x00010005
+  BASE_NAME           = PrmSampleContextBufferModule
+  FILE_GUID           = 5A6CF42B-8BB4-472C-A233-5C4DC4033DC7
+  MODULE_TYPE         = DXE_RUNTIME_DRIVER
+  VERSION_STRING      = 1.0
+  ENTRY_POINT         = PrmSampleContextBufferModuleInit
+
+[Sources]
+  Include/StaticData.h
+  PrmSampleContextBufferModule.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PrintLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Depex]
+  TRUE
+
+[BuildOptions.common]
+  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 09/41] PrmPkg: Add initial package DSC file
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (7 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 08/41] PrmPkg: Add initial PrmSampleContextBufferModule Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 10/41] Readme.md: Add initial content Michael Kubacki
                   ` (31 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

Adds the PrmPkg DSC file so all of the contents can be built as a
stand-alone package.

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>
---
 PrmPkg/PrmPkg.dsc | 107 ++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
new file mode 100644
index 000000000000..a0237d1fe059
--- /dev/null
+++ b/PrmPkg/PrmPkg.dsc
@@ -0,0 +1,107 @@
+## @file
+# Build description file for PrmPkg
+#
+# Copyright (C) Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  PLATFORM_NAME                  = Prm
+  PLATFORM_GUID                  = C29BB610-84F9-448D-A7DD-5A04C5A54F52
+  PLATFORM_VERSION               = 0.1
+  DSC_SPECIFICATION              = 0x00010005
+  OUTPUT_DIRECTORY               = Build/$(PLATFORM_NAME)
+  SUPPORTED_ARCHITECTURES        = IA32|X64
+  BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
+  SKUID_IDENTIFIER               = DEFAULT
+
+  DEFINE  PLATFORM_PACKAGE       = $(PLATFORM_NAME)Pkg
+
+[LibraryClasses.common]
+  #
+  # EDK II Packages
+  #
+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+  MemoryAllocationLib|MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
+  MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+  RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
+  RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+
+[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER]
+  #
+  # EDK II Packages
+  #
+  BaseMemoryLib|MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf
+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+
+  #
+  # PRM Package
+  #
+  PrmContextBufferLib|$(PLATFORM_PACKAGE)/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
+
+###################################################################################################
+#
+# Components Section - List of the modules and components that will be processed by compilation
+#                      tools and the EDK II tools to generate PE32/PE32+/Coff image file.
+#
+###################################################################################################
+
+[Components]
+  #
+  # PRM Libraries
+  #
+  $(PLATFORM_PACKAGE)/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
+  $(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
+  $(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
+
+  #
+  # PRM Configuration Driver
+  #
+  $(PLATFORM_PACKAGE)/PrmConfigDxe/PrmConfigDxe.inf {
+    <LibraryClasses>
+      NULL|$(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
+  }
+
+  #
+  # PRM Module Loader Driver
+  #
+  $(PLATFORM_PACKAGE)/PrmLoaderDxe/PrmLoaderDxe.inf
+
+  #
+  # PRM Sample Modules
+  #
+  $(PLATFORM_PACKAGE)/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
+  $(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf {
+    <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+  }
+  $(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
+
+  #
+  # The SampleMemoryAllocationModule was used during a time in the POC when the OS
+  # provided memory allocation services. This module was successful in using those services.
+  # Since OS services have been removed (aside from debug prints), this module is no longer
+  # relevant but kept around for archival purposes.
+  #
+  #$(PLATFORM_PACKAGE)/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
+
+[BuildOptions]
+# Force deprecated interfaces off
+  *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 10/41] Readme.md: Add initial content
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (8 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 09/41] PrmPkg: Add initial package DSC file Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 11/41] PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option Michael Kubacki
                   ` (30 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3812

Adds the following content to Readme.md:

1. A basic explanation of how the package is organized and where to
   find important items.

2. Adds instructions for building PrmPkg with edk2.

3. Adds a "Build Flags" section to the build instructions to explain
   any build flags that may be passed to influence the build.

   The final package will not have any build flags. A reasonable
   number are temporarily used to test different flows until final
   decisions are made as to which flow to keep.

   Most notably, only Visual Studio tool chains are currently
   supported due to the modifications made to support export tables.

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>
---
 PrmPkg/Readme.md | 212 ++++++++++++++++++++
 1 file changed, 212 insertions(+)

diff --git a/PrmPkg/Readme.md b/PrmPkg/Readme.md
new file mode 100644
index 000000000000..b67b3a391e37
--- /dev/null
+++ b/PrmPkg/Readme.md
@@ -0,0 +1,212 @@
+# **Platform Runtime Mechanism**
+
+Platform Runtime Mechanism (PRM) introduces the capability of moving platform-specific code out of SMM and into a
+code module that executes within the OS context. Moving this firmware to the OS context provides better transparency
+and mitigates the negative system impact currently accompanied with SMM solutions. Futhermore, the PRM code is
+packaged into modules with well-defined entry points, each representing a specific PRM functionality.
+
+The `PrmPkg` maintained in this branch provides a single cohesive set of generic PRM functionality that is intended
+to be leveraged by platform firmware with minimal overhead to integrate PRM functionality in the firmware.
+
+## **IMPORTANT NOTE**
+> The code provided  in this package and branch are for proof-of-concept purposes only. The code does not represent a
+formal design and is not validated at product quality. The development of this feature is shared in the edk2-staging
+branch to simplify collaboration by allowing direct code contributions and early feedback throughout its development.
+
+## How to Build PrmPkg
+As noted earlier, resources in `PrmPkg` are intended to be referenced by a platform firmware so it can adopt support
+for PRM. In that case, the platform firmware should add the `PrmConfigDxe` and `PrmLoaderDxe` drivers to its DSC and
+FDF files so they are built in the platform firmware build and dispatched during its runtime. All that is left is to
+add individual PRM modules to the DSC and FDF. These can be built from source or included as binaries into the platform
+firmware flash map.
+
+### PrmPkg Standalone Build
+**All changes to `PrmPkg` must not regress the standalone package build**. Any time a change is made to `PrmPkg`, the
+package build must be tested. Since this is a forward looking package, to ease potential integration into the edk2
+project in the future, the build is tested against the tip of the master branch in the [edk2](https://github.com/tianocore/edk2)
+repository.
+
+To build `PrmPkg` as a standalone package:
+1. If new to EDK II, follow the directions in [Getting Started with EDK II](https://github.com/tianocore/tianocore.github.io/wiki/Getting-Started-with-EDK-II)
+
+2. Clone the *master* branch on the edk2 repository locally \
+   ``git clone https://github.com/tianocore/edk2.git``
+
+3. Clone the *PlatformRuntimeMechanism* branch on the edk2-staging repository locally \
+   ``git clone -b PlatformRuntimeMechanism --single-branch https://github.com/tianocore/edk2-staging.git``
+   > __*Note*__: The *--single-branch* argument is recommended since edk2-staging hosts many branches for completely
+   unrelated features. If you are just interested in PRM, this will avoid fetching all of the other branches.
+
+4. Change to the edk2 workspace directory \
+   ``cd edk2``
+
+5. Run *edksetup* to set local environment variables needed for build
+   * Windows:
+     * ``edksetup.bat``
+   * Linux:
+     * If you have not already built BaseTools:
+       * ``make -C BaseTools``
+     * ``. edksetup.sh``
+
+6. Set the PACKAGES_PATH environment variable to include the directory path that contains `PrmPkg`
+   * Windows example:
+     *  ``set PACKAGES_PATH=c:\src\edk2-staging``
+
+7. Change to the edk2-staging workspace directory
+   * Example: ``cd ../edk2-staging``
+
+8. Build PrmPkg \
+   ``build -p PrmPkg/PrmPkg.dsc -a IA32 -a X64``
+   > __*Note*__: Due to the way PRM modules are compiled with exports, **only building on Visual Studio compiler tool
+   chains is currently supported**.
+
+### Build Flags
+As PRM is a new feature at a proof-of-concept (POC) level of maturity, there's some changes to the normal build
+available as build flags. By default, if no flags are specified, the build is done with the currently expected plan of
+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).
+
+## Overview
+At a high-level, PRM can be viewed from three levels of granularity:
+
+1. PRM interface - Encompassing the entirety of firmware functionalities and data provided to OS runtime. Most
+   information is provided through ACPI tables to be agnostic to a UEFI implementation.
+2. PRM module - An independently updatable package of PRM handlers. The PRM interface will be composed of multiple
+   PRM modules. This requirement allows for the separation of OEM and IHV PRM code, each of which can be serviced
+   independently.
+3. PRM handler - The implementation/callback of a single PRM functionality as identified by a GUID.
+
+## Firmware Design
+The firmware has three key generic drivers to support PRM:
+
+1. A PRM Loader driver - Functionality is split across three phases:
+   1. Discover - Find all PRM modules in the firmware image made available by the platform firmware author.
+      * This phase includes verifying authenticity/integrity of the image, the image executable type, the export
+        table is present and the PRM Export Module Descriptor is present and valid.
+   2. Process - Convert PRM handler GUID to name mappings in the PRM Module Export Descriptor to PRM handler Name
+      to physical address mappings required to construct the PRM ACPI table.
+   3. Publish - Publish the PRM ACPI table using the information from the Process phase.
+
+2. A PRM Configuration driver - A generic driver responsible for processing PRM module configuration information
+   consumed through a `PRM_CONFIG_PROTOCOL` per PRM module instance. Therefore, the `PRM_CONFIG_PROTOCOL` serves
+   as the dynamic interface for this driver to process PRM module resources and prepare the module's data to be
+   configured properly for OS runtime.
+
+3. A PRM Module - Not a single driver but a user written PE/COFF image that follows the PRM module authoring process.
+   A PRM module groups together cohesive sets of PRM functionality into functions referred to as "PRM handlers".
+
+## PrmPkg Code Organization
+The package follows a standard EDK II style package format. The list below contains some notable areas to
+explore in the package:
+
+* [ACPI Table Definitions](PrmPkg/PrmLoaderDxe/PrmAcpiTable.h)
+* [Common Interface Definitions](PrmPkg/Include)
+* [PRM Config Driver](PrmPkg/PrmConfigDxe)
+* [PRM Loader Driver](PrmPkg/PrmLoaderDxe)
+* [Sample PRM Modules](PrmPkg/Samples)
+
+While the package does provide sample PRM modules to be used as a reference, actual PRM modules should not be
+maintained in PrmPkg. It is intended to only contain PRM infrastructure code and a few samples of how to use
+that infrastructure. The PrmPkg is meant to be used as-is by firmware that supports PRM. Any shortcomings that
+prevent the package from being used as-is should be addressed directly in PrmPkg.
+
+## PRM Module
+
+By default, the EDK II implementation of UEFI does not allow images with the subsystem type
+IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER to be built with exports. 
+
+```
+ERROR - Linker #1294 from LINK : fatal exports and import libraries are not supported with /SUBSYSTEM:EFI_RUNTIME_DRIVER
+```
+This can adjusted in the MSVC linker options.
+
+__For the purposes of this POC__, the subsystem type is changed in the firmware build to allow the export table to be
+added but the subsystem type in the final image is still 0xC (EFI Runtime Driver). This is important to allow the DXE
+dispatcher to use its standard image verification and loading algorithms to load the image into permanent memory during
+the DXE execution phase.
+
+All firmware-loaded PRM modules are loaded into a memory buffer of type EfiRuntimeServicesCode. This means the
+operating system must preserve all PRM handler code and the buffer will be reflected in the UEFI memory map. The
+execution for invoking PRM handlers is the same as that required for UEFI Runtime Services, notably 4KiB or more of
+available stack space must be provided and the stack must be 16-byte aligned. 
+
+__*Note:*__ Long term it is possible to similarly load the modules into a EfiRuntimeServicesCode buffer and perform
+relocation fixups with a new EFI module type for PRM if desired. It was simply not done since it is not essential
+for this POC.
+
+Where possible, PRM module information is stored and generated using industry compiler tool chains. This is a key
+motivation behind using PE/COFF export tables to expose PRM module information and using a single PRM module binary
+definition consistent between firmware and OS load.
+
+### PRM Module Exports
+A PRM module must contain at least three exports: A PRM Module Export Descriptor, a PRM Module Update Lock Descriptor,
+and at least one PRM handler. Here's an example of an export table from a PRM module that has a single PRM handler:
+
+```
+  0000000000005000: 00 00 00 00 FF FF FF FF 00 00 00 00 46 50 00 00  ....ÿÿÿÿ....FP..
+  0000000000005010: 01 00 00 00 03 00 00 00 03 00 00 00 28 50 00 00  ............(P..
+  0000000000005020: 34 50 00 00 40 50 00 00 78 13 00 00 30 40 00 00  4P..@P..x...0@..
+  0000000000005030: 20 40 00 00 67 50 00 00 86 50 00 00 A0 50 00 00   @..gP...P...P..
+  0000000000005040: 00 00 01 00 02 00 50 72 6D 53 61 6D 70 6C 65 43  ......PrmSampleC
+  0000000000005050: 6F 6E 74 65 78 74 42 75 66 66 65 72 4D 6F 64 75  ontextBufferModu
+  0000000000005060: 6C 65 2E 64 6C 6C 00 44 75 6D 70 53 74 61 74 69  le.dll.DumpStati
+  0000000000005070: 63 44 61 74 61 42 75 66 66 65 72 50 72 6D 48 61  cDataBufferPrmHa
+  0000000000005080: 6E 64 6C 65 72 00 50 72 6D 4D 6F 64 75 6C 65 45  ndler.PrmModuleE
+  0000000000005090: 78 70 6F 72 74 44 65 73 63 72 69 70 74 6F 72 00  xportDescriptor.
+  00000000000050A0: 50 72 6D 4D 6F 64 75 6C 65 55 70 64 61 74 65 4C  PrmModuleUpdateL
+  00000000000050B0: 6F 63 6B 00                                      ock.
+
+    00000000 characteristics
+    FFFFFFFF time date stamp
+        0.10 version
+           1 ordinal base
+           3 number of functions
+           3 number of names
+
+    ordinal hint RVA      name
+          1    0 00001378 DumpStaticDataBufferPrmHandler
+          2    1 00004030 PrmModuleExportDescriptor
+          3    2 00004020 PrmModuleUpdateLock
+```
+### PRM Image Format
+PRM modules are ultimately PE/COFF images. However, when packaged in firmware the PE/COFF image is placed into a
+Firmware File System (FFS) file. This is transparent to the operating system but done to better align with the typical
+packaging of PE32(+) images managed in the firmware binary image. In the dump of the PRM FV binary image shown earlier,
+the FFS sections placed by EDK II build tools ("DXE dependency", "User interface", "Version") that reside alongside the
+PE/COFF binary are shown. A PRM module can be placed into a firmware image as a pre-built PE/COFF binary or built
+during the firmware build process. In either case, the PE/COFF section is contained in a FFS file as shown in that
+image.
+
+### PRM Module Implementation
+To simplify building the PRM Module Export Descriptor, a PRM module implementation can use the following macros to mark
+functions as PRM handlers. In this example, a PRM module registers three functions by name as PRM handlers with the
+associated GUIDs.
+
+```
+//
+// Register the PRM export information for this PRM Module
+//
+PRM_MODULE_EXPORT (
+  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_1_GUID, PrmHandler1),
+  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_2_GUID, PrmHandler2),
+  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_N_GUID, PrmHandlerN)
+  );
+```
+
+`PRM_MODULE_EXPORT` take a variable-length argument list of `PRM_HANDLER_EXPORT_ENTRY` entries that each describe an
+individual PRM handler being exported for the module. Ultimately, this information is used to define the structure
+necessary to statically allocate the PRM Module Export Descriptor Structure (and its PRM Handler Export Descriptor
+substructures) in the image.
+
+Another required export for PRM modules is automatically provided in `PrmModule.h`, a header file that pulls together
+all the includes needed to author a PRM module. This export is `PRM_MODULE_UPDATE_LOCK_EXPORT`. By including,
+`PrmModule.h`, a PRM module has the `PRM_MODULE_UPDATE_LOCK_DESCRIPTOR` automatically exported.
+
+## PRM Handler Constraints
+At this time, PRM handlers are restricted to a maximum identifier length of 128 characters. This is checked when using
+the `PRM_HANDLER_EXPORT` macro by using a static assert that reports a violation at build-time.
+
+PRM handlers are **not** allowed to use UEFI Runtime Services and should not rely upon any UEFI constructs. For the
+purposes of this POC, this is currently not explicitly enforced but should be in the final changes.
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 11/41] PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (9 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 10/41] Readme.md: Add initial content Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 12/41] PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro Michael Kubacki
                   ` (29 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

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>
---
 PrmPkg/PrmConfigDxe/PrmConfigDxe.c                                                                                    | 51 +++++++++++++-------
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c                                                                                    |  6 ++-
 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c | 16 ++++++
 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h                                                                                    |  4 ++
 PrmPkg/PrmPkg.dsc                                                                                                     |  5 ++
 PrmPkg/Readme.md                                                                                                      | 12 +++++
 6 files changed, 76 insertions(+), 18 deletions(-)

diff --git a/PrmPkg/PrmConfigDxe/PrmConfigDxe.c b/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
index cb38146bc9e0..7215c2e1dc6f 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/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index b43e6d6bf078..85fffdcbd9f1 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/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
index 3bf5beba7d4a..b0b12c012a41 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;
diff --git a/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
index 6b9099ca7ba7..8a9c82347d93 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/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index a0237d1fe059..1a0ddc6ac181 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -105,3 +105,8 @@ [Components]
 [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 b67b3a391e37..00ef41bc5f42 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:
 
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 12/41] PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (10 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 11/41] PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 13/41] PrmPkg: Publish PRM operation region to support PRM ACPI _DSM invocation Michael Kubacki
                   ` (28 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

The PRM_MODULE_EXPORT parameterized macro allows a caller to produce
a static PRM module export descriptor structure in the binary by
simply passing PRM_HANDLER_EXPORT_ENTRY arguments with each argument
representing a PRM handler to be exported by the module.

Previously, the PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT used in the
PRM_MODULE_EXPORT macro was fixed to a maximum of three handlers.

This change removes that restriction and allows the structure to
grow based on the number of PRM handlers given to the macro. This
means a local type will be customized per PRM module. The reference
type PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT keeps a field at the end
that allows array access to PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT
members.

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>
---
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c   | 14 +++++------
 PrmPkg/Include/PrmExportDescriptor.h | 25 +++++++++++++++++---
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index 85fffdcbd9f1..5fda4c1b01da 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -122,7 +122,7 @@ GetPrmModuleExportDescriptorTable (
         return EFI_NOT_FOUND;
       }
       TempExportDescriptor = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *) ((UINTN) CurrentImageAddress + ExportAddressTable[PrmModuleExportDescriptorOrdinal]);
-      if (TempExportDescriptor->Signature == PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE) {
+      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 {
@@ -528,7 +528,7 @@ DiscoverPrmModules (
       sizeof (*(PrmModuleImageContextListEntry->Context))
       );
     InsertTailList (&mPrmModuleList, &PrmModuleImageContextListEntry->Link);
-    mPrmHandlerCount += TempPrmModuleImageContext.ExportDescriptor->NumberPrmHandlers;
+    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__));
   }
@@ -684,16 +684,16 @@ ProcessPrmModules (
       _DBGMSGID_,
       __FUNCTION__,
       (CHAR8 *) ((UINTN) CurrentImageAddress + CurrentImageExportDirectory->Name),
-      CurrentExportDescriptorStruct->NumberPrmHandlers
+      CurrentExportDescriptorStruct->Header.NumberPrmHandlers
       ));
 
     CurrentModuleInfoStruct->StructureRevision = PRM_MODULE_INFORMATION_STRUCT_REVISION;
     CurrentModuleInfoStruct->StructureLength = (
                                              OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) +
-                                             (CurrentExportDescriptorStruct->NumberPrmHandlers * sizeof (PRM_HANDLER_INFORMATION_STRUCT))
+                                             (CurrentExportDescriptorStruct->Header.NumberPrmHandlers * sizeof (PRM_HANDLER_INFORMATION_STRUCT))
                                              );
-    CopyGuid (&CurrentModuleInfoStruct->Identifier, &CurrentExportDescriptorStruct->ModuleGuid);
-    CurrentModuleInfoStruct->HandlerCount       = (UINT32) CurrentExportDescriptorStruct->NumberPrmHandlers;
+    CopyGuid (&CurrentModuleInfoStruct->Identifier, &CurrentExportDescriptorStruct->Header.ModuleGuid);
+    CurrentModuleInfoStruct->HandlerCount       = (UINT32) CurrentExportDescriptorStruct->Header.NumberPrmHandlers;
     CurrentModuleInfoStruct->HandlerInfoOffset  = OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure);
 
     CurrentModuleInfoStruct->MajorRevision = 0;
@@ -737,7 +737,7 @@ ProcessPrmModules (
     //
     // Iterate across all PRM handlers in the PRM Module
     //
-    for (HandlerIndex = 0; HandlerIndex < CurrentExportDescriptorStruct->NumberPrmHandlers; HandlerIndex++) {
+    for (HandlerIndex = 0; HandlerIndex < CurrentExportDescriptorStruct->Header.NumberPrmHandlers; HandlerIndex++) {
       CurrentHandlerInfoStruct = &(CurrentModuleInfoStruct->HandlerInfoStructure[HandlerIndex]);
 
       CurrentHandlerInfoStruct->StructureRevision = PRM_HANDLER_INFORMATION_STRUCT_REVISION;
diff --git a/PrmPkg/Include/PrmExportDescriptor.h b/PrmPkg/Include/PrmExportDescriptor.h
index 95198cef659c..fc313fd1acc7 100644
--- a/PrmPkg/Include/PrmExportDescriptor.h
+++ b/PrmPkg/Include/PrmExportDescriptor.h
@@ -31,11 +31,23 @@ typedef struct {
   UINT16                                Revision;
   UINT16                                NumberPrmHandlers;
   GUID                                  ModuleGuid;
-  PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT  PrmHandlerExportDescriptors[3];
+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;
+
+typedef struct {
+  PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER  Header;
+  PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT        PrmHandlerExportDescriptors[1];
 } PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;
 
 #pragma pack(pop)
 
+#if defined(_MSC_VER)
+  #define PRM_PACKED_STRUCT(definition) \
+  __pragma(pack(push, 1)) typedef struct definition __pragma(pack(pop))
+#elif defined (__GNUC__) || defined (__clang__)
+  #define PRM_PACKED_STRUCT(definition) \
+  typedef struct __attribute__((packed)) definition
+#endif
+
 /**
   A macro that declares a PRM Handler Export Descriptor for a PRM Handler.
 
@@ -73,8 +85,15 @@ typedef struct {
                                     this module.
 
 **/
-#define PRM_MODULE_EXPORT(...)                                                              \
-  PRM_EXPORT_API PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT PRM_MODULE_EXPORT_DESCRIPTOR_NAME = {               \
+#define PRM_MODULE_EXPORT(...)                                                                            \
+  PRM_PACKED_STRUCT(                                                                                      \
+    {                                                                                                     \
+      PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER  Header;                                                 \
+      PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT        PrmHandlerExportDescriptors[VA_ARG_COUNT(__VA_ARGS__)]; \
+    } PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_                                                                \
+  );                                                                                                      \
+                                                                                                          \
+  PRM_EXPORT_API PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_ PRM_MODULE_EXPORT_DESCRIPTOR_NAME = {               \
     {                                                                                                     \
       PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE,                                                             \
       PRM_MODULE_EXPORT_REVISION,                                                                         \
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 13/41] PrmPkg: Publish PRM operation region to support PRM ACPI _DSM invocation
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (11 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 12/41] PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 14/41] PrmPkg: Export major/minor version in PRM module PE COFF header Michael Kubacki
                   ` (27 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Liu <yun.y.liu@intel.com>

A PRM Handler has a 1-to-1 mapping to the corresponding _DSM method.
The UUID of the _DSM Method will be passed by the ASL code to the
OpRegionHandler which will look up the PRMT Table to extract the
pointer of the corresponding PRM Handler.

PRM loader pre-builds an SSDT that includes this PRM operation region.
In boot time, the PRM loader will load and publish this SSDT, so that
in OS runtime ACPI _DSM can invoke the PRM handler by pass the UUID to
PRM operation region.

The pre-build SSDT also includes a PRMT device as a Sample ACPI _DSM to
invoke PRM handler.

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: Liu Yun <yun.y.liu@intel.com>
---
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c   | 34 ++++++++
 PrmPkg/PrmLoaderDxe/Prm.asl          | 87 ++++++++++++++++++++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf |  4 +
 3 files changed, 125 insertions(+)

diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index 5fda4c1b01da..5e14b8e09dd0 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -3,6 +3,7 @@
   This file contains the implementation for a Platform Runtime Mechanism (PRM)
   loader driver.
 
+  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
   Copyright (c) Microsoft Corporation
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -19,6 +20,7 @@
 #include <Library/PrmContextBufferLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
+#include <Library/DxeServicesLib.h>
 #include <Protocol/AcpiTable.h>
 #include <Protocol/LoadedImage.h>
 #include <Protocol/PrmConfig.h>
@@ -809,6 +811,8 @@ PublishPrmAcpiTable (
   EFI_STATUS                              Status;
   EFI_ACPI_TABLE_PROTOCOL                 *AcpiTableProtocol;
   UINTN                                   TableKey;
+  EFI_ACPI_DESCRIPTION_HEADER             *Ssdt;
+  UINTN                                   SsdtSize;
 
   if (PrmAcpiDescriptionTable == NULL || PrmAcpiDescriptionTable->Header.Signature != PRM_TABLE_SIGNATURE) {
     return EFI_INVALID_PARAMETER;
@@ -832,6 +836,36 @@ PublishPrmAcpiTable (
   }
   ASSERT_EFI_ERROR (Status);
 
+  //
+  // Load SSDT
+  //
+  Status = GetSectionFromFv (
+               &gEfiCallerIdGuid,
+               EFI_SECTION_RAW,
+               0,
+               (VOID **) &Ssdt,
+               &SsdtSize
+               );
+  ASSERT_EFI_ERROR (Status);
+  DEBUG ((DEBUG_INFO, "%a %a: SSDT loaded ...\n", _DBGMSGID_, __FUNCTION__));
+
+  //
+  // Update OEM ID
+  //
+  CopyMem (&Ssdt->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Ssdt->OemId));
+
+  //
+  // Publish the SSDT. Table is re-checksumed.
+  //
+  TableKey = 0;
+  Status = AcpiTableProtocol->InstallAcpiTable (
+                        AcpiTableProtocol,
+                        Ssdt,
+                        SsdtSize,
+                        &TableKey
+                        );
+  ASSERT_EFI_ERROR (Status);
+
   return Status;
 }
 
diff --git a/PrmPkg/PrmLoaderDxe/Prm.asl b/PrmPkg/PrmLoaderDxe/Prm.asl
new file mode 100644
index 000000000000..76b56de732da
--- /dev/null
+++ b/PrmPkg/PrmLoaderDxe/Prm.asl
@@ -0,0 +1,87 @@
+/** @file
+  The definition block in ACPI table for PRM Operation Region
+
+  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+DefinitionBlock (
+    "Prm.aml",
+    "SSDT",
+    0x01,
+    "OEMID",
+    "PRMOPREG",
+    0x3000
+    )
+{
+    Scope (\_SB)
+    {
+        //
+        // PRM Bridge Device
+        //
+
+        Device (PRMB)
+        {
+            Name (_HID, "80860222")
+            Name (_CID, "80860222")
+            Name (_DDN, "PRM Bridge Device")
+            Name (_STA, 0xF)
+            OperationRegion (OPR1, 0x80, 0, 16)
+            Field (OPR1, DWordAcc, NoLock, Preserve) //Make it ByteAcc for parameter validation
+            {
+                Var0, 128
+            }
+            Method (SETV, 1, Serialized)
+            {
+                CopyObject (Arg0, \_SB.PRMB.Var0)
+            }
+        }
+
+        //
+        // PRM Test Device
+        //
+
+        Device (PRMT)
+        {
+            Name (_HID, "80860223")
+            Name (_CID, "80860223")
+            Name (_DDN, "PRM Test Device")
+            Name (_STA, 0xF)
+            Name (BUF1, Buffer(16)
+            {
+                0x5F, 0xAD, 0xF2, 0xD5, 0x47, 0xA3, 0x3E, 0x4D, //Guid_0
+                0x87, 0xBC, 0xC2, 0xCE, 0x63, 0x02, 0x9C, 0xC8, //Guid_1
+            })
+            Name (BUF2, Buffer(16)
+            {
+                0xC3, 0xAD, 0xE7, 0xA9, 0xD0, 0x8C, 0x9A, 0x42, //Guid_0
+                0x89, 0x15, 0x10, 0x94, 0x6E, 0xBD, 0xE3, 0x18, //Guid_1
+            })
+            Name (BUF3, Buffer(16)
+            {
+                0x14, 0xC2, 0x88, 0xB6, 0x81, 0x40, 0xEB, 0x4E, //Guid_0
+                0x8D, 0x26, 0x1E, 0xB5, 0xA3, 0xBC, 0xF1, 0x1A, //Guid_1
+            })
+            Method (NTST)
+            {
+                \_SB.PRMB.SETV (BUF1)
+            }
+            Method (TST1)
+            {
+                \_SB.PRMB.SETV (BUF1)
+            }
+            Method (TST2)
+            {
+                \_SB.PRMB.SETV (BUF2)
+            }
+            Method (TST3)
+            {
+                \_SB.PRMB.SETV (BUF3)
+            }
+        }
+    }
+
+} // End of Definition Block
+
+
+
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
index 643e1a7989f2..016ced4b3732 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
@@ -5,6 +5,7 @@
 #  PRM handlers within those modules into a PRMT ACPI table such that the handlers are
 #  made available for invocation in the OS.
 #
+#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) Microsoft Corporation
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -23,6 +24,7 @@ [Sources]
   PrmAcpiTable.h
   PrmLoader.h
   PrmLoaderDxe.c
+  Prm.asl
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -42,6 +44,8 @@ [LibraryClasses]
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
+  DxeServicesLib
+  PcdLib
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId            ## CONSUMES
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 14/41] PrmPkg: Export major/minor version in PRM module PE COFF header
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (12 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 13/41] PrmPkg: Publish PRM operation region to support PRM ACPI _DSM invocation Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 15/41] PrmPkg: Add initial PrmSsdtInstallDxe module Michael Kubacki
                   ` (26 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Liu <yun.y.liu@intel.com>

PRMT ACPI defined major version and minor version for each PRM module.

PRM module will build its major/minor version in its PE COFF header.
In boot time, PRM loader will collect the major/minor version from PE COFF
header and fill them into PRMT ACPI table.

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: Liu Yun <yun.y.liu@intel.com>
---
 PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf       | 2 ++
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf     | 2 ++
 PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf | 4 +++-
 PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf                       | 4 +++-
 4 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf b/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
index 4dd77f526116..b97af923c47a 100644
--- a/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
@@ -5,6 +5,7 @@
 #  that applies the configuration for the PRM context data in the boot environment. A PRM handler
 #  is provided that accesses the context buffer resources and prints their value at OS runtime.
 #
+#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) Microsoft Corporation
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -40,3 +41,4 @@ [Depex]
 
 [BuildOptions.common]
   MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
+  MSFT:*_*_*_GENFW_FLAGS = --keepoptionalheader
diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
index 302183c576f9..369d1eb1e86d 100644
--- a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
@@ -4,6 +4,7 @@
 #  A sample PRM Module implementation. This PRM Module provides PRM handlers that perform various types
 #  of hardware access. This is simply meant to demonstrate hardware access capabilities from a PRM handler.
 #
+#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) Microsoft Corporation
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -40,3 +41,4 @@ [Depex]
 
 [BuildOptions.common]
   MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
+  MSFT:*_*_*_GENFW_FLAGS = --keepoptionalheader
diff --git a/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf b/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
index e6798afe19e8..06be8f40f4ec 100644
--- a/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
+++ b/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
@@ -5,6 +5,7 @@
 #  a debug message. Three PRM handlers are provided that each print a unique
 #  debug message.
 #
+#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) Microsoft Corporation
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -38,4 +39,5 @@ [Depex]
   TRUE
 
 [BuildOptions.common]
-  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE
+  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
+  MSFT:*_*_*_GENFW_FLAGS = --keepoptionalheader
diff --git a/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf b/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
index d685bf888a1c..7ac291bc6e8a 100644
--- a/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
+++ b/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
@@ -5,6 +5,7 @@
 #  a debug message. Three PRM handlers are provided that each print a unique
 #  debug message.
 #
+#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) Microsoft Corporation
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -36,4 +37,5 @@ [Depex]
   TRUE
 
 [BuildOptions.common]
-  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE
+  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
+  MSFT:*_*_*_GENFW_FLAGS = --keepoptionalheader
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 15/41] PrmPkg: Add initial PrmSsdtInstallDxe module
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (13 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 14/41] PrmPkg: Export major/minor version in PRM module PE COFF header Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 16/41] PrmPkg: Remove PRM Module Update Lock Michael Kubacki
                   ` (25 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a new module that installs a PRM SSDT.

Note: A library class would allow a high degree of flexibility for
platforms that choose:
  1. To not install a PRM SSDT at all (using a NULL library instance)
  2. To install a specific PRM SSDT implementation

However, it is implemented as a driver since build tools are not
linking ACPI tables to drivers from linked library classes.

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>
---
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c                 |  33 ------
 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c       | 110 ++++++++++++++++++++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf               |   4 +-
 PrmPkg/PrmPkg.dsc                                  |   5 +
 PrmPkg/{PrmLoaderDxe => PrmSsdtInstallDxe}/Prm.asl |  18 +---
 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf     |  52 +++++++++
 6 files changed, 171 insertions(+), 51 deletions(-)

diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index 5e14b8e09dd0..e45f8685e81f 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -20,7 +20,6 @@
 #include <Library/PrmContextBufferLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/UefiLib.h>
-#include <Library/DxeServicesLib.h>
 #include <Protocol/AcpiTable.h>
 #include <Protocol/LoadedImage.h>
 #include <Protocol/PrmConfig.h>
@@ -811,8 +810,6 @@ PublishPrmAcpiTable (
   EFI_STATUS                              Status;
   EFI_ACPI_TABLE_PROTOCOL                 *AcpiTableProtocol;
   UINTN                                   TableKey;
-  EFI_ACPI_DESCRIPTION_HEADER             *Ssdt;
-  UINTN                                   SsdtSize;
 
   if (PrmAcpiDescriptionTable == NULL || PrmAcpiDescriptionTable->Header.Signature != PRM_TABLE_SIGNATURE) {
     return EFI_INVALID_PARAMETER;
@@ -836,36 +833,6 @@ PublishPrmAcpiTable (
   }
   ASSERT_EFI_ERROR (Status);
 
-  //
-  // Load SSDT
-  //
-  Status = GetSectionFromFv (
-               &gEfiCallerIdGuid,
-               EFI_SECTION_RAW,
-               0,
-               (VOID **) &Ssdt,
-               &SsdtSize
-               );
-  ASSERT_EFI_ERROR (Status);
-  DEBUG ((DEBUG_INFO, "%a %a: SSDT loaded ...\n", _DBGMSGID_, __FUNCTION__));
-
-  //
-  // Update OEM ID
-  //
-  CopyMem (&Ssdt->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Ssdt->OemId));
-
-  //
-  // Publish the SSDT. Table is re-checksumed.
-  //
-  TableKey = 0;
-  Status = AcpiTableProtocol->InstallAcpiTable (
-                        AcpiTableProtocol,
-                        Ssdt,
-                        SsdtSize,
-                        &TableKey
-                        );
-  ASSERT_EFI_ERROR (Status);
-
   return Status;
 }
 
diff --git a/PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c b/PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
new file mode 100644
index 000000000000..bd9ce2c6fa02
--- /dev/null
+++ b/PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
@@ -0,0 +1,110 @@
+/** @file
+
+  This file contains a sample implementation of the Platform Runtime Mechanism (PRM)
+  SSDT Install library.
+
+  Copyright (c) Microsoft Corporation
+  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+
+#define _DBGMSGID_  "[PRMSSDTINSTALL]"
+
+/**
+  Installs the PRM SSDT.
+
+  @param[in]  OemId                       OEM ID to be used in the SSDT installation.
+
+  @retval EFI_SUCCESS                     The PRM SSDT was installed successfully.
+  @retval EFI_INVALID_PARAMETER           The OemId pointer argument is NULL.
+  @retval EFI_NOT_FOUND                   An instance of gEfiAcpiTableProtocolGuid was not found installed or
+                                          the SSDT (AML RAW section) could not be found in the current FV.
+  @retval EFI_OUT_OF_RESOURCES            Insufficient memory resources to install the PRM SSDT.
+
+**/
+EFI_STATUS
+InstallPrmSsdt (
+  IN  CONST UINT8                         *OemId
+  )
+{
+  EFI_STATUS                              Status;
+  UINTN                                   SsdtSize;
+  UINTN                                   TableKey;
+  EFI_ACPI_TABLE_PROTOCOL                 *AcpiTableProtocol;
+  EFI_ACPI_DESCRIPTION_HEADER             *Ssdt;
+
+  DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
+
+  if (OemId == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
+  if (!EFI_ERROR (Status)) {
+    //
+    // Discover the SSDT
+    //
+    Status =  GetSectionFromFv (
+                &gEfiCallerIdGuid,
+                EFI_SECTION_RAW,
+                0,
+                (VOID **) &Ssdt,
+                &SsdtSize
+                );
+    ASSERT_EFI_ERROR (Status);
+    DEBUG ((DEBUG_INFO, "%a %a: SSDT loaded...\n", _DBGMSGID_, __FUNCTION__));
+
+    //
+    // Update OEM ID in the SSDT
+    //
+    CopyMem (&Ssdt->OemId, OemId, sizeof (Ssdt->OemId));
+
+    //
+    // Publish the SSDT. Table is re-checksummed.
+    //
+    TableKey = 0;
+    Status = AcpiTableProtocol->InstallAcpiTable (
+                                  AcpiTableProtocol,
+                                  Ssdt,
+                                  SsdtSize,
+                                  &TableKey
+                                  );
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return Status;
+}
+
+/**
+  The entry point for this module.
+
+  @param[in]  ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in]  SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS    The entry point is executed successfully.
+  @retval Others         An error occurred when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+PrmSsdtInstallEntryPoint (
+  IN EFI_HANDLE                           ImageHandle,
+  IN EFI_SYSTEM_TABLE                     *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+
+  Status = InstallPrmSsdt ((UINT8 *) PcdGetPtr (PcdAcpiDefaultOemId));
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
index 016ced4b3732..4d959ccd35a3 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
@@ -24,7 +24,6 @@ [Sources]
   PrmAcpiTable.h
   PrmLoader.h
   PrmLoaderDxe.c
-  Prm.asl
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -39,13 +38,12 @@ [LibraryClasses]
   BaseMemoryLib
   DebugLib
   MemoryAllocationLib
+  PcdLib
   PeCoffLib
   PrmContextBufferLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
-  DxeServicesLib
-  PcdLib
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId            ## CONSUMES
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index 1a0ddc6ac181..d3aeffa152e0 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -84,6 +84,11 @@ [Components]
   #
   $(PLATFORM_PACKAGE)/PrmLoaderDxe/PrmLoaderDxe.inf
 
+  #
+  # PRM SSDT Installation Driver
+  #
+  $(PLATFORM_PACKAGE)/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
+
   #
   # PRM Sample Modules
   #
diff --git a/PrmPkg/PrmLoaderDxe/Prm.asl b/PrmPkg/PrmSsdtInstallDxe/Prm.asl
similarity index 82%
rename from PrmPkg/PrmLoaderDxe/Prm.asl
rename to PrmPkg/PrmSsdtInstallDxe/Prm.asl
index 76b56de732da..0457d09e6954 100644
--- a/PrmPkg/PrmLoaderDxe/Prm.asl
+++ b/PrmPkg/PrmSsdtInstallDxe/Prm.asl
@@ -8,10 +8,10 @@
 DefinitionBlock (
     "Prm.aml",
     "SSDT",
-    0x01,
-    "OEMID",
+    2,
+    "OEMID ",
     "PRMOPREG",
-    0x3000
+    0x1000
     )
 {
     Scope (\_SB)
@@ -66,18 +66,6 @@ DefinitionBlock (
             {
                 \_SB.PRMB.SETV (BUF1)
             }
-            Method (TST1)
-            {
-                \_SB.PRMB.SETV (BUF1)
-            }
-            Method (TST2)
-            {
-                \_SB.PRMB.SETV (BUF2)
-            }
-            Method (TST3)
-            {
-                \_SB.PRMB.SETV (BUF3)
-            }
         }
     }
 
diff --git a/PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf b/PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
new file mode 100644
index 000000000000..e68e9460ddc5
--- /dev/null
+++ b/PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
@@ -0,0 +1,52 @@
+## @file
+#  PRM SSDT Installation Driver
+#
+#  This driver installs the PRM SSDT.
+#  * Not all PRM implementations may need this support and if it is not needed, the driver
+#    can simply be removed from the platform build.
+#  * The platform may also choose to use this driver but modify the ASL file.
+#
+#  Copyright (c) Microsoft Corporation
+#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PrmSsdtInstallDxe
+  FILE_GUID                      = B0423E2F-3B2C-4A36-BF98-3EB3B4B7CB0E
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PrmSsdtInstallEntryPoint
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PrmSsdtInstallDxe.c
+  Prm.asl
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  DxeServicesLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId            ## CONSUMES
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid
+
+[Depex]
+  gEfiAcpiTableProtocolGuid
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 16/41] PrmPkg: Remove PRM Module Update Lock
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (14 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 15/41] PrmPkg: Add initial PrmSsdtInstallDxe module Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 17/41] PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag Michael Kubacki
                   ` (24 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Per latest design direction, we've abandoned treating the PRM Module
Update Lock as an exported object. There was concern sharing the PRM
module address space (where the lock structure resided in a data section)
with the OS kernel mode driver. The lock will now be entirely maintained
in OS context with interaces to control the lock available to ASL
(for _DSM invocation) and OS native code (for direct call).

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>
---
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c | 18 --------
 PrmPkg/Include/PrmModule.h         | 20 ---------
 PrmPkg/Include/PrmModuleUpdate.h   | 46 --------------------
 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h |  2 -
 PrmPkg/Readme.md                   | 37 ++++++++--------
 5 files changed, 18 insertions(+), 105 deletions(-)

diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index e45f8685e81f..e2a838ea29bd 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -26,7 +26,6 @@
 
 #include <PrmContextBuffer.h>
 #include <PrmMmio.h>
-#include <PrmModuleUpdate.h>
 
 LIST_ENTRY          mPrmModuleList;
 
@@ -707,23 +706,6 @@ ProcessPrmModules (
                 );
     ASSERT_EFI_ERROR (Status);
 
-    Status =  GetExportEntryAddress (
-                PRM_STRING (PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_NAME),
-                CurrentImageAddress,
-                CurrentImageExportDirectory,
-                (EFI_PHYSICAL_ADDRESS *) &(CurrentModuleInfoStruct->ModuleUpdateLock)
-                );
-    ASSERT_EFI_ERROR (Status);
-    if (!EFI_ERROR (Status)) {
-      DEBUG ((
-        DEBUG_INFO,
-        "    %a %a: Found PRM module update lock physical address at 0x%016x.\n",
-        _DBGMSGID_,
-        __FUNCTION__,
-        CurrentModuleInfoStruct->ModuleUpdateLock
-        ));
-    }
-
     // It is currently valid for a PRM module not to use a context buffer
     Status = GetModuleContextBuffers (
               ByModuleGuid,
diff --git a/PrmPkg/Include/PrmModule.h b/PrmPkg/Include/PrmModule.h
index f40fb42a2b4f..d7047d8eec58 100644
--- a/PrmPkg/Include/PrmModule.h
+++ b/PrmPkg/Include/PrmModule.h
@@ -15,7 +15,6 @@
 #include <PrmDataBuffer.h>
 #include <PrmExportDescriptor.h>
 #include <PrmMmio.h>
-#include <PrmModuleUpdate.h>
 #include <PrmOsServices.h>
 
 /**
@@ -46,23 +45,4 @@
     IN PRM_CONTEXT_BUFFER   *ContextBuffer      \
     )                                           \
 
-/**
-  A macro that declares the PRM Module Update Lock Descriptor for a PRM Module.
-
-  This macro is intended to be used once in a PRM Module so the module update lock descriptor is
-  exported for the module.
-
-**/
-#define PRM_MODULE_UPDATE_LOCK_EXPORT                                                           \
-  PRM_EXPORT_API PRM_MODULE_UPDATE_LOCK_DESCRIPTOR PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_NAME = {   \
-    PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_SIGNATURE,                                                \
-    PRM_MODULE_UPDATE_LOCK_REVISION,                                                            \
-    { 0 }                                                                                       \
-  }                                                                                             \
-
-//
-// A PRM module is required to export the PRM Module Update Lock
-//
-PRM_MODULE_UPDATE_LOCK_EXPORT;
-
 #endif
diff --git a/PrmPkg/Include/PrmModuleUpdate.h b/PrmPkg/Include/PrmModuleUpdate.h
deleted file mode 100644
index fde97eff0462..000000000000
--- a/PrmPkg/Include/PrmModuleUpdate.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/** @file
-
-  Definition for the Platform Runtime Mechanism (PRM) module update structures.
-
-  Copyright (c) Microsoft Corporation
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef PRM_MODULE_UPDATE_H_
-#define PRM_MODULE_UPDATE_H_
-
-#include <Uefi.h>
-
-#define PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_NAME        PrmModuleUpdateLock
-#define PRM_MODULE_UPDATE_LOCK_DESCRIPTOR_SIGNATURE   SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'U', 'L', '_')
-#define PRM_MODULE_UPDATE_LOCK_REVISION               0x0
-
-#pragma pack(push, 1)
-
-///
-/// Maintains the PRM Module Update Lock state
-///
-typedef union {
-  ///
-  /// Individual bit fields
-  ///
-  struct {
-    UINT8 Acquired          : 1;  ///< [0] - If 1 lock is acquired. If 0 lock is released.
-    UINT8 Reserved          : 7;  ///< [7:1] - Reserved
-  } Bits;
-  ///
-  /// All bit fields as an 8-bit value
-  ///
-  UINT8 Uint8;
-} PRM_MODULE_UPDATE_LOCK;
-
-typedef struct {
-  UINT64                                Signature;
-  UINT16                                Revision;
-  PRM_MODULE_UPDATE_LOCK                Lock;
-} PRM_MODULE_UPDATE_LOCK_DESCRIPTOR;
-
-#pragma pack(pop)
-
-#endif
diff --git a/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
index 8a9c82347d93..ca09be389235 100644
--- a/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
+++ b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
@@ -55,8 +55,6 @@ typedef struct {
   UINT16                              HandlerCount;               ///< Number of entries in the Handler Info array
   UINT32                              HandlerInfoOffset;          ///< Offset in bytes from the beginning of this
                                                                   ///< structure to the Handler Info array
-  UINT64                              ModuleUpdateLock;           ///< Physical address of the PRM Module Update Lock
-                                                                  ///< descriptor (PRM_MODULE_UPDATE_LOCK_DESCRIPTOR *)
   UINT64                              RuntimeMmioRanges;          ///< Physical address of the PRM MMIO Ranges
                                                                   ///< structure (PRM_MODULE_RUNTIME_MMIO_RANGES *)
   PRM_HANDLER_INFORMATION_STRUCT      HandlerInfoStructure[1];
diff --git a/PrmPkg/Readme.md b/PrmPkg/Readme.md
index 00ef41bc5f42..f430006905c5 100644
--- a/PrmPkg/Readme.md
+++ b/PrmPkg/Readme.md
@@ -153,34 +153,33 @@ motivation behind using PE/COFF export tables to expose PRM module information a
 definition consistent between firmware and OS load.
 
 ### PRM Module Exports
-A PRM module must contain at least three exports: A PRM Module Export Descriptor, a PRM Module Update Lock Descriptor,
-and at least one PRM handler. Here's an example of an export table from a PRM module that has a single PRM handler:
+A PRM module must contain at least two exports: A PRM Module Export Descriptor and at least one PRM handler. Here's
+an example of an export table from a PRM module that has a single PRM handler:
 
 ```
-  0000000000005000: 00 00 00 00 FF FF FF FF 00 00 00 00 46 50 00 00  ....ÿÿÿÿ....FP..
-  0000000000005010: 01 00 00 00 03 00 00 00 03 00 00 00 28 50 00 00  ............(P..
-  0000000000005020: 34 50 00 00 40 50 00 00 78 13 00 00 30 40 00 00  4P..@P..x...0@..
-  0000000000005030: 20 40 00 00 67 50 00 00 86 50 00 00 A0 50 00 00   @..gP...P...P..
-  0000000000005040: 00 00 01 00 02 00 50 72 6D 53 61 6D 70 6C 65 43  ......PrmSampleC
-  0000000000005050: 6F 6E 74 65 78 74 42 75 66 66 65 72 4D 6F 64 75  ontextBufferModu
-  0000000000005060: 6C 65 2E 64 6C 6C 00 44 75 6D 70 53 74 61 74 69  le.dll.DumpStati
-  0000000000005070: 63 44 61 74 61 42 75 66 66 65 72 50 72 6D 48 61  cDataBufferPrmHa
-  0000000000005080: 6E 64 6C 65 72 00 50 72 6D 4D 6F 64 75 6C 65 45  ndler.PrmModuleE
-  0000000000005090: 78 70 6F 72 74 44 65 73 63 72 69 70 74 6F 72 00  xportDescriptor.
-  00000000000050A0: 50 72 6D 4D 6F 64 75 6C 65 55 70 64 61 74 65 4C  PrmModuleUpdateL
-  00000000000050B0: 6F 63 6B 00                                      ock.
+  0000000000005000: 00 00 00 00 FF FF FF FF 00 00 00 00 3C 50 00 00  ............<P..
+  0000000000005010: 01 00 00 00 02 00 00 00 02 00 00 00 28 50 00 00  ............(P..
+  0000000000005020: 30 50 00 00 38 50 00 00 78 13 00 00 20 40 00 00  0P..8P..x... @..
+  0000000000005030: 5D 50 00 00 7C 50 00 00 00 00 01 00 50 72 6D 53  ]P..|P......PrmS
+  0000000000005040: 61 6D 70 6C 65 43 6F 6E 74 65 78 74 42 75 66 66  ampleContextBuff
+  0000000000005050: 65 72 4D 6F 64 75 6C 65 2E 64 6C 6C 00 44 75 6D  erModule.dll.Dum
+  0000000000005060: 70 53 74 61 74 69 63 44 61 74 61 42 75 66 66 65  pStaticDataBuffe
+  0000000000005070: 72 50 72 6D 48 61 6E 64 6C 65 72 00 50 72 6D 4D  rPrmHandler.PrmM
+  0000000000005080: 6F 64 75 6C 65 45 78 70 6F 72 74 44 65 73 63 72  oduleExportDescr
+  0000000000005090: 69 70 74 6F 72 00                                iptor.
 
     00000000 characteristics
     FFFFFFFF time date stamp
-        0.10 version
+        0.00 version
            1 ordinal base
-           3 number of functions
-           3 number of names
+           2 number of functions
+           2 number of names
 
     ordinal hint RVA      name
+
           1    0 00001378 DumpStaticDataBufferPrmHandler
-          2    1 00004030 PrmModuleExportDescriptor
-          3    2 00004020 PrmModuleUpdateLock
+          2    1 00004020 PrmModuleExportDescriptor
+
 ```
 ### PRM Image Format
 PRM modules are ultimately PE/COFF images. However, when packaged in firmware the PE/COFF image is placed into a
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 17/41] PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (15 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 16/41] PrmPkg: Remove PRM Module Update Lock Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 18/41] PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures Michael Kubacki
                   ` (23 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

The POR is firmly to use an OS allocated context buffer now so the
build flag that allows firmware to allocate the context buffer
is removed along with supporting code.

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>
---
 PrmPkg/PrmConfigDxe/PrmConfigDxe.c                                                                                    | 72 --------------------
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c                                                                                    |  4 --
 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c | 12 +---
 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h                                                                                    |  6 --
 PrmPkg/PrmPkg.dsc                                                                                                     |  5 --
 PrmPkg/Readme.md                                                                                                      | 12 +---
 6 files changed, 4 insertions(+), 107 deletions(-)

diff --git a/PrmPkg/PrmConfigDxe/PrmConfigDxe.c b/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
index 7215c2e1dc6f..c547db3eca5e 100644
--- a/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
+++ b/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
@@ -26,10 +26,8 @@
 #define _DBGMSGID_                "[PRMCONFIG]"
 
 STATIC  UINTN                     mMaxRuntimeMmioRangeCount;
-STATIC  UINTN                     mMaxStaticDataBufferCount;
 
 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.
@@ -181,32 +179,12 @@ StoreVirtualMemoryAddressChangePointers (
   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;
 
   DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __FUNCTION__));
 
   RangeIndex = 0;
-#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW
-  StaticDataBufferIndex = 0;
-
-  mStaticDataBuffers = AllocateRuntimeZeroPool (sizeof (*mStaticDataBuffers) * mMaxStaticDataBufferCount);
-  if (mStaticDataBuffers == NULL && mMaxStaticDataBufferCount > 0) {
-    DEBUG ((
-      DEBUG_ERROR,
-      "  %a %a: Memory allocation for PRM static data buffer pointer array failed.\n",
-      _DBGMSGID_,
-      __FUNCTION__
-      ));
-    ASSERT (FALSE);
-    return;
-  }
-#endif
 
   mRuntimeMmioRanges = AllocateRuntimeZeroPool (sizeof (*mRuntimeMmioRanges) * mMaxRuntimeMmioRangeCount);
   if (mRuntimeMmioRanges == NULL && mMaxRuntimeMmioRangeCount > 0) {
@@ -240,28 +218,6 @@ StoreVirtualMemoryAddressChangePointers (
         continue;
       }
 
-#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW
-      for (BufferIndex = 0; BufferIndex < PrmConfigProtocol->ModuleContextBuffers.BufferCount; BufferIndex++) {
-        CurrentContextBuffer = &(PrmConfigProtocol->ModuleContextBuffers.Buffer[BufferIndex]);
-
-        if (CurrentContextBuffer->StaticDataBuffer != NULL) {
-          if (StaticDataBufferIndex >= mMaxStaticDataBufferCount) {
-            Status = EFI_BUFFER_TOO_SMALL;
-            DEBUG ((
-              DEBUG_ERROR,
-              "  %a %a: Index out of bounds - Actual count (%d) of PRM data buffers exceeds maximum count (%d).\n",
-              _DBGMSGID_,
-              __FUNCTION__,
-              StaticDataBufferIndex + 1,
-              mMaxStaticDataBufferCount
-              ));
-            ASSERT_EFI_ERROR (Status);
-            return;
-          }
-          mStaticDataBuffers[StaticDataBufferIndex++] = &CurrentContextBuffer->StaticDataBuffer;
-        }
-      }
-#endif
       if (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges != NULL) {
         if (RangeIndex >= mMaxRuntimeMmioRangeCount) {
           Status = EFI_BUFFER_TOO_SMALL;
@@ -286,15 +242,6 @@ StoreVirtualMemoryAddressChangePointers (
       __FUNCTION__,
       RangeIndex
       ));
-#ifdef ALLOCATE_CONTEXT_BUFFER_IN_FW
-    DEBUG ((
-      DEBUG_INFO,
-      "  %a %a: %d static buffers saved for future virtual memory conversion.\n",
-      _DBGMSGID_,
-      __FUNCTION__,
-      StaticDataBufferIndex
-      ));
-#endif
   }
 }
 
@@ -396,15 +343,6 @@ 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
   //
@@ -485,9 +423,6 @@ PrmConfigEndOfDxeNotification (
             CurrentContextBuffer->HandlerGuid
             ));
         }
-        if (CurrentContextBuffer->StaticDataBuffer != NULL) {
-          mMaxStaticDataBufferCount++;
-        }
       }
       DEBUG ((DEBUG_INFO, "      %a %a: Module context buffer validation complete.\n", _DBGMSGID_, __FUNCTION__));
 
@@ -551,13 +486,6 @@ 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/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index e2a838ea29bd..433d81cf8009 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -738,11 +738,7 @@ ProcessPrmModules (
                   &CurrentContextBuffer
                   );
       if (!EFI_ERROR (Status)) {
-#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/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
index b0b12c012a41..c222c961f23b 100644
--- a/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
@@ -151,16 +151,7 @@ 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.
@@ -170,7 +161,6 @@ ContextBufferModuleConfigLibConstructor (
   // 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;
diff --git a/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
index ca09be389235..ec3be529d119 100644
--- a/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
+++ b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
@@ -30,10 +30,6 @@ 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
@@ -41,8 +37,6 @@ 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/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index d3aeffa152e0..6d352dfadb26 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -110,8 +110,3 @@ [Components]
 [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 f430006905c5..52b44a95ddbc 100644
--- a/PrmPkg/Readme.md
+++ b/PrmPkg/Readme.md
@@ -68,17 +68,11 @@ 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).
+* NONE - No build flags are currently used.
 
    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.
+   This structure is passed as the context buffer to PRM handlers. The structure actually passed to PRM handlers is
+   allocated and populated by the OS where it gets all the information to populate the context buffer from other structures.
 
 ## Overview
 At a high-level, PRM can be viewed from three levels of granularity:
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 18/41] PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (16 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 17/41] PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 19/41] PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support Michael Kubacki
                   ` (22 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a new type ACPI_PARAMETER_BUFFER_DESCRIPTOR that can be
used by PRM module configuration code to associate a PRM handler
GUID with an ACPI parameter buffer allocated by the PRM module
configuration code.

The ACPI parameter buffer descriptors for a given PRM module
are tracked in the firmware internal structure
PRM_MODULE_CONTEXT_BUFFERS produced by the module configuration
code.

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>
---
 PrmPkg/Include/PrmContextBuffer.h | 41 ++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/PrmPkg/Include/PrmContextBuffer.h b/PrmPkg/Include/PrmContextBuffer.h
index 8f8144545e64..869480101773 100644
--- a/PrmPkg/Include/PrmContextBuffer.h
+++ b/PrmPkg/Include/PrmContextBuffer.h
@@ -19,6 +19,18 @@
 
 #pragma pack(push, 1)
 
+//
+// Associates an ACPI parameter buffer with a particular PRM handler in
+// a PRM module.
+//
+// If either the GUID or address are zero then neither value is used to
+// copy the ACPI parameter buffer address to the PRMT ACPI table.
+//
+typedef struct {
+  EFI_GUID                              HandlerGuid;
+  UINT64                                AcpiParameterBufferAddress;
+} ACPI_PARAMETER_BUFFER_DESCRIPTOR;
+
 //
 // This is the context buffer structure that is passed to a PRM handler.
 //
@@ -124,6 +136,35 @@ typedef struct
   /// This pointer may be NULL if runtime memory ranges are not needed.
   ///
   PRM_RUNTIME_MMIO_RANGES                 *RuntimeMmioRanges;
+
+  ///
+  /// The number of ACPI parameter buffer descriptors in the array
+  /// AcpiParameterBufferDescriptors
+  ///
+  UINTN                                   AcpiParameterBufferDescriptorCount;
+
+  ///
+  /// A pointer to an array of ACPI parameter buffer descriptors. PRM module
+  /// configuration code uses this structure to associate a specific PRM
+  /// handler with an ACPI parameter buffer.
+  ///
+  /// An ACPI parameter buffer is a parameter buffer allocated by the PRM
+  /// module configuration code to be used by ACPI as a parameter buffer
+  /// to the associated PRM handler at OS runtime.
+  ///
+  /// This buffer is not required if:
+  /// 1. A parameter buffer is not used by a PRM handler at all
+  /// 2. A parameter buffer is used but the PRM handler is never invoked
+  ///    from ACPI (it is directly called by an OS device driver for example)
+  ///
+  /// In case #2 above, the direct PRM handler is responsible for allocating
+  /// a parameter buffer and passing that buffer to the PRM handler.
+  ///
+  /// A PRM module only needs to provide an ACPI_PARAMETER_BUFFER_DESCRIPTOR
+  /// for each PRM handler that actually uses an ACPI parameter buffer. If
+  /// no handlers use an ACPI parameter buffer this pointer should be NULL.
+  ///
+  ACPI_PARAMETER_BUFFER_DESCRIPTOR        *AcpiParameterBufferDescriptors;
 } PRM_MODULE_CONTEXT_BUFFERS;
 
 #pragma pack(pop)
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 19/41] PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (17 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 18/41] PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 20/41] PrmPkg/PrmSampleContextBufferModule: Remove OS debug print requirement Michael Kubacki
                   ` (21 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds support to PrmLoaderDxe to move the ACPI parameter buffer
address for a given PRM handler to the corresponding field
in the PRM handler information structure (PRMT ACPI table).

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>
---
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index 433d81cf8009..6416e388a668 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -621,6 +621,7 @@ ProcessPrmModules (
   PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY     *TempListEntry;
   CONST CHAR8                             *CurrentExportDescriptorHandlerName;
 
+  ACPI_PARAMETER_BUFFER_DESCRIPTOR        *CurrentModuleAcpiParamDescriptors;
   PRM_CONTEXT_BUFFER                      *CurrentContextBuffer;
   PRM_MODULE_CONTEXT_BUFFERS              *CurrentModuleContextBuffers;
   PRM_MODULE_INFORMATION_STRUCT           *CurrentModuleInfoStruct;
@@ -628,6 +629,7 @@ ProcessPrmModules (
 
   EFI_STATUS                              Status;
   EFI_PHYSICAL_ADDRESS                    CurrentImageAddress;
+  UINTN                                   AcpiParamIndex;
   UINTN                                   HandlerIndex;
   UINT32                                  PrmAcpiDescriptionTableBufferSize;
 
@@ -677,6 +679,7 @@ ProcessPrmModules (
     CurrentImageAddress = TempListEntry->Context->PeCoffImageContext.ImageAddress;
     CurrentImageExportDirectory = TempListEntry->Context->ExportDirectory;
     CurrentExportDescriptorStruct = TempListEntry->Context->ExportDescriptor;
+    CurrentModuleAcpiParamDescriptors = NULL;
 
     DEBUG ((
       DEBUG_INFO,
@@ -715,6 +718,7 @@ ProcessPrmModules (
     ASSERT (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND);
     if (!EFI_ERROR (Status) && CurrentModuleContextBuffers != NULL) {
       CurrentModuleInfoStruct->RuntimeMmioRanges = (UINT64) (UINTN) CurrentModuleContextBuffers->RuntimeMmioRanges;
+      CurrentModuleAcpiParamDescriptors = CurrentModuleContextBuffers->AcpiParameterBufferDescriptors;
     }
 
     //
@@ -759,6 +763,19 @@ ProcessPrmModules (
           CurrentHandlerInfoStruct->PhysicalAddress
           ));
       }
+
+      //
+      // Update the handler ACPI parameter buffer address if applicable
+      //
+      if (CurrentModuleAcpiParamDescriptors != NULL) {
+        for (AcpiParamIndex = 0; AcpiParamIndex < CurrentModuleContextBuffers->AcpiParameterBufferDescriptorCount; AcpiParamIndex++) {
+          if (CompareGuid (&CurrentModuleAcpiParamDescriptors[AcpiParamIndex].HandlerGuid, &CurrentHandlerInfoStruct->Identifier)) {
+            CurrentHandlerInfoStruct->AcpiParameterBuffer = (UINT64) (UINTN) (
+                                                              CurrentModuleAcpiParamDescriptors[AcpiParamIndex].AcpiParameterBufferAddress
+                                                              );
+          }
+        }
+      }
     }
     CurrentModuleInfoStruct = (PRM_MODULE_INFORMATION_STRUCT *) ((UINTN) CurrentModuleInfoStruct + CurrentModuleInfoStruct->StructureLength);
   }
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 20/41] PrmPkg/PrmSampleContextBufferModule: Remove OS debug print requirement
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (18 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 19/41] PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 21/41] PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM handlers Michael Kubacki
                   ` (20 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Removes the expectation that the parameter buffer contain an OS
debug print service at the beginning of the buffer. All supporting
code related to printing is also removed.

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>
---
 PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c |   4 +-
 PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c                                            | 128 +++-----------------
 2 files changed, 17 insertions(+), 115 deletions(-)

diff --git a/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
index c222c961f23b..4c0c3348459c 100644
--- a/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.c
@@ -24,7 +24,7 @@ STATIC EFI_HANDLE  mPrmConfigProtocolHandle;
 STATIC CONST EFI_GUID mPrmModuleGuid = {0x5a6cf42b, 0x8bb4, 0x472c, {0xa2, 0x33, 0x5c, 0x4d, 0xc4, 0x03, 0x3d, 0xc7}};
 
 // {e1466081-7562-430f-896b-b0e523dc335a}
-STATIC CONST EFI_GUID mDumpStaticDataBufferPrmHandlerGuid = {0xe1466081, 0x7562, 0x430f, {0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a}};
+STATIC CONST EFI_GUID mCheckStaticDataBufferPrmHandlerGuid = {0xe1466081, 0x7562, 0x430f, {0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a}};
 
 /**
   Populates the static data buffer for this PRM module.
@@ -166,7 +166,7 @@ ContextBufferModuleConfigLibConstructor (
     Status = EFI_OUT_OF_RESOURCES;
     goto Done;
   }
-  CopyGuid (&PrmContextBuffer->HandlerGuid, &mDumpStaticDataBufferPrmHandlerGuid);
+  CopyGuid (&PrmContextBuffer->HandlerGuid, &mCheckStaticDataBufferPrmHandlerGuid);
   PrmContextBuffer->Signature = PRM_CONTEXT_BUFFER_SIGNATURE;
   PrmContextBuffer->Version = PRM_CONTEXT_BUFFER_INTERFACE_VERSION;
   PrmContextBuffer->StaticDataBuffer = StaticDataBuffer;
diff --git a/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c b/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c
index 074552d0c07e..5c4e5c7a10eb 100644
--- a/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c
+++ b/PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.c
@@ -21,146 +21,39 @@
 //
 
 // {e1466081-7562-430f-896b-b0e523dc335a}
-#define DUMP_STATIC_DATA_BUFFER_PRM_HANDLER_GUID {0xe1466081, 0x7562, 0x430f, {0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a}}
-
-/**
-  Dumps the contents of a given buffer.
-
-  @param[in]  OsServiceDebugPrint   A pointer to the debug print OS service.
-  @param[in]  Buffer                A pointer to the buffer that should be dumped.
-  @param[in]  BufferSize            The size of Buffer in bytes.
-
-**/
-STATIC
-VOID
-DumpBuffer (
-  IN PRM_OS_SERVICE_DEBUG_PRINT OsServiceDebugPrint,
-  IN CONST VOID                 *Buffer,
-  IN UINTN                      BufferSize
-  )
-{
-  UINTN Count;
-  CONST UINT8 *Char = Buffer;
-  CHAR8 DebugMessage[16];
-
-  if (OsServiceDebugPrint == NULL || Buffer == NULL) {
-    return;
-  }
-
-  OsServiceDebugPrint ("    ");
-  for (Count = 0; Count < BufferSize; Count++)
-  {
-    if (Count && !(Count % 16)) {
-      OsServiceDebugPrint ("\n    ");
-    }
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "%02X ",
-      Char[Count]
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-  }
-  OsServiceDebugPrint ("\n\n");
-}
-
-/**
-  Prints the contents of this PRM module's static data buffer.
-
-  @param[in]  OsServiceDebugPrint   A pointer to the debug print OS service.
-  @param[in]  StaticDataBuffer      A pointer to the static buffer.
-
-**/
-VOID
-EFIAPI
-PrintStaticDataBuffer (
-  IN PRM_OS_SERVICE_DEBUG_PRINT                       OsServiceDebugPrint,
-  IN CONST STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE   *StaticDataBuffer
-  )
-{
-  CHAR8 DebugMessage[256];
-
-  if (OsServiceDebugPrint == NULL || StaticDataBuffer == NULL) {
-    return;
-  }
-
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  Policy1Enabled = 0x%x.\n",
-    StaticDataBuffer->Policy1Enabled
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
-
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  Policy2Enabled = 0x%x.\n",
-    StaticDataBuffer->Policy2Enabled
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
-
-  OsServiceDebugPrint ("  Dumping SomeValueArray:\n");
-  DumpBuffer (
-    OsServiceDebugPrint,
-    (CONST VOID *) &StaticDataBuffer->SomeValueArray[0],
-    ARRAY_SIZE (StaticDataBuffer->SomeValueArray)
-    );
-}
+#define CHECK_STATIC_DATA_BUFFER_PRM_HANDLER_GUID {0xe1466081, 0x7562, 0x430f, {0x89, 0x6b, 0xb0, 0xe5, 0x23, 0xdc, 0x33, 0x5a}}
 
 /**
   A sample Platform Runtime Mechanism (PRM) handler.
 
-  This sample handler attempts to read the contents of the static data buffer that were configured
-  during the firmware boot environment and print those contents at OS runtime.
+  This sample handler checks that a static data buffer can be accessed from a given context buffer.
 
-  @param[in]  OsServices          An array of pointers to OS provided services for PRM handlers
-  @param[in]  Context             Handler context info
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
 
   @retval EFI_STATUS              The PRM handler executed successfully.
   @retval Others                  An error occurred in the PRM handler.
 
 **/
-PRM_HANDLER_EXPORT (DumpStaticDataBufferPrmHandler)
+PRM_HANDLER_EXPORT (CheckStaticDataBufferPrmHandler)
 {
-  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
-
   if (ContextBuffer == NULL) {
     return EFI_INVALID_PARAMETER;
   }
 
-  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
-  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
-  if (OsServiceDebugPrint == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  OsServiceDebugPrint ("Context Buffer DumpStaticDataBufferPrmHandler entry.\n");
-
   if (ContextBuffer->StaticDataBuffer == NULL) {
-    OsServiceDebugPrint ("The static buffer is not allocated!\n");
     return EFI_INVALID_PARAMETER;
   }
 
-  OsServiceDebugPrint ("  Printing the contents of the static data buffer:\n");
-
   //
   // Verify PRM data buffer signature is valid
   //
   if (
     ContextBuffer->Signature != PRM_CONTEXT_BUFFER_SIGNATURE ||
     ContextBuffer->StaticDataBuffer->Header.Signature != PRM_DATA_BUFFER_HEADER_SIGNATURE) {
-    OsServiceDebugPrint ("  A buffer signature is invalid!\n");
     return EFI_NOT_FOUND;
   }
 
-  PrintStaticDataBuffer (
-    OsServiceDebugPrint,
-    (CONST STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE *) &(ContextBuffer->StaticDataBuffer->Data[0])
-    );
-
-  OsServiceDebugPrint ("Context Buffer DumpStaticDataBufferPrmHandler exit.\n");
-
   return EFI_SUCCESS;
 }
 
@@ -168,9 +61,18 @@ PRM_HANDLER_EXPORT (DumpStaticDataBufferPrmHandler)
 // Register the PRM export information for this PRM Module
 //
 PRM_MODULE_EXPORT (
-  PRM_HANDLER_EXPORT_ENTRY (DUMP_STATIC_DATA_BUFFER_PRM_HANDLER_GUID, DumpStaticDataBufferPrmHandler)
+  PRM_HANDLER_EXPORT_ENTRY (CHECK_STATIC_DATA_BUFFER_PRM_HANDLER_GUID, CheckStaticDataBufferPrmHandler)
   );
 
+/**
+  Module entry point.
+
+  @param[in]   ImageHandle     The image handle.
+  @param[in]   SystemTable     A pointer to the system table.
+
+  @retval  EFI_SUCCESS         This function always returns success.
+
+**/
 EFI_STATUS
 EFIAPI
 PrmSampleContextBufferModuleInit (
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 21/41] PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM handlers
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (19 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 20/41] PrmPkg/PrmSampleContextBufferModule: Remove OS debug print requirement Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 22/41] PrmPkg/SampleAcpiParameterBufferModule: Add initial module Michael Kubacki
                   ` (19 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

For each PRM handler that is currently present, a corresponding PRM
handler is added that does not print. This allows a caller to execute
a sample hardware access PRM handler without requiring that caller to
provide a debug print service.

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>
---
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c | 375 +++++++++++++-------
 1 file changed, 243 insertions(+), 132 deletions(-)

diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
index 87fe9cafc912..32e04c5e8592 100644
--- a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
@@ -27,12 +27,21 @@
 // {2120cd3c-848b-4d8f-abbb-4b74ce64ac89}
 #define MSR_ACCESS_MICROCODE_SIGNATURE_PRM_HANDLER_GUID {0x2120cd3c, 0x848b, 0x4d8f, {0xab, 0xbb, 0x4b, 0x74, 0xce, 0x64, 0xac, 0x89}}
 
+// {5d28b4e7-3867-4aee-aa09-51fc282c3b22}
+#define MSR_PRINT_MICROCODE_SIGNATURE_PRM_HANDLER_GUID {0x5d28b4e7, 0x3867, 0x4aee, {0xaa, 0x09, 0x51, 0xfc, 0x28, 0x2c, 0x3b, 0x22}}
+
 // {ea0935a7-506b-4159-bbbb-48deeecb6f58}
 #define MSR_ACCESS_MTRR_DUMP_PRM_HANDLER_GUID {0xea0935a7, 0x506b, 0x4159, {0xbb, 0xbb, 0x48, 0xde, 0xee, 0xcb, 0x6f, 0x58}}
 
+// {4b64b702-4d2b-4dfe-ac5a-0b4110a2ca47}
+#define MSR_PRINT_MTRR_DUMP_PRM_HANDLER_GUID {0x4b64b702, 0x4d2b, 0x4dfe, {0xac, 0x5a, 0x0b, 0x41, 0x10, 0xa2, 0xca, 0x47}}
+
 // {1bd1bda9-909a-4614-9699-25ec0c2783f7}
 #define MMIO_ACCESS_HPET_PRM_HANDLER_GUID {0x1bd1bda9, 0x909a, 0x4614, {0x96, 0x99, 0x25, 0xec, 0x0c, 0x27, 0x83, 0xf7}}
 
+// {8a0efdde-78d0-45f0-aea0-c28245c7e1db}
+#define MMIO_PRINT_HPET_PRM_HANDLER_GUID {0x8a0efdde, 0x78d0, 0x45f0, {0xae, 0xa0, 0xc2, 0x82, 0x45, 0xc7, 0xe1, 0xdb}}
+
 #define HPET_BASE_ADDRESS 0xFED00000
 
 //
@@ -124,13 +133,18 @@ MtrrLibApplyVariableMtrrs (
 //
 
 /**
-  Prints all MTRR values including architectural and variable MTTRs.
+  Accesses MTRR values including architectural and variable MTRRs.
+
+  If the optional OsServiceDebugPrint function pointer is provided that function is
+  used to print the MTRR settings.
+
+  @param[in]  OsServiceDebugPrint   A pointer to an OS-provided debug print function.
 
 **/
 VOID
 EFIAPI
-PrintAllMtrrs (
-  IN PRM_OS_SERVICE_DEBUG_PRINT   OsServiceDebugPrint
+AccessAllMtrrs (
+  IN PRM_OS_SERVICE_DEBUG_PRINT   OsServiceDebugPrint   OPTIONAL
   )
 {
   MTRR_SETTINGS                   LocalMtrrs;
@@ -148,7 +162,7 @@ PrintAllMtrrs (
     ];
   MTRR_MEMORY_RANGE RawVariableRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)];
 
-  if (OsServiceDebugPrint == NULL || !IsMtrrSupported ()) {
+  if (!IsMtrrSupported ()) {
     return;
   }
 
@@ -160,56 +174,63 @@ PrintAllMtrrs (
   //
   // Dump RAW MTRR contents
   //
-  OsServiceDebugPrint ("  MTRR Settings:\n");
-  OsServiceDebugPrint ("  =============\n");
+  if (OsServiceDebugPrint != NULL) {
+    OsServiceDebugPrint ("  MTRR Settings:\n");
+    OsServiceDebugPrint ("  =============\n");
 
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  MTRR Default Type: %016lx\n",
-    Mtrrs->MtrrDefType
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
-
-  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
     AsciiSPrint (
       &DebugMessage[0],
       ARRAY_SIZE (DebugMessage),
-      "  Fixed MTRR[%02d]   : %016lx\n",
-      Index,
-      Mtrrs->Fixed.Mtrr[Index]
+      "  MTRR Default Type: %016lx\n",
+      Mtrrs->MtrrDefType
       );
     OsServiceDebugPrint (&DebugMessage[0]);
   }
-  ContainVariableMtrr = FALSE;
-  for (Index = 0; Index < VariableMtrrCount; Index++) {
-    if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {
-      //
-      // If mask is not valid, then do not display range
-      //
-      continue;
+
+  if (OsServiceDebugPrint != NULL) {
+    for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
+        AsciiSPrint (
+          &DebugMessage[0],
+          ARRAY_SIZE (DebugMessage),
+          "  Fixed MTRR[%02d]   : %016lx\n",
+          Index,
+          Mtrrs->Fixed.Mtrr[Index]
+          );
+        OsServiceDebugPrint (&DebugMessage[0]);
+      }
+
+    ContainVariableMtrr = FALSE;
+    for (Index = 0; Index < VariableMtrrCount; Index++) {
+      if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {
+        //
+        // If mask is not valid, then do not display range
+        //
+        continue;
+      }
+      ContainVariableMtrr = TRUE;
+      AsciiSPrint (
+        &DebugMessage[0],
+        ARRAY_SIZE (DebugMessage),
+        "  Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
+        Index,
+        Mtrrs->Variables.Mtrr[Index].Base,
+        Mtrrs->Variables.Mtrr[Index].Mask
+        );
+      OsServiceDebugPrint (&DebugMessage[0]);
     }
-    ContainVariableMtrr = TRUE;
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
-      Index,
-      Mtrrs->Variables.Mtrr[Index].Base,
-      Mtrrs->Variables.Mtrr[Index].Mask
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-  }
-  if (!ContainVariableMtrr) {
-    OsServiceDebugPrint ("  Variable MTRR    : None.\n");
+    if (!ContainVariableMtrr) {
+      OsServiceDebugPrint ("  Variable MTRR    : None.\n");
+    }
+    OsServiceDebugPrint ("\n");
   }
-  OsServiceDebugPrint ("\n");
 
   //
   // Dump MTRR setting in ranges
   //
-  OsServiceDebugPrint ("  Memory Ranges:\n");
-  OsServiceDebugPrint ("  ====================================\n");
+  if (OsServiceDebugPrint != NULL) {
+    OsServiceDebugPrint ("  Memory Ranges:\n");
+    OsServiceDebugPrint ("  ====================================\n");
+  }
   MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
   Ranges[0].BaseAddress = 0;
   Ranges[0].Length      = MtrrValidBitsMask + 1;
@@ -227,15 +248,17 @@ PrintAllMtrrs (
 
   MtrrLibApplyFixedMtrrs (&Mtrrs->Fixed, Ranges, ARRAY_SIZE (Ranges), &RangeCount);
 
-  for (Index = 0; Index < RangeCount; Index++) {
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  %a:%016lx-%016lx\n",
-      mMtrrMemoryCacheTypeShortName[Ranges[Index].Type],
-      Ranges[Index].BaseAddress, Ranges[Index].BaseAddress + Ranges[Index].Length - 1
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
+  if (OsServiceDebugPrint != NULL) {
+    for (Index = 0; Index < RangeCount; Index++) {
+      AsciiSPrint (
+        &DebugMessage[0],
+        ARRAY_SIZE (DebugMessage),
+        "  %a:%016lx-%016lx\n",
+        mMtrrMemoryCacheTypeShortName[Ranges[Index].Type],
+        Ranges[Index].BaseAddress, Ranges[Index].BaseAddress + Ranges[Index].Length - 1
+        );
+      OsServiceDebugPrint (&DebugMessage[0]);
+    }
   }
 }
 
@@ -277,12 +300,17 @@ HpetRead (
 }
 
 /**
-  Prints HPET configuration information.
+  Accesses HPET configuration information.
+
+  If the optional OsServiceDebugPrint function pointer is provided that function is
+  used to print HPET settings.
+
+  @param[in]  OsServiceDebugPrint   A pointer to an OS-provided debug print function
 
 **/
 VOID
 EFIAPI
-PrintHpetConfiguration (
+AccessHpetConfiguration (
   IN PRM_OS_SERVICE_DEBUG_PRINT           OsServiceDebugPrint
   )
 {
@@ -291,117 +319,132 @@ PrintHpetConfiguration (
   HPET_GENERAL_CONFIGURATION_REGISTER     HpetGeneralConfiguration;
   CHAR8                                   DebugMessage[256];
 
-  if (OsServiceDebugPrint == NULL) {
-    return;
-  }
-
   HpetGeneralCapabilities.Uint64  = HpetRead (HPET_GENERAL_CAPABILITIES_ID_OFFSET);
   HpetGeneralConfiguration.Uint64 = HpetRead (HPET_GENERAL_CONFIGURATION_OFFSET);
 
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  HPET Base Address = 0x%08x\n",
-    HPET_BASE_ADDRESS
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
-
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  HPET_GENERAL_CAPABILITIES_ID  = 0x%016lx\n",
-    HpetGeneralCapabilities
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
-
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  HPET_GENERAL_CONFIGURATION    = 0x%016lx\n",
-    HpetGeneralConfiguration.Uint64
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
-
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  HPET_GENERAL_INTERRUPT_STATUS = 0x%016lx\n",
-    HpetRead (HPET_GENERAL_INTERRUPT_STATUS_OFFSET)
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
+  if (OsServiceDebugPrint != NULL) {
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  HPET Base Address = 0x%08x\n",
+      HPET_BASE_ADDRESS
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
 
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  HPET_MAIN_COUNTER             = 0x%016lx\n",
-    HpetRead (HPET_MAIN_COUNTER_OFFSET)
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  HPET_GENERAL_CAPABILITIES_ID  = 0x%016lx\n",
+      HpetGeneralCapabilities
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
 
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  HPET Main Counter Period      = %d (fs)\n",
-    HpetGeneralCapabilities.Bits.CounterClockPeriod
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
+    AsciiSPrint (
+      &DebugMessage[0],
+      ARRAY_SIZE (DebugMessage),
+      "  HPET_GENERAL_CONFIGURATION    = 0x%016lx\n",
+      HpetGeneralConfiguration.Uint64
+      );
+    OsServiceDebugPrint (&DebugMessage[0]);
 
-  for (TimerIndex = 0; TimerIndex <= HpetGeneralCapabilities.Bits.NumberOfTimers; TimerIndex++) {
     AsciiSPrint (
       &DebugMessage[0],
       ARRAY_SIZE (DebugMessage),
-      "  HPET_TIMER%d_CONFIGURATION     = 0x%016lx\n",
-      TimerIndex,
-      HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + TimerIndex * HPET_TIMER_STRIDE)
+      "  HPET_GENERAL_INTERRUPT_STATUS = 0x%016lx\n",
+      HpetRead (HPET_GENERAL_INTERRUPT_STATUS_OFFSET)
       );
     OsServiceDebugPrint (&DebugMessage[0]);
 
     AsciiSPrint (
       &DebugMessage[0],
       ARRAY_SIZE (DebugMessage),
-      "  HPET_TIMER%d_COMPARATOR        = 0x%016lx\n",
-      TimerIndex,
-      HpetRead (HPET_TIMER_COMPARATOR_OFFSET    + TimerIndex * HPET_TIMER_STRIDE)
+      "  HPET_MAIN_COUNTER             = 0x%016lx\n",
+      HpetRead (HPET_MAIN_COUNTER_OFFSET)
       );
     OsServiceDebugPrint (&DebugMessage[0]);
 
     AsciiSPrint (
       &DebugMessage[0],
       ARRAY_SIZE (DebugMessage),
-      "  HPET_TIMER%d_MSI_ROUTE         = 0x%016lx\n",
-      TimerIndex,
-      HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET     + TimerIndex * HPET_TIMER_STRIDE)
+      "  HPET Main Counter Period      = %d (fs)\n",
+      HpetGeneralCapabilities.Bits.CounterClockPeriod
       );
     OsServiceDebugPrint (&DebugMessage[0]);
+
+    for (TimerIndex = 0; TimerIndex <= HpetGeneralCapabilities.Bits.NumberOfTimers; TimerIndex++) {
+      AsciiSPrint (
+        &DebugMessage[0],
+        ARRAY_SIZE (DebugMessage),
+        "  HPET_TIMER%d_CONFIGURATION     = 0x%016lx\n",
+        TimerIndex,
+        HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + TimerIndex * HPET_TIMER_STRIDE)
+        );
+      OsServiceDebugPrint (&DebugMessage[0]);
+
+      AsciiSPrint (
+        &DebugMessage[0],
+        ARRAY_SIZE (DebugMessage),
+        "  HPET_TIMER%d_COMPARATOR        = 0x%016lx\n",
+        TimerIndex,
+        HpetRead (HPET_TIMER_COMPARATOR_OFFSET    + TimerIndex * HPET_TIMER_STRIDE)
+        );
+      OsServiceDebugPrint (&DebugMessage[0]);
+
+      AsciiSPrint (
+        &DebugMessage[0],
+        ARRAY_SIZE (DebugMessage),
+        "  HPET_TIMER%d_MSI_ROUTE         = 0x%016lx\n",
+        TimerIndex,
+        HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET     + TimerIndex * HPET_TIMER_STRIDE)
+        );
+      OsServiceDebugPrint (&DebugMessage[0]);
+    }
   }
 }
 
 /**
-  Prints the microcode update signature as read from architectural MSR 0x8B.
+  Reads the microcode signature from architectural MSR 0x8B.
 
+  @retval MicrocodeSignature      The microcode signature value.
 **/
-VOID
-EFIAPI
-PrintMicrocodeUpdateSignature (
-  IN PRM_OS_SERVICE_DEBUG_PRINT   OsServiceDebugPrint
+UINT32
+GetMicrocodeSignature (
+  VOID
   )
 {
   MSR_IA32_BIOS_SIGN_ID_REGISTER  BiosSignIdMsr;
-  CHAR8                           DebugMessage[256];
-
-  if (OsServiceDebugPrint == NULL) {
-    return;
-  }
 
   AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
   AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
   BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);
 
+  return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;
+}
+
+/**
+  Prints the microcode update signature as read from architectural MSR 0x8B.
+
+**/
+VOID
+EFIAPI
+PrintMicrocodeUpdateSignature (
+  IN PRM_OS_SERVICE_DEBUG_PRINT   OsServiceDebugPrint
+  )
+{
+  UINT32                          MicrocodeSignature;
+  CHAR8                           DebugMessage[256];
+
+  if (OsServiceDebugPrint == NULL) {
+    return;
+  }
+
+  MicrocodeSignature = GetMicrocodeSignature ();
+
   AsciiSPrint (
     &DebugMessage[0],
     ARRAY_SIZE (DebugMessage),
     "  Signature read = 0x%x.\n",
-    BiosSignIdMsr.Bits.MicrocodeUpdateSignature
+    MicrocodeSignature
     );
   OsServiceDebugPrint (&DebugMessage[0]);
 }
@@ -409,7 +452,7 @@ PrintMicrocodeUpdateSignature (
 /**
   A sample Platform Runtime Mechanism (PRM) handler.
 
-  This sample handler attempts to read the microcode update signature MSR and print the result to a debug message.
+  This sample handler attempts to read the microcode update signature.
 
   @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
   @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
@@ -419,6 +462,32 @@ PrintMicrocodeUpdateSignature (
 
 **/
 PRM_HANDLER_EXPORT (MsrAccessMicrocodeSignaturePrmHandler)
+{
+  UINT32  MicrocodeSignature;
+
+  MicrocodeSignature = 0;
+  MicrocodeSignature = GetMicrocodeSignature ();
+
+  if (MicrocodeSignature == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler attempts to read the microcode update signature MSR and print the result to a debug message.
+
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+PRM_HANDLER_EXPORT (MsrPrintMicrocodeSignaturePrmHandler)
 {
   PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
 
@@ -426,7 +495,7 @@ PRM_HANDLER_EXPORT (MsrAccessMicrocodeSignaturePrmHandler)
     return EFI_INVALID_PARAMETER;
   }
 
-  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  // The OS debug print service is assumed to be at the beginning of ParameterBuffer
   OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
   if (OsServiceDebugPrint == NULL) {
     return EFI_INVALID_PARAMETER;
@@ -443,7 +512,7 @@ PRM_HANDLER_EXPORT (MsrAccessMicrocodeSignaturePrmHandler)
 /**
   A sample Platform Runtime Mechanism (PRM) handler.
 
-  This sample handler attempts to read the current MTRR settings and print the result to a debug message.
+  This sample handler attempts to read the current MTRR settings.
 
   @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
   @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
@@ -453,6 +522,25 @@ PRM_HANDLER_EXPORT (MsrAccessMicrocodeSignaturePrmHandler)
 
 **/
 PRM_HANDLER_EXPORT (MsrAccessMtrrDumpPrmHandler)
+{
+  AccessAllMtrrs (NULL);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler attempts to read the current MTRR settings and print the result to a debug message.
+
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+PRM_HANDLER_EXPORT (MsrPrintMtrrDumpPrmHandler)
 {
   PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
 
@@ -468,16 +556,17 @@ PRM_HANDLER_EXPORT (MsrAccessMtrrDumpPrmHandler)
 
   OsServiceDebugPrint ("Hardware Access MsrAccessMtrrDumpPrmHandler entry.\n");
   OsServiceDebugPrint ("  Attempting to dump MTRR values:\n");
-  PrintAllMtrrs (OsServiceDebugPrint);
+  AccessAllMtrrs (OsServiceDebugPrint);
   OsServiceDebugPrint ("Hardware Access MsrAccessMtrrDumpPrmHandler exit.\n");
 
   return EFI_SUCCESS;
 }
 
+
 /**
   A sample Platform Runtime Mechanism (PRM) handler.
 
-  This sample handler attempts to read from a HPET MMIO resource and print the result to a debug message.
+  This sample handler attempts to read from a HPET MMIO resource.
 
   @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
   @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
@@ -487,6 +576,25 @@ PRM_HANDLER_EXPORT (MsrAccessMtrrDumpPrmHandler)
 
 **/
 PRM_HANDLER_EXPORT (MmioAccessHpetPrmHandler)
+{
+  AccessHpetConfiguration (NULL);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler attempts to read from a HPET MMIO resource and print the result to a debug message.
+
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+PRM_HANDLER_EXPORT (MmioPrintHpetPrmHandler)
 {
   PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
 
@@ -494,16 +602,16 @@ PRM_HANDLER_EXPORT (MmioAccessHpetPrmHandler)
     return EFI_INVALID_PARAMETER;
   }
 
-  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
+  // An OS debug print service is assumed to be at the beginning of ParameterBuffer
   OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
   if (OsServiceDebugPrint == NULL) {
     return EFI_INVALID_PARAMETER;
   }
 
-  OsServiceDebugPrint ("Hardware Access MmioAccessHpetPrmHandler entry.\n");
+  OsServiceDebugPrint ("Hardware Access MmioPrintHpetPrmHandler entry.\n");
   OsServiceDebugPrint ("  Attempting to read HPET configuration...\n");
-  PrintHpetConfiguration (OsServiceDebugPrint);
-  OsServiceDebugPrint ("Hardware Access MmioAccessHpetPrmHandler exit.\n");
+  AccessHpetConfiguration (OsServiceDebugPrint);
+  OsServiceDebugPrint ("Hardware Access MmioPrintHpetPrmHandler exit.\n");
 
   return EFI_SUCCESS;
 }
@@ -514,7 +622,10 @@ PRM_HANDLER_EXPORT (MmioAccessHpetPrmHandler)
 PRM_MODULE_EXPORT (
   PRM_HANDLER_EXPORT_ENTRY (MSR_ACCESS_MICROCODE_SIGNATURE_PRM_HANDLER_GUID, MsrAccessMicrocodeSignaturePrmHandler),
   PRM_HANDLER_EXPORT_ENTRY (MSR_ACCESS_MTRR_DUMP_PRM_HANDLER_GUID, MsrAccessMtrrDumpPrmHandler),
-  PRM_HANDLER_EXPORT_ENTRY (MMIO_ACCESS_HPET_PRM_HANDLER_GUID, MmioAccessHpetPrmHandler)
+  PRM_HANDLER_EXPORT_ENTRY (MMIO_ACCESS_HPET_PRM_HANDLER_GUID, MmioAccessHpetPrmHandler),
+  PRM_HANDLER_EXPORT_ENTRY (MSR_PRINT_MICROCODE_SIGNATURE_PRM_HANDLER_GUID, MsrPrintMicrocodeSignaturePrmHandler),
+  PRM_HANDLER_EXPORT_ENTRY (MSR_PRINT_MTRR_DUMP_PRM_HANDLER_GUID, MsrPrintMtrrDumpPrmHandler),
+  PRM_HANDLER_EXPORT_ENTRY (MMIO_PRINT_HPET_PRM_HANDLER_GUID, MmioPrintHpetPrmHandler)
   );
 
 /**
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 22/41] PrmPkg/SampleAcpiParameterBufferModule: Add initial module
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (20 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 21/41] PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM handlers Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 23/41] PrmPkg/HardwareAccessModuleConfigLib: Add initial library Michael Kubacki
                   ` (18 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a new PRM module called SampleAcpiParameterBufferModule that
demonstrates how a PRM module can use an ACPI parameter buffer with
a PRM handler.

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>
---
 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c   | 120 ++++++++++++++++++++
 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.c                                                    |  79 +++++++++++++
 PrmPkg/PrmPkg.dsc                                                                                                                         |   3 +
 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf |  39 +++++++
 PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf                                                  |  41 +++++++
 5 files changed, 282 insertions(+)

diff --git a/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c b/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c
new file mode 100644
index 000000000000..b135517232f7
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c
@@ -0,0 +1,120 @@
+/** @file
+
+  The boot services environment configuration library for the ACPI Parameter Buffer Sample PRM module.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/PrmConfig.h>
+
+STATIC EFI_HANDLE  mPrmConfigProtocolHandle;
+
+// {dc2a58a6-5927-4776-b995-d118a27335a2}
+STATIC CONST EFI_GUID mPrmModuleGuid = {0xdc2a58a6, 0x5927, 0x4776, {0xb9, 0x95, 0xd1, 0x18, 0xa2, 0x73, 0x35, 0xa2}};
+
+// {2e4f2d13-6240-4ed0-a401-c723fbdc34e8}
+STATIC CONST EFI_GUID mCheckParamBufferPrmHandlerGuid = {0x2e4f2d13, 0x6240, 0x4ed0, {0xa4, 0x01, 0xc7, 0x23, 0xfb, 0xdc, 0x34, 0xe8}};
+
+/**
+  Constructor of the PRM configuration library.
+
+  @param[in] ImageHandle        The image handle of the driver.
+  @param[in] SystemTable        The EFI System Table pointer.
+
+  @retval EFI_SUCCESS           The shell command handlers were installed successfully.
+  @retval EFI_UNSUPPORTED       The shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+AcpiParameterBufferModuleConfigLibConstructor (
+  IN  EFI_HANDLE                    ImageHandle,
+  IN  EFI_SYSTEM_TABLE              *SystemTable
+  )
+{
+  EFI_STATUS                        Status;
+  VOID                              *AcpiParameterBuffer;
+  ACPI_PARAMETER_BUFFER_DESCRIPTOR  *AcpiParamBufferDescriptor;
+  PRM_CONFIG_PROTOCOL               *PrmConfigProtocol;
+
+  AcpiParameterBuffer = NULL;
+  AcpiParamBufferDescriptor = NULL;
+  PrmConfigProtocol = NULL;
+
+  /*
+    In this sample PRM module, the protocol describing this sample module's resources is simply
+    installed in the constructor.
+
+    However, if some data is not available until later, this constructor could register a callback
+    on the dependency for the data to be available (e.g. ability to communicate with some device)
+    and then install the protocol. The requirement is that the protocol is installed before end of DXE.
+  */
+
+  // Allocate the ACPI parameter buffer
+
+  // A parameter buffer is arbitrary data that is handler specific. This handler buffer is specified
+  // to consist of a UINT32 that represents the test data signature ('T', 'E', 'S', 'T').
+  AcpiParameterBuffer = AllocateRuntimeZeroPool (sizeof (UINT32));
+  ASSERT (AcpiParameterBuffer != NULL);
+  if (AcpiParameterBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  // Allocate the ACPI Parameter Buffer Descriptor structure for a single PRM handler
+  AcpiParamBufferDescriptor = AllocateZeroPool (sizeof (*AcpiParamBufferDescriptor));
+  ASSERT (AcpiParamBufferDescriptor != NULL);
+  if (AcpiParamBufferDescriptor == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  // Allocate the PRM Configuration protocol structure for this PRM module
+  PrmConfigProtocol = AllocateZeroPool (sizeof (*PrmConfigProtocol));
+  ASSERT (PrmConfigProtocol != NULL);
+  if (PrmConfigProtocol == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CopyGuid (&PrmConfigProtocol->ModuleContextBuffers.ModuleGuid, &mPrmModuleGuid);
+
+  // Populate the ACPI Parameter Buffer Descriptor structure
+  CopyGuid (&AcpiParamBufferDescriptor->HandlerGuid, &mCheckParamBufferPrmHandlerGuid);
+  AcpiParamBufferDescriptor->AcpiParameterBufferAddress = (UINT64) (UINTN) AcpiParameterBuffer;
+
+  // Populate the PRM Module Context Buffers structure
+  PrmConfigProtocol->ModuleContextBuffers.AcpiParameterBufferDescriptorCount = 1;
+  PrmConfigProtocol->ModuleContextBuffers.AcpiParameterBufferDescriptors = AcpiParamBufferDescriptor;
+
+  //
+  // Install the PRM Configuration Protocol for this module. This indicates the configuration
+  // library has completed resource initialization for the PRM module.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mPrmConfigProtocolHandle,
+                  &gPrmConfigProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID *) PrmConfigProtocol
+                  );
+
+Done:
+  if (EFI_ERROR (Status)) {
+    if (AcpiParameterBuffer != NULL) {
+      FreePool (AcpiParameterBuffer);
+    }
+    if (AcpiParamBufferDescriptor != NULL) {
+      FreePool (AcpiParamBufferDescriptor);
+    }
+    if (PrmConfigProtocol != NULL) {
+      FreePool (PrmConfigProtocol);
+    }
+  }
+
+  return Status;
+}
diff --git a/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.c b/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.c
new file mode 100644
index 000000000000..ebb5ba01a30c
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.c
@@ -0,0 +1,79 @@
+/** @file
+
+  This PRM Module demonstrates how to define an ACPI parameter buffer that is used by a PRM handler.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PrmModule.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+
+// TEMP
+#include <Library/DebugLib.h>
+
+#define PARAM_BUFFER_TEST_SIGNATURE         SIGNATURE_32('T','E','S','T')
+
+//
+// PRM Handler GUIDs
+//
+
+// {2e4f2d13-6240-4ed0-a401-c723fbdc34e8}
+#define CHECK_PARAM_BUFFER_PRM_HANDLER_GUID {0x2e4f2d13, 0x6240, 0x4ed0, {0xa4, 0x01, 0xc7, 0x23, 0xfb, 0xdc, 0x34, 0xe8}}
+
+/**
+  A sample Platform Runtime Mechanism (PRM) handler.
+
+  This sample handler checks if a parameter buffer is provided with the data signature
+  ('T', 'E', 'S', 'T') at the beginning of the buffer.
+
+  The contents are expected to be updated by ACPI code at OS runtime.
+
+  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
+  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
+
+  @retval EFI_STATUS              The PRM handler executed successfully.
+  @retval Others                  An error occurred in the PRM handler.
+
+**/
+PRM_HANDLER_EXPORT (CheckParamBufferPrmHandler)
+{
+  if (ParameterBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*((UINT32 *) ParameterBuffer) == PARAM_BUFFER_TEST_SIGNATURE) {
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+//
+// Register the PRM export information for this PRM Module
+//
+PRM_MODULE_EXPORT (
+  PRM_HANDLER_EXPORT_ENTRY (CHECK_PARAM_BUFFER_PRM_HANDLER_GUID, CheckParamBufferPrmHandler)
+  );
+
+/**
+  Module entry point.
+
+  @param[in]   ImageHandle     The image handle.
+  @param[in]   SystemTable     A pointer to the system table.
+
+  @retval  EFI_SUCCESS         This function always returns success.
+
+**/
+EFI_STATUS
+EFIAPI
+PrmSampleAcpiParameterBufferModuleInit (
+  IN  EFI_HANDLE                  ImageHandle,
+  IN  EFI_SYSTEM_TABLE            *SystemTable
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index 6d352dfadb26..2409378926b9 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -68,6 +68,7 @@ [Components]
   # PRM Libraries
   #
   $(PLATFORM_PACKAGE)/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
+  $(PLATFORM_PACKAGE)/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
   $(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
   $(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
 
@@ -76,6 +77,7 @@ [Components]
   #
   $(PLATFORM_PACKAGE)/PrmConfigDxe/PrmConfigDxe.inf {
     <LibraryClasses>
+      NULL|$(PLATFORM_PACKAGE)/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
       NULL|$(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
   }
 
@@ -93,6 +95,7 @@ [Components]
   # PRM Sample Modules
   #
   $(PLATFORM_PACKAGE)/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
+  $(PLATFORM_PACKAGE)/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf
   $(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf {
     <LibraryClasses>
       DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
diff --git a/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf b/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
new file mode 100644
index 000000000000..9ac83857cf8e
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
@@ -0,0 +1,39 @@
+## @file
+#  Sample PRM Configuration Library Instance
+#
+#  The PRM configuration library instance is responsible for initializing and setting the corresponding
+#  PRM module's configuration in the boot environment.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION         = 0x00010005
+  BASE_NAME           = DxeAcpiParameterBufferModuleConfigLib
+  FILE_GUID           = D43D19E9-007A-4D40-AC4A-418F958AFB9D
+  MODULE_TYPE         = DXE_DRIVER
+  VERSION_STRING      = 1.0
+  LIBRARY_CLASS       = NULL |DXE_DRIVER
+  CONSTRUCTOR         = AcpiParameterBufferModuleConfigLibConstructor
+
+[Sources]
+  DxeAcpiParameterBufferModuleConfigLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[Protocols]
+  gPrmConfigProtocolGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
diff --git a/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf b/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf
new file mode 100644
index 000000000000..e8b71a970d83
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf
@@ -0,0 +1,41 @@
+## @file
+#  Sample PRM Driver
+#
+#  A sample PRM Module implementation. This PRM Module includes a PRM Module configuration library instance
+#  that applies the configuration for an ACPI parameter buffer in the boot environment. A PRM handler
+#  is provided that checks for a specific value in the parameter buffer that should be provided by ACPI
+#  code at OS runtime.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION         = 0x00010005
+  BASE_NAME           = PrmSampleAcpiParameterBufferModule
+  FILE_GUID           = DC2A58A6-5927-4776-B995-D118A27335A2
+  MODULE_TYPE         = DXE_RUNTIME_DRIVER
+  VERSION_STRING      = 1.0
+  ENTRY_POINT         = PrmSampleAcpiParameterBufferModuleInit
+
+[Sources]
+  PrmSampleAcpiParameterBufferModule.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Depex]
+  TRUE
+
+[BuildOptions.common]
+  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
+  MSFT:*_*_*_GENFW_FLAGS = --keepoptionalheader
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 23/41] PrmPkg/HardwareAccessModuleConfigLib: Add initial library
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (21 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 22/41] PrmPkg/SampleAcpiParameterBufferModule: Add initial module Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 24/41] PrmPkg/Samples/Readme.md: Add initial file Michael Kubacki
                   ` (17 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a PRM module configuration library for PrmSampleHardwareAccessModule
that demonstrates marking a runtime MMIO range. In the case of this
sample module, the range used is for HPET.

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>
---
 PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c   | 104 ++++++++++++++++++++
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c                                               |   2 -
 PrmPkg/PrmPkg.dsc                                                                                                          |   1 +
 PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h                                                                        |   3 +
 PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf |  39 ++++++++
 5 files changed, 147 insertions(+), 2 deletions(-)

diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c b/PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
new file mode 100644
index 000000000000..c00ab9ffbbe3
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
@@ -0,0 +1,104 @@
+/** @file
+
+  The boot services environment configuration library for the Hardware Access Sample PRM module.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/PrmConfig.h>
+#include <Samples/PrmSampleHardwareAccessModule/Hpet.h>
+
+STATIC EFI_HANDLE  mPrmConfigProtocolHandle;
+
+// {0ef93ed7-14ae-425b-928f-b85a6213b57e}
+STATIC CONST EFI_GUID mPrmModuleGuid = {0x0ef93ed7, 0x14ae, 0x425b, {0x92, 0x8f, 0xb8, 0x5a, 0x62, 0x13, 0xb5, 0x7e}};
+
+/**
+  Constructor of the PRM configuration library.
+
+  @param[in] ImageHandle        The image handle of the driver.
+  @param[in] SystemTable        The EFI System Table pointer.
+
+  @retval EFI_SUCCESS           The shell command handlers were installed successfully.
+  @retval EFI_UNSUPPORTED       The shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+HardwareAccessModuleConfigLibConstructor (
+  IN  EFI_HANDLE                    ImageHandle,
+  IN  EFI_SYSTEM_TABLE              *SystemTable
+  )
+{
+  EFI_STATUS                        Status;
+  PRM_RUNTIME_MMIO_RANGES           *RuntimeMmioRanges;
+  PRM_CONFIG_PROTOCOL               *PrmConfigProtocol;
+
+  RuntimeMmioRanges = NULL;
+  PrmConfigProtocol = NULL;
+
+  /*
+    In this sample PRM module, the protocol describing this sample module's resources is simply
+    installed in the constructor.
+
+    However, if some data is not available until later, this constructor could register a callback
+    on the dependency for the data to be available (e.g. ability to communicate with some device)
+    and then install the protocol. The requirement is that the protocol is installed before end of DXE.
+  */
+
+  // Runtime MMIO Ranges structure
+
+  // Since this sample module only uses 1 runtime MMIO range, it can use the PRM_RUNTIME_MMIO_RANGES
+  // type directly without extending the size of the data buffer for additional MMIO ranges.
+  RuntimeMmioRanges = AllocateRuntimeZeroPool (sizeof (*RuntimeMmioRanges));
+  ASSERT (RuntimeMmioRanges != NULL);
+  if (RuntimeMmioRanges == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  // Allocate the PRM Configuration protocol structure for this PRM module
+  PrmConfigProtocol = AllocateZeroPool (sizeof (*PrmConfigProtocol));
+  ASSERT (PrmConfigProtocol != NULL);
+  if (PrmConfigProtocol == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+  CopyGuid (&PrmConfigProtocol->ModuleContextBuffers.ModuleGuid, &mPrmModuleGuid);
+
+  // Populate the Runtime MMIO Ranges structure
+  RuntimeMmioRanges->Count = 1;
+  RuntimeMmioRanges->Range[0].PhysicalBaseAddress = HPET_BASE_ADDRESS;
+  RuntimeMmioRanges->Range[0].Length = HPET_RANGE_LENGTH;
+
+  PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges = RuntimeMmioRanges;
+
+  //
+  // Install the PRM Configuration Protocol for this module. This indicates the configuration
+  // library has completed resource initialization for the PRM module.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mPrmConfigProtocolHandle,
+                  &gPrmConfigProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID *) PrmConfigProtocol
+                  );
+
+Done:
+  if (EFI_ERROR (Status)) {
+    if (RuntimeMmioRanges != NULL) {
+      FreePool (RuntimeMmioRanges);
+    }
+    if (PrmConfigProtocol != NULL) {
+      FreePool (PrmConfigProtocol);
+    }
+  }
+
+  return Status;
+}
diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
index 32e04c5e8592..35da1fcf5f17 100644
--- a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
@@ -42,8 +42,6 @@
 // {8a0efdde-78d0-45f0-aea0-c28245c7e1db}
 #define MMIO_PRINT_HPET_PRM_HANDLER_GUID {0x8a0efdde, 0x78d0, 0x45f0, {0xae, 0xa0, 0xc2, 0x82, 0x45, 0xc7, 0xe1, 0xdb}}
 
-#define HPET_BASE_ADDRESS 0xFED00000
-
 //
 // BEGIN: MtrrLib internal library globals and function prototypes here for testing
 //
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index 2409378926b9..19b996eb3a02 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -79,6 +79,7 @@ [Components]
     <LibraryClasses>
       NULL|$(PLATFORM_PACKAGE)/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
       NULL|$(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
+      NULL|$(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
   }
 
   #
diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h b/PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
index c7eb0cbfa747..a4f8758516c0 100644
--- a/PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
@@ -15,6 +15,9 @@
 #ifndef HPET_REGISTER_H_
 #define HPET_REGISTER_H_
 
+#define HPET_BASE_ADDRESS 0xFED00000
+#define HPET_RANGE_LENGTH 0x1000
+
 ///
 /// HPET General Register Offsets
 ///
diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf b/PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
new file mode 100644
index 000000000000..1a50480dd2c5
--- /dev/null
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
@@ -0,0 +1,39 @@
+## @file
+#  Sample PRM Configuration Library Instance
+#
+#  The PRM configuration library instance is responsible for initializing and setting the corresponding
+#  PRM module's configuration in the boot environment.
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION         = 0x00010005
+  BASE_NAME           = DxeHardwareAccessModuleConfigLib
+  FILE_GUID           = 88AA72FE-AE5A-435F-A267-E24D526C666C
+  MODULE_TYPE         = DXE_DRIVER
+  VERSION_STRING      = 1.0
+  LIBRARY_CLASS       = NULL |DXE_DRIVER
+  CONSTRUCTOR         = HardwareAccessModuleConfigLibConstructor
+
+[Sources]
+  DxeHardwareAccessModuleConfigLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PrmPkg/PrmPkg.dec
+
+[Protocols]
+  gPrmConfigProtocolGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 24/41] PrmPkg/Samples/Readme.md: Add initial file
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (22 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 23/41] PrmPkg/HardwareAccessModuleConfigLib: Add initial library Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 25/41] PrmPkg: Refactor some PrmLoaderDxe functionality into libraries Michael Kubacki
                   ` (16 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a Readme.md file for the Samples to help a user get started
building and using the PRM sample modules.

Includes a reference to the Samples/Readme.md file in the top-level
file to help make the reader aware the file exists.

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>
---
 PrmPkg/Readme.md         |   5 +-
 PrmPkg/Samples/Readme.md | 263 ++++++++++++++++++++
 2 files changed, 267 insertions(+), 1 deletion(-)

diff --git a/PrmPkg/Readme.md b/PrmPkg/Readme.md
index 52b44a95ddbc..b79cb66c4790 100644
--- a/PrmPkg/Readme.md
+++ b/PrmPkg/Readme.md
@@ -9,7 +9,7 @@ The `PrmPkg` maintained in this branch provides a single cohesive set of generic
 to be leveraged by platform firmware with minimal overhead to integrate PRM functionality in the firmware.
 
 ## **IMPORTANT NOTE**
-> The code provided  in this package and branch are for proof-of-concept purposes only. The code does not represent a
+> The code provided in this package and branch are for proof-of-concept purposes only. The code does not represent a
 formal design and is not validated at product quality. The development of this feature is shared in the edk2-staging
 branch to simplify collaboration by allowing direct code contributions and early feedback throughout its development.
 
@@ -120,6 +120,9 @@ prevent the package from being used as-is should be addressed directly in PrmPkg
 
 ## PRM Module
 
+> __*Note*__: You can find simple examples of PRM modules in the Samples directory of this package.
+> [Samples/Readme.md](PrmPkg/Samples/Readme.md) has more information.
+
 By default, the EDK II implementation of UEFI does not allow images with the subsystem type
 IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER to be built with exports. 
 
diff --git a/PrmPkg/Samples/Readme.md b/PrmPkg/Samples/Readme.md
new file mode 100644
index 000000000000..4926be243018
--- /dev/null
+++ b/PrmPkg/Samples/Readme.md
@@ -0,0 +1,263 @@
+# **Platform Runtime Mechanism Sample Modules**
+
+The PRM module samples provided here serve as focused examples of how to perform various tasks in a PRM module. The
+samples can also be used to verify the basic infrastructure needed in your firmware implementation is working as
+expected by checking that the sample modules are found properly and the handlers perform their tasks as noted.
+
+## **IMPORTANT NOTE**
+> The sample modules have currently only been tested on the Visual Studio compiler tool chain. Sample module
+build may fail on other tool chains. A future work item is to enable broader build support.
+
+## How to Build PRM Sample Modules
+The sample modules are built as part of the normal `PrmPkg` build so you can follow the
+[package build instructions](../../Readme.md#how-to-build-prmpkg) and then find the PRM sample binaries in your
+workspace build output directory. For example, if your build workspace is called "edk2" and you build
+64-bit binaries on the Visual Studio 2017 tool chain, your sample module binaries will be in the following
+location: \
+``edk2/Build/Prm/DEBUG_VS2017/X64/PrmPkg/Samples``
+
+### Build an Individual PRM Sample Module
+Note that the build command does provide the option to build a specific module in a package which can result in
+faster build time. If you would like to just build a single PRM module that can be done by specifying the path to
+the module INF file with the "-m" argument to `build`. For example, this command builds 32-bit and 64-bit binaries
+with Visual Studio 2019: \
+``build -p PrmPkg/PrmPkg.dsc -m PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf -a IA32 -a X64 -t VS2019``
+
+## PRM Sample Module User's Guide
+
+The following table provides an overview of each sample module provided. By nature, different PRM handlers have
+different requirements. The information here is summarized for a user to understand how to use a given sample
+PRM handler along with GUID/name information to identify the sample PRM modules and their PRM handlers.
+
+It is recommended that all PRM authors write a similar set of documentation for their users to better understand
+and interact with their PRM modules.
+
+---
+### Module: PRM Sample Print Module
+>* Name: `PrmSamplePrintModule`
+>* GUID: `1652b3c2-a7a1-46ac-af93-dd6dee446669`
+> * Purpose:
+>   * Simplest PRM module example
+>   * Example of a PRM module with multiple PRM handlers
+
+**Handlers:**
+#### Handler: PRM Handler 1
+* Name: `PrmHandler1`
+* GUID: `d5f2ad5f-a347-4d3e-87bc-c2ce63029cc8`
+* Actions:
+  * Use an OS-provided function pointer (pointer at the beginning of the parameter buffer) to write the message
+    “PRM1 handler sample message!”
+
+* Parameter Buffer Required: Yes
+* Parameter Buffer Contents:
+  ```c
+  typedef struct {
+
+    PRM_OS_SERVICE_DEBUG_PRINT *
+
+  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
+  ```
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: No
+
+#### Handler: PRM Handler 2
+* Name: `PrmHandler2`
+* GUID: `a9e7adc3-8cd0-429a-8915-10946ebde318`
+* Actions:
+  * Use an OS-provided function pointer (pointer at the beginning of the parameter buffer) to write the message
+    “PRM2 handler sample message!”
+
+* Parameter Buffer Required: Yes
+* Parameter Buffer Contents:
+  ```c
+  typedef struct {
+
+    PRM_OS_SERVICE_DEBUG_PRINT *
+
+  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
+  ```
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: No
+
+#### Handler: PRM Handler N
+* Name: `PrmHandlerN`
+* GUID: `b688c214-4081-4eeb-8d26-1eb5a3bcf11a`
+* Actions:
+  * Use an OS-provided function pointer (pointer at the beginning of the parameter buffer) to write the message
+    “PRMN handler sample message!”
+
+* Parameter Buffer Required: Yes
+* Parameter Buffer Contents:
+  ```c
+  typedef struct {
+
+    PRM_OS_SERVICE_DEBUG_PRINT *
+
+  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
+  ```
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: No
+
+### Module: PRM Sample ACPI Parameter Buffer
+>* Name: `PrmSampleAcpiParameterBufferModule`
+>* GUID: `dc2a58a6-5927-4776-b995-d118a27335a2`
+> * Purpose:
+>   * Provides an example of how to configure an ACPI parameter buffer
+
+**Handlers:**
+#### Handler: Check Parameter Buffer PRM Handler
+* Name: `CheckParamBufferPrmHandler`
+* GUID: `2e4f2d13-6240-4ed0-a401-c723fbdc34e8`
+* Actions:
+  * Checks for the data signature ‘T’, ‘E’, ‘S’, ‘T’ (DWORD) at the beginning of the parameter buffer.
+
+* Parameter Buffer Required: Yes
+* Parameter Buffer Contents:
+  * A data signature of ['T', 'E', 'S', 'T'] (DWORD) at the beginning of the buffer.
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: No
+
+### Module: PRM Sample Context Buffer
+>* Name: `PrmSampleContextBufferModule`
+>* GUID: `5a6cf42b-8bb4-472c-a233-5c4dc4033dc7`
+> * Purpose:
+>   * Provides an example of how to configure a static data buffer (which is pointed to in a context buffer) in
+      firmware and consume the buffer contents at runtime
+
+**Handlers:**
+#### Handler: Check Static Data Buffer PRM Handler
+* Name: `CheckStaticDataBufferPrmHandler`
+* GUID: `e1466081-7562-430f-896b-b0e523dc335a`
+* Actions:
+  * Checks that the context buffer signature and static data buffer signature match in the context buffer provided.
+
+* Parameter Buffer Required: No
+
+* Context Buffer Required: Yes
+  * Static Data Buffer Contents:
+  ```c
+  #define   SOME_VALUE_ARRAY_MAX_VALUES   16
+
+  typedef struct {
+    BOOLEAN       Policy1Enabled;
+    BOOLEAN       Policy2Enabled;
+    UINT8         SomeValueArray[SOME_VALUE_ARRAY_MAX_VALUES];
+  } STATIC_DATA_SAMPLE_CONTEXT_BUFFER_MODULE;
+  ```
+
+* Runtime MMIO Range(s) Required: No
+
+### Module: PRM Sample Hardware Access Buffer
+>* Name: `PrmSampleHardwareAccessModule`
+>* GUID: `0ef93ed7-14ae-425b-928f-b85a6213b57e`
+> * Purpose:
+>   * Demonstrate access of several types of hardware resources from a PRM module
+
+**Handlers:**
+#### Handler: MSR Access Microcode Signature PRM Handler
+* Name: `MsrAccessMicrocodeSignaturePrmHandler`
+* GUID: `2120cd3c-848b-4d8f-abbb-4b74ce64ac89`
+* Actions:
+  * Access the loaded microcode signature at MSR 0x8B.
+
+* Parameter Buffer Required: No
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: No
+
+#### Handler: MSR Access MTRR Dump PRM Handler
+* Name: `MsrAccessMtrrDumpPrmHandler`
+* GUID: `ea0935a7-506b-4159-bbbb-48deeecb6f58`
+* Actions:
+  * Access the fixed and variable MTRR values using MSRs.
+
+* Parameter Buffer Required: No
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: No
+
+#### Handler: HPET MMIO Access PRM Handler
+* Name: `MmioAccessHpetPrmHandler`
+* GUID: `1bd1bda9-909a-4614-9699-25ec0c2783f7`
+* Actions:
+  * Access some HPET registers using MMIO at 0xFED00000.
+
+* Parameter Buffer Required: No
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: Yes
+  * Physical Base Address: 0xFED00000
+  * Length: 0x1000
+
+#### Handler: MSR Print Microcode Signature PRM Handler
+* Name: `MsrPrintMicrocodeSignaturePrmHandler`
+* GUID: `5d28b4e7-3867-4aee-aa09-51fc282c3b22`
+* Actions:
+  * Use the provided print function to print the loaded microcode signature at MSR 0x8B.
+
+* Parameter Buffer Required: Yes
+* Parameter Buffer Contents:
+  ```c
+  typedef struct {
+
+    PRM_OS_SERVICE_DEBUG_PRINT *
+
+  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
+  ```
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: No
+
+#### Handler: MSR Print MTRR Dump PRM Handler
+* Name: `MsrPrintMtrrDumpPrmHandler`
+* GUID: `4b64b702-4d2b-4dfe-ac5a-0b4110a2ca47`
+* Actions:
+  * Use the provided print function to print the fixed and variable MTRR values using MSRs.
+
+* Parameter Buffer Required: Yes
+* Parameter Buffer Contents:
+  ```c
+  typedef struct {
+
+    PRM_OS_SERVICE_DEBUG_PRINT *
+
+  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
+  ```
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: No
+
+#### Handler: HPET MMIO Print PRM Handler
+* Name: `MmioPrintHpetPrmHandler`
+* GUID: `8a0efdde-78d0-45f0-aea0-c28245c7e1db`
+* Actions:
+  * Use the provided print function to print some HPET registers using MMIO at 0xFED00000.
+
+* Parameter Buffer Required: Yes
+* Parameter Buffer Contents:
+  ```c
+  typedef struct {
+
+    PRM_OS_SERVICE_DEBUG_PRINT *
+
+  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
+  ```
+
+* Context Buffer Required: No
+
+* Runtime MMIO Range(s) Required: Yes
+  * Physical Base Address: 0xFED00000
+  * Length: 0x1000
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 25/41] PrmPkg: Refactor some PrmLoaderDxe functionality into libraries
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (23 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 24/41] PrmPkg/Samples/Readme.md: Add initial file Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 26/41] PrmPkg/Application/PrmInfo: Add initial application Michael Kubacki
                   ` (15 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

This change breaks out two sets of responsibilities in
PrmLoaderDxe into libraries:
  * PE/COFF functions -> PrmPeCoffLib
  * PRM module discovery functions -> PrmModuleDiscoveryLib

This is core infrastructure code for PRM functionality that needs
to be directly reused and tested in other places. At this time,
the primary motivating factor is to use this code in two other
locations:
  1.) Link the functionality into unit testing modules
  2.) Link the functionality into a PRM UEFI application

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>
---
 PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c   | 382 +++++++++++++
 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c                     | 411 ++++++++++++++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c                                   | 600 +-------------------
 PrmPkg/Include/Library/PrmModuleDiscoveryLib.h                       |  60 ++
 PrmPkg/Include/Library/PrmPeCoffLib.h                                | 111 ++++
 PrmPkg/Include/PrmModuleImageContext.h                               |  28 +
 PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf |  41 ++
 PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h         |  27 +
 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf                   |  32 ++
 PrmPkg/PrmLoaderDxe/PrmLoader.h                                      |  51 --
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf                                 |   5 +-
 PrmPkg/PrmPkg.dec                                                    |   8 +
 PrmPkg/PrmPkg.dsc                                                    |  13 +
 13 files changed, 1133 insertions(+), 636 deletions(-)

diff --git a/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c b/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
new file mode 100644
index 000000000000..6977799aa8f3
--- /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/DxePrmPeCoffLib/DxePrmPeCoffLib.c b/PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
new file mode 100644
index 000000000000..d760d137dc2b
--- /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/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index 6416e388a668..407c48257432 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/Include/Library/PrmModuleDiscoveryLib.h b/PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
new file mode 100644
index 000000000000..fe3a42586afa
--- /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 000000000000..4698a9477699
--- /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 000000000000..10146a272b6f
--- /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.inf b/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
new file mode 100644
index 000000000000..1115df3a3446
--- /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 000000000000..79058d15317e
--- /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.inf b/PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
new file mode 100644
index 000000000000..f139d5380b98
--- /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 1356c7a0c923..000000000000
--- 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.inf b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
index 4d959ccd35a3..554d49685e2a 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
@@ -22,7 +22,6 @@ [Defines]
 
 [Sources]
   PrmAcpiTable.h
-  PrmLoader.h
   PrmLoaderDxe.c
 
 [Packages]
@@ -39,8 +38,9 @@ [LibraryClasses]
   DebugLib
   MemoryAllocationLib
   PcdLib
-  PeCoffLib
   PrmContextBufferLib
+  PrmModuleDiscoveryLib
+  PrmPeCoffLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
@@ -54,7 +54,6 @@ [Pcd]
 
 [Protocols]
   gEfiAcpiTableProtocolGuid
-  gEfiLoadedImageProtocolGuid
   gPrmConfigProtocolGuid
 
 [Depex]
diff --git a/PrmPkg/PrmPkg.dec b/PrmPkg/PrmPkg.dec
index ff681d423d30..785e2c24c2f9 100644
--- a/PrmPkg/PrmPkg.dec
+++ b/PrmPkg/PrmPkg.dec
@@ -36,6 +36,14 @@ [LibraryClasses]
   #
   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 19b996eb3a02..e876f2053a8e 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -55,6 +55,9 @@ [LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER]
   # PRM Package
   #
   PrmContextBufferLib|$(PLATFORM_PACKAGE)/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
+  PrmModuleDiscoveryLib|$(PLATFORM_PACKAGE)/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
+  PrmPeCoffLib|$(PLATFORM_PACKAGE)/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
+
 
 ###################################################################################################
 #
@@ -72,6 +75,16 @@ [Components]
   $(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
   $(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
   #
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 26/41] PrmPkg/Application/PrmInfo: Add initial application
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (24 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 25/41] PrmPkg: Refactor some PrmLoaderDxe functionality into libraries Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 27/41] PrmPkg: Enforce stricter types Michael Kubacki
                   ` (14 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a new UEFI application called "PrmInfo" that allows a user
to display and test Platform Runtime Mechanism (PRM) modules.

Execute the application help command for detailed usage
instructions and examples of how to use the application:
  "PrmInfo -?"

This application is intended to be helpful during PRM enabling
by allowing the user to:

1. Confirm that their firmware port of the PRM infrastructure
   implemented in this package is functioning correctly.

2. Quickly get information about what PRM modules and handlers
   are present on a given system.

3. Quickly test PRM handlers without booting to a fully featured
   operating system.

4. Develop and exercise PRM handlers prior to the availability of
   an operating system that is PRM aware.

Adds a brief section to Readme.md about the PrmInfo UEFI application
with a link to allow the reader to find more information about the
application if interested.

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>
---
 PrmPkg/Application/PrmInfo/PrmInfo.c          | 725 ++++++++++++++++++++
 PrmPkg/Application/PrmInfo/PrmInfo.h          |  49 ++
 PrmPkg/Application/PrmInfo/PrmInfo.inf        |  66 ++
 PrmPkg/Application/PrmInfo/PrmInfo.uni        |  11 +
 PrmPkg/Application/PrmInfo/PrmInfoExtra.uni   |  12 +
 PrmPkg/Application/PrmInfo/PrmInfoStrings.uni | 132 ++++
 PrmPkg/PrmPkg.dec                             |  10 +
 PrmPkg/PrmPkg.dsc                             |  28 +-
 PrmPkg/Readme.md                              |  19 +
 9 files changed, 1050 insertions(+), 2 deletions(-)

diff --git a/PrmPkg/Application/PrmInfo/PrmInfo.c b/PrmPkg/Application/PrmInfo/PrmInfo.c
new file mode 100644
index 000000000000..431a6f206163
--- /dev/null
+++ b/PrmPkg/Application/PrmInfo/PrmInfo.c
@@ -0,0 +1,725 @@
+/** @file
+  Prints information about the PRM configuration loaded by the system firmware.
+
+  This application also provides some additional testing features for PRM configuration. For example,
+  the application can be used to selectively invoke PRM handlers in the UEFI shell environment to
+  provide a quick testing path of the PRM infrastructure on the firmware and the PRM module implementation.
+
+  This can also be useful to prepare a PRM enabled firmware and PRM modules prior to formal OS support to
+  test the PRM code.
+
+  Copyright (C) Microsoft Corporation. All rights reserved.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/ZeroGuid.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrmContextBufferLib.h>
+#include <Library/PrmModuleDiscoveryLib.h>
+#include <Library/PrmPeCoffLib.h>
+#include <Library/ShellLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/UefiLib.h>
+
+#include "PrmInfo.h"
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringPrmInfoHelpTokenId = STRING_TOKEN (STR_PRMINFO_HELP);
+//
+// This is the generated String package data for all .UNI files.
+// This data array is ready to be used as input of HiiAddPackages() to
+// create a packagelist (which contains Form packages, String packages, etc).
+//
+extern UINT8                PrmInfoStrings[];
+
+STATIC UINTN                mPrmHandlerCount;
+STATIC UINTN                mPrmModuleCount;
+
+STATIC EFI_HII_HANDLE       mPrmInfoHiiHandle;
+STATIC LIST_ENTRY           mPrmHandlerList;
+
+STATIC CONST SHELL_PARAM_ITEM mParamList[] = {
+  {L"-l", TypeFlag},
+  {L"-t", TypeValue},
+  {NULL, TypeMax}
+  };
+
+/**
+  Frees all of the nodes in a linked list.
+
+  @param[in] ListHead                   A pointer to the head of the list that should be freed.
+
+  **/
+VOID
+EFIAPI
+FreeList (
+  IN LIST_ENTRY                         *ListHead
+  )
+{
+  LIST_ENTRY                            *Link;
+  LIST_ENTRY                            *NextLink;
+  PRM_HANDLER_CONTEXT_LIST_ENTRY        *ListEntry;
+
+  if (ListHead == NULL) {
+    return;
+  }
+
+  Link = GetFirstNode (&mPrmHandlerList);
+  while (!IsNull (&mPrmHandlerList, Link)) {
+    ListEntry = CR (Link, PRM_HANDLER_CONTEXT_LIST_ENTRY, Link, PRM_HANDLER_CONTEXT_LIST_ENTRY_SIGNATURE);
+    NextLink = GetNextNode (&mPrmHandlerList, Link);
+
+    RemoveEntryList (Link);
+    FreePool (ListEntry);
+
+    Link = NextLink;
+  }
+}
+
+/**
+  Creates a new PRM Module Image Context linked list entry.
+
+  @retval    PrmHandlerContextListEntry If successful, a pointer a PRM Handler Context linked list entry
+                                        otherwise, NULL is returned.
+
+**/
+PRM_HANDLER_CONTEXT_LIST_ENTRY *
+CreateNewPrmHandlerListEntry (
+  VOID
+  )
+{
+  PRM_HANDLER_CONTEXT_LIST_ENTRY        *PrmHandlerContextListEntry;
+
+  PrmHandlerContextListEntry = AllocateZeroPool (sizeof (*PrmHandlerContextListEntry));
+  if (PrmHandlerContextListEntry == NULL) {
+    return NULL;
+  }
+  PrmHandlerContextListEntry->Signature = PRM_HANDLER_CONTEXT_LIST_ENTRY_SIGNATURE;
+
+  return PrmHandlerContextListEntry;
+}
+
+/**
+  Creates a new PRM Module Image Context linked list entry.
+
+  @param[in]  RuntimeMmioRanges  A pointer to an array of PRM module config runtime MMIO ranges.
+
+**/
+VOID
+PrintMmioRuntimeRangeInfo (
+  IN PRM_RUNTIME_MMIO_RANGES  *RuntimeMmioRanges
+  )
+{
+  UINTN RuntimeMmioRangeCount;
+  UINTN RuntimeMmioRangeIndex;
+
+  if (RuntimeMmioRanges == NULL) {
+    return;
+  }
+
+  RuntimeMmioRangeCount = (UINTN) RuntimeMmioRanges->Count;
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_RUNTIME_MMIO_COUNT), mPrmInfoHiiHandle, RuntimeMmioRangeCount);
+
+  for (RuntimeMmioRangeIndex = 0; RuntimeMmioRangeIndex < RuntimeMmioRangeCount; RuntimeMmioRangeIndex++) {
+    ShellPrintHiiEx (
+      -1,
+      -1,
+      NULL,
+      STRING_TOKEN (STR_PRMINFO_RUNTIME_MMIO_INFO),
+      mPrmInfoHiiHandle,
+      RuntimeMmioRangeIndex,
+      RuntimeMmioRanges->Range[RuntimeMmioRangeIndex].PhysicalBaseAddress,
+      RuntimeMmioRanges->Range[RuntimeMmioRangeIndex].VirtualBaseAddress,
+      RuntimeMmioRanges->Range[RuntimeMmioRangeIndex].Length
+      );
+  }
+}
+
+/**
+  Gathers the PRM handler (and by extension module) information discovered on this system.
+
+  This function must be called to build up the discovered context for other functions in the application. The
+  function will optionally print results as determed by the value of the PrintInformation parameter.
+
+  @param[in] PrintInformation           Indicates whether to print information as discovered in the function.
+
+**/
+VOID
+GatherPrmHandlerInfo (
+  IN  BOOLEAN                           PrintInformation
+  )
+{
+  EFI_STATUS                            Status;
+  UINT16                                MajorVersion;
+  UINT16                                MinorVersion;
+  UINT16                                HandlerCount;
+  UINTN                                 HandlerIndex;
+  EFI_PHYSICAL_ADDRESS                  CurrentHandlerPhysicalAddress;
+  EFI_PHYSICAL_ADDRESS                  CurrentImageAddress;
+  PRM_HANDLER_CONTEXT                   CurrentHandlerContext;
+  EFI_GUID                              *CurrentModuleGuid;
+  EFI_IMAGE_EXPORT_DIRECTORY            *CurrentImageExportDirectory;
+  PRM_CONTEXT_BUFFER                    *CurrentContextBuffer;
+  PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT   *CurrentExportDescriptorStruct;
+  PRM_MODULE_CONTEXT_BUFFERS            *CurrentModuleContextBuffers;
+  PRM_HANDLER_CONTEXT_LIST_ENTRY        *CurrentHandlerContextListEntry;
+  PRM_MODULE_IMAGE_CONTEXT              *CurrentPrmModuleImageContext;
+  PRM_RUNTIME_MMIO_RANGES               *CurrentPrmModuleRuntimeMmioRanges;
+
+  ASSERT (mPrmModuleCount <= mPrmHandlerCount);
+
+  if (mPrmHandlerCount == 0) {
+    return;
+  }
+
+  // Iterate across all PRM modules discovered
+  for (
+    CurrentPrmModuleImageContext = NULL, Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext);
+    !EFI_ERROR (Status);
+    Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext)) {
+
+    CurrentImageAddress = CurrentPrmModuleImageContext->PeCoffImageContext.ImageAddress;
+    CurrentImageExportDirectory = CurrentPrmModuleImageContext->ExportDirectory;
+    CurrentExportDescriptorStruct = CurrentPrmModuleImageContext->ExportDescriptor;
+
+    CurrentModuleGuid = &CurrentExportDescriptorStruct->Header.ModuleGuid;
+    HandlerCount = CurrentExportDescriptorStruct->Header.NumberPrmHandlers;
+
+    MajorVersion = 0;
+    MinorVersion = 0;
+    Status =  GetImageVersionInPeCoffImage (
+                (VOID *) (UINTN) CurrentImageAddress,
+                &CurrentPrmModuleImageContext->PeCoffImageContext,
+                &MajorVersion,
+                &MinorVersion
+                );
+    ASSERT_EFI_ERROR (Status);
+
+    if (PrintInformation) {
+      ShellPrintHiiEx (
+        -1,
+        -1,
+        NULL,
+        STRING_TOKEN (STR_PRMINFO_MODULE_NAME),
+        mPrmInfoHiiHandle,
+        (CHAR8 *) ((UINTN) CurrentImageAddress + CurrentImageExportDirectory->Name)
+        );
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_MODULE_GUID), mPrmInfoHiiHandle, CurrentModuleGuid);
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_MODULE_VERSION), mPrmInfoHiiHandle, MajorVersion, MinorVersion);
+    }
+
+    // It is currently valid for a PRM module not to use a context buffer
+    CurrentPrmModuleRuntimeMmioRanges = NULL;
+    Status = GetModuleContextBuffers (
+              ByModuleGuid,
+              CurrentModuleGuid,
+              &CurrentModuleContextBuffers
+              );
+    ASSERT (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND);
+    if (!EFI_ERROR (Status) && CurrentModuleContextBuffers != NULL) {
+      CurrentPrmModuleRuntimeMmioRanges = CurrentModuleContextBuffers->RuntimeMmioRanges;
+    }
+
+    if (PrintInformation) {
+      if (CurrentPrmModuleRuntimeMmioRanges != NULL) {
+        PrintMmioRuntimeRangeInfo (CurrentPrmModuleRuntimeMmioRanges);
+      } else {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_MMIO_RANGES), mPrmInfoHiiHandle);
+      }
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_COUNT), mPrmInfoHiiHandle, HandlerCount);
+    }
+
+    for (HandlerIndex = 0; HandlerIndex < HandlerCount; HandlerIndex++) {
+      ZeroMem (&CurrentHandlerContext, sizeof (CurrentHandlerContext));
+
+      CurrentHandlerContext.ModuleName = (CHAR8 *) ((UINTN) CurrentImageAddress + CurrentImageExportDirectory->Name);
+      CurrentHandlerContext.Guid = &CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerGuid;
+      CurrentHandlerContext.Name = (CHAR8 *) CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerName;
+
+      if (PrintInformation) {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_NAME), mPrmInfoHiiHandle, CurrentHandlerContext.Name);
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_GUID), mPrmInfoHiiHandle, CurrentHandlerContext.Guid);
+      }
+
+      Status =  GetExportEntryAddress (
+                  CurrentHandlerContext.Name,
+                  CurrentImageAddress,
+                  CurrentImageExportDirectory,
+                  &CurrentHandlerPhysicalAddress
+                  );
+      ASSERT_EFI_ERROR (Status);
+      if (!EFI_ERROR (Status)) {
+        CurrentHandlerContext.Handler = (PRM_HANDLER *) (UINTN) CurrentHandlerPhysicalAddress;
+
+        if (PrintInformation) {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_PA), mPrmInfoHiiHandle, CurrentHandlerPhysicalAddress);
+        }
+      } else {
+        if (PrintInformation) {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_PA_ERROR), mPrmInfoHiiHandle, Status);
+        }
+      }
+
+      Status =  GetContextBuffer (
+                  CurrentHandlerContext.Guid,
+                  CurrentModuleContextBuffers,
+                  &CurrentContextBuffer
+                  );
+      if (!EFI_ERROR (Status)) {
+        CurrentHandlerContext.StaticDataBuffer = CurrentContextBuffer->StaticDataBuffer;
+      }
+
+      if (PrintInformation) {
+        if (CurrentHandlerContext.StaticDataBuffer != NULL) {
+          ShellPrintHiiEx (
+            -1,
+            -1,
+            NULL,
+            STRING_TOKEN (STR_PRMINFO_STATIC_DATA_BUFFER),
+            mPrmInfoHiiHandle,
+            (UINTN) CurrentHandlerContext.StaticDataBuffer
+            );
+        } else {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_STATIC_BUFFER), mPrmInfoHiiHandle);
+        }
+      }
+
+      CurrentHandlerContextListEntry = CreateNewPrmHandlerListEntry ();
+      ASSERT (CurrentHandlerContextListEntry != NULL);
+      if (CurrentHandlerContextListEntry != NULL) {
+        CopyMem (
+          &CurrentHandlerContextListEntry->Context,
+          &CurrentHandlerContext,
+          sizeof (CurrentHandlerContextListEntry->Context)
+          );
+        InsertTailList (&mPrmHandlerList, &CurrentHandlerContextListEntry->Link);
+      }
+    }
+  }
+}
+
+/**
+  Populates the given context buffer so it can be passed to a PRM handler.
+
+  @param[in] StaticDataBuffer           A pointer to the static data buffer that will be referenced in the context
+                                        buffer that is populated. This is an optional pointer that, if not provided,
+                                        by passing NULL will be ignored.
+  @param[in] HandlerGuid                A pointer to the GUID of the PRM handler.
+  @param[in] ContextBuffer              A pointer to a caller allocated ContextBuffer structure that will be populated
+                                        by this function.
+
+  @retval EFI_SUCCESS                   The given ContextBuffer was populated successfully.
+  @retval EFI_INVALID_PARAMETER         The HandlerGuid or ContextBuffer actual argument is NULL.
+
+**/
+EFI_STATUS
+PopulateContextBuffer (
+  IN  PRM_DATA_BUFFER                   *StaticDataBuffer OPTIONAL,
+  IN  EFI_GUID                          *HandlerGuid,
+  IN  PRM_CONTEXT_BUFFER                *ContextBuffer
+  )
+{
+  if (HandlerGuid == NULL || ContextBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (ContextBuffer, sizeof (*ContextBuffer));
+
+  ContextBuffer->Signature = PRM_CONTEXT_BUFFER_SIGNATURE;
+  ContextBuffer->Version = PRM_CONTEXT_BUFFER_INTERFACE_VERSION;
+  CopyGuid (&ContextBuffer->HandlerGuid, HandlerGuid);
+
+  if (StaticDataBuffer != NULL) {
+    ContextBuffer->StaticDataBuffer = StaticDataBuffer;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Prints a given execution time in the appropriate unit.
+
+  @param[in] TimeInNanoSec              The time to print in unit of nanoseconds.
+
+**/
+VOID
+PrintExecutionTime (
+  IN  UINT64                            TimeInNanoSec
+  )
+{
+  UINT64  Sec;
+  UINT64  MilliSec;
+  UINT64  MicroSec;
+  UINT64  NanoSec;
+  UINT64  RemainingTime;
+
+  Sec = 0;
+  MilliSec = 0;
+  MicroSec = 0;
+  NanoSec = 0;
+  RemainingTime = TimeInNanoSec;
+
+  if (RemainingTime > ONE_SECOND)  {
+    Sec = DivU64x32 (RemainingTime, ONE_SECOND);
+    RemainingTime -= MultU64x32 (Sec, ONE_SECOND);
+  }
+
+  if (RemainingTime > ONE_MILLISECOND) {
+    MilliSec = DivU64x32 (RemainingTime, ONE_MILLISECOND);
+    RemainingTime -= MultU64x32 (MilliSec, ONE_MILLISECOND);
+  }
+
+  if (RemainingTime > ONE_MICROSECOND) {
+    MicroSec = DivU64x32 (RemainingTime, ONE_MICROSECOND);
+    RemainingTime -= MultU64x32 (MicroSec, ONE_MICROSECOND);
+  }
+
+  if (RemainingTime > 0) {
+    NanoSec = RemainingTime;
+  }
+
+  if (Sec > 0) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_SECS), mPrmInfoHiiHandle, Sec, MilliSec, MicroSec, NanoSec);
+  } else if (MilliSec > 0) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_MILLI_SECS), mPrmInfoHiiHandle, MilliSec, MicroSec, NanoSec);
+  } else if (MicroSec > 0) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_USECS), mPrmInfoHiiHandle, MicroSec, NanoSec);
+  } else {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NANO_SECS), mPrmInfoHiiHandle, NanoSec);
+  }
+}
+
+/**
+  Executes the PRM handler with the provided GUID.
+
+  @param[in] HandlerGuid                A pointer to the GUID of the PRM handler to execute.
+                                        A zero GUID indicates that all PRM handlers present should be executed.
+
+  @retval EFI_SUCCESS                   The PRM handler(s) were executed.
+  @retval EFI_INVALID_PARAMETER         The HandlerGuid actual argument is NULL.
+  @retval EFI_NOT_FOUND                 The PRM handler could not be found.
+
+**/
+EFI_STATUS
+ExecutePrmHandlerByGuid (
+  IN  EFI_GUID                          *HandlerGuid
+  )
+{
+  EFI_STATUS                            Status;
+  BOOLEAN                               ExecuteAllHandlers;
+  BOOLEAN                               HandlerFound;
+  UINT64                                StartTime;
+  UINT64                                EndTime;
+  PRM_CONTEXT_BUFFER                    CurrentContextBuffer;
+  PRM_HANDLER_CONTEXT                   *HandlerContext;
+  PRM_HANDLER_CONTEXT_LIST_ENTRY        *HandlerContextListEntry;
+  LIST_ENTRY                            *Link;
+
+  Link = NULL;
+  HandlerFound = FALSE;
+
+  if (HandlerGuid == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Zero GUID means execute all discovered handlers
+  //
+  ExecuteAllHandlers = CompareGuid (HandlerGuid, &gZeroGuid);
+
+  EFI_LIST_FOR_EACH (Link, &mPrmHandlerList) {
+    HandlerContextListEntry = CR (Link, PRM_HANDLER_CONTEXT_LIST_ENTRY, Link, PRM_HANDLER_CONTEXT_LIST_ENTRY_SIGNATURE);
+    HandlerContext = &HandlerContextListEntry->Context;
+
+    if (!ExecuteAllHandlers && !CompareGuid (HandlerGuid, HandlerContext->Guid)) {
+      continue;
+    }
+
+    HandlerFound = TRUE;
+    Status = PopulateContextBuffer (HandlerContext->StaticDataBuffer, HandlerContext->Guid, &CurrentContextBuffer);
+    if (!EFI_ERROR (Status)) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);
+      ShellPrintHiiEx (
+        -1,
+        -1,
+        NULL,
+        STRING_TOKEN (STR_PRMINFO_MODULE_NAME),
+        mPrmInfoHiiHandle,
+        HandlerContext->ModuleName
+        );
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_NAME_HL), mPrmInfoHiiHandle, HandlerContext->Name);
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_GUID), mPrmInfoHiiHandle, HandlerContext->Guid);
+
+      StartTime = 0;
+      EndTime = 0;
+      if (PcdGetBool (PcdPrmInfoPrintHandlerExecutionTime)) {
+        StartTime = GetPerformanceCounter ();
+      }
+      Status = HandlerContext->Handler (NULL, &CurrentContextBuffer);
+      if (PcdGetBool (PcdPrmInfoPrintHandlerExecutionTime)) {
+        EndTime = GetPerformanceCounter ();
+      }
+
+      if (EFI_ERROR (Status)) {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_ERR_STATUS), mPrmInfoHiiHandle, Status);
+      } else {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_SUCC_STATUS), mPrmInfoHiiHandle, Status);
+      }
+
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_EXEC_TIME), mPrmInfoHiiHandle);
+      if (StartTime == 0 && EndTime == 0) {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_UNKNOWN), mPrmInfoHiiHandle);
+      } else {
+        PrintExecutionTime (GetTimeInNanoSecond (EndTime - StartTime));
+      }
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);
+    } else {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a - %a: An error occurred creating a context buffer for handler %g\n",
+        gEfiCallerBaseName,
+        __FUNCTION__,
+        HandlerContext->Guid
+        ));
+    }
+
+    if (!ExecuteAllHandlers) {
+      break;
+    }
+  }
+
+  if (!HandlerFound) {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Parses the application parameter list and performs the appropriate operations based on the results.
+
+  @retval EFI_SUCCESS                   The parameter list was parsed successfully.
+  @retval EFI_INVALID_PARAMETER         An invalid parameter was given to the application.
+  @retval EFI_LOAD_ERROR                An error occurred loading the application.
+
+**/
+EFI_STATUS
+ParseParameterList (
+  VOID
+  )
+{
+  EFI_STATUS                            Status;
+  SHELL_STATUS                          ReturnStatus;
+  UINTN                                 ArgumentCount;
+  EFI_GUID                              HandlerGuid;
+  BOOLEAN                               PrintHandlerInfo;
+  LIST_ENTRY                            *Package;
+  LIST_ENTRY                            *TempNode;
+  CHAR16                                *ProblemParam;
+  CONST CHAR16                          *HandlerGuidStr;
+
+  HandlerGuidStr = NULL;
+  Package = NULL;
+  PrintHandlerInfo = FALSE;
+  ReturnStatus = EFI_SUCCESS;
+
+  InitializeListHead (&mPrmHandlerList);
+
+  //
+  // Basic application parameter validation
+  //
+  Status = ShellCommandLineParseEx (mParamList, &Package, &ProblemParam, FALSE, FALSE);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_GEN_PROBLEM), mPrmInfoHiiHandle, APPLICATION_NAME, ProblemParam);
+      ReturnStatus = EFI_INVALID_PARAMETER;
+      FreePool (ProblemParam);
+    } else {
+      ReturnStatus = EFI_LOAD_ERROR;
+      ASSERT (FALSE);
+    }
+
+    goto Done;
+  } else if (Package == NULL) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_ARG), mPrmInfoHiiHandle, APPLICATION_NAME);
+    ReturnStatus = EFI_INVALID_PARAMETER;
+    goto Done;
+  }
+
+  //
+  // Get argument count including flags
+  //
+  for (
+    ArgumentCount = 0, TempNode = Package;
+    GetNextNode (Package, TempNode) != Package;
+    ArgumentCount++, TempNode = GetNextNode (Package, TempNode)
+    );
+
+  if (ArgumentCount == 1) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_ARG), mPrmInfoHiiHandle, APPLICATION_NAME);
+    ReturnStatus = EFI_INVALID_PARAMETER;
+    goto Done;
+  }
+
+  if (ArgumentCount > 6) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_TOO_MANY), mPrmInfoHiiHandle, APPLICATION_NAME);
+    ReturnStatus = EFI_INVALID_PARAMETER;
+    goto Done;
+  }
+
+  //
+  // Parse the actual arguments provided
+  //
+  if (ShellCommandLineGetFlag (Package, L"-b")) {
+    if (ArgumentCount <= 2) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_PARAM_INV), mPrmInfoHiiHandle, APPLICATION_NAME, L"-b");
+      ReturnStatus = EFI_INVALID_PARAMETER;
+      goto Done;
+    } else {
+      ShellSetPageBreakMode (TRUE);
+    }
+  }
+
+  if (ShellCommandLineGetFlag (Package, L"-l")) {
+    PrintHandlerInfo = TRUE;
+  }
+
+  if (ShellCommandLineGetFlag (Package, L"-t")) {
+    HandlerGuidStr = ShellCommandLineGetValue (Package, L"-t");
+    if (HandlerGuidStr != NULL) {
+      if (StrnCmp (HandlerGuidStr, L"all", StrLen (HandlerGuidStr)) == 0) {
+        CopyGuid (&HandlerGuid, &gZeroGuid);
+      } else {
+        Status = StrToGuid (HandlerGuidStr, &HandlerGuid);
+        if (EFI_ERROR (Status) || (HandlerGuidStr[GUID_STRING_LENGTH] != L'\0')) {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_GUID_INV), mPrmInfoHiiHandle, APPLICATION_NAME, HandlerGuidStr);
+          ReturnStatus = EFI_INVALID_PARAMETER;
+          goto Done;
+        }
+      }
+    } else {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_NO_VALUE), mPrmInfoHiiHandle, APPLICATION_NAME, L"-t");
+      ReturnStatus = EFI_INVALID_PARAMETER;
+      goto Done;
+    }
+  }
+
+  Status = DiscoverPrmModules (&mPrmModuleCount, &mPrmHandlerCount);
+  if (EFI_ERROR (Status)) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_DISCOVERY_FAILED), mPrmInfoHiiHandle, APPLICATION_NAME);
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a - %a: An error occurred during PRM module discovery (%r)\n",
+      gEfiCallerBaseName,
+      __FUNCTION__,
+      Status
+      ));
+    ReturnStatus = Status;
+    goto Done;
+  }
+
+  if (PrintHandlerInfo) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LIST_TITLE), mPrmInfoHiiHandle);
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_MODULES_FOUND), mPrmInfoHiiHandle, mPrmModuleCount);
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLERS_FOUND), mPrmInfoHiiHandle, mPrmHandlerCount);
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_LINE_BREAK), mPrmInfoHiiHandle);
+  }
+  GatherPrmHandlerInfo (PrintHandlerInfo);
+
+  if (HandlerGuidStr != NULL) {
+      Status = ExecutePrmHandlerByGuid (&HandlerGuid);
+      if (Status == EFI_NOT_FOUND) {
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PRMINFO_HANDLER_NOT_FOUND), mPrmInfoHiiHandle, APPLICATION_NAME, HandlerGuid);
+      }
+  }
+
+Done:
+  FreeList (&mPrmHandlerList);
+
+  if (Package != NULL) {
+    ShellCommandLineFreeVarList (Package);
+  }
+
+  return ReturnStatus;
+}
+
+/**
+  Entry point of this UEFI application.
+
+  @param[in] ImageHandle                The firmware allocated handle for the EFI image.
+  @param[in] SystemTable                A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS                   The entry point is executed successfully.
+  @retval other                         Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_HII_PACKAGE_LIST_HEADER   *PackageList;
+
+  //
+  // Retrieve the HII package list from ImageHandle
+  //
+  Status = gBS->OpenProtocol (
+                  ImageHandle,
+                  &gEfiHiiPackageListProtocolGuid,
+                  (VOID **) &PackageList,
+                  ImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Publish the HII package list to the HII Database
+  //
+  Status =  gHiiDatabase->NewPackageList (
+                            gHiiDatabase,
+                            PackageList,
+                            NULL,
+                            &mPrmInfoHiiHandle
+                            );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (mPrmInfoHiiHandle == NULL) {
+    return EFI_SUCCESS;
+  }
+
+  Status = ParseParameterList ();
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a - %a: An error occurred parsing user-provided arguments (%r)\n",
+      gEfiCallerBaseName,
+      __FUNCTION__,
+      Status
+      ));
+  }
+
+  if (mPrmInfoHiiHandle != NULL) {
+    HiiRemovePackages (mPrmInfoHiiHandle);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/Application/PrmInfo/PrmInfo.h b/PrmPkg/Application/PrmInfo/PrmInfo.h
new file mode 100644
index 000000000000..c2c3fa2f23fc
--- /dev/null
+++ b/PrmPkg/Application/PrmInfo/PrmInfo.h
@@ -0,0 +1,49 @@
+/** @file
+  Prints information about the PRM configuration loaded by the system firmware.
+
+  Copyright (C) Microsoft Corporation. All rights reserved.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PRM_INFO_H_
+#define PRM_INFO_H_
+
+#include <Base.h>
+#include <Prm.h>
+#include <PrmDataBuffer.h>
+#include <Uefi.h>
+
+#define  APPLICATION_NAME   L"PrmInfo"
+
+#define PRM_HANDLER_CONTEXT_LIST_ENTRY_SIGNATURE SIGNATURE_32('P','R','H','E')
+
+#pragma pack(push, 1)
+
+typedef struct {
+  CHAR8                     *Name;
+  EFI_GUID                  *Guid;
+  PRM_DATA_BUFFER           *StaticDataBuffer;
+  CHAR8                     *ModuleName;
+  PRM_HANDLER               *Handler;
+} PRM_HANDLER_CONTEXT;
+
+typedef struct {
+  UINTN                     Signature;
+  LIST_ENTRY                Link;
+  PRM_HANDLER_CONTEXT       Context;
+} PRM_HANDLER_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)
+
+#define ONE_MICROSECOND (1000)
+#define ONE_MILLISECOND (1000 * ONE_MICROSECOND)
+#define ONE_SECOND      (1000 * ONE_MILLISECOND)
+
+#endif
diff --git a/PrmPkg/Application/PrmInfo/PrmInfo.inf b/PrmPkg/Application/PrmInfo/PrmInfo.inf
new file mode 100644
index 000000000000..df8fb9ccc0db
--- /dev/null
+++ b/PrmPkg/Application/PrmInfo/PrmInfo.inf
@@ -0,0 +1,66 @@
+## @file
+# PrmInfo.inf
+#
+# Reports information about the PRM configuration currently loaded on the system.
+#
+# Copyright (C) Microsoft Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = PrmInfo
+  FILE_GUID                      = F26C503B-BD8E-4274-A80B-2C4E20FADA6E
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = UefiMain
+  UEFI_HII_RESOURCE_SECTION      = TRUE
+  MODULE_UNI_FILE                = PrmInfo.uni
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+  PrmInfoStrings.uni
+  PrmInfo.h
+  PrmInfo.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ShellPkg/ShellPkg.dec
+  PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  HiiLib
+  MemoryAllocationLib
+  PcdLib
+  PrmContextBufferLib
+  PrmModuleDiscoveryLib
+  PrmPeCoffLib
+  ShellLib
+  TimerLib
+  UefiApplicationEntryPoint
+  UefiBootServicesTableLib
+  UefiHiiServicesLib
+  UefiLib
+
+[Pcd]
+   gPrmPkgTokenSpaceGuid.PcdPrmInfoPrintHandlerExecutionTime
+
+[Protocols]
+  gEfiHiiPackageListProtocolGuid    ## CONSUMES
+
+[Guids]
+  gPrmHiiGuid
+  gZeroGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  PrmInfoExtra.uni
diff --git a/PrmPkg/Application/PrmInfo/PrmInfo.uni b/PrmPkg/Application/PrmInfo/PrmInfo.uni
new file mode 100644
index 000000000000..1b65e117e8e2
--- /dev/null
+++ b/PrmPkg/Application/PrmInfo/PrmInfo.uni
@@ -0,0 +1,11 @@
+// /**
+// Platform Runtime Mechanism (PRM) Information UEFI shell application
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// */
+
+#string STR_MODULE_ABSTRACT     #language en-US "A shell application that displays information about the PRM configuration loaded by system firmware"
+
+#string STR_MODULE_DESCRIPTION  #language en-US "This application displays information about the PRM configuration loaded by system firmware."
diff --git a/PrmPkg/Application/PrmInfo/PrmInfoExtra.uni b/PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
new file mode 100644
index 000000000000..f50c17903a0a
--- /dev/null
+++ b/PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
@@ -0,0 +1,12 @@
+// /** @file
+// PrmInfo Localized Strings and Content
+//
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Platform Runtime Mechanism (PRM) Information Application"
diff --git a/PrmPkg/Application/PrmInfo/PrmInfoStrings.uni b/PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
new file mode 100644
index 000000000000..9385fd848344
--- /dev/null
+++ b/PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
@@ -0,0 +1,132 @@
+/** @file
+  String definitions for the PRM Information UEFI shell application.
+
+  Copyright (C) Microsoft Corporation. All rights reserved.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+*/
+
+#langdef en-US "English"
+
+//
+// Parameter error messages
+//
+#string STR_PRMINFO_DISCOVERY_FAILED  #language en-US "%H%s%N: PRM module discovery failed.\r\n"
+#string STR_PRMINFO_GEN_PROBLEM       #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_PRMINFO_GUID_INV          #language en-US "%H%s%N: Invalid GUID - '%H%s%N'\r\n"
+#string STR_PRMINFO_HANDLER_NOT_FOUND #language en-US "%H%s%N: PRM Handler not found - '%H{%g}%N'\r\n"
+#string STR_PRMINFO_MISSING_OPTION    #language en-US "%H%s%N: Missing option '%H%s%N' required by flag - '%H%s%N'\r\n"
+#string STR_PRMINFO_NO_ARG            #language en-US "%H%s%N: An argument must be provided, try "-?" for help.\n"
+#string STR_PRMINFO_NO_VALUE          #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n"
+#string STR_PRMINFO_PARAM_INV         #language en-US "%H%s%N: Invalid argument - '%H%s%N', try "-?" for help.\r\n"
+#string STR_PRMINFO_TOO_MANY          #language en-US "%H%s%N: Too many arguments.\r\n"
+
+//
+// Application informational messages
+//
+#string STR_PRMINFO_HANDLER_COUNT       #language en-US "  Handler Count: %d\r\n"
+#string STR_PRMINFO_HANDLER_EXEC_TIME   #language en-US "  Execution Time: "
+#string STR_PRMINFO_HANDLER_GUID        #language en-US "  Handler GUID: %g\r\n"
+#string STR_PRMINFO_HANDLER_NAME        #language en-US "  Handler Name: %a\r\n"
+#string STR_PRMINFO_HANDLER_NAME_HL     #language en-US "  Handler Name: %H%a%N\r\n"
+#string STR_PRMINFO_HANDLER_PA          #language en-US "    Handler Physical Address: 0x%016x\r\n"
+#string STR_PRMINFO_HANDLER_ERR_STATUS  #language en-US "  Return Status: %E%r%N\r\n"
+#string STR_PRMINFO_HANDLER_SUCC_STATUS #language en-US "  Return Status: %V%r%N\r\n"
+#string STR_PRMINFO_HANDLERS_FOUND      #language en-US "  %d PRM handlers found.\r\n"
+#string STR_PRMINFO_LINE_BREAK          #language en-US "\r\n"
+#string STR_PRMINFO_LIST_TITLE          #language en-US "PRM Modules and Handlers:\r\n"
+#string STR_PRMINFO_MODULE_GUID         #language en-US "Module GUID: %g\r\n"
+#string STR_PRMINFO_MODULE_NAME         #language en-US "Module Name: %a\r\n"
+#string STR_PRMINFO_MODULE_VERSION      #language en-US "Module Version: %02d.%02d\r\n\r\n"
+#string STR_PRMINFO_MODULES_FOUND       #language en-US "  %d PRM modules found.\r\n"
+#string STR_PRMINFO_NO_MMIO_RANGES      #language en-US "  No runtime MMIO ranges used by this module.\r\n"
+#string STR_PRMINFO_NO_STATIC_BUFFER    #language en-US "      This handler does not define a static data buffer.\r\n\r\n"
+#string STR_PRMINFO_RUNTIME_MMIO_COUNT  #language en-US "  Runtime MMIO Range Count: %d\r\n"
+#string STR_PRMINFO_RUNTIME_MMIO_INFO   #language en-US "    [%d]: Physical Base Address = 0x%016x\r\n          Virtual Base Address = 0x%016x\r\n          Length = 0x%x\r\n"
+#string STR_PRMINFO_STATIC_DATA_BUFFER  #language en-US "    Static Data Buffer: 0x%016x\r\n"
+#string STR_PRMINFO_UNKNOWN             #language en-US "Unknown"
+#string STR_PRMINFO_USECS               #language en-US "%H%ld.%ld microseconds%N"
+#string STR_PRMINFO_NANO_SECS           #language en-US "%H%ld nanoseconds%N"
+#string STR_PRMINFO_SECS                #language en-US "%H%ld.%ld%ld%ld seconds%N"
+#string STR_PRMINFO_MILLI_SECS          #language en-US "%H%ld.%ld%ld milliseconds%N"
+
+//
+// Application error messages
+//
+#string STR_PRMINFO_HANDLER_PA_ERROR    #language en-US "    An ERROR (%r) occurred determining the handler physical address.\r\n"
+
+#string STR_PRMINFO_HELP                  #language en-US ""
+".TH PrmInfo 0 "Display and test Platform Runtime Mechanism (PRM) modules."\r\n"
+".SH NAME:\r\n"
+"Display and test Platform Runtime Mechanism (PRM) modules.\r\n"
+".SH SYNOPSIS\r\n"
+"\r\n"
+"PRMINFO [[-?] | [-b] [-l] [-r] [-t (guid | all)]]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+"  -? - Show help.\r\n"
+"  -b - Displays one screen of output at a time.\r\n"
+"  -l - Display a list of installed PRM modules and handlers.\r\n"
+"  -t - Call a given PRM handler by the specified GUID.\r\n"
+"         guid - A 32 digit GUID string with hyphen separation with no enclosing\r\n"
+"                character such as braces.\r\n"
+"           Example: 00000000-0000-0000-0000-000000000000\r\n"
+"         all - The string 'all' indicating all PRM handlers should be called\r\n"
+"               in order discovered.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"  This program is provided to allow examination of the Platform Runtime\r\n"
+"  Mechanism (PRM) configuration present on the current system. In addition,\r\n"
+"  the application contains some lightweight tests to verify that the firmware\r\n"
+"  set up the PRM  information that will be conveyed to the loaded operating\r\n"
+"  system correctly.\r\n"
+" \r\n"
+"  Default behavior is to display the content of all the PRM modules and\r\n"
+"  handlers currently installed (equivalent to the -l argument). To facilitate\r\n"
+"  debugging and verifying correct implementation of the PRM infrastructure\r\n"
+"  and PRM modules in a given firmware, the application can also call a\r\n"
+"  given PRM handler and perform basic validation of the PRMT ACPI table\r\n"
+"  to confirm it satisfies the basic constraints required for the table\r\n"
+"  in the PRM Specification.\r\n"
+" \r\n"
+"NOTES:\r\n"
+"  1. Calling PRM handlers from this application:\r\n"
+"     -  The user should exercise caution when calling PRM handlers in the\r\n"
+"        pre-OS environment. The PRM author may have only considered\r\n"
+"        execution within the context of OS runtime."
+"\r\n"
+"     -  The application will not perform any manipulation of PRM handler\r\n"
+"        parameter buffers prior to calling the handler.\r\n"
+"\r\n"
+"     -  This feature is intended to provide a quick method to exercise\r\n"
+"        PRM code without loading a full OS that is PRM aware and to perform\r\n"
+"        testing of PRM code that is aware it will be executed in such an\r\n"
+"        environment. It is not recommended to call PRM handlers on a\r\n"
+"        production system if you are not fully aware of how the PRM handler\r\n"
+"        behaves and any side effect(s) it might have on the system.\r\n"
+".SH STANDARDS\r\n"
+" \r\n"
+"STANDARDS:\r\n"
+"  Platform Runtime Mechanism (PRM) is currently in a draft state and the\r\n"
+"  specification is not yet publicly available. A reference to the publicly\r\n"
+"  available document will replace this text when it is available.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+"  * To display a list of the installed PRM modules and PRM handlers:\r\n"
+"    fs0:\> prminfo -l\r\n"
+" \r\n"
+"  * To validate the installed PRMT ACPI table:\r\n"
+"    fs0:\> prminfo -r\r\n"
+" \r\n"
+"  * To call a PRM handler by GUID:\r\n"
+"    fs0:\> prminfo -t e1466081-7562-430f-896b-b0e523dc335a\r\n"
+" \r\n"
+"  * To call all of the PRM handlers discovered on the system:\r\n"
+"    fs0:\> prminfo -t all\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+"  SHELL_SUCCESS             Data was displayed as requested.\r\n"
+"  SHELL_INVALID_PARAMETER   The operation failed.\r\n"
+" \r\n"
diff --git a/PrmPkg/PrmPkg.dec b/PrmPkg/PrmPkg.dec
index 785e2c24c2f9..94888d1c70a4 100644
--- a/PrmPkg/PrmPkg.dec
+++ b/PrmPkg/PrmPkg.dec
@@ -30,6 +30,7 @@ [Includes]
 
 [Guids]
   gPrmPkgTokenSpaceGuid = { 0x46f56acc, 0x600b, 0x450f, { 0xa5, 0x9c, 0x3a, 0x1a, 0x4a, 0xd4, 0x35, 0x3e }}
+  gPrmHiiGuid = { 0xee4cd885, 0xd104, 0x4056, { 0x84, 0xba, 0x46, 0x18, 0x82, 0xa7, 0x2a, 0x18 }}
 
 [LibraryClasses]
   ## @libraryclass Provides a general abstraction for PRM context buffer management
@@ -55,3 +56,12 @@ [PcdsFixedAtBuild]
 
   ## Size in bytes of a PRM firmware volume
   gPrmPkgTokenSpaceGuid.PcdFlashFvPrmSize|0x00000000|UINT32|0x00000002
+
+  ## Print PRM handler execution time in PrmInfo
+  #
+  #  Provides an option to disable usage of a timer library to record PRM handler
+  #  execution time. In most cases, the platform should provide a valid TimerLib
+  #  instance that can be used when the application is built with that package to
+  #  report PRM handler execution time in the application. If such a TimerLib
+  #  instance is not available, set this PCD to FALSE in the package DSC file.
+  gPrmPkgTokenSpaceGuid.PcdPrmInfoPrintHandlerExecutionTime|TRUE|BOOLEAN|0x00000003
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index e876f2053a8e..5241354cb220 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -36,13 +36,14 @@ [LibraryClasses.common]
   RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
   RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
   UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
 
-[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER]
+[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_APPLICATION]
   #
   # EDK II Packages
   #
   BaseMemoryLib|MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf
-  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+  DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
@@ -59,6 +60,24 @@ [LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER]
   PrmPeCoffLib|$(PLATFORM_PACKAGE)/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
 
 
+[LibraryClasses.common.UEFI_APPLICATION]
+  FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+
+################################################################################
+#
+# Pcd Section - List of PCD entries modified by this package
+#
+################################################################################
+
+[PcdsFixedAtBuild.common]
+  gPrmPkgTokenSpaceGuid.PcdPrmInfoPrintHandlerExecutionTime|FALSE
+
 ###################################################################################################
 #
 # Components Section - List of the modules and components that will be processed by compilation
@@ -116,6 +135,11 @@ [Components]
   }
   $(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
 
+  #
+  # PRM Information UEFI Application
+  #
+  $(PLATFORM_PACKAGE)/Application/PrmInfo/PrmInfo.inf
+
   #
   # The SampleMemoryAllocationModule was used during a time in the POC when the OS
   # provided memory allocation services. This module was successful in using those services.
diff --git a/PrmPkg/Readme.md b/PrmPkg/Readme.md
index b79cb66c4790..2a8a40c924c0 100644
--- a/PrmPkg/Readme.md
+++ b/PrmPkg/Readme.md
@@ -118,6 +118,25 @@ maintained in PrmPkg. It is intended to only contain PRM infrastructure code and
 that infrastructure. The PrmPkg is meant to be used as-is by firmware that supports PRM. Any shortcomings that
 prevent the package from being used as-is should be addressed directly in PrmPkg.
 
+## PRM Information UEFI Application
+A UEFI application is provided in this package called "PrmInfo" that allows a user to display and test PRM
+modules on their system.
+
+[Link to application source code](PrmPkg/Application/PrmInfo).
+
+This application is intended to be helpful during PRM enabling by allowing the user to:
+  1. Confirm that their firmware port of the PRM infrastructure implemented in this package is functioning correctly.
+  2. Quickly get information about what PRM modules and handlers that are present on a given system.
+  3. Quickly test PRM handlers without booting into a full operating system.
+  4. Develop and exercise PRM handlers prior to the availability of an operating system that is PRM aware.
+
+Execute the application help command for detailed usage instructions and examples of how to use the application: \
+  ``PrmInfo -?``
+
+*Example Usage:*
+
+![](PrmPkg/Application/PrmInfo/PrmInfo_Usage_Example.gif)
+
 ## PRM Module
 
 > __*Note*__: You can find simple examples of PRM modules in the Samples directory of this package.
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 27/41] PrmPkg: Enforce stricter types
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (25 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 26/41] PrmPkg/Application/PrmInfo: Add initial application Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 28/41] PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file Michael Kubacki
                   ` (13 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Makes the following changes to enforce stricter types:

1. PrmPkg/PrmConfigDxe

   The function PrmConfigEndOfDxeNotification () is used as a notify
   function (of type EFI_EVENT_NOTIFY), however it has a return type
   of EFI_STATUS whereas the return type should actually be VOID.

2. PrmPkg/PrmLoaderDxe

   Updates the following types to be more accurate than were allowed
   in the VS compiler:
   * 3rd actual argument given to GetModuleContextBuffers () is
     explicitly marked as CONST PRM_MODULE_CONTEXT_BUFFERS **

   * 3rd actual argument given to GetContextBuffer () is
     explicitly marked as CONST PRM_CONTEXT_BUFFER **

   * PrmLoaderEndOfDxeNotification () return type is changed to VOID
     to align with the EFI_EVENT_NOTIFY type

3. PrmPkg/Application/PrmInfo

   Updates the following types to be more accurate than were allowed
   in the VS compiler:
   * SHELL_STATUS in ParseParameterList () is now EFI_STATUS

   * 3rd actual argument given to GetModuleContextBuffers () is
     explicitly marked as CONST PRM_MODULE_CONTEXT_BUFFERS **

   * 3rd actual argument given to GetContextBuffer () is
     explicitly marked as CONST PRM_CONTEXT_BUFFER **

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>
---
 PrmPkg/Application/PrmInfo/PrmInfo.c |  6 +++---
 PrmPkg/PrmConfigDxe/PrmConfigDxe.c   |  8 ++------
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c   | 10 +++-------
 3 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/PrmPkg/Application/PrmInfo/PrmInfo.c b/PrmPkg/Application/PrmInfo/PrmInfo.c
index 431a6f206163..e479667ec7eb 100644
--- a/PrmPkg/Application/PrmInfo/PrmInfo.c
+++ b/PrmPkg/Application/PrmInfo/PrmInfo.c
@@ -221,7 +221,7 @@ GatherPrmHandlerInfo (
     Status = GetModuleContextBuffers (
               ByModuleGuid,
               CurrentModuleGuid,
-              &CurrentModuleContextBuffers
+              (CONST PRM_MODULE_CONTEXT_BUFFERS **) &CurrentModuleContextBuffers
               );
     ASSERT (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND);
     if (!EFI_ERROR (Status) && CurrentModuleContextBuffers != NULL) {
@@ -272,7 +272,7 @@ GatherPrmHandlerInfo (
       Status =  GetContextBuffer (
                   CurrentHandlerContext.Guid,
                   CurrentModuleContextBuffers,
-                  &CurrentContextBuffer
+                  (CONST PRM_CONTEXT_BUFFER **) &CurrentContextBuffer
                   );
       if (!EFI_ERROR (Status)) {
         CurrentHandlerContext.StaticDataBuffer = CurrentContextBuffer->StaticDataBuffer;
@@ -520,7 +520,7 @@ ParseParameterList (
   )
 {
   EFI_STATUS                            Status;
-  SHELL_STATUS                          ReturnStatus;
+  EFI_STATUS                            ReturnStatus;
   UINTN                                 ArgumentCount;
   EFI_GUID                              HandlerGuid;
   BOOLEAN                               PrintHandlerInfo;
diff --git a/PrmPkg/PrmConfigDxe/PrmConfigDxe.c b/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
index c547db3eca5e..f3223d63de0c 100644
--- a/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
+++ b/PrmPkg/PrmConfigDxe/PrmConfigDxe.c
@@ -361,10 +361,8 @@ PrmConfigVirtualAddressChangeEvent (
   @param[in]  Context         The pointer to the notification function's context,
                               which is implementation-dependent.
 
-  @retval EFI_SUCCESS         The function executed successfully
-
 **/
-EFI_STATUS
+VOID
 EFIAPI
 PrmConfigEndOfDxeNotification (
   IN  EFI_EVENT               Event,
@@ -446,8 +444,6 @@ PrmConfigEndOfDxeNotification (
     gBS->FreePool (HandleBuffer);
   }
   gBS->CloseEvent(Event);
-
-  return EFI_SUCCESS;
 }
 
 /**
@@ -476,7 +472,7 @@ PrmConfigEntryPoint (
   // Register a notification function to change memory attributes at end of DXE
   //
   Event = NULL;
-  Status = gBS->CreateEventEx(
+  Status = gBS->CreateEventEx (
                   EVT_NOTIFY_SIGNAL,
                   TPL_CALLBACK,
                   PrmConfigEndOfDxeNotification,
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index 407c48257432..aa7aab391e8c 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -151,7 +151,7 @@ ProcessPrmModules (
     Status = GetModuleContextBuffers (
               ByModuleGuid,
               &CurrentModuleInfoStruct->Identifier,
-              &CurrentModuleContextBuffers
+              (CONST PRM_MODULE_CONTEXT_BUFFERS **) &CurrentModuleContextBuffers
               );
     ASSERT (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND);
     if (!EFI_ERROR (Status) && CurrentModuleContextBuffers != NULL) {
@@ -177,7 +177,7 @@ ProcessPrmModules (
       Status =  GetContextBuffer (
                   &CurrentHandlerInfoStruct->Identifier,
                   CurrentModuleContextBuffers,
-                  &CurrentContextBuffer
+                  (CONST PRM_CONTEXT_BUFFER **) &CurrentContextBuffer
                   );
       if (!EFI_ERROR (Status)) {
         CurrentHandlerInfoStruct->StaticDataBuffer = (UINT64) (UINTN) CurrentContextBuffer->StaticDataBuffer;
@@ -286,10 +286,8 @@ PublishPrmAcpiTable (
   @param[in]  Context                     The pointer to the notification function's context,
                                           which is implementation-dependent.
 
-  @retval EFI_SUCCESS                     The function executed successfully
-
 **/
-EFI_STATUS
+VOID
 EFIAPI
 PrmLoaderEndOfDxeNotification (
   IN  EFI_EVENT                           Event,
@@ -314,8 +312,6 @@ PrmLoaderEndOfDxeNotification (
     FreePool (PrmAcpiDescriptionTable);
   }
   gBS->CloseEvent (Event);
-
-  return EFI_SUCCESS;
 }
 
 /**
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 28/41] PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (26 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 27/41] PrmPkg: Enforce stricter types Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 29/41] PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib Michael Kubacki
                   ` (12 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a new DSC file that will be used to build host-based unit tests
in PrmPkg.

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>
---
 PrmPkg/Test/PrmPkgHostTest.dsc | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/PrmPkg/Test/PrmPkgHostTest.dsc b/PrmPkg/Test/PrmPkgHostTest.dsc
new file mode 100644
index 000000000000..41f3c32b8d19
--- /dev/null
+++ b/PrmPkg/Test/PrmPkgHostTest.dsc
@@ -0,0 +1,17 @@
+## @file
+# PrmPkg DSC file used to build host-based unit tests.
+#
+# Copyright (c) Microsoft Corporation.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  PLATFORM_NAME           = PrmPkgHostTest
+  PLATFORM_GUID           = 5BCCFC54-2162-42FB-ABCA-5B8D0DC4013C
+  PLATFORM_VERSION        = 0.1
+  DSC_SPECIFICATION       = 0x00010005
+  OUTPUT_DIRECTORY        = Build/$(PLATFORM_NAME)/HostTest
+  SUPPORTED_ARCHITECTURES = IA32|X64
+  BUILD_TARGETS           = NOOPT
+  SKUID_IDENTIFIER        = DEFAULT
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 29/41] PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (27 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 28/41] PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 30/41] PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests Michael Kubacki
                   ` (11 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a host-based specific implementation of UefiBootServicesTableLib.
This library implements relatively simple versions of the functionality
in the actual boot services implementation and does not depend on
dynamic linking to the boot services table.

Most unit tests can install the dependencies their code under test
depends on prior to invocation and uninstall those dependencies after
the test to test code that directly depends on boot services.

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>
---
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.c           |  119 ++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestEventTimer.c |  180 +++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestImage.c      |  163 ++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMemory.c     |  145 ++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMisc.c       |  198 +++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.c   | 1633 ++++++++++++++++++++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestTpl.c        |   43 +
 PrmPkg/PrmPkg.dsc                                                                                          |    1 +
 PrmPkg/Test/PrmPkgHostTest.dsc                                                                             |   11 +
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibTest.uni             |   12 +
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.h           | 1046 +++++++++++++
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf         |   46 +
 PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.h   |  123 ++
 13 files changed, 3720 insertions(+)

diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.c b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.c
new file mode 100644
index 000000000000..d41cba3fea0e
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.c
@@ -0,0 +1,119 @@
+/** @file
+  This library supports a Boot Services table library implementation that allows code dependent
+  upon UefiBootServicesTableLib to operate in an isolated execution environment such as within
+  the context of a host-based unit test framework.
+
+  The unit test should initialize the Boot Services database with any required elements
+  (e.g. protocols, events, handles, etc.) prior to the services being invoked by code under test.
+
+  It is strongly recommended to clean any global databases (e.g. protocol, event, handles, etc.) after
+  every unit test so the tests execute in a predictable manner from a clean state.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiBootServicesTableLibUnitTest.h"
+
+EFI_HANDLE         gImageHandle           = NULL;
+EFI_SYSTEM_TABLE   *gST                   = NULL;
+
+STATIC EFI_BOOT_SERVICES  mBootServices   = {
+  {
+    EFI_BOOT_SERVICES_SIGNATURE,                                                              // Signature
+    EFI_BOOT_SERVICES_REVISION,                                                               // Revision
+    sizeof (EFI_BOOT_SERVICES),                                                               // HeaderSize
+    0,                                                                                        // CRC32
+    0                                                                                         // Reserved
+  },
+  (EFI_RAISE_TPL)                               UnitTestRaiseTpl,                             // RaiseTPL
+  (EFI_RESTORE_TPL)                             UnitTestRestoreTpl,                           // RestoreTPL
+  (EFI_ALLOCATE_PAGES)                          UnitTestAllocatePages,                        // AllocatePages
+  (EFI_FREE_PAGES)                              UnitTestFreePages,                            // FreePages
+  (EFI_GET_MEMORY_MAP)                          UnitTestGetMemoryMap,                         // GetMemoryMap
+  (EFI_ALLOCATE_POOL)                           UnitTestAllocatePool,                         // AllocatePool
+  (EFI_FREE_POOL)                               UnitTestFreePool,                             // FreePool
+  (EFI_CREATE_EVENT)                            UnitTestCreateEvent,                          // CreateEvent
+  (EFI_SET_TIMER)                               UnitTestSetTimer,                             // SetTimer
+  (EFI_WAIT_FOR_EVENT)                          UnitTestWaitForEvent,                         // WaitForEvent
+  (EFI_SIGNAL_EVENT)                            UnitTestSignalEvent,                          // SignalEvent
+  (EFI_CLOSE_EVENT)                             UnitTestCloseEvent,                           // CloseEvent
+  (EFI_CHECK_EVENT)                             UnitTestCheckEvent,                           // CheckEvent
+  (EFI_INSTALL_PROTOCOL_INTERFACE)              UnitTestInstallProtocolInterface,             // InstallProtocolInterface
+  (EFI_REINSTALL_PROTOCOL_INTERFACE)            UnitTestReinstallProtocolInterface,           // ReinstallProtocolInterface
+  (EFI_UNINSTALL_PROTOCOL_INTERFACE)            UnitTestUninstallProtocolInterface,           // UninstallProtocolInterface
+  (EFI_HANDLE_PROTOCOL)                         UnitTestHandleProtocol,                       // HandleProtocol
+  (VOID *)                                      NULL,                                         // Reserved
+  (EFI_REGISTER_PROTOCOL_NOTIFY)                UnitTestRegisterProtocolNotify,               // RegisterProtocolNotify
+  (EFI_LOCATE_HANDLE)                           UnitTestLocateHandle,                         // LocateHandle
+  (EFI_LOCATE_DEVICE_PATH)                      UnitTestLocateDevicePath,                     // LocateDevicePath
+  (EFI_INSTALL_CONFIGURATION_TABLE)             UnitTestInstallConfigurationTable,            // InstallConfigurationTable
+  (EFI_IMAGE_LOAD)                              UnitTestLoadImage,                            // LoadImage
+  (EFI_IMAGE_START)                             UnitTestStartImage,                           // StartImage
+  (EFI_EXIT)                                    UnitTestExit,                                 // Exit
+  (EFI_IMAGE_UNLOAD)                            UnitTestUnloadImage,                          // UnloadImage
+  (EFI_EXIT_BOOT_SERVICES)                      UnitTestExitBootServices,                     // ExitBootServices
+  (EFI_GET_NEXT_MONOTONIC_COUNT)                UnitTestGetNextMonotonicCount,                // GetNextMonotonicCount
+  (EFI_STALL)                                   UnitTestStall,                                // Stall
+  (EFI_SET_WATCHDOG_TIMER)                      UnitTestSetWatchdogTimer,                     // SetWatchdogTimer
+  (EFI_CONNECT_CONTROLLER)                      UnitTestConnectController,                    // ConnectController
+  (EFI_DISCONNECT_CONTROLLER)                   UnitTestDisconnectController,                 // DisconnectController
+  (EFI_OPEN_PROTOCOL)                           UnitTestOpenProtocol,                         // OpenProtocol
+  (EFI_CLOSE_PROTOCOL)                          UnitTestCloseProtocol,                        // CloseProtocol
+  (EFI_OPEN_PROTOCOL_INFORMATION)               UnitTestOpenProtocolInformation,              // OpenProtocolInformation
+  (EFI_PROTOCOLS_PER_HANDLE)                    UnitTestProtocolsPerHandle,                   // ProtocolsPerHandle
+  (EFI_LOCATE_HANDLE_BUFFER)                    UnitTestLocateHandleBuffer,                   // LocateHandleBuffer
+  (EFI_LOCATE_PROTOCOL)                         UnitTestLocateProtocol,                       // LocateProtocol
+  (EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES)    UnitTestInstallMultipleProtocolInterfaces,    // InstallMultipleProtocolInterfaces
+  (EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES)  UnitTestUninstallMultipleProtocolInterfaces,  // UninstallMultipleProtocolInterfaces
+  (EFI_CALCULATE_CRC32)                         UnitTestCalculateCrc32,                       // CalculateCrc32
+  (EFI_COPY_MEM)                                CopyMem,                                      // CopyMem
+  (EFI_SET_MEM)                                 SetMem,                                       // SetMem
+  (EFI_CREATE_EVENT_EX)                         UnitTestCreateEventEx                         // CreateEventEx
+};
+
+EFI_BOOT_SERVICES  *gBS = &mBootServices;
+
+/**
+  The constructor function caches the pointer of Boot Services Table.
+
+  The constructor function caches the pointer of Boot Services Table through System Table.
+  It will ASSERT() if the pointer of System Table is NULL.
+  It will ASSERT() if the pointer of Boot Services Table is NULL.
+  It will always return EFI_SUCCESS.
+
+  @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
+UefiBootServicesTableLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  //
+  // Cache the Image Handle
+  //
+  gImageHandle = ImageHandle;
+  ASSERT (gImageHandle != NULL);
+
+  //
+  // Cache pointer to the EFI System Table
+  //
+
+  // Note: The system table is not implemented
+  gST = NULL;
+
+  //
+  // Cache pointer to the EFI Boot Services Table
+  //
+  gBS = SystemTable->BootServices;
+  ASSERT (gBS != NULL);
+
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestEventTimer.c b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestEventTimer.c
new file mode 100644
index 000000000000..16bd3f4c547d
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestEventTimer.c
@@ -0,0 +1,180 @@
+/** @file
+  Implementation of event and timer related services in the UEFI Boot Services table for use in unit tests.
+
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiBootServicesTableLibUnitTest.h"
+
+/**
+  Creates an event.
+
+  @param  Type                   The type of event to create and its mode and
+                                 attributes
+  @param  NotifyTpl              The task priority level of event notifications
+  @param  NotifyFunction         Pointer to the events notification function
+  @param  NotifyContext          Pointer to the notification functions context
+                                 corresponds to parameter "Context" in the
+                                 notification function
+  @param  Event                  Pointer to the newly created event if the call
+                                 succeeds  undefined otherwise
+
+  @retval EFI_SUCCESS            The event structure was created
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value
+  @retval EFI_OUT_OF_RESOURCES   The event could not be allocated
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCreateEvent (
+  IN UINT32                   Type,
+  IN EFI_TPL                  NotifyTpl,
+  IN EFI_EVENT_NOTIFY         NotifyFunction, OPTIONAL
+  IN VOID                     *NotifyContext, OPTIONAL
+  OUT EFI_EVENT               *Event
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Sets the type of timer and the trigger time for a timer event.
+
+  @param  UserEvent              The timer event that is to be signaled at the
+                                 specified time
+  @param  Type                   The type of time that is specified in
+                                 TriggerTime
+  @param  TriggerTime            The number of 100ns units until the timer
+                                 expires
+
+  @retval EFI_SUCCESS            The event has been set to be signaled at the
+                                 requested time
+  @retval EFI_INVALID_PARAMETER  Event or Type is not valid
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestSetTimer (
+  IN EFI_EVENT            UserEvent,
+  IN EFI_TIMER_DELAY      Type,
+  IN UINT64               TriggerTime
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Stops execution until an event is signaled.
+
+  @param  NumberOfEvents         The number of events in the UserEvents array
+  @param  UserEvents             An array of EFI_EVENT
+  @param  UserIndex              Pointer to the index of the event which
+                                 satisfied the wait condition
+
+  @retval EFI_SUCCESS            The event indicated by Index was signaled.
+  @retval EFI_INVALID_PARAMETER  The event indicated by Index has a notification
+                                 function or Event was not a valid type
+  @retval EFI_UNSUPPORTED        The current TPL is not TPL_APPLICATION
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestWaitForEvent (
+  IN UINTN        NumberOfEvents,
+  IN EFI_EVENT    *UserEvents,
+  OUT UINTN       *UserIndex
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Signals the event.  Queues the event to be notified if needed.
+
+  @param  UserEvent              The event to signal .
+
+  @retval EFI_INVALID_PARAMETER  Parameters are not valid.
+  @retval EFI_SUCCESS            The event was signaled.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestSignalEvent (
+  IN EFI_EVENT    UserEvent
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Closes an event and frees the event structure.
+
+  @param  UserEvent              Event to close
+
+  @retval EFI_INVALID_PARAMETER  Parameters are not valid.
+  @retval EFI_SUCCESS            The event has been closed
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCloseEvent (
+  IN EFI_EVENT    UserEvent
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Check the status of an event.
+
+  @param  UserEvent              The event to check
+
+  @retval EFI_SUCCESS            The event is in the signaled state
+  @retval EFI_NOT_READY          The event is not in the signaled state
+  @retval EFI_INVALID_PARAMETER  Event is of type EVT_NOTIFY_SIGNAL
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCheckEvent (
+  IN EFI_EVENT        UserEvent
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Creates an event in a group.
+
+  @param  Type                   The type of event to create and its mode and
+                                 attributes
+  @param  NotifyTpl              The task priority level of event notifications
+  @param  NotifyFunction         Pointer to the events notification function
+  @param  NotifyContext          Pointer to the notification functions context
+                                 corresponds to parameter "Context" in the
+                                 notification function
+  @param  EventGroup             GUID for EventGroup if NULL act the same as
+                                 gBS->CreateEvent().
+  @param  Event                  Pointer to the newly created event if the call
+                                 succeeds  undefined otherwise
+
+  @retval EFI_SUCCESS            The event structure was created
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value
+  @retval EFI_OUT_OF_RESOURCES   The event could not be allocated
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCreateEventEx (
+  IN UINT32                   Type,
+  IN EFI_TPL                  NotifyTpl,
+  IN EFI_EVENT_NOTIFY         NotifyFunction, OPTIONAL
+  IN CONST VOID               *NotifyContext, OPTIONAL
+  IN CONST EFI_GUID           *EventGroup,    OPTIONAL
+  OUT EFI_EVENT               *Event
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestImage.c b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestImage.c
new file mode 100644
index 000000000000..b6083a4c3f27
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestImage.c
@@ -0,0 +1,163 @@
+/** @file
+  Implementation of image related services in the UEFI Boot Services table for use in unit tests.
+
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiBootServicesTableLibUnitTest.h"
+
+/**
+  Loads an EFI image into memory and returns a handle to the image.
+
+  @param  BootPolicy              If TRUE, indicates that the request originates
+                                  from the boot manager, and that the boot
+                                  manager is attempting to load FilePath as a
+                                  boot selection.
+  @param  ParentImageHandle       The caller's image handle.
+  @param  FilePath                The specific file path from which the image is
+                                  loaded.
+  @param  SourceBuffer            If not NULL, a pointer to the memory location
+                                  containing a copy of the image to be loaded.
+  @param  SourceSize              The size in bytes of SourceBuffer.
+  @param  ImageHandle             Pointer to the returned image handle that is
+                                  created when the image is successfully loaded.
+
+  @retval EFI_SUCCESS             The image was loaded into memory.
+  @retval EFI_NOT_FOUND           The FilePath was not found.
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.
+  @retval EFI_UNSUPPORTED         The image type is not supported, or the device
+                                  path cannot be parsed to locate the proper
+                                  protocol for loading the file.
+  @retval EFI_OUT_OF_RESOURCES    Image was not loaded due to insufficient
+                                  resources.
+  @retval EFI_LOAD_ERROR          Image was not loaded because the image format was corrupt or not
+                                  understood.
+  @retval EFI_DEVICE_ERROR        Image was not loaded because the device returned a read error.
+  @retval EFI_ACCESS_DENIED       Image was not loaded because the platform policy prohibits the
+                                  image from being loaded. NULL is returned in *ImageHandle.
+  @retval EFI_SECURITY_VIOLATION  Image was loaded and an ImageHandle was created with a
+                                  valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
+                                  platform policy specifies that the image should not be started.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLoadImage (
+  IN BOOLEAN                    BootPolicy,
+  IN EFI_HANDLE                 ParentImageHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,
+  IN VOID                       *SourceBuffer   OPTIONAL,
+  IN UINTN                      SourceSize,
+  OUT EFI_HANDLE                *ImageHandle
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Transfer control to a loaded image's entry point.
+
+  @param  ImageHandle             Handle of image to be started.
+  @param  ExitDataSize            Pointer of the size to ExitData
+  @param  ExitData                Pointer to a pointer to a data buffer that
+                                  includes a Null-terminated string,
+                                  optionally followed by additional binary data.
+                                  The string is a description that the caller may
+                                  use to further indicate the reason for the
+                                  image's exit.
+
+  @retval EFI_INVALID_PARAMETER   Invalid parameter
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+  @retval EFI_SECURITY_VIOLATION  The current platform policy specifies that the image should not be started.
+  @retval EFI_SUCCESS             Successfully transfer control to the image's
+                                  entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestStartImage (
+  IN EFI_HANDLE  ImageHandle,
+  OUT UINTN      *ExitDataSize,
+  OUT CHAR16     **ExitData  OPTIONAL
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Terminates the currently loaded EFI image and returns control to boot services.
+
+  @param  ImageHandle             Handle that identifies the image. This
+                                  parameter is passed to the image on entry.
+  @param  Status                  The image's exit code.
+  @param  ExitDataSize            The size, in bytes, of ExitData. Ignored if
+                                  ExitStatus is EFI_SUCCESS.
+  @param  ExitData                Pointer to a data buffer that includes a
+                                  Null-terminated Unicode string, optionally
+                                  followed by additional binary data. The string
+                                  is a description that the caller may use to
+                                  further indicate the reason for the image's
+                                  exit.
+
+  @retval EFI_INVALID_PARAMETER   Image handle is NULL or it is not current
+                                  image.
+  @retval EFI_SUCCESS             Successfully terminates the currently loaded
+                                  EFI image.
+  @retval EFI_ACCESS_DENIED       Should never reach there.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate pool
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestExit (
+  IN EFI_HANDLE  ImageHandle,
+  IN EFI_STATUS  Status,
+  IN UINTN       ExitDataSize,
+  IN CHAR16      *ExitData  OPTIONAL
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle             Handle that identifies the image to be
+                                  unloaded.
+
+  @retval EFI_SUCCESS             The image has been unloaded.
+  @retval EFI_UNSUPPORTED         The image has been started, and does not support
+                                  unload.
+  @retval EFI_INVALID_PARAMPETER  ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestUnloadImage (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Terminates all boot services.
+
+  @param  ImageHandle            Handle that identifies the exiting image.
+  @param  MapKey                 Key to the latest memory map.
+
+  @retval EFI_SUCCESS            Boot Services terminated
+  @retval EFI_INVALID_PARAMETER  MapKey is incorrect.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestExitBootServices (
+  IN EFI_HANDLE   ImageHandle,
+  IN UINTN        MapKey
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMemory.c b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMemory.c
new file mode 100644
index 000000000000..48da39d0c359
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMemory.c
@@ -0,0 +1,145 @@
+/** @file
+  Implementation of memory related services in the UEFI Boot Services table for use in unit tests.
+
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiBootServicesTableLibUnitTest.h"
+
+/**
+  Allocates pages from the memory map.
+
+  @param  Type                   The type of allocation to perform
+  @param  MemoryType             The type of memory to turn the allocated pages
+                                 into
+  @param  NumberOfPages          The number of pages to allocate
+  @param  Memory                 A pointer to receive the base allocated memory
+                                 address
+
+  @return Status. On success, Memory is filled in with the base address allocated
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in
+                                 spec.
+  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
+  @retval EFI_SUCCESS            Pages successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestAllocatePages (
+  IN EFI_ALLOCATE_TYPE      Type,
+  IN EFI_MEMORY_TYPE        MemoryType,
+  IN UINTN                  NumberOfPages,
+  IN OUT EFI_PHYSICAL_ADDRESS  *Memory
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Frees previous allocated pages.
+
+  @param  Memory                 Base address of memory being freed
+  @param  NumberOfPages          The number of pages to free
+
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range
+  @retval EFI_INVALID_PARAMETER  Address not aligned
+  @return EFI_SUCCESS         -Pages successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestFreePages (
+  IN EFI_PHYSICAL_ADDRESS   Memory,
+  IN UINTN                  NumberOfPages
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  This function returns a copy of the current memory map. The map is an array of
+  memory descriptors, each of which describes a contiguous block of memory.
+
+  @param  MemoryMapSize          A pointer to the size, in bytes, of the
+                                 MemoryMap buffer. On input, this is the size of
+                                 the buffer allocated by the caller.  On output,
+                                 it is the size of the buffer returned by the
+                                 firmware  if the buffer was large enough, or the
+                                 size of the buffer needed  to contain the map if
+                                 the buffer was too small.
+  @param  MemoryMap              A pointer to the buffer in which firmware places
+                                 the current memory map.
+  @param  MapKey                 A pointer to the location in which firmware
+                                 returns the key for the current memory map.
+  @param  DescriptorSize         A pointer to the location in which firmware
+                                 returns the size, in bytes, of an individual
+                                 EFI_MEMORY_DESCRIPTOR.
+  @param  DescriptorVersion      A pointer to the location in which firmware
+                                 returns the version number associated with the
+                                 EFI_MEMORY_DESCRIPTOR.
+
+  @retval EFI_SUCCESS            The memory map was returned in the MemoryMap
+                                 buffer.
+  @retval EFI_BUFFER_TOO_SMALL   The MemoryMap buffer was too small. The current
+                                 buffer size needed to hold the memory map is
+                                 returned in MemoryMapSize.
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestGetMemoryMap (
+  IN OUT UINTN                  *MemoryMapSize,
+  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
+  OUT UINTN                     *MapKey,
+  OUT UINTN                     *DescriptorSize,
+  OUT UINT32                    *DescriptorVersion
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Allocate pool of a particular type.
+
+  @param  PoolType               Type of pool to allocate
+  @param  Size                   The amount of pool to allocate
+  @param  Buffer                 The address to return a pointer to the allocated
+                                 pool
+
+  @retval EFI_INVALID_PARAMETER  PoolType not valid or Buffer is NULL
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.
+  @retval EFI_SUCCESS            Pool successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestAllocatePool (
+  IN EFI_MEMORY_TYPE  PoolType,
+  IN UINTN            Size,
+  OUT VOID            **Buffer
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Frees pool.
+
+  @param  Buffer                 The allocated pool entry to free
+
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.
+  @retval EFI_SUCCESS            Pool successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestFreePool (
+  IN VOID        *Buffer
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMisc.c b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMisc.c
new file mode 100644
index 000000000000..dbe3e76b549f
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestMisc.c
@@ -0,0 +1,198 @@
+/** @file
+  Implementation of miscellaneous services in the UEFI Boot Services table for use in unit tests.
+
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiBootServicesTableLibUnitTest.h"
+
+/**
+  Returns a monotonically increasing count for the platform.
+
+  @param[out]  Count            The pointer to returned value.
+
+  @retval EFI_SUCCESS           The next monotonic count was returned.
+  @retval EFI_INVALID_PARAMETER Count is NULL.
+  @retval EFI_DEVICE_ERROR      The device is not functioning properly.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestGetNextMonotonicCount (
+  OUT UINT64                  *Count
+  )
+{
+  STATIC  UINT64  StaticCount = 0;
+
+  *Count = StaticCount++;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Introduces a fine-grained stall.
+
+  @param  Microseconds           The number of microseconds to stall execution.
+
+  @retval EFI_SUCCESS            Execution was stalled for at least the requested
+                                 amount of microseconds.
+  @retval EFI_NOT_AVAILABLE_YET  gMetronome is not available yet
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestStall (
+  IN UINTN            Microseconds
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Sets the system's watchdog timer.
+
+  @param  Timeout         The number of seconds to set the watchdog timer to.
+                          A value of zero disables the timer.
+  @param  WatchdogCode    The numeric code to log on a watchdog timer timeout
+                          event. The firmware reserves codes 0x0000 to 0xFFFF.
+                          Loaders and operating systems may use other timeout
+                          codes.
+  @param  DataSize        The size, in bytes, of WatchdogData.
+  @param  WatchdogData    A data buffer that includes a Null-terminated Unicode
+                          string, optionally followed by additional binary data.
+                          The string is a description that the call may use to
+                          further indicate the reason to be logged with a
+                          watchdog event.
+
+  @return EFI_SUCCESS               Timeout has been set
+  @return EFI_NOT_AVAILABLE_YET     WatchdogTimer is not available yet
+  @return EFI_UNSUPPORTED           System does not have a timer (currently not used)
+  @return EFI_DEVICE_ERROR          Could not complete due to hardware error
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestSetWatchdogTimer (
+  IN UINTN    Timeout,
+  IN UINT64   WatchdogCode,
+  IN UINTN    DataSize,
+  IN CHAR16   *WatchdogData OPTIONAL
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Connects one or more drivers to a controller.
+
+  @param  ControllerHandle      The handle of the controller to which driver(s) are to be connected.
+  @param  DriverImageHandle     A pointer to an ordered list handles that support the
+                                EFI_DRIVER_BINDING_PROTOCOL.
+  @param  RemainingDevicePath   A pointer to the device path that specifies a child of the
+                                controller specified by ControllerHandle.
+  @param  Recursive             If TRUE, then ConnectController() is called recursively
+                                until the entire tree of controllers below the controller specified
+                                by ControllerHandle have been created. If FALSE, then
+                                the tree of controllers is only expanded one level.
+
+  @retval EFI_SUCCESS           1) One or more drivers were connected to ControllerHandle.
+                                2) No drivers were connected to ControllerHandle, but
+                                RemainingDevicePath is not NULL, and it is an End Device
+                                Path Node.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_NOT_FOUND         1) There are no EFI_DRIVER_BINDING_PROTOCOL instances
+                                present in the system.
+                                2) No drivers were connected to ControllerHandle.
+  @retval EFI_SECURITY_VIOLATION
+                                The user has no permission to start UEFI device drivers on the device path
+                                associated with the ControllerHandle or specified by the RemainingDevicePath.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestConnectController (
+  IN  EFI_HANDLE                ControllerHandle,
+  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
+  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,
+  IN  BOOLEAN                   Recursive
+  )
+{
+  return EFI_SUCCESS; // Return success for now
+}
+
+/**
+  Disconnects a controller from a driver
+
+  @param  ControllerHandle                      ControllerHandle The handle of
+                                                the controller from which
+                                                driver(s)  are to be
+                                                disconnected.
+  @param  DriverImageHandle                     DriverImageHandle The driver to
+                                                disconnect from ControllerHandle.
+  @param  ChildHandle                           ChildHandle The handle of the
+                                                child to destroy.
+
+  @retval EFI_SUCCESS                           One or more drivers were
+                                                disconnected from the controller.
+  @retval EFI_SUCCESS                           On entry, no drivers are managing
+                                                ControllerHandle.
+  @retval EFI_SUCCESS                           DriverImageHandle is not NULL,
+                                                and on entry DriverImageHandle is
+                                                not managing ControllerHandle.
+  @retval EFI_INVALID_PARAMETER                 ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER                 DriverImageHandle is not NULL,
+                                                and it is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER                 ChildHandle is not NULL, and it
+                                                is not a valid EFI_HANDLE.
+  @retval EFI_OUT_OF_RESOURCES                  There are not enough resources
+                                                available to disconnect any
+                                                drivers from ControllerHandle.
+  @retval EFI_DEVICE_ERROR                      The controller could not be
+                                                disconnected because of a device
+                                                error.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestDisconnectController (
+  IN  EFI_HANDLE  ControllerHandle,
+  IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
+  IN  EFI_HANDLE  ChildHandle        OPTIONAL
+  )
+{
+  return EFI_SUCCESS; // Return success for now
+}
+
+/**
+  Computes and returns a 32-bit CRC for a data buffer.
+
+  @param[in]   Data             A pointer to the buffer on which the 32-bit CRC is to be computed.
+  @param[in]   DataSize         The number of bytes in the buffer Data.
+  @param[out]  Crc32            The 32-bit CRC that was computed for the data buffer specified by Data
+                                and DataSize.
+
+  @retval EFI_SUCCESS           The 32-bit CRC was computed for the data buffer and returned in
+                                Crc32.
+  @retval EFI_INVALID_PARAMETER Data is NULL.
+  @retval EFI_INVALID_PARAMETER Crc32 is NULL.
+  @retval EFI_INVALID_PARAMETER DataSize is 0.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCalculateCrc32 (
+  IN  VOID                              *Data,
+  IN  UINTN                             DataSize,
+  OUT UINT32                            *Crc32
+  )
+{
+  if (Data == NULL || Crc32 == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Crc32 = CalculateCrc32 (Data, DataSize);
+
+  return EFI_SUCCESS;
+}
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.c b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.c
new file mode 100644
index 000000000000..65e69ecc3d94
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.c
@@ -0,0 +1,1633 @@
+/** @file
+  Implementation of protocol related services in the UEFI Boot Services table for use in unit tests.
+
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiBootServicesTableLibUnitTestProtocol.h"
+
+STATIC LIST_ENTRY   mProtocolDatabase       = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
+STATIC LIST_ENTRY   gHandleList             = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
+STATIC UINT64       gHandleDatabaseKey      = 0;
+STATIC UINTN        mEfiLocateHandleRequest = 0;
+
+//
+// Helper Functions
+//
+
+/**
+  Check whether a handle is a valid EFI_HANDLE
+
+  @param  UserHandle             The handle to check
+
+  @retval EFI_INVALID_PARAMETER  The handle is NULL or not a valid EFI_HANDLE.
+  @retval EFI_SUCCESS            The handle is valid EFI_HANDLE.
+
+**/
+EFI_STATUS
+ UnitTestValidateHandle (
+  IN  EFI_HANDLE                UserHandle
+  )
+{
+  IHANDLE             *Handle;
+  LIST_ENTRY          *Link;
+
+  if (UserHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {
+    Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+    if (Handle == (IHANDLE *) UserHandle) {
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  Finds the protocol entry for the requested protocol.
+
+  @param  Protocol               The ID of the protocol
+  @param  Create                 Create a new entry if not found
+
+  @return Protocol entry
+
+**/
+PROTOCOL_ENTRY  *
+UnitTestFindProtocolEntry (
+  IN EFI_GUID   *Protocol,
+  IN BOOLEAN    Create
+  )
+{
+  LIST_ENTRY          *Link;
+  PROTOCOL_ENTRY      *Item;
+  PROTOCOL_ENTRY      *ProtEntry;
+
+  //
+  // Search the database for the matching GUID
+  //
+
+  ProtEntry = NULL;
+  for (Link = mProtocolDatabase.ForwardLink;
+       Link != &mProtocolDatabase;
+       Link = Link->ForwardLink) {
+
+    Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
+    if (CompareGuid (&Item->ProtocolID, Protocol)) {
+
+      //
+      // This is the protocol entry
+      //
+
+      ProtEntry = Item;
+      break;
+    }
+  }
+
+  //
+  // If the protocol entry was not found and Create is TRUE, then
+  // allocate a new entry
+  //
+  if ((ProtEntry == NULL) && Create) {
+    ProtEntry = AllocatePool (sizeof (PROTOCOL_ENTRY));
+
+    if (ProtEntry != NULL) {
+      //
+      // Initialize new protocol entry structure
+      //
+      ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
+      CopyGuid ((VOID *) &ProtEntry->ProtocolID, Protocol);
+      InitializeListHead (&ProtEntry->Protocols);
+      InitializeListHead (&ProtEntry->Notify);
+
+      //
+      // Add it to protocol database
+      //
+      InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
+    }
+  }
+
+  return ProtEntry;
+}
+
+/**
+  Finds the protocol instance for the requested handle and protocol.
+  Note: This function doesn't do parameters checking, it's caller's responsibility
+  to pass in valid parameters.
+
+  @param  Handle                 The handle to search the protocol on
+  @param  Protocol               GUID of the protocol
+  @param  Interface              The interface for the protocol being searched
+
+  @return Protocol instance (NULL: Not found)
+
+**/
+PROTOCOL_INTERFACE *
+UnitTestFindProtocolInterface (
+  IN IHANDLE        *Handle,
+  IN EFI_GUID       *Protocol,
+  IN VOID           *Interface
+  )
+{
+  PROTOCOL_INTERFACE  *Prot;
+  PROTOCOL_ENTRY      *ProtEntry;
+  LIST_ENTRY          *Link;
+
+  Prot = NULL;
+
+  //
+  // Lookup the protocol entry for this protocol ID
+  //
+
+  ProtEntry = UnitTestFindProtocolEntry (Protocol, FALSE);
+  if (ProtEntry != NULL) {
+
+    //
+    // Look at each protocol interface for any matches
+    //
+    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {
+
+      //
+      // If this protocol interface matches, remove it
+      //
+      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+      if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {
+        break;
+      }
+
+      Prot = NULL;
+    }
+  }
+
+  return Prot;
+}
+
+/**
+  Signal event for every protocol in protocol entry.
+
+  @param  ProtEntry              Protocol entry
+
+**/
+VOID
+UnitTestNotifyProtocolEntry (
+  IN PROTOCOL_ENTRY   *ProtEntry
+  )
+{
+  PROTOCOL_NOTIFY     *ProtNotify;
+  LIST_ENTRY          *Link;
+
+  for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
+    ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+    UnitTestSignalEvent (ProtNotify->Event);
+  }
+}
+
+/**
+  Routine to get the next Handle, when you are searching for all handles.
+
+  @param  Position               Information about which Handle to seach for.
+  @param  Interface              Return the interface structure for the matching
+                                 protocol.
+
+  @return An pointer to IHANDLE if the next Position is not the end of the list.
+          Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+UnitTestGetNextLocateAllHandles (
+  IN OUT LOCATE_POSITION    *Position,
+  OUT VOID                  **Interface
+  )
+{
+  IHANDLE     *Handle;
+
+  //
+  // Next handle
+  //
+  Position->Position = Position->Position->ForwardLink;
+
+  //
+  // If not at the end of the list, get the handle
+  //
+  Handle      = NULL;
+  *Interface  = NULL;
+  if (Position->Position != &gHandleList) {
+    Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+  }
+
+  return Handle;
+}
+
+/**
+  Routine to get the next Handle, when you are searching for register protocol
+  notifies.
+
+  @param  Position               Information about which Handle to seach for.
+  @param  Interface              Return the interface structure for the matching
+                                 protocol.
+
+  @return An pointer to IHANDLE if the next Position is not the end of the list.
+          Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+UnitTestGetNextLocateByRegisterNotify (
+  IN OUT LOCATE_POSITION    *Position,
+  OUT VOID                  **Interface
+  )
+{
+  IHANDLE             *Handle;
+  PROTOCOL_NOTIFY     *ProtNotify;
+  PROTOCOL_INTERFACE  *Prot;
+  LIST_ENTRY          *Link;
+
+  Handle      = NULL;
+  *Interface  = NULL;
+  ProtNotify = Position->SearchKey;
+
+  //
+  // If this is the first request, get the next handle
+  //
+  if (ProtNotify != NULL) {
+    ASSERT (ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
+    Position->SearchKey = NULL;
+
+    //
+    // If not at the end of the list, get the next handle
+    //
+    Link = ProtNotify->Position->ForwardLink;
+    if (Link != &ProtNotify->Protocol->Protocols) {
+      Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
+      Handle = Prot->Handle;
+      *Interface = Prot->Interface;
+    }
+  }
+
+  return Handle;
+}
+
+
+/**
+  Routine to get the next Handle, when you are searching for a given protocol.
+
+  @param  Position               Information about which Handle to seach for.
+  @param  Interface              Return the interface structure for the matching
+                                 protocol.
+
+  @return An pointer to IHANDLE if the next Position is not the end of the list.
+          Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+UnitTestGetNextLocateByProtocol (
+  IN OUT LOCATE_POSITION    *Position,
+  OUT VOID                  **Interface
+  )
+{
+  IHANDLE             *Handle;
+  LIST_ENTRY          *Link;
+  PROTOCOL_INTERFACE  *Prot;
+
+  Handle      = NULL;
+  *Interface  = NULL;
+  for (; ;) {
+    //
+    // Next entry
+    //
+    Link = Position->Position->ForwardLink;
+    Position->Position = Link;
+
+    //
+    // If not at the end, return the handle
+    //
+    if (Link == &Position->ProtEntry->Protocols) {
+      Handle = NULL;
+      break;
+    }
+
+    //
+    // Get the handle
+    //
+    Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
+    Handle = Prot->Handle;
+    *Interface = Prot->Interface;
+
+    //
+    // If this handle has not been returned this request, then
+    // return it now
+    //
+    if (Handle->LocateRequest != mEfiLocateHandleRequest) {
+      Handle->LocateRequest = mEfiLocateHandleRequest;
+      break;
+    }
+  }
+
+  return Handle;
+}
+
+/**
+  Attempts to disconnect all drivers that are using the protocol interface being queried.
+  If failed, reconnect all drivers disconnected.
+  Note: This function doesn't do parameters checking, it's caller's responsibility
+  to pass in valid parameters.
+
+  @param  UserHandle             The handle on which the protocol is installed
+  @param  Prot                   The protocol to disconnect drivers from
+
+  @retval EFI_SUCCESS            Drivers using the protocol interface are all
+                                 disconnected
+  @retval EFI_ACCESS_DENIED      Failed to disconnect one or all of the drivers
+
+**/
+EFI_STATUS
+UnitTestDisconnectControllersUsingProtocolInterface (
+  IN EFI_HANDLE           UserHandle,
+  IN PROTOCOL_INTERFACE   *Prot
+  )
+{
+  EFI_STATUS            Status;
+  BOOLEAN               ItemFound;
+  LIST_ENTRY            *Link;
+  OPEN_PROTOCOL_DATA    *OpenData;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Attempt to disconnect all drivers from this protocol interface
+  //
+  do {
+    ItemFound = FALSE;
+    for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
+      OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+      if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+        Status = UnitTestDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
+        if (!EFI_ERROR (Status)) {
+          ItemFound = TRUE;
+        }
+        break;
+      }
+    }
+  } while (ItemFound);
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // Attempt to remove BY_HANDLE_PROTOCOL and GET_PROTOCOL and TEST_PROTOCOL Open List items
+    //
+    for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {
+      OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+      if ((OpenData->Attributes &
+          (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) {
+        Link = RemoveEntryList (&OpenData->Link);
+        Prot->OpenListCount--;
+        FreePool (OpenData);
+      } else {
+        Link = Link->ForwardLink;
+      }
+    }
+  }
+
+  //
+  // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
+  //
+  if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
+    UnitTestConnectController (UserHandle, NULL, NULL, TRUE);
+    Status = EFI_ACCESS_DENIED;
+  }
+
+  return Status;
+}
+
+/**
+  Removes Protocol from the protocol list (but not the handle list).
+
+  @param  Handle                 The handle to remove protocol on.
+  @param  Protocol               GUID of the protocol to be moved
+  @param  Interface              The interface of the protocol
+
+  @return Protocol Entry
+
+**/
+PROTOCOL_INTERFACE *
+UnitTestRemoveInterfaceFromProtocol (
+  IN IHANDLE        *Handle,
+  IN EFI_GUID       *Protocol,
+  IN VOID           *Interface
+  )
+{
+  PROTOCOL_INTERFACE  *Prot;
+  PROTOCOL_NOTIFY     *ProtNotify;
+  PROTOCOL_ENTRY      *ProtEntry;
+  LIST_ENTRY          *Link;
+
+  Prot = UnitTestFindProtocolInterface (Handle, Protocol, Interface);
+  if (Prot != NULL) {
+
+    ProtEntry = Prot->Protocol;
+
+    //
+    // If there's a protocol notify location pointing to this entry, back it up one
+    //
+    for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
+      ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+
+      if (ProtNotify->Position == &Prot->ByProtocol) {
+        ProtNotify->Position = Prot->ByProtocol.BackLink;
+      }
+    }
+
+    //
+    // Remove the protocol interface entry
+    //
+    RemoveEntryList (&Prot->ByProtocol);
+  }
+
+  return Prot;
+}
+
+//
+// Boot Services Function Implementation
+//
+
+/**
+  Locate a certain GUID protocol interface in a Handle's protocols.
+
+  @param  UserHandle             The handle to obtain the protocol interface on
+  @param  Protocol               The GUID of the protocol
+
+  @return The requested protocol interface for the handle
+
+**/
+PROTOCOL_INTERFACE  *
+UnitTestGetProtocolInterface (
+  IN  EFI_HANDLE                UserHandle,
+  IN  EFI_GUID                  *Protocol
+  )
+{
+  EFI_STATUS          Status;
+  PROTOCOL_ENTRY      *ProtEntry;
+  PROTOCOL_INTERFACE  *Prot;
+  IHANDLE             *Handle;
+  LIST_ENTRY          *Link;
+
+  Status = UnitTestValidateHandle (UserHandle);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  Handle = (IHANDLE *) UserHandle;
+
+  //
+  // Look at each protocol interface for a match
+  //
+  for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+    Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+    ProtEntry = Prot->Protocol;
+    if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
+      return Prot;
+    }
+  }
+  return NULL;
+}
+
+/**
+  Installs a protocol interface into the boot services environment.
+
+  @param  UserHandle             The handle to install the protocol handler on,
+                                 or NULL if a new handle is to be allocated
+  @param  Protocol               The protocol to add to the handle
+  @param  InterfaceType          Indicates whether Interface is supplied in
+                                 native form.
+  @param  Interface              The interface for the protocol being added
+  @param  Notify                 indicates whether notify the notification list
+                                 for this protocol
+
+  @retval EFI_INVALID_PARAMETER  Invalid parameter
+  @retval EFI_OUT_OF_RESOURCES   No enough buffer to allocate
+  @retval EFI_SUCCESS            Protocol interface successfully installed
+
+**/
+EFI_STATUS
+UnitTestInstallProtocolInterfaceNotify (
+  IN OUT EFI_HANDLE     *UserHandle,
+  IN EFI_GUID           *Protocol,
+  IN EFI_INTERFACE_TYPE InterfaceType,
+  IN VOID               *Interface,
+  IN BOOLEAN            Notify
+  )
+{
+  PROTOCOL_INTERFACE  *Prot;
+  PROTOCOL_ENTRY      *ProtEntry;
+  IHANDLE             *Handle;
+  EFI_STATUS          Status;
+  VOID                *ExistingInterface;
+
+  //
+  // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
+  // Also added check for invalid UserHandle and Protocol pointers.
+  //
+  if (UserHandle == NULL || Protocol == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (InterfaceType != EFI_NATIVE_INTERFACE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Print debug message
+  //
+  UT_LOG_INFO ("InstallProtocolInterface: %g %p\n", Protocol, Interface);
+
+  Status = EFI_OUT_OF_RESOURCES;
+  Prot = NULL;
+  Handle = NULL;
+
+  if (*UserHandle != NULL) {
+    Status = UnitTestHandleProtocol (*UserHandle, Protocol, (VOID **) &ExistingInterface);
+    if (!EFI_ERROR (Status)) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // Lookup the Protocol Entry for the requested protocol
+  //
+  ProtEntry = UnitTestFindProtocolEntry (Protocol, TRUE);
+  if (ProtEntry == NULL) {
+    goto Done;
+  }
+
+  //
+  // Allocate a new protocol interface structure
+  //
+  Prot = AllocateZeroPool (sizeof (PROTOCOL_INTERFACE));
+  if (Prot == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  //
+  // If caller didn't supply a handle, allocate a new one
+  //
+  Handle = (IHANDLE *) *UserHandle;
+  if (Handle == NULL) {
+    Handle = AllocateZeroPool (sizeof (IHANDLE));
+    if (Handle == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto Done;
+    }
+
+    //
+    // Initialize new handler structure
+    //
+    Handle->Signature = EFI_HANDLE_SIGNATURE;
+    InitializeListHead (&Handle->Protocols);
+
+    //
+    // Initialize the Key to show that the handle has been created/modified
+    //
+    gHandleDatabaseKey++;
+    Handle->Key = gHandleDatabaseKey;
+
+    //
+    // Add this handle to the list global list of all handles
+    // in the system
+    //
+    InsertTailList (&gHandleList, &Handle->AllHandles);
+  } else {
+    Status =  UnitTestValidateHandle (Handle);
+    if (EFI_ERROR (Status)) {
+      DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));
+      goto Done;
+    }
+  }
+
+  //
+  // Each interface that is added must be unique
+  //
+  ASSERT (UnitTestFindProtocolInterface (Handle, Protocol, Interface) == NULL);
+
+  //
+  // Initialize the protocol interface structure
+  //
+  Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
+  Prot->Handle = Handle;
+  Prot->Protocol = ProtEntry;
+  Prot->Interface = Interface;
+
+  //
+  // Initialize OpenProtocol Data base
+  //
+  InitializeListHead (&Prot->OpenList);
+  Prot->OpenListCount = 0;
+
+  //
+  // Add this protocol interface to the head of the supported
+  // protocol list for this handle
+  //
+  InsertHeadList (&Handle->Protocols, &Prot->Link);
+
+  //
+  // Add this protocol interface to the tail of the
+  // protocol entry
+  //
+  InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
+
+  //
+  // Notify the notification list for this protocol
+  //
+  if (Notify) {
+    UnitTestNotifyProtocolEntry (ProtEntry);
+  }
+  Status = EFI_SUCCESS;
+
+Done:
+  if (!EFI_ERROR (Status)) {
+    //
+    // Return the new handle back to the caller
+    //
+    *UserHandle = Handle;
+  } else {
+    //
+    // There was an error, clean up
+    //
+    if (Prot != NULL) {
+      UnitTestFreePool (Prot);
+    }
+    DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));
+  }
+
+  return Status;
+}
+
+/**
+  Wrapper function to UnitTestInstallProtocolInterfaceNotify.  This is the public API which
+  Calls the private one which contains a BOOLEAN parameter for notifications
+
+  @param  UserHandle             The handle to install the protocol handler on,
+                                 or NULL if a new handle is to be allocated
+  @param  Protocol               The protocol to add to the handle
+  @param  InterfaceType          Indicates whether Interface is supplied in
+                                 native form.
+  @param  Interface              The interface for the protocol being added
+
+  @return Status code
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestInstallProtocolInterface (
+  IN OUT EFI_HANDLE     *UserHandle,
+  IN EFI_GUID           *Protocol,
+  IN EFI_INTERFACE_TYPE InterfaceType,
+  IN VOID               *Interface
+  )
+{
+  return UnitTestInstallProtocolInterfaceNotify (
+            UserHandle,
+            Protocol,
+            InterfaceType,
+            Interface,
+            TRUE
+            );
+}
+
+/**
+  Reinstall a protocol interface on a device handle.  The OldInterface for Protocol is replaced by the NewInterface.
+
+  @param  UserHandle             Handle on which the interface is to be
+                                 reinstalled
+  @param  Protocol               The numeric ID of the interface
+  @param  OldInterface           A pointer to the old interface
+  @param  NewInterface           A pointer to the new interface
+
+  @retval EFI_SUCCESS            The protocol interface was installed
+  @retval EFI_NOT_FOUND          The OldInterface on the handle was not found
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestReinstallProtocolInterface (
+  IN EFI_HANDLE     UserHandle,
+  IN EFI_GUID       *Protocol,
+  IN VOID           *OldInterface,
+  IN VOID           *NewInterface
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Uninstalls all instances of a protocol:interfacer from a handle.
+  If the last protocol interface is remove from the handle, the
+  handle is freed.
+
+  @param  UserHandle             The handle to remove the protocol handler from
+  @param  Protocol               The protocol, of protocol:interface, to remove
+  @param  Interface              The interface, of protocol:interface, to remove
+
+  @retval EFI_INVALID_PARAMETER  Protocol is NULL.
+  @retval EFI_SUCCESS            Protocol interface successfully uninstalled.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestUninstallProtocolInterface (
+  IN EFI_HANDLE       UserHandle,
+  IN EFI_GUID         *Protocol,
+  IN VOID             *Interface
+  )
+{
+  EFI_STATUS            Status;
+  IHANDLE               *Handle;
+  PROTOCOL_INTERFACE    *Prot;
+
+  //
+  // Check that Protocol is valid
+  //
+  if (Protocol == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check that UserHandle is a valid handle
+  //
+  Status = UnitTestValidateHandle (UserHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
+  //
+  Prot = UnitTestFindProtocolInterface (UserHandle, Protocol, Interface);
+  if (Prot == NULL) {
+    Status = EFI_NOT_FOUND;
+    goto Done;
+  }
+
+  //
+  // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
+  //
+  Status = UnitTestDisconnectControllersUsingProtocolInterface (
+             UserHandle,
+             Prot
+             );
+  if (EFI_ERROR (Status)) {
+    //
+    // One or more drivers refused to release, so return the error
+    //
+    goto Done;
+  }
+
+  //
+  // Remove the protocol interface from the protocol
+  //
+  Status = EFI_NOT_FOUND;
+  Handle = (IHANDLE *) UserHandle;
+  Prot   = UnitTestRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
+
+  if (Prot != NULL) {
+    //
+    // Update the Key to show that the handle has been created/modified
+    //
+    gHandleDatabaseKey++;
+    Handle->Key = gHandleDatabaseKey;
+
+    //
+    // Remove the protocol interface from the handle
+    //
+    RemoveEntryList (&Prot->Link);
+
+    //
+    // Free the memory
+    //
+    Prot->Signature = 0;
+    FreePool (Prot);
+    Status = EFI_SUCCESS;
+  }
+
+  //
+  // If there are no more handlers for the handle, free the handle
+  //
+  if (IsListEmpty (&Handle->Protocols)) {
+    Handle->Signature = 0;
+    RemoveEntryList (&Handle->AllHandles);
+    FreePool (Handle);
+  }
+
+Done:
+  return Status;
+}
+
+/**
+  Queries a handle to determine if it supports a specified protocol.
+
+  @param  UserHandle             The handle being queried.
+  @param  Protocol               The published unique identifier of the protocol.
+  @param  Interface              Supplies the address where a pointer to the
+                                 corresponding Protocol Interface is returned.
+
+  @return The requested protocol interface for the handle
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestHandleProtocol (
+  IN EFI_HANDLE       UserHandle,
+  IN EFI_GUID         *Protocol,
+  OUT VOID            **Interface
+  )
+{
+  return  UnitTestOpenProtocol (
+            UserHandle,
+            Protocol,
+            Interface,
+            gImageHandle,
+            NULL,
+            EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+            );
+}
+
+/**
+  Add a new protocol notification record for the request protocol.
+
+  @param  Protocol               The requested protocol to add the notify
+                                 registration
+  @param  Event                  The event to signal
+  @param  Registration           Returns the registration record
+
+  @retval EFI_INVALID_PARAMETER  Invalid parameter
+  @retval EFI_SUCCESS            Successfully returned the registration record
+                                 that has been added
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestRegisterProtocolNotify (
+  IN EFI_GUID       *Protocol,
+  IN EFI_EVENT      Event,
+  OUT  VOID         **Registration
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Locates the requested handle(s) and returns them in Buffer.
+
+  @param  SearchType             The type of search to perform to locate the
+                                 handles
+  @param  Protocol               The protocol to search for
+  @param  SearchKey              Dependant on SearchType
+  @param  BufferSize             On input the size of Buffer.  On output the
+                                 size of data returned.
+  @param  Buffer                 The buffer to return the results in
+
+  @retval EFI_BUFFER_TOO_SMALL   Buffer too small, required buffer size is
+                                 returned in BufferSize.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter
+  @retval EFI_SUCCESS            Successfully found the requested handle(s) and
+                                 returns them in Buffer.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLocateHandle (
+  IN EFI_LOCATE_SEARCH_TYPE   SearchType,
+  IN EFI_GUID                 *Protocol   OPTIONAL,
+  IN VOID                     *SearchKey  OPTIONAL,
+  IN OUT UINTN                *BufferSize,
+  OUT EFI_HANDLE              *Buffer
+  )
+{
+  EFI_STATUS          Status;
+  LOCATE_POSITION     Position;
+  PROTOCOL_NOTIFY     *ProtNotify;
+  UNIT_TEST_GET_NEXT  GetNext;
+  UINTN               ResultSize;
+  IHANDLE             *Handle;
+  IHANDLE             **ResultBuffer;
+  VOID                *Interface;
+
+  if (BufferSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((*BufferSize > 0) && (Buffer == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  GetNext = NULL;
+
+  //
+  // Set initial position
+  //
+  Position.Protocol  = Protocol;
+  Position.SearchKey = SearchKey;
+  Position.Position  = &gHandleList;
+
+  ResultSize = 0;
+  ResultBuffer = (IHANDLE **) Buffer;
+  Status = EFI_SUCCESS;
+
+  //
+  // Get the search function based on type
+  //
+  switch (SearchType) {
+  case AllHandles:
+    GetNext = UnitTestGetNextLocateAllHandles;
+    break;
+
+  case ByRegisterNotify:
+    //
+    // Must have SearchKey for locate ByRegisterNotify
+    //
+    if (SearchKey == NULL) {
+      Status = EFI_INVALID_PARAMETER;
+      break;
+    }
+    GetNext = UnitTestGetNextLocateByRegisterNotify;
+    break;
+
+  case ByProtocol:
+    GetNext = UnitTestGetNextLocateByProtocol;
+    if (Protocol == NULL) {
+      Status = EFI_INVALID_PARAMETER;
+      break;
+    }
+    //
+    // Look up the protocol entry and set the head pointer
+    //
+    Position.ProtEntry = UnitTestFindProtocolEntry (Protocol, FALSE);
+    if (Position.ProtEntry == NULL) {
+      Status = EFI_NOT_FOUND;
+      break;
+    }
+    Position.Position = &Position.ProtEntry->Protocols;
+    break;
+
+  default:
+    Status = EFI_INVALID_PARAMETER;
+    break;
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ASSERT (GetNext != NULL);
+  //
+  // Enumerate out the matching handles
+  //
+  mEfiLocateHandleRequest += 1;
+  for (; ;) {
+    //
+    // Get the next handle.  If no more handles, stop
+    //
+    Handle = GetNext (&Position, &Interface);
+    if (NULL == Handle) {
+      break;
+    }
+
+    //
+    // Increase the resulting buffer size, and if this handle
+    // fits return it
+    //
+    ResultSize += sizeof (Handle);
+    if (ResultSize <= *BufferSize) {
+        *ResultBuffer = Handle;
+        ResultBuffer += 1;
+    }
+  }
+
+  //
+  // If the result is a zero length buffer, then there were no
+  // matching handles
+  //
+  if (ResultSize == 0) {
+    Status = EFI_NOT_FOUND;
+  } else {
+    //
+    // Return the resulting buffer size.  If it's larger than what
+    // was passed, then set the error code
+    //
+    if (ResultSize > *BufferSize) {
+      Status = EFI_BUFFER_TOO_SMALL;
+    }
+
+    *BufferSize = ResultSize;
+
+    if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {
+      //
+      // If this is a search by register notify and a handle was
+      // returned, update the register notification position
+      //
+      ASSERT (SearchKey != NULL);
+      ProtNotify = SearchKey;
+      ProtNotify->Position = ProtNotify->Position->ForwardLink;
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Locates the handle to a device on the device path that best matches the specified protocol.
+
+  @param  Protocol               The protocol to search for.
+  @param  DevicePath             On input, a pointer to a pointer to the device
+                                 path. On output, the device path pointer is
+                                 modified to point to the remaining part of the
+                                 devicepath.
+  @param  Device                 A pointer to the returned device handle.
+
+  @retval EFI_SUCCESS            The resulting handle was returned.
+  @retval EFI_NOT_FOUND          No handles matched the search.
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLocateDevicePath (
+  IN EFI_GUID                       *Protocol,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL   **DevicePath,
+  OUT EFI_HANDLE                    *Device
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Boot Service called to add, modify, or remove a system configuration table from
+  the EFI System Table.
+
+  @param  Guid           Pointer to the GUID for the entry to add, update, or
+                         remove
+  @param  Table          Pointer to the configuration table for the entry to add,
+                         update, or remove, may be NULL.
+
+  @return EFI_SUCCESS               Guid, Table pair added, updated, or removed.
+  @return EFI_INVALID_PARAMETER     Input GUID not valid.
+  @return EFI_NOT_FOUND             Attempted to delete non-existant entry
+  @return EFI_OUT_OF_RESOURCES      Not enough memory available
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestInstallConfigurationTable (
+  IN EFI_GUID *Guid,
+  IN VOID     *Table
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Locates the installed protocol handler for the handle, and
+  invokes it to obtain the protocol interface. Usage information
+  is registered in the protocol data base.
+
+  @param  UserHandle             The handle to obtain the protocol interface on
+  @param  Protocol               The ID of the protocol
+  @param  Interface              The location to return the protocol interface
+  @param  ImageHandle            The handle of the Image that is opening the
+                                 protocol interface specified by Protocol and
+                                 Interface.
+  @param  ControllerHandle       The controller handle that is requiring this
+                                 interface.
+  @param  Attributes             The open mode of the protocol interface
+                                 specified by Handle and Protocol.
+
+  @retval EFI_INVALID_PARAMETER  Protocol is NULL.
+  @retval EFI_SUCCESS            Get the protocol interface.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestOpenProtocol (
+  IN  EFI_HANDLE                UserHandle,
+  IN  EFI_GUID                  *Protocol,
+  OUT VOID                      **Interface OPTIONAL,
+  IN  EFI_HANDLE                ImageHandle,
+  IN  EFI_HANDLE                ControllerHandle,
+  IN  UINT32                    Attributes
+  )
+{
+  EFI_STATUS          Status;
+  PROTOCOL_INTERFACE  *Prot;
+  LIST_ENTRY          *Link;
+  OPEN_PROTOCOL_DATA  *OpenData;
+  BOOLEAN             ByDriver;
+  BOOLEAN             Exclusive;
+  BOOLEAN             Disconnect;
+  BOOLEAN             ExactMatch;
+
+  //
+  // Check for invalid Protocol
+  //
+  if (Protocol == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check for invalid Interface
+  //
+  if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check for invalid UserHandle
+  //
+  Status =  UnitTestValidateHandle (UserHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Check for invalid Attributes
+  //
+  switch (Attributes) {
+  case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
+    Status =  UnitTestValidateHandle (ImageHandle);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    Status =  UnitTestValidateHandle (ControllerHandle);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    if (UserHandle == ControllerHandle) {
+      return EFI_INVALID_PARAMETER;
+    }
+    break;
+  case EFI_OPEN_PROTOCOL_BY_DRIVER :
+  case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
+    Status =  UnitTestValidateHandle (ImageHandle);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    Status =  UnitTestValidateHandle (ControllerHandle);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    break;
+  case EFI_OPEN_PROTOCOL_EXCLUSIVE :
+    Status =  UnitTestValidateHandle (ImageHandle);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    break;
+  case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
+  case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
+  case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Look at each protocol interface for a match
+  //
+  Prot = UnitTestGetProtocolInterface (UserHandle, Protocol);
+  if (Prot == NULL) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
+  Status = EFI_SUCCESS;
+
+  ByDriver        = FALSE;
+  Exclusive       = FALSE;
+  for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
+    OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+    ExactMatch =  (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
+                            (OpenData->Attributes == Attributes)  &&
+                            (OpenData->ControllerHandle == ControllerHandle));
+    if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+      ByDriver = TRUE;
+      if (ExactMatch) {
+        Status = EFI_ALREADY_STARTED;
+        goto Done;
+      }
+    }
+    if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
+      Exclusive = TRUE;
+    } else if (ExactMatch) {
+      OpenData->OpenCount++;
+      Status = EFI_SUCCESS;
+      goto Done;
+    }
+  }
+
+  //
+  // ByDriver  TRUE  -> A driver is managing (UserHandle, Protocol)
+  // ByDriver  FALSE -> There are no drivers managing (UserHandle, Protocol)
+  // Exclusive TRUE  -> Something has exclusive access to (UserHandle, Protocol)
+  // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
+  //
+
+  switch (Attributes) {
+  case EFI_OPEN_PROTOCOL_BY_DRIVER :
+    if (Exclusive || ByDriver) {
+      Status = EFI_ACCESS_DENIED;
+      goto Done;
+    }
+    break;
+  case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
+  case EFI_OPEN_PROTOCOL_EXCLUSIVE :
+    if (Exclusive) {
+      Status = EFI_ACCESS_DENIED;
+      goto Done;
+    }
+    if (ByDriver) {
+      do {
+        Disconnect = FALSE;
+        for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
+          OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+            Disconnect = TRUE;
+            Status = UnitTestDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
+            if (EFI_ERROR (Status)) {
+              Status = EFI_ACCESS_DENIED;
+              goto Done;
+            } else {
+              break;
+            }
+          }
+        }
+      } while (Disconnect);
+    }
+    break;
+  case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
+  case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
+  case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
+  case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
+    break;
+  }
+
+  if (ImageHandle == NULL) {
+    Status = EFI_SUCCESS;
+    goto Done;
+  }
+  //
+  // Create new entry
+  //
+  OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));
+  if (OpenData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+  } else {
+    OpenData->Signature         = OPEN_PROTOCOL_DATA_SIGNATURE;
+    OpenData->AgentHandle       = ImageHandle;
+    OpenData->ControllerHandle  = ControllerHandle;
+    OpenData->Attributes        = Attributes;
+    OpenData->OpenCount         = 1;
+    InsertTailList (&Prot->OpenList, &OpenData->Link);
+    Prot->OpenListCount++;
+    Status = EFI_SUCCESS;
+  }
+
+Done:
+
+  if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
+    //
+    // Keep Interface unmodified in case of any Error
+    // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.
+    //
+    if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {
+      //
+      // According to above logic, if 'Prot' is NULL, then the 'Status' must be
+      // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'
+      // must be not NULL.
+      //
+      // The ASSERT here is for addressing a false positive NULL pointer
+      // dereference issue raised from static analysis.
+      //
+      ASSERT (Prot != NULL);
+      //
+      // EFI_ALREADY_STARTED is not an error for bus driver.
+      // Return the corresponding protocol interface.
+      //
+      *Interface = Prot->Interface;
+    } else if (Status == EFI_UNSUPPORTED) {
+      //
+      // Return NULL Interface if Unsupported Protocol.
+      //
+      *Interface = NULL;
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Closes a protocol on a handle that was opened using OpenProtocol().
+
+  @param  UserHandle             The handle for the protocol interface that was
+                                 previously opened with OpenProtocol(), and is
+                                 now being closed.
+  @param  Protocol               The published unique identifier of the protocol.
+                                 It is the caller's responsibility to pass in a
+                                 valid GUID.
+  @param  AgentHandle            The handle of the agent that is closing the
+                                 protocol interface.
+  @param  ControllerHandle       If the agent that opened a protocol is a driver
+                                 that follows the EFI Driver Model, then this
+                                 parameter is the controller handle that required
+                                 the protocol interface. If the agent does not
+                                 follow the EFI Driver Model, then this parameter
+                                 is optional and may be NULL.
+
+  @retval EFI_SUCCESS            The protocol instance was closed.
+  @retval EFI_INVALID_PARAMETER  Handle, AgentHandle or ControllerHandle is not a
+                                 valid EFI_HANDLE.
+  @retval EFI_NOT_FOUND          Can not find the specified protocol or
+                                 AgentHandle.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCloseProtocol (
+  IN  EFI_HANDLE                UserHandle,
+  IN  EFI_GUID                  *Protocol,
+  IN  EFI_HANDLE                AgentHandle,
+  IN  EFI_HANDLE                ControllerHandle
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Return information about Opened protocols in the system
+
+  @param  UserHandle             The handle to close the protocol interface on
+  @param  Protocol               The ID of the protocol
+  @param  EntryBuffer            A pointer to a buffer of open protocol
+                                 information in the form of
+                                 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
+  @param  EntryCount             Number of EntryBuffer entries
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestOpenProtocolInformation (
+  IN  EFI_HANDLE                          UserHandle,
+  IN  EFI_GUID                            *Protocol,
+  OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
+  OUT UINTN                               *EntryCount
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
+  from pool.
+
+  @param  UserHandle             The handle from which to retrieve the list of
+                                 protocol interface GUIDs.
+  @param  ProtocolBuffer         A pointer to the list of protocol interface GUID
+                                 pointers that are installed on Handle.
+  @param  ProtocolBufferCount    A pointer to the number of GUID pointers present
+                                 in ProtocolBuffer.
+
+  @retval EFI_SUCCESS            The list of protocol interface GUIDs installed
+                                 on Handle was returned in ProtocolBuffer. The
+                                 number of protocol interface GUIDs was returned
+                                 in ProtocolBufferCount.
+  @retval EFI_INVALID_PARAMETER  Handle is NULL.
+  @retval EFI_INVALID_PARAMETER  Handle is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER  ProtocolBuffer is NULL.
+  @retval EFI_INVALID_PARAMETER  ProtocolBufferCount is NULL.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough pool memory to store the
+                                 results.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestProtocolsPerHandle (
+  IN EFI_HANDLE       UserHandle,
+  OUT EFI_GUID        ***ProtocolBuffer,
+  OUT UINTN           *ProtocolBufferCount
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Function returns an array of handles that support the requested protocol
+  in a buffer allocated from pool. This is a version of UnitTestLocateHandle()
+  that allocates a buffer for the caller.
+
+  @param  SearchType             Specifies which handle(s) are to be returned.
+  @param  Protocol               Provides the protocol to search by.    This
+                                 parameter is only valid for SearchType
+                                 ByProtocol.
+  @param  SearchKey              Supplies the search key depending on the
+                                 SearchType.
+  @param  NumberHandles          The number of handles returned in Buffer.
+  @param  Buffer                 A pointer to the buffer to return the requested
+                                 array of  handles that support Protocol.
+
+  @retval EFI_SUCCESS            The result array of handles was returned.
+  @retval EFI_NOT_FOUND          No handles match the search.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough pool memory to store the
+                                 matching results.
+  @retval EFI_INVALID_PARAMETER  One or more parameters are not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLocateHandleBuffer (
+  IN EFI_LOCATE_SEARCH_TYPE       SearchType,
+  IN EFI_GUID                     *Protocol OPTIONAL,
+  IN VOID                         *SearchKey OPTIONAL,
+  IN OUT UINTN                    *NumberHandles,
+  OUT EFI_HANDLE                  **Buffer
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               BufferSize;
+
+  if (NumberHandles == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BufferSize = 0;
+  *NumberHandles = 0;
+  *Buffer = NULL;
+  Status = UnitTestLocateHandle (
+             SearchType,
+             Protocol,
+             SearchKey,
+             &BufferSize,
+             *Buffer
+             );
+  //
+  // LocateHandleBuffer() returns incorrect status code if SearchType is
+  // invalid.
+  //
+  // Add code to correctly handle expected errors from UnitTestLocateHandle().
+  //
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+    if (Status != EFI_INVALID_PARAMETER) {
+      Status = EFI_NOT_FOUND;
+    }
+    return Status;
+  }
+
+  *Buffer = AllocatePool (BufferSize);
+  if (*Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = UnitTestLocateHandle (
+             SearchType,
+             Protocol,
+             SearchKey,
+             &BufferSize,
+             *Buffer
+             );
+
+  *NumberHandles = BufferSize / sizeof (EFI_HANDLE);
+  if (EFI_ERROR (Status)) {
+    *NumberHandles = 0;
+  }
+
+  return Status;
+}
+
+/**
+  Return the first Protocol Interface that matches the Protocol GUID. If
+  Registration is passed in, return a Protocol Instance that was just add
+  to the system. If Registration is NULL return the first Protocol Interface
+  you find.
+
+  @param  Protocol               The protocol to search for
+  @param  Registration           Optional Registration Key returned from
+                                 RegisterProtocolNotify()
+  @param  Interface              Return the Protocol interface (instance).
+
+  @retval EFI_SUCCESS            If a valid Interface is returned
+  @retval EFI_INVALID_PARAMETER  Invalid parameter
+  @retval EFI_NOT_FOUND          Protocol interface not found
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLocateProtocol (
+  IN  EFI_GUID  *Protocol,
+  IN  VOID      *Registration OPTIONAL,
+  OUT VOID      **Interface
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Installs a list of protocol interface into the boot services environment.
+  This function calls InstallProtocolInterface() in a loop. If any error
+  occurs all the protocols added by this function are removed. This is
+  basically a lib function to save space.
+
+  @param  Handle                 The handle to install the protocol handlers on,
+                                 or NULL if a new handle is to be allocated
+  @param  ...                    EFI_GUID followed by protocol instance. A NULL
+                                 terminates the  list. The pairs are the
+                                 arguments to InstallProtocolInterface(). All the
+                                 protocols are added to Handle.
+
+  @retval EFI_SUCCESS            All the protocol interface was installed.
+  @retval EFI_OUT_OF_RESOURCES   There was not enough memory in pool to install all the protocols.
+  @retval EFI_ALREADY_STARTED    A Device Path Protocol instance was passed in that is already present in
+                                 the handle database.
+  @retval EFI_INVALID_PARAMETER  Handle is NULL.
+  @retval EFI_INVALID_PARAMETER  Protocol is already installed on the handle specified by Handle.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestInstallMultipleProtocolInterfaces (
+  IN OUT EFI_HANDLE           *Handle,
+  ...
+  )
+{
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Uninstalls a list of protocol interface in the boot services environment.
+  This function calls UninstallProtocolInterface() in a loop. This is
+  basically a lib function to save space.
+
+  @param  Handle                 The handle to uninstall the protocol
+  @param  ...                    EFI_GUID followed by protocol instance. A NULL
+                                 terminates the  list. The pairs are the
+                                 arguments to UninstallProtocolInterface(). All
+                                 the protocols are added to Handle.
+
+  @return Status code
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestUninstallMultipleProtocolInterfaces (
+  IN EFI_HANDLE           Handle,
+  ...
+  )
+{
+  EFI_STATUS      Status;
+  VA_LIST         Args;
+  EFI_GUID        *Protocol;
+  VOID            *Interface;
+  UINTN           Index;
+
+  VA_START (Args, Handle);
+  for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+    //
+    // If protocol is NULL, then it's the end of the list
+    //
+    Protocol = VA_ARG (Args, EFI_GUID *);
+    if (Protocol == NULL) {
+      break;
+    }
+
+    Interface = VA_ARG (Args, VOID *);
+
+    //
+    // Uninstall it
+    //
+    Status = UnitTestUninstallProtocolInterface (Handle, Protocol, Interface);
+  }
+  VA_END (Args);
+
+  //
+  // If there was an error, add all the interfaces that were
+  // uninstalled without any errors
+  //
+  if (EFI_ERROR (Status)) {
+    //
+    // Reset the va_arg back to the first argument.
+    //
+    VA_START (Args, Handle);
+    for (; Index > 1; Index--) {
+      Protocol = VA_ARG(Args, EFI_GUID *);
+      Interface = VA_ARG(Args, VOID *);
+      UnitTestInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
+    }
+    VA_END (Args);
+    Status = EFI_INVALID_PARAMETER;
+  }
+
+  return Status;
+}
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestTpl.c b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestTpl.c
new file mode 100644
index 000000000000..7e1849fbd4a9
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestTpl.c
@@ -0,0 +1,43 @@
+/** @file
+  Implementation of Task Priority Level (TPL) related services in the UEFI Boot Services table for use in unit tests.
+
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiBootServicesTableLibUnitTest.h"
+
+/**
+  Raise the task priority level to the new level.
+  High level is implemented by disabling processor interrupts.
+
+  @param  NewTpl  New task priority level
+
+  @return The previous task priority level
+
+**/
+EFI_TPL
+EFIAPI
+UnitTestRaiseTpl (
+  IN EFI_TPL      NewTpl
+  )
+{
+  return TPL_APPLICATION;
+}
+
+/**
+  Lowers the task priority to the previous value.   If the new
+  priority unmasks events at a higher priority, they are dispatched.
+
+  @param  NewTpl  New, lower, task priority
+
+**/
+VOID
+EFIAPI
+UnitTestRestoreTpl (
+  IN EFI_TPL NewTpl
+  )
+{
+  return;
+}
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index 5241354cb220..911158302404 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -93,6 +93,7 @@ [Components]
   $(PLATFORM_PACKAGE)/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
   $(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf
   $(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareAccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
+  $(PLATFORM_PACKAGE)/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
 
   #
   # PRM Module Discovery Library
diff --git a/PrmPkg/Test/PrmPkgHostTest.dsc b/PrmPkg/Test/PrmPkgHostTest.dsc
index 41f3c32b8d19..2d718f8888b8 100644
--- a/PrmPkg/Test/PrmPkgHostTest.dsc
+++ b/PrmPkg/Test/PrmPkgHostTest.dsc
@@ -15,3 +15,14 @@ [Defines]
   SUPPORTED_ARCHITECTURES = IA32|X64
   BUILD_TARGETS           = NOOPT
   SKUID_IDENTIFIER        = DEFAULT
+
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+
+[LibraryClasses]
+  UefiBootServicesTableLib|PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
+
+[Components]
+  #
+  # Unit test helper libraries
+  #
+  PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibTest.uni b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibTest.uni
new file mode 100644
index 000000000000..1f742bb6d8e9
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibTest.uni
@@ -0,0 +1,12 @@
+// /** @file
+// UEFI Boot Services Table Library for unit tests implementation.
+//
+// Copyright (c) Microsoft Corporation
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "UEFI Boot Services Table Library for unit tests"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "UEFI Boot Services Table Library for unit tests."
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.h b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.h
new file mode 100644
index 000000000000..687508cf1faf
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.h
@@ -0,0 +1,1046 @@
+/** @file
+  An internal header file for the Unit Test instance of the UEFI Boot Services Table Library.
+
+  This file includes common header files, defines internal structure and functions used by
+  the library implementation.
+
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef UEFI_BOOT_SERVICES_TABLE_LIB_UNIT_TEST_H_
+#define UEFI_BOOT_SERVICES_TABLE_LIB_UNIT_TEST_H_
+
+#include <Uefi.h>
+
+#include <Pi/PiMultiPhase.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+  Raise the task priority level to the new level.
+  High level is implemented by disabling processor interrupts.
+
+  @param  NewTpl  New task priority level
+
+  @return The previous task priority level
+
+**/
+EFI_TPL
+EFIAPI
+UnitTestRaiseTpl (
+  IN EFI_TPL      NewTpl
+  );
+
+
+
+/**
+  Lowers the task priority to the previous value.   If the new
+  priority unmasks events at a higher priority, they are dispatched.
+
+  @param  NewTpl  New, lower, task priority
+
+**/
+VOID
+EFIAPI
+UnitTestRestoreTpl (
+  IN EFI_TPL NewTpl
+  );
+
+/**
+  Allocates pages from the memory map.
+
+  @param  Type                   The type of allocation to perform
+  @param  MemoryType             The type of memory to turn the allocated pages
+                                 into
+  @param  NumberOfPages          The number of pages to allocate
+  @param  Memory                 A pointer to receive the base allocated memory
+                                 address
+
+  @return Status. On success, Memory is filled in with the base address allocated
+  @retval EFI_INVALID_PARAMETER  Parameters violate checking rules defined in
+                                 spec.
+  @retval EFI_NOT_FOUND          Could not allocate pages match the requirement.
+  @retval EFI_OUT_OF_RESOURCES   No enough pages to allocate.
+  @retval EFI_SUCCESS            Pages successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestAllocatePages (
+  IN EFI_ALLOCATE_TYPE      Type,
+  IN EFI_MEMORY_TYPE        MemoryType,
+  IN UINTN                  NumberOfPages,
+  IN OUT EFI_PHYSICAL_ADDRESS  *Memory
+  );
+
+/**
+  Frees previous allocated pages.
+
+  @param  Memory                 Base address of memory being freed
+  @param  NumberOfPages          The number of pages to free
+
+  @retval EFI_NOT_FOUND          Could not find the entry that covers the range
+  @retval EFI_INVALID_PARAMETER  Address not aligned
+  @return EFI_SUCCESS         -Pages successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestFreePages (
+  IN EFI_PHYSICAL_ADDRESS   Memory,
+  IN UINTN                  NumberOfPages
+  );
+
+/**
+  This function returns a copy of the current memory map. The map is an array of
+  memory descriptors, each of which describes a contiguous block of memory.
+
+  @param  MemoryMapSize          A pointer to the size, in bytes, of the
+                                 MemoryMap buffer. On input, this is the size of
+                                 the buffer allocated by the caller.  On output,
+                                 it is the size of the buffer returned by the
+                                 firmware  if the buffer was large enough, or the
+                                 size of the buffer needed  to contain the map if
+                                 the buffer was too small.
+  @param  MemoryMap              A pointer to the buffer in which firmware places
+                                 the current memory map.
+  @param  MapKey                 A pointer to the location in which firmware
+                                 returns the key for the current memory map.
+  @param  DescriptorSize         A pointer to the location in which firmware
+                                 returns the size, in bytes, of an individual
+                                 EFI_MEMORY_DESCRIPTOR.
+  @param  DescriptorVersion      A pointer to the location in which firmware
+                                 returns the version number associated with the
+                                 EFI_MEMORY_DESCRIPTOR.
+
+  @retval EFI_SUCCESS            The memory map was returned in the MemoryMap
+                                 buffer.
+  @retval EFI_BUFFER_TOO_SMALL   The MemoryMap buffer was too small. The current
+                                 buffer size needed to hold the memory map is
+                                 returned in MemoryMapSize.
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestGetMemoryMap (
+  IN OUT UINTN                  *MemoryMapSize,
+  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
+  OUT UINTN                     *MapKey,
+  OUT UINTN                     *DescriptorSize,
+  OUT UINT32                    *DescriptorVersion
+  );
+
+
+
+/**
+  Allocate pool of a particular type.
+
+  @param  PoolType               Type of pool to allocate
+  @param  Size                   The amount of pool to allocate
+  @param  Buffer                 The address to return a pointer to the allocated
+                                 pool
+
+  @retval EFI_INVALID_PARAMETER  PoolType not valid or Buffer is NULL
+  @retval EFI_OUT_OF_RESOURCES   Size exceeds max pool size or allocation failed.
+  @retval EFI_SUCCESS            Pool successfully allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestAllocatePool (
+  IN EFI_MEMORY_TYPE  PoolType,
+  IN UINTN            Size,
+  OUT VOID            **Buffer
+  );
+
+/**
+  Frees pool.
+
+  @param  Buffer                 The allocated pool entry to free
+
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.
+  @retval EFI_SUCCESS            Pool successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestFreePool (
+  IN VOID        *Buffer
+  );
+
+/**
+  Frees pool.
+
+  @param  Buffer                 The allocated pool entry to free
+  @param  PoolType               Pointer to pool type
+
+  @retval EFI_INVALID_PARAMETER  Buffer is not a valid value.
+  @retval EFI_SUCCESS            Pool successfully freed.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestInternalFreePool (
+  IN VOID               *Buffer,
+  OUT EFI_MEMORY_TYPE   *PoolType OPTIONAL
+  );
+
+/**
+  Creates an event.
+
+  @param  Type                   The type of event to create and its mode and
+                                 attributes
+  @param  NotifyTpl              The task priority level of event notifications
+  @param  NotifyFunction         Pointer to the events notification function
+  @param  NotifyContext          Pointer to the notification functions context;
+                                 corresponds to parameter "Context" in the
+                                 notification function
+  @param  Event                  Pointer to the newly created event if the call
+                                 succeeds; undefined otherwise
+
+  @retval EFI_SUCCESS            The event structure was created
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value
+  @retval EFI_OUT_OF_RESOURCES   The event could not be allocated
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCreateEvent (
+  IN UINT32                   Type,
+  IN EFI_TPL                  NotifyTpl,
+  IN EFI_EVENT_NOTIFY         NotifyFunction, OPTIONAL
+  IN VOID                     *NotifyContext, OPTIONAL
+  OUT EFI_EVENT               *Event
+  );
+
+/**
+  Sets the type of timer and the trigger time for a timer event.
+
+  @param  UserEvent              The timer event that is to be signaled at the
+                                 specified time
+  @param  Type                   The type of time that is specified in
+                                 TriggerTime
+  @param  TriggerTime            The number of 100ns units until the timer
+                                 expires
+
+  @retval EFI_SUCCESS            The event has been set to be signaled at the
+                                 requested time
+  @retval EFI_INVALID_PARAMETER  Event or Type is not valid
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestSetTimer (
+  IN EFI_EVENT            UserEvent,
+  IN EFI_TIMER_DELAY      Type,
+  IN UINT64               TriggerTime
+  );
+
+/**
+  Stops execution until an event is signaled.
+
+  @param  NumberOfEvents         The number of events in the UserEvents array
+  @param  UserEvents             An array of EFI_EVENT
+  @param  UserIndex              Pointer to the index of the event which
+                                 satisfied the wait condition
+
+  @retval EFI_SUCCESS            The event indicated by Index was signaled.
+  @retval EFI_INVALID_PARAMETER  The event indicated by Index has a notification
+                                 function or Event was not a valid type
+  @retval EFI_UNSUPPORTED        The current TPL is not TPL_APPLICATION
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestWaitForEvent (
+  IN UINTN        NumberOfEvents,
+  IN EFI_EVENT    *UserEvents,
+  OUT UINTN       *UserIndex
+  );
+
+/**
+  Signals the event.  Queues the event to be notified if needed.
+
+  @param  UserEvent              The event to signal .
+
+  @retval EFI_INVALID_PARAMETER  Parameters are not valid.
+  @retval EFI_SUCCESS            The event was signaled.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestSignalEvent (
+  IN EFI_EVENT    UserEvent
+  );
+
+/**
+  Closes an event and frees the event structure.
+
+  @param  UserEvent              Event to close
+
+  @retval EFI_INVALID_PARAMETER  Parameters are not valid.
+  @retval EFI_SUCCESS            The event has been closed
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCloseEvent (
+  IN EFI_EVENT    UserEvent
+  );
+
+/**
+  Check the status of an event.
+
+  @param  UserEvent              The event to check
+
+  @retval EFI_SUCCESS            The event is in the signaled state
+  @retval EFI_NOT_READY          The event is not in the signaled state
+  @retval EFI_INVALID_PARAMETER  Event is of type EVT_NOTIFY_SIGNAL
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCheckEvent (
+  IN EFI_EVENT        UserEvent
+  );
+
+/**
+  Wrapper function to UnitTestInstallProtocolInterfaceNotify.  This is the public API which
+  Calls the private one which contains a BOOLEAN parameter for notifications
+
+  @param  UserHandle             The handle to install the protocol handler on,
+                                 or NULL if a new handle is to be allocated
+  @param  Protocol               The protocol to add to the handle
+  @param  InterfaceType          Indicates whether Interface is supplied in
+                                 native form.
+  @param  Interface              The interface for the protocol being added
+
+  @return Status code
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestInstallProtocolInterface (
+  IN OUT EFI_HANDLE     *UserHandle,
+  IN EFI_GUID           *Protocol,
+  IN EFI_INTERFACE_TYPE InterfaceType,
+  IN VOID               *Interface
+  );
+
+/**
+  Reinstall a protocol interface on a device handle.  The OldInterface for Protocol is replaced by the NewInterface.
+
+  @param  UserHandle             Handle on which the interface is to be
+                                 reinstalled
+  @param  Protocol               The numeric ID of the interface
+  @param  OldInterface           A pointer to the old interface
+  @param  NewInterface           A pointer to the new interface
+
+  @retval EFI_SUCCESS            The protocol interface was installed
+  @retval EFI_NOT_FOUND          The OldInterface on the handle was not found
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestReinstallProtocolInterface (
+  IN EFI_HANDLE     UserHandle,
+  IN EFI_GUID       *Protocol,
+  IN VOID           *OldInterface,
+  IN VOID           *NewInterface
+  );
+
+/**
+  Uninstalls all instances of a protocol:interfacer from a handle.
+  If the last protocol interface is remove from the handle, the
+  handle is freed.
+
+  @param  UserHandle             The handle to remove the protocol handler from
+  @param  Protocol               The protocol, of protocol:interface, to remove
+  @param  Interface              The interface, of protocol:interface, to remove
+
+  @retval EFI_INVALID_PARAMETER  Protocol is NULL.
+  @retval EFI_SUCCESS            Protocol interface successfully uninstalled.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestUninstallProtocolInterface (
+  IN EFI_HANDLE       UserHandle,
+  IN EFI_GUID         *Protocol,
+  IN VOID             *Interface
+  );
+
+/**
+  Queries a handle to determine if it supports a specified protocol.
+
+  @param  UserHandle             The handle being queried.
+  @param  Protocol               The published unique identifier of the protocol.
+  @param  Interface              Supplies the address where a pointer to the
+                                 corresponding Protocol Interface is returned.
+
+  @return The requested protocol interface for the handle
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestHandleProtocol (
+  IN EFI_HANDLE       UserHandle,
+  IN EFI_GUID         *Protocol,
+  OUT VOID            **Interface
+  );
+
+/**
+  Add a new protocol notification record for the request protocol.
+
+  @param  Protocol               The requested protocol to add the notify
+                                 registration
+  @param  Event                  The event to signal
+  @param  Registration           Returns the registration record
+
+  @retval EFI_INVALID_PARAMETER  Invalid parameter
+  @retval EFI_SUCCESS            Successfully returned the registration record
+                                 that has been added
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestRegisterProtocolNotify (
+  IN EFI_GUID       *Protocol,
+  IN EFI_EVENT      Event,
+  OUT  VOID         **Registration
+  );
+
+/**
+  Locates the requested handle(s) and returns them in Buffer.
+
+  @param  SearchType             The type of search to perform to locate the
+                                 handles
+  @param  Protocol               The protocol to search for
+  @param  SearchKey              Dependant on SearchType
+  @param  BufferSize             On input the size of Buffer.  On output the
+                                 size of data returned.
+  @param  Buffer                 The buffer to return the results in
+
+  @retval EFI_BUFFER_TOO_SMALL   Buffer too small, required buffer size is
+                                 returned in BufferSize.
+  @retval EFI_INVALID_PARAMETER  Invalid parameter
+  @retval EFI_SUCCESS            Successfully found the requested handle(s) and
+                                 returns them in Buffer.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLocateHandle (
+  IN EFI_LOCATE_SEARCH_TYPE   SearchType,
+  IN EFI_GUID                 *Protocol   OPTIONAL,
+  IN VOID                     *SearchKey  OPTIONAL,
+  IN OUT UINTN                *BufferSize,
+  OUT EFI_HANDLE              *Buffer
+  );
+
+/**
+  Locates the handle to a device on the device path that best matches the specified protocol.
+
+  @param  Protocol               The protocol to search for.
+  @param  DevicePath             On input, a pointer to a pointer to the device
+                                 path. On output, the device path pointer is
+                                 modified to point to the remaining part of the
+                                 devicepath.
+  @param  Device                 A pointer to the returned device handle.
+
+  @retval EFI_SUCCESS            The resulting handle was returned.
+  @retval EFI_NOT_FOUND          No handles matched the search.
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLocateDevicePath (
+  IN EFI_GUID                       *Protocol,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL   **DevicePath,
+  OUT EFI_HANDLE                    *Device
+  );
+
+/**
+  Boot Service called to add, modify, or remove a system configuration table from
+  the EFI System Table.
+
+  @param  Guid           Pointer to the GUID for the entry to add, update, or
+                         remove
+  @param  Table          Pointer to the configuration table for the entry to add,
+                         update, or remove, may be NULL.
+
+  @return EFI_SUCCESS               Guid, Table pair added, updated, or removed.
+  @return EFI_INVALID_PARAMETER     Input GUID not valid.
+  @return EFI_NOT_FOUND             Attempted to delete non-existant entry
+  @return EFI_OUT_OF_RESOURCES      Not enough memory available
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestInstallConfigurationTable (
+  IN EFI_GUID *Guid,
+  IN VOID     *Table
+  );
+
+/**
+  Loads an EFI image into memory and returns a handle to the image.
+
+  @param  BootPolicy              If TRUE, indicates that the request originates
+                                  from the boot manager, and that the boot
+                                  manager is attempting to load FilePath as a
+                                  boot selection.
+  @param  ParentImageHandle       The caller's image handle.
+  @param  FilePath                The specific file path from which the image is
+                                  loaded.
+  @param  SourceBuffer            If not NULL, a pointer to the memory location
+                                  containing a copy of the image to be loaded.
+  @param  SourceSize              The size in bytes of SourceBuffer.
+  @param  ImageHandle             Pointer to the returned image handle that is
+                                  created when the image is successfully loaded.
+
+  @retval EFI_SUCCESS             The image was loaded into memory.
+  @retval EFI_NOT_FOUND           The FilePath was not found.
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.
+  @retval EFI_UNSUPPORTED         The image type is not supported, or the device
+                                  path cannot be parsed to locate the proper
+                                  protocol for loading the file.
+  @retval EFI_OUT_OF_RESOURCES    Image was not loaded due to insufficient
+                                  resources.
+  @retval EFI_LOAD_ERROR          Image was not loaded because the image format was corrupt or not
+                                  understood.
+  @retval EFI_DEVICE_ERROR        Image was not loaded because the device returned a read error.
+  @retval EFI_ACCESS_DENIED       Image was not loaded because the platform policy prohibits the
+                                  image from being loaded. NULL is returned in *ImageHandle.
+  @retval EFI_SECURITY_VIOLATION  Image was loaded and an ImageHandle was created with a
+                                  valid EFI_LOADED_IMAGE_PROTOCOL. However, the current
+                                  platform policy specifies that the image should not be started.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLoadImage (
+  IN BOOLEAN                    BootPolicy,
+  IN EFI_HANDLE                 ParentImageHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL   *FilePath,
+  IN VOID                       *SourceBuffer   OPTIONAL,
+  IN UINTN                      SourceSize,
+  OUT EFI_HANDLE                *ImageHandle
+  );
+
+/**
+  Transfer control to a loaded image's entry point.
+
+  @param  ImageHandle             Handle of image to be started.
+  @param  ExitDataSize            Pointer of the size to ExitData
+  @param  ExitData                Pointer to a pointer to a data buffer that
+                                  includes a Null-terminated string,
+                                  optionally followed by additional binary data.
+                                  The string is a description that the caller may
+                                  use to further indicate the reason for the
+                                  image's exit.
+
+  @retval EFI_INVALID_PARAMETER   Invalid parameter
+  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
+  @retval EFI_SECURITY_VIOLATION  The current platform policy specifies that the image should not be started.
+  @retval EFI_SUCCESS             Successfully transfer control to the image's
+                                  entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestStartImage (
+  IN EFI_HANDLE  ImageHandle,
+  OUT UINTN      *ExitDataSize,
+  OUT CHAR16     **ExitData  OPTIONAL
+  );
+
+/**
+  Terminates the currently loaded EFI image and returns control to boot services.
+
+  @param  ImageHandle             Handle that identifies the image. This
+                                  parameter is passed to the image on entry.
+  @param  Status                  The image's exit code.
+  @param  ExitDataSize            The size, in bytes, of ExitData. Ignored if
+                                  ExitStatus is EFI_SUCCESS.
+  @param  ExitData                Pointer to a data buffer that includes a
+                                  Null-terminated Unicode string, optionally
+                                  followed by additional binary data. The string
+                                  is a description that the caller may use to
+                                  further indicate the reason for the image's
+                                  exit.
+
+  @retval EFI_INVALID_PARAMETER   Image handle is NULL or it is not current
+                                  image.
+  @retval EFI_SUCCESS             Successfully terminates the currently loaded
+                                  EFI image.
+  @retval EFI_ACCESS_DENIED       Should never reach there.
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate pool
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestExit (
+  IN EFI_HANDLE  ImageHandle,
+  IN EFI_STATUS  Status,
+  IN UINTN       ExitDataSize,
+  IN CHAR16      *ExitData  OPTIONAL
+  );
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle             Handle that identifies the image to be
+                                  unloaded.
+
+  @retval EFI_SUCCESS             The image has been unloaded.
+  @retval EFI_UNSUPPORTED         The image has been started, and does not support
+                                  unload.
+  @retval EFI_INVALID_PARAMPETER  ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestUnloadImage (
+  IN EFI_HANDLE  ImageHandle
+  );
+
+/**
+  Terminates all boot services.
+
+  @param  ImageHandle            Handle that identifies the exiting image.
+  @param  MapKey                 Key to the latest memory map.
+
+  @retval EFI_SUCCESS            Boot Services terminated
+  @retval EFI_INVALID_PARAMETER  MapKey is incorrect.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestExitBootServices (
+  IN EFI_HANDLE   ImageHandle,
+  IN UINTN        MapKey
+  );
+
+/**
+  Returns a monotonically increasing count for the platform.
+
+  @param[out]  Count            The pointer to returned value.
+
+  @retval EFI_SUCCESS           The next monotonic count was returned.
+  @retval EFI_INVALID_PARAMETER Count is NULL.
+  @retval EFI_DEVICE_ERROR      The device is not functioning properly.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestGetNextMonotonicCount (
+  OUT UINT64                  *Count
+  );
+
+/**
+  Introduces a fine-grained stall.
+
+  @param  Microseconds           The number of microseconds to stall execution.
+
+  @retval EFI_SUCCESS            Execution was stalled for at least the requested
+                                 amount of microseconds.
+  @retval EFI_NOT_AVAILABLE_YET  gMetronome is not available yet
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestStall (
+  IN UINTN            Microseconds
+  );
+
+/**
+  Sets the system's watchdog timer.
+
+  @param  Timeout         The number of seconds to set the watchdog timer to.
+                          A value of zero disables the timer.
+  @param  WatchdogCode    The numeric code to log on a watchdog timer timeout
+                          event. The firmware reserves codes 0x0000 to 0xFFFF.
+                          Loaders and operating systems may use other timeout
+                          codes.
+  @param  DataSize        The size, in bytes, of WatchdogData.
+  @param  WatchdogData    A data buffer that includes a Null-terminated Unicode
+                          string, optionally followed by additional binary data.
+                          The string is a description that the call may use to
+                          further indicate the reason to be logged with a
+                          watchdog event.
+
+  @return EFI_SUCCESS               Timeout has been set
+  @return EFI_NOT_AVAILABLE_YET     WatchdogTimer is not available yet
+  @return EFI_UNSUPPORTED           System does not have a timer (currently not used)
+  @return EFI_DEVICE_ERROR          Could not complete due to hardware error
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestSetWatchdogTimer (
+  IN UINTN    Timeout,
+  IN UINT64   WatchdogCode,
+  IN UINTN    DataSize,
+  IN CHAR16   *WatchdogData OPTIONAL
+  );
+
+/**
+  Connects one or more drivers to a controller.
+
+  @param  ControllerHandle      The handle of the controller to which driver(s) are to be connected.
+  @param  DriverImageHandle     A pointer to an ordered list handles that support the
+                                EFI_DRIVER_BINDING_PROTOCOL.
+  @param  RemainingDevicePath   A pointer to the device path that specifies a child of the
+                                controller specified by ControllerHandle.
+  @param  Recursive             If TRUE, then ConnectController() is called recursively
+                                until the entire tree of controllers below the controller specified
+                                by ControllerHandle have been created. If FALSE, then
+                                the tree of controllers is only expanded one level.
+
+  @retval EFI_SUCCESS           1) One or more drivers were connected to ControllerHandle.
+                                2) No drivers were connected to ControllerHandle, but
+                                RemainingDevicePath is not NULL, and it is an End Device
+                                Path Node.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_NOT_FOUND         1) There are no EFI_DRIVER_BINDING_PROTOCOL instances
+                                present in the system.
+                                2) No drivers were connected to ControllerHandle.
+  @retval EFI_SECURITY_VIOLATION
+                                The user has no permission to start UEFI device drivers on the device path
+                                associated with the ControllerHandle or specified by the RemainingDevicePath.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestConnectController (
+  IN  EFI_HANDLE                ControllerHandle,
+  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
+  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,
+  IN  BOOLEAN                   Recursive
+  );
+
+/**
+  Disconnects a controller from a driver
+
+  @param  ControllerHandle                      ControllerHandle The handle of
+                                                the controller from which
+                                                driver(s)  are to be
+                                                disconnected.
+  @param  DriverImageHandle                     DriverImageHandle The driver to
+                                                disconnect from ControllerHandle.
+  @param  ChildHandle                           ChildHandle The handle of the
+                                                child to destroy.
+
+  @retval EFI_SUCCESS                           One or more drivers were
+                                                disconnected from the controller.
+  @retval EFI_SUCCESS                           On entry, no drivers are managing
+                                                ControllerHandle.
+  @retval EFI_SUCCESS                           DriverImageHandle is not NULL,
+                                                and on entry DriverImageHandle is
+                                                not managing ControllerHandle.
+  @retval EFI_INVALID_PARAMETER                 ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER                 DriverImageHandle is not NULL,
+                                                and it is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER                 ChildHandle is not NULL, and it
+                                                is not a valid EFI_HANDLE.
+  @retval EFI_OUT_OF_RESOURCES                  There are not enough resources
+                                                available to disconnect any
+                                                drivers from ControllerHandle.
+  @retval EFI_DEVICE_ERROR                      The controller could not be
+                                                disconnected because of a device
+                                                error.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestDisconnectController (
+  IN  EFI_HANDLE  ControllerHandle,
+  IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
+  IN  EFI_HANDLE  ChildHandle        OPTIONAL
+  );
+
+/**
+  Locates the installed protocol handler for the handle, and
+  invokes it to obtain the protocol interface. Usage information
+  is registered in the protocol data base.
+
+  @param  UserHandle             The handle to obtain the protocol interface on
+  @param  Protocol               The ID of the protocol
+  @param  Interface              The location to return the protocol interface
+  @param  ImageHandle            The handle of the Image that is opening the
+                                 protocol interface specified by Protocol and
+                                 Interface.
+  @param  ControllerHandle       The controller handle that is requiring this
+                                 interface.
+  @param  Attributes             The open mode of the protocol interface
+                                 specified by Handle and Protocol.
+
+  @retval EFI_INVALID_PARAMETER  Protocol is NULL.
+  @retval EFI_SUCCESS            Get the protocol interface.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestOpenProtocol (
+  IN  EFI_HANDLE                UserHandle,
+  IN  EFI_GUID                  *Protocol,
+  OUT VOID                      **Interface OPTIONAL,
+  IN  EFI_HANDLE                ImageHandle,
+  IN  EFI_HANDLE                ControllerHandle,
+  IN  UINT32                    Attributes
+  );
+
+/**
+  Closes a protocol on a handle that was opened using OpenProtocol().
+
+  @param  UserHandle             The handle for the protocol interface that was
+                                 previously opened with OpenProtocol(), and is
+                                 now being closed.
+  @param  Protocol               The published unique identifier of the protocol.
+                                 It is the caller's responsibility to pass in a
+                                 valid GUID.
+  @param  AgentHandle            The handle of the agent that is closing the
+                                 protocol interface.
+  @param  ControllerHandle       If the agent that opened a protocol is a driver
+                                 that follows the EFI Driver Model, then this
+                                 parameter is the controller handle that required
+                                 the protocol interface. If the agent does not
+                                 follow the EFI Driver Model, then this parameter
+                                 is optional and may be NULL.
+
+  @retval EFI_SUCCESS            The protocol instance was closed.
+  @retval EFI_INVALID_PARAMETER  Handle, AgentHandle or ControllerHandle is not a
+                                 valid EFI_HANDLE.
+  @retval EFI_NOT_FOUND          Can not find the specified protocol or
+                                 AgentHandle.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCloseProtocol (
+  IN  EFI_HANDLE                UserHandle,
+  IN  EFI_GUID                  *Protocol,
+  IN  EFI_HANDLE                AgentHandle,
+  IN  EFI_HANDLE                ControllerHandle
+  );
+
+/**
+  Return information about Opened protocols in the system
+
+  @param  UserHandle             The handle to close the protocol interface on
+  @param  Protocol               The ID of the protocol
+  @param  EntryBuffer            A pointer to a buffer of open protocol
+                                 information in the form of
+                                 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
+  @param  EntryCount             Number of EntryBuffer entries
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestOpenProtocolInformation (
+  IN  EFI_HANDLE                          UserHandle,
+  IN  EFI_GUID                            *Protocol,
+  OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
+  OUT UINTN                               *EntryCount
+  );
+
+/**
+  Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
+  from pool.
+
+  @param  UserHandle             The handle from which to retrieve the list of
+                                 protocol interface GUIDs.
+  @param  ProtocolBuffer         A pointer to the list of protocol interface GUID
+                                 pointers that are installed on Handle.
+  @param  ProtocolBufferCount    A pointer to the number of GUID pointers present
+                                 in ProtocolBuffer.
+
+  @retval EFI_SUCCESS            The list of protocol interface GUIDs installed
+                                 on Handle was returned in ProtocolBuffer. The
+                                 number of protocol interface GUIDs was returned
+                                 in ProtocolBufferCount.
+  @retval EFI_INVALID_PARAMETER  Handle is NULL.
+  @retval EFI_INVALID_PARAMETER  Handle is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER  ProtocolBuffer is NULL.
+  @retval EFI_INVALID_PARAMETER  ProtocolBufferCount is NULL.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough pool memory to store the
+                                 results.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestProtocolsPerHandle (
+  IN EFI_HANDLE       UserHandle,
+  OUT EFI_GUID        ***ProtocolBuffer,
+  OUT UINTN           *ProtocolBufferCount
+  );
+
+/**
+  Function returns an array of handles that support the requested protocol
+  in a buffer allocated from pool. This is a version of UnitTestLocateHandle()
+  that allocates a buffer for the caller.
+
+  @param  SearchType             Specifies which handle(s) are to be returned.
+  @param  Protocol               Provides the protocol to search by.    This
+                                 parameter is only valid for SearchType
+                                 ByProtocol.
+  @param  SearchKey              Supplies the search key depending on the
+                                 SearchType.
+  @param  NumberHandles          The number of handles returned in Buffer.
+  @param  Buffer                 A pointer to the buffer to return the requested
+                                 array of  handles that support Protocol.
+
+  @retval EFI_SUCCESS            The result array of handles was returned.
+  @retval EFI_NOT_FOUND          No handles match the search.
+  @retval EFI_OUT_OF_RESOURCES   There is not enough pool memory to store the
+                                 matching results.
+  @retval EFI_INVALID_PARAMETER  One or more parameters are not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLocateHandleBuffer (
+  IN EFI_LOCATE_SEARCH_TYPE       SearchType,
+  IN EFI_GUID                     *Protocol OPTIONAL,
+  IN VOID                         *SearchKey OPTIONAL,
+  IN OUT UINTN                    *NumberHandles,
+  OUT EFI_HANDLE                  **Buffer
+  );
+
+/**
+  Return the first Protocol Interface that matches the Protocol GUID. If
+  Registration is passed in, return a Protocol Instance that was just add
+  to the system. If Registration is NULL return the first Protocol Interface
+  you find.
+
+  @param  Protocol               The protocol to search for
+  @param  Registration           Optional Registration Key returned from
+                                 RegisterProtocolNotify()
+  @param  Interface              Return the Protocol interface (instance).
+
+  @retval EFI_SUCCESS            If a valid Interface is returned
+  @retval EFI_INVALID_PARAMETER  Invalid parameter
+  @retval EFI_NOT_FOUND          Protocol interface not found
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestLocateProtocol (
+  IN  EFI_GUID  *Protocol,
+  IN  VOID      *Registration OPTIONAL,
+  OUT VOID      **Interface
+  );
+
+/**
+  Installs a list of protocol interface into the boot services environment.
+  This function calls InstallProtocolInterface() in a loop. If any error
+  occurs all the protocols added by this function are removed. This is
+  basically a lib function to save space.
+
+  @param  Handle                 The handle to install the protocol handlers on,
+                                 or NULL if a new handle is to be allocated
+  @param  ...                    EFI_GUID followed by protocol instance. A NULL
+                                 terminates the  list. The pairs are the
+                                 arguments to InstallProtocolInterface(). All the
+                                 protocols are added to Handle.
+
+  @retval EFI_SUCCESS            All the protocol interface was installed.
+  @retval EFI_OUT_OF_RESOURCES   There was not enough memory in pool to install all the protocols.
+  @retval EFI_ALREADY_STARTED    A Device Path Protocol instance was passed in that is already present in
+                                 the handle database.
+  @retval EFI_INVALID_PARAMETER  Handle is NULL.
+  @retval EFI_INVALID_PARAMETER  Protocol is already installed on the handle specified by Handle.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestInstallMultipleProtocolInterfaces (
+  IN OUT EFI_HANDLE           *Handle,
+  ...
+  );
+
+/**
+  Uninstalls a list of protocol interface in the boot services environment.
+  This function calls UninstallProtocolInterface() in a loop. This is
+  basically a lib function to save space.
+
+  @param  Handle                 The handle to uninstall the protocol
+  @param  ...                    EFI_GUID followed by protocol instance. A NULL
+                                 terminates the  list. The pairs are the
+                                 arguments to UninstallProtocolInterface(). All
+                                 the protocols are added to Handle.
+
+  @return Status code
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestUninstallMultipleProtocolInterfaces (
+  IN EFI_HANDLE           Handle,
+  ...
+  );
+
+/**
+  Computes and returns a 32-bit CRC for a data buffer.
+
+  @param[in]   Data             A pointer to the buffer on which the 32-bit CRC is to be computed.
+  @param[in]   DataSize         The number of bytes in the buffer Data.
+  @param[out]  Crc32            The 32-bit CRC that was computed for the data buffer specified by Data
+                                and DataSize.
+
+  @retval EFI_SUCCESS           The 32-bit CRC was computed for the data buffer and returned in
+                                Crc32.
+  @retval EFI_INVALID_PARAMETER Data is NULL.
+  @retval EFI_INVALID_PARAMETER Crc32 is NULL.
+  @retval EFI_INVALID_PARAMETER DataSize is 0.
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCalculateCrc32 (
+  IN  VOID                              *Data,
+  IN  UINTN                             DataSize,
+  OUT UINT32                            *Crc32
+  );
+
+/**
+  Creates an event in a group.
+
+  @param  Type                   The type of event to create and its mode and
+                                 attributes
+  @param  NotifyTpl              The task priority level of event notifications
+  @param  NotifyFunction         Pointer to the events notification function
+  @param  NotifyContext          Pointer to the notification functions context;
+                                 corresponds to parameter "Context" in the
+                                 notification function
+  @param  EventGroup             GUID for EventGroup if NULL act the same as
+                                 gBS->CreateEvent().
+  @param  Event                  Pointer to the newly created event if the call
+                                 succeeds; undefined otherwise
+
+  @retval EFI_SUCCESS            The event structure was created
+  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value
+  @retval EFI_OUT_OF_RESOURCES   The event could not be allocated
+
+**/
+EFI_STATUS
+EFIAPI
+UnitTestCreateEventEx (
+  IN UINT32                   Type,
+  IN EFI_TPL                  NotifyTpl,
+  IN EFI_EVENT_NOTIFY         NotifyFunction, OPTIONAL
+  IN CONST VOID               *NotifyContext, OPTIONAL
+  IN CONST EFI_GUID           *EventGroup,    OPTIONAL
+  OUT EFI_EVENT               *Event
+  );
+
+#endif
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
new file mode 100644
index 000000000000..3b85dbb1b715
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
@@ -0,0 +1,46 @@
+## @file
+# UEFI Boot Services Table Library for unit tests implementation.
+#
+# Copyright (c) Microsoft Corporation
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = UefiBootServicesTableLibUnitTest
+  MODULE_UNI_FILE                = UefiBootServicesTableLibTest.uni
+  FILE_GUID                      = 725E1CCD-07F1-4964-9A3E-9AA6DCC51DE6
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = UefiBootServicesTableLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE
+
+  CONSTRUCTOR                    = UefiBootServicesTableLibUnitTestConstructor
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  UefiBootServicesTableLibUnitTest.h
+  UefiBootServicesTableLibUnitTest.c
+  UefiBootServicesTableLibUnitTestEventTimer.c
+  UefiBootServicesTableLibUnitTestImage.c
+  UefiBootServicesTableLibUnitTestMemory.c
+  UefiBootServicesTableLibUnitTestProtocol.h
+  UefiBootServicesTableLibUnitTestProtocol.c
+  UefiBootServicesTableLibUnitTestMisc.c
+  UefiBootServicesTableLibUnitTestTpl.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UnitTestLib
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  TimerExtra.uni
diff --git a/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.h b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.h
new file mode 100644
index 000000000000..2857db2b2c7f
--- /dev/null
+++ b/PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTestProtocol.h
@@ -0,0 +1,123 @@
+/** @file
+  An internal header file for the Unit Test instance of the UEFI Boot Services Table Library.
+
+  This file includes common header files, defines internal structure and functions used by
+  the library implementation.
+
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef UEFI_BOOT_SERVICES_TABLE_LIB_UNIT_TEST_PROTOCOL_H_
+#define UEFI_BOOT_SERVICES_TABLE_LIB_UNIT_TEST_PROTOCOL_H_
+
+#include "UefiBootServicesTableLibUnitTest.h"
+
+#define EFI_HANDLE_SIGNATURE            SIGNATURE_32('h','n','d','l')
+
+///
+/// IHANDLE - contains a list of protocol handles
+///
+typedef struct {
+  UINTN               Signature;
+  /// All handles list of IHANDLE
+  LIST_ENTRY          AllHandles;
+  /// List of PROTOCOL_INTERFACE's for this handle
+  LIST_ENTRY          Protocols;
+  UINTN               LocateRequest;
+  /// The Handle Database Key value when this handle was last created or modified
+  UINT64              Key;
+} IHANDLE;
+
+#define ASSERT_IS_HANDLE(a)  ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE)
+
+#define PROTOCOL_ENTRY_SIGNATURE        SIGNATURE_32('p','r','t','e')
+
+///
+/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol
+/// database.  Each handler that supports this protocol is listed, along
+/// with a list of registered notifies.
+///
+typedef struct {
+  UINTN               Signature;
+  /// Link Entry inserted to mProtocolDatabase
+  LIST_ENTRY          AllEntries;
+  /// ID of the protocol
+  EFI_GUID            ProtocolID;
+  /// All protocol interfaces
+  LIST_ENTRY          Protocols;
+  /// Registered notification handlers
+  LIST_ENTRY          Notify;
+} PROTOCOL_ENTRY;
+
+
+#define PROTOCOL_INTERFACE_SIGNATURE  SIGNATURE_32('p','i','f','c')
+
+///
+/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked
+/// with a protocol interface structure
+///
+typedef struct {
+  UINTN                       Signature;
+  /// Link on IHANDLE.Protocols
+  LIST_ENTRY                  Link;
+  /// Back pointer
+  IHANDLE                     *Handle;
+  /// Link on PROTOCOL_ENTRY.Protocols
+  LIST_ENTRY                  ByProtocol;
+  /// The protocol ID
+  PROTOCOL_ENTRY              *Protocol;
+  /// The interface value
+  VOID                        *Interface;
+  /// OPEN_PROTOCOL_DATA list
+  LIST_ENTRY                  OpenList;
+  UINTN                       OpenListCount;
+
+} PROTOCOL_INTERFACE;
+
+#define OPEN_PROTOCOL_DATA_SIGNATURE  SIGNATURE_32('p','o','d','l')
+
+typedef struct {
+  UINTN                       Signature;
+  ///Link on PROTOCOL_INTERFACE.OpenList
+  LIST_ENTRY                  Link;
+
+  EFI_HANDLE                  AgentHandle;
+  EFI_HANDLE                  ControllerHandle;
+  UINT32                      Attributes;
+  UINT32                      OpenCount;
+} OPEN_PROTOCOL_DATA;
+
+
+#define PROTOCOL_NOTIFY_SIGNATURE       SIGNATURE_32('p','r','t','n')
+
+///
+/// PROTOCOL_NOTIFY - used for each register notification for a protocol
+///
+typedef struct {
+  UINTN               Signature;
+  PROTOCOL_ENTRY      *Protocol;
+  /// All notifications for this protocol
+  LIST_ENTRY          Link;
+  /// Event to notify
+  EFI_EVENT           Event;
+  /// Last position notified
+  LIST_ENTRY          *Position;
+} PROTOCOL_NOTIFY;
+
+typedef struct {
+  EFI_GUID        *Protocol;
+  VOID            *SearchKey;
+  LIST_ENTRY      *Position;
+  PROTOCOL_ENTRY  *ProtEntry;
+} LOCATE_POSITION;
+
+typedef
+IHANDLE *
+(* UNIT_TEST_GET_NEXT) (
+  IN OUT LOCATE_POSITION    *Position,
+  OUT VOID                  **Interface
+  );
+
+#endif
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 30/41] PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (28 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 29/41] PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 31/41] PrmPkg/DxePrmModuleDiscoveryLib: Add initial " Michael Kubacki
                   ` (10 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds host-based unit tests for DxePrmContextBufferLib. This tests
each function in DxePrmContextBufferLib.

Any changes to DxePrmContextBufferLib moving forward must pass the unit
tests. The unit tests should be updated as needed if the library API
changes.

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>
---
 PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTest.c       | 649 ++++++++++++++++++++
 PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTestHost.inf |  46 ++
 PrmPkg/Test/PrmPkgHostTest.dsc                                                        |   6 +
 3 files changed, 701 insertions(+)

diff --git a/PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTest.c b/PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTest.c
new file mode 100644
index 000000000000..07e247305880
--- /dev/null
+++ b/PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTest.c
@@ -0,0 +1,649 @@
+/** @file
+
+  Unit tests for the PRM Context Buffer Library.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <Uefi.h>
+
+#include <Guid/ZeroGuid.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PrmContextBufferLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UnitTestLib.h>
+#include <Protocol/PrmConfig.h>
+
+#define UNIT_TEST_NAME          "PRM Context Buffer Library Unit Test"
+#define UNIT_TEST_VERSION       "0.1"
+
+///=== TEST DATA ==================================================================================
+
+EFI_HANDLE  mTestProtocolHandle;
+
+//*----------------------------------------------------------------------------------*
+//* Context Structures                                                               *
+//*----------------------------------------------------------------------------------*
+typedef struct {
+  PRM_MODULE_CONTEXT_BUFFERS  *InstallationStructure;
+  EFI_HANDLE                  Handle;
+  PRM_GUID_SEARCH_TYPE        GuidSearchType;
+  EFI_GUID                    *Guid;
+  EFI_GUID                    *ExpectedModuleGuid;
+  EFI_STATUS                  ExpectedStatus;
+} PRM_CONTEXT_BUFFERS_TEST_CONTEXT;
+
+typedef struct {
+  EFI_GUID                    *HandlerGuid;
+  PRM_MODULE_CONTEXT_BUFFERS  *ContextBuffers;
+  PRM_CONTEXT_BUFFER          *ExpectedContextBuffer;
+  EFI_STATUS                  ExpectedStatus;
+} PRM_CONTEXT_BUFFER_TEST_CONTEXT;
+
+//*----------------------------------------------------------------------------------*
+//* Test GUIDs                                                                       *
+//*----------------------------------------------------------------------------------*
+
+// {52960b90-2f3a-4917-b91a-ed5f599a8809}
+#define HANDLER_TEST_GUID_1 {0x52960b90, 0x2f3a, 0x4917, { 0xb9, 0x1a, 0xed, 0x5f, 0x59, 0x9a, 0x88, 0x09 }}
+EFI_GUID mHandlerTestGuid1 = HANDLER_TEST_GUID_1;
+
+// {9316a80d-06dc-417b-b21d-6b3c2ae4ed6f}
+#define HANDLER_TEST_GUID_2 {0x9316a80d, 0x06dc, 0x417b, { 0xb2, 0x1d, 0x6b, 0x3c, 0x2a, 0xe4, 0xed, 0x6f }}
+EFI_GUID mHandlerTestGuid2 = HANDLER_TEST_GUID_2;
+
+// {d32ac8ba-6cc6-456f-9ed9-9233fa310434}
+#define HANDLER_TEST_GUID_3 {0xd32ac8ba, 0x6cc6, 0x456f, { 0x9e, 0xd9, 0x92, 0x33, 0xfa, 0x31, 0x04, 0x34 }}
+EFI_GUID mHandlerTestGuid3 = HANDLER_TEST_GUID_3;
+
+// {faadaa95-070b-4a34-a919-18305dc07370}
+#define MODULE_TEST_GUID_1 {0xfaadaa95, 0x070b, 0x4a34, { 0xa9, 0x19, 0x18, 0x30, 0x5d, 0xc0, 0x73, 0x70 }}
+EFI_GUID mModuleTestGuid1 = MODULE_TEST_GUID_1;
+
+// {0ea24584-731c-4863-9100-75780af509a7}
+#define MODULE_TEST_GUID_2 {0x0ea24584, 0x731c, 0x4863, { 0x91, 0x00, 0x75, 0x78, 0x0a, 0xf5, 0x09, 0xa7 }}
+EFI_GUID mModuleTestGuid2 = MODULE_TEST_GUID_2;
+
+// {f456b7a1-82a6-4427-8486-87e3a602df43}
+#define MODULE_TEST_GUID_3 {0xf456b7a1, 0x82a6, 0x4427, { 0x84, 0x86, 0x87, 0xe3, 0xa6, 0x02, 0xdf, 0x43 }}
+EFI_GUID mModuleTestGuid3 = MODULE_TEST_GUID_3;
+
+// {4a941a9c-9dcf-471b-94b5-d9e2d8c64a1b}
+#define NEGATIVE_TEST_GUID {0x4a941a9c, 0x9dcf, 0x471b,  {0x94, 0xb5, 0xd9, 0xe2, 0xd8, 0xc6, 0x4a, 0x1b }}
+EFI_GUID mNegativeTestGuid = NEGATIVE_TEST_GUID;
+
+//*----------------------------------------------------------------------------------*
+//* PRM Static Test Structures                                                       *
+//*----------------------------------------------------------------------------------*
+
+PRM_DATA_BUFFER mTestStaticDataBuffer1 = {
+  {
+    PRM_DATA_BUFFER_HEADER_SIGNATURE,
+    sizeof (PRM_DATA_BUFFER)
+  }
+  // No data in the buffer (only a header)
+};
+
+PRM_CONTEXT_BUFFER mTestPrmContextBuffer1 = {
+  PRM_CONTEXT_BUFFER_SIGNATURE,             // Signature
+  PRM_CONTEXT_BUFFER_INTERFACE_VERSION,     // Version
+  0,                                        // Reserved
+  HANDLER_TEST_GUID_1,                      // HandlerGuid
+  &mTestStaticDataBuffer1                   // StaticDataBuffer
+};
+
+PRM_CONTEXT_BUFFER mTestPrmContextBuffer2[2] = {
+  // Context buffer #1
+  {
+    PRM_CONTEXT_BUFFER_SIGNATURE,           // Signature
+    PRM_CONTEXT_BUFFER_INTERFACE_VERSION,   // Version
+    0,                                      // Reserved
+    HANDLER_TEST_GUID_2,                    // HandlerGuid
+    NULL                                    // StaticDataBuffer
+  },
+  // Context buffer #2
+  {
+    PRM_CONTEXT_BUFFER_SIGNATURE,           // Signature
+    PRM_CONTEXT_BUFFER_INTERFACE_VERSION,   // Version
+    0,                                      // Reserved
+    HANDLER_TEST_GUID_3,                    // HandlerGuid
+    &mTestStaticDataBuffer1                 // StaticDataBuffer (reuse buffer StaticDataBuffer1)
+  }
+};
+
+PRM_MODULE_CONTEXT_BUFFERS mTestPrmModuleContextBuffers1 = {
+  MODULE_TEST_GUID_1,
+  1,
+  &mTestPrmContextBuffer1,
+  NULL
+};
+
+PRM_MODULE_CONTEXT_BUFFERS mTestPrmModuleContextBuffers2 = {
+  MODULE_TEST_GUID_2,
+  1,
+  &mTestPrmContextBuffer1,
+  NULL
+};
+
+PRM_MODULE_CONTEXT_BUFFERS mTestPrmModuleContextBuffers3 = {
+  MODULE_TEST_GUID_3,
+  2,
+  &mTestPrmContextBuffer2[0],
+  NULL
+};
+
+
+//*----------------------------------------------------------------------------------*
+//* Test Contexts                                                                    *
+//*----------------------------------------------------------------------------------*
+
+//* Searches by module GUID *
+//                                                   +--------------------------------+--------+----------------+--------------------+--------------------+--------------------+
+//                                                   + InstallationStructure          | Handle | GuidSearchType | Guid               | ExpectedModuleGuid | ExpectedStatus     |
+//                                                   +--------------------------------+--------+----------------+--------------------+--------------------+--------------------+
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers00 = { &mTestPrmModuleContextBuffers1,  NULL,    ByModuleGuid,    &mModuleTestGuid1,   &mModuleTestGuid1,   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers01 = { &mTestPrmModuleContextBuffers2,  NULL,    ByModuleGuid,    &mModuleTestGuid2,   &mModuleTestGuid2,   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers02 = { &mTestPrmModuleContextBuffers3,  NULL,    ByModuleGuid,    &mModuleTestGuid3,   &mModuleTestGuid3,   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers03 = { &mTestPrmModuleContextBuffers3,  NULL,    ByModuleGuid,    &mNegativeTestGuid,  &gZeroGuid,          EFI_NOT_FOUND      };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers04 = { &mTestPrmModuleContextBuffers1,  NULL,    ByModuleGuid,    &gZeroGuid,          &gZeroGuid,          EFI_NOT_FOUND      };
+
+//* Searches by handler GUID *
+//                                                   +--------------------------------+--------+----------------+--------------------+--------------------+--------------------+
+//                                                   + InstallationStructure          | Handle | GuidSearchType | Guid               | ExpectedModuleGuid | ExpectedStatus     |
+//                                                   +--------------------------------+--------+----------------+--------------------+--------------------+--------------------+
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers05 = { &mTestPrmModuleContextBuffers1,  NULL,    ByHandlerGuid,   &mHandlerTestGuid1,  &mModuleTestGuid1,   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers06 = { &mTestPrmModuleContextBuffers1,  NULL,    ByHandlerGuid,   &gZeroGuid,          &gZeroGuid,          EFI_NOT_FOUND      };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers07 = { &mTestPrmModuleContextBuffers2,  NULL,    ByHandlerGuid,   &mHandlerTestGuid1,  &mModuleTestGuid2,   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers08 = { &mTestPrmModuleContextBuffers2,  NULL,    ByHandlerGuid,   &mNegativeTestGuid,  &gZeroGuid,          EFI_NOT_FOUND      };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers09 = { &mTestPrmModuleContextBuffers3,  NULL,    ByHandlerGuid,   &mHandlerTestGuid1,  &gZeroGuid,          EFI_NOT_FOUND      };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers10 = { &mTestPrmModuleContextBuffers3,  NULL,    ByHandlerGuid,   &mHandlerTestGuid2,  &mModuleTestGuid3,   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers11 = { &mTestPrmModuleContextBuffers3,  NULL,    ByHandlerGuid,   &mHandlerTestGuid3,  &mModuleTestGuid3,   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT mContextBuffers12 = { &mTestPrmModuleContextBuffers3,  NULL,    ByHandlerGuid,   &gZeroGuid,          &gZeroGuid,          EFI_NOT_FOUND      };
+
+PRM_CONTEXT_BUFFERS_TEST_CONTEXT *mContextBuffersArray[] = {
+  &mContextBuffers00,
+  &mContextBuffers01,
+  &mContextBuffers02,
+  &mContextBuffers03,
+  &mContextBuffers04,
+  &mContextBuffers05,
+  &mContextBuffers06,
+  &mContextBuffers07,
+  &mContextBuffers08,
+  &mContextBuffers09,
+  &mContextBuffers10,
+  &mContextBuffers11,
+  &mContextBuffers12
+};
+
+//                                                 +----------------------+----------------------------------+------------------------------------------+--------------------+
+//                                                 + HandlerGuid          | ContextBuffers                   | ExpectedContextBuffer                    | ExpectedStatus     |
+//                                                 +----------------------+----------------------------------+------------------------------------------+--------------------+
+PRM_CONTEXT_BUFFER_TEST_CONTEXT mContextBuffer00 = { &mHandlerTestGuid1,    &mTestPrmModuleContextBuffers1,    &mTestPrmContextBuffer1,                   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFER_TEST_CONTEXT mContextBuffer01 = { &mHandlerTestGuid1,    &mTestPrmModuleContextBuffers2,    &mTestPrmContextBuffer1,                   EFI_SUCCESS        };
+PRM_CONTEXT_BUFFER_TEST_CONTEXT mContextBuffer02 = { &mHandlerTestGuid2,    &mTestPrmModuleContextBuffers3,    &mTestPrmContextBuffer2[0],                EFI_SUCCESS        };
+PRM_CONTEXT_BUFFER_TEST_CONTEXT mContextBuffer03 = { &mHandlerTestGuid3,    &mTestPrmModuleContextBuffers3,    &mTestPrmContextBuffer2[1],                EFI_SUCCESS        };
+PRM_CONTEXT_BUFFER_TEST_CONTEXT mContextBuffer04 = { &mNegativeTestGuid,    &mTestPrmModuleContextBuffers1,    NULL,                                      EFI_NOT_FOUND      };
+PRM_CONTEXT_BUFFER_TEST_CONTEXT mContextBuffer05 = { &gZeroGuid,            &mTestPrmModuleContextBuffers3,    NULL,                                      EFI_NOT_FOUND      };
+
+PRM_CONTEXT_BUFFER_TEST_CONTEXT *mContextBufferArray[] = {
+  &mContextBuffer00,
+  &mContextBuffer01,
+  &mContextBuffer02,
+  &mContextBuffer03,
+  &mContextBuffer04,
+  &mContextBuffer05
+};
+
+///=== HELPER FUNCTIONS ===========================================================================
+
+// None
+
+///=== TEST CASES =================================================================================
+
+///===== BASIC SUITE ==================================================
+
+/**
+  Verifies that passing NULL arguments to all library functions fails with EFI_INVALID_PARAMETER.
+
+  @param[in]  Context             [Optional] An optional context parameter.
+                                  Not used in this unit test.
+
+  @retval  UNIT_TEST_PASSED                      Unit test case prerequisites are met.
+  @retval  UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  Test case should be skipped..
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+NullPointerArgumentsShouldFailGracefully (
+  IN UNIT_TEST_CONTEXT            Context
+  )
+{
+  EFI_GUID                        Guid;
+  PRM_CONTEXT_BUFFER              *ContextBufferPtr;
+  PRM_MODULE_CONTEXT_BUFFERS      ModuleContextBuffers;
+  PRM_MODULE_CONTEXT_BUFFERS      *ModuleContextBuffersPtr;
+
+  UT_ASSERT_EQUAL (FindContextBufferInModuleBuffers (NULL, NULL, NULL), EFI_INVALID_PARAMETER);
+  UT_ASSERT_EQUAL (FindContextBufferInModuleBuffers (NULL, &ModuleContextBuffers, &ContextBufferPtr), EFI_INVALID_PARAMETER);
+  UT_ASSERT_EQUAL (FindContextBufferInModuleBuffers (&Guid, NULL, &ContextBufferPtr), EFI_INVALID_PARAMETER);
+  UT_ASSERT_EQUAL (FindContextBufferInModuleBuffers (&Guid, &ModuleContextBuffers, NULL), EFI_INVALID_PARAMETER);
+
+  UT_ASSERT_EQUAL (GetModuleContextBuffers (ByModuleGuid, NULL, NULL), EFI_INVALID_PARAMETER);
+  UT_ASSERT_EQUAL (GetModuleContextBuffers (ByModuleGuid, NULL, &ModuleContextBuffersPtr), EFI_INVALID_PARAMETER);
+  UT_ASSERT_EQUAL (GetModuleContextBuffers (ByModuleGuid, &Guid, NULL), EFI_INVALID_PARAMETER);
+
+  UT_ASSERT_EQUAL (GetContextBuffer (NULL, NULL, NULL), EFI_INVALID_PARAMETER);
+  UT_ASSERT_EQUAL (GetContextBuffer (NULL, &ModuleContextBuffers, &ContextBufferPtr), EFI_INVALID_PARAMETER);
+  UT_ASSERT_EQUAL (GetContextBuffer (&Guid, NULL, &ContextBufferPtr), EFI_NOT_FOUND);
+  UT_ASSERT_EQUAL (GetContextBuffer (&Guid, &ModuleContextBuffers, NULL), EFI_INVALID_PARAMETER);
+
+  return UNIT_TEST_PASSED;
+}
+
+///===== FUNCTIONAL CORRECTNESS SUITE ==================================================
+
+/**
+  Functional Correctness pre-requisite function.
+
+  Installs a gPrmConfigProtocolGuid protocol instance as specified by the provided
+  context in preparation for unit test execution
+
+  @param[in]  Context         [Optional] An optional parameter that enables:
+                              A pointer to a PRM_CONTEXT_BUFFERS_TEST_CONTEXT structure with
+                              context information for this unit test.
+
+  @retval  UNIT_TEST_PASSED                      Unit test case prerequisites
+                                                 are met.
+  @retval  UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  Test case should be skipped.
+
+**/
+STATIC
+UNIT_TEST_STATUS
+EFIAPI
+InitializeFunctionalCorrectness (
+  IN  UNIT_TEST_CONTEXT                 Context
+  )
+{
+  EFI_STATUS                            Status;
+  PRM_CONFIG_PROTOCOL                   *PrmConfigProtocol;
+  PRM_MODULE_CONTEXT_BUFFERS            *ModuleContextBuffers;
+  PRM_CONTEXT_BUFFERS_TEST_CONTEXT      *TestContext;
+
+  UT_ASSERT_NOT_NULL (Context);
+  TestContext = (PRM_CONTEXT_BUFFERS_TEST_CONTEXT *) Context;
+  ModuleContextBuffers = TestContext->InstallationStructure;
+
+  PrmConfigProtocol = AllocateZeroPool (sizeof (*PrmConfigProtocol));
+  if (PrmConfigProtocol == NULL) {
+    return UNIT_TEST_ERROR_PREREQUISITE_NOT_MET;
+  }
+
+  CopyGuid (&PrmConfigProtocol->ModuleContextBuffers.ModuleGuid, &ModuleContextBuffers->ModuleGuid);
+  PrmConfigProtocol->ModuleContextBuffers.BufferCount = ModuleContextBuffers->BufferCount;
+  PrmConfigProtocol->ModuleContextBuffers.Buffer = ModuleContextBuffers->Buffer;
+
+  Status =  gBS->InstallProtocolInterface (
+                  &TestContext->Handle,
+                  &gPrmConfigProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  (VOID *) PrmConfigProtocol
+                  );
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Functional Correctness cleanup function.
+
+  Uninstalls the gPrmConfigProtocolGuid protocol instance as specified by the
+  provided context. This is used to clean up the mocked protocol database after
+  unit test execution.
+
+  @param[in]  Context       [Optional] An optional parameter that enables:
+                            A pointer to a PRM_CONTEXT_BUFFERS_TEST_CONTEXT structure with
+                            context information for this unit test.
+
+  @retval  UNIT_TEST_PASSED                Test case cleanup succeeded.
+  @retval  UNIT_TEST_ERROR_CLEANUP_FAILED  Test case cleanup failed.
+
+**/
+STATIC
+UNIT_TEST_STATUS
+EFIAPI
+DeInitializeFunctionalCorrectness (
+  IN  UNIT_TEST_CONTEXT               Context
+  )
+{
+  EFI_STATUS                          Status;
+  PRM_CONFIG_PROTOCOL                 *PrmConfigProtocol;
+  PRM_CONTEXT_BUFFERS_TEST_CONTEXT    *TestContext;
+
+  UT_ASSERT_NOT_NULL (Context);
+  TestContext = (PRM_CONTEXT_BUFFERS_TEST_CONTEXT *) Context;
+
+  Status = gBS->HandleProtocol (
+                  TestContext->Handle,
+                  &gPrmConfigProtocolGuid,
+                  (VOID **) &PrmConfigProtocol
+                  );
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  if (!EFI_ERROR (Status)) {
+    Status =  gBS->UninstallProtocolInterface (
+                     TestContext->Handle,
+                     &gPrmConfigProtocolGuid,
+                     PrmConfigProtocol
+                    );
+    UT_ASSERT_NOT_EFI_ERROR (Status);
+    if (!EFI_ERROR (Status)) {
+      FreePool (PrmConfigProtocol);
+    }
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Verifies that the correct PRM_MODULE_CONTEXT_BUFFERS structure instance is found
+  for a given PRM module or PRM handler GUID.
+
+  @param[in]  Context       [Optional] An optional context parameter.
+                            A pointer to a PRM_CONTEXT_BUFFERS_TEST_CONTEXT structure with
+                            context information for this unit test.
+
+  @retval  UNIT_TEST_PASSED                      Unit test case prerequisites are met.
+  @retval  UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  Test case should be skipped..
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+VerifyGetModuleContextBuffers (
+  IN UNIT_TEST_CONTEXT                Context
+  )
+{
+  EFI_STATUS                          Status;
+  PRM_MODULE_CONTEXT_BUFFERS          *ContextBuffers;
+  PRM_CONTEXT_BUFFERS_TEST_CONTEXT    *TestContext;
+
+  ContextBuffers = NULL;
+  TestContext = (PRM_CONTEXT_BUFFERS_TEST_CONTEXT *) Context;
+
+  Status = GetModuleContextBuffers (TestContext->GuidSearchType, TestContext->Guid, &ContextBuffers);
+  UT_ASSERT_STATUS_EQUAL (Status, TestContext->ExpectedStatus);
+
+  if (!EFI_ERROR (TestContext->ExpectedStatus)) {
+    UT_ASSERT_TRUE (CompareGuid (TestContext->ExpectedModuleGuid, &ContextBuffers->ModuleGuid));
+    UT_LOG_INFO (
+      "%a: Searching by %a GUID ({%g}) returned ContextBuffers at 0x%x\n",
+      __FUNCTION__,
+      ((TestContext->GuidSearchType == ByModuleGuid) ? "module" : "handler"),
+      TestContext->Guid,
+      (UINTN) ContextBuffers
+      );
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Verifies that the expected PRM_CONTEXT_BUFFER instance is found for the given HandlerGuid
+  in the provided PRM_MODULE_CONTEXT_BUFFERS structure.
+
+  @param[in]  Context       [Optional] An optional context parameter.
+                            A pointer to a PRM_CONTEXT_BUFFERS_TEST_CONTEXT structure with
+                            context information for this unit test.
+
+  @retval  UNIT_TEST_PASSED                      Unit test case prerequisites are met.
+  @retval  UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  Test case should be skipped..
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+VerifyFindContextBufferInModuleBuffers (
+  IN UNIT_TEST_CONTEXT                Context
+  )
+{
+  EFI_STATUS                          Status;
+  PRM_CONTEXT_BUFFER                  *FoundContextBuffer;
+  PRM_MODULE_CONTEXT_BUFFERS          *ContextBuffers;
+  PRM_CONTEXT_BUFFER_TEST_CONTEXT     *TestContext;
+
+  ContextBuffers = NULL;
+  FoundContextBuffer = NULL;
+  TestContext = (PRM_CONTEXT_BUFFER_TEST_CONTEXT *) Context;
+
+  Status = FindContextBufferInModuleBuffers (TestContext->HandlerGuid, TestContext->ContextBuffers, &FoundContextBuffer);
+  UT_ASSERT_STATUS_EQUAL (Status, TestContext->ExpectedStatus);
+
+  if (!EFI_ERROR (TestContext->ExpectedStatus)) {
+    UT_ASSERT_NOT_NULL (FoundContextBuffer);
+    UT_ASSERT_TRUE (FoundContextBuffer == TestContext->ExpectedContextBuffer);
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Verifies that the expected PRM_CONTEXT_BUFFER instance is found for the given HandlerGuid.
+
+  This function checks both the case when a PRM_MODULE_CONTEXT_BUFFERS structure pointer is provided and
+  not provided.
+
+  NOTES:
+  - In the future, this function should mock the internal calls to other library functions but the direct
+    calls are left in place for now.
+  - The PrmModuleContextBuffers being NULL is not actually tested at the moment. In the future, that case
+    should also be added.
+
+  @param[in]  Context       [Optional] An optional context parameter.
+                            A pointer to a PRM_CONTEXT_BUFFERS_TEST_CONTEXT structure with
+                            context information for this unit test.
+
+  @retval  UNIT_TEST_PASSED                      Unit test case prerequisites are met.
+  @retval  UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  Test case should be skipped..
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+VerifyGetContextBuffer (
+  IN UNIT_TEST_CONTEXT                Context
+  )
+{
+  EFI_STATUS                          Status;
+  PRM_CONTEXT_BUFFER                  *FoundContextBuffer;
+  PRM_MODULE_CONTEXT_BUFFERS          *ContextBuffers;
+  PRM_CONTEXT_BUFFER_TEST_CONTEXT     *TestContext;
+
+  ContextBuffers = NULL;
+  FoundContextBuffer = NULL;
+  TestContext = (PRM_CONTEXT_BUFFER_TEST_CONTEXT *) Context;
+
+  Status = GetContextBuffer (TestContext->HandlerGuid, TestContext->ContextBuffers, &FoundContextBuffer);
+  UT_ASSERT_STATUS_EQUAL (Status, TestContext->ExpectedStatus);
+
+  if (!EFI_ERROR (TestContext->ExpectedStatus)) {
+    UT_ASSERT_NOT_NULL (FoundContextBuffer);
+    UT_ASSERT_TRUE (FoundContextBuffer == TestContext->ExpectedContextBuffer);
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+///=== TEST ENGINE ================================================================================
+
+/**
+  Entry point for the PRM Context Buffer Library unit tests.
+
+  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
+  @param[in] SystemTable  A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS     The entry point executed successfully.
+  @retval other           Some error occurred when executing this entry point.
+
+**/
+int main ()
+{
+  EFI_STATUS                  Status;
+  UINTN                       Index;
+  UNIT_TEST_FRAMEWORK_HANDLE  Framework;
+  UNIT_TEST_SUITE_HANDLE      BasicTests;
+  UNIT_TEST_SUITE_HANDLE      FunctionalCorrectnessTests;
+  CHAR8                       TestCaseClassNameString[256];
+  CHAR8                       TestCaseDescriptionString[256];
+
+  Framework = NULL;
+
+  DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+  //
+  // Start setting up the test framework for running the tests.
+  //
+  Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+    goto EXIT;
+  }
+
+  //
+  // Add all test suites and tests.
+  //
+  Status = CreateUnitTestSuite (&BasicTests, Framework, "Basic Context Buffer Tests", "PrmContextBufferLib.Basic", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for PrmContextBufferLib.Basic\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  AddTestCase (
+    BasicTests,
+    "",
+    "PrmContextBufferLib.Basic.NullPointerGracefulFailure",
+    NullPointerArgumentsShouldFailGracefully,
+    NULL,
+    NULL,
+    NULL
+    );
+
+  Status = CreateUnitTestSuite (&FunctionalCorrectnessTests, Framework, "Functional Correctness Tests", "PrmContextBufferLib.Functional", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for PrmContextBufferLib.Functional\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  //
+  // Add Functional Correctness unit tests
+  //
+  for (Index = 0; Index < ARRAY_SIZE (mContextBuffersArray); Index++) {
+    ZeroMem (&TestCaseClassNameString[0], ARRAY_SIZE (TestCaseClassNameString));
+    ZeroMem (&TestCaseDescriptionString[0], ARRAY_SIZE (TestCaseDescriptionString));
+
+    AsciiSPrint (
+      &TestCaseClassNameString[0],
+      ARRAY_SIZE (TestCaseClassNameString),
+      "PrmContextBufferLib.Functional.VerifyGetModuleContextBuffers%d",
+      Index + 1
+      );
+    AsciiSPrint (
+      &TestCaseDescriptionString[0],
+      ARRAY_SIZE (TestCaseDescriptionString),
+      "Verify Get PRM Module Context Buffers Structure by %a GUID %d\n",
+      ((mContextBuffersArray[Index]->GuidSearchType == ByModuleGuid) ? "module" : "handler"),
+      Index + 1
+      );
+
+    AddTestCase (
+      FunctionalCorrectnessTests,
+      &TestCaseDescriptionString[0],
+      &TestCaseClassNameString[0],
+      VerifyGetModuleContextBuffers,
+      InitializeFunctionalCorrectness,
+      DeInitializeFunctionalCorrectness,
+      mContextBuffersArray[Index]
+      );
+  }
+
+  for (Index = 0; Index < ARRAY_SIZE (mContextBufferArray); Index++) {
+    ZeroMem (&TestCaseClassNameString[0], ARRAY_SIZE (TestCaseClassNameString));
+    ZeroMem (&TestCaseDescriptionString[0], ARRAY_SIZE (TestCaseDescriptionString));
+
+    AsciiSPrint (
+      &TestCaseClassNameString[0],
+      ARRAY_SIZE (TestCaseClassNameString),
+      "PrmContextBufferLib.Functional.VerifyFindContextBufferInModuleBuffers%d",
+      Index + 1
+      );
+    AsciiSPrint (
+      &TestCaseDescriptionString[0],
+      ARRAY_SIZE (TestCaseDescriptionString),
+      "Verify Find PRM Context Buffer by Handler GUID %d\n",
+      Index + 1
+      );
+
+    AddTestCase (
+      FunctionalCorrectnessTests,
+      &TestCaseDescriptionString[0],
+      &TestCaseClassNameString[0],
+      VerifyFindContextBufferInModuleBuffers,
+      NULL,
+      NULL,
+      mContextBufferArray[Index]
+      );
+  }
+
+  for (Index = 0; Index < ARRAY_SIZE (mContextBufferArray); Index++) {
+    ZeroMem (&TestCaseClassNameString[0], ARRAY_SIZE (TestCaseClassNameString));
+    ZeroMem (&TestCaseDescriptionString[0], ARRAY_SIZE (TestCaseDescriptionString));
+
+    AsciiSPrint (
+      &TestCaseClassNameString[0],
+      ARRAY_SIZE (TestCaseClassNameString),
+      "PrmContextBufferLib.Functional.VerifyGetContextBuffer%d",
+      Index + 1
+      );
+    AsciiSPrint (
+      &TestCaseDescriptionString[0],
+      ARRAY_SIZE (TestCaseDescriptionString),
+      "Verify Get PRM Context Buffer by Handler GUID %d\n",
+      Index + 1
+      );
+
+    AddTestCase (
+      FunctionalCorrectnessTests,
+      &TestCaseDescriptionString[0],
+      &TestCaseClassNameString[0],
+      VerifyGetContextBuffer,
+      NULL,
+      NULL,
+      mContextBufferArray[Index]
+      );
+  }
+
+  //
+  // Execute the tests.
+  //
+  Status = RunAllTestSuites (Framework);
+
+EXIT:
+  if (Framework)
+  {
+    FreeUnitTestFramework (Framework);
+  }
+
+  return Status;
+}
diff --git a/PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTestHost.inf b/PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTestHost.inf
new file mode 100644
index 000000000000..7cf6a16867d4
--- /dev/null
+++ b/PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTestHost.inf
@@ -0,0 +1,46 @@
+## @file
+#  PRM Context Buffer Library Host-Based Unit Tests
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = PrmContextBufferLibUnitTestHost
+  FILE_GUID                      = F1FB5F32-BDB5-4391-BD6D-979E90EE2DC3
+  MODULE_TYPE                    = HOST_APPLICATION
+  VERSION_STRING                 = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+  DxePrmContextBufferLibUnitTest.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+  PrmPkg/PrmPkg.dec
+
+[Guids]
+  gZeroGuid
+
+[Protocols]
+  gPrmConfigProtocolGuid
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  PrintLib
+  PrmContextBufferLib
+  UefiBootServicesTableLib
+  UnitTestLib
diff --git a/PrmPkg/Test/PrmPkgHostTest.dsc b/PrmPkg/Test/PrmPkgHostTest.dsc
index 2d718f8888b8..1f44037d0102 100644
--- a/PrmPkg/Test/PrmPkgHostTest.dsc
+++ b/PrmPkg/Test/PrmPkgHostTest.dsc
@@ -19,6 +19,7 @@ [Defines]
 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
 
 [LibraryClasses]
+  PrmContextBufferLib|PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
   UefiBootServicesTableLib|PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
 
 [Components]
@@ -26,3 +27,8 @@ [Components]
   # Unit test helper libraries
   #
   PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
+
+  #
+  # Unit test host applications
+  #
+  PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTestHost.inf
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 31/41] PrmPkg/DxePrmModuleDiscoveryLib: Add initial host-based unit tests
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (29 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 30/41] PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 32/41] PrmPkg: Add PlatformGuid Michael Kubacki
                   ` (9 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds host-based unit tests for DxePrmModuleDiscoveryLib. This is
an initial set of support, more tests should be added in the
future.

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>
---
 PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c                        |   1 -
 PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTest.c       | 209 ++++++++++++++++++++
 PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h                              |  12 ++
 PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTestHost.inf |  39 ++++
 PrmPkg/Test/PrmPkgHostTest.dsc                                                            |   5 +
 5 files changed, 265 insertions(+), 1 deletion(-)

diff --git a/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c b/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
index 6977799aa8f3..0dd6a76be4d7 100644
--- a/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
+++ b/PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
@@ -87,7 +87,6 @@ GetNextPrmModuleEntry (
                                           otherwise, NULL is returned.
 
 **/
-STATIC
 PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *
 CreateNewPrmModuleImageContextListEntry (
   VOID
diff --git a/PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTest.c b/PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTest.c
new file mode 100644
index 000000000000..ef8abe397cd4
--- /dev/null
+++ b/PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTest.c
@@ -0,0 +1,209 @@
+/** @file
+
+  Unit tests for the PRM Module Discovery Library.
+
+  Copyright (c) Microsoft Corporation
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrmModuleDiscoveryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UnitTestLib.h>
+
+#include "../PrmModuleDiscovery.h"
+
+#define UNIT_TEST_NAME          "PRM Module Discovery Library Unit Test"
+#define UNIT_TEST_VERSION       "0.1"
+
+///=== TEST CASES =================================================================================
+
+///===== CREATE NEW PRM MODULE IMAGE CONTEXT LIST ENTRY TESTS SUITE ==================================================
+
+/**
+  Verifies that the buffer returned can be deallocated.
+
+  @param[in]  Context             [Optional] An optional context parameter.
+                                  Not used in this unit test.
+
+  @retval  UNIT_TEST_PASSED                      Unit test case prerequisites are met.
+  @retval  UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  Test case should be skipped..
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+PrmModuleImageContextListEntryShouldDeallocate (
+  IN UNIT_TEST_CONTEXT            Context
+  )
+{
+  PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY   *ListEntry;
+
+  ListEntry = CreateNewPrmModuleImageContextListEntry ();
+
+  UT_ASSERT_NOT_NULL (ListEntry);
+  if (ListEntry != NULL) {
+    FreePool (ListEntry);
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Verifies that the list entry signature is set to the appropriate value.
+
+  @param[in]  Context             [Optional] An optional context parameter.
+                                  Not used in this unit test.
+
+  @retval  UNIT_TEST_PASSED                      Unit test case prerequisites are met.
+  @retval  UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  Test case should be skipped..
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+PrmModuleImageContextListEntrySignatureShouldBeValid (
+  IN UNIT_TEST_CONTEXT            Context
+  )
+{
+  PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY   *ListEntry;
+
+  ListEntry = CreateNewPrmModuleImageContextListEntry ();
+
+  UT_ASSERT_TRUE (ListEntry->Signature == PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE);
+
+  if (ListEntry != NULL) {
+    FreePool (ListEntry);
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Verifies that the Context buffer in the list entry is initialized to zero.
+
+  @param[in]  Context             [Optional] An optional context parameter.
+                                  Not used in this unit test.
+
+  @retval  UNIT_TEST_PASSED                      Unit test case prerequisites are met.
+  @retval  UNIT_TEST_ERROR_PREREQUISITE_NOT_MET  Test case should be skipped..
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+PrmModuleImageContextListEntryImageContextShouldBeZeroed (
+  IN UNIT_TEST_CONTEXT            Context
+  )
+{
+  PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY   *ListEntry;
+  PRM_MODULE_IMAGE_CONTEXT              ImageContext;
+
+  ListEntry = CreateNewPrmModuleImageContextListEntry ();
+
+  ZeroMem (&ImageContext, sizeof (ImageContext));
+  UT_ASSERT_MEM_EQUAL (&ListEntry->Context, &ImageContext, sizeof (ImageContext));
+
+  if (ListEntry != NULL) {
+    FreePool (ListEntry);
+  }
+
+  return UNIT_TEST_PASSED;
+}
+
+///=== TEST ENGINE ================================================================================
+
+/**
+  Entry point for the PRM Context Buffer Library unit tests.
+
+  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
+  @param[in] SystemTable  A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS     The entry point executed successfully.
+  @retval other           Some error occurred when executing this entry point.
+
+**/
+int main ()
+{
+  EFI_STATUS                  Status;
+  UNIT_TEST_FRAMEWORK_HANDLE  Framework;
+  UNIT_TEST_SUITE_HANDLE      CreateNewPrmModuleImageContextListEntryTests;
+
+  Framework = NULL;
+
+  DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+  //
+  // Start setting up the test framework for running the tests.
+  //
+  Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+    goto EXIT;
+  }
+
+  Status =  CreateUnitTestSuite (
+              &CreateNewPrmModuleImageContextListEntryTests,
+              Framework,
+              "Create New PRM Module Image Context List Entry Tests",
+              "PrmModuleDiscoveryLib.CreateNewPrmModuleImageContextListEntry",
+              NULL,
+              NULL
+              );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for PrmModuleDiscoveryLib.CreateNewPrmModuleImageContextListEntry\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+
+  AddTestCase (
+    CreateNewPrmModuleImageContextListEntryTests,
+    "",
+    "PrmModuleDiscoveryLib.CreateNewPrmModuleImageContextListEntry.ListEntryShouldDeallocate",
+    PrmModuleImageContextListEntryShouldDeallocate,
+    NULL,
+    NULL,
+    NULL
+    );
+
+  AddTestCase (
+    CreateNewPrmModuleImageContextListEntryTests,
+    "",
+    "PrmModuleDiscoveryLib.CreateNewPrmModuleImageContextListEntry.ListEntrySignatureShouldBeValid",
+    PrmModuleImageContextListEntrySignatureShouldBeValid,
+    NULL,
+    NULL,
+    NULL
+    );
+
+  AddTestCase (
+    CreateNewPrmModuleImageContextListEntryTests,
+    "",
+    "PrmModuleDiscoveryLib.CreateNewPrmModuleImageContextListEntry.ListEntryImageContextShouldBeZeroed",
+    PrmModuleImageContextListEntryImageContextShouldBeZeroed,
+    NULL,
+    NULL,
+    NULL
+    );
+
+  //
+  // Execute the tests.
+  //
+  Status = RunAllTestSuites (Framework);
+
+EXIT:
+  if (Framework)
+  {
+    FreeUnitTestFramework (Framework);
+  }
+
+  return Status;
+}
diff --git a/PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h b/PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
index 79058d15317e..ea42cf272550 100644
--- a/PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
+++ b/PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
@@ -24,4 +24,16 @@ typedef struct {
 
 #pragma pack(pop)
 
+/**
+  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.
+
+**/
+PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *
+CreateNewPrmModuleImageContextListEntry (
+  VOID
+  );
+
 #endif
diff --git a/PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTestHost.inf b/PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTestHost.inf
new file mode 100644
index 000000000000..8aae1f7cd78a
--- /dev/null
+++ b/PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTestHost.inf
@@ -0,0 +1,39 @@
+## @file
+#  PRM Module Discovery Library Host-Based Unit Tests
+#
+#  Copyright (c) Microsoft Corporation
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = PrmModuleDiscoveryLibUnitTestHost
+  FILE_GUID                      = 864886C5-5458-4FF5-A160-4D5B2EAEC558
+  MODULE_TYPE                    = HOST_APPLICATION
+  VERSION_STRING                 = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+  DxePrmModuleDiscoveryLibUnitTest.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+  PrmPkg/PrmPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  PrmModuleDiscoveryLib
+  UefiBootServicesTableLib
+  UnitTestLib
diff --git a/PrmPkg/Test/PrmPkgHostTest.dsc b/PrmPkg/Test/PrmPkgHostTest.dsc
index 1f44037d0102..67fb4f5bd0d2 100644
--- a/PrmPkg/Test/PrmPkgHostTest.dsc
+++ b/PrmPkg/Test/PrmPkgHostTest.dsc
@@ -19,7 +19,11 @@ [Defines]
 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
 
 [LibraryClasses]
+  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
   PrmContextBufferLib|PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
+  PrmModuleDiscoveryLib|PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
+  PrmPeCoffLib|PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
   UefiBootServicesTableLib|PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootServicesTableLibUnitTest.inf
 
 [Components]
@@ -32,3 +36,4 @@ [Components]
   # Unit test host applications
   #
   PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibUnitTestHost.inf
+  PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscoveryLibUnitTestHost.inf
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 32/41] PrmPkg: Add PlatformGuid
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (30 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 31/41] PrmPkg/DxePrmModuleDiscoveryLib: Add initial " Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 33/41] PrmPkg: Update PRM OpRegion Michael Kubacki
                   ` (8 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <mikuback@microsoft.com>

Adds a "platform GUID" field to the PRM ACPI table. This field
is used by a platform to uniquely identify itself such that it
can be targeted by runtime PRM module updates for that platform.

Platforms using PRM are currently required to set a unique value
for gPrmPkgTokenSpaceGuid.PcdPrmPlatformGuid in their platform
DSC.

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>
---
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c   | 17 +++++++++++++++++
 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h   |  3 +++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf |  2 ++
 PrmPkg/PrmPkg.dec                    | 10 ++++++++++
 PrmPkg/Readme.md                     | 12 ++++++++++++
 5 files changed, 44 insertions(+)

diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index aa7aab391e8c..f78c682a654b 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -11,6 +11,7 @@
 
 #include "PrmAcpiTable.h"
 
+#include <Guid/ZeroGuid.h>
 #include <IndustryStandard/Acpi.h>
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
@@ -52,6 +53,7 @@ ProcessPrmModules (
   OUT PRM_ACPI_DESCRIPTION_TABLE          **PrmAcpiDescriptionTable
   )
 {
+  EFI_GUID                                *PlatformGuid;
   EFI_IMAGE_EXPORT_DIRECTORY              *CurrentImageExportDirectory;
   PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT     *CurrentExportDescriptorStruct;
   PRM_ACPI_DESCRIPTION_TABLE              *PrmAcpiTable;
@@ -79,6 +81,20 @@ ProcessPrmModules (
   }
   *PrmAcpiDescriptionTable = NULL;
 
+  PlatformGuid = (EFI_GUID *) PcdGetPtr (PcdPrmPlatformGuid);
+  //
+  // The platform should set PcdPrmPlatformGuid to a non-zero value
+  //
+  if (CompareGuid (PlatformGuid, &gZeroGuid)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "  %a %a: PcdPrmPlatformGuid must be set to a unique value in the platform DSC file.\n",
+      _DBGMSGID_,
+      __FUNCTION__
+      ));
+    ASSERT (!CompareGuid (PlatformGuid, &gZeroGuid));
+  }
+
   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));
 
@@ -102,6 +118,7 @@ ProcessPrmModules (
   PrmAcpiTable->Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
   PrmAcpiTable->Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
   PrmAcpiTable->Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+  CopyGuid (&PrmAcpiTable->PrmPlatformGuid, PlatformGuid);
   PrmAcpiTable->PrmModuleInfoOffset     = OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure);
   PrmAcpiTable->PrmModuleInfoCount      = (UINT32) mPrmModuleCount;
 
diff --git a/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
index ec3be529d119..6f9ba8f77724 100644
--- a/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
+++ b/PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
@@ -56,6 +56,9 @@ typedef struct {
 
 typedef struct {
   EFI_ACPI_DESCRIPTION_HEADER         Header;                     ///< Standard ACPI description header
+  GUID                                PrmPlatformGuid;            ///< A GUID that uniquely identifies this platform.
+                                                                  ///< Used to check for compatibility in PRM module
+                                                                  ///< runtime updates.
   UINT32                              PrmModuleInfoOffset;        ///< Offset in bytes from the beginning of this
                                                                   ///< structure to the PRM Module Info array
   UINT32                              PrmModuleInfoCount;         ///< Number of entries in the PRM Module Info array
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
index 554d49685e2a..7efefdae960f 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
@@ -31,6 +31,7 @@ [Packages]
 
 [Guids]
   gEfiEndOfDxeEventGroupGuid
+  gZeroGuid
 
 [LibraryClasses]
   BaseLib
@@ -51,6 +52,7 @@ [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision      ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId        ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision  ## CONSUMES
+  gPrmPkgTokenSpaceGuid.PcdPrmPlatformGuid                      ## CONSUMES
 
 [Protocols]
   gEfiAcpiTableProtocolGuid
diff --git a/PrmPkg/PrmPkg.dec b/PrmPkg/PrmPkg.dec
index 94888d1c70a4..6753ac624444 100644
--- a/PrmPkg/PrmPkg.dec
+++ b/PrmPkg/PrmPkg.dec
@@ -65,3 +65,13 @@ [PcdsFixedAtBuild]
   #  report PRM handler execution time in the application. If such a TimerLib
   #  instance is not available, set this PCD to FALSE in the package DSC file.
   gPrmPkgTokenSpaceGuid.PcdPrmInfoPrintHandlerExecutionTime|TRUE|BOOLEAN|0x00000003
+
+  ## PRM Platform GUID
+  #
+  #  Uniquely identifies a specific platform targeted for PRM module updates. Each
+  #  platform MUST provide a new GUID. This GUID is checked against the platform
+  #  GUID in the PRM module export descriptor during PRM runtime updates to determine
+  #  if a given PRM module update is valid for a given system. Even if PRM runtime
+  #  updates are not planned for a given platform, this value should still be given
+  #  a unique value in the platform DSC.
+  gPrmPkgTokenSpaceGuid.PcdPrmPlatformGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}|VOID*|0x00000004
diff --git a/PrmPkg/Readme.md b/PrmPkg/Readme.md
index 2a8a40c924c0..40df8f00a0c8 100644
--- a/PrmPkg/Readme.md
+++ b/PrmPkg/Readme.md
@@ -74,6 +74,18 @@ The following list are the currently defined build flags (if any) that may be pa
    This structure is passed as the context buffer to PRM handlers. The structure actually passed to PRM handlers is
    allocated and populated by the OS where it gets all the information to populate the context buffer from other structures.
 
+### PRM Platform GUID
+**IMPORTANT**
+
+A configuration item that requires user attention is the PRM platform GUID. Each platform that uses PRM must be
+uniquely identifiable so that various instances of a PRM module can target the correct platform in PRM module updates.
+
+To apply a unique platform GUID set the following PCD to a unique value in your platform DSC file.
+  ``gPrmPkgTokenSpaceGuid.PcdPrmPlatformGuid``
+
+The default value assigned in [PrmPkg.dec](PrmPkg/PrmPkg.dec) is zero. By design, this is an invalid value that will
+cause an ASSERT if it is not updated.
+
 ## Overview
 At a high-level, PRM can be viewed from three levels of granularity:
 
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 33/41] PrmPkg: Update PRM OpRegion
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (31 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 32/41] PrmPkg: Add PlatformGuid Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 34/41] Readme.md: Add iASL note and QEMU sample link Michael Kubacki
                   ` (7 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Liu Yun Y <yun.y.liu@intel.com>

1. Enable new PRM OpRegion structure
2. Add PRM Handler Update Lock/Unlock support

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: Liu Yun <yun.y.liu@intel.com>
---
 PrmPkg/PrmSsdtInstallDxe/Prm.asl | 131 +++++++++++++-------
 1 file changed, 88 insertions(+), 43 deletions(-)

diff --git a/PrmPkg/PrmSsdtInstallDxe/Prm.asl b/PrmPkg/PrmSsdtInstallDxe/Prm.asl
index 0457d09e6954..20a6fef9be7b 100644
--- a/PrmPkg/PrmSsdtInstallDxe/Prm.asl
+++ b/PrmPkg/PrmSsdtInstallDxe/Prm.asl
@@ -1,7 +1,7 @@
 /** @file
   The definition block in ACPI table for PRM Operation Region
 
-  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020-2021, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
@@ -16,60 +16,105 @@ DefinitionBlock (
 {
     Scope (\_SB)
     {
-        //
-        // PRM Bridge Device
-        //
-
-        Device (PRMB)
-        {
-            Name (_HID, "80860222")
-            Name (_CID, "80860222")
-            Name (_DDN, "PRM Bridge Device")
-            Name (_STA, 0xF)
-            OperationRegion (OPR1, 0x80, 0, 16)
-            Field (OPR1, DWordAcc, NoLock, Preserve) //Make it ByteAcc for parameter validation
-            {
-                Var0, 128
-            }
-            Method (SETV, 1, Serialized)
-            {
-                CopyObject (Arg0, \_SB.PRMB.Var0)
-            }
-        }
-
         //
         // PRM Test Device
         //
-
         Device (PRMT)
         {
             Name (_HID, "80860223")
             Name (_CID, "80860223")
             Name (_DDN, "PRM Test Device")
-            Name (_STA, 0xF)
-            Name (BUF1, Buffer(16)
+
+            // PrmSamplePrintModule handler GUIDs
+            Name (BUF1, ToUUID("d5f2ad5f-a347-4d3e-87bc-c2ce63029cc8"))
+            Name (BUF2, ToUUID("a9e7adc3-8cd0-429a-8915-10946ebde318"))
+            Name (BUFN, ToUUID("b688c214-4081-4eeb-8d26-1eb5a3bcf11a"))
+
+            //PRM operation region format
+            OperationRegion (PRMR, PlatformRtMechanism, 0, 1)
+            Field (PRMR, BufferAcc, NoLock, Preserve) //Make it ByteAcc for parameter validation
             {
-                0x5F, 0xAD, 0xF2, 0xD5, 0x47, 0xA3, 0x3E, 0x4D, //Guid_0
-                0x87, 0xBC, 0xC2, 0xCE, 0x63, 0x02, 0x9C, 0xC8, //Guid_1
-            })
-            Name (BUF2, Buffer(16)
+                PRMF, 8
+            }
+
+            /*
+            * Control method to invoke PRM OperationRegion handler
+            * Arg0 contains a buffer representing a _DSM GUID
+            */
+            Method (RUNS, 1)
             {
-                0xC3, 0xAD, 0xE7, 0xA9, 0xD0, 0x8C, 0x9A, 0x42, //Guid_0
-                0x89, 0x15, 0x10, 0x94, 0x6E, 0xBD, 0xE3, 0x18, //Guid_1
-            })
-            Name (BUF3, Buffer(16)
+                /* Local0 is the PRM data buffer */
+                Local0 = buffer (26){}
+
+                /* Create byte fields over the buffer */
+                CreateByteField (Local0, 0x0, PSTA)
+                CreateQWordField (Local0, 0x1, USTA)
+                CreateByteField (Local0, 0x9, CMD)
+                CreateField (Local0, 0x50, 0x80, GUID)
+
+                /* Fill in the command and data fields of the data buffer */
+                CMD = 0 // run command
+                GUID = Arg0
+
+                /* Invoke PRM OperationRegion Handler and store the result into Local0 */
+                Local0 = (PRMF = Local0)
+
+                /* Return status */
+                Return (PSTA)
+            }
+
+            /*
+            * Control method to lock a PRM transaction
+            * Arg0 contains a buffer representing a _DSM GUID
+            */
+            Method (LCKH, 1)
             {
-                0x14, 0xC2, 0x88, 0xB6, 0x81, 0x40, 0xEB, 0x4E, //Guid_0
-                0x8D, 0x26, 0x1E, 0xB5, 0xA3, 0xBC, 0xF1, 0x1A, //Guid_1
-            })
-            Method (NTST)
+                /* Local0 is the PRM data buffer */
+                Local0 = buffer (26){}
+
+                /* Create byte fields over the buffer */
+                CreateByteField (Local0, 0x0, STAT)
+                CreateByteField (Local0, 0x9, CMD)
+                CreateField (Local0, 0x50, 0x80, GUID)
+                CMD = 1 // Lock command
+                GUID = Arg0
+                Local0 = (PRMF = Local0)
+
+                /* Note STAT contains the return status */
+                Return (STAT)
+            }
+
+            /*
+            * Control method to unlock a PRM transaction
+            * Arg0 contains a buffer representing a _DSM GUID
+            */
+            Method (ULCK, 1)
             {
-                \_SB.PRMB.SETV (BUF1)
+                /* Local0 is the PRM data buffer */
+                Local0 = buffer (26){}
+
+                /* Create byte fields over the buffer */
+                CreateByteField (Local0, 0x0, STAT)
+                CreateByteField (Local0, 0x9, CMD)
+                CreateField (Local0, 0x50, 0x80, GUID)
+                CMD = 2 // Unlock command
+                GUID = Arg0
+                Local0 = (PRMF = Local0)
+
+               /* Note STAT contains the return status */
+                Return (STAT)
+            }
+
+            /*
+            *Bit [0] Set if the device is present.
+            *Bit [1] Set if the device is enabled and decoding its resources.
+            *Bit [2] Set if the device should be shown in the UI.
+            *Bit [3] Set if the device is functioning properly (cleared if device failed its diagnostics).
+            */
+            Method (_STA, 0, NotSerialized)
+            {
+                Return (0x0B) // Device present, but not shown
             }
         }
     }
-
-} // End of Definition Block
-
-
-
+}
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 34/41] Readme.md: Add iASL note and QEMU sample link
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (32 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 33/41] PrmPkg: Update PRM OpRegion Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 35/41] PrmPkg: Replace PcdPrmPlatformGuid with EDKII_DSC_PLATFORM_GUID Michael Kubacki
                   ` (6 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a note that the build now depends on an ASL compiler supporting
PlatformRtMechanism by default. The minimum iASL version supported
is noted in addition to an alternative to remove the code that
requires the new OperationRegion.

Also, a link is provided to an example of how to integrate the
package into a platform using QEMU/OvmfPkg as the sample platform
and firmware.

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>
---
 PrmPkg/Readme.md | 23 ++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/PrmPkg/Readme.md b/PrmPkg/Readme.md
index 40df8f00a0c8..f340eeb64258 100644
--- a/PrmPkg/Readme.md
+++ b/PrmPkg/Readme.md
@@ -13,6 +13,14 @@ to be leveraged by platform firmware with minimal overhead to integrate PRM func
 formal design and is not validated at product quality. The development of this feature is shared in the edk2-staging
 branch to simplify collaboration by allowing direct code contributions and early feedback throughout its development.
 
+> By default, the build makes use of a new ACPI OperationRegion type specifically introduced for PRM called
+`PlatformRtMechanism`. Support for this OperationRegion is planned for the next release of the ACPI specification.
+However, support for `PlatformRtMechanism` is already included in the iASL Compiler/Disassembler for early prototyping
+(i.e. this package). If you would like the default build to work and/or to use PRM handlers that are invoked
+through ACPI, iASL compiler [20200528](https://acpica.org/node/181) or greater must be used. If you are only
+interested in compiling the code and/or using direct call style PRM handlers, you can simply remove
+`PrmSsdtInstallDxe` from `PrmPkg.dsc`.
+
 ## How to Build PrmPkg
 As noted earlier, resources in `PrmPkg` are intended to be referenced by a platform firmware so it can adopt support
 for PRM. In that case, the platform firmware should add the `PrmConfigDxe` and `PrmLoaderDxe` drivers to its DSC and
@@ -60,6 +68,21 @@ To build `PrmPkg` as a standalone package:
    > __*Note*__: Due to the way PRM modules are compiled with exports, **only building on Visual Studio compiler tool
    chains is currently supported**.
 
+In the future, each new terminal session can start at step #4. Within a terminal session, start at step #8.
+
+> __*Note*__: \
+> This package has been used without modification in several environments including client, server,
+> and virtual systems.
+>
+> A functional example of how to integrate this code into a platform is available here:
+> https://github.com/makubacki/edk2/tree/sample_ovmfpkg_prmpkg_integration
+>
+> That build will load the drivers and PRM sample modules provided in this package in the open source emulator
+> [QEMU](https://www.qemu.org/) by including it in the [`OvmfPkg`](https://github.com/tianocore/edk2/tree/master/OvmfPkg) build.
+>
+> You can add your own PRM modules into the build and check them with the `PrmInfo` UEFI application described
+> later in this document and dump the PRMT table in the OS to check if your PRM module is represented as expected.
+
 ### Build Flags
 As PRM is a new feature at a proof-of-concept (POC) level of maturity, there's some changes to the normal build
 available as build flags. By default, if no flags are specified, the build is done with the currently expected plan of
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 35/41] PrmPkg: Replace PcdPrmPlatformGuid with EDKII_DSC_PLATFORM_GUID
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (33 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 34/41] Readme.md: Add iASL note and QEMU sample link Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 36/41] PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule Michael Kubacki
                   ` (5 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Bugzilla request https://bugzilla.tianocore.org/show_bug.cgi?id=2969
was recently completed which causes the PLATFORM_GUID value from the
DSC file to be placed into Autogen file .c & .h files. With this
change, the PRM Platform GUID can be directly matched to the DSC
PLATFORM_GUID value.

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>
---
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c   | 12 +++++-----
 PrmPkg/Include/PrmExportDescriptor.h |  2 ++
 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf |  1 -
 PrmPkg/PrmPkg.dec                    | 10 ---------
 PrmPkg/Readme.md                     | 23 +++++++++++++++-----
 5 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
index f78c682a654b..e2779f5c1786 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
@@ -53,7 +53,6 @@ ProcessPrmModules (
   OUT PRM_ACPI_DESCRIPTION_TABLE          **PrmAcpiDescriptionTable
   )
 {
-  EFI_GUID                                *PlatformGuid;
   EFI_IMAGE_EXPORT_DIRECTORY              *CurrentImageExportDirectory;
   PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT     *CurrentExportDescriptorStruct;
   PRM_ACPI_DESCRIPTION_TABLE              *PrmAcpiTable;
@@ -81,18 +80,17 @@ ProcessPrmModules (
   }
   *PrmAcpiDescriptionTable = NULL;
 
-  PlatformGuid = (EFI_GUID *) PcdGetPtr (PcdPrmPlatformGuid);
   //
-  // The platform should set PcdPrmPlatformGuid to a non-zero value
+  // The platform DSC GUID must be set to a non-zero value
   //
-  if (CompareGuid (PlatformGuid, &gZeroGuid)) {
+  if (CompareGuid (&gEdkiiDscPlatformGuid, &gZeroGuid)) {
     DEBUG ((
       DEBUG_ERROR,
-      "  %a %a: PcdPrmPlatformGuid must be set to a unique value in the platform DSC file.\n",
+      "  %a %a: The Platform GUID in the DSC file must be set to a unique non-zero value.\n",
       _DBGMSGID_,
       __FUNCTION__
       ));
-    ASSERT (!CompareGuid (PlatformGuid, &gZeroGuid));
+    ASSERT (!CompareGuid (&gEdkiiDscPlatformGuid, &gZeroGuid));
   }
 
   DEBUG ((DEBUG_INFO, "  %a %a: %d total PRM modules to process.\n", _DBGMSGID_, __FUNCTION__, mPrmModuleCount));
@@ -118,7 +116,7 @@ ProcessPrmModules (
   PrmAcpiTable->Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
   PrmAcpiTable->Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
   PrmAcpiTable->Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
-  CopyGuid (&PrmAcpiTable->PrmPlatformGuid, PlatformGuid);
+  CopyGuid (&PrmAcpiTable->PrmPlatformGuid, &gEdkiiDscPlatformGuid);
   PrmAcpiTable->PrmModuleInfoOffset     = OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure);
   PrmAcpiTable->PrmModuleInfoCount      = (UINT32) mPrmModuleCount;
 
diff --git a/PrmPkg/Include/PrmExportDescriptor.h b/PrmPkg/Include/PrmExportDescriptor.h
index fc313fd1acc7..76b67a05458a 100644
--- a/PrmPkg/Include/PrmExportDescriptor.h
+++ b/PrmPkg/Include/PrmExportDescriptor.h
@@ -30,6 +30,7 @@ typedef struct {
   UINT64                                Signature;
   UINT16                                Revision;
   UINT16                                NumberPrmHandlers;
+  GUID                                  PlatformGuid;
   GUID                                  ModuleGuid;
 } PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;
 
@@ -98,6 +99,7 @@ typedef struct {
       PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE,                                                             \
       PRM_MODULE_EXPORT_REVISION,                                                                         \
       VA_ARG_COUNT(__VA_ARGS__),                                                                          \
+      EDKII_DSC_PLATFORM_GUID,                                                                            \
       EFI_CALLER_ID_GUID                                                                                  \
     },                                                                                                    \
     { __VA_ARGS__ }                                                                                       \
diff --git a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
index 7efefdae960f..26e7cc169897 100644
--- a/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
+++ b/PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
@@ -52,7 +52,6 @@ [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision      ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId        ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision  ## CONSUMES
-  gPrmPkgTokenSpaceGuid.PcdPrmPlatformGuid                      ## CONSUMES
 
 [Protocols]
   gEfiAcpiTableProtocolGuid
diff --git a/PrmPkg/PrmPkg.dec b/PrmPkg/PrmPkg.dec
index 6753ac624444..94888d1c70a4 100644
--- a/PrmPkg/PrmPkg.dec
+++ b/PrmPkg/PrmPkg.dec
@@ -65,13 +65,3 @@ [PcdsFixedAtBuild]
   #  report PRM handler execution time in the application. If such a TimerLib
   #  instance is not available, set this PCD to FALSE in the package DSC file.
   gPrmPkgTokenSpaceGuid.PcdPrmInfoPrintHandlerExecutionTime|TRUE|BOOLEAN|0x00000003
-
-  ## PRM Platform GUID
-  #
-  #  Uniquely identifies a specific platform targeted for PRM module updates. Each
-  #  platform MUST provide a new GUID. This GUID is checked against the platform
-  #  GUID in the PRM module export descriptor during PRM runtime updates to determine
-  #  if a given PRM module update is valid for a given system. Even if PRM runtime
-  #  updates are not planned for a given platform, this value should still be given
-  #  a unique value in the platform DSC.
-  gPrmPkgTokenSpaceGuid.PcdPrmPlatformGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}|VOID*|0x00000004
diff --git a/PrmPkg/Readme.md b/PrmPkg/Readme.md
index f340eeb64258..4aec5982af54 100644
--- a/PrmPkg/Readme.md
+++ b/PrmPkg/Readme.md
@@ -13,6 +13,10 @@ to be leveraged by platform firmware with minimal overhead to integrate PRM func
 formal design and is not validated at product quality. The development of this feature is shared in the edk2-staging
 branch to simplify collaboration by allowing direct code contributions and early feedback throughout its development.
 
+> **Use recent edk2/master** - This code makes use of a very recent change in edk2 BaseTools. Specifically, commit
+[b65afdd](https://github.com/tianocore/edk2/commit/b65afdde74d6c1fac1cdbd2efdad23ba26295808). Ensure you have that
+change to build the code in this repo as-is.
+
 > By default, the build makes use of a new ACPI OperationRegion type specifically introduced for PRM called
 `PlatformRtMechanism`. Support for this OperationRegion is planned for the next release of the ACPI specification.
 However, support for `PlatformRtMechanism` is already included in the iASL Compiler/Disassembler for early prototyping
@@ -100,14 +104,21 @@ The following list are the currently defined build flags (if any) that may be pa
 ### PRM Platform GUID
 **IMPORTANT**
 
-A configuration item that requires user attention is the PRM platform GUID. Each platform that uses PRM must be
-uniquely identifiable so that various instances of a PRM module can target the correct platform in PRM module updates.
+PRM has a concept of a "Platform GUID" which associates a specific platform with a set of PRM modules built for
+that platform. This GUID is used to ensure system compatibility for a given collection of PRM modules.
 
-To apply a unique platform GUID set the following PCD to a unique value in your platform DSC file.
-  ``gPrmPkgTokenSpaceGuid.PcdPrmPlatformGuid``
+Therefore, each PRM module must only target a single platform and each platform must have a unique GUID. Even if a
+PRM module is unchanged between two different platforms now, there is no guarantee that will remain the case so always
+assign a unique Platform GUID for each platform.
 
-The default value assigned in [PrmPkg.dec](PrmPkg/PrmPkg.dec) is zero. By design, this is an invalid value that will
-cause an ASSERT if it is not updated.
+The PRM Platform GUID is primarily used during PRM module runtime updates in the OS to ensure that the Platform GUID
+in the system's ACPI table (PRMT) matches the Platform GUID of the module requested for update. Even if runtime
+updates are not a planned feature for a given platform, still assign a unique Platform GUID for binary module
+identification (the Platform GUID is in the module's export descriptor) and to ensure such updates can be seamlessly
+supported in the future if needed.
+
+In the `PrmPkg` implementation, the Platform GUID is automatically derived from the PLATFORM_GUID in the DSC file of
+the package being built.
 
 ## Overview
 At a high-level, PRM can be viewed from three levels of granularity:
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 36/41] PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (34 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 35/41] PrmPkg: Replace PcdPrmPlatformGuid with EDKII_DSC_PLATFORM_GUID Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 37/41] PrmPkg/Samples: Remove PrmSamplePrintModule Michael Kubacki
                   ` (4 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Removes PrmSampleMemoryAllocationModule since the module depends
upon the deprecated concept of OS services.

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>
---
 PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.c   | 115 --------------------
 PrmPkg/PrmPkg.dsc                                                                  |   8 --
 PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf |  43 --------
 3 files changed, 166 deletions(-)

diff --git a/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.c b/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.c
deleted file mode 100644
index f1245664ab9c..000000000000
--- a/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/** @file
-
-  A sample PRM Module implementation. This PRM Module provides 3 PRM handlers that simply take a DEBUG print
-  function from the OS and invoke it with a debug message internal the PRM handler.
-
-  Copyright (c) Microsoft Corporation
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PrmModule.h>
-
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/PrintLib.h>
-#include <Library/UefiLib.h>
-
-//
-// PRM Handler GUIDs
-//
-
-// {149a5cb3-6a9c-403f-940a-156abf63938a}
-#define PRM_HANDLER_1_GUID {0x149a5cb3, 0x6a9c, 0x403f, {0x94, 0x0a, 0x15, 0x6a, 0xbf, 0x63, 0x93, 0x8a}}
-
-// Note: If the signature size is modified, the PRM Handler test code in this module needs to be updated.
-#define MEMORY_ALLOCATION_TEST_DATA_SIGNATURE     SIGNATURE_32('T','E','S','T')
-#define MEMORY_ALLOCATION_TEST_DATA_SIZE          sizeof(UINT32)
-#define MEMORY_ALLOCATION_TEST_DATA_BUFFER_SIZE   256
-
-/**
-  A sample Platform Runtime Mechanism (PRM) handler.
-
-  This sample handler currently uses the OS_SERVICES to write a debug message
-  indicating this is PRM handler 1.
-
-  @param[in]  ParameterBuffer    A pointer to the PRM handler parameter buffer
-  @param[in]  ContextBuffer      A pointer to the PRM handler context buffer
-
-  @retval EFI_STATUS              The PRM handler executed successfully.
-  @retval Others                  An error occurred in the PRM handler.
-
-**/
-EFI_STATUS
-PRM_EXPORT_API
-EFIAPI
-PrmHandler1 (
-  IN VOID                         *ParameterBuffer,
-  IN PRM_CONTEXT_BUFFER           *ContextBUffer
-  )
-{
-  EFI_STATUS                      Status;
-  UINTN                           Index;
-  VOID                            *NonPagedPool;
-  CHAR8                           DebugMessage[256];
-
-  if (OsServices == NULL || OsServices->DebugPrint == NULL || OsServices->AllocateMemory == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  OsServices->DebugPrint ("Memory Allocation PrmHandler1 entry.\n");
-  OsServices->DebugPrint ("  Requesting allocation of a 256 byte non-paged pool...\n");
-
-  NonPagedPool = NULL;
-  NonPagedPool = OsServices->AllocateMemory (MEMORY_ALLOCATION_TEST_DATA_BUFFER_SIZE, FALSE);
-  if (NonPagedPool == NULL) {
-    OsServices->DebugPrint ("  NULL was returned from AllocateMemory()...\n");
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  Buffer address returned from AllocateMemory() = 0x%016lx.\n",
-    (UINTN) NonPagedPool
-    );
-  OsServices->DebugPrint (&DebugMessage[0]);
-
-  // Write the test data
-  OsServices->DebugPrint ("  Beginning memory buffer write and read back test...\n");
-  SetMem32 (NonPagedPool, MEMORY_ALLOCATION_TEST_DATA_BUFFER_SIZE, MEMORY_ALLOCATION_TEST_DATA_SIGNATURE);
-
-  // Read back and verify the test data is valid
-  for (Index = 0, Status = EFI_SUCCESS; Index < (MEMORY_ALLOCATION_TEST_DATA_BUFFER_SIZE / MEMORY_ALLOCATION_TEST_DATA_SIZE); Index++) {
-    if (((UINT32 *) NonPagedPool)[Index] != MEMORY_ALLOCATION_TEST_DATA_SIGNATURE) {
-      Status = EFI_DEVICE_ERROR;
-      break;
-    }
-  }
-  if (EFI_ERROR (Status)) {
-    OsServices->DebugPrint ("    Memory write & read test failed.\n");
-  } else {
-    OsServices->DebugPrint ("    Memory write & read test passed.\n");
-  }
-
-  OsServices->DebugPrint ("Memory Allocation PrmHandler1 exit.\n");
-
-  return EFI_SUCCESS;
-}
-
-//
-// Register the PRM export information for this PRM Module
-//
-PRM_MODULE_EXPORT (
-  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_1_GUID, PrmHandler1)
-  );
-
-EFI_STATUS
-EFIAPI
-PrmSampleMemoryAllocationModuleInit (
-  IN  EFI_HANDLE                  ImageHandle,
-  IN  EFI_SYSTEM_TABLE            *SystemTable
-  )
-{
-  return EFI_SUCCESS;
-}
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index 911158302404..c6e5a151eeca 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -141,14 +141,6 @@ [Components]
   #
   $(PLATFORM_PACKAGE)/Application/PrmInfo/PrmInfo.inf
 
-  #
-  # The SampleMemoryAllocationModule was used during a time in the POC when the OS
-  # provided memory allocation services. This module was successful in using those services.
-  # Since OS services have been removed (aside from debug prints), this module is no longer
-  # relevant but kept around for archival purposes.
-  #
-  #$(PLATFORM_PACKAGE)/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
-
 [BuildOptions]
 # Force deprecated interfaces off
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf b/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
deleted file mode 100644
index 06be8f40f4ec..000000000000
--- a/PrmPkg/Samples/PrmSampleMemoryAllocationModule/PrmSampleMemoryAllocationModule.inf
+++ /dev/null
@@ -1,43 +0,0 @@
-## @file
-#  Sample PRM Driver
-#
-#  This driver simply uses an OS-provided debug message print service to write
-#  a debug message. Three PRM handlers are provided that each print a unique
-#  debug message.
-#
-#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
-#  Copyright (c) Microsoft Corporation
-#
-#  SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
-  INF_VERSION                    = 0x00010005
-  BASE_NAME                      = PrmSampleMemoryAllocationModule
-  FILE_GUID                      = C6B3E74A-12E3-4364-8FB4-8C8B34DD153B
-  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
-  VERSION_STRING                 = 1.0
-  ENTRY_POINT                    = PrmSampleMemoryAllocationModuleInit
-
-[Sources]
-  PrmSampleMemoryAllocationModule.c
-
-[Packages]
-  MdePkg/MdePkg.dec
-  MdeModulePkg/MdeModulePkg.dec
-  PrmPkg/PrmPkg.dec
-
-[LibraryClasses]
-  BaseLib
-  BaseMemoryLib
-  PrintLib
-  UefiDriverEntryPoint
-  UefiLib
-
-[Depex]
-  TRUE
-
-[BuildOptions.common]
-  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
-  MSFT:*_*_*_GENFW_FLAGS = --keepoptionalheader
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 37/41] PrmPkg/Samples: Remove PrmSamplePrintModule
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (35 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 36/41] PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 38/41] PrmPkg: Remove the concept of OS services Michael Kubacki
                   ` (3 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

This sample module is removed since it directly depends on OS
services which are no longer supported as of the current PRM
design.

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>
---
 PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.c   | 157 --------------------
 PrmPkg/PrmPkg.dsc                                            |   1 -
 PrmPkg/PrmSsdtInstallDxe/Prm.asl                             |   5 -
 PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf |  41 -----
 PrmPkg/Samples/Readme.md                                     |  73 +--------
 5 files changed, 1 insertion(+), 276 deletions(-)

diff --git a/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.c b/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.c
deleted file mode 100644
index 85e8eb28a231..000000000000
--- a/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/** @file
-
-  A sample PRM Module implementation. This PRM Module provides 3 PRM handlers that simply take a DEBUG print
-  function from the OS and invoke it with a debug message internal the PRM handler.
-
-  Copyright (c) Microsoft Corporation
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PrmModule.h>
-
-#include <Library/BaseLib.h>
-#include <Library/UefiLib.h>
-
-//
-// PRM Handler GUIDs
-//
-
-// {d5f2ad5f-a347-4d3e-87bc-c2ce63029cc8}
-#define PRM_HANDLER_1_GUID {0xd5f2ad5f, 0xa347, 0x4d3e, {0x87, 0xbc, 0xc2, 0xce, 0x63, 0x02, 0x9c, 0xc8}}
-
-// {a9e7adc3-8cd0-429a-8915-10946ebde318}
-#define PRM_HANDLER_2_GUID  {0xa9e7adc3, 0x8cd0, 0x429a, {0x89, 0x15, 0x10, 0x94, 0x6e, 0xbd, 0xe3, 0x18}}
-
-// {b688c214-4081-4eeb-8d26-1eb5a3bcf11a}
-#define PRM_HANDLER_N_GUID {0xb688c214, 0x4081, 0x4eeb, {0x8d, 0x26, 0x1e, 0xb5, 0xa3, 0xbc, 0xf1, 0x1a}}
-
-/**
-  A sample Platform Runtime Mechanism (PRM) handler.
-
-  This sample handler currently uses the OS_SERVICES to write a debug message
-  indicating this is PRM handler 1.
-
-  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
-  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
-
-  @retval EFI_STATUS              The PRM handler executed successfully.
-  @retval Others                  An error occurred in the PRM handler.
-
-**/
-EFI_STATUS
-PRM_EXPORT_API
-EFIAPI
-PrmHandler1 (
-  IN VOID                         *ParameterBuffer,
-  IN PRM_CONTEXT_BUFFER           *ContextBUffer
-  )
-{
-  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
-
-  if (ParameterBuffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
-  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
-  if (OsServiceDebugPrint == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-  OsServiceDebugPrint ("PRM1 handler sample message!\n");
-
-  return EFI_SUCCESS;
-}
-
-/**
-  A sample Platform Runtime Mechanism (PRM) handler.
-
-  This sample handler currently uses the OS_SERVICES to write a debug message
-  indicating this is PRM handler 2.
-
-  @param[in]  ParameterBuffer    A pointer to the PRM handler parameter buffer
-  @param[in]  ContextBUffer      A pointer to the PRM handler context buffer
-
-  @retval EFI_STATUS             The PRM handler executed successfully.
-  @retval Others                 An error occurred in the PRM handler.
-
-**/
-EFI_STATUS
-PRM_EXPORT_API
-EFIAPI
-PrmHandler2 (
-  IN VOID                         *ParameterBuffer,
-  IN PRM_CONTEXT_BUFFER           *ContextBUffer
-  )
-{
-  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
-
-  if (ParameterBuffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
-  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
-  if (OsServiceDebugPrint == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-  OsServiceDebugPrint ("PRM2 handler sample message!\n");
-
-  return EFI_SUCCESS;
-}
-
-/**
-  A sample Platform Runtime Mechanism (PRM) handler.
-
-  This sample handler currently uses the OS_SERVICES to write a debug message
-  indicating this is PRM handler N.
-
-  @param[in]  ParameterBuffer    A pointer to the PRM handler parameter buffer
-  @param[in]  ContextBUffer      A pointer to the PRM handler context buffer
-
-  @retval EFI_STATUS             The PRM handler executed successfully.
-  @retval Others                 An error occurred in the PRM handler.
-
-**/
-EFI_STATUS
-PRM_EXPORT_API
-EFIAPI
-PrmHandlerN (
-  IN VOID                         *ParameterBuffer,
-  IN PRM_CONTEXT_BUFFER           *ContextBUffer
-  )
-{
-  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
-
-  if (ParameterBuffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
-  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
-  if (OsServiceDebugPrint == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-  OsServiceDebugPrint ("PRMN handler sample message!\n");
-
-  return EFI_SUCCESS;
-}
-
-//
-// Register the PRM export information for this PRM Module
-//
-PRM_MODULE_EXPORT (
-  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_1_GUID, PrmHandler1),
-  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_2_GUID, PrmHandler2),
-  PRM_HANDLER_EXPORT_ENTRY (PRM_HANDLER_N_GUID, PrmHandlerN)
-  );
-
-EFI_STATUS
-EFIAPI
-PrmSamplePrintModuleInit (
-  IN  EFI_HANDLE                  ImageHandle,
-  IN  EFI_SYSTEM_TABLE            *SystemTable
-  )
-{
-  return EFI_SUCCESS;
-}
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index c6e5a151eeca..68768c87f276 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -128,7 +128,6 @@ [Components]
   #
   # PRM Sample Modules
   #
-  $(PLATFORM_PACKAGE)/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
   $(PLATFORM_PACKAGE)/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf
   $(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf {
     <LibraryClasses>
diff --git a/PrmPkg/PrmSsdtInstallDxe/Prm.asl b/PrmPkg/PrmSsdtInstallDxe/Prm.asl
index 20a6fef9be7b..e34336b4eee6 100644
--- a/PrmPkg/PrmSsdtInstallDxe/Prm.asl
+++ b/PrmPkg/PrmSsdtInstallDxe/Prm.asl
@@ -25,11 +25,6 @@ DefinitionBlock (
             Name (_CID, "80860223")
             Name (_DDN, "PRM Test Device")
 
-            // PrmSamplePrintModule handler GUIDs
-            Name (BUF1, ToUUID("d5f2ad5f-a347-4d3e-87bc-c2ce63029cc8"))
-            Name (BUF2, ToUUID("a9e7adc3-8cd0-429a-8915-10946ebde318"))
-            Name (BUFN, ToUUID("b688c214-4081-4eeb-8d26-1eb5a3bcf11a"))
-
             //PRM operation region format
             OperationRegion (PRMR, PlatformRtMechanism, 0, 1)
             Field (PRMR, BufferAcc, NoLock, Preserve) //Make it ByteAcc for parameter validation
diff --git a/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf b/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
deleted file mode 100644
index 7ac291bc6e8a..000000000000
--- a/PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf
+++ /dev/null
@@ -1,41 +0,0 @@
-## @file
-#  Sample PRM Driver
-#
-#  This driver simply uses an OS-provided debug message print service to write
-#  a debug message. Three PRM handlers are provided that each print a unique
-#  debug message.
-#
-#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
-#  Copyright (c) Microsoft Corporation
-#
-#  SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
-  INF_VERSION                    = 0x00010005
-  BASE_NAME                      = PrmSamplePrintModule
-  FILE_GUID                      = 1652B3C2-A7A1-46AC-AF93-DD6DEE446669
-  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
-  VERSION_STRING                 = 1.0
-  ENTRY_POINT                    = PrmSamplePrintModuleInit
-
-[Sources]
-  PrmSamplePrintModule.c
-
-[Packages]
-  MdePkg/MdePkg.dec
-  MdeModulePkg/MdeModulePkg.dec
-  PrmPkg/PrmPkg.dec
-
-[LibraryClasses]
-  BaseLib
-  UefiDriverEntryPoint
-  UefiLib
-
-[Depex]
-  TRUE
-
-[BuildOptions.common]
-  MSFT:*_*_*_DLINK_FLAGS  = /DLL /SUBSYSTEM:CONSOLE /VERSION:1.0
-  MSFT:*_*_*_GENFW_FLAGS = --keepoptionalheader
diff --git a/PrmPkg/Samples/Readme.md b/PrmPkg/Samples/Readme.md
index 4926be243018..d9f06f8b87de 100644
--- a/PrmPkg/Samples/Readme.md
+++ b/PrmPkg/Samples/Readme.md
@@ -21,7 +21,7 @@ Note that the build command does provide the option to build a specific module i
 faster build time. If you would like to just build a single PRM module that can be done by specifying the path to
 the module INF file with the "-m" argument to `build`. For example, this command builds 32-bit and 64-bit binaries
 with Visual Studio 2019: \
-``build -p PrmPkg/PrmPkg.dsc -m PrmPkg/Samples/PrmSamplePrintModule/PrmSamplePrintModule.inf -a IA32 -a X64 -t VS2019``
+``build -p PrmPkg/PrmPkg.dsc -m PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf -a IA32 -a X64 -t VS2019``
 
 ## PRM Sample Module User's Guide
 
@@ -33,77 +33,6 @@ It is recommended that all PRM authors write a similar set of documentation for
 and interact with their PRM modules.
 
 ---
-### Module: PRM Sample Print Module
->* Name: `PrmSamplePrintModule`
->* GUID: `1652b3c2-a7a1-46ac-af93-dd6dee446669`
-> * Purpose:
->   * Simplest PRM module example
->   * Example of a PRM module with multiple PRM handlers
-
-**Handlers:**
-#### Handler: PRM Handler 1
-* Name: `PrmHandler1`
-* GUID: `d5f2ad5f-a347-4d3e-87bc-c2ce63029cc8`
-* Actions:
-  * Use an OS-provided function pointer (pointer at the beginning of the parameter buffer) to write the message
-    “PRM1 handler sample message!”
-
-* Parameter Buffer Required: Yes
-* Parameter Buffer Contents:
-  ```c
-  typedef struct {
-
-    PRM_OS_SERVICE_DEBUG_PRINT *
-
-  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
-  ```
-
-* Context Buffer Required: No
-
-* Runtime MMIO Range(s) Required: No
-
-#### Handler: PRM Handler 2
-* Name: `PrmHandler2`
-* GUID: `a9e7adc3-8cd0-429a-8915-10946ebde318`
-* Actions:
-  * Use an OS-provided function pointer (pointer at the beginning of the parameter buffer) to write the message
-    “PRM2 handler sample message!”
-
-* Parameter Buffer Required: Yes
-* Parameter Buffer Contents:
-  ```c
-  typedef struct {
-
-    PRM_OS_SERVICE_DEBUG_PRINT *
-
-  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
-  ```
-
-* Context Buffer Required: No
-
-* Runtime MMIO Range(s) Required: No
-
-#### Handler: PRM Handler N
-* Name: `PrmHandlerN`
-* GUID: `b688c214-4081-4eeb-8d26-1eb5a3bcf11a`
-* Actions:
-  * Use an OS-provided function pointer (pointer at the beginning of the parameter buffer) to write the message
-    “PRMN handler sample message!”
-
-* Parameter Buffer Required: Yes
-* Parameter Buffer Contents:
-  ```c
-  typedef struct {
-
-    PRM_OS_SERVICE_DEBUG_PRINT *
-
-  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
-  ```
-
-* Context Buffer Required: No
-
-* Runtime MMIO Range(s) Required: No
-
 ### Module: PRM Sample ACPI Parameter Buffer
 >* Name: `PrmSampleAcpiParameterBufferModule`
 >* GUID: `dc2a58a6-5927-4776-b995-d118a27335a2`
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 38/41] PrmPkg: Remove the concept of OS services
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (36 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 37/41] PrmPkg/Samples: Remove PrmSamplePrintModule Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-22 16:19 ` [PATCH v1 39/41] Readme.md: Add a link to PRM Specification Michael Kubacki
                   ` (2 subsequent siblings)
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

OS services are no longer supported as of the current PRM design.

1. Removes OS services from PrmSampleHardwareAccessModule
2. Removes the PrmOsServices.h file

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>
---
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c   | 328 +-------------------
 PrmPkg/Include/PrmModule.h                                                     |   1 -
 PrmPkg/Include/PrmOsServices.h                                                 |  45 ---
 PrmPkg/PrmPkg.dsc                                                              |   5 +-
 PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf |   1 -
 PrmPkg/Samples/Readme.md                                                       |  62 ----
 6 files changed, 8 insertions(+), 434 deletions(-)

diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
index 35da1fcf5f17..14d1e56ab88a 100644
--- a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.c
@@ -12,7 +12,6 @@
 
 #include <Library/BaseLib.h>
 #include <Library/MtrrLib.h>
-#include <Library/PrintLib.h>
 #include <Library/UefiLib.h>
 
 #include <Register/Intel/ArchitecturalMsr.h>
@@ -27,21 +26,12 @@
 // {2120cd3c-848b-4d8f-abbb-4b74ce64ac89}
 #define MSR_ACCESS_MICROCODE_SIGNATURE_PRM_HANDLER_GUID {0x2120cd3c, 0x848b, 0x4d8f, {0xab, 0xbb, 0x4b, 0x74, 0xce, 0x64, 0xac, 0x89}}
 
-// {5d28b4e7-3867-4aee-aa09-51fc282c3b22}
-#define MSR_PRINT_MICROCODE_SIGNATURE_PRM_HANDLER_GUID {0x5d28b4e7, 0x3867, 0x4aee, {0xaa, 0x09, 0x51, 0xfc, 0x28, 0x2c, 0x3b, 0x22}}
-
 // {ea0935a7-506b-4159-bbbb-48deeecb6f58}
 #define MSR_ACCESS_MTRR_DUMP_PRM_HANDLER_GUID {0xea0935a7, 0x506b, 0x4159, {0xbb, 0xbb, 0x48, 0xde, 0xee, 0xcb, 0x6f, 0x58}}
 
-// {4b64b702-4d2b-4dfe-ac5a-0b4110a2ca47}
-#define MSR_PRINT_MTRR_DUMP_PRM_HANDLER_GUID {0x4b64b702, 0x4d2b, 0x4dfe, {0xac, 0x5a, 0x0b, 0x41, 0x10, 0xa2, 0xca, 0x47}}
-
 // {1bd1bda9-909a-4614-9699-25ec0c2783f7}
 #define MMIO_ACCESS_HPET_PRM_HANDLER_GUID {0x1bd1bda9, 0x909a, 0x4614, {0x96, 0x99, 0x25, 0xec, 0x0c, 0x27, 0x83, 0xf7}}
 
-// {8a0efdde-78d0-45f0-aea0-c28245c7e1db}
-#define MMIO_PRINT_HPET_PRM_HANDLER_GUID {0x8a0efdde, 0x78d0, 0x45f0, {0xae, 0xa0, 0xc2, 0x82, 0x45, 0xc7, 0xe1, 0xdb}}
-
 //
 // BEGIN: MtrrLib internal library globals and function prototypes here for testing
 //
@@ -133,27 +123,19 @@ MtrrLibApplyVariableMtrrs (
 /**
   Accesses MTRR values including architectural and variable MTRRs.
 
-  If the optional OsServiceDebugPrint function pointer is provided that function is
-  used to print the MTRR settings.
-
-  @param[in]  OsServiceDebugPrint   A pointer to an OS-provided debug print function.
-
 **/
 VOID
 EFIAPI
 AccessAllMtrrs (
-  IN PRM_OS_SERVICE_DEBUG_PRINT   OsServiceDebugPrint   OPTIONAL
+  VOID
   )
 {
   MTRR_SETTINGS                   LocalMtrrs;
   MTRR_SETTINGS                   *Mtrrs;
-  UINTN                           Index;
   UINTN                           RangeCount;
   UINT64                          MtrrValidBitsMask;
   UINT64                          MtrrValidAddressMask;
   UINT32                          VariableMtrrCount;
-  BOOLEAN                         ContainVariableMtrr;
-  CHAR8                           DebugMessage[256];
 
   MTRR_MEMORY_RANGE Ranges[
     MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * ARRAY_SIZE (Mtrrs->Variables.Mtrr) + 1
@@ -169,66 +151,6 @@ AccessAllMtrrs (
   MtrrGetAllMtrrs (&LocalMtrrs);
   Mtrrs = &LocalMtrrs;
 
-  //
-  // Dump RAW MTRR contents
-  //
-  if (OsServiceDebugPrint != NULL) {
-    OsServiceDebugPrint ("  MTRR Settings:\n");
-    OsServiceDebugPrint ("  =============\n");
-
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  MTRR Default Type: %016lx\n",
-      Mtrrs->MtrrDefType
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-  }
-
-  if (OsServiceDebugPrint != NULL) {
-    for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
-        AsciiSPrint (
-          &DebugMessage[0],
-          ARRAY_SIZE (DebugMessage),
-          "  Fixed MTRR[%02d]   : %016lx\n",
-          Index,
-          Mtrrs->Fixed.Mtrr[Index]
-          );
-        OsServiceDebugPrint (&DebugMessage[0]);
-      }
-
-    ContainVariableMtrr = FALSE;
-    for (Index = 0; Index < VariableMtrrCount; Index++) {
-      if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {
-        //
-        // If mask is not valid, then do not display range
-        //
-        continue;
-      }
-      ContainVariableMtrr = TRUE;
-      AsciiSPrint (
-        &DebugMessage[0],
-        ARRAY_SIZE (DebugMessage),
-        "  Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
-        Index,
-        Mtrrs->Variables.Mtrr[Index].Base,
-        Mtrrs->Variables.Mtrr[Index].Mask
-        );
-      OsServiceDebugPrint (&DebugMessage[0]);
-    }
-    if (!ContainVariableMtrr) {
-      OsServiceDebugPrint ("  Variable MTRR    : None.\n");
-    }
-    OsServiceDebugPrint ("\n");
-  }
-
-  //
-  // Dump MTRR setting in ranges
-  //
-  if (OsServiceDebugPrint != NULL) {
-    OsServiceDebugPrint ("  Memory Ranges:\n");
-    OsServiceDebugPrint ("  ====================================\n");
-  }
   MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
   Ranges[0].BaseAddress = 0;
   Ranges[0].Length      = MtrrValidBitsMask + 1;
@@ -245,19 +167,6 @@ AccessAllMtrrs (
     );
 
   MtrrLibApplyFixedMtrrs (&Mtrrs->Fixed, Ranges, ARRAY_SIZE (Ranges), &RangeCount);
-
-  if (OsServiceDebugPrint != NULL) {
-    for (Index = 0; Index < RangeCount; Index++) {
-      AsciiSPrint (
-        &DebugMessage[0],
-        ARRAY_SIZE (DebugMessage),
-        "  %a:%016lx-%016lx\n",
-        mMtrrMemoryCacheTypeShortName[Ranges[Index].Type],
-        Ranges[Index].BaseAddress, Ranges[Index].BaseAddress + Ranges[Index].Length - 1
-        );
-      OsServiceDebugPrint (&DebugMessage[0]);
-    }
-  }
 }
 
 /**
@@ -300,104 +209,15 @@ HpetRead (
 /**
   Accesses HPET configuration information.
 
-  If the optional OsServiceDebugPrint function pointer is provided that function is
-  used to print HPET settings.
-
-  @param[in]  OsServiceDebugPrint   A pointer to an OS-provided debug print function
-
 **/
 VOID
 EFIAPI
 AccessHpetConfiguration (
-  IN PRM_OS_SERVICE_DEBUG_PRINT           OsServiceDebugPrint
+  VOID
   )
 {
-  UINTN                                   TimerIndex;
-  HPET_GENERAL_CAPABILITIES_ID_REGISTER   HpetGeneralCapabilities;
-  HPET_GENERAL_CONFIGURATION_REGISTER     HpetGeneralConfiguration;
-  CHAR8                                   DebugMessage[256];
-
-  HpetGeneralCapabilities.Uint64  = HpetRead (HPET_GENERAL_CAPABILITIES_ID_OFFSET);
-  HpetGeneralConfiguration.Uint64 = HpetRead (HPET_GENERAL_CONFIGURATION_OFFSET);
-
-  if (OsServiceDebugPrint != NULL) {
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  HPET Base Address = 0x%08x\n",
-      HPET_BASE_ADDRESS
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  HPET_GENERAL_CAPABILITIES_ID  = 0x%016lx\n",
-      HpetGeneralCapabilities
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  HPET_GENERAL_CONFIGURATION    = 0x%016lx\n",
-      HpetGeneralConfiguration.Uint64
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  HPET_GENERAL_INTERRUPT_STATUS = 0x%016lx\n",
-      HpetRead (HPET_GENERAL_INTERRUPT_STATUS_OFFSET)
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  HPET_MAIN_COUNTER             = 0x%016lx\n",
-      HpetRead (HPET_MAIN_COUNTER_OFFSET)
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-
-    AsciiSPrint (
-      &DebugMessage[0],
-      ARRAY_SIZE (DebugMessage),
-      "  HPET Main Counter Period      = %d (fs)\n",
-      HpetGeneralCapabilities.Bits.CounterClockPeriod
-      );
-    OsServiceDebugPrint (&DebugMessage[0]);
-
-    for (TimerIndex = 0; TimerIndex <= HpetGeneralCapabilities.Bits.NumberOfTimers; TimerIndex++) {
-      AsciiSPrint (
-        &DebugMessage[0],
-        ARRAY_SIZE (DebugMessage),
-        "  HPET_TIMER%d_CONFIGURATION     = 0x%016lx\n",
-        TimerIndex,
-        HpetRead (HPET_TIMER_CONFIGURATION_OFFSET + TimerIndex * HPET_TIMER_STRIDE)
-        );
-      OsServiceDebugPrint (&DebugMessage[0]);
-
-      AsciiSPrint (
-        &DebugMessage[0],
-        ARRAY_SIZE (DebugMessage),
-        "  HPET_TIMER%d_COMPARATOR        = 0x%016lx\n",
-        TimerIndex,
-        HpetRead (HPET_TIMER_COMPARATOR_OFFSET    + TimerIndex * HPET_TIMER_STRIDE)
-        );
-      OsServiceDebugPrint (&DebugMessage[0]);
-
-      AsciiSPrint (
-        &DebugMessage[0],
-        ARRAY_SIZE (DebugMessage),
-        "  HPET_TIMER%d_MSI_ROUTE         = 0x%016lx\n",
-        TimerIndex,
-        HpetRead (HPET_TIMER_MSI_ROUTE_OFFSET     + TimerIndex * HPET_TIMER_STRIDE)
-        );
-      OsServiceDebugPrint (&DebugMessage[0]);
-    }
-  }
+  HpetRead (HPET_GENERAL_CAPABILITIES_ID_OFFSET);
+  HpetRead (HPET_GENERAL_CONFIGURATION_OFFSET);
 }
 
 /**
@@ -419,34 +239,6 @@ GetMicrocodeSignature (
   return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;
 }
 
-/**
-  Prints the microcode update signature as read from architectural MSR 0x8B.
-
-**/
-VOID
-EFIAPI
-PrintMicrocodeUpdateSignature (
-  IN PRM_OS_SERVICE_DEBUG_PRINT   OsServiceDebugPrint
-  )
-{
-  UINT32                          MicrocodeSignature;
-  CHAR8                           DebugMessage[256];
-
-  if (OsServiceDebugPrint == NULL) {
-    return;
-  }
-
-  MicrocodeSignature = GetMicrocodeSignature ();
-
-  AsciiSPrint (
-    &DebugMessage[0],
-    ARRAY_SIZE (DebugMessage),
-    "  Signature read = 0x%x.\n",
-    MicrocodeSignature
-    );
-  OsServiceDebugPrint (&DebugMessage[0]);
-}
-
 /**
   A sample Platform Runtime Mechanism (PRM) handler.
 
@@ -473,40 +265,6 @@ PRM_HANDLER_EXPORT (MsrAccessMicrocodeSignaturePrmHandler)
   return EFI_SUCCESS;
 }
 
-/**
-  A sample Platform Runtime Mechanism (PRM) handler.
-
-  This sample handler attempts to read the microcode update signature MSR and print the result to a debug message.
-
-  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
-  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
-
-  @retval EFI_STATUS              The PRM handler executed successfully.
-  @retval Others                  An error occurred in the PRM handler.
-
-**/
-PRM_HANDLER_EXPORT (MsrPrintMicrocodeSignaturePrmHandler)
-{
-  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
-
-  if (ParameterBuffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // The OS debug print service is assumed to be at the beginning of ParameterBuffer
-  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
-  if (OsServiceDebugPrint == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  OsServiceDebugPrint ("Hardware Access MsrAccessMicrocodeSignaturePrmHandler entry.\n");
-  OsServiceDebugPrint ("  Attempting to read the Microcode Update Signature MSR (0x8B)...\n");
-  PrintMicrocodeUpdateSignature (OsServiceDebugPrint);
-  OsServiceDebugPrint ("Hardware Access MsrAccessMicrocodeSignaturePrmHandler exit.\n");
-
-  return EFI_SUCCESS;
-}
-
 /**
   A sample Platform Runtime Mechanism (PRM) handler.
 
@@ -521,46 +279,11 @@ PRM_HANDLER_EXPORT (MsrPrintMicrocodeSignaturePrmHandler)
 **/
 PRM_HANDLER_EXPORT (MsrAccessMtrrDumpPrmHandler)
 {
-  AccessAllMtrrs (NULL);
+  AccessAllMtrrs ();
 
   return EFI_SUCCESS;
 }
 
-/**
-  A sample Platform Runtime Mechanism (PRM) handler.
-
-  This sample handler attempts to read the current MTRR settings and print the result to a debug message.
-
-  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
-  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
-
-  @retval EFI_STATUS              The PRM handler executed successfully.
-  @retval Others                  An error occurred in the PRM handler.
-
-**/
-PRM_HANDLER_EXPORT (MsrPrintMtrrDumpPrmHandler)
-{
-  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
-
-  if (ParameterBuffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // In the POC, the OS debug print service is assumed to be at the beginning of ParameterBuffer
-  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
-  if (OsServiceDebugPrint == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  OsServiceDebugPrint ("Hardware Access MsrAccessMtrrDumpPrmHandler entry.\n");
-  OsServiceDebugPrint ("  Attempting to dump MTRR values:\n");
-  AccessAllMtrrs (OsServiceDebugPrint);
-  OsServiceDebugPrint ("Hardware Access MsrAccessMtrrDumpPrmHandler exit.\n");
-
-  return EFI_SUCCESS;
-}
-
-
 /**
   A sample Platform Runtime Mechanism (PRM) handler.
 
@@ -575,41 +298,7 @@ PRM_HANDLER_EXPORT (MsrPrintMtrrDumpPrmHandler)
 **/
 PRM_HANDLER_EXPORT (MmioAccessHpetPrmHandler)
 {
-  AccessHpetConfiguration (NULL);
-
-  return EFI_SUCCESS;
-}
-
-/**
-  A sample Platform Runtime Mechanism (PRM) handler.
-
-  This sample handler attempts to read from a HPET MMIO resource and print the result to a debug message.
-
-  @param[in]  ParameterBuffer     A pointer to the PRM handler parameter buffer
-  @param[in]  ContextBUffer       A pointer to the PRM handler context buffer
-
-  @retval EFI_STATUS              The PRM handler executed successfully.
-  @retval Others                  An error occurred in the PRM handler.
-
-**/
-PRM_HANDLER_EXPORT (MmioPrintHpetPrmHandler)
-{
-  PRM_OS_SERVICE_DEBUG_PRINT      OsServiceDebugPrint;
-
-  if (ParameterBuffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // An OS debug print service is assumed to be at the beginning of ParameterBuffer
-  OsServiceDebugPrint = *((PRM_OS_SERVICE_DEBUG_PRINT *) ParameterBuffer);
-  if (OsServiceDebugPrint == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  OsServiceDebugPrint ("Hardware Access MmioPrintHpetPrmHandler entry.\n");
-  OsServiceDebugPrint ("  Attempting to read HPET configuration...\n");
-  AccessHpetConfiguration (OsServiceDebugPrint);
-  OsServiceDebugPrint ("Hardware Access MmioPrintHpetPrmHandler exit.\n");
+  AccessHpetConfiguration ();
 
   return EFI_SUCCESS;
 }
@@ -620,10 +309,7 @@ PRM_HANDLER_EXPORT (MmioPrintHpetPrmHandler)
 PRM_MODULE_EXPORT (
   PRM_HANDLER_EXPORT_ENTRY (MSR_ACCESS_MICROCODE_SIGNATURE_PRM_HANDLER_GUID, MsrAccessMicrocodeSignaturePrmHandler),
   PRM_HANDLER_EXPORT_ENTRY (MSR_ACCESS_MTRR_DUMP_PRM_HANDLER_GUID, MsrAccessMtrrDumpPrmHandler),
-  PRM_HANDLER_EXPORT_ENTRY (MMIO_ACCESS_HPET_PRM_HANDLER_GUID, MmioAccessHpetPrmHandler),
-  PRM_HANDLER_EXPORT_ENTRY (MSR_PRINT_MICROCODE_SIGNATURE_PRM_HANDLER_GUID, MsrPrintMicrocodeSignaturePrmHandler),
-  PRM_HANDLER_EXPORT_ENTRY (MSR_PRINT_MTRR_DUMP_PRM_HANDLER_GUID, MsrPrintMtrrDumpPrmHandler),
-  PRM_HANDLER_EXPORT_ENTRY (MMIO_PRINT_HPET_PRM_HANDLER_GUID, MmioPrintHpetPrmHandler)
+  PRM_HANDLER_EXPORT_ENTRY (MMIO_ACCESS_HPET_PRM_HANDLER_GUID, MmioAccessHpetPrmHandler)
   );
 
 /**
diff --git a/PrmPkg/Include/PrmModule.h b/PrmPkg/Include/PrmModule.h
index d7047d8eec58..1369adda1aa7 100644
--- a/PrmPkg/Include/PrmModule.h
+++ b/PrmPkg/Include/PrmModule.h
@@ -15,7 +15,6 @@
 #include <PrmDataBuffer.h>
 #include <PrmExportDescriptor.h>
 #include <PrmMmio.h>
-#include <PrmOsServices.h>
 
 /**
   Macro that provides a condensed form of a PRM Handler.
diff --git a/PrmPkg/Include/PrmOsServices.h b/PrmPkg/Include/PrmOsServices.h
deleted file mode 100644
index 62dfa0018787..000000000000
--- a/PrmPkg/Include/PrmOsServices.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/** @file
-
-  Definitions for the Platform Runtime Mechanism (PRM) OS Services.
-
-  Note: OS Services have been removed from POR. This file has been reduced to just debug print
-        OS Service for use during PRM enabling.
-
-  Copyright (c) Microsoft Corporation
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef PRM_OS_SERVICES_H_
-#define PRM_OS_SERVICES_H_
-
-#include <Uefi.h>
-
-typedef struct _PRM_OS_SERVICES PRM_OS_SERVICES;
-
-//
-// PRM OS Services function signatures
-//
-typedef
-VOID
-(EFIAPI *PRM_OS_SERVICE_DEBUG_PRINT) (
-  IN  CONST CHAR8           *String
-  );
-
-#pragma pack(push, 1)
-
-//
-// PRM OS Services table
-//
-struct _PRM_OS_SERVICES {
-    // Structure information
-    UINT16                                MajorVersion;
-    UINT16                                MinorVersion;
-
-    // OS Services
-    PRM_OS_SERVICE_DEBUG_PRINT            DebugPrint;
-};
-
-#pragma pack(pop)
-
-#endif
diff --git a/PrmPkg/PrmPkg.dsc b/PrmPkg/PrmPkg.dsc
index 68768c87f276..d10aa3d547ce 100644
--- a/PrmPkg/PrmPkg.dsc
+++ b/PrmPkg/PrmPkg.dsc
@@ -129,10 +129,7 @@ [Components]
   # PRM Sample Modules
   #
   $(PLATFORM_PACKAGE)/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf
-  $(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf {
-    <LibraryClasses>
-      DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
-  }
+  $(PLATFORM_PACKAGE)/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
   $(PLATFORM_PACKAGE)/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf
 
   #
diff --git a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
index 369d1eb1e86d..46d4a88185a9 100644
--- a/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
+++ b/PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareAccessModule.inf
@@ -32,7 +32,6 @@ [Packages]
 [LibraryClasses]
   BaseLib
   MtrrLib
-  PrintLib
   UefiDriverEntryPoint
   UefiLib
 
diff --git a/PrmPkg/Samples/Readme.md b/PrmPkg/Samples/Readme.md
index d9f06f8b87de..590b81c349b4 100644
--- a/PrmPkg/Samples/Readme.md
+++ b/PrmPkg/Samples/Readme.md
@@ -128,65 +128,3 @@ and interact with their PRM modules.
 * Runtime MMIO Range(s) Required: Yes
   * Physical Base Address: 0xFED00000
   * Length: 0x1000
-
-#### Handler: MSR Print Microcode Signature PRM Handler
-* Name: `MsrPrintMicrocodeSignaturePrmHandler`
-* GUID: `5d28b4e7-3867-4aee-aa09-51fc282c3b22`
-* Actions:
-  * Use the provided print function to print the loaded microcode signature at MSR 0x8B.
-
-* Parameter Buffer Required: Yes
-* Parameter Buffer Contents:
-  ```c
-  typedef struct {
-
-    PRM_OS_SERVICE_DEBUG_PRINT *
-
-  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
-  ```
-
-* Context Buffer Required: No
-
-* Runtime MMIO Range(s) Required: No
-
-#### Handler: MSR Print MTRR Dump PRM Handler
-* Name: `MsrPrintMtrrDumpPrmHandler`
-* GUID: `4b64b702-4d2b-4dfe-ac5a-0b4110a2ca47`
-* Actions:
-  * Use the provided print function to print the fixed and variable MTRR values using MSRs.
-
-* Parameter Buffer Required: Yes
-* Parameter Buffer Contents:
-  ```c
-  typedef struct {
-
-    PRM_OS_SERVICE_DEBUG_PRINT *
-
-  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
-  ```
-
-* Context Buffer Required: No
-
-* Runtime MMIO Range(s) Required: No
-
-#### Handler: HPET MMIO Print PRM Handler
-* Name: `MmioPrintHpetPrmHandler`
-* GUID: `8a0efdde-78d0-45f0-aea0-c28245c7e1db`
-* Actions:
-  * Use the provided print function to print some HPET registers using MMIO at 0xFED00000.
-
-* Parameter Buffer Required: Yes
-* Parameter Buffer Contents:
-  ```c
-  typedef struct {
-
-    PRM_OS_SERVICE_DEBUG_PRINT *
-
-  } SAMPLE_OSDEBUGPRINT_PARAMETER_BUFFER;
-  ```
-
-* Context Buffer Required: No
-
-* Runtime MMIO Range(s) Required: Yes
-  * Physical Base Address: 0xFED00000
-  * Length: 0x1000
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v1 39/41] Readme.md: Add a link to PRM Specification
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (37 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 38/41] PrmPkg: Remove the concept of OS services Michael Kubacki
@ 2022-03-22 16:19 ` Michael Kubacki
  2022-03-28  8:48 ` 回复: [edk2-devel] [PATCH v1 00/41] Add PrmPkg gaoliming
  2022-03-29 16:28 ` Sinha, Ankit
  40 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-22 16:19 UTC (permalink / raw)
  To: devel
  Cc: Andrew Fish, Kang Gao, Michael D Kinney, Michael Kubacki,
	Leif Lindholm, Benjamin You, Liu Yun, Ankit Sinha, Nate DeSimone

From: Michael Kubacki <michael.kubacki@microsoft.com>

Adds a link to the PRM Specification now that it is available on uefi.org.

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>
---
 PrmPkg/Readme.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/PrmPkg/Readme.md b/PrmPkg/Readme.md
index 4aec5982af54..848f898ab6d3 100644
--- a/PrmPkg/Readme.md
+++ b/PrmPkg/Readme.md
@@ -5,6 +5,8 @@ code module that executes within the OS context. Moving this firmware to the OS
 and mitigates the negative system impact currently accompanied with SMM solutions. Futhermore, the PRM code is
 packaged into modules with well-defined entry points, each representing a specific PRM functionality.
 
+For more details on PRM, refer to the [Platform Runtime Mechanism Specification on uefi.org](https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mechanism%20-%20with%20legal%20notice.pdf).
+
 The `PrmPkg` maintained in this branch provides a single cohesive set of generic PRM functionality that is intended
 to be leveraged by platform firmware with minimal overhead to integrate PRM functionality in the firmware.
 
-- 
2.28.0.windows.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* 回复: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (38 preceding siblings ...)
  2022-03-22 16:19 ` [PATCH v1 39/41] Readme.md: Add a link to PRM Specification Michael Kubacki
@ 2022-03-28  8:48 ` gaoliming
  2022-03-28 14:05   ` Michael Kubacki
  2022-03-29 16:28 ` Sinha, Ankit
  40 siblings, 1 reply; 44+ messages in thread
From: gaoliming @ 2022-03-28  8:48 UTC (permalink / raw)
  To: devel, mikuback
  Cc: 'Andrew Fish', 'Kang Gao',
	'Michael D Kinney', 'Michael Kubacki',
	'Leif Lindholm', 'Benjamin You',
	'Liu Yun', 'Ankit Sinha', 'Nate DeSimone'

Michael:
  Please also update Maintainers.txt to specify maintainer for new PrmPkg. 

Thanks
Liming
> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Michael
> Kubacki
> 发送时间: 2022年3月23日 0:19
> 收件人: devel@edk2.groups.io
> 抄送: Andrew Fish <afish@apple.com>; Kang Gao <kang.gao@intel.com>;
> Michael D Kinney <michael.d.kinney@intel.com>; Michael Kubacki
> <michael.kubacki@microsoft.com>; Leif Lindholm <leif@nuviainc.com>;
> Benjamin You <benjamin.you@intel.com>; Liu Yun <yun.y.liu@intel.com>;
> Ankit Sinha <ankit.sinha@intel.com>; Nate DeSimone
> <nathaniel.l.desimone@intel.com>
> 主题: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
> 
> From: Michael Kubacki <michael.kubacki@microsoft.com>
> 
> This patch series adds a new package called PrmPkg. An RFC was sent
> to the edk2 mailing list on January 28, 2022 detailing the proposal,
> see https://edk2.groups.io/g/devel/message/86181.
> 
> Platform Runtime Mechanism (PRM) is a new firmware solution that has
> been developed in edk2-staging/PlatformRuntimeMechanism.
> 
> This patch series has been organized to greatly condense the history
> from the edk2-staging branch but to preserve important decisions and
> changes in history that help establish context of changes and will
> serve as valuable references for future development.
> 
> Interest in PRM has increased across various vendors and we believe
> it is beneficial to make the source code more widely available for
> the following reasons:
> 
>   1. PRM specification adoption
>   2. Feature completeness
>   3. Overall validation coverage
>   4. Interest from the community and future collaboration
> 
> The technical details of PRM are covered in the PRM Specification
> in addition to the Readme.md file located in the root of PrmPkg
> in this patch series.
> 
> 1. PRM specification adoption
> 
> Intel and Microsoft have worked together to standardize PRM in the
> ACPI Specification and the PRM Specification hosted on uefi.org.
> 
>   * ACPI 6.4 Specification:
>   https://uefi.org/node/4149
> 
>   * PRM Specification:
> 
> https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mech
> anism%20-%20with%20legal%20notice.pdf
> 
> 2. Feature completeness
> 
> PrmPkg implements the full firmware functionality described in the
> PRM Specification and there are no significant changes to
> functionality planned at this time.
> 
> Though we are very much interested in evolving PRM based on
> feedback.
> 
> 3. Overall validation coverage
> 
> PrmPkg has been integrated and tested on client and server systems
> in addition to virtual platforms (OvmfPkg/QEMU).
> 
> Platform integration is simple and a demonstration of this
> integration for OvmfPkg is available in the following branch:
> https://github.com/makubacki/edk2/tree/ovmf_prmpkg_integration
> 
> The code has been built with:
>   * MSFT VS2015, VS2017, and VS2019
>   * GCC5 (see https://bugzilla.tianocore.org/show_bug.cgi?id=3802)
>   * iASL compiler (20200528 - https://acpica.org/node/181)
> 
> The Linux kernel currently includes the following PRM support:
>   * _OSC PRM bit - allows FW to know determine the OS is
>     PRM-capable and can redirect _DSM method from alternate
>     triggers (such as SMI) to PRM.
>   * PRM invocation via _DSM, includes PRM module and handler parsing
>     from ACPI PRMT table, and also the PRM operation region handler
>     for runtime PRM service invocation.
>   * An OS configuration for PRM enabling, PRM support can be
>     disabled during OS image build.
> 
> Note that upstream Linux does not currently support the following:
>   * Ability for the OS driver to call a PRM handler directly,
>     it has to be via ACPI _DSM.
>   * Run time update PRM module and handler via PE/COFF PRM image.
> 
> This commit provides additional context of the changes in Linux:
> https://github.com/torvalds/linux/commit/cefc7ca46235f01d5233e3abd4b79
> 452af01d9e9
> 
> Windows 11 (https://www.microsoft.com/software-download/windows11)
> and Windows Server 2022
> (https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the
> -wdk)
> include the PRM functionality noted above in addition to PRM direct
> call and PRM runtime updates.
> 
> PRM has been tested on IA32, X64, and AARCH64 targets.
> 
> 4. Interest from the community and future collaboration
> 
> PRM has been presented at several industry conferences:
> 
> * OSFC 2020 - "PRM: SMM Goes on a Diet"
>   https://cfp.osfc.io/osfc2020/talk/MCJASB/
> 
> * OCP Summit 2019 - "Case Study Alternatives for SMM Usage in
>   Intel Platforms"
>   https://www.youtube.com/watch?v=mu3DRLM1dPA
> 
> In addition, Microsoft plans to publish the Windows PRM driver
> interface and a WDF sample driver that uses the interface to the
> Windows Driver Samples GitHub repository
> (https://github.com/microsoft/Windows-driver-samples).
> 
> We believe a PrmPkg in edk2 can increase accessibility to PRM and
> ease collaboration.
> 
> PrmPkg
> ------
> PrmPkg contains the common functionality needed to enable PRM on
> any system. It does not contain platform-specific code such as PRM
> modules (and by extension PRM handlers). Other than sample modules,
> PrmPkg will only contain code needed to provide PRM feature
> functionality as defined in the PRM Specification.
> 
> PrmPkg is scoped to continue to only contain platform-agnostic
> functionality in the future.
> 
> The proposed maintainers of PrmPkg are:
> * Michael Kubacki <mikuback@linux.microsoft.com>
> * Nate DeSimone <nathaniel.l.desimone@intel.com>
> 
> The proposed reviewers of PrmPkg are:
> * Ankit Sinha <ankit.sinha@intel.com>
> 
> 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>
> 
> Liu (2):
>   PrmPkg: Publish PRM operation region to support PRM ACPI _DSM
>     invocation
>   PrmPkg: Export major/minor version in PRM module PE COFF header
> 
> Liu Yun Y (1):
>   PrmPkg: Update PRM OpRegion
> 
> Michael Kubacki (38):
>   PrmPkg: Add package and include headers
>   PrmPkg: Add PrmConfig protocol interface
>   PrmPkg/PrmContextBufferLib: Add initial library instance
>   PrmPkg/PrmConfigDxe: Add initial driver
>   PrmPkg: Add initial PrmSamplePrintModule
>   PrmPkg: Add initial PrmSampleMemoryAllocationModule
>   PrmPkg: Add initial PrmSampleHardwareAccessModule
>   PrmPkg: Add initial PrmSampleContextBufferModule
>   PrmPkg: Add initial package DSC file
>   Readme.md: Add initial content
>   PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option
>   PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro
>   PrmPkg: Add initial PrmSsdtInstallDxe module
>   PrmPkg: Remove PRM Module Update Lock
>   PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag
>   PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures
>   PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support
>   PrmPkg/PrmSampleContextBufferModule: Remove OS debug print
> requirement
>   PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM handlers
>   PrmPkg/SampleAcpiParameterBufferModule: Add initial module
>   PrmPkg/HardwareAccessModuleConfigLib: Add initial library
>   PrmPkg/Samples/Readme.md: Add initial file
>   PrmPkg: Refactor some PrmLoaderDxe functionality into libraries
>   PrmPkg/Application/PrmInfo: Add initial application
>   PrmPkg: Enforce stricter types
>   PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file
>   PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib
>   PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests
>   PrmPkg/DxePrmModuleDiscoveryLib: Add initial host-based unit tests
>   PrmPkg: Add PlatformGuid
>   Readme.md: Add iASL note and QEMU sample link
>   PrmPkg: Replace PcdPrmPlatformGuid with EDKII_DSC_PLATFORM_GUID
>   PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule
>   PrmPkg/Samples: Remove PrmSamplePrintModule
>   PrmPkg: Remove the concept of OS services
>   Readme.md: Add a link to PRM Specification
>   PrmPkg: Changes for edk2 repo transition
>   PrmPkg: Apply uncrustify changes
> 
>  PrmPkg/Application/PrmInfo/PrmInfo.c
> |  732 +++++++++
>  PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
> |  199 +++
> 
> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibU
> nitTest.c
> |  649 ++++++++
>  PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
> |  386 +++++
> 
> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscove
> ryLibUnitTest.c
> |  210 +++
>  PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
> |  417 +++++
>  PrmPkg/PrmConfigDxe/PrmConfigDxe.c
> |  512 ++++++
>  PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
> |  377 +++++
>  PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
> |  110 ++
> 
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiPa
> rameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c
> |  127 ++
> 
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiPa
> rameterBufferModule.c
> |   78 +
> 
> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuffer
> ModuleConfigLib/DxeContextBufferModuleConfigLib.c
> |  218 +++
> 
> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuffer
> Module.c
> |   84 +
> 
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareA
> ccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
> |  108 ++
> 
> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareA
> ccessModule.c
> |  335 ++++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTest.c                                          |
> 119 ++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestEventTimer.c                                |
> 180 +++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestImage.c                                     |
> 163 ++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestMemory.c                                    |
> 145 ++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestMisc.c                                      |
> 198 +++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestProtocol.c                                  |
> 1650 ++++++++++++++++++++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestTpl.c                                       |
> 43 +
>  .azurepipelines/templates/pr-gate-build-job.yml
> |    2 +-
>  .pytool/CISettings.py
> |    1 +
>  Maintainers.txt
> |    8 +
>  PrmPkg/Application/PrmInfo/PrmInfo.h
> |   49 +
>  PrmPkg/Application/PrmInfo/PrmInfo.inf
> |   66 +
>  PrmPkg/Application/PrmInfo/PrmInfo.uni
> |   11 +
>  PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
> |   12 +
>  PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
> |  132 ++
>  PrmPkg/Include/Library/PrmContextBufferLib.h
> |   99 ++
>  PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
> |   60 +
>  PrmPkg/Include/Library/PrmPeCoffLib.h
> |  111 ++
>  PrmPkg/Include/Prm.h
> |   46 +
>  PrmPkg/Include/PrmContextBuffer.h
> |  171 ++
>  PrmPkg/Include/PrmDataBuffer.h
> |   50 +
>  PrmPkg/Include/PrmExportDescriptor.h
> |  109 ++
>  PrmPkg/Include/PrmMmio.h
> |   45 +
>  PrmPkg/Include/PrmModule.h
> |   47 +
>  PrmPkg/Include/PrmModuleImageContext.h
> |   28 +
>  PrmPkg/Include/Protocol/PrmConfig.h
> |   31 +
>  PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
> |   35 +
> 
> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibU
> nitTestHost.inf
> |   46 +
>  PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
> |   41 +
>  PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
> |   39 +
> 
> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscove
> ryLibUnitTestHost.inf
> |   39 +
>  PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
> |   32 +
>  PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
> |   48 +
>  PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
> |   96 ++
>  PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
> |   61 +
>  PrmPkg/PrmPkg.ci.yaml
> |  110 ++
>  PrmPkg/PrmPkg.dec
> |   67 +
>  PrmPkg/PrmPkg.dsc
> |  142 ++
>  PrmPkg/PrmPkg.uni
> |   10 +
>  PrmPkg/PrmSsdtInstallDxe/Prm.asl
> |  115 ++
>  PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
> |   52 +
>  PrmPkg/Readme.md
> |  264 ++++
> 
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiPa
> rameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
> |   39 +
> 
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiPa
> rameterBufferModule.inf
> |   41 +
>  PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
> |   24 +
> 
> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuffer
> ModuleConfigLib/DxeContextBufferModuleConfigLib.inf
> |   39 +
> 
> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuffer
> Module.inf
> |   44 +
>  PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
> |  108 ++
> 
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareA
> ccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
> |   39 +
> 
> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareA
> ccessModule.inf
> |   43 +
>  PrmPkg/Samples/Readme.md
> |  146 ++
>  PrmPkg/Test/PrmPkgHostTest.dsc
> |   39 +
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibTest.uni                                            |
> 12 +
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTest.h                                          |
> 1042 ++++++++++++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTest.inf                                        |
> 46 +
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestProtocol.h                                  |
> 120 ++
>  71 files changed, 11096 insertions(+), 1 deletion(-)
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.c
>  create mode 100644
> PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
>  create mode 100644
> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibU
> nitTest.c
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscove
> ryLibUnitTest.c
>  create mode 100644 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
>  create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.c
>  create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
>  create mode 100644 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiPa
> rameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiPa
> rameterBufferModule.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuffer
> ModuleConfigLib/DxeContextBufferModuleConfigLib.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuffer
> Module.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareA
> ccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareA
> ccessModule.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTest.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestEventTimer.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestImage.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestMemory.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestMisc.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestProtocol.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestTpl.c
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.h
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.inf
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.uni
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
>  create mode 100644 PrmPkg/Include/Library/PrmContextBufferLib.h
>  create mode 100644 PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
>  create mode 100644 PrmPkg/Include/Library/PrmPeCoffLib.h
>  create mode 100644 PrmPkg/Include/Prm.h
>  create mode 100644 PrmPkg/Include/PrmContextBuffer.h
>  create mode 100644 PrmPkg/Include/PrmDataBuffer.h
>  create mode 100644 PrmPkg/Include/PrmExportDescriptor.h
>  create mode 100644 PrmPkg/Include/PrmMmio.h
>  create mode 100644 PrmPkg/Include/PrmModule.h
>  create mode 100644 PrmPkg/Include/PrmModuleImageContext.h
>  create mode 100644 PrmPkg/Include/Protocol/PrmConfig.h
>  create mode 100644
> PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
>  create mode 100644
> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibU
> nitTestHost.inf
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscove
> ryLibUnitTestHost.inf
>  create mode 100644 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
>  create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
>  create mode 100644 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
>  create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
>  create mode 100644 PrmPkg/PrmPkg.ci.yaml
>  create mode 100644 PrmPkg/PrmPkg.dec
>  create mode 100644 PrmPkg/PrmPkg.dsc
>  create mode 100644 PrmPkg/PrmPkg.uni
>  create mode 100644 PrmPkg/PrmSsdtInstallDxe/Prm.asl
>  create mode 100644 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
>  create mode 100644 PrmPkg/Readme.md
>  create mode 100644
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiPa
> rameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiPa
> rameterBufferModule.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuffer
> ModuleConfigLib/DxeContextBufferModuleConfigLib.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuffer
> Module.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareA
> ccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareA
> ccessModule.inf
>  create mode 100644 PrmPkg/Samples/Readme.md
>  create mode 100644 PrmPkg/Test/PrmPkgHostTest.dsc
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibTest.uni
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTest.h
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTest.inf
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
> vicesTableLibUnitTestProtocol.h
> 
> --
> 2.28.0.windows.1
> 
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#87842): https://edk2.groups.io/g/devel/message/87842
> Mute This Topic: https://groups.io/mt/89955942/4905953
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub
> [gaoliming@byosoft.com.cn]
> -=-=-=-=-=-=
> 




^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: 回复: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
  2022-03-28  8:48 ` 回复: [edk2-devel] [PATCH v1 00/41] Add PrmPkg gaoliming
@ 2022-03-28 14:05   ` Michael Kubacki
  0 siblings, 0 replies; 44+ messages in thread
From: Michael Kubacki @ 2022-03-28 14:05 UTC (permalink / raw)
  To: devel, gaoliming
  Cc: 'Andrew Fish', 'Kang Gao',
	'Michael D Kinney', 'Michael Kubacki',
	'Leif Lindholm', 'Benjamin You',
	'Liu Yun', 'Ankit Sinha', 'Nate DeSimone'

Hi Liming,

I updated Maintainers.txt in patch [40/41].
https://edk2.groups.io/g/devel/message/87882

Due to the email limit on the mailing list the last few patches had to 
be sent shortly after the initial series.

Regards,
Michael

On 3/28/2022 4:48 AM, gaoliming wrote:
> Michael:
>    Please also update Maintainers.txt to specify maintainer for new PrmPkg.
> 
> Thanks
> Liming
>> -----邮件原件-----
>> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Michael
>> Kubacki
>> 发送时间: 2022年3月23日 0:19
>> 收件人: devel@edk2.groups.io
>> 抄送: Andrew Fish <afish@apple.com>; Kang Gao <kang.gao@intel.com>;
>> Michael D Kinney <michael.d.kinney@intel.com>; Michael Kubacki
>> <michael.kubacki@microsoft.com>; Leif Lindholm <leif@nuviainc.com>;
>> Benjamin You <benjamin.you@intel.com>; Liu Yun <yun.y.liu@intel.com>;
>> Ankit Sinha <ankit.sinha@intel.com>; Nate DeSimone
>> <nathaniel.l.desimone@intel.com>
>> 主题: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
>>
>> From: Michael Kubacki <michael.kubacki@microsoft.com>
>>
>> This patch series adds a new package called PrmPkg. An RFC was sent
>> to the edk2 mailing list on January 28, 2022 detailing the proposal,
>> see https://edk2.groups.io/g/devel/message/86181.
>>
>> Platform Runtime Mechanism (PRM) is a new firmware solution that has
>> been developed in edk2-staging/PlatformRuntimeMechanism.
>>
>> This patch series has been organized to greatly condense the history
>> from the edk2-staging branch but to preserve important decisions and
>> changes in history that help establish context of changes and will
>> serve as valuable references for future development.
>>
>> Interest in PRM has increased across various vendors and we believe
>> it is beneficial to make the source code more widely available for
>> the following reasons:
>>
>>    1. PRM specification adoption
>>    2. Feature completeness
>>    3. Overall validation coverage
>>    4. Interest from the community and future collaboration
>>
>> The technical details of PRM are covered in the PRM Specification
>> in addition to the Readme.md file located in the root of PrmPkg
>> in this patch series.
>>
>> 1. PRM specification adoption
>>
>> Intel and Microsoft have worked together to standardize PRM in the
>> ACPI Specification and the PRM Specification hosted on uefi.org.
>>
>>    * ACPI 6.4 Specification:
>>    https://uefi.org/node/4149
>>
>>    * PRM Specification:
>>
>> https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mech
>> anism%20-%20with%20legal%20notice.pdf
>>
>> 2. Feature completeness
>>
>> PrmPkg implements the full firmware functionality described in the
>> PRM Specification and there are no significant changes to
>> functionality planned at this time.
>>
>> Though we are very much interested in evolving PRM based on
>> feedback.
>>
>> 3. Overall validation coverage
>>
>> PrmPkg has been integrated and tested on client and server systems
>> in addition to virtual platforms (OvmfPkg/QEMU).
>>
>> Platform integration is simple and a demonstration of this
>> integration for OvmfPkg is available in the following branch:
>> https://github.com/makubacki/edk2/tree/ovmf_prmpkg_integration
>>
>> The code has been built with:
>>    * MSFT VS2015, VS2017, and VS2019
>>    * GCC5 (see https://bugzilla.tianocore.org/show_bug.cgi?id=3802)
>>    * iASL compiler (20200528 - https://acpica.org/node/181)
>>
>> The Linux kernel currently includes the following PRM support:
>>    * _OSC PRM bit - allows FW to know determine the OS is
>>      PRM-capable and can redirect _DSM method from alternate
>>      triggers (such as SMI) to PRM.
>>    * PRM invocation via _DSM, includes PRM module and handler parsing
>>      from ACPI PRMT table, and also the PRM operation region handler
>>      for runtime PRM service invocation.
>>    * An OS configuration for PRM enabling, PRM support can be
>>      disabled during OS image build.
>>
>> Note that upstream Linux does not currently support the following:
>>    * Ability for the OS driver to call a PRM handler directly,
>>      it has to be via ACPI _DSM.
>>    * Run time update PRM module and handler via PE/COFF PRM image.
>>
>> This commit provides additional context of the changes in Linux:
>> https://github.com/torvalds/linux/commit/cefc7ca46235f01d5233e3abd4b79
>> 452af01d9e9
>>
>> Windows 11 (https://www.microsoft.com/software-download/windows11)
>> and Windows Server 2022
>> (https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the
>> -wdk)
>> include the PRM functionality noted above in addition to PRM direct
>> call and PRM runtime updates.
>>
>> PRM has been tested on IA32, X64, and AARCH64 targets.
>>
>> 4. Interest from the community and future collaboration
>>
>> PRM has been presented at several industry conferences:
>>
>> * OSFC 2020 - "PRM: SMM Goes on a Diet"
>>    https://cfp.osfc.io/osfc2020/talk/MCJASB/
>>
>> * OCP Summit 2019 - "Case Study Alternatives for SMM Usage in
>>    Intel Platforms"
>>    https://www.youtube.com/watch?v=mu3DRLM1dPA
>>
>> In addition, Microsoft plans to publish the Windows PRM driver
>> interface and a WDF sample driver that uses the interface to the
>> Windows Driver Samples GitHub repository
>> (https://github.com/microsoft/Windows-driver-samples).
>>
>> We believe a PrmPkg in edk2 can increase accessibility to PRM and
>> ease collaboration.
>>
>> PrmPkg
>> ------
>> PrmPkg contains the common functionality needed to enable PRM on
>> any system. It does not contain platform-specific code such as PRM
>> modules (and by extension PRM handlers). Other than sample modules,
>> PrmPkg will only contain code needed to provide PRM feature
>> functionality as defined in the PRM Specification.
>>
>> PrmPkg is scoped to continue to only contain platform-agnostic
>> functionality in the future.
>>
>> The proposed maintainers of PrmPkg are:
>> * Michael Kubacki <mikuback@linux.microsoft.com>
>> * Nate DeSimone <nathaniel.l.desimone@intel.com>
>>
>> The proposed reviewers of PrmPkg are:
>> * Ankit Sinha <ankit.sinha@intel.com>
>>
>> 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>
>>
>> Liu (2):
>>    PrmPkg: Publish PRM operation region to support PRM ACPI _DSM
>>      invocation
>>    PrmPkg: Export major/minor version in PRM module PE COFF header
>>
>> Liu Yun Y (1):
>>    PrmPkg: Update PRM OpRegion
>>
>> Michael Kubacki (38):
>>    PrmPkg: Add package and include headers
>>    PrmPkg: Add PrmConfig protocol interface
>>    PrmPkg/PrmContextBufferLib: Add initial library instance
>>    PrmPkg/PrmConfigDxe: Add initial driver
>>    PrmPkg: Add initial PrmSamplePrintModule
>>    PrmPkg: Add initial PrmSampleMemoryAllocationModule
>>    PrmPkg: Add initial PrmSampleHardwareAccessModule
>>    PrmPkg: Add initial PrmSampleContextBufferModule
>>    PrmPkg: Add initial package DSC file
>>    Readme.md: Add initial content
>>    PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option
>>    PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro
>>    PrmPkg: Add initial PrmSsdtInstallDxe module
>>    PrmPkg: Remove PRM Module Update Lock
>>    PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag
>>    PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures
>>    PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support
>>    PrmPkg/PrmSampleContextBufferModule: Remove OS debug print
>> requirement
>>    PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM handlers
>>    PrmPkg/SampleAcpiParameterBufferModule: Add initial module
>>    PrmPkg/HardwareAccessModuleConfigLib: Add initial library
>>    PrmPkg/Samples/Readme.md: Add initial file
>>    PrmPkg: Refactor some PrmLoaderDxe functionality into libraries
>>    PrmPkg/Application/PrmInfo: Add initial application
>>    PrmPkg: Enforce stricter types
>>    PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file
>>    PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib
>>    PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests
>>    PrmPkg/DxePrmModuleDiscoveryLib: Add initial host-based unit tests
>>    PrmPkg: Add PlatformGuid
>>    Readme.md: Add iASL note and QEMU sample link
>>    PrmPkg: Replace PcdPrmPlatformGuid with EDKII_DSC_PLATFORM_GUID
>>    PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule
>>    PrmPkg/Samples: Remove PrmSamplePrintModule
>>    PrmPkg: Remove the concept of OS services
>>    Readme.md: Add a link to PRM Specification
>>    PrmPkg: Changes for edk2 repo transition
>>    PrmPkg: Apply uncrustify changes
>>
>>   PrmPkg/Application/PrmInfo/PrmInfo.c
>> |  732 +++++++++
>>   PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
>> |  199 +++
>>
>> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibU
>> nitTest.c
>> |  649 ++++++++
>>   PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
>> |  386 +++++
>>
>> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscove
>> ryLibUnitTest.c
>> |  210 +++
>>   PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
>> |  417 +++++
>>   PrmPkg/PrmConfigDxe/PrmConfigDxe.c
>> |  512 ++++++
>>   PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
>> |  377 +++++
>>   PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
>> |  110 ++
>>
>> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiPa
>> rameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c
>> |  127 ++
>>
>> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiPa
>> rameterBufferModule.c
>> |   78 +
>>
>> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuffer
>> ModuleConfigLib/DxeContextBufferModuleConfigLib.c
>> |  218 +++
>>
>> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuffer
>> Module.c
>> |   84 +
>>
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareA
>> ccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
>> |  108 ++
>>
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareA
>> ccessModule.c
>> |  335 ++++
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTest.c                                          |
>> 119 ++
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestEventTimer.c                                |
>> 180 +++
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestImage.c                                     |
>> 163 ++
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestMemory.c                                    |
>> 145 ++
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestMisc.c                                      |
>> 198 +++
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestProtocol.c                                  |
>> 1650 ++++++++++++++++++++
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestTpl.c                                       |
>> 43 +
>>   .azurepipelines/templates/pr-gate-build-job.yml
>> |    2 +-
>>   .pytool/CISettings.py
>> |    1 +
>>   Maintainers.txt
>> |    8 +
>>   PrmPkg/Application/PrmInfo/PrmInfo.h
>> |   49 +
>>   PrmPkg/Application/PrmInfo/PrmInfo.inf
>> |   66 +
>>   PrmPkg/Application/PrmInfo/PrmInfo.uni
>> |   11 +
>>   PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
>> |   12 +
>>   PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
>> |  132 ++
>>   PrmPkg/Include/Library/PrmContextBufferLib.h
>> |   99 ++
>>   PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
>> |   60 +
>>   PrmPkg/Include/Library/PrmPeCoffLib.h
>> |  111 ++
>>   PrmPkg/Include/Prm.h
>> |   46 +
>>   PrmPkg/Include/PrmContextBuffer.h
>> |  171 ++
>>   PrmPkg/Include/PrmDataBuffer.h
>> |   50 +
>>   PrmPkg/Include/PrmExportDescriptor.h
>> |  109 ++
>>   PrmPkg/Include/PrmMmio.h
>> |   45 +
>>   PrmPkg/Include/PrmModule.h
>> |   47 +
>>   PrmPkg/Include/PrmModuleImageContext.h
>> |   28 +
>>   PrmPkg/Include/Protocol/PrmConfig.h
>> |   31 +
>>   PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
>> |   35 +
>>
>> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibU
>> nitTestHost.inf
>> |   46 +
>>   PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
>> |   41 +
>>   PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
>> |   39 +
>>
>> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscove
>> ryLibUnitTestHost.inf
>> |   39 +
>>   PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
>> |   32 +
>>   PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
>> |   48 +
>>   PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
>> |   96 ++
>>   PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
>> |   61 +
>>   PrmPkg/PrmPkg.ci.yaml
>> |  110 ++
>>   PrmPkg/PrmPkg.dec
>> |   67 +
>>   PrmPkg/PrmPkg.dsc
>> |  142 ++
>>   PrmPkg/PrmPkg.uni
>> |   10 +
>>   PrmPkg/PrmSsdtInstallDxe/Prm.asl
>> |  115 ++
>>   PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
>> |   52 +
>>   PrmPkg/Readme.md
>> |  264 ++++
>>
>> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiPa
>> rameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
>> |   39 +
>>
>> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiPa
>> rameterBufferModule.inf
>> |   41 +
>>   PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
>> |   24 +
>>
>> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuffer
>> ModuleConfigLib/DxeContextBufferModuleConfigLib.inf
>> |   39 +
>>
>> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuffer
>> Module.inf
>> |   44 +
>>   PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
>> |  108 ++
>>
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareA
>> ccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
>> |   39 +
>>
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareA
>> ccessModule.inf
>> |   43 +
>>   PrmPkg/Samples/Readme.md
>> |  146 ++
>>   PrmPkg/Test/PrmPkgHostTest.dsc
>> |   39 +
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibTest.uni                                            |
>> 12 +
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTest.h                                          |
>> 1042 ++++++++++++
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTest.inf                                        |
>> 46 +
>>
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestProtocol.h                                  |
>> 120 ++
>>   71 files changed, 11096 insertions(+), 1 deletion(-)
>>   create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.c
>>   create mode 100644
>> PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
>>   create mode 100644
>> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibU
>> nitTest.c
>>   create mode 100644
>> PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
>>   create mode 100644
>> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscove
>> ryLibUnitTest.c
>>   create mode 100644 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
>>   create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.c
>>   create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
>>   create mode 100644 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiPa
>> rameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.c
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiPa
>> rameterBufferModule.c
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuffer
>> ModuleConfigLib/DxeContextBufferModuleConfigLib.c
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuffer
>> Module.c
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareA
>> ccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareA
>> ccessModule.c
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTest.c
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestEventTimer.c
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestImage.c
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestMemory.c
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestMisc.c
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestProtocol.c
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestTpl.c
>>   create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.h
>>   create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.inf
>>   create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.uni
>>   create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
>>   create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
>>   create mode 100644 PrmPkg/Include/Library/PrmContextBufferLib.h
>>   create mode 100644 PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
>>   create mode 100644 PrmPkg/Include/Library/PrmPeCoffLib.h
>>   create mode 100644 PrmPkg/Include/Prm.h
>>   create mode 100644 PrmPkg/Include/PrmContextBuffer.h
>>   create mode 100644 PrmPkg/Include/PrmDataBuffer.h
>>   create mode 100644 PrmPkg/Include/PrmExportDescriptor.h
>>   create mode 100644 PrmPkg/Include/PrmMmio.h
>>   create mode 100644 PrmPkg/Include/PrmModule.h
>>   create mode 100644 PrmPkg/Include/PrmModuleImageContext.h
>>   create mode 100644 PrmPkg/Include/Protocol/PrmConfig.h
>>   create mode 100644
>> PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
>>   create mode 100644
>> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLibU
>> nitTestHost.inf
>>   create mode 100644
>> PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf
>>   create mode 100644
>> PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
>>   create mode 100644
>> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDiscove
>> ryLibUnitTestHost.inf
>>   create mode 100644 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
>>   create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
>>   create mode 100644 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
>>   create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
>>   create mode 100644 PrmPkg/PrmPkg.ci.yaml
>>   create mode 100644 PrmPkg/PrmPkg.dec
>>   create mode 100644 PrmPkg/PrmPkg.dsc
>>   create mode 100644 PrmPkg/PrmPkg.uni
>>   create mode 100644 PrmPkg/PrmSsdtInstallDxe/Prm.asl
>>   create mode 100644 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
>>   create mode 100644 PrmPkg/Readme.md
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiPa
>> rameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiPa
>> rameterBufferModule.inf
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuffer
>> ModuleConfigLib/DxeContextBufferModuleConfigLib.inf
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuffer
>> Module.inf
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardwareA
>> ccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
>>   create mode 100644
>> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardwareA
>> ccessModule.inf
>>   create mode 100644 PrmPkg/Samples/Readme.md
>>   create mode 100644 PrmPkg/Test/PrmPkgHostTest.dsc
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibTest.uni
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTest.h
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTest.inf
>>   create mode 100644
>> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootSer
>> vicesTableLibUnitTestProtocol.h
>>
>> --
>> 2.28.0.windows.1
>>
>>
>>
>> -=-=-=-=-=-=
>> Groups.io Links: You receive all messages sent to this group.
>> View/Reply Online (#87842): https://edk2.groups.io/g/devel/message/87842
>> Mute This Topic: https://groups.io/mt/89955942/4905953
>> Group Owner: devel+owner@edk2.groups.io
>> Unsubscribe: https://edk2.groups.io/g/devel/unsub
>> [gaoliming@byosoft.com.cn]
>> -=-=-=-=-=-=
>>
> 
> 
> 
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
  2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
                   ` (39 preceding siblings ...)
  2022-03-28  8:48 ` 回复: [edk2-devel] [PATCH v1 00/41] Add PrmPkg gaoliming
@ 2022-03-29 16:28 ` Sinha, Ankit
  2022-03-31  0:52   ` 回复: " gaoliming
  40 siblings, 1 reply; 44+ messages in thread
From: Sinha, Ankit @ 2022-03-29 16:28 UTC (permalink / raw)
  To: devel@edk2.groups.io, mikuback@linux.microsoft.com
  Cc: Andrew Fish, Gao, Kang, Kinney, Michael D, Kubacki, Michael,
	Leif Lindholm, You, Benjamin, Liu, Yun Y, Desimone, Nathaniel L

Reviewed-by: Ankit Sinha <ankit.sinha@intel.com>

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Michael
> Kubacki
> Sent: Tuesday, March 22, 2022 9:19 AM
> To: devel@edk2.groups.io
> Cc: Andrew Fish <afish@apple.com>; Gao, Kang <kang.gao@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; Kubacki, Michael
> <michael.kubacki@microsoft.com>; Leif Lindholm <leif@nuviainc.com>; You,
> Benjamin <benjamin.you@intel.com>; Liu, Yun Y <yun.y.liu@intel.com>;
> Sinha, Ankit <ankit.sinha@intel.com>; Desimone, Nathaniel L
> <nathaniel.l.desimone@intel.com>
> Subject: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
> 
> From: Michael Kubacki <michael.kubacki@microsoft.com>
> 
> This patch series adds a new package called PrmPkg. An RFC was sent to the
> edk2 mailing list on January 28, 2022 detailing the proposal, see
> https://edk2.groups.io/g/devel/message/86181.
> 
> Platform Runtime Mechanism (PRM) is a new firmware solution that has
> been developed in edk2-staging/PlatformRuntimeMechanism.
> 
> This patch series has been organized to greatly condense the history from
> the edk2-staging branch but to preserve important decisions and changes in
> history that help establish context of changes and will serve as valuable
> references for future development.
> 
> Interest in PRM has increased across various vendors and we believe it is
> beneficial to make the source code more widely available for the following
> reasons:
> 
>   1. PRM specification adoption
>   2. Feature completeness
>   3. Overall validation coverage
>   4. Interest from the community and future collaboration
> 
> The technical details of PRM are covered in the PRM Specification in addition
> to the Readme.md file located in the root of PrmPkg in this patch series.
> 
> 1. PRM specification adoption
> 
> Intel and Microsoft have worked together to standardize PRM in the ACPI
> Specification and the PRM Specification hosted on uefi.org.
> 
>   * ACPI 6.4 Specification:
>   https://uefi.org/node/4149
> 
>   * PRM Specification:
> 
> https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mec
> hanism%20-%20with%20legal%20notice.pdf
> 
> 2. Feature completeness
> 
> PrmPkg implements the full firmware functionality described in the PRM
> Specification and there are no significant changes to functionality planned at
> this time.
> 
> Though we are very much interested in evolving PRM based on feedback.
> 
> 3. Overall validation coverage
> 
> PrmPkg has been integrated and tested on client and server systems in
> addition to virtual platforms (OvmfPkg/QEMU).
> 
> Platform integration is simple and a demonstration of this integration for
> OvmfPkg is available in the following branch:
> https://github.com/makubacki/edk2/tree/ovmf_prmpkg_integration
> 
> The code has been built with:
>   * MSFT VS2015, VS2017, and VS2019
>   * GCC5 (see https://bugzilla.tianocore.org/show_bug.cgi?id=3802)
>   * iASL compiler (20200528 - https://acpica.org/node/181)
> 
> The Linux kernel currently includes the following PRM support:
>   * _OSC PRM bit - allows FW to know determine the OS is
>     PRM-capable and can redirect _DSM method from alternate
>     triggers (such as SMI) to PRM.
>   * PRM invocation via _DSM, includes PRM module and handler parsing
>     from ACPI PRMT table, and also the PRM operation region handler
>     for runtime PRM service invocation.
>   * An OS configuration for PRM enabling, PRM support can be
>     disabled during OS image build.
> 
> Note that upstream Linux does not currently support the following:
>   * Ability for the OS driver to call a PRM handler directly,
>     it has to be via ACPI _DSM.
>   * Run time update PRM module and handler via PE/COFF PRM image.
> 
> This commit provides additional context of the changes in Linux:
> https://github.com/torvalds/linux/commit/cefc7ca46235f01d5233e3abd4b79
> 452af01d9e9
> 
> Windows 11 (https://www.microsoft.com/software-download/windows11)
> and Windows Server 2022 (https://docs.microsoft.com/en-us/windows-
> hardware/drivers/download-the-wdk)
> include the PRM functionality noted above in addition to PRM direct call and
> PRM runtime updates.
> 
> PRM has been tested on IA32, X64, and AARCH64 targets.
> 
> 4. Interest from the community and future collaboration
> 
> PRM has been presented at several industry conferences:
> 
> * OSFC 2020 - "PRM: SMM Goes on a Diet"
>   https://cfp.osfc.io/osfc2020/talk/MCJASB/
> 
> * OCP Summit 2019 - "Case Study Alternatives for SMM Usage in
>   Intel Platforms"
>   https://www.youtube.com/watch?v=mu3DRLM1dPA
> 
> In addition, Microsoft plans to publish the Windows PRM driver interface and
> a WDF sample driver that uses the interface to the Windows Driver Samples
> GitHub repository (https://github.com/microsoft/Windows-driver-samples).
> 
> We believe a PrmPkg in edk2 can increase accessibility to PRM and ease
> collaboration.
> 
> PrmPkg
> ------
> PrmPkg contains the common functionality needed to enable PRM on any
> system. It does not contain platform-specific code such as PRM modules (and
> by extension PRM handlers). Other than sample modules, PrmPkg will only
> contain code needed to provide PRM feature functionality as defined in the
> PRM Specification.
> 
> PrmPkg is scoped to continue to only contain platform-agnostic functionality
> in the future.
> 
> The proposed maintainers of PrmPkg are:
> * Michael Kubacki <mikuback@linux.microsoft.com>
> * Nate DeSimone <nathaniel.l.desimone@intel.com>
> 
> The proposed reviewers of PrmPkg are:
> * Ankit Sinha <ankit.sinha@intel.com>
> 
> 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>
> 
> Liu (2):
>   PrmPkg: Publish PRM operation region to support PRM ACPI _DSM
>     invocation
>   PrmPkg: Export major/minor version in PRM module PE COFF header
> 
> Liu Yun Y (1):
>   PrmPkg: Update PRM OpRegion
> 
> Michael Kubacki (38):
>   PrmPkg: Add package and include headers
>   PrmPkg: Add PrmConfig protocol interface
>   PrmPkg/PrmContextBufferLib: Add initial library instance
>   PrmPkg/PrmConfigDxe: Add initial driver
>   PrmPkg: Add initial PrmSamplePrintModule
>   PrmPkg: Add initial PrmSampleMemoryAllocationModule
>   PrmPkg: Add initial PrmSampleHardwareAccessModule
>   PrmPkg: Add initial PrmSampleContextBufferModule
>   PrmPkg: Add initial package DSC file
>   Readme.md: Add initial content
>   PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option
>   PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro
>   PrmPkg: Add initial PrmSsdtInstallDxe module
>   PrmPkg: Remove PRM Module Update Lock
>   PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag
>   PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures
>   PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support
>   PrmPkg/PrmSampleContextBufferModule: Remove OS debug print
> requirement
>   PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM handlers
>   PrmPkg/SampleAcpiParameterBufferModule: Add initial module
>   PrmPkg/HardwareAccessModuleConfigLib: Add initial library
>   PrmPkg/Samples/Readme.md: Add initial file
>   PrmPkg: Refactor some PrmLoaderDxe functionality into libraries
>   PrmPkg/Application/PrmInfo: Add initial application
>   PrmPkg: Enforce stricter types
>   PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file
>   PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib
>   PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests
>   PrmPkg/DxePrmModuleDiscoveryLib: Add initial host-based unit tests
>   PrmPkg: Add PlatformGuid
>   Readme.md: Add iASL note and QEMU sample link
>   PrmPkg: Replace PcdPrmPlatformGuid with EDKII_DSC_PLATFORM_GUID
>   PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule
>   PrmPkg/Samples: Remove PrmSamplePrintModule
>   PrmPkg: Remove the concept of OS services
>   Readme.md: Add a link to PRM Specification
>   PrmPkg: Changes for edk2 repo transition
>   PrmPkg: Apply uncrustify changes
> 
>  PrmPkg/Application/PrmInfo/PrmInfo.c
> |  732 +++++++++
>  PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
> |  199 +++
> 
> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLi
> bUnitTest.c                                                           |  649 ++++++++
>  PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
> |  386 +++++
> 
> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDisco
> veryLibUnitTest.c                                                       |  210 +++
>  PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
> |  417 +++++
>  PrmPkg/PrmConfigDxe/PrmConfigDxe.c
> |  512 ++++++
>  PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
> |  377 +++++
>  PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
> |  110 ++
> 
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiP
> arameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.
> c   |  127 ++
> 
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiP
> arameterBufferModule.c                                                    |   78 +
> 
> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuff
> erModuleConfigLib/DxeContextBufferModuleConfigLib.c                     |  218
> +++
> 
> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuff
> erModule.c                                                                |   84 +
> 
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardware
> AccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c                  |
> 108 ++
> 
> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardware
> AccessModule.c                                                              |  335 ++++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTest.c                                          |  119 ++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestEventTimer.c                                |  180 +++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestImage.c                                     |  163 ++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestMemory.c                                    |  145 ++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestMisc.c                                      |  198 +++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestProtocol.c                                  | 1650
> ++++++++++++++++++++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestTpl.c                                       |   43 +
>  .azurepipelines/templates/pr-gate-build-job.yml
> |    2 +-
>  .pytool/CISettings.py
> |    1 +
>  Maintainers.txt
> |    8 +
>  PrmPkg/Application/PrmInfo/PrmInfo.h
> |   49 +
>  PrmPkg/Application/PrmInfo/PrmInfo.inf
> |   66 +
>  PrmPkg/Application/PrmInfo/PrmInfo.uni
> |   11 +
>  PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
> |   12 +
>  PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
> |  132 ++
>  PrmPkg/Include/Library/PrmContextBufferLib.h
> |   99 ++
>  PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
> |   60 +
>  PrmPkg/Include/Library/PrmPeCoffLib.h
> |  111 ++
>  PrmPkg/Include/Prm.h
> |   46 +
>  PrmPkg/Include/PrmContextBuffer.h
> |  171 ++
>  PrmPkg/Include/PrmDataBuffer.h
> |   50 +
>  PrmPkg/Include/PrmExportDescriptor.h
> |  109 ++
>  PrmPkg/Include/PrmMmio.h
> |   45 +
>  PrmPkg/Include/PrmModule.h
> |   47 +
>  PrmPkg/Include/PrmModuleImageContext.h
> |   28 +
>  PrmPkg/Include/Protocol/PrmConfig.h
> |   31 +
>  PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
> |   35 +
> 
> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLi
> bUnitTestHost.inf                                                     |   46 +
> 
> PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.in
> f                                                                      |   41 +
>  PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
> |   39 +
> 
> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDisco
> veryLibUnitTestHost.inf                                                 |   39 +
>  PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
> |   32 +
>  PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
> |   48 +
>  PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
> |   96 ++
>  PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
> |   61 +
>  PrmPkg/PrmPkg.ci.yaml
> |  110 ++
>  PrmPkg/PrmPkg.dec
> |   67 +
>  PrmPkg/PrmPkg.dsc
> |  142 ++
>  PrmPkg/PrmPkg.uni
> |   10 +
>  PrmPkg/PrmSsdtInstallDxe/Prm.asl
> |  115 ++
>  PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
> |   52 +
>  PrmPkg/Readme.md
> |  264 ++++
> 
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiP
> arameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.
> inf |   39 +
> 
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiP
> arameterBufferModule.inf                                                  |   41 +
>  PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
> |   24 +
> 
> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuff
> erModuleConfigLib/DxeContextBufferModuleConfigLib.inf                   |   39 +
> 
> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuff
> erModule.inf                                                              |   44 +
>  PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
> |  108 ++
> 
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardware
> AccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf                |
> 39 +
> 
> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardware
> AccessModule.inf                                                            |   43 +
>  PrmPkg/Samples/Readme.md
> |  146 ++
>  PrmPkg/Test/PrmPkgHostTest.dsc
> |   39 +
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibTest.uni                                            |   12 +
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTest.h                                          | 1042 ++++++++++++
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTest.inf                                        |   46 +
> 
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestProtocol.h                                  |  120 ++
>  71 files changed, 11096 insertions(+), 1 deletion(-)  create mode 100644
> PrmPkg/Application/PrmInfo/PrmInfo.c
>  create mode 100644
> PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
>  create mode 100644
> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLi
> bUnitTest.c
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDisco
> veryLibUnitTest.c
>  create mode 100644 PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
>  create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.c
>  create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
>  create mode 100644 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiP
> arameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.
> c
>  create mode 100644
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiP
> arameterBufferModule.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuff
> erModuleConfigLib/DxeContextBufferModuleConfigLib.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuff
> erModule.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardware
> AccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardware
> AccessModule.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTest.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestEventTimer.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestImage.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestMemory.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestMisc.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestProtocol.c
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestTpl.c
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.h
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.inf
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.uni
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
>  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
>  create mode 100644 PrmPkg/Include/Library/PrmContextBufferLib.h
>  create mode 100644 PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
>  create mode 100644 PrmPkg/Include/Library/PrmPeCoffLib.h
>  create mode 100644 PrmPkg/Include/Prm.h  create mode 100644
> PrmPkg/Include/PrmContextBuffer.h  create mode 100644
> PrmPkg/Include/PrmDataBuffer.h  create mode 100644
> PrmPkg/Include/PrmExportDescriptor.h
>  create mode 100644 PrmPkg/Include/PrmMmio.h  create mode 100644
> PrmPkg/Include/PrmModule.h  create mode 100644
> PrmPkg/Include/PrmModuleImageContext.h
>  create mode 100644 PrmPkg/Include/Protocol/PrmConfig.h
>  create mode 100644
> PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
>  create mode 100644
> PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLi
> bUnitTestHost.inf
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.in
> f
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
>  create mode 100644
> PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDisco
> veryLibUnitTestHost.inf
>  create mode 100644
> PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
>  create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
>  create mode 100644 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
>  create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
>  create mode 100644 PrmPkg/PrmPkg.ci.yaml  create mode 100644
> PrmPkg/PrmPkg.dec  create mode 100644 PrmPkg/PrmPkg.dsc  create mode
> 100644 PrmPkg/PrmPkg.uni  create mode 100644
> PrmPkg/PrmSsdtInstallDxe/Prm.asl  create mode 100644
> PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
>  create mode 100644 PrmPkg/Readme.md
>  create mode 100644
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiP
> arameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.
> inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiP
> arameterBufferModule.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuff
> erModuleConfigLib/DxeContextBufferModuleConfigLib.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuff
> erModule.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardware
> AccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
>  create mode 100644
> PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardware
> AccessModule.inf
>  create mode 100644 PrmPkg/Samples/Readme.md  create mode 100644
> PrmPkg/Test/PrmPkgHostTest.dsc  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibTest.uni
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTest.h
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTest.inf
>  create mode 100644
> PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> ervicesTableLibUnitTestProtocol.h
> 
> --
> 2.28.0.windows.1
> 
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#87842): https://edk2.groups.io/g/devel/message/87842
> Mute This Topic: https://groups.io/mt/89955942/1772825
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub [ankit.sinha@intel.com]
> -=-=-=-=-=-=
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* 回复: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
  2022-03-29 16:28 ` Sinha, Ankit
@ 2022-03-31  0:52   ` gaoliming
  0 siblings, 0 replies; 44+ messages in thread
From: gaoliming @ 2022-03-31  0:52 UTC (permalink / raw)
  To: devel, ankit.sinha, mikuback
  Cc: 'Andrew Fish', 'Gao, Kang',
	'Kinney, Michael D', 'Kubacki, Michael',
	'Leif Lindholm', 'You, Benjamin',
	'Liu, Yun Y', 'Desimone, Nathaniel L'

Acked-by: Liming Gao <gaoliming@byosoft.com.cn>

> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Sinha, Ankit
> 发送时间: 2022年3月30日 0:29
> 收件人: devel@edk2.groups.io; mikuback@linux.microsoft.com
> 抄送: Andrew Fish <afish@apple.com>; Gao, Kang <kang.gao@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>; Kubacki, Michael
> <michael.kubacki@microsoft.com>; Leif Lindholm <leif@nuviainc.com>; You,
> Benjamin <benjamin.you@intel.com>; Liu, Yun Y <yun.y.liu@intel.com>;
> Desimone, Nathaniel L <nathaniel.l.desimone@intel.com>
> 主题: Re: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
> 
> Reviewed-by: Ankit Sinha <ankit.sinha@intel.com>
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Michael
> > Kubacki
> > Sent: Tuesday, March 22, 2022 9:19 AM
> > To: devel@edk2.groups.io
> > Cc: Andrew Fish <afish@apple.com>; Gao, Kang <kang.gao@intel.com>;
> > Kinney, Michael D <michael.d.kinney@intel.com>; Kubacki, Michael
> > <michael.kubacki@microsoft.com>; Leif Lindholm <leif@nuviainc.com>;
> You,
> > Benjamin <benjamin.you@intel.com>; Liu, Yun Y <yun.y.liu@intel.com>;
> > Sinha, Ankit <ankit.sinha@intel.com>; Desimone, Nathaniel L
> > <nathaniel.l.desimone@intel.com>
> > Subject: [edk2-devel] [PATCH v1 00/41] Add PrmPkg
> >
> > From: Michael Kubacki <michael.kubacki@microsoft.com>
> >
> > This patch series adds a new package called PrmPkg. An RFC was sent to
the
> > edk2 mailing list on January 28, 2022 detailing the proposal, see
> > https://edk2.groups.io/g/devel/message/86181.
> >
> > Platform Runtime Mechanism (PRM) is a new firmware solution that has
> > been developed in edk2-staging/PlatformRuntimeMechanism.
> >
> > This patch series has been organized to greatly condense the history
from
> > the edk2-staging branch but to preserve important decisions and changes
in
> > history that help establish context of changes and will serve as
valuable
> > references for future development.
> >
> > Interest in PRM has increased across various vendors and we believe it
is
> > beneficial to make the source code more widely available for the
following
> > reasons:
> >
> >   1. PRM specification adoption
> >   2. Feature completeness
> >   3. Overall validation coverage
> >   4. Interest from the community and future collaboration
> >
> > The technical details of PRM are covered in the PRM Specification in
> addition
> > to the Readme.md file located in the root of PrmPkg in this patch
series.
> >
> > 1. PRM specification adoption
> >
> > Intel and Microsoft have worked together to standardize PRM in the ACPI
> > Specification and the PRM Specification hosted on uefi.org.
> >
> >   * ACPI 6.4 Specification:
> >   https://uefi.org/node/4149
> >
> >   * PRM Specification:
> >
> > https://uefi.org/sites/default/files/resources/Platform%20Runtime%20Mec
> > hanism%20-%20with%20legal%20notice.pdf
> >
> > 2. Feature completeness
> >
> > PrmPkg implements the full firmware functionality described in the PRM
> > Specification and there are no significant changes to functionality
planned at
> > this time.
> >
> > Though we are very much interested in evolving PRM based on feedback.
> >
> > 3. Overall validation coverage
> >
> > PrmPkg has been integrated and tested on client and server systems in
> > addition to virtual platforms (OvmfPkg/QEMU).
> >
> > Platform integration is simple and a demonstration of this integration
for
> > OvmfPkg is available in the following branch:
> > https://github.com/makubacki/edk2/tree/ovmf_prmpkg_integration
> >
> > The code has been built with:
> >   * MSFT VS2015, VS2017, and VS2019
> >   * GCC5 (see https://bugzilla.tianocore.org/show_bug.cgi?id=3802)
> >   * iASL compiler (20200528 - https://acpica.org/node/181)
> >
> > The Linux kernel currently includes the following PRM support:
> >   * _OSC PRM bit - allows FW to know determine the OS is
> >     PRM-capable and can redirect _DSM method from alternate
> >     triggers (such as SMI) to PRM.
> >   * PRM invocation via _DSM, includes PRM module and handler parsing
> >     from ACPI PRMT table, and also the PRM operation region handler
> >     for runtime PRM service invocation.
> >   * An OS configuration for PRM enabling, PRM support can be
> >     disabled during OS image build.
> >
> > Note that upstream Linux does not currently support the following:
> >   * Ability for the OS driver to call a PRM handler directly,
> >     it has to be via ACPI _DSM.
> >   * Run time update PRM module and handler via PE/COFF PRM image.
> >
> > This commit provides additional context of the changes in Linux:
> >
> https://github.com/torvalds/linux/commit/cefc7ca46235f01d5233e3abd4b79
> > 452af01d9e9
> >
> > Windows 11 (https://www.microsoft.com/software-download/windows11)
> > and Windows Server 2022 (https://docs.microsoft.com/en-us/windows-
> > hardware/drivers/download-the-wdk)
> > include the PRM functionality noted above in addition to PRM direct call
and
> > PRM runtime updates.
> >
> > PRM has been tested on IA32, X64, and AARCH64 targets.
> >
> > 4. Interest from the community and future collaboration
> >
> > PRM has been presented at several industry conferences:
> >
> > * OSFC 2020 - "PRM: SMM Goes on a Diet"
> >   https://cfp.osfc.io/osfc2020/talk/MCJASB/
> >
> > * OCP Summit 2019 - "Case Study Alternatives for SMM Usage in
> >   Intel Platforms"
> >   https://www.youtube.com/watch?v=mu3DRLM1dPA
> >
> > In addition, Microsoft plans to publish the Windows PRM driver interface
> and
> > a WDF sample driver that uses the interface to the Windows Driver
Samples
> > GitHub repository (https://github.com/microsoft/Windows-driver-samples).
> >
> > We believe a PrmPkg in edk2 can increase accessibility to PRM and ease
> > collaboration.
> >
> > PrmPkg
> > ------
> > PrmPkg contains the common functionality needed to enable PRM on any
> > system. It does not contain platform-specific code such as PRM modules
> (and
> > by extension PRM handlers). Other than sample modules, PrmPkg will only
> > contain code needed to provide PRM feature functionality as defined in
the
> > PRM Specification.
> >
> > PrmPkg is scoped to continue to only contain platform-agnostic
functionality
> > in the future.
> >
> > The proposed maintainers of PrmPkg are:
> > * Michael Kubacki <mikuback@linux.microsoft.com>
> > * Nate DeSimone <nathaniel.l.desimone@intel.com>
> >
> > The proposed reviewers of PrmPkg are:
> > * Ankit Sinha <ankit.sinha@intel.com>
> >
> > 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>
> >
> > Liu (2):
> >   PrmPkg: Publish PRM operation region to support PRM ACPI _DSM
> >     invocation
> >   PrmPkg: Export major/minor version in PRM module PE COFF header
> >
> > Liu Yun Y (1):
> >   PrmPkg: Update PRM OpRegion
> >
> > Michael Kubacki (38):
> >   PrmPkg: Add package and include headers
> >   PrmPkg: Add PrmConfig protocol interface
> >   PrmPkg/PrmContextBufferLib: Add initial library instance
> >   PrmPkg/PrmConfigDxe: Add initial driver
> >   PrmPkg: Add initial PrmSamplePrintModule
> >   PrmPkg: Add initial PrmSampleMemoryAllocationModule
> >   PrmPkg: Add initial PrmSampleHardwareAccessModule
> >   PrmPkg: Add initial PrmSampleContextBufferModule
> >   PrmPkg: Add initial package DSC file
> >   Readme.md: Add initial content
> >   PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option
> >   PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro
> >   PrmPkg: Add initial PrmSsdtInstallDxe module
> >   PrmPkg: Remove PRM Module Update Lock
> >   PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag
> >   PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures
> >   PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support
> >   PrmPkg/PrmSampleContextBufferModule: Remove OS debug print
> > requirement
> >   PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM
> handlers
> >   PrmPkg/SampleAcpiParameterBufferModule: Add initial module
> >   PrmPkg/HardwareAccessModuleConfigLib: Add initial library
> >   PrmPkg/Samples/Readme.md: Add initial file
> >   PrmPkg: Refactor some PrmLoaderDxe functionality into libraries
> >   PrmPkg/Application/PrmInfo: Add initial application
> >   PrmPkg: Enforce stricter types
> >   PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file
> >   PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib
> >   PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests
> >   PrmPkg/DxePrmModuleDiscoveryLib: Add initial host-based unit tests
> >   PrmPkg: Add PlatformGuid
> >   Readme.md: Add iASL note and QEMU sample link
> >   PrmPkg: Replace PcdPrmPlatformGuid with
> EDKII_DSC_PLATFORM_GUID
> >   PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule
> >   PrmPkg/Samples: Remove PrmSamplePrintModule
> >   PrmPkg: Remove the concept of OS services
> >   Readme.md: Add a link to PRM Specification
> >   PrmPkg: Changes for edk2 repo transition
> >   PrmPkg: Apply uncrustify changes
> >
> >  PrmPkg/Application/PrmInfo/PrmInfo.c
> > |  732 +++++++++
> >  PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
> > |  199 +++
> >
> > PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLi
> > bUnitTest.c
> |  649 ++++++++
> >
> PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
> > |  386 +++++
> >
> > PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDisco
> > veryLibUnitTest.c
> |  210 +++
> >  PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
> > |  417 +++++
> >  PrmPkg/PrmConfigDxe/PrmConfigDxe.c
> > |  512 ++++++
> >  PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
> > |  377 +++++
> >  PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
> > |  110 ++
> >
> >
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiP
> > arameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.
> > c   |  127 ++
> >
> > PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiP
> > arameterBufferModule.c
> |   78 +
> >
> > PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuff
> > erModuleConfigLib/DxeContextBufferModuleConfigLib.c
> |  218
> > +++
> >
> > PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuff
> > erModule.c
> |   84 +
> >
> >
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardware
> > AccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
> |
> > 108 ++
> >
> > PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardware
> > AccessModule.c
> |  335 ++++
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTest.c
> |  119 ++
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestEventTimer.c
> |  180 +++
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestImage.c
> |  163 ++
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestMemory.c
> |  145 ++
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestMisc.c
> |  198 +++
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestProtocol.c
> | 1650
> > ++++++++++++++++++++
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestTpl.c
> |   43 +
> >  .azurepipelines/templates/pr-gate-build-job.yml
> > |    2 +-
> >  .pytool/CISettings.py
> > |    1 +
> >  Maintainers.txt
> > |    8 +
> >  PrmPkg/Application/PrmInfo/PrmInfo.h
> > |   49 +
> >  PrmPkg/Application/PrmInfo/PrmInfo.inf
> > |   66 +
> >  PrmPkg/Application/PrmInfo/PrmInfo.uni
> > |   11 +
> >  PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
> > |   12 +
> >  PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
> > |  132 ++
> >  PrmPkg/Include/Library/PrmContextBufferLib.h
> > |   99 ++
> >  PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
> > |   60 +
> >  PrmPkg/Include/Library/PrmPeCoffLib.h
> > |  111 ++
> >  PrmPkg/Include/Prm.h
> > |   46 +
> >  PrmPkg/Include/PrmContextBuffer.h
> > |  171 ++
> >  PrmPkg/Include/PrmDataBuffer.h
> > |   50 +
> >  PrmPkg/Include/PrmExportDescriptor.h
> > |  109 ++
> >  PrmPkg/Include/PrmMmio.h
> > |   45 +
> >  PrmPkg/Include/PrmModule.h
> > |   47 +
> >  PrmPkg/Include/PrmModuleImageContext.h
> > |   28 +
> >  PrmPkg/Include/Protocol/PrmConfig.h
> > |   31 +
> >  PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
> > |   35 +
> >
> > PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLi
> > bUnitTestHost.inf
> |   46 +
> >
> > PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.in
> > f
> |   41 +
> >  PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
> > |   39 +
> >
> > PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDisco
> > veryLibUnitTestHost.inf
> |   39 +
> >  PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
> > |   32 +
> >  PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
> > |   48 +
> >  PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
> > |   96 ++
> >  PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
> > |   61 +
> >  PrmPkg/PrmPkg.ci.yaml
> > |  110 ++
> >  PrmPkg/PrmPkg.dec
> > |   67 +
> >  PrmPkg/PrmPkg.dsc
> > |  142 ++
> >  PrmPkg/PrmPkg.uni
> > |   10 +
> >  PrmPkg/PrmSsdtInstallDxe/Prm.asl
> > |  115 ++
> >  PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
> > |   52 +
> >  PrmPkg/Readme.md
> > |  264 ++++
> >
> >
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiP
> > arameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.
> > inf |   39 +
> >
> > PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiP
> > arameterBufferModule.inf
> |   41 +
> >  PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
> > |   24 +
> >
> > PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuff
> > erModuleConfigLib/DxeContextBufferModuleConfigLib.inf
> |   39 +
> >
> > PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuff
> > erModule.inf
> |   44 +
> >  PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
> > |  108 ++
> >
> >
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardware
> > AccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
> |
> > 39 +
> >
> > PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardware
> > AccessModule.inf
> |   43 +
> >  PrmPkg/Samples/Readme.md
> > |  146 ++
> >  PrmPkg/Test/PrmPkgHostTest.dsc
> > |   39 +
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibTest.uni
> |   12 +
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTest.h
> | 1042 ++++++++++++
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTest.inf
> |   46 +
> >
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestProtocol.h
> |  120 ++
> >  71 files changed, 11096 insertions(+), 1 deletion(-)  create mode
100644
> > PrmPkg/Application/PrmInfo/PrmInfo.c
> >  create mode 100644
> > PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.c
> >  create mode 100644
> > PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLi
> > bUnitTest.c
> >  create mode 100644
> > PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.c
> >  create mode 100644
> > PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDisco
> > veryLibUnitTest.c
> >  create mode 100644
> PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.c
> >  create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.c
> >  create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.c
> >  create mode 100644 PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.c
> >  create mode 100644
> >
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiP
> > arameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.
> > c
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiP
> > arameterBufferModule.c
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuff
> > erModuleConfigLib/DxeContextBufferModuleConfigLib.c
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuff
> > erModule.c
> >  create mode 100644
> >
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardware
> > AccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.c
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardware
> > AccessModule.c
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTest.c
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestEventTimer.c
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestImage.c
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestMemory.c
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestMisc.c
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestProtocol.c
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestTpl.c
> >  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.h
> >  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.inf
> >  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfo.uni
> >  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoExtra.uni
> >  create mode 100644 PrmPkg/Application/PrmInfo/PrmInfoStrings.uni
> >  create mode 100644 PrmPkg/Include/Library/PrmContextBufferLib.h
> >  create mode 100644 PrmPkg/Include/Library/PrmModuleDiscoveryLib.h
> >  create mode 100644 PrmPkg/Include/Library/PrmPeCoffLib.h
> >  create mode 100644 PrmPkg/Include/Prm.h  create mode 100644
> > PrmPkg/Include/PrmContextBuffer.h  create mode 100644
> > PrmPkg/Include/PrmDataBuffer.h  create mode 100644
> > PrmPkg/Include/PrmExportDescriptor.h
> >  create mode 100644 PrmPkg/Include/PrmMmio.h  create mode 100644
> > PrmPkg/Include/PrmModule.h  create mode 100644
> > PrmPkg/Include/PrmModuleImageContext.h
> >  create mode 100644 PrmPkg/Include/Protocol/PrmConfig.h
> >  create mode 100644
> > PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf
> >  create mode 100644
> > PrmPkg/Library/DxePrmContextBufferLib/UnitTest/DxePrmContextBufferLi
> > bUnitTestHost.inf
> >  create mode 100644
> > PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.in
> > f
> >  create mode 100644
> > PrmPkg/Library/DxePrmModuleDiscoveryLib/PrmModuleDiscovery.h
> >  create mode 100644
> > PrmPkg/Library/DxePrmModuleDiscoveryLib/UnitTest/DxePrmModuleDisco
> > veryLibUnitTestHost.inf
> >  create mode 100644
> > PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf
> >  create mode 100644 PrmPkg/PrmConfigDxe/PrmConfigDxe.inf
> >  create mode 100644 PrmPkg/PrmLoaderDxe/PrmAcpiTable.h
> >  create mode 100644 PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf
> >  create mode 100644 PrmPkg/PrmPkg.ci.yaml  create mode 100644
> > PrmPkg/PrmPkg.dec  create mode 100644 PrmPkg/PrmPkg.dsc  create
> mode
> > 100644 PrmPkg/PrmPkg.uni  create mode 100644
> > PrmPkg/PrmSsdtInstallDxe/Prm.asl  create mode 100644
> > PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf
> >  create mode 100644 PrmPkg/Readme.md
> >  create mode 100644
> >
> PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiP
> > arameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.
> > inf
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiP
> > arameterBufferModule.inf
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleContextBufferModule/Include/StaticData.h
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBuff
> > erModuleConfigLib/DxeContextBufferModuleConfigLib.inf
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBuff
> > erModule.inf
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleHardwareAccessModule/Hpet.h
> >  create mode 100644
> >
> PrmPkg/Samples/PrmSampleHardwareAccessModule/Library/DxeHardware
> > AccessModuleConfigLib/DxeHardwareAccessModuleConfigLib.inf
> >  create mode 100644
> > PrmPkg/Samples/PrmSampleHardwareAccessModule/PrmSampleHardware
> > AccessModule.inf
> >  create mode 100644 PrmPkg/Samples/Readme.md  create mode
> 100644
> > PrmPkg/Test/PrmPkgHostTest.dsc  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibTest.uni
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTest.h
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTest.inf
> >  create mode 100644
> > PrmPkg/Test/UnitTest/Library/UefiBootServicesTableLibUnitTest/UefiBootS
> > ervicesTableLibUnitTestProtocol.h
> >
> > --
> > 2.28.0.windows.1
> >
> >
> >
> > -=-=-=-=-=-=
> > Groups.io Links: You receive all messages sent to this group.
> > View/Reply Online (#87842):
> https://edk2.groups.io/g/devel/message/87842
> > Mute This Topic: https://groups.io/mt/89955942/1772825
> > Group Owner: devel+owner@edk2.groups.io
> > Unsubscribe: https://edk2.groups.io/g/devel/unsub
> [ankit.sinha@intel.com]
> > -=-=-=-=-=-=
> >
> 
> 
> 
> 
> 




^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2022-03-31  0:52 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-22 16:19 [PATCH v1 00/41] Add PrmPkg Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 01/41] PrmPkg: Add package and include headers Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 02/41] PrmPkg: Add PrmConfig protocol interface Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 03/41] PrmPkg/PrmContextBufferLib: Add initial library instance Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 04/41] PrmPkg/PrmConfigDxe: Add initial driver Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 05/41] PrmPkg: Add initial PrmSamplePrintModule Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 06/41] PrmPkg: Add initial PrmSampleMemoryAllocationModule Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 07/41] PrmPkg: Add initial PrmSampleHardwareAccessModule Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 08/41] PrmPkg: Add initial PrmSampleContextBufferModule Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 09/41] PrmPkg: Add initial package DSC file Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 10/41] Readme.md: Add initial content Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 11/41] PrmPkg: Add ALLOCATE_CONTEXT_BUFFER_IN_FW build option Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 12/41] PrmPkg: Enable variable growth for the PRM_MODULE_EXPORT macro Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 13/41] PrmPkg: Publish PRM operation region to support PRM ACPI _DSM invocation Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 14/41] PrmPkg: Export major/minor version in PRM module PE COFF header Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 15/41] PrmPkg: Add initial PrmSsdtInstallDxe module Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 16/41] PrmPkg: Remove PRM Module Update Lock Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 17/41] PrmPkg: Remove ALLOCATE_CONTEXT_BUFFER_IN_FW build flag Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 18/41] PrmPkg/PrmContextBuffer.h: Add ACPI parameter support structures Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 19/41] PrmPkg/PrmLoaderDxe: Add ACPI parameter buffer support Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 20/41] PrmPkg/PrmSampleContextBufferModule: Remove OS debug print requirement Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 21/41] PrmPkg/PrmSampleHardwareAccessModule: Add non-print PRM handlers Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 22/41] PrmPkg/SampleAcpiParameterBufferModule: Add initial module Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 23/41] PrmPkg/HardwareAccessModuleConfigLib: Add initial library Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 24/41] PrmPkg/Samples/Readme.md: Add initial file Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 25/41] PrmPkg: Refactor some PrmLoaderDxe functionality into libraries Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 26/41] PrmPkg/Application/PrmInfo: Add initial application Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 27/41] PrmPkg: Enforce stricter types Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 28/41] PrmPkg/Test/PrmPkgHostTest.dsc: Add initial file Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 29/41] PrmPkg/Test/UnitTest/Library: Add initial UEFI Boot Services test lib Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 30/41] PrmPkg/Library/DxePrmContextBufferLib: Add host-based unit tests Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 31/41] PrmPkg/DxePrmModuleDiscoveryLib: Add initial " Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 32/41] PrmPkg: Add PlatformGuid Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 33/41] PrmPkg: Update PRM OpRegion Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 34/41] Readme.md: Add iASL note and QEMU sample link Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 35/41] PrmPkg: Replace PcdPrmPlatformGuid with EDKII_DSC_PLATFORM_GUID Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 36/41] PrmPkg/Samples: Remove PrmSampleMemoryAllocationModule Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 37/41] PrmPkg/Samples: Remove PrmSamplePrintModule Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 38/41] PrmPkg: Remove the concept of OS services Michael Kubacki
2022-03-22 16:19 ` [PATCH v1 39/41] Readme.md: Add a link to PRM Specification Michael Kubacki
2022-03-28  8:48 ` 回复: [edk2-devel] [PATCH v1 00/41] Add PrmPkg gaoliming
2022-03-28 14:05   ` Michael Kubacki
2022-03-29 16:28 ` Sinha, Ankit
2022-03-31  0:52   ` 回复: " gaoliming

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox