VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),\r
SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
\r
-Copyright (c) 2010 - 2015, 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) 2018, Linaro, Ltd. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <Protocol/SmmVariable.h>\r
#include <Protocol/SmmFirmwareVolumeBlock.h>\r
#include <Protocol/SmmFaultTolerantWrite.h>\r
-#include <Protocol/SmmEndOfDxe.h>\r
+#include <Protocol/MmEndOfDxe.h>\r
#include <Protocol/SmmVarCheck.h>\r
\r
-#include <Library/SmmServicesTableLib.h>\r
-#include <Library/SmmMemLib.h>\r
+#include <Library/MmServicesTableLib.h>\r
+#include <Library/VariablePolicyLib.h>\r
\r
#include <Guid/SmmVariableCommon.h>\r
-#include <Guid/ZeroGuid.h>\r
#include "Variable.h"\r
+#include "VariableParsing.h"\r
+#include "VariableRuntimeCache.h"\r
+\r
+extern VARIABLE_STORE_HEADER *mNvVariableCache;\r
\r
-extern VARIABLE_INFO_ENTRY *gVariableInfo;\r
-EFI_HANDLE mSmmVariableHandle = NULL;\r
-EFI_HANDLE mVariableHandle = NULL;\r
-BOOLEAN mAtRuntime = FALSE;\r
-UINT8 *mVariableBufferPayload = NULL;\r
-UINTN mVariableBufferPayloadSize;\r
-extern BOOLEAN mEndOfDxe;\r
-extern VAR_CHECK_REQUEST_SOURCE mRequestSource;\r
+BOOLEAN mAtRuntime = FALSE;\r
+UINT8 *mVariableBufferPayload = NULL;\r
+UINTN mVariableBufferPayloadSize;\r
\r
/**\r
SecureBoot Hook for SetVariable.\r
VOID\r
EFIAPI\r
SecureBootHook (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid\r
)\r
{\r
- return ;\r
+ return;\r
}\r
\r
/**\r
EFI_STATUS\r
EFIAPI\r
SmmVariableSetVariable (\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid,\r
- IN UINT32 Attributes,\r
- IN UINTN DataSize,\r
- IN VOID *Data\r
+ IN CHAR16 *VariableName,\r
+ IN EFI_GUID *VendorGuid,\r
+ IN UINT32 Attributes,\r
+ IN UINTN DataSize,\r
+ IN VOID *Data\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
//\r
// Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.\r
return Status;\r
}\r
\r
-EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {\r
+EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {\r
VariableServiceGetVariable,\r
VariableServiceGetNextVariableName,\r
SmmVariableSetVariable,\r
VariableServiceQueryVariableInfo\r
};\r
\r
-EDKII_SMM_VAR_CHECK_PROTOCOL mSmmVarCheck = { VarCheckRegisterSetVariableCheckHandler,\r
- VarCheckVariablePropertySet,\r
- VarCheckVariablePropertyGet };\r
+EDKII_SMM_VAR_CHECK_PROTOCOL mSmmVarCheck = {\r
+ VarCheckRegisterSetVariableCheckHandler,\r
+ VarCheckVariablePropertySet,\r
+ VarCheckVariablePropertyGet\r
+};\r
\r
/**\r
Return TRUE if ExitBootServices () has been called.\r
**/\r
EFI_LOCK *\r
InitializeLock (\r
- IN OUT EFI_LOCK *Lock,\r
- IN EFI_TPL Priority\r
+ IN OUT EFI_LOCK *Lock,\r
+ IN EFI_TPL Priority\r
)\r
{\r
return Lock;\r
**/\r
VOID\r
AcquireLockOnlyAtBootTime (\r
- IN EFI_LOCK *Lock\r
+ IN EFI_LOCK *Lock\r
)\r
{\r
-\r
}\r
\r
-\r
/**\r
Releases lock only at boot time. Simply returns at runtime.\r
\r
**/\r
VOID\r
ReleaseLockOnlyAtBootTime (\r
- IN EFI_LOCK *Lock\r
+ IN EFI_LOCK *Lock\r
)\r
{\r
-\r
}\r
\r
/**\r
- Retrive the SMM Fault Tolerent Write protocol interface.\r
+ Retrieve the SMM Fault Tolerent Write protocol interface.\r
\r
@param[out] FtwProtocol The interface of SMM Ftw protocol\r
\r
**/\r
EFI_STATUS\r
GetFtwProtocol (\r
- OUT VOID **FtwProtocol\r
+ OUT VOID **FtwProtocol\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
//\r
// Locate Smm Fault Tolerent Write protocol\r
//\r
- Status = gSmst->SmmLocateProtocol (\r
+ Status = gMmst->MmLocateProtocol (\r
&gEfiSmmFaultTolerantWriteProtocolGuid,\r
NULL,\r
FtwProtocol\r
return Status;\r
}\r
\r
-\r
/**\r
- Retrive the SMM FVB protocol interface by HANDLE.\r
+ Retrieve the SMM FVB protocol interface by HANDLE.\r
\r
@param[in] FvBlockHandle The handle of SMM FVB protocol that provides services for\r
reading, writing, and erasing the target block.\r
//\r
// To get the SMM FVB protocol interface on the handle\r
//\r
- return gSmst->SmmHandleProtocol (\r
+ return gMmst->MmHandleProtocol (\r
FvBlockHandle,\r
&gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
- (VOID **) FvBlock\r
+ (VOID **)FvBlock\r
);\r
}\r
\r
-\r
/**\r
Function returns an array of handles that support the SMM FVB protocol\r
in a buffer allocated from pool.\r
**/\r
EFI_STATUS\r
GetFvbCountAndBuffer (\r
- OUT UINTN *NumberHandles,\r
- OUT EFI_HANDLE **Buffer\r
+ OUT UINTN *NumberHandles,\r
+ OUT EFI_HANDLE **Buffer\r
)\r
{\r
- EFI_STATUS Status;\r
- UINTN BufferSize;\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
\r
if ((NumberHandles == NULL) || (Buffer == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
BufferSize = 0;\r
*NumberHandles = 0;\r
*Buffer = NULL;\r
- Status = gSmst->SmmLocateHandle (\r
- ByProtocol,\r
- &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
- NULL,\r
- &BufferSize,\r
- *Buffer\r
- );\r
- if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+ Status = gMmst->MmLocateHandle (\r
+ ByProtocol,\r
+ &gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
+ NULL,\r
+ &BufferSize,\r
+ *Buffer\r
+ );\r
+ if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
return EFI_NOT_FOUND;\r
}\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Status = gSmst->SmmLocateHandle (\r
+ Status = gMmst->MmLocateHandle (\r
ByProtocol,\r
&gEfiSmmFirmwareVolumeBlockProtocolGuid,\r
NULL,\r
*Buffer\r
);\r
\r
- *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
- if (EFI_ERROR(Status)) {\r
+ *NumberHandles = BufferSize / sizeof (EFI_HANDLE);\r
+ if (EFI_ERROR (Status)) {\r
*NumberHandles = 0;\r
FreePool (*Buffer);\r
*Buffer = NULL;\r
return Status;\r
}\r
\r
-\r
/**\r
Get the variable statistics information from the information buffer pointed by gVariableInfo.\r
\r
**/\r
EFI_STATUS\r
SmmVariableGetStatistics (\r
- IN OUT VARIABLE_INFO_ENTRY *InfoEntry,\r
- IN OUT UINTN *InfoSize\r
+ IN OUT VARIABLE_INFO_ENTRY *InfoEntry,\r
+ IN OUT UINTN *InfoSize\r
)\r
{\r
- VARIABLE_INFO_ENTRY *VariableInfo;\r
- UINTN NameLength;\r
- UINTN StatisticsInfoSize;\r
- CHAR16 *InfoName;\r
- EFI_GUID VendorGuid;\r
+ VARIABLE_INFO_ENTRY *VariableInfo;\r
+ UINTN NameSize;\r
+ UINTN StatisticsInfoSize;\r
+ CHAR16 *InfoName;\r
+ UINTN InfoNameMaxSize;\r
+ EFI_GUID VendorGuid;\r
\r
if (InfoEntry == NULL) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_UNSUPPORTED;\r
}\r
\r
- StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);\r
+ StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY);\r
if (*InfoSize < StatisticsInfoSize) {\r
*InfoSize = StatisticsInfoSize;\r
return EFI_BUFFER_TOO_SMALL;\r
}\r
- InfoName = (CHAR16 *)(InfoEntry + 1);\r
+\r
+ InfoName = (CHAR16 *)(InfoEntry + 1);\r
+ InfoNameMaxSize = (*InfoSize - sizeof (VARIABLE_INFO_ENTRY));\r
\r
CopyGuid (&VendorGuid, &InfoEntry->VendorGuid);\r
\r
- if (CompareGuid (&VendorGuid, &gZeroGuid)) {\r
+ if (IsZeroGuid (&VendorGuid)) {\r
//\r
// Return the first variable info\r
//\r
+ NameSize = StrSize (VariableInfo->Name);\r
+ StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize;\r
+ if (*InfoSize < StatisticsInfoSize) {\r
+ *InfoSize = StatisticsInfoSize;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
- CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
+ CopyMem (InfoName, VariableInfo->Name, NameSize);\r
*InfoSize = StatisticsInfoSize;\r
return EFI_SUCCESS;\r
}\r
//\r
while (VariableInfo != NULL) {\r
if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) {\r
- NameLength = StrSize (VariableInfo->Name);\r
- if (NameLength == StrSize (InfoName)) {\r
- if (CompareMem (VariableInfo->Name, InfoName, NameLength) == 0) {\r
+ NameSize = StrSize (VariableInfo->Name);\r
+ if (NameSize <= InfoNameMaxSize) {\r
+ if (CompareMem (VariableInfo->Name, InfoName, NameSize) == 0) {\r
//\r
// Find the match one\r
//\r
}\r
}\r
}\r
+\r
VariableInfo = VariableInfo->Next;\r
- };\r
+ }\r
\r
if (VariableInfo == NULL) {\r
*InfoSize = 0;\r
//\r
// Output the new variable info\r
//\r
- StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);\r
+ NameSize = StrSize (VariableInfo->Name);\r
+ StatisticsInfoSize = sizeof (VARIABLE_INFO_ENTRY) + NameSize;\r
if (*InfoSize < StatisticsInfoSize) {\r
*InfoSize = StatisticsInfoSize;\r
return EFI_BUFFER_TOO_SMALL;\r
}\r
\r
CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
- CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
+ CopyMem (InfoName, VariableInfo->Name, NameSize);\r
*InfoSize = StatisticsInfoSize;\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Communication service SMI Handler entry.\r
\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
- if (CommBuffer == NULL || CommBufferSize == NULL) {\r
+ if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {\r
return EFI_SUCCESS;\r
}\r
\r
TempCommBufferSize = *CommBufferSize;\r
\r
if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {\r
- DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));\r
+ DEBUG ((DEBUG_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
+\r
CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
if (CommBufferPayloadSize > mVariableBufferPayloadSize) {\r
- DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));\r
+ DEBUG ((DEBUG_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
\r
- if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
- DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
+ if (!VariableSmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {\r
+ DEBUG ((DEBUG_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));\r
return EFI_SUCCESS;\r
}\r
\r
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;\r
switch (SmmVariableFunctionHeader->Function) {\r
case SMM_VARIABLE_FUNCTION_GET_VARIABLE:\r
- if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
- DEBUG ((EFI_D_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));\r
+ if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
+ DEBUG ((DEBUG_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
+\r
//\r
// Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
//\r
CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
- SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;\r
- if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
- ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {\r
+ SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)mVariableBufferPayload;\r
+ if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
+ ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize))\r
+ {\r
//\r
// Prevent InfoSize overflow happen\r
//\r
Status = EFI_ACCESS_DENIED;\r
goto EXIT;\r
}\r
- InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
+\r
+ InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
+ SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
\r
//\r
// SMRAM range check already covered before\r
//\r
if (InfoSize > CommBufferPayloadSize) {\r
- DEBUG ((EFI_D_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));\r
+ DEBUG ((DEBUG_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));\r
Status = EFI_ACCESS_DENIED;\r
goto EXIT;\r
}\r
\r
- if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
+ //\r
+ // The VariableSpeculationBarrier() call here is to ensure the previous\r
+ // range/content checks for the CommBuffer have been completed before the\r
+ // subsequent consumption of the CommBuffer content.\r
+ //\r
+ VariableSpeculationBarrier ();\r
+ if ((SmmVariableHeader->NameSize < sizeof (CHAR16)) || (SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0')) {\r
//\r
// Make sure VariableName is A Null-terminated string.\r
//\r
break;\r
\r
case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:\r
- if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
- DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));\r
+ if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
+ DEBUG ((DEBUG_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
+\r
//\r
// Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
//\r
CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
- GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) mVariableBufferPayload;\r
- if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
+ GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *)mVariableBufferPayload;\r
+ if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
//\r
// Prevent InfoSize overflow happen\r
//\r
Status = EFI_ACCESS_DENIED;\r
goto EXIT;\r
}\r
- InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;\r
+\r
+ InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;\r
\r
//\r
// SMRAM range check already covered before\r
//\r
if (InfoSize > CommBufferPayloadSize) {\r
- DEBUG ((EFI_D_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));\r
+ DEBUG ((DEBUG_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));\r
Status = EFI_ACCESS_DENIED;\r
goto EXIT;\r
}\r
\r
- NameBufferSize = CommBufferPayloadSize - OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
- if (NameBufferSize < sizeof (CHAR16) || GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0') {\r
+ NameBufferSize = CommBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);\r
+ if ((NameBufferSize < sizeof (CHAR16)) || (GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0')) {\r
//\r
// Make sure input VariableName is A Null-terminated string.\r
//\r
break;\r
\r
case SMM_VARIABLE_FUNCTION_SET_VARIABLE:\r
- if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
- DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));\r
+ if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
+ DEBUG ((DEBUG_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
+\r
//\r
// Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
//\r
CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
- SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;\r
- if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
- ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {\r
+ SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)mVariableBufferPayload;\r
+ if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||\r
+ ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize))\r
+ {\r
//\r
// Prevent InfoSize overflow happen\r
//\r
Status = EFI_ACCESS_DENIED;\r
goto EXIT;\r
}\r
- InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
+\r
+ InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
+ SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
\r
//\r
// Data buffer should not contain SMM range\r
//\r
if (InfoSize > CommBufferPayloadSize) {\r
- DEBUG ((EFI_D_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));\r
+ DEBUG ((DEBUG_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));\r
Status = EFI_ACCESS_DENIED;\r
goto EXIT;\r
}\r
\r
- if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
+ //\r
+ // The VariableSpeculationBarrier() call here is to ensure the previous\r
+ // range/content checks for the CommBuffer have been completed before the\r
+ // subsequent consumption of the CommBuffer content.\r
+ //\r
+ VariableSpeculationBarrier ();\r
+ if ((SmmVariableHeader->NameSize < sizeof (CHAR16)) || (SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0')) {\r
//\r
// Make sure VariableName is A Null-terminated string.\r
//\r
\r
case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:\r
if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {\r
- DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));\r
+ DEBUG ((DEBUG_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
- QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;\r
+\r
+ QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *)SmmVariableFunctionHeader->Data;\r
\r
Status = VariableServiceQueryVariableInfo (\r
QueryVariableInfo->Attributes,\r
\r
case SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE:\r
if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE)) {\r
- DEBUG ((EFI_D_ERROR, "GetPayloadSize: SMM communication buffer size invalid!\n"));\r
+ DEBUG ((DEBUG_ERROR, "GetPayloadSize: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
- GetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;\r
+\r
+ GetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *)SmmVariableFunctionHeader->Data;\r
GetPayloadSize->VariablePayloadSize = mVariableBufferPayloadSize;\r
- Status = EFI_SUCCESS;\r
+ Status = EFI_SUCCESS;\r
break;\r
\r
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:\r
- if (AtRuntime()) {\r
+ if (AtRuntime ()) {\r
Status = EFI_UNSUPPORTED;\r
break;\r
}\r
+\r
if (!mEndOfDxe) {\r
+ MorLockInitAtEndOfDxe ();\r
+ Status = LockVariablePolicy ();\r
+ ASSERT_EFI_ERROR (Status);\r
mEndOfDxe = TRUE;\r
VarCheckLibInitializeAtEndOfDxe (NULL);\r
//\r
//\r
InitializeVariableQuota ();\r
}\r
+\r
ReclaimForOS ();\r
Status = EFI_SUCCESS;\r
break;\r
\r
case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE:\r
mAtRuntime = TRUE;\r
- Status = EFI_SUCCESS;\r
+ Status = EFI_SUCCESS;\r
break;\r
\r
case SMM_VARIABLE_FUNCTION_GET_STATISTICS:\r
- VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;\r
- InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
+ VariableInfo = (VARIABLE_INFO_ENTRY *)SmmVariableFunctionHeader->Data;\r
+ InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
\r
//\r
// Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.\r
// It is covered by previous CommBuffer check\r
//\r
\r
- if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {\r
- DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));\r
- Status = EFI_ACCESS_DENIED;\r
- goto EXIT;\r
- }\r
+ //\r
+ // Do not need to check CommBufferSize buffer as it should point to SMRAM\r
+ // that was used by SMM core to cache CommSize from SmmCommunication protocol.\r
+ //\r
\r
- Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);\r
+ Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);\r
*CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
break;\r
\r
if (mEndOfDxe) {\r
Status = EFI_ACCESS_DENIED;\r
} else {\r
- VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;\r
- Status = VariableLockRequestToLock (\r
- NULL,\r
- VariableToLock->Name,\r
- &VariableToLock->Guid\r
- );\r
+ VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *)SmmVariableFunctionHeader->Data;\r
+ Status = VariableLockRequestToLock (\r
+ NULL,\r
+ VariableToLock->Name,\r
+ &VariableToLock->Guid\r
+ );\r
}\r
+\r
break;\r
case SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET:\r
if (mEndOfDxe) {\r
Status = EFI_ACCESS_DENIED;\r
} else {\r
- CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *) SmmVariableFunctionHeader->Data;\r
- Status = VarCheckVariablePropertySet (\r
- CommVariableProperty->Name,\r
- &CommVariableProperty->Guid,\r
- &CommVariableProperty->VariableProperty\r
- );\r
+ CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *)SmmVariableFunctionHeader->Data;\r
+ Status = VarCheckVariablePropertySet (\r
+ CommVariableProperty->Name,\r
+ &CommVariableProperty->Guid,\r
+ &CommVariableProperty->VariableProperty\r
+ );\r
}\r
+\r
break;\r
case SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET:\r
if (CommBufferPayloadSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
- DEBUG ((EFI_D_ERROR, "VarCheckVariablePropertyGet: SMM communication buffer size invalid!\n"));\r
+ DEBUG ((DEBUG_ERROR, "VarCheckVariablePropertyGet: SMM communication buffer size invalid!\n"));\r
return EFI_SUCCESS;\r
}\r
+\r
//\r
// Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.\r
//\r
CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);\r
- CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *) mVariableBufferPayload;\r
- if ((UINTN) (~0) - CommVariableProperty->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
+ CommVariableProperty = (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *)mVariableBufferPayload;\r
+ if ((UINTN)(~0) - CommVariableProperty->NameSize < OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name)) {\r
//\r
// Prevent InfoSize overflow happen\r
//\r
Status = EFI_ACCESS_DENIED;\r
goto EXIT;\r
}\r
+\r
InfoSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) + CommVariableProperty->NameSize;\r
\r
//\r
// SMRAM range check already covered before\r
//\r
if (InfoSize > CommBufferPayloadSize) {\r
- DEBUG ((EFI_D_ERROR, "VarCheckVariablePropertyGet: Data size exceed communication buffer size limit!\n"));\r
+ DEBUG ((DEBUG_ERROR, "VarCheckVariablePropertyGet: Data size exceed communication buffer size limit!\n"));\r
Status = EFI_ACCESS_DENIED;\r
goto EXIT;\r
}\r
\r
- if (CommVariableProperty->NameSize < sizeof (CHAR16) || CommVariableProperty->Name[CommVariableProperty->NameSize/sizeof (CHAR16) - 1] != L'\0') {\r
+ //\r
+ // The VariableSpeculationBarrier() call here is to ensure the previous\r
+ // range/content checks for the CommBuffer have been completed before the\r
+ // subsequent consumption of the CommBuffer content.\r
+ //\r
+ VariableSpeculationBarrier ();\r
+ if ((CommVariableProperty->NameSize < sizeof (CHAR16)) || (CommVariableProperty->Name[CommVariableProperty->NameSize/sizeof (CHAR16) - 1] != L'\0')) {\r
//\r
// Make sure VariableName is A Null-terminated string.\r
//\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
+\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
+ {\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
+ {\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
+ ))\r
+ {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime HOB cache buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN)RuntimeVariableCacheContext->RuntimeVolatileCache,\r
+ (UINTN)RuntimeVariableCacheContext->RuntimeVolatileCache->Size\r
+ ))\r
+ {\r
+ DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: Runtime volatile cache buffer in SMRAM or overflow!\n"));\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto EXIT;\r
+ }\r
+\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN)RuntimeVariableCacheContext->RuntimeNvCache,\r
+ (UINTN)RuntimeVariableCacheContext->RuntimeNvCache->Size\r
+ ))\r
+ {\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
+\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN)RuntimeVariableCacheContext->PendingUpdate,\r
+ sizeof (*(RuntimeVariableCacheContext->PendingUpdate))\r
+ ))\r
+ {\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
+\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN)RuntimeVariableCacheContext->ReadLock,\r
+ sizeof (*(RuntimeVariableCacheContext->ReadLock))\r
+ ))\r
+ {\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
+\r
+ if (!VariableSmmIsBufferOutsideSmmValid (\r
+ (UINTN)RuntimeVariableCacheContext->HobFlushComplete,\r
+ sizeof (*(RuntimeVariableCacheContext->HobFlushComplete))\r
+ ))\r
+ {\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
+ {\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
+\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
+\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
EFI_STATUS\r
EFIAPI\r
SmmEndOfDxeCallback (\r
- IN CONST EFI_GUID *Protocol,\r
- IN VOID *Interface,\r
- IN EFI_HANDLE Handle\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
)\r
{\r
- DEBUG ((EFI_D_INFO, "[Variable]SMM_END_OF_DXE is signaled\n"));\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((DEBUG_INFO, "[Variable]SMM_END_OF_DXE is signaled\n"));\r
+ MorLockInitAtEndOfDxe ();\r
+ Status = LockVariablePolicy ();\r
+ ASSERT_EFI_ERROR (Status);\r
mEndOfDxe = TRUE;\r
VarCheckLibInitializeAtEndOfDxe (NULL);\r
//\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Initializes variable write service for SMM.\r
+\r
+**/\r
+VOID\r
+VariableWriteServiceInitializeSmm (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = VariableWriteServiceInitialize ();\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));\r
+ }\r
+\r
+ //\r
+ // Notify the variable wrapper driver the variable write service is ready\r
+ //\r
+ VariableNotifySmmWriteReady ();\r
+}\r
+\r
/**\r
SMM Fault Tolerant Write protocol notification event handler.\r
\r
EFI_STATUS\r
EFIAPI\r
SmmFtwNotificationEvent (\r
- IN CONST EFI_GUID *Protocol,\r
- IN VOID *Interface,\r
- IN EFI_HANDLE Handle\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS VariableStoreBase;\r
EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;\r
EFI_PHYSICAL_ADDRESS NvStorageVariableBase;\r
ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);\r
}\r
\r
+ NvStorageVariableBase = NV_STORAGE_VARIABLE_BASE;\r
+ VariableStoreBase = NvStorageVariableBase + mNvFvHeaderCache->HeaderLength;\r
+\r
+ //\r
+ // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.\r
+ //\r
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
+\r
//\r
// Find the proper FVB protocol for variable.\r
//\r
- NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
- if (NvStorageVariableBase == 0) {\r
- NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
- }\r
Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);\r
if (EFI_ERROR (Status)) {\r
return EFI_NOT_FOUND;\r
\r
mVariableModuleGlobal->FvbInstance = FvbProtocol;\r
\r
- Status = VariableWriteServiceInitialize ();\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));\r
- }\r
-\r
//\r
- // Notify the variable wrapper driver the variable write service is ready\r
+ // Initializes variable write service after FTW was ready.\r
//\r
- Status = gBS->InstallProtocolInterface (\r
- &mSmmVariableHandle,\r
- &gSmmVariableWriteGuid,\r
- EFI_NATIVE_INTERFACE,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ VariableWriteServiceInitializeSmm ();\r
\r
return EFI_SUCCESS;\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
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] SystemTable A pointer to the EFI System Table.\r
-\r
@retval EFI_SUCCESS Variable service successfully initialized.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-VariableServiceInitialize (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+MmVariableServiceInitialize (\r
+ VOID\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_HANDLE VariableHandle;\r
- VOID *SmmFtwRegistration;\r
- VOID *SmmEndOfDxeRegistration;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE VariableHandle;\r
+ VOID *SmmFtwRegistration;\r
+ VOID *SmmEndOfDxeRegistration;\r
\r
//\r
// Variable initialize.\r
// Install the Smm Variable Protocol on a new handle.\r
//\r
VariableHandle = NULL;\r
- Status = gSmst->SmmInstallProtocolInterface (\r
- &VariableHandle,\r
- &gEfiSmmVariableProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &gSmmVariable\r
- );\r
+ Status = gMmst->MmInstallProtocolInterface (\r
+ &VariableHandle,\r
+ &gEfiSmmVariableProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &gSmmVariable\r
+ );\r
ASSERT_EFI_ERROR (Status);\r
\r
- Status = gSmst->SmmInstallProtocolInterface (\r
+ Status = gMmst->MmInstallProtocolInterface (\r
&VariableHandle,\r
&gEdkiiSmmVarCheckProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- mVariableBufferPayloadSize = GetNonVolatileMaxVariableSize () +\r
- OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();\r
+ mVariableBufferPayloadSize = GetMaxVariableSize () +\r
+ OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) -\r
+ GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat);\r
\r
- Status = gSmst->SmmAllocatePool (\r
+ Status = gMmst->MmAllocatePool (\r
EfiRuntimeServicesData,\r
mVariableBufferPayloadSize,\r
(VOID **)&mVariableBufferPayload\r
/// Register SMM variable SMI handler\r
///\r
VariableHandle = NULL;\r
- Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
+ Status = gMmst->MmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
// Notify the variable wrapper driver the variable service is ready\r
//\r
- Status = SystemTable->BootServices->InstallProtocolInterface (\r
- &mVariableHandle,\r
- &gEfiSmmVariableProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &gSmmVariable\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
+ VariableNotifySmmReady ();\r
\r
//\r
// Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.\r
//\r
- Status = gSmst->SmmRegisterProtocolNotify (\r
- &gEfiSmmEndOfDxeProtocolGuid,\r
+ Status = gMmst->MmRegisterProtocolNotify (\r
+ &gEfiMmEndOfDxeProtocolGuid,\r
SmmEndOfDxeCallback,\r
&SmmEndOfDxeRegistration\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- //\r
- // Register FtwNotificationEvent () notify function.\r
- //\r
- Status = gSmst->SmmRegisterProtocolNotify (\r
- &gEfiSmmFaultTolerantWriteProtocolGuid,\r
- SmmFtwNotificationEvent,\r
- &SmmFtwRegistration\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- SmmFtwNotificationEvent (NULL, NULL, NULL);\r
+ if (!PcdGetBool (PcdEmuVariableNvModeEnable)) {\r
+ //\r
+ // Register FtwNotificationEvent () notify function.\r
+ //\r
+ Status = gMmst->MmRegisterProtocolNotify (\r
+ &gEfiSmmFaultTolerantWriteProtocolGuid,\r
+ SmmFtwNotificationEvent,\r
+ &SmmFtwRegistration\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ SmmFtwNotificationEvent (NULL, NULL, NULL);\r
+ } else {\r
+ //\r
+ // Emulated non-volatile variable mode does not depend on FVB and FTW.\r
+ //\r
+ VariableWriteServiceInitializeSmm ();\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
-\r
-\r