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 GetFspBaseAddress:PROC
41 EXTERN GetBootFirmwareVolumeOffset:PROC
42 EXTERN Pei2LoaderSwitchStack:PROC
43 EXTERN LoadMicrocode(LoadMicrocodeDefault):PROC
44 EXTERN SecPlatformInit(SecPlatformInitDefault):PROC
45 EXTERN SecCarInit:PROC
48 ; Define the data length that we saved on the stack top
50 DATA_LEN_OF_PER0 EQU 18h
51 DATA_LEN_OF_MCUD EQU 18h
52 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
57 LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
58 mov esi, ReturnAddress
59 movd MmxRegister, esi ; save ReturnAddress into MMX
62 CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
64 mov esi, offset ReturnAddress
65 movd MmxRegister, esi ; save ReturnAddress into MMX
70 RET_ESI_EXT MACRO MmxRegister
71 movd esi, MmxRegister ; move ReturnAddress from MMX to ESI
75 CALL_MMX MACRO RoutineLabel
76 CALL_MMX_EXT RoutineLabel, mm7
83 ;------------------------------------------------------------------------------
84 SecPlatformInitDefault PROC NEAR PUBLIC
86 ; mm7 -> Return address
88 ; eax -> 0 - Successful, Non-zero - Failed.
90 ; eax is cleared and ebp is used for return address.
91 ; All others reserved.
93 ; Save return address to EBP
99 SecPlatformInitDefault ENDP
101 ;------------------------------------------------------------------------------
102 LoadMicrocodeDefault PROC NEAR PUBLIC
104 ; esp -> LoadMicrocodeParams pointer
107 ; All others destroyed
109 ; No memory available, stack is hard-coded and used for return address
110 ; Executed by SBSP and NBSP
111 ; Beginning of microcode update region starts on paragraph boundary
115 ; Save return address to EBP
120 mov eax, dword ptr [esp + 4] ; Parameter pointer
124 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
126 jnz check_main_header
132 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
135 ; Get processor signature and platform ID from the installed processor
136 ; and save into registers for later use
137 ; ebx = processor signature
142 mov ecx, MSR_IA32_PLATFORM_ID
150 ; Current register usage
151 ; esp -> stack with paramters
152 ; esi -> microcode update to check
153 ; ebx = processor signature
156 ; Check for valid microcode header
157 ; Minimal test checking for header version and loader version as 1
159 cmp [esi].MicrocodeHdr.MicrocodeHdrVersion, eax
160 jne advance_fixed_size
161 cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
162 jne advance_fixed_size
164 ; Check if signature and plaform ID match
165 cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
167 test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
168 jnz load_check ; Jif signature and platform ID match
171 ; Check if extended header exists
172 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
174 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
176 cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
179 ; Then verify total size - sizeof header > data size
180 mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
181 sub ecx, sizeof MicrocodeHdr
182 cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
183 jng next_microcode ; Jif extended header does not exist
185 ; Set edi -> extended header
187 add edi, sizeof MicrocodeHdr
188 add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
190 ; Get count of extended structures
191 mov ecx, [edi].ExtSigHdr.ExtSigHdrCount
193 ; Move pointer to first signature structure
194 add edi, sizeof ExtSigHdr
197 ; Check if extended signature and platform ID match
198 cmp [edi].ExtSig.ExtSigProcessor, ebx
200 test [edi].ExtSig.ExtSigFlags, edx
201 jnz load_check ; Jif signature and platform ID match
203 ; Check if any more extended signatures exist
204 add edi, sizeof ExtSig
208 ; Advance just after end of this microcode
210 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
212 add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
215 add esi, dword ptr 2048
219 ; Advance by 4X dwords
220 add esi, dword ptr 1024
223 ; Is valid Microcode start point ?
224 cmp dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
227 ; Is automatic size detection ?
228 mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
232 ; Address >= microcode region address + microcode region size?
233 add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
235 jae done ;Jif address is outside of microcode region
236 jmp check_main_header
240 ; Get the revision of the current microcode update loaded
241 mov ecx, MSR_IA32_BIOS_SIGN_ID
242 xor eax, eax ; Clear EAX
243 xor edx, edx ; Clear EDX
244 wrmsr ; Load 0 to MSR at 8Bh
248 mov ecx, MSR_IA32_BIOS_SIGN_ID
249 rdmsr ; Get current microcode signature
251 ; Verify this microcode update is not already loaded
252 cmp [esi].MicrocodeHdr.MicrocodeHdrRevision, edx
256 ; EAX contains the linear address of the start of the Update Data
258 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
259 ; Start microcode load with wrmsr
261 add eax, sizeof MicrocodeHdr
263 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
274 mov ecx, MSR_IA32_BIOS_SIGN_ID
275 rdmsr ; Get current microcode signature
284 LoadMicrocodeDefault ENDP
286 EstablishStackFsp PROC NEAR PRIVATE
288 ; Save parameter pointer in edx
290 mov edx, dword ptr [esp + 4]
295 mov esp, PcdGet32 (PcdTemporaryRamBase)
296 add esp, PcdGet32 (PcdTemporaryRamSize)
298 push DATA_LEN_OF_MCUD ; Size of the data region
299 push 4455434Dh ; Signature of the data region 'MCUD'
300 push dword ptr [edx + 12] ; Code size
301 push dword ptr [edx + 8] ; Code base
302 push dword ptr [edx + 4] ; Microcode size
303 push dword ptr [edx] ; Microcode base
306 ; Save API entry/exit timestamp into stack
308 push DATA_LEN_OF_PER0 ; Size of the data region
309 push 30524550h ; Signature of the data region 'PER0'
319 ; Terminator for the data on stack
324 ; Set ECX/EDX to the BootLoader temporary memory range
326 mov ecx, PcdGet32 (PcdTemporaryRamBase)
328 add edx, PcdGet32 (PcdTemporaryRamSize)
329 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
335 EstablishStackFsp ENDP
338 ;----------------------------------------------------------------------------
341 ; This FSP API will load the microcode update, enable code caching for the
342 ; region specified by the boot loader and also setup a temporary stack to be
343 ; used till main memory is initialized.
345 ;----------------------------------------------------------------------------
346 TempRamInitApi PROC NEAR PUBLIC
348 ; Ensure SSE is enabled
353 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
358 ; Save timestamp into XMM6
367 mov eax, dword ptr [esp + 4]
373 ; CPUID/DeviceID check
374 ; and Sec Platform Init
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
508 jmp Pei2LoaderSwitchStack
512 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
516 ; Store the address in FSP which will return control to the BL
521 ; Create a Task Frame in the stack for the Boot Loader
523 pushfd ; 2 pushf for 4 byte alignment
527 ; Reserve 8 bytes for IDT save/restore
532 ; Setup new FSP stack
535 mov esp, PcdGet32(PcdTemporaryRamBase)
536 add esp, PcdGet32(PcdTemporaryRamSize)
537 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
540 ; Pass the API Idx to SecStartup
545 ; Pass the BootLoader stack to SecStartup
550 ; Pass entry point of the PEI core
552 call GetFspBaseAddress
554 add edi, PcdGet32 (PcdFspAreaSize)
556 add eax, DWORD PTR ds:[edi]
560 ; Pass BFV into the PEI Core
561 ; It uses relative address to calucate the actual boot FV base
562 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
563 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
564 ; they are different. The code below can handle both cases.
566 call GetFspBaseAddress
568 call GetBootFirmwareVolumeOffset
573 ; Pass stack base and size into the PEI Core
575 mov eax, PcdGet32(PcdTemporaryRamBase)
576 add eax, PcdGet32(PcdTemporaryRamSize)
577 sub eax, PcdGet32(PcdFspTemporaryRamSize)
579 push PcdGet32(PcdFspTemporaryRamSize)
582 ; Pass Control into the PEI Core