Home | History | Annotate | Download | only in Ia32
      1 #------------------------------------------------------------------------------
      2 #
      3 # Copyright (c) 2014, 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 # Module Name:
     13 #
     14 #  SecEntry.S
     15 #
     16 # Abstract:
     17 #
     18 #  This is the code that goes from real-mode to protected mode.
     19 #  It consumes the reset vector, calls TempRamInit API from FSP binary.
     20 #
     21 #------------------------------------------------------------------------------
     22 
     23 #include "Fsp.h"
     24 
     25 ASM_GLOBAL    ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspBase)
     26 ASM_GLOBAL    ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspSize)
     27 
     28 ASM_GLOBAL ASM_PFX(_TEXT_REALMODE)
     29 ASM_PFX(_TEXT_REALMODE):
     30 #----------------------------------------------------------------------------
     31 #
     32 # Procedure:    _ModuleEntryPoint
     33 #
     34 # Input:        None
     35 #
     36 # Output:       None
     37 #
     38 # Destroys:     Assume all registers
     39 #
     40 # Description:
     41 #
     42 #   Transition to non-paged flat-model protected mode from a
     43 #   hard-coded GDT that provides exactly two descriptors.
     44 #   This is a bare bones transition to protected mode only
     45 #   used for a while in PEI and possibly DXE.
     46 #
     47 #   After enabling protected mode, a far jump is executed to
     48 #   transfer to PEI using the newly loaded GDT.
     49 #
     50 # Return:       None
     51 #
     52 #  MMX Usage:
     53 #              MM0 = BIST State
     54 #              MM5 = Save time-stamp counter value high32bit
     55 #              MM6 = Save time-stamp counter value low32bit.
     56 #
     57 #----------------------------------------------------------------------------
     58 
     59 .align 4
     60 ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
     61 ASM_PFX(_ModuleEntryPoint):
     62   fninit                                # clear any pending Floating point exceptions
     63   #
     64   # Store the BIST value in mm0
     65   #
     66   movd    %eax, %mm0
     67 
     68   #
     69   # Save time-stamp counter value
     70   # rdtsc load 64bit time-stamp counter to EDX:EAX
     71   #
     72   rdtsc
     73   movd    %edx, %mm5
     74   movd    %ecx, %mm6
     75 
     76   #
     77   # Load the GDT table in GdtDesc
     78   #
     79   movl    $GdtDesc, %esi
     80   .byte   0x66
     81   lgdt    %cs:(%si)
     82 
     83   #
     84   # Transition to 16 bit protected mode
     85   #
     86   movl    %cr0, %eax                 # Get control register 0
     87   orl     $0x00000003, %eax          # Set PE bit (bit #0) & MP bit (bit #1)
     88   movl    %eax, %cr0                 # Activate protected mode
     89 
     90   movl    %cr4, %eax                 # Get control register 4
     91   orl     $0x00000600, %eax          # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
     92   movl    %eax, %cr4
     93 
     94   #
     95   # Now we're in 16 bit protected mode
     96   # Set up the selectors for 32 bit protected mode entry
     97   #
     98   movw    SYS_DATA_SEL, %ax
     99   movw    %ax, %ds
    100   movw    %ax, %es
    101   movw    %ax, %fs
    102   movw    %ax, %gs
    103   movw    %ax, %ss
    104 
    105   #
    106   # Transition to Flat 32 bit protected mode
    107   # The jump to a far pointer causes the transition to 32 bit mode
    108   #
    109   movl    ASM_PFX(ProtectedModeEntryLinearAddress), %esi
    110   jmp     *%cs:(%si)
    111 
    112 ASM_GLOBAL ASM_PFX(_TEXT_PROTECTED_MODE)
    113 ASM_PFX(_TEXT_PROTECTED_MODE):
    114 
    115 #----------------------------------------------------------------------------
    116 #
    117 # Procedure:    ProtectedModeEntryPoint
    118 #
    119 # Input:        None
    120 #
    121 # Output:       None
    122 #
    123 # Destroys:     Assume all registers
    124 #
    125 # Description:
    126 #
    127 # This function handles:
    128 #   Call two basic APIs from FSP binary
    129 #   Initializes stack with some early data (BIST, PEI entry, etc)
    130 #
    131 # Return:       None
    132 #
    133 #----------------------------------------------------------------------------
    134 
    135 .align 4
    136 ASM_GLOBAL ASM_PFX(ProtectedModeEntryPoint)
    137 ASM_PFX(ProtectedModeEntryPoint):
    138 
    139   # Find the fsp info header
    140   movl ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspBase), %edi
    141   movl ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspSize), %ecx
    142 
    143   movl FVH_SIGINATURE_OFFSET(%edi), %eax
    144   cmp  $FVH_SIGINATURE_VALID_VALUE, %eax
    145   jnz  FspHeaderNotFound
    146 
    147   xorl %eax, %eax
    148   movw FVH_EXTHEADER_OFFSET_OFFSET(%edi), %ax
    149   cmp  %ax, 0
    150   jnz  FspFvExtHeaderExist
    151 
    152   xorl %eax, %eax
    153   movw FVH_HEADER_LENGTH_OFFSET(%edi), %ax   # Bypass Fv Header
    154   addl %eax, %edi
    155   jmp  FspCheckFfsHeader
    156 
    157 FspFvExtHeaderExist:
    158   addl %eax, %edi
    159   movl FVH_EXTHEADER_SIZE_OFFSET(%edi), %eax  # Bypass Ext Fv Header
    160   addl %eax, %edi
    161 
    162   # Round up to 8 byte alignment
    163   movl %edi, %eax
    164   andb $0x07, %al
    165   jz FspCheckFfsHeader
    166 
    167   and  $0xFFFFFFF8, %edi
    168   add  $0x08, %edi
    169 
    170 FspCheckFfsHeader:
    171   # Check the ffs guid
    172   movl (%edi), %eax
    173   cmp  $FSP_HEADER_GUID_DWORD1, %eax
    174   jnz  FspHeaderNotFound
    175 
    176   movl 0x4(%edi), %eax
    177   cmp  $FSP_HEADER_GUID_DWORD2, %eax
    178   jnz  FspHeaderNotFound
    179 
    180   movl 0x08(%edi), %eax
    181   cmp  $FSP_HEADER_GUID_DWORD3, %eax
    182   jnz  FspHeaderNotFound
    183 
    184   movl 0x0c(%edi), %eax
    185   cmp  $FSP_HEADER_GUID_DWORD4, %eax
    186   jnz  FspHeaderNotFound
    187 
    188   add  $FFS_HEADER_SIZE_VALUE, %edi        # Bypass the ffs header
    189 
    190   # Check the section type as raw section
    191   movb SECTION_HEADER_TYPE_OFFSET(%edi), %al
    192   cmp  $0x19, %al
    193   jnz  FspHeaderNotFound
    194 
    195   addl $RAW_SECTION_HEADER_SIZE_VALUE, %edi  # Bypass the section header
    196   jmp  FspHeaderFound
    197 
    198 FspHeaderNotFound:
    199   jmp  .
    200 
    201 FspHeaderFound:
    202   # Get the fsp TempRamInit Api address
    203   movl FSP_HEADER_IMAGEBASE_OFFSET(%edi), %eax
    204   addl FSP_HEADER_TEMPRAMINIT_OFFSET(%edi), %eax
    205 
    206   # Setup the hardcode stack
    207   movl $TempRamInitStack, %esp
    208 
    209   # Call the fsp TempRamInit Api
    210   jmp  *%eax
    211 
    212 TempRamInitDone:
    213   cmp  $0x8000000E, %eax   #Check if EFI_NOT_FOUND returned. Error code for Microcode Update not found.
    214   je   CallSecFspInit      #If microcode not found, don't hang, but continue.
    215 
    216   cmp  $0x0, %eax
    217   jnz  FspApiFailed
    218 
    219   #   ECX: start of range
    220   #   EDX: end of range
    221 CallSecFspInit:
    222   xorl    %eax, %eax
    223   movl    %edx, %esp
    224 
    225   # Align the stack at DWORD
    226   addl  $3, %esp
    227   andl  $0xFFFFFFFC, %esp
    228 
    229   pushl   %edx
    230   pushl   %ecx
    231   pushl   %eax # zero - no hob list yet
    232   call ASM_PFX(CallPeiCoreEntryPoint)
    233 
    234 FspApiFailed:
    235   jmp .
    236 
    237 .align 0x10
    238 TempRamInitStack:
    239     .long  TempRamInitDone
    240     .long  ASM_PFX(TempRamInitParams)
    241 
    242 #
    243 # ROM-based Global-Descriptor Table for the Tiano PEI Phase
    244 #
    245 .align 16
    246 
    247 #
    248 # GDT[0]: 0x00: Null entry, never used.
    249 #
    250 .equ NULL_SEL,             . - GDT_BASE    # Selector [0]
    251 GDT_BASE:
    252 BootGdtTable:       .long  0
    253                     .long  0
    254 #
    255 # Linear data segment descriptor
    256 #
    257 .equ LINEAR_SEL,           . - GDT_BASE    # Selector [0x8]
    258     .word  0xFFFF                          # limit 0xFFFFF
    259     .word  0                               # base 0
    260     .byte  0
    261     .byte  0x92                            # present, ring 0, data, expand-up, writable
    262     .byte  0xCF                            # page-granular, 32-bit
    263     .byte  0
    264 #
    265 # Linear code segment descriptor
    266 #
    267 .equ LINEAR_CODE_SEL,      . - GDT_BASE    # Selector [0x10]
    268     .word  0xFFFF                          # limit 0xFFFFF
    269     .word  0                               # base 0
    270     .byte  0
    271     .byte  0x9B                            # present, ring 0, data, expand-up, not-writable
    272     .byte  0xCF                            # page-granular, 32-bit
    273     .byte  0
    274 #
    275 # System data segment descriptor
    276 #
    277 .equ SYS_DATA_SEL,         . - GDT_BASE    # Selector [0x18]
    278     .word  0xFFFF                          # limit 0xFFFFF
    279     .word  0                               # base 0
    280     .byte  0
    281     .byte  0x93                            # present, ring 0, data, expand-up, not-writable
    282     .byte  0xCF                            # page-granular, 32-bit
    283     .byte  0
    284 
    285 #
    286 # System code segment descriptor
    287 #
    288 .equ SYS_CODE_SEL,         . - GDT_BASE    # Selector [0x20]
    289     .word  0xFFFF                          # limit 0xFFFFF
    290     .word  0                               # base 0
    291     .byte  0
    292     .byte  0x9A                            # present, ring 0, data, expand-up, writable
    293     .byte  0xCF                            # page-granular, 32-bit
    294     .byte  0
    295 #
    296 # Spare segment descriptor
    297 #
    298 .equ SYS16_CODE_SEL,       . - GDT_BASE    # Selector [0x28]
    299     .word  0xFFFF                          # limit 0xFFFFF
    300     .word  0                               # base 0
    301     .byte  0x0E                            # Changed from F000 to E000.
    302     .byte  0x9B                            # present, ring 0, code, expand-up, writable
    303     .byte  0x00                            # byte-granular, 16-bit
    304     .byte  0
    305 #
    306 # Spare segment descriptor
    307 #
    308 .equ SYS16_DATA_SEL,       . - GDT_BASE    # Selector [0x30]
    309     .word  0xFFFF                          # limit 0xFFFF
    310     .word  0                               # base 0
    311     .byte  0
    312     .byte  0x93                            # present, ring 0, data, expand-up, not-writable
    313     .byte  0x00                            # byte-granular, 16-bit
    314     .byte  0
    315 
    316 #
    317 # Spare segment descriptor
    318 #
    319 .equ SPARE5_SEL,           . - GDT_BASE    # Selector [0x38]
    320     .word  0                               # limit 0
    321     .word  0                               # base 0
    322     .byte  0
    323     .byte  0                               # present, ring 0, data, expand-up, writable
    324     .byte  0                               # page-granular, 32-bit
    325     .byte  0
    326 .equ GDT_SIZE,             . - BootGdtTable    # Size, in bytes
    327 
    328 #
    329 # GDT Descriptor
    330 #
    331 GdtDesc:                                # GDT descriptor
    332     .word  GDT_SIZE - 1                    # GDT limit
    333     .long  BootGdtTable                    # GDT base address
    334 
    335 ASM_PFX(ProtectedModeEntryLinearAddress):
    336 ProtectedModeEntryLinearOffset:
    337   .long      ASM_PFX(ProtectedModeEntryPoint)  # Offset of our 32 bit code
    338   .word      LINEAR_CODE_SEL
    339