]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
IntelFsp2Pkg: FSP should support input UPD as NULL.
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / X64 / FspApiEntryT.nasm
CommitLineData
00aa71ce
TK
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 "SaveRestoreSseAvxNasm.inc"\r
11%include "MicrocodeLoadNasm.inc"\r
12\r
13;\r
14; Following are fixed PCDs\r
15;\r
16extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))\r
17extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))\r
18extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))\r
19\r
20;\r
21; Following functions will be provided in PlatformSecLib\r
22;\r
23extern ASM_PFX(AsmGetFspBaseAddress)\r
b84f32ae 24extern ASM_PFX(AsmGetFspInfoHeaderNoStack)\r
00aa71ce
TK
25;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation\r
26extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation\r
27extern ASM_PFX(SecCarInit)\r
28\r
29;\r
30; Define the data length that we saved on the stack top\r
31;\r
32DATA_LEN_OF_PER0 EQU 18h\r
33DATA_LEN_OF_MCUD EQU 18h\r
34DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)\r
35\r
36;\r
37; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid\r
38; build error. This needs to be fixed later on.\r
39;\r
40struc MicrocodeHdr\r
41 .MicrocodeHdrVersion: resd 1\r
42 .MicrocodeHdrRevision: resd 1\r
43 .MicrocodeHdrDate: resd 1\r
44 .MicrocodeHdrProcessor: resd 1\r
45 .MicrocodeHdrChecksum: resd 1\r
46 .MicrocodeHdrLoader: resd 1\r
47 .MicrocodeHdrFlags: resd 1\r
48 .MicrocodeHdrDataSize: resd 1\r
49 .MicrocodeHdrTotalSize: resd 1\r
50 .MicrocodeHdrRsvd: resd 3\r
51 .size:\r
52endstruc\r
53\r
54struc ExtSigHdr\r
55 .ExtSigHdrCount: resd 1\r
56 .ExtSigHdrChecksum: resd 1\r
57 .ExtSigHdrRsvd: resd 3\r
58 .size:\r
59endstruc\r
60\r
61struc ExtSig\r
62 .ExtSigProcessor: resd 1\r
63 .ExtSigFlags: resd 1\r
64 .ExtSigChecksum: resd 1\r
65 .size:\r
66endstruc\r
67\r
68struc LoadMicrocodeParamsFsp24\r
69 ; FSP_UPD_HEADER {\r
70 .FspUpdHeaderSignature: resd 2\r
71 .FspUpdHeaderRevision: resb 1\r
72 .FspUpdHeaderReserved: resb 23\r
73 ; }\r
74 ; FSPT_ARCH2_UPD {\r
75 .FsptArchRevision: resb 1\r
76 .FsptArchReserved: resb 3\r
77 .FsptArchLength: resd 1\r
78 .FspDebugHandler resq 1\r
79 .FsptArchUpd: resd 4\r
80 ; }\r
81 ; FSPT_CORE_UPD {\r
82 .MicrocodeCodeAddr: resq 1\r
83 .MicrocodeCodeSize: resq 1\r
84 .CodeRegionBase: resq 1\r
85 .CodeRegionSize: resq 1\r
86 ; }\r
87 .size:\r
88endstruc\r
89\r
b84f32ae
CC
90%macro CALL_RDI 1\r
91\r
92 mov rdi, %%ReturnAddress\r
93 jmp %1\r
94%%ReturnAddress:\r
95\r
96%endmacro\r
97\r
00aa71ce
TK
98;\r
99; @todo: The strong/weak implementation does not work.\r
100; This needs to be reviewed later.\r
101;\r
102;------------------------------------------------------------------------------\r
103;\r
104;;global ASM_PFX(SecPlatformInitDefault)\r
105;ASM_PFX(SecPlatformInitDefault):\r
106; ; Inputs:\r
107; ; ymm7 -> Return address\r
108; ; Outputs:\r
109; ; rax -> 0 - Successful, Non-zero - Failed.\r
110; ; Register Usage:\r
111; ; rax is cleared and rbp is used for return address.\r
112; ; All others reserved.\r
113;\r
114; ; Save return address to RBP\r
115; LOAD_RBP\r
116;\r
117; xor rax, rax\r
118;Exit1:\r
119; jmp rbp\r
120\r
121;------------------------------------------------------------------------------\r
122global ASM_PFX(LoadMicrocodeDefault)\r
123ASM_PFX(LoadMicrocodeDefault):\r
124 ; Inputs:\r
11d8abcb 125 ; rcx -> LoadMicrocodeParams pointer\r
00aa71ce 126 ; Register Usage:\r
b84f32ae 127 ; All are destroyed\r
00aa71ce
TK
128 ; Assumptions:\r
129 ; No memory available, stack is hard-coded and used for return address\r
130 ; Executed by SBSP and NBSP\r
131 ; Beginning of microcode update region starts on paragraph boundary\r
132\r
133 ;\r
134 ; Save return address to RBP\r
135 ;\r
136 LOAD_RBP\r
137\r
138 cmp rsp, 0\r
139 jz ParamError\r
11d8abcb 140 cmp rcx, 0\r
00aa71ce 141 jz ParamError\r
11d8abcb 142 mov rsp, rcx\r
00aa71ce
TK
143\r
144 ; skip loading Microcode if the MicrocodeCodeSize is zero\r
145 ; and report error if size is less than 2k\r
146 ; first check UPD header revision\r
147 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2\r
148 jb ParamError\r
149 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2\r
150 jne ParamError\r
151\r
152 ; UPD structure is compliant with FSP spec 2.4\r
11d8abcb
DC
153 mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]\r
154 cmp rax, 0\r
00aa71ce 155 jz Exit2\r
11d8abcb 156 cmp rax, 0800h\r
00aa71ce
TK
157 jl ParamError\r
158\r
11d8abcb
DC
159 mov rsi, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]\r
160 cmp rsi, 0\r
00aa71ce
TK
161 jnz CheckMainHeader\r
162\r
163ParamError:\r
164 mov rax, 08000000000000002h\r
165 jmp Exit2\r
166\r
167CheckMainHeader:\r
168 ; Get processor signature and platform ID from the installed processor\r
169 ; and save into registers for later use\r
170 ; ebx = processor signature\r
171 ; edx = platform ID\r
172 mov eax, 1\r
173 cpuid\r
174 mov ebx, eax\r
175 mov ecx, MSR_IA32_PLATFORM_ID\r
176 rdmsr\r
177 mov ecx, edx\r
178 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits\r
179 and ecx, 7h ; platform id at bit[52..50]\r
180 mov edx, 1\r
181 shl edx, cl\r
182\r
183 ; Current register usage\r
184 ; esp -> stack with parameters\r
185 ; esi -> microcode update to check\r
186 ; ebx = processor signature\r
187 ; edx = platform ID\r
188\r
189 ; Check for valid microcode header\r
190 ; Minimal test checking for header version and loader version as 1\r
191 mov eax, dword 1\r
192 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax\r
193 jne AdvanceFixedSize\r
194 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax\r
195 jne AdvanceFixedSize\r
196\r
197 ; Check if signature and plaform ID match\r
198 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]\r
199 jne LoadMicrocodeDefault1\r
200 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]\r
201 jnz LoadCheck ; Jif signature and platform ID match\r
202\r
203LoadMicrocodeDefault1:\r
204 ; Check if extended header exists\r
205 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid\r
206 xor rax, rax\r
207 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax\r
208 je NextMicrocode\r
209 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax\r
210 je NextMicrocode\r
211\r
212 ; Then verify total size - sizeof header > data size\r
213 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]\r
214 sub ecx, MicrocodeHdr.size\r
215 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]\r
216 jng NextMicrocode ; Jif extended header does not exist\r
217\r
218 ; Set edi -> extended header\r
219 mov edi, esi\r
220 add edi, MicrocodeHdr.size\r
221 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]\r
222\r
223 ; Get count of extended structures\r
224 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]\r
225\r
226 ; Move pointer to first signature structure\r
227 add edi, ExtSigHdr.size\r
228\r
229CheckExtSig:\r
230 ; Check if extended signature and platform ID match\r
231 cmp dword [edi + ExtSig.ExtSigProcessor], ebx\r
232 jne LoadMicrocodeDefault2\r
233 test dword [edi + ExtSig.ExtSigFlags], edx\r
234 jnz LoadCheck ; Jif signature and platform ID match\r
235LoadMicrocodeDefault2:\r
236 ; Check if any more extended signatures exist\r
237 add edi, ExtSig.size\r
238 loop CheckExtSig\r
239\r
240NextMicrocode:\r
241 ; Advance just after end of this microcode\r
242 xor rax, rax\r
243 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax\r
244 je LoadMicrocodeDefault3\r
245 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]\r
246 jmp CheckAddress\r
247LoadMicrocodeDefault3:\r
248 add esi, dword 2048\r
249 jmp CheckAddress\r
250\r
251AdvanceFixedSize:\r
252 ; Advance by 4X dwords\r
253 add esi, dword 1024\r
254\r
255CheckAddress:\r
256 ; Check UPD header revision\r
257 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2\r
258 jb ParamError\r
259 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2\r
260 jne ParamError\r
261\r
262 ; UPD structure is compliant with FSP spec 2.4\r
263 ; Is automatic size detection ?\r
264 mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]\r
11d8abcb
DC
265 mov rcx, 0ffffffffffffffffh\r
266 cmp rax, rcx\r
00aa71ce
TK
267 jz LoadMicrocodeDefault4\r
268\r
269 ; Address >= microcode region address + microcode region size?\r
270 add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]\r
271 cmp rsi, rax\r
272 jae Done ;Jif address is outside of microcode region\r
273 jmp CheckMainHeader\r
274\r
275LoadMicrocodeDefault4:\r
276 ; Is valid Microcode start point ?\r
277 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh\r
278 jz Done\r
279\r
280LoadCheck:\r
281 ; Get the revision of the current microcode update loaded\r
282 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
283 xor eax, eax ; Clear EAX\r
284 xor edx, edx ; Clear EDX\r
285 wrmsr ; Load 0 to MSR at 8Bh\r
286\r
287 mov eax, 1\r
288 cpuid\r
289 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
290 rdmsr ; Get current microcode signature\r
291\r
292 ; Verify this microcode update is not already loaded\r
293 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx\r
294 je Continue\r
295\r
296LoadMicrocode:\r
297 ; EAX contains the linear address of the start of the Update Data\r
298 ; EDX contains zero\r
299 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)\r
300 ; Start microcode load with wrmsr\r
301 mov eax, esi\r
302 add eax, MicrocodeHdr.size\r
303 xor edx, edx\r
304 mov ecx, MSR_IA32_BIOS_UPDT_TRIG\r
305 wrmsr\r
306 mov eax, 1\r
307 cpuid\r
308\r
309Continue:\r
310 jmp NextMicrocode\r
311\r
312Done:\r
313 mov eax, 1\r
314 cpuid\r
315 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
316 rdmsr ; Get current microcode signature\r
317 xor eax, eax\r
318 cmp edx, 0\r
319 jnz Exit2\r
320 mov eax, 0800000000000000Eh\r
321\r
322Exit2:\r
323 jmp rbp\r
324\r
325\r
326global ASM_PFX(EstablishStackFsp)\r
327ASM_PFX(EstablishStackFsp):\r
328 ;\r
329 ; Save parameter pointer in rdx\r
330 ;\r
11d8abcb 331 mov rdx, rcx\r
00aa71ce
TK
332 ;\r
333 ; Enable FSP STACK\r
334 ;\r
335 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))\r
336 mov esp, DWORD[rax]\r
337 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))\r
338 add esp, DWORD[rax]\r
339\r
340 sub esp, 4\r
341 mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region\r
342 sub esp, 4\r
343 mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'\r
344\r
345 ; check UPD structure revision (rdx + 8)\r
346 cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2\r
347 jb ParamError1\r
348 cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2\r
349 je Fsp24UpdHeader\r
350\r
351ParamError1:\r
352 mov rax, 08000000000000002h\r
353 jmp EstablishStackFspExit\r
354\r
355Fsp24UpdHeader:\r
356 ; UPD structure is compliant with FSP spec 2.4\r
357 xor rax, rax\r
358 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h\r
359 sub rsp, 8\r
360 mov qword[rsp], rax\r
361 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h\r
362 sub rsp, 8\r
363 mov qword[rsp], rax\r
364 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h\r
365 sub rsp, 8\r
366 mov qword[rsp], rax\r
367 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h\r
368 sub rsp, 8\r
369 mov qword[rsp], rax\r
370\r
371ContinueAfterUpdPush:\r
372 ;\r
373 ; Save API entry/exit timestamp into stack\r
374 ;\r
375 sub esp, 4\r
376 mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region\r
377 sub esp, 4\r
378 mov dword[esp], 30524550h ; Signature of the data region 'PER0'\r
379 rdtsc\r
380 sub esp, 4\r
381 mov dword[esp], edx\r
382 sub esp, 4\r
383 mov dword[esp], eax\r
384 LOAD_TS rax\r
385 push rax\r
386\r
387 ;\r
388 ; Terminator for the data on stack\r
389 ;\r
390 push 0\r
391\r
392 ;\r
393 ; Set ECX/EDX to the BootLoader temporary memory range\r
394 ;\r
395 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))\r
396 mov edx, [ecx]\r
397 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))\r
398 add edx, [ecx]\r
399 mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))\r
400 sub edx, [ecx]\r
401 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))\r
402 mov ecx, [ecx]\r
403\r
404 cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.\r
405 jb EstablishStackFspSuccess\r
406 mov rax, 08000000000000003h ; EFI_UNSUPPORTED\r
407 jmp EstablishStackFspExit\r
408EstablishStackFspSuccess:\r
409 xor rax, rax\r
410\r
411EstablishStackFspExit:\r
412 RET_YMM\r
413\r
414;----------------------------------------------------------------------------\r
415; TempRamInit API\r
416;\r
417; This FSP API will load the microcode update, enable code caching for the\r
418; region specified by the boot loader and also setup a temporary stack to be\r
419; used till main memory is initialized.\r
420;\r
421;----------------------------------------------------------------------------\r
422global ASM_PFX(TempRamInitApi)\r
423ASM_PFX(TempRamInitApi):\r
424 ;\r
425 ; Ensure both SSE and AVX are enabled\r
426 ;\r
427 ENABLE_SSE\r
428 ENABLE_AVX\r
11d8abcb 429 ;\r
00aa71ce
TK
430 ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6\r
431 ;\r
432 SAVE_REGS\r
433\r
434 ;\r
435 ; Save BFV address in YMM9\r
436 ;\r
437 SAVE_BFV rbp\r
438\r
b84f32ae
CC
439 ;\r
440 ; Save Input Parameter in YMM10\r
441 ;\r
442 cmp rcx, 0\r
443 jnz ParamValid\r
444\r
445 ;\r
446 ; Fall back to default UPD\r
447 ;\r
448 CALL_RDI ASM_PFX(AsmGetFspInfoHeaderNoStack)\r
449 xor rcx, rcx\r
450 mov ecx, DWORD [rax + 01Ch] ; Read FsptImageBaseAddress\r
451 add ecx, DWORD [rax + 024h] ; Get Cfg Region base address = FsptImageBaseAddress + CfgRegionOffset\r
452ParamValid:\r
453 SAVE_RCX\r
454\r
00aa71ce
TK
455 ;\r
456 ; Save timestamp into YMM6\r
457 ;\r
458 rdtsc\r
459 shl rdx, 32\r
460 or rax, rdx\r
461 SAVE_TS rax\r
462\r
00aa71ce
TK
463 ;\r
464 ; Sec Platform Init\r
465 ;\r
466 CALL_YMM ASM_PFX(SecPlatformInit)\r
467 cmp eax, 0\r
468 jnz TempRamInitExit\r
469\r
470 ; Load microcode\r
11d8abcb 471 LOAD_RCX\r
00aa71ce
TK
472 CALL_YMM ASM_PFX(LoadMicrocodeDefault)\r
473 SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).\r
474 ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.\r
475\r
476 ; Call Sec CAR Init\r
11d8abcb 477 LOAD_RCX\r
00aa71ce
TK
478 CALL_YMM ASM_PFX(SecCarInit)\r
479 cmp rax, 0\r
480 jnz TempRamInitExit\r
481\r
11d8abcb 482 LOAD_RCX\r
00aa71ce
TK
483 CALL_YMM ASM_PFX(EstablishStackFsp)\r
484 cmp rax, 0\r
485 jnz TempRamInitExit\r
486\r
487 LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).\r
488\r
489TempRamInitExit:\r
490 mov bl, al ; save al data in bl\r
491 mov al, 07Fh ; API exit postcode 7f\r
492 out 080h, al\r
493 mov al, bl ; restore al data from bl\r
494\r
495 ;\r
496 ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6\r
497 ;\r
498 LOAD_REGS\r
499 LOAD_BFV rbp\r
500 ret\r
501\r
502;----------------------------------------------------------------------------\r
503; Module Entrypoint API\r
504;----------------------------------------------------------------------------\r
505global ASM_PFX(_ModuleEntryPoint)\r
506ASM_PFX(_ModuleEntryPoint):\r
507 jmp $\r
508\r