Home | History | Annotate | Download | only in Ia32
      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(AsmGetFspBaseAddress)
    219 ASM_GLOBAL    ASM_PFX(AsmGetFspInfoHeader)
    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                        # 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 
    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   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 
    716 FspApiCommonL1:
    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 
    725 FspApiCommonL2:
    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
    811 FspApiCommonExit:
    812   ret
    813 
    814