diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe')
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; +} |
