diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h index 969a4f7e9d8..4e50850cc07 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h @@ -100,6 +100,15 @@ VariableNotifySmmReady ( VOID ); +/** + Revert the variable ready notification. + This function will be called when an error happens in variable initializing process. +**/ +VOID +VariableClearNotifySmmReady ( + VOID + ); + /** Notify the system that the SMM variable write driver is ready. **/ @@ -114,7 +123,12 @@ VariableNotifySmmWriteReady ( for variable read and write services being available. It also registers a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event. - @retval EFI_SUCCESS Variable service successfully initialized. + @retval EFI_SUCCESS Variable service successfully initialized. + @retval EFI_OUT_OF_RESOURCES Insufficient memory to allocate variable + storage or communication buffers. + @retval EFI_VOLUME_CORRUPTED The non-volatile variable store is corrupted. + @retval Others An error from protocol installation, SMI handler + registration, or protocol notification registration. **/ EFI_STATUS EFIAPI diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c index 0ea888d233d..ee703b71205 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c @@ -3843,6 +3843,9 @@ GetHobVariableStore ( /** Initializes variable store area for non-volatile and volatile variable. + On any failure, the caller must invoke VariableCommonUninitialize() to + release resources that may have been partially allocated. + @retval EFI_SUCCESS Function successfully executed. @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource. @@ -3872,7 +3875,6 @@ VariableCommonInitialize ( // Status = InitNonVolatileVariableStore (); if (EFI_ERROR (Status)) { - FreePool (mVariableModuleGlobal); return Status; } @@ -3898,11 +3900,6 @@ VariableCommonInitialize ( // Status = GetHobVariableStore (VariableGuid); if (EFI_ERROR (Status)) { - if (mNvFvHeaderCache != NULL) { - FreePool (mNvFvHeaderCache); - } - - FreePool (mVariableModuleGlobal); return Status; } @@ -3917,15 +3914,6 @@ VariableCommonInitialize ( mVariableModuleGlobal->ScratchBufferSize = ScratchSize; VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize); if (VolatileVariableStore == NULL) { - if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) { - FreePool ((VOID *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase); - } - - if (mNvFvHeaderCache != NULL) { - FreePool (mNvFvHeaderCache); - } - - FreePool (mVariableModuleGlobal); return EFI_OUT_OF_RESOURCES; } @@ -3947,6 +3935,47 @@ VariableCommonInitialize ( return EFI_SUCCESS; } +/** + Uninitialize variable store area, freeing all resources allocated by + VariableCommonInitialize(). + +**/ +VOID +VariableCommonUninitialize ( + VOID + ) +{ + if (mVariableModuleGlobal != NULL) { + if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) { + FreePool ((VOID *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase); + mVariableModuleGlobal->VariableGlobal.HobVariableBase = 0; + } + + if (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase != 0) { + FreePool ((VOID *)(UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase); + } + + FreePool (mVariableModuleGlobal); + mVariableModuleGlobal = NULL; + } + + if (mNvFvHeaderCache != NULL) { + // + // In real NV mode, mNvVariableCache points into the same allocation as mNvFvHeaderCache. + // + ASSERT ((UINTN)mNvVariableCache == (UINTN)mNvFvHeaderCache + mNvFvHeaderCache->HeaderLength); + FreePool (mNvFvHeaderCache); + mNvFvHeaderCache = NULL; + mNvVariableCache = NULL; + } else if ((mNvVariableCache != NULL) && (PcdGet64 (PcdEmuVariableNvStoreReserved) == 0)) { + // + // In emulated NV mode without a pre-reserved store, mNvVariableCache is a dynamic allocation. + // + FreePool (mNvVariableCache); + mNvVariableCache = NULL; + } +} + /** Get the proper fvb handle and/or fvb protocol by the given Flash address. diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h index 033c0625afb..5b91a87a623 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h @@ -368,6 +368,16 @@ VariableCommonInitialize ( VOID ); +/** + Uninitialize variable store area, freeing all resources allocated by + VariableCommonInitialize(). + +**/ +VOID +VariableCommonUninitialize ( + VOID + ); + /** This function reclaims variable storage if free size is below the threshold. diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c index cf803f44d39..c62f3e2d9ee 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c @@ -534,7 +534,12 @@ ProtocolIsVariablePolicyEnabled ( @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. - @retval EFI_SUCCESS Variable service successfully initialized. + @retval EFI_SUCCESS Variable service successfully initialized. + @retval EFI_OUT_OF_RESOURCES Insufficient memory to allocate variable + storage or event/protocol resources. + @retval EFI_VOLUME_CORRUPTED The non-volatile variable store is corrupted. + @retval Others An error from protocol installation, event + creation, or variable policy initialization. **/ EFI_STATUS @@ -547,9 +552,40 @@ VariableServiceInitialize ( EFI_STATUS Status; EFI_EVENT ReadyToBootEvent; EFI_EVENT EndOfDxeEvent; + EFI_EVENT FtwNotifyEvent; + BOOLEAN VariableLockProtocolInstalled; + BOOLEAN VarCheckProtocolInstalled; + BOOLEAN RuntimeServicesUpdated; + BOOLEAN FtwNotifyRegistered; + BOOLEAN VirtualAddressChangeRegistered; + BOOLEAN ReadyToBootEventCreated; + BOOLEAN EndOfDxeEventCreated; + BOOLEAN VariablePolicyLibInitialized; + BOOLEAN VariablePolicyProtocolInstalled; + + ReadyToBootEvent = NULL; + EndOfDxeEvent = NULL; + FtwNotifyEvent = NULL; + VariableLockProtocolInstalled = FALSE; + VarCheckProtocolInstalled = FALSE; + RuntimeServicesUpdated = FALSE; + FtwNotifyRegistered = FALSE; + VirtualAddressChangeRegistered = FALSE; + ReadyToBootEventCreated = FALSE; + EndOfDxeEventCreated = FALSE; + VariablePolicyLibInitialized = FALSE; + VariablePolicyProtocolInstalled = FALSE; Status = VariableCommonInitialize (); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: VariableCommonInitialize failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } Status = gBS->InstallMultipleProtocolInterfaces ( &mHandle, @@ -557,7 +593,17 @@ VariableServiceInitialize ( &mVariableLock, NULL ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Installing gEdkiiVariableLockProtocolGuid failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + VariableLockProtocolInstalled = TRUE; Status = gBS->InstallMultipleProtocolInterfaces ( &mHandle, @@ -565,35 +611,46 @@ VariableServiceInitialize ( &mVarCheck, NULL ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Installing gEdkiiVarCheckProtocolGuid failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + VarCheckProtocolInstalled = TRUE; SystemTable->RuntimeServices->GetVariable = VariableServiceGetVariable; SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName; SystemTable->RuntimeServices->SetVariable = VariableServiceSetVariable; SystemTable->RuntimeServices->QueryVariableInfo = VariableServiceQueryVariableInfo; - - // - // Now install the Variable Runtime Architectural protocol on a new handle. - // - Status = gBS->InstallProtocolInterface ( - &mHandle, - &gEfiVariableArchProtocolGuid, - EFI_NATIVE_INTERFACE, - NULL - ); - ASSERT_EFI_ERROR (Status); + RuntimeServicesUpdated = TRUE; if (!PcdGetBool (PcdEmuVariableNvModeEnable)) { // // Register FtwNotificationEvent () notify function. // - EfiCreateProtocolNotifyEvent ( - &gEfiFaultTolerantWriteProtocolGuid, - TPL_CALLBACK, - FtwNotificationEvent, - (VOID *)SystemTable, - &mFtwRegistration - ); + FtwNotifyEvent = EfiCreateProtocolNotifyEvent ( + &gEfiFaultTolerantWriteProtocolGuid, + TPL_CALLBACK, + FtwNotificationEvent, + (VOID *)SystemTable, + &mFtwRegistration + ); + if (FtwNotifyEvent == NULL) { + DEBUG (( + DEBUG_ERROR, + "%a: EfiCreateProtocolNotifyEvent for FTW failed. Aborting variable init.\n", + __func__ + )); + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + FtwNotifyRegistered = TRUE; } else { // // Emulated non-volatile variable mode does not depend on FVB and FTW. @@ -609,7 +666,17 @@ VariableServiceInitialize ( &gEfiEventVirtualAddressChangeGuid, &mVirtualAddressChangeEvent ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: CreateEventEx for VirtualAddressChange failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + VirtualAddressChangeRegistered = TRUE; // // Register the event handling function to reclaim variable for OS usage. @@ -620,7 +687,17 @@ VariableServiceInitialize ( NULL, &ReadyToBootEvent ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: EfiCreateEventReadyToBootEx failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + ReadyToBootEventCreated = TRUE; // // Register the event handling function to set the End Of DXE flag. @@ -633,22 +710,157 @@ VariableServiceInitialize ( &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: CreateEventEx for EndOfDxe failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + EndOfDxeEventCreated = TRUE; // Register and initialize the VariablePolicy engine. Status = InitVariablePolicyLib (VariableServiceGetVariable); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: InitVariablePolicyLib failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + VariablePolicyLibInitialized = TRUE; + Status = VarCheckRegisterSetVariableCheckHandler (ValidateSetVariable); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: VarCheckRegisterSetVariableCheckHandler failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + Status = gBS->InstallMultipleProtocolInterfaces ( &mHandle, &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol, NULL ); - ASSERT_EFI_ERROR (Status); - Status = InitializeVariablePolicyLocking (&mVariablePolicyProtocol); // MU_CHANGE - Isolate the VariablePolicy locking event into its own code. - ASSERT_EFI_ERROR (Status); // MU_CHANGE - Isolate the VariablePolicy locking event into its own code. + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Installing gEdkiiVariablePolicyProtocolGuid failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + VariablePolicyProtocolInstalled = TRUE; + + // MU_CHANGE START - Isolate the VariablePolicy locking event into its own code. + Status = InitializeVariablePolicyLocking (&mVariablePolicyProtocol); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: InitializeVariablePolicyLocking failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + // MU_CHANGE END + + // + // Install the Variable Runtime Architectural protocol last so that + // dependent drivers are not notified until the variable service is + // fully initialized. + // + Status = gBS->InstallProtocolInterface ( + &mHandle, + &gEfiVariableArchProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Installing gEfiVariableArchProtocolGuid failed - %r. Aborting variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } return EFI_SUCCESS; + +ErrorExit: + if (EndOfDxeEventCreated) { + gBS->CloseEvent (EndOfDxeEvent); + } + + if (ReadyToBootEventCreated) { + gBS->CloseEvent (ReadyToBootEvent); + } + + if (VirtualAddressChangeRegistered) { + gBS->CloseEvent (mVirtualAddressChangeEvent); + mVirtualAddressChangeEvent = NULL; + } + + if (FtwNotifyRegistered) { + gBS->CloseEvent (FtwNotifyEvent); + mFtwRegistration = NULL; + } + + if (RuntimeServicesUpdated) { + SystemTable->RuntimeServices->GetVariable = NULL; + SystemTable->RuntimeServices->GetNextVariableName = NULL; + SystemTable->RuntimeServices->SetVariable = NULL; + SystemTable->RuntimeServices->QueryVariableInfo = NULL; + } + + if (VarCheckProtocolInstalled) { + gBS->UninstallMultipleProtocolInterfaces ( + mHandle, + &gEdkiiVarCheckProtocolGuid, + &mVarCheck, + NULL + ); + } + + if (VariableLockProtocolInstalled) { + gBS->UninstallMultipleProtocolInterfaces ( + mHandle, + &gEdkiiVariableLockProtocolGuid, + &mVariableLock, + NULL + ); + } + + if (VariablePolicyProtocolInstalled) { + gBS->UninstallMultipleProtocolInterfaces ( + mHandle, + &gEdkiiVariablePolicyProtocolGuid, + &mVariablePolicyProtocol, + NULL + ); + } + + if (VariablePolicyLibInitialized) { + DeinitVariablePolicyLib (); + } + + VariableCommonUninitialize (); + + ASSERT_EFI_ERROR (Status); + return Status; } diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c index 370106d4852..40321e4ae7a 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c @@ -1181,7 +1181,12 @@ SmmFtwNotificationEvent ( for variable read and write services being available. It also registers a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event. - @retval EFI_SUCCESS Variable service successfully initialized. + @retval EFI_SUCCESS Variable service successfully initialized. + @retval EFI_OUT_OF_RESOURCES Insufficient memory to allocate variable + storage or communication buffers. + @retval EFI_VOLUME_CORRUPTED The non-volatile variable store is corrupted. + @retval Others An error from protocol installation, SMI handler + registration, or protocol notification registration. **/ EFI_STATUS @@ -1192,14 +1197,63 @@ MmVariableServiceInitialize ( { EFI_STATUS Status; EFI_HANDLE VariableHandle; + EFI_HANDLE SmmVariableDispatchHandle; VOID *SmmFtwRegistration; VOID *SmmEndOfDxeRegistration; + BOOLEAN SmmVariableProtocolInstalled; + BOOLEAN SmmVarCheckProtocolInstalled; + BOOLEAN SmmVariableHandlerRegistered; + BOOLEAN SmmEndOfDxeNotifyRegistered; + BOOLEAN SmmFtwNotifyRegistered; + BOOLEAN SmmNotifiedSmmReady; + + SmmVariableDispatchHandle = NULL; + SmmFtwRegistration = NULL; + SmmEndOfDxeRegistration = NULL; + SmmVariableProtocolInstalled = FALSE; + SmmVarCheckProtocolInstalled = FALSE; + SmmVariableHandlerRegistered = FALSE; + SmmEndOfDxeNotifyRegistered = FALSE; + SmmFtwNotifyRegistered = FALSE; + SmmNotifiedSmmReady = FALSE; // // Variable initialize. // Status = VariableCommonInitialize (); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: VariableCommonInitialize failed - %r. Aborting SMM variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + // + // Allocate the communication payload buffer before installing any protocols or + // registering any handlers. A failure here requires no global state cleanup. + // + mVariableBufferPayloadSize = GetMaxVariableSize () + + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - + GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat); + + Status = gMmst->MmAllocatePool ( + EfiRuntimeServicesData, + mVariableBufferPayloadSize, + (VOID **)&mVariableBufferPayload + ); + if (EFI_ERROR (Status)) { + mVariableBufferPayloadSize = 0; + DEBUG (( + DEBUG_ERROR, + "%a: MmAllocatePool for variable buffer payload failed - %r. Aborting SMM variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } // // Install the Smm Variable Protocol on a new handle. @@ -1211,7 +1265,17 @@ MmVariableServiceInitialize ( EFI_NATIVE_INTERFACE, &gSmmVariable ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Installing gEfiSmmVariableProtocolGuid failed - %r. Aborting SMM variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + SmmVariableProtocolInstalled = TRUE; Status = gMmst->MmInstallProtocolInterface ( &VariableHandle, @@ -1219,30 +1283,43 @@ MmVariableServiceInitialize ( EFI_NATIVE_INTERFACE, &mSmmVarCheck ); - ASSERT_EFI_ERROR (Status); - - mVariableBufferPayloadSize = GetMaxVariableSize () + - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - - GetVariableHeaderSize (mVariableModuleGlobal->VariableGlobal.AuthFormat); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Installing gEdkiiSmmVarCheckProtocolGuid failed - %r. Aborting SMM variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } - Status = gMmst->MmAllocatePool ( - EfiRuntimeServicesData, - mVariableBufferPayloadSize, - (VOID **)&mVariableBufferPayload - ); - ASSERT_EFI_ERROR (Status); + SmmVarCheckProtocolInstalled = TRUE; /// /// Register SMM variable SMI handler /// - VariableHandle = NULL; - Status = gMmst->MmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle); - ASSERT_EFI_ERROR (Status); + Status = gMmst->MmiHandlerRegister ( + SmmVariableHandler, + &gEfiSmmVariableProtocolGuid, + &SmmVariableDispatchHandle + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: MmiHandlerRegister failed - %r. Aborting SMM variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + SmmVariableHandlerRegistered = TRUE; // // Notify the variable wrapper driver the variable service is ready // VariableNotifySmmReady (); + SmmNotifiedSmmReady = TRUE; // // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function. @@ -1252,7 +1329,17 @@ MmVariableServiceInitialize ( SmmEndOfDxeCallback, &SmmEndOfDxeRegistration ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Register MmEndOfDxe notify failed - %r. Aborting SMM variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + SmmEndOfDxeNotifyRegistered = TRUE; if (!PcdGetBool (PcdEmuVariableNvModeEnable)) { // @@ -1263,9 +1350,22 @@ MmVariableServiceInitialize ( SmmFtwNotificationEvent, &SmmFtwRegistration ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Register SmmFaultTolerantWrite protocol notify failed - %r. Aborting SMM variable init.\n", + __func__, + Status + )); + goto ErrorExit; + } + + SmmFtwNotifyRegistered = TRUE; - SmmFtwNotificationEvent (NULL, NULL, NULL); + Status = SmmFtwNotificationEvent (NULL, NULL, NULL); + if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_FOUND)) { + goto ErrorExit; + } } else { // // Emulated non-volatile variable mode does not depend on FVB and FTW. @@ -1276,4 +1376,56 @@ MmVariableServiceInitialize ( AdvLoggerAccessInit (); // MU_CHANGE return EFI_SUCCESS; + +ErrorExit: + if (SmmFtwNotifyRegistered) { + gMmst->MmRegisterProtocolNotify ( + &gEfiSmmFaultTolerantWriteProtocolGuid, + NULL, + &SmmFtwRegistration + ); + } + + if (SmmEndOfDxeNotifyRegistered) { + gMmst->MmRegisterProtocolNotify ( + &gEfiMmEndOfDxeProtocolGuid, + NULL, + &SmmEndOfDxeRegistration + ); + } + + if (SmmNotifiedSmmReady) { + VariableClearNotifySmmReady (); + } + + if (SmmVariableHandlerRegistered) { + gMmst->MmiHandlerUnRegister (SmmVariableDispatchHandle); + } + + if (mVariableBufferPayload != NULL) { + gMmst->MmFreePool (mVariableBufferPayload); + mVariableBufferPayload = NULL; + mVariableBufferPayloadSize = 0; + } + + if (SmmVarCheckProtocolInstalled) { + gMmst->MmUninstallProtocolInterface ( + VariableHandle, + &gEdkiiSmmVarCheckProtocolGuid, + &mSmmVarCheck + ); + } + + if (SmmVariableProtocolInstalled) { + gMmst->MmUninstallProtocolInterface ( + VariableHandle, + &gEfiSmmVariableProtocolGuid, + &gSmmVariable + ); + } + + VariableCommonUninitialize (); + + ASSERT_EFI_ERROR (Status); + return Status; } diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c index 10578226c60..a580b951462 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c @@ -61,6 +61,17 @@ VariableNotifySmmReady ( { } +/** + Revert the variable ready notification. + This function will be called when an error happens in variable initializing process. +**/ +VOID +VariableClearNotifySmmReady ( + VOID + ) +{ +} + /** Notify the system that the SMM variable write driver is ready. **/ diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c index cd82bb56756..2fb2e2be091 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c @@ -12,6 +12,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include "Variable.h" +EFI_HANDLE mDxeSmmVariableHandle = NULL; + /** This function checks if the Primary Buffer (CommBuffer) is valid. @@ -60,11 +62,11 @@ VariableNotifySmmReady ( ) { EFI_STATUS Status; - EFI_HANDLE Handle; - Handle = NULL; + mDxeSmmVariableHandle = NULL; + Status = gBS->InstallProtocolInterface ( - &Handle, + &mDxeSmmVariableHandle, &gEfiSmmVariableProtocolGuid, EFI_NATIVE_INTERFACE, NULL @@ -72,6 +74,25 @@ VariableNotifySmmReady ( ASSERT_EFI_ERROR (Status); } +/** + Revert the variable ready notification. + This function will be called when an error happens in variable initializing process. +**/ +VOID +VariableClearNotifySmmReady ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->UninstallProtocolInterface ( + mDxeSmmVariableHandle, + &gEfiSmmVariableProtocolGuid, + NULL + ); + ASSERT_EFI_ERROR (Status); +} + /** Notify the system that the SMM variable write driver is ready. **/