summaryrefslogtreecommitdiffstats
path: root/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy.c
diff options
context:
space:
mode:
authorMichael Kubacki <michael.kubacki@microsoft.com>2023-10-30 16:31:10 -0400
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-10-31 14:40:50 +0000
commitd4358a7f7629c996f80236588c95b62cd9c93584 (patch)
tree191250573385970bb47b6cc35897de0a2c0826b3 /ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy.c
parentf3b2187d558b1540e65e86024423ee39fe6264aa (diff)
downloadedk2-d4358a7f7629c996f80236588c95b62cd9c93584.tar.gz
edk2-d4358a7f7629c996f80236588c95b62cd9c93584.tar.bz2
edk2-d4358a7f7629c996f80236588c95b62cd9c93584.zip
ShellPkg: Add varpolicy dynamic shell command and app
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 ``` A standalone UEFI application can also be built that uses the same underlying functional code as the dynamic shell command. The path to use in the DSC and FDF for the app: ``` ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicyApp.inf ``` Cc: Zhichao Gao <zhichao.gao@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Zhichao Gao <zhichao.gao@intel.com> Message-Id: <20231030203112.736-3-mikuback@linux.microsoft.com>
Diffstat (limited to 'ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy.c')
-rw-r--r--ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy.c897
1 files changed, 897 insertions, 0 deletions
diff --git a/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy.c b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy.c
new file mode 100644
index 0000000000..ed991be4ed
--- /dev/null
+++ b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy.c
@@ -0,0 +1,897 @@
+/** @file
+ Main file for the "varpolicy" dynamic UEFI shell command and application.
+
+ This feature can provide detailed UEFI variable policy configuration
+ information in the UEFI shell.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VariablePolicy.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/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"
+ },
+ {
+ VariableVendorMemoryTypeInfo,
+ &gEfiMemoryTypeInformationGuid,
+ L"Memory Type Information"
+ },
+ {
+ VariableVendorMonotonicCounter,
+ &gMtcVendorGuid,
+ L"Monotonic Counter"
+ },
+ {
+ VariableVendorMorControl,
+ &gEfiMemoryOverwriteRequestControlLockGuid,
+ L"Memory Overwrite Request (MOR) Control Lock"
+ },
+ {
+ VariableVendorShell,
+ &gShellVariableGuid,
+ L"UEFI Shell"
+ },
+ {
+ VariableVendorShell,
+ &gShellAliasGuid,
+ L"UEFI Shell Alias"
+ }
+};
+
+/**
+ 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/app.
+
+ @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_ABORTED Failed to initialize the shell library.
+ @retval SHELL_INVALID_PARAMETER An argument passed to the shell command is invalid.
+ @retval Others A different error occurred.
+
+**/
+SHELL_STATUS
+EFIAPI
+RunVarPolicy (
+ 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 ();
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return SHELL_ABORTED;
+ }
+
+ 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;
+}
+
+/**
+ Retrieve HII package list from ImageHandle and publish to HII database.
+
+ @param[in] ImageHandle The image handle of the process.
+
+ @return HII handle.
+
+**/
+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;
+}