Update IntelFspPkg according to FSP1.1.
[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 # PlatformBasicInitDflt
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(PlatformBasicInitDflt)
218 ASM_PFX(PlatformBasicInitDflt):
219 #
220 # Save return address to EBP
221 #
222 movl %eax, %ebp
223 xorl %eax, %eax
224
225 PlatformBasicInitDfltExit:
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 %xmm7, %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 # Following is the code copied from BYTFSP, need to figure out what it is doing..
455 #
456 #----------------------------------------------------------------------------
457 ASM_GLOBAL ASM_PFX(EstablishStackFsp)
458 ASM_PFX(EstablishStackFsp):
459 #
460 # Save parameter pointer in edx
461 #
462 movl 4(%esp), %edx
463
464 #
465 # Enable FSP STACK
466 #
467 movl PcdGet32(PcdTemporaryRamBase), %esp
468 addl PcdGet32(PcdTemporaryRamSize), %esp
469
470 pushl $DATA_LEN_OF_MCUD # Size of the data region
471 pushl $0x4455434D # Signature of the data region 'MCUD'
472 pushl 12(%edx) # Code size
473 pushl 8(%edx) # Code base
474 cmpl $0, %edx # Is parameter pointer valid ?
475 jz InvalidMicrocodeRegion
476 pushl 4(%edx) # Microcode size
477 pushl (%edx) # Microcode base
478 jmp EstablishStackFspExit
479
480 InvalidMicrocodeRegion:
481 push $0 # Microcode size
482 push $0 # Microcode base
483
484 EstablishStackFspExit:
485 #
486 # Save API entry/exit timestamp into stack
487 #
488 pushl $DATA_LEN_OF_PER0 # Size of the data region
489 pushl $0x30524550 # Signature of the data region 'PER0'
490 movd %xmm4, %eax
491 pushl %eax
492 movd %xmm5, %eax
493 pushl %eax
494 rdtsc
495 pushl %edx
496 pushl %eax
497
498 #
499 # Terminator for the data on stack
500 #
501 push $0x00
502
503 #
504 # Set ECX/EDX to the bootloader temporary memory range
505 #
506 movl PcdGet32 (PcdTemporaryRamBase), %ecx
507 movl %ecx, %edx
508 addl PcdGet32 (PcdTemporaryRamSize), %edx
509 subl PcdGet32 (PcdFspTemporaryRamSize), %edx
510
511 xorl %eax, %eax
512
513 movd %mm7, %esi #RET_ESI
514 jmp *%esi
515
516 #----------------------------------------------------------------------------
517 # TempRamInit API
518 #
519 # This FSP API will load the microcode update, enable code caching for the
520 # region specified by the boot loader and also setup a temporary stack to be
521 # used till main memory is initialized.
522 #
523 #----------------------------------------------------------------------------
524 ASM_GLOBAL ASM_PFX(TempRamInitApi)
525 ASM_PFX(TempRamInitApi):
526 #
527 # Ensure SSE is enabled
528 #
529 ENABLE_SSE
530
531 #
532 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
533 #
534 SAVE_REGS
535
536 #
537 # Save timestamp into XMM4 & XMM5
538 #
539 rdtsc
540 movd %edx, %xmm4
541 movd %eax, %xmm5
542
543 #
544 # CPUID/DeviceID check
545 #
546 movl $TempRamInitApiL0, %eax
547 jmp ASM_PFX(FspSelfCheckDflt) # @note: ESP can not be changed.
548 TempRamInitApiL0:
549 cmpl $0x00, %eax
550 jnz NemInitExit
551
552 #
553 # Sec Platform Init
554 #
555 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit
556 movd %mm7, %esi
557 jmp ASM_PFX(SecPlatformInit)
558 TempRamInitApiL1:
559
560 #
561 # Call Sec CAR Init
562 #
563 movl $TempRamInitApiL2, %esi #CALL_MMX SecCarInit
564 movd %mm7, %esi
565 jmp ASM_PFX(SecCarInit)
566 TempRamInitApiL2:
567
568 # @todo: ESP has been modified, we need to restore here.
569
570 LOAD_REGS
571 SAVE_REGS
572
573 #
574 # Load microcode
575 #
576 movl $TempRamInitApiL3, %esi #CALL_MMX LoadUcode
577 movd %mm7, %esi
578 jmp ASM_PFX(LoadUcode)
579 TempRamInitApiL3:
580
581 #
582 # EstablishStackFsp
583 #
584 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp
585 movd %mm7, %esi
586 jmp ASM_PFX(EstablishStackFsp)
587 TempRamInitApiL4:
588
589 NemInitExit:
590 #
591 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
592 #
593 LOAD_REGS
594 ret
595
596 #----------------------------------------------------------------------------
597 # FspInit API
598 #
599 # This FSP API will perform the processor and chipset initialization.
600 # This API will not return. Instead, it transfers the control to the
601 # ContinuationFunc provided in the parameter.
602 #
603 #----------------------------------------------------------------------------
604 ASM_GLOBAL ASM_PFX(FspInitApi)
605 ASM_PFX(FspInitApi):
606 movl $0x01, %eax
607 jmp FspApiCommon
608
609 #----------------------------------------------------------------------------
610 # NotifyPhase API
611 #
612 # This FSP API will notify the FSP about the different phases in the boot
613 # process
614 #
615 #----------------------------------------------------------------------------
616 ASM_GLOBAL ASM_PFX(NotifyPhaseApi)
617 ASM_PFX(NotifyPhaseApi):
618 movl $0x02, %eax
619 jmp FspApiCommon
620
621 #----------------------------------------------------------------------------
622 # FspMemoryInit API
623 #
624 # This FSP API is called after TempRamInit and initializes the memory.
625 #
626 #----------------------------------------------------------------------------
627 ASM_GLOBAL ASM_PFX(FspMemoryInitApi)
628 ASM_PFX(FspMemoryInitApi):
629 movl $0x03, %eax
630 jmp FspApiCommon
631
632 #----------------------------------------------------------------------------
633 # TempRamExitApi API
634 #
635 # This API tears down temporary RAM
636 #
637 #----------------------------------------------------------------------------
638 ASM_GLOBAL ASM_PFX(TempRamExitApi)
639 ASM_PFX(TempRamExitApi):
640 movl $0x04, %eax
641 jmp FspApiCommon
642
643 #----------------------------------------------------------------------------
644 # FspSiliconInit API
645 #
646 # This FSP API initializes the CPU and the chipset including the IO
647 # controllers in the chipset to enable normal operation of these devices.
648 #
649 #----------------------------------------------------------------------------
650 ASM_GLOBAL ASM_PFX(FspSiliconInitApi)
651 ASM_PFX(FspSiliconInitApi):
652 movl $0x05, %eax
653 jmp FspApiCommon
654
655 #----------------------------------------------------------------------------
656 # FspApiCommon API
657 #
658 # This is the FSP API common entry point to resume the FSP execution
659 #
660 #----------------------------------------------------------------------------
661 ASM_GLOBAL ASM_PFX(FspApiCommon)
662 ASM_PFX(FspApiCommon):
663 #
664 # EAX holds the API index
665 #
666
667 #
668 # Stack must be ready
669 #
670 pushl %eax
671 addl $0x04, %esp
672 cmpl -4(%esp), %eax
673 jz FspApiCommonL0
674 movl $0x080000003, %eax
675 jmp FspApiCommonExit
676
677 FspApiCommonL0:
678 #
679 # Verify the calling condition
680 #
681 pushal
682 pushl %eax
683 call ASM_PFX(FspApiCallingCheck)
684 addl $0x04, %esp
685 cmpl $0x00, %eax
686 jz FspApiCommonL1
687 movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax
688 popal
689 ret
690
691 FspApiCommonL1:
692 popal
693 cmpl $0x01, %eax # FspInit API
694 jz FspApiCommonL2
695 cmpl $0x03, %eax # FspMemoryInit API
696 jz FspApiCommonL2
697 jmp Pei2LoaderSwitchStack
698
699 FspApiCommonL2:
700 #
701 # FspInit and FspMemoryInit APIs, setup the initial stack frame
702 #
703
704 #
705 # Store the address in FSP which will return control to the BL
706 #
707 pushl $FspApiCommonExit
708
709 #
710 # Create a Task Frame in the stack for the Boot Loader
711 #
712 pushfl # 2 pushf for 4 byte alignment
713 cli
714 pushal
715
716 #
717 # Reserve 8 bytes for IDT save/restore
718 #
719 subl $0x08, %esp
720 sidt (%esp)
721
722 #
723 # Setup new FSP stack
724 #
725 movl %esp, %edi
726 movl PcdGet32(PcdTemporaryRamBase), %esp
727 addl PcdGet32(PcdTemporaryRamSize), %esp
728 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp
729
730 #
731 # Pass the API Idx to SecStartup
732 #
733 pushl %eax
734
735 #
736 # Pass the bootloader stack to SecStartup
737 #
738 pushl %edi
739
740 #
741 # Pass entry point of the PEI core
742 #
743 call ASM_PFX(GetFspBaseAddress)
744 movl %eax, %edi
745 addl PcdGet32(PcdFspAreaSize), %edi
746 subl $0x20, %edi
747 addl %ds:(%edi), %eax
748 pushl %eax
749
750 #
751 # Pass BFV into the PEI Core
752 # It uses relative address to calucate the actual boot FV base
753 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
754 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
755 # they are different. The code below can handle both cases.
756 #
757 call ASM_PFX(GetFspBaseAddress)
758 movl %eax, %edi
759 call ASM_PFX(GetBootFirmwareVolumeOffset)
760 addl %edi, %eax
761 pushl %eax
762
763 #
764 # Pass stack base and size into the PEI Core
765 #
766 movl PcdGet32(PcdTemporaryRamBase), %eax
767 addl PcdGet32(PcdTemporaryRamSize), %eax
768 subl PcdGet32(PcdFspTemporaryRamSize), %eax
769 pushl %eax
770 pushl PcdGet32(PcdFspTemporaryRamSize)
771
772 #
773 # Pass Control into the PEI Core
774 #
775 call ASM_PFX(SecStartup)
776
777 FspApiCommonExit:
778 ret
779
780