]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.S
QuarkPlatformPkg: Add new package for Galileo boards
[mirror_edk2.git] / QuarkPlatformPkg / Library / PlatformSecLib / Ia32 / Flat32.S
diff --git a/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.S b/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.S
new file mode 100644 (file)
index 0000000..fbdad53
--- /dev/null
@@ -0,0 +1,827 @@
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2013 Intel Corporation.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+# Module Name:\r
+#\r
+#  Flat32.S\r
+#\r
+# Abstract:\r
+#\r
+#  This is the code that goes from real-mode to protected mode.\r
+#  It consumes the reset vector, configures the stack.\r
+#\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+.macro RET32\r
+    jmp    *%esp\r
+.endm\r
+\r
+#\r
+# ROM/SPI/MEMORY Definitions\r
+#\r
+.equ  QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000)    # Memory Base Address = 0\r
+.equ  QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000)    # DDR3 Memory Size = 2GB\r
+.equ  QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000)    # eSRAM Memory Size = 512K\r
+.equ  QUARK_STACK_SIZE_BYTES, (0x008000)      # Quark stack size = 32K\r
+\r
+#\r
+# RTC/CMOS definitions\r
+#\r
+.equ  RTC_INDEX, (0x70)\r
+.equ    NMI_DISABLE, (0x80)  # Bit7=1 disables NMI\r
+.equ    NMI_ENABLE, (0x00)  # Bit7=0 disables NMI\r
+.equ  RTC_DATA, (0x71)\r
+\r
+#\r
+# PCI Configuration definitions\r
+#\r
+.equ  PCI_CFG, (0x80000000) # PCI configuration access mechanism\r
+.equ  PCI_ADDRESS_PORT, (0xCF8)\r
+.equ  PCI_DATA_PORT, (0xCFC)\r
+\r
+#\r
+# Quark PCI devices\r
+#\r
+.equ  HOST_BRIDGE_PFA, (0x0000)   # B0:D0:F0 (Host Bridge)\r
+.equ  ILB_PFA, (0x00F8)      # B0:D31:F0 (Legacy Block)\r
+\r
+#\r
+# ILB PCI Config Registers\r
+#\r
+.equ  BDE, (0x0D4)                                # BIOS Decode Enable register\r
+.equ    DECODE_ALL_REGIONS_ENABLE, (0xFF000000)    # Decode all BIOS decode ranges\r
+\r
+#\r
+# iLB Reset Register\r
+#\r
+.equ  ILB_RESET_REG, (0x0CF9)\r
+.equ    CF9_WARM_RESET, (0x02)\r
+.equ    CF9_COLD_RESET, (0x08)\r
+\r
+#\r
+# Host Bridge PCI Config Registers\r
+#\r
+.equ  MESSAGE_BUS_CONTROL_REG, (0xD0)       # Message Bus Control Register\r
+.equ    SB_OPCODE_FIELD, (0x18)              # Bit location of Opcode field\r
+.equ      OPCODE_SIDEBAND_REG_READ, (0x10)  # Read opcode\r
+.equ      OPCODE_SIDEBAND_REG_WRITE, (0x11) # Write opcode\r
+.equ      OPCODE_SIDEBAND_ALT_REG_READ, (0x06)  # Alternate Read opcode\r
+.equ      OPCODE_SIDEBAND_ALT_REG_WRITE, (0x07) # Alternate Write opcode\r
+.equ      OPCODE_WARM_RESET_REQUEST, (0xF4)  # Reset Warm\r
+.equ      OPCODE_COLD_RESET_REQUEST, (0xF5) # Reset Cold\r
+.equ    SB_PORT_FIELD, (0x10)               # Bit location of Port ID field\r
+.equ      MEMORY_ARBITER_PORT_ID, (0x00)\r
+.equ      HOST_BRIDGE_PORT_ID, (0x03)\r
+.equ      RMU_PORT_ID, (0x04)\r
+.equ      MEMORY_MANAGER_PORT_ID, (0x05)\r
+.equ      SOC_UNIT_PORT_ID, (0x31)\r
+.equ    SB_ADDR_FIELD, (0x08)               # Bit location of Register field\r
+.equ    SB_BE_FIELD, (0x04)                  # Bit location of Byte Enables field\r
+.equ      ALL_BYTE_EN, (0x0F)                # All Byte Enables\r
+.equ  MESSAGE_DATA_REG, (0xD4)              # Message Data Register\r
+\r
+#\r
+# Memory Arbiter Config Registers\r
+#\r
+.equ  AEC_CTRL_OFFSET, (0x00)\r
+\r
+#\r
+# Host Bridge Config Registers\r
+#\r
+.equ  HMISC2_OFFSET, (0x03) # PCI configuration access mechanism\r
+.equ    OR_PM_FIELD, (0x10)\r
+.equ      SMI_EN, (0x00080000)\r
+\r
+.equ  HMBOUND_OFFSET, (0x08)\r
+.equ    HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)\r
+.equ    HMBOUND_LOCK, (0x01)\r
+.equ  HECREG_OFFSET, (0x09)\r
+.equ    EC_BASE, (0xE0000000)\r
+.equ    EC_ENABLE, (0x01)\r
+.equ  HLEGACY_OFFSET, (0x0A)\r
+.equ    NMI, (0x00004000)\r
+.equ    SMI, (0x00001000)\r
+.equ    INTR, (0x00000400)\r
+\r
+#\r
+# Memory Manager Config Registers\r
+#\r
+.equ  ESRAMPGCTRL_BLOCK_OFFSET, (0x82)\r
+.equ    BLOCK_ENABLE_PG, (0x10000000)\r
+.equ  BIMRVCTL_OFFSET, (0x19)\r
+.equ    ENABLE_IMR_INTERRUPT, (0x80000000)\r
+\r
+#\r
+# SOC UNIT Debug Registers\r
+#\r
+.equ  CFGSTICKY_W1_OFFSET, (0x50)\r
+.equ    FORCE_COLD_RESET, (0x00000001)\r
+.equ  CFGSTICKY_RW_OFFSET, (0x51)\r
+.equ    RESET_FOR_ESRAM_LOCK, (0x00000020)\r
+.equ    RESET_FOR_HMBOUND_LOCK, (0x00000040)\r
+.equ  CFGNONSTICKY_W1_OFFSET, (0x52)\r
+.equ    FORCE_WARM_RESET, (0x00000001)\r
+\r
+#\r
+# CR0 cache control bit definition\r
+#\r
+.equ                    CR0_CACHE_DISABLE, 0x040000000\r
+.equ                    CR0_NO_WRITE,      0x020000000\r
+\r
+ASM_GLOBAL  ASM_PFX(PcdGet32(PcdEsramStage1Base))\r
+\r
+\r
+#\r
+# Contrary to the name, this file contains 16 bit code as well.\r
+#\r
+.text\r
+#----------------------------------------------------------------------------\r
+#\r
+# Procedure:    _ModuleEntryPoint\r
+#\r
+# Input:        None\r
+#\r
+# Output:       None\r
+#\r
+# Destroys:     Assume all registers\r
+#\r
+# Description:\r
+#\r
+#   Transition to non-paged flat-model protected mode from a\r
+#   hard-coded GDT that provides exactly two descriptors.\r
+#   This is a bare bones transition to protected mode only\r
+#   used for a while in PEI and possibly DXE.\r
+#\r
+#   After enabling protected mode, a far jump is executed to\r
+#   transfer to PEI using the newly loaded GDT.\r
+#\r
+# Return:       None\r
+#\r
+#----------------------------------------------------------------------------\r
+ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)\r
+ASM_PFX(_ModuleEntryPoint):\r
+\r
+  #\r
+  # Warm Reset (INIT#) check.\r
+  #\r
+  .byte   0xbe,0x00,0xf0   #movw    $0xF000, %si\r
+  .byte   0x8e,0xde        #movw    %si, %ds\r
+  .byte   0xbe,0xf0,0xff   #movw    $0xFFF0, %si\r
+  .byte   0x80,0x3c,0xea   #cmpb    $0xEA, (%si)          # Is it warm reset ?\r
+  jne     NotWarmReset     # Jump if not.\r
+  .byte   0xb0,0x08        #movb    $0x08, %al\r
+  .byte   0xba,0xf9,0x0c   #movw    $0xcf9, %dx\r
+  .byte   0xee             #outb    %al, %dx\r
+  .byte   0xb0,0x55        #movb    $0x55, %al\r
+  .byte   0xe6,0x80        #outb    %al, $0x80\r
+  jmp     .\r
+NotWarmReset:\r
+  .byte   0x66,0x8b,0xe8   #movl    %eax, %ebp\r
+\r
+  #\r
+  # Load the GDT table in GdtDesc\r
+  #\r
+  .byte   0x66,0xbe        #movl    $GdtDesc, %esi\r
+  .long   GdtDesc\r
+\r
+  .byte   0x66,0x2e,0x0f,0x01,0x14   #lgdt    %cs:(%si)\r
+\r
+  #\r
+  # Transition to 16 bit protected mode\r
+  #\r
+  .byte   0x0f,0x20,0xc0       #movl    %cr0, %eax                  # Get control register 0\r
+  .byte   0x66,0x83,0xc8,0x03  #orl     $0x0000003, %eax           # Set PE bit (bit #0) & MP bit (bit #1)\r
+  .byte   0x0f,0x22,0xc0       #movl    %eax, %cr0                  # Activate protected mode\r
+\r
+  #\r
+  # Now we're in 16 bit protected mode\r
+  # Set up the selectors for 32 bit protected mode entry\r
+  #\r
+  .byte   0xb8                 #movw    SYS_DATA_SEL, %ax\r
+  .word   SYS_DATA_SEL\r
+\r
+  .byte   0x8e,0xd8            #movw    %ax, %ds\r
+  .byte   0x8e,0xc0            #movw    %ax, %es\r
+  .byte   0x8e,0xe0            #movw    %ax, %fs\r
+  .byte   0x8e,0xe8            #movw    %ax, %gs\r
+  .byte   0x8e,0xd0            #movw    %ax, %ss\r
+\r
+  #\r
+  # Transition to Flat 32 bit protected mode\r
+  # The jump to a far pointer causes the transition to 32 bit mode\r
+  #\r
+  .byte   0x66,0xbe            #movl   ProtectedModeEntryLinearAddress, %esi\r
+  .long   ProtectedModeEntryLinearAddress\r
+  .byte   0x66,0x2e,0xff,0x2c  #jmp    %cs:(%esi)\r
+\r
+#\r
+# Protected mode portion initializes stack, configures cache, and calls C entry point\r
+#\r
+\r
+#----------------------------------------------------------------------------\r
+#\r
+# Procedure:    ProtectedModeEntryPoint\r
+#\r
+# Input:        Executing in 32 Bit Protected (flat) mode\r
+#                cs: 0-4GB\r
+#                ds: 0-4GB\r
+#                es: 0-4GB\r
+#                fs: 0-4GB\r
+#                gs: 0-4GB\r
+#                ss: 0-4GB\r
+#\r
+# Output:       This function never returns\r
+#\r
+# Destroys:\r
+#               ecx\r
+#               edi\r
+#                esi\r
+#                esp\r
+#\r
+# Description:\r
+#                Perform any essential early platform initilaisation\r
+#               Setup a stack\r
+#               Transfer control to EDKII code in eSRAM\r
+#\r
+#----------------------------------------------------------------------------\r
+ProtectedModeEntryPoint:\r
+  leal  L0, %esp\r
+  jmp  stackless_EarlyPlatformInit\r
+L0:\r
+\r
+  #\r
+  # Set up stack pointer\r
+  #\r
+  movl    ASM_PFX(PcdGet32(PcdEsramStage1Base)), %esp\r
+  movl    $QUARK_STACK_SIZE_BYTES, %esi\r
+  addl    %esi, %esp                          # ESP = top of stack (stack grows downwards).\r
+\r
+  #\r
+  # Store the the BIST value in EBP\r
+  #\r
+  movl    $0, %ebp    # No processor BIST on Quark\r
+\r
+  #\r
+  # Push processor count to stack first, then BIST status (AP then BSP)\r
+  #\r
+  movl    $1, %eax\r
+  cpuid\r
+  shrl    $16, %ebx\r
+  andl    $0x000000FF, %ebx\r
+  cmpb    $1, %bl\r
+  jae     PushProcessorCount\r
+\r
+  #\r
+  # Some processors report 0 logical processors.  Effectively 0 = 1.\r
+  # So we fix up the processor count\r
+  #\r
+  incl    %ebx\r
+\r
+PushProcessorCount:\r
+  pushl   %ebx\r
+\r
+  #\r
+  # We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST\r
+  # for all processor threads\r
+  #\r
+  xorl    %ecx, %ecx\r
+  movb    %bl, %cl\r
+\r
+PushBist:\r
+  pushl   %ebp\r
+  loop    PushBist\r
+\r
+  #\r
+  # Pass entry point of the PEI core\r
+  #\r
+  movl $0xFFFFFFE0, %edi\r
+  pushl %ds:(%edi)\r
+\r
+  #\r
+  # Pass BFV into the PEI Core\r
+  #\r
+  movl $0xFFFFFFFC, %edi\r
+  pushl %ds:(%edi)\r
+\r
+  #\r
+  # Pass Temp Ram Base into the PEI Core\r
+  #\r
+  movl    ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax\r
+  addl    $(QUARK_ESRAM_MEM_SIZE_BYTES - QUARK_STACK_SIZE_BYTES), %eax\r
+  pushl   %eax\r
+\r
+\r
+  #\r
+  # Pass stack size into the PEI Core\r
+  #\r
+  pushl   $QUARK_STACK_SIZE_BYTES\r
+\r
+  #\r
+  # Pass Control into the PEI Core\r
+  #\r
+  call SecStartup\r
+\r
+  #\r
+  # PEI Core should never return to here, this is just to capture an invalid return.\r
+  #\r
+  jmp     .\r
+\r
+#----------------------------------------------------------------------------\r
+#\r
+# Procedure:    stackless_EarlyPlatformInit\r
+#\r
+# Input:        esp - Return address\r
+#\r
+# Output:       None\r
+#\r
+# Destroys:     Assume all registers\r
+#\r
+# Description:\r
+#        Any early platform initialisation required\r
+#\r
+# Return:\r
+#      None\r
+#\r
+#----------------------------------------------------------------------------\r
+stackless_EarlyPlatformInit:\r
+\r
+  #\r
+  # Save return address\r
+  #\r
+  movl  %esp, %ebp\r
+\r
+  #\r
+  # Ensure cache is disabled.\r
+  #\r
+  movl %cr0, %eax\r
+  orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax\r
+  invd\r
+  movl    %eax, %cr0\r
+\r
+  #\r
+  # Disable NMI operation\r
+  # Good convention suggests you should read back RTC data port after\r
+  # accessing the RTC index port.\r
+  #\r
+  movb $(NMI_DISABLE), %al\r
+  movw $(RTC_INDEX), %dx\r
+  outb %al, %dx\r
+  movw $(RTC_DATA), %dx\r
+  inb  %dx, %al\r
+\r
+  #\r
+  # Disable SMI (Disables SMI wire, not SMI messages)\r
+  #\r
+  movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L1, %esp\r
+  jmp  stackless_SideBand_Read\r
+L1:\r
+  andl $(~SMI_EN), %eax\r
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L2, %esp\r
+  jmp  stackless_SideBand_Write\r
+L2:\r
+\r
+  #\r
+  # Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset\r
+  #\r
+  movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L3, %esp\r
+  jmp  stackless_SideBand_Read\r
+L3:\r
+  andl $(FORCE_WARM_RESET), %eax\r
+  jz TestForceColdReset    # Zero means bit clear, we're not requested to warm reset so continue as normal\r
+  jmp IssueWarmReset\r
+\r
+TestForceColdReset:\r
+  movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L4, %esp\r
+  jmp  stackless_SideBand_Read\r
+L4:\r
+  andl $(FORCE_COLD_RESET), %eax\r
+  jz TestHmboundLock    # Zero means bit clear, we're not requested to cold reset so continue as normal\r
+  jmp IssueColdReset\r
+\r
+  #\r
+  # Before setting HMBOUND, check it's not locked\r
+  #\r
+TestHmboundLock:\r
+  movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L5, %esp\r
+  jmp  stackless_SideBand_Read\r
+L5:\r
+  andl $(HMBOUND_LOCK), %eax\r
+  jz ConfigHmbound  # Zero means bit clear, we have the config we want so continue as normal\r
+  #\r
+  # Failed to config - store sticky bit debug\r
+  #\r
+  movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L6, %esp\r
+  jmp  stackless_SideBand_Read\r
+L6:\r
+  orl $(RESET_FOR_HMBOUND_LOCK), %eax\r
+  movl  $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L7, %esp\r
+  jmp  stackless_SideBand_Write\r
+L7:\r
+  jmp IssueWarmReset\r
+\r
+  #\r
+  # Set up the HMBOUND register\r
+  #\r
+ConfigHmbound:\r
+  movl $(HMBOUND_ADDRESS), %eax      # Data (Set HMBOUND location)\r
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L8, %esp\r
+  jmp  stackless_SideBand_Write\r
+L8:\r
+\r
+  #\r
+  # Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.\r
+  #\r
+  movl $(ENABLE_IMR_INTERRUPT), %eax      # Data (Set interrupt enable mask)\r
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (BIMRVCTL_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L9, %esp\r
+  jmp  stackless_SideBand_Write\r
+L9:\r
+\r
+  #\r
+  # Set eSRAM address\r
+  #\r
+  movl    ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax   # Data (Set eSRAM location)\r
+  shr   $(0x18), %eax\r
+  addl  $(BLOCK_ENABLE_PG), %eax\r
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L10, %esp\r
+  jmp  stackless_SideBand_Write\r
+L10:\r
+\r
+  #\r
+  # Check that we're not blocked from setting the config that we want.\r
+  #\r
+  movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L11, %esp\r
+  jmp  stackless_SideBand_Read\r
+L11:\r
+  andl $(BLOCK_ENABLE_PG), %eax\r
+  jnz ConfigPci  # Non-zero means bit set, we have the config we want so continue as normal\r
+  #\r
+  # Failed to config - store sticky bit debug\r
+  #\r
+  movl  $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L12, %esp\r
+  jmp  stackless_SideBand_Read\r
+L12:\r
+  orl $(RESET_FOR_ESRAM_LOCK), %eax     # Set the bit we're interested in\r
+  movl  $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L13, %esp\r
+  jmp  stackless_SideBand_Write\r
+L13:\r
+  jmp IssueWarmReset\r
+\r
+  #\r
+  # Enable PCIEXBAR\r
+  #\r
+ConfigPci:\r
+  movl $(EC_BASE + EC_ENABLE), %eax      # Data\r
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L14, %esp\r
+  jmp  stackless_SideBand_Write\r
+L14:\r
+\r
+  movl $(EC_BASE + EC_ENABLE), %eax      # Data\r
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L15, %esp\r
+  jmp  stackless_SideBand_Write\r
+L15:\r
+\r
+  #\r
+  #  Open up full 8MB SPI decode\r
+  #\r
+  movl  $(PCI_CFG | (ILB_PFA << 8) | BDE), %ebx  # PCI Configuration address\r
+  movl $(DECODE_ALL_REGIONS_ENABLE), %eax\r
+  leal  L16, %esp\r
+  jmp  stackless_PCIConfig_Write\r
+L16:\r
+\r
+  #\r
+  # Enable NMI operation\r
+  # Good convention suggests you should read back RTC data port after\r
+  # accessing the RTC index port.\r
+  #\r
+  movb $(NMI_ENABLE), %al\r
+  movw $(RTC_INDEX), %dx\r
+  outb %al, %dx\r
+  movw $(RTC_DATA), %dx\r
+  inb  %dx, %al\r
+\r
+  #\r
+  # Clear Host Bridge SMI, NMI, INTR fields\r
+  #\r
+  movl  $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L21, %esp\r
+  jmp  stackless_SideBand_Read\r
+L21:\r
+  andl $~(NMI + SMI + INTR), %eax      # Clear NMI, SMI, INTR fields\r
+  movl  $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx\r
+  leal  L22, %esp\r
+  jmp  stackless_SideBand_Write\r
+L22:\r
+\r
+  #\r
+  # Restore return address\r
+  #\r
+  movl  %ebp, %esp\r
+  RET32\r
+\r
+IssueWarmReset:\r
+  #\r
+  # Issue Warm Reset request to Remote Management Unit via iLB\r
+  #\r
+  movw  $(CF9_WARM_RESET), %ax\r
+  movw  $(ILB_RESET_REG), %dx\r
+  outw  %ax, %dx\r
+  jmp  .  # Stay here until we are reset.\r
+\r
+IssueColdReset:\r
+  #\r
+  # Issue Cold Reset request to Remote Management Unit via iLB\r
+  #\r
+  movw  $(CF9_COLD_RESET), %ax\r
+  movw  $(ILB_RESET_REG), %dx\r
+  outw  %ax, %dx\r
+  jmp  .  # Stay here until we are reset.\r
+\r
+#----------------------------------------------------------------------------\r
+#\r
+# Procedure:    stackless_SideBand_Read\r
+#\r
+# Input:        esp - return address\r
+#                ecx[15:8] - Register offset\r
+#                ecx[23:16] - Port ID\r
+#                ecx[31:24] - Opcode\r
+#\r
+# Output:       eax - Data read\r
+#\r
+# Destroys:\r
+#                eax\r
+#                ebx\r
+#                cl\r
+#                esi\r
+#\r
+# Description:\r
+#        Perform requested sideband read\r
+#\r
+#----------------------------------------------------------------------------\r
+stackless_SideBand_Read:\r
+\r
+  movl  %esp, %esi      # Save the return address\r
+\r
+  #\r
+  # Load the SideBand Packet Register to generate the transaction\r
+  #\r
+  movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx   # PCI Configuration address\r
+  movb  $(ALL_BYTE_EN << SB_BE_FIELD), %cl      # Set all Byte Enable bits\r
+  xchgl  %ecx, %eax\r
+  leal  L17, %esp\r
+  jmp  stackless_PCIConfig_Write\r
+L17:\r
+  xchgl  %ecx, %eax\r
+\r
+  #\r
+  # Read the SideBand Data Register\r
+  #\r
+  movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx   # PCI Configuration address\r
+  leal  L18, %esp\r
+  jmp  stackless_PCIConfig_Read\r
+L18:\r
+\r
+  movl  %esi, %esp      # Restore the return address\r
+  RET32\r
+\r
+\r
+#----------------------------------------------------------------------------\r
+#\r
+# Procedure:    stackless_SideBand_Write\r
+#\r
+# Input:        esp - return address\r
+#                eax - Data\r
+#                ecx[15:8] - Register offset\r
+#                ecx[23:16] - Port ID\r
+#                ecx[31:24] - Opcode\r
+#\r
+# Output:       None\r
+#\r
+# Destroys:\r
+#                ebx\r
+#                cl\r
+#                esi\r
+#\r
+# Description:\r
+#        Perform requested sideband write\r
+#\r
+#\r
+#----------------------------------------------------------------------------\r
+stackless_SideBand_Write:\r
+\r
+  movl  %esp, %esi      # Save the return address\r
+\r
+  #\r
+  # Load the SideBand Data Register with the data\r
+  #\r
+  movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx   # PCI Configuration address\r
+  leal  L19, %esp\r
+  jmp  stackless_PCIConfig_Write\r
+L19:\r
+\r
+  #\r
+  # Load the SideBand Packet Register to generate the transaction\r
+  #\r
+  movl  $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx   # PCI Configuration address\r
+  movb  $(ALL_BYTE_EN << SB_BE_FIELD), %cl      # Set all Byte Enable bits\r
+  xchgl  %ecx, %eax\r
+  leal  L20, %esp\r
+  jmp  stackless_PCIConfig_Write\r
+L20:\r
+  xchgl  %ecx, %eax\r
+\r
+  movl  %esi, %esp      # Restore the return address\r
+  RET32\r
+\r
+\r
+#----------------------------------------------------------------------------\r
+#\r
+# Procedure:    stackless_PCIConfig_Write\r
+#\r
+# Input:        esp - return address\r
+#                eax - Data to write\r
+#                ebx - PCI Config Address\r
+#\r
+# Output:       None\r
+#\r
+# Destroys:\r
+#                dx\r
+#\r
+# Description:\r
+#        Perform a DWORD PCI Configuration write\r
+#\r
+#----------------------------------------------------------------------------\r
+stackless_PCIConfig_Write:\r
+\r
+  #\r
+  # Write the PCI Config Address to the address port\r
+  #\r
+  xchgl  %ebx, %eax\r
+  movw  $(PCI_ADDRESS_PORT), %dx\r
+  outl  %eax, %dx\r
+  xchgl  %ebx, %eax\r
+\r
+  #\r
+  # Write the PCI DWORD Data to the data port\r
+  #\r
+  movw  $(PCI_DATA_PORT), %dx\r
+  outl  %eax, %dx\r
+\r
+  RET32\r
+\r
+\r
+#----------------------------------------------------------------------------\r
+#\r
+# Procedure:    stackless_PCIConfig_Read\r
+#\r
+# Input:        esp - return address\r
+#                ebx - PCI Config Address\r
+#\r
+# Output:       eax - Data read\r
+#\r
+# Destroys:\r
+#                eax\r
+#                dx\r
+#\r
+# Description:\r
+#        Perform a DWORD PCI Configuration read\r
+#\r
+#----------------------------------------------------------------------------\r
+stackless_PCIConfig_Read:\r
+\r
+  #\r
+  # Write the PCI Config Address to the address port\r
+  #\r
+  xchgl  %ebx, %eax\r
+  movw  $(PCI_ADDRESS_PORT), %dx\r
+  outl  %eax, %dx\r
+  xchgl  %ebx, %eax\r
+\r
+  #\r
+  # Read the PCI DWORD Data from the data port\r
+  #\r
+  movw  $(PCI_DATA_PORT), %dx\r
+  inl  %dx, %eax\r
+\r
+  RET32\r
+\r
+\r
+#\r
+# ROM-based Global-Descriptor Table for the Tiano PEI Phase\r
+#\r
+.align 16\r
+#\r
+# GDT[0]: 000h: Null entry, never used.\r
+#\r
+\r
+GDT_BASE:\r
+BootGdtTable:\r
+# null descriptor\r
+.equ                NULL_SEL, . - GDT_BASE # Selector [0]\r
+        .word 0         # limit 15:0\r
+        .word 0         # base 15:0\r
+        .byte 0         # base 23:16\r
+        .byte 0         # type\r
+        .byte 0         # limit 19:16, flags\r
+        .byte 0         # base 31:24\r
+\r
+# linear data segment descriptor\r
+.equ            LINEAR_SEL, . - GDT_BASE # Selector [0x8]\r
+        .word 0xFFFF    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x92      # present, ring 0, data, expand-up, writable\r
+        .byte 0xCF              # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# linear code segment descriptor\r
+.equ            LINEAR_CODE_SEL, . - GDT_BASE # Selector [0x10]\r
+        .word 0xFFFF    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x9A      # present, ring 0, data, expand-up, writable\r
+        .byte 0xCF              # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# system data segment descriptor\r
+.equ            SYS_DATA_SEL, . - GDT_BASE # Selector [0x18]\r
+        .word 0xFFFF    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x92      # present, ring 0, data, expand-up, writable\r
+        .byte 0xCF              # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# system code segment descriptor\r
+.equ            SYS_CODE_SEL, . - GDT_BASE\r
+        .word 0xFFFF    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x9A      # present, ring 0, data, expand-up, writable\r
+        .byte 0xCF              # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# spare segment descriptor\r
+.equ        SYS16_CODE_SEL, . - GDT_BASE\r
+        .word 0xffff    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0x0f\r
+        .byte 0x9b      # present, ring 0, data, expand-up, writable\r
+        .byte 0         # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# spare segment descriptor\r
+.equ        SYS16_DATA_SEL, . - GDT_BASE\r
+        .word 0xffff    # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0x93      # present, ring 0, data, expand-up, not-writable\r
+        .byte 0         # page-granular, 32-bit\r
+        .byte 0\r
+\r
+# spare segment descriptor\r
+.equ        SPARE5_SEL, . - GDT_BASE\r
+        .word 0         # limit 0xFFFFF\r
+        .word 0         # base 0\r
+        .byte 0\r
+        .byte 0         # present, ring 0, data, expand-up, writable\r
+        .byte 0         # page-granular, 32-bit\r
+        .byte 0\r
+.equ        GDT_SIZE, . - GDT_BASE\r
+\r
+#\r
+# GDT Descriptor\r
+#\r
+GdtDesc:                                     # GDT descriptor\r
+       .word    GDT_SIZE - 1\r
+       .long    BootGdtTable\r
+\r
+ProtectedModeEntryLinearAddress:\r
+ProtectedModeEntryLinearOffset:\r
+       .long    ProtectedModeEntryPoint\r
+       .word    LINEAR_CODE_SEL\r