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