]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg DxeS3BootScriptLib: Add DESTRUCTOR S3BootScriptLibDeinitialize
authorStar Zeng <star.zeng@intel.com>
Wed, 25 May 2016 05:11:17 +0000 (13:11 +0800)
committerStar Zeng <star.zeng@intel.com>
Tue, 7 Jun 2016 02:01:10 +0000 (10:01 +0800)
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>
MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf

index d954503f864d9a97b2946b1ccb9c6efc3fd56d4d..0bd0bd04f6afbede784d62e9295cc23810f3b91d 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
-  Save the S3 data to S3 boot script. \r
\r
-  Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Save the S3 data to S3 boot script.\r
+\r
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions\r
@@ -124,6 +124,14 @@ EFI_GUID                         mBootScriptSmmPrivateDataGuid = {
   0x627ee2da, 0x3bf9, 0x439b, { 0x92, 0x9f, 0x2e, 0xe, 0x6e, 0x9d, 0xba, 0x62 }\r
 };\r
 \r
+EFI_EVENT                        mEventDxeSmmReadyToLock = NULL;\r
+VOID                             *mRegistrationSmmExitBootServices = NULL;\r
+VOID                             *mRegistrationSmmLegacyBoot = NULL;\r
+VOID                             *mRegistrationSmmReadyToLock = NULL;\r
+BOOLEAN                          mS3BootScriptTableAllocated = FALSE;\r
+BOOLEAN                          mS3BootScriptTableSmmAllocated = FALSE;\r
+EFI_SMM_SYSTEM_TABLE2            *mSmst = NULL;\r
+\r
 /**\r
   This is an internal function to add a terminate node the entry, recalculate the table \r
   length and fill into the table. \r
@@ -417,8 +425,8 @@ S3BootScriptSmmAtRuntimeCallBack (
   @param  ImageHandle   The firmware allocated handle for the EFI image.\r
   @param  SystemTable   A pointer to the EFI System Table.\r
 \r
-  @retval  RETURN_SUCCESS            Allocate the global memory space to store S3 boot script table private data\r
-  @retval  RETURN_OUT_OF_RESOURCES   No enough memory to allocated.\r
+  @retval RETURN_SUCCESS    The constructor always returns RETURN_SUCCESS.\r
+\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
@@ -433,9 +441,7 @@ S3BootScriptLibInitialize (
   VOID                           *Registration;\r
   EFI_SMM_BASE2_PROTOCOL         *SmmBase2;\r
   BOOLEAN                        InSmm;\r
-  EFI_SMM_SYSTEM_TABLE2          *Smst;\r
   EFI_PHYSICAL_ADDRESS           Buffer;\r
-  EFI_EVENT                      Event;\r
 \r
   if (!PcdGetBool (PcdAcpiS3Enable)) {\r
     return RETURN_SUCCESS;\r
@@ -453,25 +459,24 @@ S3BootScriptLibInitialize (
                     EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)),\r
                     &Buffer\r
                     );\r
-    if (EFI_ERROR (Status)) {\r
-      return RETURN_OUT_OF_RESOURCES;\r
-    }\r
+    ASSERT_EFI_ERROR (Status);\r
+    mS3BootScriptTableAllocated = TRUE;\r
     S3TablePtr = (VOID *) (UINTN) Buffer;\r
 \r
     Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr);\r
     ASSERT_EFI_ERROR (Status);\r
-    ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));  \r
+    ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));\r
     //\r
     // Create event to notify the library system enter the SmmLocked phase.\r
     //\r
-    Event = EfiCreateProtocolNotifyEvent  (\r
-              &gEfiDxeSmmReadyToLockProtocolGuid,\r
-              TPL_CALLBACK,\r
-              S3BootScriptEventCallBack,\r
-              NULL,\r
-              &Registration\r
-              );\r
-    ASSERT (Event != NULL);\r
+    mEventDxeSmmReadyToLock = EfiCreateProtocolNotifyEvent (\r
+                                &gEfiDxeSmmReadyToLockProtocolGuid,\r
+                                TPL_CALLBACK,\r
+                                S3BootScriptEventCallBack,\r
+                                NULL,\r
+                                &Registration\r
+                                );\r
+    ASSERT (mEventDxeSmmReadyToLock != NULL);\r
   }\r
   mS3BootScriptTablePtr = S3TablePtr;\r
 \r
@@ -492,7 +497,7 @@ S3BootScriptLibInitialize (
   //\r
   // Good, we are in SMM\r
   //\r
-  Status = SmmBase2->GetSmstLocation (SmmBase2, &Smst);\r
+  Status = SmmBase2->GetSmstLocation (SmmBase2, &mSmst);\r
   if (EFI_ERROR (Status)) {\r
     return RETURN_SUCCESS;\r
   }\r
@@ -502,14 +507,13 @@ S3BootScriptLibInitialize (
   // The Boot script private data in SMM is not be initialized. create it\r
   //\r
   if (S3TableSmmPtr == 0) {\r
-    Status = Smst->SmmAllocatePool (\r
+    Status = mSmst->SmmAllocatePool (\r
                      EfiRuntimeServicesData,\r
                      sizeof(SCRIPT_TABLE_PRIVATE_DATA),\r
                      (VOID **) &S3TableSmmPtr\r
                      );\r
-    if (EFI_ERROR (Status)) {\r
-      return RETURN_OUT_OF_RESOURCES;\r
-    }\r
+    ASSERT_EFI_ERROR (Status);\r
+    mS3BootScriptTableSmmAllocated = TRUE;\r
 \r
     Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64) (UINTN)S3TableSmmPtr);\r
     ASSERT_EFI_ERROR (Status);\r
@@ -518,19 +522,17 @@ S3BootScriptLibInitialize (
     //\r
     // Register SmmExitBootServices and SmmLegacyBoot notification.\r
     //\r
-    Registration = NULL;\r
-    Status = Smst->SmmRegisterProtocolNotify (\r
+    Status = mSmst->SmmRegisterProtocolNotify (\r
                      &gEdkiiSmmExitBootServicesProtocolGuid,\r
                      S3BootScriptSmmAtRuntimeCallBack,\r
-                     &Registration\r
+                     &mRegistrationSmmExitBootServices\r
                      );\r
     ASSERT_EFI_ERROR (Status);\r
 \r
-    Registration = NULL;\r
-    Status = Smst->SmmRegisterProtocolNotify (\r
+    Status = mSmst->SmmRegisterProtocolNotify (\r
                      &gEdkiiSmmLegacyBootProtocolGuid,\r
                      S3BootScriptSmmAtRuntimeCallBack,\r
-                     &Registration\r
+                     &mRegistrationSmmLegacyBoot\r
                      );\r
     ASSERT_EFI_ERROR (Status);\r
   }\r
@@ -539,16 +541,103 @@ S3BootScriptLibInitialize (
   //\r
   // Register SmmReadyToLock notification.\r
   //\r
-  Registration = NULL;\r
-  Status = Smst->SmmRegisterProtocolNotify (\r
+  Status = mSmst->SmmRegisterProtocolNotify (\r
                    &gEfiSmmReadyToLockProtocolGuid,\r
                    S3BootScriptSmmEventCallBack,\r
-                   &Registration\r
+                   &mRegistrationSmmReadyToLock\r
                    );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
+\r
+/**\r
+  Library Destructor to free the resources allocated by\r
+  S3BootScriptLibInitialize() and unregister callbacks.\r
+\r
+  NOTICE: The destructor doesn't support unloading as a separate action, and it\r
+  only supports unloading if the containing driver's entry point function fails.\r
+\r
+  @param ImageHandle        The firmware allocated handle for the EFI image.\r
+  @param SystemTable        A pointer to the EFI System Table.\r
+\r
+  @retval RETURN_SUCCESS    The destructor always returns RETURN_SUCCESS.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+S3BootScriptLibDeinitialize (\r
+  IN EFI_HANDLE             ImageHandle,\r
+  IN EFI_SYSTEM_TABLE       *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  DEBUG ((EFI_D_INFO, "%a() in %a module\n", __FUNCTION__, gEfiCallerBaseName));\r
+\r
+  if (mEventDxeSmmReadyToLock != NULL) {\r
+    //\r
+    // Close the DxeSmmReadyToLock event.\r
+    //\r
+    Status = gBS->CloseEvent (mEventDxeSmmReadyToLock);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  if (mSmst != NULL) {\r
+    if (mRegistrationSmmExitBootServices != NULL) {\r
+      //\r
+      // Unregister SmmExitBootServices notification.\r
+      //\r
+      Status = mSmst->SmmRegisterProtocolNotify (\r
+                       &gEdkiiSmmExitBootServicesProtocolGuid,\r
+                       NULL,\r
+                       &mRegistrationSmmExitBootServices\r
+                       );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    if (mRegistrationSmmLegacyBoot != NULL) {\r
+      //\r
+      // Unregister SmmLegacyBoot notification.\r
+      //\r
+      Status = mSmst->SmmRegisterProtocolNotify (\r
+                       &gEdkiiSmmLegacyBootProtocolGuid,\r
+                       NULL,\r
+                       &mRegistrationSmmLegacyBoot\r
+                       );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+    if (mRegistrationSmmReadyToLock != NULL) {\r
+      //\r
+      // Unregister SmmReadyToLock notification.\r
+      //\r
+      Status = mSmst->SmmRegisterProtocolNotify (\r
+                       &gEfiSmmReadyToLockProtocolGuid,\r
+                       NULL,\r
+                       &mRegistrationSmmReadyToLock\r
+                       );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Free the resources allocated and set PCDs to 0.\r
+  //\r
+  if (mS3BootScriptTableAllocated) {\r
+    Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) mS3BootScriptTablePtr, EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)));\r
+    ASSERT_EFI_ERROR (Status);\r
+    Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, 0);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+  if (mS3BootScriptTableSmmAllocated) {\r
+    Status = mSmst->SmmFreePool (mS3BootScriptTableSmmPtr);\r
+    ASSERT_EFI_ERROR (Status);\r
+    Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, 0);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
 /**\r
   To get the start address from which a new boot time s3 boot script entry will write into.\r
   If the table is not exist, the functio will first allocate a buffer for the table\r
index 4e0919ea2c79ab03b1b3a86343743650384a673c..0f4151180f6a9b070a98726af1ad305db5a419b8 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # DXE S3 boot script Library.\r
 #\r
-# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
 #\r
 # This program and the accompanying materials are\r
 # licensed and made available under the terms and conditions of the BSD License\r
@@ -24,6 +24,7 @@
 \r
 \r
   CONSTRUCTOR                    = S3BootScriptLibInitialize\r
+  DESTRUCTOR                     = S3BootScriptLibDeinitialize\r
 \r
 #\r
 # The following information is for reference only and not required by the build tools.\r