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 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
185 ; Get processor signature and platform ID from the installed processor
186 ; and save into registers for later use
187 ; ebx = processor signature
192 mov ecx, MSR_IA32_PLATFORM_ID
195 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
196 and ecx, 7h ; platform id at bit[52..50]
200 ; Current register usage
201 ; esp -> stack with parameters
202 ; esi -> microcode update to check
203 ; ebx = processor signature
206 ; Check for valid microcode header
207 ; Minimal test checking for header version and loader version as 1
209 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
211 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
214 ; Check if signature and plaform ID match
215 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
216 jne LoadMicrocodeDefault1
217 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
218 jnz LoadCheck ; Jif signature and platform ID match
220 LoadMicrocodeDefault1:
221 ; Check if extended header exists
222 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
224 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
226 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
229 ; Then verify total size - sizeof header > data size
230 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
231 sub ecx, MicrocodeHdr.size
232 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
233 jng NextMicrocode ; Jif extended header does not exist
235 ; Set edi -> extended header
237 add edi, MicrocodeHdr.size
238 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
240 ; Get count of extended structures
241 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
243 ; Move pointer to first signature structure
244 add edi, ExtSigHdr.size
247 ; Check if extended signature and platform ID match
248 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
249 jne LoadMicrocodeDefault2
250 test dword [edi + ExtSig.ExtSigFlags], edx
251 jnz LoadCheck ; Jif signature and platform ID match
252 LoadMicrocodeDefault2:
253 ; Check if any more extended signatures exist
258 ; Advance just after end of this microcode
260 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
261 je LoadMicrocodeDefault3
262 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
264 LoadMicrocodeDefault3:
269 ; Advance by 4X dwords
273 ; Is valid Microcode start point ?
274 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
277 ; Is automatic size detection ?
278 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
280 jz LoadMicrocodeDefault4
282 ; Address >= microcode region address + microcode region size?
283 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
285 jae Done ;Jif address is outside of microcode region
288 LoadMicrocodeDefault4:
290 ; Get the revision of the current microcode update loaded
291 mov ecx, MSR_IA32_BIOS_SIGN_ID
292 xor eax, eax ; Clear EAX
293 xor edx, edx ; Clear EDX
294 wrmsr ; Load 0 to MSR at 8Bh
298 mov ecx, MSR_IA32_BIOS_SIGN_ID
299 rdmsr ; Get current microcode signature
301 ; Verify this microcode update is not already loaded
302 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
306 ; EAX contains the linear address of the start of the Update Data
308 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
309 ; Start microcode load with wrmsr
311 add eax, MicrocodeHdr.size
313 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
324 mov ecx, MSR_IA32_BIOS_SIGN_ID
325 rdmsr ; Get current microcode signature
335 global ASM_PFX(EstablishStackFsp)
336 ASM_PFX(EstablishStackFsp):
338 ; Save parameter pointer in edx
340 mov edx, dword [esp + 4]
345 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
346 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
348 push DATA_LEN_OF_MCUD ; Size of the data region
349 push 4455434Dh ; Signature of the data region 'MCUD'
350 push dword [edx + 2Ch] ; Code size sizeof(FSPT_UPD_COMMON) + 12
351 push dword [edx + 28h] ; Code base sizeof(FSPT_UPD_COMMON) + 8
352 push dword [edx + 24h] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
353 push dword [edx + 20h] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
356 ; Save API entry/exit timestamp into stack
358 push DATA_LEN_OF_PER0 ; Size of the data region
359 push 30524550h ; Signature of the data region 'PER0'
369 ; Terminator for the data on stack
374 ; Set ECX/EDX to the BootLoader temporary memory range
376 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
378 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
379 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
381 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
382 jb EstablishStackFspSuccess
383 mov eax, 80000003h ;EFI_UNSUPPORTED
384 jmp EstablishStackFspExit
385 EstablishStackFspSuccess:
388 EstablishStackFspExit:
391 ;----------------------------------------------------------------------------
394 ; This FSP API will load the microcode update, enable code caching for the
395 ; region specified by the boot loader and also setup a temporary stack to be
396 ; used till main memory is initialized.
398 ;----------------------------------------------------------------------------
399 global ASM_PFX(TempRamInitApi)
400 ASM_PFX(TempRamInitApi):
402 ; Ensure SSE is enabled
407 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
412 ; Save timestamp into XMM6
421 mov eax, dword [esp + 4]
429 CALL_MMX ASM_PFX(SecPlatformInit)
435 CALL_MMX ASM_PFX(LoadMicrocodeDefault)
436 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
437 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
441 CALL_MMX ASM_PFX(SecCarInit)
446 CALL_MMX ASM_PFX(EstablishStackFsp)
450 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
453 mov bl, al ; save al data in bl
454 mov al, 07Fh ; API exit postcode 7f
456 mov al, bl ; restore al data from bl
459 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
464 ;----------------------------------------------------------------------------
465 ; Module Entrypoint API
466 ;----------------------------------------------------------------------------
467 global ASM_PFX(_ModuleEntryPoint)
468 ASM_PFX(_ModuleEntryPoint):