]> 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 8769509f76b10b56c0b56248031c2fb7cc1cb894..0ff73211acc44a7de6aba29bc45485bca3a1b761 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
-  Save the S3 data to S3 boot script. \r
\r
-  Copyright (c) 2006 - 2010, 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
 \r
   Data structure usage:\r
 \r
-  +------------------------------+<-- PcdS3BootScriptTablePrivateDataPtr\r
+  +------------------------------+<------- PcdS3BootScriptTablePrivateDataPtr\r
+  | SCRIPT_TABLE_PRIVATE_DATA    |          (mS3BootScriptTablePtr, Before SmmReadyToLock)\r
+  |    TableBase                 |---      PcdS3BootScriptTablePrivateSmmDataPtr\r
+  |    TableLength               |--|--     (mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr, After SmmReadyToLock InSmm)\r
+  |    TableMemoryPageNumber     |--|-|----\r
+  |    AtRuntime                 |  | |   |\r
+  |    InSmm                     |  | |   |\r
+  |    BootTimeScriptLength      |--|-|---|---\r
+  |    SmmLocked                 |  | |   |  |\r
+  |    BackFromS3                |  | |   |  |\r
+  +------------------------------+  | |   |  |\r
+                                    | |   |  |\r
+  +------------------------------+<-- |   |  |\r
+  | EFI_BOOT_SCRIPT_TABLE_HEADER |    |   |  |\r
+  |    TableLength               |----|-- |  |\r
+  +------------------------------+    | | |  |\r
+  |     ......                   |    | | |  |\r
+  +------------------------------+<---- | |  |\r
+  | EFI_BOOT_SCRIPT_TERMINATE    |      | |  |\r
+  +------------------------------+<------ |  |\r
+                                          |  |\r
+                                          |  |\r
+  mBootScriptDataBootTimeGuid LockBox:    |  |\r
+   Used to restore data after back from S3|  |\r
+   to handle potential INSERT boot script |  |\r
+   at runtime.                            |  |\r
+  +------------------------------+        |  |\r
+  | Boot Time Boot Script        |        |  |\r
+  | Before SmmReadyToLock        |        |  |\r
+  |                              |        |  |\r
+  |                              |        |  |\r
+  +------------------------------+        |  |\r
+  | Boot Time Boot Script        |        |  |\r
+  | After SmmReadyToLock InSmm   |        |  |\r
+  |                              |        |  |\r
+  +------------------------------+<-------|--|\r
+                                          |  |\r
+                                          |  |\r
+  mBootScriptDataGuid LockBox: (IN_PLACE) |  |\r
+   Used to restore data at S3 resume.     |  |\r
+  +------------------------------+        |  |\r
+  | Boot Time Boot Script        |        |  |\r
+  | Before SmmReadyToLock        |        |  |\r
+  |                              |        |  |\r
+  |                              |        |  |\r
+  +------------------------------+        |  |\r
+  | Boot Time Boot Script        |        |  |\r
+  | After SmmReadyToLock InSmm   |        |  |\r
+  |                              |        |  |\r
+  +------------------------------+<-------|---\r
+  | Runtime Boot Script          |        |\r
+  | After SmmReadyToLock InSmm   |        |\r
+  +------------------------------+        |\r
+  |     ......                   |        |\r
+  +------------------------------+<--------\r
+\r
+\r
+  mBootScriptTableBaseGuid LockBox: (IN_PLACE)\r
+  +------------------------------+\r
+  | mS3BootScriptTablePtr->      |\r
+  |  TableBase                   |\r
+  +------------------------------+\r
+\r
+\r
+  mBootScriptSmmPrivateDataGuid LockBox: (IN_PLACE)\r
+   SMM private data with BackFromS3 = TRUE\r
+   at runtime. S3 will help restore it to\r
+   tell the Library the system is back from S3.\r
+  +------------------------------+\r
   | SCRIPT_TABLE_PRIVATE_DATA    |\r
-  |    TableBase                 |---\r
-  |    TableLength               |--|--\r
-  |    AtRuntime                 |  | |\r
-  |    InSmm                     |  | |\r
-  +------------------------------+  | |\r
-                                    | |\r
-  +------------------------------+<-- |\r
-  | EFI_BOOT_SCRIPT_TABLE_HEADER |    |\r
-  |    TableLength               |----|--\r
-  +------------------------------+    | |\r
-  |     ......                   |    | |\r
-  +------------------------------+<---- |\r
-  | EFI_BOOT_SCRIPT_TERMINATE    |      |\r
-  +------------------------------+<------\r
+  |    TableBase                 |\r
+  |    TableLength               |\r
+  |    TableMemoryPageNumber     |\r
+  |    AtRuntime                 |\r
+  |    InSmm                     |\r
+  |    BootTimeScriptLength      |\r
+  |    SmmLocked                 |\r
+  |    BackFromS3 = TRUE         |\r
+  +------------------------------+\r
 \r
 **/\r
 \r
 SCRIPT_TABLE_PRIVATE_DATA        *mS3BootScriptTablePtr;\r
-EFI_EVENT                        mEnterRuntimeEvent;\r
+\r
 //\r
-// Allocate local copy in SMM because we can not use mS3BootScriptTablePtr when we AtRuntime in InSmm.\r
+// Allocate SMM copy because we can not use mS3BootScriptTablePtr after SmmReadyToLock in InSmm.\r
 //\r
-SCRIPT_TABLE_PRIVATE_DATA        mS3BootScriptTable;\r
-UINTN                            mLockBoxLength;\r
+SCRIPT_TABLE_PRIVATE_DATA        *mS3BootScriptTableSmmPtr;\r
 \r
 EFI_GUID                         mBootScriptDataGuid = {\r
-  0xaea6b965, 0xdcf5, 0x4311, 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2\r
+  0xaea6b965, 0xdcf5, 0x4311, { 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2 }\r
+};\r
+\r
+EFI_GUID                         mBootScriptDataBootTimeGuid = {\r
+  0xb5af1d7a, 0xb8cf, 0x4eb3, { 0x89, 0x25, 0xa8, 0x20, 0xe1, 0x6b, 0x68, 0x7d }\r
 };\r
 \r
