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