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
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 FspSelfCheck(FspSelfCheckDefault):PROC
44 EXTERN LoadUcode(LoadUcodeDefault):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 MM7
63 CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
65 mov esi, offset ReturnAddress
66 movd MmxRegister, esi ; save ReturnAddress into MM7
71 RET_ESI_EXT MACRO MmxRegister
72 movd esi, MmxRegister ; restore ESP from MM7
76 CALL_MMX MACRO RoutineLabel
77 CALL_MMX_EXT RoutineLabel, mm7
84 ;------------------------------------------------------------------------------
85 FspSelfCheckDefault PROC NEAR PUBLIC
87 ; eax -> 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 FspSelfCheckDefault ENDP
102 ;------------------------------------------------------------------------------
103 SecPlatformInitDefault PROC NEAR PUBLIC
105 ; eax -> Return address
107 ; eax -> 0 - Successful, Non-zero - Failed.
109 ; eax is cleared and ebp is used for return address.
110 ; All others reserved.
112 ; Save return address to EBP
118 SecPlatformInitDefault ENDP
120 ;------------------------------------------------------------------------------
121 LoadUcodeDefault PROC NEAR PUBLIC
123 ; esp -> LOAD_UCODE_PARAMS pointer
126 ; All others destroyed
128 ; No memory available, stack is hard-coded and used for return address
129 ; Executed by SBSP and NBSP
130 ; Beginning of microcode update region starts on paragraph boundary
134 ; Save return address to EBP
139 mov eax, dword ptr [esp] ; Parameter pointer
143 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
145 jnz check_main_header
151 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
154 ; Get processor signature and platform ID from the installed processor
155 ; and save into registers for later use
156 ; ebx = processor signature
161 mov ecx, MSR_IA32_PLATFORM_ID
169 ; Current register usage
170 ; esp -> stack with paramters
171 ; esi -> microcode update to check
172 ; ebx = processor signature
175 ; Check for valid microcode header
176 ; Minimal test checking for header version and loader version as 1
178 cmp [esi].ucode_hdr.version, eax
179 jne advance_fixed_size
180 cmp [esi].ucode_hdr.loader, eax
181 jne advance_fixed_size
183 ; Check if signature and plaform ID match
184 cmp ebx, [esi].ucode_hdr.processor
186 test edx, [esi].ucode_hdr.flags
187 jnz load_check ; Jif signature and platform ID match
190 ; Check if extended header exists
191 ; First check if total_size and data_size are valid
193 cmp [esi].ucode_hdr.total_size, eax
195 cmp [esi].ucode_hdr.data_size, eax
198 ; Then verify total size - sizeof header > data size
199 mov ecx, [esi].ucode_hdr.total_size
200 sub ecx, sizeof ucode_hdr
201 cmp ecx, [esi].ucode_hdr.data_size
202 jng next_microcode ; Jif extended header does not exist
204 ; Set edi -> extended header
206 add edi, sizeof ucode_hdr
207 add edi, [esi].ucode_hdr.data_size
209 ; Get count of extended structures
210 mov ecx, [edi].ext_sig_hdr.count
212 ; Move pointer to first signature structure
213 add edi, sizeof ext_sig_hdr
216 ; Check if extended signature and platform ID match
217 cmp [edi].ext_sig.processor, ebx
219 test [edi].ext_sig.flags, edx
220 jnz load_check ; Jif signature and platform ID match
222 ; Check if any more extended signatures exist
223 add edi, sizeof ext_sig
227 ; Advance just after end of this microcode
229 cmp [esi].ucode_hdr.total_size, eax
231 add esi, [esi].ucode_hdr.total_size
234 add esi, dword ptr 2048
238 ; Advance by 4X dwords
239 add esi, dword ptr 1024
242 ; Is valid Microcode start point ?
243 cmp dword ptr [esi].ucode_hdr.version, 0ffffffffh
246 ; Is automatic size detection ?
247 mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_size
251 ; Address >= microcode region address + microcode region size?
252 add eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
254 jae done ;Jif address is outside of ucode region
255 jmp check_main_header
259 ; Get the revision of the current microcode update loaded
260 mov ecx, MSR_IA32_BIOS_SIGN_ID
261 xor eax, eax ; Clear EAX
262 xor edx, edx ; Clear EDX
263 wrmsr ; Load 0 to MSR at 8Bh
267 mov ecx, MSR_IA32_BIOS_SIGN_ID
268 rdmsr ; Get current microcode signature
270 ; Verify this microcode update is not already loaded
271 cmp [esi].ucode_hdr.revision, edx
275 ; EAX contains the linear address of the start of the Update Data
277 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
278 ; Start microcode load with wrmsr
280 add eax, sizeof ucode_hdr
282 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
293 mov ecx, MSR_IA32_BIOS_SIGN_ID
294 rdmsr ; Get current microcode signature
303 LoadUcodeDefault ENDP
305 EstablishStackFsp PROC NEAR PRIVATE
307 ; Save parameter pointer in edx
309 mov edx, dword ptr [esp + 4]
314 mov esp, PcdGet32 (PcdTemporaryRamBase)
315 add esp, PcdGet32 (PcdTemporaryRamSize)
317 push DATA_LEN_OF_MCUD ; Size of the data region
318 push 4455434Dh ; Signature of the data region 'MCUD'
319 push dword ptr [edx + 12] ; Code size
320 push dword ptr [edx + 8] ; Code base
321 cmp edx, 0 ; Is parameter pointer valid ?
322 jz InvalidMicrocodeRegion
323 push dword ptr [edx + 4] ; Microcode size
324 push dword ptr [edx] ; Microcode base
327 InvalidMicrocodeRegion:
328 push 0 ; Microcode size
329 push 0 ; Microcode base
333 ; Save API entry/exit timestamp into stack
335 push DATA_LEN_OF_PER0 ; Size of the data region
336 push 30524550h ; Signature of the data region 'PER0'
346 ; Terminator for the data on stack
351 ; Set ECX/EDX to the bootloader temporary memory range
353 mov ecx, PcdGet32 (PcdTemporaryRamBase)
355 add edx, PcdGet32 (PcdTemporaryRamSize)
356 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
362 EstablishStackFsp ENDP
365 ;----------------------------------------------------------------------------
368 ; This FSP API will load the microcode update, enable code caching for the
369 ; region specified by the boot loader and also setup a temporary stack to be
370 ; used till main memory is initialized.
372 ;----------------------------------------------------------------------------
373 TempRamInitApi PROC NEAR PUBLIC
375 ; Ensure SSE is enabled
380 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
385 ; Save timestamp into XMM4 & XMM5
394 mov eax, dword ptr [esp + 4]
400 ; CPUID/DeviceID check
403 jmp FspSelfCheck ; Note: ESP can not be changed.
408 CALL_MMX SecPlatformInit
425 CALL_MMX EstablishStackFsp
429 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
435 ;----------------------------------------------------------------------------
438 ; This FSP API will perform the processor and chipset initialization.
439 ; This API will not return. Instead, it transfers the control to the
440 ; ContinuationFunc provided in the parameter.
442 ;----------------------------------------------------------------------------
443 FspInitApi PROC NEAR PUBLIC
448 ;----------------------------------------------------------------------------
451 ; This FSP API will notify the FSP about the different phases in the boot
454 ;----------------------------------------------------------------------------
455 NotifyPhaseApi PROC C PUBLIC
460 ;----------------------------------------------------------------------------
463 ; This FSP API is called after TempRamInit and initializes the memory.
465 ;----------------------------------------------------------------------------
466 FspMemoryInitApi PROC NEAR PUBLIC
469 FspMemoryInitApi ENDP
472 ;----------------------------------------------------------------------------
475 ; This API tears down temporary RAM
477 ;----------------------------------------------------------------------------
478 TempRamExitApi PROC C PUBLIC
484 ;----------------------------------------------------------------------------
487 ; This FSP API initializes the CPU and the chipset including the IO
488 ; controllers in the chipset to enable normal operation of these devices.
490 ;----------------------------------------------------------------------------
491 FspSiliconInitApi PROC C PUBLIC
494 FspSiliconInitApi ENDP
496 ;----------------------------------------------------------------------------
499 ; This is the FSP API common entry point to resume the FSP execution
501 ;----------------------------------------------------------------------------
502 FspApiCommon PROC C PUBLIC
504 ; EAX holds the API index
508 ; Stack must be ready
512 cmp eax, dword ptr [esp - 4]
519 ; Verify the calling condition
523 call FspApiCallingCheck
527 mov dword ptr [esp + 4 * 7], eax
533 cmp eax, 1 ; FspInit API
535 cmp eax, 3 ; FspMemoryInit API
537 jmp Pei2LoaderSwitchStack
541 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
545 ; Store the address in FSP which will return control to the BL
550 ; Create a Task Frame in the stack for the Boot Loader
552 pushfd ; 2 pushf for 4 byte alignment
556 ; Reserve 8 bytes for IDT save/restore
561 ; Setup new FSP stack
564 mov esp, PcdGet32(PcdTemporaryRamBase)
565 add esp, PcdGet32(PcdTemporaryRamSize)
566 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
569 ; Pass the API Idx to SecStartup
574 ; Pass the bootloader stack to SecStartup
579 ; Pass entry point of the PEI core
581 call GetFspBaseAddress
583 add edi, PcdGet32 (PcdFspAreaSize)
585 add eax, DWORD PTR ds:[edi]
589 ; Pass BFV into the PEI Core
590 ; It uses relative address to calucate the actual boot FV base
591 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
592 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
593 ; they are different. The code below can handle both cases.
595 call GetFspBaseAddress
597 call GetBootFirmwareVolumeOffset
602 ; Pass stack base and size into the PEI Core
604 mov eax, PcdGet32(PcdTemporaryRamBase)
605 add eax, PcdGet32(PcdTemporaryRamSize)
606 sub eax, PcdGet32(PcdFspTemporaryRamSize)
608 push PcdGet32(PcdFspTemporaryRamSize)
611 ; Pass Control into the PEI Core