-EFI_GUID                         mBootScriptHeaderDataGuid = {\r
-  0x1810ab4a, 0x2314, 0x4df6, 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91\r
+EFI_GUID                         mBootScriptTableBaseGuid = {\r
+  0x1810ab4a, 0x2314, 0x4df6, { 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91 }\r
 };\r
 \r
+EFI_GUID                         mBootScriptSmmPrivateDataGuid = {\r
+  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
   \r
-  @return the base address of the boot script tble.   \r
+  @return the base address of the boot script table.   \r
  **/\r
 UINT8*\r
 S3BootScriptInternalCloseTable (\r
@@ -93,33 +171,31 @@ S3BootScriptInternalCloseTable (
   return S3TableBase;\r
   //\r
   // NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to \r
-  // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE). Because \r
-  // maybe in runtime, we still need add entries into the table, and the runtime entry should be\r
-  // added start before this TERMINATE node.\r
+  // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE).\r
+  // Because maybe after SmmReadyToLock, we still need add entries into the table,\r
+  // and the entry should be added start before this TERMINATE node.\r
   //\r
 }  \r
 \r
 /**\r
   This function save boot script data to LockBox.\r
-  1. BootSriptPrivate data, BootScript data - Image and DispatchContext are handled by platform.\r
-  2. BootScriptExecutor, BootScriptExecutor context\r
-  - ACPI variable - (PI version) sould be handled by SMM driver. S3 Page table is handled here.\r
-  - ACPI variable - framework version is already handled by Framework CPU driver.\r
+\r
 **/\r
 VOID\r
 SaveBootScriptDataToLockBox (\r
   VOID\r
   )\r
 {\r
-  EFI_STATUS Status;\r
+  EFI_STATUS            Status;\r
+\r
   //\r
-  // mS3BootScriptTablePtr->TableLength does not include EFI_BOOT_SCRIPT_TERMINATE, because we need add entry at runtime.\r
-  // Save all info here, just in case that no one will add boot script entry in SMM.\r
+  // Save whole memory copy into LockBox.\r
+  // It will be used to restore data at S3 resume.\r
   //\r
   Status = SaveLockBox (\r
              &mBootScriptDataGuid,\r
              (VOID *)mS3BootScriptTablePtr->TableBase,\r
-             mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE)\r
+             EFI_PAGES_TO_SIZE (mS3BootScriptTablePtr->TableMemoryPageNumber)\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -131,22 +207,22 @@ SaveBootScriptDataToLockBox (
   // Do not update other field because they will NOT be used in S3.\r
   //\r
   Status = SaveLockBox (\r
-             &mBootScriptHeaderDataGuid,\r
+             &mBootScriptTableBaseGuid,\r
              (VOID *)&mS3BootScriptTablePtr->TableBase,\r
              sizeof(mS3BootScriptTablePtr->TableBase)\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = SetLockBoxAttributes (&mBootScriptHeaderDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+  Status = SetLockBoxAttributes (&mBootScriptTableBaseGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
 /**\r
   This is the Event call back function to notify the Library the system is entering\r
-  run time phase.\r
+  SmmLocked phase.\r
   \r
   @param  Event   Pointer to this event\r
-  @param  Context Event hanlder private data \r
+  @param  Context Event handler private data \r
  **/\r
 VOID\r
 EFIAPI\r
@@ -172,28 +248,29 @@ S3BootScriptEventCallBack (
   }\r
 \r
   //\r
-  // Here we should tell the library that we are enter into runtime phase. and \r
-  // the memory page number occupied by the table should not grow anymore.\r
+  // Here we should tell the library that we are entering SmmLocked phase.\r
+  // and the memory page number occupied by the table should not grow anymore.\r
   //\r
-  if (!mS3BootScriptTablePtr->AtRuntime) {\r
+  if (!mS3BootScriptTablePtr->SmmLocked) {\r
     //\r
-    // In boot time, we need not write the terminate node when adding a node to boot scipt table\r
-    // or else, that will impact the performance. However, in runtime, we should append terminate\r
-    // node on every add to boot script table\r
+    // Before SmmReadyToLock, we need not write the terminate node when adding a node to boot scipt table\r
+    // or else, that will impact the performance. However, after SmmReadyToLock, we should append terminate\r
+    // node on every add to boot script table.\r
     //\r
     S3BootScriptInternalCloseTable ();\r
-    mS3BootScriptTablePtr->AtRuntime = TRUE;\r
+    mS3BootScriptTablePtr->SmmLocked = TRUE;\r
 \r
     //\r
     // Save BootScript data to lockbox\r
     //\r
     SaveBootScriptDataToLockBox ();\r
   }\r
-} \r
+}\r
+\r
 /**\r
-  This is the Event call back function is triggered in SMM to notify the Library the system is entering\r
-  run time phase and set InSmm flag.\r
-  \r
+  This is the Event call back function is triggered in SMM to notify the Library\r
+  the system is entering SmmLocked phase and set InSmm flag.\r
+\r
   @param  Protocol   Points to the protocol's unique identifier\r
   @param  Interface  Points to the interface instance\r
   @param  Handle     The handle on which the interface was installed\r
@@ -211,34 +288,131 @@ S3BootScriptSmmEventCallBack (
   //\r
   // Check if it is already done\r
   //\r
-  if (mS3BootScriptTablePtr == &mS3BootScriptTable) {\r
+  if (mS3BootScriptTablePtr == mS3BootScriptTableSmmPtr) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   //\r
-  // Last chance to call-out, just make sure AtRuntime is set\r
+  // Last chance to call-out, just make sure SmmLocked is set.\r
   //\r
   S3BootScriptEventCallBack (NULL, NULL);\r
 \r
   //\r
-  // Save a local copy\r
+  // Save a SMM copy. If TableBase is NOT null, it means SMM copy has been ready, skip copy mem.\r
+  //\r
+  if (mS3BootScriptTableSmmPtr->TableBase == NULL) {\r
+    CopyMem (mS3BootScriptTableSmmPtr, mS3BootScriptTablePtr, sizeof(*mS3BootScriptTablePtr));\r
+\r
+    //\r
+    // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.\r
+    // InSmm will only be checked if SmmLocked is TRUE.\r
+    //\r
+    mS3BootScriptTableSmmPtr->InSmm = TRUE;\r
+  }\r
+  //\r
+  // We should not use ACPI Reserved copy, because it is not safe.\r
+  //\r
+  mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is to save boot time boot script data to LockBox.\r
+\r
+  Because there may be INSERT boot script at runtime in SMM.\r
+  The boot time copy will be used to restore data after back from S3.\r
+  Otherwise the data inserted may cause some boot time boot script data lost\r
+  if only BootScriptData used.\r
+\r
+**/\r
+VOID\r
+SaveBootTimeDataToLockBox (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  //\r
+  // ACPI Reserved copy is not safe, restore from BootScriptData LockBox first,\r
+  // and then save the data to BootScriptDataBootTime LockBox.\r
   //\r
-  CopyMem (&mS3BootScriptTable, mS3BootScriptTablePtr, sizeof(*mS3BootScriptTablePtr));\r
+  Status = RestoreLockBox (\r
+             &mBootScriptDataGuid,\r
+             NULL,\r
+             NULL\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
   //\r
-  // We should not use ACPINvs copy, because it is not safe.\r
+  // Save BootScriptDataBootTime\r
+  // It will be used to restore data after back from S3.\r
   //\r
-  mS3BootScriptTablePtr = &mS3BootScriptTable;\r
+  Status = SaveLockBox (\r
+             &mBootScriptDataBootTimeGuid,\r
+             (VOID *) mS3BootScriptTablePtr->TableBase,\r
+             mS3BootScriptTablePtr->BootTimeScriptLength\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r
+/**\r
+  This function save boot script SMM private data to LockBox with BackFromS3 = TRUE at runtime.\r
+  S3 resume will help restore it to tell the Library the system is back from S3.\r
+\r
+**/\r
+VOID\r
+SaveSmmPriviateDataToLockBoxAtRuntime (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
 \r
   //\r
-  // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.\r
-  // InSmm will only be checked if AtRuntime is TRUE.\r
+  // Save boot script SMM private data with BackFromS3 = TRUE.\r
   //\r
-  mS3BootScriptTablePtr->InSmm = TRUE;\r
+  mS3BootScriptTablePtr->BackFromS3 = TRUE;\r
+  Status = SaveLockBox (\r
+             &mBootScriptSmmPrivateDataGuid,\r
+             (VOID *) mS3BootScriptTablePtr,\r
+             sizeof (SCRIPT_TABLE_PRIVATE_DATA)\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = SetLockBoxAttributes (&mBootScriptSmmPrivateDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Record LockBoxLength\r
+  // Set BackFromS3 flag back to FALSE to indicate that now is not back from S3.\r
   //\r
-  mLockBoxLength = mS3BootScriptTable.TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE);\r
+  mS3BootScriptTablePtr->BackFromS3 = FALSE;\r
+}\r
+\r
+/**\r
+  This is the Event call back function is triggered in SMM to notify the Library\r
+  the system is entering runtime phase.\r
+\r
+  @param[in] Protocol   Points to the protocol's unique identifier\r
+  @param[in] Interface  Points to the interface instance\r
+  @param[in] Handle     The handle on which the interface was installed\r
+\r
+  @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully\r
+ **/\r
+EFI_STATUS\r
+EFIAPI\r
+S3BootScriptSmmAtRuntimeCallBack (\r
+  IN CONST EFI_GUID     *Protocol,\r
+  IN VOID               *Interface,\r
+  IN EFI_HANDLE         Handle\r
+  )\r
+{\r
+  if (!mS3BootScriptTablePtr->AtRuntime) {\r
+    mS3BootScriptTablePtr->BootTimeScriptLength = (UINT32) (mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
+    SaveBootTimeDataToLockBox ();\r
+\r
+    mS3BootScriptTablePtr->AtRuntime = TRUE;\r
+    SaveSmmPriviateDataToLockBoxAtRuntime ();\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -251,8 +425,8 @@ S3BootScriptSmmEventCallBack (
   @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
@@ -263,10 +437,10 @@ S3BootScriptLibInitialize (
 {\r
   EFI_STATUS                      Status;\r
   SCRIPT_TABLE_PRIVATE_DATA      *S3TablePtr;\r
+  SCRIPT_TABLE_PRIVATE_DATA      *S3TableSmmPtr;\r
   VOID                           *Registration;\r
   EFI_SMM_BASE2_PROTOCOL         *SmmBase2;\r
   BOOLEAN                        InSmm;\r
-  EFI_SMM_SYSTEM_TABLE2          *Smst;\r
   EFI_PHYSICAL_ADDRESS           Buffer;\r
 \r
   S3TablePtr = (SCRIPT_TABLE_PRIVATE_DATA*)(UINTN)PcdGet64(PcdS3BootScriptTablePrivateDataPtr);\r
@@ -277,29 +451,29 @@ S3BootScriptLibInitialize (
     Buffer = SIZE_4GB - 1;\r
     Status = gBS->AllocatePages (\r
                     AllocateMaxAddress,\r
-                    EfiACPIMemoryNVS,\r
+                    EfiReservedMemoryType,\r
                     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
-    PcdSet64 (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr); \r
-    ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));  \r
+    Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr);\r
+    ASSERT_EFI_ERROR (Status);\r
+    ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));\r
     //\r
-    // create event to notify the library system enter the runtime phase\r
+    // Create event to notify the library system enter the SmmLocked phase.\r
     //\r
-    mEnterRuntimeEvent = EfiCreateProtocolNotifyEvent  (\r
-                          &gEfiDxeSmmReadyToLockProtocolGuid,\r
-                          TPL_CALLBACK,\r
-                          S3BootScriptEventCallBack,\r
-                          NULL,\r
-                          &Registration\r
-                          );\r
-    ASSERT (mEnterRuntimeEvent != NULL);\r
-  } \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
   //\r
@@ -319,24 +493,147 @@ 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
 \r
+  S3TableSmmPtr = (SCRIPT_TABLE_PRIVATE_DATA*)(UINTN)PcdGet64(PcdS3BootScriptTablePrivateSmmDataPtr);\r
+  //\r
+  // The Boot script private data in SMM is not be initialized. create it\r
+  //\r
+  if (S3TableSmmPtr == 0) {\r
+    Status = mSmst->SmmAllocatePool (\r
+                     EfiRuntimeServicesData,\r
+                     sizeof(SCRIPT_TABLE_PRIVATE_DATA),\r
+                     (VOID **) &S3TableSmmPtr\r
+                     );\r
+    ASSERT_EFI_ERROR (Status);\r
+    mS3BootScriptTableSmmAllocated = TRUE;\r
+\r
+    Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64) (UINTN)S3TableSmmPtr);\r
+    ASSERT_EFI_ERROR (Status);\r
+    ZeroMem (S3TableSmmPtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));\r
+\r
+    //\r
+    // Register SmmExitBootServices and SmmLegacyBoot notification.\r
+    //\r
+    Status = mSmst->SmmRegisterProtocolNotify (\r
+                     &gEdkiiSmmExitBootServicesProtocolGuid,\r
+                     S3BootScriptSmmAtRuntimeCallBack,\r
+                     &mRegistrationSmmExitBootServices\r
+                     );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    Status = mSmst->SmmRegisterProtocolNotify (\r
+                     &gEdkiiSmmLegacyBootProtocolGuid,\r
+                     S3BootScriptSmmAtRuntimeCallBack,\r
+                     &mRegistrationSmmLegacyBoot\r
+                     );\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
+  mS3BootScriptTableSmmPtr = S3TableSmmPtr;\r
+\r
   //\r
-  // Then register event after lock\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
@@ -362,14 +659,14 @@ S3BootScriptGetBootTimeEntryAddAddress (
    \r
    S3TableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(mS3BootScriptTablePtr->TableBase);\r
    if (S3TableBase == 0) {\r
+     //\r
      // The table is not exist. This is the first to add entry. \r
-     // Allocate ACPI script table space under 4G memory. We need it to save\r
-     // some settings done by CSM, which runs after normal script table closed\r
+     // Allocate ACPI script table space under 4G memory.\r
      //\r
      S3TableBase = 0xffffffff;\r
      Status = gBS->AllocatePages (\r
                   AllocateMaxAddress,\r
-                  EfiACPIMemoryNVS,\r
+                  EfiReservedMemoryType,\r
                   2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),\r
                   (EFI_PHYSICAL_ADDRESS*)&S3TableBase\r
                   );\r
@@ -384,6 +681,7 @@ S3BootScriptGetBootTimeEntryAddAddress (
      ScriptTableInfo              = (EFI_BOOT_SCRIPT_TABLE_HEADER*)(UINTN)S3TableBase;\r
      ScriptTableInfo->OpCode      = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;\r
      ScriptTableInfo->Length      = (UINT8) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);\r
+     ScriptTableInfo->Version     = BOOT_SCRIPT_TABLE_VERSION;\r
      ScriptTableInfo->TableLength = 0;   // will be calculate at CloseTable\r
      mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);\r
      mS3BootScriptTablePtr->TableBase = (UINT8*)(UINTN)S3TableBase;\r
@@ -391,16 +689,16 @@ S3BootScriptGetBootTimeEntryAddAddress (
    }\r
      \r
    // Here we do not count the reserved memory for runtime script table.\r
-   PageNumber   = (UINT16)(mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));   \r
+   PageNumber = (UINT16) (mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));\r
    TableLength =  mS3BootScriptTablePtr->TableLength;\r
-   if ((UINT32)(PageNumber * EFI_PAGE_SIZE) < (TableLength + EntryLength)) {\r
+   if ((UINTN) EFI_PAGES_TO_SIZE ((UINTN) PageNumber) < (UINTN) (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {\r
      // \r
      // The buffer is too small to hold the table, Reallocate the buffer\r
      //\r
      NewS3TableBase = 0xffffffff;\r
      Status = gBS->AllocatePages (\r
                   AllocateMaxAddress,\r
-                  EfiACPIMemoryNVS,\r
+                  EfiReservedMemoryType,\r
                   2 + PageNumber + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),\r
                   (EFI_PHYSICAL_ADDRESS*)&NewS3TableBase\r
                   );\r
@@ -436,12 +734,12 @@ S3BootScriptGetBootTimeEntryAddAddress (
    return NewEntryPtr;    \r
 }\r
 /**\r
-  To get the start address from which a new runtime s3 boot script entry will write into.\r
+  To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.\r
   In this case, it should be ensured that there is enough buffer to hold the entry.\r
   \r
   @param EntryLength      the new entry length.\r
   \r
-  @retval the address from which the a new s3 runtime script entry will write into\r
+  @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into\r
  **/\r
 UINT8*\r
 S3BootScriptGetRuntimeEntryAddAddress (\r
@@ -454,7 +752,7 @@ S3BootScriptGetRuntimeEntryAddAddress (
    //\r
    // Check if the memory range reserved for S3 Boot Script table is large enough to hold the node. \r
    //\r
-   if (mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE) <= EFI_PAGES_TO_SIZE((UINT32)(mS3BootScriptTablePtr->TableMemoryPageNumber))) {\r
+   if ((UINTN) (mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE)) <= (UINTN) EFI_PAGES_TO_SIZE ((UINTN) (mS3BootScriptTablePtr->TableMemoryPageNumber))) {\r
      NewEntryPtr = mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength;   \r
      mS3BootScriptTablePtr->TableLength = mS3BootScriptTablePtr->TableLength + EntryLength;\r
      //\r
@@ -464,12 +762,53 @@ S3BootScriptGetRuntimeEntryAddAddress (
    }\r
    return (UINT8*)NewEntryPtr;    \r
 }\r
+\r
+/**\r
+  This function is to restore boot time boot script data from LockBox.\r
+\r
+**/\r
+VOID\r
+RestoreBootTimeDataFromLockBox (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  UINTN         LockBoxLength;\r
+\r
+  //\r
+  // Restore boot time boot script data from LockBox.\r
+  //\r
+  LockBoxLength = mS3BootScriptTablePtr->BootTimeScriptLength;\r
+  Status = RestoreLockBox (\r
+             &mBootScriptDataBootTimeGuid,\r
+             (VOID *) mS3BootScriptTablePtr->TableBase,\r
+             &LockBoxLength\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Update the data to BootScriptData LockBox.\r
+  //\r
+  Status = UpdateLockBox (\r
+             &mBootScriptDataGuid,\r
+             0,\r
+             (VOID *) mS3BootScriptTablePtr->TableBase,\r
+             LockBoxLength\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Update TableLength.\r
+  //\r
+  mS3BootScriptTablePtr->TableLength = (UINT32) (mS3BootScriptTablePtr->BootTimeScriptLength - sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
+}\r
+\r
 /**\r
   To get the start address from which a new s3 boot script entry will write into.\r
   \r
   @param EntryLength      the new entry length.\r
   \r
-  @retval the address from which the a new s3 runtime script entry will write into \r
+  @retval the address from which the a new s3 boot script entry will write into \r
  **/ \r
 UINT8* \r
 S3BootScriptGetEntryAddAddress (\r
@@ -477,56 +816,31 @@ S3BootScriptGetEntryAddAddress (
   )\r
 {\r
   UINT8*                         NewEntryPtr;\r
-  EFI_BOOT_SCRIPT_TABLE_HEADER   TableHeader;\r
-  EFI_STATUS                     Status;\r
 \r
-  if (mS3BootScriptTablePtr->AtRuntime) {\r
+  if (mS3BootScriptTablePtr->SmmLocked) {\r
     //\r
-    // We need check InSmm when AtRuntime, because after SmmReadyToLock, only SMM driver is allowed to write boot script.\r
+    // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.\r
     //\r
     if (!mS3BootScriptTablePtr->InSmm) {\r
       //\r
-      // Add DEBUG ERROR, so that we can find it at boot time.\r
-      // Do not use ASSERT, because we may have test invoke this interface.\r
+      // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.\r
+      // Do not use ASSERT, because we may have test to invoke this interface.\r
       //\r
-      DEBUG ((EFI_D_ERROR, "FATAL ERROR: Set boot script after ReadyToLock!!!\n"));\r
+      DEBUG ((EFI_D_ERROR, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));\r
       return NULL;\r
     }\r
 \r
-    //\r
-    // NOTE: OS will restore ACPINvs data. After S3, the table length in mS3BootScriptTable (SMM) is different with\r
-    // table length in BootScriptTable header (ACPINvs).\r
-    // So here we need sync them. We choose ACPINvs table length, because we want to override the boot script saved\r
-    // in SMM every time.\r
-    //\r
-    ASSERT (mS3BootScriptTablePtr == &mS3BootScriptTable);\r
-    CopyMem ((VOID*)&TableHeader, (VOID*)mS3BootScriptTablePtr->TableBase, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));\r
-    if (mS3BootScriptTablePtr->TableLength + sizeof(EFI_BOOT_SCRIPT_TERMINATE) != TableHeader.TableLength) {\r
+    if (mS3BootScriptTablePtr->BackFromS3) {\r
       //\r
-      // Restore it to use original value\r
+      // Back from S3, restore boot time boot script data from LockBox\r
+      // and set BackFromS3 flag back to FALSE.\r
       //\r
-      RestoreLockBox (&mBootScriptDataGuid, NULL, NULL);\r
-      //\r
-      // Copy it again to get original value\r
-      // NOTE: We should NOT use TableHeader.TableLength, because it is already updated to be whole length.\r
-      //\r
-      mS3BootScriptTablePtr->TableLength = (UINT32)(mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE));\r
+      RestoreBootTimeDataFromLockBox ();\r
+      mS3BootScriptTablePtr->BackFromS3 = FALSE;\r
     }\r
 \r
     NewEntryPtr  = S3BootScriptGetRuntimeEntryAddAddress (EntryLength);\r
-    //\r
-    // Now the length field is updated, need sync to lockbox.\r
-    // So in S3 resume, the data can be restored correctly.\r
-    //\r
-    CopyMem ((VOID*)&TableHeader, (VOID*)mS3BootScriptTablePtr->TableBase, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));\r
-    Status = UpdateLockBox (\r
-               &mBootScriptDataGuid,\r
-               OFFSET_OF(EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),\r
-               &TableHeader.TableLength,\r
-               sizeof(TableHeader.TableLength)\r
-               );\r
-    ASSERT_EFI_ERROR (Status);\r
-  } else {   \r
+  } else {\r
     NewEntryPtr  = S3BootScriptGetBootTimeEntryAddAddress (EntryLength);\r
   }  \r
   return NewEntryPtr;\r
@@ -535,26 +849,52 @@ S3BootScriptGetEntryAddAddress (
 \r
 /**\r
   Sync BootScript LockBox data.\r
+\r
+  @param Script           The address from where the boot script has been added or updated.\r
+\r
 **/\r
 VOID\r
 SyncBootScript (\r
-  VOID\r
+  IN UINT8      *Script\r
   )\r
 {\r
   EFI_STATUS  Status;\r
+  UINT32      ScriptOffset;\r
+  UINT32      TotalScriptLength;\r
 \r
-  if (!mS3BootScriptTablePtr->AtRuntime || !mS3BootScriptTablePtr->InSmm) {\r
+  if (!mS3BootScriptTablePtr->SmmLocked || !mS3BootScriptTablePtr->InSmm) {\r
+    //\r
+    // If it is not after SmmReadyToLock in SMM,\r
+    // just return.\r
+    //\r
     return ;\r
   }\r
+\r
+  ScriptOffset = (UINT32) (Script - mS3BootScriptTablePtr->TableBase);\r
+\r
+  TotalScriptLength = (UINT32) (mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
+\r
   //\r
-  // Update Terminate\r
+  // Update BootScriptData\r
   // So in S3 resume, the data can be restored correctly.\r
   //\r
   Status = UpdateLockBox (\r
              &mBootScriptDataGuid,\r
-             mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE),\r
-             (VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + mLockBoxLength - sizeof(EFI_BOOT_SCRIPT_TERMINATE)),\r
-             sizeof(EFI_BOOT_SCRIPT_TERMINATE)\r
+             ScriptOffset,\r
+             (VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + ScriptOffset),\r
+             TotalScriptLength - ScriptOffset\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Now the length field is updated, need sync to lockbox.\r
+  // So at S3 resume, the data can be restored correctly.\r
+  //\r
+  Status = UpdateLockBox (\r
+             &mBootScriptDataGuid,\r
+             OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),\r
+             &TotalScriptLength,\r
+             sizeof (TotalScriptLength)\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
@@ -577,10 +917,10 @@ SyncBootScript (
   for Framework Spec compatibility.\r
   \r
   If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out \r
-  how to get the script to run on an S3 resume because the boot script maintained by the lib will be \r
+  how to get the script to run at S3 resume because the boot script maintained by the lib will be \r
   destroyed.\r
  \r
-  @return the base address of the new copy of the boot script tble.   \r
+  @return the base address of the new copy of the boot script table.   \r
   @note this function could only called in boot time phase\r
 \r
 **/\r
@@ -675,7 +1015,7 @@ S3BootScriptSaveIoWrite (
   CopyMem ((VOID*)Script, (VOID*)&ScriptIoWrite, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));\r
   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)), Buffer, WidthInByte * Count);\r
 \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -724,7 +1064,7 @@ S3BootScriptSaveIoReadWrite (
   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE)), Data, WidthInByte);\r
   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + WidthInByte), DataMask, WidthInByte);\r
 \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -772,7 +1112,7 @@ S3BootScriptSaveMemWrite (
   CopyMem ((VOID*)Script, (VOID*)&ScriptMemWrite, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));\r
   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)), Buffer, WidthInByte * Count);\r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -820,7 +1160,7 @@ S3BootScriptSaveMemReadWrite (
   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE)), Data, WidthInByte);\r
   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + WidthInByte), DataMask, WidthInByte);\r
 \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -834,6 +1174,8 @@ S3BootScriptSaveMemReadWrite (
 \r
   @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.\r
   @retval RETURN_SUCCESS           Opcode is added.\r
+  @note  A known Limitations in the implementation which is 64bits operations are not supported.\r
+\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
@@ -849,6 +1191,12 @@ S3BootScriptSavePciCfgWrite (
   UINT8                 WidthInByte;\r
   EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE  ScriptPciWrite;\r
 \r
+  if (Width == S3BootScriptWidthUint64 ||\r
+      Width == S3BootScriptWidthFifoUint64 ||\r
+      Width == S3BootScriptWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count));\r
   \r
@@ -868,7 +1216,7 @@ S3BootScriptSavePciCfgWrite (
   CopyMem ((VOID*)Script, (VOID*)&ScriptPciWrite,  sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));\r
   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)), Buffer, WidthInByte * Count);\r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -882,6 +1230,8 @@ S3BootScriptSavePciCfgWrite (
 \r
   @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.\r
   @retval RETURN__SUCCESS           Opcode is added.\r
+  @note  A known Limitations in the implementation which is 64bits operations are not supported.\r
+\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
@@ -897,6 +1247,12 @@ S3BootScriptSavePciCfgReadWrite (
   UINT8                 WidthInByte;\r
   EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE  ScriptPciReadWrite;\r
 \r
+  if (Width == S3BootScriptWidthUint64 ||\r
+      Width == S3BootScriptWidthFifoUint64 ||\r
+      Width == S3BootScriptWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + (WidthInByte * 2));\r
   \r
@@ -920,12 +1276,12 @@ S3BootScriptSavePciCfgReadWrite (
     WidthInByte\r
     );\r
 \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
 /**\r
-  Adds a record for a PCI configuration space modify operation into a specified boot script table.\r
+  Adds a record for a PCI configuration 2 space write operation into a specified boot script table.\r
 \r
   @param Width     The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
   @param Segment   The PCI segment number for Address.\r
@@ -935,6 +1291,8 @@ S3BootScriptSavePciCfgReadWrite (
 \r
   @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.\r
   @retval RETURN_SUCCESS           Opcode is added.\r
+  @note  A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.\r
+\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
@@ -950,7 +1308,14 @@ S3BootScriptSavePciCfg2Write (
   UINT8                *Script;\r
   UINT8                 WidthInByte;\r
   EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE  ScriptPciWrite2;\r
-  \r
+\r
+  if (Segment != 0 ||\r
+      Width == S3BootScriptWidthUint64 ||\r
+      Width == S3BootScriptWidthFifoUint64 ||\r
+      Width == S3BootScriptWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE) + (WidthInByte * Count));\r
   \r
@@ -971,12 +1336,12 @@ S3BootScriptSavePciCfg2Write (
   CopyMem ((VOID*)Script, (VOID*)&ScriptPciWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));\r
   CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE)), Buffer, WidthInByte * Count);\r
 \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
 /**\r
-  Adds a record for a PCI configuration space modify operation into a specified boot script table.\r
+  Adds a record for a PCI configuration space modify operation into a specified boot script table.\r
 \r
   @param Width     The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
   @param Segment   The PCI segment number for Address.\r
@@ -986,6 +1351,8 @@ S3BootScriptSavePciCfg2Write (
 \r
   @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.\r
   @retval RETURN_SUCCESS           Opcode is added.\r
+  @note  A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.\r
+\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
@@ -1001,6 +1368,13 @@ S3BootScriptSavePciCfg2ReadWrite (
   UINT8                *Script;\r
   UINT8                 WidthInByte;\r
   EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE  ScriptPciReadWrite2;\r
+\r
+  if (Segment != 0 ||\r
+      Width == S3BootScriptWidthUint64 ||\r
+      Width == S3BootScriptWidthFifoUint64 ||\r
+      Width == S3BootScriptWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
   \r
   WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + (WidthInByte * 2));\r
@@ -1026,10 +1400,111 @@ S3BootScriptSavePciCfg2ReadWrite (
     WidthInByte\r
     );\r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
+\r
+/**\r
+  Checks the parameter of S3BootScriptSaveSmbusExecute().\r
+\r
+  This function checks the input parameters of SmbusExecute().  If the input parameters are valid\r
+  for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain\r
+  error code based on the input SMBus bus protocol.\r
+\r
+  @param  SmBusAddress            Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, \r
+                                  and PEC.\r
+  @param  Operation               Signifies which particular SMBus hardware protocol instance that\r
+                                  it will use to execute the SMBus transactions. This SMBus\r
+                                  hardware protocol is defined by the SMBus Specification and is\r
+                                  not related to EFI.\r
+  @param  Length                  Signifies the number of bytes that this operation will do. The\r
+                                  maximum number of bytes can be revision specific and operation\r
+                                  specific. This field will contain the actual number of bytes that\r
+                                  are executed for this operation. Not all operations require this\r
+                                  argument.\r
+  @param  Buffer                  Contains the value of data to execute to the SMBus slave device.\r
+                                  Not all operations require this argument. The length of this\r
+                                  buffer is identified by Length.\r
+\r
+  @retval EFI_SUCCESS             All the parameters are valid for the corresponding SMBus bus\r
+                                  protocol. \r
+  @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.\r
+  @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead\r
+                                  and EfiSmbusQuickWrite. Length is outside the range of valid\r
+                                  values.\r
+  @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.\r
+  @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.\r
+\r
+**/\r
+EFI_STATUS\r
+CheckParameters (\r
+  IN     UINTN                    SmBusAddress,\r
+  IN     EFI_SMBUS_OPERATION      Operation,\r
+  IN OUT UINTN                    *Length,\r
+  IN     VOID                     *Buffer\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       RequiredLen;\r
+  EFI_SMBUS_DEVICE_COMMAND Command;\r
+  BOOLEAN                  PecCheck;\r
\r
+  Command      = SMBUS_LIB_COMMAND (SmBusAddress);\r
+  PecCheck     = SMBUS_LIB_PEC (SmBusAddress);\r
+  //\r
+  // Set default value to be 2:\r
+  // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall. \r
+  //\r
+  RequiredLen = 2;\r
+  Status      = EFI_SUCCESS;\r
+  switch (Operation) {\r
+    case EfiSmbusQuickRead:\r
+    case EfiSmbusQuickWrite:\r
+      if (PecCheck || Command != 0) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+      break;\r
+    case EfiSmbusReceiveByte:\r
+    case EfiSmbusSendByte:\r
+      if (Command != 0) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+      //\r
+      // Cascade to check length parameter.\r
+      //\r
+    case EfiSmbusReadByte:\r
+    case EfiSmbusWriteByte:\r
+      RequiredLen = 1;\r
+      //\r
+      // Cascade to check length parameter.\r
+      //\r
+    case EfiSmbusReadWord:\r
+    case EfiSmbusWriteWord:\r
+    case EfiSmbusProcessCall:\r
+      if (Buffer == NULL || Length == NULL) {\r
+        return EFI_INVALID_PARAMETER;\r
+      } else if (*Length < RequiredLen) {\r
+        Status = EFI_BUFFER_TOO_SMALL;\r
+      }\r
+      *Length = RequiredLen;\r
+      break;\r
+    case EfiSmbusReadBlock:\r
+    case EfiSmbusWriteBlock:\r
+    case EfiSmbusBWBRProcessCall:\r
+      if ((Buffer == NULL) || \r
+          (Length == NULL) || \r
+          (*Length < MIN_SMBUS_BLOCK_LEN) ||\r
+          (*Length > MAX_SMBUS_BLOCK_LEN)) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   Adds a record for an SMBus command execution into a specified boot script table.\r
 \r
@@ -1051,11 +1526,24 @@ S3BootScriptSaveSmbusExecute (
   IN  VOID                              *Buffer\r
   )\r
 {\r
+  EFI_STATUS            Status;\r
+  UINTN                 BufferLength;\r
   UINT8                 DataSize;\r
   UINT8                *Script;\r
   EFI_BOOT_SCRIPT_SMBUS_EXECUTE  ScriptSmbusExecute;\r
 \r
-  DataSize = (UINT8)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE) + (*Length));\r
+  if (Length == NULL) {\r
+    BufferLength = 0;\r
+  } else {\r
+    BufferLength = *Length;\r
+  }\r
+\r
+  Status = CheckParameters (SmBusAddress, Operation, &BufferLength, Buffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DataSize = (UINT8)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE) + BufferLength);\r
   \r
   Script = S3BootScriptGetEntryAddAddress (DataSize);\r
   if (Script == NULL) {\r
@@ -1068,16 +1556,16 @@ S3BootScriptSaveSmbusExecute (
   ScriptSmbusExecute.Length       = DataSize;\r
   ScriptSmbusExecute.SmBusAddress = (UINT64) SmBusAddress;\r
   ScriptSmbusExecute.Operation    = Operation;\r
-  ScriptSmbusExecute.DataSize     = (UINT32) *Length;\r
+  ScriptSmbusExecute.DataSize     = (UINT32) BufferLength;\r
 \r
   CopyMem ((VOID*)Script, (VOID*)&ScriptSmbusExecute, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE));\r
   CopyMem (\r
     (VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)),\r
     Buffer,\r
-    (*Length)\r
+    BufferLength\r
     );\r
 \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -1114,12 +1602,12 @@ S3BootScriptSaveStall (
   \r
   CopyMem ((VOID*)Script, (VOID*)&ScriptStall, sizeof (EFI_BOOT_SCRIPT_STALL));\r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
 /**\r
-  Adds a record for an execution stall on the processor into a specified boot script table.\r
+  Adds a record for dispatching specified arbitrary code into a specified boot script table.\r
 \r
   @param EntryPoint   Entry point of the code to be dispatched.\r
   @param Context      Argument to be passed into the EntryPoint of the code to be dispatched.\r
@@ -1153,7 +1641,7 @@ S3BootScriptSaveDispatch2 (
   \r
   CopyMem ((VOID*)Script, (VOID*)&ScriptDispatch2, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));\r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 \r
@@ -1161,7 +1649,12 @@ S3BootScriptSaveDispatch2 (
 /**\r
   Adds a record for memory reads of the memory location and continues when the exit criteria is\r
   satisfied or after a defined duration.\r
-  \r
+\r
+  Please aware, below interface is different with PI specification, Vol 5:\r
+  EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.\r
+  "Duration" below is microseconds, while "Delay" in PI specification means\r
+  the number of 100ns units to poll.\r
+\r
   @param Width     The width of the memory operations.\r
   @param Address   The base address of the memory operations.\r
   @param BitMask   A pointer to the bit mask to be AND-ed with the data read from the register.\r
@@ -1211,7 +1704,7 @@ S3BootScriptSaveMemPoll (
   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + WidthInByte), BitMask, WidthInByte);\r
   CopyMem ((VOID*)Script, (VOID*)&ScriptMemPoll, sizeof (EFI_BOOT_SCRIPT_MEM_POLL)); \r
 \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -1222,7 +1715,6 @@ S3BootScriptSaveMemPoll (
   @param InformationLength   Length of the data in bytes\r
   @param Information       Information to be logged in the boot scrpit\r
  \r
-  @retval RETURN_UNSUPPORTED       If  entering runtime, this method will not support.\r
   @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.\r
   @retval RETURN_SUCCESS           Opcode is added.\r
 \r
@@ -1234,28 +1726,12 @@ S3BootScriptSaveInformation (
   IN  VOID                                 *Information\r
   )\r
 {\r
-  RETURN_STATUS         Status;\r
   UINT8                 Length;\r
   UINT8                 *Script;\r
-  EFI_PHYSICAL_ADDRESS  Buffer;\r
   EFI_BOOT_SCRIPT_INFORMATION  ScriptInformation;\r
 \r
-  if (mS3BootScriptTablePtr->AtRuntime) {\r
-    return RETURN_UNSUPPORTED;\r
-  }\r
-  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION));\r
-  \r
-  Buffer = 0xFFFFFFFF;\r
-  Status = gBS->AllocatePages (\r
-                  AllocateMaxAddress,\r
-                  EfiACPIMemoryNVS,\r
-                  EFI_SIZE_TO_PAGES(InformationLength),\r
-                  &Buffer\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return RETURN_OUT_OF_RESOURCES;\r
-  }\r
-  \r
+  Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);\r
+\r
   Script = S3BootScriptGetEntryAddAddress (Length);\r
   if (Script == NULL) {\r
     return RETURN_OUT_OF_RESOURCES;\r
@@ -1269,10 +1745,11 @@ S3BootScriptSaveInformation (
 \r
   ScriptInformation.InformationLength = InformationLength;  \r
 \r
-  CopyMem ((VOID *)(UINTN)Buffer, Information,(UINTN) InformationLength);  \r
-  ScriptInformation.Information = (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer;\r
-  \r
-  CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));  \r
+  CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));\r
+  CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *) Information, (UINTN) InformationLength);\r
+\r
+  SyncBootScript (Script);\r
+\r
   return RETURN_SUCCESS;\r
 \r
 }\r
@@ -1330,7 +1807,7 @@ S3BootScriptSaveDispatch (
   \r
   CopyMem ((VOID*)Script, (VOID*)&ScriptDispatch, sizeof (EFI_BOOT_SCRIPT_DISPATCH)); \r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 \r
@@ -1387,7 +1864,7 @@ S3BootScriptSaveIoPoll (
   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL)), Data, WidthInByte);\r
   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL) + WidthInByte), DataMask, WidthInByte);\r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -1406,6 +1883,7 @@ S3BootScriptSaveIoPoll (
 \r
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.\r
  @retval RETURN_SUCCESS           Opcode is added.\r
+  @note  A known Limitations in the implementation which is 64bits operations are not supported.\r
 \r
 **/\r
 RETURN_STATUS\r
@@ -1423,6 +1901,12 @@ S3BootScriptSavePciPoll (
   UINT8                    Length;\r
   EFI_BOOT_SCRIPT_PCI_CONFIG_POLL  ScriptPciPoll;\r
 \r
+  if (Width == S3BootScriptWidthUint64 ||\r
+      Width == S3BootScriptWidthFifoUint64 ||\r
+      Width == S3BootScriptWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));\r
   \r
@@ -1443,7 +1927,7 @@ S3BootScriptSavePciPoll (
   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL)), Data, WidthInByte);\r
   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + WidthInByte), DataMask, WidthInByte);\r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -1462,9 +1946,8 @@ S3BootScriptSavePciPoll (
 \r
  @retval RETURN_OUT_OF_RESOURCES  Not enough memory for the table do operation.\r
  @retval RETURN_SUCCESS           Opcode is added.\r
- @note   A known Limitations in the implementation: When interpreting the opcode  EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE\r
-         EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE and EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE, the 'Segment' parameter is assumed as \r
-         Zero, or else, assert.\r
+  @note  A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.\r
+\r
 **/\r
 RETURN_STATUS\r
 EFIAPI\r
@@ -1481,7 +1964,14 @@ S3BootScriptSavePci2Poll (
   UINT8                   *Script;\r
   UINT8                    Length;\r
   EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL  ScriptPci2Poll;\r
-  \r
+\r
+  if (Segment != 0 ||\r
+      Width == S3BootScriptWidthUint64 ||\r
+      Width == S3BootScriptWidthFifoUint64 ||\r
+      Width == S3BootScriptWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));\r
   \r
@@ -1503,7 +1993,7 @@ S3BootScriptSavePci2Poll (
   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL)), Data, WidthInByte);\r
   CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + WidthInByte), DataMask, WidthInByte);\r
   \r
-  SyncBootScript ();\r
+  SyncBootScript (Script);\r
 \r
   return RETURN_SUCCESS;\r
 }\r
@@ -1605,10 +2095,16 @@ S3BootScriptMoveLastOpcode (
   \r
   ValidatePosition = FALSE;\r
   TempPosition = (Position == NULL) ? NULL:(*Position);\r
-  Script = mS3BootScriptTablePtr->TableBase;\r
-  if (Script == 0) {    \r
-    return EFI_OUT_OF_RESOURCES;\r
+\r
+  //\r
+  // Check that the script is initialized and synced without adding an entry to the script.\r
+  //\r
+  Script = S3BootScriptGetEntryAddAddress (0);\r
+  if (Script == NULL) {\r
+    return RETURN_OUT_OF_RESOURCES;\r
   }\r
+  Script = mS3BootScriptTablePtr->TableBase;\r
+\r
   StartAddress  = (UINTN) Script;\r
   TableLength   = mS3BootScriptTablePtr->TableLength;\r
   Script        = Script + sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);\r
@@ -1651,7 +2147,10 @@ S3BootScriptMoveLastOpcode (
   //\r
   // Copy the node to Boot script table\r
   //\r
-  CopyMem((VOID*)Script, (VOID*)TempBootScriptEntry, ScriptHeader.Length); \r
+  CopyMem((VOID*)Script, (VOID*)TempBootScriptEntry, ScriptHeader.Length);\r
+\r
+  SyncBootScript (Script);\r
+\r
   //\r
   // return out the Position\r
   //\r
@@ -1689,7 +2188,6 @@ S3BootScriptLabelInternal (
 {\r
   UINT8                 Length;\r
   UINT8                 *Script;\r
-  VOID                  *Buffer;\r
   EFI_BOOT_SCRIPT_INFORMATION  ScriptInformation;\r
  \r
   Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);\r
@@ -1698,7 +2196,6 @@ S3BootScriptLabelInternal (
   if (Script == NULL) {\r
     return RETURN_OUT_OF_RESOURCES;\r
   }\r
-  Buffer =  Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);\r
   //\r
   // Build script data\r
   //\r
@@ -1708,11 +2205,11 @@ S3BootScriptLabelInternal (
 \r
   ScriptInformation.InformationLength = InformationLength;  \r
 \r
-  AsciiStrnCpy (Buffer, Information,(UINTN) InformationLength);  \r
-  ScriptInformation.Information = (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer;\r
-  \r
-  CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));  \r
-  \r
+  CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));\r
+  CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *) Information, (UINTN) InformationLength);\r
+\r
+  SyncBootScript (Script);\r
+\r
   return S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);\r
 \r
 }\r
