]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg: Add S3Resume2Pei PEIM
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 29 Aug 2011 22:19:13 +0000 (22:19 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 29 Aug 2011 22:19:13 +0000 (22:19 +0000)
Signed-off-by: jljusten
Reviewed-by: mdkinney
Reviewed-by: rsun3
Reviewed-by: jyao1
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12227 6f19259b-4bc3-4df7-8a09-765794883524

UefiCpuPkg/UefiCpuPkg.dsc
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c [new file with mode: 0644]
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf [new file with mode: 0644]

index bf966b6c892bea7745ba0872f00b9d8f8663543e..d4a81755b8891dbe4c55a18d52d328f96ab1d4ad 100644 (file)
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf\r
   PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf\r
   PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf\r
+  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf\r
+  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
+  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf\r
+  LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf\r
+  ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf  \r
 \r
 [LibraryClasses.common.PEIM]\r
   MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf\r
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf\r
+  LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf\r
 \r
 [LibraryClasses.IA32.PEIM, LibraryClasses.X64.PEIM]\r
   PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf\r
@@ -78,4 +85,5 @@
   UefiCpuPkg/Library/MtrrLib/MtrrLib.inf\r
   UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf\r
   UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf\r
+  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf\r
 \r
diff --git a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
new file mode 100644 (file)
index 0000000..3242876
--- /dev/null
@@ -0,0 +1,925 @@
+/** @file\r
+  This module produces the EFI_PEI_S3_RESUME_PPI.\r
+  This module works with StandAloneBootScriptExecutor to S3 resume to OS.\r
+  This module will excute the boot script saved during last boot and after that,\r
+  control is passed to OS waking up handler.\r
+\r
+  Copyright (c) 2006 - 2011, 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
+  of the BSD License which accompanies this distribution.  The\r
+  full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Guid/AcpiS3Context.h>\r
+#include <Guid/BootScriptExecutorVariable.h>\r
+#include <Guid/Performance.h>\r
+#include <Ppi/ReadOnlyVariable2.h>\r
+#include <Ppi/S3Resume2.h>\r
+#include <Ppi/SmmAccess.h>\r
+#include <Ppi/PostBootScriptTable.h>\r
+#include <Ppi/EndOfPeiPhase.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/PeimEntryPoint.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/PeiServicesTablePointerLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+#include <Library/LocalApicLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/LockBoxLib.h>\r
+#include <IndustryStandard/Acpi.h>\r
+\r
+#pragma pack(1)\r
+typedef union {\r
+  struct {\r
+    UINT32  LimitLow    : 16;\r
+    UINT32  BaseLow     : 16;\r
+    UINT32  BaseMid     : 8;\r
+    UINT32  Type        : 4;\r
+    UINT32  System      : 1;\r
+    UINT32  Dpl         : 2;\r
+    UINT32  Present     : 1;\r
+    UINT32  LimitHigh   : 4;\r
+    UINT32  Software    : 1;\r
+    UINT32  Reserved    : 1;\r
+    UINT32  DefaultSize : 1;\r
+    UINT32  Granularity : 1;\r
+    UINT32  BaseHigh    : 8;\r
+  } Bits;\r
+  UINT64  Uint64;\r
+} IA32_GDT;\r
+\r
+//\r
+// Page-Map Level-4 Offset (PML4) and\r
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory\r
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write\r
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User\r
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching\r
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached\r
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)\r
+    UINT64  Reserved:1;               // Reserved\r
+    UINT64  MustBeZero:2;             // Must Be Zero\r
+    UINT64  Available:3;              // Available for use by system software\r
+    UINT64  PageTableBaseAddress:40;  // Page Table Base Address\r
+    UINT64  AvabilableHigh:11;        // Available for use by system software\r
+    UINT64  Nx:1;                     // No Execute bit\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} PAGE_MAP_AND_DIRECTORY_POINTER;\r
+\r
+//\r
+// Page Table Entry 2MB\r
+//\r
+typedef union {\r
+  struct {\r
+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory\r
+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write\r
+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User\r
+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching\r
+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached\r
+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)\r
+    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page\r
+    UINT64  MustBe1:1;                // Must be 1 \r
+    UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write\r
+    UINT64  Available:3;              // Available for use by system software\r
+    UINT64  PAT:1;                    //\r
+    UINT64  MustBeZero:8;             // Must be zero;\r
+    UINT64  PageTableBaseAddress:31;  // Page Table Base Address\r
+    UINT64  AvabilableHigh:11;        // Available for use by system software\r
+    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution\r
+  } Bits;\r
+  UINT64    Uint64;\r
+} PAGE_TABLE_ENTRY;\r
+\r
+#pragma pack()\r
+\r
+//\r
+// Function prototypes\r
+//\r
+/**\r
+  a ASM function to transfer control to OS.\r
+  \r
+  @param  S3WakingVector  The S3 waking up vector saved in ACPI Facs table\r
+  @param  AcpiLowMemoryBase a buffer under 1M which could be used during the transfer             \r
+**/\r
+typedef\r
+VOID\r
+(EFIAPI *ASM_TRANSFER_CONTROL) (\r
+  IN   UINT32           S3WakingVector,\r
+  IN   UINT32           AcpiLowMemoryBase\r
+  );\r
+\r
+/**\r
+  Restores the platform to its preboot configuration for an S3 resume and\r
+  jumps to the OS waking vector.\r
+\r
+  This function will restore the platform to its pre-boot configuration that was\r
+  pre-stored in the boot script table and transfer control to OS waking vector.\r
+  Upon invocation, this function is responsible for locating the following\r
+  information before jumping to OS waking vector:\r
+    - ACPI tables\r
+    - boot script table\r
+    - any other information that it needs\r
+\r
+  The S3RestoreConfig() function then executes the pre-stored boot script table\r
+  and transitions the platform to the pre-boot state. The boot script is recorded\r
+  during regular boot using the EFI_S3_SAVE_STATE_PROTOCOL.Write() and\r
+  EFI_S3_SMM_SAVE_STATE_PROTOCOL.Write() functions.  Finally, this function\r
+  transfers control to the OS waking vector. If the OS supports only a real-mode\r
+  waking vector, this function will switch from flat mode to real mode before\r
+  jumping to the waking vector.  If all platform pre-boot configurations are\r
+  successfully restored and all other necessary information is ready, this\r
+  function will never return and instead will directly jump to the OS waking\r
+  vector. If this function returns, it indicates that the attempt to resume\r
+  from the ACPI S3 sleep state failed.\r
+\r
+  @param[in] This         Pointer to this instance of the PEI_S3_RESUME_PPI\r
+\r
+  @retval EFI_ABORTED     Execution of the S3 resume boot script table failed.\r
+  @retval EFI_NOT_FOUND   Some necessary information that is used for the S3\r
+                          resume boot path could not be located.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+S3RestoreConfig2 (\r
+  IN EFI_PEI_S3_RESUME2_PPI  *This\r
+  );\r
+\r
+//\r
+// Globals\r
+//\r
+EFI_PEI_S3_RESUME2_PPI      mS3ResumePpi = { S3RestoreConfig2 };\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPpiList = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEfiPeiS3Resume2PpiGuid,\r
+  &mS3ResumePpi\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPpiListPostScriptTable = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gPeiPostScriptTablePpiGuid,\r
+  0\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPpiListEndOfPeiTable = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEfiEndOfPeiSignalPpiGuid,\r
+  0\r
+};\r
+\r
+//\r
+// Global Descriptor Table (GDT)\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {\r
+/* selector { Global Segment Descriptor                              } */\r
+/* 0x00 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},\r
+/* 0x08 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},\r
+/* 0x10 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}},\r
+/* 0x18 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}},\r
+/* 0x20 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},\r
+/* 0x28 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 0,  1,  0}},\r
+/* 0x30 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 0,  1,  0}},\r
+/* 0x38 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  1, 0,  1,  0}},\r
+/* 0x40 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},\r
+};\r
+\r
+//\r
+// IA32 Gdt register\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR mGdt = {\r
+  sizeof (mGdtEntries) - 1,\r
+  (UINTN) mGdtEntries\r
+  };\r
+\r
+/**\r
+  Performance measure function to get S3 detailed performance data.\r
+\r
+  This function will getS3 detailed performance data and saved in pre-reserved ACPI memory.\r
+**/\r
+VOID\r
+WriteToOsS3PerformanceData (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                                    Status;\r
+  EFI_PHYSICAL_ADDRESS                          mAcpiLowMemoryBase;\r
+  PERF_HEADER                                   *PerfHeader;\r
+  PERF_DATA                                     *PerfData;\r
+  UINT64                                        Ticker;\r
+  UINTN                                         Index;\r
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI               *VariableServices;\r
+  UINTN                                         VarSize;\r
+  UINTN                                         LogEntryKey;\r
+  CONST VOID                                    *Handle;\r
+  CONST CHAR8                                   *Token;\r
+  CONST CHAR8                                   *Module;\r
+  UINT64                                        StartTicker;\r
+  UINT64                                        EndTicker;\r
+  UINT64                                        StartValue;\r
+  UINT64                                        EndValue;\r
+  BOOLEAN                                       CountUp;\r
+  UINT64                                        Freq;\r
+\r
+  //\r
+  // Retrive time stamp count as early as possilbe\r
+  //\r
+  Ticker = GetPerformanceCounter ();\r
+\r
+  Freq   = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
+\r
+  Freq   = DivU64x32 (Freq, 1000);\r
+\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiReadOnlyVariable2PpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **) &VariableServices\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  VarSize   = sizeof (EFI_PHYSICAL_ADDRESS);\r
+  Status = VariableServices->GetVariable (\r
+                               VariableServices,\r
+                               L"PerfDataMemAddr",\r
+                               &gPerformanceProtocolGuid,\r
+                               NULL,\r
+                               &VarSize,\r
+                               &mAcpiLowMemoryBase\r
+                               );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Fail to retrieve variable to log S3 performance data \n"));\r
+    return;\r
+  }\r
+\r
+  PerfHeader = (PERF_HEADER *) (UINTN) mAcpiLowMemoryBase;\r
+\r
+  if (PerfHeader->Signiture != PERFORMANCE_SIGNATURE) {\r
+    DEBUG ((EFI_D_ERROR, "Performance data in ACPI memory get corrupted! \n"));\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Record total S3 resume time.\r
+  //\r
+  if (EndValue >= StartValue) {\r
+    PerfHeader->S3Resume = Ticker - StartValue;\r
+    CountUp              = TRUE;\r
+  } else {\r
+    PerfHeader->S3Resume = StartValue - Ticker;\r
+    CountUp              = FALSE;\r
+  }\r
+\r
+  //\r
+  // Get S3 detailed performance data\r
+  //\r
+  Index = 0;\r
+  LogEntryKey = 0;\r
+  while ((LogEntryKey = GetPerformanceMeasurement (\r
+                          LogEntryKey,\r
+                          &Handle,\r
+                          &Token,\r
+                          &Module,\r
+                          &StartTicker,\r
+                          &EndTicker)) != 0) {\r
+    if (EndTicker != 0) {\r
+      PerfData = &PerfHeader->S3Entry[Index];\r
+\r
+      //\r
+      // Use File Handle to specify the different performance log for PEIM.\r
+      // File Handle is the base address of PEIM FFS file.\r
+      //\r
+      if ((AsciiStrnCmp (Token, "PEIM", PEI_PERFORMANCE_STRING_SIZE) == 0) && (Handle != NULL)) {\r
+        AsciiSPrint (PerfData->Token, PERF_TOKEN_LENGTH, "0x%11p", Handle);\r
+      } else {\r
+        AsciiStrnCpy (PerfData->Token, Token, PERF_TOKEN_LENGTH);\r
+      }\r
+      if (StartTicker == 1) {\r
+        StartTicker = StartValue;\r
+      }\r
+      if (EndTicker == 1) {\r
+        EndTicker = StartValue;\r
+      }\r
+      Ticker = CountUp? (EndTicker - StartTicker) : (StartTicker - EndTicker);\r
+      PerfData->Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);\r
+\r
+      //\r
+      // Only Record > 1ms performance data so that more big performance can be recorded.\r
+      //\r
+      if ((Ticker > Freq) && (++Index >= PERF_PEI_ENTRY_MAX_NUM)) {\r
+        //\r
+        // Reach the maximum number of PEI performance log entries.\r
+        //\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  PerfHeader->S3EntryNum = (UINT32) Index;\r
+}\r
+\r
+/**\r
+  Jump to OS waking vector.\r
+  The function will install boot script done PPI, report S3 resume status code, and then jump to OS waking vector.\r
+\r
+  @param  AcpiS3Context                 a pointer to a structure of ACPI_S3_CONTEXT\r
+  @param  PeiS3ResumeState              a pointer to a structure of PEI_S3_RESUME_STATE\r
+**/\r
+VOID\r
+EFIAPI\r
+S3ResumeBootOs (\r
+  IN ACPI_S3_CONTEXT                *AcpiS3Context,\r
+  IN PEI_S3_RESUME_STATE            *PeiS3ResumeState\r
+  )\r
+{\r
+  EFI_STATUS                                    Status;\r
+  EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;\r
+  ASM_TRANSFER_CONTROL                          AsmTransferControl;\r
+  UINTN                                         TempStackTop;\r
+  UINTN                                         TempStack[0x10];\r
+\r
+  //\r
+  // Restore IDT\r
+  //\r
+  AsmWriteIdtr (&PeiS3ResumeState->Idtr);\r
+\r
+  //\r
+  // Install BootScriptDonePpi\r
+  //\r
+  Status = PeiServicesInstallPpi (&mPpiListPostScriptTable);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get ACPI Table Address\r
+  //\r
+  Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable));\r
+\r
+  if ((Facs == NULL) ||\r
+      (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||\r
+      ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)) ) {\r
+    CpuDeadLoop ();\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // report status code on S3 resume\r
+  //\r
+  REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE);\r
+\r
+  //\r
+  // Install EndOfPeiPpi\r
+  //\r
+  Status = PeiServicesInstallPpi (&mPpiListEndOfPeiTable);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  PERF_CODE (\r
+    WriteToOsS3PerformanceData ();\r
+    );\r
+\r
+  AsmTransferControl = (ASM_TRANSFER_CONTROL)(UINTN)PeiS3ResumeState->AsmTransferControl;\r
+  if (Facs->XFirmwareWakingVector != 0) {\r
+    //\r
+    // Switch to native waking vector\r
+    //\r
+    TempStackTop = (UINTN)&TempStack + sizeof(TempStack);\r
+    if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
+        ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&\r
+        ((Facs->Flags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0)) {\r
+      //\r
+      // X64 long mode waking vector\r
+      //\r
+      DEBUG (( EFI_D_ERROR, "Transfer to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));\r
+      if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+        AsmEnablePaging64 (\r
+          0x38,\r
+          Facs->XFirmwareWakingVector,\r
+          0,\r
+          0,\r
+          (UINT64)(UINTN)TempStackTop\r
+          );\r
+      } else {\r
+        DEBUG (( EFI_D_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));\r
+        ASSERT (FALSE);\r
+      }\r
+    } else {\r
+      //\r
+      // IA32 protected mode waking vector (Page disabled)\r
+      //\r
+      DEBUG (( EFI_D_ERROR, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));\r
+      SwitchStack (\r
+        (SWITCH_STACK_ENTRY_POINT) (UINTN) Facs->XFirmwareWakingVector,\r
+        NULL,\r
+        NULL,\r
+        (VOID *)(UINTN)TempStackTop\r
+        );\r
+    }\r
+  } else {\r
+    //\r
+    // 16bit Realmode waking vector\r
+    //\r
+    DEBUG (( EFI_D_ERROR, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));\r
+    AsmTransferControl (Facs->FirmwareWakingVector, 0x0);\r
+  }\r
+\r
+  //\r
+  // Never run to here\r
+  //\r
+  CpuDeadLoop();\r
+}\r
+\r
+/**\r
+  Restore S3 page table because we do not trust ACPINvs content.\r
+  If BootScriptExector driver will not run in 64-bit mode, this function will do nothing. \r
+\r
+  @param S3NvsPageTableAddress   PageTableAddress in ACPINvs\r
+**/\r
+VOID\r
+RestoreS3PageTables (\r
+  IN UINTN                                         S3NvsPageTableAddress\r
+  )\r
+{\r
+  if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+    UINT32                                        RegEax;\r
+    UINT8                                         PhysicalAddressBits;\r
+    EFI_PHYSICAL_ADDRESS                          PageAddress;\r
+    UINTN                                         IndexOfPml4Entries;\r
+    UINTN                                         IndexOfPdpEntries;\r
+    UINTN                                         IndexOfPageDirectoryEntries;\r
+    UINT64                                        NumberOfPml4EntriesNeeded;\r
+    UINT64                                        NumberOfPdpEntriesNeeded;\r
+    PAGE_MAP_AND_DIRECTORY_POINTER                *PageMapLevel4Entry;\r
+    PAGE_MAP_AND_DIRECTORY_POINTER                *PageMap;\r
+    PAGE_MAP_AND_DIRECTORY_POINTER                *PageDirectoryPointerEntry;\r
+    PAGE_TABLE_ENTRY                              *PageDirectoryEntry;\r
+\r
+    //\r
+    // NOTE: We have to ASSUME the page table generation format, because we do not know whole page table information.\r
+    // The whole page table is too large to be saved in SMRAM.\r
+    //\r
+    // The assumption is : whole page table is allocated in CONTINOUS memory and CR3 points to TOP page.\r
+    //\r
+    DEBUG ((EFI_D_ERROR, "S3NvsPageTableAddress - %x\n", S3NvsPageTableAddress));\r
+\r
+    //\r
+    // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it.\r
+    //\r
+    PageMap = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;\r
+    S3NvsPageTableAddress += SIZE_4KB;\r
+    \r
+    //\r
+    // Get physical address bits supported.\r
+    //\r
+    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+    if (RegEax >= 0x80000008) {\r
+      AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+      PhysicalAddressBits = (UINT8) RegEax;\r
+    } else {\r
+      PhysicalAddressBits = 36;\r
+    }\r
+    \r
+    //\r
+    // Calculate the table entries needed.\r
+    //\r
+    if (PhysicalAddressBits <= 39) {\r
+      NumberOfPml4EntriesNeeded = 1;\r
+      NumberOfPdpEntriesNeeded = LShiftU64 (1, (PhysicalAddressBits - 30));\r
+    } else {\r
+      NumberOfPml4EntriesNeeded = LShiftU64 (1, (PhysicalAddressBits - 39));\r
+      NumberOfPdpEntriesNeeded = 512;\r
+    }\r
+    \r
+    PageMapLevel4Entry = PageMap;\r
+    PageAddress        = 0;\r
+    for (IndexOfPml4Entries = 0; IndexOfPml4Entries < NumberOfPml4EntriesNeeded; IndexOfPml4Entries++, PageMapLevel4Entry++) {\r
+      //\r
+      // Each PML4 entry points to a page of Page Directory Pointer entires.\r
+      // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.\r
+      //\r
+      PageDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER *)S3NvsPageTableAddress;\r
+      S3NvsPageTableAddress += SIZE_4KB;\r
+    \r
+      //\r
+      // Make a PML4 Entry\r
+      //\r
+      PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry;\r
+      PageMapLevel4Entry->Bits.ReadWrite = 1;\r
+      PageMapLevel4Entry->Bits.Present = 1;\r
+    \r
+      for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
+        //\r
+        // Each Directory Pointer entries points to a page of Page Directory entires.\r
+        // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
+        //       \r
+        PageDirectoryEntry = (PAGE_TABLE_ENTRY *)S3NvsPageTableAddress;\r
+        S3NvsPageTableAddress += SIZE_4KB;\r
+    \r
+        //\r
+        // Fill in a Page Directory Pointer Entries\r
+        //\r
+        PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry;\r
+        PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
+        PageDirectoryPointerEntry->Bits.Present = 1;\r
+    \r
+        for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {\r
+          //\r
+          // Fill in the Page Directory entries\r
+          //\r
+          PageDirectoryEntry->Uint64 = (UINT64)PageAddress;\r
+          PageDirectoryEntry->Bits.ReadWrite = 1;\r
+          PageDirectoryEntry->Bits.Present = 1;\r
+          PageDirectoryEntry->Bits.MustBe1 = 1;\r
+        }\r
+      }\r
+    }\r
+    return ;\r
+  } else {\r
+       //\r
+       // If DXE is running 32-bit mode, no need to establish page table.\r
+       //\r
+    return ;\r
+  }\r
+}\r
+\r
+/**\r
+  Jump to boot script executor driver.\r
+\r
+  The function will close and lock SMRAM and then jump to boot script execute driver to executing S3 boot script table.\r
+\r
+  @param  AcpiS3Context                 a pointer to a structure of ACPI_S3_CONTEXT\r
+  @param  EfiBootScriptExecutorVariable The function entry to executing S3 boot Script table. This function is build in\r
+                                        boot script execute driver\r
+**/\r
+VOID\r
+EFIAPI\r
+S3ResumeExecuteBootScript (\r
+  IN ACPI_S3_CONTEXT                *AcpiS3Context,\r
+  IN BOOT_SCRIPT_EXECUTOR_VARIABLE  *EfiBootScriptExecutorVariable\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  PEI_SMM_ACCESS_PPI         *SmmAccess;\r
+  UINTN                      Index;\r
+  VOID                       *GuidHob;\r
+  IA32_DESCRIPTOR            *IdtDescriptor;\r
+  VOID                       *IdtBuffer;\r
+  PEI_S3_RESUME_STATE        *PeiS3ResumeState;\r
+\r
+  DEBUG ((EFI_D_ERROR, "S3ResumeExecuteBootScript()\n"));\r
+\r
+  //\r
+  // Attempt to use content from SMRAM first\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
+  if (GuidHob != NULL) {\r
+    //\r
+    // Last step for SMM - send SMI for initialization\r
+    //\r
+\r
+    //\r
+    // Send SMI to APs\r
+    //    \r
+    SendSmiIpiAllExcludingSelf ();\r
+    //\r
+    // Send SMI to BSP\r
+    //\r
+    SendSmiIpi (GetApicId ());\r
+\r
+    Status = PeiServicesLocatePpi (\r
+                              &gPeiSmmAccessPpiGuid,\r
+                              0,\r
+                              NULL,\r
+                              (VOID **) &SmmAccess\r
+                              );\r
+\r
+    DEBUG ((EFI_D_ERROR, "Close all SMRAM regions before executing boot script\n"));\r
+\r
+    for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
+      Status = SmmAccess->Close ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+    }\r
+\r
+    DEBUG ((EFI_D_ERROR, "Lock all SMRAM regions before executing boot script\n"));\r
+\r
+    for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
+      Status = SmmAccess->Lock ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+    }\r
+  }\r
+\r
+  if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+    //\r
+    // Need reconstruct page table here, since we do not trust ACPINvs.\r
+    //\r
+    RestoreS3PageTables ((UINTN)AcpiS3Context->S3NvsPageTableAddress);\r
+    AsmWriteCr3 ((UINTN)AcpiS3Context->S3NvsPageTableAddress);\r
+  }\r
+\r
+  if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
+    //\r
+    // On some platform, such as ECP, a dispatch node in boot script table may execute a 32-bit PEIM which may need PeiServices\r
+    // pointer. So PeiServices need preserve in (IDTBase- sizeof (UINTN)). \r
+    //\r
+    IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);\r
+    //\r
+    // Make sure the newly allcated IDT align with 16-bytes\r
+    // \r
+    IdtBuffer = AllocatePages (EFI_SIZE_TO_PAGES((IdtDescriptor->Limit + 1) + 16));\r
+    ASSERT (IdtBuffer != NULL);\r
+    CopyMem ((VOID*)((UINT8*)IdtBuffer + 16),(VOID*)(IdtDescriptor->Base), (IdtDescriptor->Limit + 1));\r
+    IdtDescriptor->Base = (UINTN)((UINT8*)IdtBuffer + 16);\r
+    *(UINTN*)(IdtDescriptor->Base - sizeof(UINTN)) = (UINTN)GetPeiServicesTablePointer ();\r
+  }\r
+\r
+  //\r
+  // Need to make sure the GDT is loaded with values that support long mode and real mode.\r
+  //\r
+  AsmWriteGdtr (&mGdt);\r
+\r
+  //\r
+  // Prepare data for return back\r
+  //\r
+  PeiS3ResumeState = AllocatePool (sizeof(*PeiS3ResumeState));\r
+  ASSERT (PeiS3ResumeState != NULL);\r
+  DEBUG (( EFI_D_ERROR, "PeiS3ResumeState - %x\r\n", PeiS3ResumeState));\r
+  PeiS3ResumeState->ReturnCs           = 0x10;\r
+  PeiS3ResumeState->ReturnEntryPoint   = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeBootOs;\r
+  PeiS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;\r
+  //\r
+  // Save IDT\r
+  //\r
+  AsmReadIdtr (&PeiS3ResumeState->Idtr);\r
+\r
+  if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+    //\r
+    // X64 S3 Resume\r
+    //\r
+    DEBUG (( EFI_D_ERROR, "Enable X64 and transfer control to Standalone Boot Script Executor\r\n"));\r
+\r
+    //\r
+    // Switch to long mode to complete resume.\r
+    //\r
+    AsmEnablePaging64 (\r
+      0x38,\r
+      EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint,\r
+      (UINT64)(UINTN)AcpiS3Context,\r
+      (UINT64)(UINTN)PeiS3ResumeState,\r
+      (UINT64)(UINTN)(AcpiS3Context->BootScriptStackBase + AcpiS3Context->BootScriptStackSize)\r
+      );\r
+  } else {\r
+    //\r
+    // IA32 S3 Resume\r
+    //\r
+    DEBUG (( EFI_D_ERROR, "transfer control to Standalone Boot Script Executor\r\n"));\r
+    SwitchStack (\r
+      (SWITCH_STACK_ENTRY_POINT) (UINTN) EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint,\r
+      (VOID *)AcpiS3Context,\r
+      (VOID *)PeiS3ResumeState,\r
+      (VOID *)(UINTN)(AcpiS3Context->BootScriptStackBase + AcpiS3Context->BootScriptStackSize)\r
+      );\r
+  }\r
+\r
+  //\r
+  // Never run to here\r
+  //\r
+  CpuDeadLoop();\r
+}\r
+/**\r
+  Restores the platform to its preboot configuration for an S3 resume and\r
+  jumps to the OS waking vector.\r
+\r
+  This function will restore the platform to its pre-boot configuration that was\r
+  pre-stored in the boot script table and transfer control to OS waking vector.\r
+  Upon invocation, this function is responsible for locating the following\r
+  information before jumping to OS waking vector:\r
+    - ACPI tables\r
+    - boot script table\r
+    - any other information that it needs\r
+\r
+  The S3RestoreConfig() function then executes the pre-stored boot script table\r
+  and transitions the platform to the pre-boot state. The boot script is recorded\r
+  during regular boot using the EFI_S3_SAVE_STATE_PROTOCOL.Write() and\r
+  EFI_S3_SMM_SAVE_STATE_PROTOCOL.Write() functions.  Finally, this function\r
+  transfers control to the OS waking vector. If the OS supports only a real-mode\r
+  waking vector, this function will switch from flat mode to real mode before\r
+  jumping to the waking vector.  If all platform pre-boot configurations are\r
+  successfully restored and all other necessary information is ready, this\r
+  function will never return and instead will directly jump to the OS waking\r
+  vector. If this function returns, it indicates that the attempt to resume\r
+  from the ACPI S3 sleep state failed.\r
+\r
+  @param[in] This         Pointer to this instance of the PEI_S3_RESUME_PPI\r
+\r
+  @retval EFI_ABORTED     Execution of the S3 resume boot script table failed.\r
+  @retval EFI_NOT_FOUND   Some necessary information that is used for the S3\r
+                          resume boot path could not be located.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+S3RestoreConfig2 (\r
+  IN EFI_PEI_S3_RESUME2_PPI  *This\r
+  )\r
+{\r
+  EFI_STATUS                                    Status;\r
+  PEI_SMM_ACCESS_PPI                            *SmmAccess;\r
+  UINTN                                         Index;\r
+  ACPI_S3_CONTEXT                               *AcpiS3Context;\r
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI               *VariableServices;\r
+  EFI_PHYSICAL_ADDRESS                          TempEfiBootScriptExecutorVariable;\r
+  EFI_PHYSICAL_ADDRESS                          TempAcpiS3Context;\r
+  BOOT_SCRIPT_EXECUTOR_VARIABLE                 *EfiBootScriptExecutorVariable;\r
+  UINTN                                         VarSize;\r
+  EFI_SMRAM_DESCRIPTOR                          *SmramDescriptor;\r
+  SMM_S3_RESUME_STATE                           *SmmS3ResumeState;\r
+  VOID                                          *GuidHob;\r
+\r
+  DEBUG ((EFI_D_ERROR, "Enter S3 PEIM\r\n"));\r
+\r
+  Status = PeiServicesLocatePpi (\r
+                            &gPeiSmmAccessPpiGuid,\r
+                            0,\r
+                            NULL,\r
+                            (VOID **) &SmmAccess\r
+                            );\r
+  for (Index = 0; !EFI_ERROR (Status); Index++) {\r
+    Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);\r
+  }\r
+\r
+  Status = PeiServicesLocatePpi (\r
+                            &gEfiPeiReadOnlyVariable2PpiGuid,\r
+                            0,\r
+                            NULL,\r
+                            (VOID **) &VariableServices\r
+                            );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  VarSize = sizeof (EFI_PHYSICAL_ADDRESS);\r
+  Status = RestoreLockBox (\r
+             &gEfiAcpiVariableGuid,\r
+             &TempAcpiS3Context,\r
+             &VarSize\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  AcpiS3Context = (ACPI_S3_CONTEXT *)(UINTN)TempAcpiS3Context;\r
+  ASSERT (AcpiS3Context != NULL);\r
+\r
+  Status = RestoreLockBox (\r
+             &gEfiAcpiS3ContextGuid,\r
+             NULL,\r
+             NULL\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  VarSize   = sizeof (TempEfiBootScriptExecutorVariable);\r
+  Status = RestoreLockBox (\r
+             &gEfiBootScriptExecutorVariableGuid,\r
+             &TempEfiBootScriptExecutorVariable,\r
+             &VarSize\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = RestoreLockBox (\r
+             &gEfiBootScriptExecutorContextGuid,\r
+             NULL,\r
+             NULL\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *) (UINTN) TempEfiBootScriptExecutorVariable;\r
+\r
+  DEBUG (( EFI_D_ERROR, "AcpiS3Context = %x\n", AcpiS3Context));\r
+  DEBUG (( EFI_D_ERROR, "Waking Vector = %x\n", ((EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) ((UINTN) (AcpiS3Context->AcpiFacsTable)))->FirmwareWakingVector));\r
+  DEBUG (( EFI_D_ERROR, "AcpiS3Context->AcpiFacsTable = %x\n", AcpiS3Context->AcpiFacsTable));\r
+  DEBUG (( EFI_D_ERROR, "AcpiS3Context->S3NvsPageTableAddress = %x\n", AcpiS3Context->S3NvsPageTableAddress));\r
+  DEBUG (( EFI_D_ERROR, "AcpiS3Context->S3DebugBufferAddress = %x\n", AcpiS3Context->S3DebugBufferAddress));\r
+  DEBUG (( EFI_D_ERROR, "EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = %x\n", EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint));\r
+\r
+  //\r
+  // Additional step for BootScript integrity - we only handle BootScript and BootScriptExecutor.\r
+  // Script dispatch image and context (parameter) are handled by platform.\r
+  // We just use restore all lock box in place, no need restore one by one.\r
+  //\r
+  Status = RestoreAllLockBoxInPlace ();\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (EFI_ERROR (Status)) {\r
+    // Something wrong\r
+    CpuDeadLoop ();\r
+  }\r
+\r
+  //\r
+  // Attempt to use content from SMRAM first\r
+  //\r
+  GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);\r
+  if (GuidHob != NULL) {\r
+    SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);\r
+    SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;\r
+\r
+    SmmS3ResumeState->ReturnCs           = AsmReadCs ();\r
+    SmmS3ResumeState->ReturnEntryPoint   = (EFI_PHYSICAL_ADDRESS)(UINTN)S3ResumeExecuteBootScript;\r
+    SmmS3ResumeState->ReturnContext1     = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;\r
+    SmmS3ResumeState->ReturnContext2     = (EFI_PHYSICAL_ADDRESS)(UINTN)EfiBootScriptExecutorVariable;\r
+    SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)&Status;\r
+\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Signature                = %x\n", SmmS3ResumeState->Signature));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Stack Base               = %x\n", SmmS3ResumeState->SmmS3StackBase));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Stack Size               = %x\n", SmmS3ResumeState->SmmS3StackSize));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Resume Entry Point       = %x\n", SmmS3ResumeState->SmmS3ResumeEntryPoint));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 CR0                      = %x\n", SmmS3ResumeState->SmmS3Cr0));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 CR3                      = %x\n", SmmS3ResumeState->SmmS3Cr3));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 CR4                      = %x\n", SmmS3ResumeState->SmmS3Cr4));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Return CS                = %x\n", SmmS3ResumeState->ReturnCs));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Return Entry Point       = %x\n", SmmS3ResumeState->ReturnEntryPoint));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Return Context1          = %x\n", SmmS3ResumeState->ReturnContext1));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Return Context2          = %x\n", SmmS3ResumeState->ReturnContext2));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Return Stack Pointer     = %x\n", SmmS3ResumeState->ReturnStackPointer));\r
+    DEBUG (( EFI_D_ERROR, "SMM S3 Smst                     = %x\n", SmmS3ResumeState->Smst));\r
+\r
+    //\r
+    // Disable interrupt of Debug timer.\r
+    //\r
+    SaveAndSetDebugTimerInterrupt (FALSE);\r
+\r
+    if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) {\r
+      SwitchStack (\r
+        (SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->SmmS3ResumeEntryPoint,\r
+        (VOID *)AcpiS3Context,\r
+        0,\r
+        (VOID *)(UINTN)(SmmS3ResumeState->SmmS3StackBase + SmmS3ResumeState->SmmS3StackSize)\r
+        );\r
+    }\r
+    if (SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) {\r
+      //\r
+      // Switch to long mode to complete resume.\r
+      //\r
+\r
+      //\r
+      // Need to make sure the GDT is loaded with values that support long mode and real mode.\r
+      //\r
+      AsmWriteGdtr (&mGdt);\r
+      AsmWriteCr3 ((UINTN)SmmS3ResumeState->SmmS3Cr3);\r
+      AsmEnablePaging64 (\r
+        0x38,\r
+        SmmS3ResumeState->SmmS3ResumeEntryPoint,\r
+        (UINT64)(UINTN)AcpiS3Context,\r
+        0,\r
+        SmmS3ResumeState->SmmS3StackBase + SmmS3ResumeState->SmmS3StackSize\r
+        );\r
+    }\r
+\r
+  }\r
+\r
+  S3ResumeExecuteBootScript (AcpiS3Context, EfiBootScriptExecutorVariable );\r
+  return EFI_SUCCESS;\r
+}\r
+/**\r
+  Main entry for S3 Resume PEIM.\r
+\r
+  This routine is to install EFI_PEI_S3_RESUME2_PPI.\r
+  \r
+  @param  FileHandle              Handle of the file being invoked.\r
+  @param  PeiServices             Pointer to PEI Services table.\r
+\r
+  @retval EFI_SUCCESS S3Resume Ppi is installed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeimS3ResumeEntryPoint (\r
+  IN EFI_PEI_FILE_HANDLE       FileHandle,\r
+  IN CONST EFI_PEI_SERVICES    **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Install S3 Resume Ppi\r
+  //\r
+  Status = (**PeiServices).InstallPpi (PeiServices, &mPpiList);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
new file mode 100644 (file)
index 0000000..58e2398
--- /dev/null
@@ -0,0 +1,79 @@
+## @file\r
+# S3 Resume Module:\r
+# This module works with StandAloneBootScriptExecutor to S3 resume to OS.\r
+# This module will excute the boot script saved during last boot and after that,\r
+# control is passed to OS waking up handler.\r
+#\r
+# Copyright (c) 2010 - 2011, 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
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = S3Resume2Pei\r
+  FILE_GUID                      = 89E549B0-7CFE-449d-9BA3-10D8B2312D71\r
+  MODULE_TYPE                    = PEIM\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = PeimS3ResumeEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64\r
+#\r
+\r
+[Sources]\r
+  S3Resume.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  PeiServicesTablePointerLib\r
+  PerformanceLib\r
+  HobLib\r
+  PeiServicesLib\r
+  PeimEntryPoint\r
+  TimerLib\r
+  BaseLib\r
+  DebugLib\r
+  PcdLib\r
+  IoLib\r
+  BaseMemoryLib\r
+  MemoryAllocationLib\r
+  DebugAgentLib\r
+  LocalApicLib\r
+  ReportStatusCodeLib\r
+  LockBoxLib\r
+  PrintLib\r
+\r
+[Guids]\r
+  gEfiBootScriptExecutorVariableGuid            # SOMETIMES_CONSUMED\r
+  gEfiBootScriptExecutorContextGuid             # SOMETIMES_CONSUMED\r
+  gPerformanceProtocolGuid                      # ALWAYS_CONSUMED L"PerfDataMemAddr"\r
+  gEfiAcpiVariableGuid                          # ALWAYS_CONSUMED  Hob: GUID_EXTENSION\r
+  gEfiAcpiS3ContextGuid                         # ALWAYS_CONSUMED\r
+\r
+[Ppis]\r
+  gEfiPeiReadOnlyVariable2PpiGuid                # PPI ALWAYS_CONSUMED\r
+  gEfiPeiS3Resume2PpiGuid                        # PPI ALWAYS_PRODUCED\r
+  gPeiSmmAccessPpiGuid                           # PPI ALWAYS_CONSUMED\r
+  gPeiPostScriptTablePpiGuid                     # PPI ALWAYS_PRODUCED\r
+  gEfiEndOfPeiSignalPpiGuid                      # PPI ALWAYS_PRODUCED\r
+\r
+[FeaturePcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport\r
+\r
+[Depex]\r
+  gEfiPeiReadOnlyVariable2PpiGuid\r