1;------------------------------------------------------------------------------
2;
3; Copyright (c) 2013-2015 Intel Corporation.
4;
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
9;
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.
12;
13; Module Name:
14;
15;  Flat32.asm
16;
17; Abstract:
18;
19;  This is the code that goes from real-mode to protected mode.
20;  It consumes the reset vector, configures the stack.
21;
22;
23;------------------------------------------------------------------------------
24
25
26;
27; Define assembler characteristics
28;
29.586p
30.model flat, c
31
32;
33; Include processor definitions
34;
35
36INCLUDE Platform.inc
37
38
39;
40; CR0 cache control bit definition
41;
42CR0_CACHE_DISABLE       EQU 040000000h
43CR0_NO_WRITE            EQU 020000000h
44
45;
46; External and public declarations
47;  TopOfStack is used by C code
48;  SecStartup is the entry point to the C code
49; Neither of these names can be modified without
50; updating the C code.
51;
52EXTRN   PlatformSecLibStartup: NEAR
53EXTERNDEF   C   PcdGet32 (PcdEsramStage1Base):DWORD
54
55;
56; Contrary to the name, this file contains 16 bit code as well.
57;
58_TEXT_REALMODE      SEGMENT PARA PUBLIC USE16 'CODE'
59                    ASSUME  CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
60
61;----------------------------------------------------------------------------
62;
63; Procedure:    _ModuleEntryPoint
64;
65; Input:        None
66;
67; Output:       None
68;
69; Destroys:     Assume all registers
70;
71; Description:
72;
73;   Transition to non-paged flat-model protected mode from a
74;   hard-coded GDT that provides exactly two descriptors.
75;   This is a bare bones transition to protected mode only
76;   used for a while in PEI and possibly DXE.
77;
78;   After enabling protected mode, a far jump is executed to
79;   transfer to PEI using the newly loaded GDT.
80;
81; Return:       None
82;
83;----------------------------------------------------------------------------
84align 16
85_ModuleEntryPoint      PROC C PUBLIC
86
87  ;
88  ; Warm Reset (INIT#) check.
89  ;
90  mov     si, 0F000h
91  mov     ds, si
92  mov     si, 0FFF0h
93  cmp     BYTE PTR [si], 0EAh   ; Is it warm reset ?
94  jne     NotWarmReset          ; JIf not.
95
96  mov     al, 08
97  mov     dx, 0cf9h
98  out     dx, al
99  mov     al, 055h
100  out     080h, al;
101  jmp $
102NotWarmReset:
103
104  ;
105  ; Load the GDT table in GdtDesc
106  ;
107  mov     esi, OFFSET GdtDesc
108  db      66h
109  lgdt    fword ptr cs:[si]
110
111  ;
112  ; Transition to 16 bit protected mode
113  ;
114  mov     eax, cr0                   ; Get control register 0
115  or      eax, 00000003h             ; Set PE bit (bit #0) & MP bit (bit #1)
116  mov     cr0, eax                   ; Activate protected mode
117
118  ;
119  ; Now we're in 16 bit protected mode
120  ; Set up the selectors for 32 bit protected mode entry
121  ;
122  mov     ax, SYS_DATA_SEL
123  mov     ds, ax
124  mov     es, ax
125  mov     fs, ax
126  mov     gs, ax
127  mov     ss, ax
128
129  ;
130  ; Transition to Flat 32 bit protected mode
131  ; The jump to a far pointer causes the transition to 32 bit mode
132  ;
133  mov esi, offset ProtectedModeEntryLinearAddress
134  jmp     fword ptr cs:[si]
135
136_ModuleEntryPoint   ENDP
137
138_TEXT_REALMODE      ENDS
139
140.code
141;
142; Protected mode portion initializes stack, configures cache, and calls C entry point
143;
144
145;----------------------------------------------------------------------------
146;
147; Procedure:    ProtectedModeEntryPoint
148;
149; Input:        Executing in 32 Bit Protected (flat) mode
150;                cs: 0-4GB
151;                ds: 0-4GB
152;                es: 0-4GB
153;                fs: 0-4GB
154;                gs: 0-4GB
155;                ss: 0-4GB
156;
157; Output:       This function never returns
158;
159; Destroys:
160;               ecx
161;               edi
162;                esi
163;                esp
164;
165; Description:
166;                Perform any essential early platform initilaisation
167;               Setup a stack
168;               Call the main EDKII Sec C code
169;
170;----------------------------------------------------------------------------
171
172ProtectedModeEntryPoint PROC NEAR C PUBLIC
173
174  JMP32  stackless_EarlyPlatformInit
175
176  ;
177  ; Set up stack pointer
178  ;
179  mov     esp, PcdGet32(PcdEsramStage1Base)
180  mov     esi, QUARK_ESRAM_MEM_SIZE_BYTES
181  add     esp, esi                         ; ESP = top of stack (stack grows downwards).
182
183  ;
184  ; Store the the BIST value in EBP
185  ;
186  mov     ebp, 00h        ; No processor BIST on Quark
187
188  ;
189  ; Push processor count to stack first, then BIST status (AP then BSP)
190  ;
191  mov     eax, 1
192  cpuid
193  shr     ebx, 16
194  and     ebx, 0000000FFh
195  cmp     bl, 1
196  jae     PushProcessorCount
197
198  ;
199  ; Some processors report 0 logical processors.  Effectively 0 = 1.
200  ; So we fix up the processor count
201  ;
202  inc     ebx
203
204PushProcessorCount:
205  push    ebx
206
207  ;
208  ; We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST
209  ; for all processor threads
210  ;
211  xor     ecx, ecx
212  mov     cl, bl
213PushBist:
214  push    ebp
215  loop    PushBist
216
217  ;
218  ; Pass Control into the PEI Core
219  ;
220  call PlatformSecLibStartup
221
222  ;
223  ; PEI Core should never return to here, this is just to capture an invalid return.
224  ;
225  jmp     $
226
227ProtectedModeEntryPoint ENDP
228
229;----------------------------------------------------------------------------
230;
231; Procedure:    stackless_EarlyPlatformInit
232;
233; Input:        esp - Return address
234;
235; Output:       None
236;
237; Destroys:
238;                eax
239;                ecx
240;                dx
241;                ebp
242;
243; Description:
244;        Any essential early platform initialisation required:
245;        (1) Disable Cache
246;        (2) Disable NMI's/SMI's
247;        (3) Setup HMBOUND (defines what memory accesses go to MMIO/RAM)
248;        (4) Setup eSRAM (provide early memory to the system)
249;        (5) Setup PCIEXBAR access mechanism
250;        (6) Open up full SPI flash decode
251;
252;----------------------------------------------------------------------------
253stackless_EarlyPlatformInit  PROC NEAR C PUBLIC
254
255  ;
256  ; Save return address
257  ;
258  mov  ebp, esp
259
260  ;
261  ; Ensure cache is disabled.
262  ;
263  mov     eax, cr0
264  or      eax, CR0_CACHE_DISABLE + CR0_NO_WRITE
265  invd
266  mov     cr0, eax
267
268  ;
269  ; Disable NMI
270  ; Good convention suggests you should read back RTC data port after
271  ; accessing the RTC index port.
272  ;
273  mov  al, NMI_DISABLE
274  mov  dx, RTC_INDEX
275  out  dx, al
276  mov  dx, RTC_DATA
277  in  al, dx
278
279  ;
280  ; Disable SMI (Disables SMI wire, not SMI messages)
281  ;
282  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMISC2_OFFSET SHL SB_ADDR_FIELD)
283  JMP32  stackless_SideBand_Read
284  and  eax, NOT (SMI_EN)
285  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMISC2_OFFSET SHL SB_ADDR_FIELD)
286  JMP32  stackless_SideBand_Write
287
288  ;
289  ; Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
290  ;
291  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGNONSTICKY_W1_OFFSET SHL SB_ADDR_FIELD)
292  JMP32  stackless_SideBand_Read
293  and  eax, FORCE_WARM_RESET
294  jz TestForceColdReset    ; Zero means bit clear, we're not requested to warm reset so continue as normal
295  jmp IssueWarmReset
296
297TestForceColdReset:
298  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_W1_OFFSET SHL SB_ADDR_FIELD)
299  JMP32  stackless_SideBand_Read
300  and  eax, FORCE_COLD_RESET
301  jz TestHmboundLock    ; Zero means bit clear, we're not requested to cold reset so continue as normal
302  jmp IssueColdReset
303
304  ;
305  ; Before setting HMBOUND, check it's not locked
306  ;
307TestHmboundLock:
308  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)
309  JMP32  stackless_SideBand_Read
310  and  eax, HMBOUND_LOCK
311  jz ConfigHmbound  ; Zero means bit clear, we have the config we want so continue as normal
312  ;
313  ; Failed to config - store sticky bit debug
314  ;
315  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
316  JMP32  stackless_SideBand_Read
317  or  eax, RESET_FOR_HMBOUND_LOCK  ; Set the bit we're interested in
318  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_WRITE SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
319  JMP32  stackless_SideBand_Write
320  jmp IssueWarmReset
321
322  ;
323  ; Set up the HMBOUND register
324  ;
325ConfigHmbound:
326  mov  eax, HMBOUND_ADDRESS    ; Data (Set HMBOUND location)
327  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)
328  JMP32  stackless_SideBand_Write
329
330  ;
331  ; Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
332  ;
333  mov  eax, ENABLE_IMR_INTERRUPT        ; Data (Set interrupt enable mask)
334  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (BIMRVCTL_OFFSET SHL SB_ADDR_FIELD)
335  JMP32  stackless_SideBand_Write
336
337  ;
338  ; Set eSRAM address
339  ;
340  mov  eax, PcdGet32 (PcdEsramStage1Base)        ; Data (Set eSRAM location)
341  shr  eax, 18h        ; Data (Set eSRAM location)
342  add eax, BLOCK_ENABLE_PG
343  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (ESRAMPGCTRL_BLOCK_OFFSET SHL SB_ADDR_FIELD)
344  JMP32  stackless_SideBand_Write
345  ;
346  ; Check that we're not blocked from setting the config that we want.
347  ;
348  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (ESRAMPGCTRL_BLOCK_OFFSET SHL SB_ADDR_FIELD)
349  JMP32  stackless_SideBand_Read
350  and  eax, BLOCK_ENABLE_PG
351  jnz ConfigPci  ; Non-zero means bit set, we have the config we want so continue as normal
352  ;
353  ; Failed to config - store sticky bit debug
354  ;
355  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
356  JMP32  stackless_SideBand_Read
357  or  eax, RESET_FOR_ESRAM_LOCK  ; Set the bit we're interested in
358  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_WRITE SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)
359  JMP32  stackless_SideBand_Write
360  jmp IssueWarmReset
361
362  ;
363  ; Enable PCIEXBAR
364  ;
365ConfigPci:
366  mov  eax, (EC_BASE + EC_ENABLE)      ; Data
367  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_ARBITER_PORT_ID SHL SB_PORT_FIELD) OR (AEC_CTRL_OFFSET SHL SB_ADDR_FIELD)
368  JMP32  stackless_SideBand_Write
369
370  mov  eax, (EC_BASE + EC_ENABLE)      ; Data
371  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HECREG_OFFSET SHL SB_ADDR_FIELD)
372  JMP32  stackless_SideBand_Write
373
374  ;
375  ;  Open up full 8MB SPI decode
376  ;
377  mov  ebx, PCI_CFG OR (ILB_PFA SHL 8) OR BDE  ; PCI Configuration address
378  mov eax, DECODE_ALL_REGIONS_ENABLE
379  JMP32  stackless_PCIConfig_Write
380
381  ;
382  ; Enable NMI operation
383  ; Good convention suggests you should read back RTC data port after
384  ; accessing the RTC index port.
385  ;
386  mov al, NMI_ENABLE
387  mov dx, RTC_INDEX
388  out dx, al
389  mov dx, RTC_DATA
390  in  al, dx
391
392  ;
393  ; Clear Host Bridge SMI, NMI, INTR fields
394  ;
395  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HLEGACY_OFFSET SHL SB_ADDR_FIELD)
396  JMP32  stackless_SideBand_Read
397  and  eax, NOT(NMI + SMI + INTR)  ; Clear NMI, SMI, INTR fields
398  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HLEGACY_OFFSET SHL SB_ADDR_FIELD)
399  JMP32  stackless_SideBand_Write
400
401  ;
402  ; Restore return address
403  ;
404  mov  esp, ebp
405  RET32
406
407IssueWarmReset:
408  ;
409  ; Issue Warm Reset request to Remote Management Unit via iLB
410  ;
411  mov ax, CF9_WARM_RESET
412  mov  dx, ILB_RESET_REG
413  out  dx, ax
414  jmp  $  ; Stay here until we are reset.
415
416IssueColdReset:
417  ;
418  ; Issue Cold Reset request to Remote Management Unit via iLB
419  ;
420  mov ax, CF9_COLD_RESET
421  mov  dx, ILB_RESET_REG
422  out  dx, ax
423  jmp  $  ; Stay here until we are reset.
424
425stackless_EarlyPlatformInit ENDP
426
427;----------------------------------------------------------------------------
428;
429; Procedure:    stackless_SideBand_Read
430;
431; Input:        esp - return address
432;                ecx[15:8] - Register offset
433;                ecx[23:16] - Port ID
434;                ecx[31:24] - Opcode
435;
436; Output:       eax - Data read
437;
438; Destroys:
439;                eax
440;                ebx
441;                cl
442;                esi
443;
444; Description:
445;        Perform requested sideband read
446;
447;----------------------------------------------------------------------------
448stackless_SideBand_Read  PROC NEAR C PUBLIC
449
450  mov  esi, esp        ; Save the return address
451
452  ;
453  ; Load the SideBand Packet Register to generate the transaction
454  ;
455  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG  ; PCI Configuration address
456  mov  cl, (ALL_BYTE_EN SHL SB_BE_FIELD)    ; Set all Byte Enable bits
457  xchg  eax, ecx
458  JMP32  stackless_PCIConfig_Write
459  xchg  eax, ecx
460
461  ;
462  ; Read the SideBand Data Register
463  ;
464  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG    ; PCI Configuration address
465  JMP32  stackless_PCIConfig_Read
466
467  mov  esp, esi        ; Restore the return address
468  RET32
469
470stackless_SideBand_Read ENDP
471
472;----------------------------------------------------------------------------
473;
474; Procedure:    stackless_SideBand_Write
475;
476; Input:        esp - return address
477;                eax - Data
478;                ecx[15:8] - Register offset
479;                ecx[23:16] - Port ID
480;                ecx[31:24] - Opcode
481;
482; Output:       None
483;
484; Destroys:
485;                ebx
486;                cl
487;                esi
488;
489; Description:
490;        Perform requested sideband write
491;
492;
493;----------------------------------------------------------------------------
494stackless_SideBand_Write  PROC NEAR C PUBLIC
495
496  mov  esi, esp        ; Save the return address
497
498  ;
499  ; Load the SideBand Data Register with the data
500  ;
501  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG  ; PCI Configuration address
502  JMP32  stackless_PCIConfig_Write
503
504  ;
505  ; Load the SideBand Packet Register to generate the transaction
506  ;
507  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG  ; PCI Configuration address
508  mov  cl, (ALL_BYTE_EN SHL SB_BE_FIELD)    ; Set all Byte Enable bits
509  xchg  eax, ecx
510  JMP32  stackless_PCIConfig_Write
511  xchg  eax, ecx
512
513  mov  esp, esi        ; Restore the return address
514  RET32
515
516stackless_SideBand_Write ENDP
517
518;----------------------------------------------------------------------------
519;
520; Procedure:    stackless_PCIConfig_Write
521;
522; Input:        esp - return address
523;                eax - Data to write
524;                ebx - PCI Config Address
525;
526; Output:       None
527;
528; Destroys:
529;                dx
530;
531; Description:
532;        Perform a DWORD PCI Configuration write
533;
534;----------------------------------------------------------------------------
535stackless_PCIConfig_Write  PROC NEAR C PUBLIC
536
537  ;
538  ; Write the PCI Config Address to the address port
539  ;
540  xchg  eax, ebx
541  mov  dx, PCI_ADDRESS_PORT
542  out  dx, eax
543  xchg  eax, ebx
544
545  ;
546  ; Write the PCI DWORD Data to the data port
547  ;
548  mov  dx, PCI_DATA_PORT
549  out  dx, eax
550
551  RET32
552
553stackless_PCIConfig_Write ENDP
554
555;----------------------------------------------------------------------------
556;
557; Procedure:    stackless_PCIConfig_Read
558;
559; Input:        esp - return address
560;                ebx - PCI Config Address
561;
562; Output:       eax - Data read
563;
564; Destroys:
565;                eax
566;                dx
567;
568; Description:
569;        Perform a DWORD PCI Configuration read
570;
571;----------------------------------------------------------------------------
572stackless_PCIConfig_Read  PROC NEAR C PUBLIC
573
574  ;
575  ; Write the PCI Config Address to the address port
576  ;
577  xchg  eax, ebx
578  mov  dx, PCI_ADDRESS_PORT
579  out  dx, eax
580  xchg  eax, ebx
581
582  ;
583  ; Read the PCI DWORD Data from the data port
584  ;
585  mov  dx, PCI_DATA_PORT
586  in  eax, dx
587
588  RET32
589
590stackless_PCIConfig_Read ENDP
591
592;
593; ROM-based Global-Descriptor Table for the Tiano PEI Phase
594;
595align 16
596PUBLIC  BootGdtTable
597
598;
599; GDT[0]: 0x00: Null entry, never used.
600;
601NULL_SEL        equ     $ - GDT_BASE        ; Selector [0]
602GDT_BASE:
603BootGdtTable    DD      0
604                DD      0
605;
606; Linear data segment descriptor
607;
608LINEAR_SEL      equ     $ - GDT_BASE        ; Selector [0x8]
609        DW      0FFFFh                      ; limit 0xFFFF
610        DW      0                           ; base 0
611        DB      0
612        DB      092h                        ; present, ring 0, data, expand-up, writable
613        DB      0CFh                        ; page-granular, 32-bit
614        DB      0
615;
616; Linear code segment descriptor
617;
618LINEAR_CODE_SEL equ     $ - GDT_BASE        ; Selector [0x10]
619        DW      0FFFFh                      ; limit 0xFFFF
620        DW      0                           ; base 0
621        DB      0
622        DB      09Bh                        ; present, ring 0, data, expand-up, not-writable
623        DB      0CFh                        ; page-granular, 32-bit
624        DB      0
625;
626; System data segment descriptor
627;
628SYS_DATA_SEL    equ     $ - GDT_BASE        ; Selector [0x18]
629        DW      0FFFFh                      ; limit 0xFFFF
630        DW      0                           ; base 0
631        DB      0
632        DB      093h                        ; present, ring 0, data, expand-up, not-writable
633        DB      0CFh                        ; page-granular, 32-bit
634        DB      0
635
636;
637; System code segment descriptor
638;
639SYS_CODE_SEL    equ     $ - GDT_BASE        ; Selector [0x20]
640        DW      0FFFFh                      ; limit 0xFFFF
641        DW      0                           ; base 0
642        DB      0
643        DB      09Ah                        ; present, ring 0, data, expand-up, writable
644        DB      0CFh                        ; page-granular, 32-bit
645        DB      0
646;
647; Spare segment descriptor
648;
649SYS16_CODE_SEL  equ     $ - GDT_BASE        ; Selector [0x28]
650        DW      0FFFFh                      ; limit 0xFFFF
651        DW      0                           ; base 0
652        DB      0Fh
653        DB      09Bh                        ; present, ring 0, code, expand-up, writable
654        DB      00h                         ; byte-granular, 16-bit
655        DB      0
656;
657; Spare segment descriptor
658;
659SYS16_DATA_SEL  equ     $ - GDT_BASE        ; Selector [0x30]
660        DW      0FFFFh                      ; limit 0xFFFF
661        DW      0                           ; base 0
662        DB      0
663        DB      093h                        ; present, ring 0, data, expand-up, not-writable
664        DB      00h                         ; byte-granular, 16-bit
665        DB      0
666
667;
668; Spare segment descriptor
669;
670SPARE5_SEL      equ     $ - GDT_BASE        ; Selector [0x38]
671        DW      0                           ; limit 0xFFFF
672        DW      0                           ; base 0
673        DB      0
674        DB      0                           ; present, ring 0, data, expand-up, writable
675        DB      0                           ; page-granular, 32-bit
676        DB      0
677GDT_SIZE        EQU     $ - BootGDTtable    ; Size, in bytes
678
679;
680; GDT Descriptor
681;
682GdtDesc:                                    ; GDT descriptor
683        DW      GDT_SIZE - 1                ; GDT limit
684        DD      OFFSET BootGdtTable         ; GDT base address
685
686ProtectedModeEntryLinearAddress   LABEL   FWORD
687ProtectedModeEntryLinearOffset    LABEL   DWORD
688  DD      OFFSET ProtectedModeEntryPoint  ; Offset of our 32 bit code
689  DW      LINEAR_CODE_SEL
690
691END
692