2 ; Provide FSP API entry points.
4 ; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
5 ; SPDX-License-Identifier: BSD-2-Clause-Patent
10 %include "PushPopRegsNasm.inc"
13 ; Following are fixed PCDs
15 extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))
17 struc FSPM_UPD_COMMON_FSP24
27 .BootLoaderTolumSize: resd 1
29 .FspEventHandler resq 1
36 ; Following functions will be provided in C
38 extern ASM_PFX(SecStartup)
39 extern ASM_PFX(FspApiCommon)
42 ; Following functions will be provided in PlatformSecLib
44 extern ASM_PFX(AsmGetFspBaseAddress)
45 extern ASM_PFX(AsmGetFspInfoHeader)
46 extern ASM_PFX(FspMultiPhaseMemInitApiHandler)
48 STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index
49 FSP_HEADER_IMGBASE_OFFSET EQU 1Ch
50 FSP_HEADER_CFGREG_OFFSET EQU 24h
52 ;----------------------------------------------------------------------------
55 ; This FSP API is called after TempRamInit and initializes the memory.
57 ;----------------------------------------------------------------------------
58 global ASM_PFX(FspMemoryInitApi)
59 ASM_PFX(FspMemoryInitApi):
60 mov rax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex
61 jmp ASM_PFX(FspApiCommon)
63 ;----------------------------------------------------------------------------
64 ; FspMultiPhaseMemoryInitApi API
66 ; This FSP API provides multi-phase Memory initialization, which brings greater
67 ; modularity beyond the existing FspMemoryInit() API.
68 ; Increased modularity is achieved by adding an extra API to FSP-M.
69 ; This allows the bootloader to add board specific initialization steps throughout
70 ; the MemoryInit flow as needed.
72 ;----------------------------------------------------------------------------
73 global ASM_PFX(FspMultiPhaseMemoryInitApi)
74 ASM_PFX(FspMultiPhaseMemoryInitApi):
75 mov rax, 8 ; FSP_API_INDEX.FspMultiPhaseMemInitApiIndex
76 jmp ASM_PFX(FspApiCommon)
77 ;----------------------------------------------------------------------------
80 ; This API tears down temporary RAM
82 ;----------------------------------------------------------------------------
83 global ASM_PFX(TempRamExitApi)
84 ASM_PFX(TempRamExitApi):
85 mov rax, 4 ; FSP_API_INDEX.TempRamExitApiIndex
86 jmp ASM_PFX(FspApiCommon)
88 ;----------------------------------------------------------------------------
89 ; FspApiCommonContinue API
91 ; This is the FSP API common entry point to resume the FSP execution
93 ;----------------------------------------------------------------------------
94 global ASM_PFX(FspApiCommonContinue)
95 ASM_PFX(FspApiCommonContinue):
97 ; Handle FspMultiPhaseMemoInitApiIndex API
99 push rdx ; Push a QWORD data for stack alignment
101 cmp rax, 8 ; FspMultiPhaseMemInitApiIndex
102 jnz NotMultiPhaseMemoryInitApi
105 mov rdx, rcx ; move ApiParam to rdx
106 mov rcx, rax ; move ApiIdx to rcx
107 sub rsp, 0x20 ; calling C function may need shadow space
108 call ASM_PFX(FspMultiPhaseMemInitApiHandler)
109 add rsp, 0x20 ; restore shadow space
110 mov qword [rsp + STACK_SAVED_RAX_OFFSET], rax
115 NotMultiPhaseMemoryInitApi:
116 ; Push RDX and RCX to form CONTEXT_STACK_64
117 push rdx ; Push API Parameter2 on stack
118 push rcx ; Push API Parameter1 on stack
121 ; FspMemoryInit API setup the initial stack frame
125 ; Place holder to store the FspInfoHeader pointer
130 ; Update the FspInfoHeader pointer
133 call ASM_PFX(AsmGetFspInfoHeader)
138 ; Create a Task Frame in the stack for the Boot Loader
144 ; Reserve 16 bytes for IDT save/restore
148 ; Get Stackbase and StackSize from FSPM_UPD Param
149 mov rdx, rcx ; Put FSPM_UPD Param to rdx
153 ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null
155 call ASM_PFX(AsmGetFspInfoHeader)
156 mov edx, [rax + FSP_HEADER_IMGBASE_OFFSET]
157 add edx, [rax + FSP_HEADER_CFGREG_OFFSET]
161 mov cl, [rdx + FSPM_UPD_COMMON_FSP24.Revision]
163 jae FspmUpdCommonFsp24
165 mov rax, 08000000000000002h ; RETURN_INVALID_PARAMETER
171 ; StackBase = temp memory base, StackSize = temp memory size
173 mov rdi, [rdx + FSPM_UPD_COMMON_FSP24.StackBase]
174 mov ecx, [rdx + FSPM_UPD_COMMON_FSP24.StackSize]
177 ; Keep using bootloader stack if heap size % is 0
179 mov rbx, ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))
185 ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0
189 ; Switch to new FSP stack
191 xchg rdi, rsp ; Exchange rdi and rsp, rdi will be assigned to the current rsp pointer and rsp will be Stack base + Stack size
195 ; If heap size % is 0:
196 ; EDI is FSPM_UPD_COMMON_FSP24.StackBase and will hold ESP later (boot loader stack pointer)
197 ; ECX is FSPM_UPD_COMMON_FSP24.StackSize
198 ; ESP is boot loader stack pointer (no stack switch)
199 ; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON_FSP24.StackBase later)
201 ; If heap size % is not 0
202 ; EDI is boot loader stack pointer
203 ; ECX is FSPM_UPD_COMMON_FSP24.StackSize
204 ; ESP is new stack (FSPM_UPD_COMMON_FSP24.StackBase + FSPM_UPD_COMMON_FSP24.StackSize)
205 ; BL is NOT 0 to indicate stack has switched
208 jnz StackHasBeenSwitched
210 mov rbx, rdi ; Put FSPM_UPD_COMMON_FSP24.StackBase to rbx as temp memory base
211 mov rdi, rsp ; Put boot loader stack pointer to rdi
214 StackHasBeenSwitched:
215 mov rbx, rsp ; Put Stack base + Stack size in ebx
216 sub rbx, rcx ; Stack base + Stack size - Stack size as temp memory base
221 ; Per X64 calling convention, make sure RSP is 16-byte aligned.
228 ; Pass the API Idx to SecStartup
233 ; Pass the BootLoader stack to SecStartup
238 ; Pass BFV into the PEI Core
239 ; It uses relative address to calculate the actual boot FV base
240 ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and
241 ; PcdFspAreaBaseAddress are the same. For FSP with multiple FVs,
242 ; they are different. The code below can handle both cases.
244 call ASM_PFX(AsmGetFspBaseAddress)
248 ; Pass entry point of the PEI core
250 call ASM_PFX(AsmGetPeiCoreOffset)
254 ; Pass stack base and size into the PEI Core
260 ; Pass Control into the PEI Core
261 ; RCX = SizeOfRam, RDX = TempRamBase, R8 = BFV, R9 = PeiCoreEntry, Last 1 Stack = BL stack, Last 2 Stack = API index
262 ; According to X64 calling convention, caller has to allocate 32 bytes as a shadow store on call stack right before
263 ; calling the function.
266 call ASM_PFX(SecStartup)
271 global ASM_PFX(FspPeiCoreEntryOff)
272 ASM_PFX(FspPeiCoreEntryOff):
274 ; This value will be patched by the build script
278 global ASM_PFX(AsmGetPeiCoreOffset)
279 ASM_PFX(AsmGetPeiCoreOffset):
281 mov rbx, ASM_PFX(FspPeiCoreEntryOff)
286 ;----------------------------------------------------------------------------
289 ; Empty function for WHOLEARCHIVE build option
291 ;----------------------------------------------------------------------------
292 global ASM_PFX(TempRamInitApi)
293 ASM_PFX(TempRamInitApi):
297 ;----------------------------------------------------------------------------
298 ; Module Entrypoint API
299 ;----------------------------------------------------------------------------
300 global ASM_PFX(_ModuleEntryPoint)
301 ASM_PFX(_ModuleEntryPoint):