1 ;------------------------------------------------------------------------------
3 ; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
4 ; This program and the accompanying materials
5 ; are licensed and made available under the terms and conditions of the BSD License
6 ; which accompanies this distribution. The full text of the license may be found at
7 ; http://opensource.org/licenses/bsd-license.php.
9 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 ; Provide FSP API entry points.
16 ;------------------------------------------------------------------------------
23 INCLUDE SaveRestoreSse.inc
27 ; Following are fixed PCDs
29 EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
30 EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
31 EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
34 ; Following functions will be provided in C
36 EXTERN FspImageSizeOffset:DWORD
37 EXTERN SecStartup:PROC
38 EXTERN FspApiCallingCheck:PROC
41 ; Following functions will be provided in PlatformSecLib
43 EXTERN GetFspBaseAddress:PROC
44 EXTERN GetBootFirmwareVolumeOffset:PROC
45 EXTERN PlatformTempRamInit:PROC
46 EXTERN Pei2LoaderSwitchStack:PROC
47 EXTERN FspSelfCheck(FspSelfCheckDflt):PROC
48 EXTERN PlatformBasicInit(PlatformBasicInitDflt):PROC
49 EXTERN LoadUcode(LoadUcodeDflt):PROC
52 ; Define the data length that we saved on the stack top
54 DATA_LEN_OF_PER0 EQU 18h
55 DATA_LEN_OF_MCUD EQU 18h
56 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
58 ;------------------------------------------------------------------------------
59 FspSelfCheckDflt PROC NEAR PUBLIC
61 ; eax -> Return address
63 ; eax -> 0 - Successful, Non-zero - Failed.
65 ; eax is cleared and ebp is used for return address.
66 ; All others reserved.
68 ; Save return address to EBP
76 ;------------------------------------------------------------------------------
77 PlatformBasicInitDflt PROC NEAR PUBLIC
79 ; eax -> Return address
81 ; eax -> 0 - Successful, Non-zero - Failed.
83 ; eax is cleared and ebp is used for return address.
84 ; All others reserved.
86 ; Save return address to EBP
92 PlatformBasicInitDflt ENDP
94 ;------------------------------------------------------------------------------
95 LoadUcodeDflt PROC NEAR PUBLIC
97 ; esp -> LOAD_UCODE_PARAMS pointer
100 ; All others destroyed
102 ; No memory available, stack is hard-coded and used for return address
103 ; Executed by SBSP and NBSP
104 ; Beginning of microcode update region starts on paragraph boundary
108 ; Save return address to EBP
113 mov eax, dword ptr [esp] ; Parameter pointer
117 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
119 jnz check_main_header
125 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
128 ; Get processor signature and platform ID from the installed processor
129 ; and save into registers for later use
130 ; ebx = processor signature
135 mov ecx, MSR_IA32_PLATFORM_ID
143 ; Current register usage
144 ; esp -> stack with paramters
145 ; esi -> microcode update to check
146 ; ebx = processor signature
149 ; Check for valid microcode header
150 ; Minimal test checking for header version and loader version as 1
152 cmp [esi].ucode_hdr.version, eax
153 jne advance_fixed_size
154 cmp [esi].ucode_hdr.loader, eax
155 jne advance_fixed_size
157 ; Check if signature and plaform ID match
158 cmp ebx, [esi].ucode_hdr.processor
160 test edx, [esi].ucode_hdr.flags
161 jnz load_check ; Jif signature and platform ID match
164 ; Check if extended header exists
165 ; First check if total_size and data_size are valid
167 cmp [esi].ucode_hdr.total_size, eax
169 cmp [esi].ucode_hdr.data_size, eax
172 ; Then verify total size - sizeof header > data size
173 mov ecx, [esi].ucode_hdr.total_size
174 sub ecx, sizeof ucode_hdr
175 cmp ecx, [esi].ucode_hdr.data_size
176 jng next_microcode ; Jif extended header does not exist
178 ; Set edi -> extended header
180 add edi, sizeof ucode_hdr
181 add edi, [esi].ucode_hdr.data_size
183 ; Get count of extended structures
184 mov ecx, [edi].ext_sig_hdr.count
186 ; Move pointer to first signature structure
187 add edi, sizeof ext_sig_hdr
190 ; Check if extended signature and platform ID match
191 cmp [edi].ext_sig.processor, ebx
193 test [edi].ext_sig.flags, edx
194 jnz load_check ; Jif signature and platform ID match
196 ; Check if any more extended signatures exist
197 add edi, sizeof ext_sig
201 ; Advance just after end of this microcode
203 cmp [esi].ucode_hdr.total_size, eax
205 add esi, [esi].ucode_hdr.total_size
208 add esi, dword ptr 2048
212 ; Advance by 4X dwords
213 add esi, dword ptr 1024
216 ; Is valid Microcode start point ?
217 cmp dword ptr [esi], 0ffffffffh
220 ; Address >= microcode region address + microcode region size?
221 mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
222 add eax, [esp].LOAD_UCODE_PARAMS.ucode_code_size
224 jae done ;Jif address is outside of ucode region
225 jmp check_main_header
228 ; Get the revision of the current microcode update loaded
229 mov ecx, MSR_IA32_BIOS_SIGN_ID
230 xor eax, eax ; Clear EAX
231 xor edx, edx ; Clear EDX
232 wrmsr ; Load 0 to MSR at 8Bh
236 mov ecx, MSR_IA32_BIOS_SIGN_ID
237 rdmsr ; Get current microcode signature
239 ; Verify this microcode update is not already loaded
240 cmp [esi].ucode_hdr.revision, edx
244 ; EAX contains the linear address of the start of the Update Data
246 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
247 ; Start microcode load with wrmsr
249 add eax, sizeof ucode_hdr
251 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
262 mov ecx, MSR_IA32_BIOS_SIGN_ID
263 rdmsr ; Get current microcode signature
274 ;----------------------------------------------------------------------------
277 ; This FSP API will load the microcode update, enable code caching for the
278 ; region specified by the boot loader and also setup a temporary stack to be
279 ; used till main memory is initialized.
281 ;----------------------------------------------------------------------------
282 TempRamInitApi PROC NEAR PUBLIC
284 ; Ensure SSE is enabled
289 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
294 ; Save timestamp into XMM4 & XMM5
303 mov eax, dword ptr [esp + 4]
309 ; CPUID/DeviceID check
312 jmp FspSelfCheck ; Note: ESP can not be changed.
318 ; Platform Basic Init.
321 jmp PlatformBasicInit
338 ; Call platform NEM init
342 jmp PlatformTempRamInit
349 ; Save parameter pointer in edx
351 mov edx, dword ptr [esp + 4]
356 mov esp, PcdGet32(PcdTemporaryRamBase)
357 add esp, PcdGet32(PcdTemporaryRamSize)
359 push DATA_LEN_OF_MCUD ; Size of the data region
360 push 4455434Dh ; Signature of the data region 'MCUD'
361 push dword ptr [edx + 4] ; Microcode size
362 push dword ptr [edx + 0] ; Microcode base
363 push dword ptr [edx + 12] ; Code size
364 push dword ptr [edx + 8] ; Code base
367 ; Save API entry/exit timestamp into stack
369 push DATA_LEN_OF_PER0 ; Size of the data region
370 push 30524550h ; Signature of the data region 'PER0'
380 ; Terminator for the data on stack
385 ; Set ECX/EDX to the bootloader temporary memory range
387 mov ecx, PcdGet32(PcdTemporaryRamBase)
389 add edx, PcdGet32(PcdTemporaryRamSize)
390 sub edx, PcdGet32(PcdFspTemporaryRamSize)
396 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
402 ;----------------------------------------------------------------------------
405 ; This FSP API will perform the processor and chipset initialization.
406 ; This API will not return. Instead, it transfers the control to the
407 ; ContinuationFunc provided in the parameter.
409 ;----------------------------------------------------------------------------
410 FspInitApi PROC NEAR PUBLIC
412 ; Stack must be ready
427 call FspApiCallingCheck
429 mov dword ptr [esp + 4 * 7], eax
437 ; Store the address in FSP which will return control to the BL
442 ; Create a Task Frame in the stack for the Boot Loader
444 pushfd ; 2 pushf for 4 byte alignment
448 ; Reserve 8 bytes for IDT save/restore
453 ; Setup new FSP stack
456 mov esp, PcdGet32(PcdTemporaryRamBase)
457 add esp, PcdGet32(PcdTemporaryRamSize)
458 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
461 ; Save the bootloader's stack pointer
466 ; Pass entry point of the PEI core
468 call GetFspBaseAddress
469 mov edi, FspImageSizeOffset
470 mov edi, DWORD PTR [eax + edi]
473 add eax, DWORD PTR [edi]
477 ; Pass BFV into the PEI Core
478 ; It uses relative address to calucate the actual boot FV base
479 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
480 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
481 ; they are different. The code below can handle both cases.
483 call GetFspBaseAddress
485 call GetBootFirmwareVolumeOffset
490 ; Pass stack base and size into the PEI Core
492 mov eax, PcdGet32(PcdTemporaryRamBase)
493 add eax, PcdGet32(PcdTemporaryRamSize)
494 sub eax, PcdGet32(PcdFspTemporaryRamSize)
496 push PcdGet32(PcdFspTemporaryRamSize)
499 ; Pass Control into the PEI Core
508 ;----------------------------------------------------------------------------
511 ; This FSP API will notify the FSP about the different phases in the boot
514 ;----------------------------------------------------------------------------
515 NotifyPhaseApi PROC C PUBLIC
517 ; Stack must be ready
528 ; Verify the calling condition
532 call FspApiCallingCheck
534 mov dword ptr [esp + 4 * 7], eax
547 jmp Pei2LoaderSwitchStack