]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
MdeModulePkg DxeS3BootScriptLib: Check (mSmst != NULL) before freeing SMRAM
[mirror_edk2.git] / MdeModulePkg / Library / PiDxeS3BootScriptLib / BootScriptSave.c
index d954503f864d9a97b2946b1ccb9c6efc3fd56d4d..0ff73211acc44a7de6aba29bc45485bca3a1b761 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,13 +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
-  }\r
 \r
   S3TablePtr = (SCRIPT_TABLE_PRIVATE_DATA*)(UINTN)PcdGet64(PcdS3BootScriptTablePrivateDataPtr);\r
   //\r
@@ -453,25 +455,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 +493,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 +503,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 +518,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 +537,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 ((mSmst != NULL) && 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