2 ; Provide FSP API entry points.
4 ; Copyright (c) 2016 - 2020, 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
91 .MicrocodeCodeAddr: resd 1
92 .MicrocodeCodeSize: resd 1
93 .CodeRegionBase: resd 1
94 .CodeRegionSize: resd 1
103 ;args 1: ReturnAddress 2:MmxRegister
105 %macro LOAD_MMX_EXT 2
107 movd %2, esi ; save ReturnAddress into MMX
111 ;args 1: RoutineLabel 2:MmxRegister
113 %macro CALL_MMX_EXT 2
114 mov esi, %%ReturnAddress
115 movd %2, esi ; save ReturnAddress into MMX
124 movd esi, %1 ; move ReturnAddress from MMX to ESI
140 ; @todo: The strong/weak implementation does not work.
141 ; This needs to be reviewed later.
143 ;------------------------------------------------------------------------------
145 ;;global ASM_PFX(SecPlatformInitDefault)
146 ;ASM_PFX(SecPlatformInitDefault):
148 ; ; mm7 -> Return address
150 ; ; eax -> 0 - Successful, Non-zero - Failed.
152 ; ; eax is cleared and ebp is used for return address.
153 ; ; All others reserved.
155 ; ; Save return address to EBP
162 ;------------------------------------------------------------------------------
163 global ASM_PFX(LoadMicrocodeDefault)
164 ASM_PFX(LoadMicrocodeDefault):
166 ; esp -> LoadMicrocodeParams pointer
169 ; All others destroyed
171 ; No memory available, stack is hard-coded and used for return address
172 ; Executed by SBSP and NBSP
173 ; Beginning of microcode update region starts on paragraph boundary
177 ; Save return address to EBP
182 mov eax, dword [esp + 4] ; Parameter pointer
187 ; skip loading Microcode if the MicrocodeCodeSize is zero
188 ; and report error if size is less than 2k
189 ; first check UPD header revision
190 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
193 ; UPD structure is compliant with FSP spec 2.0/2.1
194 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
200 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
206 ; UPD structure is compliant with FSP spec 2.2
207 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
213 mov esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
222 ; Get processor signature and platform ID from the installed processor
223 ; and save into registers for later use
224 ; ebx = processor signature
229 mov ecx, MSR_IA32_PLATFORM_ID
232 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
233 and ecx, 7h ; platform id at bit[52..50]
237 ; Current register usage
238 ; esp -> stack with parameters
239 ; esi -> microcode update to check
240 ; ebx = processor signature
243 ; Check for valid microcode header
244 ; Minimal test checking for header version and loader version as 1
246 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
248 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
251 ; Check if signature and plaform ID match
252 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
253 jne LoadMicrocodeDefault1
254 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
255 jnz LoadCheck ; Jif signature and platform ID match
257 LoadMicrocodeDefault1:
258 ; Check if extended header exists
259 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
261 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
263 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
266 ; Then verify total size - sizeof header > data size
267 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
268 sub ecx, MicrocodeHdr.size
269 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
270 jng NextMicrocode ; Jif extended header does not exist
272 ; Set edi -> extended header
274 add edi, MicrocodeHdr.size
275 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
277 ; Get count of extended structures
278 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
280 ; Move pointer to first signature structure
281 add edi, ExtSigHdr.size
284 ; Check if extended signature and platform ID match
285 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
286 jne LoadMicrocodeDefault2
287 test dword [edi + ExtSig.ExtSigFlags], edx
288 jnz LoadCheck ; Jif signature and platform ID match
289 LoadMicrocodeDefault2:
290 ; Check if any more extended signatures exist
295 ; Advance just after end of this microcode
297 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
298 je LoadMicrocodeDefault3
299 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
301 LoadMicrocodeDefault3:
306 ; Advance by 4X dwords
310 ; Check UPD header revision
311 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
314 ; UPD structure is compliant with FSP spec 2.0/2.1
315 ; Is automatic size detection ?
316 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
318 jz LoadMicrocodeDefault4
320 ; Address >= microcode region address + microcode region size?
321 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
323 jae Done ;Jif address is outside of microcode region
327 ; UPD structure is compliant with FSP spec 2.2
328 ; Is automatic size detection ?
329 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
331 jz LoadMicrocodeDefault4
333 ; Address >= microcode region address + microcode region size?
334 add eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
336 jae Done ;Jif address is outside of microcode region
339 LoadMicrocodeDefault4:
340 ; Is valid Microcode start point ?
341 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
345 ; Get the revision of the current microcode update loaded
346 mov ecx, MSR_IA32_BIOS_SIGN_ID
347 xor eax, eax ; Clear EAX
348 xor edx, edx ; Clear EDX
349 wrmsr ; Load 0 to MSR at 8Bh
353 mov ecx, MSR_IA32_BIOS_SIGN_ID
354 rdmsr ; Get current microcode signature
356 ; Verify this microcode update is not already loaded
357 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
361 ; EAX contains the linear address of the start of the Update Data
363 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
364 ; Start microcode load with wrmsr
366 add eax, MicrocodeHdr.size
368 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
379 mov ecx, MSR_IA32_BIOS_SIGN_ID
380 rdmsr ; Get current microcode signature
390 global ASM_PFX(EstablishStackFsp)
391 ASM_PFX(EstablishStackFsp):
393 ; Save parameter pointer in edx
395 mov edx, dword [esp + 4]
400 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
401 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
403 push DATA_LEN_OF_MCUD ; Size of the data region
404 push 4455434Dh ; Signature of the data region 'MCUD'
406 ; check UPD structure revision (edx + 8)
407 cmp byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
410 ; UPD structure is compliant with FSP spec 2.0/2.1
411 push dword [edx + LoadMicrocodeParams.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
412 push dword [edx + LoadMicrocodeParams.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
413 push dword [edx + LoadMicrocodeParams.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
414 push dword [edx + LoadMicrocodeParams.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
415 jmp ContinueAfterUpdPush
418 ; UPD structure is compliant with FSP spec 2.2
419 push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
420 push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
421 push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
422 push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
424 ContinueAfterUpdPush:
426 ; Save API entry/exit timestamp into stack
428 push DATA_LEN_OF_PER0 ; Size of the data region
429 push 30524550h ; Signature of the data region 'PER0'
439 ; Terminator for the data on stack
444 ; Set ECX/EDX to the BootLoader temporary memory range
446 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
448 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
449 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
451 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
452 jb EstablishStackFspSuccess
453 mov eax, 80000003h ;EFI_UNSUPPORTED
454 jmp EstablishStackFspExit
455 EstablishStackFspSuccess:
458 EstablishStackFspExit:
461 ;----------------------------------------------------------------------------
464 ; This FSP API will load the microcode update, enable code caching for the
465 ; region specified by the boot loader and also setup a temporary stack to be
466 ; used till main memory is initialized.
468 ;----------------------------------------------------------------------------
469 global ASM_PFX(TempRamInitApi)
470 ASM_PFX(TempRamInitApi):
472 ; Ensure SSE is enabled
477 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
482 ; Save timestamp into XMM6
491 mov eax, dword [esp + 4]
499 CALL_MMX ASM_PFX(SecPlatformInit)
505 CALL_MMX ASM_PFX(LoadMicrocodeDefault)
506 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
507 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
511 CALL_MMX ASM_PFX(SecCarInit)
516 CALL_MMX ASM_PFX(EstablishStackFsp)
520 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
523 mov bl, al ; save al data in bl
524 mov al, 07Fh ; API exit postcode 7f
526 mov al, bl ; restore al data from bl
529 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
534 ;----------------------------------------------------------------------------
535 ; Module Entrypoint API
536 ;----------------------------------------------------------------------------
537 global ASM_PFX(_ModuleEntryPoint)
538 ASM_PFX(_ModuleEntryPoint):