1 ;------------------------------------------------------------------------------
3 ;* Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>
4 ;* 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 FAT_DIRECTORY_ENTRY_SIZE EQU 020h
24 FAT_DIRECTORY_ENTRY_SHIFT EQU 5
31 jmp BootSectorEntryPoint ; JMP inst - 3 bytes
34 OemId db "INTEL " ; OemId - 8 bytes
36 SectorSize dw 0 ; Sector Size - 16 bits
37 SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits
38 ReservedSectors dw 0 ; Reserved Sectors - 16 bits
39 NoFats db 0 ; Number of FATs - 8 bits
40 RootEntries dw 0 ; Root Entries - 16 bits
41 Sectors dw 0 ; Number of Sectors - 16 bits
42 Media db 0 ; Media - 8 bits - ignored
43 SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits
44 SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored
45 Heads dw 0 ; Heads - 16 bits - ignored
46 HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored
47 LargeSectors dd 0 ; Large Sectors - 32 bits
48 PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored
49 CurrentHead db 0 ; Current Head - 8 bits
50 Signature db 0 ; Signature - 8 bits - ignored
51 VolId db " " ; Volume Serial Number- 4 bytes
52 FatLabel db " " ; Label - 11 bytes
53 SystemId db "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
77 mov byte ptr es:[4],al
82 cmp dword ptr ds:[di+2], 04000h
88 mov byte ptr es:[4],al
98 mov ax,word ptr [bp+VolId]
99 mov word ptr es:[0],ax ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
100 mov ax,word ptr [bp+VolId+2]
101 mov word ptr es:[2],ax
105 ; cx = Start Cluster of Efildr -> BS.com has filled already
106 ; ES:DI = 2000:0, first cluster will be read again
112 mov word ptr cs:[JumpSegment],ax
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 mov si,1 ; NumberOfClusters = 1
155 push cx ; Push Start Cluster onto stack
156 mov dx,0fffh ; CachedFatSectorNumber = 0xfff
158 mov ax,cx ; ax = ClusterNumber
159 and ax,0ff8h ; ax = ax & 0xff8
160 cmp ax,0ff8h ; See if this is the last cluster
161 je FoundLastCluster ; Jump if last cluster found
162 mov ax,cx ; ax = ClusterNumber
163 shl ax,1 ; ax = ClusterNumber * 2
164 add ax,cx ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
165 shr ax,1 ; FatOffset = ClusterNumber*3 / 2
167 mov si,ax ; si = FatOffset
168 shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
169 add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
170 and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
171 cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
177 call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
179 mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
181 mov bx,word ptr [si] ; bx = NextClusterNumber
182 mov ax,cx ; ax = ClusterNumber
183 and ax,1 ; See if this is an odd cluster number
185 shr bx,4 ; NextClusterNumber = NextClusterNumber >> 4
187 and bx,0fffh ; Strip upper 4 bits of NextClusterNumber
189 dec bx ; bx = NextClusterNumber - 1
190 cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
192 inc bx ; bx = NextClusterNumber
193 inc si ; NumberOfClusters++
194 mov cx,bx ; ClusterNumber = NextClusterNumber
198 pop ax ; ax = StartCluster
199 push bx ; StartCluster = NextClusterNumber
200 mov cx,bx ; ClusterNumber = NextClusterNumber
201 sub ax,2 ; ax = StartCluster - 2
203 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
204 mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
205 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
206 push ax ; save start sector
207 mov ax,si ; ax = NumberOfClusters
208 mul bx ; ax = NumberOfClusters * SectorsPerCluster
209 mov bx,ax ; bx = Number of Sectors
210 pop ax ; ax = Start Sector
212 mov si,1 ; 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 add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
235 add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
236 mov esi,eax ; esi = Start LBA
237 mov cx,bx ; cx = Number of blocks to read
239 mov bp,07bfch ; bp = 0x7bfc
240 mov eax,esi ; eax = Start LBA
241 xor edx,edx ; edx = 0
242 movzx ebx,word ptr [bp] ; bx = MaxSector
243 div ebx ; ax = StartLBA / MaxSector
244 inc dx ; dx = (StartLBA % MaxSector) + 1
246 mov bx,word ptr [bp] ; bx = MaxSector
247 sub bx,dx ; bx = MaxSector - Sector
248 inc bx ; bx = MaxSector - Sector + 1
249 cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
251 mov bx,cx ; bx = Blocks
255 shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
256 and ax,07fh ; ax = Number of blocks into current seg
257 add ax,bx ; ax = End Block number of transfer
258 cmp ax,080h ; See if it crosses a 64K boundry
259 jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
260 sub ax,080h ; ax = Number of blocks past 64K boundry
261 sub bx,ax ; Decrease transfer size by block overage
262 NotCrossing64KBoundry:
266 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
268 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
269 ; dx = ax % (MaxHead + 1) = Head
271 push bx ; Save number of blocks to transfer
272 mov dh,dl ; dh = Head
273 mov bp,07c00h ; bp = 0x7c00
274 mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
275 mov ch,al ; ch = Cylinder
276 mov al,bl ; al = Blocks
277 mov ah,2 ; ah = Function 2
278 mov bx,di ; es:bx = Buffer address
284 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
285 sub cx,bx ; Blocks = Blocks - NumberOfBlocks
287 shl bx,(BLOCK_SHIFT-4)
289 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
298 lea si, [ErrorString]
300 jmp PrintStringAndHalt
311 db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
314 LBAOffsetForBootSector:
320 ;******************************************************************************
321 ;******************************************************************************
322 ;******************************************************************************
324 DELAY_PORT equ 0edh ; Port to use for 1uS delay
325 KBD_CONTROL_PORT equ 060h ; 8042 control port
326 KBD_STATUS_PORT equ 064h ; 8042 status port
327 WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
328 ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
333 db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch
344 ; mov byte ptr es:[160],'a'
362 sub edi,eax ; Get the address of the memory map
363 mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
366 mov bx,cs ; BX=segment
367 shl ebx,4 ; BX="linear" address of segment base
368 lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
369 mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
370 lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
371 mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
372 lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
376 ; mov byte ptr es:[162],'b'
384 mov ax,2401h ; Enable A20 Gate
386 jnc A20GateEnabled ; Jump if it suceeded
389 ; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
392 call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
393 jnz Timeout8042 ; Jump if the 8042 timed out
394 out DELAY_PORT,ax ; Delay 1 uS
395 mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
396 out KBD_STATUS_PORT,al ; Send command to the 8042
397 call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
398 jnz Timeout8042 ; Jump if the 8042 timed out
399 mov al,ENABLE_A20_CMD ; gate address bit 20 on
400 out KBD_CONTROL_PORT,al ; Send command to thre 8042
401 call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
402 mov cx,25 ; Delay 25 uS for the command to complete on the 8042
404 out DELAY_PORT,ax ; Delay 1 uS
412 ; DISABLE INTERRUPTS - Entering Protected Mode
419 ; mov byte ptr es:[164],'c'
423 lea eax, OffsetIn32BitProtectedMode
425 mov dword ptr[OffsetIn32BitProtectedMode], eax
427 lea eax, OffsetInLongMode
429 mov dword ptr[OffsetInLongMode], eax
435 lgdt fword ptr [gdtr]
438 ; Enable Protect Mode (set CR0.PE=1)
440 mov eax, cr0 ; Read CR0.
441 or eax, 1h ; Set PE=1
442 mov cr0, eax ; Write CR0.
444 db 0eah ; jmp far 16:32
445 OffsetIn32BitProtectedMode:
446 dd 00000000h ; offset $+8 (In32BitProtectedMode)
447 dw 10h ; selector (flat CS)
448 In32BitProtectedMode:
460 ; Enable the 64-bit page-translation-table entries by
461 ; setting CR4.PAE=1 (this is _required_ before activating
462 ; long mode). Paging is not enabled until after long mode
476 ; This is the Trapolean Page Tables that are guarenteed
480 ; 10000 ~ 12000 - efildr (loaded)
481 ; 20000 ~ 21000 - start64.com
482 ; 21000 ~ 22000 - efi64.com
483 ; 22000 ~ 90000 - efildr
484 ; 90000 ~ 96000 - 4G pagetable (will be reload later)
492 ; Enable long mode (set EFER.LME=1).
496 ; mov ecx, 0c0000080h ; EFER MSR number.
504 ; bts eax, 8 ; Set LME=1.
507 ; wrmsr ; Write EFER.
510 ; Enable paging to activate long mode (set CR0.PG=1)
512 mov eax, cr0 ; Read CR0.
517 ; bts eax, 31 ; Set PG=1.
518 mov cr0, eax ; Write CR0.
523 db 0eah ; Far Jump $+9:Selector to reload CS
525 dd 00000000 ; $+9 Offset is ensuing instruction boundary
526 dw 038h ; Selector is our code selector, 38h
541 ; mov ebp,000400000h ; Destination of EFILDR32
544 ; mov ebx,000070000h ; Length of copy
563 ; lidt fword ptr [rax]
576 Empty8042InputBuffer:
579 out DELAY_PORT,ax ; Delay 1us
580 in al,KBD_STATUS_PORT ; Read the 8042 Status Port
581 and al,02h ; Check the Input Buffer Full Flag
582 loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
585 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
587 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
591 gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
592 dd 0 ; (GDT base gets set above)
593 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
594 ; global descriptor table (GDT)
595 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
602 NULL_SEL equ $-GDT_BASE ; Selector [0x0]
607 db 0 ; limit 19:16, flags
610 ; linear data segment descriptor
611 LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
612 dw 0FFFFh ; limit 0xFFFFF
615 db 092h ; present, ring 0, data, expand-up, writable
616 db 0CFh ; page-granular, 32-bit
619 ; linear code segment descriptor
620 LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
621 dw 0FFFFh ; limit 0xFFFFF
624 db 09Ah ; present, ring 0, data, expand-up, writable
625 db 0CFh ; page-granular, 32-bit
628 ; system data segment descriptor
629 SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
630 dw 0FFFFh ; limit 0xFFFFF
633 db 092h ; present, ring 0, data, expand-up, writable
634 db 0CFh ; page-granular, 32-bit
637 ; system code segment descriptor
638 SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
639 dw 0FFFFh ; limit 0xFFFFF
642 db 09Ah ; present, ring 0, data, expand-up, writable
643 db 0CFh ; page-granular, 32-bit
646 ; spare segment descriptor
647 SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
651 db 0 ; present, ring 0, data, expand-up, writable
652 db 0 ; page-granular, 32-bit
656 ; system data segment descriptor
658 SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
659 dw 0FFFFh ; limit 0xFFFFF
662 db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
663 db 0CFh ; G | D | L | AVL | Segment [19..16]
667 ; system code segment descriptor
669 SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
670 dw 0FFFFh ; limit 0xFFFFF
673 db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
674 db 0AFh ; G | D | L | AVL | Segment [19..16]
677 ; spare segment descriptor
678 SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
682 db 0 ; present, ring 0, data, expand-up, writable
683 db 0 ; page-granular, 32-bit
692 idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
693 dq 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 DIV_ZERO_SEL equ $-IDT_BASE
712 dw SYS_CODE64_SEL ; selector 15:0
713 db 0 ; 0 for interrupt gate
714 db 0eh OR 80h ; type = 386 interrupt gate, present
717 dd 0 ; 0 for reserved
719 ; debug exception (INT 1)
720 DEBUG_EXCEPT_SEL equ $-IDT_BASE
722 dw SYS_CODE64_SEL ; selector 15:0
723 db 0 ; 0 for interrupt gate
724 db 0eh OR 80h ; type = 386 interrupt gate, present
727 dd 0 ; 0 for reserved
730 NMI_SEL equ $-IDT_BASE
732 dw SYS_CODE64_SEL ; selector 15:0
733 db 0 ; 0 for interrupt gate
734 db 0eh OR 80h ; type = 386 interrupt gate, present
737 dd 0 ; 0 for reserved
739 ; soft breakpoint (INT 3)
740 BREAKPOINT_SEL equ $-IDT_BASE
742 dw SYS_CODE64_SEL ; selector 15:0
743 db 0 ; 0 for interrupt gate
744 db 0eh OR 80h ; type = 386 interrupt gate, present
747 dd 0 ; 0 for reserved
750 OVERFLOW_SEL equ $-IDT_BASE
752 dw SYS_CODE64_SEL ; selector 15:0
753 db 0 ; 0 for interrupt gate
754 db 0eh OR 80h ; type = 386 interrupt gate, present
757 dd 0 ; 0 for reserved
759 ; bounds check (INT 5)
760 BOUNDS_CHECK_SEL equ $-IDT_BASE
762 dw SYS_CODE64_SEL ; selector 15:0
763 db 0 ; 0 for interrupt gate
764 db 0eh OR 80h ; type = 386 interrupt gate, present
767 dd 0 ; 0 for reserved
769 ; invalid opcode (INT 6)
770 INVALID_OPCODE_SEL equ $-IDT_BASE
772 dw SYS_CODE64_SEL ; selector 15:0
773 db 0 ; 0 for interrupt gate
774 db 0eh OR 80h ; type = 386 interrupt gate, present
777 dd 0 ; 0 for reserved
779 ; device not available (INT 7)
780 DEV_NOT_AVAIL_SEL equ $-IDT_BASE
782 dw SYS_CODE64_SEL ; selector 15:0
783 db 0 ; 0 for interrupt gate
784 db 0eh OR 80h ; type = 386 interrupt gate, present
787 dd 0 ; 0 for reserved
789 ; double fault (INT 8)
790 DOUBLE_FAULT_SEL equ $-IDT_BASE
792 dw SYS_CODE64_SEL ; selector 15:0
793 db 0 ; 0 for interrupt gate
794 db 0eh OR 80h ; type = 386 interrupt gate, present
797 dd 0 ; 0 for reserved
799 ; Coprocessor segment overrun - reserved (INT 9)
800 RSVD_INTR_SEL1 equ $-IDT_BASE
802 dw SYS_CODE64_SEL ; selector 15:0
803 db 0 ; 0 for interrupt gate
804 db 0eh OR 80h ; type = 386 interrupt gate, present
807 dd 0 ; 0 for reserved
809 ; invalid TSS (INT 0ah)
810 INVALID_TSS_SEL equ $-IDT_BASE
812 dw SYS_CODE64_SEL ; selector 15:0
813 db 0 ; 0 for interrupt gate
814 db 0eh OR 80h ; type = 386 interrupt gate, present
817 dd 0 ; 0 for reserved
819 ; segment not present (INT 0bh)
820 SEG_NOT_PRESENT_SEL equ $-IDT_BASE
822 dw SYS_CODE64_SEL ; selector 15:0
823 db 0 ; 0 for interrupt gate
824 db 0eh OR 80h ; type = 386 interrupt gate, present
827 dd 0 ; 0 for reserved
829 ; stack fault (INT 0ch)
830 STACK_FAULT_SEL equ $-IDT_BASE
832 dw SYS_CODE64_SEL ; selector 15:0
833 db 0 ; 0 for interrupt gate
834 db 0eh OR 80h ; type = 386 interrupt gate, present
837 dd 0 ; 0 for reserved
839 ; general protection (INT 0dh)
840 GP_FAULT_SEL equ $-IDT_BASE
842 dw SYS_CODE64_SEL ; selector 15:0
843 db 0 ; 0 for interrupt gate
844 db 0eh OR 80h ; type = 386 interrupt gate, present
847 dd 0 ; 0 for reserved
849 ; page fault (INT 0eh)
850 PAGE_FAULT_SEL equ $-IDT_BASE
852 dw SYS_CODE64_SEL ; selector 15:0
853 db 0 ; 0 for interrupt gate
854 db 0eh OR 80h ; type = 386 interrupt gate, present
857 dd 0 ; 0 for reserved
859 ; Intel reserved - do not use (INT 0fh)
860 RSVD_INTR_SEL2 equ $-IDT_BASE
862 dw SYS_CODE64_SEL ; selector 15:0
863 db 0 ; 0 for interrupt gate
864 db 0eh OR 80h ; type = 386 interrupt gate, present
867 dd 0 ; 0 for reserved
869 ; floating point error (INT 10h)
870 FLT_POINT_ERR_SEL equ $-IDT_BASE
872 dw SYS_CODE64_SEL ; selector 15:0
873 db 0 ; 0 for interrupt gate
874 db 0eh OR 80h ; type = 386 interrupt gate, present
877 dd 0 ; 0 for reserved
879 ; alignment check (INT 11h)
880 ALIGNMENT_CHECK_SEL equ $-IDT_BASE
882 dw SYS_CODE64_SEL ; selector 15:0
883 db 0 ; 0 for interrupt gate
884 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
887 dd 0 ; 0 for reserved
889 ; machine check (INT 12h)
890 MACHINE_CHECK_SEL equ $-IDT_BASE
892 dw SYS_CODE64_SEL ; selector 15:0
893 db 0 ; 0 for interrupt gate
894 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
897 dd 0 ; 0 for reserved
899 ; SIMD floating-point exception (INT 13h)
900 SIMD_EXCEPTION_SEL equ $-IDT_BASE
902 dw SYS_CODE64_SEL ; selector 15:0
903 db 0 ; 0 for interrupt gate
904 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
907 dd 0 ; 0 for reserved
909 ; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
912 ; IRQ 0 (System timer) - (INT 68h)
913 IRQ0_SEL equ $-IDT_BASE
915 dw SYS_CODE64_SEL ; selector 15:0
916 db 0 ; 0 for interrupt gate
917 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
920 dd 0 ; 0 for reserved
922 ; IRQ 1 (8042 Keyboard controller) - (INT 69h)
923 IRQ1_SEL equ $-IDT_BASE
925 dw SYS_CODE64_SEL ; selector 15:0
926 db 0 ; 0 for interrupt gate
927 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
930 dd 0 ; 0 for reserved
932 ; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
933 IRQ2_SEL equ $-IDT_BASE
935 dw SYS_CODE64_SEL ; selector 15:0
936 db 0 ; 0 for interrupt gate
937 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
940 dd 0 ; 0 for reserved
942 ; IRQ 3 (COM 2) - (INT 6bh)
943 IRQ3_SEL equ $-IDT_BASE
945 dw SYS_CODE64_SEL ; selector 15:0
946 db 0 ; 0 for interrupt gate
947 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
950 dd 0 ; 0 for reserved
952 ; IRQ 4 (COM 1) - (INT 6ch)
953 IRQ4_SEL equ $-IDT_BASE
955 dw SYS_CODE64_SEL ; selector 15:0
956 db 0 ; 0 for interrupt gate
957 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
960 dd 0 ; 0 for reserved
962 ; IRQ 5 (LPT 2) - (INT 6dh)
963 IRQ5_SEL equ $-IDT_BASE
965 dw SYS_CODE64_SEL ; selector 15:0
966 db 0 ; 0 for interrupt gate
967 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
970 dd 0 ; 0 for reserved
972 ; IRQ 6 (Floppy controller) - (INT 6eh)
973 IRQ6_SEL equ $-IDT_BASE
975 dw SYS_CODE64_SEL ; selector 15:0
976 db 0 ; 0 for interrupt gate
977 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
980 dd 0 ; 0 for reserved
982 ; IRQ 7 (LPT 1) - (INT 6fh)
983 IRQ7_SEL equ $-IDT_BASE
985 dw SYS_CODE64_SEL ; selector 15:0
986 db 0 ; 0 for interrupt gate
987 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
990 dd 0 ; 0 for reserved
992 ; IRQ 8 (RTC Alarm) - (INT 70h)
993 IRQ8_SEL equ $-IDT_BASE
995 dw SYS_CODE64_SEL ; selector 15:0
996 db 0 ; 0 for interrupt gate
997 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1000 dd 0 ; 0 for reserved
1003 IRQ9_SEL equ $-IDT_BASE
1005 dw SYS_CODE64_SEL ; selector 15:0
1006 db 0 ; 0 for interrupt gate
1007 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1010 dd 0 ; 0 for reserved
1012 ; IRQ 10 - (INT 72h)
1013 IRQ10_SEL equ $-IDT_BASE
1015 dw SYS_CODE64_SEL ; selector 15:0
1016 db 0 ; 0 for interrupt gate
1017 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1020 dd 0 ; 0 for reserved
1022 ; IRQ 11 - (INT 73h)
1023 IRQ11_SEL equ $-IDT_BASE
1025 dw SYS_CODE64_SEL ; selector 15:0
1026 db 0 ; 0 for interrupt gate
1027 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1030 dd 0 ; 0 for reserved
1032 ; IRQ 12 (PS/2 mouse) - (INT 74h)
1033 IRQ12_SEL equ $-IDT_BASE
1035 dw SYS_CODE64_SEL ; selector 15:0
1036 db 0 ; 0 for interrupt gate
1037 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1040 dd 0 ; 0 for reserved
1042 ; IRQ 13 (Floating point error) - (INT 75h)
1043 IRQ13_SEL equ $-IDT_BASE
1045 dw SYS_CODE64_SEL ; selector 15:0
1046 db 0 ; 0 for interrupt gate
1047 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1050 dd 0 ; 0 for reserved
1052 ; IRQ 14 (Secondary IDE) - (INT 76h)
1053 IRQ14_SEL equ $-IDT_BASE
1055 dw SYS_CODE64_SEL ; selector 15:0
1056 db 0 ; 0 for interrupt gate
1057 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1060 dd 0 ; 0 for reserved
1062 ; IRQ 15 (Primary IDE) - (INT 77h)
1063 IRQ15_SEL equ $-IDT_BASE
1065 dw SYS_CODE64_SEL ; selector 15:0
1066 db 0 ; 0 for interrupt gate
1067 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1070 dd 0 ; 0 for reserved
1077 MemoryMap dd 0,0,0,0,0,0,0,0
1108 dd 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 dd 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