@@ -1754,15 +2251,21 @@ S3BootScriptLabel (
   EFI_BOOT_SCRIPT_TABLE_HEADER   TableHeader;\r
   UINT32                         LabelLength;\r
   //\r
-  // Assume Label is not NULL\r
+  // Check NULL Label\r
+  //\r
+  if (Label == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Check empty Label\r
   //\r
if (Label == NULL) {\r
 if (Label[0] == '\0') {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   \r
   //\r
-  // Check that the script is initialized without adding an entry to the script.\r
-  // The code must search for the label first befor it knows if a new entry needs\r
+  // Check that the script is initialized and synced without adding an entry to the script.\r
+  // The code must search for the label first before it knows if a new entry needs\r
   // to be added.\r
   //\r
   Script = S3BootScriptGetEntryAddAddress (0);\r
@@ -1825,20 +2328,23 @@ S3BootScriptCompare (
   UINT8*                    Script;\r
   UINT32                    TableLength; \r
 \r
-  Script = mS3BootScriptTablePtr->TableBase;\r
-  if (Script == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
   if (RelativePosition == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  TableLength = ((EFI_BOOT_SCRIPT_TABLE_HEADER*)Script)->TableLength;\r
+\r
   //\r
-  // If in boot time, TableLength does not include the termination node. so add it up \r
+  // Check that the script is initialized and synced without adding an entry to the script.\r
   //\r
-  if (!mS3BootScriptTablePtr->AtRuntime) {\r
-    TableLength += sizeof(EFI_BOOT_SCRIPT_TERMINATE);\r
+  Script = S3BootScriptGetEntryAddAddress (0);\r
+  if (Script == NULL) {\r
+    return RETURN_OUT_OF_RESOURCES;\r
   }\r
+  Script = mS3BootScriptTablePtr->TableBase;\r
+\r
+  //\r
+  // mS3BootScriptTablePtr->TableLength does not include the termination node, so add it up\r
+  //\r
+  TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);\r
   if (Position1 < Script || Position1 > Script+TableLength) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r