2 ; Provide FSP API entry points.
4 ; Copyright (c) 2014 - 2015, 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.
19 INCLUDE SaveRestoreSse.inc
20 INCLUDE MicrocodeLoad.inc
23 ; Following are fixed PCDs
25 EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
26 EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
27 EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
28 EXTERN PcdGet32(PcdFspAreaSize):DWORD
31 ; Following functions will be provided in C
34 EXTERN SecStartup:PROC
35 EXTERN FspApiCallingCheck:PROC
38 ; Following functions will be provided in PlatformSecLib
40 EXTERN AsmGetFspBaseAddress:PROC
41 EXTERN AsmGetFspInfoHeader:PROC
42 EXTERN GetBootFirmwareVolumeOffset:PROC
43 EXTERN Loader2PeiSwitchStack:PROC
44 EXTERN LoadMicrocode(LoadMicrocodeDefault):PROC
45 EXTERN SecPlatformInit(SecPlatformInitDefault):PROC
46 EXTERN SecCarInit:PROC
49 ; Define the data length that we saved on the stack top
51 DATA_LEN_OF_PER0 EQU 18h
52 DATA_LEN_OF_MCUD EQU 18h
53 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
58 LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
59 mov esi, ReturnAddress
60 movd MmxRegister, esi ; save ReturnAddress into MMX
63 CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
65 mov esi, offset ReturnAddress
66 movd MmxRegister, esi ; save ReturnAddress into MMX
71 RET_ESI_EXT MACRO MmxRegister
72 movd esi, MmxRegister ; move ReturnAddress from MMX to ESI
76 CALL_MMX MACRO RoutineLabel
77 CALL_MMX_EXT RoutineLabel, mm7
84 ;------------------------------------------------------------------------------
85 SecPlatformInitDefault PROC NEAR PUBLIC
87 ; mm7 -> Return address
89 ; eax -> 0 - Successful, Non-zero - Failed.
91 ; eax is cleared and ebp is used for return address.
92 ; All others reserved.
94 ; Save return address to EBP
100 SecPlatformInitDefault ENDP
102 ;------------------------------------------------------------------------------
103 LoadMicrocodeDefault PROC NEAR PUBLIC
105 ; esp -> LoadMicrocodeParams pointer
108 ; All others destroyed
110 ; No memory available, stack is hard-coded and used for return address
111 ; Executed by SBSP and NBSP
112 ; Beginning of microcode update region starts on paragraph boundary
116 ; Save return address to EBP
121 mov eax, dword ptr [esp + 4] ; Parameter pointer
125 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
127 jnz check_main_header
133 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
136 ; Get processor signature and platform ID from the installed processor
137 ; and save into registers for later use
138 ; ebx = processor signature
143 mov ecx, MSR_IA32_PLATFORM_ID
151 ; Current register usage
152 ; esp -> stack with paramters
153 ; esi -> microcode update to check
154 ; ebx = processor signature
157 ; Check for valid microcode header
158 ; Minimal test checking for header version and loader version as 1
160 cmp [esi].MicrocodeHdr.MicrocodeHdrVersion, eax
161 jne advance_fixed_size
162 cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
163 jne advance_fixed_size
165 ; Check if signature and plaform ID match
166 cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
168 test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
169 jnz load_check ; Jif signature and platform ID match
172 ; Check if extended header exists
173 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
175 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
177 cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
180 ; Then verify total size - sizeof header > data size
181 mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
182 sub ecx, sizeof MicrocodeHdr
183 cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
184 jng next_microcode ; Jif extended header does not exist
186 ; Set edi -> extended header
188 add edi, sizeof MicrocodeHdr
189 add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
191 ; Get count of extended structures
192 mov ecx, [edi].ExtSigHdr.ExtSigHdrCount
194 ; Move pointer to first signature structure
195 add edi, sizeof ExtSigHdr
198 ; Check if extended signature and platform ID match
199 cmp [edi].ExtSig.ExtSigProcessor, ebx
201 test [edi].ExtSig.ExtSigFlags, edx
202 jnz load_check ; Jif signature and platform ID match
204 ; Check if any more extended signatures exist
205 add edi, sizeof ExtSig
209 ; Advance just after end of this microcode
211 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
213 add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
216 add esi, dword ptr 2048
220 ; Advance by 4X dwords
221 add esi, dword ptr 1024
224 ; Is valid Microcode start point ?
225 cmp dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
228 ; Is automatic size detection ?
229 mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
233 ; Address >= microcode region address + microcode region size?
234 add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
236 jae done ;Jif address is outside of microcode region
237 jmp check_main_header
241 ; Get the revision of the current microcode update loaded
242 mov ecx, MSR_IA32_BIOS_SIGN_ID
243 xor eax, eax ; Clear EAX
244 xor edx, edx ; Clear EDX
245 wrmsr ; Load 0 to MSR at 8Bh
249 mov ecx, MSR_IA32_BIOS_SIGN_ID
250 rdmsr ; Get current microcode signature
252 ; Verify this microcode update is not already loaded
253 cmp [esi].MicrocodeHdr.MicrocodeHdrRevision, edx
257 ; EAX contains the linear address of the start of the Update Data
259 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
260 ; Start microcode load with wrmsr
262 add eax, sizeof MicrocodeHdr
264 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
275 mov ecx, MSR_IA32_BIOS_SIGN_ID
276 rdmsr ; Get current microcode signature
285 LoadMicrocodeDefault ENDP
287 EstablishStackFsp PROC NEAR PRIVATE
289 ; Save parameter pointer in edx
291 mov edx, dword ptr [esp + 4]
296 mov esp, PcdGet32 (PcdTemporaryRamBase)
297 add esp, PcdGet32 (PcdTemporaryRamSize)
299 push DATA_LEN_OF_MCUD ; Size of the data region
300 push 4455434Dh ; Signature of the data region 'MCUD'
301 push dword ptr [edx + 12] ; Code size
302 push dword ptr [edx + 8] ; Code base
303 push dword ptr [edx + 4] ; Microcode size
304 push dword ptr [edx] ; Microcode base
307 ; Save API entry/exit timestamp into stack
309 push DATA_LEN_OF_PER0 ; Size of the data region
310 push 30524550h ; Signature of the data region 'PER0'
320 ; Terminator for the data on stack
325 ; Set ECX/EDX to the BootLoader temporary memory range
327 mov ecx, PcdGet32 (PcdTemporaryRamBase)
329 add edx, PcdGet32 (PcdTemporaryRamSize)
330 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
336 EstablishStackFsp ENDP
339 ;----------------------------------------------------------------------------
342 ; This FSP API will load the microcode update, enable code caching for the
343 ; region specified by the boot loader and also setup a temporary stack to be
344 ; used till main memory is initialized.
346 ;----------------------------------------------------------------------------
347 TempRamInitApi PROC NEAR PUBLIC
349 ; Ensure SSE is enabled
354 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
359 ; Save timestamp into XMM6
368 mov eax, dword ptr [esp + 4]
376 CALL_MMX SecPlatformInit
382 CALL_MMX LoadMicrocode
383 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
384 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
393 CALL_MMX EstablishStackFsp
395 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
399 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
405 ;----------------------------------------------------------------------------
408 ; This FSP API will perform the processor and chipset initialization.
409 ; This API will not return. Instead, it transfers the control to the
410 ; ContinuationFunc provided in the parameter.
412 ;----------------------------------------------------------------------------
413 FspInitApi PROC NEAR PUBLIC
418 ;----------------------------------------------------------------------------
421 ; This FSP API will notify the FSP about the different phases in the boot
424 ;----------------------------------------------------------------------------
425 NotifyPhaseApi PROC C PUBLIC
430 ;----------------------------------------------------------------------------
433 ; This FSP API is called after TempRamInit and initializes the memory.
435 ;----------------------------------------------------------------------------
436 FspMemoryInitApi PROC NEAR PUBLIC
439 FspMemoryInitApi ENDP
442 ;----------------------------------------------------------------------------
445 ; This API tears down temporary RAM
447 ;----------------------------------------------------------------------------
448 TempRamExitApi PROC C PUBLIC
454 ;----------------------------------------------------------------------------
457 ; This FSP API initializes the CPU and the chipset including the IO
458 ; controllers in the chipset to enable normal operation of these devices.
460 ;----------------------------------------------------------------------------
461 FspSiliconInitApi PROC C PUBLIC
464 FspSiliconInitApi ENDP
466 ;----------------------------------------------------------------------------
469 ; This is the FSP API common entry point to resume the FSP execution
471 ;----------------------------------------------------------------------------
472 FspApiCommon PROC C PUBLIC
474 ; EAX holds the API index
478 ; Stack must be ready
482 cmp eax, dword ptr [esp - 4]
489 ; Verify the calling condition
492 push [esp + 4 * 8 + 4]
494 call FspApiCallingCheck
498 mov dword ptr [esp + 4 * 7], eax
504 cmp eax, 1 ; FspInit API
506 cmp eax, 3 ; FspMemoryInit API
509 call AsmGetFspInfoHeader
510 jmp Loader2PeiSwitchStack
514 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
518 ; Place holder to store the FspInfoHeader pointer
523 ; Update the FspInfoHeader pointer
526 call AsmGetFspInfoHeader
531 ; Create a Task Frame in the stack for the Boot Loader
533 pushfd ; 2 pushf for 4 byte alignment
537 ; Reserve 8 bytes for IDT save/restore
542 ; Setup new FSP stack
545 mov esp, PcdGet32(PcdTemporaryRamBase)
546 add esp, PcdGet32(PcdTemporaryRamSize)
547 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
550 ; Pass the API Idx to SecStartup
555 ; Pass the BootLoader stack to SecStartup
560 ; Pass entry point of the PEI core
562 call AsmGetFspBaseAddress
564 add edi, PcdGet32 (PcdFspAreaSize)
566 add eax, DWORD PTR ds:[edi]
570 ; Pass BFV into the PEI Core
571 ; It uses relative address to calucate the actual boot FV base
572 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
573 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
574 ; they are different. The code below can handle both cases.
576 call AsmGetFspBaseAddress
578 call GetBootFirmwareVolumeOffset
583 ; Pass stack base and size into the PEI Core
585 mov eax, PcdGet32(PcdTemporaryRamBase)
586 add eax, PcdGet32(PcdTemporaryRamSize)
587 sub eax, PcdGet32(PcdFspTemporaryRamSize)
589 push PcdGet32(PcdFspTemporaryRamSize)
592 ; Pass Control into the PEI Core