IntelFsp2Pkg: FspSecCore support for X64

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.
3.Corrected few typos.

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>
Reviewed-by: Chasel Chiu <chasel.chiu@intel.com>
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
diff --git a/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf b/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
index 0a24eb2..4a67388 100644
--- a/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
+++ b/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
@@ -1,7 +1,7 @@
 ## @file

 #  Sec Core for FSP to support MultiPhase (SeparatePhase) SiInitialization.

 #

-#  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>

+#  Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>

 #

 #  SPDX-License-Identifier: BSD-2-Clause-Patent

 #

@@ -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 7b05cae..a7fc07d 100644
--- a/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
+++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
@@ -1,7 +1,7 @@
 ## @file

 #  Sec Core for FSP

 #

-#  Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>

+#  Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>

 #

 #  SPDX-License-Identifier: BSD-2-Clause-Patent

 #

@@ -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 1d9c255..fb80c0e 100644
--- a/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
+++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
@@ -1,7 +1,7 @@
 ## @file

 #  Sec Core for FSP

 #

-#  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>

+#  Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>

 #

 #  SPDX-License-Identifier: BSD-2-Clause-Patent

 #

@@ -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 664bde5..e5a6eaa 100644
--- a/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
+++ b/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
@@ -1,7 +1,7 @@
 ## @file

 #  Sec Core for FSP

 #

-#  Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>

+#  Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>

 #

 #  SPDX-License-Identifier: BSD-2-Clause-Patent

 #

@@ -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 26ae7d9..8d8deba 100644
--- a/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
+++ b/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
@@ -1,12 +1,14 @@
 ;; @file

 ;  Provide FSP API entry points.

 ;

-; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>

+; Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>

 ; SPDX-License-Identifier: BSD-2-Clause-Patent

 ;;

 

     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 @@
   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 0000000..c739793
--- /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 0000000..718e672
--- /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 0000000..4d965e1
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryM.nasm
@@ -0,0 +1,271 @@
+;; @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

+    .Reserved1:                 resb 24

+    ; }

+    .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:

+  mov    cl, [rdx + FSPM_UPD_COMMON_FSP24.Revision]

+  cmp    cl, 3

+  jae    FspmUpdCommonFsp24

+

+  mov    rax, 08000000000000002h                 ; RETURN_INVALID_PARAMETER

+  sub    rsp, 0b8h

+  ret

+

+FspmUpdCommonFsp24:

+  ;

+  ; 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 patched 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 0000000..f863ef0
--- /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 0000000..a9f5f28
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
@@ -0,0 +1,495 @@
+;; @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

+    .FsptArchUpd:             resd    4

+    ; }

+    ; FSPT_CORE_UPD {

+    .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 0000000..122fa1d
--- /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 0000000..4ec5070
--- /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 0000000..af82509
--- /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 0000000..0af7f54
--- /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 e5a9d7a..c660def 100644
--- a/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h
+++ b/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h
@@ -2,11 +2,13 @@
   Intel FSP Header File definition from Intel Firmware Support Package External

   Architecture Specification v2.0 and above.

 

-  Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>

+  Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 

 **/

 

+#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 @@
   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 @@
   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 0000000..e8bd916
--- /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 cd10b63..67e08a9 100644
--- a/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
+++ b/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
@@ -1,6 +1,6 @@
 /** @file

 

-  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>

+  Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>

   SPDX-License-Identifier: BSD-2-Clause-Patent

 

 **/

@@ -38,7 +38,8 @@
 } CONTEXT_STACK;

 

 //

-//   API return address           +0xB0

+//   API return address           +0xB8

+//   Reserved                     +0xB0

 //   push    API Parameter2       +0xA8

 //   push    API Parameter1       +0xA0

 //   push    FspInfoHeader        +0x98

@@ -54,6 +55,7 @@
   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 bd36fe4..1ea1220 100644
--- a/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm
+++ b/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/X64/Stack.nasm
@@ -47,7 +47,8 @@
 ;------------------------------------------------------------------------------

 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 @@
     add     rsp, 16

     POPA_64

     popfq

-    add     rsp, 24 ; FspInfoHeader + ApiParam[2]

+    add     rsp, 32 ; FspInfoHeader + ApiParam[2] + Reserved QWORD

     ret