From: "Judah Vang" <judah.vang@intel.com>
To: devel@edk2.groups.io
Cc: Judah Vang <judah.vang@intel.com>,
Jian J Wang <jian.j.wang@intel.com>,
Liming Gao <gaoliming@byosoft.com.cn>,
Nishant C Mistry <nishant.c.mistry@intel.com>
Subject: [PATCH v1 08/28] MdeModulePkg: Add new Variable functionality
Date: Fri, 25 Mar 2022 16:28:05 -0700 [thread overview]
Message-ID: <20220325232825.2167-4-judah.vang@intel.com> (raw)
In-Reply-To: <20220325232825.2167-1-judah.vang@intel.com>
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2594
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: Nishant C Mistry <nishant.c.mistry@intel.com>
Signed-off-by: Judah Vang <judah.vang@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 | 886 +++---------------
MdeModulePkg/Universal/Variable/Pei/VariableParsing.c | 941 ++++++++++++++++++++
MdeModulePkg/Universal/Variable/Pei/VariableStore.c | 305 +++++++
7 files changed, 1891 insertions(+), 756 deletions(-)
diff --git a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
index 7cbdd2385e8f..af172126a011 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
@@ -39,6 +43,7 @@ [LibraryClasses]
DebugLib
PeiServicesTablePointerLib
PeiServicesLib
+ ProtectedVariableLib
[Guids]
## CONSUMES ## GUID # Variable store header
@@ -56,7 +61,8 @@ [Guids]
gEdkiiFaultTolerantWriteGuid
[Ppis]
- gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES
+ gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES
+ gEfiPeiVariableStoreDiscoveredPpiGuid ## CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.h b/MdeModulePkg/Universal/Variable/Pei/Variable.h
index 7f9ad5bfc357..115426edd626 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
**/
@@ -20,11 +20,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseMemoryLib.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Library/PeiServicesLib.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,
@@ -142,4 +144,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
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.
+
+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 b36dd0de67b2..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.
-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,759 +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_HOB_GUID_TYPE *GuidHob;
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
- VARIABLE_STORE_HEADER *VariableStoreHeader;
- EFI_PHYSICAL_ADDRESS NvStorageBase;
- UINT32 NvStorageSize;
- 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.
- //
-
- NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
- NvStorageBase = (EFI_PHYSICAL_ADDRESS)(PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?
- PcdGet64 (PcdFlashNvStorageVariableBase64) :
- PcdGet32 (PcdFlashNvStorageVariableBase)
- );
- 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.
@@ -1246,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.
+
+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
+ // of its header in consecutive buffer.
+ //
+ if (!GetVariableHeader (&StoreInfo, VariablePtr, &VariableHeader)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return GetVariableInfoInternal (VariableInfo, &StoreInfo, VariablePtr, VariableHeader);
+}
+
+/**
+
+ Retrieve details of the variable next to given variable within VariableStore.
+
+ If VarInfo->Buffer is NULL, the first one in VariableStore is returned.
+
+ VariableStart and/or VariableEnd can be given optionally for the situation
+ in which the valid storage space is smaller than the VariableStore->Size.
+ This usually happens when PEI variable services make a compact variable
+ cache to save memory, which cannot make use VariableStore->Size to determine
+ the correct variable storage range.
+
+ @param[in,out] VariableInfo Pointer to variable information.
+
+ @retval EFI_INVALID_PARAMETER VariableInfo or VariableStore is NULL.
+ @retval EFI_NOT_FOUND If the end of VariableStore is reached.
+ @retval EFI_SUCCESS The next variable is retrieved successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextVariableInfo (
+ IN OUT PROTECTED_VARIABLE_INFO *VariableInfo
+ )
+{
+ VARIABLE_HEADER *VariablePtr;
+ VARIABLE_HEADER *VariableHeader;
+ VARIABLE_STORE_INFO StoreInfo;
+ VARIABLE_STORE_TYPE StoreType;
+ UINTN Offset;
+
+ if (VariableInfo == NULL) {
+ ASSERT (VariableInfo != NULL);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StoreInfo.VariableStoreHeader = NULL;
+ for (StoreType = VariableStoreTypeHob; StoreType < VariableStoreTypeMax; ++StoreType) {
+ GetVariableStore (StoreType, &StoreInfo);
+ if (StoreInfo.VariableStoreHeader != NULL) {
+ break;
+ }
+ }
+
+ ASSERT (StoreInfo.VariableStoreHeader != NULL);
+
+ //
+ // VariableInfo->StoreIndex is supposed to be the index to variable found
+ // last time. Use it to get the variable next to it in store. If it's invalid,
+ // return the first variable available in store.
+ //
+ VariableInfo->Flags.Auth = StoreInfo.AuthFlag;
+ if (VariableInfo->StoreIndex == VAR_INDEX_INVALID) {
+ VariablePtr = GetStartPointer (StoreInfo.VariableStoreHeader);
+ } else {
+ Offset = (UINTN)VariableInfo->StoreIndex;
+ if ( (StoreInfo.FtwLastWriteData != NULL)
+ && (Offset >= ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress
+ - (UINTN)StoreInfo.VariableStoreHeader)))
+ {
+ Offset -= ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress
+ - (UINTN)StoreInfo.VariableStoreHeader);
+ VariablePtr = (VARIABLE_HEADER *)
+ ((UINTN)StoreInfo.FtwLastWriteData->SpareAddress + Offset);
+ } else {
+ VariablePtr = (VARIABLE_HEADER *)
+ ((UINTN)StoreInfo.VariableStoreHeader + Offset);
+ }
+
+ //
+ // Note that variable might be in unconsecutive space. Always get a copy
+ // 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..72bd17a43048
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/Pei/VariableStore.c
@@ -0,0 +1,305 @@
+/** @file
+ Implement ReadOnly Variable Services required by PEIM and install
+ PEI ReadOnly Varaiable2 PPI. These services operates the non volatile storage space.
+
+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_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;
+
+ NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
+ NvStorageBase = (EFI_PHYSICAL_ADDRESS)
+ (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0)
+ ? PcdGet64 (PcdFlashNvStorageVariableBase64)
+ : PcdGet32 (PcdFlashNvStorageVariableBase);
+ ASSERT (NvStorageBase != 0);
+
+ 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.26.2.windows.1
next prev parent reply other threads:[~2022-03-25 23:28 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-25 23:28 [PATCH v1 05/28] MdeModulePkg: Add new ProtectedVariable GUIDs Judah Vang
2022-03-25 23:28 ` [PATCH v1 06/28] MdeModulePkg: Add new include files Judah Vang
2022-03-25 23:28 ` [PATCH v1 07/28] MdeModulePkg: Add Null ProtectedVariable Library Judah Vang
2022-03-25 23:28 ` Judah Vang [this message]
2022-03-25 23:28 ` [PATCH v1 09/28] MdeModulePkg: Add support for Protected Variables Judah Vang
2022-03-25 23:28 ` [PATCH v1 10/28] SecurityPkg: Add new KeyService types and defines Judah Vang
2022-03-25 23:28 ` [PATCH v1 11/28] SecurityPkg: Update RPMC APIs with index Judah Vang
2022-03-25 23:28 ` [PATCH v1 12/28] SecurityPkg: Add new variable types and functions Judah Vang
2022-03-25 23:28 ` [PATCH v1 13/28] SecurityPkg: Fix GetVariableKey API Judah Vang
2022-03-25 23:28 ` [PATCH v1 14/28] SecurityPkg: Add null encryption variable libs Judah Vang
2022-03-25 23:28 ` [PATCH v1 15/28] SecurityPkg: Add VariableKey library function Judah Vang
2022-03-25 23:28 ` [PATCH v1 16/28] SecurityPkg: Add EncryptionVariable lib with AES Judah Vang
2022-03-25 23:28 ` [PATCH v1 17/28] SecurityPkg: Add Protected Variable Services Judah Vang
2022-03-25 23:28 ` [PATCH v1 18/28] MdeModulePkg: Reference Null ProtectedVariableLib Judah Vang
2022-03-25 23:28 ` [PATCH v1 19/28] SecurityPkg: Add references to new *.inf files Judah Vang
2022-03-25 23:28 ` [PATCH v1 20/28] ArmVirtPkg: Add reference to ProtectedVariableNull Judah Vang
2022-03-25 23:28 ` [PATCH v1 21/28] UefiPayloadPkg: Add ProtectedVariable reference Judah Vang
2022-03-28 1:31 ` Ni, Ray
2022-03-25 23:28 ` [PATCH v1 22/28] EmulatorPkg: " Judah Vang
2022-03-28 1:30 ` Ni, Ray
2022-03-25 23:28 ` [PATCH v1 23/28] OvmfPkg: " Judah Vang
2022-03-25 23:28 ` [PATCH v1 24/28] OvmfPkg: Add ProtectedVariableLib reference Judah Vang
2022-03-25 23:28 ` [PATCH v1 25/28] " Judah Vang
2022-03-25 23:28 ` [PATCH v1 26/28] " Judah Vang
2022-03-25 23:28 ` [PATCH v1 27/28] OvmfPkg: Add ProtectedVariable reference Judah Vang
2022-03-28 7:42 ` Boeuf, Sebastien
2022-03-25 23:28 ` [PATCH v1 28/28] CryptoPkg: Enable cypto HMAC KDF library 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=20220325232825.2167-4-judah.vang@intel.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