/** @file\r
-\r
Implement all four UEFI Runtime Variable services for the nonvolatile\r
and volatile storage space and install variable architecture protocol\r
based on SMM variable module.\r
\r
-Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
+ Caution: This module requires additional review when modified.\r
+ This driver will have external input - variable data.\r
+ This external input must be validated carefully to avoid security issue like\r
+ buffer overflow, integer overflow.\r
+\r
+ RuntimeServiceGetVariable() and RuntimeServiceSetVariable() are external API\r
+ to receive data buffer. The size should be checked carefully.\r
+\r
+ InitCommunicateBuffer() is really function to check the variable data size.\r
\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
#include <PiDxe.h>\r
#include <Protocol/Variable.h>\r
#include <Protocol/SmmCommunication.h>\r
#include <Protocol/SmmVariable.h>\r
+#include <Protocol/VariableLock.h>\r
+#include <Protocol/VarCheck.h>\r
\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiRuntimeServicesTableLib.h>\r
#include <Library/UefiRuntimeLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
-#include <Library/PcdLib.h>\r
#include <Library/UefiLib.h>\r
#include <Library/BaseLib.h>\r
\r
#include <Guid/EventGroup.h>\r
-#include <Guid/VariableFormat.h>\r
#include <Guid/SmmVariableCommon.h>\r
\r
-EFI_HANDLE mHandle = NULL; \r
+#include "PrivilegePolymorphic.h"\r
+#include "VariableParsing.h"\r
+\r
+EFI_HANDLE mHandle = NULL;\r
EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;\r
EFI_EVENT mVirtualAddressChangeEvent = NULL;\r
EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;\r
UINT8 *mVariableBuffer = NULL;\r
UINT8 *mVariableBufferPhysical = NULL;\r
+VARIABLE_INFO_ENTRY *mVariableInfo = NULL;\r
+VARIABLE_STORE_HEADER *mVariableRuntimeHobCacheBuffer = NULL;\r
+VARIABLE_STORE_HEADER *mVariableRuntimeNvCacheBuffer = NULL;\r
+VARIABLE_STORE_HEADER *mVariableRuntimeVolatileCacheBuffer = NULL;\r
UINTN mVariableBufferSize;\r
+UINTN mVariableRuntimeHobCacheBufferSize;\r
+UINTN mVariableRuntimeNvCacheBufferSize;\r
+UINTN mVariableRuntimeVolatileCacheBufferSize;\r
+UINTN mVariableBufferPayloadSize;\r
+BOOLEAN mVariableRuntimeCachePendingUpdate;\r
+BOOLEAN mVariableRuntimeCacheReadLock;\r
+BOOLEAN mVariableAuthFormat;\r
+BOOLEAN mHobFlushComplete;\r
EFI_LOCK mVariableServicesLock;\r
+EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;\r
+EDKII_VAR_CHECK_PROTOCOL mVarCheck;\r
+\r
+/**\r
+ Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).\r
+ Record their initial State when variable write service is ready.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RecordSecureBootPolicyVarData(\r
+ VOID\r
+ );\r
\r
/**\r
Acquires lock only at boot time. Simply returns at runtime.\r
}\r
}\r
\r
+/**\r
+ Return TRUE if ExitBootServices () has been called.\r
+\r
+ @retval TRUE If ExitBootServices () has been called. FALSE if ExitBootServices () has not been called.\r
+**/\r
+BOOLEAN\r
+AtRuntime (\r
+ VOID\r
+ )\r
+{\r
+ return EfiAtRuntime ();\r
+}\r
+\r
+/**\r
+ Initialize the variable cache buffer as an empty variable store.\r
+\r
+ @param[out] VariableCacheBuffer A pointer to pointer of a cache variable store.\r
+ @param[in,out] TotalVariableCacheSize On input, the minimum size needed for the UEFI variable store cache\r
+ buffer that is allocated. On output, the actual size of the buffer allocated.\r
+ If TotalVariableCacheSize is zero, a buffer will not be allocated and the\r
+ function will return with EFI_SUCCESS.\r
+\r
+ @retval EFI_SUCCESS The variable cache was allocated and initialized successfully.\r
+ @retval EFI_INVALID_PARAMETER A given pointer is NULL or an invalid variable store size was specified.\r
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources are available to allocate the variable store cache buffer.\r
+\r
+**/\r
+EFI_STATUS\r
+InitVariableCache (\r
+ OUT VARIABLE_STORE_HEADER **VariableCacheBuffer,\r
+ IN OUT UINTN *TotalVariableCacheSize\r
+ )\r
+{\r
+ VARIABLE_STORE_HEADER *VariableCacheStorePtr;\r
+\r
+ if (TotalVariableCacheSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (*TotalVariableCacheSize == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ if (VariableCacheBuffer == NULL || *TotalVariableCacheSize < sizeof (VARIABLE_STORE_HEADER)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ *TotalVariableCacheSize = ALIGN_VALUE (*TotalVariableCacheSize, sizeof (UINT32));\r
+\r
+ //\r
+ // Allocate NV Storage Cache and initialize it to all 1's (like an erased FV)\r
+ //\r
+ *VariableCacheBuffer = (VARIABLE_STORE_HEADER *) AllocateRuntimePages (\r
+ EFI_SIZE_TO_PAGES (*TotalVariableCacheSize)\r
+ );\r
+ if (*VariableCacheBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ VariableCacheStorePtr = *VariableCacheBuffer;\r
+ SetMem32 ((VOID *) VariableCacheStorePtr, *TotalVariableCacheSize, (UINT32) 0xFFFFFFFF);\r
+\r
+ ZeroMem ((VOID *) VariableCacheStorePtr, sizeof (VARIABLE_STORE_HEADER));\r
+ VariableCacheStorePtr->Size = (UINT32) *TotalVariableCacheSize;\r
+ VariableCacheStorePtr->Format = VARIABLE_STORE_FORMATTED;\r
+ VariableCacheStorePtr->State = VARIABLE_STORE_HEALTHY;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Initialize the communicate buffer using DataSize and Function.\r
\r
The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +\r
DataSize.\r
\r
+ Caution: This function may receive untrusted input.\r
+ The data size external input, so this function will validate it carefully to avoid buffer overflow.\r
+\r
@param[out] DataPtr Points to the data in the communicate buffer.\r
@param[in] DataSize The data size to send to SMM.\r
@param[in] Function The function number to initialize the communicate header.\r
- \r
+\r
@retval EFI_INVALID_PARAMETER The data size is too big.\r
@retval EFI_SUCCESS Find the specified variable.\r
\r
IN UINTN Function\r
)\r
{\r
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; \r
- SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader; \r
+ EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
+ SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
+\r
\r
- \r
if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {\r
return EFI_INVALID_PARAMETER;\r
}\r
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;\r
CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
- \r
+\r
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
SmmVariableFunctionHeader->Function = Function;\r
if (DataPtr != NULL) {\r
@param[in] DataSize This size of the function header and the data.\r
\r
@retval EFI_SUCCESS Success is returned from the functin in SMM.\r
- @retval Others Failure is returned from the function in SMM. \r
- \r
+ @retval Others Failure is returned from the function in SMM.\r
+\r
**/\r
EFI_STATUS\r
SendCommunicateBuffer (\r
{\r
EFI_STATUS Status;\r
UINTN CommSize;\r
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; \r
+ EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
- \r
+\r
CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);\r
ASSERT_EFI_ERROR (Status);\r
return SmmVariableFunctionHeader->ReturnStatus;\r
}\r
\r
+/**\r
+ Mark a variable that will become read-only after leaving the DXE phase of execution.\r
+\r
+ @param[in] This The VARIABLE_LOCK_PROTOCOL instance.\r
+ @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.\r
+ @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.\r
+\r
+ @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked\r
+ as pending to be read-only.\r
+ @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.\r
+ Or VariableName is an empty string.\r
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
+ already been signaled.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableLockRequestToLock (\r
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN VariableNameSize;\r
+ UINTN PayloadSize;\r
+ SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
+\r
+ if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ VariableNameSize = StrSize (VariableName);\r
+ VariableToLock = NULL;\r
+\r
+ //\r
+ // If VariableName exceeds SMM payload limit. Return failure\r
+ //\r
+ if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
+\r
+ //\r
+ // Init the communicate buffer. The buffer data size is:\r
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
+ //\r
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;\r
+ Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ ASSERT (VariableToLock != NULL);\r
+\r
+ CopyGuid (&VariableToLock->Guid, VendorGuid);\r
+ VariableToLock->NameSize = VariableNameSize;\r
+ CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);\r
+\r
+ //\r
+ // Send data to SMM.\r
+ //\r
+ Status = SendCommunicateBuffer (PayloadSize);\r
+\r
+Done:\r
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+ return Status;\r
+}\r
\r
/**\r
- This code finds variable in storage blocks (Volatile or Non-Volatile).\r
+ Register SetVariable check handler.\r
+\r
+ @param[in] Handler Pointer to check handler.\r
+\r
+ @retval EFI_SUCCESS The SetVariable check handler was registered successfully.\r
+ @retval EFI_INVALID_PARAMETER Handler is NULL.\r
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
+ already been signaled.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource for the SetVariable check handler register request.\r
+ @retval EFI_UNSUPPORTED This interface is not implemented.\r
+ For example, it is unsupported in VarCheck protocol if both VarCheck and SmmVarCheck protocols are present.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VarCheckRegisterSetVariableCheckHandler (\r
+ IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Variable property set.\r
+\r
+ @param[in] Name Pointer to the variable name.\r
+ @param[in] Guid Pointer to the vendor GUID.\r
+ @param[in] VariableProperty Pointer to the input variable property.\r
+\r
+ @retval EFI_SUCCESS The property of variable specified by the Name and Guid was set successfully.\r
+ @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,\r
+ or the fields of VariableProperty are not valid.\r
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
+ already been signaled.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource for the variable property set request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VarCheckVariablePropertySet (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *Guid,\r
+ IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN VariableNameSize;\r
+ UINTN PayloadSize;\r
+ SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
+\r
+ if (Name == NULL || Name[0] == 0 || Guid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (VariableProperty == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ VariableNameSize = StrSize (Name);\r
+ CommVariableProperty = NULL;\r
+\r
+ //\r
+ // If VariableName exceeds SMM payload limit. Return failure\r
+ //\r
+ if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+ //\r
+ // Init the communicate buffer. The buffer data size is:\r
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
+ //\r
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + VariableNameSize;\r
+ Status = InitCommunicateBuffer ((VOID **) &CommVariableProperty, PayloadSize, SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ ASSERT (CommVariableProperty != NULL);\r
+\r
+ CopyGuid (&CommVariableProperty->Guid, Guid);\r
+ CopyMem (&CommVariableProperty->VariableProperty, VariableProperty, sizeof (*VariableProperty));\r
+ CommVariableProperty->NameSize = VariableNameSize;\r
+ CopyMem (CommVariableProperty->Name, Name, CommVariableProperty->NameSize);\r
+\r
+ //\r
+ // Send data to SMM.\r
+ //\r
+ Status = SendCommunicateBuffer (PayloadSize);\r
+\r
+Done:\r
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Variable property get.\r
+\r
+ @param[in] Name Pointer to the variable name.\r
+ @param[in] Guid Pointer to the vendor GUID.\r
+ @param[out] VariableProperty Pointer to the output variable property.\r
+\r
+ @retval EFI_SUCCESS The property of variable specified by the Name and Guid was got successfully.\r
+ @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.\r
+ @retval EFI_NOT_FOUND The property of variable specified by the Name and Guid was not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VarCheckVariablePropertyGet (\r
+ IN CHAR16 *Name,\r
+ IN EFI_GUID *Guid,\r
+ OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN VariableNameSize;\r
+ UINTN PayloadSize;\r
+ SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
+\r
+ if (Name == NULL || Name[0] == 0 || Guid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (VariableProperty == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ VariableNameSize = StrSize (Name);\r
+ CommVariableProperty = NULL;\r
+\r
+ //\r
+ // If VariableName exceeds SMM payload limit. Return failure\r
+ //\r
+ if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+ //\r
+ // Init the communicate buffer. The buffer data size is:\r
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
+ //\r
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + VariableNameSize;\r
+ Status = InitCommunicateBuffer ((VOID **) &CommVariableProperty, PayloadSize, SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ ASSERT (CommVariableProperty != NULL);\r
+\r
+ CopyGuid (&CommVariableProperty->Guid, Guid);\r
+ CommVariableProperty->NameSize = VariableNameSize;\r
+ CopyMem (CommVariableProperty->Name, Name, CommVariableProperty->NameSize);\r
+\r
+ //\r
+ // Send data to SMM.\r
+ //\r
+ Status = SendCommunicateBuffer (PayloadSize);\r
+ if (Status == EFI_SUCCESS) {\r
+ CopyMem (VariableProperty, &CommVariableProperty->VariableProperty, sizeof (*VariableProperty));\r
+ }\r
+\r
+Done:\r
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Signals SMM to synchronize any pending variable updates with the runtime cache(s).\r
+\r
+**/\r
+VOID\r
+SyncRuntimeCache (\r
+ VOID\r
+ )\r
+{\r
+ //\r
+ // Init the communicate buffer. The buffer data size is:\r
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
+ //\r
+ InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE);\r
+\r
+ //\r
+ // Send data to SMM.\r
+ //\r
+ SendCommunicateBuffer (0);\r
+}\r
+\r
+/**\r
+ Check whether a SMI must be triggered to retrieve pending cache updates.\r
+\r
+ If the variable HOB was finished being flushed since the last check for a runtime cache update, this function\r
+ will prevent the HOB cache from being used for future runtime cache hits.\r
+\r
+**/\r
+VOID\r
+CheckForRuntimeCacheSync (\r
+ VOID\r
+ )\r
+{\r
+ if (mVariableRuntimeCachePendingUpdate) {\r
+ SyncRuntimeCache ();\r
+ }\r
+ ASSERT (!mVariableRuntimeCachePendingUpdate);\r
+\r
+ //\r
+ // The HOB variable data may have finished being flushed in the runtime cache sync update\r
+ //\r
+ if (mHobFlushComplete && mVariableRuntimeHobCacheBuffer != NULL) {\r
+ if (!EfiAtRuntime ()) {\r
+ FreePages (mVariableRuntimeHobCacheBuffer, EFI_SIZE_TO_PAGES (mVariableRuntimeHobCacheBufferSize));\r
+ }\r
+ mVariableRuntimeHobCacheBuffer = NULL;\r
+ }\r
+}\r
+\r
+/**\r
+ Finds the given variable in a runtime cache variable store.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ The data size is external input, so this function will validate it carefully to avoid buffer overflow.\r
\r
@param[in] VariableName Name of Variable to be found.\r
@param[in] VendorGuid Variable vendor GUID.\r
@param[in, out] DataSize Size of Data found. If size is less than the\r
data, this value contains the required size.\r
@param[out] Data Data pointer.\r
- \r
+\r
+ @retval EFI_SUCCESS Found the specified variable.\r
@retval EFI_INVALID_PARAMETER Invalid parameter.\r
- @retval EFI_SUCCESS Find the specified variable.\r
- @retval EFI_NOT_FOUND Not found.\r
- @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
+ @retval EFI_NOT_FOUND The specified variable could not be found.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-RuntimeServiceGetVariable (\r
+FindVariableInRuntimeCache (\r
IN CHAR16 *VariableName,\r
IN EFI_GUID *VendorGuid,\r
OUT UINT32 *Attributes OPTIONAL,\r
IN OUT UINTN *DataSize,\r
- OUT VOID *Data\r
+ OUT VOID *Data OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN TempDataSize;\r
+ VARIABLE_POINTER_TRACK RtPtrTrack;\r
+ VARIABLE_STORE_TYPE StoreType;\r
+ VARIABLE_STORE_HEADER *VariableStoreList[VariableStoreTypeMax];\r
+\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // The UEFI specification restricts Runtime Services callers from invoking the same or certain other Runtime Service\r
+ // functions prior to completion and return from a previous Runtime Service call. These restrictions prevent\r
+ // a GetVariable () or GetNextVariable () call from being issued until a prior call has returned. The runtime\r
+ // cache read lock should always be free when entering this function.\r
+ //\r
+ ASSERT (!mVariableRuntimeCacheReadLock);\r
+\r
+ mVariableRuntimeCacheReadLock = TRUE;\r
+ CheckForRuntimeCacheSync ();\r
+\r
+ if (!mVariableRuntimeCachePendingUpdate) {\r
+ //\r
+ // 0: Volatile, 1: HOB, 2: Non-Volatile.\r
+ // The index and attributes mapping must be kept in this order as FindVariable\r
+ // makes use of this mapping to implement search algorithm.\r
+ //\r
+ VariableStoreList[VariableStoreTypeVolatile] = mVariableRuntimeVolatileCacheBuffer;\r
+ VariableStoreList[VariableStoreTypeHob] = mVariableRuntimeHobCacheBuffer;\r
+ VariableStoreList[VariableStoreTypeNv] = mVariableRuntimeNvCacheBuffer;\r
+\r
+ for (StoreType = (VARIABLE_STORE_TYPE) 0; StoreType < VariableStoreTypeMax; StoreType++) {\r
+ if (VariableStoreList[StoreType] == NULL) {\r
+ continue;\r
+ }\r
+\r
+ RtPtrTrack.StartPtr = GetStartPointer (VariableStoreList[StoreType]);\r
+ RtPtrTrack.EndPtr = GetEndPointer (VariableStoreList[StoreType]);\r
+ RtPtrTrack.Volatile = (BOOLEAN) (StoreType == VariableStoreTypeVolatile);\r
+\r
+ Status = FindVariableEx (VariableName, VendorGuid, FALSE, &RtPtrTrack, mVariableAuthFormat);\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Get data size\r
+ //\r
+ TempDataSize = DataSizeOfVariable (RtPtrTrack.CurrPtr, mVariableAuthFormat);\r
+ ASSERT (TempDataSize != 0);\r
+\r
+ if (*DataSize >= TempDataSize) {\r
+ if (Data == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Done;\r
+ }\r
+\r
+ CopyMem (Data, GetVariableDataPtr (RtPtrTrack.CurrPtr, mVariableAuthFormat), TempDataSize);\r
+ if (Attributes != NULL) {\r
+ *Attributes = RtPtrTrack.CurrPtr->Attributes;\r
+ }\r
+\r
+ *DataSize = TempDataSize;\r
+\r
+ UpdateVariableInfo (VariableName, VendorGuid, RtPtrTrack.Volatile, TRUE, FALSE, FALSE, TRUE, &mVariableInfo);\r
+\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ } else {\r
+ *DataSize = TempDataSize;\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+Done:\r
+ mVariableRuntimeCacheReadLock = FALSE;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Finds the given variable in a variable store in SMM.\r
+\r
+ Caution: This function may receive untrusted input.\r
+ The data size is external input, so this function will validate it carefully to avoid buffer overflow.\r
+\r
+ @param[in] VariableName Name of Variable to be found.\r
+ @param[in] VendorGuid Variable vendor GUID.\r
+ @param[out] Attributes Attribute value of the variable found.\r
+ @param[in, out] DataSize Size of Data found. If size is less than the\r
+ data, this value contains the required size.\r
+ @param[out] Data Data pointer.\r
+\r
+ @retval EFI_SUCCESS Found the specified variable.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_NOT_FOUND The specified variable could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+FindVariableInSmm (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINT32 *Attributes OPTIONAL,\r
+ IN OUT UINTN *DataSize,\r
+ OUT VOID *Data OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
UINTN PayloadSize;\r
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
- UINTN SmmCommBufPayloadSize;\r
UINTN TempDataSize;\r
+ UINTN VariableNameSize;\r
\r
if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if ((*DataSize != 0) && (Data == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // SMM Communication Buffer max payload size\r
- //\r
- SmmCommBufPayloadSize = mVariableBufferSize - (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE);\r
TempDataSize = *DataSize;\r
+ VariableNameSize = StrSize (VariableName);\r
+ SmmVariableHeader = NULL;\r
\r
//\r
// If VariableName exceeds SMM payload limit. Return failure\r
//\r
- if (StrSize (VariableName) > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
+ if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
-\r
//\r
// Init the communicate buffer. The buffer data size is:\r
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
//\r
- if (TempDataSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName)) {\r
+ if (TempDataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) {\r
//\r
// If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size\r
//\r
- TempDataSize = SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - StrSize (VariableName);\r
+ TempDataSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize;\r
}\r
- PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + TempDataSize;\r
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize;\r
\r
- Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);\r
+ Status = InitCommunicateBuffer ((VOID **) &SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
\r
CopyGuid (&SmmVariableHeader->Guid, VendorGuid);\r
SmmVariableHeader->DataSize = TempDataSize;\r
- SmmVariableHeader->NameSize = StrSize (VariableName);\r
+ SmmVariableHeader->NameSize = VariableNameSize;\r
if (Attributes == NULL) {\r
SmmVariableHeader->Attributes = 0;\r
} else {\r
Status = SendCommunicateBuffer (PayloadSize);\r
\r
//\r
- // Get data from SMM.\r
+ // Get data from SMM.\r
+ //\r
+ if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // SMM CommBuffer DataSize can be a trimed value\r
+ // Only update DataSize when needed\r
+ //\r
+ *DataSize = SmmVariableHeader->DataSize;\r
+ }\r
+ if (Attributes != NULL) {\r
+ *Attributes = SmmVariableHeader->Attributes;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (Data != NULL) {\r
+ CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);\r
+ } else {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+Done:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This code finds variable in storage blocks (Volatile or Non-Volatile).\r
+\r
+ Caution: This function may receive untrusted input.\r
+ The data size is external input, so this function will validate it carefully to avoid buffer overflow.\r
+\r
+ @param[in] VariableName Name of Variable to be found.\r
+ @param[in] VendorGuid Variable vendor GUID.\r
+ @param[out] Attributes Attribute value of the variable found.\r
+ @param[in, out] DataSize Size of Data found. If size is less than the\r
+ data, this value contains the required size.\r
+ @param[out] Data Data pointer.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_SUCCESS Find the specified variable.\r
+ @retval EFI_NOT_FOUND Not found.\r
+ @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RuntimeServiceGetVariable (\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ OUT UINT32 *Attributes OPTIONAL,\r
+ IN OUT UINTN *DataSize,\r
+ OUT VOID *Data\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ if (VariableName[0] == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
+ if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) {\r
+ Status = FindVariableInRuntimeCache (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+ } else {\r
+ Status = FindVariableInSmm (VariableName, VendorGuid, Attributes, DataSize, Data);\r
+ }\r
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Finds the next available variable in a runtime cache variable store.\r
+\r
+ @param[in, out] VariableNameSize Size of the variable name.\r
+ @param[in, out] VariableName Pointer to variable name.\r
+ @param[in, out] VendorGuid Variable Vendor Guid.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_SUCCESS Find the specified variable.\r
+ @retval EFI_NOT_FOUND Not found.\r
+ @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
+\r
+**/\r
+EFI_STATUS\r
+GetNextVariableNameInRuntimeCache (\r
+ IN OUT UINTN *VariableNameSize,\r
+ IN OUT CHAR16 *VariableName,\r
+ IN OUT EFI_GUID *VendorGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN VarNameSize;\r
+ VARIABLE_HEADER *VariablePtr;\r
+ VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];\r
+\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ //\r
+ // The UEFI specification restricts Runtime Services callers from invoking the same or certain other Runtime Service\r
+ // functions prior to completion and return from a previous Runtime Service call. These restrictions prevent\r
+ // a GetVariable () or GetNextVariable () call from being issued until a prior call has returned. The runtime\r
+ // cache read lock should always be free when entering this function.\r
//\r
- if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {\r
+ ASSERT (!mVariableRuntimeCacheReadLock);\r
+\r
+ CheckForRuntimeCacheSync ();\r
+\r
+ mVariableRuntimeCacheReadLock = TRUE;\r
+ if (!mVariableRuntimeCachePendingUpdate) {\r
//\r
- // SMM CommBuffer DataSize can be a trimed value\r
- // Only update DataSize when needed\r
+ // 0: Volatile, 1: HOB, 2: Non-Volatile.\r
+ // The index and attributes mapping must be kept in this order as FindVariable\r
+ // makes use of this mapping to implement search algorithm.\r
//\r
- *DataSize = SmmVariableHeader->DataSize;\r
+ VariableStoreHeader[VariableStoreTypeVolatile] = mVariableRuntimeVolatileCacheBuffer;\r
+ VariableStoreHeader[VariableStoreTypeHob] = mVariableRuntimeHobCacheBuffer;\r
+ VariableStoreHeader[VariableStoreTypeNv] = mVariableRuntimeNvCacheBuffer;\r
+\r
+ Status = VariableServiceGetNextVariableInternal (\r
+ VariableName,\r
+ VendorGuid,\r
+ VariableStoreHeader,\r
+ &VariablePtr,\r
+ mVariableAuthFormat\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ VarNameSize = NameSizeOfVariable (VariablePtr, mVariableAuthFormat);\r
+ ASSERT (VarNameSize != 0);\r
+ if (VarNameSize <= *VariableNameSize) {\r
+ CopyMem (VariableName, GetVariableNamePtr (VariablePtr, mVariableAuthFormat), VarNameSize);\r
+ CopyMem (VendorGuid, GetVendorGuidPtr (VariablePtr, mVariableAuthFormat), sizeof (EFI_GUID));\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *VariableNameSize = VarNameSize;\r
+ }\r
}\r
- if (Attributes != NULL) {\r
- *Attributes = SmmVariableHeader->Attributes;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);\r
+ mVariableRuntimeCacheReadLock = FALSE;\r
\r
-Done:\r
- ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
return Status;\r
}\r
\r
-\r
/**\r
- This code Finds the Next available variable.\r
+ Finds the next available variable in a SMM variable store.\r
\r
@param[in, out] VariableNameSize Size of the variable name.\r
@param[in, out] VariableName Pointer to variable name.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
-RuntimeServiceGetNextVariableName (\r
+GetNextVariableNameInSmm (\r
IN OUT UINTN *VariableNameSize,\r
IN OUT CHAR16 *VariableName,\r
IN OUT EFI_GUID *VendorGuid\r
EFI_STATUS Status;\r
UINTN PayloadSize;\r
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;\r
- UINTN SmmCommBufPayloadSize;\r
-\r
- if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ UINTN OutVariableNameSize;\r
+ UINTN InVariableNameSize;\r
\r
- //\r
- // SMM Communication Buffer max payload size\r
- //\r
- SmmCommBufPayloadSize = mVariableBufferSize - (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE);\r
+ OutVariableNameSize = *VariableNameSize;\r
+ InVariableNameSize = StrSize (VariableName);\r
+ SmmGetNextVariableName = NULL;\r
\r
//\r
// If input string exceeds SMM payload limit. Return failure\r
//\r
- if (StrSize (VariableName) > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
+ if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
-\r
//\r
// Init the communicate buffer. The buffer data size is:\r
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
//\r
- if (*VariableNameSize > SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
+ if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
//\r
// If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size\r
//\r
- *VariableNameSize = SmmCommBufPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
+ OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
}\r
//\r
// Payload should be Guid + NameSize + MAX of Input & Output buffer\r
//\r
- PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (*VariableNameSize, StrSize (VariableName));\r
-\r
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);\r
\r
Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);\r
if (EFI_ERROR (Status)) {\r
//\r
// SMM comm buffer->NameSize is buffer size for return string\r
//\r
- SmmGetNextVariableName->NameSize = *VariableNameSize;\r
+ SmmGetNextVariableName->NameSize = OutVariableNameSize;\r
\r
CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);\r
//\r
// Copy whole string\r
//\r
- CopyMem (SmmGetNextVariableName->Name, VariableName, StrSize (VariableName));\r
+ CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize);\r
+ if (OutVariableNameSize > InVariableNameSize) {\r
+ ZeroMem ((UINT8 *) SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize);\r
+ }\r
\r
//\r
// Send data to SMM\r
//\r
// Get data from SMM.\r
//\r
- *VariableNameSize = SmmGetNextVariableName->NameSize; \r
+ if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // SMM CommBuffer NameSize can be a trimed value\r
+ // Only update VariableNameSize when needed\r
+ //\r
+ *VariableNameSize = SmmGetNextVariableName->NameSize;\r
+ }\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
- \r
+\r
CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);\r
- CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize); \r
+ CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);\r
\r
Done:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This code Finds the Next available variable.\r
+\r
+ @param[in, out] VariableNameSize Size of the variable name.\r
+ @param[in, out] VariableName Pointer to variable name.\r
+ @param[in, out] VendorGuid Variable Vendor Guid.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_SUCCESS Find the specified variable.\r
+ @retval EFI_NOT_FOUND Not found.\r
+ @retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RuntimeServiceGetNextVariableName (\r
+ IN OUT UINTN *VariableNameSize,\r
+ IN OUT CHAR16 *VariableName,\r
+ IN OUT EFI_GUID *VendorGuid\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN MaxLen;\r
+\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Calculate the possible maximum length of name string, including the Null terminator.\r
+ //\r
+ MaxLen = *VariableNameSize / sizeof (CHAR16);\r
+ if ((MaxLen == 0) || (StrnLenS (VariableName, MaxLen) == MaxLen)) {\r
+ //\r
+ // Null-terminator is not found in the first VariableNameSize bytes of the input VariableName buffer,\r
+ // follow spec to return EFI_INVALID_PARAMETER.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
+ if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) {\r
+ Status = GetNextVariableNameInRuntimeCache (VariableNameSize, VariableName, VendorGuid);\r
+ } else {\r
+ Status = GetNextVariableNameInSmm (VariableNameSize, VariableName, VendorGuid);\r
+ }\r
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
return Status;\r
}\r
\r
/**\r
This code sets variable in storage blocks (Volatile or Non-Volatile).\r
\r
+ Caution: This function may receive untrusted input.\r
+ The data size and data are external input, so this function will validate it carefully to avoid buffer overflow.\r
+\r
@param[in] VariableName Name of Variable to be found.\r
@param[in] VendorGuid Variable vendor GUID.\r
@param[in] Attributes Attribute value of the variable found\r
)\r
{\r
EFI_STATUS Status;\r
- UINTN PayloadSize; \r
+ UINTN PayloadSize;\r
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
- \r
+ UINTN VariableNameSize;\r
+\r
//\r
// Check input parameters.\r
//\r
if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
return EFI_INVALID_PARAMETER;\r
- } \r
+ }\r
\r
if (DataSize != 0 && Data == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (DataSize >= mVariableBufferSize) {\r
- //\r
- // DataSize may be near MAX_ADDRESS incorrectly, this can cause the computed PayLoadSize to\r
- // overflow to a small value and pass the check in InitCommunicateBuffer().\r
- // To protect against this vulnerability, return EFI_INVALID_PARAMETER if DataSize is >= mVariableBufferSize.\r
- // And there will be further check to ensure the total size is also not > mVariableBufferSize.\r
- //\r
+ VariableNameSize = StrSize (VariableName);\r
+ SmmVariableHeader = NULL;\r
+\r
+ //\r
+ // If VariableName or DataSize exceeds SMM payload limit. Return failure\r
+ //\r
+ if ((VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
+ (DataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize)){\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
- \r
+\r
//\r
// Init the communicate buffer. The buffer data size is:\r
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
//\r
- PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;\r
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize;\r
Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
\r
CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);\r
SmmVariableHeader->DataSize = DataSize;\r
- SmmVariableHeader->NameSize = StrSize (VariableName);\r
+ SmmVariableHeader->NameSize = VariableNameSize;\r
SmmVariableHeader->Attributes = Attributes;\r
CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);\r
CopyMem ((UINT8 *) SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);\r
\r
Done:\r
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+ if (!EfiAtRuntime ()) {\r
+ if (!EFI_ERROR (Status)) {\r
+ SecureBootHook (\r
+ VariableName,\r
+ VendorGuid\r
+ );\r
+ }\r
+ }\r
return Status;\r
}\r
\r
UINTN PayloadSize;\r
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;\r
\r
+ SmmQueryVariableInfo = NULL;\r
+\r
if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
//\r
*MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;\r
*MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;\r
- *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize; \r
+ *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;\r
\r
Done:\r
ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
// Init the communicate buffer. The buffer data size is:\r
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
//\r
- InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE); \r
+ InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);\r
\r
//\r
// Send data to SMM.\r
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
//\r
InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);\r
- \r
+\r
//\r
// Send data to SMM.\r
//\r
SendCommunicateBuffer (0);\r
+\r
+ //\r
+ // Install the system configuration table for variable info data captured\r
+ //\r
+ if (FeaturePcdGet (PcdEnableVariableRuntimeCache) && FeaturePcdGet (PcdVariableCollectStatistics)) {\r
+ if (mVariableAuthFormat) {\r
+ gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, mVariableInfo);\r
+ } else {\r
+ gBS->InstallConfigurationTable (&gEfiVariableGuid, mVariableInfo);\r
+ }\r
+ }\r
+\r
+ gBS->CloseEvent (Event);\r
}\r
\r
\r
{\r
EfiConvertPointer (0x0, (VOID **) &mVariableBuffer);\r
EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);\r
+ EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **) &mVariableRuntimeHobCacheBuffer);\r
+ EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **) &mVariableRuntimeNvCacheBuffer);\r
+ EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **) &mVariableRuntimeVolatileCacheBuffer);\r
+}\r
+\r
+/**\r
+ This code gets variable payload size.\r
+\r
+ @param[out] VariablePayloadSize Output pointer to variable payload size.\r
+\r
+ @retval EFI_SUCCESS Get successfully.\r
+ @retval Others Get unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetVariablePayloadSize (\r
+ OUT UINTN *VariablePayloadSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *SmmGetPayloadSize;\r
+ EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
+ SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
+ UINTN CommSize;\r
+ UINT8 *CommBuffer;\r
+\r
+ SmmGetPayloadSize = NULL;\r
+ CommBuffer = NULL;\r
+\r
+ if(VariablePayloadSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
+\r
+ //\r
+ // Init the communicate buffer. The buffer data size is:\r
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
+ //\r
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
+ CommBuffer = AllocateZeroPool (CommSize);\r
+ if (CommBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) CommBuffer;\r
+ CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
+ SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
+\r
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;\r
+ SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;\r
+\r
+ //\r
+ // Send data to SMM.\r
+ //\r
+ Status = mSmmCommunication->Communicate (mSmmCommunication, CommBuffer, &CommSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = SmmVariableFunctionHeader->ReturnStatus;\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get data from SMM.\r
+ //\r
+ *VariablePayloadSize = SmmGetPayloadSize->VariablePayloadSize;\r
+\r
+Done:\r
+ if (CommBuffer != NULL) {\r
+ FreePool (CommBuffer);\r
+ }\r
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This code gets information needed from SMM for runtime cache initialization.\r
+\r
+ @param[out] TotalHobStorageSize Output pointer for the total HOB storage size in bytes.\r
+ @param[out] TotalNvStorageSize Output pointer for the total non-volatile storage size in bytes.\r
+ @param[out] TotalVolatileStorageSize Output pointer for the total volatile storage size in bytes.\r
+ @param[out] AuthenticatedVariableUsage Output pointer that indicates if authenticated variables are to be used.\r
+\r
+ @retval EFI_SUCCESS Retrieved the size successfully.\r
+ @retval EFI_INVALID_PARAMETER TotalNvStorageSize parameter is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES The memory resources needed for a CommBuffer are not available.\r
+ @retval Others Could not retrieve the size successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+GetRuntimeCacheInfo (\r
+ OUT UINTN *TotalHobStorageSize,\r
+ OUT UINTN *TotalNvStorageSize,\r
+ OUT UINTN *TotalVolatileStorageSize,\r
+ OUT BOOLEAN *AuthenticatedVariableUsage\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *SmmGetRuntimeCacheInfo;\r
+ EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
+ SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
+ UINTN CommSize;\r
+ UINT8 *CommBuffer;\r
+\r
+ SmmGetRuntimeCacheInfo = NULL;\r
+ CommBuffer = mVariableBuffer;\r
+\r
+ if (TotalHobStorageSize == NULL || TotalNvStorageSize == NULL || TotalVolatileStorageSize == NULL || AuthenticatedVariableUsage == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (CommBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);\r
+ ZeroMem (CommBuffer, CommSize);\r
+\r
+ SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) CommBuffer;\r
+ CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
+ SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);\r
+\r
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO;\r
+ SmmGetRuntimeCacheInfo = (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *) SmmVariableFunctionHeader->Data;\r
+\r
+ //\r
+ // Send data to SMM.\r
+ //\r
+ Status = mSmmCommunication->Communicate (mSmmCommunication, CommBuffer, &CommSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (CommSize <= SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
+ Status = EFI_BAD_BUFFER_SIZE;\r
+ goto Done;\r
+ }\r
+\r
+ Status = SmmVariableFunctionHeader->ReturnStatus;\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Get data from SMM.\r
+ //\r
+ *TotalHobStorageSize = SmmGetRuntimeCacheInfo->TotalHobStorageSize;\r
+ *TotalNvStorageSize = SmmGetRuntimeCacheInfo->TotalNvStorageSize;\r
+ *TotalVolatileStorageSize = SmmGetRuntimeCacheInfo->TotalVolatileStorageSize;\r
+ *AuthenticatedVariableUsage = SmmGetRuntimeCacheInfo->AuthenticatedVariableUsage;\r
+\r
+Done:\r
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+ return Status;\r
}\r
\r
+/**\r
+ Sends the runtime variable cache context information to SMM.\r
+\r
+ @retval EFI_SUCCESS Retrieved the size successfully.\r
+ @retval EFI_INVALID_PARAMETER TotalNvStorageSize parameter is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES The memory resources needed for a CommBuffer are not available.\r
+ @retval Others Could not retrieve the size successfully.;\r
+\r
+**/\r
+EFI_STATUS\r
+SendRuntimeVariableCacheContextToSmm (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *SmmRuntimeVarCacheContext;\r
+ EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;\r
+ SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
+ UINTN CommSize;\r
+ UINT8 *CommBuffer;\r
+\r
+ SmmRuntimeVarCacheContext = NULL;\r
+ CommBuffer = mVariableBuffer;\r
+\r
+ if (CommBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ AcquireLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+ //\r
+ // Init the communicate buffer. The buffer data size is:\r
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);\r
+ //\r
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);\r
+ ZeroMem (CommBuffer, CommSize);\r
+\r
+ SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) CommBuffer;\r
+ CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
+ SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);\r
+\r
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT;\r
+ SmmRuntimeVarCacheContext = (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *) SmmVariableFunctionHeader->Data;\r
+\r
+ SmmRuntimeVarCacheContext->RuntimeHobCache = mVariableRuntimeHobCacheBuffer;\r
+ SmmRuntimeVarCacheContext->RuntimeVolatileCache = mVariableRuntimeVolatileCacheBuffer;\r
+ SmmRuntimeVarCacheContext->RuntimeNvCache = mVariableRuntimeNvCacheBuffer;\r
+ SmmRuntimeVarCacheContext->PendingUpdate = &mVariableRuntimeCachePendingUpdate;\r
+ SmmRuntimeVarCacheContext->ReadLock = &mVariableRuntimeCacheReadLock;\r
+ SmmRuntimeVarCacheContext->HobFlushComplete = &mHobFlushComplete;\r
+\r
+ //\r
+ // Send data to SMM.\r
+ //\r
+ Status = mSmmCommunication->Communicate (mSmmCommunication, CommBuffer, &CommSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (CommSize <= SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
+ Status = EFI_BAD_BUFFER_SIZE;\r
+ goto Done;\r
+ }\r
+\r
+ Status = SmmVariableFunctionHeader->ReturnStatus;\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+Done:\r
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+ return Status;\r
+}\r
\r
/**\r
Initialize variable service and install Variable Architectural protocol.\r
\r
@param[in] Event Event whose notification function is being invoked.\r
@param[in] Context Pointer to the notification function's context.\r
- \r
+\r
**/\r
VOID\r
EFIAPI\r
{\r
EFI_STATUS Status;\r
\r
- Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);\r
+ Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **) &mSmmVariable);\r
if (EFI_ERROR (Status)) {\r
return;\r
}\r
- \r
+\r
Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);\r
ASSERT_EFI_ERROR (Status);\r
- \r
+\r
//\r
- // Allocate memory for variable store.\r
+ // Allocate memory for variable communicate buffer.\r
//\r
- mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
- mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));\r
+ Status = GetVariablePayloadSize (&mVariableBufferPayloadSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+ mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;\r
mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);\r
ASSERT (mVariableBuffer != NULL);\r
\r
//\r
mVariableBufferPhysical = mVariableBuffer;\r
\r
+ if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) {\r
+ DEBUG ((DEBUG_INFO, "Variable driver runtime cache is enabled.\n"));\r
+ //\r
+ // Allocate runtime variable cache memory buffers.\r
+ //\r
+ Status = GetRuntimeCacheInfo (\r
+ &mVariableRuntimeHobCacheBufferSize,\r
+ &mVariableRuntimeNvCacheBufferSize,\r
+ &mVariableRuntimeVolatileCacheBufferSize,\r
+ &mVariableAuthFormat\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = InitVariableCache (&mVariableRuntimeHobCacheBuffer, &mVariableRuntimeHobCacheBufferSize);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = InitVariableCache (&mVariableRuntimeNvCacheBuffer, &mVariableRuntimeNvCacheBufferSize);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = InitVariableCache (&mVariableRuntimeVolatileCacheBuffer, &mVariableRuntimeVolatileCacheBufferSize);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SendRuntimeVariableCacheContextToSmm ();\r
+ if (!EFI_ERROR (Status)) {\r
+ SyncRuntimeCache ();\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ mVariableRuntimeHobCacheBuffer = NULL;\r
+ mVariableRuntimeNvCacheBuffer = NULL;\r
+ mVariableRuntimeVolatileCacheBuffer = NULL;\r
+ }\r
+ }\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "Variable driver runtime cache is disabled.\n"));\r
+ }\r
+\r
gRT->GetVariable = RuntimeServiceGetVariable;\r
gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;\r
gRT->SetVariable = RuntimeServiceSetVariable;\r
gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;\r
- \r
+\r
//\r
// Install the Variable Architectural Protocol on a new handle.\r
//\r
Status = gBS->InstallProtocolInterface (\r
&mHandle,\r
- &gEfiVariableArchProtocolGuid, \r
+ &gEfiVariableArchProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
NULL\r
);\r
ASSERT_EFI_ERROR (Status);\r
+\r
+ mVariableLock.RequestToLock = VariableLockRequestToLock;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mHandle,\r
+ &gEdkiiVariableLockProtocolGuid,\r
+ &mVariableLock,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ mVarCheck.RegisterSetVariableCheckHandler = VarCheckRegisterSetVariableCheckHandler;\r
+ mVarCheck.VariablePropertySet = VarCheckVariablePropertySet;\r
+ mVarCheck.VariablePropertyGet = VarCheckVariablePropertyGet;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mHandle,\r
+ &gEdkiiVarCheckProtocolGuid,\r
+ &mVarCheck,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ gBS->CloseEvent (Event);\r
}\r
\r
\r
\r
@param[in] Event Event whose notification function is being invoked.\r
@param[in] Context Pointer to the notification function's context.\r
- \r
+\r
**/\r
VOID\r
EFIAPI\r
if (EFI_ERROR (Status)) {\r
return;\r
}\r
- \r
+\r
+ //\r
+ // Some Secure Boot Policy Var (SecureBoot, etc) updates following other\r
+ // Secure Boot Policy Variable change. Record their initial value.\r
+ //\r
+ RecordSecureBootPolicyVarData();\r
+\r
Status = gBS->InstallProtocolInterface (\r
&mHandle,\r
- &gEfiVariableWriteArchProtocolGuid, \r
+ &gEfiVariableWriteArchProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
NULL\r
);\r
- ASSERT_EFI_ERROR (Status); \r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ gBS->CloseEvent (Event);\r
}\r
\r
\r
/**\r
Variable Driver main entry point. The Variable driver places the 4 EFI\r
- runtime services in the EFI System Table and installs arch protocols \r
+ runtime services in the EFI System Table and installs arch protocols\r
for variable read and write services being available. It also registers\r
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
@param[in] SystemTable A pointer to the EFI System Table.\r
- \r
+\r
@retval EFI_SUCCESS Variable service successfully initialized.\r
\r
**/\r
VOID *SmmVariableWriteRegistration;\r
EFI_EVENT OnReadyToBootEvent;\r
EFI_EVENT ExitBootServiceEvent;\r
+ EFI_EVENT LegacyBootEvent;\r
\r
EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);\r
\r
// Smm variable service is ready\r
//\r
EfiCreateProtocolNotifyEvent (\r
- &gEfiSmmVariableProtocolGuid, \r
- TPL_CALLBACK, \r
- SmmVariableReady, \r
- NULL, \r
+ &gEfiSmmVariableProtocolGuid,\r
+ TPL_CALLBACK,\r
+ SmmVariableReady,\r
+ NULL,\r
&SmmVariableRegistration\r
);\r
\r
// Smm Non-Volatile variable write service is ready\r
//\r
EfiCreateProtocolNotifyEvent (\r
- &gSmmVariableWriteGuid, \r
- TPL_CALLBACK, \r
- SmmVariableWriteReady, \r
- NULL, \r
+ &gSmmVariableWriteGuid,\r
+ TPL_CALLBACK,\r
+ SmmVariableWriteReady,\r
+ NULL,\r
&SmmVariableWriteRegistration\r
);\r
\r
// Register the event to reclaim variable for OS usage.\r
//\r
EfiCreateEventReadyToBootEx (\r
- TPL_NOTIFY, \r
- OnReadyToBoot, \r
- NULL, \r
+ TPL_NOTIFY,\r
+ OnReadyToBoot,\r
+ NULL,\r
&OnReadyToBootEvent\r
- ); \r
+ );\r
\r
//\r
// Register the event to inform SMM variable that it is at runtime.\r
NULL,\r
&gEfiEventExitBootServicesGuid,\r
&ExitBootServiceEvent\r
- ); \r
+ );\r
+\r
+ //\r
+ // Register the event to inform SMM variable that it is at runtime for legacy boot.\r
+ // Reuse OnExitBootServices() here.\r
+ //\r
+ EfiCreateEventLegacyBootEx(\r
+ TPL_NOTIFY,\r
+ OnExitBootServices,\r
+ NULL,\r
+ &LegacyBootEvent\r
+ );\r
\r
//\r
// Register the event to convert the pointer for runtime.\r
&gEfiEventVirtualAddressChangeGuid,\r
&mVirtualAddressChangeEvent\r
);\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r