2 ; Provide FSP API entry points.
4 ; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
5 ; SPDX-License-Identifier: BSD-2-Clause-Patent
10 %include "SaveRestoreSseAvxNasm.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 LoadMicrocodeParamsFsp24
70 .FspUpdHeaderSignature: resd 2
71 .FspUpdHeaderRevision: resb 1
72 .FspUpdHeaderReserved: resb 23
75 .FsptArchRevision: resb 1
76 .FsptArchReserved: resb 3
77 .FsptArchLength: resd 1
78 .FspDebugHandler resq 1
82 .MicrocodeCodeAddr: resq 1
83 .MicrocodeCodeSize: resq 1
84 .CodeRegionBase: resq 1
85 .CodeRegionSize: resq 1
91 ; @todo: The strong/weak implementation does not work.
92 ; This needs to be reviewed later.
94 ;------------------------------------------------------------------------------
96 ;;global ASM_PFX(SecPlatformInitDefault)
97 ;ASM_PFX(SecPlatformInitDefault):
99 ; ; ymm7 -> Return address
101 ; ; rax -> 0 - Successful, Non-zero - Failed.
103 ; ; rax is cleared and rbp is used for return address.
104 ; ; All others reserved.
106 ; ; Save return address to RBP
113 ;------------------------------------------------------------------------------
114 global ASM_PFX(LoadMicrocodeDefault)
115 ASM_PFX(LoadMicrocodeDefault):
117 ; rcx -> LoadMicrocodeParams pointer
120 ; All others destroyed
122 ; No memory available, stack is hard-coded and used for return address
123 ; Executed by SBSP and NBSP
124 ; Beginning of microcode update region starts on paragraph boundary
127 ; Save return address to RBP
137 ; skip loading Microcode if the MicrocodeCodeSize is zero
138 ; and report error if size is less than 2k
139 ; first check UPD header revision
140 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
142 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
145 ; UPD structure is compliant with FSP spec 2.4
146 mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
152 mov rsi, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
157 mov rax, 08000000000000002h
161 ; Get processor signature and platform ID from the installed processor
162 ; and save into registers for later use
163 ; ebx = processor signature
168 mov ecx, MSR_IA32_PLATFORM_ID
171 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
172 and ecx, 7h ; platform id at bit[52..50]
176 ; Current register usage
177 ; esp -> stack with parameters
178 ; esi -> microcode update to check
179 ; ebx = processor signature
182 ; Check for valid microcode header
183 ; Minimal test checking for header version and loader version as 1
185 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
187 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
190 ; Check if signature and plaform ID match
191 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
192 jne LoadMicrocodeDefault1
193 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
194 jnz LoadCheck ; Jif signature and platform ID match
196 LoadMicrocodeDefault1:
197 ; Check if extended header exists
198 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
200 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
202 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
205 ; Then verify total size - sizeof header > data size
206 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
207 sub ecx, MicrocodeHdr.size
208 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
209 jng NextMicrocode ; Jif extended header does not exist
211 ; Set edi -> extended header
213 add edi, MicrocodeHdr.size
214 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
216 ; Get count of extended structures
217 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
219 ; Move pointer to first signature structure
220 add edi, ExtSigHdr.size
223 ; Check if extended signature and platform ID match
224 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
225 jne LoadMicrocodeDefault2
226 test dword [edi + ExtSig.ExtSigFlags], edx
227 jnz LoadCheck ; Jif signature and platform ID match
228 LoadMicrocodeDefault2:
229 ; Check if any more extended signatures exist
234 ; Advance just after end of this microcode
236 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
237 je LoadMicrocodeDefault3
238 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
240 LoadMicrocodeDefault3:
245 ; Advance by 4X dwords
249 ; Check UPD header revision
250 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
252 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
255 ; UPD structure is compliant with FSP spec 2.4
256 ; Is automatic size detection ?
257 mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
258 mov rcx, 0ffffffffffffffffh
260 jz LoadMicrocodeDefault4
262 ; Address >= microcode region address + microcode region size?
263 add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
265 jae Done ;Jif address is outside of microcode region
268 LoadMicrocodeDefault4:
269 ; Is valid Microcode start point ?
270 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
274 ; Get the revision of the current microcode update loaded
275 mov ecx, MSR_IA32_BIOS_SIGN_ID
276 xor eax, eax ; Clear EAX
277 xor edx, edx ; Clear EDX
278 wrmsr ; Load 0 to MSR at 8Bh
282 mov ecx, MSR_IA32_BIOS_SIGN_ID
283 rdmsr ; Get current microcode signature
285 ; Verify this microcode update is not already loaded
286 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
290 ; EAX contains the linear address of the start of the Update Data
292 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
293 ; Start microcode load with wrmsr
295 add eax, MicrocodeHdr.size
297 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
308 mov ecx, MSR_IA32_BIOS_SIGN_ID
309 rdmsr ; Get current microcode signature
313 mov eax, 0800000000000000Eh
319 global ASM_PFX(EstablishStackFsp)
320 ASM_PFX(EstablishStackFsp):
322 ; Save parameter pointer in rdx
328 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
330 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
334 mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region
336 mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'
338 ; check UPD structure revision (rdx + 8)
339 cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
341 cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
345 mov rax, 08000000000000002h
346 jmp EstablishStackFspExit
349 ; UPD structure is compliant with FSP spec 2.4
351 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h
354 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h
357 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h
360 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h
364 ContinueAfterUpdPush:
366 ; Save API entry/exit timestamp into stack
369 mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region
371 mov dword[esp], 30524550h ; Signature of the data region 'PER0'
381 ; Terminator for the data on stack
386 ; Set ECX/EDX to the BootLoader temporary memory range
388 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
390 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
392 mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
394 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
397 cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
398 jb EstablishStackFspSuccess
399 mov rax, 08000000000000003h ; EFI_UNSUPPORTED
400 jmp EstablishStackFspExit
401 EstablishStackFspSuccess:
404 EstablishStackFspExit:
407 ;----------------------------------------------------------------------------
410 ; This FSP API will load the microcode update, enable code caching for the
411 ; region specified by the boot loader and also setup a temporary stack to be
412 ; used till main memory is initialized.
414 ;----------------------------------------------------------------------------
415 global ASM_PFX(TempRamInitApi)
416 ASM_PFX(TempRamInitApi):
418 ; Ensure both SSE and AVX are enabled
423 ; Save Input Parameter in YMM10
427 ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6
432 ; Save BFV address in YMM9
437 ; Save timestamp into YMM6
448 mov rcx, 08000000000000002h
454 CALL_YMM ASM_PFX(SecPlatformInit)
460 CALL_YMM ASM_PFX(LoadMicrocodeDefault)
461 SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).
462 ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.
466 CALL_YMM ASM_PFX(SecCarInit)
471 CALL_YMM ASM_PFX(EstablishStackFsp)
475 LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).
478 mov bl, al ; save al data in bl
479 mov al, 07Fh ; API exit postcode 7f
481 mov al, bl ; restore al data from bl
484 ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6
490 ;----------------------------------------------------------------------------
491 ; Module Entrypoint API
492 ;----------------------------------------------------------------------------
493 global ASM_PFX(_ModuleEntryPoint)
494 ASM_PFX(_ModuleEntryPoint):