One more comment: For all header files, no need to remove the opening '_' of include guard macro. Protected variable code are now in different folder than original variable driver. They won't reference code from each other. Please add the opening '_' for those macros to confirm to edk2 coding convention.
Regards, Jian > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Wang, Jian > J > Sent: Monday, November 14, 2022 11:43 AM > To: Vang, Judah <judah.v...@intel.com>; devel@edk2.groups.io > Cc: Gao, Liming <gaolim...@byosoft.com.cn>; Wu, Hao A > <hao.a...@intel.com>; Mistry, Nishant C <nishant.c.mis...@intel.com> > Subject: Re: [edk2-devel] [PATCH v5 07/19] MdeModulePkg: Add new Variable > functionality > > Hi Judah, > > See my comments (starting with [JianJW]) inline below. > > > > -----Original Message----- > > From: Vang, Judah <judah.v...@intel.com> > > Sent: Sunday, November 06, 2022 3:35 PM > > To: devel@edk2.groups.io > > Cc: Wang, Jian J <jian.j.w...@intel.com>; Gao, Liming > > <gaolim...@byosoft.com.cn>; Wu, Hao A <hao.a...@intel.com>; Mistry, > > Nishant C <nishant.c.mis...@intel.com> > > Subject: [PATCH v5 07/19] MdeModulePkg: Add new Variable functionality > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2594 > > > > V5: Add PEI Variable Protection into a new directory and leave the > > existing PEI Variable unchanged. > > > > 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.w...@intel.com> > > Cc: Liming Gao <gaolim...@byosoft.com.cn> > > Cc: Hao A Wu <hao.a...@intel.com> > > Cc: Nishant C Mistry <nishant.c.mis...@intel.com> > > Signed-off-by: Jian J Wang <jian.j.w...@intel.com> > > Signed-off-by: Nishant C Mistry <nishant.c.mis...@intel.com> > > Signed-off-by: Judah Vang <judah.v...@intel.com> > > Acked-by: Hao A Wu <hao.a...@intel.com> > > --- > > MdeModulePkg/Universal/Variable/Protected/Pei/VariablePei.inf | 79 ++ > > MdeModulePkg/Universal/Variable/Protected/Pei/Variable.h | 225 > +++++ > > MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.h | 309 > > +++++++ > > MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.h | 116 > +++ > > MdeModulePkg/Universal/Variable/Protected/Pei/Variable.c | 628 > > +++++++++++++ > > MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.c | 941 > > ++++++++++++++++++++ > > MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.c | 307 > > +++++++ > > MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariable.uni | 16 + > > MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariableExtra.uni | 14 + > > 9 files changed, 2635 insertions(+) > > > > diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/VariablePei.inf > > b/MdeModulePkg/Universal/Variable/Protected/Pei/VariablePei.inf > > new file mode 100644 > > index 000000000000..953a7c6b884f > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/VariablePei.inf > > @@ -0,0 +1,79 @@ > > +## @file > > +# Implements ReadOnly Variable Services required by PEIM and installs PEI > > ReadOnly Varaiable2 PPI. > > [JianJW] typo: "Varaiable2" -> "Variable2" > > > +# > > +# This module implements ReadOnly Variable Services required by PEIM and > > installs PEI ReadOnly Varaiable2 PPI. > > [JianJW] typo: "Varaiable2" -> "Variable2" > > > +# > > +# Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR> > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x00010005 > > + BASE_NAME = PeiVariable > > + MODULE_UNI_FILE = PeiVariable.uni > > + FILE_GUID = 8D104D19-593B-4DDF-81CF-8168A9EDE9C7 > > + MODULE_TYPE = PEIM > > + VERSION_STRING = 1.0 > > + ENTRY_POINT = PeimInitializeVariableServices > > + > > +# > > +# The following information is for reference only and not required by the > build > > tools. > > +# > > +# VALID_ARCHITECTURES = IA32 X64 EBC > > +# > > + > > +[Sources] > > + Variable.c > > + Variable.h > > + VariableStore.c > > + VariableStore.h > > + VariableParsing.c > > + VariableParsing.h > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + > > +[LibraryClasses] > > + BaseMemoryLib > > + PcdLib > > + HobLib > > + PeimEntryPoint > > + DebugLib > > + PeiServicesTablePointerLib > > + PeiServicesLib > > + SafeIntLib > > + VariableFlashInfoLib > > + ProtectedVariableLib > > + > > +[Guids] > > + ## CONSUMES ## GUID # Variable store header > > + ## SOMETIMES_CONSUMES ## HOB > > + gEfiAuthenticatedVariableGuid > > + ## SOMETIMES_CONSUMES ## GUID # Variable store header > > + ## SOMETIMES_CONSUMES ## HOB > > + gEfiVariableGuid > > + ## SOMETIMES_PRODUCES ## HOB > > + ## SOMETIMES_CONSUMES ## HOB > > + gEfiVariableIndexTableGuid > > + gEfiSystemNvDataFvGuid ## SOMETIMES_CONSUMES ## GUID > > + ## SOMETIMES_CONSUMES ## HOB > > + ## CONSUMES ## GUID # Dependence > > + gEdkiiFaultTolerantWriteGuid > > + > > +[Ppis] > > + gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES > > + gEfiPeiVariableStoreDiscoveredPpiGuid ## CONSUMES > > + > > +[Pcd] > > + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable ## > > SOMETIMES_CONSUMES > > + > > +[Depex] > > + gEdkiiFaultTolerantWriteGuid > > + > > +# [BootMode] > > +# RECOVERY_FULL ## SOMETIMES_CONSUMES > > + > > +[UserExtensions.TianoCore."ExtraFiles"] > > + PeiVariableExtra.uni > > diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.h > > b/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.h > > new file mode 100644 > > index 000000000000..1bdbdd2b807b > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.h > > @@ -0,0 +1,225 @@ > > +/** @file > > + The internal header file includes the common header files, defines > > + internal structure and functions used by PeiVariable module. > > + > > +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR> > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef PEI_VARIABLE_H_ > > +#define PEI_VARIABLE_H_ > > + > > +#include <PiPei.h> > > +#include <Ppi/ReadOnlyVariable2.h> > > + > > +#include <Library/DebugLib.h> > > +#include <Library/PeimEntryPoint.h> > > +#include <Library/HobLib.h> > > +#include <Library/PcdLib.h> > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/PeiServicesTablePointerLib.h> > > +#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, > > + VariableStoreTypeNv, > > + VariableStoreTypeMax > > +} VARIABLE_STORE_TYPE; > > + > > +typedef struct { > > + VARIABLE_STORE_HEADER *VariableStoreHeader; > > + VARIABLE_INDEX_TABLE *IndexTable; > > + // > > + // If it is not NULL, it means there may be an inconsecutive variable > > whose > > + // partial content is still in NV storage, but another partial content > > is backed > > up > > + // in spare block. > > + // > > + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData; > > + BOOLEAN AuthFlag; > > +} VARIABLE_STORE_INFO; > > + > > +// > > +// Functions > > +// > > + > > +/** > > + Provide the functionality of the variable services. > > + > > + @param FileHandle Handle of the file being invoked. > > + Type EFI_PEI_FILE_HANDLE is defined in > > FfsFindNextFile(). > > + @param PeiServices General purpose services available to every PEIM. > > + > > + @retval EFI_SUCCESS If the interface could be successfully installed > > + @retval Others Returned from PeiServicesInstallPpi() > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeimInitializeVariableServices ( > > + IN EFI_PEI_FILE_HANDLE FileHandle, > > + IN CONST EFI_PEI_SERVICES **PeiServices > > + ); > > + > > +/** > > + 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 > > +PeiGetVariable ( > > + 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 > > +PeiGetNextVariableName ( > > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > > + IN OUT UINTN *VariableNameSize, > > + IN OUT CHAR16 *VariableName, > > + 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/Protected/Pei/VariableParsing.h > > b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.h > > new file mode 100644 > > index 000000000000..d7af6cb6e8be > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/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. > > [JianJW] This part doesn't match the function implementation any more. > 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 > > + ); > > + > > +/** > > + > > + 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/Protected/Pei/VariableStore.h > > b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.h > > new file mode 100644 > > index 000000000000..6e2f6f939bab > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/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/Protected/Pei/Variable.c > > b/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.c > > new file mode 100644 > > index 000000000000..ce790946626e > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.c > > @@ -0,0 +1,628 @@ > > +/** @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) 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 = { > > + PeiGetVariableEx, > > + PeiGetNextVariableNameEx > > +}; > > + > > +EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = { > > + (EFI_PEI_PPI_DESCRIPTOR_PPI | > EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > > + &gEfiPeiReadOnlyVariable2PpiGuid, > > + &mVariablePpi > > +}; > > + > > +/** > > + Provide the functionality of the variable services. > > + > > + @param FileHandle Handle of the file being invoked. > > + Type EFI_PEI_FILE_HANDLE is defined in > > FfsFindNextFile(). > > + @param PeiServices General purpose services available to every PEIM. > > + > > + @retval EFI_SUCCESS If the interface could be successfully installed > > + @retval Others Returned from PeiServicesInstallPpi() > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeimInitializeVariableServices ( > > + IN EFI_PEI_FILE_HANDLE FileHandle, > > + 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); > > +} > > + > > +/** > > + Find the variable in the specified variable store. > > + > > + @param StoreInfo Pointer to the store info structure. > > + @param VariableName Name of the variable to be found > > + @param VendorGuid Vendor GUID to be found. > > + @param PtrTrack Variable Track Pointer structure that > > contains > > Variable Information. > > + > > + @retval EFI_SUCCESS Variable found successfully > > + @retval EFI_NOT_FOUND Variable not found > > + @retval EFI_INVALID_PARAMETER Invalid variable name > > + > > +**/ > > +EFI_STATUS > > +FindVariableEx ( > > + IN VARIABLE_STORE_INFO *StoreInfo, > > + IN CONST CHAR16 *VariableName, > > + IN CONST EFI_GUID *VendorGuid, > > + OUT VARIABLE_POINTER_TRACK *PtrTrack > > + ) > > +{ > > + VARIABLE_HEADER *Variable; > > + VARIABLE_HEADER *LastVariable; > > + VARIABLE_HEADER *MaxIndex; > > + UINTN Index; > > + UINTN Offset; > > + BOOLEAN StopRecord; > > + VARIABLE_HEADER *InDeletedVariable; > > + VARIABLE_STORE_HEADER *VariableStoreHeader; > > + VARIABLE_INDEX_TABLE *IndexTable; > > + VARIABLE_HEADER *VariableHeader; > > + > > + VariableStoreHeader = StoreInfo->VariableStoreHeader; > > + > > + if (VariableStoreHeader == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) { > > + return EFI_UNSUPPORTED; > > + } > > + > > + if (~VariableStoreHeader->Size == 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + IndexTable = StoreInfo->IndexTable; > > + PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader); > > + PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader); > > + > > + InDeletedVariable = NULL; > > + > > + // > > + // No Variable Address equals zero, so 0 as initial value is safe. > > + // > > + MaxIndex = NULL; > > + VariableHeader = NULL; > > + > > + if (IndexTable != NULL) { > > + // > > + // traverse the variable index table to look for varible. > > + // The IndexTable->Index[Index] records the distance of two > > neighbouring > > VAR_ADDED type variables. > > + // > > + for (Offset = 0, Index = 0; Index < IndexTable->Length; Index++) { > > + ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable- > >Index[0])); > > + Offset += IndexTable->Index[Index]; > > + MaxIndex = (VARIABLE_HEADER *)((UINT8 *)IndexTable->StartPtr + > Offset); > > + GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader); > > + if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, > > VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) { > > + if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & > > VAR_ADDED)) { > > + InDeletedVariable = PtrTrack->CurrPtr; > > + } else { > > + return EFI_SUCCESS; > > + } > > + } > > + } > > + > > + if (IndexTable->GoneThrough != 0) { > > + // > > + // If the table has all the existing variables indexed, return. > > + // > > + PtrTrack->CurrPtr = InDeletedVariable; > > + return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; > > + } > > + } > > + > > + if (MaxIndex != NULL) { > > + // > > + // HOB exists but the variable cannot be found in HOB > > + // If not found in HOB, then let's start from the MaxIndex we've found. > > + // > > + Variable = GetNextVariablePtr (StoreInfo, MaxIndex, > > VariableHeader); > > + LastVariable = MaxIndex; > > + } else { > > + // > > + // Start Pointers for the variable. > > + // Actual Data Pointer where data can be written. > > + // > > + Variable = PtrTrack->StartPtr; > > + LastVariable = PtrTrack->StartPtr; > > + } > > + > > + // > > + // Find the variable by walk through variable store > > + // > > + StopRecord = FALSE; > > + while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) { > > + if ((VariableHeader->State == VAR_ADDED) || (VariableHeader->State == > > (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) { > > + // > > + // Record Variable in VariableIndex HOB > > + // > > + if ((IndexTable != NULL) && !StopRecord) { > > + Offset = (UINTN)Variable - (UINTN)LastVariable; > > + if ((Offset > 0x0FFFF) || (IndexTable->Length >= sizeof > > (IndexTable- > >Index) > > / sizeof (IndexTable->Index[0]))) { > > + // > > + // Stop to record if the distance of two neighbouring VAR_ADDED > > variable is larger than the allowable scope(UINT16), > > + // or the record buffer is full. > > + // > > + StopRecord = TRUE; > > + } else { > > + IndexTable->Index[IndexTable->Length++] = (UINT16)Offset; > > + LastVariable = Variable; > > + } > > + } > > + > > + if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, > > VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) { > > + if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & > > VAR_ADDED)) { > > + InDeletedVariable = PtrTrack->CurrPtr; > > + } else { > > + return EFI_SUCCESS; > > + } > > + } > > + } > > + > > + Variable = GetNextVariablePtr (StoreInfo, Variable, VariableHeader); > > + } > > + > > + // > > + // If gone through the VariableStore, that means we never find in > > Firmware > > any more. > > + // > > + if ((IndexTable != NULL) && !StopRecord) { > > + IndexTable->GoneThrough = 1; > > + } > > + > > + PtrTrack->CurrPtr = InDeletedVariable; > > + > > + return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; > > +} > > + > > +/** > > + Find the variable in HOB and Non-Volatile variable storages. > > + > > + @param VariableName Name of the variable to be found > > + @param VendorGuid Vendor GUID to be found. > > + @param PtrTrack Variable Track Pointer structure that contains > > Variable > > Information. > > + @param StoreInfo Return the store info. > > + > > + @retval EFI_SUCCESS Variable found successfully > > + @retval EFI_NOT_FOUND Variable not found > > + @retval EFI_INVALID_PARAMETER Invalid variable name > > +**/ > > +EFI_STATUS > > +FindVariable ( > > + IN CONST CHAR16 *VariableName, > > + IN CONST EFI_GUID *VendorGuid, > > + OUT VARIABLE_POINTER_TRACK *PtrTrack, > > + OUT VARIABLE_STORE_INFO *StoreInfo > > + ) > > +{ > > + EFI_STATUS Status; > > + VARIABLE_STORE_TYPE Type; > > + > > + if ((VariableName[0] != 0) && (VendorGuid == NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + for (Type = (VARIABLE_STORE_TYPE)0; Type < VariableStoreTypeMax; > Type++) > > { > > + GetVariableStore (Type, StoreInfo); > > + Status = FindVariableEx ( > > + StoreInfo, > > + VariableName, > > + VendorGuid, > > + PtrTrack > > + ); > > + if (!EFI_ERROR (Status)) { > > + return Status; > > + } > > + } > > + > > + return EFI_NOT_FOUND; > > +} > > + > > +/** > > + 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 > > +PeiGetVariable ( > > + 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 > > + ) > > +{ > > + VARIABLE_POINTER_TRACK Variable; > > + UINTN VarDataSize; > > + EFI_STATUS Status; > > + VARIABLE_STORE_INFO StoreInfo; > > + VARIABLE_HEADER *VariableHeader; > > + > > + if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize == > > NULL)) > { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (VariableName[0] == 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + VariableHeader = NULL; > > + > > + // > > + // Find existing variable > > + // > > + Status = FindVariable (VariableName, VariableGuid, &Variable, > > &StoreInfo); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader); > > + > > + // > > + // Get data size > > + // > > + VarDataSize = DataSizeOfVariable (VariableHeader, StoreInfo.AuthFlag); > > + if (*DataSize >= VarDataSize) { > > + if (Data == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + GetVariableNameOrData (&StoreInfo, GetVariableDataPtr > > (Variable.CurrPtr, > > VariableHeader, StoreInfo.AuthFlag), VarDataSize, Data); > > + Status = EFI_SUCCESS; > > + } else { > > + Status = EFI_BUFFER_TOO_SMALL; > > + } > > + > > + if (Attributes != NULL) { > > + *Attributes = VariableHeader->Attributes; > > + } > > + > > + *DataSize = VarDataSize; > > + > > + return Status; > > +} > > + > > +/** > > + 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 > > +PeiGetNextVariableName ( > > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > > + IN OUT UINTN *VariableNameSize, > > + IN OUT CHAR16 *VariableName, > > + IN OUT EFI_GUID *VariableGuid > > + ) > > +{ > > + VARIABLE_STORE_TYPE Type; > > + VARIABLE_POINTER_TRACK Variable; > > + VARIABLE_POINTER_TRACK VariableInHob; > > + VARIABLE_POINTER_TRACK VariablePtrTrack; > > + UINTN VarNameSize; > > + EFI_STATUS Status; > > + VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; > > + VARIABLE_HEADER *VariableHeader; > > + VARIABLE_STORE_INFO StoreInfo; > > + VARIABLE_STORE_INFO StoreInfoForNv; > > + VARIABLE_STORE_INFO StoreInfoForHob; > > + > > + if ((VariableName == NULL) || (VariableGuid == NULL) || (VariableNameSize > > == NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + VariableHeader = NULL; > > + > > + Status = FindVariable (VariableName, VariableGuid, &Variable, > > &StoreInfo); > > + if ((Variable.CurrPtr == NULL) || (Status != EFI_SUCCESS)) { > > + return Status; > > + } > > + > > + if (VariableName[0] != 0) { > > + // > > + // If variable name is not NULL, get next variable > > + // > > + GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader); > > + Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, > > VariableHeader); > > + } > > + > > + VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore > > (VariableStoreTypeHob, &StoreInfoForHob); > > + VariableStoreHeader[VariableStoreTypeNv] = GetVariableStore > > (VariableStoreTypeNv, &StoreInfoForNv); > > + > > + while (TRUE) { > > + // > > + // Switch from HOB to Non-Volatile. > > + // > > + while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, > > &VariableHeader)) > { > > + // > > + // Find current storage index > > + // > > + for (Type = (VARIABLE_STORE_TYPE)0; Type < VariableStoreTypeMax; > > Type++) { > > + if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == > > GetStartPointer (VariableStoreHeader[Type]))) { > > + break; > > + } > > + } > > + > > + ASSERT (Type < VariableStoreTypeMax); > > + // > > + // Switch to next storage > > + // > > + for (Type++; Type < VariableStoreTypeMax; Type++) { > > + if (VariableStoreHeader[Type] != NULL) { > > + break; > > + } > > + } > > + > > + // > > + // Capture the case that > > + // 1. current storage is the last one, or > > + // 2. no further storage > > + // > > + if (Type == VariableStoreTypeMax) { > > + return EFI_NOT_FOUND; > > + } > > + > > + Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]); > > + Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]); > > + Variable.CurrPtr = Variable.StartPtr; > > + GetVariableStore (Type, &StoreInfo); > > + } > > + > > + if ((VariableHeader->State == VAR_ADDED) || (VariableHeader->State == > > (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) { > > + if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & > > VAR_ADDED)) { > > + // > > + // If it is a IN_DELETED_TRANSITION variable, > > + // and there is also a same ADDED one at the same time, > > + // don't return it. > > + // > > + Status = FindVariableEx ( > > + &StoreInfo, > > + GetVariableNamePtr (Variable.CurrPtr, > > StoreInfo.AuthFlag), > > + GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), > > + &VariablePtrTrack > > + ); > > + if (!EFI_ERROR (Status) && (VariablePtrTrack.CurrPtr != > > Variable.CurrPtr)) > { > > + Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, > > Variable.CurrPtr, > > VariableHeader); > > + continue; > > + } > > + } > > + > > + // > > + // Don't return NV variable when HOB overrides it > > + // > > + if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && > > (VariableStoreHeader[VariableStoreTypeNv] != NULL) && > > + (Variable.StartPtr == GetStartPointer > > (VariableStoreHeader[VariableStoreTypeNv])) > > + ) > > + { > > + Status = FindVariableEx ( > > + &StoreInfoForHob, > > + GetVariableNamePtr (Variable.CurrPtr, > > StoreInfo.AuthFlag), > > + GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), > > + &VariableInHob > > + ); > > + if (!EFI_ERROR (Status)) { > > + Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, > > Variable.CurrPtr, > > VariableHeader); > > + continue; > > + } > > + } > > + > > + VarNameSize = NameSizeOfVariable (VariableHeader, > > StoreInfo.AuthFlag); > > + ASSERT (VarNameSize != 0); > > + > > + if (VarNameSize <= *VariableNameSize) { > > + GetVariableNameOrData (&StoreInfo, (UINT8 *)GetVariableNamePtr > > (Variable.CurrPtr, StoreInfo.AuthFlag), VarNameSize, (UINT8 *)VariableName); > > + > > + CopyMem (VariableGuid, GetVendorGuidPtr (VariableHeader, > > StoreInfo.AuthFlag), sizeof (EFI_GUID)); > > + > > + Status = EFI_SUCCESS; > > + } else { > > + Status = EFI_BUFFER_TOO_SMALL; > > + } > > + > > + *VariableNameSize = VarNameSize; > > + // > > + // Variable is found > > + // > > + return Status; > > + } else { > > + Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, > > VariableHeader); > > + } > > + } > > +} > > + > > +/** > > + 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/Protected/Pei/VariableParsing.c > > b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.c > > new file mode 100644 > > index 000000000000..2d605d39cbb6 > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/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. > > + > > + @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/Protected/Pei/VariableStore.c > > b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.c > > new file mode 100644 > > index 000000000000..75edc3fc5051 > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/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; > > +} > > diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariable.uni > > b/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariable.uni > > new file mode 100644 > > index 000000000000..106c1dfdc5c0 > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariable.uni > > @@ -0,0 +1,16 @@ > > +// /** @file > > +// Implements ReadOnly Variable Services required by PEIM and installs PEI > > ReadOnly Varaiable2 PPI. > > [JianJW] typo: "Varaiable2" -> "Variable2" > > > +// > > +// This module implements ReadOnly Variable Services required by PEIM and > > installs PEI ReadOnly Varaiable2 PPI. > > [JianJW] typo: "Varaiable2" -> "Variable2" > > > +// > > +// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> > > +// > > +// SPDX-License-Identifier: BSD-2-Clause-Patent > > +// > > +// **/ > > + > > + > > +#string STR_MODULE_ABSTRACT #language en-US "Implements > > ReadOnly Variable Services required by PEIM and installs PEI ReadOnly > > Varaiable2 PPI" > > [JianJW] typo: "Varaiable2" -> "Variable2" > > > + > > +#string STR_MODULE_DESCRIPTION #language en-US "This module > > implements ReadOnly Variable Services required by PEIM and installs PEI > > ReadOnly Varaiable2 PPI." > > [JianJW] typo: "Varaiable2" -> "Variable2" > > > + > > diff --git > > a/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariableExtra.uni > > b/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariableExtra.uni > > new file mode 100644 > > index 000000000000..22dd992be908 > > --- /dev/null > > +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariableExtra.uni > > @@ -0,0 +1,14 @@ > > +// /** @file > > +// PeiVariable Localized Strings and Content > > +// > > +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> > > +// > > +// SPDX-License-Identifier: BSD-2-Clause-Patent > > +// > > +// **/ > > + > > +#string STR_PROPERTIES_MODULE_NAME > > +#language en-US > > +"Variable Access PEI Module" > > + > > + > > -- > > 2.35.1.windows.2 > > > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#96341): https://edk2.groups.io/g/devel/message/96341 Mute This Topic: https://groups.io/mt/94840824/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-