From: Michael Kubacki <michael.kuba...@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 <af...@apple.com>
Cc: Kang Gao <kang....@intel.com>
Cc: Michael D Kinney <michael.d.kin...@intel.com>
Cc: Michael Kubacki <michael.kuba...@microsoft.com>
Cc: Leif Lindholm <l...@nuviainc.com>
Cc: Benjamin You <benjamin....@intel.com>
Cc: Liu Yun <yun.y....@intel.com>
Cc: Ankit Sinha <ankit.si...@intel.com>
Cc: Nate DeSimone <nathaniel.l.desim...@intel.com>
Signed-off-by: Michael Kubacki <michael.kuba...@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



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#87868): https://edk2.groups.io/g/devel/message/87868
Mute This Topic: https://groups.io/mt/89956016/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to