Home | History | Annotate | Download | only in Ia32
      1 ;; @file
      2 ;  Provide FSP API entry points.
      3 ;
      4 ; Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
      5 ; This program and the accompanying materials
      6 ; are licensed and made available under the terms and conditions of the BSD License
      7 ; which accompanies this distribution.  The full text of the license may be found at
      8 ; http://opensource.org/licenses/bsd-license.php.
      9 ;
     10 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 ;;
     13 
     14     .586p
     15     .model  flat,C
     16     .code
     17     .xmm
     18 
     19 INCLUDE    SaveRestoreSse.inc
     20 INCLUDE    MicrocodeLoad.inc
     21 
     22 ;
     23 ; Following are fixed PCDs
     24 ;
     25 EXTERN   PcdGet32(PcdTemporaryRamBase):DWORD
     26 EXTERN   PcdGet32(PcdTemporaryRamSize):DWORD
     27 EXTERN   PcdGet32(PcdFspTemporaryRamSize):DWORD
     28 EXTERN   PcdGet32(PcdFspAreaSize):DWORD
     29 
     30 ;
     31 ; Following functions will be provided in C
     32 ;
     33 
     34 EXTERN   SecStartup:PROC
     35 EXTERN   FspApiCallingCheck:PROC
     36 
     37 ;
     38 ; Following functions will be provided in PlatformSecLib
     39 ;
     40 EXTERN   AsmGetFspBaseAddress:PROC
     41 EXTERN   AsmGetFspInfoHeader:PROC
     42 EXTERN   GetBootFirmwareVolumeOffset:PROC
     43 EXTERN   Loader2PeiSwitchStack:PROC
     44 EXTERN   LoadMicrocode(LoadMicrocodeDefault):PROC
     45 EXTERN   SecPlatformInit(SecPlatformInitDefault):PROC
     46 EXTERN   SecCarInit:PROC
     47 
     48 ;
     49 ; Define the data length that we saved on the stack top
     50 ;
     51 DATA_LEN_OF_PER0         EQU   18h
     52 DATA_LEN_OF_MCUD         EQU   18h
     53 DATA_LEN_AT_STACK_TOP    EQU   (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
     54 
     55 ;
     56 ; Define SSE macros
     57 ;
     58 LOAD_MMX_EXT MACRO   ReturnAddress, MmxRegister
     59   mov     esi, ReturnAddress
     60   movd    MmxRegister, esi              ; save ReturnAddress into MMX
     61 ENDM
     62 
     63 CALL_MMX_EXT MACRO   RoutineLabel, MmxRegister
     64   local   ReturnAddress
     65   mov     esi, offset ReturnAddress
     66   movd    MmxRegister, esi              ; save ReturnAddress into MMX
     67   jmp     RoutineLabel
     68 ReturnAddress:
     69 ENDM
     70 
     71 RET_ESI_EXT  MACRO   MmxRegister
     72   movd    esi, MmxRegister              ; move ReturnAddress from MMX to ESI
     73   jmp     esi
     74 ENDM
     75 
     76 CALL_MMX MACRO   RoutineLabel
     77          CALL_MMX_EXT  RoutineLabel, mm7
     78 ENDM
     79 
     80 RET_ESI  MACRO
     81          RET_ESI_EXT   mm7
     82 ENDM
     83 
     84 ;------------------------------------------------------------------------------
     85 SecPlatformInitDefault PROC NEAR PUBLIC
     86    ; Inputs:
     87    ;   mm7 -> Return address
     88    ; Outputs:
     89    ;   eax -> 0 - Successful, Non-zero - Failed.
     90    ; Register Usage:
     91    ;   eax is cleared and ebp is used for return address.
     92    ;   All others reserved.
     93    
     94    ; Save return address to EBP
     95    movd  ebp, mm7
     96 
     97    xor   eax, eax
     98 exit:
     99    jmp   ebp
    100 SecPlatformInitDefault   ENDP
    101 
    102 ;------------------------------------------------------------------------------
    103 LoadMicrocodeDefault   PROC  NEAR PUBLIC
    104    ; Inputs:
    105    ;   esp -> LoadMicrocodeParams pointer
    106    ; Register Usage:
    107    ;   esp  Preserved
    108    ;   All others destroyed
    109    ; Assumptions:
    110    ;   No memory available, stack is hard-coded and used for return address
    111    ;   Executed by SBSP and NBSP
    112    ;   Beginning of microcode update region starts on paragraph boundary
    113 
    114    ;
    115    ;
    116    ; Save return address to EBP
    117    movd   ebp, mm7
    118 
    119    cmp    esp, 0
    120    jz     paramerror
    121    mov    eax, dword ptr [esp + 4]    ; Parameter pointer
    122    cmp    eax, 0
    123    jz     paramerror
    124    mov    esp, eax
    125    mov    esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
    126    cmp    esi, 0
    127    jnz    check_main_header
    128 
    129 paramerror:
    130    mov    eax, 080000002h
    131    jmp    exit
    132 
    133    mov    esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
    134 
    135 check_main_header:
    136    ; Get processor signature and platform ID from the installed processor
    137    ; and save into registers for later use
    138    ; ebx = processor signature
    139    ; edx = platform ID
    140    mov   eax, 1
    141    cpuid
    142    mov   ebx, eax
    143    mov   ecx, MSR_IA32_PLATFORM_ID
    144    rdmsr
    145    mov   ecx, edx
    146    shr   ecx, 50-32                          ; shift (50d-32d=18d=0x12) bits
    147    and   ecx, 7h                             ; platform id at bit[52..50]
    148    mov   edx, 1
    149    shl   edx, cl
    150 
    151    ; Current register usage
    152    ; esp -> stack with paramters
    153    ; esi -> microcode update to check
    154    ; ebx = processor signature
    155    ; edx = platform ID
    156 
    157    ; Check for valid microcode header
    158    ; Minimal test checking for header version and loader version as 1
    159    mov   eax, dword ptr 1
    160    cmp   [esi].MicrocodeHdr.MicrocodeHdrVersion, eax
    161    jne   advance_fixed_size
    162    cmp   [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
    163    jne   advance_fixed_size
    164 
    165    ; Check if signature and plaform ID match
    166    cmp   ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
    167    jne   @f
    168    test  edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
    169    jnz   load_check  ; Jif signature and platform ID match
    170 
    171 @@:
    172    ; Check if extended header exists
    173    ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
    174    xor   eax, eax
    175    cmp   [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
    176    je    next_microcode
    177    cmp   [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
    178    je    next_microcode
    179 
    180    ; Then verify total size - sizeof header > data size
    181    mov   ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
    182    sub   ecx, sizeof MicrocodeHdr
    183    cmp   ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
    184    jng   next_microcode    ; Jif extended header does not exist
    185 
    186    ; Set edi -> extended header
    187    mov   edi, esi
    188    add   edi, sizeof MicrocodeHdr
    189    add   edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
    190 
    191    ; Get count of extended structures
    192    mov   ecx, [edi].ExtSigHdr.ExtSigHdrCount
    193 
    194    ; Move pointer to first signature structure
    195    add   edi, sizeof ExtSigHdr
    196 
    197 check_ext_sig:
    198    ; Check if extended signature and platform ID match
    199    cmp   [edi].ExtSig.ExtSigProcessor, ebx
    200    jne   @f
    201    test  [edi].ExtSig.ExtSigFlags, edx
    202    jnz   load_check     ; Jif signature and platform ID match
    203 @@:
    204    ; Check if any more extended signatures exist
    205    add   edi, sizeof ExtSig
    206    loop  check_ext_sig
    207 
    208 next_microcode:
    209    ; Advance just after end of this microcode
    210    xor   eax, eax
    211    cmp   [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
    212    je    @f
    213    add   esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
    214    jmp   check_address
    215 @@:
    216    add   esi, dword ptr 2048
    217    jmp   check_address
    218 
    219 advance_fixed_size:
    220    ; Advance by 4X dwords
    221    add   esi, dword ptr 1024
    222 
    223 check_address:
    224    ; Is valid Microcode start point ?
    225    cmp   dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
    226    jz    done
    227 
    228    ; Is automatic size detection ?
    229    mov   eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
    230    cmp   eax, 0ffffffffh
    231    jz    @f
    232 
    233    ; Address >= microcode region address + microcode region size?
    234    add   eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
    235    cmp   esi, eax
    236    jae   done        ;Jif address is outside of microcode region
    237    jmp   check_main_header
    238 
    239 @@:
    240 load_check:
    241    ; Get the revision of the current microcode update loaded
    242    mov   ecx, MSR_IA32_BIOS_SIGN_ID
    243    xor   eax, eax               ; Clear EAX
    244    xor   edx, edx               ; Clear EDX
    245    wrmsr                        ; Load 0 to MSR at 8Bh
    246 
    247    mov   eax, 1
    248    cpuid
    249    mov   ecx, MSR_IA32_BIOS_SIGN_ID
    250    rdmsr                         ; Get current microcode signature
    251 
    252    ; Verify this microcode update is not already loaded
    253    cmp   [esi].MicrocodeHdr.MicrocodeHdrRevision, edx
    254    je    continue
    255 
    256 load_microcode:
    257    ; EAX contains the linear address of the start of the Update Data
    258    ; EDX contains zero
    259    ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
    260    ; Start microcode load with wrmsr
    261    mov   eax, esi
    262    add   eax, sizeof MicrocodeHdr
    263    xor   edx, edx
    264    mov   ecx, MSR_IA32_BIOS_UPDT_TRIG
    265    wrmsr
    266    mov   eax, 1
    267    cpuid
    268 
    269 continue:
    270    jmp   next_microcode
    271 
    272 done:
    273    mov   eax, 1
    274    cpuid
    275    mov   ecx, MSR_IA32_BIOS_SIGN_ID
    276    rdmsr                         ; Get current microcode signature
    277    xor   eax, eax
    278    cmp   edx, 0
    279    jnz   exit
    280    mov   eax, 08000000Eh
    281 
    282 exit:
    283    jmp   ebp
    284 
    285 LoadMicrocodeDefault   ENDP
    286 
    287 EstablishStackFsp    PROC    NEAR    PRIVATE
    288   ;
    289   ; Save parameter pointer in edx
    290   ;
    291   mov       edx, dword ptr [esp + 4]
    292 
    293   ;
    294   ; Enable FSP STACK
    295   ;
    296   mov       esp, PcdGet32 (PcdTemporaryRamBase)
    297   add       esp, PcdGet32 (PcdTemporaryRamSize)
    298 
    299   push      DATA_LEN_OF_MCUD     ; Size of the data region
    300   push      4455434Dh            ; Signature of the  data region 'MCUD'
    301   push      dword ptr [edx + 12] ; Code size
    302   push      dword ptr [edx + 8]  ; Code base
    303   push      dword ptr [edx + 4]  ; Microcode size
    304   push      dword ptr [edx]      ; Microcode base
    305 
    306   ;
    307   ; Save API entry/exit timestamp into stack
    308   ;
    309   push      DATA_LEN_OF_PER0     ; Size of the data region 
    310   push      30524550h            ; Signature of the  data region 'PER0'
    311   LOAD_EDX
    312   push      edx
    313   LOAD_EAX
    314   push      eax
    315   rdtsc
    316   push      edx
    317   push      eax
    318 
    319   ;
    320   ; Terminator for the data on stack
    321   ; 
    322   push      0
    323 
    324   ;
    325   ; Set ECX/EDX to the BootLoader temporary memory range
    326   ;
    327   mov       ecx, PcdGet32 (PcdTemporaryRamBase)
    328   mov       edx, ecx
    329   add       edx, PcdGet32 (PcdTemporaryRamSize)
    330   sub       edx, PcdGet32 (PcdFspTemporaryRamSize)
    331 
    332   xor       eax, eax
    333 
    334   RET_ESI
    335 
    336 EstablishStackFsp    ENDP
    337 
    338 
    339 ;----------------------------------------------------------------------------
    340 ; TempRamInit API
    341 ;
    342 ; This FSP API will load the microcode update, enable code caching for the
    343 ; region specified by the boot loader and also setup a temporary stack to be
    344 ; used till main memory is initialized.
    345 ;
    346 ;----------------------------------------------------------------------------
    347 TempRamInitApi   PROC    NEAR    PUBLIC
    348   ;
    349   ; Ensure SSE is enabled
    350   ;
    351   ENABLE_SSE
    352 
    353   ;
    354   ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
    355   ;
    356   SAVE_REGS
    357 
    358   ;
    359   ; Save timestamp into XMM6
    360   ;
    361   rdtsc
    362   SAVE_EAX
    363   SAVE_EDX
    364 
    365   ;
    366   ; Check Parameter
    367   ;
    368   mov       eax, dword ptr [esp + 4]
    369   cmp       eax, 0
    370   mov       eax, 80000002h
    371   jz        TempRamInitExit
    372 
    373   ;
    374   ; Sec Platform Init
    375   ;
    376   CALL_MMX  SecPlatformInit
    377   cmp       eax, 0
    378   jnz       TempRamInitExit
    379 
    380   ; Load microcode
    381   LOAD_ESP
    382   CALL_MMX  LoadMicrocode
    383   SXMMN     xmm6, 3, eax            ;Save microcode return status in ECX-SLOT 3 in xmm6.
    384   ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
    385 
    386   ; Call Sec CAR Init
    387   LOAD_ESP
    388   CALL_MMX  SecCarInit
    389   cmp       eax, 0
    390   jnz       TempRamInitExit
    391 
    392   LOAD_ESP
    393   CALL_MMX  EstablishStackFsp
    394 
    395   LXMMN      xmm6, eax, 3  ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
    396 
    397 TempRamInitExit:
    398   ;
    399   ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
    400   ;
    401   LOAD_REGS
    402   ret
    403 TempRamInitApi   ENDP
    404 
    405 ;----------------------------------------------------------------------------
    406 ; FspInit API
    407 ;
    408 ; This FSP API will perform the processor and chipset initialization.
    409 ; This API will not return.  Instead, it transfers the control to the
    410 ; ContinuationFunc provided in the parameter.
    411 ;
    412 ;----------------------------------------------------------------------------
    413 FspInitApi   PROC    NEAR    PUBLIC
    414   mov    eax,  1
    415   jmp    FspApiCommon
    416   FspInitApi   ENDP
    417 
    418 ;----------------------------------------------------------------------------
    419 ; NotifyPhase API
    420 ;
    421 ; This FSP API will notify the FSP about the different phases in the boot
    422 ; process
    423 ;
    424 ;----------------------------------------------------------------------------
    425 NotifyPhaseApi   PROC C PUBLIC
    426   mov    eax,  2
    427   jmp    FspApiCommon
    428 NotifyPhaseApi   ENDP
    429 
    430 ;----------------------------------------------------------------------------
    431 ; FspMemoryInit API
    432 ;
    433 ; This FSP API is called after TempRamInit and initializes the memory.
    434 ;
    435 ;----------------------------------------------------------------------------
    436 FspMemoryInitApi   PROC    NEAR    PUBLIC
    437   mov    eax,  3
    438   jmp    FspApiCommon
    439 FspMemoryInitApi   ENDP
    440 
    441 
    442 ;----------------------------------------------------------------------------
    443 ; TempRamExitApi API
    444 ;
    445 ; This API tears down temporary RAM
    446 ;
    447 ;----------------------------------------------------------------------------
    448 TempRamExitApi   PROC C PUBLIC
    449   mov    eax,  4
    450   jmp    FspApiCommon
    451 TempRamExitApi   ENDP
    452 
    453 
    454 ;----------------------------------------------------------------------------
    455 ; FspSiliconInit API
    456 ;
    457 ; This FSP API initializes the CPU and the chipset including the IO
    458 ; controllers in the chipset to enable normal operation of these devices.
    459 ;
    460 ;----------------------------------------------------------------------------
    461 FspSiliconInitApi   PROC C PUBLIC
    462   mov    eax,  5
    463   jmp    FspApiCommon
    464 FspSiliconInitApi   ENDP
    465 
    466 ;----------------------------------------------------------------------------
    467 ; FspApiCommon API
    468 ;
    469 ; This is the FSP API common entry point to resume the FSP execution
    470 ;
    471 ;----------------------------------------------------------------------------
    472 FspApiCommon   PROC C PUBLIC
    473   ;
    474   ; EAX holds the API index
    475   ;
    476 
    477   ;
    478   ; Stack must be ready
    479   ;  
    480   push   eax
    481   add    esp, 4
    482   cmp    eax, dword ptr [esp - 4]
    483   jz     @F
    484   mov    eax, 080000003h
    485   jmp    exit
    486 
    487 @@:
    488   ;
    489   ; Verify the calling condition
    490   ;
    491   pushad
    492   push   [esp + 4 * 8 + 4]  ; push ApiParam
    493   push   eax                ; push ApiIdx
    494   call   FspApiCallingCheck
    495   add    esp, 8
    496   cmp    eax, 0
    497   jz     @F
    498   mov    dword ptr [esp + 4 * 7], eax
    499   popad
    500   ret
    501 
    502 @@:
    503   popad
    504   cmp    eax, 1   ; FspInit API
    505   jz     @F
    506   cmp    eax, 3   ; FspMemoryInit API
    507   jz     @F
    508 
    509   call   AsmGetFspInfoHeader
    510   jmp    Loader2PeiSwitchStack
    511 
    512 @@:
    513   ;
    514   ; FspInit and FspMemoryInit APIs, setup the initial stack frame
    515   ;
    516   
    517   ;
    518   ; Place holder to store the FspInfoHeader pointer
    519   ;
    520   push   eax
    521 
    522   ;
    523   ; Update the FspInfoHeader pointer
    524   ;
    525   push   eax
    526   call   AsmGetFspInfoHeader
    527   mov    [esp + 4], eax
    528   pop    eax
    529 
    530   ;
    531   ; Create a Task Frame in the stack for the Boot Loader
    532   ;
    533   pushfd     ; 2 pushf for 4 byte alignment
    534   cli
    535   pushad
    536 
    537   ; Reserve 8 bytes for IDT save/restore
    538   sub     esp, 8
    539   sidt    fword ptr [esp]
    540 
    541   ;
    542   ; Setup new FSP stack
    543   ;
    544   mov     edi, esp
    545   mov     esp, PcdGet32(PcdTemporaryRamBase)
    546   add     esp, PcdGet32(PcdTemporaryRamSize)
    547   sub     esp, (DATA_LEN_AT_STACK_TOP + 40h)
    548 
    549   ;
    550   ; Pass the API Idx to SecStartup
    551   ;
    552   push    eax
    553   
    554   ;
    555   ; Pass the BootLoader stack to SecStartup
    556   ;
    557   push    edi
    558 
    559   ;
    560   ; Pass entry point of the PEI core
    561   ;
    562   call    AsmGetFspBaseAddress
    563   mov     edi, eax
    564   add     edi, PcdGet32 (PcdFspAreaSize) 
    565   sub     edi, 20h
    566   add     eax, DWORD PTR ds:[edi]
    567   push    eax
    568 
    569   ;
    570   ; Pass BFV into the PEI Core
    571   ; It uses relative address to calucate the actual boot FV base
    572   ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and
    573   ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
    574   ; they are different. The code below can handle both cases.
    575   ;
    576   call    AsmGetFspBaseAddress
    577   mov     edi, eax
    578   call    GetBootFirmwareVolumeOffset
    579   add     eax, edi
    580   push    eax
    581 
    582   ;
    583   ; Pass stack base and size into the PEI Core
    584   ;
    585   mov     eax,  PcdGet32(PcdTemporaryRamBase)
    586   add     eax,  PcdGet32(PcdTemporaryRamSize)
    587   sub     eax,  PcdGet32(PcdFspTemporaryRamSize)
    588   push    eax
    589   push    PcdGet32(PcdFspTemporaryRamSize)
    590 
    591   ;
    592   ; Pass Control into the PEI Core
    593   ;
    594   call    SecStartup
    595   add     esp, 4
    596 exit:
    597   ret
    598 
    599 FspApiCommon   ENDP
    600 
    601 END
    602