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 24MicrocodeHdr: 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 35MicrocodeHdrEnd: 36.equ MicrocodeHdrLength, 0x0030 # MicrocodeHdrLength = MicrocodeHdrEnd - MicrocodeHdr 37 38 39ExtSigHdr: 40.equ ExtSigHdrCount, 0x0000 41.equ ExtSigHdrChecksum, 0x0004 42.equ ExtSigHdrRsvd, 0x0008 43ExtSigHdrEnd: 44.equ ExtSigHdrLength, 0x0014 #ExtSigHdrLength = ExtSigHdrEnd - ExtSigHdr 45 46ExtSig: 47.equ ExtSigProcessor, 0x0000 48.equ ExtSigFlags, 0x0004 49.equ ExtSigChecksum, 0x0008 50ExtSigEnd: 51.equ ExtSigLength, 0x000C #ExtSigLength = ExtSigEnd - ExtSig 52 53LoadMicrocodeParams: 54.equ MicrocodeCodeAddr, 0x0000 55.equ MicrocodeCodeSize, 0x0004 56LoadMicrocodeParamsEnd: 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 # 144ASM_PFX(mFpuControlWord): .word 0x027F 145 # 146 # Multimedia-extensions control word: 147 # all exceptions masked, round-to-nearest, flush to zero for masked underflow 148 # 149ASM_PFX(mMmxControlWord): .long 0x01F80 150SseError: 151 # 152 # Processor has to support SSE 153 # 154 jmp SseError 155NextAddress: 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# 205ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase) 206ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize) 207ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize) 208 209# 210# Following functions will be provided in C 211# 212ASM_GLOBAL ASM_PFX(SecStartup) 213ASM_GLOBAL ASM_PFX(FspApiCallingCheck) 214 215# 216# Following functions will be provided in PlatformSecLib 217# 218ASM_GLOBAL ASM_PFX(AsmGetFspBaseAddress) 219ASM_GLOBAL ASM_PFX(AsmGetFspInfoHeader) 220ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset) 221ASM_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#------------------------------------------------------------------------------ 241ASM_GLOBAL ASM_PFX(SecPlatformInitDefault) 242ASM_PFX(SecPlatformInitDefault): 243 # 244 # Save return address to EBP 245 # 246 movd %mm7, %ebp 247 xorl %eax, %eax 248 249SecPlatformInitDefaultExit: 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#------------------------------------------------------------------------------ 266ASM_GLOBAL ASM_PFX(LoadMicrocodeDefault) 267ASM_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 283ParamError: 284 movl $0x080000002, %eax 285 jmp LoadMicrocodeExit 286 287CheckMainHeader: 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 # shift (50d-32d=18d=0x12) bits 301 andl $0x07, %ecx # platform id at bit[52..50] 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 331LoadMicrocodeL0: 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 367CheckExtSig: 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 375LoadMicrocodeL1: 376 # 377 # Check if any more extended signatures exist 378 # 379 addl $ExtSigLength, %edi 380 loop CheckExtSig 381 382NextMicrocode: 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 391LoadMicrocodeL2: 392 addl $0x800, %esi #add esi, dword ptr 2048 393 jmp CheckAddress 394 395AdvanceFixedSize: 396 # 397 # Advance by 4X dwords 398 # 399 addl $0x400, %esi #add esi, dword ptr 1024 400 401CheckAddress: 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 422LoadMicrocodeL3: 423LoadCheck: 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 443LoadMicrocode0: 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 458Continue: 459 jmp NextMicrocode 460 461Done: 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 471LoadMicrocodeExit: 472 jmp *%ebp 473 474 475#---------------------------------------------------------------------------- 476# EstablishStackFsp 477# 478#---------------------------------------------------------------------------- 479ASM_GLOBAL ASM_PFX(EstablishStackFsp) 480ASM_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#---------------------------------------------------------------------------- 538ASM_GLOBAL ASM_PFX(TempRamInitApi) 539ASM_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) 573TempRamInitApiL1: 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) 586TempRamInitApiL2: 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) 597TempRamInitApiL3: 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) 608TempRamInitApiL4: 609 610 LOAD_EAX_MICROCODE_RET_STATUS #Restore microcode status if no CAR init error. 611 612NemInitExit: 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#---------------------------------------------------------------------------- 628ASM_GLOBAL ASM_PFX(FspInitApi) 629ASM_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#---------------------------------------------------------------------------- 640ASM_GLOBAL ASM_PFX(NotifyPhaseApi) 641ASM_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#---------------------------------------------------------------------------- 651ASM_GLOBAL ASM_PFX(FspMemoryInitApi) 652ASM_PFX(FspMemoryInitApi): 653 movl $0x03, %eax 654 jmp FspApiCommon 655 656#---------------------------------------------------------------------------- 657# TempRamExitApi API 658# 659# This API tears down temporary RAM 660# 661#---------------------------------------------------------------------------- 662ASM_GLOBAL ASM_PFX(TempRamExitApi) 663ASM_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#---------------------------------------------------------------------------- 674ASM_GLOBAL ASM_PFX(FspSiliconInitApi) 675ASM_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#---------------------------------------------------------------------------- 685ASM_GLOBAL ASM_PFX(FspApiCommon) 686ASM_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 701FspApiCommonL0: 702 # 703 # Verify the calling condition 704 # 705 pushal 706 pushl 36(%esp) #push ApiParam [esp + 4 * 8 + 4] 707 pushl %eax #push ApiIdx 708 call ASM_PFX(FspApiCallingCheck) 709 addl $0x08, %esp 710 cmpl $0x00, %eax 711 jz FspApiCommonL1 712 movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax 713 popal 714 ret 715 716FspApiCommonL1: 717 popal 718 cmpl $0x01, %eax # FspInit API 719 jz FspApiCommonL2 720 cmpl $0x03, %eax # FspMemoryInit API 721 jz FspApiCommonL2 722 call ASM_PFX(AsmGetFspInfoHeader) 723 jmp Loader2PeiSwitchStack 724 725FspApiCommonL2: 726 # 727 # FspInit and FspMemoryInit APIs, setup the initial stack frame 728 # 729 730 # 731 # Place holder to store the FspInfoHeader pointer 732 # 733 pushl %eax 734 735 # 736 # Update the FspInfoHeader pointer 737 # 738 pushl %eax 739 call ASM_PFX(AsmGetFspInfoHeader) 740 movl %eax, 4(%esp) 741 popl %eax 742 743 # 744 # Create a Task Frame in the stack for the Boot Loader 745 # 746 pushfl # 2 pushf for 4 byte alignment 747 cli 748 pushal 749 750 # 751 # Reserve 8 bytes for IDT save/restore 752 # 753 subl $0x08, %esp 754 sidt (%esp) 755 756 # 757 # Setup new FSP stack 758 # 759 movl %esp, %edi 760 movl PcdGet32(PcdTemporaryRamBase), %esp 761 addl PcdGet32(PcdTemporaryRamSize), %esp 762 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp 763 764 # 765 # Pass the API Idx to SecStartup 766 # 767 pushl %eax 768 769 # 770 # Pass the BootLoader stack to SecStartup 771 # 772 pushl %edi 773 774 # 775 # Pass entry point of the PEI core 776 # 777 call ASM_PFX(AsmGetFspBaseAddress) 778 movl %eax, %edi 779 addl PcdGet32(PcdFspAreaSize), %edi 780 subl $0x20, %edi 781 addl %ds:(%edi), %eax 782 pushl %eax 783 784 # 785 # Pass BFV into the PEI Core 786 # It uses relative address to calucate the actual boot FV base 787 # For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and 788 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs, 789 # they are different. The code below can handle both cases. 790 # 791 call ASM_PFX(AsmGetFspBaseAddress) 792 movl %eax, %edi 793 call ASM_PFX(GetBootFirmwareVolumeOffset) 794 addl %edi, %eax 795 pushl %eax 796 797 # 798 # Pass stack base and size into the PEI Core 799 # 800 movl PcdGet32(PcdTemporaryRamBase), %eax 801 addl PcdGet32(PcdTemporaryRamSize), %eax 802 subl PcdGet32(PcdFspTemporaryRamSize), %eax 803 pushl %eax 804 pushl PcdGet32(PcdFspTemporaryRamSize) 805 806 # 807 # Pass Control into the PEI Core 808 # 809 call ASM_PFX(SecStartup) 810 addl $4, %esp 811FspApiCommonExit: 812 ret 813 814