From nobody Tue Feb 10 15:29:46 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+95988+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+95988+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1667720145; cv=none; d=zohomail.com; s=zohoarc; b=iz6bWo53XCXZQ/6MEz5NDjyVozQ6RwEI2iWkMrtOqTF3deM4hUfu2cgQtxk3x0Lu3MTmJuurkde+TWy8W4J799IDyh/ZxV0CQxaMNgLRLvT/LI0yR672nSld1TBLF7Q1Cmr5c90FsYQwzcTH9gNa3/o2evSZgqWrjtq2GWGingI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1667720145; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=Zgr7zofCp/+/tzPjxf+n40i4Jt9TWUS8xdvFpJ3gKGs=; b=hmoUQYemcLiX07O72C4SiXfYHfV3MgTZWNgVwHnsDqaTjW2Kzm5KlGAQrfBet8/MFDg10u8wgW7OTTLyljIikGG9RViEjxuVFA8Cc/zndEVoIQubXJMIaGaI578pyw3GYDvTtOvIPL3ht0FRG+WU4K8RxJ7qobY+r9RKcAMRPdw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+95988+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1667720145913802.5773735385036; Sun, 6 Nov 2022 00:35:45 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id Xh6cYY1788612xfTG8msnkuq; Sun, 06 Nov 2022 00:35:44 -0700 X-Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mx.groups.io with SMTP id smtpd.web10.14306.1667720141929357296 for ; Sun, 06 Nov 2022 00:35:42 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10522"; a="336948734" X-IronPort-AV: E=Sophos;i="5.96,142,1665471600"; d="scan'208";a="336948734" X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Nov 2022 00:35:28 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10522"; a="810513452" X-IronPort-AV: E=Sophos;i="5.96,142,1665471600"; d="scan'208";a="810513452" X-Received: from jvang-mobl.amr.corp.intel.com ([10.209.139.244]) by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Nov 2022 00:35:27 -0700 From: "Judah Vang" To: devel@edk2.groups.io Cc: Jian J Wang , Liming Gao , Hao A Wu , Nishant C Mistry Subject: [edk2-devel] [PATCH v5 07/19] MdeModulePkg: Add new Variable functionality Date: Sun, 6 Nov 2022 00:34:57 -0700 Message-Id: <20221106073509.3071-8-judah.vang@intel.com> In-Reply-To: <20221106073509.3071-1-judah.vang@intel.com> References: <20221106073509.3071-1-judah.vang@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,judah.vang@intel.com X-Gm-Message-State: wS0dgPLn0QmioVpbPRLHwpI0x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1667720144; bh=lYiISyCC0S9F0pR6S8GT7W5lng+QqNSdvRIXsvaOWSQ=; h=Cc:Date:From:Reply-To:Subject:To; b=FzhSeLJUZnOpc17+KlxWyetfl1fq1B0KGLIYj8vkNxM4PT6tzEImALKXA5dbN1P0Sef OV+j6l/Sk1DjvCraIWlqTpaf/ejAELn8kwxLNNOtEE1Vs3/vFTNwNudnO4ArOgwgreV1n tP02n4HwTof3oLrNH868a8ZWeQUYEnJFa2E= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1667720146951100032 Content-Type: text/plain; charset="utf-8" REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2594 V5: Add PEI Variable Protection into a new directory and leave the existing PEI Variable unchanged. V3: Update GetNvVariableStore() to call GetVariableFlashNvStorageInfo() and SafeUint64ToUint32(). V1: Provide new APIs for retrieving variable information. Add new function stubs for retrieving Protected variable information. Cc: Jian J Wang Cc: Liming Gao Cc: Hao A Wu Cc: Nishant C Mistry Signed-off-by: Jian J Wang Signed-off-by: Nishant C Mistry Signed-off-by: Judah Vang Acked-by: Hao A Wu --- MdeModulePkg/Universal/Variable/Protected/Pei/VariablePei.inf | 79 ++ MdeModulePkg/Universal/Variable/Protected/Pei/Variable.h | 225 += ++++ MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.h | 309 += ++++++ MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.h | 116 += ++ MdeModulePkg/Universal/Variable/Protected/Pei/Variable.c | 628 += ++++++++++++ MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.c | 941 += +++++++++++++++++++ MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.c | 307 += ++++++ MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariable.uni | 16 + MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariableExtra.uni | 14 + 9 files changed, 2635 insertions(+) diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/VariablePei.inf = b/MdeModulePkg/Universal/Variable/Protected/Pei/VariablePei.inf new file mode 100644 index 000000000000..953a7c6b884f --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/VariablePei.inf @@ -0,0 +1,79 @@ +## @file +# Implements ReadOnly Variable Services required by PEIM and installs PEI= ReadOnly Varaiable2 PPI. +# +# This module implements ReadOnly Variable Services required by PEIM and = installs PEI ReadOnly Varaiable2 PPI. +# +# Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PeiVariable + MODULE_UNI_FILE =3D PeiVariable.uni + FILE_GUID =3D 8D104D19-593B-4DDF-81CF-8168A9EDE9C7 + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D PeimInitializeVariableServices + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +# + +[Sources] + Variable.c + Variable.h + VariableStore.c + VariableStore.h + VariableParsing.c + VariableParsing.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseMemoryLib + PcdLib + HobLib + PeimEntryPoint + DebugLib + PeiServicesTablePointerLib + PeiServicesLib + SafeIntLib + VariableFlashInfoLib + ProtectedVariableLib + +[Guids] + ## CONSUMES ## GUID # Variable store header + ## SOMETIMES_CONSUMES ## HOB + gEfiAuthenticatedVariableGuid + ## SOMETIMES_CONSUMES ## GUID # Variable store header + ## SOMETIMES_CONSUMES ## HOB + gEfiVariableGuid + ## SOMETIMES_PRODUCES ## HOB + ## SOMETIMES_CONSUMES ## HOB + gEfiVariableIndexTableGuid + gEfiSystemNvDataFvGuid ## SOMETIMES_CONSUMES ## GUID + ## SOMETIMES_CONSUMES ## HOB + ## CONSUMES ## GUID # Dependence + gEdkiiFaultTolerantWriteGuid + +[Ppis] + gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES + gEfiPeiVariableStoreDiscoveredPpiGuid ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable ## SOM= ETIMES_CONSUMES + +[Depex] + gEdkiiFaultTolerantWriteGuid + +# [BootMode] +# RECOVERY_FULL ## SOMETIMES_CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + PeiVariableExtra.uni diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.h b/Mde= ModulePkg/Universal/Variable/Protected/Pei/Variable.h new file mode 100644 index 000000000000..1bdbdd2b807b --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.h @@ -0,0 +1,225 @@ +/** @file + The internal header file includes the common header files, defines + internal structure and functions used by PeiVariable module. + +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PEI_VARIABLE_H_ +#define PEI_VARIABLE_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +typedef enum { + VariableStoreTypeHob, + VariableStoreTypeNv, + VariableStoreTypeMax +} VARIABLE_STORE_TYPE; + +typedef struct { + VARIABLE_STORE_HEADER *VariableStoreHeader; + VARIABLE_INDEX_TABLE *IndexTable; + // + // If it is not NULL, it means there may be an inconsecutive variable wh= ose + // partial content is still in NV storage, but another partial content i= s backed up + // in spare block. + // + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData; + BOOLEAN AuthFlag; +} VARIABLE_STORE_INFO; + +// +// Functions +// + +/** + Provide the functionality of the variable services. + + @param FileHandle Handle of the file being invoked. + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFi= le(). + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed + @retval Others Returned from PeiServicesInstallPpi() + +**/ +EFI_STATUS +EFIAPI +PeimInitializeVariableServices ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + This service retrieves a variable's value using its name and GUID. + + Read the specified variable from the UEFI variable store. If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buf= fer + 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 varia= ble's GUID. The combination of + VariableGuid and VariableName must be uniq= ue. + @param Attributes If non-NULL, on return, points to the vari= able's attributes. + @param DataSize On entry, points to the size in bytes of t= he Data buffer. + On return, points to the size of the data = returned in Data. + @param Data Points to the buffer which will hold the r= eturned 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 resultin= g data. + DataSize is updated with the size required= for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Da= ta is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved becaus= e of a device error. + +**/ +EFI_STATUS +EFIAPI +PeiGetVariable ( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param This A pointer to this instance of the EFI_PEI_READ= _ONLY_VARIABLE2_PPI. + + @param VariableNameSize On entry, points to the size of the buffer poi= nted to by VariableName. + @param VariableName On entry, a pointer to a null-terminated strin= g 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 t= he variable's GUID. + On return, a pointer to the next variable's GU= ID. + + @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 becaus= e of a device error. + +**/ +EFI_STATUS +EFIAPI +PeiGetNextVariableName ( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid + ); + +/** + This service retrieves a variable's value using its name and GUID. + + Read the specified variable from the UEFI variable store. If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buf= fer + 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 varia= ble's GUID. The combination of + VariableGuid and VariableName must be uniq= ue. + @param Attributes If non-NULL, on return, points to the vari= able's attributes. + @param DataSize On entry, points to the size in bytes of t= he Data buffer. + On return, points to the size of the data = returned in Data. + @param Data Points to the buffer which will hold the r= eturned 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 resultin= g data. + DataSize is updated with the size required= for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Da= ta is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved becaus= e 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 poi= nted to by VariableName. + @param VariableName On entry, a pointer to a null-terminated strin= g 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 t= he variable's GUID. + On return, a pointer to the next variable's GU= ID. + + @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 becaus= e 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/Protected/Pei/VariableParsing.= h b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.h new file mode 100644 index 000000000000..d7af6cb6e8be --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.h @@ -0,0 +1,309 @@ +/** @file + The internal header file includes the common header files, defines + internal structure and functions used by PeiVariable module. + +Copyright (c) 2022, Intel Corporation. All rights reserved.
+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 ar= ea. + + @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 co= nsecutive 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 co= nsecutive 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 tha= t 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 conse= cutive 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 VariableS= tore. + + If VarInfo->Address is NULL, the first one in VariableStore is returned. + + VariableStart and/or VariableEnd can be given optionally for the situati= on + 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 deter= mine + 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 successful= ly. + +**/ +EFI_STATUS +EFIAPI +GetNextVariableInfo ( + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo + ); + +/** + + Retrieve details about a variable and return them in VariableInfo->Heade= r. + + If VariableInfo->Address is given, this function will calculate its offs= et + relative to given variable storage via VariableStore; Otherwise, it will= try + other internal variable storages or cached copies. It's assumed that, fo= r all + copies of NV variable storage, all variables are stored in the same rela= tive + 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->Addres= s, + this function will return the variable memory address inside VariableSto= re, + if given, via VariableInfo->Address; Otherwise, the address of other sto= rage + 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 rang= e of + any given or internal storage copies. + @retval EFI_SUCCESS Variable details are retrieved successful= ly. + +**/ +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 rang= e of + any given or internal storage copies. + @retval EFI_SUCCESS Variable details are retrieved successful= ly. + +**/ +EFI_STATUS +FindVariableEx ( + IN VARIABLE_STORE_INFO *StoreInfo, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack + ); + +#endif diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.h = b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.h new file mode 100644 index 000000000000..6e2f6f939bab --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.h @@ -0,0 +1,116 @@ +/** @file + Implement ReadOnly Variable Services required by PEIM and install + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile st= orage space. + +Copyright (c) 2022, Intel Corporation. All rights reserved.
+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 sto= re. + +**/ +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 en= tries of + VariableNumber. + @param[out] VariableNumber Number of valid variables. + @param[out] AuthFlag Aut-variable indicator. + + @return EFI_INVALID_PARAMETER Invalid StoreCacheSize and/or StoreCacheBa= se. + @return EFI_VOLUME_CORRUPTED Invalid or no NV variable storage found. + @return EFI_BUFFER_TOO_SMALL StoreCacheSize is smaller than needed. + @return EFI_SUCCESS NV variable storage is cached successfully. +**/ +EFI_STATUS +EFIAPI +InitNvVariableStore ( + OUT EFI_PHYSICAL_ADDRESS StoreCacheBase OPTIONAL, + IN OUT UINT32 *StoreCacheSize, + OUT UINT32 *IndexTable OPTIONAL, + OUT UINT32 *VariableNumber OPTIONAL, + OUT BOOLEAN *AuthFlag OPTIONAL + ); + +#endif diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.c b/Mde= ModulePkg/Universal/Variable/Protected/Pei/Variable.c new file mode 100644 index 000000000000..ce790946626e --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/Variable.c @@ -0,0 +1,628 @@ +/** @file + Implement ReadOnly Variable Services required by PEIM and install + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile st= orage space. + +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
+Copyright (c) Microsoft Corporation.
+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 =3D { + PeiGetVariableEx, + PeiGetNextVariableNameEx +}; + +EFI_PEI_PPI_DESCRIPTOR mPpiListVariable =3D { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiReadOnlyVariable2PpiGuid, + &mVariablePpi +}; + +/** + Provide the functionality of the variable services. + + @param FileHandle Handle of the file being invoked. + Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextF= ile(). + @param PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS If the interface could be successfully installed + @retval Others Returned from PeiServicesInstallPpi() +**/ +EFI_STATUS +EFIAPI +PeimInitializeVariableServices ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + PROTECTED_VARIABLE_CONTEXT_IN ContextIn; + + // + // If protected variable services are not supported, EFI_UNSUPPORTED sho= uld + // be always returned. Check it here. + // + ContextIn.StructVersion =3D PROTECTED_VARIABLE_CONTEXT_IN_STRUCT_VERSION; + ContextIn.StructSize =3D sizeof (ContextIn); + + ContextIn.MaxVariableSize =3D 0; + ContextIn.VariableServiceUser =3D FromPeiModule; + ContextIn.GetVariableInfo =3D GetVariableInfo; + ContextIn.GetNextVariableInfo =3D GetNextVariableInfo; + ContextIn.FindVariableSmm =3D NULL; + ContextIn.UpdateVariableStore =3D NULL; + ContextIn.UpdateVariable =3D NULL; + ContextIn.IsHobVariableStoreAvailable =3D IsHobVariableStoreAvailable; + + Status =3D ProtectedVariableLibInitialize (&ContextIn); + if (EFI_ERROR (Status) && (Status !=3D EFI_UNSUPPORTED)) { + return Status; + } + + return PeiServicesInstallPpi (&mPpiListVariable); +} + +/** + Find the variable in the specified variable store. + + @param StoreInfo Pointer to the store info structure. + @param VariableName Name of the variable to be found + @param VendorGuid Vendor GUID to be found. + @param PtrTrack Variable Track Pointer structure that contai= ns Variable Information. + + @retval EFI_SUCCESS Variable found successfully + @retval EFI_NOT_FOUND Variable not found + @retval EFI_INVALID_PARAMETER Invalid variable name + +**/ +EFI_STATUS +FindVariableEx ( + IN VARIABLE_STORE_INFO *StoreInfo, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack + ) +{ + VARIABLE_HEADER *Variable; + VARIABLE_HEADER *LastVariable; + VARIABLE_HEADER *MaxIndex; + UINTN Index; + UINTN Offset; + BOOLEAN StopRecord; + VARIABLE_HEADER *InDeletedVariable; + VARIABLE_STORE_HEADER *VariableStoreHeader; + VARIABLE_INDEX_TABLE *IndexTable; + VARIABLE_HEADER *VariableHeader; + + VariableStoreHeader =3D StoreInfo->VariableStoreHeader; + + if (VariableStoreHeader =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (GetVariableStoreStatus (VariableStoreHeader) !=3D EfiValid) { + return EFI_UNSUPPORTED; + } + + if (~VariableStoreHeader->Size =3D=3D 0) { + return EFI_NOT_FOUND; + } + + IndexTable =3D StoreInfo->IndexTable; + PtrTrack->StartPtr =3D GetStartPointer (VariableStoreHeader); + PtrTrack->EndPtr =3D GetEndPointer (VariableStoreHeader); + + InDeletedVariable =3D NULL; + + // + // No Variable Address equals zero, so 0 as initial value is safe. + // + MaxIndex =3D NULL; + VariableHeader =3D NULL; + + if (IndexTable !=3D NULL) { + // + // traverse the variable index table to look for varible. + // The IndexTable->Index[Index] records the distance of two neighbouri= ng VAR_ADDED type variables. + // + for (Offset =3D 0, Index =3D 0; Index < IndexTable->Length; Index++) { + ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Ind= ex[0])); + Offset +=3D IndexTable->Index[Index]; + MaxIndex =3D (VARIABLE_HEADER *)((UINT8 *)IndexTable->StartPtr + Off= set); + GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader); + if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, V= ariableName, VendorGuid, PtrTrack) =3D=3D EFI_SUCCESS) { + if (VariableHeader->State =3D=3D (VAR_IN_DELETED_TRANSITION & VAR_= ADDED)) { + InDeletedVariable =3D PtrTrack->CurrPtr; + } else { + return EFI_SUCCESS; + } + } + } + + if (IndexTable->GoneThrough !=3D 0) { + // + // If the table has all the existing variables indexed, return. + // + PtrTrack->CurrPtr =3D InDeletedVariable; + return (PtrTrack->CurrPtr =3D=3D NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; + } + } + + if (MaxIndex !=3D NULL) { + // + // HOB exists but the variable cannot be found in HOB + // If not found in HOB, then let's start from the MaxIndex we've found. + // + Variable =3D GetNextVariablePtr (StoreInfo, MaxIndex, VariableHead= er); + LastVariable =3D MaxIndex; + } else { + // + // Start Pointers for the variable. + // Actual Data Pointer where data can be written. + // + Variable =3D PtrTrack->StartPtr; + LastVariable =3D PtrTrack->StartPtr; + } + + // + // Find the variable by walk through variable store + // + StopRecord =3D FALSE; + while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) { + if ((VariableHeader->State =3D=3D VAR_ADDED) || (VariableHeader->State= =3D=3D (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) { + // + // Record Variable in VariableIndex HOB + // + if ((IndexTable !=3D NULL) && !StopRecord) { + Offset =3D (UINTN)Variable - (UINTN)LastVariable; + if ((Offset > 0x0FFFF) || (IndexTable->Length >=3D sizeof (IndexTa= ble->Index) / sizeof (IndexTable->Index[0]))) { + // + // Stop to record if the distance of two neighbouring VAR_ADDED = variable is larger than the allowable scope(UINT16), + // or the record buffer is full. + // + StopRecord =3D TRUE; + } else { + IndexTable->Index[IndexTable->Length++] =3D (UINT16)Offset; + LastVariable =3D Variable; + } + } + + if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, V= ariableName, VendorGuid, PtrTrack) =3D=3D EFI_SUCCESS) { + if (VariableHeader->State =3D=3D (VAR_IN_DELETED_TRANSITION & VAR_= ADDED)) { + InDeletedVariable =3D PtrTrack->CurrPtr; + } else { + return EFI_SUCCESS; + } + } + } + + Variable =3D GetNextVariablePtr (StoreInfo, Variable, VariableHeader); + } + + // + // If gone through the VariableStore, that means we never find in Firmwa= re any more. + // + if ((IndexTable !=3D NULL) && !StopRecord) { + IndexTable->GoneThrough =3D 1; + } + + PtrTrack->CurrPtr =3D InDeletedVariable; + + return (PtrTrack->CurrPtr =3D=3D NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; +} + +/** + Find the variable in HOB and Non-Volatile variable storages. + + @param VariableName Name of the variable to be found + @param VendorGuid Vendor GUID to be found. + @param PtrTrack Variable Track Pointer structure that contains Var= iable Information. + @param StoreInfo Return the store info. + + @retval EFI_SUCCESS Variable found successfully + @retval EFI_NOT_FOUND Variable not found + @retval EFI_INVALID_PARAMETER Invalid variable name +**/ +EFI_STATUS +FindVariable ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack, + OUT VARIABLE_STORE_INFO *StoreInfo + ) +{ + EFI_STATUS Status; + VARIABLE_STORE_TYPE Type; + + if ((VariableName[0] !=3D 0) && (VendorGuid =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + for (Type =3D (VARIABLE_STORE_TYPE)0; Type < VariableStoreTypeMax; Type+= +) { + GetVariableStore (Type, StoreInfo); + Status =3D FindVariableEx ( + StoreInfo, + VariableName, + VendorGuid, + PtrTrack + ); + if (!EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_NOT_FOUND; +} + +/** + This service retrieves a variable's value using its name and GUID. + + Read the specified variable from the UEFI variable store. If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buf= fer + 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 varia= ble's GUID. The combination of + VariableGuid and VariableName must be uniq= ue. + @param Attributes If non-NULL, on return, points to the vari= able's attributes. + @param DataSize On entry, points to the size in bytes of t= he Data buffer. + On return, points to the size of the data = returned in Data. + @param Data Points to the buffer which will hold the r= eturned 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 resultin= g data. + DataSize is updated with the size required= for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Da= ta is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved becaus= e of a device error. + +**/ +EFI_STATUS +EFIAPI +PeiGetVariable ( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ) +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarDataSize; + EFI_STATUS Status; + VARIABLE_STORE_INFO StoreInfo; + VARIABLE_HEADER *VariableHeader; + + if ((VariableName =3D=3D NULL) || (VariableGuid =3D=3D NULL) || (DataSiz= e =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (VariableName[0] =3D=3D 0) { + return EFI_NOT_FOUND; + } + + VariableHeader =3D NULL; + + // + // Find existing variable + // + Status =3D FindVariable (VariableName, VariableGuid, &Variable, &StoreIn= fo); + if (EFI_ERROR (Status)) { + return Status; + } + + GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader); + + // + // Get data size + // + VarDataSize =3D DataSizeOfVariable (VariableHeader, StoreInfo.AuthFlag); + if (*DataSize >=3D VarDataSize) { + if (Data =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPt= r, VariableHeader, StoreInfo.AuthFlag), VarDataSize, Data); + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_BUFFER_TOO_SMALL; + } + + if (Attributes !=3D NULL) { + *Attributes =3D VariableHeader->Attributes; + } + + *DataSize =3D VarDataSize; + + return Status; +} + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param This A pointer to this instance of the EFI_PEI_READ= _ONLY_VARIABLE2_PPI. + + @param VariableNameSize On entry, points to the size of the buffer poi= nted to by VariableName. + On return, the size of the variable name buffe= r. + @param VariableName On entry, a pointer to a null-terminated strin= g 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 GU= ID. + + @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 becaus= e of a device error. + +**/ +EFI_STATUS +EFIAPI +PeiGetNextVariableName ( + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid + ) +{ + VARIABLE_STORE_TYPE Type; + VARIABLE_POINTER_TRACK Variable; + VARIABLE_POINTER_TRACK VariableInHob; + VARIABLE_POINTER_TRACK VariablePtrTrack; + UINTN VarNameSize; + EFI_STATUS Status; + VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; + VARIABLE_HEADER *VariableHeader; + VARIABLE_STORE_INFO StoreInfo; + VARIABLE_STORE_INFO StoreInfoForNv; + VARIABLE_STORE_INFO StoreInfoForHob; + + if ((VariableName =3D=3D NULL) || (VariableGuid =3D=3D NULL) || (Variabl= eNameSize =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + VariableHeader =3D NULL; + + Status =3D FindVariable (VariableName, VariableGuid, &Variable, &StoreIn= fo); + if ((Variable.CurrPtr =3D=3D NULL) || (Status !=3D EFI_SUCCESS)) { + return Status; + } + + if (VariableName[0] !=3D 0) { + // + // If variable name is not NULL, get next variable + // + GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader); + Variable.CurrPtr =3D GetNextVariablePtr (&StoreInfo, Variable.CurrPtr,= VariableHeader); + } + + VariableStoreHeader[VariableStoreTypeHob] =3D GetVariableStore (Variable= StoreTypeHob, &StoreInfoForHob); + VariableStoreHeader[VariableStoreTypeNv] =3D GetVariableStore (Variable= StoreTypeNv, &StoreInfoForNv); + + while (TRUE) { + // + // Switch from HOB to Non-Volatile. + // + while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHead= er)) { + // + // Find current storage index + // + for (Type =3D (VARIABLE_STORE_TYPE)0; Type < VariableStoreTypeMax; T= ype++) { + if ((VariableStoreHeader[Type] !=3D NULL) && (Variable.StartPtr = =3D=3D GetStartPointer (VariableStoreHeader[Type]))) { + break; + } + } + + ASSERT (Type < VariableStoreTypeMax); + // + // Switch to next storage + // + for (Type++; Type < VariableStoreTypeMax; Type++) { + if (VariableStoreHeader[Type] !=3D NULL) { + break; + } + } + + // + // Capture the case that + // 1. current storage is the last one, or + // 2. no further storage + // + if (Type =3D=3D VariableStoreTypeMax) { + return EFI_NOT_FOUND; + } + + Variable.StartPtr =3D GetStartPointer (VariableStoreHeader[Type]); + Variable.EndPtr =3D GetEndPointer (VariableStoreHeader[Type]); + Variable.CurrPtr =3D Variable.StartPtr; + GetVariableStore (Type, &StoreInfo); + } + + if ((VariableHeader->State =3D=3D VAR_ADDED) || (VariableHeader->State= =3D=3D (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) { + if (VariableHeader->State =3D=3D (VAR_IN_DELETED_TRANSITION & VAR_AD= DED)) { + // + // If it is a IN_DELETED_TRANSITION variable, + // and there is also a same ADDED one at the same time, + // don't return it. + // + Status =3D FindVariableEx ( + &StoreInfo, + GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFla= g), + GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), + &VariablePtrTrack + ); + if (!EFI_ERROR (Status) && (VariablePtrTrack.CurrPtr !=3D Variable= .CurrPtr)) { + Variable.CurrPtr =3D GetNextVariablePtr (&StoreInfo, Variable.Cu= rrPtr, VariableHeader); + continue; + } + } + + // + // Don't return NV variable when HOB overrides it + // + if ((VariableStoreHeader[VariableStoreTypeHob] !=3D NULL) && (Variab= leStoreHeader[VariableStoreTypeNv] !=3D NULL) && + (Variable.StartPtr =3D=3D GetStartPointer (VariableStoreHeader[V= ariableStoreTypeNv])) + ) + { + Status =3D FindVariableEx ( + &StoreInfoForHob, + GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFla= g), + GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), + &VariableInHob + ); + if (!EFI_ERROR (Status)) { + Variable.CurrPtr =3D GetNextVariablePtr (&StoreInfo, Variable.Cu= rrPtr, VariableHeader); + continue; + } + } + + VarNameSize =3D NameSizeOfVariable (VariableHeader, StoreInfo.AuthFl= ag); + ASSERT (VarNameSize !=3D 0); + + if (VarNameSize <=3D *VariableNameSize) { + GetVariableNameOrData (&StoreInfo, (UINT8 *)GetVariableNamePtr (Va= riable.CurrPtr, StoreInfo.AuthFlag), VarNameSize, (UINT8 *)VariableName); + + CopyMem (VariableGuid, GetVendorGuidPtr (VariableHeader, StoreInfo= .AuthFlag), sizeof (EFI_GUID)); + + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize =3D VarNameSize; + // + // Variable is found + // + return Status; + } else { + Variable.CurrPtr =3D GetNextVariablePtr (&StoreInfo, Variable.CurrPt= r, VariableHeader); + } + } +} + +/** + This service retrieves a variable's value using its name and GUID. + + Read the specified variable from the UEFI variable store. If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buf= fer + 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 varia= ble's GUID. The combination of + VariableGuid and VariableName must be uniq= ue. + @param Attributes If non-NULL, on return, points to the vari= able's attributes. + @param DataSize On entry, points to the size in bytes of t= he Data buffer. + On return, points to the size of the data = returned in Data. + @param Data Points to the buffer which will hold the r= eturned 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 resultin= g data. + DataSize is updated with the size required= for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Da= ta is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved becaus= e 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 =3D ProtectedVariableLibGetByName (VariableName, VariableGuid, At= tributes, DataSize, Data); + if (Status !=3D EFI_UNSUPPORTED) { + return Status; + } + + return PeiGetVariable (This, VariableName, VariableGuid, Attributes, Dat= aSize, 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 poi= nted to by VariableName. + On return, the size of the variable name buffe= r. + @param VariableName On entry, a pointer to a null-terminated strin= g 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 GU= ID. + + @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 becaus= e 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 =3D ProtectedVariableLibFindNext (VariableNameSize, VariableName,= VariableGuid); + if (Status !=3D EFI_UNSUPPORTED) { + return Status; + } + + return PeiGetNextVariableName (This, VariableNameSize, VariableName, Var= iableGuid); +} diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.= c b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.c new file mode 100644 index 000000000000..2d605d39cbb6 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableParsing.c @@ -0,0 +1,941 @@ +/** @file + Implement ReadOnly Variable Services required by PEIM and install + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile st= orage space. + +Copyright (c) 2022, Intel Corporation. All rights reserved.
+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 ar= ea. + + @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 + VarStore= Header->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 =3D=3D NULL) || (Variable->StartId !=3D 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 =3D sizeof (AUTHENTICATED_VARIABLE_HEADER); + } else { + Value =3D 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 =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; + if (AuthFlag) { + if ((AuthVariable->State =3D=3D (UINT8)(-1)) || + (AuthVariable->DataSize =3D=3D (UINT32)(-1)) || + (AuthVariable->NameSize =3D=3D (UINT32)(-1)) || + (AuthVariable->Attributes =3D=3D (UINT32)(-1))) + { + return 0; + } + + return (UINTN)AuthVariable->NameSize; + } else { + if ((Variable->State =3D=3D (UINT8)(-1)) || + (Variable->DataSize =3D=3D (UINT32)(-1)) || + (Variable->NameSize =3D=3D (UINT32)(-1)) || + (Variable->Attributes =3D=3D (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 =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; + if (AuthFlag) { + if ((AuthVariable->State =3D=3D (UINT8)(-1)) || + (AuthVariable->DataSize =3D=3D (UINT32)(-1)) || + (AuthVariable->NameSize =3D=3D (UINT32)(-1)) || + (AuthVariable->Attributes =3D=3D (UINT32)(-1))) + { + return 0; + } + + return (UINTN)AuthVariable->DataSize; + } else { + if ((Variable->State =3D=3D (UINT8)(-1)) || + (Variable->DataSize =3D=3D (UINT32)(-1)) || + (Variable->NameSize =3D=3D (UINT32)(-1)) || + (Variable->Attributes =3D=3D (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 =3D (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 co= nsecutive 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 =3D (UINTN)GetVariableNamePtr (Variable, AuthFlag); + Value +=3D NameSizeOfVariable (VariableHeader, AuthFlag); + Value +=3D 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 co= nsecutive 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 =3D (UINTN)GetVariableDataPtr (Variable, VariableHeader, StoreIn= fo->AuthFlag); + Value +=3D DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag); + Value +=3D GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo->= AuthFlag)); + // + // Be careful about pad size for alignment + // + Value =3D HEADER_ALIGN (Value); + + if (StoreInfo->FtwLastWriteData !=3D NULL) { + TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; + SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; + if (((UINTN)Variable < (UINTN)TargetAddress) && (Value >=3D (UINTN)Tar= getAddress)) { + // + // Next variable is in spare block. + // + Value =3D (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 !=3D NULL) { + TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; + SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; + if (((UINTN)Name1 < (UINTN)TargetAddress) && (((UINTN)Name1 + NameSize= ) > (UINTN)TargetAddress)) { + // + // Name1 is inconsecutive. + // + PartialNameSize =3D (UINTN)TargetAddress - (UINTN)Name1; + // + // Partial content is in NV storage. + // + if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, PartialNameSize) =3D= =3D 0) { + // + // Another partial content is in spare block. + // + if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name2 + Par= tialNameSize, NameSize - PartialNameSize) =3D=3D 0) { + return TRUE; + } + } + + return FALSE; + } else if (((UINTN)Name2 < (UINTN)TargetAddress) && (((UINTN)Name2 + N= ameSize) > (UINTN)TargetAddress)) { + // + // Name2 is inconsecutive. + // + PartialNameSize =3D (UINTN)TargetAddress - (UINTN)Name2; + // + // Partial content is in NV storage. + // + if (CompareMem ((UINT8 *)Name2, (UINT8 *)Name1, PartialNameSize) =3D= =3D 0) { + // + // Another partial content is in spare block. + // + if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name1 + Par= tialNameSize, NameSize - PartialNameSize) =3D=3D 0) { + return TRUE; + } + } + + return FALSE; + } + } + + // + // Both Name1 and Name2 are consecutive. + // + if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, NameSize) =3D=3D 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 'Variab= le' + @param[in] VendorGuid GUID of the variable to compare to 'Variab= le' + @param[out] PtrTrack Variable Track Pointer structure that cont= ains + 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 =3D GetVendorGuidPtr (VariableHeader, StoreInfo->AuthFlag= ); + + if (VariableName[0] =3D=3D 0) { + PtrTrack->CurrPtr =3D 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] =3D=3D ((INT32 *)TempVendorGuid)[0]) && + (((INT32 *)VendorGuid)[1] =3D=3D ((INT32 *)TempVendorGuid)[1]) && + (((INT32 *)VendorGuid)[2] =3D=3D ((INT32 *)TempVendorGuid)[2]) && + (((INT32 *)VendorGuid)[3] =3D=3D ((INT32 *)TempVendorGuid)[3]) + ) + { + ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != =3D 0); + Point =3D (VOID *)GetVariableNamePtr (Variable, StoreInfo->AuthFlag); + if (CompareVariableName (StoreInfo, VariableName, Point, NameSizeOfV= ariable (VariableHeader, StoreInfo->AuthFlag))) { + PtrTrack->CurrPtr =3D 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 =3D=3D NULL) { + return FALSE; + } + + // + // First assume variable header pointed by Variable is consecutive. + // + *VariableHeader =3D Variable; + + if (StoreInfo->FtwLastWriteData !=3D NULL) { + TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; + SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; + if (((UINTN)Variable > (UINTN)SpareAddress) && + (((UINTN)Variable - (UINTN)SpareAddress + (UINTN)TargetAddress) >= =3D (UINTN)GetEndPointer (StoreInfo->VariableStoreHeader))) + { + // + // Reach the end of variable store. + // + return FALSE; + } + + if (((UINTN)Variable < (UINTN)TargetAddress) && (((UINTN)Variable + Ge= tVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN)TargetAddress)) { + // + // Variable header pointed by Variable is inconsecutive, + // create a guid hob to combine the two partial variable header cont= ent together. + // + GuidHob =3D GetFirstGuidHob (&gEfiCallerIdGuid); + if (GuidHob !=3D NULL) { + *VariableHeader =3D (VARIABLE_HEADER *)GET_GUID_HOB_DATA (GuidHob); + } else { + *VariableHeader =3D (VARIABLE_HEADER *)BuildGuidHob (&gEfiCaller= IdGuid, GetVariableHeaderSize (StoreInfo->AuthFlag)); + PartialHeaderSize =3D (UINTN)TargetAddress - (UINTN)Variable; + // + // Partial content is in NV storage. + // + CopyMem ((UINT8 *)*VariableHeader, (UINT8 *)Variable, PartialHeade= rSize); + // + // Another partial content is in spare block. + // + CopyMem ((UINT8 *)*VariableHeader + PartialHeaderSize, (UINT8 *)(U= INTN)SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) - PartialHea= derSize); + } + } + } else { + if (Variable >=3D 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 !=3D NULL) { + TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; + SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; + if (((UINTN)NameOrData < (UINTN)TargetAddress) && (((UINTN)NameOrData = + Size) > (UINTN)TargetAddress)) { + // + // Variable name/data is inconsecutive. + // + PartialSize =3D (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 (optio= nal). + @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 successful= ly. + +**/ +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 =3D=3D NULL) || (VariablePtr =3D=3D NULL) || (Variable= Header =3D=3D NULL)) { + ASSERT (VariableInfo !=3D NULL); + ASSERT (VariablePtr !=3D NULL); + ASSERT (VariableHeader !=3D NULL); + return EFI_INVALID_PARAMETER; + } + + VariableBuffer =3D VariableInfo->Buffer; + + // + // Make a copy of the whole variable if VariableInfo->Buffer is given. B= ut + // don't do this if StoreInfo is not given, because VariableInfo->Buffer + // has already hold a copy of variable in such situation. + // + NameSize =3D NameSizeOfVariable (VariableHeader, VariableInfo->Flags.Aut= h); + DataSize =3D DataSizeOfVariable (VariableHeader, VariableInfo->Flags.Aut= h); + if ((VariableBuffer !=3D NULL) && (VariableBuffer !=3D VariablePtr)) { + if (StoreInfo !=3D NULL) { + CopyMem ( + VariableBuffer, + VariableHeader, + GetVariableHeaderSize (VariableInfo->Flags.Auth) + ); + GetVariableNameOrData ( + StoreInfo, + (UINT8 *)GetVariableNamePtr (VariablePtr, VariableInfo->Flags.Auth= ), + NameSize, + (UINT8 *)GetVariableNamePtr (VariableBuffer, VariableInfo->Flags.A= uth) + ); + GetVariableNameOrData ( + StoreInfo, + (UINT8 *)GetVariableDataPtr (VariablePtr, VariableHeader, Variable= Info->Flags.Auth), + DataSize, + (UINT8 *)GetVariableDataPtr (VariableBuffer, VariableHeader, Varia= bleInfo->Flags.Auth) + ); + } else { + // + // Suppose the variable is in consecutive space. + // + VariableSize =3D 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 i= nside + // 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 correspondi= ng + // data. + // + // + + // + // AuthVariable header + // + if (VariableInfo->Flags.Auth) { + AuthVariableHeader =3D (AUTHENTICATED_VARIABLE_HEADER *)VariableHeader; + + VariableInfo->Header.State =3D AuthVariableHeader->State; + VariableInfo->Header.Attributes =3D AuthVariableHeader->Attributes; + VariableInfo->Header.PubKeyIndex =3D AuthVariableHeader->PubKeyInde= x; + VariableInfo->Header.MonotonicCount =3D ReadUnaligned64 ( + &(AuthVariableHeader->Monotoni= cCount) + ); + if (VariableInfo->Header.TimeStamp !=3D NULL) { + CopyMem ( + VariableInfo->Header.TimeStamp, + &AuthVariableHeader->TimeStamp, + sizeof (EFI_TIME) + ); + } else if (VariableBuffer !=3D NULL) { + AuthVariableHeader =3D (AUTHENTICATED_VARIABLE_HEADER *)= VariableBuffer; + VariableInfo->Header.TimeStamp =3D &AuthVariableHeader->TimeStamp; + } + } else { + VariableInfo->Header.State =3D VariableHeader->State; + VariableInfo->Header.Attributes =3D VariableHeader->Attributes; + VariableInfo->Header.PubKeyIndex =3D 0; + VariableInfo->Header.MonotonicCount =3D 0; + VariableInfo->Header.TimeStamp =3D NULL; + } + + // + // VendorGuid + // + if (VariableInfo->Header.VendorGuid !=3D NULL) { + CopyGuid ( + VariableInfo->Header.VendorGuid, + GetVendorGuidPtr (VariableHeader, VariableInfo->Flags.Auth) + ); + } else if (VariableBuffer !=3D NULL) { + VariableInfo->Header.VendorGuid + =3D GetVendorGuidPtr (VariableBuffer, VariableInfo->Flags.Auth); + } + + // + // VariableName + // + if ( (VariableInfo->Header.VariableName !=3D NULL) + && (VariableInfo->Header.NameSize >=3D NameSize)) + { + GetVariableNameOrData ( + StoreInfo, + (UINT8 *)GetVariableNamePtr (VariablePtr, VariableInfo->Flags.Auth), + NameSize, + (UINT8 *)VariableInfo->Header.VariableName + ); + } else if (VariableBuffer !=3D NULL) { + VariableInfo->Header.VariableName + =3D GetVariableNamePtr (VariableBuffer, VariableInfo->Flags.Auth); + } else if (VariableInfo->Header.VariableName !=3D NULL) { + return EFI_BUFFER_TOO_SMALL; + } + + // + // Data + // + if ( (VariableInfo->Header.Data !=3D NULL) + && (VariableInfo->Header.DataSize >=3D DataSize)) + { + GetVariableNameOrData ( + StoreInfo, + GetVariableDataPtr (VariablePtr, VariableHeader, StoreInfo->AuthFlag= ), + DataSize, + VariableInfo->Header.Data + ); + } else if (VariableBuffer !=3D NULL) { + VariableInfo->Header.Data + =3D GetVariableDataPtr (VariableBuffer, VariableBuffer, VariableInfo= ->Flags.Auth); + } else if (VariableInfo->Header.Data !=3D NULL) { + return EFI_BUFFER_TOO_SMALL; + } + + // + // Update size information about name & data. + // + VariableInfo->Header.NameSize =3D NameSize; + VariableInfo->Header.DataSize =3D 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 var= iable + data in variable store. If pointers in the structure of VariableInfo->He= ader + are not NULL, it's supposed that they are buffers passed in to hold a co= py of + data of corresponding data fields in variable data structure. Otherwise,= this + function simply returns pointers pointing to address of those data field= s. + + The variable is specified by either VariableInfo->Index or VariableInfo-= >Buffer. + If VariableInfo->Index is given, this function finds the corresponding v= ariable + first from variable storage according to the Index. + + If both VariableInfo->Index and VariableInfo->Buffer are given, it's sup= posed + 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 successful= ly. + +**/ +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 =3D=3D NULL) || + ((VariableInfo->Buffer =3D=3D NULL) && (VariableInfo->StoreIndex =3D= =3D VAR_INDEX_INVALID))) + { + ASSERT (VariableInfo !=3D NULL); + ASSERT (VariableInfo->StoreIndex !=3D VAR_INDEX_INVALID || VariableInf= o->Buffer !=3D NULL); + return EFI_INVALID_PARAMETER; + } + + StoreInfo.VariableStoreHeader =3D NULL; + for (StoreType =3D VariableStoreTypeHob; StoreType < VariableStoreTypeMa= x; ++StoreType) { + GetVariableStore (StoreType, &StoreInfo); + if (StoreInfo.VariableStoreHeader !=3D NULL) { + break; + } + } + + ASSERT (StoreInfo.VariableStoreHeader !=3D NULL); + + // + // No StoreIndex? Don't retrieve variable information from store but jus= t from + // VariableInfo->Buffer. + // + if (VariableInfo->StoreIndex =3D=3D VAR_INDEX_INVALID) { + VariablePtr =3D VariableInfo->Buffer; + VariableHeader =3D VariablePtr; + + return GetVariableInfoInternal (VariableInfo, NULL, VariablePtr, Varia= bleHeader); + } + + Offset =3D (UINTN)VariableInfo->StoreIndex; + if ( (StoreInfo.FtwLastWriteData !=3D NULL) + && (Offset >=3D ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress + - (UINTN)StoreInfo.VariableStoreHeader))) + { + Offset -=3D ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress + - (UINTN)StoreInfo.VariableStoreHeader); + VariablePtr =3D (VARIABLE_HEADER *) + ((UINTN)StoreInfo.FtwLastWriteData->SpareAddress + Offse= t); + } else { + VariablePtr =3D (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, V= ariableHeader); +} + +/** + + Retrieve details of the variable next to given variable within VariableS= tore. + + If VarInfo->Buffer is NULL, the first one in VariableStore is returned. + + VariableStart and/or VariableEnd can be given optionally for the situati= on + 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 deter= mine + 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 successful= ly. + +**/ +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 =3D=3D NULL) { + ASSERT (VariableInfo !=3D NULL); + return EFI_INVALID_PARAMETER; + } + + StoreInfo.VariableStoreHeader =3D NULL; + for (StoreType =3D VariableStoreTypeHob; StoreType < VariableStoreTypeMa= x; ++StoreType) { + GetVariableStore (StoreType, &StoreInfo); + if (StoreInfo.VariableStoreHeader !=3D NULL) { + break; + } + } + + ASSERT (StoreInfo.VariableStoreHeader !=3D 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 in= valid, + // return the first variable available in store. + // + VariableInfo->Flags.Auth =3D StoreInfo.AuthFlag; + if (VariableInfo->StoreIndex =3D=3D VAR_INDEX_INVALID) { + VariablePtr =3D GetStartPointer (StoreInfo.VariableStoreHeader); + } else { + Offset =3D (UINTN)VariableInfo->StoreIndex; + if ( (StoreInfo.FtwLastWriteData !=3D NULL) + && (Offset >=3D ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress + - (UINTN)StoreInfo.VariableStoreHeader))) + { + Offset -=3D ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress + - (UINTN)StoreInfo.VariableStoreHeader); + VariablePtr =3D (VARIABLE_HEADER *) + ((UINTN)StoreInfo.FtwLastWriteData->SpareAddress + Off= set); + } else { + VariablePtr =3D (VARIABLE_HEADER *) + ((UINTN)StoreInfo.VariableStoreHeader + Offset); + } + + // + // Note that variable might be in unconsecutive space. Always get a co= py + // of its header in consecutive buffer. + // + if (!GetVariableHeader (&StoreInfo, VariablePtr, &VariableHeader)) { + return EFI_NOT_FOUND; + } + + VariablePtr =3D GetNextVariablePtr (&StoreInfo, VariablePtr, VariableH= eader); + } + + // + // 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 variabl= e. + // + if ( (StoreInfo.FtwLastWriteData =3D=3D NULL) + || ((UINTN)VariablePtr < (UINTN)StoreInfo.FtwLastWriteData->TargetAdd= ress)) + { + VariableInfo->StoreIndex + =3D (UINT64)((UINTN)VariablePtr - (UINTN)StoreInfo.VariableStoreHead= er); + } else { + VariableInfo->StoreIndex + =3D (UINT64)((UINTN)StoreInfo.FtwLastWriteData->TargetAddress + - (UINTN)StoreInfo.VariableStoreHeader); + VariableInfo->StoreIndex + +=3D (UINT64)((UINTN)VariablePtr - (UINTN)StoreInfo.FtwLastWriteData= ->SpareAddress); + } + + if ((StoreType =3D=3D VariableStoreTypeHob) && (VariableInfo->Buffer =3D= =3D NULL)) { + VariableInfo->Buffer =3D VariablePtr; + } + + return GetVariableInfoInternal (VariableInfo, &StoreInfo, VariablePtr, V= ariableHeader); +} diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.c = b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.c new file mode 100644 index 000000000000..75edc3fc5051 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/VariableStore.c @@ -0,0 +1,307 @@ +/** @file + Implement ReadOnly Variable Services required by PEIM and install + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile st= orage space. + +Copyright (c) 2022, Intel Corporation. All rights reserved.
+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, &gEfiAuthenticatedVariable= Guid) || + CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) && + (VarStoreHeader->Format =3D=3D VARIABLE_STORE_FORMATTED) && + (VarStoreHeader->State =3D=3D VARIABLE_STORE_HEALTHY) + ) + { + return EfiValid; + } + + if ((((UINT32 *)(&VarStoreHeader->Signature))[0] =3D=3D 0xffffffff) && + (((UINT32 *)(&VarStoreHeader->Signature))[1] =3D=3D 0xffffffff) && + (((UINT32 *)(&VarStoreHeader->Signature))[2] =3D=3D 0xffffffff) && + (((UINT32 *)(&VarStoreHeader->Signature))[3] =3D=3D 0xffffffff) && + (VarStoreHeader->Size =3D=3D 0xffffffff) && + (VarStoreHeader->Format =3D=3D 0xff) && + (VarStoreHeader->State =3D=3D 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 dr= iver. + // It contains information regards to HOB or NV Variable Store availabil= ity + // + GuidHob =3D GetFirstGuidHob (&gEfiPeiVariableStoreDiscoveredPpiGuid); + if (GuidHob =3D=3D NULL) { + return EFI_NOT_READY; + } + + // + // Check if HOB Variable Store is available + // + VariableStoreInfoHob =3D GET_GUID_HOB_DATA (GuidHob); + if (*(BOOLEAN *)VariableStoreInfoHob =3D=3D 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 =3D GetFirstGuidHob (&gEfiAuthenticatedVariableGuid); + if (GuidHob !=3D NULL) { + if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB (Gui= dHob)) !=3D NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n")); + ASSERT (FALSE); + } else if (GetFirstGuidHob (&gEfiVariableGuid) !=3D NULL) { + DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable HO= Bs\n")); + ASSERT (FALSE); + } + } else { + GuidHob =3D GetFirstGuidHob (&gEfiVariableGuid); + if (GuidHob !=3D NULL) { + if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) !=3D= NULL)) { + DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n")); + ASSERT (FALSE); + } + } + } + + DEBUG_CODE_END (); + + GuidHob =3D GetFirstGuidHob (&gEfiAuthenticatedVariableGuid); + if (GuidHob !=3D NULL) { + StoreInfo->VariableStoreHeader =3D (VARIABLE_STORE_HEADER *)GET_GUID_H= OB_DATA (GuidHob); + StoreInfo->AuthFlag =3D TRUE; + } else { + GuidHob =3D GetFirstGuidHob (&gEfiVariableGuid); + if (GuidHob !=3D NULL) { + StoreInfo->VariableStoreHeader =3D (VARIABLE_STORE_HEADER *)GET_GUID= _HOB_DATA (GuidHob); + StoreInfo->AuthFlag =3D FALSE; + } + } +} + +/** + Get NV variable store. + + @param[out] StoreInfo Return the store info. + @param[out] VariableFvHeader Return header of FV containing the sto= re. + +**/ +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 =3D GetVariableFlashNvStorageInfo (&NvStorageBase, &NvStorageSize= 64); + ASSERT_EFI_ERROR (Status); + + Status =3D SafeUint64ToUint32 (NvStorageSize64, &NvStorageSize); + // This driver currently assumes the size will be UINT32 so assert the v= alue is safe for now. + ASSERT_EFI_ERROR (Status); + + FvHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)NvStorageBase; + + // + // Check the FTW last write data hob. + // + BackUpOffset =3D 0; + FtwLastWriteData =3D NULL; + HobData =3D NULL; + GuidHob =3D GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid); + + if (GuidHob !=3D NULL) { + HobData =3D (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *)GET_GUID_HOB_DATA = (GuidHob); + if (HobData->TargetAddress =3D=3D 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 =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)HobData->SpareAddr= ess; + HobData =3D NULL; + } else if ((HobData->TargetAddress > NvStorageBase) && + (HobData->TargetAddress < (NvStorageBase + NvStorageSize))) + { + // + // Flash NV storage from the offset is backed up in spare block. + // + BackUpOffset =3D (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 st= ill + // leave FvHeader point to NV storage base. + // + } + } + + if (StoreInfo !=3D NULL) { + StoreInfo->FtwLastWriteData =3D HobData; + } + + if (VariableFvHeader !=3D NULL) { + *VariableFvHeader =3D FvHeader; + } + + // + // Check if the Firmware Volume is not corrupted + // + if ((FvHeader->Signature =3D=3D EFI_FVH_SIGNATURE) && + CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid)) + { + StoreHeader =3D (VARIABLE_STORE_HEADER *)((UINTN)FvHeader + FvHeader->= HeaderLength); + } else { + StoreHeader =3D NULL; + DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is corrupted\= n")); + } + + if (StoreInfo !=3D NULL) { + StoreInfo->VariableStoreHeader =3D StoreHeader; + if (StoreHeader !=3D NULL) { + StoreInfo->AuthFlag =3D 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 =3D NULL; + StoreInfo->IndexTable =3D NULL; + StoreInfo->FtwLastWriteData =3D NULL; + StoreInfo->AuthFlag =3D 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 !=3D NULL) { + GuidHob =3D GetFirstGuidHob (&gEfiVariableIndexTableGuid); + if (GuidHob !=3D NULL) { + StoreInfo->IndexTable =3D 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 sto= re the limited number of + // VAR_ADDED type variables to reduce access time. + // + StoreInfo->IndexTable =3D (VARIABLE_INDEX_TABLE *= )BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE)); + StoreInfo->IndexTable->Length =3D 0; + StoreInfo->IndexTable->StartPtr =3D GetStartPointer (StoreI= nfo->VariableStoreHeader); + StoreInfo->IndexTable->EndPtr =3D GetEndPointer (StoreInf= o->VariableStoreHeader); + StoreInfo->IndexTable->GoneThrough =3D 0; + } + } + } + + break; + + default: + ASSERT (FALSE); + break; + } + + return StoreInfo->VariableStoreHeader; +} diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariable.uni = b/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariable.uni new file mode 100644 index 000000000000..106c1dfdc5c0 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariable.uni @@ -0,0 +1,16 @@ +// /** @file +// Implements ReadOnly Variable Services required by PEIM and installs PEI= ReadOnly Varaiable2 PPI. +// +// This module implements ReadOnly Variable Services required by PEIM and = installs PEI ReadOnly Varaiable2 PPI. +// +// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Implements ReadOn= ly Variable Services required by PEIM and installs PEI ReadOnly Varaiable2 = PPI" + +#string STR_MODULE_DESCRIPTION #language en-US "This module imple= ments ReadOnly Variable Services required by PEIM and installs PEI ReadOnly= Varaiable2 PPI." + diff --git a/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariableExtra= .uni b/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariableExtra.uni new file mode 100644 index 000000000000..22dd992be908 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/Protected/Pei/PeiVariableExtra.uni @@ -0,0 +1,14 @@ +// /** @file +// PeiVariable Localized Strings and Content +// +// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Variable Access PEI Module" + + --=20 2.35.1.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#95988): https://edk2.groups.io/g/devel/message/95988 Mute This Topic: https://groups.io/mt/94840824/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-