summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe')
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf172
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.uni34
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxeExtra.uni28
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.nasm124
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c112
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c1014
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h190
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.nasm260
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c544
9 files changed, 1239 insertions, 1239 deletions
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
index fb149c2f02..d5ad07362c 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
@@ -1,86 +1,86 @@
-## @file
-# Boot Script Executor Module
-#
-# This is a standalone Boot Script Executor. Standalone means it does not
-# depends on any PEI or DXE service.
-#
-# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = BootScriptExecutorDxe
- MODULE_UNI_FILE = BootScriptExecutorDxe.uni
- FILE_GUID = FA20568B-548B-4b2b-81EF-1BA08D4A3CEC
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
-
- ENTRY_POINT = BootScriptExecutorEntryPoint
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-[Sources]
- ScriptExecute.h
- ScriptExecute.c
-
-[Sources.X64]
- X64/SetIdtEntry.c
- X64/S3Asm.nasm
-
-[Sources.Ia32]
- IA32/SetIdtEntry.c
- IA32/S3Asm.nasm
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
- PcdLib
- BaseMemoryLib
- UefiDriverEntryPoint
- BaseLib
- S3BootScriptLib
- PeCoffLib
- DxeServicesLib
- UefiBootServicesTableLib
- CacheMaintenanceLib
- UefiLib
- DebugAgentLib
- LockBoxLib
- CpuExceptionHandlerLib
- DevicePathLib
- DxeServicesTableLib
-
-[Guids]
- gEfiBootScriptExecutorVariableGuid ## PRODUCES ## UNDEFINED # SaveLockBox
- gEfiBootScriptExecutorContextGuid ## PRODUCES ## UNDEFINED # SaveLockBox
- gEdkiiMemoryProfileGuid ## SOMETIMES_CONSUMES ## GUID # Locate protocol
-
-[Protocols]
- ## NOTIFY
- ## CONSUMES
- gEfiDxeSmmReadyToLockProtocolGuid
-
-[FeaturePcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
-
-[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
-
-[Depex]
- gEfiLockBoxProtocolGuid
-
-[UserExtensions.TianoCore."ExtraFiles"]
- BootScriptExecutorDxeExtra.uni
+## @file
+# Boot Script Executor Module
+#
+# This is a standalone Boot Script Executor. Standalone means it does not
+# depends on any PEI or DXE service.
+#
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BootScriptExecutorDxe
+ MODULE_UNI_FILE = BootScriptExecutorDxe.uni
+ FILE_GUID = FA20568B-548B-4b2b-81EF-1BA08D4A3CEC
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BootScriptExecutorEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ ScriptExecute.h
+ ScriptExecute.c
+
+[Sources.X64]
+ X64/SetIdtEntry.c
+ X64/S3Asm.nasm
+
+[Sources.Ia32]
+ IA32/SetIdtEntry.c
+ IA32/S3Asm.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ BaseLib
+ S3BootScriptLib
+ PeCoffLib
+ DxeServicesLib
+ UefiBootServicesTableLib
+ CacheMaintenanceLib
+ UefiLib
+ DebugAgentLib
+ LockBoxLib
+ CpuExceptionHandlerLib
+ DevicePathLib
+ DxeServicesTableLib
+
+[Guids]
+ gEfiBootScriptExecutorVariableGuid ## PRODUCES ## UNDEFINED # SaveLockBox
+ gEfiBootScriptExecutorContextGuid ## PRODUCES ## UNDEFINED # SaveLockBox
+ gEdkiiMemoryProfileGuid ## SOMETIMES_CONSUMES ## GUID # Locate protocol
+
+[Protocols]
+ ## NOTIFY
+ ## CONSUMES
+ gEfiDxeSmmReadyToLockProtocolGuid
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMemoryProfilePropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
+
+[Depex]
+ gEfiLockBoxProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ BootScriptExecutorDxeExtra.uni
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.uni b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.uni
index 44aaf1e4cc..3af6153a96 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.uni
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.uni
@@ -1,17 +1,17 @@
-// /** @file
-// Boot Script Executor Module
-//
-// This is a standalone Boot Script Executor. Standalone means it does not
-// depends on any PEI or DXE service.
-//
-// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT #language en-US "Boot Script Executor Module"
-
-#string STR_MODULE_DESCRIPTION #language en-US "This is a standalone Boot Script Executor. Standalone means it does not depends on any PEI or DXE service."
-
+// /** @file
+// Boot Script Executor Module
+//
+// This is a standalone Boot Script Executor. Standalone means it does not
+// depends on any PEI or DXE service.
+//
+// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Boot Script Executor Module"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This is a standalone Boot Script Executor. Standalone means it does not depends on any PEI or DXE service."
+
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxeExtra.uni b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxeExtra.uni
index 05b472b44a..8bd4239d72 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxeExtra.uni
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxeExtra.uni
@@ -1,14 +1,14 @@
-// /** @file
-// BootScriptExecutorDxe Localized Strings and Content
-//
-// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-#string STR_PROPERTIES_MODULE_NAME
-#language en-US
-"Boot Script Execution DXE Driver"
-
-
+// /** @file
+// BootScriptExecutorDxe Localized Strings and Content
+//
+// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Boot Script Execution DXE Driver"
+
+
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.nasm b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.nasm
index e121cc937b..1f7c1f585b 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.nasm
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/S3Asm.nasm
@@ -1,62 +1,62 @@
-;; @file
-; This is the assembly code for transferring to control to OS S3 waking vector
-; for IA32 platform
-;
-; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
-;
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-;;
- SECTION .text
-
-global ASM_PFX(AsmFixAddress16)
-global ASM_PFX(AsmJmpAddr32)
-
-;-----------------------------------------
-;VOID
-;AsmTransferControl (
-; IN UINT32 S3WakingVector,
-; IN UINT32 AcpiLowMemoryBase
-; );
-;-----------------------------------------
-
-global ASM_PFX(AsmTransferControl)
-ASM_PFX(AsmTransferControl):
- ; S3WakingVector :DWORD
- ; AcpiLowMemoryBase :DWORD
- push ebp
- mov ebp, esp
- lea eax, [.0]
- push 0x28 ; CS
- push eax
- mov ecx, [ebp + 8]
- shrd ebx, ecx, 20
- and ecx, 0xf
- mov bx, cx
- mov [@jmp_addr + 1], ebx
- retf
-
-BITS 16
-.0:
- mov ax, 0x30
-o32 mov ds, eax
-o32 mov es, eax
-o32 mov fs, eax
-o32 mov gs, eax
-o32 mov ss, eax
- mov eax, cr0 ; Get control register 0
- and eax, 0x0fffffffe ; Clear PE bit (bit #0)
- mov cr0, eax ; Activate real mode
-@jmp_addr:
- jmp 0x0:0x0
-
-global ASM_PFX(AsmTransferControl32)
-ASM_PFX(AsmTransferControl32):
- jmp ASM_PFX(AsmTransferControl)
-
-; dummy
-global ASM_PFX(AsmTransferControl16)
-ASM_PFX(AsmTransferControl16):
-ASM_PFX(AsmFixAddress16): DD 0
-ASM_PFX(AsmJmpAddr32): DD 0
-
+;; @file
+; This is the assembly code for transferring to control to OS S3 waking vector
+; for IA32 platform
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;;
+ SECTION .text
+
+global ASM_PFX(AsmFixAddress16)
+global ASM_PFX(AsmJmpAddr32)
+
+;-----------------------------------------
+;VOID
+;AsmTransferControl (
+; IN UINT32 S3WakingVector,
+; IN UINT32 AcpiLowMemoryBase
+; );
+;-----------------------------------------
+
+global ASM_PFX(AsmTransferControl)
+ASM_PFX(AsmTransferControl):
+ ; S3WakingVector :DWORD
+ ; AcpiLowMemoryBase :DWORD
+ push ebp
+ mov ebp, esp
+ lea eax, [.0]
+ push 0x28 ; CS
+ push eax
+ mov ecx, [ebp + 8]
+ shrd ebx, ecx, 20
+ and ecx, 0xf
+ mov bx, cx
+ mov [@jmp_addr + 1], ebx
+ retf
+
+BITS 16
+.0:
+ mov ax, 0x30
+o32 mov ds, eax
+o32 mov es, eax
+o32 mov fs, eax
+o32 mov gs, eax
+o32 mov ss, eax
+ mov eax, cr0 ; Get control register 0
+ and eax, 0x0fffffffe ; Clear PE bit (bit #0)
+ mov cr0, eax ; Activate real mode
+@jmp_addr:
+ jmp 0x0:0x0
+
+global ASM_PFX(AsmTransferControl32)
+ASM_PFX(AsmTransferControl32):
+ jmp ASM_PFX(AsmTransferControl)
+
+; dummy
+global ASM_PFX(AsmTransferControl16)
+ASM_PFX(AsmTransferControl16):
+ASM_PFX(AsmFixAddress16): DD 0
+ASM_PFX(AsmJmpAddr32): DD 0
+
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c
index 8f535af26a..7736ba9f45 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/IA32/SetIdtEntry.c
@@ -1,56 +1,56 @@
-/** @file
- Set a IDT entry for debug purpose
-
- Set a IDT entry for interrupt vector 3 for debug purpose for IA32 platform
-
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
-
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-#include "ScriptExecute.h"
-
-/**
- Set a IDT entry for interrupt vector 3 for debug purpose.
-
- @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
-
-**/
-VOID
-SetIdtEntry (
- IN ACPI_S3_CONTEXT *AcpiS3Context
- )
-{
- IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
- IA32_DESCRIPTOR *IdtDescriptor;
- UINTN S3DebugBuffer;
- EFI_STATUS Status;
-
- //
- // Restore IDT for debug
- //
- IdtDescriptor = (IA32_DESCRIPTOR *)(UINTN)(AcpiS3Context->IdtrProfile);
- AsmWriteIdtr (IdtDescriptor);
-
- //
- // Setup the default CPU exception handlers
- //
- Status = InitializeCpuExceptionHandlers (NULL);
- ASSERT_EFI_ERROR (Status);
-
- DEBUG_CODE_BEGIN ();
- //
- // Update IDT entry INT3 if the instruction is valid in it
- //
- S3DebugBuffer = (UINTN)(AcpiS3Context->S3DebugBufferAddress);
- if (*(UINTN *)S3DebugBuffer != (UINTN)-1) {
- IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));
- IdtEntry->Bits.OffsetLow = (UINT16)S3DebugBuffer;
- IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();
- IdtEntry->Bits.Reserved_0 = 0;
- IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
- IdtEntry->Bits.OffsetHigh = (UINT16)(S3DebugBuffer >> 16);
- }
-
- DEBUG_CODE_END ();
-}
+/** @file
+ Set a IDT entry for debug purpose
+
+ Set a IDT entry for interrupt vector 3 for debug purpose for IA32 platform
+
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "ScriptExecute.h"
+
+/**
+ Set a IDT entry for interrupt vector 3 for debug purpose.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+
+**/
+VOID
+SetIdtEntry (
+ IN ACPI_S3_CONTEXT *AcpiS3Context
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR *IdtDescriptor;
+ UINTN S3DebugBuffer;
+ EFI_STATUS Status;
+
+ //
+ // Restore IDT for debug
+ //
+ IdtDescriptor = (IA32_DESCRIPTOR *)(UINTN)(AcpiS3Context->IdtrProfile);
+ AsmWriteIdtr (IdtDescriptor);
+
+ //
+ // Setup the default CPU exception handlers
+ //
+ Status = InitializeCpuExceptionHandlers (NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Update IDT entry INT3 if the instruction is valid in it
+ //
+ S3DebugBuffer = (UINTN)(AcpiS3Context->S3DebugBufferAddress);
+ if (*(UINTN *)S3DebugBuffer != (UINTN)-1) {
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));
+ IdtEntry->Bits.OffsetLow = (UINT16)S3DebugBuffer;
+ IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();
+ IdtEntry->Bits.Reserved_0 = 0;
+ IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ IdtEntry->Bits.OffsetHigh = (UINT16)(S3DebugBuffer >> 16);
+ }
+
+ DEBUG_CODE_END ();
+}
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
index 98c5abecf8..a898faa1ea 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
@@ -1,507 +1,507 @@
-/** @file
- This is the code for Boot Script Executer module.
-
- This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
- in the entry point. The functionality is to interpret and restore the S3 boot script
-
-Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
-Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
-
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "ScriptExecute.h"
-
-EFI_GUID mBootScriptExecutorImageGuid = {
- 0x9a8d3433, 0x9fe8, 0x42b6, { 0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b }
-};
-
-BOOLEAN mPage1GSupport = FALSE;
-UINT64 mAddressEncMask = 0;
-
-/**
- Entry function of Boot script exector. This function will be executed in
- S3 boot path.
- This function should not return, because it is invoked by switch stack.
-
- @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
- @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
-
- @retval EFI_INVALID_PARAMETER - OS waking vector not found
- @retval EFI_UNSUPPORTED - something wrong when we resume to OS
-**/
-EFI_STATUS
-EFIAPI
-S3BootScriptExecutorEntryFunction (
- IN ACPI_S3_CONTEXT *AcpiS3Context,
- IN PEI_S3_RESUME_STATE *PeiS3ResumeState
- )
-{
- EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
- EFI_STATUS Status;
- UINTN TempStackTop;
- UINTN TempStack[0x10];
- UINTN AsmTransferControl16Address;
- IA32_DESCRIPTOR IdtDescriptor;
-
- //
- // Disable interrupt of Debug timer, since new IDT table cannot handle it.
- //
- SaveAndSetDebugTimerInterrupt (FALSE);
-
- AsmReadIdtr (&IdtDescriptor);
- //
- // Restore IDT for debug
- //
- SetIdtEntry (AcpiS3Context);
-
- //
- // Initialize Debug Agent to support source level debug in S3 path, it will disable interrupt and Debug Timer.
- //
- InitializeDebugAgent (DEBUG_AGENT_INIT_S3, (VOID *)&IdtDescriptor, NULL);
-
- //
- // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL
- // for that parameter.
- //
- Status = S3BootScriptExecute ();
-
- //
- // If invalid script table or opcode in S3 boot script table.
- //
- ASSERT_EFI_ERROR (Status);
-
- if (EFI_ERROR (Status)) {
- CpuDeadLoop ();
- return Status;
- }
-
- AsmWbinvd ();
-
- //
- // Get ACPI Table Address
- //
- Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)((UINTN)(AcpiS3Context->AcpiFacsTable));
-
- //
- // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume.
- //
- if (PeiS3ResumeState != 0) {
- //
- // Need report status back to S3ResumePeim.
- // If boot script execution is failed, S3ResumePeim wil report the error status code.
- //
- PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status;
- if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
- //
- // X64 DXE to IA32 PEI S3 Resume
- //
- DEBUG ((DEBUG_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));
- PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl32;
-
- if ((Facs != NULL) &&
- (Facs->Signature == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) &&
- (Facs->FirmwareWakingVector != 0))
- {
- //
- // more step needed - because relative address is handled differently between X64 and IA32.
- //
- AsmTransferControl16Address = (UINTN)AsmTransferControl16;
- AsmFixAddress16 = (UINT32)AsmTransferControl16Address;
- AsmJmpAddr32 = (UINT32)((Facs->FirmwareWakingVector & 0xF) | ((Facs->FirmwareWakingVector & 0xFFFF0) << 12));
- }
-
- AsmDisablePaging64 (
- PeiS3ResumeState->ReturnCs,
- (UINT32)PeiS3ResumeState->ReturnEntryPoint,
- (UINT32)(UINTN)AcpiS3Context,
- (UINT32)(UINTN)PeiS3ResumeState,
- (UINT32)PeiS3ResumeState->ReturnStackPointer
- );
- } else {
- //
- // IA32 DXE to IA32 PEI S3 Resume / X64 DXE to X64 PEI S3 Resume
- //
- DEBUG ((DEBUG_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));
- PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl;
-
- SwitchStack (
- (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint,
- (VOID *)(UINTN)AcpiS3Context,
- (VOID *)(UINTN)PeiS3ResumeState,
- (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer
- );
- }
-
- //
- // Never run to here
- //
- CpuDeadLoop ();
- return EFI_UNSUPPORTED;
- }
-
- //
- // S3ResumePeim does not provide a way to jump back to itself, so resume to OS here directly
- //
- if (Facs->XFirmwareWakingVector != 0) {
- //
- // Switch to native waking vector
- //
- TempStackTop = (UINTN)&TempStack + sizeof (TempStack);
- if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
- ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
- ((Facs->OspmFlags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0))
- {
- //
- // X64 long mode waking vector
- //
- DEBUG ((DEBUG_INFO, "Transfer from 64bit DXE to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
- if (sizeof (UINTN) == sizeof (UINT64)) {
- //
- // 64bit DXE calls to 64bit OS S3 waking vector
- //
- SwitchStack (
- (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,
- NULL,
- NULL,
- (VOID *)(UINTN)TempStackTop
- );
- } else {
- // Unsupported for 32bit DXE, 64bit OS vector
- DEBUG ((DEBUG_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));
- ASSERT (FALSE);
- }
- } else {
- //
- // IA32 protected mode waking vector (Page disabled)
- //
- DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
- if (sizeof (UINTN) == sizeof (UINT64)) {
- //
- // 64bit DXE calls to 32bit OS S3 waking vector
- //
- AsmDisablePaging64 (
- 0x10,
- (UINT32)Facs->XFirmwareWakingVector,
- 0,
- 0,
- (UINT32)TempStackTop
- );
- } else {
- //
- // 32bit DXE calls to 32bit OS S3 waking vector
- //
- SwitchStack (
- (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,
- NULL,
- NULL,
- (VOID *)(UINTN)TempStackTop
- );
- }
- }
- } else {
- //
- // 16bit Realmode waking vector
- //
- DEBUG ((DEBUG_INFO, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));
- AsmTransferControl (Facs->FirmwareWakingVector, 0x0);
- }
-
- //
- // Never run to here
- //
- CpuDeadLoop ();
- return EFI_UNSUPPORTED;
-}
-
-/**
- Register image to memory profile.
-
- @param FileName File name of the image.
- @param ImageBase Image base address.
- @param ImageSize Image size.
- @param FileType File type of the image.
-
-**/
-VOID
-RegisterMemoryProfileImage (
- IN EFI_GUID *FileName,
- IN PHYSICAL_ADDRESS ImageBase,
- IN UINT64 ImageSize,
- IN EFI_FV_FILETYPE FileType
- )
-{
- EFI_STATUS Status;
- EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
- UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
-
- if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {
- FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
- Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **)&ProfileProtocol);
- if (!EFI_ERROR (Status)) {
- EfiInitializeFwVolDevicepathNode (FilePath, FileName);
- SetDevicePathEndNode (FilePath + 1);
-
- Status = ProfileProtocol->RegisterImage (
- ProfileProtocol,
- (EFI_DEVICE_PATH_PROTOCOL *)FilePath,
- ImageBase,
- ImageSize,
- FileType
- );
- }
- }
-}
-
-/**
- This is the Event notification function to reload BootScriptExecutor image
- to RESERVED mem and save it to LockBox.
-
- @param Event Pointer to this event
- @param Context Event handler private data
- **/
-VOID
-EFIAPI
-ReadyToLockEventNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- VOID *Interface;
- UINT8 *Buffer;
- UINTN BufferSize;
- EFI_HANDLE NewImageHandle;
- UINTN Pages;
- EFI_PHYSICAL_ADDRESS FfsBuffer;
- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
-
- Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
- if (EFI_ERROR (Status)) {
- return;
- }
-
- //
- // A workaround: Here we install a dummy handle
- //
- NewImageHandle = NULL;
- Status = gBS->InstallProtocolInterface (
- &NewImageHandle,
- &gEfiCallerIdGuid,
- EFI_NATIVE_INTERFACE,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Reload BootScriptExecutor image itself to RESERVED mem
- //
- Status = GetSectionFromAnyFv (
- &gEfiCallerIdGuid,
- EFI_SECTION_PE32,
- 0,
- (VOID **)&Buffer,
- &BufferSize
- );
- ASSERT_EFI_ERROR (Status);
- ImageContext.Handle = Buffer;
- ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
- //
- // Get information about the image being loaded
- //
- Status = PeCoffLoaderGetImageInfo (&ImageContext);
- ASSERT_EFI_ERROR (Status);
- if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
- Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
- } else {
- Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
- }
-
- FfsBuffer = 0xFFFFFFFF;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- Pages,
- &FfsBuffer
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Make sure that the buffer can be used to store code.
- //
- Status = gDS->GetMemorySpaceDescriptor (FfsBuffer, &MemDesc);
- if (!EFI_ERROR (Status) && ((MemDesc.Attributes & EFI_MEMORY_XP) != 0)) {
- gDS->SetMemorySpaceAttributes (
- FfsBuffer,
- EFI_PAGES_TO_SIZE (Pages),
- MemDesc.Attributes & (~EFI_MEMORY_XP)
- );
- }
-
- ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
- //
- // Align buffer on section boundary
- //
- ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
- ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
- //
- // Load the image to our new buffer
- //
- Status = PeCoffLoaderLoadImage (&ImageContext);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Relocate the image in our new buffer
- //
- Status = PeCoffLoaderRelocateImage (&ImageContext);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
- //
- gBS->FreePool (Buffer);
-
- //
- // Flush the instruction cache so the image data is written before we execute it
- //
- InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
-
- RegisterMemoryProfileImage (
- &gEfiCallerIdGuid,
- ImageContext.ImageAddress,
- ImageContext.ImageSize,
- EFI_FV_FILETYPE_DRIVER
- );
-
- Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Additional step for BootScript integrity
- // Save BootScriptExecutor image
- //
- Status = SaveLockBox (
- &mBootScriptExecutorImageGuid,
- (VOID *)(UINTN)ImageContext.ImageAddress,
- (UINTN)ImageContext.ImageSize
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
- ASSERT_EFI_ERROR (Status);
-
- gBS->CloseEvent (Event);
-}
-
-/**
- Entrypoint of Boot script exector driver, this function will be executed in
- normal boot phase and invoked by DXE dispatch.
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
-**/
-EFI_STATUS
-EFIAPI
-BootScriptExecutorEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- UINTN BufferSize;
- UINTN Pages;
- BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
- EFI_PHYSICAL_ADDRESS BootScriptExecutorBuffer;
- EFI_STATUS Status;
- VOID *DevicePath;
- EFI_EVENT ReadyToLockEvent;
- VOID *Registration;
- UINT32 RegEax;
- UINT32 RegEdx;
-
- if (!PcdGetBool (PcdAcpiS3Enable)) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Make sure AddressEncMask is contained to smallest supported address field.
- //
- mAddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
-
- //
- // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
- // point is loaded by DXE code which is the first time loaded. or else, it is already
- // be reloaded be itself.This is a work-around
- //
- Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
- if (EFI_ERROR (Status)) {
- //
- // Create ReadyToLock event to reload BootScriptExecutor image
- // to RESERVED mem and save it to LockBox.
- //
- ReadyToLockEvent = EfiCreateProtocolNotifyEvent (
- &gEfiDxeSmmReadyToLockProtocolGuid,
- TPL_NOTIFY,
- ReadyToLockEventNotify,
- NULL,
- &Registration
- );
- ASSERT (ReadyToLockEvent != NULL);
- } else {
- //
- // the entry point is invoked after reloading. following code only run in RESERVED mem
- //
- if (PcdGetBool (PcdUse1GPageTable)) {
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000001) {
- AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT26) != 0) {
- mPage1GSupport = TRUE;
- }
- }
- }
-
- BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
-
- BootScriptExecutorBuffer = 0xFFFFFFFF;
- Pages = EFI_SIZE_TO_PAGES (BufferSize);
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- Pages,
- &BootScriptExecutorBuffer
- );
- ASSERT_EFI_ERROR (Status);
-
- EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer;
- EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN)S3BootScriptExecutorEntryFunction;
-
- Status = SaveLockBox (
- &gEfiBootScriptExecutorVariableGuid,
- &BootScriptExecutorBuffer,
- sizeof (BootScriptExecutorBuffer)
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Additional step for BootScript integrity
- // Save BootScriptExecutor context
- //
- Status = SaveLockBox (
- &gEfiBootScriptExecutorContextGuid,
- EfiBootScriptExecutorVariable,
- sizeof (*EfiBootScriptExecutorVariable)
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
- ASSERT_EFI_ERROR (Status);
- }
-
- return EFI_SUCCESS;
-}
+/** @file
+ This is the code for Boot Script Executer module.
+
+ This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
+ in the entry point. The functionality is to interpret and restore the S3 boot script
+
+Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "ScriptExecute.h"
+
+EFI_GUID mBootScriptExecutorImageGuid = {
+ 0x9a8d3433, 0x9fe8, 0x42b6, { 0x87, 0xb, 0x1e, 0x31, 0xc8, 0x4e, 0xbe, 0x3b }
+};
+
+BOOLEAN mPage1GSupport = FALSE;
+UINT64 mAddressEncMask = 0;
+
+/**
+ Entry function of Boot script exector. This function will be executed in
+ S3 boot path.
+ This function should not return, because it is invoked by switch stack.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+ @param PeiS3ResumeState a pointer to a structure of PEI_S3_RESUME_STATE
+
+ @retval EFI_INVALID_PARAMETER - OS waking vector not found
+ @retval EFI_UNSUPPORTED - something wrong when we resume to OS
+**/
+EFI_STATUS
+EFIAPI
+S3BootScriptExecutorEntryFunction (
+ IN ACPI_S3_CONTEXT *AcpiS3Context,
+ IN PEI_S3_RESUME_STATE *PeiS3ResumeState
+ )
+{
+ EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+ EFI_STATUS Status;
+ UINTN TempStackTop;
+ UINTN TempStack[0x10];
+ UINTN AsmTransferControl16Address;
+ IA32_DESCRIPTOR IdtDescriptor;
+
+ //
+ // Disable interrupt of Debug timer, since new IDT table cannot handle it.
+ //
+ SaveAndSetDebugTimerInterrupt (FALSE);
+
+ AsmReadIdtr (&IdtDescriptor);
+ //
+ // Restore IDT for debug
+ //
+ SetIdtEntry (AcpiS3Context);
+
+ //
+ // Initialize Debug Agent to support source level debug in S3 path, it will disable interrupt and Debug Timer.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_S3, (VOID *)&IdtDescriptor, NULL);
+
+ //
+ // Because not install BootScriptExecute PPI(used just in this module), So just pass NULL
+ // for that parameter.
+ //
+ Status = S3BootScriptExecute ();
+
+ //
+ // If invalid script table or opcode in S3 boot script table.
+ //
+ ASSERT_EFI_ERROR (Status);
+
+ if (EFI_ERROR (Status)) {
+ CpuDeadLoop ();
+ return Status;
+ }
+
+ AsmWbinvd ();
+
+ //
+ // Get ACPI Table Address
+ //
+ Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)((UINTN)(AcpiS3Context->AcpiFacsTable));
+
+ //
+ // We need turn back to S3Resume - install boot script done ppi and report status code on S3resume.
+ //
+ if (PeiS3ResumeState != 0) {
+ //
+ // Need report status back to S3ResumePeim.
+ // If boot script execution is failed, S3ResumePeim wil report the error status code.
+ //
+ PeiS3ResumeState->ReturnStatus = (UINT64)(UINTN)Status;
+ if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ //
+ // X64 DXE to IA32 PEI S3 Resume
+ //
+ DEBUG ((DEBUG_INFO, "Call AsmDisablePaging64() to return to S3 Resume in PEI Phase\n"));
+ PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl32;
+
+ if ((Facs != NULL) &&
+ (Facs->Signature == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) &&
+ (Facs->FirmwareWakingVector != 0))
+ {
+ //
+ // more step needed - because relative address is handled differently between X64 and IA32.
+ //
+ AsmTransferControl16Address = (UINTN)AsmTransferControl16;
+ AsmFixAddress16 = (UINT32)AsmTransferControl16Address;
+ AsmJmpAddr32 = (UINT32)((Facs->FirmwareWakingVector & 0xF) | ((Facs->FirmwareWakingVector & 0xFFFF0) << 12));
+ }
+
+ AsmDisablePaging64 (
+ PeiS3ResumeState->ReturnCs,
+ (UINT32)PeiS3ResumeState->ReturnEntryPoint,
+ (UINT32)(UINTN)AcpiS3Context,
+ (UINT32)(UINTN)PeiS3ResumeState,
+ (UINT32)PeiS3ResumeState->ReturnStackPointer
+ );
+ } else {
+ //
+ // IA32 DXE to IA32 PEI S3 Resume / X64 DXE to X64 PEI S3 Resume
+ //
+ DEBUG ((DEBUG_INFO, "Call SwitchStack() to return to S3 Resume in PEI Phase\n"));
+ PeiS3ResumeState->AsmTransferControl = (EFI_PHYSICAL_ADDRESS)(UINTN)AsmTransferControl;
+
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiS3ResumeState->ReturnEntryPoint,
+ (VOID *)(UINTN)AcpiS3Context,
+ (VOID *)(UINTN)PeiS3ResumeState,
+ (VOID *)(UINTN)PeiS3ResumeState->ReturnStackPointer
+ );
+ }
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop ();
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // S3ResumePeim does not provide a way to jump back to itself, so resume to OS here directly
+ //
+ if (Facs->XFirmwareWakingVector != 0) {
+ //
+ // Switch to native waking vector
+ //
+ TempStackTop = (UINTN)&TempStack + sizeof (TempStack);
+ if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
+ ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
+ ((Facs->OspmFlags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0))
+ {
+ //
+ // X64 long mode waking vector
+ //
+ DEBUG ((DEBUG_INFO, "Transfer from 64bit DXE to 64bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ //
+ // 64bit DXE calls to 64bit OS S3 waking vector
+ //
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,
+ NULL,
+ NULL,
+ (VOID *)(UINTN)TempStackTop
+ );
+ } else {
+ // Unsupported for 32bit DXE, 64bit OS vector
+ DEBUG ((DEBUG_ERROR, "Unsupported for 32bit DXE transfer to 64bit OS waking vector!\r\n"));
+ ASSERT (FALSE);
+ }
+ } else {
+ //
+ // IA32 protected mode waking vector (Page disabled)
+ //
+ DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ //
+ // 64bit DXE calls to 32bit OS S3 waking vector
+ //
+ AsmDisablePaging64 (
+ 0x10,
+ (UINT32)Facs->XFirmwareWakingVector,
+ 0,
+ 0,
+ (UINT32)TempStackTop
+ );
+ } else {
+ //
+ // 32bit DXE calls to 32bit OS S3 waking vector
+ //
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)Facs->XFirmwareWakingVector,
+ NULL,
+ NULL,
+ (VOID *)(UINTN)TempStackTop
+ );
+ }
+ }
+ } else {
+ //
+ // 16bit Realmode waking vector
+ //
+ DEBUG ((DEBUG_INFO, "Transfer to 16bit OS waking vector - %x\r\n", (UINTN)Facs->FirmwareWakingVector));
+ AsmTransferControl (Facs->FirmwareWakingVector, 0x0);
+ }
+
+ //
+ // Never run to here
+ //
+ CpuDeadLoop ();
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Register image to memory profile.
+
+ @param FileName File name of the image.
+ @param ImageBase Image base address.
+ @param ImageSize Image size.
+ @param FileType File type of the image.
+
+**/
+VOID
+RegisterMemoryProfileImage (
+ IN EFI_GUID *FileName,
+ IN PHYSICAL_ADDRESS ImageBase,
+ IN UINT64 ImageSize,
+ IN EFI_FV_FILETYPE FileType
+ )
+{
+ EFI_STATUS Status;
+ EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
+ UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
+
+ if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {
+ FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
+ Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **)&ProfileProtocol);
+ if (!EFI_ERROR (Status)) {
+ EfiInitializeFwVolDevicepathNode (FilePath, FileName);
+ SetDevicePathEndNode (FilePath + 1);
+
+ Status = ProfileProtocol->RegisterImage (
+ ProfileProtocol,
+ (EFI_DEVICE_PATH_PROTOCOL *)FilePath,
+ ImageBase,
+ ImageSize,
+ FileType
+ );
+ }
+ }
+}
+
+/**
+ This is the Event notification function to reload BootScriptExecutor image
+ to RESERVED mem and save it to LockBox.
+
+ @param Event Pointer to this event
+ @param Context Event handler private data
+ **/
+VOID
+EFIAPI
+ReadyToLockEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *Interface;
+ UINT8 *Buffer;
+ UINTN BufferSize;
+ EFI_HANDLE NewImageHandle;
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS FfsBuffer;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
+
+ Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, &Interface);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ //
+ // A workaround: Here we install a dummy handle
+ //
+ NewImageHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewImageHandle,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Reload BootScriptExecutor image itself to RESERVED mem
+ //
+ Status = GetSectionFromAnyFv (
+ &gEfiCallerIdGuid,
+ EFI_SECTION_PE32,
+ 0,
+ (VOID **)&Buffer,
+ &BufferSize
+ );
+ ASSERT_EFI_ERROR (Status);
+ ImageContext.Handle = Buffer;
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+ //
+ // Get information about the image being loaded
+ //
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ ASSERT_EFI_ERROR (Status);
+ if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
+ Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
+ } else {
+ Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
+ }
+
+ FfsBuffer = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ Pages,
+ &FfsBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Make sure that the buffer can be used to store code.
+ //
+ Status = gDS->GetMemorySpaceDescriptor (FfsBuffer, &MemDesc);
+ if (!EFI_ERROR (Status) && ((MemDesc.Attributes & EFI_MEMORY_XP) != 0)) {
+ gDS->SetMemorySpaceAttributes (
+ FfsBuffer,
+ EFI_PAGES_TO_SIZE (Pages),
+ MemDesc.Attributes & (~EFI_MEMORY_XP)
+ );
+ }
+
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
+ //
+ // Align buffer on section boundary
+ //
+ ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+ ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
+ //
+ gBS->FreePool (Buffer);
+
+ //
+ // Flush the instruction cache so the image data is written before we execute it
+ //
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+
+ RegisterMemoryProfileImage (
+ &gEfiCallerIdGuid,
+ ImageContext.ImageAddress,
+ ImageContext.ImageSize,
+ EFI_FV_FILETYPE_DRIVER
+ );
+
+ Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Additional step for BootScript integrity
+ // Save BootScriptExecutor image
+ //
+ Status = SaveLockBox (
+ &mBootScriptExecutorImageGuid,
+ (VOID *)(UINTN)ImageContext.ImageAddress,
+ (UINTN)ImageContext.ImageSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SetLockBoxAttributes (&mBootScriptExecutorImageGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ ASSERT_EFI_ERROR (Status);
+
+ gBS->CloseEvent (Event);
+}
+
+/**
+ Entrypoint of Boot script exector driver, this function will be executed in
+ normal boot phase and invoked by DXE dispatch.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+**/
+EFI_STATUS
+EFIAPI
+BootScriptExecutorEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINTN BufferSize;
+ UINTN Pages;
+ BOOT_SCRIPT_EXECUTOR_VARIABLE *EfiBootScriptExecutorVariable;
+ EFI_PHYSICAL_ADDRESS BootScriptExecutorBuffer;
+ EFI_STATUS Status;
+ VOID *DevicePath;
+ EFI_EVENT ReadyToLockEvent;
+ VOID *Registration;
+ UINT32 RegEax;
+ UINT32 RegEdx;
+
+ if (!PcdGetBool (PcdAcpiS3Enable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure AddressEncMask is contained to smallest supported address field.
+ //
+ mAddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
+
+ //
+ // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
+ // point is loaded by DXE code which is the first time loaded. or else, it is already
+ // be reloaded be itself.This is a work-around
+ //
+ Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
+ if (EFI_ERROR (Status)) {
+ //
+ // Create ReadyToLock event to reload BootScriptExecutor image
+ // to RESERVED mem and save it to LockBox.
+ //
+ ReadyToLockEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiDxeSmmReadyToLockProtocolGuid,
+ TPL_NOTIFY,
+ ReadyToLockEventNotify,
+ NULL,
+ &Registration
+ );
+ ASSERT (ReadyToLockEvent != NULL);
+ } else {
+ //
+ // the entry point is invoked after reloading. following code only run in RESERVED mem
+ //
+ if (PcdGetBool (PcdUse1GPageTable)) {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT26) != 0) {
+ mPage1GSupport = TRUE;
+ }
+ }
+ }
+
+ BufferSize = sizeof (BOOT_SCRIPT_EXECUTOR_VARIABLE);
+
+ BootScriptExecutorBuffer = 0xFFFFFFFF;
+ Pages = EFI_SIZE_TO_PAGES (BufferSize);
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ Pages,
+ &BootScriptExecutorBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EfiBootScriptExecutorVariable = (BOOT_SCRIPT_EXECUTOR_VARIABLE *)(UINTN)BootScriptExecutorBuffer;
+ EfiBootScriptExecutorVariable->BootScriptExecutorEntrypoint = (UINTN)S3BootScriptExecutorEntryFunction;
+
+ Status = SaveLockBox (
+ &gEfiBootScriptExecutorVariableGuid,
+ &BootScriptExecutorBuffer,
+ sizeof (BootScriptExecutorBuffer)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Additional step for BootScript integrity
+ // Save BootScriptExecutor context
+ //
+ Status = SaveLockBox (
+ &gEfiBootScriptExecutorContextGuid,
+ EfiBootScriptExecutorVariable,
+ sizeof (*EfiBootScriptExecutorVariable)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SetLockBoxAttributes (&gEfiBootScriptExecutorContextGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h
index 0ea38223d7..3f779a8410 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.h
@@ -1,95 +1,95 @@
-/** @file
- The header file for Boot Script Executer module.
-
- This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
- in the entry point. The functionality is to interpret and restore the S3 boot script
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
-
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _BOOT_SCRIPT_EXECUTOR_H_
-#define _BOOT_SCRIPT_EXECUTOR_H_
-
-#include <PiDxe.h>
-
-#include <Library/BaseLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-#include <Library/S3BootScriptLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/DxeServicesLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/PcdLib.h>
-#include <Library/CacheMaintenanceLib.h>
-#include <Library/TimerLib.h>
-#include <Library/UefiLib.h>
-#include <Library/DebugAgentLib.h>
-#include <Library/LockBoxLib.h>
-#include <Library/CpuExceptionHandlerLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/DxeServicesTableLib.h>
-
-#include <Guid/AcpiS3Context.h>
-#include <Guid/BootScriptExecutorVariable.h>
-#include <Guid/MemoryProfile.h>
-
-#include <Protocol/DxeSmmReadyToLock.h>
-#include <IndustryStandard/Acpi.h>
-
-#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
-
-/**
- a ASM function to transfer control to OS.
-
- @param S3WakingVector The S3 waking up vector saved in ACPI Facs table
- @param AcpiLowMemoryBase a buffer under 1M which could be used during the transfer
-**/
-VOID
-AsmTransferControl (
- IN UINT32 S3WakingVector,
- IN UINT32 AcpiLowMemoryBase
- );
-
-/**
- a 32bit ASM function to transfer control to OS.
-
- @param S3WakingVector The S3 waking up vector saved in ACPI Facs table
- @param AcpiLowMemoryBase a buffer under 1M which could be used during the transfer
-**/
-VOID
-AsmTransferControl32 (
- IN UINT32 S3WakingVector,
- IN UINT32 AcpiLowMemoryBase
- );
-
-/**
- a 16bit ASM function to transfer control to OS.
-**/
-VOID
-AsmTransferControl16 (
- VOID
- );
-
-/**
- Set a IDT entry for interrupt vector 3 for debug purpose.
-
- @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
-
-**/
-VOID
-SetIdtEntry (
- IN ACPI_S3_CONTEXT *AcpiS3Context
- );
-
-extern UINT32 AsmFixAddress16;
-extern UINT32 AsmJmpAddr32;
-extern BOOLEAN mPage1GSupport;
-extern UINT64 mAddressEncMask;
-
-#endif //_BOOT_SCRIPT_EXECUTOR_H_
+/** @file
+ The header file for Boot Script Executer module.
+
+ This driver is dispatched by Dxe core and the driver will reload itself to ACPI reserved memory
+ in the entry point. The functionality is to interpret and restore the S3 boot script
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _BOOT_SCRIPT_EXECUTOR_H_
+#define _BOOT_SCRIPT_EXECUTOR_H_
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/CpuExceptionHandlerLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DxeServicesTableLib.h>
+
+#include <Guid/AcpiS3Context.h>
+#include <Guid/BootScriptExecutorVariable.h>
+#include <Guid/MemoryProfile.h>
+
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <IndustryStandard/Acpi.h>
+
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
+
+/**
+ a ASM function to transfer control to OS.
+
+ @param S3WakingVector The S3 waking up vector saved in ACPI Facs table
+ @param AcpiLowMemoryBase a buffer under 1M which could be used during the transfer
+**/
+VOID
+AsmTransferControl (
+ IN UINT32 S3WakingVector,
+ IN UINT32 AcpiLowMemoryBase
+ );
+
+/**
+ a 32bit ASM function to transfer control to OS.
+
+ @param S3WakingVector The S3 waking up vector saved in ACPI Facs table
+ @param AcpiLowMemoryBase a buffer under 1M which could be used during the transfer
+**/
+VOID
+AsmTransferControl32 (
+ IN UINT32 S3WakingVector,
+ IN UINT32 AcpiLowMemoryBase
+ );
+
+/**
+ a 16bit ASM function to transfer control to OS.
+**/
+VOID
+AsmTransferControl16 (
+ VOID
+ );
+
+/**
+ Set a IDT entry for interrupt vector 3 for debug purpose.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+
+**/
+VOID
+SetIdtEntry (
+ IN ACPI_S3_CONTEXT *AcpiS3Context
+ );
+
+extern UINT32 AsmFixAddress16;
+extern UINT32 AsmJmpAddr32;
+extern BOOLEAN mPage1GSupport;
+extern UINT64 mAddressEncMask;
+
+#endif //_BOOT_SCRIPT_EXECUTOR_H_
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.nasm b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.nasm
index 713fd7b2e5..1e19925c00 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.nasm
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.nasm
@@ -1,130 +1,130 @@
-;; @file
-; This is the assembly code for transferring to control to OS S3 waking vector
-; for X64 platform
-;
-; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
-;
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-;;
-
-extern ASM_PFX(mOriginalHandler)
-extern ASM_PFX(PageFaultHandler)
-
- DEFAULT REL
- SECTION .text
-
-global ASM_PFX(AsmFixAddress16)
-global ASM_PFX(AsmJmpAddr32)
-
-global ASM_PFX(AsmTransferControl)
-ASM_PFX(AsmTransferControl):
- ; rcx S3WakingVector :DWORD
- ; rdx AcpiLowMemoryBase :DWORD
- lea eax, [.0]
- mov r8, 0x2800000000
- or rax, r8
- push rax
- shrd ebx, ecx, 20
- and ecx, 0xf
- mov bx, cx
- mov [@jmp_addr + 1], ebx
- retf
-BITS 16
-.0:
- mov ax, 0x30
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- mov eax, cr0
- mov ebx, cr4
- and eax, ((~ 0x80000001) & 0xffffffff)
- and bl, ~ (1 << 5)
- mov cr0, eax
- mov ecx, 0xc0000080
- rdmsr
- and ah, ~ 1
- wrmsr
- mov cr4, ebx
-@jmp_addr:
- jmp 0x0:0x0
-
-global ASM_PFX(AsmTransferControl32)
-ASM_PFX(AsmTransferControl32):
-BITS 32
- ; S3WakingVector :DWORD
- ; AcpiLowMemoryBase :DWORD
- push ebp
- mov ebp, esp
- DB 0x8d, 0x5 ; lea eax, AsmTransferControl16
-ASM_PFX(AsmFixAddress16): DD 0
- push 0x28 ; CS
- push eax
- retf
-
-global ASM_PFX(AsmTransferControl16)
-ASM_PFX(AsmTransferControl16):
-BITS 16
- mov ax, 0x30
-o32 mov ds, eax
-o32 mov es, eax
-o32 mov fs, eax
-o32 mov gs, eax
-o32 mov ss, eax
- mov eax, cr0 ; Get control register 0
- and eax, 0fffffffeh ; Clear PE bit (bit #0)
- mov cr0, eax ; Activate real mode
- DB 0xea ; jmp far AsmJmpAddr32
-ASM_PFX(AsmJmpAddr32): DD 0
-
-global ASM_PFX(PageFaultHandlerHook)
-ASM_PFX(PageFaultHandlerHook):
-BITS 64
- push rax ; save all volatile registers
- push rcx
- push rdx
- push r8
- push r9
- push r10
- push r11
- ; save volatile fp registers
- add rsp, -0x68
- stmxcsr [rsp + 0x60]
- movdqa [rsp + 0x0], xmm0
- movdqa [rsp + 0x10], xmm1
- movdqa [rsp + 0x20], xmm2
- movdqa [rsp + 0x30], xmm3
- movdqa [rsp + 0x40], xmm4
- movdqa [rsp + 0x50], xmm5
-
- add rsp, -0x20
- call ASM_PFX(PageFaultHandler)
- add rsp, 0x20
-
- ; load volatile fp registers
- ldmxcsr [rsp + 0x60]
- movdqa xmm0, [rsp + 0x0]
- movdqa xmm1, [rsp + 0x10]
- movdqa xmm2, [rsp + 0x20]
- movdqa xmm3, [rsp + 0x30]
- movdqa xmm4, [rsp + 0x40]
- movdqa xmm5, [rsp + 0x50]
- add rsp, 0x68
-
- test al, al
-
- pop r11
- pop r10
- pop r9
- pop r8
- pop rdx
- pop rcx
- pop rax ; restore all volatile registers
- jnz .1
- jmp qword [ASM_PFX(mOriginalHandler)]
-.1:
- add rsp, 0x8 ; skip error code for PF
- iretq
-
+;; @file
+; This is the assembly code for transferring to control to OS S3 waking vector
+; for X64 platform
+;
+; Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;;
+
+extern ASM_PFX(mOriginalHandler)
+extern ASM_PFX(PageFaultHandler)
+
+ DEFAULT REL
+ SECTION .text
+
+global ASM_PFX(AsmFixAddress16)
+global ASM_PFX(AsmJmpAddr32)
+
+global ASM_PFX(AsmTransferControl)
+ASM_PFX(AsmTransferControl):
+ ; rcx S3WakingVector :DWORD
+ ; rdx AcpiLowMemoryBase :DWORD
+ lea eax, [.0]
+ mov r8, 0x2800000000
+ or rax, r8
+ push rax
+ shrd ebx, ecx, 20
+ and ecx, 0xf
+ mov bx, cx
+ mov [@jmp_addr + 1], ebx
+ retf
+BITS 16
+.0:
+ mov ax, 0x30
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ mov eax, cr0
+ mov ebx, cr4
+ and eax, ((~ 0x80000001) & 0xffffffff)
+ and bl, ~ (1 << 5)
+ mov cr0, eax
+ mov ecx, 0xc0000080
+ rdmsr
+ and ah, ~ 1
+ wrmsr
+ mov cr4, ebx
+@jmp_addr:
+ jmp 0x0:0x0
+
+global ASM_PFX(AsmTransferControl32)
+ASM_PFX(AsmTransferControl32):
+BITS 32
+ ; S3WakingVector :DWORD
+ ; AcpiLowMemoryBase :DWORD
+ push ebp
+ mov ebp, esp
+ DB 0x8d, 0x5 ; lea eax, AsmTransferControl16
+ASM_PFX(AsmFixAddress16): DD 0
+ push 0x28 ; CS
+ push eax
+ retf
+
+global ASM_PFX(AsmTransferControl16)
+ASM_PFX(AsmTransferControl16):
+BITS 16
+ mov ax, 0x30
+o32 mov ds, eax
+o32 mov es, eax
+o32 mov fs, eax
+o32 mov gs, eax
+o32 mov ss, eax
+ mov eax, cr0 ; Get control register 0
+ and eax, 0fffffffeh ; Clear PE bit (bit #0)
+ mov cr0, eax ; Activate real mode
+ DB 0xea ; jmp far AsmJmpAddr32
+ASM_PFX(AsmJmpAddr32): DD 0
+
+global ASM_PFX(PageFaultHandlerHook)
+ASM_PFX(PageFaultHandlerHook):
+BITS 64
+ push rax ; save all volatile registers
+ push rcx
+ push rdx
+ push r8
+ push r9
+ push r10
+ push r11
+ ; save volatile fp registers
+ add rsp, -0x68
+ stmxcsr [rsp + 0x60]
+ movdqa [rsp + 0x0], xmm0
+ movdqa [rsp + 0x10], xmm1
+ movdqa [rsp + 0x20], xmm2
+ movdqa [rsp + 0x30], xmm3
+ movdqa [rsp + 0x40], xmm4
+ movdqa [rsp + 0x50], xmm5
+
+ add rsp, -0x20
+ call ASM_PFX(PageFaultHandler)
+ add rsp, 0x20
+
+ ; load volatile fp registers
+ ldmxcsr [rsp + 0x60]
+ movdqa xmm0, [rsp + 0x0]
+ movdqa xmm1, [rsp + 0x10]
+ movdqa xmm2, [rsp + 0x20]
+ movdqa xmm3, [rsp + 0x30]
+ movdqa xmm4, [rsp + 0x40]
+ movdqa xmm5, [rsp + 0x50]
+ add rsp, 0x68
+
+ test al, al
+
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rdx
+ pop rcx
+ pop rax ; restore all volatile registers
+ jnz .1
+ jmp qword [ASM_PFX(mOriginalHandler)]
+.1:
+ add rsp, 0x8 ; skip error code for PF
+ iretq
+
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c
index 7fc6cdcb4e..1525b38906 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/SetIdtEntry.c
@@ -1,272 +1,272 @@
-/** @file
- Set a IDT entry for debug purpose
-
- Set a IDT entry for interrupt vector 3 for debug purpose for x64 platform
-
-Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
-Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
-
-
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-#include "ScriptExecute.h"
-
-//
-// 8 extra pages for PF handler.
-//
-#define EXTRA_PAGE_TABLE_PAGES 8
-
-#define IA32_PG_P BIT0
-#define IA32_PG_RW BIT1
-#define IA32_PG_PS BIT7
-
-UINT64 mPhyMask;
-VOID *mOriginalHandler;
-UINTN mPageFaultBuffer;
-UINTN mPageFaultIndex = 0;
-//
-// Store the uplink information for each page being used.
-//
-UINT64 *mPageFaultUplink[EXTRA_PAGE_TABLE_PAGES];
-
-/**
- Page fault handler.
-
-**/
-VOID
-EFIAPI
-PageFaultHandlerHook (
- VOID
- );
-
-/**
- Hook IDT with our page fault handler so that the on-demand paging works on page fault.
-
- @param IdtEntry a pointer to IDT entry
-
-**/
-VOID
-HookPageFaultHandler (
- IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
- )
-{
- UINT32 RegEax;
- UINT8 PhysicalAddressBits;
- UINTN PageFaultHandlerHookAddress;
-
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000008) {
- AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
- PhysicalAddressBits = (UINT8)RegEax;
- } else {
- PhysicalAddressBits = 36;
- }
-
- mPhyMask = LShiftU64 (1, PhysicalAddressBits) - 1;
- mPhyMask &= (1ull << 48) - SIZE_4KB;
-
- //
- // Set Page Fault entry to catch >4G access
- //
- PageFaultHandlerHookAddress = (UINTN)PageFaultHandlerHook;
- mOriginalHandler = (VOID *)(UINTN)(LShiftU64 (IdtEntry->Bits.OffsetUpper, 32) + IdtEntry->Bits.OffsetLow + (IdtEntry->Bits.OffsetHigh << 16));
- IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
- IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();
- IdtEntry->Bits.Reserved_0 = 0;
- IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
- IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
- IdtEntry->Bits.OffsetUpper = (UINT32)(PageFaultHandlerHookAddress >> 32);
- IdtEntry->Bits.Reserved_1 = 0;
-
- if (mPage1GSupport) {
- mPageFaultBuffer = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE (2);
- } else {
- mPageFaultBuffer = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE (6);
- }
-
- ZeroMem (mPageFaultUplink, sizeof (mPageFaultUplink));
-}
-
-/**
- The function will check if current waking vector is long mode.
-
- @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
-
- @retval TRUE Current context need long mode waking vector.
- @retval FALSE Current context need not long mode waking vector.
-**/
-BOOLEAN
-IsLongModeWakingVector (
- IN ACPI_S3_CONTEXT *AcpiS3Context
- )
-{
- EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
-
- Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)((UINTN)(AcpiS3Context->AcpiFacsTable));
- if ((Facs == NULL) ||
- (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
- ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)))
- {
- // Something wrong with FACS
- return FALSE;
- }
-
- if (Facs->XFirmwareWakingVector != 0) {
- if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
- ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
- ((Facs->OspmFlags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0))
- {
- // Both BIOS and OS wants 64bit vector
- if (sizeof (UINTN) == sizeof (UINT64)) {
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-/**
- Set a IDT entry for interrupt vector 3 for debug purpose.
-
- @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
-
-**/
-VOID
-SetIdtEntry (
- IN ACPI_S3_CONTEXT *AcpiS3Context
- )
-{
- IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
- IA32_DESCRIPTOR *IdtDescriptor;
- UINTN S3DebugBuffer;
- EFI_STATUS Status;
-
- //
- // Restore IDT for debug
- //
- IdtDescriptor = (IA32_DESCRIPTOR *)(UINTN)(AcpiS3Context->IdtrProfile);
- AsmWriteIdtr (IdtDescriptor);
-
- //
- // Setup the default CPU exception handlers
- //
- Status = InitializeCpuExceptionHandlers (NULL);
- ASSERT_EFI_ERROR (Status);
-
- DEBUG_CODE_BEGIN ();
- //
- // Update IDT entry INT3 if the instruction is valid in it
- //
- S3DebugBuffer = (UINTN)(AcpiS3Context->S3DebugBufferAddress);
- if (*(UINTN *)S3DebugBuffer != (UINTN)-1) {
- IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));
- IdtEntry->Bits.OffsetLow = (UINT16)S3DebugBuffer;
- IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();
- IdtEntry->Bits.Reserved_0 = 0;
- IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
- IdtEntry->Bits.OffsetHigh = (UINT16)(S3DebugBuffer >> 16);
- IdtEntry->Bits.OffsetUpper = (UINT32)(S3DebugBuffer >> 32);
- IdtEntry->Bits.Reserved_1 = 0;
- }
-
- DEBUG_CODE_END ();
-
- //
- // If both BIOS and OS wants long mode waking vector,
- // S3ResumePei should have established 1:1 Virtual to Physical identity mapping page table,
- // no need to hook page fault handler.
- //
- if (!IsLongModeWakingVector (AcpiS3Context)) {
- IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (14 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));
- HookPageFaultHandler (IdtEntry);
- }
-}
-
-/**
- Acquire page for page fault.
-
- @param[in, out] Uplink Pointer to up page table entry.
-
-**/
-VOID
-AcquirePage (
- IN OUT UINT64 *Uplink
- )
-{
- UINTN Address;
-
- Address = mPageFaultBuffer + EFI_PAGES_TO_SIZE (mPageFaultIndex);
- ZeroMem ((VOID *)Address, EFI_PAGES_TO_SIZE (1));
-
- //
- // Cut the previous uplink if it exists and wasn't overwritten.
- //
- if ((mPageFaultUplink[mPageFaultIndex] != NULL) &&
- ((*mPageFaultUplink[mPageFaultIndex] & ~mAddressEncMask & mPhyMask) == Address))
- {
- *mPageFaultUplink[mPageFaultIndex] = 0;
- }
-
- //
- // Link & Record the current uplink.
- //
- *Uplink = Address | mAddressEncMask | IA32_PG_P | IA32_PG_RW;
- mPageFaultUplink[mPageFaultIndex] = Uplink;
-
- mPageFaultIndex = (mPageFaultIndex + 1) % EXTRA_PAGE_TABLE_PAGES;
-}
-
-/**
- The page fault handler that on-demand read >4G memory/MMIO.
-
- @retval TRUE The page fault is correctly handled.
- @retval FALSE The page fault is not handled and is passed through to original handler.
-
-**/
-BOOLEAN
-EFIAPI
-PageFaultHandler (
- VOID
- )
-{
- UINT64 *PageTable;
- UINT64 PFAddress;
- UINTN PTIndex;
-
- PFAddress = AsmReadCr2 ();
- DEBUG ((DEBUG_INFO, "BootScript - PageFaultHandler: Cr2 - %lx\n", PFAddress));
-
- if (PFAddress >= mPhyMask + SIZE_4KB) {
- return FALSE;
- }
-
- PFAddress &= mPhyMask;
-
- PageTable = (UINT64 *)(UINTN)(AsmReadCr3 () & mPhyMask);
-
- PTIndex = BitFieldRead64 (PFAddress, 39, 47);
- // PML4E
- if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
- AcquirePage (&PageTable[PTIndex]);
- }
-
- PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & mPhyMask);
- PTIndex = BitFieldRead64 (PFAddress, 30, 38);
- // PDPTE
- if (mPage1GSupport) {
- PageTable[PTIndex] = ((PFAddress | mAddressEncMask) & ~((1ull << 30) - 1)) | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;
- } else {
- if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
- AcquirePage (&PageTable[PTIndex]);
- }
-
- PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & mPhyMask);
- PTIndex = BitFieldRead64 (PFAddress, 21, 29);
- // PD
- PageTable[PTIndex] = ((PFAddress | mAddressEncMask) & ~((1ull << 21) - 1)) | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;
- }
-
- return TRUE;
-}
+/** @file
+ Set a IDT entry for debug purpose
+
+ Set a IDT entry for interrupt vector 3 for debug purpose for x64 platform
+
+Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "ScriptExecute.h"
+
+//
+// 8 extra pages for PF handler.
+//
+#define EXTRA_PAGE_TABLE_PAGES 8
+
+#define IA32_PG_P BIT0
+#define IA32_PG_RW BIT1
+#define IA32_PG_PS BIT7
+
+UINT64 mPhyMask;
+VOID *mOriginalHandler;
+UINTN mPageFaultBuffer;
+UINTN mPageFaultIndex = 0;
+//
+// Store the uplink information for each page being used.
+//
+UINT64 *mPageFaultUplink[EXTRA_PAGE_TABLE_PAGES];
+
+/**
+ Page fault handler.
+
+**/
+VOID
+EFIAPI
+PageFaultHandlerHook (
+ VOID
+ );
+
+/**
+ Hook IDT with our page fault handler so that the on-demand paging works on page fault.
+
+ @param IdtEntry a pointer to IDT entry
+
+**/
+VOID
+HookPageFaultHandler (
+ IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+ UINTN PageFaultHandlerHookAddress;
+
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8)RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+
+ mPhyMask = LShiftU64 (1, PhysicalAddressBits) - 1;
+ mPhyMask &= (1ull << 48) - SIZE_4KB;
+
+ //
+ // Set Page Fault entry to catch >4G access
+ //
+ PageFaultHandlerHookAddress = (UINTN)PageFaultHandlerHook;
+ mOriginalHandler = (VOID *)(UINTN)(LShiftU64 (IdtEntry->Bits.OffsetUpper, 32) + IdtEntry->Bits.OffsetLow + (IdtEntry->Bits.OffsetHigh << 16));
+ IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
+ IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();
+ IdtEntry->Bits.Reserved_0 = 0;
+ IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
+ IdtEntry->Bits.OffsetUpper = (UINT32)(PageFaultHandlerHookAddress >> 32);
+ IdtEntry->Bits.Reserved_1 = 0;
+
+ if (mPage1GSupport) {
+ mPageFaultBuffer = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE (2);
+ } else {
+ mPageFaultBuffer = (UINTN)(AsmReadCr3 () & mPhyMask) + EFI_PAGES_TO_SIZE (6);
+ }
+
+ ZeroMem (mPageFaultUplink, sizeof (mPageFaultUplink));
+}
+
+/**
+ The function will check if current waking vector is long mode.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+
+ @retval TRUE Current context need long mode waking vector.
+ @retval FALSE Current context need not long mode waking vector.
+**/
+BOOLEAN
+IsLongModeWakingVector (
+ IN ACPI_S3_CONTEXT *AcpiS3Context
+ )
+{
+ EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
+
+ Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)((UINTN)(AcpiS3Context->AcpiFacsTable));
+ if ((Facs == NULL) ||
+ (Facs->Signature != EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) ||
+ ((Facs->FirmwareWakingVector == 0) && (Facs->XFirmwareWakingVector == 0)))
+ {
+ // Something wrong with FACS
+ return FALSE;
+ }
+
+ if (Facs->XFirmwareWakingVector != 0) {
+ if ((Facs->Version == EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
+ ((Facs->Flags & EFI_ACPI_4_0_64BIT_WAKE_SUPPORTED_F) != 0) &&
+ ((Facs->OspmFlags & EFI_ACPI_4_0_OSPM_64BIT_WAKE__F) != 0))
+ {
+ // Both BIOS and OS wants 64bit vector
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Set a IDT entry for interrupt vector 3 for debug purpose.
+
+ @param AcpiS3Context a pointer to a structure of ACPI_S3_CONTEXT
+
+**/
+VOID
+SetIdtEntry (
+ IN ACPI_S3_CONTEXT *AcpiS3Context
+ )
+{
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
+ IA32_DESCRIPTOR *IdtDescriptor;
+ UINTN S3DebugBuffer;
+ EFI_STATUS Status;
+
+ //
+ // Restore IDT for debug
+ //
+ IdtDescriptor = (IA32_DESCRIPTOR *)(UINTN)(AcpiS3Context->IdtrProfile);
+ AsmWriteIdtr (IdtDescriptor);
+
+ //
+ // Setup the default CPU exception handlers
+ //
+ Status = InitializeCpuExceptionHandlers (NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG_CODE_BEGIN ();
+ //
+ // Update IDT entry INT3 if the instruction is valid in it
+ //
+ S3DebugBuffer = (UINTN)(AcpiS3Context->S3DebugBufferAddress);
+ if (*(UINTN *)S3DebugBuffer != (UINTN)-1) {
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (3 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));
+ IdtEntry->Bits.OffsetLow = (UINT16)S3DebugBuffer;
+ IdtEntry->Bits.Selector = (UINT16)AsmReadCs ();
+ IdtEntry->Bits.Reserved_0 = 0;
+ IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ IdtEntry->Bits.OffsetHigh = (UINT16)(S3DebugBuffer >> 16);
+ IdtEntry->Bits.OffsetUpper = (UINT32)(S3DebugBuffer >> 32);
+ IdtEntry->Bits.Reserved_1 = 0;
+ }
+
+ DEBUG_CODE_END ();
+
+ //
+ // If both BIOS and OS wants long mode waking vector,
+ // S3ResumePei should have established 1:1 Virtual to Physical identity mapping page table,
+ // no need to hook page fault handler.
+ //
+ if (!IsLongModeWakingVector (AcpiS3Context)) {
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *)(IdtDescriptor->Base + (14 * sizeof (IA32_IDT_GATE_DESCRIPTOR)));
+ HookPageFaultHandler (IdtEntry);
+ }
+}
+
+/**
+ Acquire page for page fault.
+
+ @param[in, out] Uplink Pointer to up page table entry.
+
+**/
+VOID
+AcquirePage (
+ IN OUT UINT64 *Uplink
+ )
+{
+ UINTN Address;
+
+ Address = mPageFaultBuffer + EFI_PAGES_TO_SIZE (mPageFaultIndex);
+ ZeroMem ((VOID *)Address, EFI_PAGES_TO_SIZE (1));
+
+ //
+ // Cut the previous uplink if it exists and wasn't overwritten.
+ //
+ if ((mPageFaultUplink[mPageFaultIndex] != NULL) &&
+ ((*mPageFaultUplink[mPageFaultIndex] & ~mAddressEncMask & mPhyMask) == Address))
+ {
+ *mPageFaultUplink[mPageFaultIndex] = 0;
+ }
+
+ //
+ // Link & Record the current uplink.
+ //
+ *Uplink = Address | mAddressEncMask | IA32_PG_P | IA32_PG_RW;
+ mPageFaultUplink[mPageFaultIndex] = Uplink;
+
+ mPageFaultIndex = (mPageFaultIndex + 1) % EXTRA_PAGE_TABLE_PAGES;
+}
+
+/**
+ The page fault handler that on-demand read >4G memory/MMIO.
+
+ @retval TRUE The page fault is correctly handled.
+ @retval FALSE The page fault is not handled and is passed through to original handler.
+
+**/
+BOOLEAN
+EFIAPI
+PageFaultHandler (
+ VOID
+ )
+{
+ UINT64 *PageTable;
+ UINT64 PFAddress;
+ UINTN PTIndex;
+
+ PFAddress = AsmReadCr2 ();
+ DEBUG ((DEBUG_INFO, "BootScript - PageFaultHandler: Cr2 - %lx\n", PFAddress));
+
+ if (PFAddress >= mPhyMask + SIZE_4KB) {
+ return FALSE;
+ }
+
+ PFAddress &= mPhyMask;
+
+ PageTable = (UINT64 *)(UINTN)(AsmReadCr3 () & mPhyMask);
+
+ PTIndex = BitFieldRead64 (PFAddress, 39, 47);
+ // PML4E
+ if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
+ AcquirePage (&PageTable[PTIndex]);
+ }
+
+ PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & mPhyMask);
+ PTIndex = BitFieldRead64 (PFAddress, 30, 38);
+ // PDPTE
+ if (mPage1GSupport) {
+ PageTable[PTIndex] = ((PFAddress | mAddressEncMask) & ~((1ull << 30) - 1)) | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;
+ } else {
+ if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
+ AcquirePage (&PageTable[PTIndex]);
+ }
+
+ PageTable = (UINT64 *)(UINTN)(PageTable[PTIndex] & ~mAddressEncMask & mPhyMask);
+ PTIndex = BitFieldRead64 (PFAddress, 21, 29);
+ // PD
+ PageTable[PTIndex] = ((PFAddress | mAddressEncMask) & ~((1ull << 21) - 1)) | IA32_PG_P | IA32_PG_RW | IA32_PG_PS;
+ }
+
+ return TRUE;
+}