1 #------------------------------------------------------------------------------
3 #* Copyright 2006 - 2007, Intel Corporation
4 #* All rights reserved. This program and the accompanying materials
5 #* are licensed and made available under the terms and conditions of the BSD License
6 #* which accompanies this distribution. The full text of the license may be found at
7 #* http://opensource.org/licenses/bsd-license.php
9 #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #------------------------------------------------------------------------------
23 .equ FAT_DIRECTORY_ENTRY_SIZE, 0x020
24 .equ FAT_DIRECTORY_ENTRY_SHIFT, 5
25 .equ BLOCK_SIZE, 0x0200
26 .equ BLOCK_MASK, 0x01ff
31 jmp BootSectorEntryPoint # JMP inst - 3 bytes
34 OemId: .ascii "INTEL " # OemId - 8 bytes
36 SectorSize: .word 0 # Sector Size - 16 bits
37 SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits
38 ReservedSectors: .word 0 # Reserved Sectors - 16 bits
39 NoFats: .byte 0 # Number of FATs - 8 bits
40 RootEntries: .word 0 # Root Entries - 16 bits
41 Sectors: .word 0 # Number of Sectors - 16 bits
42 Media: .byte 0 # Media - 8 bits - ignored
43 SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits
44 SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored
45 Heads: .word 0 # Heads - 16 bits - ignored
46 HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored
47 LargeSectors: .long 0 # Large Sectors - 32 bits
48 PhysicalDrive: .byte 0 # PhysicalDriveNumber - 8 bits - ignored
49 CurrentHead: .byte 0 # Current Head - 8 bits
50 Signature: .byte 0 # Signature - 8 bits - ignored
51 VolId: .ascii " " # Volume Serial Number- 4 bytes
52 FatLabel: .ascii " " # Label - 11 bytes
53 SystemId: .ascii "FAT12 " # SystemId - 8 bytes
58 # ds = 1000, es = 2000 + x (size of first cluster >> 4)
59 # cx = Start Cluster of EfiLdr
60 # dx = Start Cluster of Efivar.bin
62 # Re use the BPB data stored in Boot Sector
67 # 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
76 # Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
82 cmpl $0x4000, %ds:2(%di)
100 movw VolId+2(%bp), %ax
105 # cx = Start Cluster of Efildr -> BS.com has filled already
106 # ES:DI = 2000:0, first cluster will be read again
107 xorw %di,%di # di = 0
112 movw %ax, %cs:JumpSegment
115 movl $0x80000001,%eax
124 jmp PrintStringAndHalt
135 # ****************************************************************************
139 # CX = Start Cluster of File
140 # ES:DI = Buffer to store file content read from disk
143 # (ES << 4 + DI) = end of file content Buffer
145 # ****************************************************************************
147 # si = NumberOfClusters
149 # dx = CachedFatSectorNumber
150 # ds:0000 = CacheFatSectorBuffer
151 # es:di = Buffer to load file
152 # bx = NextClusterNumber
154 movw $1,%si # NumberOfClusters = 1
155 pushw %cx # Push Start Cluster onto stack
156 movw $0xfff,%dx # CachedFatSectorNumber = 0xfff
158 movw %cx,%ax # ax = ClusterNumber
159 andw $0xff8,%ax # ax = ax & 0xff8
160 cmpw $0xff8,%ax # See if this is the last cluster
161 je FoundLastCluster # Jump if last cluster found
162 movw %cx,%ax # ax = ClusterNumber
163 shlw %ax # ax = ClusterNumber * 2
164 addw %cx,%ax # ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
165 shrw %ax # FatOffset = ClusterNumber*3 / 2
167 movw %ax,%si # si = FatOffset
168 shrw $BLOCK_SHIFT, %ax # ax = FatOffset >> BLOCK_SHIFT
169 addw ReservedSectors(%bp), %ax # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
170 andw $BLOCK_MASK, %si # si = FatOffset & BLOCK_MASK
171 cmpw %dx,%ax # Compare FatSectorNumber to CachedFatSectorNumber
177 call ReadBlocks # Read 2 blocks starting at AX storing at ES:DI
179 movw %ax,%dx # CachedFatSectorNumber = FatSectorNumber
181 movw (%si), %bx # bx = NextClusterNumber
182 movw %cx,%ax # ax = ClusterNumber
183 andw $1,%ax # See if this is an odd cluster number
185 shrw $4,%bx # NextClusterNumber = NextClusterNumber >> 4
187 andw $0xfff,%bx # Strip upper 4 bits of NextClusterNumber
188 popw %si # Restore si
189 decw %bx # bx = NextClusterNumber - 1
190 cmpw %cx,%bx # See if (NextClusterNumber-1)==ClusterNumber
192 incw %bx # bx = NextClusterNumber
193 incw %si # NumberOfClusters++
194 movw %bx,%cx # ClusterNumber = NextClusterNumber
198 popw %ax # ax = StartCluster
199 pushw %bx # StartCluster = NextClusterNumber
200 movw %bx,%cx # ClusterNumber = NextClusterNumber
201 subw $2,%ax # ax = StartCluster - 2
203 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
204 mulw %bx # ax = (StartCluster - 2) * SectorsPerCluster
205 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
206 pushw %ax # save start sector
207 movw %si,%ax # ax = NumberOfClusters
208 mulw %bx # ax = NumberOfClusters * SectorsPerCluster
209 movw %ax,%bx # bx = Number of Sectors
210 popw %ax # ax = Start Sector
212 movw $1,%si # NumberOfClusters = 1
220 # ****************************************************************************
221 # ReadBlocks - Reads a set of blocks from a block device
224 # BX = Number of Blocks to Read
225 # ES:DI = Buffer to store sectors read from disk
226 # ****************************************************************************
229 # bx = NumberOfBlocks
234 addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
235 addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
236 movl %eax,%esi # esi = Start LBA
237 movw %bx,%cx # cx = Number of blocks to read
239 movw $0x7bfc,%bp # bp = 0x7bfc
240 movl %esi,%eax # eax = Start LBA
241 xorl %edx,%edx # edx = 0
242 movzwl (%bp), %ebx # bx = MaxSector
243 divl %ebx # ax = StartLBA / MaxSector
244 incw %dx # dx = (StartLBA % MaxSector) + 1
246 movw (%bp), %bx # bx = MaxSector
247 subw %dx,%bx # bx = MaxSector - Sector
248 incw %bx # bx = MaxSector - Sector + 1
249 cmpw %bx,%cx # Compare (Blocks) to (MaxSector - Sector + 1)
251 movw %cx,%bx # bx = Blocks
254 movw %es,%ax # ax = es
255 shrw $(BLOCK_SHIFT-4), %ax # ax = Number of blocks into mem system
256 andw $0x7f,%ax # ax = Number of blocks into current seg
257 addw %bx,%ax # ax = End Block number of transfer
258 cmpw $0x80,%ax # See if it crosses a 64K boundry
259 jle NotCrossing64KBoundry # Branch if not crossing 64K boundry
260 subw $0x80,%ax # ax = Number of blocks past 64K boundry
261 subw %ax,%bx # Decrease transfer size by block overage
262 NotCrossing64KBoundry:
263 popw %ax # restore ax
266 movb %dl,%cl # cl = (StartLBA % MaxSector) + 1 = Sector
267 xorw %dx,%dx # dx = 0
268 divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
269 # dx = ax % (MaxHead + 1) = Head
271 pushw %bx # Save number of blocks to transfer
272 movb %dl,%dh # dh = Head
273 movw $0x7c00,%bp # bp = 0x7c00
274 movb PhysicalDrive(%bp), %dl # dl = Drive Number
275 movb %al,%ch # ch = Cylinder
276 movb %bl,%al # al = Blocks
277 movb $2,%ah # ah = Function 2
278 movw %di,%bx # es:bx = Buffer address
284 addl %ebx,%esi # StartLBA = StartLBA + NumberOfBlocks
285 subw %bx,%cx # Blocks = Blocks - NumberOfBlocks
287 shlw $(BLOCK_SHIFT-4), %bx
289 movw %ax,%es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
300 jmp PrintStringAndHalt
312 .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c
315 LBAOffsetForBootSector:
321 #******************************************************************************
322 #******************************************************************************
323 #******************************************************************************
325 .equ DELAY_PORT, 0x0ed # Port to use for 1uS delay
326 .equ KBD_CONTROL_PORT, 0x060 # 8042 control port
327 .equ KBD_STATUS_PORT, 0x064 # 8042 status port
328 .equ WRITE_DATA_PORT_CMD, 0x0d1 # 8042 command to write the data port
329 .equ ENABLE_A20_CMD, 0x0df # 8042 command to enable A20
334 .byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c
345 # mov byte ptr es:[160],'a'
354 movl $0x534d4150, %edx # SMAP
363 subl %eax,%edi # Get the address of the memory map
364 movl %edi, MemoryMapSize # Save the size of the memory map
367 movw %cs,%bx # BX=segment
368 shll $4,%ebx # BX="linear" address of segment base
369 leal GDT_BASE(%ebx), %eax # EAX=PHYSICAL address of gdt
370 movl %eax, (gdtr + 2) # Put address of gdt into the gdtr
371 leal IDT_BASE(%ebx), %eax # EAX=PHYSICAL address of idt
372 movl %eax, (idtr + 2) # Put address of idt into the idtr
373 leal MemoryMapSize(%ebx), %edx # Physical base address of the memory map
377 # mov byte ptr es:[162],'b'
385 movw $0x2401,%ax # Enable A20 Gate
387 jnc A20GateEnabled # Jump if it suceeded
390 # If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
393 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller
394 jnz Timeout8042 # Jump if the 8042 timed out
395 outw %ax, $DELAY_PORT # Delay 1 uS
396 movb $WRITE_DATA_PORT_CMD, %al # 8042 cmd to write output port
397 outb %al, $KBD_STATUS_PORT # Send command to the 8042
398 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller
399 jnz Timeout8042 # Jump if the 8042 timed out
400 movb $ENABLE_A20_CMD, %al # gate address bit 20 on
401 outb %al, $KBD_CONTROL_PORT # Send command to thre 8042
402 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller
403 movw $25,%cx # Delay 25 uS for the command to complete on the 8042
405 outw %ax, $DELAY_PORT # Delay 1 uS
413 # DISABLE INTERRUPTS - Entering Protected Mode
420 # mov byte ptr es:[164],'c'
424 leal OffsetIn32BitProtectedMode, %eax
425 addl $0x20000+0x6,%eax
426 movl %eax, OffsetIn32BitProtectedMode
428 leal OffsetInLongMode, %eax
429 addl $0x20000+0x6,%eax
430 movl %eax, OffsetInLongMode
439 # Enable Protect Mode (set CR0.PE=1)
441 movl %cr0, %eax # Read CR0.
442 orl $0x1,%eax # Set PE=1
443 movl %eax, %cr0 # Write CR0.
445 .byte 0xea # jmp far 16:32
446 OffsetIn32BitProtectedMode:
447 .long 0x0000000 # offset $+8 (In32BitProtectedMode)
448 .word 0x10 # selector (flat CS)
449 In32BitProtectedMode:
461 # Enable the 64-bit page-translation-table entries by
462 # setting CR4.PAE=1 (this is _required_ before activating
463 # long mode). Paging is not enabled until after long mode
477 # This is the Trapolean Page Tables that are guarenteed
481 # 10000 ~ 12000 - efildr (loaded)
482 # 20000 ~ 21000 - start64.com
483 # 21000 ~ 22000 - efi64.com
484 # 22000 ~ 90000 - efildr
485 # 90000 ~ 96000 - 4G pagetable (will be reload later)
493 # Enable long mode (set EFER.LME=1).
497 # mov ecx, 0c0000080h ; EFER MSR number.
505 # bts eax, 8 ; Set LME=1.
508 # wrmsr ; Write EFER.
511 # Enable paging to activate long mode (set CR0.PG=1)
513 movl $cr0, %eax # Read CR0.
518 # bts eax, 31 ; Set PG=1.
519 movl %eax, %cr0 # Write CR0.
524 .byte 0xea # Far Jump $+9:Selector to reload CS
526 .long 00000000 # $+9 Offset is ensuing instruction boundary
527 .word 0x38 # Selector is our code selector, 38h
542 # mov ebp,000400000h ; Destination of EFILDR32
545 # mov ebx,000070000h ; Length of copy
564 # lidt fword ptr [rax]
577 Empty8042InputBuffer:
580 outw %ax, $DELAY_PORT # Delay 1us
581 inb $KBD_STATUS_PORT, %al # Read the 8042 Status Port
582 andb $0x2,%al # Check the Input Buffer Full Flag
583 loopnz Empty8042Loop # Loop until the input buffer is empty or a timout of 65536 uS
586 ##############################################################################
588 ##############################################################################
592 gdtr: .long GDT_END - GDT_BASE - 1 # GDT limit
593 .long 0 # (GDT base gets set above)
594 ##############################################################################
595 # global descriptor table (GDT)
596 ##############################################################################
602 .equ NULL_SEL, .-GDT_BASE # Selector [0x0]
607 .byte 0 # limit 19:16, flags
610 # linear data segment descriptor
611 .equ LINEAR_SEL, .-GDT_BASE # Selector [0x8]
612 .word 0xFFFF # limit 0xFFFFF
615 .byte 0x92 # present, ring 0, data, expand-up, writable
616 .byte 0xCF # page-granular, 32-bit
619 # linear code segment descriptor
620 .equ LINEAR_CODE_SEL, .-GDT_BASE # Selector [0x10]
621 .word 0xFFFF # limit 0xFFFFF
624 .byte 0x9A # present, ring 0, data, expand-up, writable
625 .byte 0xCF # page-granular, 32-bit
628 # system data segment descriptor
629 .equ SYS_DATA_SEL, .-GDT_BASE # Selector [0x18]
630 .word 0xFFFF # limit 0xFFFFF
633 .byte 0x92 # present, ring 0, data, expand-up, writable
634 .byte 0xCF # page-granular, 32-bit
637 # system code segment descriptor
638 .equ SYS_CODE_SEL, .-GDT_BASE # Selector [0x20]
639 .word 0xFFFF # limit 0xFFFFF
642 .byte 0x9A # present, ring 0, data, expand-up, writable
643 .byte 0xCF # page-granular, 32-bit
646 # spare segment descriptor
647 .equ SPARE3_SEL, .-GDT_BASE # Selector [0x28]
648 .word 0 # limit 0xFFFFF
651 .byte 0 # present, ring 0, data, expand-up, writable
652 .byte 0 # page-granular, 32-bit
656 # system data segment descriptor
658 .equ SYS_DATA64_SEL, .-GDT_BASE # Selector [0x30]
659 .word 0xFFFF # limit 0xFFFFF
662 .byte 0x92 # P | DPL [1..2] | 1 | 1 | C | R | A
663 .byte 0xCF # G | D | L | AVL | Segment [19..16]
667 # system code segment descriptor
669 .equ SYS_CODE64_SEL, .-GDT_BASE # Selector [0x38]
670 .word 0xFFFF # limit 0xFFFFF
673 .byte 0x9A # P | DPL [1..2] | 1 | 1 | C | R | A
674 .byte 0xAF # G | D | L | AVL | Segment [19..16]
677 # spare segment descriptor
678 .equ SPARE4_SEL, .-GDT_BASE # Selector [0x40]
679 .word 0 # limit 0xFFFFF
682 .byte 0 # present, ring 0, data, expand-up, writable
683 .byte 0 # page-granular, 32-bit
692 idtr: .long IDT_END - IDT_BASE - 1 # IDT limit
693 .quad 0 # (IDT base gets set above)
695 ##############################################################################
696 # interrupt descriptor table (IDT)
698 # Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
699 # mappings. This implementation only uses the system timer and all other
700 # IRQs will remain masked. The descriptors for vectors 33+ are provided
702 ##############################################################################
709 # divide by zero (INT 0)
710 .equ DIV_ZERO_SEL, .-IDT_BASE
711 .word 0 # offset 15:0
712 .long SYS_CODE64_SEL # selector 15:0
713 .byte 0 # 0 for interrupt gate
714 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
715 .word 0 # offset 31:16
716 .long 0 # offset 63:32
717 .long 0 # 0 for reserved
719 # debug exception (INT 1)
720 .equ DEBUG_EXCEPT_SEL, .-IDT_BASE
721 .word 0 # offset 15:0
722 .long SYS_CODE64_SEL # selector 15:0
723 .byte 0 # 0 for interrupt gate
724 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
725 .word 0 # offset 31:16
726 .long 0 # offset 63:32
727 .long 0 # 0 for reserved
730 .equ NMI_SEL, .-IDT_BASE
731 .word 0 # offset 15:0
732 .long SYS_CODE64_SEL # selector 15:0
733 .byte 0 # 0 for interrupt gate
734 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
735 .word 0 # offset 31:16
736 .long 0 # offset 63:32
737 .long 0 # 0 for reserved
739 # soft breakpoint (INT 3)
740 .equ BREAKPOINT_SEL, .-IDT_BASE
741 .word 0 # offset 15:0
742 .long SYS_CODE64_SEL # selector 15:0
743 .byte 0 # 0 for interrupt gate
744 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
745 .word 0 # offset 31:16
746 .long 0 # offset 63:32
747 .long 0 # 0 for reserved
750 .equ OVERFLOW_SEL, .-IDT_BASE
751 .word 0 # offset 15:0
752 .long SYS_CODE64_SEL # selector 15:0
753 .byte 0 # 0 for interrupt gate
754 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
755 .word 0 # offset 31:16
756 .long 0 # offset 63:32
757 .long 0 # 0 for reserved
759 # bounds check (INT 5)
760 .equ BOUNDS_CHECK_SEL, .-IDT_BASE
761 .word 0 # offset 15:0
762 .long SYS_CODE64_SEL # selector 15:0
763 .byte 0 # 0 for interrupt gate
764 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
765 .word 0 # offset 31:16
766 .long 0 # offset 63:32
767 .long 0 # 0 for reserved
769 # invalid opcode (INT 6)
770 .equ INVALID_OPCODE_SEL, .-IDT_BASE
771 .word 0 # offset 15:0
772 .long SYS_CODE64_SEL # selector 15:0
773 .byte 0 # 0 for interrupt gate
774 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
775 .word 0 # offset 31:16
776 .long 0 # offset 63:32
777 .long 0 # 0 for reserved
779 # device not available (INT 7)
780 .equ DEV_NOT_AVAIL_SEL, .-IDT_BASE
781 .word 0 # offset 15:0
782 .long SYS_CODE64_SEL # selector 15:0
783 .byte 0 # 0 for interrupt gate
784 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
785 .word 0 # offset 31:16
786 .long 0 # offset 63:32
787 .long 0 # 0 for reserved
789 # double fault (INT 8)
790 .equ DOUBLE_FAULT_SEL, .-IDT_BASE
791 .word 0 # offset 15:0
792 .long SYS_CODE64_SEL # selector 15:0
793 .byte 0 # 0 for interrupt gate
794 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
795 .word 0 # offset 31:16
796 .long 0 # offset 63:32
797 .long 0 # 0 for reserved
799 # Coprocessor segment overrun - reserved (INT 9)
800 .equ RSVD_INTR_SEL1, .-IDT_BASE
801 .word 0 # offset 15:0
802 .long SYS_CODE64_SEL # selector 15:0
803 .byte 0 # 0 for interrupt gate
804 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
805 .word 0 # offset 31:16
806 .long 0 # offset 63:32
807 .long 0 # 0 for reserved
809 # invalid TSS (INT 0ah)
810 .equ INVALID_TSS_SEL, .-IDT_BASE
811 .word 0 # offset 15:0
812 .long SYS_CODE64_SEL # selector 15:0
813 .byte 0 # 0 for interrupt gate
814 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
815 .word 0 # offset 31:16
816 .long 0 # offset 63:32
817 .long 0 # 0 for reserved
819 # segment not present (INT 0bh)
820 .equ SEG_NOT_PRESENT_SEL, .-IDT_BASE
821 .word 0 # offset 15:0
822 .long SYS_CODE64_SEL # selector 15:0
823 .byte 0 # 0 for interrupt gate
824 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
825 .word 0 # offset 31:16
826 .long 0 # offset 63:32
827 .long 0 # 0 for reserved
829 # stack fault (INT 0ch)
830 .equ STACK_FAULT_SEL, .-IDT_BASE
831 .word 0 # offset 15:0
832 .long SYS_CODE64_SEL # selector 15:0
833 .byte 0 # 0 for interrupt gate
834 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
835 .word 0 # offset 31:16
836 .long 0 # offset 63:32
837 .long 0 # 0 for reserved
839 # general protection (INT 0dh)
840 .equ GP_FAULT_SEL, .-IDT_BASE
841 .word 0 # offset 15:0
842 .long SYS_CODE64_SEL # selector 15:0
843 .byte 0 # 0 for interrupt gate
844 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
845 .word 0 # offset 31:16
846 .long 0 # offset 63:32
847 .long 0 # 0 for reserved
849 # page fault (INT 0eh)
850 .equ PAGE_FAULT_SEL, .-IDT_BASE
851 .word 0 # offset 15:0
852 .long SYS_CODE64_SEL # selector 15:0
853 .byte 0 # 0 for interrupt gate
854 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
855 .word 0 # offset 31:16
856 .long 0 # offset 63:32
857 .long 0 # 0 for reserved
859 # Intel reserved - do not use (INT 0fh)
860 .equ RSVD_INTR_SEL2, .-IDT_BASE
861 .word 0 # offset 15:0
862 .long SYS_CODE64_SEL # selector 15:0
863 .byte 0 # 0 for interrupt gate
864 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
865 .word 0 # offset 31:16
866 .long 0 # offset 63:32
867 .long 0 # 0 for reserved
869 # floating point error (INT 10h)
870 .equ FLT_POINT_ERR_SEL, .-IDT_BASE
871 .word 0 # offset 15:0
872 .long SYS_CODE64_SEL # selector 15:0
873 .byte 0 # 0 for interrupt gate
874 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
875 .word 0 # offset 31:16
876 .long 0 # offset 63:32
877 .long 0 # 0 for reserved
879 # alignment check (INT 11h)
880 .equ ALIGNMENT_CHECK_SEL, .-IDT_BASE
881 .word 0 # offset 15:0
882 .long SYS_CODE64_SEL # selector 15:0
883 .byte 0 # 0 for interrupt gate
884 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
885 .word 0 # offset 31:16
886 .long 0 # offset 63:32
887 .long 0 # 0 for reserved
889 # machine check (INT 12h)
890 .equ MACHINE_CHECK_SEL, .-IDT_BASE
891 .word 0 # offset 15:0
892 .long SYS_CODE64_SEL # selector 15:0
893 .byte 0 # 0 for interrupt gate
894 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
895 .word 0 # offset 31:16
896 .long 0 # offset 63:32
897 .long 0 # 0 for reserved
899 # SIMD floating-point exception (INT 13h)
900 .equ SIMD_EXCEPTION_SEL, .-IDT_BASE
901 .word 0 # offset 15:0
902 .long SYS_CODE64_SEL # selector 15:0
903 .byte 0 # 0 for interrupt gate
904 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
905 .word 0 # offset 31:16
906 .long 0 # offset 63:32
907 .long 0 # 0 for reserved
909 # 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
910 .fill 85 * 16, 1, 0 # db (85 * 16) dup(0)
912 # IRQ 0 (System timer) - (INT 68h)
913 .equ IRQ0_SEL, .-IDT_BASE
914 .word 0 # offset 15:0
915 .long SYS_CODE64_SEL # selector 15:0
916 .byte 0 # 0 for interrupt gate
917 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
918 .word 0 # offset 31:16
919 .long 0 # offset 63:32
920 .long 0 # 0 for reserved
922 # IRQ 1 (8042 Keyboard controller) - (INT 69h)
923 .equ IRQ1_SEL, .-IDT_BASE
924 .word 0 # offset 15:0
925 .long SYS_CODE64_SEL # selector 15:0
926 .byte 0 # 0 for interrupt gate
927 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
928 .word 0 # offset 31:16
929 .long 0 # offset 63:32
930 .long 0 # 0 for reserved
932 # Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
933 .equ IRQ2_SEL, .-IDT_BASE
934 .word 0 # offset 15:0
935 .long SYS_CODE64_SEL # selector 15:0
936 .byte 0 # 0 for interrupt gate
937 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
938 .word 0 # offset 31:16
939 .long 0 # offset 63:32
940 .long 0 # 0 for reserved
942 # IRQ 3 (COM 2) - (INT 6bh)
943 .equ IRQ3_SEL, .-IDT_BASE
944 .word 0 # offset 15:0
945 .long SYS_CODE64_SEL # selector 15:0
946 .byte 0 # 0 for interrupt gate
947 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
948 .word 0 # offset 31:16
949 .long 0 # offset 63:32
950 .long 0 # 0 for reserved
952 # IRQ 4 (COM 1) - (INT 6ch)
953 .equ IRQ4_SEL, .-IDT_BASE
954 .word 0 # offset 15:0
955 .long SYS_CODE64_SEL # selector 15:0
956 .byte 0 # 0 for interrupt gate
957 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
958 .word 0 # offset 31:16
959 .long 0 # offset 63:32
960 .long 0 # 0 for reserved
962 # IRQ 5 (LPT 2) - (INT 6dh)
963 .equ IRQ5_SEL, .-IDT_BASE
964 .word 0 # offset 15:0
965 .long SYS_CODE64_SEL # selector 15:0
966 .byte 0 # 0 for interrupt gate
967 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
968 .word 0 # offset 31:16
969 .long 0 # offset 63:32
970 .long 0 # 0 for reserved
972 # IRQ 6 (Floppy controller) - (INT 6eh)
973 .equ IRQ6_SEL, .-IDT_BASE
974 .word 0 # offset 15:0
975 .long SYS_CODE64_SEL # selector 15:0
976 .byte 0 # 0 for interrupt gate
977 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
978 .word 0 # offset 31:16
979 .long 0 # offset 63:32
980 .long 0 # 0 for reserved
982 # IRQ 7 (LPT 1) - (INT 6fh)
983 .equ IRQ7_SEL, .-IDT_BASE
984 .word 0 # offset 15:0
985 .long SYS_CODE64_SEL # selector 15:0
986 .byte 0 # 0 for interrupt gate
987 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
988 .word 0 # offset 31:16
989 .long 0 # offset 63:32
990 .long 0 # 0 for reserved
992 # IRQ 8 (RTC Alarm) - (INT 70h)
993 .equ IRQ8_SEL, .-IDT_BASE
994 .word 0 # offset 15:0
995 .long SYS_CODE64_SEL # selector 15:0
996 .byte 0 # 0 for interrupt gate
997 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
998 .word 0 # offset 31:16
999 .long 0 # offset 63:32
1000 .long 0 # 0 for reserved
1003 .equ IRQ9_SEL, .-IDT_BASE
1004 .word 0 # offset 15:0
1005 .long SYS_CODE64_SEL # selector 15:0
1006 .byte 0 # 0 for interrupt gate
1007 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1008 .word 0 # offset 31:16
1009 .long 0 # offset 63:32
1010 .long 0 # 0 for reserved
1012 # IRQ 10 - (INT 72h)
1013 .equ IRQ10_SEL, .-IDT_BASE
1014 .word 0 # offset 15:0
1015 .long SYS_CODE64_SEL # selector 15:0
1016 .byte 0 # 0 for interrupt gate
1017 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1018 .word 0 # offset 31:16
1019 .long 0 # offset 63:32
1020 .long 0 # 0 for reserved
1022 # IRQ 11 - (INT 73h)
1023 .equ IRQ11_SEL, .-IDT_BASE
1024 .word 0 # offset 15:0
1025 .long SYS_CODE64_SEL # selector 15:0
1026 .byte 0 # 0 for interrupt gate
1027 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1028 .word 0 # offset 31:16
1029 .long 0 # offset 63:32
1030 .long 0 # 0 for reserved
1032 # IRQ 12 (PS/2 mouse) - (INT 74h)
1033 .equ IRQ12_SEL, .-IDT_BASE
1034 .word 0 # offset 15:0
1035 .long SYS_CODE64_SEL # selector 15:0
1036 .byte 0 # 0 for interrupt gate
1037 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1038 .word 0 # offset 31:16
1039 .long 0 # offset 63:32
1040 .long 0 # 0 for reserved
1042 # IRQ 13 (Floating point error) - (INT 75h)
1043 .equ IRQ13_SEL, .-IDT_BASE
1044 .word 0 # offset 15:0
1045 .long SYS_CODE64_SEL # selector 15:0
1046 .byte 0 # 0 for interrupt gate
1047 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1048 .word 0 # offset 31:16
1049 .long 0 # offset 63:32
1050 .long 0 # 0 for reserved
1052 # IRQ 14 (Secondary IDE) - (INT 76h)
1053 .equ IRQ14_SEL, .-IDT_BASE
1054 .word 0 # offset 15:0
1055 .long SYS_CODE64_SEL # selector 15:0
1056 .byte 0 # 0 for interrupt gate
1057 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1058 .word 0 # offset 31:16
1059 .long 0 # offset 63:32
1060 .long 0 # 0 for reserved
1062 # IRQ 15 (Primary IDE) - (INT 77h)
1063 .equ IRQ15_SEL, .-IDT_BASE
1064 .word 0 # offset 15:0
1065 .long SYS_CODE64_SEL # selector 15:0
1066 .byte 0 # 0 for interrupt gate
1067 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1068 .word 0 # offset 31:16
1069 .long 0 # offset 63:32
1070 .long 0 # 0 for reserved
1076 MemoryMapSize: .long 0
1077 MemoryMap: .long 0,0,0,0,0,0,0,0
1078 .long 0,0,0,0,0,0,0,0
1079 .long 0,0,0,0,0,0,0,0
1080 .long 0,0,0,0,0,0,0,0
1081 .long 0,0,0,0,0,0,0,0
1082 .long 0,0,0,0,0,0,0,0
1083 .long 0,0,0,0,0,0,0,0
1084 .long 0,0,0,0,0,0,0,0
1085 .long 0,0,0,0,0,0,0,0
1086 .long 0,0,0,0,0,0,0,0
1087 .long 0,0,0,0,0,0,0,0
1088 .long 0,0,0,0,0,0,0,0
1089 .long 0,0,0,0,0,0,0,0
1090 .long 0,0,0,0,0,0,0,0
1091 .long 0,0,0,0,0,0,0,0
1092 .long 0,0,0,0,0,0,0,0
1093 .long 0,0,0,0,0,0,0,0
1094 .long 0,0,0,0,0,0,0,0
1095 .long 0,0,0,0,0,0,0,0
1096 .long 0,0,0,0,0,0,0,0
1097 .long 0,0,0,0,0,0,0,0
1098 .long 0,0,0,0,0,0,0,0
1099 .long 0,0,0,0,0,0,0,0
1100 .long 0,0,0,0,0,0,0,0
1101 .long 0,0,0,0,0,0,0,0
1102 .long 0,0,0,0,0,0,0,0
1103 .long 0,0,0,0,0,0,0,0
1104 .long 0,0,0,0,0,0,0,0
1105 .long 0,0,0,0,0,0,0,0
1106 .long 0,0,0,0,0,0,0,0
1108 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1109 .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1113 # below is the pieces of the IVT that is used to redirect INT 68h - 6fh
1114 # back to INT 08h - 0fh when in real mode... It is 'org'ed to a
1115 # known low address (20f00) so it can be set up by PlMapIrqToVect in