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