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