REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3916

Adopt MultiPhase functions for both FspSecCoreS and FspSecCoreM.
For backward compatibility, new INF are created for new modules.

Cc: Nate DeSimone <nathaniel.l.desim...@intel.com>
Cc: Star Zeng <star.z...@intel.com>
Signed-off-by: Chasel Chiu <chasel.c...@intel.com>
---
 IntelFsp2Pkg/FspSecCore/SecFsp.c                    |   4 ++++
 IntelFsp2Pkg/FspSecCore/SecFspApiChk.c              |   9 +++++++++
 IntelFsp2Pkg/FspSecCore/Fsp24SecCoreM.inf           |  75 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 IntelFsp2Pkg/FspSecCore/Fsp24SecCoreS.inf           |  59 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryM.nasm    | 304 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryS.nasm    | 101 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm |   3 +++
 IntelFsp2Pkg/FspSecCore/X64/Fsp24ApiEntryM.nasm     | 303 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 IntelFsp2Pkg/FspSecCore/X64/Fsp24ApiEntryS.nasm     | 108 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm  |   3 +++
 10 files changed, 969 insertions(+)

diff --git a/IntelFsp2Pkg/FspSecCore/SecFsp.c b/IntelFsp2Pkg/FspSecCore/SecFsp.c
index d9085ef51f..11be1f97ca 100644
--- a/IntelFsp2Pkg/FspSecCore/SecFsp.c
+++ b/IntelFsp2Pkg/FspSecCore/SecFsp.c
@@ -135,6 +135,10 @@ FspGlobalDataInit (
   PeiFspData->CoreStack = BootLoaderStack;
   PeiFspData->PerfIdx   = 2;
   PeiFspData->PerfSig   = FSP_PERFORMANCE_DATA_SIGNATURE;
+  //
+  // Cache FspHobList pointer passed by bootloader via ApiParameter2
+  //
+  PeiFspData->FspHobListPtr = (VOID **)GetFspApiParameter2 ();
 
   SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_ENTRY);
 
diff --git a/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c 
b/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c
index 35d223a404..a44fbf2a50 100644
--- a/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c
+++ b/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c
@@ -69,8 +69,17 @@ FspApiCallingCheck (
         Status = EFI_UNSUPPORTED;
       } else if (EFI_ERROR (FspUpdSignatureCheck (FspSiliconInitApiIndex, 
ApiParam))) {
         Status = EFI_INVALID_PARAMETER;
+      } else if (ApiIdx == FspSiliconInitApiIndex) {
+        //
+        // Reset MultiPhase NumberOfPhases to zero
+        //
+        FspData->NumberOfPhases = 0;
       }
     }
