[edk2-devel] [PATCH v3] MdeModulePkg/DumpDynPcd: Add application to dump dynamic PCD settings

Zhang, Shenglei posted 1 patch 4 years, 11 months ago
Failed in applying to current master (apply log)
.../Application/DumpDynPcd/DumpDynPcd.c       | 612 ++++++++++++++++++
.../Application/DumpDynPcd/DumpDynPcd.inf     |  50 ++
.../Application/DumpDynPcd/DumpDynPcdStr.uni  |  28 +
MdeModulePkg/MdeModulePkg.dsc                 |   1 +
4 files changed, 691 insertions(+)
create mode 100644 MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c
create mode 100644 MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
create mode 100644 MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni
[edk2-devel] [PATCH v3] MdeModulePkg/DumpDynPcd: Add application to dump dynamic PCD settings
Posted by Zhang, Shenglei 4 years, 11 months ago
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: Hao Wu <hao.a.wu@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>
---
 .../Application/DumpDynPcd/DumpDynPcd.c       | 612 ++++++++++++++++++
 .../Application/DumpDynPcd/DumpDynPcd.inf     |  50 ++
 .../Application/DumpDynPcd/DumpDynPcdStr.uni  |  28 +
 MdeModulePkg/MdeModulePkg.dsc                 |   1 +
 4 files changed, 691 insertions(+)
 create mode 100644 MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c
 create mode 100644 MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
 create mode 100644 MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni

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


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#40073): https://edk2.groups.io/g/devel/message/40073
Mute This Topic: https://groups.io/mt/31529240/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [PATCH v3] MdeModulePkg/DumpDynPcd: Add application to dump dynamic PCD settings
Posted by Wu, Hao A 4 years, 11 months ago
> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Zhang, Shenglei
> Sent: Tuesday, May 07, 2019 1:55 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J; Wu, Hao A; Ni, Ray; Zeng, Star; Dong, Eric
> Subject: [edk2-devel] [PATCH v3] MdeModulePkg/DumpDynPcd: Add application
> to dump dynamic PCD settings
> 
> 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.

I found that the ECC tool cannot handle lower case 'static' before
functions at this moment. Hence, I filed the below BZ for ECC:

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

Meanwhile, I think the behavior in this patch is good.

> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao Wu <hao.a.wu@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>
> ---
>  .../Application/DumpDynPcd/DumpDynPcd.c       | 612 ++++++++++++++++++
>  .../Application/DumpDynPcd/DumpDynPcd.inf     |  50 ++
>  .../Application/DumpDynPcd/DumpDynPcdStr.uni  |  28 +
>  MdeModulePkg/MdeModulePkg.dsc                 |   1 +
>  4 files changed, 691 insertions(+)
>  create mode 100644 MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c
>  create mode 100644
> MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
>  create mode 100644
> MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni
> 
> diff --git a/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c
> b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c
> new file mode 100644
> index 0000000000..025300ae3f
> --- /dev/null
> +++ b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.c
> @@ -0,0 +1,612 @@
> +/** @file
> +  A shell application to dump dynamic PCD settings.
> +
> +  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi.h>
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +
> +
> +#include <Protocol/UnicodeCollation.h>
> +#include <Protocol/PiPcd.h>
> +#include <Protocol/Pcd.h>
> +#include <Protocol/PiPcdInfo.h>
> +#include <Protocol/PcdInfo.h>
> +#include <Protocol/ShellParameters.h>
> +#include <Protocol/Shell.h>
> +
> +
> +//
> +// String token ID of help message text.
> +// Shell supports to find help message in the resource section of an
> application image if
> +// .MAN file is not found. This global variable is added to make build tool
> recognizes
> +// that the help string is consumed by user and then build tool will add the
> string into
> +// the resource section. Thus the application can use '-?' option to show help
> message in
> +// Shell.
> +//
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID
> mStrDumpDynPcdHelpTokenId = STRING_TOKEN
> (STR_DUMP_DYN_PCD_HELP_INFORMATION);
> +
> +#define MAJOR_VERSION   1
> +#define MINOR_VERSION   0
> +
> +static EFI_UNICODE_COLLATION_PROTOCOL  *mUnicodeCollation  = NULL;
> +static EFI_PCD_PROTOCOL                *mPiPcd             = NULL;
> +static PCD_PROTOCOL                    *mPcd               = NULL;
> +static EFI_GET_PCD_INFO_PROTOCOL       *mPiPcdInfo         = NULL;
> +static GET_PCD_INFO_PROTOCOL           *mPcdInfo           = NULL;
> +static CHAR16                   *mTempPcdNameBuffer = NULL;
> +static UINTN                     mTempPcdNameBufferSize = 0;
> +
> +static CONST CHAR8 mHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
> 'C', 'D', 'E', 'F'};
> +
> +static UINTN  Argc;
> +static CHAR16 **Argv;
> +
> +
> +/**
> +
> +  This function parse application ARG.
> +
> +  @return Status
> +**/
> +static
> +EFI_STATUS
> +GetArg (
> +  VOID
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;
> +
> +  Status = gBS->HandleProtocol (
> +                  gImageHandle,
> +                  &gEfiShellParametersProtocolGuid,
> +                  (VOID**)&ShellParameters
> +                  );
> +  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  Argc = ShellParameters->Argc;
> +  Argv = ShellParameters->Argv;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +   Display current version.
> +**/
> +static
> +VOID
> +ShowVersion (
> +  )
> +{
> +  Print (L"DumpDynPcd Version %d.%02d\n", MAJOR_VERSION,
> MINOR_VERSION);
> +}
> +
> +/**
> +   Display Usage and Help information.
> +**/
> +static
> +VOID
> +ShowHelp (
> +  )
> +{
> +  Print (L"Dump dynamic[ex] PCD info.\n");
> +  Print (L"\n");
> +  Print (L"DumpDynPcd [PcdName]\n");
> +  Print (L"\n");
> +  Print (L"  PcdName    Specifies the name of PCD.\n");
> +  Print (L"             A literal[or partial] name or a pattern as specified in\n");
> +  Print (L"             the MetaiMatch() function of the
> EFI_UNICODE_COLLATION2_PROCOOL.\n");
> +  Print (L"             If it is absent, dump all PCDs' info.\n");
> +  Print (L"The PCD data is printed as hexadecimal dump.\n");
> +}
> +
> +/**
> +  Dump some hexadecimal data to the screen.
> +
> +  @param[in] Indent     How many spaces to indent the output.
> +  @param[in] Offset     The offset of the printing.
> +  @param[in] DataSize   The size in bytes of UserData.
> +  @param[in] UserData   The data to print out.
> +**/
> +static
> +VOID
> +DumpHex (
> +  IN UINTN        Indent,
> +  IN UINTN        Offset,
> +  IN UINTN        DataSize,
> +  IN VOID         *UserData
> +  )
> +{
> +  UINT8 *Data;
> +
> +  CHAR8 Val[50];
> +
> +  CHAR8 Str[20];
> +
> +  UINT8 TempByte;
> +  UINTN Size;
> +  UINTN Index;
> +
> +  Data = UserData;
> +  while (DataSize != 0) {
> +    Size = 16;
> +    if (Size > DataSize) {
> +      Size = DataSize;
> +    }
> +
> +    for (Index = 0; Index < Size; Index += 1) {
> +      TempByte            = Data[Index];
> +      Val[Index * 3 + 0]  = mHex[TempByte >> 4];
> +      Val[Index * 3 + 1]  = mHex[TempByte & 0xF];
> +      Val[Index * 3 + 2]  = (CHAR8) ((Index == 7) ? '-' : ' ');
> +      Str[Index]          = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' :
> TempByte);
> +    }
> +
> +    Val[Index * 3]  = 0;
> +    Str[Index]      = 0;
> +    Print (L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
> +
> +    Data += Size;
> +    Offset += Size;
> +    DataSize -= Size;
> +  }
> +}
> +
> +
> +/**
> +  Safely append with automatic string resizing given length of Destination and
> +  desired length of copy from Source.
> +
> +  append the first D characters of Source to the end of Destination, where D is
> +  the lesser of Count and the StrLen() of Source. If appending those D
> characters
> +  will fit within Destination (whose Size is given as CurrentSize) and
> +  still leave room for a NULL terminator, then those characters are appended,
> +  starting at the original terminating NULL of Destination, and a new
> terminating
> +  NULL is appended.
> +
> +  If appending D characters onto Destination will result in a overflow of the
> size
> +  given in CurrentSize the string will be grown such that the copy can be
> performed
> +  and CurrentSize will be updated to the new size.
> +
> +  If Source is NULL, there is nothing to append, just return the current buffer in
> +  Destination.
> +
> +  if Destination is NULL, then ASSERT()
> +  if Destination's current length (including NULL terminator) is already more
> then
> +  CurrentSize, then ASSERT()
> +
> +  @param[in, out] Destination   The String to append onto
> +  @param[in, out] CurrentSize   on call the number of bytes in Destination.  On
> +                                return possibly the new size (still in bytes).  if NULL
> +                                then allocate whatever is needed.
> +  @param[in]      Source        The String to append from
> +  @param[in]      Count         Maximum number of characters to append.  if 0
> then
> +                                all are appended.

If there is no other comments, I will remove the above redundant comment
(for parameter 'Count') before pushing this commit. There is no need to
send a new version.

Other than that,
Reviewed-by: Hao Wu <hao.a.wu@intel.com>

Best Regards,
Hao Wu

> +
> +  @return Destination           return the resultant string.
> +**/
> +static
> +CHAR16*
> +InternalStrnCatGrow (
> +  IN OUT CHAR16           **Destination,
> +  IN OUT UINTN            *CurrentSize,
> +  IN     CONST CHAR16     *Source
> +  )
> +{
> +  UINTN DestinationStartSize;
> +  UINTN NewSize;
> +  UINTN SourceLen;
> +
> +  SourceLen = StrLen(Source);
> +
> +  //
> +  // ASSERTs
> +  //
> +  ASSERT(Destination != NULL);
> +
> +  //
> +  // If there's nothing to do then just return Destination
> +  //
> +  if (Source == NULL) {
> +    return (*Destination);
> +  }
> +
> +  //
> +  // allow for un-initialized pointers, based on size being 0
> +  //
> +  if (CurrentSize != NULL && *CurrentSize == 0) {
> +    *Destination = NULL;
> +  }
> +
> +  //
> +  // allow for NULL pointers address as Destination
> +  //
> +  if (*Destination != NULL) {
> +    ASSERT(CurrentSize != 0);
> +    DestinationStartSize = StrSize(*Destination);
> +    ASSERT(DestinationStartSize <= *CurrentSize);
> +  } else {
> +    DestinationStartSize = 0;
> +  }
> +
> +  //
> +  // Test and grow if required
> +  //
> +  if (CurrentSize != NULL) {
> +    NewSize = *CurrentSize;
> +    if (NewSize < DestinationStartSize + (SourceLen * sizeof(CHAR16))) {
> +      while (NewSize < (DestinationStartSize + (SourceLen*sizeof(CHAR16)))) {
> +        NewSize += 2 * SourceLen * sizeof(CHAR16);
> +      }
> +      *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);
> +      *CurrentSize = NewSize;
> +    }
> +  } else {
> +    NewSize = (SourceLen + 1)*sizeof(CHAR16);
> +    *Destination = AllocateZeroPool(NewSize);
> +  }
> +
> +  //
> +  // Now use standard StrnCat on a big enough buffer
> +  //
> +  if (*Destination == NULL) {
> +    return (NULL);
> +  }
> +
> +  StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, SourceLen);
> +  return *Destination;
> +}
> +
> +/**
> +  Get PCD type string based on input PCD type.
> +
> +  @param[in]    TokenSpace      PCD Token Space.
> +  @param[in]    PcdType         The input PCD type.
> +
> +  @return       Pointer to PCD type string.
> +**/
> +static
> +CHAR16 *
> +GetPcdTypeString (
> +  IN CONST EFI_GUID     *TokenSpace,
> +  IN EFI_PCD_TYPE       PcdType
> +  )
> +{
> +  UINTN  BufLen;
> +  CHAR16 *RetString;
> +
> +  BufLen      = 0;
> +  RetString   = NULL;
> +
> +  switch (PcdType) {
> +    case EFI_PCD_TYPE_8:
> +      InternalStrnCatGrow (&RetString, &BufLen, L"UINT8");
> +      break;
> +    case EFI_PCD_TYPE_16:
> +      InternalStrnCatGrow (&RetString, &BufLen, L"UINT16");
> +      break;
> +    case EFI_PCD_TYPE_32:
> +      InternalStrnCatGrow (&RetString, &BufLen, L"UINT32");
> +      break;
> +    case EFI_PCD_TYPE_64:
> +      InternalStrnCatGrow (&RetString, &BufLen, L"UINT64");
> +      break;
> +    case EFI_PCD_TYPE_BOOL:
> +      InternalStrnCatGrow (&RetString, &BufLen, L"BOOLEAN");
> +      break;
> +    case EFI_PCD_TYPE_PTR:
> +      InternalStrnCatGrow (&RetString, &BufLen, L"POINTER");
> +      break;
> +    default:
> +      InternalStrnCatGrow (&RetString, &BufLen, L"UNKNOWN");
> +      break;
> +  }
> +
> +  if (TokenSpace == NULL) {
> +    InternalStrnCatGrow (&RetString, &BufLen, L":DYNAMIC");
> +  } else {
> +    InternalStrnCatGrow (&RetString, &BufLen, L":DYNAMICEX");
> +  }
> +
> +  return RetString;
> +}
> +
> +/**
> +  Dump PCD info.
> +
> +  @param[in]    TokenSpace      PCD Token Space.
> +  @param[in]    TokenNumber     PCD Token Number.
> +  @param[in]    PcdInfo         Pointer to PCD info.
> +**/
> +static
> +VOID
> +DumpPcdInfo (
> +  IN CONST EFI_GUID     *TokenSpace,
> +  IN UINTN              TokenNumber,
> +  IN EFI_PCD_INFO       *PcdInfo
> +  )
> +{
> +  CHAR16                *RetString;
> +  UINT8                 Uint8;
> +  UINT16                Uint16;
> +  UINT32                Uint32;
> +  UINT64                Uint64;
> +  BOOLEAN               Boolean;
> +  VOID                  *PcdData;
> +
> +  RetString = NULL;
> +
> +  if (PcdInfo->PcdName != NULL) {
> +    Print (L"%a\n", PcdInfo->PcdName);
> +  } else {
> +    if (TokenSpace == NULL) {
> +      Print (L"Default Token Space\n");
> +    } else {
> +      Print (L"%g\n", TokenSpace);
> +    }
> +  }
> +
> +  RetString = GetPcdTypeString (TokenSpace, PcdInfo->PcdType);
> +
> +  switch (PcdInfo->PcdType) {
> +    case EFI_PCD_TYPE_8:
> +      if (TokenSpace == NULL) {
> +        Uint8 = mPcd->Get8 (TokenNumber);
> +      } else {
> +        Uint8 = mPiPcd->Get8 (TokenSpace, TokenNumber);
> +      }
> +      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value =
> 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint8);
> +      break;
> +    case EFI_PCD_TYPE_16:
> +      if (TokenSpace == NULL) {
> +        Uint16 = mPcd->Get16 (TokenNumber);
> +      } else {
> +        Uint16 = mPiPcd->Get16 (TokenSpace, TokenNumber);
> +      }
> +      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value =
> 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint16);
> +      break;
> +    case EFI_PCD_TYPE_32:
> +      if (TokenSpace == NULL) {
> +        Uint32 = mPcd->Get32 (TokenNumber);
> +      } else {
> +        Uint32 = mPiPcd->Get32 (TokenSpace, TokenNumber);
> +      }
> +      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value =
> 0x%x\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint32);
> +      break;
> +    case EFI_PCD_TYPE_64:
> +      if (TokenSpace == NULL) {
> +        Uint64 = mPcd->Get64 (TokenNumber);
> +      } else {
> +        Uint64 = mPiPcd->Get64 (TokenSpace, TokenNumber);
> +      }
> +      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value =
> 0x%lx\n", TokenNumber, RetString, PcdInfo->PcdSize, Uint64);
> +      break;
> +    case EFI_PCD_TYPE_BOOL:
> +      if (TokenSpace == NULL) {
> +        Boolean = mPcd->GetBool (TokenNumber);
> +      } else {
> +        Boolean = mPiPcd->GetBool (TokenSpace, TokenNumber);
> +      }
> +      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x - Value
> = %a\n", TokenNumber, RetString, PcdInfo->PcdSize, Boolean ? "TRUE" :
> "FALSE");
> +      break;
> +    case EFI_PCD_TYPE_PTR:
> +      if (TokenSpace == NULL) {
> +        PcdData = mPcd->GetPtr (TokenNumber);
> +      } else {
> +        PcdData = mPiPcd->GetPtr (TokenSpace, TokenNumber);
> +      }
> +      Print (L"  Token = 0x%08x - Type = %H%-17s%N - Size = 0x%x\n",
> TokenNumber, RetString, PcdInfo->PcdSize);
> +      DumpHex (2, 0, PcdInfo->PcdSize, PcdData);
> +      break;
> +    default:
> +      return;
> +  }
> +
> +  if (RetString != NULL) {
> +    FreePool (RetString);
> +  }
> +  Print (L"\n");
> +}
> +
> +/**
> +  Show one or all PCDs' info.
> +
> +  @param[in]  InputPcdName       Pointer to PCD name to show. If NULL, show
> all PCDs' info.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough resources were available to
> run the command.
> +  @retval EFI_ABORTED            Aborted by user.
> +  @retval EFI_NOT_FOUND          The specified PCD is not found.
> +**/
> +static
> +EFI_STATUS
> +ProcessPcd (
> +  IN CHAR16     *InputPcdName
> +  )
> +{
> +  EFI_STATUS            Status;
> +  EFI_GUID              *TokenSpace;
> +  UINTN                 TokenNumber;
> +  EFI_PCD_INFO          PcdInfo;
> +  BOOLEAN               Found;
> +  UINTN                 PcdNameSize;
> +
> +  PcdInfo.PcdName = NULL;
> +  PcdInfo.PcdSize = 0;
> +  PcdInfo.PcdType = 0xFF;
> +  Found = FALSE;
> +
> +  Print (L"Current system SKU ID: 0x%x\n\n", mPiPcdInfo->GetSku ());
> +
> +  TokenSpace = NULL;
> +  do {
> +    TokenNumber = 0;
> +    do {
> +      Status = mPiPcd->GetNextToken (TokenSpace, &TokenNumber);
> +      if (!EFI_ERROR (Status) && TokenNumber != 0) {
> +        if (TokenSpace == NULL) {
> +          //
> +          // PCD in default Token Space.
> +          //
> +          mPcdInfo->GetInfo (TokenNumber, &PcdInfo);
> +        } else {
> +          mPiPcdInfo->GetInfo (TokenSpace, TokenNumber, &PcdInfo);
> +        }
> +        if (InputPcdName != NULL) {
> +          if (PcdInfo.PcdName == NULL) {
> +            continue;
> +          }
> +          PcdNameSize = AsciiStrSize (PcdInfo.PcdName) * sizeof (CHAR16);
> +          if (mTempPcdNameBuffer == NULL) {
> +            mTempPcdNameBufferSize = PcdNameSize;
> +            mTempPcdNameBuffer = AllocatePool (mTempPcdNameBufferSize);
> +          } else if (mTempPcdNameBufferSize < PcdNameSize) {
> +            mTempPcdNameBuffer = ReallocatePool (mTempPcdNameBufferSize,
> PcdNameSize, mTempPcdNameBuffer);
> +            mTempPcdNameBufferSize = PcdNameSize;
> +          }
> +          if (mTempPcdNameBuffer == NULL) {
> +            return EFI_OUT_OF_RESOURCES;
> +          }
> +          AsciiStrToUnicodeStrS (PcdInfo.PcdName, mTempPcdNameBuffer,
> mTempPcdNameBufferSize / sizeof (CHAR16));
> +          //
> +          // Compare the input PCD name with the PCD name in PCD database.
> +          //
> +          if ((StrStr (mTempPcdNameBuffer, InputPcdName) != NULL) ||
> +              (mUnicodeCollation != NULL && mUnicodeCollation->MetaiMatch
> (mUnicodeCollation, mTempPcdNameBuffer, InputPcdName))) {
> +            //
> +            // Found matched PCD.
> +            //
> +            DumpPcdInfo (TokenSpace, TokenNumber, &PcdInfo);
> +            Found = TRUE;
> +          }
> +        } else {
> +          DumpPcdInfo (TokenSpace, TokenNumber, &PcdInfo);
> +        }
> +      }
> +    } while (!EFI_ERROR (Status) && TokenNumber != 0);
> +
> +    Status = mPiPcd->GetNextTokenSpace ((CONST EFI_GUID **) &TokenSpace);
> +  } while (!EFI_ERROR (Status) && TokenSpace != NULL);
> +
> +  if ((InputPcdName != NULL) && !Found) {
> +    //
> +    // The specified PCD is not found, print error.
> +    //
> +    Print (L"%EError. %NNo matching PCD found: %s.\n", InputPcdName);
> +    return EFI_NOT_FOUND;
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Main entrypoint for DumpDynPcd shell application.
> +
> +  @param[in]  ImageHandle     The image handle.
> +  @param[in]  SystemTable     The system table.
> +
> +  @retval EFI_SUCCESS            Command completed successfully.
> +  @retval EFI_INVALID_PARAMETER  Command usage error.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough resources were available to
> run the command.
> +  @retval EFI_ABORTED            Aborted by user.
> +  @retval EFI_NOT_FOUND          The specified PCD is not found.
> +  @retval Others                 Error status returned from gBS->LocateProtocol.
> +**/
> +EFI_STATUS
> +EFIAPI
> +DumpDynPcdMain (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS    Status;
> +  CHAR16        *InputPcdName;
> +
> +  InputPcdName  = NULL;
> +
> +  Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL,
> (VOID **) &mUnicodeCollation);
> +  if (EFI_ERROR (Status)) {
> +    mUnicodeCollation = NULL;
> +  }
> +
> +  Status = gBS->LocateProtocol (&gEfiPcdProtocolGuid, NULL, (VOID **)
> &mPiPcd);
> +  if (EFI_ERROR (Status)) {
> +    Print (L"DumpDynPcd: %EError. %NPI PCD protocol is not present.\n");
> +    return Status;
> +  }
> +
> +  Status = gBS->LocateProtocol (&gEfiGetPcdInfoProtocolGuid, NULL, (VOID **)
> &mPiPcdInfo);
> +  if (EFI_ERROR (Status)) {
> +    Print (L"DumpDynPcd: %EError. %NPI PCD info protocol is not present.\n");
> +    return Status;
> +  }
> +
> +  Status = gBS->LocateProtocol (&gPcdProtocolGuid, NULL, (VOID **) &mPcd);
> +  if (EFI_ERROR (Status)) {
> +    Print (L"DumpDynPcd: %EError. %NPCD protocol is not present.\n");
> +    return Status;
> +  }
> +
> +  Status = gBS->LocateProtocol (&gGetPcdInfoProtocolGuid, NULL, (VOID **)
> &mPcdInfo);
> +  if (EFI_ERROR (Status)) {
> +    Print (L"DumpDynPcd: %EError. %NPCD info protocol is not present.\n");
> +    return Status;
> +  }
> +
> +  //
> +  // get the command line arguments
> +  //
> +  Status = GetArg();
> +  if (EFI_ERROR(Status)){
> +    Print (L"DumpDynPcd: %EError. %NThe input parameters are not
> recognized.\n");
> +    Status = EFI_INVALID_PARAMETER;
> +    return Status;
> +  }
> +
> +  if (Argc > 2){
> +    Print (L"DumpDynPcd: %EError. %NToo many arguments specified.\n");
> +    Status = EFI_INVALID_PARAMETER;
> +    return Status;
> +  }
> +
> +  if (Argc == 1){
> +    Status = ProcessPcd (InputPcdName);
> +    goto Done;
> +  }
> +
> +  if ((StrCmp(Argv[1], L"-?") == 0)||(StrCmp(Argv[1], L"-h") ==
> 0)||(StrCmp(Argv[1], L"-H") == 0)){
> +    ShowHelp ();
> +    goto Done;
> +  } else {
> +    if ((StrCmp(Argv[1], L"-v") == 0)||(StrCmp(Argv[1], L"-V") == 0)){
> +      ShowVersion ();
> +      goto Done;
> +    } else {
> +      if (StrStr(Argv[1], L"-") != NULL){
> +        Print (L"DumpDynPcd: %EError. %NThe argument '%B%s%N' is invalid.\n",
> Argv[1]);
> +        goto Done;
> +      }
> +    }
> +  }
> +
> +  InputPcdName = Argv[1];
> +  Status = ProcessPcd (InputPcdName);
> +
> +  Done:
> +
> +  if (mTempPcdNameBuffer != NULL) {
> +    FreePool (mTempPcdNameBuffer);
> +  }
> +
> +  return Status;
> +}
> +
> diff --git a/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
> b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
> new file mode 100644
> index 0000000000..a3542dd367
> --- /dev/null
> +++ b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
> @@ -0,0 +1,50 @@
> +##  @file
> +#  DumpDynPcd is a shell application to dump dynamic pcd information.
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = DumpDynPcd
> +  FILE_GUID                      = 31ADA2B2-62EA-4866-9B87-03FEA8425974
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = DumpDynPcdMain
> +
> +#
> +# This flag specifies whether HII resource section is generated into PE image.
> +#
> +  UEFI_HII_RESOURCE_SECTION      = TRUE
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC
> +#
> +
> +[Sources]
> +  DumpDynPcd.c
> +  DumpDynPcdStr.uni
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  UefiApplicationEntryPoint
> +  DebugLib
> +  MemoryAllocationLib
> +  UefiLib
> +  UefiBootServicesTableLib
> +
> +[Protocols]
> +  gEfiUnicodeCollation2ProtocolGuid     ## SOMETIMES_CONSUMES
> +  gEfiPcdProtocolGuid                   ## CONSUMES
> +  gPcdProtocolGuid                      ## CONSUMES
> +  gEfiGetPcdInfoProtocolGuid            ## CONSUMES
> +  gGetPcdInfoProtocolGuid               ## CONSUMES
> +  gEfiShellParametersProtocolGuid       ## CONSUMES
> +
> diff --git a/MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni
> b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni
> new file mode 100644
> index 0000000000..f0ee98219b
> --- /dev/null
> +++ b/MdeModulePkg/Application/DumpDynPcd/DumpDynPcdStr.uni
> @@ -0,0 +1,28 @@
> +//
> +// DumpDynPcd is a shell application to dump dynamic pcd information.
> +//
> +// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +//**/
> +
> +/=#
> +
> +#langdef en-US "English"
> +
> +#string STR_DUMP_DYN_PCD_HELP_INFORMATION       #language en-US ""
> +                                                                ".TH DumpDynPcd 0 "Dump
> dynamic[ex] PCD info."\r\n"
> +                                                                ".SH NAME\r\n"
> +                                                                "Dump dynamic[ex] PCD info.\r\n"
> +                                                                ".SH SYNOPSIS\r\n"
> +                                                                " \r\n"
> +                                                                "DumpDynPcd [PcdName].\r\n"
> +                                                                ".SH OPTIONS\r\n"
> +                                                                " \r\n"
> +                                                                "  PcdName    Specifies the name of
> PCD.\r\n"
> +                                                                "             A literal[or partial] name or a
> pattern as specified in\r\n"
> +                                                                "             the MetaiMatch() function of
> the EFI_UNICODE_COLLATION2_PROCOOL.\r\n"
> +                                                                "             If it is absent, dump all PCDs'
> info.\r\n"
> +                                                                "The PCD data is printed as
> hexadecimal dump.\n"
> +                                                                "\r\n"
> +
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc
> index b302f4a4f3..a8b9d8d027 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -206,6 +206,7 @@
> 
>  [Components]
>    MdeModulePkg/Application/HelloWorld/HelloWorld.inf
> +  MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
>    MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
> 
>    MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
> --
> 2.18.0.windows.1
> 
> 
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#40108): https://edk2.groups.io/g/devel/message/40108
Mute This Topic: https://groups.io/mt/31529240/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-

Re: [edk2-devel] [PATCH v3] MdeModulePkg/DumpDynPcd: Add application to dump dynamic PCD settings
Posted by Wu, Hao A 4 years, 11 months ago
Patch has been pushed via commit:
a642e2b42e

Best Regards,
Hao Wu


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


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#40181): https://edk2.groups.io/g/devel/message/40181
Mute This Topic: https://groups.io/mt/31529240/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-