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 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 "FAT16 " ; 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,0fff8h ; ax = ax & 0xfff8
160 cmp ax,0fff8h ; 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 ; FatOffset = ClusterNumber * 2
165 mov si,ax ; si = FatOffset
166 shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
167 add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
168 and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
169 cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
175 call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
177 mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
179 mov bx,word ptr [si] ; bx = NextClusterNumber
180 mov ax,cx ; ax = ClusterNumber
182 dec bx ; bx = NextClusterNumber - 1
183 cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
185 inc bx ; bx = NextClusterNumber
186 inc si ; NumberOfClusters++
187 mov cx,bx ; ClusterNumber = NextClusterNumber
191 pop ax ; ax = StartCluster
192 push bx ; StartCluster = NextClusterNumber
193 mov cx,bx ; ClusterNumber = NextClusterNumber
194 sub ax,2 ; ax = StartCluster - 2
196 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
197 mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
198 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
199 push ax ; save start sector
200 mov ax,si ; ax = NumberOfClusters
201 mul bx ; ax = NumberOfClusters * SectorsPerCluster
202 mov bx,ax ; bx = Number of Sectors
203 pop ax ; ax = Start Sector
205 mov si,1 ; NumberOfClusters = 1
213 ; ****************************************************************************
214 ; ReadBlocks - Reads a set of blocks from a block device
217 ; BX = Number of Blocks to Read
218 ; ES:DI = Buffer to store sectors read from disk
219 ; ****************************************************************************
222 ; bx = NumberOfBlocks
227 add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
228 add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
229 mov esi,eax ; esi = Start LBA
230 mov cx,bx ; cx = Number of blocks to read
232 mov bp,07bfch ; bp = 0x7bfc
233 mov eax,esi ; eax = Start LBA
234 xor edx,edx ; edx = 0
235 movzx ebx,word ptr [bp] ; bx = MaxSector
236 div ebx ; ax = StartLBA / MaxSector
237 inc dx ; dx = (StartLBA % MaxSector) + 1
239 mov bx,word ptr [bp] ; bx = MaxSector
240 sub bx,dx ; bx = MaxSector - Sector
241 inc bx ; bx = MaxSector - Sector + 1
242 cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
244 mov bx,cx ; bx = Blocks
248 shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
249 and ax,07fh ; ax = Number of blocks into current seg
250 add ax,bx ; ax = End Block number of transfer
251 cmp ax,080h ; See if it crosses a 64K boundry
252 jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
253 sub ax,080h ; ax = Number of blocks past 64K boundry
254 sub bx,ax ; Decrease transfer size by block overage
255 NotCrossing64KBoundry:
259 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
261 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
262 ; dx = ax % (MaxHead + 1) = Head
264 push bx ; Save number of blocks to transfer
265 mov dh,dl ; dh = Head
266 mov bp,07c00h ; bp = 0x7c00
267 mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
268 mov ch,al ; ch = Cylinder
269 mov al,bl ; al = Blocks
270 mov ah,2 ; ah = Function 2
271 mov bx,di ; es:bx = Buffer address
277 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
278 sub cx,bx ; Blocks = Blocks - NumberOfBlocks
280 shl bx,(BLOCK_SHIFT-4)
282 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
291 lea si, [ErrorString]
293 jmp PrintStringAndHalt
304 db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
307 LBAOffsetForBootSector:
313 ;******************************************************************************
314 ;******************************************************************************
315 ;******************************************************************************
317 DELAY_PORT equ 0edh ; Port to use for 1uS delay
318 KBD_CONTROL_PORT equ 060h ; 8042 control port
319 KBD_STATUS_PORT equ 064h ; 8042 status port
320 WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
321 ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
326 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
337 ; mov byte ptr es:[160],'a'
355 sub edi,eax ; Get the address of the memory map
356 mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
359 mov bx,cs ; BX=segment
360 shl ebx,4 ; BX="linear" address of segment base
361 lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
362 mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
363 lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
364 mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
365 lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
369 ; mov byte ptr es:[162],'b'
377 mov ax,2401h ; Enable A20 Gate
379 jnc A20GateEnabled ; Jump if it suceeded
382 ; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
385 call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
386 jnz Timeout8042 ; Jump if the 8042 timed out
387 out DELAY_PORT,ax ; Delay 1 uS
388 mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
389 out KBD_STATUS_PORT,al ; Send command to the 8042
390 call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
391 jnz Timeout8042 ; Jump if the 8042 timed out
392 mov al,ENABLE_A20_CMD ; gate address bit 20 on
393 out KBD_CONTROL_PORT,al ; Send command to thre 8042
394 call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
395 mov cx,25 ; Delay 25 uS for the command to complete on the 8042
397 out DELAY_PORT,ax ; Delay 1 uS
405 ; DISABLE INTERRUPTS - Entering Protected Mode
412 ; mov byte ptr es:[164],'c'
416 lea eax, OffsetIn32BitProtectedMode
418 mov dword ptr[OffsetIn32BitProtectedMode], eax
420 lea eax, OffsetInLongMode
422 mov dword ptr[OffsetInLongMode], eax
428 lgdt fword ptr [gdtr]
431 ; Enable Protect Mode (set CR0.PE=1)
433 mov eax, cr0 ; Read CR0.
434 or eax, 1h ; Set PE=1
435 mov cr0, eax ; Write CR0.
437 db 0eah ; jmp far 16:32
438 OffsetIn32BitProtectedMode:
439 dd 00000000h ; offset $+8 (In32BitProtectedMode)
440 dw 10h ; selector (flat CS)
441 In32BitProtectedMode:
453 ; Enable the 64-bit page-translation-table entries by
454 ; setting CR4.PAE=1 (this is _required_ before activating
455 ; long mode). Paging is not enabled until after long mode
469 ; This is the Trapolean Page Tables that are guarenteed
473 ; 10000 ~ 12000 - efildr (loaded)
474 ; 20000 ~ 21000 - start64.com
475 ; 21000 ~ 22000 - efi64.com
476 ; 22000 ~ 90000 - efildr
477 ; 90000 ~ 96000 - 4G pagetable (will be reload later)
485 ; Enable long mode (set EFER.LME=1).
489 ; mov ecx, 0c0000080h ; EFER MSR number.
497 ; bts eax, 8 ; Set LME=1.
500 ; wrmsr ; Write EFER.
503 ; Enable paging to activate long mode (set CR0.PG=1)
505 mov eax, cr0 ; Read CR0.
510 ; bts eax, 31 ; Set PG=1.
511 mov cr0, eax ; Write CR0.
516 db 0eah ; Far Jump $+9:Selector to reload CS
518 dd 00000000 ; $+9 Offset is ensuing instruction boundary
519 dw 038h ; Selector is our code selector, 38h
534 ; mov ebp,000400000h ; Destination of EFILDR32
537 ; mov ebx,000070000h ; Length of copy
556 ; lidt fword ptr [rax]
569 Empty8042InputBuffer:
572 out DELAY_PORT,ax ; Delay 1us
573 in al,KBD_STATUS_PORT ; Read the 8042 Status Port
574 and al,02h ; Check the Input Buffer Full Flag
575 loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
578 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
580 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
584 gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
585 dd 0 ; (GDT base gets set above)
586 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
587 ; global descriptor table (GDT)
588 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
595 NULL_SEL equ $-GDT_BASE ; Selector [0x0]
600 db 0 ; limit 19:16, flags
603 ; linear data segment descriptor
604 LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
605 dw 0FFFFh ; limit 0xFFFFF
608 db 092h ; present, ring 0, data, expand-up, writable
609 db 0CFh ; page-granular, 32-bit
612 ; linear code segment descriptor
613 LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
614 dw 0FFFFh ; limit 0xFFFFF
617 db 09Ah ; present, ring 0, data, expand-up, writable
618 db 0CFh ; page-granular, 32-bit
621 ; system data segment descriptor
622 SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
623 dw 0FFFFh ; limit 0xFFFFF
626 db 092h ; present, ring 0, data, expand-up, writable
627 db 0CFh ; page-granular, 32-bit
630 ; system code segment descriptor
631 SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]
632 dw 0FFFFh ; limit 0xFFFFF
635 db 09Ah ; present, ring 0, data, expand-up, writable
636 db 0CFh ; page-granular, 32-bit
639 ; spare segment descriptor
640 SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]
644 db 0 ; present, ring 0, data, expand-up, writable
645 db 0 ; page-granular, 32-bit
649 ; system data segment descriptor
651 SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]
652 dw 0FFFFh ; limit 0xFFFFF
655 db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A
656 db 0CFh ; G | D | L | AVL | Segment [19..16]
660 ; system code segment descriptor
662 SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]
663 dw 0FFFFh ; limit 0xFFFFF
666 db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A
667 db 0AFh ; G | D | L | AVL | Segment [19..16]
670 ; spare segment descriptor
671 SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]
675 db 0 ; present, ring 0, data, expand-up, writable
676 db 0 ; page-granular, 32-bit
685 idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
686 dq 0 ; (IDT base gets set above)
688 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
689 ; interrupt descriptor table (IDT)
691 ; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
692 ; mappings. This implementation only uses the system timer and all other
693 ; IRQs will remain masked. The descriptors for vectors 33+ are provided
695 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
702 ; divide by zero (INT 0)
703 DIV_ZERO_SEL equ $-IDT_BASE
705 dw SYS_CODE64_SEL ; selector 15:0
706 db 0 ; 0 for interrupt gate
707 db 0eh OR 80h ; type = 386 interrupt gate, present
710 dd 0 ; 0 for reserved
712 ; debug exception (INT 1)
713 DEBUG_EXCEPT_SEL equ $-IDT_BASE
715 dw SYS_CODE64_SEL ; selector 15:0
716 db 0 ; 0 for interrupt gate
717 db 0eh OR 80h ; type = 386 interrupt gate, present
720 dd 0 ; 0 for reserved
723 NMI_SEL equ $-IDT_BASE
725 dw SYS_CODE64_SEL ; selector 15:0
726 db 0 ; 0 for interrupt gate
727 db 0eh OR 80h ; type = 386 interrupt gate, present
730 dd 0 ; 0 for reserved
732 ; soft breakpoint (INT 3)
733 BREAKPOINT_SEL equ $-IDT_BASE
735 dw SYS_CODE64_SEL ; selector 15:0
736 db 0 ; 0 for interrupt gate
737 db 0eh OR 80h ; type = 386 interrupt gate, present
740 dd 0 ; 0 for reserved
743 OVERFLOW_SEL equ $-IDT_BASE
745 dw SYS_CODE64_SEL ; selector 15:0
746 db 0 ; 0 for interrupt gate
747 db 0eh OR 80h ; type = 386 interrupt gate, present
750 dd 0 ; 0 for reserved
752 ; bounds check (INT 5)
753 BOUNDS_CHECK_SEL equ $-IDT_BASE
755 dw SYS_CODE64_SEL ; selector 15:0
756 db 0 ; 0 for interrupt gate
757 db 0eh OR 80h ; type = 386 interrupt gate, present
760 dd 0 ; 0 for reserved
762 ; invalid opcode (INT 6)
763 INVALID_OPCODE_SEL equ $-IDT_BASE
765 dw SYS_CODE64_SEL ; selector 15:0
766 db 0 ; 0 for interrupt gate
767 db 0eh OR 80h ; type = 386 interrupt gate, present
770 dd 0 ; 0 for reserved
772 ; device not available (INT 7)
773 DEV_NOT_AVAIL_SEL equ $-IDT_BASE
775 dw SYS_CODE64_SEL ; selector 15:0
776 db 0 ; 0 for interrupt gate
777 db 0eh OR 80h ; type = 386 interrupt gate, present
780 dd 0 ; 0 for reserved
782 ; double fault (INT 8)
783 DOUBLE_FAULT_SEL equ $-IDT_BASE
785 dw SYS_CODE64_SEL ; selector 15:0
786 db 0 ; 0 for interrupt gate
787 db 0eh OR 80h ; type = 386 interrupt gate, present
790 dd 0 ; 0 for reserved
792 ; Coprocessor segment overrun - reserved (INT 9)
793 RSVD_INTR_SEL1 equ $-IDT_BASE
795 dw SYS_CODE64_SEL ; selector 15:0
796 db 0 ; 0 for interrupt gate
797 db 0eh OR 80h ; type = 386 interrupt gate, present
800 dd 0 ; 0 for reserved
802 ; invalid TSS (INT 0ah)
803 INVALID_TSS_SEL equ $-IDT_BASE
805 dw SYS_CODE64_SEL ; selector 15:0
806 db 0 ; 0 for interrupt gate
807 db 0eh OR 80h ; type = 386 interrupt gate, present
810 dd 0 ; 0 for reserved
812 ; segment not present (INT 0bh)
813 SEG_NOT_PRESENT_SEL equ $-IDT_BASE
815 dw SYS_CODE64_SEL ; selector 15:0
816 db 0 ; 0 for interrupt gate
817 db 0eh OR 80h ; type = 386 interrupt gate, present
820 dd 0 ; 0 for reserved
822 ; stack fault (INT 0ch)
823 STACK_FAULT_SEL equ $-IDT_BASE
825 dw SYS_CODE64_SEL ; selector 15:0
826 db 0 ; 0 for interrupt gate
827 db 0eh OR 80h ; type = 386 interrupt gate, present
830 dd 0 ; 0 for reserved
832 ; general protection (INT 0dh)
833 GP_FAULT_SEL equ $-IDT_BASE
835 dw SYS_CODE64_SEL ; selector 15:0
836 db 0 ; 0 for interrupt gate
837 db 0eh OR 80h ; type = 386 interrupt gate, present
840 dd 0 ; 0 for reserved
842 ; page fault (INT 0eh)
843 PAGE_FAULT_SEL equ $-IDT_BASE
845 dw SYS_CODE64_SEL ; selector 15:0
846 db 0 ; 0 for interrupt gate
847 db 0eh OR 80h ; type = 386 interrupt gate, present
850 dd 0 ; 0 for reserved
852 ; Intel reserved - do not use (INT 0fh)
853 RSVD_INTR_SEL2 equ $-IDT_BASE
855 dw SYS_CODE64_SEL ; selector 15:0
856 db 0 ; 0 for interrupt gate
857 db 0eh OR 80h ; type = 386 interrupt gate, present
860 dd 0 ; 0 for reserved
862 ; floating point error (INT 10h)
863 FLT_POINT_ERR_SEL equ $-IDT_BASE
865 dw SYS_CODE64_SEL ; selector 15:0
866 db 0 ; 0 for interrupt gate
867 db 0eh OR 80h ; type = 386 interrupt gate, present
870 dd 0 ; 0 for reserved
872 ; alignment check (INT 11h)
873 ALIGNMENT_CHECK_SEL equ $-IDT_BASE
875 dw SYS_CODE64_SEL ; selector 15:0
876 db 0 ; 0 for interrupt gate
877 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
880 dd 0 ; 0 for reserved
882 ; machine check (INT 12h)
883 MACHINE_CHECK_SEL equ $-IDT_BASE
885 dw SYS_CODE64_SEL ; selector 15:0
886 db 0 ; 0 for interrupt gate
887 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
890 dd 0 ; 0 for reserved
892 ; SIMD floating-point exception (INT 13h)
893 SIMD_EXCEPTION_SEL equ $-IDT_BASE
895 dw SYS_CODE64_SEL ; selector 15:0
896 db 0 ; 0 for interrupt gate
897 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
900 dd 0 ; 0 for reserved
902 ; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
905 ; IRQ 0 (System timer) - (INT 68h)
906 IRQ0_SEL equ $-IDT_BASE
908 dw SYS_CODE64_SEL ; selector 15:0
909 db 0 ; 0 for interrupt gate
910 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
913 dd 0 ; 0 for reserved
915 ; IRQ 1 (8042 Keyboard controller) - (INT 69h)
916 IRQ1_SEL equ $-IDT_BASE
918 dw SYS_CODE64_SEL ; selector 15:0
919 db 0 ; 0 for interrupt gate
920 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
923 dd 0 ; 0 for reserved
925 ; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
926 IRQ2_SEL equ $-IDT_BASE
928 dw SYS_CODE64_SEL ; selector 15:0
929 db 0 ; 0 for interrupt gate
930 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
933 dd 0 ; 0 for reserved
935 ; IRQ 3 (COM 2) - (INT 6bh)
936 IRQ3_SEL equ $-IDT_BASE
938 dw SYS_CODE64_SEL ; selector 15:0
939 db 0 ; 0 for interrupt gate
940 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
943 dd 0 ; 0 for reserved
945 ; IRQ 4 (COM 1) - (INT 6ch)
946 IRQ4_SEL equ $-IDT_BASE
948 dw SYS_CODE64_SEL ; selector 15:0
949 db 0 ; 0 for interrupt gate
950 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
953 dd 0 ; 0 for reserved
955 ; IRQ 5 (LPT 2) - (INT 6dh)
956 IRQ5_SEL equ $-IDT_BASE
958 dw SYS_CODE64_SEL ; selector 15:0
959 db 0 ; 0 for interrupt gate
960 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
963 dd 0 ; 0 for reserved
965 ; IRQ 6 (Floppy controller) - (INT 6eh)
966 IRQ6_SEL equ $-IDT_BASE
968 dw SYS_CODE64_SEL ; selector 15:0
969 db 0 ; 0 for interrupt gate
970 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
973 dd 0 ; 0 for reserved
975 ; IRQ 7 (LPT 1) - (INT 6fh)
976 IRQ7_SEL equ $-IDT_BASE
978 dw SYS_CODE64_SEL ; selector 15:0
979 db 0 ; 0 for interrupt gate
980 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
983 dd 0 ; 0 for reserved
985 ; IRQ 8 (RTC Alarm) - (INT 70h)
986 IRQ8_SEL equ $-IDT_BASE
988 dw SYS_CODE64_SEL ; selector 15:0
989 db 0 ; 0 for interrupt gate
990 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
993 dd 0 ; 0 for reserved
996 IRQ9_SEL equ $-IDT_BASE
998 dw SYS_CODE64_SEL ; selector 15:0
999 db 0 ; 0 for interrupt gate
1000 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1003 dd 0 ; 0 for reserved
1005 ; IRQ 10 - (INT 72h)
1006 IRQ10_SEL equ $-IDT_BASE
1008 dw SYS_CODE64_SEL ; selector 15:0
1009 db 0 ; 0 for interrupt gate
1010 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1013 dd 0 ; 0 for reserved
1015 ; IRQ 11 - (INT 73h)
1016 IRQ11_SEL equ $-IDT_BASE
1018 dw SYS_CODE64_SEL ; selector 15:0
1019 db 0 ; 0 for interrupt gate
1020 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1023 dd 0 ; 0 for reserved
1025 ; IRQ 12 (PS/2 mouse) - (INT 74h)
1026 IRQ12_SEL equ $-IDT_BASE
1028 dw SYS_CODE64_SEL ; selector 15:0
1029 db 0 ; 0 for interrupt gate
1030 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1033 dd 0 ; 0 for reserved
1035 ; IRQ 13 (Floating point error) - (INT 75h)
1036 IRQ13_SEL equ $-IDT_BASE
1038 dw SYS_CODE64_SEL ; selector 15:0
1039 db 0 ; 0 for interrupt gate
1040 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1043 dd 0 ; 0 for reserved
1045 ; IRQ 14 (Secondary IDE) - (INT 76h)
1046 IRQ14_SEL equ $-IDT_BASE
1048 dw SYS_CODE64_SEL ; selector 15:0
1049 db 0 ; 0 for interrupt gate
1050 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1053 dd 0 ; 0 for reserved
1055 ; IRQ 15 (Primary IDE) - (INT 77h)
1056 IRQ15_SEL equ $-IDT_BASE
1058 dw SYS_CODE64_SEL ; selector 15:0
1059 db 0 ; 0 for interrupt gate
1060 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
1063 dd 0 ; 0 for reserved
1070 MemoryMap dd 0,0,0,0,0,0,0,0
1101 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
1102 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
1106 ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
1107 ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
1108 ; known low address (20f00) so it can be set up by PlMapIrqToVect in