]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Add BootScriptExecutorDxe driver
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 29 Aug 2011 22:18:19 +0000 (22:18 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 29 Aug 2011 22:18:19 +0000 (22:18 +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@12225 6f19259b-4bc3-4df7-8a09-765794883524

12 files changed:
MdeModulePkg/Include/Guid/BootScriptExecutorVariable.h [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.S [new file with mode: 0644]
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.asm [new file with mode: 0644]
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c [new file with mode: 0644]
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c [new file with mode: 0644]
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h [new file with mode: 0644]
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S [new file with mode: 0644]
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.asm [new file with mode: 0644]
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c [new file with mode: 0644]

diff --git a/MdeModulePkg/Include/Guid/BootScriptExecutorVariable.h b/MdeModulePkg/Include/Guid/BootScriptExecutorVariable.h
new file mode 100644 (file)
index 0000000..420ccea
--- /dev/null
@@ -0,0 +1,49 @@
+/** @file\r
+  Define Name, GUID and data format for an EFI Variable that is used to save the entry point\r
+  of a code segment which will be loaded and executed by a standalone boot script \r
+  executor on S3 boot path.\r
+\r
+  Copyright (c) 2006 - 2010, 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
+#ifndef _BOOT_SCRIPT_EXECUTOR_VARIABLE_H_\r
+#define _BOOT_SCRIPT_EXECUTOR_VARIABLE_H_\r
+\r
+#define EFI_BOOT_SCRIPT_EXECUTOR_VARIABLE_GUID \\r
+  { \\r
+    0x3079818c, 0x46d4, 0x4a73, {0xae, 0xf3, 0xe3, 0xe4, 0x6c, 0xf1, 0xee, 0xdb} \\r
+  }\r
+\r
+//\r
+// The following structure boosts performance by combining structure all ACPI related variables into one.\r
+//\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  EFI_PHYSICAL_ADDRESS  BootScriptExecutorEntrypoint;\r
+} BOOT_SCRIPT_EXECUTOR_VARIABLE;\r
+\r
+#pragma pack()\r
+\r
+#define BOOT_SCRIPT_EXECUTOR_VARIABLE_NAME  L"BootScriptExecutorVariable"\r
+\r
+extern EFI_GUID gEfiBootScriptExecutorVariableGuid;\r
+\r
+#define EFI_BOOT_SCRIPT_EXECUTOR_CONTEXT_GUID \\r
+  { \\r
+    0x79cb58c4, 0xac51, 0x442f, {0xaf, 0xd7, 0x98, 0xe4, 0x7d, 0x2e, 0x99, 0x8} \\r
+  }\r
+\r
+extern EFI_GUID gEfiBootScriptExecutorContextGuid;\r
+\r
+#endif\r
index 5207fb4903115a6ad4537be0300b85eab80fb272..746d6b33b5c829b815c2009c2a3e4a101bf6e987 100644 (file)
   ## Include/Guid/AcpiS3Context.h\r
   gEfiAcpiS3ContextGuid              = { 0xef98d3a, 0x3e33, 0x497a, { 0xa4, 0x1, 0x77, 0xbe, 0x3e, 0xb7, 0x4f, 0x38 }}\r
 \r
+  ## Include/Guid/BootScriptExecutorVariable.h\r
+  gEfiBootScriptExecutorVariableGuid = { 0x3079818c, 0x46d4, 0x4a73, { 0xae, 0xf3, 0xe3, 0xe4, 0x6c, 0xf1, 0xee, 0xdb }}\r
+  gEfiBootScriptExecutorContextGuid  = { 0x79cb58c4, 0xac51, 0x442f, { 0xaf, 0xd7, 0x98, 0xe4, 0x7d, 0x2e, 0x99, 0x8 }}\r
+\r
 [Ppis]\r
   ## Include/Ppi/AtaController.h\r
   gPeiAtaControllerPpiGuid       = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}\r
index 859b2664f7c98d98ba020c6ddc84e47179d83478..1a97ef29e08e09bd4be108787fe87d609254d95c 100644 (file)
@@ -87,6 +87,8 @@
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf\r
   PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf\r
   ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf\r
+  SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf\r
+  S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf\r
 \r
 [LibraryClasses.EBC.PEIM]\r
   IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf\r
   MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.inf\r
   MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf\r
   MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf\r
+  MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf\r
 \r
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
new file mode 100644 (file)
index 0000000..0869c9d
--- /dev/null
@@ -0,0 +1,83 @@
+## @file\r
+# Boot Script Executor Module\r
+#\r
+# This is a standalone Boot Script Executor. Standalone means it does not\r
+# depends on any PEI or DXE service.\r
+#\r
+# Copyright (c) 2006 - 2010, 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                      = BootScriptExecutorDxe\r
+  FILE_GUID                      = FA20568B-548B-4b2b-81EF-1BA08D4A3CEC\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+\r
+  ENTRY_POINT                    = BootScriptExecutorEntryPoint\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
+  ScriptExecute.h\r
+  ScriptExecute.c\r
+\r
+[Sources.X64]\r
+  X64/SetIdtEntry.c  \r
+  X64/S3Asm.asm\r
+  X64/S3Asm.S\r
+  \r
+[Sources.Ia32]\r
+  IA32/SetIdtEntry.c   \r
+  IA32/S3Asm.asm\r
+  IA32/S3Asm.S\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  TimerLib\r
+  PcdLib\r
+  BaseMemoryLib\r
+  SmbusLib\r
+  UefiDriverEntryPoint\r
+  BaseLib\r
+  PciLib\r
+  IoLib\r
+  S3BootScriptLib\r
+  PeCoffLib\r
+  DxeServicesLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  CacheMaintenanceLib\r
+  PerformanceLib\r
+  UefiLib\r
+  DebugAgentLib\r
+  LockBoxLib\r
+\r
+[Guids]\r
+  gEfiBootScriptExecutorVariableGuid\r
+  gEfiBootScriptExecutorContextGuid\r
+  gPerformanceProtocolGuid\r
+  gEfiEventExitBootServicesGuid\r
+\r
+[FeaturePcd]\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode\r
+\r
+[Depex]\r
+  gEfiLockBoxProtocolGuid\r
+\r
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.S b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.S
new file mode 100644 (file)
index 0000000..21516d5
--- /dev/null
@@ -0,0 +1,66 @@
+## @file\r
+#\r
+# Copyright (c) 2010, 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
+#-----------------------------------------\r
+#VOID\r
+#AsmTransferControl (\r
+#  IN   UINT32           S3WakingVector,\r
+#  IN   UINT32           AcpiLowMemoryBase\r
+#  );\r
+#-----------------------------------------\r
+\r
+ASM_GLOBAL ASM_PFX(AsmTransferControl)\r
+ASM_PFX(AsmTransferControl):\r
+    # S3WakingVector    :DWORD\r
+    # AcpiLowMemoryBase :DWORD\r
+    pushl %ebp\r
+    movl  %esp,%ebp\r
+    leal  LABLE, %eax\r
+    pushl $0x28             # CS\r
+    pushl %eax\r
+    movl  8(%ebp),%ecx\r
+    shrdl $20,%ecx,%ebx\r
+    andl  $0xf,%ecx\r
+    movw  %cx,%bx\r
+    movl  %ebx, jmp_addr\r
+    lret\r
+LABLE: \r
+    .byte 0xb8,0x30,0       # mov ax, 30h as selector\r
+    movw  %ax,%ds\r
+    movw  %ax,%es\r
+    movw  %ax,%fs\r
+    movw  %ax,%gs\r
+    movw  %ax,%ss\r
+    movl  %cr0, %eax        # Get control register 0  \r
+    .byte 0x66\r
+    .byte 0x83,0xe0,0xfe    # and    eax, 0fffffffeh  ; Clear PE bit (bit #0)\r
+    .byte 0xf,0x22,0xc0     # mov    cr0, eax         ; Activate real mode\r
+    .byte 0xea              # jmp far @jmp_addr\r
+jmp_addr: \r
+    .long    0\r
+\r
+ASM_GLOBAL ASM_PFX(AsmTransferControl32)\r
+ASM_PFX(AsmTransferControl32):\r
+    jmp ASM_PFX(AsmTransferControl)\r
+\r
+# dummy\r
+ASM_GLOBAL ASM_PFX(AsmTransferControl16)\r
+ASM_PFX(AsmTransferControl16):\r
+ASM_GLOBAL ASM_PFX(AsmFixAddress16)\r
+ASM_PFX(AsmFixAddress16):\r
+    .long    0\r
+ASM_GLOBAL ASM_PFX(AsmJmpAddr32)\r
+ASM_PFX(AsmJmpAddr32):\r
+    .long    0\r
+\r
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.asm b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.asm
new file mode 100644 (file)
index 0000000..710546e
--- /dev/null
@@ -0,0 +1,71 @@
+;; @file\r
+;   This is the assembly code for transferring to control to OS S3 waking vector\r
+;   for IA32 platform\r
+;\r
+; Copyright (c) 2006, 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 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
+    .586P\r
+    .model  flat,C\r
+    .code\r
+\r
+EXTERNDEF   AsmFixAddress16:DWORD\r
+EXTERNDEF   AsmJmpAddr32:DWORD\r
+   \r
+;-----------------------------------------\r
+;VOID\r
+;AsmTransferControl (\r
+;  IN   UINT32           S3WakingVector,\r
+;  IN   UINT32           AcpiLowMemoryBase\r
+;  );\r
+;-----------------------------------------\r
+   \r
+AsmTransferControl  PROC\r
+    ; S3WakingVector    :DWORD\r
+    ; AcpiLowMemoryBase :DWORD\r
+    push  ebp\r
+    mov   ebp, esp    \r
+    lea   eax, @F\r
+    push  28h               ; CS\r
+    push  eax\r
+    mov   ecx, [ebp + 8]\r
+    shrd  ebx, ecx, 20\r
+    and   ecx, 0fh          \r
+    mov   bx, cx          \r
+    mov   @jmp_addr, ebx\r
+    retf\r
+@@:\r
+    DB    0b8h, 30h, 0      ; mov ax, 30h as selector\r
+    mov   ds, ax\r
+    mov   es, ax\r
+    mov   fs, ax\r
+    mov   gs, ax\r
+    mov   ss, ax\r
+    mov   eax, cr0          ; Get control register 0  \r
+    DB    66h\r
+    DB    83h, 0e0h, 0feh   ; and    eax, 0fffffffeh  ; Clear PE bit (bit #0)\r
+    DB    0fh, 22h, 0c0h    ; mov    cr0, eax         ; Activate real mode\r
+    DB    0eah              ; jmp far @jmp_addr\r
+@jmp_addr DD  ?\r
+\r
+AsmTransferControl  ENDP\r
+\r
+AsmTransferControl32  PROC\r
+  jmp AsmTransferControl\r
+AsmTransferControl32  ENDP\r
+\r
+; dummy\r
+AsmTransferControl16  PROC\r
+AsmFixAddress16  DD ?\r
+AsmJmpAddr32 DD  ?\r
+AsmTransferControl16  ENDP\r
+\r
+    END
\ No newline at end of file
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c
new file mode 100644 (file)
index 0000000..8221be6
--- /dev/null
@@ -0,0 +1,63 @@
+/** @file\r
+  Set a IDT entry for debug purpose\r
+\r
+  Set a IDT entry for interrupt vector 3 for debug purpose for IA32 platform\r
+\r
+Copyright (c) 2006 - 2010, 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 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
+#include "ScriptExecute.h"\r
+//\r
+// INTERRUPT_GATE_DESCRIPTOR and SetIdtEntry () are used to setup IDT to do debug\r
+//\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  UINT16  OffsetLow;\r
+  UINT16  SegmentSelector;\r
+  UINT16  Attributes;\r
+  UINT16  OffsetHigh;\r
+} INTERRUPT_GATE_DESCRIPTOR;\r
+\r
+#define INTERRUPT_GATE_ATTRIBUTE   0x8e00\r
+\r
+#pragma pack()\r
+/**\r
+  Set a IDT entry for interrupt vector 3 for debug purpose.\r
+\r
+  @param  AcpiS3Context  a pointer to a structure of ACPI_S3_CONTEXT\r
+\r
+**/\r
+VOID\r
+SetIdtEntry (\r
+  IN ACPI_S3_CONTEXT     *AcpiS3Context\r
+  )\r
+{\r
+  INTERRUPT_GATE_DESCRIPTOR                     *IdtEntry;\r
+  IA32_DESCRIPTOR                               *IdtDescriptor;\r
+  UINTN                                         S3DebugBuffer;\r
+\r
+  //\r
+  // Restore IDT for debug\r
+  //\r
+  IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);\r
+  IdtEntry = (INTERRUPT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (INTERRUPT_GATE_DESCRIPTOR)));\r
+  S3DebugBuffer = (UINTN) (AcpiS3Context->S3DebugBufferAddress);\r
+\r
+  IdtEntry->OffsetLow       = (UINT16)S3DebugBuffer;\r
+  IdtEntry->SegmentSelector = (UINT16)AsmReadCs ();;\r
+  IdtEntry->Attributes      = (UINT16)INTERRUPT_GATE_ATTRIBUTE;\r
+  IdtEntry->OffsetHigh      = (UINT16)(S3DebugBuffer >> 16);\r
+\r
+  AsmWriteIdtr (IdtDescriptor);\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
new file mode 100644 (file)
index 0000000..d4d2a93
--- /dev/null
@@ -0,0 +1,477 @@
+/** @file\r
+  This is the code for Boot Script Executer module.\r
+\r
+  This driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory\r
+  in the entry point. The functionality is to interpret and restore the S3 boot script\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 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
+#include "ScriptExecute.h"\r
+\r
+EFI_PHYSICAL_ADDRESS  mPerfDataMemAddress;\r
+UINT64                mS3BootScriptEntryTick;\r
+UINT64                mScriptStartTick;\r
+UINT64                mScriptEndTick;\r
+\r
+EFI_GUID              mBootScriptExecutorImageGuid = {\r
+  0x9a8d3433, 0x9fe8, 0x42b6, 0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b\r
+};\r
+\r
+/**\r
+  The event callback is used to get the base address of boot performance data structure on\r
+  LegacyBoot event and ExitBootServices event.\r
+\r
+  @param  Event    The event handle.\r
+  @param  Context  The event context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OnBootEvent (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN      VarSize;\r
+\r
+  VarSize = sizeof (EFI_PHYSICAL_ADDRESS);\r
+  Status = gRT->GetVariable (\r
+                  L"PerfDataMemAddr",\r
+                  &gPerformanceProtocolGuid,\r
+                  NULL,\r
+                  &VarSize,\r
+                  &mPerfDataMemAddress\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    mPerfDataMemAddress = 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Record S3 Script execution time and adjust total S3 resume time for script running.\r
+**/\r
+VOID\r
+WriteToOsS3PerformanceData (\r
+  VOID\r
+  )\r
+{\r
+  UINT64               Ticker;\r
+  UINT64               StartValue;\r
+  UINT64               EndValue;\r
+  UINT64               Freq;\r
+  UINT64               ScriptExecuteTicks;\r
+  PERF_HEADER          *PerfHeader;\r
+  PERF_DATA            *PerfData;\r
+\r
+  Ticker = GetPerformanceCounter ();\r
+\r
+  PerfHeader = (PERF_HEADER *)(UINTN)mPerfDataMemAddress;\r
+  if (PerfHeader == NULL) {\r
+    return;\r
+  }\r
+\r
+  Freq   = GetPerformanceCounterProperties (&StartValue, &EndValue);\r
+  Freq   = DivU64x32 (Freq, 1000);\r
+\r
+  if (EndValue >= StartValue) {\r
+    ScriptExecuteTicks = mScriptEndTick - mScriptStartTick;\r
+    PerfHeader->S3Resume += Ticker - mS3BootScriptEntryTick;\r
+  } else {\r
+    ScriptExecuteTicks = mScriptStartTick - mScriptEndTick;\r
+    PerfHeader->S3Resume += mS3BootScriptEntryTick - Ticker;\r
+  }\r
+  if (PerfHeader->S3EntryNum < PERF_PEI_ENTRY_MAX_NUM) {\r
+    PerfData = &PerfHeader->S3Entry[PerfHeader->S3EntryNum];\r
+    PerfData->Duration = (UINT32) DivU64x32 (ScriptExecuteTicks, (UINT32) Freq);;\r
+    AsciiStrnCpy (PerfData->Token, "ScriptExec", PERF_TOKEN_LENGTH);\r
+    PerfHeader->S3EntryNum++;\r
+  }\r
+}\r
+\r
+/**\r
+  Entry function of Boot script exector. This function will be executed in\r
+  S3 boot path.\r
+  This function should not return, because it is invoked by switch stack.\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
+  @retval EFI_INVALID_PARAMETER - OS waking vector not found\r
+  @retval EFI_UNSUPPORTED - something wrong when we resume to OS\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+S3BootScriptExecutorEntryFunction (\r
+  IN ACPI_S3_CONTEXT       *AcpiS3Context,\r
+  IN PEI_S3_RESUME_STATE   *PeiS3ResumeState\r
+  )\r
+{\r
+  EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;\r
+  EFI_STATUS                                    Status;\r
+  UINTN                                         TempStackTop;\r
+  UINTN                                         TempStack[0x10];\r
+  UINTN                                         AsmTransferControl16Address;\r
+\r
+  PERF_CODE (\r
+    mS3BootScriptEntryTick = GetPerformanceCounter ();\r
+    );\r
+\r
+  //\r
+  // Disable interrupt of Debug timer, since new IDT table cannot handle it.\r
+  //\r
+  SaveAndSetDebugTimerInterrupt (FALSE);\r
+\r
+  //\r
+  // Restore IDT for debug\r
+  //\r
+  SetIdtEntry (AcpiS3Context);\r
+\r
+  //\r
+  // Initialize Debug Agent to support source level debug in S3 path.\r
+  //\r
+  InitializeDebugAgent (DEBUG_AGENT_INIT_S3, NULL, NULL);\r
+\r
+  //\r
+  // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL\r
+  // for that parameter.\r
+  //\r
+  PERF_CODE (\r
+    mScriptStartTick = GetPerformanceCounter ();\r
+    );\r
+  Status = S3BootScriptExecute ();\r
+  PERF_CODE (\r
+    mScriptEndTick = GetPerformanceCounter ();\r
+    );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  AsmWbinvd ();\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 EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume.\r
+  //\r
+  if (PeiS3ResumeState != 0) {\r
+    if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+      //\r
+      // X64 S3 Resume\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));\r
+      PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl32;\r
+\r
+      //\r
+      // more step needed - because relative address is handled differently between X64 and IA32.\r
+      //\r
+      AsmTransferControl16Address = (UINTN)AsmTransferControl16;\r
+      AsmFixAddress16 = (UINT32)AsmTransferControl16Address;\r
+      AsmJmpAddr32 = (UINT32)((Facs->FirmwareWakingVector & 0xF) | ((Facs->FirmwareWakingVector & 0xFFFF0) << 12));\r
+\r
+      AsmDisablePaging64 (\r
+        PeiS3ResumeState->ReturnCs,\r
+        (UINT32)PeiS3ResumeState->ReturnEntryPoint,\r
+        (UINT32)(UINTN)AcpiS3Context,\r
+        (UINT32)(UINTN)PeiS3ResumeState,\r
+        (UINT32)PeiS3ResumeState->ReturnStackPointer\r
+        );\r
+    } else {\r
+      //\r
+      // IA32 S3 Resume\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));\r
+      PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl;\r
+\r
+      SwitchStack (\r
+        (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint,\r
+        (VOID *)(UINTN)AcpiS3Context,\r
+        (VOID *)(UINTN)PeiS3ResumeState,\r
+        (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer\r
+        );\r
+    }\r
+\r
+    //\r
+    // Never run to here\r
+    //\r
+    CpuDeadLoop();\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  PERF_CODE (\r
+    WriteToOsS3PerformanceData ();\r
+    );\r
+\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
+        SwitchStack (\r
+          (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,\r
+          NULL,\r
+          NULL,\r
+          (VOID *)(UINTN)TempStackTop\r
+          );\r
+      } else {\r
+        // Unsupported for 32bit DXE, 64bit OS vector\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
+      if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
+        AsmDisablePaging64 (\r
+          0x10,\r
+          (UINT32)Facs->XFirmwareWakingVector,\r
+          0,\r
+          0,\r
+          (UINT32)TempStackTop\r
+          );\r
+      } else {\r
+        SwitchStack (\r
+          (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,\r
+          NULL,\r
+          NULL,\r
+          (VOID *)(UINTN)TempStackTop\r
+          );\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
+  return EFI_UNSUPPORTED;\r
+}\r
+/**\r
+  Entrypoint of Boot script exector driver, this function will be executed in\r
+  normal boot phase and invoked by DXE dispatch.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurs when executing this entry point.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootScriptExecutorEntryPoint (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  UINT8                                         *Buffer;\r
+  UINTN                                         BufferSize;\r
+  UINTN                                         Pages;\r
+  EFI_PHYSICAL_ADDRESS                          FfsBuffer;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT                  ImageContext;\r
+  BOOT_SCRIPT_EXECUTOR_VARIABLE                 *EfiBootScriptExecutorVariable;\r
+  EFI_PHYSICAL_ADDRESS                          BootScriptExecutorBuffer;\r
+  EFI_STATUS                                    Status;\r
+  VOID                                          *DevicePath;\r
+  EFI_HANDLE                                    NewImageHandle;\r
+\r
+  //\r
+  // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry\r
+  // point is loaded by DXE code which is the first time loaded. or else, it is already\r
+  // be reloaded be itself.This is a work-around\r
+  //\r
+  Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);\r
+  if (EFI_ERROR (Status)) {\r
+\r
+      //\r
+      // This is the first-time loaded by DXE core. reload itself to NVS mem\r
+      //\r
+      //\r
+      // A workarouond: Here we install a dummy handle\r
+      //\r
+      NewImageHandle = NULL;\r
+      Status = gBS->InstallProtocolInterface (\r
+                  &NewImageHandle,\r
+                  &gEfiCallerIdGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  NULL\r
+                  );\r
+\r
+      Status = GetSectionFromAnyFv  (\r
+                 &gEfiCallerIdGuid,\r
+                 EFI_SECTION_PE32,\r
+                 0,\r
+                 (VOID **) &Buffer,\r
+                 &BufferSize\r
+                 );\r
+      ImageContext.Handle    = Buffer;\r
+      ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
+      //\r
+      // Get information about the image being loaded\r
+      //\r
+      Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+      Pages = EFI_SIZE_TO_PAGES(BufferSize + ImageContext.SectionAlignment);\r
+      FfsBuffer = 0xFFFFFFFF;\r
+      Status = gBS->AllocatePages (\r
+                    AllocateMaxAddress,\r
+                    EfiACPIMemoryNVS,\r
+                    Pages,\r
+                    &FfsBuffer\r
+                    );\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;\r
+      //\r
+      // Align buffer on section boundry\r
+      //\r
+      ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
+      ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);\r
+      //\r
+      // Load the image to our new buffer\r
+      //\r
+      Status = PeCoffLoaderLoadImage (&ImageContext);\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->FreePages (FfsBuffer, Pages);\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Relocate the image in our new buffer\r
+      //\r
+      Status = PeCoffLoaderRelocateImage (&ImageContext);\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        PeCoffLoaderUnloadImage (&ImageContext);\r
+        gBS->FreePages (FfsBuffer, Pages);\r
+        return Status;\r
+      }\r
+      //\r
+      // Flush the instruction cache so the image data is written before we execute it\r
+      //\r
+      InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
+      Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->FreePages (FfsBuffer, Pages);\r
+        return Status;\r
+      }\r
+      //\r
+      // Additional step for BootScript integrity\r
+      // Save BootScriptExecutor image\r
+      //\r
+      Status = SaveLockBox (\r
+                 &mBootScriptExecutorImageGuid,\r
+                 (VOID *)(UINTN)ImageContext.ImageAddress,\r
+                 (UINTN)ImageContext.ImageSize\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+    } else {\r
+      //\r
+      // the entry point is invoked after reloading. following code only run in  ACPI NVS\r
+      //\r
+      BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);\r
+\r
+      BootScriptExecutorBuffer = 0xFFFFFFFF;\r
+      Pages = EFI_SIZE_TO_PAGES(BufferSize);\r
+      Status = gBS->AllocatePages (\r
+                      AllocateMaxAddress,\r
+                      EfiACPIMemoryNVS,\r
+                      Pages,\r
+                      &BootScriptExecutorBuffer\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer;\r
+      EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN) S3BootScriptExecutorEntryFunction ;\r
+\r
+      Status = SaveLockBox (\r
+                 &gEfiBootScriptExecutorVariableGuid,\r
+                 &BootScriptExecutorBuffer,\r
+                 sizeof(BootScriptExecutorBuffer)\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      //\r
+      // Additional step for BootScript integrity\r
+      // Save BootScriptExecutor context\r
+      //\r
+      Status = SaveLockBox (\r
+                 &gEfiBootScriptExecutorContextGuid,\r
+                 EfiBootScriptExecutorVariable,\r
+                 sizeof(*EfiBootScriptExecutorVariable)\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      PERF_CODE (\r
+        EFI_EVENT Event;\r
+\r
+        gBS->CreateEventEx (\r
+              EVT_NOTIFY_SIGNAL,\r
+              TPL_NOTIFY,\r
+              OnBootEvent,\r
+              NULL,\r
+              &gEfiEventExitBootServicesGuid,\r
+              &Event\r
+              );\r
+\r
+        EfiCreateEventLegacyBootEx(\r
+          TPL_NOTIFY,\r
+          OnBootEvent,\r
+          NULL,\r
+          &Event\r
+          );\r
+        );\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h
new file mode 100644 (file)
index 0000000..6a97b77
--- /dev/null
@@ -0,0 +1,88 @@
+/** @file\r
+  The header file for Boot Script Executer module.\r
+  \r
+  This driver is dispatched by Dxe core and the driver will reload itself to ACPI NVS memory \r
+  in the entry point. The functionality is to interpret and restore the S3 boot script \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 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
+#ifndef _BOOT_SCRIPT_EXECUTOR_H_\r
+#define _BOOT_SCRIPT_EXECUTOR_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/S3BootScriptLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/DxeServicesLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/CacheMaintenanceLib.h>\r
+#include <Library/PerformanceLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+#include <Library/LockBoxLib.h>\r
+\r
+#include <Guid/AcpiS3Context.h>\r
+#include <Guid/BootScriptExecutorVariable.h>\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/Performance.h>\r
+#include <IndustryStandard/Acpi.h>\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
+VOID\r
+AsmTransferControl (\r
+  IN   UINT32           S3WakingVector,\r
+  IN   UINT32           AcpiLowMemoryBase\r
+  );\r
+/**\r
+  a 32bit 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
+VOID\r
+AsmTransferControl32 (\r
+  IN   UINT32           S3WakingVector,\r
+  IN   UINT32           AcpiLowMemoryBase\r
+  );\r
+/**\r
+  a 16bit ASM function to transfer control to OS.\r
+**/\r
+VOID\r
+AsmTransferControl16 (\r
+  VOID\r
+  );\r
+/**\r
+  Set a IDT entry for interrupt vector 3 for debug purpose.  \r
+  \r
+  @param  AcpiS3Context  a pointer to a structure of ACPI_S3_CONTEXT  \r
+              \r
+**/\r
+VOID\r
+SetIdtEntry ( \r
+  IN ACPI_S3_CONTEXT     *AcpiS3Context\r
+  );\r
+\r
+extern UINT32 AsmFixAddress16;\r
+extern UINT32 AsmJmpAddr32;\r
+\r
+#endif //_BOOT_SCRIPT_EXECUTOR_H_\r
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S
new file mode 100644 (file)
index 0000000..7f5bdeb
--- /dev/null
@@ -0,0 +1,82 @@
+## @file\r
+#   This is the assembly code for transferring to control to OS S3 waking vector\r
+#   for X64 platform\r
+#\r
+# Copyright (c) 2006, 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
+ASM_GLOBAL ASM_PFX(AsmTransferControl)\r
+ASM_PFX(AsmTransferControl):\r
+    # rcx S3WakingVector    :DWORD\r
+    # rdx AcpiLowMemoryBase :DWORD\r
+    lea   _AsmTransferControl_al_0000, %eax \r
+    movq  $0x2800000000, %r8 \r
+    orq   %r8, %rax\r
+    pushq %rax\r
+    shrd  $20, %ecx, %ebx\r
+    andl  $0x0f, %ecx \r
+    movw  %cx, %bx\r
+    movl  %ebx, jmp_addr \r
+    lret\r
+_AsmTransferControl_al_0000:\r
+    .byte    0x0b8, 0x30, 0      # mov ax, 30h as selector\r
+    movl  %eax, %ds\r
+    movl  %eax, %es\r
+    movl  %eax, %fs\r
+    movl  %eax, %gs\r
+    movl  %eax, %ss\r
+    movq  %cr0, %rax\r
+    movq  %cr4, %rbx\r
+    .byte    0x66\r
+    andl  $0x7ffffffe, %eax \r
+    andb  $0xdf, %bl \r
+    movq  %rax, %cr0\r
+    .byte    0x66\r
+    movl  $0x0c0000080, %ecx \r
+    rdmsr\r
+    andb  $0xfe, %ah \r
+    wrmsr\r
+    movq  %rbx, %cr4\r
+    .byte    0x0ea              # jmp far jmp_addr\r
+jmp_addr:\r
+    .long    0\r
+\r
+ASM_GLOBAL ASM_PFX(AsmTransferControl32)\r
+ASM_PFX(AsmTransferControl32):\r
+    # S3WakingVector    :DWORD\r
+    # AcpiLowMemoryBase :DWORD\r
+    pushq %rbp\r
+    movl  %esp,%ebp\r
+    .byte 0x8d, 0x05        #  lea   eax, AsmTransferControl16\r
+ASM_GLOBAL ASM_PFX(AsmFixAddress16)\r
+ASM_PFX(AsmFixAddress16):\r
+    .long    0\r
+    pushq $0x28             # CS\r
+    pushq %rax\r
+    lret\r
+\r
+ASM_GLOBAL ASM_PFX(AsmTransferControl16)\r
+ASM_PFX(AsmTransferControl16):\r
+    .byte 0xb8,0x30,0       # mov ax, 30h as selector\r
+    movw  %ax,%ds\r
+    movw  %ax,%es\r
+    movw  %ax,%fs\r
+    movw  %ax,%gs\r
+    movw  %ax,%ss\r
+    movq  %cr0, %rax        # Get control register 0  \r
+    .byte 0x66\r
+    .byte 0x83,0xe0,0xfe    # and    eax, 0fffffffeh  ; Clear PE bit (bit #0)\r
+    .byte 0xf,0x22,0xc0     # mov    cr0, eax         ; Activate real mode\r
+    .byte 0xea              # jmp far AsmJmpAddr32\r
+ASM_GLOBAL ASM_PFX(AsmJmpAddr32)\r
+ASM_PFX(AsmJmpAddr32):\r
+    .long    0\r
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.asm b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.asm
new file mode 100644 (file)
index 0000000..f3d327d
--- /dev/null
@@ -0,0 +1,84 @@
+;; @file\r
+;   This is the assembly code for transferring to control to OS S3 waking vector\r
+;   for X64 platform\r
+;\r
+; Copyright (c) 2006, 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 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
+    .code\r
+    \r
+EXTERNDEF   AsmFixAddress16:DWORD\r
+EXTERNDEF   AsmJmpAddr32:DWORD\r
+    \r
+AsmTransferControl  PROC\r
+    ; rcx S3WakingVector    :DWORD\r
+    ; rdx AcpiLowMemoryBase :DWORD\r
+    lea   eax, @F\r
+    mov   r8, 2800000000h\r
+    or    rax, r8\r
+    push  rax\r
+    shrd  ebx, ecx, 20\r
+    and   ecx, 0fh          \r
+    mov   bx, cx          \r
+    mov   @jmp_addr, ebx\r
+    retf\r
+@@:\r
+    DB    0b8h, 30h, 0      ; mov ax, 30h as selector\r
+    mov   ds, eax\r
+    mov   es, eax\r
+    mov   fs, eax\r
+    mov   gs, eax\r
+    mov   ss, eax\r
+    mov   rax, cr0\r
+    mov   rbx, cr4        \r
+    DB    66h\r
+    and   eax, ((NOT 080000001h) AND 0ffffffffh)\r
+    and   bl, NOT (1 SHL 5)\r
+    mov   cr0, rax\r
+    DB    66h\r
+    mov   ecx, 0c0000080h\r
+    rdmsr\r
+    and   ah, NOT 1\r
+    wrmsr\r
+    mov   cr4, rbx\r
+    DB    0eah              ; jmp far @jmp_addr\r
+@jmp_addr DD  ?\r
+AsmTransferControl  ENDP\r
+\r
+AsmTransferControl32  PROC\r
+    ; S3WakingVector    :DWORD\r
+    ; AcpiLowMemoryBase :DWORD\r
+    push  rbp\r
+    mov   ebp, esp    \r
+    DB    8dh, 05h          ;  lea   eax, AsmTransferControl16\r
+AsmFixAddress16  DD ?\r
+    push  28h               ; CS\r
+    push  rax\r
+    retf\r
+AsmTransferControl32  ENDP\r
+\r
+AsmTransferControl16  PROC\r
+    DB    0b8h, 30h, 0      ; mov ax, 30h as selector\r
+    mov   ds, ax\r
+    mov   es, ax\r
+    mov   fs, ax\r
+    mov   gs, ax\r
+    mov   ss, ax\r
+    mov   rax, cr0          ; Get control register 0  \r
+    DB    66h\r
+    DB    83h, 0e0h, 0feh   ; and    eax, 0fffffffeh  ; Clear PE bit (bit #0)\r
+    DB    0fh, 22h, 0c0h    ; mov    cr0, eax         ; Activate real mode\r
+    DB    0eah              ; jmp far AsmJmpAddr32\r
+AsmJmpAddr32 DD  ?\r
+AsmTransferControl16  ENDP\r
+\r
+    END\r
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c
new file mode 100644 (file)
index 0000000..f70f2f9
--- /dev/null
@@ -0,0 +1,67 @@
+/** @file\r
+  Set a IDT entry for debug purpose\r
+\r
+  Set a IDT entry for interrupt vector 3 for debug purpose for x64 platform\r
+\r
+Copyright (c) 2006 - 2010, 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 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
+#include "ScriptExecute.h"\r
+//\r
+// INTERRUPT_GATE_DESCRIPTOR and SetIdtEntry () are used to setup IDT to do debug\r
+//\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  UINT16    Offset15To0;\r
+  UINT16    SegmentSelector;\r
+  UINT16    Attributes;\r
+  UINT16    Offset31To16;\r
+  UINT32    Offset63To32;\r
+  UINT32    Reserved;\r
+} INTERRUPT_GATE_DESCRIPTOR;\r
+\r
+#define INTERRUPT_GATE_ATTRIBUTE   0x8e00\r
+\r
+#pragma pack()\r
+/**\r
+  Set a IDT entry for interrupt vector 3 for debug purpose.\r
+\r
+  @param  AcpiS3Context  a pointer to a structure of ACPI_S3_CONTEXT\r
+\r
+**/\r
+VOID\r
+SetIdtEntry (\r
+  IN ACPI_S3_CONTEXT     *AcpiS3Context\r
+  )\r
+{\r
+  INTERRUPT_GATE_DESCRIPTOR                     *IdtEntry;\r
+  IA32_DESCRIPTOR                               *IdtDescriptor;\r
+  UINTN                                         S3DebugBuffer;\r
+\r
+  //\r
+  // Restore IDT for debug\r
+  //\r
+  IdtDescriptor = (IA32_DESCRIPTOR *) (UINTN) (AcpiS3Context->IdtrProfile);\r
+  IdtEntry = (INTERRUPT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (INTERRUPT_GATE_DESCRIPTOR)));\r
+  S3DebugBuffer = (UINTN) (AcpiS3Context->S3DebugBufferAddress);\r
+\r
+  IdtEntry->Offset15To0     = (UINT16)S3DebugBuffer;\r
+  IdtEntry->SegmentSelector = (UINT16)AsmReadCs ();;\r
+  IdtEntry->Attributes      = (UINT16)INTERRUPT_GATE_ATTRIBUTE;\r
+  IdtEntry->Offset31To16    = (UINT16)(S3DebugBuffer >> 16);\r
+  IdtEntry->Offset63To32    = (UINT32)(S3DebugBuffer >> 32);\r
+  IdtEntry->Reserved        = 0;\r
+\r
+  AsmWriteIdtr (IdtDescriptor);\r
+}\r
+\r