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