[edk2-devel] [PATCH v1 2/3] ShellPkg: Add varpolicy dynamic shell command

Michael Kubacki mikuback at linux.microsoft.com
Tue Sep 19 14:32:59 UTC 2023


From: Michael Kubacki <michael.kubacki at microsoft.com>

Adds a new module (dynamic shell command) to ShellPkg that lists
variable policy information for all UEFI variables on the system.

Some other UEFI variable related functionality is also included to
give a greater sense of platform UEFI variable state. This command
is intended to help make variable policies more transparent and
easier to understand and configure on a platform.

Like all dynamic shell commands, a platform only needs to include
`VariablePolicyDynamicCommand.inf` in their flash image to have
the command registered in their UEFI shell.

Include the following lines in platform DSC (in DXE components section):

```
  ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf {
    <PcdsFixedAtBuild>
      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
  }
```

Include the following line in platform FDF:

```
INF  ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf
```

Cc: Zhichao Gao <zhichao.gao at intel.com>
Cc: Michael D Kinney <michael.d.kinney at intel.com>
Signed-off-by: Michael Kubacki <michael.kubacki at microsoft.com>
---
 ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.c   | 1009 ++++++++++++++++++++
 ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.h   |   94 ++
 ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf |   56 ++
 ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.uni |   86 ++
 ShellPkg/ShellPkg.dsc                                                                 |    1 +
 5 files changed, 1246 insertions(+)

