From: "Michael Kubacki" <mikuback@linux.microsoft.com>
To: devel@edk2.groups.io, zhichao.gao@intel.com, "Gao,
Liming" <gaoliming@byosoft.com.cn>
Cc: "Kinney, Michael D" <michael.d.kinney@intel.com>
Subject: Re: [edk2-devel] [PATCH v1 2/3] ShellPkg: Add varpolicy dynamic shell command
Date: Tue, 24 Oct 2023 19:36:56 -0400 [thread overview]
Message-ID: <a5b2b894-1cfd-4666-8d6a-ac2c65043e76@linux.microsoft.com> (raw)
In-Reply-To: <PH7PR11MB637704E5B403AD5D4B5F2678F6DFA@PH7PR11MB6377.namprd11.prod.outlook.com>
On 10/24/2023 2:21 AM, Gao, Zhichao wrote:
> Hi Michael:
>
> The patch looks good to me. Reviewed-by: Zhichao Gao <zhichao.gao@intel.com>
>
> Agree with Liming, Michael do you consider to add the APP version inf like DP/HTTP/TFTP?
>
Yes, that's a good suggestion. I will add it in a v2 update.
> Thanks,
> Zhichao
>
>> -----Original Message-----
>> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
>> gaoliming via groups.io
>> Sent: Tuesday, October 24, 2023 1:17 PM
>> To: devel@edk2.groups.io; mikuback@linux.microsoft.com
>> Cc: Gao, Zhichao <zhichao.gao@intel.com>; Kinney, Michael D
>> <michael.d.kinney@intel.com>
>> Subject: 回复: [edk2-devel] [PATCH v1 2/3] ShellPkg: Add varpolicy dynamic
>> shell command
>>
>> Michael:
>> Will you provide standalone application for varpolicy like tftp?
>>
>> Thanks
>> Liming
>>> -----邮件原件-----
>>> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Michael
>>> Kubacki
>>> 发送时间: 2023年9月19日 22:33
>>> 收件人: devel@edk2.groups.io
>>> 抄送: Zhichao Gao <zhichao.gao@intel.com>; Michael D Kinney
>>> <michael.d.kinney@intel.com>
>>> 主题: [edk2-devel] [PATCH v1 2/3] ShellPkg: Add varpolicy dynamic shell
>>> command
>>>
>>> From: Michael Kubacki <michael.kubacki@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/VariablePolicy
>>> DynamicCommand.inf {
>>> <PcdsFixedAtBuild>
>>> gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>>> }
>>> ```
>>>
>>> Include the following line in platform FDF:
>>>
>>> ```
>>> INF
>>>
>> ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy
>>> DynamicCommand.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>
>>> ---
>>>
>>>
>> ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy
>>> DynamicCommand.c | 1009 ++++++++++++++++++++
>>>
>>>
>> ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy
>>> DynamicCommand.h | 94 ++
>>>
>>>
>> ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy
>>> DynamicCommand.inf | 56 ++
>>>
>>>
>> ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePolicy
>>> DynamicCommand.uni | 86 ++
>>> ShellPkg/ShellPkg.dsc
>>> | 1 +
>>> 5 files changed, 1246 insertions(+)
>>>
>>> diff --git
>>>
>> a/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.c
>>>
>> b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.c
>>> new file mode 100644
>>> index 000000000000..49993f635396
>>> --- /dev/null
>>> +++
>>>
>> b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.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/VariablePoli
>>> cyDynamicCommand.h
>>>
>> b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.h
>>> new file mode 100644
>>> index 000000000000..7ce5beca389a
>>> --- /dev/null
>>> +++
>>>
>> b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.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/VariablePoli
>>> cyDynamicCommand.inf
>>>
>> b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.inf
>>> new file mode 100644
>>> index 000000000000..22b4baa5e6f2
>>> --- /dev/null
>>> +++
>>>
>> b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.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/VariablePoli
>>> cyDynamicCommand.uni
>>>
>> b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.uni
>>> new file mode 100644
>>> index 000000000000..a65f477b41c3
>>> --- /dev/null
>>> +++
>>>
>> b/ShellPkg/DynamicCommand/VariablePolicyDynamicCommand/VariablePoli
>>> cyDynamicCommand.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/VariablePolicy
>>> DynamicCommand.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/4905953
>>> Group Owner: devel+owner@edk2.groups.io
>>> Unsubscribe: https://edk2.groups.io/g/devel/unsub
>>> [gaoliming@byosoft.com.cn]
>>> -=-=-=-=-=-=
>>>
>>
>>
>>
>>
>>
>>
>>
>
>
>
>
>
>
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110012): https://edk2.groups.io/g/devel/message/110012
Mute This Topic: https://groups.io/mt/102152885/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2023-10-24 23:37 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-19 14:32 [edk2-devel] [PATCH v1 0/3] Add Variable Policy Audit and Shell Command Michael Kubacki
2023-09-19 14:32 ` [edk2-devel] [PATCH v1 1/3] MdeModulePkg/VariablePolicy: Add more granular variable policy querying Michael Kubacki
2023-10-24 5:11 ` 回复: " gaoliming via groups.io
2023-09-19 14:32 ` [edk2-devel] [PATCH v1 2/3] ShellPkg: Add varpolicy dynamic shell command Michael Kubacki
2023-10-24 5:16 ` 回复: " gaoliming via groups.io
2023-10-24 6:21 ` Gao, Zhichao
2023-10-24 23:36 ` Michael Kubacki [this message]
2023-09-19 14:33 ` [edk2-devel] [PATCH v1 3/3] OvmfPkg: Add varpolicy " Michael Kubacki
2023-10-24 0:44 ` Yao, Jiewen
2023-10-24 2:13 ` Michael D Kinney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a5b2b894-1cfd-4666-8d6a-ac2c65043e76@linux.microsoft.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox