2 ; Provide FSP API entry points.
4 ; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 ; This program and the accompanying materials
6 ; are licensed and made available under the terms and conditions of the BSD License
7 ; which accompanies this distribution. The full text of the license may be found at
8 ; http://opensource.org/licenses/bsd-license.php.
10 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 %include "SaveRestoreSseNasm.inc"
17 %include "MicrocodeLoadNasm.inc"
20 ; Following are fixed PCDs
22 extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
23 extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
24 extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
27 ; Following functions will be provided in PlatformSecLib
29 extern ASM_PFX(AsmGetFspBaseAddress)
30 extern ASM_PFX(AsmGetFspInfoHeader)
31 ;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation
32 extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation
33 extern ASM_PFX(SecCarInit)
36 ; Define the data length that we saved on the stack top
38 DATA_LEN_OF_PER0 EQU 18h
39 DATA_LEN_OF_MCUD EQU 18h
40 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
43 ; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
44 ; build error. This needs to be fixed later on.
47 .MicrocodeHdrVersion: resd 1
48 .MicrocodeHdrRevision: resd 1
49 .MicrocodeHdrDate: resd 1
50 .MicrocodeHdrProcessor: resd 1
51 .MicrocodeHdrChecksum: resd 1
52 .MicrocodeHdrLoader: resd 1
53 .MicrocodeHdrFlags: resd 1
54 .MicrocodeHdrDataSize: resd 1
55 .MicrocodeHdrTotalSize: resd 1
56 .MicrocodeHdrRsvd: resd 3
61 .ExtSigHdrCount: resd 1
62 .ExtSigHdrChecksum: resd 1
63 .ExtSigHdrRsvd: resd 3
68 .ExtSigProcessor: resd 1
70 .ExtSigChecksum: resd 1
74 struc LoadMicrocodeParams
79 .MicrocodeCodeAddr: resd 1
80 .MicrocodeCodeSize: resd 1
81 .CodeRegionBase: resd 1
82 .CodeRegionSize: resd 1
92 ;args 1: ReturnAddress 2:MmxRegister
96 movd %2, esi ; save ReturnAddress into MMX
100 ;args 1: RoutineLabel 2:MmxRegister
102 %macro CALL_MMX_EXT 2
103 mov esi, %%ReturnAddress
104 movd %2, esi ; save ReturnAddress into MMX
113 movd esi, %1 ; move ReturnAddress from MMX to ESI
129 ; @todo: The strong/weak implementation does not work.
130 ; This needs to be reviewed later.
132 ;------------------------------------------------------------------------------
134 ;;global ASM_PFX(SecPlatformInitDefault)
135 ;ASM_PFX(SecPlatformInitDefault):
137 ; ; mm7 -> Return address
139 ; ; eax -> 0 - Successful, Non-zero - Failed.
141 ; ; eax is cleared and ebp is used for return address.
142 ; ; All others reserved.
144 ; ; Save return address to EBP
151 ;------------------------------------------------------------------------------
152 global ASM_PFX(LoadMicrocodeDefault)
153 ASM_PFX(LoadMicrocodeDefault):
155 ; esp -> LoadMicrocodeParams pointer
158 ; All others destroyed
160 ; No memory available, stack is hard-coded and used for return address
161 ; Executed by SBSP and NBSP
162 ; Beginning of microcode update region starts on paragraph boundary
166 ; Save return address to EBP
171 mov eax, dword [esp + 4] ; Parameter pointer
176 ; skip loading Microcode if the MicrocodeCodeSize is zero
177 ; and report error if size is less than 2k
178 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
184 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
193 ; Get processor signature and platform ID from the installed processor
194 ; and save into registers for later use
195 ; ebx = processor signature
200 mov ecx, MSR_IA32_PLATFORM_ID
203 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
204 and ecx, 7h ; platform id at bit[52..50]
208 ; Current register usage
209 ; esp -> stack with parameters
210 ; esi -> microcode update to check
211 ; ebx = processor signature
214 ; Check for valid microcode header
215 ; Minimal test checking for header version and loader version as 1
217 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
219 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
222 ; Check if signature and plaform ID match
223 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
224 jne LoadMicrocodeDefault1
225 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
226 jnz LoadCheck ; Jif signature and platform ID match
228 LoadMicrocodeDefault1:
229 ; Check if extended header exists
230 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
232 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
234 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
237 ; Then verify total size - sizeof header > data size
238 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
239 sub ecx, MicrocodeHdr.size
240 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
241 jng NextMicrocode ; Jif extended header does not exist
243 ; Set edi -> extended header
245 add edi, MicrocodeHdr.size
246 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
248 ; Get count of extended structures
249 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
251 ; Move pointer to first signature structure
252 add edi, ExtSigHdr.size
255 ; Check if extended signature and platform ID match
256 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
257 jne LoadMicrocodeDefault2
258 test dword [edi + ExtSig.ExtSigFlags], edx
259 jnz LoadCheck ; Jif signature and platform ID match
260 LoadMicrocodeDefault2:
261 ; Check if any more extended signatures exist
266 ; Advance just after end of this microcode
268 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
269 je LoadMicrocodeDefault3
270 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
272 LoadMicrocodeDefault3:
277 ; Advance by 4X dwords
281 ; Is valid Microcode start point ?
282 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
285 ; Is automatic size detection ?
286 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
288 jz LoadMicrocodeDefault4
290 ; Address >= microcode region address + microcode region size?
291 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
293 jae Done ;Jif address is outside of microcode region
296 LoadMicrocodeDefault4:
298 ; Get the revision of the current microcode update loaded
299 mov ecx, MSR_IA32_BIOS_SIGN_ID
300 xor eax, eax ; Clear EAX
301 xor edx, edx ; Clear EDX
302 wrmsr ; Load 0 to MSR at 8Bh
306 mov ecx, MSR_IA32_BIOS_SIGN_ID
307 rdmsr ; Get current microcode signature
309 ; Verify this microcode update is not already loaded
310 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
314 ; EAX contains the linear address of the start of the Update Data
316 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
317 ; Start microcode load with wrmsr
319 add eax, MicrocodeHdr.size
321 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
332 mov ecx, MSR_IA32_BIOS_SIGN_ID
333 rdmsr ; Get current microcode signature
343 global ASM_PFX(EstablishStackFsp)
344 ASM_PFX(EstablishStackFsp):
346 ; Save parameter pointer in edx
348 mov edx, dword [esp + 4]
353 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
354 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
356 push DATA_LEN_OF_MCUD ; Size of the data region
357 push 4455434Dh ; Signature of the data region 'MCUD'
358 push dword [edx + 2Ch] ; Code size sizeof(FSPT_UPD_COMMON) + 12
359 push dword [edx + 28h] ; Code base sizeof(FSPT_UPD_COMMON) + 8
360 push dword [edx + 24h] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
361 push dword [edx + 20h] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
364 ; Save API entry/exit timestamp into stack
366 push DATA_LEN_OF_PER0 ; Size of the data region
367 push 30524550h ; Signature of the data region 'PER0'
377 ; Terminator for the data on stack
382 ; Set ECX/EDX to the BootLoader temporary memory range
384 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
386 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
387 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
389 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
390 jb EstablishStackFspSuccess
391 mov eax, 80000003h ;EFI_UNSUPPORTED
392 jmp EstablishStackFspExit
393 EstablishStackFspSuccess:
396 EstablishStackFspExit:
399 ;----------------------------------------------------------------------------
402 ; This FSP API will load the microcode update, enable code caching for the
403 ; region specified by the boot loader and also setup a temporary stack to be
404 ; used till main memory is initialized.
406 ;----------------------------------------------------------------------------
407 global ASM_PFX(TempRamInitApi)
408 ASM_PFX(TempRamInitApi):
410 ; Ensure SSE is enabled
415 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
420 ; Save timestamp into XMM6
429 mov eax, dword [esp + 4]
437 CALL_MMX ASM_PFX(SecPlatformInit)
443 CALL_MMX ASM_PFX(LoadMicrocodeDefault)
444 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
445 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
449 CALL_MMX ASM_PFX(SecCarInit)
454 CALL_MMX ASM_PFX(EstablishStackFsp)
458 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
461 mov bl, al ; save al data in bl
462 mov al, 07Fh ; API exit postcode 7f
464 mov al, bl ; restore al data from bl
467 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
472 ;----------------------------------------------------------------------------
473 ; Module Entrypoint API
474 ;----------------------------------------------------------------------------
475 global ASM_PFX(_ModuleEntryPoint)
476 ASM_PFX(_ModuleEntryPoint):