--- /dev/null
+#------------------------------------------------------------------------------\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