From 6ab9f44138c62cea69000e7ada2161c07efadf93 Mon Sep 17 00:00:00 2001 From: niruiyu Date: Mon, 20 May 2013 07:10:10 +0000 Subject: [PATCH] Add the EDKII_VARIABLE_LOCK_PROTOCOL implementation in SecurityPkg variable drivers. Signed-off-by: Ruiyu Ni Reviewed-by: Star Zeng git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14378 6f19259b-4bc3-4df7-8a09-765794883524 --- .../RuntimeDxe/Variable.c | 105 +++++++++++++++--- .../RuntimeDxe/Variable.h | 32 +++++- .../RuntimeDxe/VariableDxe.c | 57 +++++++++- .../RuntimeDxe/VariableRuntimeDxe.inf | 4 +- .../RuntimeDxe/VariableSmm.c | 99 ++++++++++++++++- .../RuntimeDxe/VariableSmm.inf | 1 + .../RuntimeDxe/VariableSmmRuntimeDxe.c | 79 +++++++++++++ .../RuntimeDxe/VariableSmmRuntimeDxe.inf | 1 + 8 files changed, 356 insertions(+), 22 deletions(-) diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c index f10d8f7d83..576623e88b 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c @@ -35,12 +35,28 @@ VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal; /// /// Define a memory cache that improves the search performance for a variable. /// -VARIABLE_STORE_HEADER *mNvVariableCache = NULL; +VARIABLE_STORE_HEADER *mNvVariableCache = NULL; /// /// The memory entry used for variable statistics data. /// -VARIABLE_INFO_ENTRY *gVariableInfo = NULL; +VARIABLE_INFO_ENTRY *gVariableInfo = NULL; + +/// +/// The list to store the variables which cannot be set after the EFI_END_OF_DXE_EVENT_GROUP_GUID +/// or EVT_GROUP_READY_TO_BOOT event. +/// +LIST_ENTRY mLockedVariableList = INITIALIZE_LIST_HEAD_VARIABLE (mLockedVariableList); + +/// +/// The flag to indicate whether the platform has left the DXE phase of execution. +/// +BOOLEAN mEndOfDxe = FALSE; + +/// +/// The flag to indicate whether the variable storage locking is enabled. +/// +BOOLEAN mEnableLocking = TRUE; /** @@ -2311,6 +2327,58 @@ IsHwErrRecVariable ( return TRUE; } +/** + Mark a variable that will become read-only after leaving the DXE phase of execution. + + @param[in] This The VARIABLE_LOCK_PROTOCOL instance. + @param[in] VariableName A pointer to the variable name that will be made read-only subsequently. + @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently. + + @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked + as pending to be read-only. + @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL. + Or VariableName is an empty string. + @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has + already been signaled. + @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request. +**/ +EFI_STATUS +EFIAPI +VariableLockRequestToLock ( + IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ) +{ + VARIABLE_ENTRY *Entry; + + if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (mEndOfDxe) { + return EFI_ACCESS_DENIED; + } + + Entry = AllocateRuntimePool (sizeof (*Entry) + StrSize (VariableName)); + if (Entry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s\n", VendorGuid, VariableName)); + + AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); + + Entry->Name = (CHAR16 *) (Entry + 1); + StrCpy (Entry->Name, VariableName); + CopyGuid (&Entry->Guid, VendorGuid); + InsertTailList (&mLockedVariableList, &Entry->Link); + + ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); + + return EFI_SUCCESS; +} + /** This code checks if variable should be treated as read-only variable. @@ -2627,6 +2695,8 @@ VariableServiceSetVariable ( VARIABLE_HEADER *NextVariable; EFI_PHYSICAL_ADDRESS Point; UINTN PayloadSize; + LIST_ENTRY *Link; + VARIABLE_ENTRY *Entry; // // Check input parameters. @@ -2717,16 +2787,6 @@ VariableServiceSetVariable ( } } - if (AtRuntime ()) { - // - // HwErrRecSupport Global Variable identifies the level of hardware error record persistence - // support implemented by the platform. This variable is only modified by firmware and is read-only to the OS. - // - if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, L"HwErrRecSupport") == 0)) { - return EFI_WRITE_PROTECTED; - } - } - AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); // @@ -2745,13 +2805,31 @@ VariableServiceSetVariable ( mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point; } + if (mEndOfDxe && mEnableLocking) { + // + // Treat the variables listed in the forbidden variable list as read-only after leaving DXE phase. + // + for ( Link = GetFirstNode (&mLockedVariableList) + ; !IsNull (&mLockedVariableList, Link) + ; Link = GetNextNode (&mLockedVariableList, Link) + ) { + Entry = BASE_CR (Link, VARIABLE_ENTRY, Link); + if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Entry->Name, VariableName) == 0)) { + Status = EFI_WRITE_PROTECTED; + DEBUG ((EFI_D_INFO, "[Variable]: Changing readonly variable after leaving DXE phase - %g:%s\n", VendorGuid, VariableName)); + goto Done; + } + } + } + // // Check whether the input variable is already existed. // Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, TRUE); if (!EFI_ERROR (Status)) { if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) { - return EFI_WRITE_PROTECTED; + Status = EFI_WRITE_PROTECTED; + goto Done; } } @@ -2776,6 +2854,7 @@ VariableServiceSetVariable ( Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, &Variable, Attributes); } +Done: InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState); ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock); diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h index 4501583648..f394414b3f 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h @@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include #include @@ -106,6 +107,12 @@ typedef struct { VOID *Data; } VARIABLE_CACHE_ENTRY; +typedef struct { + EFI_GUID Guid; + CHAR16 *Name; + LIST_ENTRY Link; +} VARIABLE_ENTRY; + /** Flush the HOB variable to flash. @@ -577,7 +584,30 @@ VariableServiceQueryVariableInfo ( OUT UINT64 *RemainingVariableStorageSize, OUT UINT64 *MaximumVariableSize ); - + +/** + Mark a variable that will become read-only after leaving the DXE phase of execution. + + @param[in] This The VARIABLE_LOCK_PROTOCOL instance. + @param[in] VariableName A pointer to the variable name that will be made read-only subsequently. + @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently. + + @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked + as pending to be read-only. + @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL. + Or VariableName is an empty string. + @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has + already been signaled. + @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request. +**/ +EFI_STATUS +EFIAPI +VariableLockRequestToLock ( + IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ); + extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal; #endif diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c index f91cb5dc56..a2e764cf61 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c @@ -16,11 +16,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "Variable.h" #include "AuthService.h" -extern VARIABLE_STORE_HEADER *mNvVariableCache; -extern VARIABLE_INFO_ENTRY *gVariableInfo; -EFI_HANDLE mHandle = NULL; -EFI_EVENT mVirtualAddressChangeEvent = NULL; -EFI_EVENT mFtwRegistration = NULL; +extern VARIABLE_STORE_HEADER *mNvVariableCache; +extern VARIABLE_INFO_ENTRY *gVariableInfo; +EFI_HANDLE mHandle = NULL; +EFI_EVENT mVirtualAddressChangeEvent = NULL; +EFI_EVENT mFtwRegistration = NULL; +extern BOOLEAN mEndOfDxe; +EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock }; /** Return TRUE if ExitBootServices () has been called. @@ -257,12 +259,34 @@ OnReadyToBoot ( VOID *Context ) { + // + // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled. + // + mEndOfDxe = TRUE; ReclaimForOS (); if (FeaturePcdGet (PcdVariableCollectStatistics)) { gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo); } } +/** + Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group. + + This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context. + +**/ +VOID +EFIAPI +OnEndOfDxe ( + EFI_EVENT Event, + VOID *Context + ) +{ + mEndOfDxe = TRUE; +} /** Fault Tolerant Write protocol notification event handler. @@ -378,10 +402,19 @@ VariableServiceInitialize ( { EFI_STATUS Status; EFI_EVENT ReadyToBootEvent; + EFI_EVENT EndOfDxeEvent; Status = VariableCommonInitialize (); ASSERT_EFI_ERROR (Status); + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEdkiiVariableLockProtocolGuid, + &mVariableLock, + NULL + ); + ASSERT_EFI_ERROR (Status); + SystemTable->RuntimeServices->GetVariable = VariableServiceGetVariable; SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName; SystemTable->RuntimeServices->SetVariable = VariableServiceSetVariable; @@ -428,6 +461,20 @@ VariableServiceInitialize ( NULL, &ReadyToBootEvent ); + ASSERT_EFI_ERROR (Status); + + // + // Register the event handling function to set the End Of DXE flag. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + OnEndOfDxe, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &EndOfDxeEvent + ); + ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; } diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf index ab676f456a..dbd7d6e470 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf @@ -67,11 +67,12 @@ gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES gEfiFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES + gEdkiiVariableLockProtocolGuid ## ALWAYS_PRODUCES [Guids] gEfiAuthenticatedVariableGuid ## PRODUCES ## Configuration Table Guid gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid - gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event gEfiCertTypeRsa2048Sha256Guid gEfiImageSecurityDatabaseGuid gEfiCertX509Guid @@ -82,6 +83,7 @@ gEfiSystemNvDataFvGuid ## CONSUMES gEfiCertDbGuid gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES + gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c index 754ab9a794..cf866cecba 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c @@ -29,6 +29,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include @@ -46,15 +47,61 @@ BOOLEAN mAtRuntime = F EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; UINT8 *mVariableBufferPayload = NULL; UINTN mVariableBufferPayloadSize; +extern BOOLEAN mEndOfDxe; +extern BOOLEAN mEnableLocking; + +/** + + This code sets variable in storage blocks (Volatile or Non-Volatile). + + @param VariableName Name of Variable to be found. + @param VendorGuid Variable vendor GUID. + @param Attributes Attribute value of the variable found + @param DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param Data Data pointer. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Set successfully. + @return EFI_OUT_OF_RESOURCES Resource not enough to set variable. + @return EFI_NOT_FOUND Not found. + @return EFI_WRITE_PROTECTED Variable is read-only. + +**/ +EFI_STATUS +EFIAPI +SmmVariableSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + EFI_STATUS Status; + + // + // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL. + // + mEnableLocking = FALSE; + Status = VariableServiceSetVariable ( + VariableName, + VendorGuid, + Attributes, + DataSize, + Data + ); + mEnableLocking = TRUE; + return Status; +} EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = { VariableServiceGetVariable, VariableServiceGetNextVariableName, - VariableServiceSetVariable, + SmmVariableSetVariable, VariableServiceQueryVariableInfo }; - /** Return TRUE if ExitBootServices () has been called. @@ -455,6 +502,7 @@ SmmVariableHandler ( SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName; SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo; VARIABLE_INFO_ENTRY *VariableInfo; + SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock; UINTN InfoSize; UINTN NameBufferSize; UINTN CommBufferPayloadSize; @@ -641,6 +689,7 @@ SmmVariableHandler ( break; case SMM_VARIABLE_FUNCTION_READY_TO_BOOT: + mEndOfDxe = TRUE; if (AtRuntime()) { Status = EFI_UNSUPPORTED; break; @@ -673,6 +722,19 @@ SmmVariableHandler ( *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE; break; + case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE: + if (mEndOfDxe) { + Status = EFI_ACCESS_DENIED; + } else { + VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data; + Status = VariableLockRequestToLock ( + NULL, + VariableToLock->Name, + &VariableToLock->Guid + ); + } + break; + default: Status = EFI_UNSUPPORTED; } @@ -683,6 +745,28 @@ EXIT: return EFI_SUCCESS; } +/** + SMM END_OF_DXE protocol notification event handler. + + @param Protocol Points to the protocol's unique identifier + @param Interface Points to the interface instance + @param Handle The handle on which the interface was installed + + @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully + +**/ +EFI_STATUS +EFIAPI +SmmEndOfDxeCallback ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n")); + mEndOfDxe = TRUE; + return EFI_SUCCESS; +} /** SMM Fault Tolerant Write protocol notification event handler. @@ -779,6 +863,7 @@ VariableServiceInitialize ( VOID *SmmFtwRegistration; EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; UINTN Size; + VOID *SmmEndOfDxeRegistration; // // Variable initialize. @@ -848,6 +933,16 @@ VariableServiceInitialize ( ); ASSERT_EFI_ERROR (Status); + // + // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function. + // + Status = gSmst->SmmRegisterProtocolNotify ( + &gEfiSmmEndOfDxeProtocolGuid, + SmmEndOfDxeCallback, + &SmmEndOfDxeRegistration + ); + ASSERT_EFI_ERROR (Status); + // // Register FtwNotificationEvent () notify function. // diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf index e0aa40ac6d..a9a10976eb 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf @@ -73,6 +73,7 @@ gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES gEfiSmmAccess2ProtocolGuid ## ALWAYS_CONSUMES + gEfiSmmEndOfDxeProtocolGuid ## ALWAYS_CONSUMES [Guids] gEfiAuthenticatedVariableGuid ## PRODUCES ## Configuration Table Guid diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c index b7c7f4ffb7..7011343872 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.c @@ -29,6 +29,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include @@ -54,6 +55,7 @@ UINT8 *mVariableBufferPhysical = NULL; UINTN mVariableBufferSize; UINTN mVariableBufferPayloadSize; EFI_LOCK mVariableServicesLock; +EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock; /** Acquires lock only at boot time. Simply returns at runtime. @@ -173,6 +175,73 @@ SendCommunicateBuffer ( return SmmVariableFunctionHeader->ReturnStatus; } +/** + Mark a variable that will become read-only after leaving the DXE phase of execution. + + @param[in] This The VARIABLE_LOCK_PROTOCOL instance. + @param[in] VariableName A pointer to the variable name that will be made read-only subsequently. + @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently. + + @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked + as pending to be read-only. + @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL. + Or VariableName is an empty string. + @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has + already been signaled. + @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request. +**/ +EFI_STATUS +EFIAPI +VariableLockRequestToLock ( + IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ) +{ + EFI_STATUS Status; + UINTN VariableNameSize; + UINTN PayloadSize; + SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock; + + if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + VariableNameSize = StrSize (VariableName); + + // + // If VariableName exceeds SMM payload limit. Return failure + // + if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) { + return EFI_INVALID_PARAMETER; + } + + AcquireLockOnlyAtBootTime(&mVariableServicesLock); + + // + // Init the communicate buffer. The buffer data size is: + // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize. + // + PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize; + Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE); + if (EFI_ERROR (Status)) { + goto Done; + } + ASSERT (VariableToLock != NULL); + + CopyGuid (&VariableToLock->Guid, VendorGuid); + VariableToLock->NameSize = VariableNameSize; + CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize); + + // + // Send data to SMM. + // + Status = SendCommunicateBuffer (PayloadSize); + +Done: + ReleaseLockOnlyAtBootTime (&mVariableServicesLock); + return Status; +} /** This code finds variable in storage blocks (Volatile or Non-Volatile). @@ -740,6 +809,7 @@ VariableSmmRuntimeInitialize ( IN EFI_SYSTEM_TABLE *SystemTable ) { + EFI_STATUS Status; VOID *SmmVariableRegistration; VOID *SmmVariableWriteRegistration; EFI_EVENT OnReadyToBootEvent; @@ -747,6 +817,15 @@ VariableSmmRuntimeInitialize ( EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY); + mVariableLock.RequestToLock = VariableLockRequestToLock; + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEdkiiVariableLockProtocolGuid, + &mVariableLock, + NULL + ); + ASSERT_EFI_ERROR (Status); + // // Smm variable service is ready // diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf index 3842f0105d..a28702765b 100644 --- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf +++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmmRuntimeDxe.inf @@ -59,6 +59,7 @@ gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES gEfiSmmCommunicationProtocolGuid gEfiSmmVariableProtocolGuid + gEdkiiVariableLockProtocolGuid ## ALWAYS_PRODUCES [Guids] gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event