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(FspSelfCheckDflt):PROC
44 EXTERN PlatformBasicInit(PlatformBasicInitDflt):PROC
45 EXTERN LoadUcode(LoadUcodeDflt):PROC
46 EXTERN SecPlatformInit:PROC
47 EXTERN SecCarInit:PROC
50 ; Define the data length that we saved on the stack top
52 DATA_LEN_OF_PER0 EQU 18h
53 DATA_LEN_OF_MCUD EQU 18h
54 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
59 LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
60 mov esi, ReturnAddress
61 movd MmxRegister, esi ; save ReturnAddress into MM7
64 CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
66 mov esi, offset ReturnAddress
67 movd MmxRegister, esi ; save ReturnAddress into MM7
72 RET_ESI_EXT MACRO MmxRegister
73 movd esi, MmxRegister ; restore ESP from MM7
77 CALL_MMX MACRO RoutineLabel
78 CALL_MMX_EXT RoutineLabel, mm7
85 ;------------------------------------------------------------------------------
86 FspSelfCheckDflt PROC NEAR PUBLIC
88 ; eax -> Return address
90 ; eax -> 0 - Successful, Non-zero - Failed.
92 ; eax is cleared and ebp is used for return address.
93 ; All others reserved.
95 ; Save return address to EBP
101 FspSelfCheckDflt ENDP
103 ;------------------------------------------------------------------------------
104 PlatformBasicInitDflt PROC NEAR PUBLIC
106 ; eax -> Return address
108 ; eax -> 0 - Successful, Non-zero - Failed.
110 ; eax is cleared and ebp is used for return address.
111 ; All others reserved.
113 ; Save return address to EBP
119 PlatformBasicInitDflt ENDP
121 ;------------------------------------------------------------------------------
122 LoadUcodeDflt PROC NEAR PUBLIC
124 ; esp -> LOAD_UCODE_PARAMS pointer
127 ; All others destroyed
129 ; No memory available, stack is hard-coded and used for return address
130 ; Executed by SBSP and NBSP
131 ; Beginning of microcode update region starts on paragraph boundary
135 ; Save return address to EBP
140 mov eax, dword ptr [esp] ; Parameter pointer
144 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
146 jnz check_main_header
152 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
155 ; Get processor signature and platform ID from the installed processor
156 ; and save into registers for later use
157 ; ebx = processor signature
162 mov ecx, MSR_IA32_PLATFORM_ID
170 ; Current register usage
171 ; esp -> stack with paramters
172 ; esi -> microcode update to check
173 ; ebx = processor signature
176 ; Check for valid microcode header
177 ; Minimal test checking for header version and loader version as 1
179 cmp [esi].ucode_hdr.version, eax
180 jne advance_fixed_size
181 cmp [esi].ucode_hdr.loader, eax
182 jne advance_fixed_size
184 ; Check if signature and plaform ID match
185 cmp ebx, [esi].ucode_hdr.processor
187 test edx, [esi].ucode_hdr.flags
188 jnz load_check ; Jif signature and platform ID match
191 ; Check if extended header exists
192 ; First check if total_size and data_size are valid
194 cmp [esi].ucode_hdr.total_size, eax
196 cmp [esi].ucode_hdr.data_size, eax
199 ; Then verify total size - sizeof header > data size
200 mov ecx, [esi].ucode_hdr.total_size
201 sub ecx, sizeof ucode_hdr
202 cmp ecx, [esi].ucode_hdr.data_size
203 jng next_microcode ; Jif extended header does not exist
205 ; Set edi -> extended header
207 add edi, sizeof ucode_hdr
208 add edi, [esi].ucode_hdr.data_size
210 ; Get count of extended structures
211 mov ecx, [edi].ext_sig_hdr.count
213 ; Move pointer to first signature structure
214 add edi, sizeof ext_sig_hdr
217 ; Check if extended signature and platform ID match
218 cmp [edi].ext_sig.processor, ebx
220 test [edi].ext_sig.flags, edx
221 jnz load_check ; Jif signature and platform ID match
223 ; Check if any more extended signatures exist
224 add edi, sizeof ext_sig
228 ; Advance just after end of this microcode
230 cmp [esi].ucode_hdr.total_size, eax
232 add esi, [esi].ucode_hdr.total_size
235 add esi, dword ptr 2048
239 ; Advance by 4X dwords
240 add esi, dword ptr 1024
243 ; Is valid Microcode start point ?
244 cmp dword ptr [esi].ucode_hdr.version, 0ffffffffh
247 ; Is automatic size detection ?
248 mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_size
252 ; Address >= microcode region address + microcode region size?
253 add eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
255 jae done ;Jif address is outside of ucode region
256 jmp check_main_header
260 ; Get the revision of the current microcode update loaded
261 mov ecx, MSR_IA32_BIOS_SIGN_ID
262 xor eax, eax ; Clear EAX
263 xor edx, edx ; Clear EDX
264 wrmsr ; Load 0 to MSR at 8Bh
268 mov ecx, MSR_IA32_BIOS_SIGN_ID
269 rdmsr ; Get current microcode signature
271 ; Verify this microcode update is not already loaded
272 cmp [esi].ucode_hdr.revision, edx
276 ; EAX contains the linear address of the start of the Update Data
278 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
279 ; Start microcode load with wrmsr
281 add eax, sizeof ucode_hdr
283 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
294 mov ecx, MSR_IA32_BIOS_SIGN_ID
295 rdmsr ; Get current microcode signature
306 EstablishStackFsp PROC NEAR PRIVATE
307 ; Following is the code copied from BYTFSP, need to figure out what it is doing..
309 ; Save parameter pointer in edx
311 mov edx, dword ptr [esp + 4]
316 mov esp, PcdGet32 (PcdTemporaryRamBase)
317 add esp, PcdGet32 (PcdTemporaryRamSize)
319 push DATA_LEN_OF_MCUD ; Size of the data region
320 push 4455434Dh ; Signature of the data region 'MCUD'
321 push dword ptr [edx + 12] ; Code size
322 push dword ptr [edx + 8] ; Code base
323 cmp edx, 0 ; Is parameter pointer valid ?
324 jz InvalidMicrocodeRegion
325 push dword ptr [edx + 4] ; Microcode size
326 push dword ptr [edx] ; Microcode base
329 InvalidMicrocodeRegion:
330 push 0 ; Microcode size
331 push 0 ; Microcode base
335 ; Save API entry/exit timestamp into stack
337 push DATA_LEN_OF_PER0 ; Size of the data region
338 push 30524550h ; Signature of the data region 'PER0'
348 ; Terminator for the data on stack
353 ; Set ECX/EDX to the bootloader temporary memory range
355 mov ecx, PcdGet32 (PcdTemporaryRamBase)
357 add edx, PcdGet32 (PcdTemporaryRamSize)
358 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
364 EstablishStackFsp ENDP
367 ;----------------------------------------------------------------------------
370 ; This FSP API will load the microcode update, enable code caching for the
371 ; region specified by the boot loader and also setup a temporary stack to be
372 ; used till main memory is initialized.
374 ;----------------------------------------------------------------------------
375 TempRamInitApi PROC NEAR PUBLIC
377 ; Ensure SSE is enabled
382 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
387 ; Save timestamp into XMM4 & XMM5
394 ; CPUID/DeviceID check
397 jmp FspSelfCheck ; Note: ESP can not be changed.
402 CALL_MMX SecPlatformInit
407 ; @todo: ESP has been modified, we need to restore here.
413 CALL_MMX EstablishStackFsp
417 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
423 ;----------------------------------------------------------------------------
426 ; This FSP API will perform the processor and chipset initialization.
427 ; This API will not return. Instead, it transfers the control to the
428 ; ContinuationFunc provided in the parameter.
430 ;----------------------------------------------------------------------------
431 FspInitApi PROC NEAR PUBLIC
436 ;----------------------------------------------------------------------------
439 ; This FSP API will notify the FSP about the different phases in the boot
442 ;----------------------------------------------------------------------------
443 NotifyPhaseApi PROC C PUBLIC
448 ;----------------------------------------------------------------------------
451 ; This FSP API is called after TempRamInit and initializes the memory.
453 ;----------------------------------------------------------------------------
454 FspMemoryInitApi PROC NEAR PUBLIC
457 FspMemoryInitApi ENDP
460 ;----------------------------------------------------------------------------
463 ; This API tears down temporary RAM
465 ;----------------------------------------------------------------------------
466 TempRamExitApi PROC C PUBLIC
472 ;----------------------------------------------------------------------------
475 ; This FSP API initializes the CPU and the chipset including the IO
476 ; controllers in the chipset to enable normal operation of these devices.
478 ;----------------------------------------------------------------------------
479 FspSiliconInitApi PROC C PUBLIC
482 FspSiliconInitApi ENDP
484 ;----------------------------------------------------------------------------
487 ; This is the FSP API common entry point to resume the FSP execution
489 ;----------------------------------------------------------------------------
490 FspApiCommon PROC C PUBLIC
492 ; EAX holds the API index
496 ; Stack must be ready
500 cmp eax, dword ptr [esp - 4]
507 ; Verify the calling condition
511 call FspApiCallingCheck
515 mov dword ptr [esp + 4 * 7], eax
521 cmp eax, 1 ; FspInit API
523 cmp eax, 3 ; FspMemoryInit API
525 jmp Pei2LoaderSwitchStack
529 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
533 ; Store the address in FSP which will return control to the BL
538 ; Create a Task Frame in the stack for the Boot Loader
540 pushfd ; 2 pushf for 4 byte alignment
544 ; Reserve 8 bytes for IDT save/restore
549 ; Setup new FSP stack
552 mov esp, PcdGet32(PcdTemporaryRamBase)
553 add esp, PcdGet32(PcdTemporaryRamSize)
554 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
557 ; Pass the API Idx to SecStartup
562 ; Pass the bootloader stack to SecStartup
567 ; Pass entry point of the PEI core
569 call GetFspBaseAddress
571 add edi, PcdGet32 (PcdFspAreaSize)
573 add eax, DWORD PTR ds:[edi]
577 ; Pass BFV into the PEI Core
578 ; It uses relative address to calucate the actual boot FV base
579 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
580 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
581 ; they are different. The code below can handle both cases.
583 call GetFspBaseAddress
585 call GetBootFirmwareVolumeOffset
590 ; Pass stack base and size into the PEI Core
592 mov eax, PcdGet32(PcdTemporaryRamBase)
593 add eax, PcdGet32(PcdTemporaryRamSize)
594 sub eax, PcdGet32(PcdFspTemporaryRamSize)
596 push PcdGet32(PcdFspTemporaryRamSize)
599 ; Pass Control into the PEI Core