From: "Kuo, Ted" <ted.kuo@intel.com>
To: devel@edk2.groups.io
Cc: Chasel Chiu <chasel.chiu@intel.com>,
Nate DeSimone <nathaniel.l.desimone@intel.com>,
Star Zeng <star.zeng@intel.com>,
Ashraf Ali S <ashraf.ali.s@intel.com>
Subject: [edk2-devel][PATCH v2 4/8] IntelFsp2Pkg: FspSecCore support for X64
Date: Mon, 4 Apr 2022 14:23:07 +0800 [thread overview]
Message-ID: <a3f5029f45a03cb4dd844506d5faebdb1ad16809.1649053236.git.ted.kuo@intel.com> (raw)
In-Reply-To: <cover.1649053236.git.ted.kuo@intel.com>
In-Reply-To: <cover.1649053236.git.ted.kuo@intel.com>
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3893
1.Added FspSecCore support for X64.
2.Bumped FSP header revision to 7 to indicate FSP 64bit is supported.
Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Ashraf Ali S <ashraf.ali.s@intel.com>
Signed-off-by: Ted Kuo <ted.kuo@intel.com>
---
IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf | 8 +-
IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf | 9 +-
IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf | 8 +-
IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf | 10 +-
.../FspSecCore/Ia32/FspApiEntryCommon.nasm | 4 +-
IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm | 103 +++++
IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm | 76 ++++
IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm | 263 +++++++++++
IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm | 67 +++
IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm | 492 +++++++++++++++++++++
IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm | 34 ++
IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc | 11 +
IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm | 22 +
IntelFsp2Pkg/FspSecCore/X64/Stack.nasm | 73 +++
| 14 +-
IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc | 284 ++++++++++++
.../Library/BaseFspCommonLib/FspCommonLib.c | 1 +
.../Library/BaseFspSwitchStackLib/X64/Stack.nasm | 5 +-
18 files changed, 1473 insertions(+), 11 deletions(-)
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm
create mode 100644 IntelFsp2Pkg/FspSecCore/X64/Stack.nasm
create mode 100644 IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc
diff --git a/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf b/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
index 0a24eb2a8b..d64ec12499 100644
--- a/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
+++ b/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
@@ -17,7 +17,7 @@
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32
+# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
@@ -30,6 +30,12 @@
Ia32/FspApiEntryCommon.nasm
Ia32/FspHelper.nasm
+[Sources.X64]
+ X64/Stack.nasm
+ X64/Fsp22ApiEntryS.nasm
+ X64/FspApiEntryCommon.nasm
+ X64/FspHelper.nasm
+
[Binaries.Ia32]
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
diff --git a/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf b/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
index 7b05cae641..34794dd16e 100644
--- a/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
+++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
@@ -17,7 +17,7 @@
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32
+# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
@@ -34,6 +34,13 @@
Ia32/FspHelper.nasm
Ia32/ReadEsp.nasm
+[Sources.X64]
+ X64/Stack.nasm
+ X64/FspApiEntryM.nasm
+ X64/FspApiEntryCommon.nasm
+ X64/FspHelper.nasm
+ X64/ReadRsp.nasm
+
[Binaries.Ia32]
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
diff --git a/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf b/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
index 1d9c2554d1..79d4e0674e 100644
--- a/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
+++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
@@ -17,7 +17,7 @@
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32
+# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
@@ -30,6 +30,12 @@
Ia32/FspApiEntryCommon.nasm
Ia32/FspHelper.nasm
+[Sources.X64]
+ X64/Stack.nasm
+ X64/FspApiEntryS.nasm
+ X64/FspApiEntryCommon.nasm
+ X64/FspHelper.nasm
+
[Binaries.Ia32]
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
diff --git a/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf b/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
index 664bde5678..f08a3b2c2b 100644
--- a/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
+++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
@@ -17,17 +17,19 @@
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32
+# VALID_ARCHITECTURES = IA32 X64
#
-[Sources]
-
-
[Sources.IA32]
Ia32/Stack.nasm
Ia32/FspApiEntryT.nasm
Ia32/FspHelper.nasm
+[Sources.X64]
+ X64/Stack.nasm
+ X64/FspApiEntryT.nasm
+ X64/FspHelper.nasm
+
[Binaries.Ia32]
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
diff --git a/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm b/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
index 26ae7d9fd3..024f7aec5c 100644
--- a/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
+++ b/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
@@ -7,6 +7,8 @@
SECTION .text
+STACK_SAVED_EAX_OFFSET EQU 4 * 7 ; size of a general purpose register * eax index
+
;
; Following functions will be provided in C
;
@@ -52,7 +54,7 @@ FspApiCommon1:
add esp, 8
cmp eax, 0
jz FspApiCommon2
- mov dword [esp + (4 * 7)], eax
+ mov dword [esp + STACK_SAVED_EAX_OFFSET], eax
popad
exit:
ret
diff --git a/IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm b/IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm
new file mode 100644
index 0000000000..c739793a39
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/Fsp22ApiEntryS.nasm
@@ -0,0 +1,103 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+;
+; Following functions will be provided in C
+;
+extern ASM_PFX(FspApiCommon)
+extern ASM_PFX(FspMultiPhaseSiInitApiHandler)
+
+STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index
+
+;----------------------------------------------------------------------------
+; NotifyPhase API
+;
+; This FSP API will notify the FSP about the different phases in the boot
+; process
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(NotifyPhaseApi)
+ASM_PFX(NotifyPhaseApi):
+ mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspSiliconInit API
+;
+; This FSP API initializes the CPU and the chipset including the IO
+; controllers in the chipset to enable normal operation of these devices.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspSiliconInitApi)
+ASM_PFX(FspSiliconInitApi):
+ mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspMultiPhaseSiInitApi API
+;
+; This FSP API provides multi-phase silicon initialization, which brings greater
+; modularity beyond the existing FspSiliconInit() API.
+; Increased modularity is achieved by adding an extra API to FSP-S.
+; This allows the bootloader to add board specific initialization steps throughout
+; the SiliconInit flow as needed.
+;
+;----------------------------------------------------------------------------
+
+%include "PushPopRegsNasm.inc"
+
+global ASM_PFX(FspMultiPhaseSiInitApi)
+ASM_PFX(FspMultiPhaseSiInitApi):
+ mov eax, 6 ; FSP_API_INDEX.FspMultiPhaseSiInitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspApiCommonContinue API
+;
+; This is the FSP API common entry point to resume the FSP execution
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspApiCommonContinue)
+ASM_PFX(FspApiCommonContinue):
+ ;
+ ; Handle FspMultiPhaseSiInitApiIndex API
+ ;
+ cmp eax, 6
+ jnz NotMultiPhaseSiInitApi
+
+ PUSHA_64
+ mov rdx, rcx ; move ApiParam to rdx
+ mov rcx, rax ; move ApiIdx to rcx
+ call ASM_PFX(FspMultiPhaseSiInitApiHandler)
+ mov qword [rsp + STACK_SAVED_RAX_OFFSET], rax
+ POPA_64
+ ret
+
+NotMultiPhaseSiInitApi:
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; Empty function for WHOLEARCHIVE build option
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; Module Entrypoint API
+;----------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ jmp $
+
diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm
new file mode 100644
index 0000000000..718e672e02
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm
@@ -0,0 +1,76 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+%include "PushPopRegsNasm.inc"
+
+STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index
+
+;
+; Following functions will be provided in C
+;
+extern ASM_PFX(Loader2PeiSwitchStack)
+extern ASM_PFX(FspApiCallingCheck)
+
+;
+; Following functions will be provided in ASM
+;
+extern ASM_PFX(FspApiCommonContinue)
+extern ASM_PFX(AsmGetFspInfoHeader)
+
+;----------------------------------------------------------------------------
+; FspApiCommon API
+;
+; This is the FSP API common entry point to resume the FSP execution
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspApiCommon)
+ASM_PFX(FspApiCommon):
+ ;
+ ; RAX holds the API index
+ ;
+
+ ;
+ ; Stack must be ready
+ ;
+ push rax
+ add rsp, 8
+ cmp rax, [rsp - 8]
+ jz FspApiCommon1
+ mov rax, 08000000000000003h
+ jmp exit
+
+FspApiCommon1:
+ ;
+ ; Verify the calling condition
+ ;
+ PUSHA_64
+ mov rdx, rcx ; move ApiParam to rdx
+ mov rcx, rax ; move ApiIdx to rcx
+ call ASM_PFX(FspApiCallingCheck)
+ cmp rax, 0
+ jz FspApiCommon2
+ mov [rsp + STACK_SAVED_RAX_OFFSET], rax
+ POPA_64
+exit:
+ ret
+
+FspApiCommon2:
+ POPA_64
+ cmp rax, 3 ; FspMemoryInit API
+ jz FspApiCommon3
+
+ cmp rax, 6 ; FspMultiPhaseSiInitApiIndex API
+ jz FspApiCommon3
+
+ call ASM_PFX(AsmGetFspInfoHeader)
+ jmp ASM_PFX(Loader2PeiSwitchStack)
+
+FspApiCommon3:
+ jmp ASM_PFX(FspApiCommonContinue)
+
diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm
new file mode 100644
index 0000000000..e6e00957f6
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm
@@ -0,0 +1,263 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+%include "PushPopRegsNasm.inc"
+
+;
+; Following are fixed PCDs
+;
+extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))
+
+struc FSPM_UPD_COMMON_FSP24
+ ; FSP_UPD_HEADER {
+ .FspUpdHeader: resd 8
+ ; }
+ ; FSPM_ARCH2_UPD {
+ .Revision: resb 1
+ .Reserved: resb 3
+ .Length resd 1
+ .StackBase: resq 1
+ .StackSize: resq 1
+ .BootLoaderTolumSize: resd 1
+ .BootMode: resd 1
+ .FspEventHandler resq 1
+ .EnableMultiPhaseMemoryInit resb 1
+ .Reserved1: resb 23
+ ; }
+ .size:
+endstruc
+
+;
+; Following functions will be provided in C
+;
+extern ASM_PFX(SecStartup)
+extern ASM_PFX(FspApiCommon)
+
+;
+; Following functions will be provided in PlatformSecLib
+;
+extern ASM_PFX(AsmGetFspBaseAddress)
+extern ASM_PFX(AsmGetFspInfoHeader)
+
+FSP_HEADER_IMGBASE_OFFSET EQU 1Ch
+FSP_HEADER_CFGREG_OFFSET EQU 24h
+
+;----------------------------------------------------------------------------
+; FspMemoryInit API
+;
+; This FSP API is called after TempRamInit and initializes the memory.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspMemoryInitApi)
+ASM_PFX(FspMemoryInitApi):
+ mov eax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; TempRamExitApi API
+;
+; This API tears down temporary RAM
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamExitApi)
+ASM_PFX(TempRamExitApi):
+ mov eax, 4 ; FSP_API_INDEX.TempRamExitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspApiCommonContinue API
+;
+; This is the FSP API common entry point to resume the FSP execution
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspApiCommonContinue)
+ASM_PFX(FspApiCommonContinue):
+ ;
+ ; RAX holds the API index
+ ; Push RDX and RCX to form CONTEXT_STACK_64
+ ;
+ push rdx ; Push a QWORD data for stack alignment
+ push rdx ; Push API Parameter2 on stack
+ push rcx ; Push API Parameter1 on stack
+
+ ;
+ ; FspMemoryInit API setup the initial stack frame
+ ;
+
+ ;
+ ; Place holder to store the FspInfoHeader pointer
+ ;
+ push rax
+
+ ;
+ ; Update the FspInfoHeader pointer
+ ;
+ push rax
+ call ASM_PFX(AsmGetFspInfoHeader)
+ mov [rsp + 8], rax
+ pop rax
+
+ ;
+ ; Create a Task Frame in the stack for the Boot Loader
+ ;
+ pushfq
+ cli
+ PUSHA_64
+
+ ; Reserve 16 bytes for IDT save/restore
+ sub rsp, 16
+ sidt [rsp]
+
+ ; Get Stackbase and StackSize from FSPM_UPD Param
+ mov rdx, rcx ; Put FSPM_UPD Param to rdx
+ cmp rdx, 0
+ jnz FspStackSetup
+
+ ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null
+ xchg rbx, rax
+ call ASM_PFX(AsmGetFspInfoHeader)
+ mov edx, [rax + FSP_HEADER_IMGBASE_OFFSET]
+ add edx, [rax + FSP_HEADER_CFGREG_OFFSET]
+ xchg rbx, rax
+
+FspStackSetup:
+ ;
+ ; StackBase = temp memory base, StackSize = temp memory size
+ ;
+ mov rdi, [rdx + FSPM_UPD_COMMON_FSP24.StackBase]
+ mov ecx, [rdx + FSPM_UPD_COMMON_FSP24.StackSize]
+
+ ;
+ ; Keep using bootloader stack if heap size % is 0
+ ;
+ mov rbx, ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))
+ mov bl, BYTE [rbx]
+ cmp bl, 0
+ jz SkipStackSwitch
+
+ ;
+ ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0
+ ;
+ add rdi, rcx
+ ;
+ ; Switch to new FSP stack
+ ;
+ xchg rdi, rsp ; Exchange rdi and rsp, rdi will be assigned to the current rsp pointer and rsp will be Stack base + Stack size
+
+SkipStackSwitch:
+ ;
+ ; If heap size % is 0:
+ ; EDI is FSPM_UPD_COMMON_FSP24.StackBase and will hold ESP later (boot loader stack pointer)
+ ; ECX is FSPM_UPD_COMMON_FSP24.StackSize
+ ; ESP is boot loader stack pointer (no stack switch)
+ ; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON_FSP24.StackBase later)
+ ;
+ ; If heap size % is not 0
+ ; EDI is boot loader stack pointer
+ ; ECX is FSPM_UPD_COMMON_FSP24.StackSize
+ ; ESP is new stack (FSPM_UPD_COMMON_FSP24.StackBase + FSPM_UPD_COMMON_FSP24.StackSize)
+ ; BL is NOT 0 to indicate stack has switched
+ ;
+ cmp bl, 0
+ jnz StackHasBeenSwitched
+
+ mov rbx, rdi ; Put FSPM_UPD_COMMON_FSP24.StackBase to rbx as temp memory base
+ mov rdi, rsp ; Put boot loader stack pointer to rdi
+ jmp StackSetupDone
+
+StackHasBeenSwitched:
+ mov rbx, rsp ; Put Stack base + Stack size in ebx
+ sub rbx, rcx ; Stack base + Stack size - Stack size as temp memory base
+
+StackSetupDone:
+
+ ;
+ ; Per X64 calling convention, make sure RSP is 16-byte aligned.
+ ;
+ mov rdx, rsp
+ and rdx, 0fh
+ sub rsp, rdx
+
+ ;
+ ; Pass the API Idx to SecStartup
+ ;
+ push rax
+
+ ;
+ ; Pass the BootLoader stack to SecStartup
+ ;
+ push rdi
+
+ ;
+ ; Pass BFV into the PEI Core
+ ; It uses relative address to calculate the actual boot FV base
+ ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and
+ ; PcdFspAreaBaseAddress are the same. For FSP with multiple FVs,
+ ; they are different. The code below can handle both cases.
+ ;
+ call ASM_PFX(AsmGetFspBaseAddress)
+ mov r8, rax
+
+ ;
+ ; Pass entry point of the PEI core
+ ;
+ call ASM_PFX(AsmGetPeiCoreOffset)
+ lea r9, [r8 + rax]
+
+ ;
+ ; Pass stack base and size into the PEI Core
+ ;
+ mov rcx, rcx
+ mov rdx, rbx
+
+ ;
+ ; Pass Control into the PEI Core
+ ; RCX = SizeOfRam, RDX = TempRamBase, R8 = BFV, R9 = PeiCoreEntry, Last 1 Stack = BL stack, Last 2 Stack = API index
+ ; According to X64 calling convention, caller has to allocate 32 bytes as a shadow store on call stack right before
+ ; calling the function.
+ ;
+ sub rsp, 20h
+ call ASM_PFX(SecStartup)
+ add rsp, 20h
+exit:
+ ret
+
+global ASM_PFX(FspPeiCoreEntryOff)
+ASM_PFX(FspPeiCoreEntryOff):
+ ;
+ ; This value will be pached by the build script
+ ;
+ DD 0x12345678
+
+global ASM_PFX(AsmGetPeiCoreOffset)
+ASM_PFX(AsmGetPeiCoreOffset):
+ push rbx
+ mov rbx, ASM_PFX(FspPeiCoreEntryOff)
+ mov eax, dword[ebx]
+ pop rbx
+ ret
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; Empty function for WHOLEARCHIVE build option
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; Module Entrypoint API
+;----------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ jmp $
+
diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm
new file mode 100644
index 0000000000..f863ef0078
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryS.nasm
@@ -0,0 +1,67 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+;
+; Following functions will be provided in C
+;
+extern ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; NotifyPhase API
+;
+; This FSP API will notify the FSP about the different phases in the boot
+; process
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(NotifyPhaseApi)
+ASM_PFX(NotifyPhaseApi):
+ mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspSiliconInit API
+;
+; This FSP API initializes the CPU and the chipset including the IO
+; controllers in the chipset to enable normal operation of these devices.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspSiliconInitApi)
+ASM_PFX(FspSiliconInitApi):
+ mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspApiCommonContinue API
+;
+; This is the FSP API common entry point to resume the FSP execution
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspApiCommonContinue)
+ASM_PFX(FspApiCommonContinue):
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; Empty function for WHOLEARCHIVE build option
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; Module Entrypoint API
+;----------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ jmp $
+
diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
new file mode 100644
index 0000000000..1406ba8833
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
@@ -0,0 +1,492 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+%include "SaveRestoreSseAvxNasm.inc"
+%include "MicrocodeLoadNasm.inc"
+
+;
+; Following are fixed PCDs
+;
+extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
+extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
+extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
+
+;
+; Following functions will be provided in PlatformSecLib
+;
+extern ASM_PFX(AsmGetFspBaseAddress)
+extern ASM_PFX(AsmGetFspInfoHeader)
+;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation
+extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation
+extern ASM_PFX(SecCarInit)
+
+;
+; Define the data length that we saved on the stack top
+;
+DATA_LEN_OF_PER0 EQU 18h
+DATA_LEN_OF_MCUD EQU 18h
+DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
+
+;
+; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
+; build error. This needs to be fixed later on.
+;
+struc MicrocodeHdr
+ .MicrocodeHdrVersion: resd 1
+ .MicrocodeHdrRevision: resd 1
+ .MicrocodeHdrDate: resd 1
+ .MicrocodeHdrProcessor: resd 1
+ .MicrocodeHdrChecksum: resd 1
+ .MicrocodeHdrLoader: resd 1
+ .MicrocodeHdrFlags: resd 1
+ .MicrocodeHdrDataSize: resd 1
+ .MicrocodeHdrTotalSize: resd 1
+ .MicrocodeHdrRsvd: resd 3
+ .size:
+endstruc
+
+struc ExtSigHdr
+ .ExtSigHdrCount: resd 1
+ .ExtSigHdrChecksum: resd 1
+ .ExtSigHdrRsvd: resd 3
+ .size:
+endstruc
+
+struc ExtSig
+ .ExtSigProcessor: resd 1
+ .ExtSigFlags: resd 1
+ .ExtSigChecksum: resd 1
+ .size:
+endstruc
+
+struc LoadMicrocodeParamsFsp24
+ ; FSP_UPD_HEADER {
+ .FspUpdHeaderSignature: resd 2
+ .FspUpdHeaderRevision: resb 1
+ .FspUpdHeaderReserved: resb 23
+ ; }
+ ; FSPT_ARCH2_UPD {
+ .FsptArchRevision: resb 1
+ .FsptArchReserved: resb 3
+ .FsptArchLength: resd 1
+ .FspDebugHandler resq 1
+ .MicrocodeCodeAddr: resq 1
+ .MicrocodeCodeSize: resq 1
+ .CodeRegionBase: resq 1
+ .CodeRegionSize: resq 1
+ ; }
+ .size:
+endstruc
+
+;
+; @todo: The strong/weak implementation does not work.
+; This needs to be reviewed later.
+;
+;------------------------------------------------------------------------------
+;
+;;global ASM_PFX(SecPlatformInitDefault)
+;ASM_PFX(SecPlatformInitDefault):
+; ; Inputs:
+; ; ymm7 -> Return address
+; ; Outputs:
+; ; rax -> 0 - Successful, Non-zero - Failed.
+; ; Register Usage:
+; ; rax is cleared and rbp is used for return address.
+; ; All others reserved.
+;
+; ; Save return address to RBP
+; LOAD_RBP
+;
+; xor rax, rax
+;Exit1:
+; jmp rbp
+
+;------------------------------------------------------------------------------
+global ASM_PFX(LoadMicrocodeDefault)
+ASM_PFX(LoadMicrocodeDefault):
+ ; Inputs:
+ ; rsp -> LoadMicrocodeParams pointer
+ ; Register Usage:
+ ; rsp Preserved
+ ; All others destroyed
+ ; Assumptions:
+ ; No memory available, stack is hard-coded and used for return address
+ ; Executed by SBSP and NBSP
+ ; Beginning of microcode update region starts on paragraph boundary
+
+ ;
+ ; Save return address to RBP
+ ;
+ LOAD_RBP
+
+ cmp rsp, 0
+ jz ParamError
+ mov eax, dword [rsp + 8] ; Parameter pointer
+ cmp eax, 0
+ jz ParamError
+ mov esp, eax
+
+ ; skip loading Microcode if the MicrocodeCodeSize is zero
+ ; and report error if size is less than 2k
+ ; first check UPD header revision
+ cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
+ jb ParamError
+ cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
+ jne ParamError
+
+ ; UPD structure is compliant with FSP spec 2.4
+ mov eax, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
+ cmp eax, 0
+ jz Exit2
+ cmp eax, 0800h
+ jl ParamError
+
+ mov esi, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
+ cmp esi, 0
+ jnz CheckMainHeader
+
+ParamError:
+ mov rax, 08000000000000002h
+ jmp Exit2
+
+CheckMainHeader:
+ ; Get processor signature and platform ID from the installed processor
+ ; and save into registers for later use
+ ; ebx = processor signature
+ ; edx = platform ID
+ mov eax, 1
+ cpuid
+ mov ebx, eax
+ mov ecx, MSR_IA32_PLATFORM_ID
+ rdmsr
+ mov ecx, edx
+ shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
+ and ecx, 7h ; platform id at bit[52..50]
+ mov edx, 1
+ shl edx, cl
+
+ ; Current register usage
+ ; esp -> stack with parameters
+ ; esi -> microcode update to check
+ ; ebx = processor signature
+ ; edx = platform ID
+
+ ; Check for valid microcode header
+ ; Minimal test checking for header version and loader version as 1
+ mov eax, dword 1
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
+ jne AdvanceFixedSize
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
+ jne AdvanceFixedSize
+
+ ; Check if signature and plaform ID match
+ cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
+ jne LoadMicrocodeDefault1
+ test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
+ jnz LoadCheck ; Jif signature and platform ID match
+
+LoadMicrocodeDefault1:
+ ; Check if extended header exists
+ ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
+ xor rax, rax
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
+ je NextMicrocode
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
+ je NextMicrocode
+
+ ; Then verify total size - sizeof header > data size
+ mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
+ sub ecx, MicrocodeHdr.size
+ cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
+ jng NextMicrocode ; Jif extended header does not exist
+
+ ; Set edi -> extended header
+ mov edi, esi
+ add edi, MicrocodeHdr.size
+ add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
+
+ ; Get count of extended structures
+ mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
+
+ ; Move pointer to first signature structure
+ add edi, ExtSigHdr.size
+
+CheckExtSig:
+ ; Check if extended signature and platform ID match
+ cmp dword [edi + ExtSig.ExtSigProcessor], ebx
+ jne LoadMicrocodeDefault2
+ test dword [edi + ExtSig.ExtSigFlags], edx
+ jnz LoadCheck ; Jif signature and platform ID match
+LoadMicrocodeDefault2:
+ ; Check if any more extended signatures exist
+ add edi, ExtSig.size
+ loop CheckExtSig
+
+NextMicrocode:
+ ; Advance just after end of this microcode
+ xor rax, rax
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
+ je LoadMicrocodeDefault3
+ add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
+ jmp CheckAddress
+LoadMicrocodeDefault3:
+ add esi, dword 2048
+ jmp CheckAddress
+
+AdvanceFixedSize:
+ ; Advance by 4X dwords
+ add esi, dword 1024
+
+CheckAddress:
+ ; Check UPD header revision
+ cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
+ jb ParamError
+ cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
+ jne ParamError
+
+ ; UPD structure is compliant with FSP spec 2.4
+ ; Is automatic size detection ?
+ mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
+ cmp rax, 0ffffffffffffffffh
+ jz LoadMicrocodeDefault4
+
+ ; Address >= microcode region address + microcode region size?
+ add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
+ cmp rsi, rax
+ jae Done ;Jif address is outside of microcode region
+ jmp CheckMainHeader
+
+LoadMicrocodeDefault4:
+ ; Is valid Microcode start point ?
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
+ jz Done
+
+LoadCheck:
+ ; Get the revision of the current microcode update loaded
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ xor eax, eax ; Clear EAX
+ xor edx, edx ; Clear EDX
+ wrmsr ; Load 0 to MSR at 8Bh
+
+ mov eax, 1
+ cpuid
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ rdmsr ; Get current microcode signature
+
+ ; Verify this microcode update is not already loaded
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
+ je Continue
+
+LoadMicrocode:
+ ; EAX contains the linear address of the start of the Update Data
+ ; EDX contains zero
+ ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
+ ; Start microcode load with wrmsr
+ mov eax, esi
+ add eax, MicrocodeHdr.size
+ xor edx, edx
+ mov ecx, MSR_IA32_BIOS_UPDT_TRIG
+ wrmsr
+ mov eax, 1
+ cpuid
+
+Continue:
+ jmp NextMicrocode
+
+Done:
+ mov eax, 1
+ cpuid
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ rdmsr ; Get current microcode signature
+ xor eax, eax
+ cmp edx, 0
+ jnz Exit2
+ mov eax, 0800000000000000Eh
+
+Exit2:
+ jmp rbp
+
+
+global ASM_PFX(EstablishStackFsp)
+ASM_PFX(EstablishStackFsp):
+ ;
+ ; Save parameter pointer in rdx
+ ;
+ mov rdx, qword [rsp + 8]
+
+ ;
+ ; Enable FSP STACK
+ ;
+ mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
+ mov esp, DWORD[rax]
+ mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
+ add esp, DWORD[rax]
+
+ sub esp, 4
+ mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region
+ sub esp, 4
+ mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'
+
+ ; check UPD structure revision (rdx + 8)
+ cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
+ jb ParamError1
+ cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
+ je Fsp24UpdHeader
+
+ParamError1:
+ mov rax, 08000000000000002h
+ jmp EstablishStackFspExit
+
+Fsp24UpdHeader:
+ ; UPD structure is compliant with FSP spec 2.4
+ xor rax, rax
+ mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h
+ sub rsp, 8
+ mov qword[rsp], rax
+ mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h
+ sub rsp, 8
+ mov qword[rsp], rax
+ mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h
+ sub rsp, 8
+ mov qword[rsp], rax
+ mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h
+ sub rsp, 8
+ mov qword[rsp], rax
+
+ContinueAfterUpdPush:
+ ;
+ ; Save API entry/exit timestamp into stack
+ ;
+ sub esp, 4
+ mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region
+ sub esp, 4
+ mov dword[esp], 30524550h ; Signature of the data region 'PER0'
+ rdtsc
+ sub esp, 4
+ mov dword[esp], edx
+ sub esp, 4
+ mov dword[esp], eax
+ LOAD_TS rax
+ push rax
+
+ ;
+ ; Terminator for the data on stack
+ ;
+ push 0
+
+ ;
+ ; Set ECX/EDX to the BootLoader temporary memory range
+ ;
+ mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
+ mov edx, [ecx]
+ mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
+ add edx, [ecx]
+ mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
+ sub edx, [ecx]
+ mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
+ mov ecx, [ecx]
+
+ cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
+ jb EstablishStackFspSuccess
+ mov rax, 08000000000000003h ; EFI_UNSUPPORTED
+ jmp EstablishStackFspExit
+EstablishStackFspSuccess:
+ xor rax, rax
+
+EstablishStackFspExit:
+ RET_YMM
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; This FSP API will load the microcode update, enable code caching for the
+; region specified by the boot loader and also setup a temporary stack to be
+; used till main memory is initialized.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ ;
+ ; Ensure both SSE and AVX are enabled
+ ;
+ ENABLE_SSE
+ ENABLE_AVX
+
+ ;
+ ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6
+ ;
+ SAVE_REGS
+
+ ;
+ ; Save BFV address in YMM9
+ ;
+ SAVE_BFV rbp
+
+ ;
+ ; Save timestamp into YMM6
+ ;
+ rdtsc
+ shl rdx, 32
+ or rax, rdx
+ SAVE_TS rax
+
+ ;
+ ; Check Parameter
+ ;
+ mov rax, qword [rsp + 8]
+ cmp rax, 0
+ mov rax, 08000000000000002h
+ jz TempRamInitExit
+
+ ;
+ ; Sec Platform Init
+ ;
+ CALL_YMM ASM_PFX(SecPlatformInit)
+ cmp eax, 0
+ jnz TempRamInitExit
+
+ ; Load microcode
+ LOAD_RSP
+ CALL_YMM ASM_PFX(LoadMicrocodeDefault)
+ SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).
+ ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.
+
+ ; Call Sec CAR Init
+ LOAD_RSP
+ CALL_YMM ASM_PFX(SecCarInit)
+ cmp rax, 0
+ jnz TempRamInitExit
+
+ LOAD_RSP
+ CALL_YMM ASM_PFX(EstablishStackFsp)
+ cmp rax, 0
+ jnz TempRamInitExit
+
+ LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).
+
+TempRamInitExit:
+ mov bl, al ; save al data in bl
+ mov al, 07Fh ; API exit postcode 7f
+ out 080h, al
+ mov al, bl ; restore al data from bl
+
+ ;
+ ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6
+ ;
+ LOAD_REGS
+ LOAD_BFV rbp
+ ret
+
+;----------------------------------------------------------------------------
+; Module Entrypoint API
+;----------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ jmp $
+
diff --git a/IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm b/IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm
new file mode 100644
index 0000000000..122fa1d174
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/FspHelper.nasm
@@ -0,0 +1,34 @@
+;; @file
+; Provide FSP helper function.
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+ DEFAULT REL
+ SECTION .text
+
+global ASM_PFX(AsmGetFspBaseAddress)
+ASM_PFX(AsmGetFspBaseAddress):
+ call ASM_PFX(AsmGetFspInfoHeader)
+ add rax, 0x1C
+ mov eax, [rax]
+ ret
+
+global ASM_PFX(AsmGetFspInfoHeader)
+ASM_PFX(AsmGetFspInfoHeader):
+ lea rax, [ASM_PFX(AsmGetFspInfoHeader)]
+ DB 0x48, 0x2d ; sub rax, 0x????????
+global ASM_PFX(FspInfoHeaderRelativeOff)
+ASM_PFX(FspInfoHeaderRelativeOff):
+ DD 0x12345678 ; This value must be patched by the build script
+ and rax, 0xffffffff
+ ret
+
+global ASM_PFX(AsmGetFspInfoHeaderNoStack)
+ASM_PFX(AsmGetFspInfoHeaderNoStack):
+ lea rax, [ASM_PFX(AsmGetFspInfoHeader)]
+ lea rcx, [ASM_PFX(FspInfoHeaderRelativeOff)]
+ mov ecx, [rcx]
+ sub rax, rcx
+ and rax, 0xffffffff
+ jmp rdi
diff --git a/IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc b/IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc
new file mode 100644
index 0000000000..4ec5070d25
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/MicrocodeLoadNasm.inc
@@ -0,0 +1,11 @@
+;; @file
+;
+;@copyright
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+MSR_IA32_PLATFORM_ID equ 000000017h
+MSR_IA32_BIOS_UPDT_TRIG equ 000000079h
+MSR_IA32_BIOS_SIGN_ID equ 00000008bh
+
diff --git a/IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm b/IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm
new file mode 100644
index 0000000000..af82509803
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/ReadRsp.nasm
@@ -0,0 +1,22 @@
+;; @file
+; Provide read RSP function
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; UINTN
+; EFIAPI
+; AsmReadStackPointer (
+; VOID
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmReadStackPointer)
+ASM_PFX(AsmReadStackPointer):
+ mov rax, rsp
+ ret
+
diff --git a/IntelFsp2Pkg/FspSecCore/X64/Stack.nasm b/IntelFsp2Pkg/FspSecCore/X64/Stack.nasm
new file mode 100644
index 0000000000..0af7f54f6f
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/Stack.nasm
@@ -0,0 +1,73 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Abstract:
+;
+; Switch the stack from temporary memory to permanent memory.
+;
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; SecSwitchStack (
+; UINT64 TemporaryMemoryBase,
+; UINT64 PermanentMemoryBase
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(SecSwitchStack)
+ASM_PFX(SecSwitchStack):
+ ;
+ ; Save four register: rax, rbx, rcx, rdx
+ ;
+ push rax
+ push rbx
+ push rcx
+ push rdx
+
+ ;
+ ; !!CAUTION!! this function address's is pushed into stack after
+ ; migration of whole temporary memory, so need save it to permanent
+ ; memory at first!
+ ;
+
+ mov rbx, rcx ; Save the first parameter
+ mov rcx, rdx ; Save the second parameter
+
+ ;
+ ; Save this function's return address into permanent memory at first.
+ ; Then, Fixup the esp point to permanent memory
+ ;
+ mov rax, rsp
+ sub rax, rbx
+ add rax, rcx
+ mov rdx, qword [rsp] ; copy pushed register's value to permanent memory
+ mov qword [rax], rdx
+ mov rdx, qword [rsp + 8]
+ mov qword [rax + 8], rdx
+ mov rdx, qword [rsp + 16]
+ mov qword [rax + 16], rdx
+ mov rdx, qword [rsp + 24]
+ mov qword [rax + 24], rdx
+ mov rdx, qword [rsp + 32] ; Update this function's return address into permanent memory
+ mov qword [rax + 32], rdx
+ mov rsp, rax ; From now, rsp is pointed to permanent memory
+
+ ;
+ ; Fixup the rbp point to permanent memory
+ ;
+ mov rax, rbp
+ sub rax, rbx
+ add rax, rcx
+ mov rbp, rax ; From now, rbp is pointed to permanent memory
+
+ pop rdx
+ pop rcx
+ pop rbx
+ pop rax
+ ret
+
--git a/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h b/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h
index e5a9d7a2b4..79ad57116a 100644
--- a/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h
+++ b/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h
@@ -7,6 +7,8 @@
**/
+#include <Base.h>
+
#ifndef __FSP_HEADER_FILE_H__
#define __FSP_HEADER_FILE_H__
@@ -24,6 +26,12 @@
#define FSP_INFO_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'H')
+#define IMAGE_ATTRIBUTE_GRAPHICS_SUPPORT BIT0
+#define IMAGE_ATTRIBUTE_DISPATCH_MODE_SUPPORT BIT1
+#define IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT BIT2
+#define FSP_IA32 0
+#define FSP_X64 1
+
#pragma pack(1)
///
@@ -49,7 +57,7 @@ typedef struct {
UINT8 SpecVersion;
///
/// Byte 0x0B: Revision of the FSP Information Header.
- /// The Current value for this field is 0x6.
+ /// The Current value for this field is 0x7.
///
UINT8 HeaderRevision;
///
@@ -82,6 +90,10 @@ typedef struct {
UINT32 ImageBase;
///
/// Byte 0x20: Attribute for the FSP binary.
+ /// Bit 0: Graphics Support - Set to 1 when FSP supports enabling Graphics Display.
+ /// Bit 1: Dispatch Mode Support - Set to 1 when FSP supports the optional Dispatch Mode API defined in Section 7.2 and 9. This bit is only valid if FSP HeaderRevision is >= 4.
+ /// Bit 2: 64-bit mode support - Set to 1 to indicate FSP supports 64-bit long mode interfaces. Set to 0 to indicate FSP supports 32-bit mode interfaces. This bit is only valid if FSP HeaderRevision is >= 7.
+ /// Bits 15:3 - Reserved
///
UINT16 ImageAttribute;
///
diff --git a/IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc b/IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc
new file mode 100644
index 0000000000..e8bd91669d
--- /dev/null
+++ b/IntelFsp2Pkg/Include/SaveRestoreSseAvxNasm.inc
@@ -0,0 +1,284 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Abstract:
+;
+; Provide macro for register save/restore using SSE registers
+;
+;------------------------------------------------------------------------------
+
+;
+; Define SSE and AVX instruction set
+;
+;
+; Define SSE macros using SSE 4.1 instructions
+; args 1:XMM, 2:IDX, 3:REG
+;
+%macro SXMMN 3
+ pinsrq %1, %3, (%2 & 3)
+ %endmacro
+
+;
+; args 1:XMM, 2:REG, 3:IDX
+;
+%macro LXMMN 3
+ pextrq %2, %1, (%3 & 3)
+ %endmacro
+
+;
+; Define AVX macros using AVX instructions
+; Save XMM to YMM
+; args 1:YMM, 2:IDX (0 - lower 128bits, 1 - upper 128bits), 3:XMM
+;
+%macro SYMMN 3
+ vinsertf128 %1, %1, %3, %2
+ %endmacro
+
+;
+; Restore XMM from YMM
+; args 1:YMM, 2:XMM, 3:IDX (0 - lower 128bits, 1 - upper 128bits)
+;
+%macro LYMMN 3
+ vextractf128 %2, %1, %3
+ %endmacro
+
+;
+; Upper half of YMM7 to save RBP and RBX. Upper half of YMM8 to save RSI and RDI.
+; Modified: XMM5, YMM6, YMM7 and YMM8
+;
+%macro SAVE_REGS 0
+ SXMMN xmm5, 0, rbp
+ SXMMN xmm5, 1, rbx
+ SYMMN ymm7, 1, xmm5
+ SXMMN xmm5, 0, rsi
+ SXMMN xmm5, 1, rdi
+ SYMMN ymm8, 1, xmm5
+ SAVE_RSP
+ %endmacro
+
+;
+; Upper half of YMM7 to restore RBP and RBX. Upper half of YMM8 to restore RSI and RDI.
+; Modified: XMM5, RBP, RBX, RSI, RDI and RSP
+;
+%macro LOAD_REGS 0
+ LYMMN ymm7, xmm5, 1
+ LXMMN xmm5, rbp, 0
+ LXMMN xmm5, rbx, 1
+ LYMMN ymm8, xmm5, 1
+ LXMMN xmm5, rsi, 0
+ LXMMN xmm5, rdi, 1
+ LOAD_RSP
+ %endmacro
+;
+; Restore RBP from YMM7[128:191]
+; Modified: XMM5 and RBP
+;
+%macro LOAD_RBP 0
+ LYMMN ymm7, xmm5, 1
+ movq rbp, xmm5
+ %endmacro
+
+;
+; Restore RBX from YMM7[192:255]
+; Modified: XMM5 and RBX
+;
+%macro LOAD_RBX 0
+ LYMMN ymm7, xmm5, 1
+ LXMMN xmm5, rbx, 1
+ %endmacro
+
+;
+; Upper half of YMM6 to save/restore Time Stamp, RSP
+;
+;
+; Save Time Stamp to YMM6[192:255]
+; arg 1:general purpose register which holds time stamp
+; Modified: XMM5 and YMM6
+;
+%macro SAVE_TS 1
+ LYMMN ymm6, xmm5, 1
+ SXMMN xmm5, 1, %1
+ SYMMN ymm6, 1, xmm5
+ %endmacro
+
+;
+; Restore Time Stamp from YMM6[192:255]
+; arg 1:general purpose register where to save time stamp
+; Modified: XMM5 and %1
+;
+%macro LOAD_TS 1
+ LYMMN ymm6, xmm5, 1
+ LXMMN xmm5, %1, 1
+ %endmacro
+
+;
+; Save RSP to YMM6[128:191]
+; Modified: XMM5 and YMM6
+;
+%macro SAVE_RSP 0
+ LYMMN ymm6, xmm5, 1
+ SXMMN xmm5, 0, rsp
+ SYMMN ymm6, 1, xmm5
+ %endmacro
+
+;
+; Restore RSP from YMM6[128:191]
+; Modified: XMM5 and RSP
+;
+%macro LOAD_RSP 0
+ LYMMN ymm6, xmm5, 1
+ movq rsp, xmm5
+ %endmacro
+
+;
+; Upper half of YMM9 to save/restore UCODE status, BFV address
+;
+;
+; Save uCode status to YMM9[192:255]
+; arg 1:general purpose register which holds uCode status
+; Modified: XMM5 and YMM9
+;
+%macro SAVE_UCODE_STATUS 1
+ LYMMN ymm9, xmm5, 1
+ SXMMN xmm5, 0, %1
+ SYMMN ymm9, 1, xmm5
+ %endmacro
+
+;
+; Restore uCode status from YMM9[192:255]
+; arg 1:general purpose register where to save uCode status
+; Modified: XMM5 and %1
+;
+%macro LOAD_UCODE_STATUS 1
+ LYMMN ymm9, xmm5, 1
+ movq %1, xmm5
+ %endmacro
+
+;
+; Save BFV address to YMM9[128:191]
+; arg 1:general purpose register which holds BFV address
+; Modified: XMM5 and YMM9
+;
+%macro SAVE_BFV 1
+ LYMMN ymm9, xmm5, 1
+ SXMMN xmm5, 1, %1
+ SYMMN ymm9, 1, xmm5
+ %endmacro
+
+;
+; Restore BFV address from YMM9[128:191]
+; arg 1:general purpose register where to save BFV address
+; Modified: XMM5 and %1
+;
+%macro LOAD_BFV 1
+ LYMMN ymm9, xmm5, 1
+ LXMMN xmm5, %1, 1
+ %endmacro
+
+;
+; YMM7[128:191] for calling stack
+; arg 1:Entry
+; Modified: RSI, XMM5, YMM7
+;
+%macro CALL_YMM 1
+ mov rsi, %%ReturnAddress
+ LYMMN ymm7, xmm5, 1
+ SXMMN xmm5, 0, rsi
+ SYMMN ymm7, 1, xmm5
+ mov rsi, %1
+ jmp rsi
+%%ReturnAddress:
+ %endmacro
+;
+; Restore RIP from YMM7[128:191]
+; Modified: RSI, XMM5
+;
+%macro RET_YMM 0
+ LYMMN ymm7, xmm5, 1
+ movq rsi, xmm5
+ jmp rsi
+ %endmacro
+
+%macro ENABLE_SSE 0
+ ;
+ ; Initialize floating point units
+ ;
+ jmp NextAddress
+align 4
+ ;
+ ; Float control word initial value:
+ ; all exceptions masked, double-precision, round-to-nearest
+ ;
+FpuControlWord DW 027Fh
+ ;
+ ; Multimedia-extensions control word:
+ ; all exceptions masked, round-to-nearest, flush to zero for masked underflow
+ ;
+MmxControlWord DQ 01F80h
+SseError:
+ ;
+ ; Processor has to support SSE
+ ;
+ jmp SseError
+NextAddress:
+ finit
+ mov rax, FpuControlWord
+ fldcw [rax]
+
+ ;
+ ; Use CpuId instruction (CPUID.01H:EDX.SSE[bit 25] = 1) to test
+ ; whether the processor supports SSE instruction.
+ ;
+ mov rax, 1
+ cpuid
+ bt rdx, 25
+ jnc SseError
+
+ ;
+ ; SSE 4.1 support
+ ;
+ bt ecx, 19
+ jnc SseError
+
+ ;
+ ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
+ ;
+ mov rax, cr4
+ or rax, 00000600h
+ mov cr4, rax
+
+ ;
+ ; The processor should support SSE instruction and we can use
+ ; ldmxcsr instruction
+ ;
+ mov rax, MmxControlWord
+ ldmxcsr [rax]
+ %endmacro
+
+%macro ENABLE_AVX 0
+ mov eax, 1
+ cpuid
+ and ecx, 10000000h
+ cmp ecx, 10000000h ; check AVX feature flag
+ je EnableAvx
+AvxError:
+ ;
+ ; Processor has to support AVX
+ ;
+ jmp AvxError
+EnableAvx:
+ ;
+ ; Set OSXSAVE bit (bit #18) to enable xgetbv/xsetbv instruction
+ ;
+ mov rax, cr4
+ or rax, 00040000h
+ mov cr4, rax
+
+ mov rcx, 0 ; index 0
+ xgetbv ; result in edx:eax
+ or eax, 00000006h ; Set XCR0 bit #1 and bit #2 to enable SSE state and AVX state
+ xsetbv
+ %endmacro
+
diff --git a/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c b/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
index cd10b63c95..7aac68bf23 100644
--- a/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
+++ b/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
@@ -54,6 +54,7 @@ typedef struct {
UINT32 Flags[2];
UINT64 FspInfoHeader;
UINT64 ApiParam[2];
+ UINT64 Reserved; // The reserved QWORD is needed for stack alignment in X64.
UINT64 ApiRet; // 64bit stack format is different from the 32bit one due to x64 calling convention
} CONTEXT_STACK_64;
diff --git a/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm b/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm
index bd36fe4b8b..1ea1220608 100644
--- a/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm
+++ b/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm
@@ -47,7 +47,8 @@ ASM_PFX(Loader2PeiSwitchStack):
;------------------------------------------------------------------------------
global ASM_PFX(FspSwitchStack)
ASM_PFX(FspSwitchStack):
- ; Save current contexts
+ ; Save current contexts. The format must align with CONTEXT_STACK_64.
+ push rdx ; Reserved QWORD for stack alignment
push rdx ; ApiParam2
push rcx ; ApiParam1
push rax ; FspInfoHeader
@@ -67,6 +68,6 @@ ASM_PFX(FspSwitchStack):
add rsp, 16
POPA_64
popfq
- add rsp, 24 ; FspInfoHeader + ApiParam[2]
+ add rsp, 32 ; FspInfoHeader + ApiParam[2] + Reserved QWORD
ret
--
2.16.2.windows.1
next prev parent reply other threads:[~2022-04-04 6:23 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-04 6:23 [edk2-devel][PATCH v2 0/8] Support PEI 64bit in IntelFsp2Pkg and IntelFsp2WrapperPkg Kuo, Ted
2022-04-04 6:23 ` [edk2-devel][PATCH v2 1/8] IntelFsp2Pkg: X64 compatible changes to support PEI in 64bit Kuo, Ted
2022-04-06 14:54 ` Chiu, Chasel
2022-04-04 6:23 ` [edk2-devel][PATCH v2 2/8] IntelFsp2Pkg: Add FSPx_ARCH2_UPD support for X64 Kuo, Ted
2022-04-06 14:39 ` Chiu, Chasel
2022-04-06 15:09 ` Chiu, Chasel
2022-04-04 6:23 ` [edk2-devel][PATCH v2 3/8] IntelFsp2Pkg: Update FSP_GLOBAL_DATA and FSP_PLAT_DATA " Kuo, Ted
2022-04-04 6:23 ` Kuo, Ted [this message]
2022-04-04 6:23 ` [edk2-devel][PATCH v2 5/8] IntelFsp2Pkg: SecFspSecPlatformLibNull support " Kuo, Ted
2022-04-04 6:23 ` [edk2-devel][PATCH v2 6/8] IntelFsp2WrapperPkg: Adopt FSPM_UPD_COMMON_FSP24 " Kuo, Ted
2022-04-04 6:23 ` [edk2-devel][PATCH v2 7/8] IntelFsp2WrapperPkg: BaseFspWrapperApiLib support " Kuo, Ted
2022-04-04 6:23 ` [edk2-devel][PATCH v2 8/8] IntelFsp2WrapperPkg: SecFspWrapperPlatformSecLibSample " Kuo, Ted
2022-04-06 15:15 ` Chiu, Chasel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a3f5029f45a03cb4dd844506d5faebdb1ad16809.1649053236.git.ted.kuo@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox