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 <[email protected]>
Cc: Laszlo Ersek <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <[email protected]>
Reviewed-by: Jiewen Yao <[email protected]>
---
 .../Library/PiDxeS3BootScriptLib/BootScriptSave.c  | 155 ++++++++++++++++-----
 .../PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf    |   3 +-
 2 files changed, 124 insertions(+), 34 deletions(-)

diff --git a/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c 
b/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
index d954503f864d..e84195ded547 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.<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 EFI_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 desturctor 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 decstructor always returns EFI_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 ((VOID *) 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 4e0919ea2c79..0f4151180f6a 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.<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 @@ [Defines]
 
 
   CONSTRUCTOR                    = S3BootScriptLibInitialize
+  DESTRUCTOR                     = S3BootScriptLibDeinitialize
 
 #
 # The following information is for reference only and not required by the 
build tools.
-- 
2.7.0.windows.1

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to