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