1 #------------------------------------------------------------------------------
3 # Copyright (c) 2013 Intel Corporation.
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 # This is the code that goes from real-mode to protected mode.
20 # It consumes the reset vector, configures the stack.
23 #------------------------------------------------------------------------------
30 # ROM/SPI/MEMORY Definitions
32 .equ QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000) # Memory Base Address = 0
33 .equ QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000) # DDR3 Memory Size = 2GB
34 .equ QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000) # eSRAM Memory Size = 512K
35 .equ QUARK_STACK_SIZE_BYTES, (0x008000) # Quark stack size = 32K
38 # RTC/CMOS definitions
40 .equ RTC_INDEX, (0x70)
41 .equ NMI_DISABLE, (0x80) # Bit7=1 disables NMI
42 .equ NMI_ENABLE, (0x00) # Bit7=0 disables NMI
46 # PCI Configuration definitions
48 .equ PCI_CFG, (0x80000000) # PCI configuration access mechanism
49 .equ PCI_ADDRESS_PORT, (0xCF8)
50 .equ PCI_DATA_PORT, (0xCFC)
55 .equ HOST_BRIDGE_PFA, (0x0000) # B0:D0:F0 (Host Bridge)
56 .equ ILB_PFA, (0x00F8) # B0:D31:F0 (Legacy Block)
59 # ILB PCI Config Registers
61 .equ BDE, (0x0D4) # BIOS Decode Enable register
62 .equ DECODE_ALL_REGIONS_ENABLE, (0xFF000000) # Decode all BIOS decode ranges
67 .equ ILB_RESET_REG, (0x0CF9)
68 .equ CF9_WARM_RESET, (0x02)
69 .equ CF9_COLD_RESET, (0x08)
72 # Host Bridge PCI Config Registers
74 .equ MESSAGE_BUS_CONTROL_REG, (0xD0) # Message Bus Control Register
75 .equ SB_OPCODE_FIELD, (0x18) # Bit location of Opcode field
76 .equ OPCODE_SIDEBAND_REG_READ, (0x10) # Read opcode
77 .equ OPCODE_SIDEBAND_REG_WRITE, (0x11) # Write opcode
78 .equ OPCODE_SIDEBAND_ALT_REG_READ, (0x06) # Alternate Read opcode
79 .equ OPCODE_SIDEBAND_ALT_REG_WRITE, (0x07) # Alternate Write opcode
80 .equ OPCODE_WARM_RESET_REQUEST, (0xF4) # Reset Warm
81 .equ OPCODE_COLD_RESET_REQUEST, (0xF5) # Reset Cold
82 .equ SB_PORT_FIELD, (0x10) # Bit location of Port ID field
83 .equ MEMORY_ARBITER_PORT_ID, (0x00)
84 .equ HOST_BRIDGE_PORT_ID, (0x03)
85 .equ RMU_PORT_ID, (0x04)
86 .equ MEMORY_MANAGER_PORT_ID, (0x05)
87 .equ SOC_UNIT_PORT_ID, (0x31)
88 .equ SB_ADDR_FIELD, (0x08) # Bit location of Register field
89 .equ SB_BE_FIELD, (0x04) # Bit location of Byte Enables field
90 .equ ALL_BYTE_EN, (0x0F) # All Byte Enables
91 .equ MESSAGE_DATA_REG, (0xD4) # Message Data Register
94 # Memory Arbiter Config Registers
96 .equ AEC_CTRL_OFFSET, (0x00)
99 # Host Bridge Config Registers
101 .equ HMISC2_OFFSET, (0x03) # PCI configuration access mechanism
102 .equ OR_PM_FIELD, (0x10)
103 .equ SMI_EN, (0x00080000)
105 .equ HMBOUND_OFFSET, (0x08)
106 .equ HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
107 .equ HMBOUND_LOCK, (0x01)
108 .equ HECREG_OFFSET, (0x09)
109 .equ EC_BASE, (0xE0000000)
110 .equ EC_ENABLE, (0x01)
111 .equ HLEGACY_OFFSET, (0x0A)
112 .equ NMI, (0x00004000)
113 .equ SMI, (0x00001000)
114 .equ INTR, (0x00000400)
117 # Memory Manager Config Registers
119 .equ ESRAMPGCTRL_BLOCK_OFFSET, (0x82)
120 .equ BLOCK_ENABLE_PG, (0x10000000)
121 .equ BIMRVCTL_OFFSET, (0x19)
122 .equ ENABLE_IMR_INTERRUPT, (0x80000000)
125 # SOC UNIT Debug Registers
127 .equ CFGSTICKY_W1_OFFSET, (0x50)
128 .equ FORCE_COLD_RESET, (0x00000001)
129 .equ CFGSTICKY_RW_OFFSET, (0x51)
130 .equ RESET_FOR_ESRAM_LOCK, (0x00000020)
131 .equ RESET_FOR_HMBOUND_LOCK, (0x00000040)
132 .equ CFGNONSTICKY_W1_OFFSET, (0x52)
133 .equ FORCE_WARM_RESET, (0x00000001)
136 # CR0 cache control bit definition
138 .equ CR0_CACHE_DISABLE, 0x040000000
139 .equ CR0_NO_WRITE, 0x020000000
141 ASM_GLOBAL ASM_PFX(PcdGet32(PcdEsramStage1Base))
145 # Contrary to the name, this file contains 16 bit code as well.
148 #----------------------------------------------------------------------------
150 # Procedure: _ModuleEntryPoint
156 # Destroys: Assume all registers
160 # Transition to non-paged flat-model protected mode from a
161 # hard-coded GDT that provides exactly two descriptors.
162 # This is a bare bones transition to protected mode only
163 # used for a while in PEI and possibly DXE.
165 # After enabling protected mode, a far jump is executed to
166 # transfer to PEI using the newly loaded GDT.
170 #----------------------------------------------------------------------------
171 ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
172 ASM_PFX(_ModuleEntryPoint):
175 # Warm Reset (INIT#) check.
177 .byte 0xbe,0x00,0xf0 #movw $0xF000, %si
178 .byte 0x8e,0xde #movw %si, %ds
179 .byte 0xbe,0xf0,0xff #movw $0xFFF0, %si
180 .byte 0x80,0x3c,0xea #cmpb $0xEA, (%si) # Is it warm reset ?
181 jne NotWarmReset # Jump if not.
182 .byte 0xb0,0x08 #movb $0x08, %al
183 .byte 0xba,0xf9,0x0c #movw $0xcf9, %dx
184 .byte 0xee #outb %al, %dx
185 .byte 0xb0,0x55 #movb $0x55, %al
186 .byte 0xe6,0x80 #outb %al, $0x80
189 .byte 0x66,0x8b,0xe8 #movl %eax, %ebp
192 # Load the GDT table in GdtDesc
194 .byte 0x66,0xbe #movl $GdtDesc, %esi
197 .byte 0x66,0x2e,0x0f,0x01,0x14 #lgdt %cs:(%si)
200 # Transition to 16 bit protected mode
202 .byte 0x0f,0x20,0xc0 #movl %cr0, %eax # Get control register 0
203 .byte 0x66,0x83,0xc8,0x03 #orl $0x0000003, %eax # Set PE bit (bit #0) & MP bit (bit #1)
204 .byte 0x0f,0x22,0xc0 #movl %eax, %cr0 # Activate protected mode
207 # Now we're in 16 bit protected mode
208 # Set up the selectors for 32 bit protected mode entry
210 .byte 0xb8 #movw SYS_DATA_SEL, %ax
213 .byte 0x8e,0xd8 #movw %ax, %ds
214 .byte 0x8e,0xc0 #movw %ax, %es
215 .byte 0x8e,0xe0 #movw %ax, %fs
216 .byte 0x8e,0xe8 #movw %ax, %gs
217 .byte 0x8e,0xd0 #movw %ax, %ss
220 # Transition to Flat 32 bit protected mode
221 # The jump to a far pointer causes the transition to 32 bit mode
223 .byte 0x66,0xbe #movl ProtectedModeEntryLinearAddress, %esi
224 .long ProtectedModeEntryLinearAddress
225 .byte 0x66,0x2e,0xff,0x2c #jmp %cs:(%esi)
228 # Protected mode portion initializes stack, configures cache, and calls C entry point
231 #----------------------------------------------------------------------------
233 # Procedure: ProtectedModeEntryPoint
235 # Input: Executing in 32 Bit Protected (flat) mode
243 # Output: This function never returns
252 # Perform any essential early platform initilaisation
254 # Transfer control to EDKII code in eSRAM
256 #----------------------------------------------------------------------------
257 ProtectedModeEntryPoint:
259 jmp stackless_EarlyPlatformInit
263 # Set up stack pointer
265 movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %esp
266 movl $QUARK_STACK_SIZE_BYTES, %esi
267 addl %esi, %esp # ESP = top of stack (stack grows downwards).
270 # Store the the BIST value in EBP
272 movl $0, %ebp # No processor BIST on Quark
275 # Push processor count to stack first, then BIST status (AP then BSP)
280 andl $0x000000FF, %ebx
282 jae PushProcessorCount
285 # Some processors report 0 logical processors. Effectively 0 = 1.
286 # So we fix up the processor count
294 # We need to implement a long-term solution for BIST capture. For now, we just copy BSP BIST
295 # for all processor threads
305 # Pass entry point of the PEI core
307 movl $0xFFFFFFE0, %edi
311 # Pass BFV into the PEI Core
313 movl $0xFFFFFFFC, %edi
317 # Pass Temp Ram Base into the PEI Core
319 movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax
320 addl $(QUARK_ESRAM_MEM_SIZE_BYTES - QUARK_STACK_SIZE_BYTES), %eax
325 # Pass stack size into the PEI Core
327 pushl $QUARK_STACK_SIZE_BYTES
330 # Pass Control into the PEI Core
335 # PEI Core should never return to here, this is just to capture an invalid return.
339 #----------------------------------------------------------------------------
341 # Procedure: stackless_EarlyPlatformInit
343 # Input: esp - Return address
347 # Destroys: Assume all registers
350 # Any early platform initialisation required
355 #----------------------------------------------------------------------------
356 stackless_EarlyPlatformInit:
359 # Save return address
364 # Ensure cache is disabled.
367 orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax
372 # Disable NMI operation
373 # Good convention suggests you should read back RTC data port after
374 # accessing the RTC index port.
376 movb $(NMI_DISABLE), %al
377 movw $(RTC_INDEX), %dx
379 movw $(RTC_DATA), %dx
383 # Disable SMI (Disables SMI wire, not SMI messages)
385 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
387 jmp stackless_SideBand_Read
389 andl $(~SMI_EN), %eax
390 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
392 jmp stackless_SideBand_Write
396 # Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
398 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
400 jmp stackless_SideBand_Read
402 andl $(FORCE_WARM_RESET), %eax
403 jz TestForceColdReset # Zero means bit clear, we're not requested to warm reset so continue as normal
407 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
409 jmp stackless_SideBand_Read
411 andl $(FORCE_COLD_RESET), %eax
412 jz TestHmboundLock # Zero means bit clear, we're not requested to cold reset so continue as normal
416 # Before setting HMBOUND, check it's not locked
419 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
421 jmp stackless_SideBand_Read
423 andl $(HMBOUND_LOCK), %eax
424 jz ConfigHmbound # Zero means bit clear, we have the config we want so continue as normal
426 # Failed to config - store sticky bit debug
428 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
430 jmp stackless_SideBand_Read
432 orl $(RESET_FOR_HMBOUND_LOCK), %eax
433 movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
435 jmp stackless_SideBand_Write
440 # Set up the HMBOUND register
443 movl $(HMBOUND_ADDRESS), %eax # Data (Set HMBOUND location)
444 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
446 jmp stackless_SideBand_Write
450 # Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
452 movl $(ENABLE_IMR_INTERRUPT), %eax # Data (Set interrupt enable mask)
453 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (BIMRVCTL_OFFSET << SB_ADDR_FIELD)), %ecx
455 jmp stackless_SideBand_Write
461 movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax # Data (Set eSRAM location)
463 addl $(BLOCK_ENABLE_PG), %eax
464 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
466 jmp stackless_SideBand_Write
470 # Check that we're not blocked from setting the config that we want.
472 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
474 jmp stackless_SideBand_Read
476 andl $(BLOCK_ENABLE_PG), %eax
477 jnz ConfigPci # Non-zero means bit set, we have the config we want so continue as normal
479 # Failed to config - store sticky bit debug
481 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
483 jmp stackless_SideBand_Read
485 orl $(RESET_FOR_ESRAM_LOCK), %eax # Set the bit we're interested in
486 movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
488 jmp stackless_SideBand_Write
496 movl $(EC_BASE + EC_ENABLE), %eax # Data
497 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx
499 jmp stackless_SideBand_Write
502 movl $(EC_BASE + EC_ENABLE), %eax # Data
503 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx
505 jmp stackless_SideBand_Write
509 # Open up full 8MB SPI decode
511 movl $(PCI_CFG | (ILB_PFA << 8) | BDE), %ebx # PCI Configuration address
512 movl $(DECODE_ALL_REGIONS_ENABLE), %eax
514 jmp stackless_PCIConfig_Write
518 # Enable NMI operation
519 # Good convention suggests you should read back RTC data port after
520 # accessing the RTC index port.
522 movb $(NMI_ENABLE), %al
523 movw $(RTC_INDEX), %dx
525 movw $(RTC_DATA), %dx
529 # Clear Host Bridge SMI, NMI, INTR fields
531 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
533 jmp stackless_SideBand_Read
535 andl $~(NMI + SMI + INTR), %eax # Clear NMI, SMI, INTR fields
536 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
538 jmp stackless_SideBand_Write
542 # Restore return address
549 # Issue Warm Reset request to Remote Management Unit via iLB
551 movw $(CF9_WARM_RESET), %ax
552 movw $(ILB_RESET_REG), %dx
554 jmp . # Stay here until we are reset.
558 # Issue Cold Reset request to Remote Management Unit via iLB
560 movw $(CF9_COLD_RESET), %ax
561 movw $(ILB_RESET_REG), %dx
563 jmp . # Stay here until we are reset.
565 #----------------------------------------------------------------------------
567 # Procedure: stackless_SideBand_Read
569 # Input: esp - return address
570 # ecx[15:8] - Register offset
571 # ecx[23:16] - Port ID
572 # ecx[31:24] - Opcode
574 # Output: eax - Data read
583 # Perform requested sideband read
585 #----------------------------------------------------------------------------
586 stackless_SideBand_Read:
588 movl %esp, %esi # Save the return address
591 # Load the SideBand Packet Register to generate the transaction
593 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
594 movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
597 jmp stackless_PCIConfig_Write
602 # Read the SideBand Data Register
604 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
606 jmp stackless_PCIConfig_Read
609 movl %esi, %esp # Restore the return address
613 #----------------------------------------------------------------------------
615 # Procedure: stackless_SideBand_Write
617 # Input: esp - return address
619 # ecx[15:8] - Register offset
620 # ecx[23:16] - Port ID
621 # ecx[31:24] - Opcode
631 # Perform requested sideband write
634 #----------------------------------------------------------------------------
635 stackless_SideBand_Write:
637 movl %esp, %esi # Save the return address
640 # Load the SideBand Data Register with the data
642 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
644 jmp stackless_PCIConfig_Write
648 # Load the SideBand Packet Register to generate the transaction
650 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
651 movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
654 jmp stackless_PCIConfig_Write
658 movl %esi, %esp # Restore the return address
662 #----------------------------------------------------------------------------
664 # Procedure: stackless_PCIConfig_Write
666 # Input: esp - return address
667 # eax - Data to write
668 # ebx - PCI Config Address
676 # Perform a DWORD PCI Configuration write
678 #----------------------------------------------------------------------------
679 stackless_PCIConfig_Write:
682 # Write the PCI Config Address to the address port
685 movw $(PCI_ADDRESS_PORT), %dx
690 # Write the PCI DWORD Data to the data port
692 movw $(PCI_DATA_PORT), %dx
698 #----------------------------------------------------------------------------
700 # Procedure: stackless_PCIConfig_Read
702 # Input: esp - return address
703 # ebx - PCI Config Address
705 # Output: eax - Data read
712 # Perform a DWORD PCI Configuration read
714 #----------------------------------------------------------------------------
715 stackless_PCIConfig_Read:
718 # Write the PCI Config Address to the address port
721 movw $(PCI_ADDRESS_PORT), %dx
726 # Read the PCI DWORD Data from the data port
728 movw $(PCI_DATA_PORT), %dx
735 # ROM-based Global-Descriptor Table for the Tiano PEI Phase
739 # GDT[0]: 000h: Null entry, never used.
745 .equ NULL_SEL, . - GDT_BASE # Selector [0]
750 .byte 0 # limit 19:16, flags
753 # linear data segment descriptor
754 .equ LINEAR_SEL, . - GDT_BASE # Selector [0x8]
755 .word 0xFFFF # limit 0xFFFFF
758 .byte 0x92 # present, ring 0, data, expand-up, writable
759 .byte 0xCF # page-granular, 32-bit
762 # linear code segment descriptor
763 .equ LINEAR_CODE_SEL, . - GDT_BASE # Selector [0x10]
764 .word 0xFFFF # limit 0xFFFFF
767 .byte 0x9A # present, ring 0, data, expand-up, writable
768 .byte 0xCF # page-granular, 32-bit
771 # system data segment descriptor
772 .equ SYS_DATA_SEL, . - GDT_BASE # Selector [0x18]
773 .word 0xFFFF # limit 0xFFFFF
776 .byte 0x92 # present, ring 0, data, expand-up, writable
777 .byte 0xCF # page-granular, 32-bit
780 # system code segment descriptor
781 .equ SYS_CODE_SEL, . - GDT_BASE
782 .word 0xFFFF # limit 0xFFFFF
785 .byte 0x9A # present, ring 0, data, expand-up, writable
786 .byte 0xCF # page-granular, 32-bit
789 # spare segment descriptor
790 .equ SYS16_CODE_SEL, . - GDT_BASE
791 .word 0xffff # limit 0xFFFFF
794 .byte 0x9b # present, ring 0, data, expand-up, writable
795 .byte 0 # page-granular, 32-bit
798 # spare segment descriptor
799 .equ SYS16_DATA_SEL, . - GDT_BASE
800 .word 0xffff # limit 0xFFFFF
803 .byte 0x93 # present, ring 0, data, expand-up, not-writable
804 .byte 0 # page-granular, 32-bit
807 # spare segment descriptor
808 .equ SPARE5_SEL, . - GDT_BASE
809 .word 0 # limit 0xFFFFF
812 .byte 0 # present, ring 0, data, expand-up, writable
813 .byte 0 # page-granular, 32-bit
815 .equ GDT_SIZE, . - GDT_BASE
820 GdtDesc: # GDT descriptor
824 ProtectedModeEntryLinearAddress:
825 ProtectedModeEntryLinearOffset:
826 .long ProtectedModeEntryPoint
827 .word LINEAR_CODE_SEL