]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
d0f5b20b96dcd9b40737e3a1ea5e5a8550878724
[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(GetFspBaseAddress)
219 ASM_GLOBAL ASM_PFX(GetFspInfoHdr)
220 ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)
221 ASM_GLOBAL ASM_PFX(Loader2PeiSwitchStack)
222
223
224 #
225 # Define the data length that we saved on the stack top
226 #
227 .equ DATA_LEN_OF_PER0, 0x018
228 .equ DATA_LEN_OF_MCUD, 0x018
229 .equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
230
231 #------------------------------------------------------------------------------
232 # SecPlatformInitDefault
233 # Inputs:
234 # mm7 -> Return address
235 # Outputs:
236 # eax -> 0 - Successful, Non-zero - Failed.
237 # Register Usage:
238 # eax is cleared and ebp is used for return address.
239 # All others reserved.
240 #------------------------------------------------------------------------------
241 ASM_GLOBAL ASM_PFX(SecPlatformInitDefault)
242 ASM_PFX(SecPlatformInitDefault):
243 #
244 # Save return address to EBP
245 #
246 movd %mm7, %ebp
247 xorl %eax, %eax
248
249 SecPlatformInitDefaultExit:
250 jmp *%ebp
251
252
253 #------------------------------------------------------------------------------
254 # LoadMicrocodeDefault
255 #
256 # Inputs:
257 # esp -> LoadMicrocodeParams pointer
258 # Register Usage:
259 # esp Preserved
260 # All others destroyed
261 # Assumptions:
262 # No memory available, stack is hard-coded and used for return address
263 # Executed by SBSP and NBSP
264 # Beginning of microcode update region starts on paragraph boundary
265 #------------------------------------------------------------------------------
266 ASM_GLOBAL ASM_PFX(LoadMicrocodeDefault)
267 ASM_PFX(LoadMicrocodeDefault):
268 #
269 # Save return address to EBP
270 #
271 movd %mm7, %ebp
272
273 cmpl $0x00, %esp
274 jz ParamError
275 movl 4(%esp), %eax #dword ptr [] Parameter pointer
276 cmpl $0x00, %eax
277 jz ParamError
278 movl %eax, %esp
279 movl MicrocodeCodeAddr(%esp), %esi
280 cmpl $0x00, %esi
281 jnz CheckMainHeader
282
283 ParamError:
284 movl $0x080000002, %eax
285 jmp LoadMicrocodeExit
286
287 CheckMainHeader:
288 #
289 # Get processor signature and platform ID from the installed processor
290 # and save into registers for later use
291 # ebx = processor signature
292 # edx = platform ID
293 #
294 movl $0x01, %eax
295 cpuid
296 movl %eax, %ebx
297 movl $MSR_IA32_PLATFORM_ID, %ecx
298 rdmsr
299 movl %edx, %ecx
300 shrl $0x12, %ecx #($50-$32)
301 andl $0x07, %ecx
302 movl $0x01, %edx
303 shll %cl,%edx
304
305 #
306 # Current register usage
307 # esp -> stack with paramters
308 # esi -> microcode update to check
309 # ebx = processor signature
310 # edx = platform ID
311 #
312
313 #
314 # Check for valid microcode header
315 # Minimal test checking for header version and loader version as 1
316 #
317 movl $0x01, %eax
318 cmpl %eax, MicrocodeHdrVersion(%esi)
319 jne AdvanceFixedSize
320 cmpl %eax, MicrocodeHdrLoader(%esi)
321 jne AdvanceFixedSize
322
323 #
324 # Check if signature and plaform ID match
325 #
326 cmpl MicrocodeHdrProcessor(%esi), %ebx
327 jne LoadMicrocodeL0
328 testl MicrocodeHdrFlags(%esi), %edx
329 jnz LoadCheck #Jif signature and platform ID match
330
331 LoadMicrocodeL0:
332 #
333 # Check if extended header exists
334 # First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
335 #
336 xorl %eax, %eax
337 cmpl %eax, MicrocodeHdrTotalSize(%esi)
338 je NextMicrocode
339 cmpl %eax, MicrocodeHdrDataSize(%esi)
340 je NextMicrocode
341
342 #
343 # Then verify total size - sizeof header > data size
344 #
345 movl MicrocodeHdrTotalSize(%esi), %ecx
346 subl $MicrocodeHdrLength, %ecx
347 cmpl MicrocodeHdrDataSize(%esi), %ecx
348 jle NextMicrocode
349
350 #
351 # Set edi -> extended header
352 #
353 movl %esi, %edi
354 addl $MicrocodeHdrLength, %edi
355 addl MicrocodeHdrDataSize(%esi), %edi
356
357 #
358 # Get count of extended structures
359 #
360 movl ExtSigHdrCount(%edi), %ecx
361
362 #
363 # Move pointer to first signature structure
364 #
365 addl ExtSigHdrLength, %edi
366
367 CheckExtSig:
368 #
369 # Check if extended signature and platform ID match
370 #
371 cmpl %ebx, ExtSigProcessor(%edi)
372 jne LoadMicrocodeL1
373 test %edx, ExtSigFlags(%edi)
374 jnz LoadCheck # Jif signature and platform ID match
375 LoadMicrocodeL1:
376 #
377 # Check if any more extended signatures exist
378 #
379 addl $ExtSigLength, %edi
380 loop CheckExtSig
381
382 NextMicrocode:
383 #
384 # Advance just after end of this microcode
385 #
386 xorl %eax, %eax
387 cmpl %eax, MicrocodeHdrTotalSize(%esi)
388 je LoadMicrocodeL2
389 addl MicrocodeHdrTotalSize(%esi), %esi
390 jmp CheckAddress
391 LoadMicrocodeL2:
392 addl $0x800, %esi #add esi, dword ptr 2048
393 jmp CheckAddress
394
395 AdvanceFixedSize:
396 #
397 # Advance by 4X dwords
398 #
399 addl $0x400, %esi #add esi, dword ptr 1024
400
401 CheckAddress:
402 #
403 # Is valid Microcode start point ?
404 #
405 cmpl $0x0ffffffff, MicrocodeHdrVersion(%esi)
406
407 #
408 # Is automatic size detection ?
409 #
410 movl MicrocodeCodeSize(%esp), %eax
411 cmpl $0x0ffffffff, %eax
412 jz LoadMicrocodeL3
413 #
414 # Address >= microcode region address + microcode region size?
415 #
416 addl MicrocodeCodeAddr(%esp), %eax
417
418 cmpl %eax, %esi
419 jae Done #Jif address is outside of microcode region
420 jmp CheckMainHeader
421
422 LoadMicrocodeL3:
423 LoadCheck:
424 #
425 # Get the revision of the current microcode update loaded
426 #
427 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
428 xorl %eax, %eax # Clear EAX
429 xorl %edx, %edx # Clear EDX
430 wrmsr # Load 0 to MSR at 8Bh
431
432 movl $0x01, %eax
433 cpuid
434 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
435 rdmsr # Get current microcode signature
436
437 #
438 # Verify this microcode update is not already loaded
439 #
440 cmpl %edx, MicrocodeHdrRevision(%esi)
441 je Continue
442
443 LoadMicrocode0:
444 #
445 # EAX contains the linear address of the start of the Update Data
446 # EDX contains zero
447 # ECX contains 79h (IA32_BIOS_UPDT_TRIG)
448 # Start microcode load with wrmsr
449 #
450 movl %esi, %eax
451 addl $MicrocodeHdrLength, %eax
452 xorl %edx, %edx
453 movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx
454 wrmsr
455 movl $0x01, %eax
456 cpuid
457
458 Continue:
459 jmp NextMicrocode
460
461 Done:
462 movl $0x01, %eax
463 cpuid
464 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
465 rdmsr # Get current microcode signature
466 xorl %eax, %eax
467 cmpl $0x00, %edx
468 jnz LoadMicrocodeExit
469 movl $0x08000000E, %eax
470
471 LoadMicrocodeExit:
472 jmp *%ebp
473
474
475 #----------------------------------------------------------------------------
476 # EstablishStackFsp
477 #
478 #----------------------------------------------------------------------------
479 ASM_GLOBAL ASM_PFX(EstablishStackFsp)
480 ASM_PFX(EstablishStackFsp):
481 #
482 # Save parameter pointer in edx
483 #
484 movl 4(%esp), %edx
485
486 #
487 # Enable FSP STACK
488 #
489 movl PcdGet32(PcdTemporaryRamBase), %esp
490 addl PcdGet32(PcdTemporaryRamSize), %esp
491
492 pushl $DATA_LEN_OF_MCUD # Size of the data region
493 pushl $0x4455434D # Signature of the data region 'MCUD'
494 pushl 12(%edx) # Code size
495 pushl 8(%edx) # Code base
496 pushl 4(%edx) # Microcode size
497 pushl (%edx) # Microcode base
498
499 #
500 # Save API entry/exit timestamp into stack
501 #
502 pushl $DATA_LEN_OF_PER0 # Size of the data region
503 pushl $0x30524550 # Signature of the data region 'PER0'
504 LOAD_EDX
505 pushl %edx
506 LOAD_EAX
507 pushl %eax
508 rdtsc
509 pushl %edx
510 pushl %eax
511
512 #
513 # Terminator for the data on stack
514 #
515 push $0x00
516
517 #
518 # Set ECX/EDX to the BootLoader temporary memory range
519 #
520 movl PcdGet32 (PcdTemporaryRamBase), %ecx
521 movl %ecx, %edx
522 addl PcdGet32 (PcdTemporaryRamSize), %edx
523 subl PcdGet32 (PcdFspTemporaryRamSize), %edx
524
525 xorl %eax, %eax
526
527 movd %mm7, %esi #RET_ESI
528 jmp *%esi
529
530 #----------------------------------------------------------------------------
531 # TempRamInit API
532 #
533 # This FSP API will load the microcode update, enable code caching for the
534 # region specified by the boot loader and also setup a temporary stack to be
535 # used till main memory is initialized.
536 #
537 #----------------------------------------------------------------------------
538 ASM_GLOBAL ASM_PFX(TempRamInitApi)
539 ASM_PFX(TempRamInitApi):
540 #
541 # Ensure SSE is enabled
542 #
543 ENABLE_SSE
544
545 #
546 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
547 #
548 SAVE_REGS
549
550 #
551 # Save timestamp into XMM6
552 #
553 rdtsc
554 SAVE_EAX
555 SAVE_EDX
556
557 #
558 # Check Parameter
559 #
560 movl 4(%esp), %eax
561 cmpl $0x00, %eax
562 movl $0x80000002, %eax
563 jz NemInitExit
564
565 #
566 # Sec Platform Init
567 #
568 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit
569 movd %esi, %mm7
570 .weak ASM_PFX(SecPlatformInit)
571 .set ASM_PFX(SecPlatformInit), ASM_PFX(SecPlatformInitDefault)
572 jmp ASM_PFX(SecPlatformInit)
573 TempRamInitApiL1:
574 cmpl $0x00, %eax
575 jnz NemInitExit
576
577 #
578 # Load microcode
579 #
580 LOAD_ESP
581 movl $TempRamInitApiL2, %esi #CALL_MMX LoadMicrocode
582 movd %esi, %mm7
583 .weak ASM_PFX(LoadMicrocode)
584 .set ASM_PFX(LoadMicrocode), ASM_PFX(LoadMicrocodeDefault)
585 jmp ASM_PFX(LoadMicrocode)
586 TempRamInitApiL2:
587 SAVE_EAX_MICROCODE_RET_STATUS #Save microcode return status in ECX-SLOT 3 in xmm6.
588 #@note If return value eax is not 0, microcode did not load, but continue and attempt to boot from ECX-SLOT 3 in xmm6.
589
590 #
591 # Call Sec CAR Init
592 #
593 LOAD_ESP
594 movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit
595 movd %esi, %mm7
596 jmp ASM_PFX(SecCarInit)
597 TempRamInitApiL3:
598 cmpl $0x00, %eax
599 jnz NemInitExit
600
601 #
602 # EstablishStackFsp
603 #
604 LOAD_ESP
605 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp
606 movd %esi, %mm7
607 jmp ASM_PFX(EstablishStackFsp)
608 TempRamInitApiL4:
609
610 LOAD_EAX_MICROCODE_RET_STATUS #Restore microcode status if no CAR init error.
611
612 NemInitExit:
613 #
614 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
615 #
616 LOAD_REGS
617 ret
618
619
620 #----------------------------------------------------------------------------
621 # FspInit API
622 #
623 # This FSP API will perform the processor and chipset initialization.
624 # This API will not return. Instead, it transfers the control to the
625 # ContinuationFunc provided in the parameter.
626 #
627 #----------------------------------------------------------------------------
628 ASM_GLOBAL ASM_PFX(FspInitApi)
629 ASM_PFX(FspInitApi):
630 movl $0x01, %eax
631 jmp FspApiCommon
632
633 #----------------------------------------------------------------------------
634 # NotifyPhase API
635 #
636 # This FSP API will notify the FSP about the different phases in the boot
637 # process
638 #
639 #----------------------------------------------------------------------------
640 ASM_GLOBAL ASM_PFX(NotifyPhaseApi)
641 ASM_PFX(NotifyPhaseApi):
642 movl $0x02, %eax
643 jmp FspApiCommon
644
645 #----------------------------------------------------------------------------
646 # FspMemoryInit API
647 #
648 # This FSP API is called after TempRamInit and initializes the memory.
649 #
650 #----------------------------------------------------------------------------
651 ASM_GLOBAL ASM_PFX(FspMemoryInitApi)
652 ASM_PFX(FspMemoryInitApi):
653 movl $0x03, %eax
654 jmp FspApiCommon
655
656 #----------------------------------------------------------------------------
657 # TempRamExitApi API
658 #
659 # This API tears down temporary RAM
660 #
661 #----------------------------------------------------------------------------
662 ASM_GLOBAL ASM_PFX(TempRamExitApi)
663 ASM_PFX(TempRamExitApi):
664 movl $0x04, %eax
665 jmp FspApiCommon
666
667 #----------------------------------------------------------------------------
668 # FspSiliconInit API
669 #
670 # This FSP API initializes the CPU and the chipset including the IO
671 # controllers in the chipset to enable normal operation of these devices.
672 #
673 #----------------------------------------------------------------------------
674 ASM_GLOBAL ASM_PFX(FspSiliconInitApi)
675 ASM_PFX(FspSiliconInitApi):
676 movl $0x05, %eax
677 jmp FspApiCommon
678
679 #----------------------------------------------------------------------------
680 # FspApiCommon API
681 #
682 # This is the FSP API common entry point to resume the FSP execution
683 #
684 #----------------------------------------------------------------------------
685 ASM_GLOBAL ASM_PFX(FspApiCommon)
686 ASM_PFX(FspApiCommon):
687 #
688 # EAX holds the API index
689 #
690
691 #
692 # Stack must be ready
693 #
694 pushl %eax
695 addl $0x04, %esp
696 cmpl -4(%esp), %eax
697 jz FspApiCommonL0
698 movl $0x080000003, %eax
699 jmp FspApiCommonExit
700
701 FspApiCommonL0:
702 #
703 # Verify the calling condition
704 #
705 pushal
706 pushl %eax
707 call ASM_PFX(FspApiCallingCheck)
708 addl $0x04, %esp
709 cmpl $0x00, %eax
710 jz FspApiCommonL1
711 movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax
712 popal
713 ret
714
715 FspApiCommonL1:
716 popal
717 cmpl $0x01, %eax # FspInit API
718 jz FspApiCommonL2
719 cmpl $0x03, %eax # FspMemoryInit API
720 jz FspApiCommonL2
721 call ASM_PFX(GetFspInfoHdr)
722 jmp Loader2PeiSwitchStack
723
724 FspApiCommonL2:
725 #
726 # FspInit and FspMemoryInit APIs, setup the initial stack frame
727 #
728
729 #
730 # Place holder to store the FspInfoHeader pointer
731 #
732 pushl %eax
733
734 #
735 # Update the FspInfoHeader pointer
736 #
737 pushl %eax
738 call ASM_PFX(GetFspInfoHdr)
739 movl %eax, 4(%esp)
740 popl %eax
741
742 #
743 # Create a Task Frame in the stack for the Boot Loader
744 #
745 pushfl # 2 pushf for 4 byte alignment
746 cli
747 pushal
748
749 #
750 # Reserve 8 bytes for IDT save/restore
751 #
752 subl $0x08, %esp
753 sidt (%esp)
754
755 #
756 # Setup new FSP stack
757 #
758 movl %esp, %edi
759 movl PcdGet32(PcdTemporaryRamBase), %esp
760 addl PcdGet32(PcdTemporaryRamSize), %esp
761 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp
762
763 #
764 # Pass the API Idx to SecStartup
765 #
766 pushl %eax
767
768 #
769 # Pass the BootLoader stack to SecStartup
770 #
771 pushl %edi
772
773 #
774 # Pass entry point of the PEI core
775 #
776 call ASM_PFX(GetFspBaseAddress)
777 movl %eax, %edi
778 addl PcdGet32(PcdFspAreaSize), %edi
779 subl $0x20, %edi
780 addl %ds:(%edi), %eax
781 pushl %eax
782
783 #
784 # Pass BFV into the PEI Core
785 # It uses relative address to calucate the actual boot FV base
786 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
787 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
788 # they are different. The code below can handle both cases.
789 #
790 call ASM_PFX(GetFspBaseAddress)
791 movl %eax, %edi
792 call ASM_PFX(GetBootFirmwareVolumeOffset)
793 addl %edi, %eax
794 pushl %eax
795
796 #
797 # Pass stack base and size into the PEI Core
798 #
799 movl PcdGet32(PcdTemporaryRamBase), %eax
800 addl PcdGet32(PcdTemporaryRamSize), %eax
801 subl PcdGet32(PcdFspTemporaryRamSize), %eax
802 pushl %eax
803 pushl PcdGet32(PcdFspTemporaryRamSize)
804
805 #
806 # Pass Control into the PEI Core
807 #
808 call ASM_PFX(SecStartup)
809 addl $4, %esp
810 FspApiCommonExit:
811 ret
812