From: "Wang, Jian J" <jian.j.wang@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"Wang, Jian J" <jian.j.wang@intel.com>,
"Vang, Judah" <judah.vang@intel.com>
Cc: "Gao, Liming" <gaoliming@byosoft.com.cn>,
"Wu, Hao A" <hao.a.wu@intel.com>,
"Mistry, Nishant C" <nishant.c.mistry@intel.com>
Subject: Re: [edk2-devel] [PATCH v4 07/28] MdeModulePkg: Add new Variable functionality
Date: Mon, 14 Nov 2022 02:34:27 +0000 [thread overview]
Message-ID: <MW4PR11MB6763D03A9503F7724A07A965B6059@MW4PR11MB6763.namprd11.prod.outlook.com> (raw)
In-Reply-To: <1727359DAB074995.1868@groups.io>
Sorry, please ignore this one. I should reply the one from v5.
Regards,
Jian
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Wang, Jian
> J
> Sent: Monday, November 14, 2022 1:39 AM
> To: Vang, Judah <judah.vang@intel.com>; devel@edk2.groups.io
> Cc: Gao, Liming <gaoliming@byosoft.com.cn>; Wu, Hao A
> <hao.a.wu@intel.com>; Mistry, Nishant C <nishant.c.mistry@intel.com>
> Subject: Re: [edk2-devel] [PATCH v4 07/28] MdeModulePkg: Add new Variable
> functionality
>
> Hi Judah,
>
> See my comments (starting with [JianJW]) inline below.
>
> Regards,
> Jian
>
> > -----Original Message-----
> > From: Vang, Judah <judah.vang@intel.com>
> > Sent: Thursday, August 11, 2022 2:53 PM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>; Mistry,
> > Nishant C <nishant.c.mistry@intel.com>
> > Subject: [PATCH v4 07/28] MdeModulePkg: Add new Variable functionality
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2594
> >
> > V3: Update GetNvVariableStore() to call GetVariableFlashNvStorageInfo()
> > and SafeUint64ToUint32().
> >
> > V1: Provide new APIs for retrieving variable information.
> > Add new function stubs for retrieving Protected
> > variable information.
> >
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Liming Gao <gaoliming@byosoft.com.cn>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Nishant C Mistry <nishant.c.mistry@intel.com>
> > Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> > Signed-off-by: Nishant C Mistry <nishant.c.mistry@intel.com>
> > Signed-off-by: Judah Vang <judah.vang@intel.com>
> > Acked-by: Hao A Wu <hao.a.wu@intel.com>
> > ---
> > MdeModulePkg/Universal/Variable/Pei/VariablePei.inf | 10 +-
> > MdeModulePkg/Universal/Variable/Pei/Variable.h | 80 +-
> > MdeModulePkg/Universal/Variable/Pei/VariableParsing.h | 309 +++++++
> > MdeModulePkg/Universal/Variable/Pei/VariableStore.h | 116 +++
> > MdeModulePkg/Universal/Variable/Pei/Variable.c | 890 +++---------------
> > MdeModulePkg/Universal/Variable/Pei/VariableParsing.c | 941
> > ++++++++++++++++++++
> > MdeModulePkg/Universal/Variable/Pei/VariableStore.c | 307 +++++++
> > 7 files changed, 1893 insertions(+), 760 deletions(-)
> >
> > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> > b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> > index 7264a24bdf71..0945b4dec435 100644
> > --- a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> > +++ b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> > @@ -3,7 +3,7 @@
> > #
> > # This module implements ReadOnly Variable Services required by PEIM and
> > installs PEI ReadOnly Varaiable2 PPI.
> > #
> > -# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > +# Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
> > # SPDX-License-Identifier: BSD-2-Clause-Patent
> > #
> > ##
> > @@ -26,6 +26,10 @@ [Defines]
> > [Sources]
> > Variable.c
> > Variable.h
> > + VariableStore.c
> > + VariableStore.h
> > + VariableParsing.c
> > + VariableParsing.h
> >
> > [Packages]
> > MdePkg/MdePkg.dec
> > @@ -41,6 +45,7 @@ [LibraryClasses]
> > PeiServicesLib
> > SafeIntLib
> > VariableFlashInfoLib
> > + ProtectedVariableLib
> >
> > [Guids]
> > ## CONSUMES ## GUID # Variable store header
> > @@ -58,7 +63,8 @@ [Guids]
> > gEdkiiFaultTolerantWriteGuid
> >
> > [Ppis]
> > - gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES
> > + gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES
> > + gEfiPeiVariableStoreDiscoveredPpiGuid ## CONSUMES
> >
> > [Pcd]
> > gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable ##
> > SOMETIMES_CONSUMES
> > diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.h
> > b/MdeModulePkg/Universal/Variable/Pei/Variable.h
> > index 51effbf79987..8c79ff850b38 100644
> > --- a/MdeModulePkg/Universal/Variable/Pei/Variable.h
> > +++ b/MdeModulePkg/Universal/Variable/Pei/Variable.h
> > @@ -2,7 +2,7 @@
> > The internal header file includes the common header files, defines
> > internal structure and functions used by PeiVariable module.
> >
> > -Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
> > SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > **/
> > @@ -22,11 +22,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > #include <Library/PeiServicesLib.h>
> > #include <Library/SafeIntLib.h>
> > #include <Library/VariableFlashInfoLib.h>
> > +#include <Library/ProtectedVariableLib.h>
> >
> > #include <Guid/VariableFormat.h>
> > #include <Guid/VariableIndexTable.h>
> > #include <Guid/SystemNvDataGuid.h>
> > #include <Guid/FaultTolerantWrite.h>
> > +#include <Guid/ProtectedVariable.h>
> >
> > typedef enum {
> > VariableStoreTypeHob,
> > @@ -144,4 +146,80 @@ PeiGetNextVariableName (
> > IN OUT EFI_GUID *VariableGuid
> > );
> >
> > +/**
> > + This service retrieves a variable's value using its name and GUID.
> > +
> > + Read the specified variable from the UEFI variable store. If the Data
> > + buffer is too small to hold the contents of the variable, the error
> > + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required
> buffer
> > + size to obtain the data.
> > +
> > + @param This A pointer to this instance of the
> > EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> > + @param VariableName A pointer to a null-terminated string that is the
> > variable's name.
> > + @param VariableGuid A pointer to an EFI_GUID that is the variable's
> > GUID. The combination of
> > + VariableGuid and VariableName must be unique.
> > + @param Attributes If non-NULL, on return, points to the variable's
> > attributes.
> > + @param DataSize On entry, points to the size in bytes of the Data
> > buffer.
> > + On return, points to the size of the data returned in Data.
> > + @param Data Points to the buffer which will hold the returned
> > variable value.
> > + May be NULL with a zero DataSize in order to determine the
> > size of the buffer needed.
> > +
> > + @retval EFI_SUCCESS The variable was read successfully.
> > + @retval EFI_NOT_FOUND The variable was not found.
> > + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the
> resulting
> > data.
> > + DataSize is updated with the size required for
> > + the specified variable.
> > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or
> > Data is NULL.
> > + @retval EFI_DEVICE_ERROR The variable could not be retrieved because
> of
> > a device error.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +PeiGetVariableEx (
> > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
> > + IN CONST CHAR16 *VariableName,
> > + IN CONST EFI_GUID *VariableGuid,
> > + OUT UINT32 *Attributes,
> > + IN OUT UINTN *DataSize,
> > + OUT VOID *Data OPTIONAL
> > + );
> > +
> > +/**
> > + Return the next variable name and GUID.
> > +
> > + This function is called multiple times to retrieve the VariableName
> > + and VariableGuid of all variables currently available in the system.
> > + On each call, the previous results are passed into the interface,
> > + and, on return, the interface returns the data for the next
> > + interface. When the entire variable list has been returned,
> > + EFI_NOT_FOUND is returned.
> > +
> > + @param This A pointer to this instance of the
> > EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> > +
> > + @param VariableNameSize On entry, points to the size of the buffer
> pointed
> > to by VariableName.
> > + @param VariableName On entry, a pointer to a null-terminated string
> that
> > is the variable's name.
> > + On return, points to the next variable's null-terminated name
> > string.
> > +
> > + @param VariableGuid On entry, a pointer to an UEFI _GUID that is the
> > variable's GUID.
> > + On return, a pointer to the next variable's GUID.
> > +
> > + @retval EFI_SUCCESS The variable was read successfully.
> > + @retval EFI_NOT_FOUND The variable could not be found.
> > + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for
> the
> > resulting
> > + data. VariableNameSize is updated with the size
> > + required for the specified variable.
> > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
> > + VariableNameSize is NULL.
> > + @retval EFI_DEVICE_ERROR The variable could not be retrieved because
> of
> > a device error.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +PeiGetNextVariableNameEx (
> > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
> > + IN OUT UINTN *VariableNameSize,
> > + IN OUT CHAR16 *VariableName,
> > + IN OUT EFI_GUID *VariableGuid
> > + );
> > +
> > #endif
>
> [JianJW]
> a. The function header comments for
> PeiGetVariableEx/PeiGetNextVariableNameEx
> are the same as non-ex version of PeiGetVariable/PeiGetNextVariableName.
> This
> doesn't do any help to users to get know about what're the differences
> between
> these two version of functions. Please update the Ex version function header
> to
> give more accurate descriptions.
> b. Please update the function header in Variable.c as well.
>
> > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariableParsing.h
> > b/MdeModulePkg/Universal/Variable/Pei/VariableParsing.h
> > new file mode 100644
> > index 000000000000..d7af6cb6e8be
> > --- /dev/null
> > +++ b/MdeModulePkg/Universal/Variable/Pei/VariableParsing.h
> > @@ -0,0 +1,309 @@
> > +/** @file
> > + The internal header file includes the common header files, defines
> > + internal structure and functions used by PeiVariable module.
> > +
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef PEI_VARIABLE_PARSING_H_
> > +#define PEI_VARIABLE_PARSING_H_
> > +
> > +#include "Variable.h"
> > +
> > +/**
> > +
> > + Gets the pointer to the first variable header in given variable store area.
> > +
> > + @param[in] VarStoreHeader Pointer to the Variable Store Header.
> > +
> > + @return Pointer to the first variable header.
> > +
> > +**/
> > +VARIABLE_HEADER *
> > +GetStartPointer (
> > + IN VARIABLE_STORE_HEADER *VarStoreHeader
> > + );
> > +
> > +/**
> > +
> > + Gets the pointer to the end of the variable storage area.
> > +
> > + This function gets pointer to the end of the variable storage
> > + area, according to the input variable store header.
> > +
> > + @param[in] VarStoreHeader Pointer to the Variable Store Header.
> > +
> > + @return Pointer to the end of the variable storage area.
> > +
> > +**/
> > +VARIABLE_HEADER *
> > +GetEndPointer (
> > + IN VARIABLE_STORE_HEADER *VarStoreHeader
> > + );
> > +
> > +/**
> > + This code checks if variable header is valid or not.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > +
> > + @retval TRUE Variable header is valid.
> > + @retval FALSE Variable header is not valid.
> > +
> > +**/
> > +BOOLEAN
> > +IsValidVariableHeader (
> > + IN VARIABLE_HEADER *Variable
> > + );
> > +
> > +/**
> > + This code gets the pointer to the next variable header.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] VariableHeader Pointer to the Variable Header that has
> > consecutive content.
> > +
> > + @return A VARIABLE_HEADER* pointer to next variable header.
> > +
> > +**/
> > +VARIABLE_HEADER *
> > +GetNextVariablePtr (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN VARIABLE_HEADER *Variable,
> > + IN VARIABLE_HEADER *VariableHeader
> > + );
> > +
> > +/**
> > + This code gets the pointer to the variable guid.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return A EFI_GUID* pointer to Vendor Guid.
> > +
> > +**/
> > +EFI_GUID *
> > +GetVendorGuidPtr (
> > + IN VARIABLE_HEADER *Variable,
> > + IN BOOLEAN AuthFlag
> > + );
> > +
> > +/**
> > + This code gets the pointer to the variable name.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return A CHAR16* pointer to Variable Name.
> > +
> > +**/
> > +CHAR16 *
> > +GetVariableNamePtr (
> > + IN VARIABLE_HEADER *Variable,
> > + IN BOOLEAN AuthFlag
> > + );
> > +
> > +/**
> > + This code gets the size of name of variable.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return Size of variable in bytes in type UINTN.
> > +
> > +**/
> > +UINTN
> > +NameSizeOfVariable (
> > + IN VARIABLE_HEADER *Variable,
> > + IN BOOLEAN AuthFlag
> > + );
> > +
> > +/**
> > + This code gets the size of data of variable.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return Size of variable in bytes in type UINTN.
> > +
> > +**/
> > +UINTN
> > +DataSizeOfVariable (
> > + IN VARIABLE_HEADER *Variable,
> > + IN BOOLEAN AuthFlag
> > + );
> > +
> > +/**
> > + This code gets the pointer to the variable data.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] VariableHeader Pointer to the Variable Header that has
> > consecutive content.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return A UINT8* pointer to Variable Data.
> > +
> > +**/
> > +UINT8 *
> > +GetVariableDataPtr (
> > + IN VARIABLE_HEADER *Variable,
> > + IN VARIABLE_HEADER *VariableHeader,
> > + IN BOOLEAN AuthFlag
> > + );
> > +
> > +/**
> > + Get variable header that has consecutive content.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[out] VariableHeader Pointer to Pointer to the Variable Header that
> > has consecutive content.
> > +
> > + @retval TRUE Variable header is valid.
> > + @retval FALSE Variable header is not valid.
> > +
> > +**/
> > +BOOLEAN
> > +GetVariableHeader (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN VARIABLE_HEADER *Variable,
> > + OUT VARIABLE_HEADER **VariableHeader
> > + );
> > +
> > +/**
> > + This code gets the size of variable header.
> > +
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return Size of variable header in bytes in type UINTN.
> > +
> > +**/
> > +UINTN
> > +GetVariableHeaderSize (
> > + IN BOOLEAN AuthFlag
> > + );
> > +
> > +/**
> > + Get variable name or data to output buffer.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] NameOrData Pointer to the variable name/data that may be
> > inconsecutive.
> > + @param[in] Size Variable name/data size.
> > + @param[out] Buffer Pointer to output buffer to hold the variable
> > name/data.
> > +
> > +**/
> > +VOID
> > +GetVariableNameOrData (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN UINT8 *NameOrData,
> > + IN UINTN Size,
> > + OUT UINT8 *Buffer
> > + );
> > +
> > +/**
> > + This function compares a variable with variable entries in database.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] Variable Pointer to the variable in our database
> > + @param[in] VariableHeader Pointer to the Variable Header that has
> > consecutive content.
> > + @param[in] VariableName Name of the variable to compare to 'Variable'
> > + @param[in] VendorGuid GUID of the variable to compare to 'Variable'
> > + @param[out] PtrTrack Variable Track Pointer structure that contains
> > Variable Information.
> > +
> > + @retval EFI_SUCCESS Found match variable
> > + @retval EFI_NOT_FOUND Variable not found
> > +
> > +**/
> > +EFI_STATUS
> > +CompareWithValidVariable (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN VARIABLE_HEADER *Variable,
> > + IN VARIABLE_HEADER *VariableHeader,
> > + IN CONST CHAR16 *VariableName,
> > + IN CONST EFI_GUID *VendorGuid,
> > + OUT VARIABLE_POINTER_TRACK *PtrTrack
> > + );
> > +
> > +/**
> > +
> > + Retrieve details of the variable next to given variable within VariableStore.
> > +
> > + If VarInfo->Address is NULL, the first one in VariableStore is returned.
> > +
> > + VariableStart and/or VariableEnd can be given optionally for the situation
> > + in which the valid storage space is smaller than the VariableStore->Size.
> > + This usually happens when PEI variable services make a compact variable
> > + cache to save memory, which cannot make use VariableStore->Size to
> > determine
> > + the correct variable storage range.
> > +
> > + @param[in,out] VariableInfo Pointer to variable information.
> > +
> > + @retval EFI_INVALID_PARAMETER VariableInfo or VariableStore is NULL.
> > + @retval EFI_NOT_FOUND If the end of VariableStore is reached.
> > + @retval EFI_SUCCESS The next variable is retrieved successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +GetNextVariableInfo (
> > + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo
> > + );
> > +
> > +/**
> > +
> > + Retrieve details about a variable and return them in VariableInfo->Header.
> > +
> > + If VariableInfo->Address is given, this function will calculate its offset
> > + relative to given variable storage via VariableStore; Otherwise, it will try
> > + other internal variable storages or cached copies. It's assumed that, for all
> > + copies of NV variable storage, all variables are stored in the same relative
> > + position. If VariableInfo->Address is found in the range of any storage
> copies,
> > + its offset relative to that storage should be the same in other copies.
> > +
> > + If VariableInfo->Offset is given (non-zero) but not VariableInfo->Address,
> > + this function will return the variable memory address inside VariableStore,
> > + if given, via VariableInfo->Address; Otherwise, the address of other storage
> > + copies will be returned, if any.
> > +
> > + For a new variable whose offset has not been determined, a value of -1 as
> > + VariableInfo->Offset should be passed to skip the offset calculation.
> > +
> > + @param[in,out] VariableInfo Pointer to variable information.
> > +
> > + @retval EFI_INVALID_PARAMETER VariableInfo is NULL or both
> VariableInfo-
> > >Address
> > + and VariableInfo->Offset are NULL (0).
> > + @retval EFI_NOT_FOUND If given Address or Offset is out of range of
> > + any given or internal storage copies.
> > + @retval EFI_SUCCESS Variable details are retrieved successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +GetVariableInfo (
> > + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo
> > + );
> > +
> > +/**
> > +
> > + Find variable specified with input parameters.
> > +
> > + @param[in] StoreInfo Pointer to variable information.
> > + @param[in] VariableName Pointer to variable name.
> > + @param[in] VendorGuid Pointer to variable GUID.
> > + @param[in] PtrTrack Pointer to variable track.
> > +
> > + @retval EFI_INVALID_PARAMETER VariableInfo is NULL or both
> VariableInfo-
> > >Address
> > + and VariableInfo->Offset are NULL (0).
> > + @retval EFI_NOT_FOUND If given Address or Offset is out of range of
> > + any given or internal storage copies.
> > + @retval EFI_SUCCESS Variable details are retrieved successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +FindVariableEx (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN CONST CHAR16 *VariableName,
> > + IN CONST EFI_GUID *VendorGuid,
> > + OUT VARIABLE_POINTER_TRACK *PtrTrack
> > + );
> > +
> > +#endif
> > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariableStore.h
> > b/MdeModulePkg/Universal/Variable/Pei/VariableStore.h
> > new file mode 100644
> > index 000000000000..6e2f6f939bab
> > --- /dev/null
> > +++ b/MdeModulePkg/Universal/Variable/Pei/VariableStore.h
> > @@ -0,0 +1,116 @@
> > +/** @file
> > + Implement ReadOnly Variable Services required by PEIM and install
> > + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile
> storage
> > space.
>
> [JianJW] Typo: ' Varaiable2' -> ' Variable2'
>
> > +
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef PEI_VARIABLE_STORE_H_
> > +#define PEI_VARIABLE_STORE_H_
> > +
> > +/**
> > + Get variable store status.
> > +
> > + @param[in] VarStoreHeader Pointer to the Variable Store Header.
> > +
> > + @retval EfiRaw Variable store is raw
> > + @retval EfiValid Variable store is valid
> > + @retval EfiInvalid Variable store is invalid
> > +
> > +**/
> > +VARIABLE_STORE_STATUS
> > +GetVariableStoreStatus (
> > + IN VARIABLE_STORE_HEADER *VarStoreHeader
> > + );
> > +
> > +/**
> > + Reports HOB variable store is available or not.
> > +
> > + @retval EFI_NOT_READY HOB variable store info not available.
> > + @retval EFI_NOT_FOUND HOB variable store is NOT available.
> > + @retval EFI_SUCCESS HOB variable store is available.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +IsHobVariableStoreAvailable (
> > + VOID
> > + );
> > +
> > +/**
> > + Get HOB variable store.
> > +
> > + @param[out] StoreInfo Return the store info.
> > +
> > +**/
> > +VOID
> > +GetHobVariableStore (
> > + OUT VARIABLE_STORE_INFO *StoreInfo
> > + );
> > +
> > +/**
> > + Get NV variable store.
> > +
> > + @param[out] StoreInfo Return the store info.
> > + @param[out] VariableStoreHeader Return header of FV containing the
> store.
> > +
> > +**/
> > +VOID
> > +GetNvVariableStore (
> > + OUT VARIABLE_STORE_INFO *StoreInfo,
> > + OUT EFI_FIRMWARE_VOLUME_HEADER **VariableFvHeader
> > + );
> > +
> > +/**
> > + Return the variable store header and the store info based on the Index.
> > +
> > + @param[in] Type The type of the variable store.
> > + @param[out] StoreInfo Return the store info.
> > +
> > + @return Pointer to the variable store header.
> > +**/
> > +VARIABLE_STORE_HEADER *
> > +GetVariableStore (
> > + IN VARIABLE_STORE_TYPE Type,
> > + OUT VARIABLE_STORE_INFO *StoreInfo
> > + );
> > +
> > +/**
> > + Make a cached copy of NV variable storage.
> > +
> > + To save memory in PEI phase, only valid variables are copied into cache.
> > + An IndexTable could be used to store the offset (relative to NV storage
> > + base) of each copied variable, in case we need to restore the storage
> > + as the same (valid) variables layout as in original one.
> > +
> > + Variables with valid format and following state can be taken as valid:
> > + - with state VAR_ADDED;
> > + - with state VAR_IN_DELETED_TRANSITION but without the same variable
> > + with state VAR_ADDED;
> > + - with state VAR_ADDED and/or VAR_IN_DELETED_TRANSITION for
> variable
> > + MetaDataHmacVar.
> > +
> > + @param[out] StoreCacheBase Base address of variable storage cache.
> > + @param[in,out] StoreCacheSize Size of space in StoreCacheBase.
> > + @param[out] IndexTable Buffer of index (offset) table with entries of
> > + VariableNumber.
> > + @param[out] VariableNumber Number of valid variables.
> > + @param[out] AuthFlag Aut-variable indicator.
> > +
> > + @return EFI_INVALID_PARAMETER Invalid StoreCacheSize and/or
> > StoreCacheBase.
> > + @return EFI_VOLUME_CORRUPTED Invalid or no NV variable storage found.
> > + @return EFI_BUFFER_TOO_SMALL StoreCacheSize is smaller than needed.
> > + @return EFI_SUCCESS NV variable storage is cached successfully.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +InitNvVariableStore (
> > + OUT EFI_PHYSICAL_ADDRESS StoreCacheBase OPTIONAL,
> > + IN OUT UINT32 *StoreCacheSize,
> > + OUT UINT32 *IndexTable OPTIONAL,
> > + OUT UINT32 *VariableNumber OPTIONAL,
> > + OUT BOOLEAN *AuthFlag OPTIONAL
> > + );
> > +
> > +#endif
> > diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.c
> > b/MdeModulePkg/Universal/Variable/Pei/Variable.c
> > index 26a4c73b45a5..ce790946626e 100644
> > --- a/MdeModulePkg/Universal/Variable/Pei/Variable.c
> > +++ b/MdeModulePkg/Universal/Variable/Pei/Variable.c
> > @@ -2,20 +2,22 @@
> > Implement ReadOnly Variable Services required by PEIM and install
> > PEI ReadOnly Varaiable2 PPI. These services operates the non volatile
> storage
> > space.
>
> [JianJW] typo: "Varaiable2" -> " Variable2"
>
> >
> > -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> > +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
> > Copyright (c) Microsoft Corporation.<BR>
> > SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > **/
> >
> > #include "Variable.h"
> > +#include "VariableParsing.h"
> > +#include "VariableStore.h"
> >
> > //
> > // Module globals
> > //
> > EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi = {
> > - PeiGetVariable,
> > - PeiGetNextVariableName
> > + PeiGetVariableEx,
> > + PeiGetNextVariableNameEx
> > };
> >
> > EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {
> > @@ -41,763 +43,33 @@ PeimInitializeVariableServices (
> > IN CONST EFI_PEI_SERVICES **PeiServices
> > )
> > {
> > + EFI_STATUS Status;
> > + PROTECTED_VARIABLE_CONTEXT_IN ContextIn;
> > +
> > + //
> > + // If protected variable services are not supported, EFI_UNSUPPORTED
> should
> > + // be always returned. Check it here.
> > + //
> > + ContextIn.StructVersion =
> > PROTECTED_VARIABLE_CONTEXT_IN_STRUCT_VERSION;
> > + ContextIn.StructSize = sizeof (ContextIn);
> > +
> > + ContextIn.MaxVariableSize = 0;
> > + ContextIn.VariableServiceUser = FromPeiModule;
> > + ContextIn.GetVariableInfo = GetVariableInfo;
> > + ContextIn.GetNextVariableInfo = GetNextVariableInfo;
> > + ContextIn.FindVariableSmm = NULL;
> > + ContextIn.UpdateVariableStore = NULL;
> > + ContextIn.UpdateVariable = NULL;
> > + ContextIn.IsHobVariableStoreAvailable = IsHobVariableStoreAvailable;
> > +
> > + Status = ProtectedVariableLibInitialize (&ContextIn);
> > + if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {
> > + return Status;
> > + }
> > +
> > return PeiServicesInstallPpi (&mPpiListVariable);
> > }
> >
> > -/**
> > -
> > - Gets the pointer to the first variable header in given variable store area.
> > -
> > - @param VarStoreHeader Pointer to the Variable Store Header.
> > -
> > - @return Pointer to the first variable header.
> > -
> > -**/
> > -VARIABLE_HEADER *
> > -GetStartPointer (
> > - IN VARIABLE_STORE_HEADER *VarStoreHeader
> > - )
> > -{
> > - //
> > - // The start of variable store
> > - //
> > - return (VARIABLE_HEADER *)HEADER_ALIGN (VarStoreHeader + 1);
> > -}
> > -
> > -/**
> > -
> > - Gets the pointer to the end of the variable storage area.
> > -
> > - This function gets pointer to the end of the variable storage
> > - area, according to the input variable store header.
> > -
> > - @param VarStoreHeader Pointer to the Variable Store Header.
> > -
> > - @return Pointer to the end of the variable storage area.
> > -
> > -**/
> > -VARIABLE_HEADER *
> > -GetEndPointer (
> > - IN VARIABLE_STORE_HEADER *VarStoreHeader
> > - )
> > -{
> > - //
> > - // The end of variable store
> > - //
> > - return (VARIABLE_HEADER *)HEADER_ALIGN ((UINTN)VarStoreHeader +
> > VarStoreHeader->Size);
> > -}
> > -
> > -/**
> > - This code checks if variable header is valid or not.
> > -
> > - @param Variable Pointer to the Variable Header.
> > -
> > - @retval TRUE Variable header is valid.
> > - @retval FALSE Variable header is not valid.
> > -
> > -**/
> > -BOOLEAN
> > -IsValidVariableHeader (
> > - IN VARIABLE_HEADER *Variable
> > - )
> > -{
> > - if ((Variable == NULL) || (Variable->StartId != VARIABLE_DATA)) {
> > - return FALSE;
> > - }
> > -
> > - return TRUE;
> > -}
> > -
> > -/**
> > - This code gets the size of variable header.
> > -
> > - @param AuthFlag Authenticated variable flag.
> > -
> > - @return Size of variable header in bytes in type UINTN.
> > -
> > -**/
> > -UINTN
> > -GetVariableHeaderSize (
> > - IN BOOLEAN AuthFlag
> > - )
> > -{
> > - UINTN Value;
> > -
> > - if (AuthFlag) {
> > - Value = sizeof (AUTHENTICATED_VARIABLE_HEADER);
> > - } else {
> > - Value = sizeof (VARIABLE_HEADER);
> > - }
> > -
> > - return Value;
> > -}
> > -
> > -/**
> > - This code gets the size of name of variable.
> > -
> > - @param Variable Pointer to the Variable Header.
> > - @param AuthFlag Authenticated variable flag.
> > -
> > - @return Size of variable in bytes in type UINTN.
> > -
> > -**/
> > -UINTN
> > -NameSizeOfVariable (
> > - IN VARIABLE_HEADER *Variable,
> > - IN BOOLEAN AuthFlag
> > - )
> > -{
> > - AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
> > -
> > - AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable;
> > - if (AuthFlag) {
> > - if ((AuthVariable->State == (UINT8)(-1)) ||
> > - (AuthVariable->DataSize == (UINT32)(-1)) ||
> > - (AuthVariable->NameSize == (UINT32)(-1)) ||
> > - (AuthVariable->Attributes == (UINT32)(-1)))
> > - {
> > - return 0;
> > - }
> > -
> > - return (UINTN)AuthVariable->NameSize;
> > - } else {
> > - if ((Variable->State == (UINT8)(-1)) ||
> > - (Variable->DataSize == (UINT32)(-1)) ||
> > - (Variable->NameSize == (UINT32)(-1)) ||
> > - (Variable->Attributes == (UINT32)(-1)))
> > - {
> > - return 0;
> > - }
> > -
> > - return (UINTN)Variable->NameSize;
> > - }
> > -}
> > -
> > -/**
> > - This code gets the size of data of variable.
> > -
> > - @param Variable Pointer to the Variable Header.
> > - @param AuthFlag Authenticated variable flag.
> > -
> > - @return Size of variable in bytes in type UINTN.
> > -
> > -**/
> > -UINTN
> > -DataSizeOfVariable (
> > - IN VARIABLE_HEADER *Variable,
> > - IN BOOLEAN AuthFlag
> > - )
> > -{
> > - AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
> > -
> > - AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable;
> > - if (AuthFlag) {
> > - if ((AuthVariable->State == (UINT8)(-1)) ||
> > - (AuthVariable->DataSize == (UINT32)(-1)) ||
> > - (AuthVariable->NameSize == (UINT32)(-1)) ||
> > - (AuthVariable->Attributes == (UINT32)(-1)))
> > - {
> > - return 0;
> > - }
> > -
> > - return (UINTN)AuthVariable->DataSize;
> > - } else {
> > - if ((Variable->State == (UINT8)(-1)) ||
> > - (Variable->DataSize == (UINT32)(-1)) ||
> > - (Variable->NameSize == (UINT32)(-1)) ||
> > - (Variable->Attributes == (UINT32)(-1)))
> > - {
> > - return 0;
> > - }
> > -
> > - return (UINTN)Variable->DataSize;
> > - }
> > -}
> > -
> > -/**
> > - This code gets the pointer to the variable name.
> > -
> > - @param Variable Pointer to the Variable Header.
> > - @param AuthFlag Authenticated variable flag.
> > -
> > - @return A CHAR16* pointer to Variable Name.
> > -
> > -**/
> > -CHAR16 *
> > -GetVariableNamePtr (
> > - IN VARIABLE_HEADER *Variable,
> > - IN BOOLEAN AuthFlag
> > - )
> > -{
> > - return (CHAR16 *)((UINTN)Variable + GetVariableHeaderSize (AuthFlag));
> > -}
> > -
> > -/**
> > - This code gets the pointer to the variable guid.
> > -
> > - @param Variable Pointer to the Variable Header.
> > - @param AuthFlag Authenticated variable flag.
> > -
> > - @return A EFI_GUID* pointer to Vendor Guid.
> > -
> > -**/
> > -EFI_GUID *
> > -GetVendorGuidPtr (
> > - IN VARIABLE_HEADER *Variable,
> > - IN BOOLEAN AuthFlag
> > - )
> > -{
> > - AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
> > -
> > - AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable;
> > - if (AuthFlag) {
> > - return &AuthVariable->VendorGuid;
> > - } else {
> > - return &Variable->VendorGuid;
> > - }
> > -}
> > -
> > -/**
> > - This code gets the pointer to the variable data.
> > -
> > - @param Variable Pointer to the Variable Header.
> > - @param VariableHeader Pointer to the Variable Header that has
> > consecutive content.
> > - @param AuthFlag Authenticated variable flag.
> > -
> > - @return A UINT8* pointer to Variable Data.
> > -
> > -**/
> > -UINT8 *
> > -GetVariableDataPtr (
> > - IN VARIABLE_HEADER *Variable,
> > - IN VARIABLE_HEADER *VariableHeader,
> > - IN BOOLEAN AuthFlag
> > - )
> > -{
> > - UINTN Value;
> > -
> > - //
> > - // Be careful about pad size for alignment
> > - //
> > - Value = (UINTN)GetVariableNamePtr (Variable, AuthFlag);
> > - Value += NameSizeOfVariable (VariableHeader, AuthFlag);
> > - Value += GET_PAD_SIZE (NameSizeOfVariable (VariableHeader, AuthFlag));
> > -
> > - return (UINT8 *)Value;
> > -}
> > -
> > -/**
> > - This code gets the pointer to the next variable header.
> > -
> > - @param StoreInfo Pointer to variable store info structure.
> > - @param Variable Pointer to the Variable Header.
> > - @param VariableHeader Pointer to the Variable Header that has
> > consecutive content.
> > -
> > - @return A VARIABLE_HEADER* pointer to next variable header.
> > -
> > -**/
> > -VARIABLE_HEADER *
> > -GetNextVariablePtr (
> > - IN VARIABLE_STORE_INFO *StoreInfo,
> > - IN VARIABLE_HEADER *Variable,
> > - IN VARIABLE_HEADER *VariableHeader
> > - )
> > -{
> > - EFI_PHYSICAL_ADDRESS TargetAddress;
> > - EFI_PHYSICAL_ADDRESS SpareAddress;
> > - UINTN Value;
> > -
> > - Value = (UINTN)GetVariableDataPtr (Variable, VariableHeader, StoreInfo-
> > >AuthFlag);
> > - Value += DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag);
> > - Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo-
> > >AuthFlag));
> > - //
> > - // Be careful about pad size for alignment
> > - //
> > - Value = HEADER_ALIGN (Value);
> > -
> > - if (StoreInfo->FtwLastWriteData != NULL) {
> > - TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
> > - SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
> > - if (((UINTN)Variable < (UINTN)TargetAddress) && (Value >=
> > (UINTN)TargetAddress)) {
> > - //
> > - // Next variable is in spare block.
> > - //
> > - Value = (UINTN)SpareAddress + (Value - (UINTN)TargetAddress);
> > - }
> > - }
> > -
> > - return (VARIABLE_HEADER *)Value;
> > -}
> > -
> > -/**
> > - Get variable store status.
> > -
> > - @param VarStoreHeader Pointer to the Variable Store Header.
> > -
> > - @retval EfiRaw Variable store is raw
> > - @retval EfiValid Variable store is valid
> > - @retval EfiInvalid Variable store is invalid
> > -
> > -**/
> > -VARIABLE_STORE_STATUS
> > -GetVariableStoreStatus (
> > - IN VARIABLE_STORE_HEADER *VarStoreHeader
> > - )
> > -{
> > - if ((CompareGuid (&VarStoreHeader->Signature,
> > &gEfiAuthenticatedVariableGuid) ||
> > - CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) &&
> > - (VarStoreHeader->Format == VARIABLE_STORE_FORMATTED) &&
> > - (VarStoreHeader->State == VARIABLE_STORE_HEALTHY)
> > - )
> > - {
> > - return EfiValid;
> > - }
> > -
> > - if ((((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff) &&
> > - (((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff) &&
> > - (((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff) &&
> > - (((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff) &&
> > - (VarStoreHeader->Size == 0xffffffff) &&
> > - (VarStoreHeader->Format == 0xff) &&
> > - (VarStoreHeader->State == 0xff)
> > - )
> > - {
> > - return EfiRaw;
> > - } else {
> > - return EfiInvalid;
> > - }
> > -}
> > -
> > -/**
> > - Compare two variable names, one of them may be inconsecutive.
> > -
> > - @param StoreInfo Pointer to variable store info structure.
> > - @param Name1 Pointer to one variable name.
> > - @param Name2 Pointer to another variable name.
> > - @param NameSize Variable name size.
> > -
> > - @retval TRUE Name1 and Name2 are identical.
> > - @retval FALSE Name1 and Name2 are not identical.
> > -
> > -**/
> > -BOOLEAN
> > -CompareVariableName (
> > - IN VARIABLE_STORE_INFO *StoreInfo,
> > - IN CONST CHAR16 *Name1,
> > - IN CONST CHAR16 *Name2,
> > - IN UINTN NameSize
> > - )
> > -{
> > - EFI_PHYSICAL_ADDRESS TargetAddress;
> > - EFI_PHYSICAL_ADDRESS SpareAddress;
> > - UINTN PartialNameSize;
> > -
> > - if (StoreInfo->FtwLastWriteData != NULL) {
> > - TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
> > - SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
> > - if (((UINTN)Name1 < (UINTN)TargetAddress) && (((UINTN)Name1 +
> > NameSize) > (UINTN)TargetAddress)) {
> > - //
> > - // Name1 is inconsecutive.
> > - //
> > - PartialNameSize = (UINTN)TargetAddress - (UINTN)Name1;
> > - //
> > - // Partial content is in NV storage.
> > - //
> > - if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, PartialNameSize) ==
> 0)
> > {
> > - //
> > - // Another partial content is in spare block.
> > - //
> > - if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name2 +
> > PartialNameSize, NameSize - PartialNameSize) == 0) {
> > - return TRUE;
> > - }
> > - }
> > -
> > - return FALSE;
> > - } else if (((UINTN)Name2 < (UINTN)TargetAddress) && (((UINTN)Name2 +
> > NameSize) > (UINTN)TargetAddress)) {
> > - //
> > - // Name2 is inconsecutive.
> > - //
> > - PartialNameSize = (UINTN)TargetAddress - (UINTN)Name2;
> > - //
> > - // Partial content is in NV storage.
> > - //
> > - if (CompareMem ((UINT8 *)Name2, (UINT8 *)Name1, PartialNameSize) ==
> 0)
> > {
> > - //
> > - // Another partial content is in spare block.
> > - //
> > - if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name1 +
> > PartialNameSize, NameSize - PartialNameSize) == 0) {
> > - return TRUE;
> > - }
> > - }
> > -
> > - return FALSE;
> > - }
> > - }
> > -
> > - //
> > - // Both Name1 and Name2 are consecutive.
> > - //
> > - if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, NameSize) == 0) {
> > - return TRUE;
> > - }
> > -
> > - return FALSE;
> > -}
> > -
> > -/**
> > - This function compares a variable with variable entries in database.
> > -
> > - @param StoreInfo Pointer to variable store info structure.
> > - @param Variable Pointer to the variable in our database
> > - @param VariableHeader Pointer to the Variable Header that has
> consecutive
> > content.
> > - @param VariableName Name of the variable to compare to 'Variable'
> > - @param VendorGuid GUID of the variable to compare to 'Variable'
> > - @param PtrTrack Variable Track Pointer structure that contains Variable
> > Information.
> > -
> > - @retval EFI_SUCCESS Found match variable
> > - @retval EFI_NOT_FOUND Variable not found
> > -
> > -**/
> > -EFI_STATUS
> > -CompareWithValidVariable (
> > - IN VARIABLE_STORE_INFO *StoreInfo,
> > - IN VARIABLE_HEADER *Variable,
> > - IN VARIABLE_HEADER *VariableHeader,
> > - IN CONST CHAR16 *VariableName,
> > - IN CONST EFI_GUID *VendorGuid,
> > - OUT VARIABLE_POINTER_TRACK *PtrTrack
> > - )
> > -{
> > - VOID *Point;
> > - EFI_GUID *TempVendorGuid;
> > -
> > - TempVendorGuid = GetVendorGuidPtr (VariableHeader, StoreInfo->AuthFlag);
> > -
> > - if (VariableName[0] == 0) {
> > - PtrTrack->CurrPtr = Variable;
> > - return EFI_SUCCESS;
> > - } else {
> > - //
> > - // Don't use CompareGuid function here for performance reasons.
> > - // Instead we compare the GUID a UINT32 at a time and branch
> > - // on the first failed comparison.
> > - //
> > - if ((((INT32 *)VendorGuid)[0] == ((INT32 *)TempVendorGuid)[0]) &&
> > - (((INT32 *)VendorGuid)[1] == ((INT32 *)TempVendorGuid)[1]) &&
> > - (((INT32 *)VendorGuid)[2] == ((INT32 *)TempVendorGuid)[2]) &&
> > - (((INT32 *)VendorGuid)[3] == ((INT32 *)TempVendorGuid)[3])
> > - )
> > - {
> > - ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != 0);
> > - Point = (VOID *)GetVariableNamePtr (Variable, StoreInfo->AuthFlag);
> > - if (CompareVariableName (StoreInfo, VariableName, Point,
> > NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag))) {
> > - PtrTrack->CurrPtr = Variable;
> > - return EFI_SUCCESS;
> > - }
> > - }
> > - }
> > -
> > - return EFI_NOT_FOUND;
> > -}
> > -
> > -/**
> > - Get HOB variable store.
> > -
> > - @param[out] StoreInfo Return the store info.
> > - @param[out] VariableStoreHeader Return variable store header.
> > -
> > -**/
> > -VOID
> > -GetHobVariableStore (
> > - OUT VARIABLE_STORE_INFO *StoreInfo,
> > - OUT VARIABLE_STORE_HEADER **VariableStoreHeader
> > - )
> > -{
> > - EFI_HOB_GUID_TYPE *GuidHob;
> > -
> > - //
> > - // Make sure there is no more than one Variable HOB.
> > - //
> > - DEBUG_CODE_BEGIN ();
> > - GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
> > - if (GuidHob != NULL) {
> > - if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB
> > (GuidHob)) != NULL)) {
> > - DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n"));
> > - ASSERT (FALSE);
> > - } else if (GetFirstGuidHob (&gEfiVariableGuid) != NULL) {
> > - DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable
> > HOBs\n"));
> > - ASSERT (FALSE);
> > - }
> > - } else {
> > - GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
> > - if (GuidHob != NULL) {
> > - if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) !=
> > NULL)) {
> > - DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n"));
> > - ASSERT (FALSE);
> > - }
> > - }
> > - }
> > -
> > - DEBUG_CODE_END ();
> > -
> > - GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
> > - if (GuidHob != NULL) {
> > - *VariableStoreHeader = (VARIABLE_STORE_HEADER
> > *)GET_GUID_HOB_DATA (GuidHob);
> > - StoreInfo->AuthFlag = TRUE;
> > - } else {
> > - GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
> > - if (GuidHob != NULL) {
> > - *VariableStoreHeader = (VARIABLE_STORE_HEADER
> > *)GET_GUID_HOB_DATA (GuidHob);
> > - StoreInfo->AuthFlag = FALSE;
> > - }
> > - }
> > -}
> > -
> > -/**
> > - Return the variable store header and the store info based on the Index.
> > -
> > - @param Type The type of the variable store.
> > - @param StoreInfo Return the store info.
> > -
> > - @return Pointer to the variable store header.
> > -**/
> > -VARIABLE_STORE_HEADER *
> > -GetVariableStore (
> > - IN VARIABLE_STORE_TYPE Type,
> > - OUT VARIABLE_STORE_INFO *StoreInfo
> > - )
> > -{
> > - EFI_STATUS Status;
> > - EFI_HOB_GUID_TYPE *GuidHob;
> > - EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
> > - VARIABLE_STORE_HEADER *VariableStoreHeader;
> > - EFI_PHYSICAL_ADDRESS NvStorageBase;
> > - UINT32 NvStorageSize;
> > - UINT64 NvStorageSize64;
> > - FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
> > - UINT32 BackUpOffset;
> > -
> > - StoreInfo->IndexTable = NULL;
> > - StoreInfo->FtwLastWriteData = NULL;
> > - StoreInfo->AuthFlag = FALSE;
> > - VariableStoreHeader = NULL;
> > - switch (Type) {
> > - case VariableStoreTypeHob:
> > - GetHobVariableStore (StoreInfo, &VariableStoreHeader);
> > -
> > - break;
> > -
> > - case VariableStoreTypeNv:
> > - if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {
> > - //
> > - // Emulated non-volatile variable mode is not enabled.
> > - //
> > -
> > - Status = GetVariableFlashNvStorageInfo (&NvStorageBase,
> > &NvStorageSize64);
> > - ASSERT_EFI_ERROR (Status);
> > -
> > - Status = SafeUint64ToUint32 (NvStorageSize64, &NvStorageSize);
> > - // This driver currently assumes the size will be UINT32 so assert the
> value
> > is safe for now.
> > - ASSERT_EFI_ERROR (Status);
> > -
> > - ASSERT (NvStorageBase != 0);
> > -
> > - //
> > - // First let FvHeader point to NV storage base.
> > - //
> > - FvHeader = (EFI_FIRMWARE_VOLUME_HEADER
> *)(UINTN)NvStorageBase;
> > -
> > - //
> > - // Check the FTW last write data hob.
> > - //
> > - BackUpOffset = 0;
> > - GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
> > - if (GuidHob != NULL) {
> > - FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA
> > *)GET_GUID_HOB_DATA (GuidHob);
> > - if (FtwLastWriteData->TargetAddress == NvStorageBase) {
> > - //
> > - // Let FvHeader point to spare block.
> > - //
> > - FvHeader = (EFI_FIRMWARE_VOLUME_HEADER
> > *)(UINTN)FtwLastWriteData->SpareAddress;
> > - DEBUG ((DEBUG_INFO, "PeiVariable: NV storage is backed up in spare
> > block: 0x%x\n", (UINTN)FtwLastWriteData->SpareAddress));
> > - } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&
> > (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {
> > - StoreInfo->FtwLastWriteData = FtwLastWriteData;
> > - //
> > - // Flash NV storage from the offset is backed up in spare block.
> > - //
> > - BackUpOffset = (UINT32)(FtwLastWriteData->TargetAddress -
> > NvStorageBase);
> > - DEBUG ((DEBUG_INFO, "PeiVariable: High partial NV storage from
> > offset: %x is backed up in spare block: 0x%x\n", BackUpOffset,
> > (UINTN)FtwLastWriteData->SpareAddress));
> > - //
> > - // At least one block data in flash NV storage is still valid, so still leave
> > FvHeader point to NV storage base.
> > - //
> > - }
> > - }
> > -
> > - //
> > - // Check if the Firmware Volume is not corrupted
> > - //
> > - if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid
> > (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
> > - DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is
> > corrupted\n"));
> > - break;
> > - }
> > -
> > - VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINT8 *)FvHeader
> +
> > FvHeader->HeaderLength);
> > -
> > - StoreInfo->AuthFlag = (BOOLEAN)(CompareGuid (&VariableStoreHeader-
> > >Signature, &gEfiAuthenticatedVariableGuid));
> > -
> > - GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
> > - if (GuidHob != NULL) {
> > - StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);
> > - } else {
> > - //
> > - // If it's the first time to access variable region in flash, create a guid hob
> > to record
> > - // VAR_ADDED type variable info.
> > - // Note that as the resource of PEI phase is limited, only store the
> limited
> > number of
> > - // VAR_ADDED type variables to reduce access time.
> > - //
> > - StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE
> *)BuildGuidHob
> > (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
> > - StoreInfo->IndexTable->Length = 0;
> > - StoreInfo->IndexTable->StartPtr = GetStartPointer
> > (VariableStoreHeader);
> > - StoreInfo->IndexTable->EndPtr = GetEndPointer
> (VariableStoreHeader);
> > - StoreInfo->IndexTable->GoneThrough = 0;
> > - }
> > - }
> > -
> > - break;
> > -
> > - default:
> > - ASSERT (FALSE);
> > - break;
> > - }
> > -
> > - StoreInfo->VariableStoreHeader = VariableStoreHeader;
> > - return VariableStoreHeader;
> > -}
> > -
> > -/**
> > - Get variable header that has consecutive content.
> > -
> > - @param StoreInfo Pointer to variable store info structure.
> > - @param Variable Pointer to the Variable Header.
> > - @param VariableHeader Pointer to Pointer to the Variable Header that has
> > consecutive content.
> > -
> > - @retval TRUE Variable header is valid.
> > - @retval FALSE Variable header is not valid.
> > -
> > -**/
> > -BOOLEAN
> > -GetVariableHeader (
> > - IN VARIABLE_STORE_INFO *StoreInfo,
> > - IN VARIABLE_HEADER *Variable,
> > - OUT VARIABLE_HEADER **VariableHeader
> > - )
> > -{
> > - EFI_PHYSICAL_ADDRESS TargetAddress;
> > - EFI_PHYSICAL_ADDRESS SpareAddress;
> > - EFI_HOB_GUID_TYPE *GuidHob;
> > - UINTN PartialHeaderSize;
> > -
> > - if (Variable == NULL) {
> > - return FALSE;
> > - }
> > -
> > - //
> > - // First assume variable header pointed by Variable is consecutive.
> > - //
> > - *VariableHeader = Variable;
> > -
> > - if (StoreInfo->FtwLastWriteData != NULL) {
> > - TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
> > - SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
> > - if (((UINTN)Variable > (UINTN)SpareAddress) &&
> > - (((UINTN)Variable - (UINTN)SpareAddress + (UINTN)TargetAddress) >=
> > (UINTN)GetEndPointer (StoreInfo->VariableStoreHeader)))
> > - {
> > - //
> > - // Reach the end of variable store.
> > - //
> > - return FALSE;
> > - }
> > -
> > - if (((UINTN)Variable < (UINTN)TargetAddress) && (((UINTN)Variable +
> > GetVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN)TargetAddress)) {
> > - //
> > - // Variable header pointed by Variable is inconsecutive,
> > - // create a guid hob to combine the two partial variable header content
> > together.
> > - //
> > - GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
> > - if (GuidHob != NULL) {
> > - *VariableHeader = (VARIABLE_HEADER *)GET_GUID_HOB_DATA
> (GuidHob);
> > - } else {
> > - *VariableHeader = (VARIABLE_HEADER *)BuildGuidHob
> (&gEfiCallerIdGuid,
> > GetVariableHeaderSize (StoreInfo->AuthFlag));
> > - PartialHeaderSize = (UINTN)TargetAddress - (UINTN)Variable;
> > - //
> > - // Partial content is in NV storage.
> > - //
> > - CopyMem ((UINT8 *)*VariableHeader, (UINT8 *)Variable,
> > PartialHeaderSize);
> > - //
> > - // Another partial content is in spare block.
> > - //
> > - CopyMem ((UINT8 *)*VariableHeader + PartialHeaderSize, (UINT8
> > *)(UINTN)SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) -
> > PartialHeaderSize);
> > - }
> > - }
> > - } else {
> > - if (Variable >= GetEndPointer (StoreInfo->VariableStoreHeader)) {
> > - //
> > - // Reach the end of variable store.
> > - //
> > - return FALSE;
> > - }
> > - }
> > -
> > - return IsValidVariableHeader (*VariableHeader);
> > -}
> > -
> > -/**
> > - Get variable name or data to output buffer.
> > -
> > - @param StoreInfo Pointer to variable store info structure.
> > - @param NameOrData Pointer to the variable name/data that may be
> > inconsecutive.
> > - @param Size Variable name/data size.
> > - @param Buffer Pointer to output buffer to hold the variable name/data.
> > -
> > -**/
> > -VOID
> > -GetVariableNameOrData (
> > - IN VARIABLE_STORE_INFO *StoreInfo,
> > - IN UINT8 *NameOrData,
> > - IN UINTN Size,
> > - OUT UINT8 *Buffer
> > - )
> > -{
> > - EFI_PHYSICAL_ADDRESS TargetAddress;
> > - EFI_PHYSICAL_ADDRESS SpareAddress;
> > - UINTN PartialSize;
> > -
> > - if (StoreInfo->FtwLastWriteData != NULL) {
> > - TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
> > - SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
> > - if (((UINTN)NameOrData < (UINTN)TargetAddress) &&
> > (((UINTN)NameOrData + Size) > (UINTN)TargetAddress)) {
> > - //
> > - // Variable name/data is inconsecutive.
> > - //
> > - PartialSize = (UINTN)TargetAddress - (UINTN)NameOrData;
> > - //
> > - // Partial content is in NV storage.
> > - //
> > - CopyMem (Buffer, NameOrData, PartialSize);
> > - //
> > - // Another partial content is in spare block.
> > - //
> > - CopyMem (Buffer + PartialSize, (UINT8 *)(UINTN)SpareAddress, Size -
> > PartialSize);
> > - return;
> > - }
> > - }
> > -
> > - //
> > - // Variable name/data is consecutive.
> > - //
> > - CopyMem (Buffer, NameOrData, Size);
> > -}
> > -
> > /**
> > Find the variable in the specified variable store.
> >
> > @@ -1250,3 +522,107 @@ PeiGetNextVariableName (
> > }
> > }
> > }
> > +
> > +/**
> > + This service retrieves a variable's value using its name and GUID.
> > +
> > + Read the specified variable from the UEFI variable store. If the Data
> > + buffer is too small to hold the contents of the variable, the error
> > + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required
> buffer
> > + size to obtain the data.
> > +
> > + @param This A pointer to this instance of the
> > EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> > + @param VariableName A pointer to a null-terminated string that is the
> > variable's name.
> > + @param VariableGuid A pointer to an EFI_GUID that is the variable's
> > GUID. The combination of
> > + VariableGuid and VariableName must be unique.
> > + @param Attributes If non-NULL, on return, points to the variable's
> > attributes.
> > + @param DataSize On entry, points to the size in bytes of the Data
> > buffer.
> > + On return, points to the size of the data returned in Data.
> > + @param Data Points to the buffer which will hold the returned
> > variable value.
> > + May be NULL with a zero DataSize in order to determine the
> > size of the buffer needed.
> > +
> > + @retval EFI_SUCCESS The variable was read successfully.
> > + @retval EFI_NOT_FOUND The variable was be found.
> > + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the
> resulting
> > data.
> > + DataSize is updated with the size required for
> > + the specified variable.
> > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or
> > Data is NULL.
> > + @retval EFI_DEVICE_ERROR The variable could not be retrieved because
> of
> > a device error.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +PeiGetVariableEx (
> > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
> > + IN CONST CHAR16 *VariableName,
> > + IN CONST EFI_GUID *VariableGuid,
> > + OUT UINT32 *Attributes,
> > + IN OUT UINTN *DataSize,
> > + OUT VOID *Data OPTIONAL
> > + )
> > +{
> > + EFI_STATUS Status;
> > +
> > + //
> > + // If variable protection is employed, always get variable data through
> > + // ProtectedVariableLib.
> > + //
> > + Status = ProtectedVariableLibGetByName (VariableName, VariableGuid,
> > Attributes, DataSize, Data);
> > + if (Status != EFI_UNSUPPORTED) {
> > + return Status;
> > + }
> > +
> > + return PeiGetVariable (This, VariableName, VariableGuid, Attributes,
> DataSize,
> > Data);
> > +}
> > +
> > +/**
> > + Return the next variable name and GUID.
> > +
> > + This function is called multiple times to retrieve the VariableName
> > + and VariableGuid of all variables currently available in the system.
> > + On each call, the previous results are passed into the interface,
> > + and, on return, the interface returns the data for the next
> > + interface. When the entire variable list has been returned,
> > + EFI_NOT_FOUND is returned.
> > +
> > + @param This A pointer to this instance of the
> > EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> > +
> > + @param VariableNameSize On entry, points to the size of the buffer
> pointed
> > to by VariableName.
> > + On return, the size of the variable name buffer.
> > + @param VariableName On entry, a pointer to a null-terminated string
> that
> > is the variable's name.
> > + On return, points to the next variable's null-terminated name
> > string.
> > + @param VariableGuid On entry, a pointer to an EFI_GUID that is the
> > variable's GUID.
> > + On return, a pointer to the next variable's GUID.
> > +
> > + @retval EFI_SUCCESS The variable was read successfully.
> > + @retval EFI_NOT_FOUND The variable could not be found.
> > + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for
> the
> > resulting
> > + data. VariableNameSize is updated with the size
> > + required for the specified variable.
> > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
> > + VariableNameSize is NULL.
> > + @retval EFI_DEVICE_ERROR The variable could not be retrieved because
> of
> > a device error.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +PeiGetNextVariableNameEx (
> > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
> > + IN OUT UINTN *VariableNameSize,
> > + IN OUT CHAR16 *VariableName,
> > + IN OUT EFI_GUID *VariableGuid
> > + )
> > +{
> > + EFI_STATUS Status;
> > +
> > + //
> > + // If variable protection is employed, always get next variable through
> > + // ProtectedVariableLib.
> > + //
> > + Status = ProtectedVariableLibFindNext (VariableNameSize, VariableName,
> > VariableGuid);
> > + if (Status != EFI_UNSUPPORTED) {
> > + return Status;
> > + }
> > +
> > + return PeiGetNextVariableName (This, VariableNameSize, VariableName,
> > VariableGuid);
> > +}
> > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariableParsing.c
> > b/MdeModulePkg/Universal/Variable/Pei/VariableParsing.c
> > new file mode 100644
> > index 000000000000..2d605d39cbb6
> > --- /dev/null
> > +++ b/MdeModulePkg/Universal/Variable/Pei/VariableParsing.c
> > @@ -0,0 +1,941 @@
> > +/** @file
> > + Implement ReadOnly Variable Services required by PEIM and install
> > + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile
> storage
> > space.
>
> [JianJW] typo: "Varaiable2" -> "Variable2"
>
> > +
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "Variable.h"
> > +#include "VariableStore.h"
> > +
> > +/**
> > +
> > + Gets the pointer to the first variable header in given variable store area.
> > +
> > + @param[in] VarStoreHeader Pointer to the Variable Store Header.
> > +
> > + @return Pointer to the first variable header.
> > +
> > +**/
> > +VARIABLE_HEADER *
> > +GetStartPointer (
> > + IN VARIABLE_STORE_HEADER *VarStoreHeader
> > + )
> > +{
> > + //
> > + // The start of variable store
> > + //
> > + return (VARIABLE_HEADER *)HEADER_ALIGN (VarStoreHeader + 1);
> > +}
> > +
> > +/**
> > +
> > + Gets the pointer to the end of the variable storage area.
> > +
> > + This function gets pointer to the end of the variable storage
> > + area, according to the input variable store header.
> > +
> > + @param[in] VarStoreHeader Pointer to the Variable Store Header.
> > +
> > + @return Pointer to the end of the variable storage area.
> > +
> > +**/
> > +VARIABLE_HEADER *
> > +GetEndPointer (
> > + IN VARIABLE_STORE_HEADER *VarStoreHeader
> > + )
> > +{
> > + //
> > + // The end of variable store
> > + //
> > + return (VARIABLE_HEADER *)HEADER_ALIGN ((UINTN)VarStoreHeader +
> > VarStoreHeader->Size);
> > +}
> > +
> > +/**
> > + This code checks if variable header is valid or not.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > +
> > + @retval TRUE Variable header is valid.
> > + @retval FALSE Variable header is not valid.
> > +
> > +**/
> > +BOOLEAN
> > +IsValidVariableHeader (
> > + IN VARIABLE_HEADER *Variable
> > + )
> > +{
> > + if ((Variable == NULL) || (Variable->StartId != VARIABLE_DATA)) {
> > + return FALSE;
> > + }
> > +
> > + return TRUE;
> > +}
> > +
> > +/**
> > + This code gets the size of variable header.
> > +
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return Size of variable header in bytes in type UINTN.
> > +
> > +**/
> > +UINTN
> > +GetVariableHeaderSize (
> > + IN BOOLEAN AuthFlag
> > + )
> > +{
> > + UINTN Value;
> > +
> > + if (AuthFlag) {
> > + Value = sizeof (AUTHENTICATED_VARIABLE_HEADER);
> > + } else {
> > + Value = sizeof (VARIABLE_HEADER);
> > + }
> > +
> > + return Value;
> > +}
> > +
> > +/**
> > + This code gets the size of name of variable.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return Size of variable in bytes in type UINTN.
> > +
> > +**/
> > +UINTN
> > +NameSizeOfVariable (
> > + IN VARIABLE_HEADER *Variable,
> > + IN BOOLEAN AuthFlag
> > + )
> > +{
> > + AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
> > +
> > + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable;
> > + if (AuthFlag) {
> > + if ((AuthVariable->State == (UINT8)(-1)) ||
> > + (AuthVariable->DataSize == (UINT32)(-1)) ||
> > + (AuthVariable->NameSize == (UINT32)(-1)) ||
> > + (AuthVariable->Attributes == (UINT32)(-1)))
> > + {
> > + return 0;
> > + }
> > +
> > + return (UINTN)AuthVariable->NameSize;
> > + } else {
> > + if ((Variable->State == (UINT8)(-1)) ||
> > + (Variable->DataSize == (UINT32)(-1)) ||
> > + (Variable->NameSize == (UINT32)(-1)) ||
> > + (Variable->Attributes == (UINT32)(-1)))
> > + {
> > + return 0;
> > + }
> > +
> > + return (UINTN)Variable->NameSize;
> > + }
> > +}
> > +
> > +/**
> > + This code gets the size of data of variable.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return Size of variable in bytes in type UINTN.
> > +
> > +**/
> > +UINTN
> > +DataSizeOfVariable (
> > + IN VARIABLE_HEADER *Variable,
> > + IN BOOLEAN AuthFlag
> > + )
> > +{
> > + AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
> > +
> > + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable;
> > + if (AuthFlag) {
> > + if ((AuthVariable->State == (UINT8)(-1)) ||
> > + (AuthVariable->DataSize == (UINT32)(-1)) ||
> > + (AuthVariable->NameSize == (UINT32)(-1)) ||
> > + (AuthVariable->Attributes == (UINT32)(-1)))
> > + {
> > + return 0;
> > + }
> > +
> > + return (UINTN)AuthVariable->DataSize;
> > + } else {
> > + if ((Variable->State == (UINT8)(-1)) ||
> > + (Variable->DataSize == (UINT32)(-1)) ||
> > + (Variable->NameSize == (UINT32)(-1)) ||
> > + (Variable->Attributes == (UINT32)(-1)))
> > + {
> > + return 0;
> > + }
> > +
> > + return (UINTN)Variable->DataSize;
> > + }
> > +}
> > +
> > +/**
> > + This code gets the pointer to the variable name.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return A CHAR16* pointer to Variable Name.
> > +
> > +**/
> > +CHAR16 *
> > +GetVariableNamePtr (
> > + IN VARIABLE_HEADER *Variable,
> > + IN BOOLEAN AuthFlag
> > + )
> > +{
> > + return (CHAR16 *)((UINTN)Variable + GetVariableHeaderSize (AuthFlag));
> > +}
> > +
> > +/**
> > + This code gets the pointer to the variable guid.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return A EFI_GUID* pointer to Vendor Guid.
> > +
> > +**/
> > +EFI_GUID *
> > +GetVendorGuidPtr (
> > + IN VARIABLE_HEADER *Variable,
> > + IN BOOLEAN AuthFlag
> > + )
> > +{
> > + AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
> > +
> > + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable;
> > + if (AuthFlag) {
> > + return &AuthVariable->VendorGuid;
> > + } else {
> > + return &Variable->VendorGuid;
> > + }
> > +}
> > +
> > +/**
> > + This code gets the pointer to the variable data.
> > +
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] VariableHeader Pointer to the Variable Header that has
> > consecutive content.
> > + @param[in] AuthFlag Authenticated variable flag.
> > +
> > + @return A UINT8* pointer to Variable Data.
> > +
> > +**/
> > +UINT8 *
> > +GetVariableDataPtr (
> > + IN VARIABLE_HEADER *Variable,
> > + IN VARIABLE_HEADER *VariableHeader,
> > + IN BOOLEAN AuthFlag
> > + )
> > +{
> > + UINTN Value;
> > +
> > + //
> > + // Be careful about pad size for alignment
> > + //
> > + Value = (UINTN)GetVariableNamePtr (Variable, AuthFlag);
> > + Value += NameSizeOfVariable (VariableHeader, AuthFlag);
> > + Value += GET_PAD_SIZE (NameSizeOfVariable (VariableHeader, AuthFlag));
> > +
> > + return (UINT8 *)Value;
> > +}
> > +
> > +/**
> > + This code gets the pointer to the next variable header.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[in] VariableHeader Pointer to the Variable Header that has
> > consecutive content.
> > +
> > + @return A VARIABLE_HEADER* pointer to next variable header.
> > +
> > +**/
> > +VARIABLE_HEADER *
> > +GetNextVariablePtr (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN VARIABLE_HEADER *Variable,
> > + IN VARIABLE_HEADER *VariableHeader
> > + )
> > +{
> > + EFI_PHYSICAL_ADDRESS TargetAddress;
> > + EFI_PHYSICAL_ADDRESS SpareAddress;
> > + UINTN Value;
> > +
> > + Value = (UINTN)GetVariableDataPtr (Variable, VariableHeader, StoreInfo-
> > >AuthFlag);
> > + Value += DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag);
> > + Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo-
> > >AuthFlag));
> > + //
> > + // Be careful about pad size for alignment
> > + //
> > + Value = HEADER_ALIGN (Value);
> > +
> > + if (StoreInfo->FtwLastWriteData != NULL) {
> > + TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
> > + SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
> > + if (((UINTN)Variable < (UINTN)TargetAddress) && (Value >=
> > (UINTN)TargetAddress)) {
> > + //
> > + // Next variable is in spare block.
> > + //
> > + Value = (UINTN)SpareAddress + (Value - (UINTN)TargetAddress);
> > + }
> > + }
> > +
> > + return (VARIABLE_HEADER *)Value;
> > +}
> > +
> > +/**
> > + Compare two variable names, one of them may be inconsecutive.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] Name1 Pointer to one variable name.
> > + @param[in] Name2 Pointer to another variable name.
> > + @param[in] NameSize Variable name size.
> > +
> > + @retval TRUE Name1 and Name2 are identical.
> > + @retval FALSE Name1 and Name2 are not identical.
> > +
> > +**/
> > +BOOLEAN
> > +CompareVariableName (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN CONST CHAR16 *Name1,
> > + IN CONST CHAR16 *Name2,
> > + IN UINTN NameSize
> > + )
> > +{
> > + EFI_PHYSICAL_ADDRESS TargetAddress;
> > + EFI_PHYSICAL_ADDRESS SpareAddress;
> > + UINTN PartialNameSize;
> > +
> > + if (StoreInfo->FtwLastWriteData != NULL) {
> > + TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
> > + SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
> > + if (((UINTN)Name1 < (UINTN)TargetAddress) && (((UINTN)Name1 +
> > NameSize) > (UINTN)TargetAddress)) {
> > + //
> > + // Name1 is inconsecutive.
> > + //
> > + PartialNameSize = (UINTN)TargetAddress - (UINTN)Name1;
> > + //
> > + // Partial content is in NV storage.
> > + //
> > + if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, PartialNameSize)
> ==
> > 0) {
> > + //
> > + // Another partial content is in spare block.
> > + //
> > + if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name2 +
> > PartialNameSize, NameSize - PartialNameSize) == 0) {
> > + return TRUE;
> > + }
> > + }
> > +
> > + return FALSE;
> > + } else if (((UINTN)Name2 < (UINTN)TargetAddress) && (((UINTN)Name2 +
> > NameSize) > (UINTN)TargetAddress)) {
> > + //
> > + // Name2 is inconsecutive.
> > + //
> > + PartialNameSize = (UINTN)TargetAddress - (UINTN)Name2;
> > + //
> > + // Partial content is in NV storage.
> > + //
> > + if (CompareMem ((UINT8 *)Name2, (UINT8 *)Name1, PartialNameSize)
> ==
> > 0) {
> > + //
> > + // Another partial content is in spare block.
> > + //
> > + if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name1 +
> > PartialNameSize, NameSize - PartialNameSize) == 0) {
> > + return TRUE;
> > + }
> > + }
> > +
> > + return FALSE;
> > + }
> > + }
> > +
> > + //
> > + // Both Name1 and Name2 are consecutive.
> > + //
> > + if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, NameSize) == 0) {
> > + return TRUE;
> > + }
> > +
> > + return FALSE;
> > +}
> > +
> > +/**
> > + This function compares a variable with variable entries in database.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] Variable Pointer to the variable in our database
> > + @param[in] VariableHeader Pointer to the Variable Header that has
> > + consecutive content.
> > + @param[in] VariableName Name of the variable to compare to
> 'Variable'
> > + @param[in] VendorGuid GUID of the variable to compare to 'Variable'
> > + @param[out] PtrTrack Variable Track Pointer structure that contains
> > + Variable Information.
> > +
> > + @retval EFI_SUCCESS Found match variable
> > + @retval EFI_NOT_FOUND Variable not found
> > +
> > +**/
> > +EFI_STATUS
> > +CompareWithValidVariable (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN VARIABLE_HEADER *Variable,
> > + IN VARIABLE_HEADER *VariableHeader,
> > + IN CONST CHAR16 *VariableName,
> > + IN CONST EFI_GUID *VendorGuid,
> > + OUT VARIABLE_POINTER_TRACK *PtrTrack
> > + )
> > +{
> > + VOID *Point;
> > + EFI_GUID *TempVendorGuid;
> > +
> > + TempVendorGuid = GetVendorGuidPtr (VariableHeader, StoreInfo-
> >AuthFlag);
> > +
> > + if (VariableName[0] == 0) {
> > + PtrTrack->CurrPtr = Variable;
> > + return EFI_SUCCESS;
> > + } else {
> > + //
> > + // Don't use CompareGuid function here for performance reasons.
> > + // Instead we compare the GUID a UINT32 at a time and branch
> > + // on the first failed comparison.
> > + //
> > + if ((((INT32 *)VendorGuid)[0] == ((INT32 *)TempVendorGuid)[0]) &&
> > + (((INT32 *)VendorGuid)[1] == ((INT32 *)TempVendorGuid)[1]) &&
> > + (((INT32 *)VendorGuid)[2] == ((INT32 *)TempVendorGuid)[2]) &&
> > + (((INT32 *)VendorGuid)[3] == ((INT32 *)TempVendorGuid)[3])
> > + )
> > + {
> > + ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != 0);
> > + Point = (VOID *)GetVariableNamePtr (Variable, StoreInfo->AuthFlag);
> > + if (CompareVariableName (StoreInfo, VariableName, Point,
> > NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag))) {
> > + PtrTrack->CurrPtr = Variable;
> > + return EFI_SUCCESS;
> > + }
> > + }
> > + }
> > +
> > + return EFI_NOT_FOUND;
> > +}
> > +
> > +/**
> > + Get variable header that has consecutive content.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] Variable Pointer to the Variable Header.
> > + @param[out] VariableHeader Pointer to Pointer to the Variable Header
> > + that has consecutive content.
> > +
> > + @retval TRUE Variable header is valid.
> > + @retval FALSE Variable header is not valid.
> > +
> > +**/
> > +BOOLEAN
> > +GetVariableHeader (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN VARIABLE_HEADER *Variable,
> > + OUT VARIABLE_HEADER **VariableHeader
> > + )
> > +{
> > + EFI_PHYSICAL_ADDRESS TargetAddress;
> > + EFI_PHYSICAL_ADDRESS SpareAddress;
> > + EFI_HOB_GUID_TYPE *GuidHob;
> > + UINTN PartialHeaderSize;
> > +
> > + if (Variable == NULL) {
> > + return FALSE;
> > + }
> > +
> > + //
> > + // First assume variable header pointed by Variable is consecutive.
> > + //
> > + *VariableHeader = Variable;
> > +
> > + if (StoreInfo->FtwLastWriteData != NULL) {
> > + TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
> > + SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
> > + if (((UINTN)Variable > (UINTN)SpareAddress) &&
> > + (((UINTN)Variable - (UINTN)SpareAddress + (UINTN)TargetAddress) >=
> > (UINTN)GetEndPointer (StoreInfo->VariableStoreHeader)))
> > + {
> > + //
> > + // Reach the end of variable store.
> > + //
> > + return FALSE;
> > + }
> > +
> > + if (((UINTN)Variable < (UINTN)TargetAddress) && (((UINTN)Variable +
> > GetVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN)TargetAddress)) {
> > + //
> > + // Variable header pointed by Variable is inconsecutive,
> > + // create a guid hob to combine the two partial variable header content
> > together.
> > + //
> > + GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
> > + if (GuidHob != NULL) {
> > + *VariableHeader = (VARIABLE_HEADER *)GET_GUID_HOB_DATA
> > (GuidHob);
> > + } else {
> > + *VariableHeader = (VARIABLE_HEADER *)BuildGuidHob
> > (&gEfiCallerIdGuid, GetVariableHeaderSize (StoreInfo->AuthFlag));
> > + PartialHeaderSize = (UINTN)TargetAddress - (UINTN)Variable;
> > + //
> > + // Partial content is in NV storage.
> > + //
> > + CopyMem ((UINT8 *)*VariableHeader, (UINT8 *)Variable,
> > PartialHeaderSize);
> > + //
> > + // Another partial content is in spare block.
> > + //
> > + CopyMem ((UINT8 *)*VariableHeader + PartialHeaderSize, (UINT8
> > *)(UINTN)SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) -
> > PartialHeaderSize);
> > + }
> > + }
> > + } else {
> > + if (Variable >= GetEndPointer (StoreInfo->VariableStoreHeader)) {
> > + //
> > + // Reach the end of variable store.
> > + //
> > + return FALSE;
> > + }
> > + }
> > +
> > + return IsValidVariableHeader (*VariableHeader);
> > +}
> > +
> > +/**
> > + Get variable name or data to output buffer.
> > +
> > + @param[in] StoreInfo Pointer to variable store info structure.
> > + @param[in] NameOrData Pointer to the variable name/data that may be
> > inconsecutive.
> > + @param[in] Size Variable name/data size.
> > + @param[out] Buffer Pointer to output buffer to hold the variable
> > name/data.
> > +
> > +**/
> > +VOID
> > +GetVariableNameOrData (
> > + IN VARIABLE_STORE_INFO *StoreInfo,
> > + IN UINT8 *NameOrData,
> > + IN UINTN Size,
> > + OUT UINT8 *Buffer
> > + )
> > +{
> > + EFI_PHYSICAL_ADDRESS TargetAddress;
> > + EFI_PHYSICAL_ADDRESS SpareAddress;
> > + UINTN PartialSize;
> > +
> > + if (StoreInfo->FtwLastWriteData != NULL) {
> > + TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
> > + SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
> > + if (((UINTN)NameOrData < (UINTN)TargetAddress) &&
> > (((UINTN)NameOrData + Size) > (UINTN)TargetAddress)) {
> > + //
> > + // Variable name/data is inconsecutive.
> > + //
> > + PartialSize = (UINTN)TargetAddress - (UINTN)NameOrData;
> > + //
> > + // Partial content is in NV storage.
> > + //
> > + CopyMem (Buffer, NameOrData, PartialSize);
> > + //
> > + // Another partial content is in spare block.
> > + //
> > + CopyMem (Buffer + PartialSize, (UINT8 *)(UINTN)SpareAddress, Size -
> > PartialSize);
> > + return;
> > + }
> > + }
> > +
> > + //
> > + // Variable name/data is consecutive.
> > + //
> > + CopyMem (Buffer, NameOrData, Size);
> > +}
> > +
> > +/**
> > +
> > + Internal function to retrieve variable information.
> > +
> > + @param[in,out] VariableInfo Pointer to variable information.
> > + @param[in] StoreInfo Pointer to store copy of variable (optional).
> > + @param[in] VariablePtr Pointer to variable buffer.
> > + @param[in] VariableHeader Pointer to variable header.
> > +
> > + @retval EFI_INVALID_PARAMETER One ore more required parameters are
> > NULL.
> > + @retval EFI_BUFFER_TOO_SMALL Given buffer is too small to hold data.
> > + @retval EFI_SUCCESS Variable details are retrieved successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +GetVariableInfoInternal (
> > + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo,
> > + IN VARIABLE_STORE_INFO *StoreInfo OPTIONAL,
> > + IN VARIABLE_HEADER *VariablePtr,
> > + IN VARIABLE_HEADER *VariableHeader
> > + )
> > +{
> > + VARIABLE_HEADER *VariableBuffer;
> > + AUTHENTICATED_VARIABLE_HEADER *AuthVariableHeader;
> > + UINTN NameSize;
> > + UINTN DataSize;
> > + UINTN VariableSize;
> > +
> > + if ((VariableInfo == NULL) || (VariablePtr == NULL) || (VariableHeader ==
> > NULL)) {
> > + ASSERT (VariableInfo != NULL);
> > + ASSERT (VariablePtr != NULL);
> > + ASSERT (VariableHeader != NULL);
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + VariableBuffer = VariableInfo->Buffer;
> > +
> > + //
> > + // Make a copy of the whole variable if VariableInfo->Buffer is given. But
> > + // don't do this if StoreInfo is not given, because VariableInfo->Buffer
> > + // has already hold a copy of variable in such situation.
> > + //
> > + NameSize = NameSizeOfVariable (VariableHeader, VariableInfo->Flags.Auth);
> > + DataSize = DataSizeOfVariable (VariableHeader, VariableInfo->Flags.Auth);
> > + if ((VariableBuffer != NULL) && (VariableBuffer != VariablePtr)) {
> > + if (StoreInfo != NULL) {
> > + CopyMem (
> > + VariableBuffer,
> > + VariableHeader,
> > + GetVariableHeaderSize (VariableInfo->Flags.Auth)
> > + );
> > + GetVariableNameOrData (
> > + StoreInfo,
> > + (UINT8 *)GetVariableNamePtr (VariablePtr, VariableInfo->Flags.Auth),
> > + NameSize,
> > + (UINT8 *)GetVariableNamePtr (VariableBuffer, VariableInfo->Flags.Auth)
> > + );
> > + GetVariableNameOrData (
> > + StoreInfo,
> > + (UINT8 *)GetVariableDataPtr (VariablePtr, VariableHeader, VariableInfo-
> > >Flags.Auth),
> > + DataSize,
> > + (UINT8 *)GetVariableDataPtr (VariableBuffer, VariableHeader,
> > VariableInfo->Flags.Auth)
> > + );
> > + } else {
> > + //
> > + // Suppose the variable is in consecutive space.
> > + //
> > + VariableSize = GetVariableHeaderSize (VariableInfo->Flags.Auth)
> > + + NameSize + GET_PAD_SIZE (NameSize)
> > + + DataSize;
> > + CopyMem (VariableBuffer, VariablePtr, VariableSize);
> > + }
> > + }
> > +
> > + //
> > + // Generally, if no consecutive buffer passed in, don't return back any data.
> > + //
> > + // If follow pointers are NULL, return back pointers to following data inside
> > + // VariableInfo->Buffer, if it's given.
> > + //
> > + // VariableInfo->Header.VariableName
> > + // VariableInfo->Header.Data
> > + // VariableInfo->Header.VendorGuid
> > + // VariableInfo->Header.TimeStamp
> > + //
> > + // Otherwise, suppose they're buffers used to hold a copy of corresponding
> > + // data.
> > + //
> > + //
> > +
> > + //
> > + // AuthVariable header
> > + //
> > + if (VariableInfo->Flags.Auth) {
> > + AuthVariableHeader = (AUTHENTICATED_VARIABLE_HEADER
> > *)VariableHeader;
> > +
> > + VariableInfo->Header.State = AuthVariableHeader->State;
> > + VariableInfo->Header.Attributes = AuthVariableHeader->Attributes;
> > + VariableInfo->Header.PubKeyIndex = AuthVariableHeader->PubKeyIndex;
> > + VariableInfo->Header.MonotonicCount = ReadUnaligned64 (
> > + &(AuthVariableHeader->MonotonicCount)
> > + );
> > + if (VariableInfo->Header.TimeStamp != NULL) {
> > + CopyMem (
> > + VariableInfo->Header.TimeStamp,
> > + &AuthVariableHeader->TimeStamp,
> > + sizeof (EFI_TIME)
> > + );
> > + } else if (VariableBuffer != NULL) {
> > + AuthVariableHeader = (AUTHENTICATED_VARIABLE_HEADER
> > *)VariableBuffer;
> > + VariableInfo->Header.TimeStamp = &AuthVariableHeader->TimeStamp;
> > + }
> > + } else {
> > + VariableInfo->Header.State = VariableHeader->State;
> > + VariableInfo->Header.Attributes = VariableHeader->Attributes;
> > + VariableInfo->Header.PubKeyIndex = 0;
> > + VariableInfo->Header.MonotonicCount = 0;
> > + VariableInfo->Header.TimeStamp = NULL;
> > + }
> > +
> > + //
> > + // VendorGuid
> > + //
> > + if (VariableInfo->Header.VendorGuid != NULL) {
> > + CopyGuid (
> > + VariableInfo->Header.VendorGuid,
> > + GetVendorGuidPtr (VariableHeader, VariableInfo->Flags.Auth)
> > + );
> > + } else if (VariableBuffer != NULL) {
> > + VariableInfo->Header.VendorGuid
> > + = GetVendorGuidPtr (VariableBuffer, VariableInfo->Flags.Auth);
> > + }
> > +
> > + //
> > + // VariableName
> > + //
> > + if ( (VariableInfo->Header.VariableName != NULL)
> > + && (VariableInfo->Header.NameSize >= NameSize))
> > + {
> > + GetVariableNameOrData (
> > + StoreInfo,
> > + (UINT8 *)GetVariableNamePtr (VariablePtr, VariableInfo->Flags.Auth),
> > + NameSize,
> > + (UINT8 *)VariableInfo->Header.VariableName
> > + );
> > + } else if (VariableBuffer != NULL) {
> > + VariableInfo->Header.VariableName
> > + = GetVariableNamePtr (VariableBuffer, VariableInfo->Flags.Auth);
> > + } else if (VariableInfo->Header.VariableName != NULL) {
> > + return EFI_BUFFER_TOO_SMALL;
> > + }
> > +
> > + //
> > + // Data
> > + //
> > + if ( (VariableInfo->Header.Data != NULL)
> > + && (VariableInfo->Header.DataSize >= DataSize))
> > + {
> > + GetVariableNameOrData (
> > + StoreInfo,
> > + GetVariableDataPtr (VariablePtr, VariableHeader, StoreInfo->AuthFlag),
> > + DataSize,
> > + VariableInfo->Header.Data
> > + );
> > + } else if (VariableBuffer != NULL) {
> > + VariableInfo->Header.Data
> > + = GetVariableDataPtr (VariableBuffer, VariableBuffer, VariableInfo-
> > >Flags.Auth);
> > + } else if (VariableInfo->Header.Data != NULL) {
> > + return EFI_BUFFER_TOO_SMALL;
> > + }
> > +
> > + //
> > + // Update size information about name & data.
> > + //
> > + VariableInfo->Header.NameSize = NameSize;
> > + VariableInfo->Header.DataSize = DataSize;
> > +
> > + return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +
> > + Retrieve details about a variable, given by VariableInfo->Buffer or
> > + VariableInfo->Index, and pass the details back in VariableInfo->Header.
> > +
> > + This function is used to resolve the variable data structure into
> > + VariableInfo->Header, for easier access later without revisiting the variable
> > + data in variable store. If pointers in the structure of VariableInfo->Header
> > + are not NULL, it's supposed that they are buffers passed in to hold a copy of
> > + data of corresponding data fields in variable data structure. Otherwise, this
> > + function simply returns pointers pointing to address of those data fields.
> > +
> > + The variable is specified by either VariableInfo->Index or VariableInfo-
> >Buffer.
> > + If VariableInfo->Index is given, this function finds the corresponding variable
> > + first from variable storage according to the Index.
> > +
> > + If both VariableInfo->Index and VariableInfo->Buffer are given, it's supposed
> > + that VariableInfo->Buffer is a buffer passed in to hold a whole copy of
> > + requested variable data to be returned.
> > +
> > + @param[in,out] VariableInfo Pointer to variable information.
> > +
> > + @retval EFI_INVALID_PARAMETER VariableInfo is NULL or both
> VariableInfo-
> > >Buffer
> > + and VariableInfo->Index are NULL (0).
> > + @retval EFI_NOT_FOUND If given Buffer or Index is out of range of
> > + any given or internal storage copies.
> > + @retval EFI_SUCCESS Variable details are retrieved successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +GetVariableInfo (
> > + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo
> > + )
> > +{
> > + VARIABLE_HEADER *VariablePtr;
> > + VARIABLE_HEADER *VariableHeader;
> > + VARIABLE_STORE_TYPE StoreType;
> > + VARIABLE_STORE_INFO StoreInfo;
> > + UINTN Offset;
> > +
> > + if ((VariableInfo == NULL) ||
> > + ((VariableInfo->Buffer == NULL) && (VariableInfo->StoreIndex ==
> > VAR_INDEX_INVALID)))
> > + {
> > + ASSERT (VariableInfo != NULL);
> > + ASSERT (VariableInfo->StoreIndex != VAR_INDEX_INVALID || VariableInfo-
> > >Buffer != NULL);
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + StoreInfo.VariableStoreHeader = NULL;
> > + for (StoreType = VariableStoreTypeHob; StoreType < VariableStoreTypeMax;
> > ++StoreType) {
> > + GetVariableStore (StoreType, &StoreInfo);
> > + if (StoreInfo.VariableStoreHeader != NULL) {
> > + break;
> > + }
> > + }
> > +
> > + ASSERT (StoreInfo.VariableStoreHeader != NULL);
> > +
> > + //
> > + // No StoreIndex? Don't retrieve variable information from store but just
> from
> > + // VariableInfo->Buffer.
> > + //
> > + if (VariableInfo->StoreIndex == VAR_INDEX_INVALID) {
> > + VariablePtr = VariableInfo->Buffer;
> > + VariableHeader = VariablePtr;
> > +
> > + return GetVariableInfoInternal (VariableInfo, NULL, VariablePtr,
> > VariableHeader);
> > + }
> > +
> > + Offset = (UINTN)VariableInfo->StoreIndex;
> > + if ( (StoreInfo.FtwLastWriteData != NULL)
> > + && (Offset >= ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress
> > + - (UINTN)StoreInfo.VariableStoreHeader)))
> > + {
> > + Offset -= ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress
> > + - (UINTN)StoreInfo.VariableStoreHeader);
> > + VariablePtr = (VARIABLE_HEADER *)
> > + ((UINTN)StoreInfo.FtwLastWriteData->SpareAddress + Offset);
> > + } else {
> > + VariablePtr = (VARIABLE_HEADER *)
> > + ((UINTN)StoreInfo.VariableStoreHeader + Offset);
> > + }
> > +
> > + //
> > + // Note that variable might be in unconsecutive space. Always get a copy
>
> [JianJW] typo: "unconsecutive" -> "inconsecutive"
>
> > + // of its header in consecutive buffer.
> > + //
> > + if (!GetVariableHeader (&StoreInfo, VariablePtr, &VariableHeader)) {
> > + return EFI_NOT_FOUND;
> > + }
> > +
> > + return GetVariableInfoInternal (VariableInfo, &StoreInfo, VariablePtr,
> > VariableHeader);
> > +}
> > +
> > +/**
> > +
> > + Retrieve details of the variable next to given variable within VariableStore.
> > +
> > + If VarInfo->Buffer is NULL, the first one in VariableStore is returned.
> > +
> > + VariableStart and/or VariableEnd can be given optionally for the situation
> > + in which the valid storage space is smaller than the VariableStore->Size.
> > + This usually happens when PEI variable services make a compact variable
> > + cache to save memory, which cannot make use VariableStore->Size to
> > determine
> > + the correct variable storage range.
>
> [JianJW] This part doesn't match the function implementation. It can be
> removed.
>
> > +
> > + @param[in,out] VariableInfo Pointer to variable information.
> > +
> > + @retval EFI_INVALID_PARAMETER VariableInfo or VariableStore is NULL.
> > + @retval EFI_NOT_FOUND If the end of VariableStore is reached.
> > + @retval EFI_SUCCESS The next variable is retrieved successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +GetNextVariableInfo (
> > + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo
> > + )
> > +{
> > + VARIABLE_HEADER *VariablePtr;
> > + VARIABLE_HEADER *VariableHeader;
> > + VARIABLE_STORE_INFO StoreInfo;
> > + VARIABLE_STORE_TYPE StoreType;
> > + UINTN Offset;
> > +
> > + if (VariableInfo == NULL) {
> > + ASSERT (VariableInfo != NULL);
> > + return EFI_INVALID_PARAMETER;
> > + }
> > +
> > + StoreInfo.VariableStoreHeader = NULL;
> > + for (StoreType = VariableStoreTypeHob; StoreType < VariableStoreTypeMax;
> > ++StoreType) {
> > + GetVariableStore (StoreType, &StoreInfo);
> > + if (StoreInfo.VariableStoreHeader != NULL) {
> > + break;
> > + }
> > + }
> > +
> > + ASSERT (StoreInfo.VariableStoreHeader != NULL);
> > +
> > + //
> > + // VariableInfo->StoreIndex is supposed to be the index to variable found
> > + // last time. Use it to get the variable next to it in store. If it's invalid,
> > + // return the first variable available in store.
> > + //
> > + VariableInfo->Flags.Auth = StoreInfo.AuthFlag;
> > + if (VariableInfo->StoreIndex == VAR_INDEX_INVALID) {
> > + VariablePtr = GetStartPointer (StoreInfo.VariableStoreHeader);
> > + } else {
> > + Offset = (UINTN)VariableInfo->StoreIndex;
> > + if ( (StoreInfo.FtwLastWriteData != NULL)
> > + && (Offset >= ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress
> > + - (UINTN)StoreInfo.VariableStoreHeader)))
> > + {
> > + Offset -= ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress
> > + - (UINTN)StoreInfo.VariableStoreHeader);
> > + VariablePtr = (VARIABLE_HEADER *)
> > + ((UINTN)StoreInfo.FtwLastWriteData->SpareAddress + Offset);
> > + } else {
> > + VariablePtr = (VARIABLE_HEADER *)
> > + ((UINTN)StoreInfo.VariableStoreHeader + Offset);
> > + }
> > +
> > + //
> > + // Note that variable might be in unconsecutive space. Always get a copy
>
> [JianJW] typo: "unconsecutive" -> "inconsecutive"
>
> > + // of its header in consecutive buffer.
> > + //
> > + if (!GetVariableHeader (&StoreInfo, VariablePtr, &VariableHeader)) {
> > + return EFI_NOT_FOUND;
> > + }
> > +
> > + VariablePtr = GetNextVariablePtr (&StoreInfo, VariablePtr, VariableHeader);
> > + }
> > +
> > + //
> > + // Get a copy of variable header in consecutive buffer.
> > + //
> > + if (!GetVariableHeader (&StoreInfo, VariablePtr, &VariableHeader)) {
> > + return EFI_NOT_FOUND;
> > + }
> > +
> > + //
> > + // Use the offset to the start of variable store as index of the variable.
> > + //
> > + if ( (StoreInfo.FtwLastWriteData == NULL)
> > + || ((UINTN)VariablePtr < (UINTN)StoreInfo.FtwLastWriteData-
> > >TargetAddress))
> > + {
> > + VariableInfo->StoreIndex
> > + = (UINT64)((UINTN)VariablePtr - (UINTN)StoreInfo.VariableStoreHeader);
> > + } else {
> > + VariableInfo->StoreIndex
> > + = (UINT64)((UINTN)StoreInfo.FtwLastWriteData->TargetAddress
> > + - (UINTN)StoreInfo.VariableStoreHeader);
> > + VariableInfo->StoreIndex
> > + += (UINT64)((UINTN)VariablePtr - (UINTN)StoreInfo.FtwLastWriteData-
> > >SpareAddress);
> > + }
> > +
> > + if ((StoreType == VariableStoreTypeHob) && (VariableInfo->Buffer == NULL))
> {
> > + VariableInfo->Buffer = VariablePtr;
> > + }
> > +
> > + return GetVariableInfoInternal (VariableInfo, &StoreInfo, VariablePtr,
> > VariableHeader);
> > +}
> > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariableStore.c
> > b/MdeModulePkg/Universal/Variable/Pei/VariableStore.c
> > new file mode 100644
> > index 000000000000..75edc3fc5051
> > --- /dev/null
> > +++ b/MdeModulePkg/Universal/Variable/Pei/VariableStore.c
> > @@ -0,0 +1,307 @@
> > +/** @file
> > + Implement ReadOnly Variable Services required by PEIM and install
> > + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile
> storage
> > space.
>
> [JianJW] typo: "Varaiable2" -> "Variable2"
>
> > +
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "VariableParsing.h"
> > +#include "VariableStore.h"
> > +
> > +/**
> > + Get variable store status.
> > +
> > + @param[in] VarStoreHeader Pointer to the Variable Store Header.
> > +
> > + @retval EfiRaw Variable store is raw
> > + @retval EfiValid Variable store is valid
> > + @retval EfiInvalid Variable store is invalid
> > +
> > +**/
> > +VARIABLE_STORE_STATUS
> > +GetVariableStoreStatus (
> > + IN VARIABLE_STORE_HEADER *VarStoreHeader
> > + )
> > +{
> > + if ((CompareGuid (&VarStoreHeader->Signature,
> > &gEfiAuthenticatedVariableGuid) ||
> > + CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) &&
> > + (VarStoreHeader->Format == VARIABLE_STORE_FORMATTED) &&
> > + (VarStoreHeader->State == VARIABLE_STORE_HEALTHY)
> > + )
> > + {
> > + return EfiValid;
> > + }
> > +
> > + if ((((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff) &&
> > + (((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff) &&
> > + (((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff) &&
> > + (((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff) &&
> > + (VarStoreHeader->Size == 0xffffffff) &&
> > + (VarStoreHeader->Format == 0xff) &&
> > + (VarStoreHeader->State == 0xff)
> > + )
> > + {
> > + return EfiRaw;
> > + } else {
> > + return EfiInvalid;
> > + }
> > +}
> > +
> > +/**
> > + Reports HOB variable store is available or not.
> > +
> > + @retval EFI_NOT_READY HOB variable store info not available.
> > + @retval EFI_NOT_FOUND HOB variable store is NOT available.
> > + @retval EFI_SUCCESS HOB variable store is available.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +IsHobVariableStoreAvailable (
> > + VOID
> > + )
> > +{
> > + EFI_HOB_GUID_TYPE *GuidHob;
> > + VOID *VariableStoreInfoHob;
> > +
> > + //
> > + // Discover if Variable Store Info Hob has been published by platform driver.
> > + // It contains information regards to HOB or NV Variable Store availability
> > + //
> > + GuidHob = GetFirstGuidHob (&gEfiPeiVariableStoreDiscoveredPpiGuid);
> > + if (GuidHob == NULL) {
> > + return EFI_NOT_READY;
> > + }
> > +
> > + //
> > + // Check if HOB Variable Store is available
> > + //
> > + VariableStoreInfoHob = GET_GUID_HOB_DATA (GuidHob);
> > + if (*(BOOLEAN *)VariableStoreInfoHob == TRUE) {
> > + return EFI_SUCCESS;
> > + }
> > +
> > + //
> > + // This might be NV Variable Store
> > + //
> > + return EFI_NOT_FOUND;
> > +}
> > +
> > +/**
> > + Get HOB variable store.
> > +
> > + @param[out] StoreInfo Return the store info.
> > +
> > +**/
> > +VOID
> > +GetHobVariableStore (
> > + OUT VARIABLE_STORE_INFO *StoreInfo
> > + )
> > +{
> > + EFI_HOB_GUID_TYPE *GuidHob;
> > +
> > + //
> > + // Make sure there is no more than one Variable HOB.
> > + //
> > + DEBUG_CODE_BEGIN ();
> > + GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
> > + if (GuidHob != NULL) {
> > + if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB
> > (GuidHob)) != NULL)) {
> > + DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n"));
> > + ASSERT (FALSE);
> > + } else if (GetFirstGuidHob (&gEfiVariableGuid) != NULL) {
> > + DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable
> > HOBs\n"));
> > + ASSERT (FALSE);
> > + }
> > + } else {
> > + GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
> > + if (GuidHob != NULL) {
> > + if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) !=
> > NULL)) {
> > + DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n"));
> > + ASSERT (FALSE);
> > + }
> > + }
> > + }
> > +
> > + DEBUG_CODE_END ();
> > +
> > + GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);
> > + if (GuidHob != NULL) {
> > + StoreInfo->VariableStoreHeader = (VARIABLE_STORE_HEADER
> > *)GET_GUID_HOB_DATA (GuidHob);
> > + StoreInfo->AuthFlag = TRUE;
> > + } else {
> > + GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
> > + if (GuidHob != NULL) {
> > + StoreInfo->VariableStoreHeader = (VARIABLE_STORE_HEADER
> > *)GET_GUID_HOB_DATA (GuidHob);
> > + StoreInfo->AuthFlag = FALSE;
> > + }
> > + }
> > +}
> > +
> > +/**
> > + Get NV variable store.
> > +
> > + @param[out] StoreInfo Return the store info.
> > + @param[out] VariableFvHeader Return header of FV containing the store.
> > +
> > +**/
> > +VOID
> > +GetNvVariableStore (
> > + OUT VARIABLE_STORE_INFO *StoreInfo,
> > + OUT EFI_FIRMWARE_VOLUME_HEADER **VariableFvHeader
> > + )
> > +{
> > + EFI_STATUS Status;
> > + EFI_HOB_GUID_TYPE *GuidHob;
> > + EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
> > + VARIABLE_STORE_HEADER *StoreHeader;
> > + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *HobData;
> > + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
> > + EFI_PHYSICAL_ADDRESS NvStorageBase;
> > + UINT32 NvStorageSize;
> > + UINT32 BackUpOffset;
> > + UINT64 NvStorageSize64;
> > +
> > + Status = GetVariableFlashNvStorageInfo (&NvStorageBase,
> > &NvStorageSize64);
> > + ASSERT_EFI_ERROR (Status);
> > +
> > + Status = SafeUint64ToUint32 (NvStorageSize64, &NvStorageSize);
> > + // This driver currently assumes the size will be UINT32 so assert the value is
> > safe for now.
> > + ASSERT_EFI_ERROR (Status);
> > +
> > + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)NvStorageBase;
> > +
> > + //
> > + // Check the FTW last write data hob.
> > + //
> > + BackUpOffset = 0;
> > + FtwLastWriteData = NULL;
> > + HobData = NULL;
> > + GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
> > +
> > + if (GuidHob != NULL) {
> > + HobData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA
> > *)GET_GUID_HOB_DATA (GuidHob);
> > + if (HobData->TargetAddress == NvStorageBase) {
> > + //
> > + // Let FvHeader point to spare block.
> > + //
> > + DEBUG ((
> > + EFI_D_INFO,
> > + "PeiVariable: NV storage is backed up in spare block: 0x%x\n",
> > + (UINTN)HobData->SpareAddress
> > + ));
> > +
> > + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)HobData-
> > >SpareAddress;
> > + HobData = NULL;
> > + } else if ((HobData->TargetAddress > NvStorageBase) &&
> > + (HobData->TargetAddress < (NvStorageBase + NvStorageSize)))
> > + {
> > + //
> > + // Flash NV storage from the offset is backed up in spare block.
> > + //
> > + BackUpOffset = (UINT32)(HobData->TargetAddress - NvStorageBase);
> > + DEBUG ((
> > + EFI_D_INFO,
> > + "PeiVariable: High partial NV storage from offset: %x is backed up in
> spare
> > block: 0x%x\n",
> > + BackUpOffset,
> > + (UINTN)FtwLastWriteData->SpareAddress
> > + ));
> > + //
> > + // At least one block data in flash NV storage is still valid, so still
> > + // leave FvHeader point to NV storage base.
> > + //
> > + }
> > + }
> > +
> > + if (StoreInfo != NULL) {
> > + StoreInfo->FtwLastWriteData = HobData;
> > + }
> > +
> > + if (VariableFvHeader != NULL) {
> > + *VariableFvHeader = FvHeader;
> > + }
> > +
> > + //
> > + // Check if the Firmware Volume is not corrupted
> > + //
> > + if ((FvHeader->Signature == EFI_FVH_SIGNATURE) &&
> > + CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))
> > + {
> > + StoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)FvHeader +
> FvHeader-
> > >HeaderLength);
> > + } else {
> > + StoreHeader = NULL;
> > + DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is
> > corrupted\n"));
> > + }
> > +
> > + if (StoreInfo != NULL) {
> > + StoreInfo->VariableStoreHeader = StoreHeader;
> > + if (StoreHeader != NULL) {
> > + StoreInfo->AuthFlag = CompareGuid (
> > + &StoreHeader->Signature,
> > + &gEfiAuthenticatedVariableGuid
> > + );
> > + }
> > + }
> > +}
> > +
> > +/**
> > + Return the variable store header and the store info based on the Index.
> > +
> > + @param[in] Type The type of the variable store.
> > + @param[out] StoreInfo Return the store info.
> > +
> > + @return Pointer to the variable store header.
> > +**/
> > +VARIABLE_STORE_HEADER *
> > +GetVariableStore (
> > + IN VARIABLE_STORE_TYPE Type,
> > + OUT VARIABLE_STORE_INFO *StoreInfo
> > + )
> > +{
> > + EFI_HOB_GUID_TYPE *GuidHob;
> > +
> > + StoreInfo->VariableStoreHeader = NULL;
> > + StoreInfo->IndexTable = NULL;
> > + StoreInfo->FtwLastWriteData = NULL;
> > + StoreInfo->AuthFlag = FALSE;
> > + switch (Type) {
> > + case VariableStoreTypeHob:
> > + GetHobVariableStore (StoreInfo);
> > + break;
> > +
> > + case VariableStoreTypeNv:
> > + if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {
> > + //
> > + // Emulated non-volatile variable mode is not enabled.
> > + //
> > + GetNvVariableStore (StoreInfo, NULL);
> > + if (StoreInfo->VariableStoreHeader != NULL) {
> > + GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
> > + if (GuidHob != NULL) {
> > + StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);
> > + } else {
> > + //
> > + // If it's the first time to access variable region in flash, create a guid
> hob
> > to record
> > + // VAR_ADDED type variable info.
> > + // Note that as the resource of PEI phase is limited, only store the
> > limited number of
> > + // VAR_ADDED type variables to reduce access time.
> > + //
> > + StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE
> > *)BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof
> (VARIABLE_INDEX_TABLE));
> > + StoreInfo->IndexTable->Length = 0;
> > + StoreInfo->IndexTable->StartPtr = GetStartPointer (StoreInfo-
> > >VariableStoreHeader);
> > + StoreInfo->IndexTable->EndPtr = GetEndPointer (StoreInfo-
> > >VariableStoreHeader);
> > + StoreInfo->IndexTable->GoneThrough = 0;
> > + }
> > + }
> > + }
> > +
> > + break;
> > +
> > + default:
> > + ASSERT (FALSE);
> > + break;
> > + }
> > +
> > + return StoreInfo->VariableStoreHeader;
> > +}
> > --
> > 2.35.1.windows.2
>
>
>
>
>
next prev parent reply other threads:[~2022-11-14 2:34 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-11 6:53 [PATCH v4 00/28] UEFI variable protection Judah Vang
2022-08-11 6:53 ` [PATCH v4 01/28] MdeModulePkg: Update AUTH_VARIABLE_INFO struct Judah Vang
2022-08-11 6:53 ` [PATCH v4 02/28] MdeModulePkg: Add reference to new Ppi Guid Judah Vang
2022-08-11 6:53 ` [PATCH v4 03/28] MdeModulePkg: Add new ProtectedVariable GUIDs Judah Vang
2022-08-11 6:53 ` [PATCH v4 04/28] MdeModulePkg: Add new include files Judah Vang
2022-08-19 3:21 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 05/28] MdeModulePkg: Add new GUID for Variable Store Info Judah Vang
2022-08-11 6:53 ` [PATCH v4 06/28] MdeModulePkg: Add Null ProtectedVariable Library Judah Vang
2022-08-19 3:20 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 07/28] MdeModulePkg: Add new Variable functionality Judah Vang
2022-11-13 17:38 ` Wang, Jian J
[not found] ` <1727359DAB074995.1868@groups.io>
2022-11-14 2:34 ` Wang, Jian J [this message]
2022-08-11 6:53 ` [PATCH v4 08/28] MdeModulePkg: Add support for Protected Variables Judah Vang
2022-08-11 6:53 ` [PATCH v4 09/28] MdeModulePkg: Reference Null ProtectedVariableLib Judah Vang
2022-08-11 6:53 ` [PATCH v4 10/28] SecurityPkg: Add new GUIDs for Judah Vang
2022-08-11 6:53 ` [PATCH v4 11/28] SecurityPkg: Add new KeyService types and defines Judah Vang
2022-08-22 2:24 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 12/28] SecurityPkg: Add new variable types and functions Judah Vang
2022-08-22 2:34 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 13/28] SecurityPkg: Update RPMC APIs with index Judah Vang
2022-08-11 6:53 ` [PATCH v4 14/28] SecurityPkg: Fix GetVariableKey API Judah Vang
2022-08-22 3:47 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 15/28] SecurityPkg: Add null encryption variable libs Judah Vang
2022-08-22 3:48 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 16/28] SecurityPkg: Add VariableKey library function Judah Vang
2022-08-22 3:52 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 17/28] SecurityPkg: Add EncryptionVariable lib with AES Judah Vang
2022-08-22 4:05 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 18/28] SecurityPkg: Add Protected Variable Services Judah Vang
2022-08-22 4:14 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 19/28] SecurityPkg: Add references to new *.inf files Judah Vang
2022-08-22 4:15 ` Wang, Jian J
2022-08-11 6:53 ` [PATCH v4 20/28] ArmVirtPkg: Add reference to ProtectedVariableNull Judah Vang
2022-08-11 6:53 ` [PATCH v4 21/28] UefiPayloadPkg: Add ProtectedVariable reference Judah Vang
2022-08-12 23:01 ` Guo Dong
2022-08-11 6:53 ` [PATCH v4 22/28] EmulatorPkg: " Judah Vang
2022-08-11 6:53 ` [PATCH v4 23/28] OvmfPkg: " Judah Vang
2022-08-11 6:53 ` [PATCH v4 24/28] OvmfPkg: Add ProtectedVariableLib reference Judah Vang
2022-08-11 6:53 ` [PATCH v4 25/28] " Judah Vang
2022-08-11 6:53 ` [PATCH v4 26/28] " Judah Vang
2022-08-11 6:53 ` [PATCH v4 27/28] OvmfPkg: Add ProtectedVariable reference Judah Vang
2022-08-11 6:53 ` [PATCH v4 28/28] IntelTdx: " Judah Vang
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=MW4PR11MB6763D03A9503F7724A07A965B6059@MW4PR11MB6763.namprd11.prod.outlook.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