#include <Guid/SmmVariableCommon.h>\r
#include "Variable.h"\r
#include "VariableParsing.h"\r
+#include "VariableRuntimeCache.h"\r
+\r
+extern VARIABLE_STORE_HEADER *mNvVariableCache;\r
\r
BOOLEAN mAtRuntime = FALSE;\r
UINT8 *mVariableBufferPayload = NULL;\r
EFI_STATUS\r
EFIAPI\r
SmmVariableHandler (\r
- IN EFI_HANDLE DispatchHandle,\r
- IN CONST VOID *RegisterContext,\r
- IN OUT VOID *CommBuffer,\r
- IN OUT UINTN *CommBufferSize\r
+ IN EFI_HANDLE DispatchHandle,\r
+ IN CONST VOID *RegisterContext,\r
+ IN OUT VOID *CommBuffer,\r
+ IN OUT UINTN *CommBufferSize\r
)\r
{\r
- EFI_STATUS Status;\r
- SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
- SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
- SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;\r
- SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;\r
- SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *GetPayloadSize;\r
- VARIABLE_INFO_ENTRY *VariableInfo;\r
- SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
- SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
- UINTN InfoSize;\r
- UINTN NameBufferSize;\r
- UINTN CommBufferPayloadSize;\r
- UINTN TempCommBufferSize;\r
+ EFI_STATUS Status;\r
+ SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;\r
+ SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;\r
+ SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;\r
+ SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;\r
+ SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *GetPayloadSize;\r
+ SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *RuntimeVariableCacheContext;\r
+ SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *GetRuntimeCacheInfo;\r
+ SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
+ SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
+ VARIABLE_INFO_ENTRY *VariableInfo;\r
+ VARIABLE_RUNTIME_CACHE_CONTEXT *VariableCacheContext;\r
+ VARIABLE_STORE_HEADER *VariableCache;\r
+ UINTN InfoSize;\r
+ UINTN NameBufferSize;\r
+ UINTN CommBufferPayloadSize;\r
+ UINTN TempCommBufferSize;\r
\r
//\r
// If input is invalid, stop processing this SMI\r
);\r
CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
break;\r
+ case SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT:\r
+ if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT)) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: SMM communication buffer size invalid!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+ if (mEndOfDxe) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Cannot init context after end of DXE!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+\r
+ //\r
+ // Copy the input communicate buffer payload to the pre-allocated SMM variable payload buffer.\r
+ //\r
+ CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
+ RuntimeVariableCacheContext = (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *) mVariableBufferPayload;\r
+\r
+ //\r
+ // Verify required runtime cache buffers are provided.\r
+ //\r
+ if (RuntimeVariableCacheContext->RuntimeVolatileCache == NULL ||\r
+ RuntimeVariableCacheContext->RuntimeNvCache == NULL ||\r
+ RuntimeVariableCacheContext->PendingUpdate == NULL ||\r
+ RuntimeVariableCacheContext->ReadLock == NULL ||\r
+ RuntimeVariableCacheContext->HobFlushComplete == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Required runtime cache buffer is NULL!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+\r
+ //\r
+ // Verify minimum size requirements for the runtime variable store buffers.\r
+ //\r
+ if ((RuntimeVariableCacheContext->RuntimeHobCache != NULL &&\r
+ RuntimeVariableCacheContext->RuntimeHobCache->Size < sizeof (VARIABLE_STORE_HEADER)) ||\r
+ RuntimeVariableCacheContext->RuntimeVolatileCache->Size < sizeof (VARIABLE_STORE_HEADER) ||\r
+ RuntimeVariableCacheContext->RuntimeNvCache->Size < sizeof (VARIABLE_STORE_HEADER)) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: A runtime cache buffer size is invalid!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+\r
+ //\r
+ // Verify runtime buffers do not overlap with SMRAM ranges.\r
+ //\r
+ if (RuntimeVariableCacheContext->RuntimeHobCache != NULL &&\r
+ !VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN) RuntimeVariableCacheContext->RuntimeHobCache,\r
+ (UINTN) RuntimeVariableCacheContext->RuntimeHobCache->Size)) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime HOB cache buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN) RuntimeVariableCacheContext->RuntimeVolatileCache,\r
+ (UINTN) RuntimeVariableCacheContext->RuntimeVolatileCache->Size)) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime volatile cache buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN) RuntimeVariableCacheContext->RuntimeNvCache,\r
+ (UINTN) RuntimeVariableCacheContext->RuntimeNvCache->Size)) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime non-volatile cache buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN) RuntimeVariableCacheContext->PendingUpdate,\r
+ sizeof (*(RuntimeVariableCacheContext->PendingUpdate)))) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime cache pending update buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN) RuntimeVariableCacheContext->ReadLock,\r
+ sizeof (*(RuntimeVariableCacheContext->ReadLock)))) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime cache read lock buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN) RuntimeVariableCacheContext->HobFlushComplete,\r
+ sizeof (*(RuntimeVariableCacheContext->HobFlushComplete)))) {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime cache HOB flush complete buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+\r
+ VariableCacheContext = &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext;\r
+ VariableCacheContext->VariableRuntimeHobCache.Store = RuntimeVariableCacheContext->RuntimeHobCache;\r
+ VariableCacheContext->VariableRuntimeVolatileCache.Store = RuntimeVariableCacheContext->RuntimeVolatileCache;\r
+ VariableCacheContext->VariableRuntimeNvCache.Store = RuntimeVariableCacheContext->RuntimeNvCache;\r
+ VariableCacheContext->PendingUpdate = RuntimeVariableCacheContext->PendingUpdate;\r
+ VariableCacheContext->ReadLock = RuntimeVariableCacheContext->ReadLock;\r
+ VariableCacheContext->HobFlushComplete = RuntimeVariableCacheContext->HobFlushComplete;\r
+\r
+ // Set up the intial pending request since the RT cache needs to be in sync with SMM cache\r
+ VariableCacheContext->VariableRuntimeHobCache.PendingUpdateOffset = 0;\r
+ VariableCacheContext->VariableRuntimeHobCache.PendingUpdateLength = 0;\r
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase > 0 &&\r
+ VariableCacheContext->VariableRuntimeHobCache.Store != NULL) {\r
+ VariableCache = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;\r
+ VariableCacheContext->VariableRuntimeHobCache.PendingUpdateLength = (UINT32) ((UINTN) GetEndPointer (VariableCache) - (UINTN) VariableCache);\r
+ CopyGuid (&(VariableCacheContext->VariableRuntimeHobCache.Store->Signature), &(VariableCache->Signature));\r
+ }\r
+ VariableCache = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;\r
+ VariableCacheContext->VariableRuntimeVolatileCache.PendingUpdateOffset = 0;\r
+ VariableCacheContext->VariableRuntimeVolatileCache.PendingUpdateLength = (UINT32) ((UINTN) GetEndPointer (VariableCache) - (UINTN) VariableCache);\r
+ CopyGuid (&(VariableCacheContext->VariableRuntimeVolatileCache.Store->Signature), &(VariableCache->Signature));\r
+\r
+ VariableCache = (VARIABLE_STORE_HEADER *) (UINTN) mNvVariableCache;\r
+ VariableCacheContext->VariableRuntimeNvCache.PendingUpdateOffset = 0;\r
+ VariableCacheContext->VariableRuntimeNvCache.PendingUpdateLength = (UINT32) ((UINTN) GetEndPointer (VariableCache) - (UINTN) VariableCache);\r
+ CopyGuid (&(VariableCacheContext->VariableRuntimeNvCache.Store->Signature), &(VariableCache->Signature));\r
+\r
+ *(VariableCacheContext->PendingUpdate) = TRUE;\r
+ *(VariableCacheContext->ReadLock) = FALSE;\r
+ *(VariableCacheContext->HobFlushComplete) = FALSE;\r
+\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ case SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE:\r
+ Status = FlushPendingRuntimeVariableCacheUpdates ();\r
+ break;\r
+ case SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO:\r
+ if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO)) {\r
+ DEBUG ((DEBUG_ERROR, "GetRuntimeCacheInfo: SMM communication buffer size invalid!\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
+ GetRuntimeCacheInfo = (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *) SmmVariableFunctionHeader->Data;\r
+\r
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase > 0) {\r
+ VariableCache = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;\r
+ GetRuntimeCacheInfo->TotalHobStorageSize = VariableCache->Size;\r
+ } else {\r
+ GetRuntimeCacheInfo->TotalHobStorageSize = 0;\r
+ }\r
+\r
+ VariableCache = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;\r
+ GetRuntimeCacheInfo->TotalVolatileStorageSize = VariableCache->Size;\r
+ VariableCache = (VARIABLE_STORE_HEADER *) (UINTN) mNvVariableCache;\r
+ GetRuntimeCacheInfo->TotalNvStorageSize = (UINTN) VariableCache->Size;\r
+ GetRuntimeCacheInfo->AuthenticatedVariableUsage = mVariableModuleGlobal->VariableGlobal.AuthFormat;\r
+\r
+ Status = EFI_SUCCESS;\r
+ break;\r
\r
default:\r
Status = EFI_UNSUPPORTED;\r