#------------------------------------------------------------------------------ # # 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