audk/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.S

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