From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: michael.a.kubacki@intel.com) Received: from mga02.intel.com (mga02.intel.com []) by groups.io with SMTP; Wed, 25 Sep 2019 21:51:16 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 25 Sep 2019 21:51:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,550,1559545200"; d="scan'208";a="191570746" Received: from makuback-desk1.amr.corp.intel.com ([10.7.159.162]) by orsmga003.jf.intel.com with ESMTP; 25 Sep 2019 21:51:16 -0700 From: "Kubacki, Michael A" To: devel@edk2.groups.io Cc: Dandan Bi , Ard Biesheuvel , Eric Dong , Laszlo Ersek , Liming Gao , Michael D Kinney , Ray Ni , Jian J Wang , Hao A Wu , Jiewen Yao Subject: [PATCH V1 1/5] MdeModulePkg/Variable: Consolidate common parsing functions Date: Wed, 25 Sep 2019 21:50:42 -0700 Message-Id: <20190926045046.34592-2-michael.a.kubacki@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: <20190926045046.34592-1-michael.a.kubacki@intel.com> References: <20190926045046.34592-1-michael.a.kubacki@intel.com> This change moves the following functions into a dedicated file so they may be used in other variable files as needed. Furthermore, it reduces the overall size of the common Variable.c file. * DataSizeOfVariable () * FindVariableEx () * GetEndPointer () * GetNextVariableEx () * GetNextVariablePtr () * GetStartPointer () * GetVariableDataOffset () * GetVariableDataPtr () * GetVariableHeaderSize () * GetVariableNamePtr () * GetVariableStoreStatus () * GetVendorGuidPtr () * IsAuthenticatedVariable () * IsValidVariableHeader () * NameSizeOfVariable () * SetDataSizeOfVariable () * SetNameSizeOfVariable () * UpdateVariableInfo () * VariableCompareTimeStampInternal () Cc: Dandan Bi Cc: Ard Biesheuvel Cc: Eric Dong Cc: Laszlo Ersek Cc: Liming Gao Cc: Michael D Kinney Cc: Ray Ni Cc: Jian J Wang Cc: Hao A Wu Cc: Jiewen Yao Signed-off-by: Michael Kubacki --- MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf | 4 + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf | 4 + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf | 8 +- MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf | 9 + MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h | 119 --- MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h | 25 + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h | 342 ++++++++ MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c | 784 +------------------ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c | 11 +- MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c | 28 + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c | 816 ++++++++++++++++++++ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c | 2 + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c | 3 +- 13 files changed, 1273 insertions(+), 882 deletions(-) diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf index 641376c9c5..08a5490787 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf @@ -36,6 +36,10 @@ Variable.c VariableDxe.c Variable.h + VariableNonVolatile.c + VariableNonVolatile.h + VariableParsing.c + VariableParsing.h PrivilegePolymorphic.h Measurement.c TcgMorLockDxe.c diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf index 0a160d269d..6dc2721b81 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf @@ -45,6 +45,10 @@ Variable.c VariableTraditionalMm.c VariableSmm.c + VariableNonVolatile.c + VariableNonVolatile.h + VariableParsing.c + VariableParsing.h VarCheck.c Variable.h PrivilegePolymorphic.h diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf index 14894e6f13..1873b4fe43 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf @@ -13,7 +13,7 @@ # may not be modified without authorization. If platform fails to protect these resources, # the authentication service provided in this driver will be broken, and the behavior is undefined. # -# Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -39,6 +39,9 @@ VariableSmmRuntimeDxe.c PrivilegePolymorphic.h Measurement.c + Variable.h + VariableParsing.c + VariableParsing.h [Packages] MdePkg/MdePkg.dec @@ -65,6 +68,9 @@ gEdkiiVariableLockProtocolGuid ## PRODUCES gEdkiiVarCheckProtocolGuid ## PRODUCES +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## CONSUMES + [Guids] gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event gEfiEventExitBootServicesGuid ## CONSUMES ## Event diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf index 21bc81163b..ca9d23ce9f 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf @@ -45,6 +45,10 @@ Variable.c VariableSmm.c VariableStandaloneMm.c + VariableNonVolatile.c + VariableNonVolatile.h + VariableParsing.c + VariableParsing.h VarCheck.c Variable.h PrivilegePolymorphic.h @@ -99,6 +103,11 @@ ## SOMETIMES_PRODUCES ## Variable:L"Lang" gEfiGlobalVariableGuid + ## SOMETIMES_CONSUMES ## Variable:L"db" + ## SOMETIMES_CONSUMES ## Variable:L"dbx" + ## SOMETIMES_CONSUMES ## Variable:L"dbt" + gEfiImageSecurityDatabaseGuid + gEfiMemoryOverwriteControlDataGuid ## SOMETIMES_CONSUMES ## Variable:L"MemoryOverwriteRequestControl" gEfiMemoryOverwriteRequestControlLockGuid ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControlLock" diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h index 9eac43759f..fb574b2e32 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h @@ -179,89 +179,6 @@ FindVariable ( IN BOOLEAN IgnoreRtCheck ); -/** - - 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 - ); - -/** - This code gets the size of variable header. - - @return Size of variable header in bytes in type UINTN. - -**/ -UINTN -GetVariableHeaderSize ( - VOID - ); - -/** - - This code gets the pointer to the variable name. - - @param Variable Pointer to the Variable Header. - - @return Pointer to Variable Name which is Unicode encoding. - -**/ -CHAR16 * -GetVariableNamePtr ( - IN VARIABLE_HEADER *Variable - ); - -/** - This code gets the pointer to the variable guid. - - @param Variable Pointer to the Variable Header. - - @return A EFI_GUID* pointer to Vendor Guid. - -**/ -EFI_GUID * -GetVendorGuidPtr ( - IN VARIABLE_HEADER *Variable - ); - -/** - - This code gets the pointer to the variable data. - - @param Variable Pointer to the Variable Header. - - @return Pointer to Variable Data. - -**/ -UINT8 * -GetVariableDataPtr ( - IN VARIABLE_HEADER *Variable - ); - -/** - - This code gets the size of variable data. - - @param Variable Pointer to the Variable Header. - - @return Size of variable in bytes. - -**/ -UINTN -DataSizeOfVariable ( - IN VARIABLE_HEADER *Variable - ); - /** This function is to check if the remaining variable space is enough to set all Variables from argument list successfully. The purpose of the check @@ -450,17 +367,6 @@ ReclaimForOS( VOID ); -/** - Get non-volatile maximum variable size. - - @return Non-volatile maximum variable size. - -**/ -UINTN -GetNonVolatileMaxVariableSize ( - VOID - ); - /** Get maximum variable size, covering both non-volatile and volatile variables. @@ -546,31 +452,6 @@ VariableServiceGetVariable ( OUT VOID *Data OPTIONAL ); -/** - This code Finds the Next available variable. - - Caution: This function may receive untrusted input. - This function may be invoked in SMM mode. This function will do basic validation, before parse the data. - - @param[in] VariableName Pointer to variable name. - @param[in] VendorGuid Variable Vendor Guid. - @param[out] VariablePtr Pointer to variable header address. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_NOT_FOUND The next variable was not found. - @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL. - @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and - GUID of an existing variable. - -**/ -EFI_STATUS -EFIAPI -VariableServiceGetNextVariableInternal ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - OUT VARIABLE_HEADER **VariablePtr - ); - /** This code Finds the Next available variable. diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h new file mode 100644 index 0000000000..82572262ef --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h @@ -0,0 +1,25 @@ +/** @file + Common variable non-volatile store routines. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VARIABLE_NON_VOLATILE_H_ +#define _VARIABLE_NON_VOLATILE_H_ + +#include "Variable.h" + +/** + Get non-volatile maximum variable size. + + @return Non-volatile maximum variable size. + +**/ +UINTN +GetNonVolatileMaxVariableSize ( + VOID + ); + +#endif diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h new file mode 100644 index 0000000000..bd617fca10 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h @@ -0,0 +1,342 @@ +/** @file + Common variable helper routines are shared by the DXE_RUNTIME variable + module and the DXE_SMM variable module. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VARIABLE_PARSING_H_ +#define _VARIABLE_PARSING_H_ + +#include +#include "Variable.h" + +/** + + This code checks if variable header is valid or not. + + @param Variable Pointer to the Variable Header. + @param VariableStoreEnd Pointer to the Variable Store End. + + @retval TRUE Variable header is valid. + @retval FALSE Variable header is not valid. + +**/ +BOOLEAN +IsValidVariableHeader ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_HEADER *VariableStoreEnd + ); + +/** + + This code gets the current status of Variable Store. + + @param VarStoreHeader Pointer to the Variable Store Header. + + @retval EfiRaw Variable store status is raw. + @retval EfiValid Variable store status is valid. + @retval EfiInvalid Variable store status is invalid. + +**/ +VARIABLE_STORE_STATUS +GetVariableStoreStatus ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ); + +/** + This code gets the size of variable header. + + @return Size of variable header in bytes in type UINTN. + +**/ +UINTN +GetVariableHeaderSize ( + VOID + ); + +/** + + This code gets the size of name of variable. + + @param Variable Pointer to the Variable Header. + + @return UINTN Size of variable in bytes. + +**/ +UINTN +NameSizeOfVariable ( + IN VARIABLE_HEADER *Variable + ); + +/** + This code sets the size of name of variable. + + @param[in] Variable Pointer to the Variable Header. + @param[in] NameSize Name size to set. + +**/ +VOID +SetNameSizeOfVariable ( + IN VARIABLE_HEADER *Variable, + IN UINTN NameSize + ); + +/** + + This code gets the size of variable data. + + @param Variable Pointer to the Variable Header. + + @return Size of variable in bytes. + +**/ +UINTN +DataSizeOfVariable ( + IN VARIABLE_HEADER *Variable + ); + +/** + This code sets the size of variable data. + + @param[in] Variable Pointer to the Variable Header. + @param[in] DataSize Data size to set. + +**/ +VOID +SetDataSizeOfVariable ( + IN VARIABLE_HEADER *Variable, + IN UINTN DataSize + ); + +/** + + This code gets the pointer to the variable name. + + @param Variable Pointer to the Variable Header. + + @return Pointer to Variable Name which is Unicode encoding. + +**/ +CHAR16 * +GetVariableNamePtr ( + IN VARIABLE_HEADER *Variable + ); + +/** + This code gets the pointer to the variable guid. + + @param Variable Pointer to the Variable Header. + + @return A EFI_GUID* pointer to Vendor Guid. + +**/ +EFI_GUID * +GetVendorGuidPtr ( + IN VARIABLE_HEADER *Variable + ); + +/** + + This code gets the pointer to the variable data. + + @param Variable Pointer to the Variable Header. + + @return Pointer to Variable Data. + +**/ +UINT8 * +GetVariableDataPtr ( + IN VARIABLE_HEADER *Variable + ); + +/** + This code gets the variable data offset related to variable header. + + @param Variable Pointer to the Variable Header. + + @return Variable Data offset. + +**/ +UINTN +GetVariableDataOffset ( + IN VARIABLE_HEADER *Variable + ); + +/** + + This code gets the pointer to the next variable header. + + @param Variable Pointer to the Variable Header. + + @return Pointer to next variable header. + +**/ +VARIABLE_HEADER * +GetNextVariablePtr ( + IN VARIABLE_HEADER *Variable + ); + +/** + + 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 + ); + +/** + + 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 + ); + +/** + Returns if this is a variable that always requires authenticated writes. + There may be other scenarios that result in a variable not identified by the + function to also require authentication. + + @param[in] VariableName Name of variable. + @param[in] VendorGuid Guid of variable. + + @retval TRUE The variable always requires authenticated writes + @retval FALSE The variable may or may not require authenticated writes +**/ +BOOLEAN +IsAuthenticatedVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ); + +/** + Compare two EFI_TIME data. + + + @param FirstTime A pointer to the first EFI_TIME data. + @param SecondTime A pointer to the second EFI_TIME data. + + @retval TRUE The FirstTime is not later than the SecondTime. + @retval FALSE The FirstTime is later than the SecondTime. + +**/ +BOOLEAN +VariableCompareTimeStampInternal ( + IN EFI_TIME *FirstTime, + IN EFI_TIME *SecondTime + ); + +/** + Find the variable in the specified variable store. + + @param[in] VariableName Name of the variable to be found + @param[in] VendorGuid Vendor GUID to be found. + @param[in] IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute + check at runtime when searching variable. + @param[in, out] PtrTrack Variable Track Pointer structure that contains Variable Information. + + @retval EFI_SUCCESS Variable found successfully + @retval EFI_NOT_FOUND Variable not found +**/ +EFI_STATUS +FindVariableEx ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN BOOLEAN IgnoreRtCheck, + IN OUT VARIABLE_POINTER_TRACK *PtrTrack + ); + +/** + This code finds the next available variable. + + Caution: This function may receive untrusted input. + This function may be invoked in SMM mode. This function will do basic validation, before parse the data. + + @param[in] VariableName Pointer to variable name. + @param[in] VendorGuid Variable Vendor Guid. + @param[in] VariableStoreList A list of variable stores that should be used to get the next variable. + The maximum number of entries is the max value of VARIABLE_STORE_TYPE. + @param[out] VariablePtr Pointer to variable header address. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The next variable was not found. + @retval EFI_INVALID_PARAMETER If VariableName is nt an empty string, while VendorGuid is NULL. + @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and + GUID of an existing variable. + +**/ +EFI_STATUS +EFIAPI +GetNextVariableEx ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN VARIABLE_STORE_HEADER **VariableStoreList, + OUT VARIABLE_HEADER **VariablePtr + ); + +/** + Routine used to track statistical information about variable usage. + The data is stored in the EFI system table so it can be accessed later. + VariableInfo.efi can dump out the table. Only Boot Services variable + accesses are tracked by this code. The PcdVariableCollectStatistics + build flag controls if this feature is enabled. + + A read that hits in the cache will have Read and Cache true for + the transaction. Data is allocated by this routine, but never + freed. + + @param[in] VariableName Name of the Variable to track. + @param[in] VendorGuid Guid of the Variable to track. + @param[in] Volatile TRUE if volatile FALSE if non-volatile. + @param[in] Read TRUE if GetVariable() was called. + @param[in] Write TRUE if SetVariable() was called. + @param[in] Delete TRUE if deleted via SetVariable(). + @param[in] Cache TRUE for a cache hit. + @param[in,out] VariableInfo Pointer to a pointer of VARIABLE_INFO_ENTRY structures. + +**/ +VOID +UpdateVariableInfo ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN BOOLEAN Volatile, + IN BOOLEAN Read, + IN BOOLEAN Write, + IN BOOLEAN Delete, + IN BOOLEAN Cache, + IN OUT VARIABLE_INFO_ENTRY **VariableInfo + ); + +/** + Initializes context needed for variable helpers. + + @param[in] AuthFormat If true then indicates authenticated variables are supported + + @retval EFI_SUCCESS Initialized successfully + @retval Others An error occurred during initialization +**/ +EFI_STATUS +EFIAPI +InitVariableHelpers ( + IN BOOLEAN AuthFormat + ); + +#endif diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c index f32c9c2808..d14fecc830 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c @@ -23,6 +23,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Variable.h" +#include "VariableNonVolatile.h" +#include "VariableParsing.h" VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal; @@ -92,131 +94,6 @@ AUTH_VAR_LIB_CONTEXT_IN mAuthContextIn = { AUTH_VAR_LIB_CONTEXT_OUT mAuthContextOut; -/** - Routine used to track statistical information about variable usage. - The data is stored in the EFI system table so it can be accessed later. - VariableInfo.efi can dump out the table. Only Boot Services variable - accesses are tracked by this code. The PcdVariableCollectStatistics - build flag controls if this feature is enabled. - - A read that hits in the cache will have Read and Cache true for - the transaction. Data is allocated by this routine, but never - freed. - - @param[in] VariableName Name of the Variable to track. - @param[in] VendorGuid Guid of the Variable to track. - @param[in] Volatile TRUE if volatile FALSE if non-volatile. - @param[in] Read TRUE if GetVariable() was called. - @param[in] Write TRUE if SetVariable() was called. - @param[in] Delete TRUE if deleted via SetVariable(). - @param[in] Cache TRUE for a cache hit. - -**/ -VOID -UpdateVariableInfo ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN BOOLEAN Volatile, - IN BOOLEAN Read, - IN BOOLEAN Write, - IN BOOLEAN Delete, - IN BOOLEAN Cache - ) -{ - VARIABLE_INFO_ENTRY *Entry; - - if (FeaturePcdGet (PcdVariableCollectStatistics)) { - - if (AtRuntime ()) { - // Don't collect statistics at runtime. - return; - } - - if (gVariableInfo == NULL) { - // - // On the first call allocate a entry and place a pointer to it in - // the EFI System Table. - // - gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY)); - ASSERT (gVariableInfo != NULL); - - CopyGuid (&gVariableInfo->VendorGuid, VendorGuid); - gVariableInfo->Name = AllocateZeroPool (StrSize (VariableName)); - ASSERT (gVariableInfo->Name != NULL); - StrCpyS (gVariableInfo->Name, StrSize(VariableName)/sizeof(CHAR16), VariableName); - gVariableInfo->Volatile = Volatile; - } - - - for (Entry = gVariableInfo; Entry != NULL; Entry = Entry->Next) { - if (CompareGuid (VendorGuid, &Entry->VendorGuid)) { - if (StrCmp (VariableName, Entry->Name) == 0) { - if (Read) { - Entry->ReadCount++; - } - if (Write) { - Entry->WriteCount++; - } - if (Delete) { - Entry->DeleteCount++; - } - if (Cache) { - Entry->CacheCount++; - } - - return; - } - } - - if (Entry->Next == NULL) { - // - // If the entry is not in the table add it. - // Next iteration of the loop will fill in the data. - // - Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY)); - ASSERT (Entry->Next != NULL); - - CopyGuid (&Entry->Next->VendorGuid, VendorGuid); - Entry->Next->Name = AllocateZeroPool (StrSize (VariableName)); - ASSERT (Entry->Next->Name != NULL); - StrCpyS (Entry->Next->Name, StrSize(VariableName)/sizeof(CHAR16), VariableName); - Entry->Next->Volatile = Volatile; - } - - } - } -} - - -/** - - This code checks if variable header is valid or not. - - @param Variable Pointer to the Variable Header. - @param VariableStoreEnd Pointer to the Variable Store End. - - @retval TRUE Variable header is valid. - @retval FALSE Variable header is not valid. - -**/ -BOOLEAN -IsValidVariableHeader ( - IN VARIABLE_HEADER *Variable, - IN VARIABLE_HEADER *VariableStoreEnd - ) -{ - if ((Variable == NULL) || (Variable >= VariableStoreEnd) || (Variable->StartId != VARIABLE_DATA)) { - // - // Variable is NULL or has reached the end of variable store, - // or the StartId is not correct. - // - return FALSE; - } - - return TRUE; -} - - /** This function writes data to the FWH at the correct LBA even if the LBAs @@ -376,345 +253,6 @@ UpdateVariableStore ( return EFI_SUCCESS; } - -/** - - This code gets the current status of Variable Store. - - @param VarStoreHeader Pointer to the Variable Store Header. - - @retval EfiRaw Variable store status is raw. - @retval EfiValid Variable store status is valid. - @retval EfiInvalid Variable store status 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; - } else 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; - } -} - -/** - This code gets the size of variable header. - - @return Size of variable header in bytes in type UINTN. - -**/ -UINTN -GetVariableHeaderSize ( - VOID - ) -{ - UINTN Value; - - if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { - 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. - - @return UINTN Size of variable in bytes. - -**/ -UINTN -NameSizeOfVariable ( - IN VARIABLE_HEADER *Variable - ) -{ - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; - - AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; - if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { - 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 sets the size of name of variable. - - @param[in] Variable Pointer to the Variable Header. - @param[in] NameSize Name size to set. - -**/ -VOID -SetNameSizeOfVariable ( - IN VARIABLE_HEADER *Variable, - IN UINTN NameSize - ) -{ - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; - - AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; - if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { - AuthVariable->NameSize = (UINT32) NameSize; - } else { - Variable->NameSize = (UINT32) NameSize; - } -} - -/** - - This code gets the size of variable data. - - @param Variable Pointer to the Variable Header. - - @return Size of variable in bytes. - -**/ -UINTN -DataSizeOfVariable ( - IN VARIABLE_HEADER *Variable - ) -{ - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; - - AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; - if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { - 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 sets the size of variable data. - - @param[in] Variable Pointer to the Variable Header. - @param[in] DataSize Data size to set. - -**/ -VOID -SetDataSizeOfVariable ( - IN VARIABLE_HEADER *Variable, - IN UINTN DataSize - ) -{ - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; - - AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; - if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { - AuthVariable->DataSize = (UINT32) DataSize; - } else { - Variable->DataSize = (UINT32) DataSize; - } -} - -/** - - This code gets the pointer to the variable name. - - @param Variable Pointer to the Variable Header. - - @return Pointer to Variable Name which is Unicode encoding. - -**/ -CHAR16 * -GetVariableNamePtr ( - IN VARIABLE_HEADER *Variable - ) -{ - return (CHAR16 *) ((UINTN) Variable + GetVariableHeaderSize ()); -} - -/** - This code gets the pointer to the variable guid. - - @param Variable Pointer to the Variable Header. - - @return A EFI_GUID* pointer to Vendor Guid. - -**/ -EFI_GUID * -GetVendorGuidPtr ( - IN VARIABLE_HEADER *Variable - ) -{ - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; - - AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; - if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { - return &AuthVariable->VendorGuid; - } else { - return &Variable->VendorGuid; - } -} - -/** - - This code gets the pointer to the variable data. - - @param Variable Pointer to the Variable Header. - - @return Pointer to Variable Data. - -**/ -UINT8 * -GetVariableDataPtr ( - IN VARIABLE_HEADER *Variable - ) -{ - UINTN Value; - - // - // Be careful about pad size for alignment. - // - Value = (UINTN) GetVariableNamePtr (Variable); - Value += NameSizeOfVariable (Variable); - Value += GET_PAD_SIZE (NameSizeOfVariable (Variable)); - - return (UINT8 *) Value; -} - -/** - This code gets the variable data offset related to variable header. - - @param Variable Pointer to the Variable Header. - - @return Variable Data offset. - -**/ -UINTN -GetVariableDataOffset ( - IN VARIABLE_HEADER *Variable - ) -{ - UINTN Value; - - // - // Be careful about pad size for alignment - // - Value = GetVariableHeaderSize (); - Value += NameSizeOfVariable (Variable); - Value += GET_PAD_SIZE (NameSizeOfVariable (Variable)); - - return Value; -} - -/** - - This code gets the pointer to the next variable header. - - @param Variable Pointer to the Variable Header. - - @return Pointer to next variable header. - -**/ -VARIABLE_HEADER * -GetNextVariablePtr ( - IN VARIABLE_HEADER *Variable - ) -{ - UINTN Value; - - Value = (UINTN) GetVariableDataPtr (Variable); - Value += DataSizeOfVariable (Variable); - Value += GET_PAD_SIZE (DataSizeOfVariable (Variable)); - - // - // Be careful about pad size for alignment. - // - return (VARIABLE_HEADER *) HEADER_ALIGN (Value); -} - -/** - - 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); -} - /** Record variable error flag. @@ -1228,75 +766,6 @@ Done: return Status; } -/** - Find the variable in the specified variable store. - - @param[in] VariableName Name of the variable to be found - @param[in] VendorGuid Vendor GUID to be found. - @param[in] IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute - check at runtime when searching variable. - @param[in, out] PtrTrack Variable Track Pointer structure that contains Variable Information. - - @retval EFI_SUCCESS Variable found successfully - @retval EFI_NOT_FOUND Variable not found -**/ -EFI_STATUS -FindVariableEx ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN BOOLEAN IgnoreRtCheck, - IN OUT VARIABLE_POINTER_TRACK *PtrTrack - ) -{ - VARIABLE_HEADER *InDeletedVariable; - VOID *Point; - - PtrTrack->InDeletedTransitionPtr = NULL; - - // - // Find the variable by walk through HOB, volatile and non-volatile variable store. - // - InDeletedVariable = NULL; - - for ( PtrTrack->CurrPtr = PtrTrack->StartPtr - ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr) - ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr) - ) { - if (PtrTrack->CurrPtr->State == VAR_ADDED || - PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED) - ) { - if (IgnoreRtCheck || !AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) { - if (VariableName[0] == 0) { - if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { - InDeletedVariable = PtrTrack->CurrPtr; - } else { - PtrTrack->InDeletedTransitionPtr = InDeletedVariable; - return EFI_SUCCESS; - } - } else { - if (CompareGuid (VendorGuid, GetVendorGuidPtr (PtrTrack->CurrPtr))) { - Point = (VOID *) GetVariableNamePtr (PtrTrack->CurrPtr); - - ASSERT (NameSizeOfVariable (PtrTrack->CurrPtr) != 0); - if (CompareMem (VariableName, Point, NameSizeOfVariable (PtrTrack->CurrPtr)) == 0) { - if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { - InDeletedVariable = PtrTrack->CurrPtr; - } else { - PtrTrack->InDeletedTransitionPtr = InDeletedVariable; - return EFI_SUCCESS; - } - } - } - } - } - } - } - - PtrTrack->CurrPtr = InDeletedVariable; - return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; -} - - /** Finds variable in storage blocks of volatile and non-volatile storage areas. @@ -2078,38 +1547,6 @@ AutoUpdateLangVariable ( } } -/** - Compare two EFI_TIME data. - - - @param FirstTime A pointer to the first EFI_TIME data. - @param SecondTime A pointer to the second EFI_TIME data. - - @retval TRUE The FirstTime is not later than the SecondTime. - @retval FALSE The FirstTime is later than the SecondTime. - -**/ -BOOLEAN -VariableCompareTimeStampInternal ( - IN EFI_TIME *FirstTime, - IN EFI_TIME *SecondTime - ) -{ - if (FirstTime->Year != SecondTime->Year) { - return (BOOLEAN) (FirstTime->Year < SecondTime->Year); - } else if (FirstTime->Month != SecondTime->Month) { - return (BOOLEAN) (FirstTime->Month < SecondTime->Month); - } else if (FirstTime->Day != SecondTime->Day) { - return (BOOLEAN) (FirstTime->Day < SecondTime->Day); - } else if (FirstTime->Hour != SecondTime->Hour) { - return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour); - } else if (FirstTime->Minute != SecondTime->Minute) { - return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute); - } - - return (BOOLEAN) (FirstTime->Second <= SecondTime->Second); -} - /** Update the variable region with Variable information. If EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set, index of associated public key is needed. @@ -2205,7 +1642,7 @@ UpdateVariable ( // go to delete this variable in variable HOB and // try to flush other variables from HOB to flash. // - UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, FALSE, TRUE, FALSE); + UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, FALSE, TRUE, FALSE, &gVariableInfo); FlushHobVariableToFlash (VariableName, VendorGuid); return EFI_SUCCESS; } @@ -2322,7 +1759,7 @@ UpdateVariable ( &State ); if (!EFI_ERROR (Status)) { - UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE); + UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE, &gVariableInfo); if (!Variable->Volatile) { CacheVariable->CurrPtr->State = State; FlushHobVariableToFlash (VariableName, VendorGuid); @@ -2341,7 +1778,7 @@ UpdateVariable ( // // Variable content unchanged and no need to update timestamp, just return. // - UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE); + UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE, &gVariableInfo); Status = EFI_SUCCESS; goto Done; } else if ((CacheVariable->CurrPtr->State == VAR_ADDED) || @@ -2570,7 +2007,7 @@ UpdateVariable ( CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr)); CacheVariable->InDeletedTransitionPtr = NULL; } - UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE); + UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE, &gVariableInfo); FlushHobVariableToFlash (VariableName, VendorGuid); } else { if (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize) > mVariableModuleGlobal->CommonMaxUserVariableSpace)) { @@ -2720,7 +2157,7 @@ UpdateVariable ( CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr)); CacheVariable->InDeletedTransitionPtr = NULL; } - UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE); + UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE, &gVariableInfo); } goto Done; } @@ -2791,7 +2228,7 @@ UpdateVariable ( } if (!EFI_ERROR (Status)) { - UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE); + UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE, &gVariableInfo); if (!Volatile) { FlushHobVariableToFlash (VariableName, VendorGuid); } @@ -2870,7 +2307,7 @@ VariableServiceGetVariable ( } *DataSize = VarDataSize; - UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE); + UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE, &gVariableInfo); Status = EFI_SUCCESS; goto Done; @@ -2885,166 +2322,6 @@ Done: return Status; } -/** - This code Finds the Next available variable. - - Caution: This function may receive untrusted input. - This function may be invoked in SMM mode. This function will do basic validation, before parse the data. - - @param[in] VariableName Pointer to variable name. - @param[in] VendorGuid Variable Vendor Guid. - @param[out] VariablePtr Pointer to variable header address. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_NOT_FOUND The next variable was not found. - @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL. - @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and - GUID of an existing variable. - -**/ -EFI_STATUS -EFIAPI -VariableServiceGetNextVariableInternal ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - OUT VARIABLE_HEADER **VariablePtr - ) -{ - VARIABLE_STORE_TYPE Type; - VARIABLE_POINTER_TRACK Variable; - VARIABLE_POINTER_TRACK VariableInHob; - VARIABLE_POINTER_TRACK VariablePtrTrack; - EFI_STATUS Status; - VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; - - Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE); - if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { - // - // For VariableName is an empty string, FindVariable() will try to find and return - // the first qualified variable, and if FindVariable() returns error (EFI_NOT_FOUND) - // as no any variable is found, still go to return the error (EFI_NOT_FOUND). - // - if (VariableName[0] != 0) { - // - // For VariableName is not an empty string, and FindVariable() returns error as - // VariableName and VendorGuid are not a name and GUID of an existing variable, - // there is no way to get next variable, follow spec to return EFI_INVALID_PARAMETER. - // - Status = EFI_INVALID_PARAMETER; - } - goto Done; - } - - if (VariableName[0] != 0) { - // - // If variable name is not NULL, get next variable. - // - Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); - } - - // - // 0: Volatile, 1: HOB, 2: Non-Volatile. - // The index and attributes mapping must be kept in this order as FindVariable - // makes use of this mapping to implement search algorithm. - // - VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase; - VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase; - VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache; - - while (TRUE) { - // - // Switch from Volatile to HOB, to Non-Volatile. - // - while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) { - // - // Find current storage index - // - for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) { - if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) { - break; - } - } - ASSERT (Type < VariableStoreTypeMax); - // - // Switch to next storage - // - for (Type++; Type < VariableStoreTypeMax; Type++) { - if (VariableStoreHeader[Type] != NULL) { - break; - } - } - // - // Capture the case that - // 1. current storage is the last one, or - // 2. no further storage - // - if (Type == VariableStoreTypeMax) { - Status = EFI_NOT_FOUND; - goto Done; - } - Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]); - Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]); - Variable.CurrPtr = Variable.StartPtr; - } - - // - // Variable is found - // - if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { - if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) { - if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { - // - // If it is a IN_DELETED_TRANSITION variable, - // and there is also a same ADDED one at the same time, - // don't return it. - // - VariablePtrTrack.StartPtr = Variable.StartPtr; - VariablePtrTrack.EndPtr = Variable.EndPtr; - Status = FindVariableEx ( - GetVariableNamePtr (Variable.CurrPtr), - GetVendorGuidPtr (Variable.CurrPtr), - FALSE, - &VariablePtrTrack - ); - if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) { - Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); - continue; - } - } - - // - // Don't return NV variable when HOB overrides it - // - if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) && - (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv])) - ) { - VariableInHob.StartPtr = GetStartPointer (VariableStoreHeader[VariableStoreTypeHob]); - VariableInHob.EndPtr = GetEndPointer (VariableStoreHeader[VariableStoreTypeHob]); - Status = FindVariableEx ( - GetVariableNamePtr (Variable.CurrPtr), - GetVendorGuidPtr (Variable.CurrPtr), - FALSE, - &VariableInHob - ); - if (!EFI_ERROR (Status)) { - Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); - continue; - } - } - - *VariablePtr = Variable.CurrPtr; - Status = EFI_SUCCESS; - goto Done; - } - } - - Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); - } - -Done: - return Status; -} - /** This code Finds the Next available variable. @@ -3082,6 +2359,7 @@ VariableServiceGetNextVariableName ( UINTN MaxLen; UINTN VarNameSize; VARIABLE_HEADER *VariablePtr; + VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) { return EFI_INVALID_PARAMETER; @@ -3101,7 +2379,16 @@ VariableServiceGetNextVariableName ( AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); - Status = VariableServiceGetNextVariableInternal (VariableName, VendorGuid, &VariablePtr); + // + // 0: Volatile, 1: HOB, 2: Non-Volatile. + // The index and attributes mapping must be kept in this order as FindVariable + // makes use of this mapping to implement search algorithm. + // + VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase; + VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase; + VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache; + + Status = GetNextVariableEx (VariableName, VendorGuid, VariableStoreHeader, &VariablePtr); if (!EFI_ERROR (Status)) { VarNameSize = NameSizeOfVariable (VariablePtr); ASSERT (VarNameSize != 0); @@ -3720,25 +3007,6 @@ ReclaimForOS( } } -/** - Get non-volatile maximum variable size. - - @return Non-volatile maximum variable size. - -**/ -UINTN -GetNonVolatileMaxVariableSize ( - VOID - ) -{ - if (PcdGet32 (PcdHwErrStorageSize) != 0) { - return MAX (MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)), - PcdGet32 (PcdMaxHardwareErrorVariableSize)); - } else { - return MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)); - } -} - /** Get maximum variable size, covering both non-volatile and volatile variables. @@ -4024,7 +3292,7 @@ InitNonVolatileVariableStore ( return Status; } mVariableModuleGlobal->VariableGlobal.EmuNvMode = TRUE; - DEBUG ((DEBUG_INFO, "Variable driver will work at emulated non-volatile variable mode!\n")); + DEBUG ((DEBUG_INFO, "Variable driver will work in emulated non-volatile variable mode!\n")); } else { Status = InitRealNonVolatileVariableStore (&VariableStoreBase); if (EFI_ERROR (Status)) { @@ -4040,6 +3308,9 @@ InitNonVolatileVariableStore ( mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize); mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize); + Status = InitVariableHelpers (mVariableModuleGlobal->VariableGlobal.AuthFormat); + ASSERT_EFI_ERROR (Status); + // // Parse non-volatile variable data and get last variable offset. // @@ -4470,18 +3741,13 @@ VariableCommonInitialize ( // // mVariableModuleGlobal->VariableGlobal.AuthFormat - // has been initialized in InitNonVolatileVariableStore(). + // is initialized in InitNonVolatileVariableStore(). // if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { DEBUG ((EFI_D_INFO, "Variable driver will work with auth variable format!\n")); - // - // Set AuthSupport to FALSE first, VariableWriteServiceInitialize() will initialize it. - // - mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE; VariableGuid = &gEfiAuthenticatedVariableGuid; } else { DEBUG ((EFI_D_INFO, "Variable driver will work without auth variable support!\n")); - mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE; VariableGuid = &gEfiVariableGuid; } diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c index cb6fcebe2d..232d9ffe25 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c @@ -1,12 +1,13 @@ /** @file Provides variable driver extended services. -Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Variable.h" +#include "VariableParsing.h" /** Finds variable in storage blocks of volatile and non-volatile storage areas. @@ -97,10 +98,16 @@ VariableExLibFindNextVariable ( EFI_STATUS Status; VARIABLE_HEADER *VariablePtr; AUTHENTICATED_VARIABLE_HEADER *AuthVariablePtr; + VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; - Status = VariableServiceGetNextVariableInternal ( + VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase; + VariableStoreHeader[VariableStoreTypeHob] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase; + VariableStoreHeader[VariableStoreTypeNv] = mNvVariableCache; + + Status = GetNextVariableEx ( VariableName, VendorGuid, + VariableStoreHeader, &VariablePtr ); if (EFI_ERROR (Status)) { diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c new file mode 100644 index 0000000000..b1b6d8282f --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c @@ -0,0 +1,28 @@ +/** @file + Common variable non-volatile store routines. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "VariableNonVolatile.h" + +/** + Get non-volatile maximum variable size. + + @return Non-volatile maximum variable size. + +**/ +UINTN +GetNonVolatileMaxVariableSize ( + VOID + ) +{ + if (PcdGet32 (PcdHwErrStorageSize) != 0) { + return MAX (MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)), + PcdGet32 (PcdMaxHardwareErrorVariableSize)); + } else { + return MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)); + } +} diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c new file mode 100644 index 0000000000..d448e5a264 --- /dev/null +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c @@ -0,0 +1,816 @@ +/** @file + The common variable helper routines shared by the DXE_RUNTIME variable + module and the DXE_SMM variable module. + + Caution: This module requires additional review when modified. + This driver will have external input - variable data. They may be input in SMM mode. + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + +Copyright (c) 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "VariableParsing.h" + +typedef struct { + CONST CHAR16 *VariableName; + EFI_GUID *VendorGuid; +} VARIABLE_TYPE; + +VARIABLE_TYPE mAlwaysAuthenticatedVariables[] = { + {EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid}, + {EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid}, + {EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid}, + {EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid}, + {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid}, + {EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid}, +}; + +STATIC BOOLEAN mAuthFormat; + +/** + + This code checks if variable header is valid or not. + + @param Variable Pointer to the Variable Header. + @param VariableStoreEnd Pointer to the Variable Store End. + + @retval TRUE Variable header is valid. + @retval FALSE Variable header is not valid. + +**/ +BOOLEAN +IsValidVariableHeader ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_HEADER *VariableStoreEnd + ) +{ + if ((Variable == NULL) || (Variable >= VariableStoreEnd) || (Variable->StartId != VARIABLE_DATA)) { + // + // Variable is NULL or has reached the end of variable store, + // or the StartId is not correct. + // + return FALSE; + } + + return TRUE; +} + +/** + + This code gets the current status of Variable Store. + + @param VarStoreHeader Pointer to the Variable Store Header. + + @retval EfiRaw Variable store status is raw. + @retval EfiValid Variable store status is valid. + @retval EfiInvalid Variable store status 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; + } else 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; + } +} + +/** + This code gets the size of variable header. + + @return Size of variable header in bytes in type UINTN. + +**/ +UINTN +GetVariableHeaderSize ( + VOID + ) +{ + UINTN Value; + + if (mAuthFormat) { + 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. + + @return UINTN Size of variable in bytes. + +**/ +UINTN +NameSizeOfVariable ( + IN VARIABLE_HEADER *Variable + ) +{ + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; + + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; + if (mAuthFormat) { + 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 sets the size of name of variable. + + @param[in] Variable Pointer to the Variable Header. + @param[in] NameSize Name size to set. + +**/ +VOID +SetNameSizeOfVariable ( + IN VARIABLE_HEADER *Variable, + IN UINTN NameSize + ) +{ + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; + + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; + if (mAuthFormat) { + AuthVariable->NameSize = (UINT32) NameSize; + } else { + Variable->NameSize = (UINT32) NameSize; + } +} + +/** + + This code gets the size of variable data. + + @param Variable Pointer to the Variable Header. + + @return Size of variable in bytes. + +**/ +UINTN +DataSizeOfVariable ( + IN VARIABLE_HEADER *Variable + ) +{ + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; + + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; + if (mAuthFormat) { + 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 sets the size of variable data. + + @param[in] Variable Pointer to the Variable Header. + @param[in] DataSize Data size to set. + +**/ +VOID +SetDataSizeOfVariable ( + IN VARIABLE_HEADER *Variable, + IN UINTN DataSize + ) +{ + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; + + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; + if (mAuthFormat) { + AuthVariable->DataSize = (UINT32) DataSize; + } else { + Variable->DataSize = (UINT32) DataSize; + } +} + +/** + + This code gets the pointer to the variable name. + + @param Variable Pointer to the Variable Header. + + @return Pointer to Variable Name which is Unicode encoding. + +**/ +CHAR16 * +GetVariableNamePtr ( + IN VARIABLE_HEADER *Variable + ) +{ + return (CHAR16 *) ((UINTN) Variable + GetVariableHeaderSize ()); +} + +/** + This code gets the pointer to the variable guid. + + @param Variable Pointer to the Variable Header. + + @return A EFI_GUID* pointer to Vendor Guid. + +**/ +EFI_GUID * +GetVendorGuidPtr ( + IN VARIABLE_HEADER *Variable + ) +{ + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; + + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable; + if (mAuthFormat) { + return &AuthVariable->VendorGuid; + } else { + return &Variable->VendorGuid; + } +} + +/** + + This code gets the pointer to the variable data. + + @param Variable Pointer to the Variable Header. + + @return Pointer to Variable Data. + +**/ +UINT8 * +GetVariableDataPtr ( + IN VARIABLE_HEADER *Variable + ) +{ + UINTN Value; + + // + // Be careful about pad size for alignment. + // + Value = (UINTN) GetVariableNamePtr (Variable); + Value += NameSizeOfVariable (Variable); + Value += GET_PAD_SIZE (NameSizeOfVariable (Variable)); + + return (UINT8 *) Value; +} + +/** + This code gets the variable data offset related to variable header. + + @param Variable Pointer to the Variable Header. + + @return Variable Data offset. + +**/ +UINTN +GetVariableDataOffset ( + IN VARIABLE_HEADER *Variable + ) +{ + UINTN Value; + + // + // Be careful about pad size for alignment + // + Value = GetVariableHeaderSize (); + Value += NameSizeOfVariable (Variable); + Value += GET_PAD_SIZE (NameSizeOfVariable (Variable)); + + return Value; +} + +/** + + This code gets the pointer to the next variable header. + + @param Variable Pointer to the Variable Header. + + @return Pointer to next variable header. + +**/ +VARIABLE_HEADER * +GetNextVariablePtr ( + IN VARIABLE_HEADER *Variable + ) +{ + UINTN Value; + + Value = (UINTN) GetVariableDataPtr (Variable); + Value += DataSizeOfVariable (Variable); + Value += GET_PAD_SIZE (DataSizeOfVariable (Variable)); + + // + // Be careful about pad size for alignment. + // + return (VARIABLE_HEADER *) HEADER_ALIGN (Value); +} + +/** + + 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 end 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); +} + +/** + Returns if this is a variable that always requires authenticated writes. + There may be other scenarios that result in a variable not identified by the + function to also require authentication. + + @param[in] VariableName Name of variable. + @param[in] VendorGuid Guid of variable. + + @retval TRUE The variable always requires authenticated writes + @retval FALSE The variable may or may not require authenticated writes +**/ +BOOLEAN +IsAuthenticatedVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ) +{ + UINTN Index; + + for (Index = 0; Index < sizeof (mAlwaysAuthenticatedVariables) / sizeof (mAlwaysAuthenticatedVariables[0]); Index++) { + if ((StrCmp (VariableName, mAlwaysAuthenticatedVariables[Index].VariableName) == 0) && + (CompareGuid (VendorGuid, mAlwaysAuthenticatedVariables[Index].VendorGuid))) { + return TRUE; + } + } + return FALSE; +} + +/** + Compare two EFI_TIME data. + + + @param FirstTime A pointer to the first EFI_TIME data. + @param SecondTime A pointer to the second EFI_TIME data. + + @retval TRUE The FirstTime is not later than the SecondTime. + @retval FALSE The FirstTime is later than the SecondTime. + +**/ +BOOLEAN +VariableCompareTimeStampInternal ( + IN EFI_TIME *FirstTime, + IN EFI_TIME *SecondTime + ) +{ + if (FirstTime->Year != SecondTime->Year) { + return (BOOLEAN) (FirstTime->Year < SecondTime->Year); + } else if (FirstTime->Month != SecondTime->Month) { + return (BOOLEAN) (FirstTime->Month < SecondTime->Month); + } else if (FirstTime->Day != SecondTime->Day) { + return (BOOLEAN) (FirstTime->Day < SecondTime->Day); + } else if (FirstTime->Hour != SecondTime->Hour) { + return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour); + } else if (FirstTime->Minute != SecondTime->Minute) { + return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute); + } + + return (BOOLEAN) (FirstTime->Second <= SecondTime->Second); +} + +/** + Find the variable in the specified variable store. + + @param[in] VariableName Name of the variable to be found + @param[in] VendorGuid Vendor GUID to be found. + @param[in] IgnoreRtCheck Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute + check at runtime when searching variable. + @param[in, out] PtrTrack Variable Track Pointer structure that contains Variable Information. + + @retval EFI_SUCCESS Variable found successfully + @retval EFI_NOT_FOUND Variable not found +**/ +EFI_STATUS +FindVariableEx ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN BOOLEAN IgnoreRtCheck, + IN OUT VARIABLE_POINTER_TRACK *PtrTrack + ) +{ + VARIABLE_HEADER *InDeletedVariable; + VOID *Point; + + PtrTrack->InDeletedTransitionPtr = NULL; + + // + // Find the variable by walk through HOB, volatile and non-volatile variable store. + // + InDeletedVariable = NULL; + + for ( PtrTrack->CurrPtr = PtrTrack->StartPtr + ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr) + ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr) + ) { + if (PtrTrack->CurrPtr->State == VAR_ADDED || + PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED) + ) { + if (IgnoreRtCheck || !AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) { + if (VariableName[0] == 0) { + if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { + InDeletedVariable = PtrTrack->CurrPtr; + } else { + PtrTrack->InDeletedTransitionPtr = InDeletedVariable; + return EFI_SUCCESS; + } + } else { + if (CompareGuid (VendorGuid, GetVendorGuidPtr (PtrTrack->CurrPtr))) { + Point = (VOID *) GetVariableNamePtr (PtrTrack->CurrPtr); + + ASSERT (NameSizeOfVariable (PtrTrack->CurrPtr) != 0); + if (CompareMem (VariableName, Point, NameSizeOfVariable (PtrTrack->CurrPtr)) == 0) { + if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { + InDeletedVariable = PtrTrack->CurrPtr; + } else { + PtrTrack->InDeletedTransitionPtr = InDeletedVariable; + return EFI_SUCCESS; + } + } + } + } + } + } + } + + PtrTrack->CurrPtr = InDeletedVariable; + return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; +} + +/** + This code finds the next available variable. + + Caution: This function may receive untrusted input. + This function may be invoked in SMM mode. This function will do basic validation, before parse the data. + + @param[in] VariableName Pointer to variable name. + @param[in] VendorGuid Variable Vendor Guid. + @param[in] VariableStoreList A list of variable stores that should be used to get the next variable. + The maximum number of entries is the max value of VARIABLE_STORE_TYPE. + @param[out] VariablePtr Pointer to variable header address. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The next variable was not found. + @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL. + @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and + GUID of an existing variable. + +**/ +EFI_STATUS +EFIAPI +GetNextVariableEx ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN VARIABLE_STORE_HEADER **VariableStoreList, + OUT VARIABLE_HEADER **VariablePtr + ) +{ + EFI_STATUS Status; + VARIABLE_STORE_TYPE StoreType; + VARIABLE_POINTER_TRACK Variable; + VARIABLE_POINTER_TRACK VariableInHob; + VARIABLE_POINTER_TRACK VariablePtrTrack; + + Status = EFI_NOT_FOUND; + + if (VariableStoreList == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Check if the variable exists in the given variable store list + for (StoreType = (VARIABLE_STORE_TYPE) 0; StoreType < VariableStoreTypeMax; StoreType++) { + if (VariableStoreList[StoreType] == NULL) { + continue; + } + + Variable.StartPtr = GetStartPointer (VariableStoreList[StoreType]); + Variable.EndPtr = GetEndPointer (VariableStoreList[StoreType]); + Variable.Volatile = (BOOLEAN) (StoreType == VariableStoreTypeVolatile); + + Status = FindVariableEx (VariableName, VendorGuid, FALSE, &Variable); + if (!EFI_ERROR (Status)) { + break; + } + } + + if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { + // + // For VariableName is an empty string, FindVariable() will try to find and return + // the first qualified variable, and if FindVariable() returns error (EFI_NOT_FOUND) + // as no any variable is found, still go to return the error (EFI_NOT_FOUND). + // + if (VariableName[0] != 0) { + // + // For VariableName is not an empty string, and FindVariable() returns error as + // VariableName and VendorGuid are not a name and GUID of an existing variable, + // there is no way to get next variable, follow spec to return EFI_INVALID_PARAMETER. + // + Status = EFI_INVALID_PARAMETER; + } + goto Done; + } + + if (VariableName[0] != 0) { + // + // If variable name is not empty, get next variable. + // + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + } + + while (TRUE) { + // + // Switch to the next variable store if needed + // + while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) { + // + // Find current storage index + // + for (StoreType = (VARIABLE_STORE_TYPE) 0; StoreType < VariableStoreTypeMax; StoreType++) { + if ((VariableStoreList[StoreType] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreList[StoreType]))) { + break; + } + } + ASSERT (StoreType < VariableStoreTypeMax); + // + // Switch to next storage + // + for (StoreType++; StoreType < VariableStoreTypeMax; StoreType++) { + if (VariableStoreList[StoreType] != NULL) { + break; + } + } + // + // Capture the case that + // 1. current storage is the last one, or + // 2. no further storage + // + if (StoreType == VariableStoreTypeMax) { + Status = EFI_NOT_FOUND; + goto Done; + } + Variable.StartPtr = GetStartPointer (VariableStoreList[StoreType]); + Variable.EndPtr = GetEndPointer (VariableStoreList[StoreType]); + Variable.CurrPtr = Variable.StartPtr; + } + + // + // Variable is found + // + if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { + if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) { + if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { + // + // If it is a IN_DELETED_TRANSITION variable, + // and there is also a same ADDED one at the same time, + // don't return it. + // + VariablePtrTrack.StartPtr = Variable.StartPtr; + VariablePtrTrack.EndPtr = Variable.EndPtr; + Status = FindVariableEx ( + GetVariableNamePtr (Variable.CurrPtr), + GetVendorGuidPtr (Variable.CurrPtr), + FALSE, + &VariablePtrTrack + ); + if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) { + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + continue; + } + } + + // + // Don't return NV variable when HOB overrides it + // + if ((VariableStoreList[VariableStoreTypeHob] != NULL) && (VariableStoreList[VariableStoreTypeNv] != NULL) && + (Variable.StartPtr == GetStartPointer (VariableStoreList[VariableStoreTypeNv])) + ) { + VariableInHob.StartPtr = GetStartPointer (VariableStoreList[VariableStoreTypeHob]); + VariableInHob.EndPtr = GetEndPointer (VariableStoreList[VariableStoreTypeHob]); + Status = FindVariableEx ( + GetVariableNamePtr (Variable.CurrPtr), + GetVendorGuidPtr (Variable.CurrPtr), + FALSE, + &VariableInHob + ); + if (!EFI_ERROR (Status)) { + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + continue; + } + } + + *VariablePtr = Variable.CurrPtr; + Status = EFI_SUCCESS; + goto Done; + } + } + + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + } + +Done: + return Status; +} + +/** + Routine used to track statistical information about variable usage. + The data is stored in the EFI system table so it can be accessed later. + VariableInfo.efi can dump out the table. Only Boot Services variable + accesses are tracked by this code. The PcdVariableCollectStatistics + build flag controls if this feature is enabled. + + A read that hits in the cache will have Read and Cache true for + the transaction. Data is allocated by this routine, but never + freed. + + @param[in] VariableName Name of the Variable to track. + @param[in] VendorGuid Guid of the Variable to track. + @param[in] Volatile TRUE if volatile FALSE if non-volatile. + @param[in] Read TRUE if GetVariable() was called. + @param[in] Write TRUE if SetVariable() was called. + @param[in] Delete TRUE if deleted via SetVariable(). + @param[in] Cache TRUE for a cache hit. + @param[in,out] VariableInfo Pointer to a pointer of VARIABLE_INFO_ENTRY structures. + +**/ +VOID +UpdateVariableInfo ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN BOOLEAN Volatile, + IN BOOLEAN Read, + IN BOOLEAN Write, + IN BOOLEAN Delete, + IN BOOLEAN Cache, + IN OUT VARIABLE_INFO_ENTRY **VariableInfo + ) +{ + VARIABLE_INFO_ENTRY *Entry; + + if (FeaturePcdGet (PcdVariableCollectStatistics)) { + if (VariableName == NULL || VendorGuid == NULL || VariableInfo == NULL) { + return; + } + if (AtRuntime ()) { + // Don't collect statistics at runtime. + return; + } + + if (*VariableInfo == NULL) { + // + // On the first call allocate a entry and place a pointer to it in + // the EFI System Table. + // + *VariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY)); + ASSERT (*VariableInfo != NULL); + + CopyGuid (&(*VariableInfo)->VendorGuid, VendorGuid); + (*VariableInfo)->Name = AllocateZeroPool (StrSize (VariableName)); + ASSERT ((*VariableInfo)->Name != NULL); + StrCpyS ((*VariableInfo)->Name, StrSize(VariableName)/sizeof(CHAR16), VariableName); + (*VariableInfo)->Volatile = Volatile; + } + + + for (Entry = (*VariableInfo); Entry != NULL; Entry = Entry->Next) { + if (CompareGuid (VendorGuid, &Entry->VendorGuid)) { + if (StrCmp (VariableName, Entry->Name) == 0) { + if (Read) { + Entry->ReadCount++; + } + if (Write) { + Entry->WriteCount++; + } + if (Delete) { + Entry->DeleteCount++; + } + if (Cache) { + Entry->CacheCount++; + } + + return; + } + } + + if (Entry->Next == NULL) { + // + // If the entry is not in the table add it. + // Next iteration of the loop will fill in the data. + // + Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY)); + ASSERT (Entry->Next != NULL); + + CopyGuid (&Entry->Next->VendorGuid, VendorGuid); + Entry->Next->Name = AllocateZeroPool (StrSize (VariableName)); + ASSERT (Entry->Next->Name != NULL); + StrCpyS (Entry->Next->Name, StrSize(VariableName)/sizeof(CHAR16), VariableName); + Entry->Next->Volatile = Volatile; + } + } + } +} + +/** + Initializes context needed for variable helpers. + + @param[in] AuthFormat If true then indicates authenticated variables are supported + + @retval EFI_SUCCESS Initialized successfully + @retval Others An error occurred during initialization +**/ +EFI_STATUS +EFIAPI +InitVariableHelpers ( + IN BOOLEAN AuthFormat + ) +{ + mAuthFormat = AuthFormat; + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c index ec463d063e..bda531d104 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c @@ -30,6 +30,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include "Variable.h" +#include "VariableNonVolatile.h" +#include "VariableParsing.h" BOOLEAN mAtRuntime = FALSE; UINT8 *mVariableBufferPayload = NULL; diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c index 0a1888e5ef..5bf90039d6 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c @@ -13,7 +13,7 @@ InitCommunicateBuffer() is really function to check the variable data size. -Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -39,6 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include "PrivilegePolymorphic.h" +#include "VariableParsing.h" EFI_HANDLE mHandle = NULL; EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL; -- 2.16.2.windows.1