--- /dev/null
+/** @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
## 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
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
--- /dev/null
+## @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
--- /dev/null
+## @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
--- /dev/null
+;; @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+/** @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
--- /dev/null
+## @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
--- /dev/null
+;; @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
--- /dev/null
+/** @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