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 ; rsp -> 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
133 mov eax, dword [rsp + 8] ; Parameter pointer
138 ; skip loading Microcode if the MicrocodeCodeSize is zero
139 ; and report error if size is less than 2k
140 ; first check UPD header revision
141 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
143 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
146 ; UPD structure is compliant with FSP spec 2.4
147 mov eax, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
153 mov esi, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
158 mov rax, 08000000000000002h
162 ; Get processor signature and platform ID from the installed processor
163 ; and save into registers for later use
164 ; ebx = processor signature
169 mov ecx, MSR_IA32_PLATFORM_ID
172 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
173 and ecx, 7h ; platform id at bit[52..50]
177 ; Current register usage
178 ; esp -> stack with parameters
179 ; esi -> microcode update to check
180 ; ebx = processor signature
183 ; Check for valid microcode header
184 ; Minimal test checking for header version and loader version as 1
186 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
188 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
191 ; Check if signature and plaform ID match
192 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
193 jne LoadMicrocodeDefault1
194 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
195 jnz LoadCheck ; Jif signature and platform ID match
197 LoadMicrocodeDefault1:
198 ; Check if extended header exists
199 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
201 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
203 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
206 ; Then verify total size - sizeof header > data size
207 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
208 sub ecx, MicrocodeHdr.size
209 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
210 jng NextMicrocode ; Jif extended header does not exist
212 ; Set edi -> extended header
214 add edi, MicrocodeHdr.size
215 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
217 ; Get count of extended structures
218 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
220 ; Move pointer to first signature structure
221 add edi, ExtSigHdr.size
224 ; Check if extended signature and platform ID match
225 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
226 jne LoadMicrocodeDefault2
227 test dword [edi + ExtSig.ExtSigFlags], edx
228 jnz LoadCheck ; Jif signature and platform ID match
229 LoadMicrocodeDefault2:
230 ; Check if any more extended signatures exist
235 ; Advance just after end of this microcode
237 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
238 je LoadMicrocodeDefault3
239 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
241 LoadMicrocodeDefault3:
246 ; Advance by 4X dwords
250 ; Check UPD header revision
251 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
253 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
256 ; UPD structure is compliant with FSP spec 2.4
257 ; Is automatic size detection ?
258 mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
259 cmp rax, 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
324 mov rdx, qword [rsp + 8]
329 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
331 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
335 mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region
337 mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'
339 ; check UPD structure revision (rdx + 8)
340 cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
342 cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
346 mov rax, 08000000000000002h
347 jmp EstablishStackFspExit
350 ; UPD structure is compliant with FSP spec 2.4
352 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h
355 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h
358 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h
361 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h
365 ContinueAfterUpdPush:
367 ; Save API entry/exit timestamp into stack
370 mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region
372 mov dword[esp], 30524550h ; Signature of the data region 'PER0'
382 ; Terminator for the data on stack
387 ; Set ECX/EDX to the BootLoader temporary memory range
389 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
391 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
393 mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
395 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
398 cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
399 jb EstablishStackFspSuccess
400 mov rax, 08000000000000003h ; EFI_UNSUPPORTED
401 jmp EstablishStackFspExit
402 EstablishStackFspSuccess:
405 EstablishStackFspExit:
408 ;----------------------------------------------------------------------------
411 ; This FSP API will load the microcode update, enable code caching for the
412 ; region specified by the boot loader and also setup a temporary stack to be
413 ; used till main memory is initialized.
415 ;----------------------------------------------------------------------------
416 global ASM_PFX(TempRamInitApi)
417 ASM_PFX(TempRamInitApi):
419 ; Ensure both SSE and AVX are enabled
425 ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6
430 ; Save BFV address in YMM9
435 ; Save timestamp into YMM6
445 mov rax, qword [rsp + 8]
447 mov rax, 08000000000000002h
453 CALL_YMM ASM_PFX(SecPlatformInit)
459 CALL_YMM ASM_PFX(LoadMicrocodeDefault)
460 SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).
461 ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.
465 CALL_YMM ASM_PFX(SecCarInit)
470 CALL_YMM ASM_PFX(EstablishStackFsp)
474 LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).
477 mov bl, al ; save al data in bl
478 mov al, 07Fh ; API exit postcode 7f
480 mov al, bl ; restore al data from bl
483 ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6
489 ;----------------------------------------------------------------------------
490 ; Module Entrypoint API
491 ;----------------------------------------------------------------------------
492 global ASM_PFX(_ModuleEntryPoint)
493 ASM_PFX(_ModuleEntryPoint):