public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Michael Kubacki" <mikuback@linux.microsoft.com>
To: devel@edk2.groups.io
Cc: 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>
Subject: [PATCH v1 26/41] PrmPkg/Application/PrmInfo: Add initial application
Date: Tue, 22 Mar 2022 12:19:32 -0400	[thread overview]
Message-ID: <20220322161947.9319-27-mikuback@linux.microsoft.com> (raw)
In-Reply-To: <20220322161947.9319-1-mikuback@linux.microsoft.com>

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


  parent reply	other threads:[~2022-03-22 16:22 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Michael Kubacki [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220322161947.9319-27-mikuback@linux.microsoft.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox