Home | History | Annotate | Download | only in Ia32
      1 ;; @file
      2 ;  Provide FSP API entry points.
      3 ;
      4 ; Copyright (c) 2016, 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     SECTION .text
     15 
     16 %include    "SaveRestoreSseNasm.inc"
     17 %include    "MicrocodeLoadNasm.inc"
     18 
     19 ;
     20 ; Following are fixed PCDs
     21 ;
     22 extern   ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
     23 extern   ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
     24 extern   ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
     25 
     26 ;
     27 ; Following functions will be provided in PlatformSecLib
     28 ;
     29 extern ASM_PFX(AsmGetFspBaseAddress)
     30 extern ASM_PFX(AsmGetFspInfoHeader)
     31 ;extern ASM_PFX(LoadMicrocode)    ; @todo: needs a weak implementation
     32 extern ASM_PFX(SecPlatformInit)   ; @todo: needs a weak implementation
     33 extern ASM_PFX(SecCarInit)
     34 
     35 ;
     36 ; Define the data length that we saved on the stack top
     37 ;
     38 DATA_LEN_OF_PER0         EQU   18h
     39 DATA_LEN_OF_MCUD         EQU   18h
     40 DATA_LEN_AT_STACK_TOP    EQU   (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
     41 
     42 ;
     43 ; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
     44 ;        build error. This needs to be fixed later on.
     45 ;
     46 struc MicrocodeHdr
     47     .MicrocodeHdrVersion:      resd    1
     48     .MicrocodeHdrRevision:     resd    1
     49     .MicrocodeHdrDate:         resd    1
     50     .MicrocodeHdrProcessor:    resd    1
     51     .MicrocodeHdrChecksum:     resd    1
     52     .MicrocodeHdrLoader:       resd    1
     53     .MicrocodeHdrFlags:        resd    1
     54     .MicrocodeHdrDataSize:     resd    1
     55     .MicrocodeHdrTotalSize:    resd    1
     56     .MicrocodeHdrRsvd:         resd    3
     57     .size:
     58 endstruc
     59 
     60 struc ExtSigHdr
     61     .ExtSigHdrCount:          resd    1
     62     .ExtSigHdrChecksum:       resd    1
     63     .ExtSigHdrRsvd:           resd    3
     64     .size:
     65 endstruc
     66 
     67 struc ExtSig
     68     .ExtSigProcessor:         resd    1
     69     .ExtSigFlags:             resd    1
     70     .ExtSigChecksum:          resd    1
     71     .size:
     72 endstruc
     73 
     74 struc LoadMicrocodeParams
     75     ; FSP_UPD_HEADER {
     76     .FspUpdHeader:            resd    8
     77     ; }
     78     ; FSPT_CORE_UPD {
     79     .MicrocodeCodeAddr:       resd    1
     80     .MicrocodeCodeSize:       resd    1
     81     .CodeRegionBase:          resd    1
     82     .CodeRegionSize:          resd    1
     83     ; }
     84     .size:
     85 endstruc
     86 
     87 
     88 ;
     89 ; Define SSE macros
     90 ;
     91 ;
     92 ;args 1: ReturnAddress  2:MmxRegister
     93 ;
     94 %macro LOAD_MMX_EXT 2
     95   mov     esi, %1
     96   movd    %2, esi              ; save ReturnAddress into MMX
     97 %endmacro
     98 
     99 ;
    100 ;args 1: RoutineLabel  2:MmxRegister
    101 ;
    102 %macro CALL_MMX_EXT  2
    103   mov     esi, %%ReturnAddress
    104   movd    %2, esi              ; save ReturnAddress into MMX
    105   jmp     %1
    106 %%ReturnAddress:
    107 %endmacro
    108 
    109 ;
    110 ;arg 1:MmxRegister
    111 ;
    112 %macro RET_ESI_EXT   1
    113   movd    esi, %1              ; move ReturnAddress from MMX to ESI
    114   jmp     esi
    115 %endmacro
    116 
    117 ;
    118 ;arg 1:RoutineLabel
    119 ;
    120 %macro CALL_MMX   1
    121          CALL_MMX_EXT  %1, mm7
    122 %endmacro
    123 
    124 %macro RET_ESI 0
    125          RET_ESI_EXT   mm7
    126 %endmacro
    127 
    128 ;
    129 ; @todo: The strong/weak implementation does not work.
    130 ;        This needs to be reviewed later.
    131 ;
    132 ;------------------------------------------------------------------------------
    133 ;
    134 ;;global ASM_PFX(SecPlatformInitDefault)
    135 ;ASM_PFX(SecPlatformInitDefault):
    136 ;   ; Inputs:
    137 ;   ;   mm7 -> Return address
    138 ;   ; Outputs:
    139 ;   ;   eax -> 0 - Successful, Non-zero - Failed.
    140 ;   ; Register Usage:
    141 ;   ;   eax is cleared and ebp is used for return address.
    142 ;   ;   All others reserved.
    143 ;
    144 ;   ; Save return address to EBP
    145 ;   movd  ebp, mm7
    146 ;
    147 ;   xor   eax, eax
    148 ;Exit1:
    149 ;   jmp   ebp
    150 
    151 ;------------------------------------------------------------------------------
    152 global ASM_PFX(LoadMicrocodeDefault)
    153 ASM_PFX(LoadMicrocodeDefault):
    154    ; Inputs:
    155    ;   esp -> LoadMicrocodeParams pointer
    156    ; Register Usage:
    157    ;   esp  Preserved
    158    ;   All others destroyed
    159    ; Assumptions:
    160    ;   No memory available, stack is hard-coded and used for return address
    161    ;   Executed by SBSP and NBSP
    162    ;   Beginning of microcode update region starts on paragraph boundary
    163 
    164    ;
    165    ;
    166    ; Save return address to EBP
    167    movd   ebp, mm7
    168 
    169    cmp    esp, 0
    170    jz     ParamError
    171    mov    eax, dword [esp + 4]    ; Parameter pointer
    172    cmp    eax, 0
    173    jz     ParamError
    174    mov    esp, eax
    175 
    176    ; skip loading Microcode if the MicrocodeCodeSize is zero
    177    ; and report error if size is less than 2k
    178    mov    eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
    179    cmp    eax, 0
    180    jz     Exit2
    181    cmp    eax, 0800h
    182    jl     ParamError
    183 
    184    mov    esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
    185    cmp    esi, 0
    186    jnz    CheckMainHeader
    187 
    188 ParamError:
    189    mov    eax, 080000002h
    190    jmp    Exit2
    191 
    192 CheckMainHeader:
    193    ; Get processor signature and platform ID from the installed processor
    194    ; and save into registers for later use
    195    ; ebx = processor signature
    196    ; edx = platform ID
    197    mov   eax, 1
    198    cpuid
    199    mov   ebx, eax
    200    mov   ecx, MSR_IA32_PLATFORM_ID
    201    rdmsr
    202    mov   ecx, edx
    203    shr   ecx, 50-32                          ; shift (50d-32d=18d=0x12) bits
    204    and   ecx, 7h                             ; platform id at bit[52..50]
    205    mov   edx, 1
    206    shl   edx, cl
    207 
    208    ; Current register usage
    209    ; esp -> stack with parameters
    210    ; esi -> microcode update to check
    211    ; ebx = processor signature
    212    ; edx = platform ID
    213 
    214    ; Check for valid microcode header
    215    ; Minimal test checking for header version and loader version as 1
    216    mov   eax, dword 1
    217    cmp   dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
    218    jne   AdvanceFixedSize
    219    cmp   dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
    220    jne   AdvanceFixedSize
    221 
    222    ; Check if signature and plaform ID match
    223    cmp   ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
    224    jne   LoadMicrocodeDefault1
    225    test  edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
    226    jnz   LoadCheck  ; Jif signature and platform ID match
    227 
    228 LoadMicrocodeDefault1:
    229    ; Check if extended header exists
    230    ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
    231    xor   eax, eax
    232    cmp   dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
    233    je    NextMicrocode
    234    cmp   dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
    235    je    NextMicrocode
    236 
    237    ; Then verify total size - sizeof header > data size
    238    mov   ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
    239    sub   ecx, MicrocodeHdr.size
    240    cmp   ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
    241    jng   NextMicrocode    ; Jif extended header does not exist
    242 
    243    ; Set edi -> extended header
    244    mov   edi, esi
    245    add   edi, MicrocodeHdr.size
    246    add   edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
    247 
    248    ; Get count of extended structures
    249    mov   ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
    250 
    251    ; Move pointer to first signature structure
    252    add   edi, ExtSigHdr.size
    253 
    254 CheckExtSig:
    255    ; Check if extended signature and platform ID match
    256    cmp   dword [edi + ExtSig.ExtSigProcessor], ebx
    257    jne   LoadMicrocodeDefault2
    258    test  dword [edi + ExtSig.ExtSigFlags], edx
    259    jnz   LoadCheck      ; Jif signature and platform ID match
    260 LoadMicrocodeDefault2:
    261    ; Check if any more extended signatures exist
    262    add   edi, ExtSig.size
    263    loop  CheckExtSig
    264 
    265 NextMicrocode:
    266    ; Advance just after end of this microcode
    267    xor   eax, eax
    268    cmp   dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
    269    je    LoadMicrocodeDefault3
    270    add   esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
    271    jmp   CheckAddress
    272 LoadMicrocodeDefault3:
    273    add   esi, dword  2048
    274    jmp   CheckAddress
    275 
    276 AdvanceFixedSize:
    277    ; Advance by 4X dwords
    278    add   esi, dword  1024
    279 
    280 CheckAddress:
    281    ; Is valid Microcode start point ?
    282    cmp   dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
    283    jz    Done
    284 
    285    ; Is automatic size detection ?
    286    mov   eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
    287    cmp   eax, 0ffffffffh
    288    jz    LoadMicrocodeDefault4
    289 
    290    ; Address >= microcode region address + microcode region size?
    291    add   eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
    292    cmp   esi, eax
    293    jae   Done        ;Jif address is outside of microcode region
    294    jmp   CheckMainHeader
    295 
    296 LoadMicrocodeDefault4:
    297 LoadCheck:
    298    ; Get the revision of the current microcode update loaded
    299    mov   ecx, MSR_IA32_BIOS_SIGN_ID
    300    xor   eax, eax               ; Clear EAX
    301    xor   edx, edx               ; Clear EDX
    302    wrmsr                        ; Load 0 to MSR at 8Bh
    303 
    304    mov   eax, 1
    305    cpuid
    306    mov   ecx, MSR_IA32_BIOS_SIGN_ID
    307    rdmsr                         ; Get current microcode signature
    308 
    309    ; Verify this microcode update is not already loaded
    310    cmp   dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
    311    je    Continue
    312 
    313 LoadMicrocode:
    314    ; EAX contains the linear address of the start of the Update Data
    315    ; EDX contains zero
    316    ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
    317    ; Start microcode load with wrmsr
    318    mov   eax, esi
    319    add   eax, MicrocodeHdr.size
    320    xor   edx, edx
    321    mov   ecx, MSR_IA32_BIOS_UPDT_TRIG
    322    wrmsr
    323    mov   eax, 1
    324    cpuid
    325 
    326 Continue:
    327    jmp   NextMicrocode
    328 
    329 Done:
    330    mov   eax, 1
    331    cpuid
    332    mov   ecx, MSR_IA32_BIOS_SIGN_ID
    333    rdmsr                         ; Get current microcode signature
    334    xor   eax, eax
    335    cmp   edx, 0
    336    jnz   Exit2
    337    mov   eax, 08000000Eh
    338 
    339 Exit2:
    340    jmp   ebp
    341 
    342 
    343 global ASM_PFX(EstablishStackFsp)
    344 ASM_PFX(EstablishStackFsp):
    345   ;
    346   ; Save parameter pointer in edx
    347   ;
    348   mov       edx, dword [esp + 4]
    349 
    350   ;
    351   ; Enable FSP STACK
    352   ;
    353   mov       esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
    354   add       esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
    355 
    356   push      DATA_LEN_OF_MCUD     ; Size of the data region
    357   push      4455434Dh            ; Signature of the  data region 'MCUD'
    358   push      dword [edx + 2Ch]    ; Code size       sizeof(FSPT_UPD_COMMON) + 12
    359   push      dword [edx + 28h]    ; Code base       sizeof(FSPT_UPD_COMMON) + 8
    360   push      dword [edx + 24h]    ; Microcode size  sizeof(FSPT_UPD_COMMON) + 4
    361   push      dword [edx + 20h]    ; Microcode base  sizeof(FSPT_UPD_COMMON) + 0
    362 
    363   ;
    364   ; Save API entry/exit timestamp into stack
    365   ;
    366   push      DATA_LEN_OF_PER0     ; Size of the data region
    367   push      30524550h            ; Signature of the  data region 'PER0'
    368   rdtsc
    369   push      edx
    370   push      eax
    371   LOAD_EDX
    372   push      edx
    373   LOAD_EAX
    374   push      eax
    375 
    376   ;
    377   ; Terminator for the data on stack
    378   ;
    379   push      0
    380 
    381   ;
    382   ; Set ECX/EDX to the BootLoader temporary memory range
    383   ;
    384   mov       ecx,  [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
    385   mov       edx, ecx
    386   add       edx,  [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
    387   sub       edx,  [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
    388 
    389   cmp       ecx, edx        ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
    390   jb        EstablishStackFspSuccess
    391   mov       eax, 80000003h  ;EFI_UNSUPPORTED
    392   jmp       EstablishStackFspExit
    393 EstablishStackFspSuccess:
    394   xor       eax, eax
    395 
    396 EstablishStackFspExit:
    397   RET_ESI
    398 
    399 ;----------------------------------------------------------------------------
    400 ; TempRamInit API
    401 ;
    402 ; This FSP API will load the microcode update, enable code caching for the
    403 ; region specified by the boot loader and also setup a temporary stack to be
    404 ; used till main memory is initialized.
    405 ;
    406 ;----------------------------------------------------------------------------
    407 global ASM_PFX(TempRamInitApi)
    408 ASM_PFX(TempRamInitApi):
    409   ;
    410   ; Ensure SSE is enabled
    411   ;
    412   ENABLE_SSE
    413 
    414   ;
    415   ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
    416   ;
    417   SAVE_REGS
    418 
    419   ;
    420   ; Save timestamp into XMM6
    421   ;
    422   rdtsc
    423   SAVE_EAX
    424   SAVE_EDX
    425 
    426   ;
    427   ; Check Parameter
    428   ;
    429   mov       eax, dword [esp + 4]
    430   cmp       eax, 0
    431   mov       eax, 80000002h
    432   jz        TempRamInitExit
    433 
    434   ;
    435   ; Sec Platform Init
    436   ;
    437   CALL_MMX  ASM_PFX(SecPlatformInit)
    438   cmp       eax, 0
    439   jnz       TempRamInitExit
    440 
    441   ; Load microcode
    442   LOAD_ESP
    443   CALL_MMX  ASM_PFX(LoadMicrocodeDefault)
    444   SXMMN     xmm6, 3, eax            ;Save microcode return status in ECX-SLOT 3 in xmm6.
    445   ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
    446 
    447   ; Call Sec CAR Init
    448   LOAD_ESP
    449   CALL_MMX  ASM_PFX(SecCarInit)
    450   cmp       eax, 0
    451   jnz       TempRamInitExit
    452 
    453   LOAD_ESP
    454   CALL_MMX  ASM_PFX(EstablishStackFsp)
    455   cmp       eax, 0
    456   jnz       TempRamInitExit
    457 
    458   LXMMN      xmm6, eax, 3  ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
    459 
    460 TempRamInitExit:
    461    mov      bl, al                  ; save al data in bl
    462    mov      al, 07Fh                ; API exit postcode 7f
    463    out      080h, al
    464    mov      al, bl                  ; restore al data from bl
    465 
    466   ;
    467   ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
    468   ;
    469   LOAD_REGS
    470   ret
    471 
    472 ;----------------------------------------------------------------------------
    473 ; Module Entrypoint API
    474 ;----------------------------------------------------------------------------
    475 global ASM_PFX(_ModuleEntryPoint)
    476 ASM_PFX(_ModuleEntryPoint):
    477   jmp $
    478