]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/DumpDynPcd: Add application to dump dynamic PCD settings
authorZhang, Shenglei <shenglei.zhang@intel.com>
Tue, 7 May 2019 05:55:05 +0000 (13:55 +0800)
committerHao A Wu <hao.a.wu@intel.com>
Wed, 8 May 2019 06:15:40 +0000 (14:15 +0800)
This is a shell application to dump dynamic PCD settings.
Type DumpDynPcd -?/h/H to get help information.
Type DumpDynPcd -v/V to get version information.
Type DumpDynPcd [PcdName] to get Pcd information.
https://bugzilla.tianocore.org/show_bug.cgi?id=1541

v2:1.Add static for global variables.
   2.Change the parameter amount of InternalStrnCatGrow in DumpDynPcd.c.
   3.Add open brace according to EDK II C Coding Standards Specification.
   4.Remove the dependency on ShellPkg.dec in DumpDynPcd.inf.

v3:Add static for all global variables and internal functions.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c [new file with mode: 0644]
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf [new file with mode: 0644]
MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dsc

diff --git a/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c
new file mode 100644 (file)
index 0000000..96b35d3
--- /dev/null
@@ -0,0 +1,610 @@
+/** @file\r
+  A shell application to dump dynamic PCD settings.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <PiDxe.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+\r
+#include <Protocol/UnicodeCollation.h>\r
+#include <Protocol/PiPcd.h>\r
+#include <Protocol/Pcd.h>\r
+#include <Protocol/PiPcdInfo.h>\r
+#include <Protocol/PcdInfo.h>\r
+#include <Protocol/ShellParameters.h>\r
+#include <Protocol/Shell.h>\r
+\r
+\r
+//\r
+// String token ID of help message text.\r
+// Shell supports to find help message in the resource section of an application image if\r
+// .MAN file is not found. This global variable is added to make build tool recognizes\r
+// that the help string is consumed by user and then build tool will add the string into\r
+// the resource section. Thus the application can use '-?' option to show help message in\r
+// Shell.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStrDumpDynPcdHelpTokenId = STRING_TOKEN (STR_DUMP_DYN_PCD_HELP_INFORMATION);\r
+\r
+#define MAJOR_VERSION   1\r
+#define MINOR_VERSION   0\r
+\r
+static EFI_UNICODE_COLLATION_PROTOCOL  *mUnicodeCollation  = NULL;\r
+static EFI_PCD_PROTOCOL                *mPiPcd             = NULL;\r
+static PCD_PROTOCOL                    *mPcd               = NULL;\r
+static EFI_GET_PCD_INFO_PROTOCOL       *mPiPcdInfo         = NULL;\r
+static GET_PCD_INFO_PROTOCOL           *mPcdInfo           = NULL;\r
+static CHAR16                   *mTempPcdNameBuffer = NULL;\r
+static UINTN                     mTempPcdNameBufferSize = 0;\r
+\r
+static CONST CHAR8 mHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};\r
+\r
+static UINTN  Argc;\r
+static CHAR16 **Argv;\r
+\r
+\r
+/**\r
+\r
+  This function parse application ARG.\r
+\r
+  @return Status\r
+**/\r
+static\r
+EFI_STATUS\r
+GetArg (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  gImageHandle,\r
+                  &gEfiShellParametersProtocolGuid,\r
+                  (VOID**)&ShellParameters\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Argc = ShellParameters->Argc;\r
+  Argv = ShellParameters->Argv;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+   Display current version.\r
+**/\r
+static\r
+VOID\r
+ShowVersion (\r
+  )\r
+{\r
+  Print (L"DumpDynPcd Version %d.%02d\n", MAJOR_VERSION, MINOR_VERSION);\r
+}\r
+\r
+/**\r
+   Display Usage and Help information.\r
+**/\r
+static\r
+VOID\r
+ShowHelp (\r
+  )\r
+{\r
+  Print (L"Dump dynamic[ex] PCD info.\n");\r
+  Print (L"\n");\r
+  Print (L"DumpDynPcd [PcdName]\n");\r
+  Print (L"\n");\r
+  Print (L"  PcdName    Specifies the name of PCD.\n");\r
+  Print (L"             A literal[or partial] name or a pattern as specified in\n");\r
+  Print (L"             the MetaiMatch() function of the EFI_UNICODE_COLLATION2_PROCOOL.\n");\r
+  Print (L"             If it is absent, dump all PCDs' info.\n");\r
+  Print (L"The PCD data is printed as hexadecimal dump.\n");\r
+}\r
+\r
+/**\r
+  Dump some hexadecimal data to the screen.\r
+\r
+  @param[in] Indent     How many spaces to indent the output.\r
+  @param[in] Offset     The offset of the printing.\r
+  @param[in] DataSize   The size in bytes of UserData.\r
+  @param[in] UserData   The data to print out.\r
+**/\r
+static\r
+VOID\r
+DumpHex (\r
+  IN UINTN        Indent,\r
+  IN UINTN        Offset,\r
+  IN UINTN        DataSize,\r
+  IN VOID         *UserData\r
+  )\r
+{\r
+  UINT8 *Data;\r
+\r
+  CHAR8 Val[50];\r
+\r
+  CHAR8 Str[20];\r
+\r
+  UINT8 TempByte;\r
+  UINTN Size;\r
+  UINTN Index;\r
+\r
+  Data = UserData;\r
+  while (DataSize != 0) {\r
+    Size = 16;\r
+    if (Size > DataSize) {\r
+      Size = DataSize;\r
+    }\r
+\r
+    for (Index = 0; Index < Size; Index += 1) {\r
+      TempByte            = Data[Index];\r
+      Val[Index * 3 + 0]  = mHex[TempByte >> 4];\r
+      Val[Index * 3 + 1]  = mHex[TempByte & 0xF];\r
+      Val[Index * 3 + 2]  = (CHAR8) ((Index == 7) ? '-' : ' ');\r
+      Str[Index]          = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);\r
+    }\r
+\r
+    Val[Index * 3]  = 0;\r
+    Str[Index]      = 0;\r
+    Print (L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);\r
+\r
+    Data += Size;\r
+    Offset += Size;\r
+    DataSize -= Size;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Safely append with automatic string resizing given length of Destination and\r
+  desired length of copy from Source.\r
+\r
+  append the first D characters of Source to the end of Destination, where D is\r
+  the lesser of Count and the StrLen() of Source. If appending those D characters\r
+  will fit within Destination (whose Size is given as CurrentSize) and\r
+  still leave room for a NULL terminator, then those characters are appended,\r
+  starting at the original terminating NULL of Destination, and a new terminating\r
+  NULL is appended.\r
+\r
+  If appending D characters onto Destination will result in a overflow of the size\r
+  given in CurrentSize the string will be grown such that the copy can be performed\r
+  and CurrentSize will be updated to the new size.\r
+\r
+  If Source is NULL, there is nothing to append, just return the current buffer in\r
+  Destination.\r
+\r
+  if Destination is NULL, then ASSERT()\r
+  if Destination's current length (including NULL terminator) is already more then\r
+  CurrentSize, then ASSERT()\r
+\r
+  @param[in, out] Destination   The String to append onto\r
+  @param[in, out] CurrentSize   on call the number of bytes in Destination.  On\r
+                                return possibly the new size (still in bytes).  if NULL\r
+                                then allocate whatever is needed.\r
+  @param[in]      Source        The String to append from\r
+\r
+  @return Destination           return the resultant string.\r
+**/\r
+static\r
+CHAR16*\r
+InternalStrnCatGrow (\r
+  IN OUT CHAR16           **Destination,\r
+  IN OUT UINTN            *CurrentSize,\r
+  IN     CONST CHAR16     *Source\r
+  )\r
+{\r
+  UINTN DestinationStartSize;\r
+  UINTN NewSize;\r
+  UINTN SourceLen;\r
+\r
+  SourceLen = StrLen(Source);\r
+\r
+  //\r
+  // ASSERTs\r
+  //\r
+  ASSERT(Destination != NULL);\r
+\r
+  //\r
+  // If there's nothing to do then just return Destination\r
+  //\r
+  if (Source == NULL) {\r
+    return (*Destination);\r
+  }\r
+\r
+  //\r
+  // allow for un-initialized pointers, based on size being 0\r
+  //\r
+  if (CurrentSize != NULL && *CurrentSize == 0) {\r
+    *Destination = NULL;\r
+  }\r
+\r
+  //\r
+  // allow for NULL pointers address as Destination\r
+  //\r
+  if (*Destination != NULL) {\r
+    ASSERT(CurrentSize != 0);\r
+    DestinationStartSize = StrSize(*Destination);\r
+    ASSERT(DestinationStartSize <= *CurrentSize);\r
+  } else {\r
+    DestinationStartSize = 0;\r
+  }\r
+\r
+  //\r
+  // Test and grow if required\r
+  //\r
+  if (CurrentSize != NULL) {\r
+    NewSize = *CurrentSize;\r
+    if (NewSize < DestinationStartSize + (SourceLen * sizeof(CHAR16))) {\r
+      while (NewSize < (DestinationStartSize + (SourceLen*sizeof(CHAR16)))) {\r
+        NewSize += 2 * SourceLen * sizeof(CHAR16);\r
+      }\r
+      *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
+      *CurrentSize = NewSize;\r
+    }\r
+  } else {\r
+    NewSize = (SourceLen + 1)*sizeof(CHAR16);\r
+    *Destination = AllocateZeroPool(NewSize);\r
+  }\r
+\r
+  //\r
+  // Now use standard StrnCat on a big enough buffer\r
+  //\r
+  if (*Destination == NULL) {\r
+    return (NULL);\r
+  }\r
+\r
+  StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, SourceLen);\r
+  return *Destination;\r
+}\r
+\r
+/**\r
+  Get PCD type string based on input PCD type.\r
+\r
+  @param[in]    TokenSpace      PCD Token Space.\r
+  @param[in]    PcdType         The input PCD type.\r
+\r
+  @return       Pointer to PCD type string.\r
+**/\r
+static\r
+CHAR16 *\r
+GetPcdTypeString (\r
+  IN CONST EFI_GUID     *TokenSpace,\r
+  IN EFI_PCD_TYPE       PcdType\r
+  )\r
+{\r
+  UINTN  BufLen;\r
+  CHAR16 *RetString;\r
+\r
+  BufLen      = 0;\r
+  RetString   = NULL;\r
+\r
+  switch (PcdType) {\r
+    case EFI_PCD_TYPE_8:\r
+      InternalStrnCatGrow (&RetString, &BufLen, L"UINT8");\r
+      break;\r
+    case EFI_PCD_TYPE_16:\r
+      InternalStrnCatGrow (&RetString, &BufLen, L"UINT16");\r
+      break;\r
+    case EFI_PCD_TYPE_32:\r
+      InternalStrnCatGrow (&RetString, &BufLen, L"UINT32");\r
+      break;\r
+    case EFI_PCD_TYPE_64:\r
+      InternalStrnCatGrow (&RetString, &BufLen, L"UINT64");\r
+      break;\r
+    case EFI_PCD_TYPE_BOOL:\r
+      InternalStrnCatGrow (&RetString, &BufLen, L"BOOLEAN");\r
+      break;\r
+    case EFI_PCD_TYPE_PTR:\r
+      InternalStrnCatGrow (&RetString, &BufLen, L"POINTER");\r
+      break;\r
+    default:\r
+      InternalStrnCatGrow (&RetString, &BufLen, L"UNKNOWN");\r
+      break;\r
+  }\r
+\r
+  if (TokenSpace == NULL) {\r
+    InternalStrnCatGrow (&RetString, &BufLen, L":DYNAMIC");\r
+  } else {\r
+    InternalStrnCatGrow (&RetString, &BufLen, L":DYNAMICEX");\r
+  }\r
+\r
+  return RetString;\r
+}\r
+\r
+/**\r
+  Dump PCD info.\r
+\r
+  @param[in]    TokenSpace      PCD Token Space.\r
+  @param[in]    TokenNumber     PCD Token Number.\r
+  @param[in]    PcdInfo         Pointer to PCD info.\r
+**/\r
+static\r
+VOID\r
+DumpPcdInfo (\r
+  IN CONST EFI_GUID     *TokenSpace,\r
+  IN UINTN              TokenNumber,\r
+  IN EFI_PCD_INFO       *PcdInfo\r
+  )\r
+{\r
+  CHAR16                *RetString;\r
+  UINT8                 Uint8;\r
+  UINT16                Uint16;\r
+  UINT32                Uint32;\r
+  UINT64                Uint64;\r
+  BOOLEAN               Boolean;\r
+  VOID                  *PcdData;\r
+\r
+  RetString = NULL;\r
+\r
+  if (PcdInfo->PcdName != NULL) {\r
+    Print (L"%a\n", PcdInfo->PcdName);\r
+  } else {\r
+    if (TokenSpace == NULL) {\r
+      Print (L"Default Token Space\n");\r
+    } else {\r
+      Print (L"%g\n", TokenSpace);\r
+    }\r
+  }\r
+\r
+  RetString = GetPcdTypeString (TokenSpace, PcdInfo->PcdType);\r
+\r
+  switch (PcdInfo->PcdType) {\r
+    case EFI_PCD_TYPE_8:\r
+      if (TokenSpace == NULL) {\r
+        Uint8 = mPcd->Get8 (TokenNumber);\r
+      } else {\r
+        Uint8 = mPiPcd->Get8 (TokenSpace, TokenNumber);\r
+      }\r
+      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint8);\r
+      break;\r
+    case EFI_PCD_TYPE_16:\r
+      if (TokenSpace == NULL) {\r
+        Uint16 = mPcd->Get16 (TokenNumber);\r
+      } else {\r
+        Uint16 = mPiPcd->Get16 (TokenSpace, TokenNumber);\r
+      }\r
+      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint16);\r
+      break;\r
+    case EFI_PCD_TYPE_32:\r
+      if (TokenSpace == NULL) {\r
+        Uint32 = mPcd->Get32 (TokenNumber);\r
+      } else {\r
+        Uint32 = mPiPcd->Get32 (TokenSpace, TokenNumber);\r
+      }\r
+      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint32);\r
+      break;\r
+    case EFI_PCD_TYPE_64:\r
+      if (TokenSpace == NULL) {\r
+        Uint64 = mPcd->Get64 (TokenNumber);\r
+      } else {\r
+        Uint64 = mPiPcd->Get64 (TokenSpace, TokenNumber);\r
+      }\r
+      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = 0x%lx\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint64);\r
+      break;\r
+    case EFI_PCD_TYPE_BOOL:\r
+      if (TokenSpace == NULL) {\r
+        Boolean = mPcd->GetBool (TokenNumber);\r
+      } else {\r
+        Boolean = mPiPcd->GetBool (TokenSpace, TokenNumber);\r
+      }\r
+      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value = %a\n", TokenNumber, RetString, PcdInfo->PcdSize, Boolean ? "TRUE" : "FALSE");\r
+      break;\r
+    case EFI_PCD_TYPE_PTR:\r
+      if (TokenSpace == NULL) {\r
+        PcdData = mPcd->GetPtr (TokenNumber);\r
+      } else {\r
+        PcdData = mPiPcd->GetPtr (TokenSpace, TokenNumber);\r
+      }\r
+      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize);\r
+      DumpHex (2, 0, PcdInfo->PcdSize, PcdData);\r
+      break;\r
+    default:\r
+      return;\r
+  }\r
+\r
+  if (RetString != NULL) {\r
+    FreePool (RetString);\r
+  }\r
+  Print (L"\n");\r
+}\r
+\r
+/**\r
+  Show one or all PCDs' info.\r
+\r
+  @param[in]  InputPcdName       Pointer to PCD name to show. If NULL, show all PCDs' info.\r
+\r
+  @retval EFI_SUCCESS            Command completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough resources were available to run the command.\r
+  @retval EFI_ABORTED            Aborted by user.\r
+  @retval EFI_NOT_FOUND          The specified PCD is not found.\r
+**/\r
+static\r
+EFI_STATUS\r
+ProcessPcd (\r
+  IN CHAR16     *InputPcdName\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_GUID              *TokenSpace;\r
+  UINTN                 TokenNumber;\r
+  EFI_PCD_INFO          PcdInfo;\r
+  BOOLEAN               Found;\r
+  UINTN                 PcdNameSize;\r
+\r
+  PcdInfo.PcdName = NULL;\r
+  PcdInfo.PcdSize = 0;\r
+  PcdInfo.PcdType = 0xFF;\r
+  Found = FALSE;\r
+\r
+  Print (L"Current system SKU ID: 0x%x\n\n", mPiPcdInfo->GetSku ());\r
+\r
+  TokenSpace = NULL;\r
+  do {\r
+    TokenNumber = 0;\r
+    do {\r
+      Status = mPiPcd->GetNextToken (TokenSpace, &TokenNumber);\r
+      if (!EFI_ERROR (Status) && TokenNumber != 0) {\r
+        if (TokenSpace == NULL) {\r
+          //\r
+          // PCD in default Token Space.\r
+          //\r
+          mPcdInfo->GetInfo (TokenNumber, &PcdInfo);\r
+        } else {\r
+          mPiPcdInfo->GetInfo (TokenSpace, TokenNumber, &PcdInfo);\r
+        }\r
+        if (InputPcdName != NULL) {\r
+          if (PcdInfo.PcdName == NULL) {\r
+            continue;\r
+          }\r
+          PcdNameSize = AsciiStrSize (PcdInfo.PcdName) * sizeof (CHAR16);\r
+          if (mTempPcdNameBuffer == NULL) {\r
+            mTempPcdNameBufferSize = PcdNameSize;\r
+            mTempPcdNameBuffer = AllocatePool (mTempPcdNameBufferSize);\r
+          } else if (mTempPcdNameBufferSize < PcdNameSize) {\r
+            mTempPcdNameBuffer = ReallocatePool (mTempPcdNameBufferSize, PcdNameSize, mTempPcdNameBuffer);\r
+            mTempPcdNameBufferSize = PcdNameSize;\r
+          }\r
+          if (mTempPcdNameBuffer == NULL) {\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+          AsciiStrToUnicodeStrS (PcdInfo.PcdName, mTempPcdNameBuffer, mTempPcdNameBufferSize / sizeof (CHAR16));\r
+          //\r
+          // Compare the input PCD name with the PCD name in PCD database.\r
+          //\r
+          if ((StrStr (mTempPcdNameBuffer, InputPcdName) != NULL) ||\r
+              (mUnicodeCollation != NULL && mUnicodeCollation->MetaiMatch (mUnicodeCollation, mTempPcdNameBuffer, InputPcdName))) {\r
+            //\r
+            // Found matched PCD.\r
+            //\r
+            DumpPcdInfo (TokenSpace, TokenNumber, &PcdInfo);\r
+            Found = TRUE;\r
+          }\r
+        } else {\r
+          DumpPcdInfo (TokenSpace, TokenNumber, &PcdInfo);\r
+        }\r
+      }\r
+    } while (!EFI_ERROR (Status) && TokenNumber != 0);\r
+\r
+    Status = mPiPcd->GetNextTokenSpace ((CONST EFI_GUID **) &TokenSpace);\r
+  } while (!EFI_ERROR (Status) && TokenSpace != NULL);\r
+\r
+  if ((InputPcdName != NULL) && !Found) {\r
+    //\r
+    // The specified PCD is not found, print error.\r
+    //\r
+    Print (L"%EError. %NNo matching PCD found: %s.\n", InputPcdName);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Main entrypoint for DumpDynPcd shell application.\r
+\r
+  @param[in]  ImageHandle     The image handle.\r
+  @param[in]  SystemTable     The system table.\r
+\r
+  @retval EFI_SUCCESS            Command completed successfully.\r
+  @retval EFI_INVALID_PARAMETER  Command usage error.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough resources were available to run the command.\r
+  @retval EFI_ABORTED            Aborted by user.\r
+  @retval EFI_NOT_FOUND          The specified PCD is not found.\r
+  @retval Others                 Error status returned from gBS->LocateProtocol.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DumpDynPcdMain (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  CHAR16        *InputPcdName;\r
+\r
+  InputPcdName  = NULL;\r
+\r
+  Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID **) &mUnicodeCollation);\r
+  if (EFI_ERROR (Status)) {\r
+    mUnicodeCollation = NULL;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (&gEfiPcdProtocolGuid, NULL, (VOID **) &mPiPcd);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"DumpDynPcd: %EError. %NPI PCD protocol is not present.\n");\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (&gEfiGetPcdInfoProtocolGuid, NULL, (VOID **) &mPiPcdInfo);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"DumpDynPcd: %EError. %NPI PCD info protocol is not present.\n");\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (&gPcdProtocolGuid, NULL, (VOID **) &mPcd);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"DumpDynPcd: %EError. %NPCD protocol is not present.\n");\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->LocateProtocol (&gGetPcdInfoProtocolGuid, NULL, (VOID **) &mPcdInfo);\r
+  if (EFI_ERROR (Status)) {\r
+    Print (L"DumpDynPcd: %EError. %NPCD info protocol is not present.\n");\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // get the command line arguments\r
+  //\r
+  Status = GetArg();\r
+  if (EFI_ERROR(Status)){\r
+    Print (L"DumpDynPcd: %EError. %NThe input parameters are not recognized.\n");\r
+    Status = EFI_INVALID_PARAMETER;\r
+    return Status;\r
+  }\r
+\r
+  if (Argc > 2){\r
+    Print (L"DumpDynPcd: %EError. %NToo many arguments specified.\n");\r
+    Status = EFI_INVALID_PARAMETER;\r
+    return Status;\r
+  }\r
+\r
+  if (Argc == 1){\r
+    Status = ProcessPcd (InputPcdName);\r
+    goto Done;\r
+  }\r
+\r
+  if ((StrCmp(Argv[1], L"-?") == 0)||(StrCmp(Argv[1], L"-h") == 0)||(StrCmp(Argv[1], L"-H") == 0)){\r
+    ShowHelp ();\r
+    goto Done;\r
+  } else {\r
+    if ((StrCmp(Argv[1], L"-v") == 0)||(StrCmp(Argv[1], L"-V") == 0)){\r
+      ShowVersion ();\r
+      goto Done;\r
+    } else {\r
+      if (StrStr(Argv[1], L"-") != NULL){\r
+        Print (L"DumpDynPcd: %EError. %NThe argument '%B%s%N' is invalid.\n", Argv[1]);\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
+  InputPcdName = Argv[1];\r
+  Status = ProcessPcd (InputPcdName);\r
+\r
+  Done:\r
+\r
+  if (mTempPcdNameBuffer != NULL) {\r
+    FreePool (mTempPcdNameBuffer);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
new file mode 100644 (file)
index 0000000..a3542dd
--- /dev/null
@@ -0,0 +1,50 @@
+##  @file\r
+#  DumpDynPcd is a shell application to dump dynamic pcd information.\r
+#\r
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010006\r
+  BASE_NAME                      = DumpDynPcd\r
+  FILE_GUID                      = 31ADA2B2-62EA-4866-9B87-03FEA8425974\r
+  MODULE_TYPE                    = UEFI_APPLICATION\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = DumpDynPcdMain\r
+\r
+#\r
+# This flag specifies whether HII resource section is generated into PE image.\r
+#\r
+  UEFI_HII_RESOURCE_SECTION      = TRUE\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 EBC\r
+#\r
+\r
+[Sources]\r
+  DumpDynPcd.c\r
+  DumpDynPcdStr.uni\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  UefiApplicationEntryPoint\r
+  DebugLib\r
+  MemoryAllocationLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+\r
+[Protocols]\r
+  gEfiUnicodeCollation2ProtocolGuid     ## SOMETIMES_CONSUMES\r
+  gEfiPcdProtocolGuid                   ## CONSUMES\r
+  gPcdProtocolGuid                      ## CONSUMES\r
+  gEfiGetPcdInfoProtocolGuid            ## CONSUMES\r
+  gGetPcdInfoProtocolGuid               ## CONSUMES\r
+  gEfiShellParametersProtocolGuid       ## CONSUMES\r
+\r
diff --git a/MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni
new file mode 100644 (file)
index 0000000..f0ee982
--- /dev/null
@@ -0,0 +1,28 @@
+//\r
+// DumpDynPcd is a shell application to dump dynamic pcd information.\r
+//\r
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+// SPDX-License-Identifier: BSD-2-Clause-Patent\r
+//\r
+//**/\r
+\r
+/=#\r
+\r
+#langdef en-US "English"\r
+\r
+#string STR_DUMP_DYN_PCD_HELP_INFORMATION       #language en-US ""\r
+                                                                ".TH DumpDynPcd 0 "Dump dynamic[ex] PCD info."\r\n"\r
+                                                                ".SH NAME\r\n"\r
+                                                                "Dump dynamic[ex] PCD info.\r\n"\r
+                                                                ".SH SYNOPSIS\r\n"\r
+                                                                " \r\n"\r
+                                                                "DumpDynPcd [PcdName].\r\n"\r
+                                                                ".SH OPTIONS\r\n"\r
+                                                                " \r\n"\r
+                                                                "  PcdName    Specifies the name of PCD.\r\n"\r
+                                                                "             A literal[or partial] name or a pattern as specified in\r\n"\r
+                                                                "             the MetaiMatch() function of the EFI_UNICODE_COLLATION2_PROCOOL.\r\n"\r
+                                                                "             If it is absent, dump all PCDs' info.\r\n"\r
+                                                                "The PCD data is printed as hexadecimal dump.\n"\r
+                                                                "\r\n"\r
+\r
index b302f4a4f3ab00e0b1e70290200cc0ca2fb2d730..a8b9d8d027f6bd5411c5e8cee4c22fabf50bd9c4 100644 (file)
 \r
 [Components]\r
   MdeModulePkg/Application/HelloWorld/HelloWorld.inf\r
+  MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf\r
   MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf\r
 \r
   MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf\r