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