]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
IntelFsp2Pkg/FspSecCore: LoadMicrocodeDefault() failed with padding in FV.
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / Ia32 / FspApiEntryT.nasm
CommitLineData
cf1d4549
JY
1;; @file\r
2; Provide FSP API entry points.\r
3;\r
89f569ae 4; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
9672cd30 5; SPDX-License-Identifier: BSD-2-Clause-Patent\r
cf1d4549
JY
6;;\r
7\r
8 SECTION .text\r
9\r
10%include "SaveRestoreSseNasm.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 LoadMicrocodeParams\r
69 ; FSP_UPD_HEADER {\r
70 .FspUpdHeader: resd 8\r
71 ; }\r
72 ; FSPT_CORE_UPD {\r
73 .MicrocodeCodeAddr: resd 1\r
74 .MicrocodeCodeSize: resd 1\r
75 .CodeRegionBase: resd 1\r
76 .CodeRegionSize: resd 1\r
77 ; }\r
78 .size:\r
79endstruc\r
80\r
89f569ae
CC
81struc LoadMicrocodeParamsFsp22\r
82 ; FSP_UPD_HEADER {\r
83 .FspUpdHeaderSignature: resd 2\r
84 .FspUpdHeaderRevision: resb 1\r
85 .FspUpdHeaderReserved: resb 23\r
86 ; }\r
87 ; FSPT_ARCH_UPD{\r
88 .FsptArchUpd: resd 8\r
89 ; }\r
90 ; FSPT_CORE_UPD {\r
91 .MicrocodeCodeAddr: resd 1\r
92 .MicrocodeCodeSize: resd 1\r
93 .CodeRegionBase: resd 1\r
94 .CodeRegionSize: resd 1\r
95 ; }\r
96 .size:\r
97endstruc\r
cf1d4549
JY
98\r
99;\r
100; Define SSE macros\r
101;\r
102;\r
103;args 1: ReturnAddress 2:MmxRegister\r
104;\r
105%macro LOAD_MMX_EXT 2\r
106 mov esi, %1\r
107 movd %2, esi ; save ReturnAddress into MMX\r
108%endmacro\r
109\r
110;\r
111;args 1: RoutineLabel 2:MmxRegister\r
112;\r
113%macro CALL_MMX_EXT 2\r
114 mov esi, %%ReturnAddress\r
115 movd %2, esi ; save ReturnAddress into MMX\r
116 jmp %1\r
117%%ReturnAddress:\r
118%endmacro\r
119\r
120;\r
121;arg 1:MmxRegister\r
122;\r
123%macro RET_ESI_EXT 1\r
124 movd esi, %1 ; move ReturnAddress from MMX to ESI\r
125 jmp esi\r
126%endmacro\r
127\r
128;\r
129;arg 1:RoutineLabel\r
130;\r
131%macro CALL_MMX 1\r
132 CALL_MMX_EXT %1, mm7\r
133%endmacro\r
134\r
135%macro RET_ESI 0\r
136 RET_ESI_EXT mm7\r
137%endmacro\r
138\r
139;\r
140; @todo: The strong/weak implementation does not work.\r
141; This needs to be reviewed later.\r
142;\r
143;------------------------------------------------------------------------------\r
144;\r
145;;global ASM_PFX(SecPlatformInitDefault)\r
146;ASM_PFX(SecPlatformInitDefault):\r
147; ; Inputs:\r
148; ; mm7 -> Return address\r
149; ; Outputs:\r
150; ; eax -> 0 - Successful, Non-zero - Failed.\r
151; ; Register Usage:\r
152; ; eax is cleared and ebp is used for return address.\r
153; ; All others reserved.\r
154;\r
155; ; Save return address to EBP\r
156; movd ebp, mm7\r
157;\r
158; xor eax, eax\r
159;Exit1:\r
160; jmp ebp\r
161\r
162;------------------------------------------------------------------------------\r
163global ASM_PFX(LoadMicrocodeDefault)\r
164ASM_PFX(LoadMicrocodeDefault):\r
165 ; Inputs:\r
166 ; esp -> LoadMicrocodeParams pointer\r
167 ; Register Usage:\r
168 ; esp Preserved\r
169 ; All others destroyed\r
170 ; Assumptions:\r
171 ; No memory available, stack is hard-coded and used for return address\r
172 ; Executed by SBSP and NBSP\r
173 ; Beginning of microcode update region starts on paragraph boundary\r
174\r
175 ;\r
176 ;\r
177 ; Save return address to EBP\r
178 movd ebp, mm7\r
179\r
180 cmp esp, 0\r
181 jz ParamError\r
182 mov eax, dword [esp + 4] ; Parameter pointer\r
183 cmp eax, 0\r
184 jz ParamError\r
185 mov esp, eax\r
4c53eb72
YS
186\r
187 ; skip loading Microcode if the MicrocodeCodeSize is zero\r
188 ; and report error if size is less than 2k\r
89f569ae
CC
189 ; first check UPD header revision\r
190 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2\r
191 jae Fsp22UpdHeader\r
192\r
193 ; UPD structure is compliant with FSP spec 2.0/2.1\r
4c53eb72
YS
194 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]\r
195 cmp eax, 0\r
196 jz Exit2\r
197 cmp eax, 0800h\r
198 jl ParamError\r
199\r
cf1d4549
JY
200 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]\r
201 cmp esi, 0\r
202 jnz CheckMainHeader\r
89f569ae
CC
203 jmp ParamError\r
204\r
205Fsp22UpdHeader:\r
206 ; UPD structure is compliant with FSP spec 2.2\r
207 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]\r
208 cmp eax, 0\r
209 jz Exit2\r
210 cmp eax, 0800h\r
211 jl ParamError\r
212\r
213 mov esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]\r
214 cmp esi, 0\r
215 jnz CheckMainHeader\r
cf1d4549
JY
216\r
217ParamError:\r
218 mov eax, 080000002h\r
219 jmp Exit2\r
220\r
221CheckMainHeader:\r
222 ; Get processor signature and platform ID from the installed processor\r
223 ; and save into registers for later use\r
224 ; ebx = processor signature\r
225 ; edx = platform ID\r
226 mov eax, 1\r
227 cpuid\r
228 mov ebx, eax\r
229 mov ecx, MSR_IA32_PLATFORM_ID\r
230 rdmsr\r
231 mov ecx, edx\r
232 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits\r
233 and ecx, 7h ; platform id at bit[52..50]\r
234 mov edx, 1\r
235 shl edx, cl\r
236\r
237 ; Current register usage\r
238 ; esp -> stack with parameters\r
239 ; esi -> microcode update to check\r
240 ; ebx = processor signature\r
241 ; edx = platform ID\r
242\r
243 ; Check for valid microcode header\r
244 ; Minimal test checking for header version and loader version as 1\r
245 mov eax, dword 1\r
246 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax\r
247 jne AdvanceFixedSize\r
248 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax\r
249 jne AdvanceFixedSize\r
250\r
251 ; Check if signature and plaform ID match\r
252 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]\r
253 jne LoadMicrocodeDefault1\r
254 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]\r
255 jnz LoadCheck ; Jif signature and platform ID match\r
256\r
257LoadMicrocodeDefault1:\r
258 ; Check if extended header exists\r
259 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid\r
260 xor eax, eax\r
261 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax\r
262 je NextMicrocode\r
263 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax\r
264 je NextMicrocode\r
265\r
266 ; Then verify total size - sizeof header > data size\r
267 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]\r
268 sub ecx, MicrocodeHdr.size\r
269 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]\r
270 jng NextMicrocode ; Jif extended header does not exist\r
271\r
272 ; Set edi -> extended header\r
273 mov edi, esi\r
274 add edi, MicrocodeHdr.size\r
275 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]\r
276\r
277 ; Get count of extended structures\r
278 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]\r
279\r
280 ; Move pointer to first signature structure\r
281 add edi, ExtSigHdr.size\r
282\r
283CheckExtSig:\r
284 ; Check if extended signature and platform ID match\r
285 cmp dword [edi + ExtSig.ExtSigProcessor], ebx\r
286 jne LoadMicrocodeDefault2\r
287 test dword [edi + ExtSig.ExtSigFlags], edx\r
288 jnz LoadCheck ; Jif signature and platform ID match\r
289LoadMicrocodeDefault2:\r
290 ; Check if any more extended signatures exist\r
291 add edi, ExtSig.size\r
292 loop CheckExtSig\r
293\r
294NextMicrocode:\r
295 ; Advance just after end of this microcode\r
296 xor eax, eax\r
297 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax\r
298 je LoadMicrocodeDefault3\r
299 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]\r
300 jmp CheckAddress\r
301LoadMicrocodeDefault3:\r
302 add esi, dword 2048\r
303 jmp CheckAddress\r
304\r
305AdvanceFixedSize:\r
306 ; Advance by 4X dwords\r
307 add esi, dword 1024\r
308\r
309CheckAddress:\r
89f569ae
CC
310 ; Check UPD header revision\r
311 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2\r
312 jae Fsp22UpdHeader1\r
313\r
314 ; UPD structure is compliant with FSP spec 2.0/2.1\r
cf1d4549
JY
315 ; Is automatic size detection ?\r
316 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]\r
317 cmp eax, 0ffffffffh\r
318 jz LoadMicrocodeDefault4\r
319\r
320 ; Address >= microcode region address + microcode region size?\r
321 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]\r
322 cmp esi, eax\r
323 jae Done ;Jif address is outside of microcode region\r
324 jmp CheckMainHeader\r
325\r
89f569ae
CC
326Fsp22UpdHeader1:\r
327 ; UPD structure is compliant with FSP spec 2.2\r
328 ; Is automatic size detection ?\r
329 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]\r
330 cmp eax, 0ffffffffh\r
331 jz LoadMicrocodeDefault4\r
332\r
333 ; Address >= microcode region address + microcode region size?\r
334 add eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]\r
335 cmp esi, eax\r
336 jae Done ;Jif address is outside of microcode region\r
337 jmp CheckMainHeader\r
338\r
cf1d4549 339LoadMicrocodeDefault4:\r
31e97bda
CL
340 ; Is valid Microcode start point ?\r
341 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh\r
342 jz Done\r
343\r
cf1d4549
JY
344LoadCheck:\r
345 ; Get the revision of the current microcode update loaded\r
346 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
347 xor eax, eax ; Clear EAX\r
348 xor edx, edx ; Clear EDX\r
349 wrmsr ; Load 0 to MSR at 8Bh\r
350\r
351 mov eax, 1\r
352 cpuid\r
353 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
354 rdmsr ; Get current microcode signature\r
355\r
356 ; Verify this microcode update is not already loaded\r
357 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx\r
358 je Continue\r
359\r
360LoadMicrocode:\r
361 ; EAX contains the linear address of the start of the Update Data\r
362 ; EDX contains zero\r
363 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)\r
364 ; Start microcode load with wrmsr\r
365 mov eax, esi\r
366 add eax, MicrocodeHdr.size\r
367 xor edx, edx\r
368 mov ecx, MSR_IA32_BIOS_UPDT_TRIG\r
369 wrmsr\r
370 mov eax, 1\r
371 cpuid\r
372\r
373Continue:\r
374 jmp NextMicrocode\r
375\r
376Done:\r
377 mov eax, 1\r
378 cpuid\r
379 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
380 rdmsr ; Get current microcode signature\r
381 xor eax, eax\r
382 cmp edx, 0\r
383 jnz Exit2\r
384 mov eax, 08000000Eh\r
385\r
386Exit2:\r
387 jmp ebp\r
388\r
389\r
390global ASM_PFX(EstablishStackFsp)\r
391ASM_PFX(EstablishStackFsp):\r
392 ;\r
393 ; Save parameter pointer in edx\r
394 ;\r
395 mov edx, dword [esp + 4]\r
396\r
397 ;\r
398 ; Enable FSP STACK\r
399 ;\r
400 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]\r
401 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]\r
402\r
403 push DATA_LEN_OF_MCUD ; Size of the data region\r
404 push 4455434Dh ; Signature of the data region 'MCUD'\r
cf1d4549 405\r
89f569ae
CC
406 ; check UPD structure revision (edx + 8)\r
407 cmp byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2\r
408 jae Fsp22UpdHeader2\r
409\r
410 ; UPD structure is compliant with FSP spec 2.0/2.1\r
411 push dword [edx + LoadMicrocodeParams.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12\r
412 push dword [edx + LoadMicrocodeParams.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8\r
413 push dword [edx + LoadMicrocodeParams.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4\r
414 push dword [edx + LoadMicrocodeParams.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0\r
415 jmp ContinueAfterUpdPush\r
416\r
417Fsp22UpdHeader2:\r
418 ; UPD structure is compliant with FSP spec 2.2\r
419 push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12\r
420 push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8\r
421 push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4\r
422 push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0\r
423\r
424ContinueAfterUpdPush:\r
cf1d4549
JY
425 ;\r
426 ; Save API entry/exit timestamp into stack\r
427 ;\r
428 push DATA_LEN_OF_PER0 ; Size of the data region\r
429 push 30524550h ; Signature of the data region 'PER0'\r
430 rdtsc\r
431 push edx\r
432 push eax\r
433 LOAD_EDX\r
434 push edx\r
435 LOAD_EAX\r
436 push eax\r
437\r
438 ;\r
439 ; Terminator for the data on stack\r
440 ;\r
441 push 0\r
442\r
443 ;\r
444 ; Set ECX/EDX to the BootLoader temporary memory range\r
445 ;\r
446 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]\r
447 mov edx, ecx\r
448 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]\r
449 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]\r
450\r
451 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.\r
452 jb EstablishStackFspSuccess\r
453 mov eax, 80000003h ;EFI_UNSUPPORTED\r
454 jmp EstablishStackFspExit\r
455EstablishStackFspSuccess:\r
456 xor eax, eax\r
457\r
458EstablishStackFspExit:\r
459 RET_ESI\r
460\r
461;----------------------------------------------------------------------------\r
462; TempRamInit API\r
463;\r
464; This FSP API will load the microcode update, enable code caching for the\r
465; region specified by the boot loader and also setup a temporary stack to be\r
466; used till main memory is initialized.\r
467;\r
468;----------------------------------------------------------------------------\r
469global ASM_PFX(TempRamInitApi)\r
470ASM_PFX(TempRamInitApi):\r
471 ;\r
472 ; Ensure SSE is enabled\r
473 ;\r
474 ENABLE_SSE\r
475\r
476 ;\r
477 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6\r
478 ;\r
479 SAVE_REGS\r
480\r
481 ;\r
482 ; Save timestamp into XMM6\r
483 ;\r
484 rdtsc\r
485 SAVE_EAX\r
486 SAVE_EDX\r
487\r
488 ;\r
489 ; Check Parameter\r
490 ;\r
491 mov eax, dword [esp + 4]\r
492 cmp eax, 0\r
493 mov eax, 80000002h\r
494 jz TempRamInitExit\r
495\r
496 ;\r
497 ; Sec Platform Init\r
498 ;\r
499 CALL_MMX ASM_PFX(SecPlatformInit)\r
500 cmp eax, 0\r
501 jnz TempRamInitExit\r
502\r
503 ; Load microcode\r
504 LOAD_ESP\r
505 CALL_MMX ASM_PFX(LoadMicrocodeDefault)\r
506 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.\r
507 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.\r
508\r
509 ; Call Sec CAR Init\r
510 LOAD_ESP\r
511 CALL_MMX ASM_PFX(SecCarInit)\r
512 cmp eax, 0\r
513 jnz TempRamInitExit\r
514\r
515 LOAD_ESP\r
516 CALL_MMX ASM_PFX(EstablishStackFsp)\r
517 cmp eax, 0\r
518 jnz TempRamInitExit\r
519\r
520 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.\r
521\r
522TempRamInitExit:\r
523 mov bl, al ; save al data in bl\r
524 mov al, 07Fh ; API exit postcode 7f\r
525 out 080h, al\r
526 mov al, bl ; restore al data from bl\r
527\r
528 ;\r
529 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
530 ;\r
531 LOAD_REGS\r
532 ret\r
533\r
534;----------------------------------------------------------------------------\r
535; Module Entrypoint API\r
536;----------------------------------------------------------------------------\r
537global ASM_PFX(_ModuleEntryPoint)\r
538ASM_PFX(_ModuleEntryPoint):\r
539 jmp $\r