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