2 ; Provide FSP API entry points.
4 ; Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
5 ; SPDX-License-Identifier: BSD-2-Clause-Patent
10 %include "SaveRestoreSseNasm.inc"
11 %include "MicrocodeLoadNasm.inc"
14 ; Following are fixed PCDs
16 extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
17 extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
18 extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
21 ; Following functions will be provided in PlatformSecLib
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)
30 ; Define the data length that we saved on the stack top
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)
37 ; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
38 ; build error. This needs to be fixed later on.
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
55 .ExtSigHdrCount: resd 1
56 .ExtSigHdrChecksum: resd 1
57 .ExtSigHdrRsvd: resd 3
62 .ExtSigProcessor: resd 1
64 .ExtSigChecksum: resd 1
68 struc LoadMicrocodeParams
73 .MicrocodeCodeAddr: resd 1
74 .MicrocodeCodeSize: resd 1
75 .CodeRegionBase: resd 1
76 .CodeRegionSize: resd 1
81 struc LoadMicrocodeParamsFsp22
83 .FspUpdHeaderSignature: resd 2
84 .FspUpdHeaderRevision: resb 1
85 .FspUpdHeaderReserved: resb 23
88 .FsptArchRevision: resb 1
89 .FsptArchReserved: resb 3
93 .MicrocodeCodeAddr: resd 1
94 .MicrocodeCodeSize: resd 1
95 .CodeRegionBase: resd 1
96 .CodeRegionSize: resd 1
101 struc LoadMicrocodeParamsFsp24
103 .FspUpdHeaderSignature: resd 2
104 .FspUpdHeaderRevision: resb 1
105 .FspUpdHeaderReserved: resb 23
108 .FsptArchRevision: resb 1
109 .FsptArchReserved: resb 3
110 .FsptArchLength: resd 1
111 .FspDebugHandler resq 1
115 .MicrocodeCodeAddr: resq 1
116 .MicrocodeCodeSize: resq 1
117 .CodeRegionBase: resq 1
118 .CodeRegionSize: resq 1
127 ;args 1: ReturnAddress 2:MmxRegister
129 %macro LOAD_MMX_EXT 2
131 movd %2, esi ; save ReturnAddress into MMX
135 ;args 1: RoutineLabel 2:MmxRegister
137 %macro CALL_MMX_EXT 2
138 mov esi, %%ReturnAddress
139 movd %2, esi ; save ReturnAddress into MMX
148 movd esi, %1 ; move ReturnAddress from MMX to ESI
164 ; @todo: The strong/weak implementation does not work.
165 ; This needs to be reviewed later.
167 ;------------------------------------------------------------------------------
169 ;;global ASM_PFX(SecPlatformInitDefault)
170 ;ASM_PFX(SecPlatformInitDefault):
172 ; ; mm7 -> Return address
174 ; ; eax -> 0 - Successful, Non-zero - Failed.
176 ; ; eax is cleared and ebp is used for return address.
177 ; ; All others reserved.
179 ; ; Save return address to EBP
186 ;------------------------------------------------------------------------------
187 global ASM_PFX(LoadMicrocodeDefault)
188 ASM_PFX(LoadMicrocodeDefault):
190 ; esp -> LoadMicrocodeParams pointer
193 ; All others destroyed
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
200 ; Save return address to EBP
206 mov eax, dword [esp + 4] ; Parameter pointer
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
216 cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
221 ; UPD structure is compliant with FSP spec 2.0/2.1
222 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
228 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
234 ; UPD structure is compliant with FSP spec 2.2
235 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
241 mov esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
247 ; UPD structure is compliant with FSP spec 2.4
248 mov eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
254 mov esi, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
263 ; Get processor signature and platform ID from the installed processor
264 ; and save into registers for later use
265 ; ebx = processor signature
270 mov ecx, MSR_IA32_PLATFORM_ID
273 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
274 and ecx, 7h ; platform id at bit[52..50]
278 ; Current register usage
279 ; esp -> stack with parameters
280 ; esi -> microcode update to check
281 ; ebx = processor signature
284 ; Check for valid microcode header
285 ; Minimal test checking for header version and loader version as 1
287 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
289 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
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
298 LoadMicrocodeDefault1:
299 ; Check if extended header exists
300 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
302 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
304 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
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
313 ; Set edi -> extended header
315 add edi, MicrocodeHdr.size
316 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
318 ; Get count of extended structures
319 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
321 ; Move pointer to first signature structure
322 add edi, ExtSigHdr.size
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
336 ; Advance just after end of this microcode
338 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
339 je LoadMicrocodeDefault3
340 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
342 LoadMicrocodeDefault3:
347 ; Advance by 4X dwords
351 ; Check UPD header revision
352 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
354 cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
359 ; UPD structure is compliant with FSP spec 2.0/2.1
360 ; Is automatic size detection ?
361 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
363 jz LoadMicrocodeDefault4
365 ; Address >= microcode region address + microcode region size?
366 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
368 jae Done ;Jif address is outside of microcode region
372 ; UPD structure is compliant with FSP spec 2.2
373 ; Is automatic size detection ?
374 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
376 jz LoadMicrocodeDefault4
378 ; Address >= microcode region address + microcode region size?
379 add eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
381 jae Done ;Jif address is outside of microcode region
385 ; UPD structure is compliant with FSP spec 2.4
386 ; Is automatic size detection ?
387 mov eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
389 jz LoadMicrocodeDefault4
391 ; Address >= microcode region address + microcode region size?
392 add eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
394 jae Done ;Jif address is outside of microcode region
397 LoadMicrocodeDefault4:
398 ; Is valid Microcode start point ?
399 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
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
411 mov ecx, MSR_IA32_BIOS_SIGN_ID
412 rdmsr ; Get current microcode signature
414 ; Verify this microcode update is not already loaded
415 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
419 ; EAX contains the linear address of the start of the Update Data
421 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
422 ; Start microcode load with wrmsr
424 add eax, MicrocodeHdr.size
426 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
437 mov ecx, MSR_IA32_BIOS_SIGN_ID
438 rdmsr ; Get current microcode signature
448 global ASM_PFX(EstablishStackFsp)
449 ASM_PFX(EstablishStackFsp):
451 ; Save parameter pointer in edx
453 mov edx, dword [esp + 4]
458 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
459 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
461 push DATA_LEN_OF_MCUD ; Size of the data region
462 push 4455434Dh ; Signature of the data region 'MCUD'
464 ; check UPD structure revision (edx + 8)
465 cmp byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
467 cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
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
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
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
494 ContinueAfterUpdPush:
496 ; Save API entry/exit timestamp into stack
498 push DATA_LEN_OF_PER0 ; Size of the data region
499 push 30524550h ; Signature of the data region 'PER0'
509 ; Terminator for the data on stack
514 ; Set ECX/EDX to the BootLoader temporary memory range
516 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
518 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
519 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
521 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
522 jb EstablishStackFspSuccess
523 mov eax, 80000003h ;EFI_UNSUPPORTED
524 jmp EstablishStackFspExit
525 EstablishStackFspSuccess:
528 EstablishStackFspExit:
531 ;----------------------------------------------------------------------------
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.
538 ;----------------------------------------------------------------------------
539 global ASM_PFX(TempRamInitApi)
540 ASM_PFX(TempRamInitApi):
542 ; Ensure SSE is enabled
547 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
552 ; Save timestamp into XMM6
561 mov eax, dword [esp + 4]
569 CALL_MMX ASM_PFX(SecPlatformInit)
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.
581 CALL_MMX ASM_PFX(SecCarInit)
586 CALL_MMX ASM_PFX(EstablishStackFsp)
590 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
593 mov bl, al ; save al data in bl
594 mov al, 07Fh ; API exit postcode 7f
596 mov al, bl ; restore al data from bl
599 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
604 ;----------------------------------------------------------------------------
605 ; Module Entrypoint API
606 ;----------------------------------------------------------------------------
607 global ASM_PFX(_ModuleEntryPoint)
608 ASM_PFX(_ModuleEntryPoint):