]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/FspSecCore/X64/Fsp24ApiEntryM.nasm
IntelFsp2Pkg: Adopt FSP 2.4 MultiPhase functions.
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / X64 / Fsp24ApiEntryM.nasm
CommitLineData
3d35a6c2
CC
1;; @file\r
2; Provide FSP API entry points.\r
3;\r
4; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
5; SPDX-License-Identifier: BSD-2-Clause-Patent\r
6;;\r
7\r
8 SECTION .text\r
9\r
10%include "PushPopRegsNasm.inc"\r
11\r
12;\r
13; Following are fixed PCDs\r
14;\r
15extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))\r
16\r
17struc FSPM_UPD_COMMON_FSP24\r
18 ; FSP_UPD_HEADER {\r
19 .FspUpdHeader: resd 8\r
20 ; }\r
21 ; FSPM_ARCH2_UPD {\r
22 .Revision: resb 1\r
23 .Reserved: resb 3\r
24 .Length resd 1\r
25 .StackBase: resq 1\r
26 .StackSize: resq 1\r
27 .BootLoaderTolumSize: resd 1\r
28 .BootMode: resd 1\r
29 .FspEventHandler resq 1\r
30 .Reserved1: resb 24\r
31 ; }\r
32 .size:\r
33endstruc\r
34\r
35;\r
36; Following functions will be provided in C\r
37;\r
38extern ASM_PFX(SecStartup)\r
39extern ASM_PFX(FspApiCommon)\r
40\r
41;\r
42; Following functions will be provided in PlatformSecLib\r
43;\r
44extern ASM_PFX(AsmGetFspBaseAddress)\r
45extern ASM_PFX(AsmGetFspInfoHeader)\r
46extern ASM_PFX(FspMultiPhaseMemInitApiHandler)\r
47\r
48STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index\r
49FSP_HEADER_IMGBASE_OFFSET EQU 1Ch\r
50FSP_HEADER_CFGREG_OFFSET EQU 24h\r
51\r
52;----------------------------------------------------------------------------\r
53; FspMemoryInit API\r
54;\r
55; This FSP API is called after TempRamInit and initializes the memory.\r
56;\r
57;----------------------------------------------------------------------------\r
58global ASM_PFX(FspMemoryInitApi)\r
59ASM_PFX(FspMemoryInitApi):\r
60 mov rax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex\r
61 jmp ASM_PFX(FspApiCommon)\r
62\r
63;----------------------------------------------------------------------------\r
64; FspMultiPhaseMemoryInitApi API\r
65;\r
66; This FSP API provides multi-phase Memory initialization, which brings greater\r
67; modularity beyond the existing FspMemoryInit() API.\r
68; Increased modularity is achieved by adding an extra API to FSP-M.\r
69; This allows the bootloader to add board specific initialization steps throughout\r
70; the MemoryInit flow as needed.\r
71;\r
72;----------------------------------------------------------------------------\r
73global ASM_PFX(FspMultiPhaseMemoryInitApi)\r
74ASM_PFX(FspMultiPhaseMemoryInitApi):\r
75 mov rax, 8 ; FSP_API_INDEX.FspMultiPhaseMemInitApiIndex\r
76 jmp ASM_PFX(FspApiCommon)\r
77;----------------------------------------------------------------------------\r
78; TempRamExitApi API\r
79;\r
80; This API tears down temporary RAM\r
81;\r
82;----------------------------------------------------------------------------\r
83global ASM_PFX(TempRamExitApi)\r
84ASM_PFX(TempRamExitApi):\r
85 mov rax, 4 ; FSP_API_INDEX.TempRamExitApiIndex\r
86 jmp ASM_PFX(FspApiCommon)\r
87\r
88;----------------------------------------------------------------------------\r
89; FspApiCommonContinue API\r
90;\r
91; This is the FSP API common entry point to resume the FSP execution\r
92;\r
93;----------------------------------------------------------------------------\r
94global ASM_PFX(FspApiCommonContinue)\r
95ASM_PFX(FspApiCommonContinue):\r
96 ;\r
97 ; Handle FspMultiPhaseMemoInitApiIndex API\r
98 ;\r
99 push rdx ; Push a QWORD data for stack alignment\r
100\r
101 cmp rax, 8 ; FspMultiPhaseMemInitApiIndex\r
102 jnz NotMultiPhaseMemoryInitApi\r
103\r
104 PUSHA_64\r
105 mov rdx, rcx ; move ApiParam to rdx\r
106 mov rcx, rax ; move ApiIdx to rcx\r
107 sub rsp, 0x20 ; calling C function may need shadow space\r
108 call ASM_PFX(FspMultiPhaseMemInitApiHandler)\r
109 add rsp, 0x20 ; restore shadow space\r
110 mov qword [rsp + STACK_SAVED_RAX_OFFSET], rax\r
111 POPA_64\r
112 add rsp, 0x08\r
113 ret\r
114\r
115NotMultiPhaseMemoryInitApi:\r
116 ; Push RDX and RCX to form CONTEXT_STACK_64\r
117 push rdx ; Push API Parameter2 on stack\r
118 push rcx ; Push API Parameter1 on stack\r
119\r
120 ;\r
121 ; FspMemoryInit API setup the initial stack frame\r
122 ;\r
123\r
124 ;\r
125 ; Place holder to store the FspInfoHeader pointer\r
126 ;\r
127 push rax\r
128\r
129 ;\r
130 ; Update the FspInfoHeader pointer\r
131 ;\r
132 push rax\r
133 call ASM_PFX(AsmGetFspInfoHeader)\r
134 mov [rsp + 8], rax\r
135 pop rax\r
136\r
137 ;\r
138 ; Create a Task Frame in the stack for the Boot Loader\r
139 ;\r
140 pushfq\r
141 cli\r
142 PUSHA_64\r
143\r
144 ; Reserve 16 bytes for IDT save/restore\r
145 sub rsp, 16\r
146 sidt [rsp]\r
147\r
148 ; Get Stackbase and StackSize from FSPM_UPD Param\r
149 mov rdx, rcx ; Put FSPM_UPD Param to rdx\r
150 cmp rdx, 0\r
151 jnz FspStackSetup\r
152\r
153 ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null\r
154 xchg rbx, rax\r
155 call ASM_PFX(AsmGetFspInfoHeader)\r
156 mov edx, [rax + FSP_HEADER_IMGBASE_OFFSET]\r
157 add edx, [rax + FSP_HEADER_CFGREG_OFFSET]\r
158 xchg rbx, rax\r
159\r
160FspStackSetup:\r
161 mov cl, [rdx + FSPM_UPD_COMMON_FSP24.Revision]\r
162 cmp cl, 3\r
163 jae FspmUpdCommonFsp24\r
164\r
165 mov rax, 08000000000000002h ; RETURN_INVALID_PARAMETER\r
166 sub rsp, 0b8h\r
167 ret\r
168\r
169FspmUpdCommonFsp24:\r
170 ;\r
171 ; StackBase = temp memory base, StackSize = temp memory size\r
172 ;\r
173 mov rdi, [rdx + FSPM_UPD_COMMON_FSP24.StackBase]\r
174 mov ecx, [rdx + FSPM_UPD_COMMON_FSP24.StackSize]\r
175\r
176 ;\r
177 ; Keep using bootloader stack if heap size % is 0\r
178 ;\r
179 mov rbx, ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))\r
180 mov bl, BYTE [rbx]\r
181 cmp bl, 0\r
182 jz SkipStackSwitch\r
183\r
184 ;\r
185 ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0\r
186 ;\r
187 add rdi, rcx\r
188 ;\r
189 ; Switch to new FSP stack\r
190 ;\r
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\r
192\r
193SkipStackSwitch:\r
194 ;\r
195 ; If heap size % is 0:\r
196 ; EDI is FSPM_UPD_COMMON_FSP24.StackBase and will hold ESP later (boot loader stack pointer)\r
197 ; ECX is FSPM_UPD_COMMON_FSP24.StackSize\r
198 ; ESP is boot loader stack pointer (no stack switch)\r
199 ; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON_FSP24.StackBase later)\r
200 ;\r
201 ; If heap size % is not 0\r
202 ; EDI is boot loader stack pointer\r
203 ; ECX is FSPM_UPD_COMMON_FSP24.StackSize\r
204 ; ESP is new stack (FSPM_UPD_COMMON_FSP24.StackBase + FSPM_UPD_COMMON_FSP24.StackSize)\r
205 ; BL is NOT 0 to indicate stack has switched\r
206 ;\r
207 cmp bl, 0\r
208 jnz StackHasBeenSwitched\r
209\r
210 mov rbx, rdi ; Put FSPM_UPD_COMMON_FSP24.StackBase to rbx as temp memory base\r
211 mov rdi, rsp ; Put boot loader stack pointer to rdi\r
212 jmp StackSetupDone\r
213\r
214StackHasBeenSwitched:\r
215 mov rbx, rsp ; Put Stack base + Stack size in ebx\r
216 sub rbx, rcx ; Stack base + Stack size - Stack size as temp memory base\r
217\r
218StackSetupDone:\r
219\r
220 ;\r
221 ; Per X64 calling convention, make sure RSP is 16-byte aligned.\r
222 ;\r
223 mov rdx, rsp\r
224 and rdx, 0fh\r
225 sub rsp, rdx\r
226\r
227 ;\r
228 ; Pass the API Idx to SecStartup\r
229 ;\r
230 push rax\r
231\r
232 ;\r
233 ; Pass the BootLoader stack to SecStartup\r
234 ;\r
235 push rdi\r
236\r
237 ;\r
238 ; Pass BFV into the PEI Core\r
239 ; It uses relative address to calculate the actual boot FV base\r
240 ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and\r
241 ; PcdFspAreaBaseAddress are the same. For FSP with multiple FVs,\r
242 ; they are different. The code below can handle both cases.\r
243 ;\r
244 call ASM_PFX(AsmGetFspBaseAddress)\r
245 mov r8, rax\r
246\r
247 ;\r
248 ; Pass entry point of the PEI core\r
249 ;\r
250 call ASM_PFX(AsmGetPeiCoreOffset)\r
251 lea r9, [r8 + rax]\r
252\r
253 ;\r
254 ; Pass stack base and size into the PEI Core\r
255 ;\r
256 mov rcx, rcx\r
257 mov rdx, rbx\r
258\r
259 ;\r
260 ; Pass Control into the PEI Core\r
261 ; RCX = SizeOfRam, RDX = TempRamBase, R8 = BFV, R9 = PeiCoreEntry, Last 1 Stack = BL stack, Last 2 Stack = API index\r
262 ; According to X64 calling convention, caller has to allocate 32 bytes as a shadow store on call stack right before\r
263 ; calling the function.\r
264 ;\r
265 sub rsp, 20h\r
266 call ASM_PFX(SecStartup)\r
267 add rsp, 20h\r
268exit:\r
269 ret\r
270\r
271global ASM_PFX(FspPeiCoreEntryOff)\r
272ASM_PFX(FspPeiCoreEntryOff):\r
273 ;\r
274 ; This value will be patched by the build script\r
275 ;\r
276 DD 0x12345678\r
277\r
278global ASM_PFX(AsmGetPeiCoreOffset)\r
279ASM_PFX(AsmGetPeiCoreOffset):\r
280 push rbx\r
281 mov rbx, ASM_PFX(FspPeiCoreEntryOff)\r
282 mov eax, dword[ebx]\r
283 pop rbx\r
284 ret\r
285\r
286;----------------------------------------------------------------------------\r
287; TempRamInit API\r
288;\r
289; Empty function for WHOLEARCHIVE build option\r
290;\r
291;----------------------------------------------------------------------------\r
292global ASM_PFX(TempRamInitApi)\r
293ASM_PFX(TempRamInitApi):\r
294 jmp $\r
295 ret\r
296\r
297;----------------------------------------------------------------------------\r
298; Module Entrypoint API\r
299;----------------------------------------------------------------------------\r
300global ASM_PFX(_ModuleEntryPoint)\r
301ASM_PFX(_ModuleEntryPoint):\r
302 jmp $\r
303\r