/** @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; | |
} |