+  } else if (ApiIdx == FspMultiPhaseMemInitApiIndex) {
+    if ((FspData == NULL) || ((UINTN)FspData == MAX_ADDRESS) || 
((UINTN)FspData == MAX_UINT32)) {
+      Status = EFI_UNSUPPORTED;
+    }
   } else if (ApiIdx == FspSmmInitApiIndex) {
     //
     // FspSmmInitApiIndex check
diff --git a/IntelFsp2Pkg/FspSecCore/Fsp24SecCoreM.inf 
b/IntelFsp2Pkg/FspSecCore/Fsp24SecCoreM.inf
new file mode 100644
index 0000000000..e93e176f15
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/Fsp24SecCoreM.inf
@@ -0,0 +1,75 @@
+## @file
+#  Sec Core for FSP to support MultiPhase (SeparatePhase) MemInitialization.
+#
+#  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Fsp24SecCoreM
+  FILE_GUID                      = C5BC0719-4A23-4F6E-94DA-05FB6A0DFA9C
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  SecMain.c
+  SecMain.h
+  SecFsp.c
+  SecFsp.h
+  SecFspApiChk.c
+
+[Sources.IA32]
+  Ia32/Stack.nasm
+  Ia32/Fsp24ApiEntryM.nasm
+  Ia32/FspApiEntryCommon.nasm
+  Ia32/FspHelper.nasm
+  Ia32/ReadEsp.nasm
+
+[Sources.X64]
+  X64/Stack.nasm
+  X64/Fsp24ApiEntryM.nasm
+  X64/FspApiEntryCommon.nasm
+  X64/FspHelper.nasm
+  X64/ReadRsp.nasm
+
+[Binaries.Ia32]
+  RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  BaseLib
+  PciCf8Lib
+  SerialPortLib
+  FspSwitchStackLib
+  FspCommonLib
+  FspSecPlatformLib
+  CpuLib
+  UefiCpuLib
+  FspMultiPhaseLib
+
+[Pcd]
+  gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase              ## CONSUMES
+  gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize              ## CONSUMES
+  gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize           ## CONSUMES
+  gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage         ## CONSUMES
+  gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxInterruptSupported      ## CONSUMES
+  gIntelFsp2PkgTokenSpaceGuid.PcdFspPrivateTemporaryRamSize    ## CONSUMES
+
+[Ppis]
+  gEfiTemporaryRamSupportPpiGuid                              ## PRODUCES
+  gFspInApiModePpiGuid                                        ## PRODUCES
diff --git a/IntelFsp2Pkg/FspSecCore/Fsp24SecCoreS.inf 
b/IntelFsp2Pkg/FspSecCore/Fsp24SecCoreS.inf
new file mode 100644
index 0000000000..1d44fb67b5
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/Fsp24SecCoreS.inf
@@ -0,0 +1,59 @@
+## @file
+#  Sec Core for FSP to support MultiPhase (SeparatePhase) SiInitialization.
+#
+#  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Fsp24SecCoreS
+  FILE_GUID                      = E039988B-0F21-4D95-AE34-C469B10E13F8
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  SecFspApiChk.c
+  SecFsp.h
+
+[Sources.IA32]
+  Ia32/Stack.nasm
+  Ia32/Fsp24ApiEntryS.nasm
+  Ia32/FspApiEntryCommon.nasm
+  Ia32/FspHelper.nasm
+
+[Sources.X64]
+  X64/Stack.nasm
+  X64/Fsp24ApiEntryS.nasm
+  X64/FspApiEntryCommon.nasm
+  X64/FspHelper.nasm
+
+[Binaries.Ia32]
+  RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  BaseLib
+  PciCf8Lib
+  SerialPortLib
+  FspSwitchStackLib
+  FspCommonLib
+  FspSecPlatformLib
+  FspMultiPhaseLib
+
+[Ppis]
+  gEfiTemporaryRamSupportPpiGuid                              ## PRODUCES
+
diff --git a/IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryM.nasm 
b/IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryM.nasm
new file mode 100644
index 0000000000..997b9c0bff
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryM.nasm
@@ -0,0 +1,304 @@
+;; @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 are fixed PCDs
+;
+extern   ASM_PFX(PcdGet32(PcdTemporaryRamBase))
+extern   ASM_PFX(PcdGet32(PcdTemporaryRamSize))
+extern   ASM_PFX(PcdGet32(PcdFspTemporaryRamSize))
+extern   ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))
+
+struc FSPM_UPD_COMMON
+    ; FSP_UPD_HEADER {
+    .FspUpdHeader:            resd    8
+    ; }
+    ; FSPM_ARCH_UPD {
+    .Revision:                resb    1
+    .Reserved:                resb    3
+    .NvsBufferPtr:            resd    1
+    .StackBase:               resd    1
+    .StackSize:               resd    1
+    .BootLoaderTolumSize:     resd    1
+    .BootMode:                resd    1
+    .Reserved1:               resb    8
+    ; }
+    .size:
+endstruc
+
+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)
+extern ASM_PFX(FspMultiPhaseMemInitApiHandler)
+
+STACK_SAVED_EAX_OFFSET       EQU   4 * 7 ; size of a general purpose register 
* eax index
+API_PARAM1_OFFSET            EQU   34h  ; ApiParam1 [ sub esp,8 + pushad + 
pushfd + push eax + call]
+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)
+
+;----------------------------------------------------------------------------
+; FspMultiPhaseMemoryInitApi API
+;
+; This FSP API provides multi-phase Memory initialization, which brings greater
+; modularity beyond the existing FspMemoryInit() API.
+; Increased modularity is achieved by adding an extra API to FSP-M.
+; This allows the bootloader to add board specific initialization steps 
throughout
+; the MemoryInit flow as needed.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspMultiPhaseMemoryInitApi)
+ASM_PFX(FspMultiPhaseMemoryInitApi):
+  mov    eax,  8 ; FSP_API_INDEX.FspMultiPhaseMemInitApiIndex
+  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):
+  ;
+  ; Handle FspMultiPhaseMemInitApiIndex API
+  ;
+  cmp    eax, 8   ; FspMultiPhaseMemInitApiIndex
+  jnz    NotMultiPhaseMemoryInitApi
+
+  pushad
+  push   DWORD [esp + (4 * 8 + 4)]  ; push ApiParam
+  push   eax                        ; push ApiIdx
+  call   ASM_PFX(FspMultiPhaseMemInitApiHandler)
+  add    esp, 8
+  mov    dword  [esp + STACK_SAVED_EAX_OFFSET], eax
+  popad
+  ret
+
+NotMultiPhaseMemoryInitApi:
+
+  ;
+  ; FspMemoryInit API setup the initial stack frame
+  ;
+
+  ;
+  ; Place holder to store the FspInfoHeader pointer
+  ;
+  push   eax
+
+  ;
+  ; Update the FspInfoHeader pointer
+  ;
+  push   eax
+  call   ASM_PFX(AsmGetFspInfoHeader)
+  mov    [esp + 4], eax
+  pop    eax
+
+  ;
+  ; Create a Task Frame in the stack for the Boot Loader
+  ;
+  pushfd     ; 2 pushf for 4 byte alignment
+  cli
+  pushad
+
+  ; Reserve 8 bytes for IDT save/restore
+  sub     esp, 8
+  sidt    [esp]
+
+
+  ;  Get Stackbase and StackSize from FSPM_UPD Param
+  mov    edx, [esp + API_PARAM1_OFFSET]
+  cmp    edx, 0
+  jnz    FspStackSetup
+
+  ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null
+  push   eax
+  call   ASM_PFX(AsmGetFspInfoHeader)
+  mov    edx, [eax + FSP_HEADER_IMGBASE_OFFSET]
+  add    edx, [eax + FSP_HEADER_CFGREG_OFFSET]
+  pop    eax
+
+FspStackSetup:
+  mov    ecx, [edx + FSPM_UPD_COMMON.Revision]
+  cmp    ecx, 3
+  jae    FspmUpdCommon2
+
+  ;
+  ; StackBase = temp memory base, StackSize = temp memory size
+  ;
+  mov    edi, [edx + FSPM_UPD_COMMON.StackBase]
+  mov    ecx, [edx + FSPM_UPD_COMMON.StackSize]
+  jmp    ChkFspHeapSize
+
+FspmUpdCommon2:
+  mov    edi, [edx + FSPM_UPD_COMMON_FSP24.StackBase]
+  mov    ecx, [edx + FSPM_UPD_COMMON_FSP24.StackSize]
+
+ChkFspHeapSize:
+  ;
+  ; Keep using bootloader stack if heap size % is 0
+  ;
+  mov    bl, BYTE [ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))]
+  cmp    bl, 0
+  jz     SkipStackSwitch
+
+  ;
+  ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0
+  ;
+  add    edi, ecx
+  ;
+  ; Switch to new FSP stack
+  ;
+  xchg   edi, esp                                ; Exchange edi and esp, edi 
will be assigned to the current esp pointer and esp 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    ebx, edi                                ; Put 
FSPM_UPD_COMMON.StackBase to ebx as temp memory base
+  mov    edi, esp                                ; Put boot loader stack 
pointer to edi
+  jmp    StackSetupDone
+
+StackHasBeenSwitched:
+  mov    ebx, esp                                ; Put Stack base + Stack size 
in ebx
+  sub    ebx, ecx                                ; Stack base + Stack size - 
Stack size as temp memory base
+
+StackSetupDone:
+
+  ;
+  ; Pass the API Idx to SecStartup
+  ;
+  push    eax
+
+  ;
+  ; Pass the BootLoader stack to SecStartup
+  ;
+  push    edi
+
+  ;
+  ; Pass entry point of the PEI core
+  ;
+  call    ASM_PFX(AsmGetFspBaseAddress)
+  mov     edi, eax
+  call    ASM_PFX(AsmGetPeiCoreOffset)
+  add     edi, eax
+  push    edi
+
+  ;
+  ; 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)
+  push    eax
+
+  ;
+  ; Pass stack base and size into the PEI Core
+  ;
+  push    ebx
+  push    ecx
+
+  ;
+  ; Pass Control into the PEI Core
+  ;
+  call    ASM_PFX(SecStartup)
+  add     esp, 4
+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):
+   mov   eax, dword [ASM_PFX(FspPeiCoreEntryOff)]
+   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/Ia32/Fsp24ApiEntryS.nasm 
b/IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryS.nasm
new file mode 100644
index 0000000000..bda99cdd80
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/Ia32/Fsp24ApiEntryS.nasm
@@ -0,0 +1,101 @@
+;; @file
+;  Provide FSP API entry points.
+;
+; Copyright (c) 2020, 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(FspMultiPhaseSiInitApiHandlerV2)
+
+STACK_SAVED_EAX_OFFSET       EQU   4 * 7 ; size of a general purpose register 
* eax 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.
+;
+;----------------------------------------------------------------------------
+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   ; FspMultiPhaseSiInitApiIndex
+  jnz    NotMultiPhaseSiInitApi
+
+  pushad
+  push   DWORD [esp + (4 * 8 + 4)]  ; push ApiParam
+  push   eax                        ; push ApiIdx
+  call   ASM_PFX(FspMultiPhaseSiInitApiHandlerV2)
+  add    esp, 8
+  mov    dword  [esp + STACK_SAVED_EAX_OFFSET], eax
+  popad
+  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/Ia32/FspApiEntryCommon.nasm 
b/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
index 8d8deba28a..87446be779 100644
--- a/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
+++ b/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
@@ -67,6 +67,9 @@ FspApiCommon2:
   cmp    eax, 6   ; FspMultiPhaseSiInitApiIndex API
   jz     FspApiCommon3
 
