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 <jiewen.yao@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Star Zeng 2016-05-25 13:11:17 +08:00
parent 738df706c1
commit cfd79783d6
2 changed files with 124 additions and 34 deletions

View File

@ -1,7 +1,7 @@
/** @file
Save the S3 data to S3 boot script.
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
Save the S3 data to S3 boot script.
Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
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

View File

@ -1,7 +1,7 @@
## @file
# DXE S3 boot script Library.
#
# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
#
# 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.