From: Star Zeng Date: Wed, 25 May 2016 05:11:17 +0000 (+0800) Subject: MdeModulePkg DxeS3BootScriptLib: Add DESTRUCTOR S3BootScriptLibDeinitialize X-Git-Tag: edk2-stable201903~6885 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=cfd79783d603bb2db98ffa0a370bea572724d51c MdeModulePkg DxeS3BootScriptLib: Add DESTRUCTOR S3BootScriptLibDeinitialize PiDxeS3BootScriptLib has a constructor S3BootScriptLibInitialize() that registers ready-to-lock callback S3BootScriptSmmEventCallBack() and several more. The library is linked to SMM modules. If the module entry-point function returns error (because of lack of resources, unsupported, whatever), the module will be unloaded and the notify callback pointers will point to undefined memory. On ready-to-lock exception occurs when calling S3BootScriptSmmEventCallBack(), and probably all the other callbacks registered by the constructor would also cause exception. This patch is to implement library Destructor to free the resources allocated by S3BootScriptLibInitialize() and unregister callbacks. Cc: Jiewen Yao Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng Reviewed-by: Jiewen Yao Reviewed-by: Laszlo Ersek Tested-by: Laszlo Ersek --- diff --git a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c index d954503f86..0bd0bd04f6 100644 --- a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c +++ b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c @@ -1,7 +1,7 @@ /** @file - Save the S3 data to S3 boot script. - - Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+ Save the S3 data to S3 boot script. + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions @@ -124,6 +124,14 @@ EFI_GUID mBootScriptSmmPrivateDataGuid = { 0x627ee2da, 0x3bf9, 0x439b, { 0x92, 0x9f, 0x2e, 0xe, 0x6e, 0x9d, 0xba, 0x62 } }; +EFI_EVENT mEventDxeSmmReadyToLock = NULL; +VOID *mRegistrationSmmExitBootServices = NULL; +VOID *mRegistrationSmmLegacyBoot = NULL; +VOID *mRegistrationSmmReadyToLock = NULL; +BOOLEAN mS3BootScriptTableAllocated = FALSE; +BOOLEAN mS3BootScriptTableSmmAllocated = FALSE; +EFI_SMM_SYSTEM_TABLE2 *mSmst = NULL; + /** This is an internal function to add a terminate node the entry, recalculate the table length and fill into the table. @@ -417,8 +425,8 @@ S3BootScriptSmmAtRuntimeCallBack ( @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. - @retval RETURN_SUCCESS Allocate the global memory space to store S3 boot script table private data - @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated. + @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS. + **/ RETURN_STATUS EFIAPI @@ -433,9 +441,7 @@ S3BootScriptLibInitialize ( VOID *Registration; EFI_SMM_BASE2_PROTOCOL *SmmBase2; BOOLEAN InSmm; - EFI_SMM_SYSTEM_TABLE2 *Smst; EFI_PHYSICAL_ADDRESS Buffer; - EFI_EVENT Event; if (!PcdGetBool (PcdAcpiS3Enable)) { return RETURN_SUCCESS; @@ -453,25 +459,24 @@ S3BootScriptLibInitialize ( EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)), &Buffer ); - if (EFI_ERROR (Status)) { - return RETURN_OUT_OF_RESOURCES; - } + ASSERT_EFI_ERROR (Status); + mS3BootScriptTableAllocated = TRUE; S3TablePtr = (VOID *) (UINTN) Buffer; Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr); ASSERT_EFI_ERROR (Status); - ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA)); + ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA)); // // Create event to notify the library system enter the SmmLocked phase. // - Event = EfiCreateProtocolNotifyEvent ( - &gEfiDxeSmmReadyToLockProtocolGuid, - TPL_CALLBACK, - S3BootScriptEventCallBack, - NULL, - &Registration - ); - ASSERT (Event != NULL); + mEventDxeSmmReadyToLock = EfiCreateProtocolNotifyEvent ( + &gEfiDxeSmmReadyToLockProtocolGuid, + TPL_CALLBACK, + S3BootScriptEventCallBack, + NULL, + &Registration + ); + ASSERT (mEventDxeSmmReadyToLock != NULL); } mS3BootScriptTablePtr = S3TablePtr; @@ -492,7 +497,7 @@ S3BootScriptLibInitialize ( // // Good, we are in SMM // - Status = SmmBase2->GetSmstLocation (SmmBase2, &Smst); + Status = SmmBase2->GetSmstLocation (SmmBase2, &mSmst); if (EFI_ERROR (Status)) { return RETURN_SUCCESS; } @@ -502,14 +507,13 @@ S3BootScriptLibInitialize ( // The Boot script private data in SMM is not be initialized. create it // if (S3TableSmmPtr == 0) { - Status = Smst->SmmAllocatePool ( + Status = mSmst->SmmAllocatePool ( EfiRuntimeServicesData, sizeof(SCRIPT_TABLE_PRIVATE_DATA), (VOID **) &S3TableSmmPtr ); - if (EFI_ERROR (Status)) { - return RETURN_OUT_OF_RESOURCES; - } + ASSERT_EFI_ERROR (Status); + mS3BootScriptTableSmmAllocated = TRUE; Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64) (UINTN)S3TableSmmPtr); ASSERT_EFI_ERROR (Status); @@ -518,19 +522,17 @@ S3BootScriptLibInitialize ( // // Register SmmExitBootServices and SmmLegacyBoot notification. // - Registration = NULL; - Status = Smst->SmmRegisterProtocolNotify ( + Status = mSmst->SmmRegisterProtocolNotify ( &gEdkiiSmmExitBootServicesProtocolGuid, S3BootScriptSmmAtRuntimeCallBack, - &Registration + &mRegistrationSmmExitBootServices ); ASSERT_EFI_ERROR (Status); - Registration = NULL; - Status = Smst->SmmRegisterProtocolNotify ( + Status = mSmst->SmmRegisterProtocolNotify ( &gEdkiiSmmLegacyBootProtocolGuid, S3BootScriptSmmAtRuntimeCallBack, - &Registration + &mRegistrationSmmLegacyBoot ); ASSERT_EFI_ERROR (Status); } @@ -539,16 +541,103 @@ S3BootScriptLibInitialize ( // // Register SmmReadyToLock notification. // - Registration = NULL; - Status = Smst->SmmRegisterProtocolNotify ( + Status = mSmst->SmmRegisterProtocolNotify ( &gEfiSmmReadyToLockProtocolGuid, S3BootScriptSmmEventCallBack, - &Registration + &mRegistrationSmmReadyToLock ); ASSERT_EFI_ERROR (Status); return RETURN_SUCCESS; } + +/** + Library Destructor to free the resources allocated by + S3BootScriptLibInitialize() and unregister callbacks. + + NOTICE: The destructor doesn't support unloading as a separate action, and it + only supports unloading if the containing driver's entry point function fails. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval RETURN_SUCCESS The destructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +S3BootScriptLibDeinitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + DEBUG ((EFI_D_INFO, "%a() in %a module\n", __FUNCTION__, gEfiCallerBaseName)); + + if (mEventDxeSmmReadyToLock != NULL) { + // + // Close the DxeSmmReadyToLock event. + // + Status = gBS->CloseEvent (mEventDxeSmmReadyToLock); + ASSERT_EFI_ERROR (Status); + } + + if (mSmst != NULL) { + if (mRegistrationSmmExitBootServices != NULL) { + // + // Unregister SmmExitBootServices notification. + // + Status = mSmst->SmmRegisterProtocolNotify ( + &gEdkiiSmmExitBootServicesProtocolGuid, + NULL, + &mRegistrationSmmExitBootServices + ); + ASSERT_EFI_ERROR (Status); + } + if (mRegistrationSmmLegacyBoot != NULL) { + // + // Unregister SmmLegacyBoot notification. + // + Status = mSmst->SmmRegisterProtocolNotify ( + &gEdkiiSmmLegacyBootProtocolGuid, + NULL, + &mRegistrationSmmLegacyBoot + ); + ASSERT_EFI_ERROR (Status); + } + if (mRegistrationSmmReadyToLock != NULL) { + // + // Unregister SmmReadyToLock notification. + // + Status = mSmst->SmmRegisterProtocolNotify ( + &gEfiSmmReadyToLockProtocolGuid, + NULL, + &mRegistrationSmmReadyToLock + ); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Free the resources allocated and set PCDs to 0. + // + if (mS3BootScriptTableAllocated) { + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) mS3BootScriptTablePtr, EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA))); + ASSERT_EFI_ERROR (Status); + Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, 0); + ASSERT_EFI_ERROR (Status); + } + if (mS3BootScriptTableSmmAllocated) { + Status = mSmst->SmmFreePool (mS3BootScriptTableSmmPtr); + ASSERT_EFI_ERROR (Status); + Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, 0); + ASSERT_EFI_ERROR (Status); + } + + return RETURN_SUCCESS; +} + /** To get the start address from which a new boot time s3 boot script entry will write into. If the table is not exist, the functio will first allocate a buffer for the table diff --git a/MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf b/MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf index 4e0919ea2c..0f4151180f 100644 --- a/MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf +++ b/MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf @@ -1,7 +1,7 @@ ## @file # DXE S3 boot script Library. # -# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
# # This program and the accompanying materials are # licensed and made available under the terms and conditions of the BSD License @@ -24,6 +24,7 @@ CONSTRUCTOR = S3BootScriptLibInitialize + DESTRUCTOR = S3BootScriptLibDeinitialize # # The following information is for reference only and not required by the build tools.