]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
8ad9744ab43935d25b8a3a83dcb4733b1da86735
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.asm
1 ;------------------------------------------------------------------------------
2 ;
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.
8 ;
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.
11 ;
12 ; Abstract:
13 ;
14 ; Provide FSP API entry points.
15 ;
16 ;------------------------------------------------------------------------------
17
18 .586p
19 .model flat,C
20 .code
21 .xmm
22
23 INCLUDE SaveRestoreSse.inc
24 INCLUDE UcodeLoad.inc
25
26 ;
27 ; Following are fixed PCDs
28 ;
29 EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
30 EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
31 EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
32
33 ;
34 ; Following functions will be provided in C
35 ;
36 EXTERN FspImageSizeOffset:DWORD
37 EXTERN SecStartup:PROC
38 EXTERN FspApiCallingCheck:PROC
39
40 ;
41 ; Following functions will be provided in PlatformSecLib
42 ;
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
50
51 ;
52 ; Define the data length that we saved on the stack top
53 ;
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)
57
58 ;------------------------------------------------------------------------------
59 FspSelfCheckDflt PROC NEAR PUBLIC
60 ; Inputs:
61 ; eax -> Return address
62 ; Outputs:
63 ; eax -> 0 - Successful, Non-zero - Failed.
64 ; Register Usage:
65 ; eax is cleared and ebp is used for return address.
66 ; All others reserved.
67
68 ; Save return address to EBP
69 mov ebp, eax
70
71 xor eax, eax
72 exit:
73 jmp ebp
74 FspSelfCheckDflt ENDP
75
76 ;------------------------------------------------------------------------------
77 PlatformBasicInitDflt PROC NEAR PUBLIC
78 ; Inputs:
79 ; eax -> Return address
80 ; Outputs:
81 ; eax -> 0 - Successful, Non-zero - Failed.
82 ; Register Usage:
83 ; eax is cleared and ebp is used for return address.
84 ; All others reserved.
85
86 ; Save return address to EBP
87 mov ebp, eax
88
89 xor eax, eax
90 exit:
91 jmp ebp
92 PlatformBasicInitDflt ENDP
93
94 ;------------------------------------------------------------------------------
95 LoadUcodeDflt PROC NEAR PUBLIC
96 ; Inputs:
97 ; esp -> LOAD_UCODE_PARAMS pointer
98 ; Register Usage:
99 ; esp Preserved
100 ; All others destroyed
101 ; Assumptions:
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
105
106 ;
107 ;
108 ; Save return address to EBP
109 mov ebp, eax
110
111 cmp esp, 0
112 jz paramerror
113 mov eax, dword ptr [esp] ; Parameter pointer
114 cmp eax, 0
115 jz paramerror
116 mov esp, eax
117 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
118 cmp esi, 0
119 jnz check_main_header
120
121 paramerror:
122 mov eax, 080000002h
123 jmp exit
124
125 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
126
127 check_main_header:
128 ; Get processor signature and platform ID from the installed processor
129 ; and save into registers for later use
130 ; ebx = processor signature
131 ; edx = platform ID
132 mov eax, 1
133 cpuid
134 mov ebx, eax
135 mov ecx, MSR_IA32_PLATFORM_ID
136 rdmsr
137 mov ecx, edx
138 shr ecx, 50-32
139 and ecx, 7h
140 mov edx, 1
141 shl edx, cl
142
143 ; Current register usage
144 ; esp -> stack with paramters
145 ; esi -> microcode update to check
146 ; ebx = processor signature
147 ; edx = platform ID
148
149 ; Check for valid microcode header
150 ; Minimal test checking for header version and loader version as 1
151 mov eax, dword ptr 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
156
157 ; Check if signature and plaform ID match
158 cmp ebx, [esi].ucode_hdr.processor
159 jne @f
160 test edx, [esi].ucode_hdr.flags
161 jnz load_check ; Jif signature and platform ID match
162
163 @@:
164 ; Check if extended header exists
165 ; First check if total_size and data_size are valid
166 xor eax, eax
167 cmp [esi].ucode_hdr.total_size, eax
168 je next_microcode
169 cmp [esi].ucode_hdr.data_size, eax
170 je next_microcode
171
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
177
178 ; Set edi -> extended header
179 mov edi, esi
180 add edi, sizeof ucode_hdr
181 add edi, [esi].ucode_hdr.data_size
182
183 ; Get count of extended structures
184 mov ecx, [edi].ext_sig_hdr.count
185
186 ; Move pointer to first signature structure
187 add edi, sizeof ext_sig_hdr
188
189 check_ext_sig:
190 ; Check if extended signature and platform ID match
191 cmp [edi].ext_sig.processor, ebx
192 jne @f
193 test [edi].ext_sig.flags, edx
194 jnz load_check ; Jif signature and platform ID match
195 @@:
196 ; Check if any more extended signatures exist
197 add edi, sizeof ext_sig
198 loop check_ext_sig
199
200 next_microcode:
201 ; Advance just after end of this microcode
202 xor eax, eax
203 cmp [esi].ucode_hdr.total_size, eax
204 je @f
205 add esi, [esi].ucode_hdr.total_size
206 jmp check_address
207 @@:
208 add esi, dword ptr 2048
209 jmp check_address
210
211 advance_fixed_size:
212 ; Advance by 4X dwords
213 add esi, dword ptr 1024
214
215 check_address:
216 ; Is valid Microcode start point ?
217 cmp dword ptr [esi], 0ffffffffh
218 jz done
219
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
223 cmp esi, eax
224 jae done ;Jif address is outside of ucode region
225 jmp check_main_header
226
227 load_check:
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
233
234 mov eax, 1
235 cpuid
236 mov ecx, MSR_IA32_BIOS_SIGN_ID
237 rdmsr ; Get current microcode signature
238
239 ; Verify this microcode update is not already loaded
240 cmp [esi].ucode_hdr.revision, edx
241 je continue
242
243 load_microcode:
244 ; EAX contains the linear address of the start of the Update Data
245 ; EDX contains zero
246 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
247 ; Start microcode load with wrmsr
248 mov eax, esi
249 add eax, sizeof ucode_hdr
250 xor edx, edx
251 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
252 wrmsr
253 mov eax, 1
254 cpuid
255
256 continue:
257 jmp next_microcode
258
259 done:
260 mov eax, 1
261 cpuid
262 mov ecx, MSR_IA32_BIOS_SIGN_ID
263 rdmsr ; Get current microcode signature
264 xor eax, eax
265 cmp edx, 0
266 jnz exit
267 mov eax, 08000000Eh
268
269 exit:
270 jmp ebp
271
272 LoadUcodeDflt ENDP
273
274 ;----------------------------------------------------------------------------
275 ; TempRamInit API
276 ;
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.
280 ;
281 ;----------------------------------------------------------------------------
282 TempRamInitApi PROC NEAR PUBLIC
283 ;
284 ; Ensure SSE is enabled
285 ;
286 ENABLE_SSE
287
288 ;
289 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
290 ;
291 SAVE_REGS
292
293 ;
294 ; Save timestamp into XMM4 & XMM5
295 ;
296 rdtsc
297 SAVE_EAX
298 SAVE_EDX
299
300 ;
301 ; Check Parameter
302 ;
303 mov eax, dword ptr [esp + 4]
304 cmp eax, 0
305 mov eax, 80000002h
306 jz NemInitExit
307
308 ;
309 ; CPUID/DeviceID check
310 ;
311 mov eax, @F
312 jmp FspSelfCheck ; Note: ESP can not be changed.
313 @@:
314 cmp eax, 0
315 jnz NemInitExit
316
317 ;
318 ; Platform Basic Init.
319 ;
320 mov eax, @F
321 jmp PlatformBasicInit
322 @@:
323 cmp eax, 0
324 jnz NemInitExit
325
326 ;
327 ; Load microcode
328 ;
329 mov eax, @F
330 add esp, 4
331 jmp LoadUcode
332 @@:
333 LOAD_ESP
334 cmp eax, 0
335 jnz NemInitExit
336
337 ;
338 ; Call platform NEM init
339 ;
340 mov eax, @F
341 add esp, 4
342 jmp PlatformTempRamInit
343 @@:
344 LOAD_ESP
345 cmp eax, 0
346 jnz NemInitExit
347
348 ;
349 ; Save parameter pointer in edx
350 ;
351 mov edx, dword ptr [esp + 4]
352
353 ;
354 ; Enable FSP STACK
355 ;
356 mov esp, PcdGet32(PcdTemporaryRamBase)
357 add esp, PcdGet32(PcdTemporaryRamSize)
358
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
365
366 ;
367 ; Save API entry/exit timestamp into stack
368 ;
369 push DATA_LEN_OF_PER0 ; Size of the data region
370 push 30524550h ; Signature of the data region 'PER0'
371 rdtsc
372 push edx
373 push eax
374 LOAD_EAX
375 LOAD_EDX
376 push edx
377 push eax
378
379 ;
380 ; Terminator for the data on stack
381 ;
382 push 0
383
384 ;
385 ; Set ECX/EDX to the bootloader temporary memory range
386 ;
387 mov ecx, PcdGet32(PcdTemporaryRamBase)
388 mov edx, ecx
389 add edx, PcdGet32(PcdTemporaryRamSize)
390 sub edx, PcdGet32(PcdFspTemporaryRamSize)
391
392 xor eax, eax
393
394 NemInitExit:
395 ;
396 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
397 ;
398 LOAD_REGS
399 ret
400 TempRamInitApi ENDP
401
402 ;----------------------------------------------------------------------------
403 ; FspInit API
404 ;
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.
408 ;
409 ;----------------------------------------------------------------------------
410 FspInitApi PROC NEAR PUBLIC
411 ;
412 ; Stack must be ready
413 ;
414 push 087654321h
415 pop eax
416 cmp eax, 087654321h
417 jz @F
418 mov eax, 080000003h
419 jmp exit
420
421 @@:
422 ;
423 ; Additional check
424 ;
425 pushad
426 push 1
427 call FspApiCallingCheck
428 add esp, 4
429 mov dword ptr [esp + 4 * 7], eax
430 popad
431 cmp eax, 0
432 jz @F
433 jmp exit
434
435 @@:
436 ;
437 ; Store the address in FSP which will return control to the BL
438 ;
439 push offset exit
440
441 ;
442 ; Create a Task Frame in the stack for the Boot Loader
443 ;
444 pushfd ; 2 pushf for 4 byte alignment
445 cli
446 pushad
447
448 ; Reserve 8 bytes for IDT save/restore
449 sub esp, 8
450 sidt fword ptr [esp]
451
452 ;
453 ; Setup new FSP stack
454 ;
455 mov eax, esp
456 mov esp, PcdGet32(PcdTemporaryRamBase)
457 add esp, PcdGet32(PcdTemporaryRamSize)
458 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
459
460 ;
461 ; Save the bootloader's stack pointer
462 ;
463 push eax
464
465 ;
466 ; Pass entry point of the PEI core
467 ;
468 call GetFspBaseAddress
469 mov edi, FspImageSizeOffset
470 mov edi, DWORD PTR [eax + edi]
471 add edi, eax
472 sub edi, 20h
473 add eax, DWORD PTR [edi]
474 push eax
475
476 ;
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.
482 ;
483 call GetFspBaseAddress
484 mov edi, eax
485 call GetBootFirmwareVolumeOffset
486 add eax, edi
487 push eax
488
489 ;
490 ; Pass stack base and size into the PEI Core
491 ;
492 mov eax, PcdGet32(PcdTemporaryRamBase)
493 add eax, PcdGet32(PcdTemporaryRamSize)
494 sub eax, PcdGet32(PcdFspTemporaryRamSize)
495 push eax
496 push PcdGet32(PcdFspTemporaryRamSize)
497
498 ;
499 ; Pass Control into the PEI Core
500 ;
501 call SecStartup
502
503 exit:
504 ret
505
506 FspInitApi ENDP
507
508 ;----------------------------------------------------------------------------
509 ; NotifyPhase API
510 ;
511 ; This FSP API will notify the FSP about the different phases in the boot
512 ; process
513 ;
514 ;----------------------------------------------------------------------------
515 NotifyPhaseApi PROC C PUBLIC
516 ;
517 ; Stack must be ready
518 ;
519 push 087654321h
520 pop eax
521 cmp eax, 087654321h
522 jz @F
523 mov eax, 080000003h
524 jmp err_exit
525
526 @@:
527 ;
528 ; Verify the calling condition
529 ;
530 pushad
531 push 2
532 call FspApiCallingCheck
533 add esp, 4
534 mov dword ptr [esp + 4 * 7], eax
535 popad
536
537 cmp eax, 0
538 jz @F
539
540 ;
541 ; Error return
542 ;
543 err_exit:
544 ret
545
546 @@:
547 jmp Pei2LoaderSwitchStack
548
549 NotifyPhaseApi ENDP
550
551
552 END