[edk2-devel][PATCH 4/5] IntelFsp2Pkg: FspSecCore support for X64

Kuo, Ted ted.kuo at intel.com
Mon Apr 4 04:13:59 UTC 2022


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 at intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
Cc: Star Zeng <star.zeng at intel.com>
Cc: Ashraf Ali S <ashraf.ali.s at intel.com>
Signed-off-by: Ted Kuo <ted.kuo at 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 +++
 IntelFsp2Pkg/Include/Guid/FspHeaderFile.h          |  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..f149066ad8
--- /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
+    ; 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.StackBase]
+  mov    ecx, [rdx + FSPM_UPD_COMMON.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.StackBase and will hold ESP later (boot loader stack pointer)
+  ;   ECX is FSPM_UPD_COMMON.StackSize
+  ;   ESP is boot loader stack pointer (no stack switch)
+  ;   BL  is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON.StackBase later)
+  ;
+  ; If heap size % is not 0
+  ;   EDI is boot loader stack pointer
+  ;   ECX is FSPM_UPD_COMMON.StackSize
+  ;   ESP is new stack (FSPM_UPD_COMMON.StackBase + FSPM_UPD_COMMON.StackSize)
+  ;   BL  is NOT 0 to indicate stack has switched
+  ;
+  cmp    bl, 0
+  jnz    StackHasBeenSwitched
+
+  mov    rbx, rdi                                ; Put FSPM_UPD_COMMON.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
+
diff --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



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#88391): https://edk2.groups.io/g/devel/message/88391
Mute This Topic: https://groups.io/mt/90234872/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list