///\r
/// Define a memory cache that improves the search performance for a variable.\r
///\r
-VARIABLE_STORE_HEADER *mNvVariableCache = NULL;\r
+VARIABLE_STORE_HEADER *mNvVariableCache = NULL;\r
\r
///\r
/// The memory entry used for variable statistics data.\r
///\r
-VARIABLE_INFO_ENTRY *gVariableInfo = NULL;\r
+VARIABLE_INFO_ENTRY *gVariableInfo = NULL;\r
+\r
+///\r
+/// The list to store the variables which cannot be set after the EFI_END_OF_DXE_EVENT_GROUP_GUID\r
+/// or EVT_GROUP_READY_TO_BOOT event.\r
+///\r
+LIST_ENTRY mLockedVariableList = INITIALIZE_LIST_HEAD_VARIABLE (mLockedVariableList);\r
+\r
+///\r
+/// The flag to indicate whether the platform has left the DXE phase of execution.\r
+///\r
+BOOLEAN mEndOfDxe = FALSE;\r
+\r
+///\r
+/// The flag to indicate whether the variable storage locking is enabled.\r
+///\r
+BOOLEAN mEnableLocking = TRUE;\r
\r
\r
/**\r
return TRUE;\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
+ VARIABLE_ENTRY *Entry;\r
+\r
+ if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (mEndOfDxe) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ Entry = AllocateRuntimePool (sizeof (*Entry) + StrSize (VariableName));\r
+ if (Entry == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s\n", VendorGuid, VariableName));\r
+\r
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+ Entry->Name = (CHAR16 *) (Entry + 1);\r
+ StrCpy (Entry->Name, VariableName);\r
+ CopyGuid (&Entry->Guid, VendorGuid);\r
+ InsertTailList (&mLockedVariableList, &Entry->Link);\r
+\r
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
This code checks if variable should be treated as read-only variable.\r
\r
VARIABLE_HEADER *NextVariable;\r
EFI_PHYSICAL_ADDRESS Point;\r
UINTN PayloadSize;\r
+ LIST_ENTRY *Link;\r
+ VARIABLE_ENTRY *Entry;\r
\r
//\r
// Check input parameters.\r
}\r
}\r
\r
- if (AtRuntime ()) {\r
- //\r
- // HwErrRecSupport Global Variable identifies the level of hardware error record persistence\r
- // support implemented by the platform. This variable is only modified by firmware and is read-only to the OS.\r
- //\r
- if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, L"HwErrRecSupport") == 0)) {\r
- return EFI_WRITE_PROTECTED;\r
- }\r
- }\r
-\r
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
\r
//\r
mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point;\r
}\r
\r
+ if (mEndOfDxe && mEnableLocking) {\r
+ //\r
+ // Treat the variables listed in the forbidden variable list as read-only after leaving DXE phase.\r
+ //\r
+ for ( Link = GetFirstNode (&mLockedVariableList)\r
+ ; !IsNull (&mLockedVariableList, Link)\r
+ ; Link = GetNextNode (&mLockedVariableList, Link)\r
+ ) {\r
+ Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);\r
+ if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Entry->Name, VariableName) == 0)) {\r
+ Status = EFI_WRITE_PROTECTED;\r
+ DEBUG ((EFI_D_INFO, "[Variable]: Changing readonly variable after leaving DXE phase - %g:%s\n", VendorGuid, VariableName));\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
//\r
// Check whether the input variable is already existed.\r
//\r
Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, TRUE);\r
if (!EFI_ERROR (Status)) {\r
if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) {\r
- return EFI_WRITE_PROTECTED;\r
+ Status = EFI_WRITE_PROTECTED;\r
+ goto Done;\r
}\r
}\r
\r
Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes);\r
}\r
\r
+Done:\r
InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);\r
ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
\r
#include <Protocol/FaultTolerantWrite.h>\r
#include <Protocol/FirmwareVolumeBlock.h>\r
#include <Protocol/Variable.h>\r
+#include <Protocol/VariableLock.h>\r
#include <Library/PcdLib.h>\r
#include <Library/HobLib.h>\r
#include <Library/UefiDriverEntryPoint.h>\r
VOID *Data;\r
} VARIABLE_CACHE_ENTRY;\r
\r
+typedef struct {\r
+ EFI_GUID Guid;\r
+ CHAR16 *Name;\r
+ LIST_ENTRY Link;\r
+} VARIABLE_ENTRY;\r
+\r
/**\r
Flush the HOB variable to flash.\r
\r
OUT UINT64 *RemainingVariableStorageSize,\r
OUT UINT64 *MaximumVariableSize\r
); \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
extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;\r
\r
#endif\r
#include "Variable.h"\r
#include "AuthService.h"\r
\r
-extern VARIABLE_STORE_HEADER *mNvVariableCache;\r
-extern VARIABLE_INFO_ENTRY *gVariableInfo;\r
-EFI_HANDLE mHandle = NULL;\r
-EFI_EVENT mVirtualAddressChangeEvent = NULL;\r
-EFI_EVENT mFtwRegistration = NULL;\r
+extern VARIABLE_STORE_HEADER *mNvVariableCache;\r
+extern VARIABLE_INFO_ENTRY *gVariableInfo;\r
+EFI_HANDLE mHandle = NULL;\r
+EFI_EVENT mVirtualAddressChangeEvent = NULL;\r
+EFI_EVENT mFtwRegistration = NULL;\r
+extern BOOLEAN mEndOfDxe;\r
+EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock };\r
\r
/**\r
Return TRUE if ExitBootServices () has been called.\r
VOID *Context\r
)\r
{\r
+ //\r
+ // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.\r
+ //\r
+ mEndOfDxe = TRUE;\r
ReclaimForOS ();\r
if (FeaturePcdGet (PcdVariableCollectStatistics)) {\r
gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo);\r
}\r
}\r
\r
+/**\r
+ Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
+\r
+ This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OnEndOfDxe (\r
+ EFI_EVENT Event,\r
+ VOID *Context\r
+ )\r
+{\r
+ mEndOfDxe = TRUE;\r
+}\r
\r
/**\r
Fault Tolerant Write protocol notification event handler.\r
{\r
EFI_STATUS Status;\r
EFI_EVENT ReadyToBootEvent;\r
+ EFI_EVENT EndOfDxeEvent;\r
\r
Status = VariableCommonInitialize ();\r
ASSERT_EFI_ERROR (Status);\r
\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mHandle,\r
+ &gEdkiiVariableLockProtocolGuid,\r
+ &mVariableLock,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
SystemTable->RuntimeServices->GetVariable = VariableServiceGetVariable;\r
SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;\r
SystemTable->RuntimeServices->SetVariable = VariableServiceSetVariable;\r
NULL,\r
&ReadyToBootEvent\r
);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Register the event handling function to set the End Of DXE flag.\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ OnEndOfDxe,\r
+ NULL,\r
+ &gEfiEndOfDxeEventGroupGuid,\r
+ &EndOfDxeEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
return EFI_SUCCESS;\r
}\r
gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES\r
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES\r
gEfiFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEdkiiVariableLockProtocolGuid ## ALWAYS_PRODUCES\r
\r
[Guids]\r
gEfiAuthenticatedVariableGuid ## PRODUCES ## Configuration Table Guid\r
gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid\r
- gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event\r
+ gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event\r
gEfiCertTypeRsa2048Sha256Guid\r
gEfiImageSecurityDatabaseGuid\r
gEfiCertX509Guid\r
gEfiSystemNvDataFvGuid ## CONSUMES\r
gEfiCertDbGuid\r
gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES\r
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event\r
\r
[Pcd]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize\r
#include <Protocol/SmmFirmwareVolumeBlock.h>\r
#include <Protocol/SmmFaultTolerantWrite.h>\r
#include <Protocol/SmmAccess2.h>\r
+#include <Protocol/SmmEndOfDxe.h>\r
\r
#include <Library/SmmServicesTableLib.h>\r
\r
EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
UINT8 *mVariableBufferPayload = NULL;\r
UINTN mVariableBufferPayloadSize;\r
+extern BOOLEAN mEndOfDxe;\r
+extern BOOLEAN mEnableLocking;\r
+\r
+/**\r
+\r
+ This code sets variable in storage blocks (Volatile or Non-Volatile).\r
+\r
+ @param VariableName Name of Variable to be found.\r
+ @param VendorGuid Variable vendor GUID.\r
+ @param Attributes Attribute value of the variable found\r
+ @param DataSize Size of Data found. If size is less than the\r
+ data, this value contains the required size.\r
+ @param Data Data pointer.\r
+\r
+ @return EFI_INVALID_PARAMETER Invalid parameter.\r
+ @return EFI_SUCCESS Set successfully.\r
+ @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.\r
+ @return EFI_NOT_FOUND Not found.\r
+ @return EFI_WRITE_PROTECTED Variable is read-only.\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
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.\r
+ //\r
+ mEnableLocking = FALSE;\r
+ Status = VariableServiceSetVariable (\r
+ VariableName,\r
+ VendorGuid,\r
+ Attributes,\r
+ DataSize,\r
+ Data\r
+ );\r
+ mEnableLocking = TRUE;\r
+ return Status;\r
+}\r
\r
EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {\r
VariableServiceGetVariable,\r
VariableServiceGetNextVariableName,\r
- VariableServiceSetVariable,\r
+ SmmVariableSetVariable,\r
VariableServiceQueryVariableInfo\r
};\r
\r
-\r
/**\r
Return TRUE if ExitBootServices () has been called.\r
\r
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;\r
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;\r
VARIABLE_INFO_ENTRY *VariableInfo;\r
+ SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;\r
UINTN InfoSize;\r
UINTN NameBufferSize;\r
UINTN CommBufferPayloadSize;\r
break;\r
\r
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:\r
+ mEndOfDxe = TRUE;\r
if (AtRuntime()) {\r
Status = EFI_UNSUPPORTED;\r
break;\r
*CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
break;\r
\r
+ case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:\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
+ }\r
+ break;\r
+\r
default:\r
Status = EFI_UNSUPPORTED;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ SMM END_OF_DXE protocol notification event handler.\r
+\r
+ @param Protocol Points to the protocol's unique identifier\r
+ @param Interface Points to the interface instance\r
+ @param Handle The handle on which the interface was installed\r
+\r
+ @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmEndOfDxeCallback (\r
+ IN CONST EFI_GUID *Protocol,\r
+ IN VOID *Interface,\r
+ IN EFI_HANDLE Handle\r
+ )\r
+{\r
+ DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));\r
+ mEndOfDxe = TRUE;\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
SMM Fault Tolerant Write protocol notification event handler.\r
VOID *SmmFtwRegistration;\r
EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
UINTN Size;\r
+ VOID *SmmEndOfDxeRegistration;\r
\r
//\r
// Variable initialize.\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\r
+ // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.\r
+ //\r
+ Status = gSmst->SmmRegisterProtocolNotify (\r
+ &gEfiSmmEndOfDxeProtocolGuid,\r
+ SmmEndOfDxeCallback,\r
+ &SmmEndOfDxeRegistration\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
//\r
// Register FtwNotificationEvent () notify function.\r
// \r
gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES\r
gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES\r
gEfiSmmAccess2ProtocolGuid ## ALWAYS_CONSUMES\r
+ gEfiSmmEndOfDxeProtocolGuid ## ALWAYS_CONSUMES\r
\r
[Guids]\r
gEfiAuthenticatedVariableGuid ## PRODUCES ## Configuration Table Guid\r
#include <Protocol/Variable.h>\r
#include <Protocol/SmmCommunication.h>\r
#include <Protocol/SmmVariable.h>\r
+#include <Protocol/VariableLock.h>\r
\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/UefiRuntimeServicesTableLib.h>\r
UINTN mVariableBufferSize;\r
UINTN mVariableBufferPayloadSize;\r
EFI_LOCK mVariableServicesLock;\r
+EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;\r
\r
/**\r
Acquires lock only at boot time. Simply returns at runtime.\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
+\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
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
+ EFI_STATUS Status;\r
VOID *SmmVariableRegistration;\r
VOID *SmmVariableWriteRegistration;\r
EFI_EVENT OnReadyToBootEvent;\r
\r
EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);\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
//\r
// Smm variable service is ready\r
//\r
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES \r
gEfiSmmCommunicationProtocolGuid\r
gEfiSmmVariableProtocolGuid\r
+ gEdkiiVariableLockProtocolGuid ## ALWAYS_PRODUCES\r
\r
[Guids]\r
gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event\r