c33e17b7ce4fb6fc961f14e683b70feea0d86eaf
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.asm
1 ;; @file
2 ; Provide FSP API entry points.
3 ;
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.
9 ;
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.
12 ;;
13
14 .586p
15 .model flat,C
16 .code
17 .xmm
18
19 INCLUDE SaveRestoreSse.inc
20 INCLUDE UcodeLoad.inc
21
22 ;
23 ; Following are fixed PCDs
24 ;
25 EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
26 EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
27 EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
28 EXTERN PcdGet32(PcdFspAreaSize):DWORD
29
30 ;
31 ; Following functions will be provided in C
32 ;
33
34 EXTERN SecStartup:PROC
35 EXTERN FspApiCallingCheck:PROC
36
37 ;
38 ; Following functions will be provided in PlatformSecLib
39 ;
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
47
48 ;
49 ; Define the data length that we saved on the stack top
50 ;
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)
54
55 ;
56 ; Define SSE macros
57 ;
58 LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
59 mov esi, ReturnAddress
60 movd MmxRegister, esi ; save ReturnAddress into MMX
61 ENDM
62
63 CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
64 local ReturnAddress
65 mov esi, offset ReturnAddress
66 movd MmxRegister, esi ; save ReturnAddress into MMX
67 jmp RoutineLabel
68 ReturnAddress:
69 ENDM
70
71 RET_ESI_EXT MACRO MmxRegister
72 movd esi, MmxRegister ; restore ESP from MMX
73 jmp esi
74 ENDM
75
76 CALL_MMX MACRO RoutineLabel
77 CALL_MMX_EXT RoutineLabel, mm7
78 ENDM
79
80 RET_ESI MACRO
81 RET_ESI_EXT mm7
82 ENDM
83
84 ;------------------------------------------------------------------------------
85 FspSelfCheckDefault PROC NEAR PUBLIC
86 ; Inputs:
87 ; eax -> Return address
88 ; Outputs:
89 ; eax -> 0 - Successful, Non-zero - Failed.
90 ; Register Usage:
91 ; eax is cleared and ebp is used for return address.
92 ; All others reserved.
93
94 ; Save return address to EBP
95 mov ebp, eax
96
97 xor eax, eax
98 exit:
99 jmp ebp
100 FspSelfCheckDefault ENDP
101
102 ;------------------------------------------------------------------------------
103 SecPlatformInitDefault PROC NEAR PUBLIC
104 ; Inputs:
105 ; mm7 -> Return address
106 ; Outputs:
107 ; eax -> 0 - Successful, Non-zero - Failed.
108 ; Register Usage:
109 ; eax is cleared and ebp is used for return address.
110 ; All others reserved.
111
112 ; Save return address to EBP
113 mov ebp, mm7
114
115 xor eax, eax
116 exit:
117 jmp ebp
118 SecPlatformInitDefault ENDP
119
120 ;------------------------------------------------------------------------------
121 LoadUcodeDefault PROC NEAR PUBLIC
122 ; Inputs:
123 ; esp -> LOAD_UCODE_PARAMS pointer
124 ; Register Usage:
125 ; esp Preserved
126 ; All others destroyed
127 ; Assumptions:
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
131
132 ;
133 ;
134 ; Save return address to EBP
135 movd ebp, mm7
136
137 cmp esp, 0
138 jz paramerror
139 mov eax, dword ptr [esp] ; Parameter pointer
140 cmp eax, 0
141 jz paramerror
142 mov esp, eax
143 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
144 cmp esi, 0
145 jnz check_main_header
146
147 paramerror:
148 mov eax, 080000002h
149 jmp exit
150
151 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
152
153 check_main_header:
154 ; Get processor signature and platform ID from the installed processor
155 ; and save into registers for later use
156 ; ebx = processor signature
157 ; edx = platform ID
158 mov eax, 1
159 cpuid
160 mov ebx, eax
161 mov ecx, MSR_IA32_PLATFORM_ID
162 rdmsr
163 mov ecx, edx
164 shr ecx, 50-32
165 and ecx, 7h
166 mov edx, 1
167 shl edx, cl
168
169 ; Current register usage
170 ; esp -> stack with paramters
171 ; esi -> microcode update to check
172 ; ebx = processor signature
173 ; edx = platform ID
174
175 ; Check for valid microcode header
176 ; Minimal test checking for header version and loader version as 1
177 mov eax, dword ptr 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
182
183 ; Check if signature and plaform ID match
184 cmp ebx, [esi].ucode_hdr.processor
185 jne @f
186 test edx, [esi].ucode_hdr.flags
187 jnz load_check ; Jif signature and platform ID match
188
189 @@:
190 ; Check if extended header exists
191 ; First check if total_size and data_size are valid
192 xor eax, eax
193 cmp [esi].ucode_hdr.total_size, eax
194 je next_microcode
195 cmp [esi].ucode_hdr.data_size, eax
196 je next_microcode
197
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
203
204 ; Set edi -> extended header
205 mov edi, esi
206 add edi, sizeof ucode_hdr
207 add edi, [esi].ucode_hdr.data_size
208
209 ; Get count of extended structures
210 mov ecx, [edi].ext_sig_hdr.count
211
212 ; Move pointer to first signature structure
213 add edi, sizeof ext_sig_hdr
214
215 check_ext_sig:
216 ; Check if extended signature and platform ID match
217 cmp [edi].ext_sig.processor, ebx
218 jne @f
219 test [edi].ext_sig.flags, edx
220 jnz load_check ; Jif signature and platform ID match
221 @@:
222 ; Check if any more extended signatures exist
223 add edi, sizeof ext_sig
224 loop check_ext_sig
225
226 next_microcode:
227 ; Advance just after end of this microcode
228 xor eax, eax
229 cmp [esi].ucode_hdr.total_size, eax
230 je @f
231 add esi, [esi].ucode_hdr.total_size
232 jmp check_address
233 @@:
234 add esi, dword ptr 2048
235 jmp check_address
236
237 advance_fixed_size:
238 ; Advance by 4X dwords
239 add esi, dword ptr 1024
240
241 check_address:
242 ; Is valid Microcode start point ?
243 cmp dword ptr [esi].ucode_hdr.version, 0ffffffffh
244 jz done
245
246 ; Is automatic size detection ?
247 mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_size
248 cmp eax, 0ffffffffh
249 jz @f
250
251 ; Address >= microcode region address + microcode region size?
252 add eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
253 cmp esi, eax
254 jae done ;Jif address is outside of ucode region
255 jmp check_main_header
256
257 @@:
258 load_check:
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
264
265 mov eax, 1
266 cpuid
267 mov ecx, MSR_IA32_BIOS_SIGN_ID
268 rdmsr ; Get current microcode signature
269
270 ; Verify this microcode update is not already loaded
271 cmp [esi].ucode_hdr.revision, edx
272 je continue
273
274 load_microcode:
275 ; EAX contains the linear address of the start of the Update Data
276 ; EDX contains zero
277 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
278 ; Start microcode load with wrmsr
279 mov eax, esi
280 add eax, sizeof ucode_hdr
281 xor edx, edx
282 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
283 wrmsr
284 mov eax, 1
285 cpuid
286
287 continue:
288 jmp next_microcode
289
290 done:
291 mov eax, 1
292 cpuid
293 mov ecx, MSR_IA32_BIOS_SIGN_ID
294 rdmsr ; Get current microcode signature
295 xor eax, eax
296 cmp edx, 0
297 jnz exit
298 mov eax, 08000000Eh
299
300 exit:
301 jmp ebp
302
303 LoadUcodeDefault ENDP
304
305 EstablishStackFsp PROC NEAR PRIVATE
306 ;
307 ; Save parameter pointer in edx
308 ;
309 mov edx, dword ptr [esp + 4]
310
311 ;
312 ; Enable FSP STACK
313 ;
314 mov esp, PcdGet32 (PcdTemporaryRamBase)
315 add esp, PcdGet32 (PcdTemporaryRamSize)
316
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
325 jmp @F
326
327 InvalidMicrocodeRegion:
328 push 0 ; Microcode size
329 push 0 ; Microcode base
330
331 @@:
332 ;
333 ; Save API entry/exit timestamp into stack
334 ;
335 push DATA_LEN_OF_PER0 ; Size of the data region
336 push 30524550h ; Signature of the data region 'PER0'
337 LOAD_EDX
338 push edx
339 LOAD_EAX
340 push eax
341 rdtsc
342 push edx
343 push eax
344
345 ;
346 ; Terminator for the data on stack
347 ;
348 push 0
349
350 ;
351 ; Set ECX/EDX to the bootloader temporary memory range
352 ;
353 mov ecx, PcdGet32 (PcdTemporaryRamBase)
354 mov edx, ecx
355 add edx, PcdGet32 (PcdTemporaryRamSize)
356 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
357
358 xor eax, eax
359
360 RET_ESI
361
362 EstablishStackFsp ENDP
363
364
365 ;----------------------------------------------------------------------------
366 ; TempRamInit API
367 ;
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.
371 ;
372 ;----------------------------------------------------------------------------
373 TempRamInitApi PROC NEAR PUBLIC
374 ;
375 ; Ensure SSE is enabled
376 ;
377 ENABLE_SSE
378
379 ;
380 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
381 ;
382 SAVE_REGS
383
384 ;
385 ; Save timestamp into XMM6
386 ;
387 rdtsc
388 SAVE_EAX
389 SAVE_EDX
390
391 ;
392 ; Check Parameter
393 ;
394 mov eax, dword ptr [esp + 4]
395 cmp eax, 0
396 mov eax, 80000002h
397 jz NemInitExit
398
399 ;
400 ; CPUID/DeviceID check
401 ;
402 mov eax, @F
403 jmp FspSelfCheck ; Note: ESP can not be changed.
404 @@:
405 cmp eax, 0
406 jnz NemInitExit
407
408 CALL_MMX SecPlatformInit
409 cmp eax, 0
410 jnz NemInitExit
411
412 ; Load microcode
413 LOAD_ESP
414 CALL_MMX LoadUcode
415 cmp eax, 0
416 jnz NemInitExit
417
418 ; Call Sec CAR Init
419 LOAD_ESP
420 CALL_MMX SecCarInit
421 cmp eax, 0
422 jnz NemInitExit
423
424 LOAD_ESP
425 CALL_MMX EstablishStackFsp
426
427 NemInitExit:
428 ;
429 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
430 ;
431 LOAD_REGS
432 ret
433 TempRamInitApi ENDP
434
435 ;----------------------------------------------------------------------------
436 ; FspInit API
437 ;
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.
441 ;
442 ;----------------------------------------------------------------------------
443 FspInitApi PROC NEAR PUBLIC
444 mov eax, 1
445 jmp FspApiCommon
446 FspInitApi ENDP
447
448 ;----------------------------------------------------------------------------
449 ; NotifyPhase API
450 ;
451 ; This FSP API will notify the FSP about the different phases in the boot
452 ; process
453 ;
454 ;----------------------------------------------------------------------------
455 NotifyPhaseApi PROC C PUBLIC
456 mov eax, 2
457 jmp FspApiCommon
458 NotifyPhaseApi ENDP
459
460 ;----------------------------------------------------------------------------
461 ; FspMemoryInit API
462 ;
463 ; This FSP API is called after TempRamInit and initializes the memory.
464 ;
465 ;----------------------------------------------------------------------------
466 FspMemoryInitApi PROC NEAR PUBLIC
467 mov eax, 3
468 jmp FspApiCommon
469 FspMemoryInitApi ENDP
470
471
472 ;----------------------------------------------------------------------------
473 ; TempRamExitApi API
474 ;
475 ; This API tears down temporary RAM
476 ;
477 ;----------------------------------------------------------------------------
478 TempRamExitApi PROC C PUBLIC
479 mov eax, 4
480 jmp FspApiCommon
481 TempRamExitApi ENDP
482
483
484 ;----------------------------------------------------------------------------
485 ; FspSiliconInit API
486 ;
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.
489 ;
490 ;----------------------------------------------------------------------------
491 FspSiliconInitApi PROC C PUBLIC
492 mov eax, 5
493 jmp FspApiCommon
494 FspSiliconInitApi ENDP
495
496 ;----------------------------------------------------------------------------
497 ; FspApiCommon API
498 ;
499 ; This is the FSP API common entry point to resume the FSP execution
500 ;
501 ;----------------------------------------------------------------------------
502 FspApiCommon PROC C PUBLIC
503 ;
504 ; EAX holds the API index
505 ;
506
507 ;
508 ; Stack must be ready
509 ;
510 push eax
511 add esp, 4
512 cmp eax, dword ptr [esp - 4]
513 jz @F
514 mov eax, 080000003h
515 jmp exit
516
517 @@:
518 ;
519 ; Verify the calling condition
520 ;
521 pushad
522 push eax
523 call FspApiCallingCheck
524 add esp, 4
525 cmp eax, 0
526 jz @F
527 mov dword ptr [esp + 4 * 7], eax
528 popad
529 ret
530
531 @@:
532 popad
533 cmp eax, 1 ; FspInit API
534 jz @F
535 cmp eax, 3 ; FspMemoryInit API
536 jz @F
537 jmp Pei2LoaderSwitchStack
538
539 @@:
540 ;
541 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
542 ;
543
544 ;
545 ; Store the address in FSP which will return control to the BL
546 ;
547 push offset exit
548
549 ;
550 ; Create a Task Frame in the stack for the Boot Loader
551 ;
552 pushfd ; 2 pushf for 4 byte alignment
553 cli
554 pushad
555
556 ; Reserve 8 bytes for IDT save/restore
557 sub esp, 8
558 sidt fword ptr [esp]
559
560 ;
561 ; Setup new FSP stack
562 ;
563 mov edi, esp
564 mov esp, PcdGet32(PcdTemporaryRamBase)
565 add esp, PcdGet32(PcdTemporaryRamSize)
566 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
567
568 ;
569 ; Pass the API Idx to SecStartup
570 ;
571 push eax
572
573 ;
574 ; Pass the bootloader stack to SecStartup
575 ;
576 push edi
577
578 ;
579 ; Pass entry point of the PEI core
580 ;
581 call GetFspBaseAddress
582 mov edi, eax
583 add edi, PcdGet32 (PcdFspAreaSize)
584 sub edi, 20h
585 add eax, DWORD PTR ds:[edi]
586 push eax
587
588 ;
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.
594 ;
595 call GetFspBaseAddress
596 mov edi, eax
597 call GetBootFirmwareVolumeOffset
598 add eax, edi
599 push eax
600
601 ;
602 ; Pass stack base and size into the PEI Core
603 ;
604 mov eax, PcdGet32(PcdTemporaryRamBase)
605 add eax, PcdGet32(PcdTemporaryRamSize)
606 sub eax, PcdGet32(PcdFspTemporaryRamSize)
607 push eax
608 push PcdGet32(PcdFspTemporaryRamSize)
609
610 ;
611 ; Pass Control into the PEI Core
612 ;
613 call SecStartup
614
615 exit:
616 ret
617
618 FspApiCommon ENDP
619
620 END