2 ; Provide FSP API entry points.
4 ; Copyright (c) 2016, 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
86 ;args 1: ReturnAddress 2:MmxRegister
90 movd %2, esi ; save ReturnAddress into MMX
94 ;args 1: RoutineLabel 2:MmxRegister
97 mov esi, %%ReturnAddress
98 movd %2, esi ; save ReturnAddress into MMX
107 movd esi, %1 ; move ReturnAddress from MMX to ESI
123 ; @todo: The strong/weak implementation does not work.
124 ; This needs to be reviewed later.
126 ;------------------------------------------------------------------------------
128 ;;global ASM_PFX(SecPlatformInitDefault)
129 ;ASM_PFX(SecPlatformInitDefault):
131 ; ; mm7 -> Return address
133 ; ; eax -> 0 - Successful, Non-zero - Failed.
135 ; ; eax is cleared and ebp is used for return address.
136 ; ; All others reserved.
138 ; ; Save return address to EBP
145 ;------------------------------------------------------------------------------
146 global ASM_PFX(LoadMicrocodeDefault)
147 ASM_PFX(LoadMicrocodeDefault):
149 ; esp -> LoadMicrocodeParams pointer
152 ; All others destroyed
154 ; No memory available, stack is hard-coded and used for return address
155 ; Executed by SBSP and NBSP
156 ; Beginning of microcode update region starts on paragraph boundary
160 ; Save return address to EBP
165 mov eax, dword [esp + 4] ; Parameter pointer
170 ; skip loading Microcode if the MicrocodeCodeSize is zero
171 ; and report error if size is less than 2k
172 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
178 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
187 ; Get processor signature and platform ID from the installed processor
188 ; and save into registers for later use
189 ; ebx = processor signature
194 mov ecx, MSR_IA32_PLATFORM_ID
197 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
198 and ecx, 7h ; platform id at bit[52..50]
202 ; Current register usage
203 ; esp -> stack with parameters
204 ; esi -> microcode update to check
205 ; ebx = processor signature
208 ; Check for valid microcode header
209 ; Minimal test checking for header version and loader version as 1
211 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
213 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
216 ; Check if signature and plaform ID match
217 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
218 jne LoadMicrocodeDefault1
219 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
220 jnz LoadCheck ; Jif signature and platform ID match
222 LoadMicrocodeDefault1:
223 ; Check if extended header exists
224 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
226 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
228 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
231 ; Then verify total size - sizeof header > data size
232 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
233 sub ecx, MicrocodeHdr.size
234 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
235 jng NextMicrocode ; Jif extended header does not exist
237 ; Set edi -> extended header
239 add edi, MicrocodeHdr.size
240 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
242 ; Get count of extended structures
243 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
245 ; Move pointer to first signature structure
246 add edi, ExtSigHdr.size
249 ; Check if extended signature and platform ID match
250 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
251 jne LoadMicrocodeDefault2
252 test dword [edi + ExtSig.ExtSigFlags], edx
253 jnz LoadCheck ; Jif signature and platform ID match
254 LoadMicrocodeDefault2:
255 ; Check if any more extended signatures exist
260 ; Advance just after end of this microcode
262 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
263 je LoadMicrocodeDefault3
264 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
266 LoadMicrocodeDefault3:
271 ; Advance by 4X dwords
275 ; Is valid Microcode start point ?
276 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
279 ; Is automatic size detection ?
280 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
282 jz LoadMicrocodeDefault4
284 ; Address >= microcode region address + microcode region size?
285 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
287 jae Done ;Jif address is outside of microcode region
290 LoadMicrocodeDefault4:
292 ; Get the revision of the current microcode update loaded
293 mov ecx, MSR_IA32_BIOS_SIGN_ID
294 xor eax, eax ; Clear EAX
295 xor edx, edx ; Clear EDX
296 wrmsr ; Load 0 to MSR at 8Bh
300 mov ecx, MSR_IA32_BIOS_SIGN_ID
301 rdmsr ; Get current microcode signature
303 ; Verify this microcode update is not already loaded
304 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
308 ; EAX contains the linear address of the start of the Update Data
310 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
311 ; Start microcode load with wrmsr
313 add eax, MicrocodeHdr.size
315 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
326 mov ecx, MSR_IA32_BIOS_SIGN_ID
327 rdmsr ; Get current microcode signature
337 global ASM_PFX(EstablishStackFsp)
338 ASM_PFX(EstablishStackFsp):
340 ; Save parameter pointer in edx
342 mov edx, dword [esp + 4]
347 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
348 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
350 push DATA_LEN_OF_MCUD ; Size of the data region
351 push 4455434Dh ; Signature of the data region 'MCUD'
352 push dword [edx + 2Ch] ; Code size sizeof(FSPT_UPD_COMMON) + 12
353 push dword [edx + 28h] ; Code base sizeof(FSPT_UPD_COMMON) + 8
354 push dword [edx + 24h] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
355 push dword [edx + 20h] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
358 ; Save API entry/exit timestamp into stack
360 push DATA_LEN_OF_PER0 ; Size of the data region
361 push 30524550h ; Signature of the data region 'PER0'
371 ; Terminator for the data on stack
376 ; Set ECX/EDX to the BootLoader temporary memory range
378 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
380 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
381 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
383 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
384 jb EstablishStackFspSuccess
385 mov eax, 80000003h ;EFI_UNSUPPORTED
386 jmp EstablishStackFspExit
387 EstablishStackFspSuccess:
390 EstablishStackFspExit:
393 ;----------------------------------------------------------------------------
396 ; This FSP API will load the microcode update, enable code caching for the
397 ; region specified by the boot loader and also setup a temporary stack to be
398 ; used till main memory is initialized.
400 ;----------------------------------------------------------------------------
401 global ASM_PFX(TempRamInitApi)
402 ASM_PFX(TempRamInitApi):
404 ; Ensure SSE is enabled
409 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
414 ; Save timestamp into XMM6
423 mov eax, dword [esp + 4]
431 CALL_MMX ASM_PFX(SecPlatformInit)
437 CALL_MMX ASM_PFX(LoadMicrocodeDefault)
438 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
439 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
443 CALL_MMX ASM_PFX(SecCarInit)
448 CALL_MMX ASM_PFX(EstablishStackFsp)
452 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
455 mov bl, al ; save al data in bl
456 mov al, 07Fh ; API exit postcode 7f
458 mov al, bl ; restore al data from bl
461 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
466 ;----------------------------------------------------------------------------
467 ; Module Entrypoint API
468 ;----------------------------------------------------------------------------
469 global ASM_PFX(_ModuleEntryPoint)
470 ASM_PFX(_ModuleEntryPoint):