Update IntelFspPkg to support 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 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 GetFspBaseAddress:PROC
41 EXTERN GetBootFirmwareVolumeOffset:PROC
42 EXTERN Pei2LoaderSwitchStack:PROC
43 EXTERN LoadMicrocode(LoadMicrocodeDefault):PROC
44 EXTERN SecPlatformInit(SecPlatformInitDefault):PROC
45 EXTERN SecCarInit:PROC
46
47 ;
48 ; Define the data length that we saved on the stack top
49 ;
50 DATA_LEN_OF_PER0 EQU 18h
51 DATA_LEN_OF_MCUD EQU 18h
52 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
53
54 ;
55 ; Define SSE macros
56 ;
57 LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
58 mov esi, ReturnAddress
59 movd MmxRegister, esi ; save ReturnAddress into MMX
60 ENDM
61
62 CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
63 local ReturnAddress
64 mov esi, offset ReturnAddress
65 movd MmxRegister, esi ; save ReturnAddress into MMX
66 jmp RoutineLabel
67 ReturnAddress:
68 ENDM
69
70 RET_ESI_EXT MACRO MmxRegister
71 movd esi, MmxRegister ; move ReturnAddress from MMX to ESI
72 jmp esi
73 ENDM
74
75 CALL_MMX MACRO RoutineLabel
76 CALL_MMX_EXT RoutineLabel, mm7
77 ENDM
78
79 RET_ESI MACRO
80 RET_ESI_EXT mm7
81 ENDM
82
83 ;------------------------------------------------------------------------------
84 SecPlatformInitDefault PROC NEAR PUBLIC
85 ; Inputs:
86 ; mm7 -> Return address
87 ; Outputs:
88 ; eax -> 0 - Successful, Non-zero - Failed.
89 ; Register Usage:
90 ; eax is cleared and ebp is used for return address.
91 ; All others reserved.
92
93 ; Save return address to EBP
94 movd ebp, mm7
95
96 xor eax, eax
97 exit:
98 jmp ebp
99 SecPlatformInitDefault ENDP
100
101 ;------------------------------------------------------------------------------
102 LoadMicrocodeDefault PROC NEAR PUBLIC
103 ; Inputs:
104 ; esp -> LoadMicrocodeParams pointer
105 ; Register Usage:
106 ; esp Preserved
107 ; All others destroyed
108 ; Assumptions:
109 ; No memory available, stack is hard-coded and used for return address
110 ; Executed by SBSP and NBSP
111 ; Beginning of microcode update region starts on paragraph boundary
112
113 ;
114 ;
115 ; Save return address to EBP
116 movd ebp, mm7
117
118 cmp esp, 0
119 jz paramerror
120 mov eax, dword ptr [esp + 4] ; Parameter pointer
121 cmp eax, 0
122 jz paramerror
123 mov esp, eax
124 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
125 cmp esi, 0
126 jnz check_main_header
127
128 paramerror:
129 mov eax, 080000002h
130 jmp exit
131
132 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
133
134 check_main_header:
135 ; Get processor signature and platform ID from the installed processor
136 ; and save into registers for later use
137 ; ebx = processor signature
138 ; edx = platform ID
139 mov eax, 1
140 cpuid
141 mov ebx, eax
142 mov ecx, MSR_IA32_PLATFORM_ID
143 rdmsr
144 mov ecx, edx
145 shr ecx, 50-32
146 and ecx, 7h
147 mov edx, 1
148 shl edx, cl
149
150 ; Current register usage
151 ; esp -> stack with paramters
152 ; esi -> microcode update to check
153 ; ebx = processor signature
154 ; edx = platform ID
155
156 ; Check for valid microcode header
157 ; Minimal test checking for header version and loader version as 1
158 mov eax, dword ptr 1
159 cmp [esi].MicrocodeHdr.MicrocodeHdrVersion, eax
160 jne advance_fixed_size
161 cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
162 jne advance_fixed_size
163
164 ; Check if signature and plaform ID match
165 cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
166 jne @f
167 test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
168 jnz load_check ; Jif signature and platform ID match
169
170 @@:
171 ; Check if extended header exists
172 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
173 xor eax, eax
174 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
175 je next_microcode
176 cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
177 je next_microcode
178
179 ; Then verify total size - sizeof header > data size
180 mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
181 sub ecx, sizeof MicrocodeHdr
182 cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
183 jng next_microcode ; Jif extended header does not exist
184
185 ; Set edi -> extended header
186 mov edi, esi
187 add edi, sizeof MicrocodeHdr
188 add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
189
190 ; Get count of extended structures
191 mov ecx, [edi].ExtSigHdr.ExtSigHdrCount
192
193 ; Move pointer to first signature structure
194 add edi, sizeof ExtSigHdr
195
196 check_ext_sig:
197 ; Check if extended signature and platform ID match
198 cmp [edi].ExtSig.ExtSigProcessor, ebx
199 jne @f
200 test [edi].ExtSig.ExtSigFlags, edx
201 jnz load_check ; Jif signature and platform ID match
202 @@:
203 ; Check if any more extended signatures exist
204 add edi, sizeof ExtSig
205 loop check_ext_sig
206
207 next_microcode:
208 ; Advance just after end of this microcode
209 xor eax, eax
210 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
211 je @f
212 add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
213 jmp check_address
214 @@:
215 add esi, dword ptr 2048
216 jmp check_address
217
218 advance_fixed_size:
219 ; Advance by 4X dwords
220 add esi, dword ptr 1024
221
222 check_address:
223 ; Is valid Microcode start point ?
224 cmp dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
225 jz done
226
227 ; Is automatic size detection ?
228 mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
229 cmp eax, 0ffffffffh
230 jz @f
231
232 ; Address >= microcode region address + microcode region size?
233 add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
234 cmp esi, eax
235 jae done ;Jif address is outside of microcode region
236 jmp check_main_header
237
238 @@:
239 load_check:
240 ; Get the revision of the current microcode update loaded
241 mov ecx, MSR_IA32_BIOS_SIGN_ID
242 xor eax, eax ; Clear EAX
243 xor edx, edx ; Clear EDX
244 wrmsr ; Load 0 to MSR at 8Bh
245
246 mov eax, 1
247 cpuid
248 mov ecx, MSR_IA32_BIOS_SIGN_ID
249 rdmsr ; Get current microcode signature
250
251 ; Verify this microcode update is not already loaded
252 cmp [esi].MicrocodeHdr.MicrocodeHdrRevision, edx
253 je continue
254
255 load_microcode:
256 ; EAX contains the linear address of the start of the Update Data
257 ; EDX contains zero
258 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
259 ; Start microcode load with wrmsr
260 mov eax, esi
261 add eax, sizeof MicrocodeHdr
262 xor edx, edx
263 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
264 wrmsr
265 mov eax, 1
266 cpuid
267
268 continue:
269 jmp next_microcode
270
271 done:
272 mov eax, 1
273 cpuid
274 mov ecx, MSR_IA32_BIOS_SIGN_ID
275 rdmsr ; Get current microcode signature
276 xor eax, eax
277 cmp edx, 0
278 jnz exit
279 mov eax, 08000000Eh
280
281 exit:
282 jmp ebp
283
284 LoadMicrocodeDefault ENDP
285
286 EstablishStackFsp PROC NEAR PRIVATE
287 ;
288 ; Save parameter pointer in edx
289 ;
290 mov edx, dword ptr [esp + 4]
291
292 ;
293 ; Enable FSP STACK
294 ;
295 mov esp, PcdGet32 (PcdTemporaryRamBase)
296 add esp, PcdGet32 (PcdTemporaryRamSize)
297
298 push DATA_LEN_OF_MCUD ; Size of the data region
299 push 4455434Dh ; Signature of the data region 'MCUD'
300 push dword ptr [edx + 12] ; Code size
301 push dword ptr [edx + 8] ; Code base
302 push dword ptr [edx + 4] ; Microcode size
303 push dword ptr [edx] ; Microcode base
304
305 ;
306 ; Save API entry/exit timestamp into stack
307 ;
308 push DATA_LEN_OF_PER0 ; Size of the data region
309 push 30524550h ; Signature of the data region 'PER0'
310 LOAD_EDX
311 push edx
312 LOAD_EAX
313 push eax
314 rdtsc
315 push edx
316 push eax
317
318 ;
319 ; Terminator for the data on stack
320 ;
321 push 0
322
323 ;
324 ; Set ECX/EDX to the BootLoader temporary memory range
325 ;
326 mov ecx, PcdGet32 (PcdTemporaryRamBase)
327 mov edx, ecx
328 add edx, PcdGet32 (PcdTemporaryRamSize)
329 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
330
331 xor eax, eax
332
333 RET_ESI
334
335 EstablishStackFsp ENDP
336
337
338 ;----------------------------------------------------------------------------
339 ; TempRamInit API
340 ;
341 ; This FSP API will load the microcode update, enable code caching for the
342 ; region specified by the boot loader and also setup a temporary stack to be
343 ; used till main memory is initialized.
344 ;
345 ;----------------------------------------------------------------------------
346 TempRamInitApi PROC NEAR PUBLIC
347 ;
348 ; Ensure SSE is enabled
349 ;
350 ENABLE_SSE
351
352 ;
353 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
354 ;
355 SAVE_REGS
356
357 ;
358 ; Save timestamp into XMM6
359 ;
360 rdtsc
361 SAVE_EAX
362 SAVE_EDX
363
364 ;
365 ; Check Parameter
366 ;
367 mov eax, dword ptr [esp + 4]
368 cmp eax, 0
369 mov eax, 80000002h
370 jz NemInitExit
371
372 ;
373 ; CPUID/DeviceID check
374 ; and 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 jmp Pei2LoaderSwitchStack
509
510 @@:
511 ;
512 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
513 ;
514
515 ;
516 ; Store the address in FSP which will return control to the BL
517 ;
518 push offset exit
519
520 ;
521 ; Create a Task Frame in the stack for the Boot Loader
522 ;
523 pushfd ; 2 pushf for 4 byte alignment
524 cli
525 pushad
526
527 ; Reserve 8 bytes for IDT save/restore
528 sub esp, 8
529 sidt fword ptr [esp]
530
531 ;
532 ; Setup new FSP stack
533 ;
534 mov edi, esp
535 mov esp, PcdGet32(PcdTemporaryRamBase)
536 add esp, PcdGet32(PcdTemporaryRamSize)
537 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
538
539 ;
540 ; Pass the API Idx to SecStartup
541 ;
542 push eax
543
544 ;
545 ; Pass the BootLoader stack to SecStartup
546 ;
547 push edi
548
549 ;
550 ; Pass entry point of the PEI core
551 ;
552 call GetFspBaseAddress
553 mov edi, eax
554 add edi, PcdGet32 (PcdFspAreaSize)
555 sub edi, 20h
556 add eax, DWORD PTR ds:[edi]
557 push eax
558
559 ;
560 ; Pass BFV into the PEI Core
561 ; It uses relative address to calucate the actual boot FV base
562 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
563 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
564 ; they are different. The code below can handle both cases.
565 ;
566 call GetFspBaseAddress
567 mov edi, eax
568 call GetBootFirmwareVolumeOffset
569 add eax, edi
570 push eax
571
572 ;
573 ; Pass stack base and size into the PEI Core
574 ;
575 mov eax, PcdGet32(PcdTemporaryRamBase)
576 add eax, PcdGet32(PcdTemporaryRamSize)
577 sub eax, PcdGet32(PcdFspTemporaryRamSize)
578 push eax
579 push PcdGet32(PcdFspTemporaryRamSize)
580
581 ;
582 ; Pass Control into the PEI Core
583 ;
584 call SecStartup
585
586 exit:
587 ret
588
589 FspApiCommon ENDP
590
591 END