Jeff Fan 26ea0da235 QuarkPlatformPkg/PlatformSecLib: Fix stack pointer issue in Flat32.S
ESP should be set to top of eSRAM range that aligns with Flat32.asm. Because CPU
BIST data will be located at top of STACK, this issue leads Platform Sec Lib
cannot get the correct CPU BIST information.

This fix is to address below issue:
  https://tianocore.acgmultimedia.com/show_bug.cgi?id=123

Cc: Steven Shi <Steven.shi@intel.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Kelly Steele <kelly.steele@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
2016-09-21 14:12:40 +08:00

803 lines
23 KiB
ArmAsm

#------------------------------------------------------------------------------
#
# Copyright (c) 2013 - 2016 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_ESRAM_MEM_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