\r
InitCommunicateBuffer() is really function to check the variable data size.\r
\r
-Copyright (c) 2010 - 2017, 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
-\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
+Copyright (c) Microsoft Corporation.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
#include <PiDxe.h>\r
#include <Guid/EventGroup.h>\r
#include <Guid/SmmVariableCommon.h>\r
\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
- SecureBoot Hook for SetVariable.\r
-\r
- @param[in] VariableName Name of Variable to be found.\r
- @param[in] VendorGuid Variable vendor GUID.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SecureBootHook (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid\r
- );\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
\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
}\r
\r
/**\r
- This code finds variable in storage blocks (Volatile or Non-Volatile).\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
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_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
+ ZeroMem (&RtPtrTrack, sizeof (RtPtrTrack));\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
+ *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
+ if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {\r
+ if (Attributes != NULL && RtPtrTrack.CurrPtr != NULL) {\r
+ *Attributes = RtPtrTrack.CurrPtr->Attributes;\r
+ }\r
+ }\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
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_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
\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
+ ASSERT (!mVariableRuntimeCacheReadLock);\r
+\r
+ CheckForRuntimeCacheSync ();\r
+\r
+ mVariableRuntimeCacheReadLock = TRUE;\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
+ 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
+ mVariableRuntimeCacheReadLock = FALSE;\r
+\r
+ return Status;\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
UINTN OutVariableNameSize;\r
UINTN InVariableNameSize;\r
\r
- if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
OutVariableNameSize = *VariableNameSize;\r
InVariableNameSize = StrSize (VariableName);\r
SmmGetNextVariableName = 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 + PayloadSize.\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
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
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
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
{\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
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