Home | History | Annotate | Download | only in Ia32
      1 #------------------------------------------------------------------------------
      2 #
      3 # Copyright (c) 2013 - 2016 Intel Corporation.
      4 #
      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 # Module Name:
     14 #
     15 #  Flat32.S
     16 #
     17 # Abstract:
     18 #
     19 #  This is the code that goes from real-mode to protected mode.
     20 #  It consumes the reset vector, configures the stack.
     21 #
     22 #
     23 #------------------------------------------------------------------------------
     24 
     25 .macro RET32
     26     jmp    *%esp
     27 .endm
     28 
     29 #
     30 # ROM/SPI/MEMORY Definitions
     31 #
     32 .equ  QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000)    # Memory Base Address = 0
     33 .equ  QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000)    # DDR3 Memory Size = 2GB
     34 .equ  QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000)    # eSRAM Memory Size = 512K
     35 .equ  QUARK_STACK_SIZE_BYTES, (0x008000)      # Quark stack size = 32K
     36 
     37 #
     38 # RTC/CMOS definitions
     39 #
     40 .equ  RTC_INDEX, (0x70)
     41 .equ    NMI_DISABLE, (0x80)  # Bit7=1 disables NMI
     42 .equ    NMI_ENABLE, (0x00)  # Bit7=0 disables NMI
     43 .equ  RTC_DATA, (0x71)
     44 
     45 #
     46 # PCI Configuration definitions
     47 #
     48 .equ  PCI_CFG, (0x80000000) # PCI configuration access mechanism
     49 .equ  PCI_ADDRESS_PORT, (0xCF8)
     50 .equ  PCI_DATA_PORT, (0xCFC)
     51 
     52 #
     53 # Quark PCI devices
     54 #
     55 .equ  HOST_BRIDGE_PFA, (0x0000)   # B0:D0:F0 (Host Bridge)
     56 .equ  ILB_PFA, (0x00F8)      # B0:D31:F0 (Legacy Block)
     57 
     58 #
     59 # ILB PCI Config Registers
     60 #
     61 .equ  BDE, (0x0D4)                                # BIOS Decode Enable register
     62 .equ    DECODE_ALL_REGIONS_ENABLE, (0xFF000000)    # Decode all BIOS decode ranges
     63 
     64 #
     65 # iLB Reset Register
     66 #
     67 .equ  ILB_RESET_REG, (0x0CF9)
     68 .equ    CF9_WARM_RESET, (0x02)
     69 .equ    CF9_COLD_RESET, (0x08)
     70 
     71 #
     72 # Host Bridge PCI Config Registers
     73 #
     74 .equ  MESSAGE_BUS_CONTROL_REG, (0xD0)       # Message Bus Control Register
     75 .equ    SB_OPCODE_FIELD, (0x18)              # Bit location of Opcode field
     76 .equ      OPCODE_SIDEBAND_REG_READ, (0x10)  # Read opcode
     77 .equ      OPCODE_SIDEBAND_REG_WRITE, (0x11) # Write opcode
     78 .equ      OPCODE_SIDEBAND_ALT_REG_READ, (0x06)  # Alternate Read opcode
     79 .equ      OPCODE_SIDEBAND_ALT_REG_WRITE, (0x07) # Alternate Write opcode
     80 .equ      OPCODE_WARM_RESET_REQUEST, (0xF4)  # Reset Warm
     81 .equ      OPCODE_COLD_RESET_REQUEST, (0xF5) # Reset Cold
     82 .equ    SB_PORT_FIELD, (0x10)               # Bit location of Port ID field
     83 .equ      MEMORY_ARBITER_PORT_ID, (0x00)
     84 .equ      HOST_BRIDGE_PORT_ID, (0x03)
     85 .equ      RMU_PORT_ID, (0x04)
     86 .equ      MEMORY_MANAGER_PORT_ID, (0x05)
     87 .equ      SOC_UNIT_PORT_ID, (0x31)
     88 .equ    SB_ADDR_FIELD, (0x08)               # Bit location of Register field
     89 .equ    SB_BE_FIELD, (0x04)                  # Bit location of Byte Enables field
     90 .equ      ALL_BYTE_EN, (0x0F)                # All Byte Enables
     91 .equ  MESSAGE_DATA_REG, (0xD4)              # Message Data Register
     92 
     93 #
     94 # Memory Arbiter Config Registers
     95 #
     96 .equ  AEC_CTRL_OFFSET, (0x00)
     97 
     98 #
     99 # Host Bridge Config Registers
    100 #
    101 .equ  HMISC2_OFFSET, (0x03) # PCI configuration access mechanism
    102 .equ    OR_PM_FIELD, (0x10)
    103 .equ      SMI_EN, (0x00080000)
    104 
    105 .equ  HMBOUND_OFFSET, (0x08)
    106 .equ    HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
    107 .equ    HMBOUND_LOCK, (0x01)
    108 .equ  HECREG_OFFSET, (0x09)
    109 .equ    EC_BASE, (0xE0000000)
    110 .equ    EC_ENABLE, (0x01)
    111 .equ  HLEGACY_OFFSET, (0x0A)
    112 .equ    NMI, (0x00004000)
    113 .equ    SMI, (0x00001000)
    114 .equ    INTR, (0x00000400)
    115 
    116 #
    117 # Memory Manager Config Registers
    118 #
    119 .equ  ESRAMPGCTRL_BLOCK_OFFSET, (0x82)
    120 .equ    BLOCK_ENABLE_PG, (0x10000000)
    121 .equ  BIMRVCTL_OFFSET, (0x19)
    122 .equ    ENABLE_IMR_INTERRUPT, (0x80000000)
    123 
    124 #
    125 # SOC UNIT Debug Registers
    126 #
    127 .equ  CFGSTICKY_W1_OFFSET, (0x50)
    128 .equ    FORCE_COLD_RESET, (0x00000001)
    129 .equ  CFGSTICKY_RW_OFFSET, (0x51)
    130 .equ    RESET_FOR_ESRAM_LOCK, (0x00000020)
    131 .equ    RESET_FOR_HMBOUND_LOCK, (0x00000040)
    132 .equ  CFGNONSTICKY_W1_OFFSET, (0x52)
    133 .equ    FORCE_WARM_RESET, (0x00000001)
    134 
    135 #
    136 # CR0 cache control bit definition
    137 #
    138 .equ                    CR0_CACHE_DISABLE, 0x040000000
    139 .equ                    CR0_NO_WRITE,      0x020000000
    140 
    141 ASM_GLOBAL  ASM_PFX(PcdGet32(PcdEsramStage1Base))
    142 
    143 
    144 #
    145 # Contrary to the name, this file contains 16 bit code as well.
    146 #
    147 .text
    148 #----------------------------------------------------------------------------
    149 #
    150 # Procedure:    _ModuleEntryPoint
    151 #
    152 # Input:        None
    153 #
    154 # Output:       None
    155 #
    156 # Destroys:     Assume all registers
    157 #
    158 # Description:
    159 #
    160 #   Transition to non-paged flat-model protected mode from a
    161 #   hard-coded GDT that provides exactly two descriptors.
    162 #   This is a bare bones transition to protected mode only
    163 #   used for a while in PEI and possibly DXE.
    164 #
    165 #   After enabling protected mode, a far jump is executed to
    166 #   transfer to PEI using the newly loaded GDT.
    167 #
    168 # Return:       None
    169 #
    170 #----------------------------------------------------------------------------
    171 ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
    172 ASM_PFX(_ModuleEntryPoint):
    173 
    174   #
    175   # Warm Reset (INIT#) check.
    176   #
    177   .byte   0xbe,0x00,0xf0   #movw    $0xF000, %si
    178   .byte   0x8e,0xde        #movw    %si, %ds
    179   .byte   0xbe,0xf0,0xff   #movw    $0xFFF0, %si
    180   .byte   0x80,0x3c,0xea   #cmpb    $0xEA, (%si)          # Is it warm reset ?
    181   jne     NotWarmReset     # Jump if not.
    182   .byte   0xb0,0x08        #movb    $0x08, %al
    183   .byte   0xba,0xf9,0x0c   #movw    $0xcf9, %dx
    184   .byte   0xee             #outb    %al, %dx
    185   .byte   0xb0,0x55        #movb    $0x55, %al
    186   .byte   0xe6,0x80        #outb    %al, $0x80
    187   jmp     .
    188 NotWarmReset:
    189   .byte   0x66,0x8b,0xe8   #movl    %eax, %ebp
    190 
    191   #
    192   # Load the GDT table in GdtDesc
    193   #
    194   .byte   0x66,0xbe        #movl    $GdtDesc, %esi
    195   .long   GdtDesc
    196 
    197   .byte   0x66,0x2e,0x0f,0x01,0x14   #lgdt    %cs:(%si)
    198 
    199   #
    200   # Transition to 16 bit protected mode
    201   #
    202   .byte   0x0f,0x20,0xc0       #movl    %cr0, %eax                  # Get control register 0
    203   .byte   0x66,0x83,0xc8,0x03  #orl     $0x0000003, %eax           # Set PE bit (bit #0) & MP bit (bit #1)
    204   .byte   0x0f,0x22,0xc0       #movl    %eax, %cr0                  # Activate protected mode
    205 
    206   #
    207   # Now we're in 16 bit protected mode
    208   # Set up the selectors for 32 bit protected mode entry
    209   #
    210   .byte   0xb8                 #movw    SYS_DATA_SEL, %ax
    211   .word   SYS_DATA_SEL
    212 
    213   .byte   0x8e,0xd8            #movw    %ax, %ds
    214   .byte   0x8e,0xc0            #movw    %ax, %es
    215   .byte   0x8e,0xe0            #movw    %ax, %fs
    216   .byte   0x8e,0xe8            #movw    %ax, %gs
    217   .byte   0x8e,0xd0            #movw    %ax, %ss
    218 
    219   #
    220   # Transition to Flat 32 bit protected mode
    221   # The jump to a far pointer causes the transition to 32 bit mode
    222   #
    223   .byte   0x66,0xbe            #movl   ProtectedModeEntryLinearAddress, %esi
    224   .long   ProtectedModeEntryLinearAddress
    225   .byte   0x66,0x2e,0xff,0x2c  #jmp    %cs:(%esi)
    226 
    227 #
    228 # Protected mode portion initializes stack, configures cache, and calls C entry point
    229 #
    230 
    231 #----------------------------------------------------------------------------
    232 #
    233 # Procedure:    ProtectedModeEntryPoint
    234 #
    235 # Input:        Executing in 32 Bit Protected (flat) mode
    236 #                cs: 0-4GB
    237 #                ds: 0-4GB
    238 #                es: 0-4GB
    239 #                fs: 0-4GB
    240 #                gs: 0-4GB
    241 #                ss: 0-4GB
    242 #
    243 # Output:       This function never returns
    244 #
    245 # Destroys:
    246 #               ecx
    247 #               edi
    248 #                esi
    249 #                esp
    250 #
    251 # Description:
    252 #                Perform any essential early platform initilaisation
    253 #               Setup a stack
    254 #               Transfer control to EDKII code in eSRAM
    255 #
    256 #----------------------------------------------------------------------------
    257 ProtectedModeEntryPoint:
    258   leal  L0, %esp
    259   jmp  stackless_EarlyPlatformInit
    260 L0:
    261 
    262   #
    263   # Set up stack pointer
    264   #
    265   movl    ASM_PFX(PcdGet32(PcdEsramStage1Base)), %esp
    266   movl    $QUARK_ESRAM_MEM_SIZE_BYTES, %esi
    267   addl    %esi, %esp                          # ESP = top of stack (stack grows downwards).
    268 
    269   #
    270   # Store the the BIST value in EBP
    271   #
    272   movl    $0, %ebp    # No processor BIST on Quark
    273 
    274   #
    275   # Push processor count to stack first, then BIST status (AP then BSP)
    276   #
    277   movl    $1, %eax
    278   cpuid
    279   shrl    $16, %ebx
    280   andl    $0x000000FF, %ebx
    281   cmpb    $1, %bl
    282   jae     PushProcessorCount
    283 
    284   #
    285   # Some processors report 0 logical processors.  Effectively 0 = 1.
    286   # So we fix up the processor count
    287   #
    288   incl    %ebx
    289 
    290 PushProcessorCount:
    291   pushl   %ebx
    292 
    293   #
    294   # We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST
    295   # for all processor threads
    296   #
    297   xorl    %ecx, %ecx
    298   movb    %bl, %cl
    299 
    300 PushBist:
    301   pushl   %ebp
    302   loop    PushBist
    303 
    304   #
    305   # Pass Control into the PEI Core
    306   #
    307   call PlatformSecLibStartup
    308 
    309   #
    310   # PEI Core should never return to here, this is just to capture an invalid return.
    311   #
    312   jmp     .
    313 
    314 #----------------------------------------------------------------------------
    315 #
    316 # Procedure:    stackless_EarlyPlatformInit
    317 #
    318 # Input:        esp - Return address
    319 #
    320 # Output:       None
    321 #
    322 # Destroys:     Assume all registers
    323 #
    324 # Description:
    325 #        Any early platform initialisation required
    326 #
    327 # Return:
    328 #      None
    329 #
    330 #----------------------------------------------------------------------------
    331 stackless_EarlyPlatformInit:
    332 
    333   #
    334   # Save return address
    335   #
    336   movl  %esp, %ebp
    337 
    338   #
    339   # Ensure cache is disabled.
    340   #
    341   movl %cr0, %eax
    342   orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax
    343   invd
    344   movl    %eax, %cr0
    345 
    346   #
    347   # Disable NMI operation
    348   # Good convention suggests you should read back RTC data port after
    349   # accessing the RTC index port.
    350   #
    351   movb $(NMI_DISABLE), %al
    352   movw $(RTC_INDEX), %dx
    353   outb %al, %dx
    354   movw $(RTC_DATA), %dx
    355   inb  %dx, %al
    356 
    357   #
    358   # Disable SMI (Disables SMI wire, not SMI messages)
    359   #
    360   movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
    361   leal  L1, %esp
    362   jmp  stackless_SideBand_Read
    363 L1:
    364   andl $(~SMI_EN), %eax
    365   movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
    366   leal  L2, %esp
    367   jmp  stackless_SideBand_Write
    368 L2:
    369 
    370   #
    371   # Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
    372   #
    373   movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
    374   leal  L3, %esp
    375   jmp  stackless_SideBand_Read
    376 L3:
    377   andl $(FORCE_WARM_RESET), %eax
    378   jz TestForceColdReset    # Zero means bit clear, we're not requested to warm reset so continue as normal
    379   jmp IssueWarmReset
    380 
    381 TestForceColdReset:
    382   movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
    383   leal  L4, %esp
    384   jmp  stackless_SideBand_Read
    385 L4:
    386   andl $(FORCE_COLD_RESET), %eax
    387   jz TestHmboundLock    # Zero means bit clear, we're not requested to cold reset so continue as normal
    388   jmp IssueColdReset
    389 
    390   #
    391   # Before setting HMBOUND, check it's not locked
    392   #
    393 TestHmboundLock:
    394   movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
    395   leal  L5, %esp
    396   jmp  stackless_SideBand_Read
    397 L5:
    398   andl $(HMBOUND_LOCK), %eax
    399   jz ConfigHmbound  # Zero means bit clear, we have the config we want so continue as normal
    400   #
    401   # Failed to config - store sticky bit debug
    402   #
    403   movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
    404   leal  L6, %esp
    405   jmp  stackless_SideBand_Read
    406 L6:
    407   orl $(RESET_FOR_HMBOUND_LOCK), %eax
    408   movl  $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
    409   leal  L7, %esp
    410   jmp  stackless_SideBand_Write
    411 L7:
    412   jmp IssueWarmReset
    413 
    414   #
    415   # Set up the HMBOUND register
    416   #
    417 ConfigHmbound:
    418   movl $(HMBOUND_ADDRESS), %eax      # Data (Set HMBOUND location)
    419   movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
    420   leal  L8, %esp
    421   jmp  stackless_SideBand_Write
    422 L8:
    423 
    424   #
    425   # Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
    426   #
    427   movl $(ENABLE_IMR_INTERRUPT), %eax      # Data (Set interrupt enable mask)
    428   movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (BIMRVCTL_OFFSET << SB_ADDR_FIELD)), %ecx
    429   leal  L9, %esp
    430   jmp  stackless_SideBand_Write
    431 L9:
    432 
    433   #
    434   # Set eSRAM address
    435   #
    436   movl    ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax   # Data (Set eSRAM location)
    437   shr   $(0x18), %eax
    438   addl  $(BLOCK_ENABLE_PG), %eax
    439   movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
    440   leal  L10, %esp
    441   jmp  stackless_SideBand_Write
    442 L10:
    443 
    444   #
    445   # Check that we're not blocked from setting the config that we want.
    446   #
    447   movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
    448   leal  L11, %esp
    449   jmp  stackless_SideBand_Read
    450 L11:
    451   andl $(BLOCK_ENABLE_PG), %eax
    452   jnz ConfigPci  # Non-zero means bit set, we have the config we want so continue as normal
    453   #
    454   # Failed to config - store sticky bit debug
    455   #
    456   movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
    457   leal  L12, %esp
    458   jmp  stackless_SideBand_Read
    459 L12:
    460   orl $(RESET_FOR_ESRAM_LOCK), %eax     # Set the bit we're interested in
    461   movl  $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
    462   leal  L13, %esp
    463   jmp  stackless_SideBand_Write
    464 L13:
    465   jmp IssueWarmReset
    466 
    467   #
    468   # Enable PCIEXBAR
    469   #
    470 ConfigPci:
    471   movl $(EC_BASE + EC_ENABLE), %eax      # Data
    472   movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx
    473   leal  L14, %esp
    474   jmp  stackless_SideBand_Write
    475 L14:
    476 
    477   movl $(EC_BASE + EC_ENABLE), %eax      # Data
    478   movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx
    479   leal  L15, %esp
    480   jmp  stackless_SideBand_Write
    481 L15:
    482 
    483   #
    484   #  Open up full 8MB SPI decode
    485   #
    486   movl  $(PCI_CFG | (ILB_PFA << 8) | BDE), %ebx  # PCI Configuration address
    487   movl $(DECODE_ALL_REGIONS_ENABLE), %eax
    488   leal  L16, %esp
    489   jmp  stackless_PCIConfig_Write
    490 L16:
    491 
    492   #
    493   # Enable NMI operation
    494   # Good convention suggests you should read back RTC data port after
    495   # accessing the RTC index port.
    496   #
    497   movb $(NMI_ENABLE), %al
    498   movw $(RTC_INDEX), %dx
    499   outb %al, %dx
    500   movw $(RTC_DATA), %dx
    501   inb  %dx, %al
    502 
    503   #
    504   # Clear Host Bridge SMI, NMI, INTR fields
    505   #
    506   movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
    507   leal  L21, %esp
    508   jmp  stackless_SideBand_Read
    509 L21:
    510   andl $~(NMI + SMI + INTR), %eax      # Clear NMI, SMI, INTR fields
    511   movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
    512   leal  L22, %esp
    513   jmp  stackless_SideBand_Write
    514 L22:
    515 
    516   #
    517   # Restore return address
    518   #
    519   movl  %ebp, %esp
    520   RET32
    521 
    522 IssueWarmReset:
    523   #
    524   # Issue Warm Reset request to Remote Management Unit via iLB
    525   #
    526   movw  $(CF9_WARM_RESET), %ax
    527   movw  $(ILB_RESET_REG), %dx
    528   outw  %ax, %dx
    529   jmp  .  # Stay here until we are reset.
    530 
    531 IssueColdReset:
    532   #
    533   # Issue Cold Reset request to Remote Management Unit via iLB
    534   #
    535   movw  $(CF9_COLD_RESET), %ax
    536   movw  $(ILB_RESET_REG), %dx
    537   outw  %ax, %dx
    538   jmp  .  # Stay here until we are reset.
    539 
    540 #----------------------------------------------------------------------------
    541 #
    542 # Procedure:    stackless_SideBand_Read
    543 #
    544 # Input:        esp - return address
    545 #                ecx[15:8] - Register offset
    546 #                ecx[23:16] - Port ID
    547 #                ecx[31:24] - Opcode
    548 #
    549 # Output:       eax - Data read
    550 #
    551 # Destroys:
    552 #                eax
    553 #                ebx
    554 #                cl
    555 #                esi
    556 #
    557 # Description:
    558 #        Perform requested sideband read
    559 #
    560 #----------------------------------------------------------------------------
    561 stackless_SideBand_Read:
    562 
    563   movl  %esp, %esi      # Save the return address
    564 
    565   #
    566   # Load the SideBand Packet Register to generate the transaction
    567   #
    568   movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx   # PCI Configuration address
    569   movb  $(ALL_BYTE_EN << SB_BE_FIELD), %cl      # Set all Byte Enable bits
    570   xchgl  %ecx, %eax
    571   leal  L17, %esp
    572   jmp  stackless_PCIConfig_Write
    573 L17:
    574   xchgl  %ecx, %eax
    575 
    576   #
    577   # Read the SideBand Data Register
    578   #
    579   movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx   # PCI Configuration address
    580   leal  L18, %esp
    581   jmp  stackless_PCIConfig_Read
    582 L18:
    583 
    584   movl  %esi, %esp      # Restore the return address
    585   RET32
    586 
    587 
    588 #----------------------------------------------------------------------------
    589 #
    590 # Procedure:    stackless_SideBand_Write
    591 #
    592 # Input:        esp - return address
    593 #                eax - Data
    594 #                ecx[15:8] - Register offset
    595 #                ecx[23:16] - Port ID
    596 #                ecx[31:24] - Opcode
    597 #
    598 # Output:       None
    599 #
    600 # Destroys:
    601 #                ebx
    602 #                cl
    603 #                esi
    604 #
    605 # Description:
    606 #        Perform requested sideband write
    607 #
    608 #
    609 #----------------------------------------------------------------------------
    610 stackless_SideBand_Write:
    611 
    612   movl  %esp, %esi      # Save the return address
    613 
    614   #
    615   # Load the SideBand Data Register with the data
    616   #
    617   movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx   # PCI Configuration address
    618   leal  L19, %esp
    619   jmp  stackless_PCIConfig_Write
    620 L19:
    621 
    622   #
    623   # Load the SideBand Packet Register to generate the transaction
    624   #
    625   movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx   # PCI Configuration address
    626   movb  $(ALL_BYTE_EN << SB_BE_FIELD), %cl      # Set all Byte Enable bits
    627   xchgl  %ecx, %eax
    628   leal  L20, %esp
    629   jmp  stackless_PCIConfig_Write
    630 L20:
    631   xchgl  %ecx, %eax
    632 
    633   movl  %esi, %esp      # Restore the return address
    634   RET32
    635 
    636 
    637 #----------------------------------------------------------------------------
    638 #
    639 # Procedure:    stackless_PCIConfig_Write
    640 #
    641 # Input:        esp - return address
    642 #                eax - Data to write
    643 #                ebx - PCI Config Address
    644 #
    645 # Output:       None
    646 #
    647 # Destroys:
    648 #                dx
    649 #
    650 # Description:
    651 #        Perform a DWORD PCI Configuration write
    652 #
    653 #----------------------------------------------------------------------------
    654 stackless_PCIConfig_Write:
    655 
    656   #
    657   # Write the PCI Config Address to the address port
    658   #
    659   xchgl  %ebx, %eax
    660   movw  $(PCI_ADDRESS_PORT), %dx
    661   outl  %eax, %dx
    662   xchgl  %ebx, %eax
    663 
    664   #
    665   # Write the PCI DWORD Data to the data port
    666   #
    667   movw  $(PCI_DATA_PORT), %dx
    668   outl  %eax, %dx
    669 
    670   RET32
    671 
    672 
    673 #----------------------------------------------------------------------------
    674 #
    675 # Procedure:    stackless_PCIConfig_Read
    676 #
    677 # Input:        esp - return address
    678 #                ebx - PCI Config Address
    679 #
    680 # Output:       eax - Data read
    681 #
    682 # Destroys:
    683 #                eax
    684 #                dx
    685 #
    686 # Description:
    687 #        Perform a DWORD PCI Configuration read
    688 #
    689 #----------------------------------------------------------------------------
    690 stackless_PCIConfig_Read:
    691 
    692   #
    693   # Write the PCI Config Address to the address port
    694   #
    695   xchgl  %ebx, %eax
    696   movw  $(PCI_ADDRESS_PORT), %dx
    697   outl  %eax, %dx
    698   xchgl  %ebx, %eax
    699 
    700   #
    701   # Read the PCI DWORD Data from the data port
    702   #
    703   movw  $(PCI_DATA_PORT), %dx
    704   inl  %dx, %eax
    705 
    706   RET32
    707 
    708 
    709 #
    710 # ROM-based Global-Descriptor Table for the Tiano PEI Phase
    711 #
    712 .align 16
    713 #
    714 # GDT[0]: 000h: Null entry, never used.
    715 #
    716 
    717 GDT_BASE:
    718 BootGdtTable:
    719 # null descriptor
    720 .equ                NULL_SEL, . - GDT_BASE # Selector [0]
    721         .word 0         # limit 15:0
    722         .word 0         # base 15:0
    723         .byte 0         # base 23:16
    724         .byte 0         # type
    725         .byte 0         # limit 19:16, flags
    726         .byte 0         # base 31:24
    727 
    728 # linear data segment descriptor
    729 .equ            LINEAR_SEL, . - GDT_BASE # Selector [0x8]
    730         .word 0xFFFF    # limit 0xFFFFF
    731         .word 0         # base 0
    732         .byte 0
    733         .byte 0x92      # present, ring 0, data, expand-up, writable
    734         .byte 0xCF              # page-granular, 32-bit
    735         .byte 0
    736 
    737 # linear code segment descriptor
    738 .equ            LINEAR_CODE_SEL, . - GDT_BASE # Selector [0x10]
    739         .word 0xFFFF    # limit 0xFFFFF
    740         .word 0         # base 0
    741         .byte 0
    742         .byte 0x9A      # present, ring 0, data, expand-up, writable
    743         .byte 0xCF              # page-granular, 32-bit
    744         .byte 0
    745 
    746 # system data segment descriptor
    747 .equ            SYS_DATA_SEL, . - GDT_BASE # Selector [0x18]
    748         .word 0xFFFF    # limit 0xFFFFF
    749         .word 0         # base 0
    750         .byte 0
    751         .byte 0x92      # present, ring 0, data, expand-up, writable
    752         .byte 0xCF              # page-granular, 32-bit
    753         .byte 0
    754 
    755 # system code segment descriptor
    756 .equ            SYS_CODE_SEL, . - GDT_BASE
    757         .word 0xFFFF    # limit 0xFFFFF
    758         .word 0         # base 0
    759         .byte 0
    760         .byte 0x9A      # present, ring 0, data, expand-up, writable
    761         .byte 0xCF              # page-granular, 32-bit
    762         .byte 0
    763 
    764 # spare segment descriptor
    765 .equ        SYS16_CODE_SEL, . - GDT_BASE
    766         .word 0xffff    # limit 0xFFFFF
    767         .word 0         # base 0
    768         .byte 0x0f
    769         .byte 0x9b      # present, ring 0, data, expand-up, writable
    770         .byte 0         # page-granular, 32-bit
    771         .byte 0
    772 
    773 # spare segment descriptor
    774 .equ        SYS16_DATA_SEL, . - GDT_BASE
    775         .word 0xffff    # limit 0xFFFFF
    776         .word 0         # base 0
    777         .byte 0
    778         .byte 0x93      # present, ring 0, data, expand-up, not-writable
    779         .byte 0         # page-granular, 32-bit
    780         .byte 0
    781 
    782 # spare segment descriptor
    783 .equ        SPARE5_SEL, . - GDT_BASE
    784         .word 0         # limit 0xFFFFF
    785         .word 0         # base 0
    786         .byte 0
    787         .byte 0         # present, ring 0, data, expand-up, writable
    788         .byte 0         # page-granular, 32-bit
    789         .byte 0
    790 .equ        GDT_SIZE, . - GDT_BASE
    791 
    792 #
    793 # GDT Descriptor
    794 #
    795 GdtDesc:                                     # GDT descriptor
    796        .word    GDT_SIZE - 1
    797        .long    BootGdtTable
    798 
    799 ProtectedModeEntryLinearAddress:
    800 ProtectedModeEntryLinearOffset:
    801        .long    ProtectedModeEntryPoint
    802        .word    LINEAR_CODE_SEL
    803