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(AsmGetFspInfoHeaderNoStack)
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
165 mov edi, %%ReturnAddress
172 mov ebp, %%ReturnAddress
178 jmp ebp ; restore EIP from EBP
182 ; Load UPD region pointer in ECX
184 global ASM_PFX(LoadUpdPointerToECX)
185 ASM_PFX(LoadUpdPointerToECX):
187 ; esp + 4 is input UPD parameter
188 ; If esp + 4 is NULL the default UPD should be used
189 ; ecx will be the UPD region that should be used
191 mov ecx, dword [esp + 4]
196 ; Fall back to default UPD region
198 CALL_EDI ASM_PFX(AsmGetFspInfoHeaderNoStack)
199 mov ecx, DWORD [eax + 01Ch] ; Read FsptImageBaseAddress
200 add ecx, DWORD [eax + 024h] ; Get Cfg Region base address = FsptImageBaseAddress + CfgRegionOffset
205 ; @todo: The strong/weak implementation does not work.
206 ; This needs to be reviewed later.
208 ;------------------------------------------------------------------------------
210 ;;global ASM_PFX(SecPlatformInitDefault)
211 ;ASM_PFX(SecPlatformInitDefault):
213 ; ; mm7 -> Return address
215 ; ; eax -> 0 - Successful, Non-zero - Failed.
217 ; ; eax is cleared and ebp is used for return address.
218 ; ; All others reserved.
220 ; ; Save return address to EBP
227 ;------------------------------------------------------------------------------
228 global ASM_PFX(LoadMicrocodeDefault)
229 ASM_PFX(LoadMicrocodeDefault):
231 ; ecx -> UPD region contains LoadMicrocodeParams pointer
235 ; No memory available, stack is hard-coded and used for return address
236 ; Executed by SBSP and NBSP
237 ; Beginning of microcode update region starts on paragraph boundary
240 ; Save return address to EBP
244 mov esp, ecx ; ECX has been assigned to UPD region
248 ; skip loading Microcode if the MicrocodeCodeSize is zero
249 ; and report error if size is less than 2k
250 ; first check UPD header revision
251 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
253 cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
258 ; UPD structure is compliant with FSP spec 2.0/2.1
259 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
265 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
271 ; UPD structure is compliant with FSP spec 2.2
272 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
278 mov esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
284 ; UPD structure is compliant with FSP spec 2.4
285 mov eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
291 mov esi, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
300 ; Get processor signature and platform ID from the installed processor
301 ; and save into registers for later use
302 ; ebx = processor signature
307 mov ecx, MSR_IA32_PLATFORM_ID
310 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
311 and ecx, 7h ; platform id at bit[52..50]
315 ; Current register usage
316 ; esp -> stack with parameters
317 ; esi -> microcode update to check
318 ; ebx = processor signature
321 ; Check for valid microcode header
322 ; Minimal test checking for header version and loader version as 1
324 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
326 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
329 ; Check if signature and plaform ID match
330 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
331 jne LoadMicrocodeDefault1
332 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
333 jnz LoadCheck ; Jif signature and platform ID match
335 LoadMicrocodeDefault1:
336 ; Check if extended header exists
337 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
339 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
341 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
344 ; Then verify total size - sizeof header > data size
345 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
346 sub ecx, MicrocodeHdr.size
347 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
348 jng NextMicrocode ; Jif extended header does not exist
350 ; Set edi -> extended header
352 add edi, MicrocodeHdr.size
353 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
355 ; Get count of extended structures
356 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
358 ; Move pointer to first signature structure
359 add edi, ExtSigHdr.size
362 ; Check if extended signature and platform ID match
363 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
364 jne LoadMicrocodeDefault2
365 test dword [edi + ExtSig.ExtSigFlags], edx
366 jnz LoadCheck ; Jif signature and platform ID match
367 LoadMicrocodeDefault2:
368 ; Check if any more extended signatures exist
373 ; Advance just after end of this microcode
375 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
376 je LoadMicrocodeDefault3
377 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
379 LoadMicrocodeDefault3:
384 ; Advance by 4X dwords
388 ; Check UPD header revision
389 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
391 cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
396 ; UPD structure is compliant with FSP spec 2.0/2.1
397 ; Is automatic size detection ?
398 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
400 jz LoadMicrocodeDefault4
402 ; Address >= microcode region address + microcode region size?
403 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
405 jae Done ;Jif address is outside of microcode region
409 ; UPD structure is compliant with FSP spec 2.2
410 ; Is automatic size detection ?
411 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
413 jz LoadMicrocodeDefault4
415 ; Address >= microcode region address + microcode region size?
416 add eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
418 jae Done ;Jif address is outside of microcode region
422 ; UPD structure is compliant with FSP spec 2.4
423 ; Is automatic size detection ?
424 mov eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
426 jz LoadMicrocodeDefault4
428 ; Address >= microcode region address + microcode region size?
429 add eax, dword [esp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
431 jae Done ;Jif address is outside of microcode region
434 LoadMicrocodeDefault4:
435 ; Is valid Microcode start point ?
436 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
440 ; Get the revision of the current microcode update loaded
441 mov ecx, MSR_IA32_BIOS_SIGN_ID
442 xor eax, eax ; Clear EAX
443 xor edx, edx ; Clear EDX
444 wrmsr ; Load 0 to MSR at 8Bh
448 mov ecx, MSR_IA32_BIOS_SIGN_ID
449 rdmsr ; Get current microcode signature
451 ; Verify this microcode update is not already loaded
452 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
456 ; EAX contains the linear address of the start of the Update Data
458 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
459 ; Start microcode load with wrmsr
461 add eax, MicrocodeHdr.size
463 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
474 mov ecx, MSR_IA32_BIOS_SIGN_ID
475 rdmsr ; Get current microcode signature
485 ; EstablishStackFsp: EDI should be preserved cross this function
487 global ASM_PFX(EstablishStackFsp)
488 ASM_PFX(EstablishStackFsp):
490 ; Save parameter pointer in edx
492 mov edx, ecx ; ECX has been assigned to UPD region
497 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
498 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
500 push DATA_LEN_OF_MCUD ; Size of the data region
501 push 4455434Dh ; Signature of the data region 'MCUD'
503 ; check UPD structure revision (edx + 8)
504 cmp byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
506 cmp byte [esp + LoadMicrocodeParamsFsp22.FsptArchRevision], 2
511 ; UPD structure is compliant with FSP spec 2.0/2.1
512 push dword [edx + LoadMicrocodeParams.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
513 push dword [edx + LoadMicrocodeParams.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
514 push dword [edx + LoadMicrocodeParams.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
515 push dword [edx + LoadMicrocodeParams.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
516 jmp ContinueAfterUpdPush
519 ; UPD structure is compliant with FSP spec 2.2
520 push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
521 push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
522 push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
523 push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
524 jmp ContinueAfterUpdPush
527 ; UPD structure is compliant with FSP spec 2.4
528 push dword [edx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 24
529 push dword [edx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 16
530 push dword [edx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8
531 push dword [edx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
533 ContinueAfterUpdPush:
535 ; Save API entry/exit timestamp into stack
537 push DATA_LEN_OF_PER0 ; Size of the data region
538 push 30524550h ; Signature of the data region 'PER0'
548 ; Terminator for the data on stack
553 ; Set ECX/EDX to the BootLoader temporary memory range
555 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
557 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
558 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
560 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
561 jb EstablishStackFspSuccess
562 mov eax, 80000003h ;EFI_UNSUPPORTED
563 jmp EstablishStackFspExit
564 EstablishStackFspSuccess:
567 EstablishStackFspExit:
570 ;----------------------------------------------------------------------------
573 ; This FSP API will load the microcode update, enable code caching for the
574 ; region specified by the boot loader and also setup a temporary stack to be
575 ; used till main memory is initialized.
577 ;----------------------------------------------------------------------------
578 global ASM_PFX(TempRamInitApi)
579 ASM_PFX(TempRamInitApi):
581 ; Ensure SSE is enabled
586 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
591 ; Save timestamp into XMM6
597 CALL_EBP ASM_PFX(LoadUpdPointerToECX) ; ECX for UPD param
598 SAVE_ECX ; save UPD param to slot 3 in xmm6
603 CALL_MMX ASM_PFX(SecPlatformInit)
610 CALL_MMX ASM_PFX(LoadMicrocodeDefault)
611 SAVE_UCODE_STATUS ; Save microcode return status in slot 1 in xmm5.
612 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
617 CALL_MMX ASM_PFX(SecCarInit)
623 mov edi, ecx ; Save UPD param to EDI for later code use
624 CALL_MMX ASM_PFX(EstablishStackFsp)
628 LOAD_UCODE_STATUS ; Restore microcode status if no CAR init error from slot 1 in xmm5.
631 mov bl, al ; save al data in bl
632 mov al, 07Fh ; API exit postcode 7f
634 mov al, bl ; restore al data from bl
637 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
642 ;----------------------------------------------------------------------------
643 ; Module Entrypoint API
644 ;----------------------------------------------------------------------------
645 global ASM_PFX(_ModuleEntryPoint)
646 ASM_PFX(_ModuleEntryPoint):