public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Wang, Jian J" <jian.j.wang@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	"Wang, Jian J" <jian.j.wang@intel.com>,
	"Vang, Judah" <judah.vang@intel.com>
Cc: "Gao, Liming" <gaoliming@byosoft.com.cn>,
	"Wu, Hao A" <hao.a.wu@intel.com>,
	"Mistry, Nishant C" <nishant.c.mistry@intel.com>
Subject: Re: [edk2-devel] [PATCH v5 07/19] MdeModulePkg: Add new Variable functionality
Date: Mon, 14 Nov 2022 04:27:48 +0000	[thread overview]
Message-ID: <MW4PR11MB6763B625FE67BCA3BF40DD72B6059@MW4PR11MB6763.namprd11.prod.outlook.com> (raw)
In-Reply-To: <1727569A8ECB6F9D.19699@groups.io>

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.vang@intel.com>; devel@edk2.groups.io
> Cc: Gao, Liming <gaoliming@byosoft.com.cn>; Wu, Hao A
> <hao.a.wu@intel.com>; Mistry, Nishant C <nishant.c.mistry@intel.com>
> Subject: Re: [edk2-devel] [PATCH v5 07/19] MdeModulePkg: Add new Variable
> functionality
> 
> Hi Judah,
> 
> See my comments (starting with [JianJW]) inline below.
> 
> 
> > -----Original Message-----
> > From: Vang, Judah <judah.vang@intel.com>
> > Sent: Sunday, November 06, 2022 3:35 PM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Gao, Liming
> > <gaoliming@byosoft.com.cn>; Wu, Hao A <hao.a.wu@intel.com>; Mistry,
> > Nishant C <nishant.c.mistry@intel.com>
> > Subject: [PATCH 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.wang@intel.com>
> > Cc: Liming Gao <gaoliming@byosoft.com.cn>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Nishant C Mistry <nishant.c.mistry@intel.com>
> > Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
> > Signed-off-by: Nishant C Mistry <nishant.c.mistry@intel.com>
> > Signed-off-by: Judah Vang <judah.vang@intel.com>
> > Acked-by: Hao A Wu <hao.a.wu@intel.com>
> > ---
> >  MdeModulePkg/Universal/Variable/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
> 
> 
> 
> 
> 


  parent reply	other threads:[~2022-11-14  4:27 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-06  7:34 [PATCH v5 00/19] UEFI variable protection Judah Vang
2022-11-06  7:34 ` [PATCH v5 01/19] MdePkg: Add reference to new Ppi Guid Judah Vang
2022-11-06  7:34 ` [PATCH v5 02/19] MdeModulePkg: Update AUTH_VARIABLE_INFO struct Judah Vang
2022-11-06  7:34 ` [PATCH v5 03/19] MdeModulePkg: Add new ProtectedVariable GUIDs Judah Vang
2022-11-06  7:34 ` [PATCH v5 04/19] MdeModulePkg: Add new include files Judah Vang
2022-11-22  6:31   ` Wang, Jian J
2022-11-06  7:34 ` [PATCH v5 05/19] MdeModulePkg: Add new GUID for Variable Store Info Judah Vang
2022-11-06  7:34 ` [PATCH v5 06/19] MdeModulePkg: Add Null ProtectedVariable Library Judah Vang
2022-11-22  6:39   ` Wang, Jian J
2022-11-06  7:34 ` [PATCH v5 07/19] MdeModulePkg: Add new Variable functionality Judah Vang
2022-11-14  3:43   ` Wang, Jian J
     [not found]   ` <1727569A8ECB6F9D.19699@groups.io>
2022-11-14  4:27     ` Wang, Jian J [this message]
2022-11-06  7:34 ` [PATCH v5 08/19] MdeModulePkg: Add support for Protected Variables Judah Vang
2022-11-14  7:14   ` Wang, Jian J
2022-11-14 17:19     ` Judah Vang
2022-11-15  8:49       ` [edk2-devel] " Sami Mujawar
2022-11-22  6:26         ` Wang, Jian J
     [not found]         ` <1729D430BF77E016.5511@groups.io>
2022-11-22  6:42           ` Wang, Jian J
2022-11-06  7:34 ` [PATCH v5 09/19] MdeModulePkg: Reference Null ProtectedVariableLib Judah Vang
2022-11-22  6:44   ` Wang, Jian J
2022-11-06  7:35 ` [PATCH v5 10/19] SecurityPkg: Add new GUIDs for Judah Vang
2022-11-06  7:35 ` [PATCH v5 11/19] SecurityPkg: Add new KeyService types and defines Judah Vang
2022-11-22  6:46   ` Wang, Jian J
2022-11-06  7:35 ` [PATCH v5 12/19] SecurityPkg: Add new variable types and functions Judah Vang
2022-11-06  7:35 ` [PATCH v5 13/19] SecurityPkg: Update RPMC APIs with index Judah Vang
2022-11-06  7:35 ` [PATCH v5 14/19] SecurityPkg: Fix GetVariableKey API Judah Vang
2022-11-06  7:35 ` [PATCH v5 15/19] SecurityPkg: Add null encryption variable libs Judah Vang
2022-11-22  6:55   ` Wang, Jian J
2022-11-06  7:35 ` [PATCH v5 16/19] SecurityPkg: Add VariableKey library function Judah Vang
2022-11-06  7:35 ` [PATCH v5 17/19] SecurityPkg: Add EncryptionVariable lib with AES Judah Vang
2022-11-22  7:15   ` Wang, Jian J
2022-11-06  7:35 ` [PATCH v5 18/19] SecurityPkg: Add Protected Variable Services Judah Vang
2022-11-22  7:59   ` Wang, Jian J
2022-11-06  7:35 ` [PATCH v5 19/19] SecurityPkg: Add references to new *.inf files Judah Vang
2022-11-22  8:05   ` Wang, Jian J
2022-12-09  8:03 ` [edk2-devel] [PATCH v5 00/19] UEFI variable protection Yao, Jiewen
     [not found] ` <172F11512E3044E7.1612@groups.io>
2022-12-09  9:41   ` Yao, Jiewen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=MW4PR11MB6763B625FE67BCA3BF40DD72B6059@MW4PR11MB6763.namprd11.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox