Fsp1.1 update.
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.s
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2014 - 2015, 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 #.INCLUDE "UcodeLoadGcc.inc" - begin
19
20 .equ MSR_IA32_PLATFORM_ID, 0x00000017
21 .equ MSR_IA32_BIOS_UPDT_TRIG, 0x00000079
22 .equ MSR_IA32_BIOS_SIGN_ID, 0x0000008b
23
24 Ucode:
25 .equ UcodeVersion, 0x0000
26 .equ UcodeRevision, 0x0004
27 .equ UcodeDate, 0x0008
28 .equ UcodeProcessor, 0x000C
29 .equ UcodeChecksum, 0x0010
30 .equ UcodeLoader, 0x0014
31 .equ UcodeRsvd, 0x0018
32 UcodeEnd:
33
34 UcodeHdr:
35 .equ UcodeHdrVersion, 0x0000
36 .equ UcodeHdrRevision, 0x0004
37 .equ UcodeHdrDate, 0x0008
38 .equ UcodeHdrProcessor, 0x000c
39 .equ UcodeHdrChecksum, 0x0010
40 .equ UcodeHdrLoader, 0x0014
41 .equ UcodeHdrFlags, 0x0018
42 .equ UcodeHdrDataSize, 0x001C
43 .equ UcodeHdrTotalSize, 0x0020
44 .equ UcodeHdrRsvd, 0x0024
45 UcodeHdrEnd:
46 .equ UcodeHdrLength, 0x0030 # UcodeHdrLength = UcodeHdrEnd - UcodeHdr
47
48
49 ExtSigHdr:
50 .equ ExtSigHdrCount, 0x0000
51 .equ ExtSigHdrChecksum, 0x0004
52 .equ rsvd, 0x0008
53 ExtSigHdrEnd:
54 .equ ExtSigHdrLength, 0x0014 #ExtSigHdrLength = ExtSigHdrEnd - ExtSigHdr
55
56 ExtSig:
57 .equ ExtSigProcessor, 0x0000
58 .equ ExtSigFlags, 0x0004
59 .equ ExtSigChecksum, 0x0008
60 ExtSigEnd:
61 .equ ExtSigLength, 0x000C #ExtSigLength = ExtSigEnd - ExtSig
62
63 LoadUcodeParams:
64 .equ LoadUcodeParamsUcodeCodeAddr, 0x0000
65 .equ LoadUcodeParamsUcodeCodeSize, 0x0004
66 LoadUcodeParamsEnd:
67
68 #.INCLUDE "UcodeLoadGcc.inc" - end
69
70 #.INCLUDE "SaveRestoreSseGcc.inc" - begin
71
72 .macro SAVE_REGS
73 pinsrw $0x00, %ebp, %xmm7
74 ror $0x10, %ebp
75 pinsrw $0x01, %ebp, %xmm7
76 ror $0x10, %ebp
77 #
78 pinsrw $0x02, %ebx, %xmm7
79 ror $0x10, %ebx
80 pinsrw $0x03, %ebx, %xmm7
81 ror $0x10, %ebx
82 #
83 pinsrw $0x04, %esi, %xmm7
84 ror $0x10, %esi
85 pinsrw $0x05, %esi, %xmm7
86 ror $0x10, %esi
87 #
88 pinsrw $0x06, %edi, %xmm7
89 ror $0x10, %edi
90 pinsrw $0x07, %edi, %xmm7
91 ror $0x10, %edi
92 #
93 pinsrw $0x00, %esp, %xmm6
94 ror $0x10, %esp
95 pinsrw $0x01, %esp, %xmm6
96 ror $0x10, %esp
97 .endm
98
99 .macro LOAD_REGS
100 pshufd $0xe4, %xmm7, %xmm7
101 movd %xmm7, %ebp
102 pshufd $0xe4, %xmm7, %xmm7
103 #
104 pshufd $0x39, %xmm7, %xmm7
105 movd %xmm7, %ebx
106 pshufd $0x93, %xmm7, %xmm7
107 #
108 pshufd $0x4e, %xmm7, %xmm7
109 movd %xmm7, %esi
110 pshufd $0x4e, %xmm7, %xmm7
111 #
112 pshufd $0x93, %xmm7, %xmm7
113 movd %xmm7, %edi
114 pshufd $0x39, %xmm7, %xmm7
115 #
116 movd %xmm6, %esp
117 .endm
118
119 .macro LOAD_EAX
120 pshufd $0x39, %xmm6, %xmm6
121 movd %xmm6, %eax
122 pshufd $0x93, %xmm6, %xmm6
123 .endm
124
125 .macro LOAD_EDX
126 pshufd $0xe4, %xmm6, %xmm6
127 movd %xmm6, %edx
128 pshufd $0xe4, %xmm6, %xmm6
129 .endm
130
131 .macro SAVE_EAX
132 pinsrw $0x02, %eax, %xmm6
133 ror $0x10, %eax
134 pinsrw $0x03, %eax, %xmm6
135 ror $0x10, %eax
136 .endm
137
138 .macro SAVE_EDX
139 pinsrw $0x04, %edx, %xmm6
140 ror $0x10, %edx
141 pinsrw $0x05, %edx, %xmm6
142 ror $0x10, %edx
143 .endm
144
145 .macro LOAD_ESP
146 movd %xmm6, %esp
147 .endm
148
149 .macro ENABLE_SSE
150 movl %cr4, %eax
151 orl $0x00000600, %eax # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
152 movl %eax,%cr4
153 .endm
154
155 #.INCLUDE "SaveRestoreSseGcc.inc" - end
156
157
158 #
159 # Following are fixed PCDs
160 #
161 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase)
162 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize)
163 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
164
165 #
166 # Following functions will be provided in C
167 #
168 ASM_GLOBAL ASM_PFX(SecStartup)
169 ASM_GLOBAL ASM_PFX(FspApiCallingCheck)
170
171 #
172 # Following functions will be provided in PlatformSecLib
173 #
174 ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)
175 ASM_GLOBAL ASM_PFX(Pei2LoaderSwitchStack)
176
177
178 #
179 # Define the data length that we saved on the stack top
180 #
181 .equ DATA_LEN_OF_PER0, 0x018
182 .equ DATA_LEN_OF_MCUD, 0x018
183 .equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
184
185 #------------------------------------------------------------------------------
186 # FspSelfCheckDflt
187 # Inputs:
188 # eax -> Return address
189 # Outputs:
190 # eax -> 0 - Successful, Non-zero - Failed.
191 # Register Usage:
192 # eax is cleared and ebp is used for return address.
193 # All others reserved.
194 #------------------------------------------------------------------------------
195 ASM_GLOBAL ASM_PFX(FspSelfCheckDflt)
196 ASM_PFX(FspSelfCheckDflt):
197 #
198 # Save return address to EBP
199 #
200 movl %eax, %ebp
201 xorl %eax, %eax
202
203 FspSelfCheckDfltExit:
204 jmp *%ebp
205
206
207 #------------------------------------------------------------------------------
208 # SecPlatformInitDflt
209 # Inputs:
210 # eax -> Return address
211 # Outputs:
212 # eax -> 0 - Successful, Non-zero - Failed.
213 # Register Usage:
214 # eax is cleared and ebp is used for return address.
215 # All others reserved.
216 #------------------------------------------------------------------------------
217 ASM_GLOBAL ASM_PFX(SecPlatformInitDflt)
218 ASM_PFX(SecPlatformInitDflt):
219 #
220 # Save return address to EBP
221 #
222 movl %eax, %ebp
223 xorl %eax, %eax
224
225 SecPlatformInitDfltExit:
226 jmp *%ebp
227
228
229 #------------------------------------------------------------------------------
230 # LoadUcode
231 #
232 # Inputs:
233 # esp -> LOAD_UCODE_PARAMS pointer
234 # Register Usage:
235 # esp Preserved
236 # All others destroyed
237 # Assumptions:
238 # No memory available, stack is hard-coded and used for return address
239 # Executed by SBSP and NBSP
240 # Beginning of microcode update region starts on paragraph boundary
241 #------------------------------------------------------------------------------
242 ASM_GLOBAL ASM_PFX(LoadUcode)
243 ASM_PFX(LoadUcode):
244 #
245 # Save return address to EBP
246 #
247 movd %mm7, %ebp
248
249 cmpl $0x00, %esp
250 jz ParamError
251 movl (%esp), %eax #dword ptr [] Parameter pointer
252 cmpl $0x00, %eax
253 jz ParamError
254 movl %eax, %esp
255 movl LoadUcodeParamsUcodeCodeAddr(%esp), %esi #mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
256 cmpl $0x00, %esi
257 jnz CheckMainHeader
258
259 ParamError:
260 movl $0x080000002, %eax
261 jmp LoadUcodeExit
262
263 CheckMainHeader:
264 #
265 # Get processor signature and platform ID from the installed processor
266 # and save into registers for later use
267 # ebx = processor signature
268 # edx = platform ID
269 #
270 movl $0x01, %eax
271 cpuid
272 movl %eax, %ebx
273 movl $MSR_IA32_PLATFORM_ID, %ecx
274 rdmsr
275 movl %edx, %ecx
276 shrl $0x12, %ecx #($50-$32)
277 andl $0x07, %ecx
278 movl $0x01, %edx
279 shll %cl,%edx
280
281 #
282 # Current register usage
283 # esp -> stack with paramters
284 # esi -> microcode update to check
285 # ebx = processor signature
286 # edx = platform ID
287 #
288
289 #
290 # Check for valid microcode header
291 # Minimal test checking for header version and loader version as 1
292 #
293 movl $0x01, %eax
294 cmpl %eax, UcodeHdrVersion(%esi) #cmp [esi].ucode_hdr.version, eax
295 jne AdvanceFixedSize
296 cmpl %eax, UcodeHdrLoader(%esi) #cmp [esi].ucode_hdr.loader, eax
297 jne AdvanceFixedSize
298
299 #
300 # Check if signature and plaform ID match
301 #
302 cmpl UcodeHdrProcessor(%esi), %ebx #cmp ebx, [esi].ucode_hdr.processor
303 jne LoadUcodeL0
304 testl UcodeHdrFlags(%esi), %edx #test edx, [esi].ucode_hdr.flags
305 jnz LoadCheck #Jif signature and platform ID match
306
307 LoadUcodeL0:
308 #
309 # Check if extended header exists
310 # First check if total_size and data_size are valid
311 #
312 xorl %eax, %eax
313 cmpl %eax, UcodeHdrTotalSize(%esi) #cmp [esi].ucode_hdr.total_size, eax
314 je NextMicrocode
315 cmpl %eax, UcodeHdrDataSize(%esi) #cmp [esi].ucode_hdr.data_size, eax
316 je NextMicrocode
317
318 #
319 # Then verify total size - sizeof header > data size
320 #
321 movl UcodeHdrTotalSize(%esi), %ecx #mov ecx, [esi].ucode_hdr.total_size
322 subl $UcodeHdrLength, %ecx #sub ecx, sizeof ucode_hdr
323 cmpl UcodeHdrDataSize(%esi), %ecx #cmp ecx, [esi].ucode_hdr.data_size
324 jle NextMicrocode
325
326 #
327 # Set edi -> extended header
328 #
329 movl %esi, %edi
330 addl $UcodeHdrLength, %edi #add edi, sizeof ucode_hdr
331 addl UcodeHdrDataSize(%esi), %edi #add edi, [esi].ucode_hdr.data_size
332
333 #
334 # Get count of extended structures
335 #
336 movl ExtSigHdrCount(%edi), %ecx #mov ecx, [edi].ext_sig_hdr.count
337
338 #
339 # Move pointer to first signature structure
340 #
341 addl ExtSigHdrLength, %edi #add edi, sizeof ext_sig_hdr
342
343 CheckExtSig:
344 #
345 # Check if extended signature and platform ID match
346 #
347 cmpl %ebx, ExtSigProcessor(%edi) #cmp [edi].ext_sig.processor, ebx
348 jne LoadUcodeL1
349 test %edx, ExtSigFlags(%edi) #test [edi].ext_sig.flags, edx
350 jnz LoadCheck # Jif signature and platform ID match
351 LoadUcodeL1:
352 #
353 # Check if any more extended signatures exist
354 #
355 addl $ExtSigLength, %edi #add edi, sizeof ext_sig
356 loop CheckExtSig
357
358 NextMicrocode:
359 #
360 # Advance just after end of this microcode
361 #
362 xorl %eax, %eax
363 cmpl %eax, UcodeHdrTotalSize(%esi) #cmp [esi].ucode_hdr.total_size, eax
364 je LoadUcodeL2
365 addl UcodeHdrTotalSize(%esi), %esi #add esi, [esi].ucode_hdr.total_size
366 jmp CheckAddress
367 LoadUcodeL2:
368 addl $0x800, %esi #add esi, dword ptr 2048
369 jmp CheckAddress
370
371 AdvanceFixedSize:
372 #
373 # Advance by 4X dwords
374 #
375 addl $0x400, %esi #add esi, dword ptr 1024
376
377 CheckAddress:
378 #
379 # Is valid Microcode start point ?
380 #
381 cmpl $0x0ffffffff, UcodeHdrVersion(%esi)
382
383 #
384 # Is automatic size detection ?
385 #
386 movl LoadUcodeParamsUcodeCodeSize(%esp), %eax
387 cmpl $0x0ffffffff, %eax
388 jz LoadUcodeL3
389 #
390 # Address >= microcode region address + microcode region size?
391 #
392 addl LoadUcodeParamsUcodeCodeAddr(%esp), %eax #mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
393
394 cmpl %eax, %esi
395 jae Done #Jif address is outside of ucode region
396 jmp CheckMainHeader
397
398 LoadUcodeL3:
399 LoadCheck:
400 #
401 # Get the revision of the current microcode update loaded
402 #
403 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
404 xorl %eax, %eax # Clear EAX
405 xorl %edx, %edx # Clear EDX
406 wrmsr # Load 0 to MSR at 8Bh
407
408 movl $0x01, %eax
409 cpuid
410 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
411 rdmsr # Get current microcode signature
412
413 #
414 # Verify this microcode update is not already loaded
415 #
416 cmpl %edx, UcodeHdrRevision(%esi) #cmp [esi].ucode_hdr.revision, edx
417 je Continue
418
419 LoadMicrocode:
420 #
421 # EAX contains the linear address of the start of the Update Data
422 # EDX contains zero
423 # ECX contains 79h (IA32_BIOS_UPDT_TRIG)
424 # Start microcode load with wrmsr
425 #
426 movl %esi, %eax
427 addl $UcodeHdrLength, %eax #add eax, sizeof ucode_hdr
428 xorl %edx, %edx
429 movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx
430 wrmsr
431 movl $0x01, %eax
432 cpuid
433
434 Continue:
435 jmp NextMicrocode
436
437 Done:
438 movl $0x01, %eax
439 cpuid
440 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
441 rdmsr # Get current microcode signature
442 xorl %eax, %eax
443 cmpl $0x00, %edx
444 jnz LoadUcodeExit
445 movl $0x08000000E, %eax
446
447 LoadUcodeExit:
448 jmp *%ebp
449
450
451 #----------------------------------------------------------------------------
452 # EstablishStackFsp
453 #
454 #----------------------------------------------------------------------------
455 ASM_GLOBAL ASM_PFX(EstablishStackFsp)
456 ASM_PFX(EstablishStackFsp):
457 #
458 # Save parameter pointer in edx
459 #
460 movl 4(%esp), %edx
461
462 #
463 # Enable FSP STACK
464 #
465 movl PcdGet32(PcdTemporaryRamBase), %esp
466 addl PcdGet32(PcdTemporaryRamSize), %esp
467
468 pushl $DATA_LEN_OF_MCUD # Size of the data region
469 pushl $0x4455434D # Signature of the data region 'MCUD'
470 pushl 12(%edx) # Code size
471 pushl 8(%edx) # Code base
472 cmpl $0, %edx # Is parameter pointer valid ?
473 jz InvalidMicrocodeRegion
474 pushl 4(%edx) # Microcode size
475 pushl (%edx) # Microcode base
476 jmp EstablishStackFspExit
477
478 InvalidMicrocodeRegion:
479 push $0 # Microcode size
480 push $0 # Microcode base
481
482 EstablishStackFspExit:
483 #
484 # Save API entry/exit timestamp into stack
485 #
486 pushl $DATA_LEN_OF_PER0 # Size of the data region
487 pushl $0x30524550 # Signature of the data region 'PER0'
488 LOAD_EDX
489 pushl %edx
490 LOAD_EAX
491 pushl %eax
492 rdtsc
493 pushl %edx
494 pushl %eax
495
496 #
497 # Terminator for the data on stack
498 #
499 push $0x00
500
501 #
502 # Set ECX/EDX to the bootloader temporary memory range
503 #
504 movl PcdGet32 (PcdTemporaryRamBase), %ecx
505 movl %ecx, %edx
506 addl PcdGet32 (PcdTemporaryRamSize), %edx
507 subl PcdGet32 (PcdFspTemporaryRamSize), %edx
508
509 xorl %eax, %eax
510
511 movd %mm7, %esi #RET_ESI
512 jmp *%esi
513
514 #----------------------------------------------------------------------------
515 # TempRamInit API
516 #
517 # This FSP API will load the microcode update, enable code caching for the
518 # region specified by the boot loader and also setup a temporary stack to be
519 # used till main memory is initialized.
520 #
521 #----------------------------------------------------------------------------
522 ASM_GLOBAL ASM_PFX(TempRamInitApi)
523 ASM_PFX(TempRamInitApi):
524 #
525 # Ensure SSE is enabled
526 #
527 ENABLE_SSE
528
529 #
530 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
531 #
532 SAVE_REGS
533
534 #
535 # Save timestamp into XMM4 & XMM5
536 #
537 rdtsc
538 SAVE_EAX
539 SAVE_EDX
540
541 #
542 # Check Parameter
543 #
544 movl 4(%esp), %eax
545 cmpl $0x00, %eax
546 movl $0x80000002, %eax
547 jz NemInitExit
548
549 #
550 # CPUID/DeviceID check
551 #
552 movl $TempRamInitApiL0, %eax
553 jmp ASM_PFX(FspSelfCheckDflt) # @note: ESP can not be changed.
554 TempRamInitApiL0:
555 cmpl $0x00, %eax
556 jnz NemInitExit
557
558 #
559 # Sec Platform Init
560 #
561 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit
562 movd %mm7, %esi
563 jmp ASM_PFX(SecPlatformInit)
564 TempRamInitApiL1:
565 cmpl $0x00, %eax
566 jnz NemInitExit
567
568 #
569 # Load microcode
570 #
571 LOAD_ESP
572 movl $TempRamInitApiL2, %esi #CALL_MMX LoadUcode
573 movd %mm7, %esi
574 jmp ASM_PFX(LoadUcode)
575 TempRamInitApiL2:
576 cmpl $0x00, %eax
577 jnz NemInitExit
578
579 #
580 # Call Sec CAR Init
581 #
582 LOAD_ESP
583 movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit
584 movd %mm7, %esi
585 jmp ASM_PFX(SecCarInit)
586 TempRamInitApiL3:
587 cmpl $0x00, %eax
588 jnz NemInitExit
589
590 #
591 # EstablishStackFsp
592 #
593 LOAD_ESP
594 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp
595 movd %mm7, %esi
596 jmp ASM_PFX(EstablishStackFsp)
597 TempRamInitApiL4:
598
599 NemInitExit:
600 #
601 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
602 #
603 LOAD_REGS
604 ret
605
606 #----------------------------------------------------------------------------
607 # FspInit API
608 #
609 # This FSP API will perform the processor and chipset initialization.
610 # This API will not return. Instead, it transfers the control to the
611 # ContinuationFunc provided in the parameter.
612 #
613 #----------------------------------------------------------------------------
614 ASM_GLOBAL ASM_PFX(FspInitApi)
615 ASM_PFX(FspInitApi):
616 movl $0x01, %eax
617 jmp FspApiCommon
618
619 #----------------------------------------------------------------------------
620 # NotifyPhase API
621 #
622 # This FSP API will notify the FSP about the different phases in the boot
623 # process
624 #
625 #----------------------------------------------------------------------------
626 ASM_GLOBAL ASM_PFX(NotifyPhaseApi)
627 ASM_PFX(NotifyPhaseApi):
628 movl $0x02, %eax
629 jmp FspApiCommon
630
631 #----------------------------------------------------------------------------
632 # FspMemoryInit API
633 #
634 # This FSP API is called after TempRamInit and initializes the memory.
635 #
636 #----------------------------------------------------------------------------
637 ASM_GLOBAL ASM_PFX(FspMemoryInitApi)
638 ASM_PFX(FspMemoryInitApi):
639 movl $0x03, %eax
640 jmp FspApiCommon
641
642 #----------------------------------------------------------------------------
643 # TempRamExitApi API
644 #
645 # This API tears down temporary RAM
646 #
647 #----------------------------------------------------------------------------
648 ASM_GLOBAL ASM_PFX(TempRamExitApi)
649 ASM_PFX(TempRamExitApi):
650 movl $0x04, %eax
651 jmp FspApiCommon
652
653 #----------------------------------------------------------------------------
654 # FspSiliconInit API
655 #
656 # This FSP API initializes the CPU and the chipset including the IO
657 # controllers in the chipset to enable normal operation of these devices.
658 #
659 #----------------------------------------------------------------------------
660 ASM_GLOBAL ASM_PFX(FspSiliconInitApi)
661 ASM_PFX(FspSiliconInitApi):
662 movl $0x05, %eax
663 jmp FspApiCommon
664
665 #----------------------------------------------------------------------------
666 # FspApiCommon API
667 #
668 # This is the FSP API common entry point to resume the FSP execution
669 #
670 #----------------------------------------------------------------------------
671 ASM_GLOBAL ASM_PFX(FspApiCommon)
672 ASM_PFX(FspApiCommon):
673 #
674 # EAX holds the API index
675 #
676
677 #
678 # Stack must be ready
679 #
680 pushl %eax
681 addl $0x04, %esp
682 cmpl -4(%esp), %eax
683 jz FspApiCommonL0
684 movl $0x080000003, %eax
685 jmp FspApiCommonExit
686
687 FspApiCommonL0:
688 #
689 # Verify the calling condition
690 #
691 pushal
692 pushl %eax
693 call ASM_PFX(FspApiCallingCheck)
694 addl $0x04, %esp
695 cmpl $0x00, %eax
696 jz FspApiCommonL1
697 movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax
698 popal
699 ret
700
701 FspApiCommonL1:
702 popal
703 cmpl $0x01, %eax # FspInit API
704 jz FspApiCommonL2
705 cmpl $0x03, %eax # FspMemoryInit API
706 jz FspApiCommonL2
707 jmp Pei2LoaderSwitchStack
708
709 FspApiCommonL2:
710 #
711 # FspInit and FspMemoryInit APIs, setup the initial stack frame
712 #
713
714 #
715 # Store the address in FSP which will return control to the BL
716 #
717 pushl $FspApiCommonExit
718
719 #
720 # Create a Task Frame in the stack for the Boot Loader
721 #
722 pushfl # 2 pushf for 4 byte alignment
723 cli
724 pushal
725
726 #
727 # Reserve 8 bytes for IDT save/restore
728 #
729 subl $0x08, %esp
730 sidt (%esp)
731
732 #
733 # Setup new FSP stack
734 #
735 movl %esp, %edi
736 movl PcdGet32(PcdTemporaryRamBase), %esp
737 addl PcdGet32(PcdTemporaryRamSize), %esp
738 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp
739
740 #
741 # Pass the API Idx to SecStartup
742 #
743 pushl %eax
744
745 #
746 # Pass the bootloader stack to SecStartup
747 #
748 pushl %edi
749
750 #
751 # Pass entry point of the PEI core
752 #
753 call ASM_PFX(GetFspBaseAddress)
754 movl %eax, %edi
755 addl PcdGet32(PcdFspAreaSize), %edi
756 subl $0x20, %edi
757 addl %ds:(%edi), %eax
758 pushl %eax
759
760 #
761 # Pass BFV into the PEI Core
762 # It uses relative address to calucate the actual boot FV base
763 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
764 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
765 # they are different. The code below can handle both cases.
766 #
767 call ASM_PFX(GetFspBaseAddress)
768 movl %eax, %edi
769 call ASM_PFX(GetBootFirmwareVolumeOffset)
770 addl %edi, %eax
771 pushl %eax
772
773 #
774 # Pass stack base and size into the PEI Core
775 #
776 movl PcdGet32(PcdTemporaryRamBase), %eax
777 addl PcdGet32(PcdTemporaryRamSize), %eax
778 subl PcdGet32(PcdFspTemporaryRamSize), %eax
779 pushl %eax
780 pushl PcdGet32(PcdFspTemporaryRamSize)
781
782 #
783 # Pass Control into the PEI Core
784 #
785 call ASM_PFX(SecStartup)
786
787 FspApiCommonExit:
788 ret
789
790