a01b3c2d49c378453a52b1c61b6b8d2589b34e2d
[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 MicrocodeLoad.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 AsmGetFspBaseAddress:PROC
41 EXTERN AsmGetFspInfoHeader:PROC
42 EXTERN GetBootFirmwareVolumeOffset:PROC
43 EXTERN Loader2PeiSwitchStack:PROC
44 EXTERN LoadMicrocode(LoadMicrocodeDefault):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 ; move ReturnAddress from MMX to ESI
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 SecPlatformInitDefault PROC NEAR PUBLIC
86 ; Inputs:
87 ; mm7 -> 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 movd ebp, mm7
96
97 xor eax, eax
98 exit:
99 jmp ebp
100 SecPlatformInitDefault ENDP
101
102 ;------------------------------------------------------------------------------
103 LoadMicrocodeDefault PROC NEAR PUBLIC
104 ; Inputs:
105 ; esp -> LoadMicrocodeParams pointer
106 ; Register Usage:
107 ; esp Preserved
108 ; All others destroyed
109 ; Assumptions:
110 ; No memory available, stack is hard-coded and used for return address
111 ; Executed by SBSP and NBSP
112 ; Beginning of microcode update region starts on paragraph boundary
113
114 ;
115 ;
116 ; Save return address to EBP
117 movd ebp, mm7
118
119 cmp esp, 0
120 jz paramerror
121 mov eax, dword ptr [esp + 4] ; Parameter pointer
122 cmp eax, 0
123 jz paramerror
124 mov esp, eax
125 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
126 cmp esi, 0
127 jnz check_main_header
128
129 paramerror:
130 mov eax, 080000002h
131 jmp exit
132
133 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
134
135 check_main_header:
136 ; Get processor signature and platform ID from the installed processor
137 ; and save into registers for later use
138 ; ebx = processor signature
139 ; edx = platform ID
140 mov eax, 1
141 cpuid
142 mov ebx, eax
143 mov ecx, MSR_IA32_PLATFORM_ID
144 rdmsr
145 mov ecx, edx
146 shr ecx, 50-32
147 and ecx, 7h
148 mov edx, 1
149 shl edx, cl
150
151 ; Current register usage
152 ; esp -> stack with paramters
153 ; esi -> microcode update to check
154 ; ebx = processor signature
155 ; edx = platform ID
156
157 ; Check for valid microcode header
158 ; Minimal test checking for header version and loader version as 1
159 mov eax, dword ptr 1
160 cmp [esi].MicrocodeHdr.MicrocodeHdrVersion, eax
161 jne advance_fixed_size
162 cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
163 jne advance_fixed_size
164
165 ; Check if signature and plaform ID match
166 cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
167 jne @f
168 test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
169 jnz load_check ; Jif signature and platform ID match
170
171 @@:
172 ; Check if extended header exists
173 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
174 xor eax, eax
175 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
176 je next_microcode
177 cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
178 je next_microcode
179
180 ; Then verify total size - sizeof header > data size
181 mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
182 sub ecx, sizeof MicrocodeHdr
183 cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
184 jng next_microcode ; Jif extended header does not exist
185
186 ; Set edi -> extended header
187 mov edi, esi
188 add edi, sizeof MicrocodeHdr
189 add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
190
191 ; Get count of extended structures
192 mov ecx, [edi].ExtSigHdr.ExtSigHdrCount
193
194 ; Move pointer to first signature structure
195 add edi, sizeof ExtSigHdr
196
197 check_ext_sig:
198 ; Check if extended signature and platform ID match
199 cmp [edi].ExtSig.ExtSigProcessor, ebx
200 jne @f
201 test [edi].ExtSig.ExtSigFlags, edx
202 jnz load_check ; Jif signature and platform ID match
203 @@:
204 ; Check if any more extended signatures exist
205 add edi, sizeof ExtSig
206 loop check_ext_sig
207
208 next_microcode:
209 ; Advance just after end of this microcode
210 xor eax, eax
211 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
212 je @f
213 add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
214 jmp check_address
215 @@:
216 add esi, dword ptr 2048
217 jmp check_address
218
219 advance_fixed_size:
220 ; Advance by 4X dwords
221 add esi, dword ptr 1024
222
223 check_address:
224 ; Is valid Microcode start point ?
225 cmp dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
226 jz done
227
228 ; Is automatic size detection ?
229 mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
230 cmp eax, 0ffffffffh
231 jz @f
232
233 ; Address >= microcode region address + microcode region size?
234 add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
235 cmp esi, eax
236 jae done ;Jif address is outside of microcode region
237 jmp check_main_header
238
239 @@:
240 load_check:
241 ; Get the revision of the current microcode update loaded
242 mov ecx, MSR_IA32_BIOS_SIGN_ID
243 xor eax, eax ; Clear EAX
244 xor edx, edx ; Clear EDX
245 wrmsr ; Load 0 to MSR at 8Bh
246
247 mov eax, 1
248 cpuid
249 mov ecx, MSR_IA32_BIOS_SIGN_ID
250 rdmsr ; Get current microcode signature
251
252 ; Verify this microcode update is not already loaded
253 cmp [esi].MicrocodeHdr.MicrocodeHdrRevision, edx
254 je continue
255
256 load_microcode:
257 ; EAX contains the linear address of the start of the Update Data
258 ; EDX contains zero
259 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
260 ; Start microcode load with wrmsr
261 mov eax, esi
262 add eax, sizeof MicrocodeHdr
263 xor edx, edx
264 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
265 wrmsr
266 mov eax, 1
267 cpuid
268
269 continue:
270 jmp next_microcode
271
272 done:
273 mov eax, 1
274 cpuid
275 mov ecx, MSR_IA32_BIOS_SIGN_ID
276 rdmsr ; Get current microcode signature
277 xor eax, eax
278 cmp edx, 0
279 jnz exit
280 mov eax, 08000000Eh
281
282 exit:
283 jmp ebp
284
285 LoadMicrocodeDefault ENDP
286
287 EstablishStackFsp PROC NEAR PRIVATE
288 ;
289 ; Save parameter pointer in edx
290 ;
291 mov edx, dword ptr [esp + 4]
292
293 ;
294 ; Enable FSP STACK
295 ;
296 mov esp, PcdGet32 (PcdTemporaryRamBase)
297 add esp, PcdGet32 (PcdTemporaryRamSize)
298
299 push DATA_LEN_OF_MCUD ; Size of the data region
300 push 4455434Dh ; Signature of the data region 'MCUD'
301 push dword ptr [edx + 12] ; Code size
302 push dword ptr [edx + 8] ; Code base
303 push dword ptr [edx + 4] ; Microcode size
304 push dword ptr [edx] ; Microcode base
305
306 ;
307 ; Save API entry/exit timestamp into stack
308 ;
309 push DATA_LEN_OF_PER0 ; Size of the data region
310 push 30524550h ; Signature of the data region 'PER0'
311 LOAD_EDX
312 push edx
313 LOAD_EAX
314 push eax
315 rdtsc
316 push edx
317 push eax
318
319 ;
320 ; Terminator for the data on stack
321 ;
322 push 0
323
324 ;
325 ; Set ECX/EDX to the BootLoader temporary memory range
326 ;
327 mov ecx, PcdGet32 (PcdTemporaryRamBase)
328 mov edx, ecx
329 add edx, PcdGet32 (PcdTemporaryRamSize)
330 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
331
332 xor eax, eax
333
334 RET_ESI
335
336 EstablishStackFsp ENDP
337
338
339 ;----------------------------------------------------------------------------
340 ; TempRamInit API
341 ;
342 ; This FSP API will load the microcode update, enable code caching for the
343 ; region specified by the boot loader and also setup a temporary stack to be
344 ; used till main memory is initialized.
345 ;
346 ;----------------------------------------------------------------------------
347 TempRamInitApi PROC NEAR PUBLIC
348 ;
349 ; Ensure SSE is enabled
350 ;
351 ENABLE_SSE
352
353 ;
354 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
355 ;
356 SAVE_REGS
357
358 ;
359 ; Save timestamp into XMM6
360 ;
361 rdtsc
362 SAVE_EAX
363 SAVE_EDX
364
365 ;
366 ; Check Parameter
367 ;
368 mov eax, dword ptr [esp + 4]
369 cmp eax, 0
370 mov eax, 80000002h
371 jz NemInitExit
372
373 ;
374 ; Sec Platform Init
375 ;
376 CALL_MMX SecPlatformInit
377 cmp eax, 0
378 jnz NemInitExit
379
380 ; Load microcode
381 LOAD_ESP
382 CALL_MMX LoadMicrocode
383 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
384 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
385
386 ; Call Sec CAR Init
387 LOAD_ESP
388 CALL_MMX SecCarInit
389 cmp eax, 0
390 jnz NemInitExit
391
392 LOAD_ESP
393 CALL_MMX EstablishStackFsp
394
395 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
396
397 NemInitExit:
398 ;
399 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
400 ;
401 LOAD_REGS
402 ret
403 TempRamInitApi ENDP
404
405 ;----------------------------------------------------------------------------
406 ; FspInit API
407 ;
408 ; This FSP API will perform the processor and chipset initialization.
409 ; This API will not return. Instead, it transfers the control to the
410 ; ContinuationFunc provided in the parameter.
411 ;
412 ;----------------------------------------------------------------------------
413 FspInitApi PROC NEAR PUBLIC
414 mov eax, 1
415 jmp FspApiCommon
416 FspInitApi ENDP
417
418 ;----------------------------------------------------------------------------
419 ; NotifyPhase API
420 ;
421 ; This FSP API will notify the FSP about the different phases in the boot
422 ; process
423 ;
424 ;----------------------------------------------------------------------------
425 NotifyPhaseApi PROC C PUBLIC
426 mov eax, 2
427 jmp FspApiCommon
428 NotifyPhaseApi ENDP
429
430 ;----------------------------------------------------------------------------
431 ; FspMemoryInit API
432 ;
433 ; This FSP API is called after TempRamInit and initializes the memory.
434 ;
435 ;----------------------------------------------------------------------------
436 FspMemoryInitApi PROC NEAR PUBLIC
437 mov eax, 3
438 jmp FspApiCommon
439 FspMemoryInitApi ENDP
440
441
442 ;----------------------------------------------------------------------------
443 ; TempRamExitApi API
444 ;
445 ; This API tears down temporary RAM
446 ;
447 ;----------------------------------------------------------------------------
448 TempRamExitApi PROC C PUBLIC
449 mov eax, 4
450 jmp FspApiCommon
451 TempRamExitApi ENDP
452
453
454 ;----------------------------------------------------------------------------
455 ; FspSiliconInit API
456 ;
457 ; This FSP API initializes the CPU and the chipset including the IO
458 ; controllers in the chipset to enable normal operation of these devices.
459 ;
460 ;----------------------------------------------------------------------------
461 FspSiliconInitApi PROC C PUBLIC
462 mov eax, 5
463 jmp FspApiCommon
464 FspSiliconInitApi ENDP
465
466 ;----------------------------------------------------------------------------
467 ; FspApiCommon API
468 ;
469 ; This is the FSP API common entry point to resume the FSP execution
470 ;
471 ;----------------------------------------------------------------------------
472 FspApiCommon PROC C PUBLIC
473 ;
474 ; EAX holds the API index
475 ;
476
477 ;
478 ; Stack must be ready
479 ;
480 push eax
481 add esp, 4
482 cmp eax, dword ptr [esp - 4]
483 jz @F
484 mov eax, 080000003h
485 jmp exit
486
487 @@:
488 ;
489 ; Verify the calling condition
490 ;
491 pushad
492 push [esp + 4 * 8 + 4]
493 push eax
494 call FspApiCallingCheck
495 add esp, 8
496 cmp eax, 0
497 jz @F
498 mov dword ptr [esp + 4 * 7], eax
499 popad
500 ret
501
502 @@:
503 popad
504 cmp eax, 1 ; FspInit API
505 jz @F
506 cmp eax, 3 ; FspMemoryInit API
507 jz @F
508
509 call AsmGetFspInfoHeader
510 jmp Loader2PeiSwitchStack
511
512 @@:
513 ;
514 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
515 ;
516
517 ;
518 ; Place holder to store the FspInfoHeader pointer
519 ;
520 push eax
521
522 ;
523 ; Update the FspInfoHeader pointer
524 ;
525 push eax
526 call AsmGetFspInfoHeader
527 mov [esp + 4], eax
528 pop eax
529
530 ;
531 ; Create a Task Frame in the stack for the Boot Loader
532 ;
533 pushfd ; 2 pushf for 4 byte alignment
534 cli
535 pushad
536
537 ; Reserve 8 bytes for IDT save/restore
538 sub esp, 8
539 sidt fword ptr [esp]
540
541 ;
542 ; Setup new FSP stack
543 ;
544 mov edi, esp
545 mov esp, PcdGet32(PcdTemporaryRamBase)
546 add esp, PcdGet32(PcdTemporaryRamSize)
547 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
548
549 ;
550 ; Pass the API Idx to SecStartup
551 ;
552 push eax
553
554 ;
555 ; Pass the BootLoader stack to SecStartup
556 ;
557 push edi
558
559 ;
560 ; Pass entry point of the PEI core
561 ;
562 call AsmGetFspBaseAddress
563 mov edi, eax
564 add edi, PcdGet32 (PcdFspAreaSize)
565 sub edi, 20h
566 add eax, DWORD PTR ds:[edi]
567 push eax
568
569 ;
570 ; Pass BFV into the PEI Core
571 ; It uses relative address to calucate the actual boot FV base
572 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
573 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
574 ; they are different. The code below can handle both cases.
575 ;
576 call AsmGetFspBaseAddress
577 mov edi, eax
578 call GetBootFirmwareVolumeOffset
579 add eax, edi
580 push eax
581
582 ;
583 ; Pass stack base and size into the PEI Core
584 ;
585 mov eax, PcdGet32(PcdTemporaryRamBase)
586 add eax, PcdGet32(PcdTemporaryRamSize)
587 sub eax, PcdGet32(PcdFspTemporaryRamSize)
588 push eax
589 push PcdGet32(PcdFspTemporaryRamSize)
590
591 ;
592 ; Pass Control into the PEI Core
593 ;
594 call SecStartup
595 add esp, 4
596 exit:
597 ret
598
599 FspApiCommon ENDP
600
601 END