+  cmp    eax, 8   ; FspMultiPhaseMemInitApiIndex API
+  jz     FspApiCommon3
+
   call   ASM_PFX(AsmGetFspInfoHeader)
   jmp    ASM_PFX(Loader2PeiSwitchStack)
 
diff --git a/IntelFsp2Pkg/FspSecCore/X64/Fsp24ApiEntryM.nasm 
b/IntelFsp2Pkg/FspSecCore/X64/Fsp24ApiEntryM.nasm
new file mode 100644
index 0000000000..8880721f29
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/Fsp24ApiEntryM.nasm
@@ -0,0 +1,303 @@
+;; @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)
+extern ASM_PFX(FspMultiPhaseMemInitApiHandler)
+
+STACK_SAVED_RAX_OFFSET       EQU   8 * 7 ; size of a general purpose register 
* rax index
+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    rax,  3 ; FSP_API_INDEX.FspMemoryInitApiIndex
+  jmp    ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspMultiPhaseMemoryInitApi API
+;
+; This FSP API provides multi-phase Memory initialization, which brings greater
+; modularity beyond the existing FspMemoryInit() API.
+; Increased modularity is achieved by adding an extra API to FSP-M.
+; This allows the bootloader to add board specific initialization steps 
throughout
+; the MemoryInit flow as needed.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspMultiPhaseMemoryInitApi)
+ASM_PFX(FspMultiPhaseMemoryInitApi):
+  mov    rax,  8 ; FSP_API_INDEX.FspMultiPhaseMemInitApiIndex
+  jmp    ASM_PFX(FspApiCommon)
+;----------------------------------------------------------------------------
+; TempRamExitApi API
+;
+; This API tears down temporary RAM
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamExitApi)
+ASM_PFX(TempRamExitApi):
+  mov    rax,  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):
+  ;
+  ; Handle FspMultiPhaseMemoInitApiIndex API
+  ;
+  push   rdx    ; Push a QWORD data for stack alignment
+
+  cmp    rax, 8 ; FspMultiPhaseMemInitApiIndex
+  jnz    NotMultiPhaseMemoryInitApi
+
+  PUSHA_64
+  mov    rdx, rcx           ; move ApiParam to rdx
+  mov    rcx, rax           ; move ApiIdx to rcx
+  sub    rsp, 0x20          ; calling C function may need shadow space
+  call   ASM_PFX(FspMultiPhaseMemInitApiHandler)
+  add    rsp, 0x20          ; restore shadow space
+  mov    qword [rsp + STACK_SAVED_RAX_OFFSET], rax
+  POPA_64
+  add    rsp, 0x08
+  ret
+
+NotMultiPhaseMemoryInitApi:
+  ; Push RDX and RCX to form CONTEXT_STACK_64
+  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/Fsp24ApiEntryS.nasm 
b/IntelFsp2Pkg/FspSecCore/X64/Fsp24ApiEntryS.nasm
new file mode 100644
index 0000000000..5bbbc5d1d0
--- /dev/null
+++ b/IntelFsp2Pkg/FspSecCore/X64/Fsp24ApiEntryS.nasm
@@ -0,0 +1,108 @@
+;; @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(FspMultiPhaseSiInitApiHandlerV2)
+
+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    rax,  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    rax,  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    rax,  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
+  ;
+  push   rdx    ; Push a QWORD data for stack alignment
+
+  cmp    rax, 6 ; FSP_API_INDEX.FspMultiPhaseSiInitApiIndex
+  jnz    NotMultiPhaseSiInitApi
+
+  PUSHA_64
+  mov    rdx, rcx           ; move ApiParam to rdx
+  mov    rcx, rax           ; move ApiIdx to rcx
+  sub    rsp, 0x20          ; calling C function may need shadow space
+  call   ASM_PFX(FspMultiPhaseSiInitApiHandlerV2)
+  add    rsp, 0x20          ; restore shadow space
+  mov    qword  [rsp + STACK_SAVED_RAX_OFFSET], rax
+  POPA_64
+  add    rsp, 0x08
+  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
index 718e672e02..dc6b8c99a1 100644
--- a/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm
+++ b/IntelFsp2Pkg/FspSecCore/X64/FspApiEntryCommon.nasm
@@ -68,6 +68,9 @@ FspApiCommon2:
   cmp    rax, 6   ; FspMultiPhaseSiInitApiIndex API
   jz     FspApiCommon3
 
+  cmp    rax, 8   ; FspMultiPhaseMemInitApiIndex API
+  jz     FspApiCommon3
+
   call   ASM_PFX(AsmGetFspInfoHeader)
   jmp    ASM_PFX(Loader2PeiSwitchStack)
 
-- 
2.35.0.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#92126): https://edk2.groups.io/g/devel/message/92126
Mute This Topic: https://groups.io/mt/92826134/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to