]> git.proxmox.com Git - mirror_edk2.git/commitdiff
PrmPkg/Application/PrmInfo: Add initial application
authorMichael Kubacki <michael.kubacki@microsoft.com>
Wed, 10 Jun 2020 18:06:07 +0000 (11:06 -0700)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Tue, 5 Apr 2022 00:42:38 +0000 (00:42 +0000)
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>
Acked-by: Michael D Kinney <michael.d.kinney@intel.com>
Acked-by: Liming Gao <gaoliming@byosoft.com.cn>
Acked-by: Leif Lindholm <quic_llindhol@quicinc.com>
Reviewed-by: Ankit Sinha <ankit.sinha@intel.com>
PrmPkg/Application/PrmInfo/PrmInfo.c [new file with mode: 0644]
PrmPkg/Application/PrmInfo/PrmInfo.h [new file with mode: 0644]
PrmPkg/Application/PrmInfo/PrmInfo.inf [new file with mode: 0644]
PrmPkg/Application/PrmInfo/PrmInfo.uni [new file with mode: 0644]
PrmPkg/Application/PrmInfo/PrmInfoExtra.uni [new file with mode: 0644]
PrmPkg/Application/PrmInfo/PrmInfoStrings.uni [new file with mode: 0644]
PrmPkg/PrmPkg.dec
PrmPkg/PrmPkg.dsc
PrmPkg/Readme.md

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