diff --git a/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.c b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.c
new file mode 100644
index 000000000000..49993f635396
--- /dev/null
+++ b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.c
@@ -0,0 +1,1009 @@
+/** @file
+  Main file for the "varpolicy" dynamic UEFI shell command.
+
+  This command can provide detailed UEFI variable policy configuration
+  information in the UEFI shell.
+
+  Copyright (c) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VariablePolicyDynamicCommand.h"
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+
+#include <Protocol/HiiPackageList.h>
+#include <Protocol/ShellDynamicCommand.h>
+#include <Protocol/VariablePolicy.h>
+
+#define VAR_POLICY_FLAG_STATS_STR    L"-s"
+#define VAR_POLICY_FLAG_POLICY_STR   L"-p"
+#define VAR_POLICY_FLAG_VERBOSE_STR  L"-v"
+
+#define VAR_POLICY_CMD_MIN_ATTR_STR_LEN  64
+
+EFI_HII_HANDLE  mVarPolicyShellCommandHiiHandle = NULL;
+
+STATIC CONST SHELL_PARAM_ITEM  ParamList[] = {
+  { VAR_POLICY_FLAG_POLICY_STR,  TypeFlag },
+  { VAR_POLICY_FLAG_STATS_STR,   TypeFlag },
+  { VAR_POLICY_FLAG_VERBOSE_STR, TypeFlag },
+  { NULL,                        TypeMax  }
+};
+
+STATIC CONST VAR_POLICY_CMD_VAR_NAMESPACE  mVarNamespaces[] = {
+  {
+    VariableVendorCapsule,
+    &gEfiCapsuleVendorGuid,
+    L"Capsule"
+  },
+  {
+    VariableVendorCapsuleReport,
+    &gEfiCapsuleReportGuid,
+    L"Capsule Reporting"
+  },
+  {
+    VariableVendorGlobal,
+    &gEfiGlobalVariableGuid,
+    L"UEFI Global"
+  },
+  {
+    VariableVendorMorControl,
+    &gEfiMemoryOverwriteRequestControlLockGuid,
+    L"Memory Overwrite Request (MOR) Control Lock"
+  }
+};
+
+/**
+  Returns UEFI variable attribute information in a string.
+
+  AttributesStrSize must at least be VAR_POLICY_CMD_MIN_ATTR_STR_LEN in length
+  or EFI_INVALID_PARAMETER will be returned.
+
+  @param[in]  Attributes             The UEFI variable attributes.
+  @param[in]  AttributesStrSize      The size, in bytes, of AttributesStr.
+  @param[out] AttributesStr          The Unicode string for the given attributes.
+
+  @retval EFI_SUCCESS           The attributes were converted to a string successfully.
+  @retval EFI_INVALID_PARAMETER The AttributesStr pointer is NULL.
+
+**/
+EFI_STATUS
+GetAttributesString (
+  IN  UINT32  Attributes,
+  IN  UINTN   AttributesStrSize,
+  OUT CHAR16  *AttributesStr
+  )
+{
+  if ((AttributesStr == NULL) || (AttributesStrSize < VAR_POLICY_CMD_MIN_ATTR_STR_LEN)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AttributesStr[0] = L'0';
+  AttributesStr[1] = L'x';
+  AttributesStr[2] = L'\0';
+
+  UnicodeValueToStringS (AttributesStr + 2, AttributesStrSize - 2, (RADIX_HEX), (INT64)Attributes, 30);
+
+  if (Attributes == 0) {
+    StrCatS (AttributesStr, AttributesStrSize, L" No Attributes");
+  } else {
+    if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE) {
+      StrCatS (AttributesStr, AttributesStrSize, L" NV");
+      Attributes ^= EFI_VARIABLE_NON_VOLATILE;
+    }
+
+    if ((Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) == EFI_VARIABLE_BOOTSERVICE_ACCESS) {
+      StrCatS (AttributesStr, AttributesStrSize, L" BS");
+      Attributes ^= EFI_VARIABLE_BOOTSERVICE_ACCESS;
+    }
+
+    if ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == EFI_VARIABLE_RUNTIME_ACCESS) {
+      StrCatS (AttributesStr, AttributesStrSize, L" RT");
+      Attributes ^= EFI_VARIABLE_RUNTIME_ACCESS;
+    }
+
+    if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
+      StrCatS (AttributesStr, AttributesStrSize, L" HW-Error");
+      Attributes ^= EFI_VARIABLE_HARDWARE_ERROR_RECORD;
+    }
+
+    if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) {
+      StrCatS (AttributesStr, AttributesStrSize, L" Auth-WA");
+      Attributes ^= EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
+    }
+
+    if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
+      StrCatS (AttributesStr, AttributesStrSize, L" Auth-TIME-WA");
+      Attributes ^= EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+    }
+
+    if ((Attributes & EFI_VARIABLE_APPEND_WRITE) == EFI_VARIABLE_APPEND_WRITE) {
+      StrCatS (AttributesStr, AttributesStrSize, L" APPEND-W");
+      Attributes ^= EFI_VARIABLE_APPEND_WRITE;
+    }
+
+    if (Attributes != 0) {
+      StrCatS (AttributesStr, AttributesStrSize, L" <Unknown Attribute>");
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Prints UEFI variable statistics information.
+
+  @param[in] TotalVariables             Total number of UEFI variables discovered.
+  @param[in] TotalVariablesSize         Total size of UEFI variables discovered.
+
+**/
+VOID
+PrintStats (
+  IN  UINTN  TotalVariables,
+  IN  UINTN  TotalVariablesSize
+  )
+{
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_STATS_HEADER_1), mVarPolicyShellCommandHiiHandle);
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_STATS_HEADER_2), mVarPolicyShellCommandHiiHandle);
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_STATS_HEADER_1), mVarPolicyShellCommandHiiHandle);
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_STATS_TOTAL_VARS), mVarPolicyShellCommandHiiHandle, TotalVariables);
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_STATS_TOTAL_SIZE), mVarPolicyShellCommandHiiHandle, TotalVariablesSize, TotalVariablesSize);
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_STATS_HEADER_1), mVarPolicyShellCommandHiiHandle);
+}
+
+/**
+  Returns information for the given variable namespace if available.
+
+  @param[in]  VariableGuid      The UEFI variable vendor (namespace) GUID.
+
+  @return     Pointer to a namespace info structure on a GUID match.
+  @return     NULL on lack of a GUID match.
+
+**/
+CONST VAR_POLICY_CMD_VAR_NAMESPACE *
+GetNameSpaceInfo (
+  IN  EFI_GUID  *VariableGuid
+  )
+{
+  UINTN  Index;
+
+  if (VariableGuid == NULL) {
+    ASSERT (VariableGuid != NULL);
+    return NULL;
+  }
+
+  for (Index = 0; Index < ARRAY_SIZE (mVarNamespaces); Index++) {
+    if (CompareGuid (mVarNamespaces[Index].VendorGuid, VariableGuid)) {
+      return &mVarNamespaces[Index];
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Print non-verbose information about the variable.
+
+  @param[in]    VariableName          A pointer the Unicode variable name.
+  @param[in]    VariableGuid          A pointer to the variable vendor GUID.
+  @param[in]    VariableSize          The size of the UEFI variable in bytes.
+  @param[in]    VariableAttributes    The UEFI variable attributes.
+
+  @retval   EFI_SUCCESS               The non-verbose variable information was printed successfully.
+  @retval   EFI_INVALID_PARAMETER     A pointer argument passed to the function was NULL.
+  @retval   EFI_OUT_OF_RESOURCES      Insufficient memory resources to print the attributes.
+
+**/
+EFI_STATUS
+PrintNonVerboseVarInfo (
+  IN CHAR16    *VariableName,
+  IN EFI_GUID  *VariableGuid,
+  IN UINTN     VariableSize,
+  IN UINT32    VariableAttributes
+  )
+{
+  EFI_STATUS                          Status;
+  CHAR16                              *AttributesStr;
+  CHAR16                              *DescriptionStr;
+  CONST VAR_POLICY_CMD_VAR_NAMESPACE  *CmdVarNamespace;
+
+  AttributesStr  = NULL;
+  DescriptionStr = NULL;
+
+  if ((VariableName == NULL) || (VariableGuid == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CmdVarNamespace = GetNameSpaceInfo (VariableGuid);
+
+  if (CmdVarNamespace == NULL) {
+    DescriptionStr = AllocatePages (1);
+    if (DescriptionStr == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto Exit;
+    }
+
+    ZeroMem ((VOID *)DescriptionStr, EFI_PAGES_TO_SIZE (1));
+    UnicodeSPrint (DescriptionStr, EFI_PAGES_TO_SIZE (1), L"Unknown Vendor (%g)", VariableGuid);
+  } else {
+    DescriptionStr = CmdVarNamespace->Description;
+  }
+
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_VAR_TYPE), mVarPolicyShellCommandHiiHandle, DescriptionStr);
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_VAR_NAME), mVarPolicyShellCommandHiiHandle, VariableName);
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_VAR_SIZE), mVarPolicyShellCommandHiiHandle, VariableSize, VariableSize);
+
+  AttributesStr = AllocatePages (1);
+  if (AttributesStr == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  ZeroMem ((VOID *)AttributesStr, EFI_PAGES_TO_SIZE (1));
+  Status = GetAttributesString (VariableAttributes, EFI_PAGES_TO_SIZE (1), AttributesStr);
+  if (Status == EFI_SUCCESS) {
+    ShellPrintHiiEx (
+      -1,
+      -1,
+      NULL,
+      STRING_TOKEN (STR_VAR_POL_VAR_ATTR),
+      mVarPolicyShellCommandHiiHandle,
+      AttributesStr
+      );
+  }
+
+  Status = EFI_SUCCESS;
+
+Exit:
+  if (AttributesStr != NULL) {
+    FreePages (AttributesStr, 1);
+  }
+
+  if ((CmdVarNamespace == NULL) && (DescriptionStr != NULL)) {
+    FreePages (DescriptionStr, 1);
+  }
+
+  return Status;
+}
+
+/**
+  Print verbose information about the variable.
+
+  @param[in]    Data                  A pointer to the variable data buffer.
+  @param[in]    DataSize              The size of data, in bytes, in the variable data buffer.
+
+  @retval   EFI_SUCCESS               The verbose variable information was printed successfully.
+  @retval   EFI_INVALID_PARAMETER     A pointer argument passed to the function was NULL.
+
+**/
+EFI_STATUS
+PrintVerboseVarInfo (
+  IN  VOID   *Data,
+  IN  UINTN  DataSize
+  )
+{
+  if ((DataSize == 0) || (Data == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  VAR_POLICY_CMD_SHELL_DUMP_HEX (0, Data, DataSize);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Prints variable policy information for the given variable.
+
+  @param[in]  VariableName    A pointer to the Unicode string of the UEFI variable name.
+  @param[in]  VendorGuid      A pointer to the UEFI variable vendor GUID.
+
+  @return TRUE if a variable policy was found and printed for the variable.
+  @return FALSE if an error occurred and/or a variable policy was not found and
+          printed for the variable.
+
+**/
+BOOLEAN
+PrintVariablePolicyInfo (
+  IN  CHAR16    *VariableName,
+  IN  EFI_GUID  *VendorGuid
+  )
+{
+  EFI_STATUS                         Status;
+  VARIABLE_POLICY_ENTRY              VariablePolicyEntry;
+  VARIABLE_LOCK_ON_VAR_STATE_POLICY  LockOnVarStatePolicy;
+  UINTN                              VariablePolicyVariableNameBufferSize;
+  UINTN                              ReturnedVariableNameSize;
+  BOOLEAN                            PolicyHeaderPresent;
+  CHAR16                             *VariablePolicyVariableName;
+  CHAR16                             *VariableAttributesStr;
+  EDKII_VARIABLE_POLICY_PROTOCOL     *VariablePolicy;
+
+  PolicyHeaderPresent        = FALSE;
+  VariableAttributesStr      = NULL;
+  VariablePolicyVariableName = NULL;
+
+  if ((VariableName == NULL) || (VendorGuid == NULL)) {
+    ASSERT ((VariableName != NULL) && (VendorGuid != NULL));
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_INT_ERR), mVarPolicyShellCommandHiiHandle);
+    return FALSE;
+  }
+
+  Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);
+  if (EFI_ERROR (Status)) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_NO_PROT), mVarPolicyShellCommandHiiHandle);
+    return FALSE;
+  }
+
+  VariablePolicyVariableNameBufferSize = EFI_PAGES_TO_SIZE (1);
+  VariablePolicyVariableName           = AllocatePages (EFI_SIZE_TO_PAGES (VariablePolicyVariableNameBufferSize));
+  if (VariablePolicyVariableName == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    ASSERT_EFI_ERROR (Status);
+    goto Done;
+  }
+
+  ZeroMem (VariablePolicyVariableName, VariablePolicyVariableNameBufferSize);
+  ReturnedVariableNameSize = VariablePolicyVariableNameBufferSize;
+  Status                   =  VariablePolicy->GetVariablePolicyInfo (
+                                                VariableName,
+                                                VendorGuid,
+                                                &ReturnedVariableNameSize,
+                                                &VariablePolicyEntry,
+                                                VariablePolicyVariableName
+                                                );
+  if (Status == EFI_NOT_READY) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_NOT_INIT), mVarPolicyShellCommandHiiHandle);
+  } else if (Status == EFI_NOT_FOUND) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_NOT_FOUND), mVarPolicyShellCommandHiiHandle);
+  } else if (EFI_ERROR (Status)) {
+    // A different error return code is not expected
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_UNEXP_ERR), mVarPolicyShellCommandHiiHandle, Status);
+  } else {
+    PolicyHeaderPresent = TRUE;
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_HEADER_1), mVarPolicyShellCommandHiiHandle);
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_HEADER_2), mVarPolicyShellCommandHiiHandle);
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_HEADER_1), mVarPolicyShellCommandHiiHandle);
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_VERSION), mVarPolicyShellCommandHiiHandle, VariablePolicyEntry.Version);
+
+    if ((ReturnedVariableNameSize > 0) && (VariablePolicyVariableName[0] != CHAR_NULL)) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_VARIABLE), mVarPolicyShellCommandHiiHandle, VariablePolicyVariableName);
+    } else {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_VARIABLE), mVarPolicyShellCommandHiiHandle, L"<Entire Namespace>");
+    }
+
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_NAMESPACE), mVarPolicyShellCommandHiiHandle, &VariablePolicyEntry.Namespace);
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_MIN_SIZE), mVarPolicyShellCommandHiiHandle, VariablePolicyEntry.MinSize);
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_MAX_SIZE), mVarPolicyShellCommandHiiHandle, VariablePolicyEntry.MaxSize);
+
+    switch (VariablePolicyEntry.LockPolicyType) {
+      case VARIABLE_POLICY_TYPE_NO_LOCK:
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_LOCK_TYPE), mVarPolicyShellCommandHiiHandle, L"No Lock");
+        break;
+      case VARIABLE_POLICY_TYPE_LOCK_NOW:
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_LOCK_TYPE), mVarPolicyShellCommandHiiHandle, L"Lock Now");
+        break;
+      case VARIABLE_POLICY_TYPE_LOCK_ON_CREATE:
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_LOCK_TYPE), mVarPolicyShellCommandHiiHandle, L"On Create");
+        break;
+      case VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE:
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_LOCK_TYPE), mVarPolicyShellCommandHiiHandle, L"On Variable State");
+
+        ZeroMem (VariablePolicyVariableName, VariablePolicyVariableNameBufferSize);
+        ReturnedVariableNameSize = VariablePolicyVariableNameBufferSize;
+        Status                   =  VariablePolicy->GetLockOnVariableStateVariablePolicyInfo (
+                                                      VariableName,
+                                                      VendorGuid,
+                                                      &ReturnedVariableNameSize,
+                                                      &LockOnVarStatePolicy,
+                                                      VariablePolicyVariableName
+                                                      );
+        if (EFI_ERROR (Status)) {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_UNEXP_ERR), mVarPolicyShellCommandHiiHandle, Status);
+          goto Done;
+        } else {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_STATE_NS), mVarPolicyShellCommandHiiHandle, &LockOnVarStatePolicy.Namespace);
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_STATE_VAL), mVarPolicyShellCommandHiiHandle, LockOnVarStatePolicy.Value);
+          if ((ReturnedVariableNameSize > 0) && (VariablePolicyVariableName[0] != CHAR_NULL)) {
+            ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_STATE_NAME), mVarPolicyShellCommandHiiHandle, VariablePolicyVariableName);
+          } else {
+            ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_STATE_NAME), mVarPolicyShellCommandHiiHandle, L"<Entire Namespace>");
+          }
+        }
+
+        break;
+      default:
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_LOCK_TYPE), mVarPolicyShellCommandHiiHandle, L"Unknown");
+        break;
+    }
+
+    VariableAttributesStr = AllocatePages (1);
+    if (VariableAttributesStr == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      ASSERT_EFI_ERROR (Status);
+      goto Done;
+    }
+
+    ZeroMem (VariableAttributesStr, EFI_PAGES_TO_SIZE (1));
+    Status = GetAttributesString (VariablePolicyEntry.AttributesMustHave, EFI_PAGES_TO_SIZE (1), VariableAttributesStr);
+    if (Status == EFI_SUCCESS) {
+      ShellPrintHiiEx (
+        -1,
+        -1,
+        NULL,
+        STRING_TOKEN (STR_VAR_POL_POLICY_ATTR_MUST),
+        mVarPolicyShellCommandHiiHandle
+        );
+      ShellPrintHiiEx (
+        -1,
+        -1,
+        NULL,
+        STRING_TOKEN (STR_VAR_POL_POLICY_ATTR_GEN),
+        mVarPolicyShellCommandHiiHandle,
+        VariableAttributesStr
+        );
+    }
+
+    ZeroMem (VariableAttributesStr, EFI_PAGES_TO_SIZE (1));
+    Status = GetAttributesString (VariablePolicyEntry.AttributesCantHave, EFI_PAGES_TO_SIZE (1), VariableAttributesStr);
+    if (Status == EFI_SUCCESS) {
+      ShellPrintHiiEx (
+        -1,
+        -1,
+        NULL,
+        STRING_TOKEN (STR_VAR_POL_POLICY_ATTR_NOT),
+        mVarPolicyShellCommandHiiHandle
+        );
+      ShellPrintHiiEx (
+        -1,
+        -1,
+        NULL,
+        STRING_TOKEN (STR_VAR_POL_POLICY_ATTR_GEN),
+        mVarPolicyShellCommandHiiHandle,
+        VariableAttributesStr
+        );
+    }
+  }
+
+Done:
+  if (PolicyHeaderPresent) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_VAR_POL_POLICY_HEADER_1), mVarPolicyShellCommandHiiHandle);
+  }
+
+  if (VariableAttributesStr != NULL) {
+    FreePages (VariableAttributesStr, 1);
+  }
+
+  if (VariablePolicyVariableName != NULL) {
+    FreePages (VariablePolicyVariableName, 1);
+  }
+
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_LINE_BREAK), mVarPolicyShellCommandHiiHandle);
+
+  return Status == EFI_SUCCESS;
+}
+
+/**
+  Gets the next UEFI variable name.
+
+  This buffer manages the UEFI variable name buffer, performing memory reallocations as necessary.
+
+  Note: The first time this function is called, VariableNameBufferSize must be 0 and
+  the VariableName buffer pointer must point to NULL.
+
+  @param[in,out] VariableNameBufferSize   On input, a pointer to a buffer that holds the current
+                                          size of the VariableName buffer in bytes.
+                                          On output, a pointer to a buffer that holds the updated
+                                          size of the VariableName buffer in bytes.
+  @param[in,out] VariableName             On input, a pointer to a pointer to a buffer that holds the
+                                          current UEFI variable name.
+                                          On output, a pointer to a pointer to a buffer that holds the
+                                          next UEFI variable name.
+  @param[in,out] VariableGuid             On input, a pointer to a buffer that holds the current UEFI
+                                          variable GUID.
+                                          On output, a pointer to a buffer that holds the next UEFI
+                                          variable GUID.
+
+  @retval    EFI_SUCCESS              The next UEFI variable name was found successfully.
+  @retval    EFI_INVALID_PARAMETER    A pointer argument is NULL or initial input values are invalid.
+  @retval    EFI_OUT_OF_RESOURCES     Insufficient memory resources to allocate a required buffer.
+  @retval    Others                   Return status codes from the UEFI spec define GetNextVariableName() interface.
+
+**/
+EFI_STATUS
+GetNextVariableNameWithDynamicReallocation (
+  IN  OUT UINTN     *VariableNameBufferSize,
+  IN  OUT CHAR16    **VariableName,
+  IN  OUT EFI_GUID  *VariableGuid
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       NextVariableNameBufferSize;
+
+  if ((VariableNameBufferSize == NULL) || (VariableName == NULL) || (VariableGuid == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*VariableNameBufferSize == 0) {
+    if (*VariableName != NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Allocate a buffer to temporarily hold variable names. To reduce memory
+    // allocations, the default buffer size is 256 characters. The buffer can
+    // be reallocated if expansion is necessary (should be very rare).
+    //
+    *VariableNameBufferSize = sizeof (CHAR16) * 256;
+    *VariableName           = AllocateZeroPool (*VariableNameBufferSize);
+    if (*VariableName == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    ZeroMem ((VOID *)VariableGuid, sizeof (EFI_GUID));
+  }
+
+  NextVariableNameBufferSize = *VariableNameBufferSize;
+  Status                     = gRT->GetNextVariableName (
+                                      &NextVariableNameBufferSize,
+                                      *VariableName,
+                                      VariableGuid
+                                      );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    *VariableName = ReallocatePool (
+                      *VariableNameBufferSize,
+                      NextVariableNameBufferSize,
+                      *VariableName
+                      );
+    if (*VariableName == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    *VariableNameBufferSize = NextVariableNameBufferSize;
+
+    Status = gRT->GetNextVariableName (
+                    &NextVariableNameBufferSize,
+                    *VariableName,
+                    VariableGuid
+                    );
+    ASSERT (Status != EFI_BUFFER_TOO_SMALL);
+  }
+
+  return Status;
+}
+
+/**
+  Dumps UEFI variable information.
+
+  This is the main function that enumerates UEFI variables and prints the information
+  selected by the user.
+
+  @param[in] Verbose            Whether to print verbose information.
+  @param[in] Stats              Whether to print statistical information.
+  @param[in] PolicyCheck        Whether to print variable policy related information.
+
+
+  @retval    EFI_SUCCESS              The UEFI variable information was dumped successfully.
+  @retval    EFI_DEVICE_ERROR         An error occurred attempting to get UEFI variable information.
+  @retval    EFI_OUT_OF_RESOURCES     Insufficient memory resources to allocate a required buffer.
+
+**/
+EFI_STATUS
+DumpVars (
+  IN  BOOLEAN  Verbose,
+  IN  BOOLEAN  Stats,
+  IN  BOOLEAN  PolicyCheck
+  )
+{
+  EFI_STATUS  Status;
+  EFI_STATUS  GetNextVariableStatus;
+  UINT32      Attributes;
+  UINTN       CurrentVariableDataBufferSize;
+  UINTN       DataSize;
+  UINTN       TotalDataSize;
+  UINTN       TotalVariables;
+  UINTN       TotalVariablesWithPolicy;
+  UINTN       VariableNameBufferSize;
+  EFI_GUID    VariableGuid;
+  CHAR16      *VariableName;
+  VOID        *Data;
+
+  Status                        = EFI_SUCCESS;
+  Data                          = NULL;
+  VariableName                  = NULL;
+  CurrentVariableDataBufferSize = 0;
+  TotalDataSize                 = 0;
+  TotalVariables                = 0;
+  TotalVariablesWithPolicy      = 0;
+  VariableNameBufferSize        = 0;
+
+  do {
+    GetNextVariableStatus = GetNextVariableNameWithDynamicReallocation (
+                              &VariableNameBufferSize,
+                              &VariableName,
+                              &VariableGuid
+                              );
+
+    if (!EFI_ERROR (GetNextVariableStatus)) {
+      DataSize = 0;
+      Status   = gRT->GetVariable (
+                        VariableName,
+                        &VariableGuid,
+                        &Attributes,
+                        &DataSize,
+                        NULL
+                        );
+      if (Status != EFI_BUFFER_TOO_SMALL) {
+        // If the variable exists, a zero size buffer should be too small
+        Status = EFI_DEVICE_ERROR;
+        goto DeallocateAndExit;
+      }
+
+      TotalDataSize += DataSize;
+      TotalVariables++;
+
+      if (!Stats || Verbose) {
+        Status = PrintNonVerboseVarInfo (VariableName, &VariableGuid, DataSize, Attributes);
+        if (!EFI_ERROR (Status)) {
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_LINE_BREAK), mVarPolicyShellCommandHiiHandle);
+        }
+      }
+
+      if (PolicyCheck || Verbose) {
+        if (PrintVariablePolicyInfo (VariableName, &VariableGuid)) {
+          TotalVariablesWithPolicy++;
+        }
+      }
+
+      if (Verbose) {
+        if (CurrentVariableDataBufferSize < DataSize) {
+          if (Data != NULL) {
+            FreePool (Data);
+          }
+
+          Data = AllocateZeroPool (DataSize);
+          if (Data == NULL) {
+            Status = EFI_OUT_OF_RESOURCES;
+            goto DeallocateAndExit;
+          }
+
+          CurrentVariableDataBufferSize = DataSize;
+        }
+
+        Status = gRT->GetVariable (
+                        VariableName,
+                        &VariableGuid,
+                        NULL,
+                        &DataSize,
+                        Data
+                        );
+        if (EFI_ERROR (Status)) {
+          Status = EFI_DEVICE_ERROR;
+          goto DeallocateAndExit;
+        }
+
+        Status = PrintVerboseVarInfo (Data, DataSize);
+        if (EFI_ERROR (Status)) {
+          Status = EFI_DEVICE_ERROR;
+          goto DeallocateAndExit;
+        }
+      }
+    }
+  } while (!EFI_ERROR (GetNextVariableStatus));
+
+  if (TotalVariables == 0) {
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VARS), mVarPolicyShellCommandHiiHandle);
+  } else {
+    if (Verbose || Stats) {
+      PrintStats (TotalVariables, TotalDataSize);
+    }
+
+    if (Verbose || PolicyCheck) {
+      ASSERT (TotalVariablesWithPolicy <= TotalVariables);
+
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_LINE_BREAK), mVarPolicyShellCommandHiiHandle);
+      if (TotalVariablesWithPolicy == TotalVariables) {
+        ShellPrintHiiEx (
+          -1,
+          -1,
+          NULL,
+          STRING_TOKEN (STR_VAR_POL_POLICY_STATS_PASS),
+          mVarPolicyShellCommandHiiHandle,
+          TotalVariablesWithPolicy,
+          TotalVariables
+          );
+      } else {
+        ShellPrintHiiEx (
+          -1,
+          -1,
+          NULL,
+          STRING_TOKEN (STR_VAR_POL_POLICY_STATS_FAIL),
+          mVarPolicyShellCommandHiiHandle,
+          TotalVariablesWithPolicy,
+          TotalVariables
+          );
+      }
+
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_LINE_BREAK), mVarPolicyShellCommandHiiHandle);
+    }
+  }
+
+  Status = EFI_SUCCESS;
+
+DeallocateAndExit:
+  if (VariableName != NULL) {
+    FreePool (VariableName);
+  }
+
+  if (Data != NULL) {
+    FreePool (Data);
+  }
+
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Main entry function for the "varpolicy" command.
+
+  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
+  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
+
+  @retval   SHELL_SUCCESS               The "varpolicy" shell command executed successfully.
+  @retval   SHELL_INVALID_PARAMETER     An argument passed to the shell command is invalid.
+  @retval   Others                      A different error occurred.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunVarPolicy (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+  SHELL_STATUS  ShellStatus;
+  BOOLEAN       PolicyCheck;
+  BOOLEAN       StatsDump;
+  BOOLEAN       VerboseDump;
+  LIST_ENTRY    *Package;
+  CHAR16        *ProblemParam;
+
+  Package     = NULL;
+  ShellStatus = SHELL_INVALID_PARAMETER;
+  Status      = EFI_SUCCESS;
+  PolicyCheck = FALSE;
+  StatsDump   = FALSE;
+  VerboseDump = FALSE;
+
+  Status = ShellInitialize ();
+  ASSERT_EFI_ERROR (Status);
+
+  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+  if (EFI_ERROR (Status)) {
+    if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mVarPolicyShellCommandHiiHandle, VAR_POLICY_COMMAND_NAME, ProblemParam);
+      FreePool (ProblemParam);
+      ShellStatus = SHELL_INVALID_PARAMETER;
+      goto Done;
+    } else {
+      ASSERT (FALSE);
+    }
+  } else {
+    if (ShellCommandLineGetCount (Package) > 1) {
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), mVarPolicyShellCommandHiiHandle, VAR_POLICY_COMMAND_NAME);
+      ShellStatus = SHELL_INVALID_PARAMETER;
+      goto Done;
+    }
+
+    PolicyCheck = ShellCommandLineGetFlag (Package, VAR_POLICY_FLAG_POLICY_STR);
+    StatsDump   = ShellCommandLineGetFlag (Package, VAR_POLICY_FLAG_STATS_STR);
+    VerboseDump = ShellCommandLineGetFlag (Package, VAR_POLICY_FLAG_VERBOSE_STR);
+
+    Status = DumpVars (VerboseDump, StatsDump, PolicyCheck);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+Done:
+  if (Package != NULL) {
+    ShellCommandLineFreeVarList (Package);
+  }
+
+  return ShellStatus;
+}
+
+/**
+  This is the shell command handler function pointer callback type.
+
+  This function handles the command when it is invoked in the shell.
+
+  @param[in] This                   The instance of the
+                                    EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+  @param[in] SystemTable            The pointer to the system table.
+  @param[in] ShellParameters        The parameters associated with the command.
+  @param[in] Shell                  The instance of the shell protocol used in
+                                    the context of processing this command.
+
+  @return EFI_SUCCESS               the operation was successful
+  @return other                     the operation failed.
+
+**/
+SHELL_STATUS
+EFIAPI
+VarPolicyCommandHandler (
+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,
+  IN EFI_SYSTEM_TABLE                    *SystemTable,
+  IN EFI_SHELL_PARAMETERS_PROTOCOL       *ShellParameters,
+  IN EFI_SHELL_PROTOCOL                  *Shell
+  )
+{
+  gEfiShellParametersProtocol = ShellParameters;
+  gEfiShellProtocol           = Shell;
+
+  return ShellCommandRunVarPolicy (gImageHandle, SystemTable);
+}
+
+/**
+  This is the command help handler function pointer callback type.  This
+  function is responsible for displaying help information for the associated
+  command.
+
+  @param[in] This                   The instance of the
+                                    EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+  @param[in] Language               The pointer to the language string to use.
+
+  @return string                    Pool allocated help string, must be freed
+                                    by caller.
+
+**/
+STATIC
+CHAR16 *
+EFIAPI
+VarPolicyCommandGetHelp (
+  IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  *This,
+  IN CONST CHAR8                         *Language
+  )
+{
+  return HiiGetString (
+           mVarPolicyShellCommandHiiHandle,
+           STRING_TOKEN (STR_GET_HELP_VAR_POLICY),
+           Language
+           );
+}
+
+STATIC EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL  mVarPolicyDynamicCommand = {
+  VAR_POLICY_COMMAND_NAME,
+  VarPolicyCommandHandler,
+  VarPolicyCommandGetHelp
+};
+
+/**
+  Retrieve HII package list from ImageHandle and publish to HII database.
+
+  @param[in] ImageHandle    The image handle of the process.
+
+  @return HII handle.
+
+**/
+STATIC
+EFI_HII_HANDLE
+InitializeHiiPackage (
+  IN  EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;
+  EFI_HII_HANDLE               HiiHandle;
+
+  //
+  // Retrieve HII package list from ImageHandle
+  //
+  Status = gBS->OpenProtocol (
+                  ImageHandle,
+                  &gEfiHiiPackageListProtocolGuid,
+                  (VOID **)&PackageList,
+                  ImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  //
+  // Publish HII package list to HII Database.
+  //
+  Status = gHiiDatabase->NewPackageList (
+                           gHiiDatabase,
+                           PackageList,
+                           NULL,
+                           &HiiHandle
+                           );
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  return HiiHandle;
+}
+
+/**
+  Entry point of the UEFI variable policy dynamic shell command.
+
+  Produce the Dynamic Command Protocol to handle the "varpolicy" command.
+
+  @param[in] ImageHandle        The image handle of the process.
+  @param[in] SystemTable        The EFI System Table pointer.
+
+  @retval EFI_SUCCESS           The "varpolicy" command executed successfully.
+  @retval EFI_ABORTED           HII package failed to initialize.
+  @retval others                Other errors when executing "varpolicy" command.
+
+**/
+EFI_STATUS
+EFIAPI
+VariablePolicyDynamicCommandEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  mVarPolicyShellCommandHiiHandle = InitializeHiiPackage (ImageHandle);
+  if (mVarPolicyShellCommandHiiHandle == NULL) {
+    return EFI_ABORTED;
+  }
+
+  Status = gBS->InstallProtocolInterface (
+                  &ImageHandle,
+                  &gEfiShellDynamicCommandProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mVarPolicyDynamicCommand
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Unload the dynamic "varpolicy" UEFI Shell command.
+
+  @param[in] ImageHandle        The image handle of the process.
+
+  @retval EFI_SUCCESS           The image is unloaded.
+  @retval Others                Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+VariablePolicyDynamicCommandUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->UninstallProtocolInterface (
+                  ImageHandle,
+                  &gEfiShellDynamicCommandProtocolGuid,
+                  &mVarPolicyDynamicCommand
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  HiiRemovePackages (mVarPolicyShellCommandHiiHandle);
+
+  return EFI_SUCCESS;
+}
diff --git a/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.h b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.h
new file mode 100644
index 000000000000..7ce5beca389a
--- /dev/null
+++ b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.h
@@ -0,0 +1,94 @@
+/** @file
+  Internal header file for the module.
+
+  Copyright (c) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef VAR_POLICY_DYNAMIC_SHELL_COMMAND_H_
+#define VAR_POLICY_DYNAMIC_SHELL_COMMAND_H_
+
+#include <Uefi.h>
+
+#define VAR_POLICY_COMMAND_NAME  L"varpolicy"
+
+typedef enum {
+  VariableVendorCapsule,
+  VariableVendorCapsuleReport,
+  VariableVendorGlobal,
+  VariableVendorMorControl,
+  VariableVendorGuidMax
+} VAR_POLICY_CMD_VENDOR_GUID_TYPE;
+
+typedef struct {
+  VAR_POLICY_CMD_VENDOR_GUID_TYPE    VendorGuidType;
+  EFI_GUID                           *VendorGuid;
+  CHAR16                             *Description;
+} VAR_POLICY_CMD_VAR_NAMESPACE;
+
+/**
+  Log a formatted console message.
+
+  This is not specific to this shell command but scoped so to prevent global
+  name conflicts.
+
+  The hex dump is split into lines of 16 dumped bytes.
+
+  The full hex dump is bracketed, and its byte ascii char also print.
+  If the byte value is not an ascii code, it will print as '.'
+
+  @param[in] Offset            Offset to be display after PrefixFormat.
+                               Offset will be increased for each print line.
+  @param[in] Data              The data to dump.
+  @param[in] DataSize          Number of bytes in Data.
+
+**/
+#define VAR_POLICY_CMD_SHELL_DUMP_HEX(Offset,                                         \
+                                      Data,                                           \
+                                      DataSize                                        \
+                                      )                                               \
+        {                                                                             \
+          UINT8 *_DataToDump;                                                         \
+          UINT8 _Val[50];                                                             \
+          UINT8 _Str[20];                                                             \
+          UINT8 _TempByte;                                                            \
+          UINTN _Size;                                                                \
+          UINTN _DumpHexIndex;                                                        \
+          UINTN _LocalOffset;                                                         \
+          UINTN _LocalDataSize;                                                       \
+          CONST CHAR8 *_Hex = "0123456789ABCDEF";                                     \
+          _LocalOffset = (Offset);                                                    \
+          _LocalDataSize = (DataSize);                                                \
+          _DataToDump = (UINT8 *)(Data);                                              \
+                                                                                      \
+          ASSERT (_DataToDump != NULL);                                               \
+                                                                                      \
+          while (_LocalDataSize != 0) {                                               \
+            _Size = 16;                                                               \
+            if (_Size > _LocalDataSize) {                                             \
+              _Size = _LocalDataSize;                                                 \
+            }                                                                         \
+                                                                                      \
+            for (_DumpHexIndex = 0; _DumpHexIndex < _Size; _DumpHexIndex += 1) {      \
+              _TempByte            = (UINT8) _DataToDump[_DumpHexIndex];              \
+              _Val[_DumpHexIndex * 3 + 0]  = (UINT8) _Hex[_TempByte >> 4];            \
+              _Val[_DumpHexIndex * 3 + 1]  = (UINT8) _Hex[_TempByte & 0xF];           \
+              _Val[_DumpHexIndex * 3 + 2]  =                                          \
+                (CHAR8) ((_DumpHexIndex == 7) ? '-' : ' ');                           \
+              _Str[_DumpHexIndex]          =                                          \
+                (CHAR8) ((_TempByte < ' ' || _TempByte > '~') ? '.' : _TempByte);     \
+            }                                                                         \
+                                                                                      \
+            _Val[_DumpHexIndex * 3]  = 0;                                             \
+            _Str[_DumpHexIndex]      = 0;                                             \
+                                                                                      \
+            ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_HEX_DUMP_LINE), mVarPolicyShellCommandHiiHandle, _LocalOffset, _Val, _Str); \
+            _DataToDump = (UINT8 *)(((UINTN)_DataToDump) + _Size);                    \
+            _LocalOffset += _Size;                                                    \
+            _LocalDataSize -= _Size;                                                  \
+          }                                                                           \
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_LINE_BREAK), mVarPolicyShellCommandHiiHandle); \
+        }
+
+#endif
diff --git a/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf
new file mode 100644
index 000000000000..22b4baa5e6f2
--- /dev/null
+++ b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf
@@ -0,0 +1,56 @@
+##  @file
+# A UEFI variable policy dynamic shell command that displays information
+# about UEFI variable policy configuration on the system.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                 = 1.27
+  BASE_NAME                   = VariablePolicyDynamicCommand
+  FILE_GUID                   = 17D0EF2A-5933-4007-8950-5749169D3DC5
+  MODULE_TYPE                 = DXE_DRIVER
+  VERSION_STRING              = 1.0
+  ENTRY_POINT                 = VariablePolicyDynamicCommandEntryPoint
+  UNLOAD_IMAGE                = VariablePolicyDynamicCommandUnload
+  UEFI_HII_RESOURCE_SECTION   = TRUE
+
+[Sources.common]
+  VariablePolicyDynamicCommand.c
+  VariablePolicyDynamicCommand.h
+  VariablePolicyDynamicCommand.uni
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  HiiLib
+  MemoryAllocationLib
+  PrintLib
+  ShellLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiHiiServicesLib
+  UefiRuntimeServicesTableLib
+
+[Protocols]
+  gEdkiiVariablePolicyProtocolGuid            ## SOMETIMES_CONSUMES
+  gEfiHiiPackageListProtocolGuid              ## CONSUMES
+  gEfiShellDynamicCommandProtocolGuid         ## PRODUCES
+
+[Guids]
+  ## SOMETIMES_CONSUMES ## Variables in Vendor Namespace
+  gEfiCapsuleReportGuid
+  gEfiCapsuleVendorGuid
+  gEfiGlobalVariableGuid
+  gEfiMemoryOverwriteRequestControlLockGuid
+
+[DEPEX]
+  TRUE
diff --git a/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.uni b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.uni
new file mode 100644
index 000000000000..a65f477b41c3
--- /dev/null
+++ b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.uni
@@ -0,0 +1,86 @@
+// /**
+// String definitions for the Variable Policy ("varpolicy") shell command.
+//
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+/=#
+
+#langdef   en-US "english"
+
+// General Strings
+#string STR_GEN_PROBLEM               #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_TOO_MANY              #language en-US "%H%s%N: Too many arguments.\r\n"
+#string STR_GEN_NO_VARS               #language en-US "No UEFI variables found!\r\n"
+#string STR_GEN_LINE_BREAK            #language en-US "\r\n"
+
+#string STR_GEN_HEX_DUMP_LINE         #language en-US "%B%08X%N: %-48a %V*%a*%N\r\n"
+
+#string STR_VAR_POL_POLICY_INT_ERR     #language en-US "%EInternal Application Error Getting Policy Info!%N\r\n"
+#string STR_VAR_POL_POLICY_NO_PROT     #language en-US "%EVariable Policy Protocol Was Not Found!%N\r\n"
+#string STR_VAR_POL_POLICY_NOT_INIT    #language en-US "%EUEFI Variable Policy is Not Initialized!%N\r\n"
+#string STR_VAR_POL_POLICY_NOT_FOUND   #language en-US "%EVariable Policy Not Found for This Variable!%N\r\n"
+#string STR_VAR_POL_POLICY_UNEXP_ERR   #language en-US "%EUnexpected Error Getting Policy Info!%N - %H%r%N\r\n"
+#string STR_VAR_POL_POLICY_HEADER_1    #language en-US "+-----------------------------------------------------------------------------+\r\n"
+#string STR_VAR_POL_POLICY_HEADER_2    #language en-US "| Variable Policy Info                                                        |\r\n"
+#string STR_VAR_POL_POLICY_VERSION     #language en-US "| Version: 0x%-8x                                                         |\r\n"
+#string STR_VAR_POL_POLICY_VARIABLE    #language en-US "| Variable: % -64s  |\r\n"
+#string STR_VAR_POL_POLICY_NAMESPACE   #language en-US "| Namespace: {%g}                           |\r\n"
+#string STR_VAR_POL_POLICY_MIN_SIZE    #language en-US "| Minimum Size: 0x%-8x                                                    |\r\n"
+#string STR_VAR_POL_POLICY_MAX_SIZE    #language en-US "| Maximum Size: 0x%-8x                                                    |\r\n"
+#string STR_VAR_POL_POLICY_ATTR_MUST   #language en-US "| Required Attributes:                                                        |\r\n"
+#string STR_VAR_POL_POLICY_ATTR_NOT    #language en-US "| Disallowed Attributes:                                                      |\r\n"
+#string STR_VAR_POL_POLICY_ATTR_GEN    #language en-US "|   %73-.73s |\r\n"
+#string STR_VAR_POL_POLICY_LOCK_TYPE   #language en-US "| Lock Type: % -64s |\r\n"
+#string STR_VAR_POL_POLICY_STATE_NS    #language en-US "|   Namespace: {%g}                         |\r\n"
+#string STR_VAR_POL_POLICY_STATE_VAL   #language en-US "|   Value: 0x%-8x                                                         |\r\n"
+#string STR_VAR_POL_POLICY_STATE_NAME  #language en-US "|   Name: % -64s    |\r\n"
+#string STR_VAR_POL_POLICY_STATS_PASS  #language en-US "  %V%d/%d UEFI variables have policy%N\r\n"
+#string STR_VAR_POL_POLICY_STATS_FAIL  #language en-US "  %E%d/%d UEFI variables have policy%N\r\n"
+
+#string STR_VAR_POL_VAR_TYPE         #language en-US "%H% -70s%N\r\n"
+#string STR_VAR_POL_VAR_NAME         #language en-US "Name: % -70s\r\n"
+#string STR_VAR_POL_VAR_SIZE         #language en-US "Size: 0x%-16x (%-,d) bytes\r\n"
+#string STR_VAR_POL_VAR_ATTR         #language en-US "Attributes: % -60s\r\n"
+
+#string STR_VAR_POL_STATS_HEADER_1   #language en-US "+----------------------------------------------------------------+\r\n"
+#string STR_VAR_POL_STATS_HEADER_2   #language en-US "| UEFI Variable Statistics                                       |\r\n"
+#string STR_VAR_POL_STATS_TOTAL_VARS #language en-US "  Total UEFI Variables: %,d\r\n"
+#string STR_VAR_POL_STATS_TOTAL_SIZE #language en-US "  Total UEFI Variable Size: 0x%x (%,d) bytes\r\n"
+
+#string STR_GET_HELP_VAR_POLICY      #language en-US ""
+".TH varpolicy 0 "Lists UEFI variable policy information."\r\n"
+".SH NAME\r\n"
+"Lists UEFI variable policy information.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"VARPOLICY [-p] [-s] [-v]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+"  -p - The policy flag will print variable policy info for each variable.\r\n"
+" \r\n"
+"  -s - The stats flag will print overall UEFI variable policy statistics.\r\n"
+" \r\n"
+"  -v - The verbose flag indicates all known information should be printed.\r\n"
+" \r\n"
+"       This includes a dump of the corresponding UEFI variable data in\r\n"
+"       addition to all other UEFI variable policy information.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+"  * To dump all active UEFI variables:\r\n"
+"    fs0:\> varpolicy\r\n"
+"\r\n"
+"  * To include UEFI variable policy information:\r\n"
+"    fs0:\> varpolicy -p\r\n"
+"\r\n"
+"  * To include UEFI variable statistics:\r\n"
+"    fs0:\> varpolicy -s\r\n"
+"\r\n"
+"  * To include a hexadecimal dump of data for each variable\r\n"
+"    and all other variable information:\r\n"
+"    fs0:\> varpolicy -v\r\n"
diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
index dd0d88603f11..c0a8a8f12bd5 100644
--- a/ShellPkg/ShellPkg.dsc
+++ b/ShellPkg/ShellPkg.dsc
@@ -154,6 +154,7 @@ [Components]
       gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
   }
   ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf
+  ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyDynamicCommand.inf
   ShellPkg/Application/AcpiViewApp/AcpiViewApp.inf
 
 [BuildOptions]
-- 
2.42.0.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108842): https://edk2.groups.io/g/devel/message/108842
Mute This Topic: https://groups.io/mt/101457414/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list