2 ; Provide FSP API entry points.
4 ; Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
5 ; SPDX-License-Identifier: BSD-2-Clause-Patent
13 INCLUDE SaveRestoreSse.inc
14 INCLUDE MicrocodeLoad.inc
17 ; Following are fixed PCDs
19 EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
20 EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
21 EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
22 EXTERN PcdGet32(PcdFspAreaSize):DWORD
25 ; Following functions will be provided in C
28 EXTERN SecStartup:PROC
29 EXTERN FspApiCallingCheck:PROC
32 ; Following functions will be provided in PlatformSecLib
34 EXTERN AsmGetFspBaseAddress:PROC
35 EXTERN AsmGetFspInfoHeader:PROC
36 EXTERN GetBootFirmwareVolumeOffset:PROC
37 EXTERN Loader2PeiSwitchStack:PROC
38 EXTERN LoadMicrocode(LoadMicrocodeDefault):PROC
39 EXTERN SecPlatformInit(SecPlatformInitDefault):PROC
40 EXTERN SecCarInit:PROC
43 ; Define the data length that we saved on the stack top
45 DATA_LEN_OF_PER0 EQU 18h
46 DATA_LEN_OF_MCUD EQU 18h
47 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
52 LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
53 mov esi, ReturnAddress
54 movd MmxRegister, esi ; save ReturnAddress into MMX
57 CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
59 mov esi, offset ReturnAddress
60 movd MmxRegister, esi ; save ReturnAddress into MMX
65 RET_ESI_EXT MACRO MmxRegister
66 movd esi, MmxRegister ; move ReturnAddress from MMX to ESI
70 CALL_MMX MACRO RoutineLabel
71 CALL_MMX_EXT RoutineLabel, mm7
78 ;------------------------------------------------------------------------------
79 SecPlatformInitDefault PROC NEAR PUBLIC
81 ; mm7 -> Return address
83 ; eax -> 0 - Successful, Non-zero - Failed.
85 ; eax is cleared and ebp is used for return address.
86 ; All others reserved.
88 ; Save return address to EBP
94 SecPlatformInitDefault ENDP
96 ;------------------------------------------------------------------------------
97 LoadMicrocodeDefault PROC NEAR PUBLIC
99 ; esp -> LoadMicrocodeParams pointer
102 ; All others destroyed
104 ; No memory available, stack is hard-coded and used for return address
105 ; Executed by SBSP and NBSP
106 ; Beginning of microcode update region starts on paragraph boundary
110 ; Save return address to EBP
115 mov eax, dword ptr [esp + 4] ; Parameter pointer
119 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
121 jnz check_main_header
127 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
130 ; Get processor signature and platform ID from the installed processor
131 ; and save into registers for later use
132 ; ebx = processor signature
137 mov ecx, MSR_IA32_PLATFORM_ID
140 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
141 and ecx, 7h ; platform id at bit[52..50]
145 ; Current register usage
146 ; esp -> stack with paramters
147 ; esi -> microcode update to check
148 ; ebx = processor signature
151 ; Check for valid microcode header
152 ; Minimal test checking for header version and loader version as 1
154 cmp [esi].MicrocodeHdr.MicrocodeHdrVersion, eax
155 jne advance_fixed_size
156 cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
157 jne advance_fixed_size
159 ; Check if signature and plaform ID match
160 cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
162 test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
163 jnz load_check ; Jif signature and platform ID match
166 ; Check if extended header exists
167 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
169 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
171 cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
174 ; Then verify total size - sizeof header > data size
175 mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
176 sub ecx, sizeof MicrocodeHdr
177 cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
178 jng next_microcode ; Jif extended header does not exist
180 ; Set edi -> extended header
182 add edi, sizeof MicrocodeHdr
183 add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
185 ; Get count of extended structures
186 mov ecx, [edi].ExtSigHdr.ExtSigHdrCount
188 ; Move pointer to first signature structure
189 add edi, sizeof ExtSigHdr
192 ; Check if extended signature and platform ID match
193 cmp [edi].ExtSig.ExtSigProcessor, ebx
195 test [edi].ExtSig.ExtSigFlags, edx
196 jnz load_check ; Jif signature and platform ID match
198 ; Check if any more extended signatures exist
199 add edi, sizeof ExtSig
203 ; Advance just after end of this microcode
205 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
207 add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
210 add esi, dword ptr 2048
214 ; Advance by 4X dwords
215 add esi, dword ptr 1024
218 ; Is valid Microcode start point ?
219 cmp dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
222 ; Is automatic size detection ?
223 mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
227 ; Address >= microcode region address + microcode region size?
228 add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
230 jae done ;Jif address is outside of microcode region
231 jmp check_main_header
235 ; Get the revision of the current microcode update loaded
236 mov ecx, MSR_IA32_BIOS_SIGN_ID
237 xor eax, eax ; Clear EAX
238 xor edx, edx ; Clear EDX
239 wrmsr ; Load 0 to MSR at 8Bh
243 mov ecx, MSR_IA32_BIOS_SIGN_ID
244 rdmsr ; Get current microcode signature
246 ; Verify this microcode update is not already loaded
247 cmp [esi].MicrocodeHdr.MicrocodeHdrRevision, edx
251 ; EAX contains the linear address of the start of the Update Data
253 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
254 ; Start microcode load with wrmsr
256 add eax, sizeof MicrocodeHdr
258 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
269 mov ecx, MSR_IA32_BIOS_SIGN_ID
270 rdmsr ; Get current microcode signature
279 LoadMicrocodeDefault ENDP
281 EstablishStackFsp PROC NEAR PRIVATE
283 ; Save parameter pointer in edx
285 mov edx, dword ptr [esp + 4]
290 mov esp, PcdGet32 (PcdTemporaryRamBase)
291 add esp, PcdGet32 (PcdTemporaryRamSize)
293 push DATA_LEN_OF_MCUD ; Size of the data region
294 push 4455434Dh ; Signature of the data region 'MCUD'
295 push dword ptr [edx + 12] ; Code size
296 push dword ptr [edx + 8] ; Code base
297 push dword ptr [edx + 4] ; Microcode size
298 push dword ptr [edx] ; Microcode base
301 ; Save API entry/exit timestamp into stack
303 push DATA_LEN_OF_PER0 ; Size of the data region
304 push 30524550h ; Signature of the data region 'PER0'
314 ; Terminator for the data on stack
319 ; Set ECX/EDX to the BootLoader temporary memory range
321 mov ecx, PcdGet32 (PcdTemporaryRamBase)
323 add edx, PcdGet32 (PcdTemporaryRamSize)
324 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
330 EstablishStackFsp ENDP
333 ;----------------------------------------------------------------------------
336 ; This FSP API will load the microcode update, enable code caching for the
337 ; region specified by the boot loader and also setup a temporary stack to be
338 ; used till main memory is initialized.
340 ;----------------------------------------------------------------------------
341 TempRamInitApi PROC NEAR PUBLIC
343 ; Ensure SSE is enabled
348 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
353 ; Save timestamp into XMM6
362 mov eax, dword ptr [esp + 4]
370 CALL_MMX SecPlatformInit
376 CALL_MMX LoadMicrocode
377 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
378 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
387 CALL_MMX EstablishStackFsp
389 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
393 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
399 ;----------------------------------------------------------------------------
402 ; This FSP API will perform the processor and chipset initialization.
403 ; This API will not return. Instead, it transfers the control to the
404 ; ContinuationFunc provided in the parameter.
406 ;----------------------------------------------------------------------------
407 FspInitApi PROC NEAR PUBLIC
412 ;----------------------------------------------------------------------------
415 ; This FSP API will notify the FSP about the different phases in the boot
418 ;----------------------------------------------------------------------------
419 NotifyPhaseApi PROC C PUBLIC
424 ;----------------------------------------------------------------------------
427 ; This FSP API is called after TempRamInit and initializes the memory.
429 ;----------------------------------------------------------------------------
430 FspMemoryInitApi PROC NEAR PUBLIC
433 FspMemoryInitApi ENDP
436 ;----------------------------------------------------------------------------
439 ; This API tears down temporary RAM
441 ;----------------------------------------------------------------------------
442 TempRamExitApi PROC C PUBLIC
448 ;----------------------------------------------------------------------------
451 ; This FSP API initializes the CPU and the chipset including the IO
452 ; controllers in the chipset to enable normal operation of these devices.
454 ;----------------------------------------------------------------------------
455 FspSiliconInitApi PROC C PUBLIC
458 FspSiliconInitApi ENDP
460 ;----------------------------------------------------------------------------
463 ; This is the FSP API common entry point to resume the FSP execution
465 ;----------------------------------------------------------------------------
466 FspApiCommon PROC C PUBLIC
468 ; EAX holds the API index
472 ; Stack must be ready
476 cmp eax, dword ptr [esp - 4]
483 ; Verify the calling condition
486 push [esp + 4 * 8 + 4] ; push ApiParam
487 push eax ; push ApiIdx
488 call FspApiCallingCheck
492 mov dword ptr [esp + 4 * 7], eax
498 cmp eax, 1 ; FspInit API
500 cmp eax, 3 ; FspMemoryInit API
503 call AsmGetFspInfoHeader
504 jmp Loader2PeiSwitchStack
508 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
512 ; Place holder to store the FspInfoHeader pointer
517 ; Update the FspInfoHeader pointer
520 call AsmGetFspInfoHeader
525 ; Create a Task Frame in the stack for the Boot Loader
527 pushfd ; 2 pushf for 4 byte alignment
531 ; Reserve 8 bytes for IDT save/restore
536 ; Setup new FSP stack
539 mov esp, PcdGet32(PcdTemporaryRamBase)
540 add esp, PcdGet32(PcdTemporaryRamSize)
541 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
544 ; Pass the API Idx to SecStartup
549 ; Pass the BootLoader stack to SecStartup
554 ; Pass entry point of the PEI core
556 call AsmGetFspBaseAddress
558 add edi, PcdGet32 (PcdFspAreaSize)
560 add eax, DWORD PTR ds:[edi]
564 ; Pass BFV into the PEI Core
565 ; It uses relative address to calucate the actual boot FV base
566 ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and
567 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
568 ; they are different. The code below can handle both cases.
570 call AsmGetFspBaseAddress
572 call GetBootFirmwareVolumeOffset
577 ; Pass stack base and size into the PEI Core
579 mov eax, PcdGet32(PcdTemporaryRamBase)
580 add eax, PcdGet32(PcdTemporaryRamSize)
581 sub eax, PcdGet32(PcdFspTemporaryRamSize)
583 push PcdGet32(PcdFspTemporaryRamSize)
586 ; Pass Control into the PEI Core