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 "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
123 ; ****************************************************************************
127 ; CX = Start Cluster of File
128 ; ES:DI = Buffer to store file content read from disk
131 ; (ES << 4 + DI) = end of file content Buffer
133 ; ****************************************************************************
135 ; si = NumberOfClusters
137 ; dx = CachedFatSectorNumber
138 ; ds:0000 = CacheFatSectorBuffer
139 ; es:di = Buffer to load file
140 ; bx = NextClusterNumber
142 mov si,1 ; NumberOfClusters = 1
143 push cx ; Push Start Cluster onto stack
144 mov dx,0fffh ; CachedFatSectorNumber = 0xfff
146 mov ax,cx ; ax = ClusterNumber
147 and ax,0ff8h ; ax = ax & 0xff8
148 cmp ax,0ff8h ; See if this is the last cluster
149 je FoundLastCluster ; Jump if last cluster found
150 mov ax,cx ; ax = ClusterNumber
151 shl ax,1 ; ax = ClusterNumber * 2
152 add ax,cx ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3
153 shr ax,1 ; FatOffset = ClusterNumber*3 / 2
155 mov si,ax ; si = FatOffset
156 shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
157 add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
158 and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
159 cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
165 call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
167 mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
169 mov bx,word ptr [si] ; bx = NextClusterNumber
170 mov ax,cx ; ax = ClusterNumber
171 and ax,1 ; See if this is an odd cluster number
173 shr bx,4 ; NextClusterNumber = NextClusterNumber >> 4
175 and bx,0fffh ; Strip upper 4 bits of NextClusterNumber
177 dec bx ; bx = NextClusterNumber - 1
178 cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
180 inc bx ; bx = NextClusterNumber
181 inc si ; NumberOfClusters++
182 mov cx,bx ; ClusterNumber = NextClusterNumber
186 pop ax ; ax = StartCluster
187 push bx ; StartCluster = NextClusterNumber
188 mov cx,bx ; ClusterNumber = NextClusterNumber
189 sub ax,2 ; ax = StartCluster - 2
191 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
192 mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
193 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
194 push ax ; save start sector
195 mov ax,si ; ax = NumberOfClusters
196 mul bx ; ax = NumberOfClusters * SectorsPerCluster
197 mov bx,ax ; bx = Number of Sectors
198 pop ax ; ax = Start Sector
200 mov si,1 ; NumberOfClusters = 1
208 ; ****************************************************************************
209 ; ReadBlocks - Reads a set of blocks from a block device
212 ; BX = Number of Blocks to Read
213 ; ES:DI = Buffer to store sectors read from disk
214 ; ****************************************************************************
217 ; bx = NumberOfBlocks
222 add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
223 add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
224 mov esi,eax ; esi = Start LBA
225 mov cx,bx ; cx = Number of blocks to read
227 mov bp,07bfch ; bp = 0x7bfc
228 mov eax,esi ; eax = Start LBA
229 xor edx,edx ; edx = 0
230 movzx ebx,word ptr [bp] ; bx = MaxSector
231 div ebx ; ax = StartLBA / MaxSector
232 inc dx ; dx = (StartLBA % MaxSector) + 1
234 mov bx,word ptr [bp] ; bx = MaxSector
235 sub bx,dx ; bx = MaxSector - Sector
236 inc bx ; bx = MaxSector - Sector + 1
237 cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
239 mov bx,cx ; bx = Blocks
243 shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
244 and ax,07fh ; ax = Number of blocks into current seg
245 add ax,bx ; ax = End Block number of transfer
246 cmp ax,080h ; See if it crosses a 64K boundry
247 jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
248 sub ax,080h ; ax = Number of blocks past 64K boundry
249 sub bx,ax ; Decrease transfer size by block overage
250 NotCrossing64KBoundry:
254 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
256 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
257 ; dx = ax % (MaxHead + 1) = Head
259 push bx ; Save number of blocks to transfer
260 mov dh,dl ; dh = Head
261 mov bp,07c00h ; bp = 0x7c00
262 mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
263 mov ch,al ; ch = Cylinder
264 mov al,bl ; al = Blocks
265 mov ah,2 ; ah = Function 2
266 mov bx,di ; es:bx = Buffer address
272 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
273 sub cx,bx ; Blocks = Blocks - NumberOfBlocks
275 shl bx,(BLOCK_SHIFT-4)
277 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
286 lea si, [ErrorString]
288 jmp PrintStringAndHalt
299 db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
302 LBAOffsetForBootSector:
308 ;******************************************************************************
309 ;******************************************************************************
310 ;******************************************************************************
312 DELAY_PORT equ 0edh ; Port to use for 1uS delay
313 KBD_CONTROL_PORT equ 060h ; 8042 control port
314 KBD_STATUS_PORT equ 064h ; 8042 status port
315 WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
316 ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
321 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
332 ; mov byte ptr es:[160],'a'
350 sub edi,eax ; Get the address of the memory map
351 mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
354 mov bx,cs ; BX=segment
355 shl ebx,4 ; BX="linear" address of segment base
356 lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
357 mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
358 lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
359 mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
360 lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
362 add ebx,01000h ; Source of EFI32
363 mov dword ptr [JUMP+2],ebx
365 mov esi,ebx ; Source of EFILDR32
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'
417 lgdt fword ptr [gdtr]
419 lidt fword ptr [idtr]
425 mov eax,0008h ; Flat data descriptor
426 mov ebp,000400000h ; Destination of EFILDR32
427 mov ebx,000070000h ; Length of copy
430 ; jmp far 0010:00020000
436 Empty8042InputBuffer:
439 out DELAY_PORT,ax ; Delay 1us
440 in al,KBD_STATUS_PORT ; Read the 8042 Status Port
441 and al,02h ; Check the Input Buffer Full Flag
442 loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
445 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
447 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
451 gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
452 dd 0 ; (GDT base gets set above)
453 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
454 ; global descriptor table (GDT)
455 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
462 NULL_SEL equ $-GDT_BASE
467 db 0 ; limit 19:16, flags
470 ; linear data segment descriptor
471 LINEAR_SEL equ $-GDT_BASE
472 dw 0FFFFh ; limit 0xFFFFF
475 db 092h ; present, ring 0, data, expand-up, writable
476 db 0CFh ; page-granular, 32-bit
479 ; linear code segment descriptor
480 LINEAR_CODE_SEL equ $-GDT_BASE
481 dw 0FFFFh ; limit 0xFFFFF
484 db 09Ah ; present, ring 0, data, expand-up, writable
485 db 0CFh ; page-granular, 32-bit
488 ; system data segment descriptor
489 SYS_DATA_SEL equ $-GDT_BASE
490 dw 0FFFFh ; limit 0xFFFFF
493 db 092h ; present, ring 0, data, expand-up, writable
494 db 0CFh ; page-granular, 32-bit
497 ; system code segment descriptor
498 SYS_CODE_SEL equ $-GDT_BASE
499 dw 0FFFFh ; limit 0xFFFFF
502 db 09Ah ; present, ring 0, data, expand-up, writable
503 db 0CFh ; page-granular, 32-bit
506 ; spare segment descriptor
507 SPARE3_SEL equ $-GDT_BASE
511 db 0 ; present, ring 0, data, expand-up, writable
512 db 0 ; page-granular, 32-bit
515 ; spare segment descriptor
516 SPARE4_SEL equ $-GDT_BASE
520 db 0 ; present, ring 0, data, expand-up, writable
521 db 0 ; page-granular, 32-bit
524 ; spare segment descriptor
525 SPARE5_SEL equ $-GDT_BASE
529 db 0 ; present, ring 0, data, expand-up, writable
530 db 0 ; page-granular, 32-bit
539 idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
540 dd 0 ; (IDT base gets set above)
541 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
542 ; interrupt descriptor table (IDT)
544 ; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
545 ; mappings. This implementation only uses the system timer and all other
546 ; IRQs will remain masked. The descriptors for vectors 33+ are provided
548 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
555 ; divide by zero (INT 0)
556 DIV_ZERO_SEL equ $-IDT_BASE
558 dw SYS_CODE_SEL ; selector 15:0
559 db 0 ; 0 for interrupt gate
560 db 0eh OR 80h ; type = 386 interrupt gate, present
563 ; debug exception (INT 1)
564 DEBUG_EXCEPT_SEL equ $-IDT_BASE
566 dw SYS_CODE_SEL ; selector 15:0
567 db 0 ; 0 for interrupt gate
568 db 0eh OR 80h ; type = 386 interrupt gate, present
572 NMI_SEL equ $-IDT_BASE
574 dw SYS_CODE_SEL ; selector 15:0
575 db 0 ; 0 for interrupt gate
576 db 0eh OR 80h ; type = 386 interrupt gate, present
579 ; soft breakpoint (INT 3)
580 BREAKPOINT_SEL equ $-IDT_BASE
582 dw SYS_CODE_SEL ; selector 15:0
583 db 0 ; 0 for interrupt gate
584 db 0eh OR 80h ; type = 386 interrupt gate, present
588 OVERFLOW_SEL equ $-IDT_BASE
590 dw SYS_CODE_SEL ; selector 15:0
591 db 0 ; 0 for interrupt gate
592 db 0eh OR 80h ; type = 386 interrupt gate, present
595 ; bounds check (INT 5)
596 BOUNDS_CHECK_SEL equ $-IDT_BASE
598 dw SYS_CODE_SEL ; selector 15:0
599 db 0 ; 0 for interrupt gate
600 db 0eh OR 80h ; type = 386 interrupt gate, present
603 ; invalid opcode (INT 6)
604 INVALID_OPCODE_SEL equ $-IDT_BASE
606 dw SYS_CODE_SEL ; selector 15:0
607 db 0 ; 0 for interrupt gate
608 db 0eh OR 80h ; type = 386 interrupt gate, present
611 ; device not available (INT 7)
612 DEV_NOT_AVAIL_SEL equ $-IDT_BASE
614 dw SYS_CODE_SEL ; selector 15:0
615 db 0 ; 0 for interrupt gate
616 db 0eh OR 80h ; type = 386 interrupt gate, present
619 ; double fault (INT 8)
620 DOUBLE_FAULT_SEL equ $-IDT_BASE
622 dw SYS_CODE_SEL ; selector 15:0
623 db 0 ; 0 for interrupt gate
624 db 0eh OR 80h ; type = 386 interrupt gate, present
627 ; Coprocessor segment overrun - reserved (INT 9)
628 RSVD_INTR_SEL1 equ $-IDT_BASE
630 dw SYS_CODE_SEL ; selector 15:0
631 db 0 ; 0 for interrupt gate
632 db 0eh OR 80h ; type = 386 interrupt gate, present
635 ; invalid TSS (INT 0ah)
636 INVALID_TSS_SEL equ $-IDT_BASE
638 dw SYS_CODE_SEL ; selector 15:0
639 db 0 ; 0 for interrupt gate
640 db 0eh OR 80h ; type = 386 interrupt gate, present
643 ; segment not present (INT 0bh)
644 SEG_NOT_PRESENT_SEL equ $-IDT_BASE
646 dw SYS_CODE_SEL ; selector 15:0
647 db 0 ; 0 for interrupt gate
648 db 0eh OR 80h ; type = 386 interrupt gate, present
651 ; stack fault (INT 0ch)
652 STACK_FAULT_SEL equ $-IDT_BASE
654 dw SYS_CODE_SEL ; selector 15:0
655 db 0 ; 0 for interrupt gate
656 db 0eh OR 80h ; type = 386 interrupt gate, present
659 ; general protection (INT 0dh)
660 GP_FAULT_SEL equ $-IDT_BASE
662 dw SYS_CODE_SEL ; selector 15:0
663 db 0 ; 0 for interrupt gate
664 db 0eh OR 80h ; type = 386 interrupt gate, present
667 ; page fault (INT 0eh)
668 PAGE_FAULT_SEL equ $-IDT_BASE
670 dw SYS_CODE_SEL ; selector 15:0
671 db 0 ; 0 for interrupt gate
672 db 0eh OR 80h ; type = 386 interrupt gate, present
675 ; Intel reserved - do not use (INT 0fh)
676 RSVD_INTR_SEL2 equ $-IDT_BASE
678 dw SYS_CODE_SEL ; selector 15:0
679 db 0 ; 0 for interrupt gate
680 db 0eh OR 80h ; type = 386 interrupt gate, present
683 ; floating point error (INT 10h)
684 FLT_POINT_ERR_SEL equ $-IDT_BASE
686 dw SYS_CODE_SEL ; selector 15:0
687 db 0 ; 0 for interrupt gate
688 db 0eh OR 80h ; type = 386 interrupt gate, present
691 ; alignment check (INT 11h)
692 ALIGNMENT_CHECK_SEL equ $-IDT_BASE
694 dw SYS_CODE_SEL ; selector 15:0
695 db 0 ; 0 for interrupt gate
696 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
699 ; machine check (INT 12h)
700 MACHINE_CHECK_SEL equ $-IDT_BASE
702 dw SYS_CODE_SEL ; selector 15:0
703 db 0 ; 0 for interrupt gate
704 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
707 ; SIMD floating-point exception (INT 13h)
708 SIMD_EXCEPTION_SEL equ $-IDT_BASE
710 dw SYS_CODE_SEL ; selector 15:0
711 db 0 ; 0 for interrupt gate
712 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
715 ; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
718 ; IRQ 0 (System timer) - (INT 68h)
719 IRQ0_SEL equ $-IDT_BASE
721 dw SYS_CODE_SEL ; selector 15:0
722 db 0 ; 0 for interrupt gate
723 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
726 ; IRQ 1 (8042 Keyboard controller) - (INT 69h)
727 IRQ1_SEL equ $-IDT_BASE
729 dw SYS_CODE_SEL ; selector 15:0
730 db 0 ; 0 for interrupt gate
731 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
734 ; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
735 IRQ2_SEL equ $-IDT_BASE
737 dw SYS_CODE_SEL ; selector 15:0
738 db 0 ; 0 for interrupt gate
739 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
742 ; IRQ 3 (COM 2) - (INT 6bh)
743 IRQ3_SEL equ $-IDT_BASE
745 dw SYS_CODE_SEL ; selector 15:0
746 db 0 ; 0 for interrupt gate
747 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
750 ; IRQ 4 (COM 1) - (INT 6ch)
751 IRQ4_SEL equ $-IDT_BASE
753 dw SYS_CODE_SEL ; selector 15:0
754 db 0 ; 0 for interrupt gate
755 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
758 ; IRQ 5 (LPT 2) - (INT 6dh)
759 IRQ5_SEL equ $-IDT_BASE
761 dw SYS_CODE_SEL ; selector 15:0
762 db 0 ; 0 for interrupt gate
763 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
766 ; IRQ 6 (Floppy controller) - (INT 6eh)
767 IRQ6_SEL equ $-IDT_BASE
769 dw SYS_CODE_SEL ; selector 15:0
770 db 0 ; 0 for interrupt gate
771 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
774 ; IRQ 7 (LPT 1) - (INT 6fh)
775 IRQ7_SEL equ $-IDT_BASE
777 dw SYS_CODE_SEL ; selector 15:0
778 db 0 ; 0 for interrupt gate
779 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
782 ; IRQ 8 (RTC Alarm) - (INT 70h)
783 IRQ8_SEL equ $-IDT_BASE
785 dw SYS_CODE_SEL ; selector 15:0
786 db 0 ; 0 for interrupt gate
787 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
791 IRQ9_SEL equ $-IDT_BASE
793 dw SYS_CODE_SEL ; selector 15:0
794 db 0 ; 0 for interrupt gate
795 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
799 IRQ10_SEL equ $-IDT_BASE
801 dw SYS_CODE_SEL ; selector 15:0
802 db 0 ; 0 for interrupt gate
803 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
807 IRQ11_SEL equ $-IDT_BASE
809 dw SYS_CODE_SEL ; selector 15:0
810 db 0 ; 0 for interrupt gate
811 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
814 ; IRQ 12 (PS/2 mouse) - (INT 74h)
815 IRQ12_SEL equ $-IDT_BASE
817 dw SYS_CODE_SEL ; selector 15:0
818 db 0 ; 0 for interrupt gate
819 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
822 ; IRQ 13 (Floating point error) - (INT 75h)
823 IRQ13_SEL equ $-IDT_BASE
825 dw SYS_CODE_SEL ; selector 15:0
826 db 0 ; 0 for interrupt gate
827 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
830 ; IRQ 14 (Secondary IDE) - (INT 76h)
831 IRQ14_SEL equ $-IDT_BASE
833 dw SYS_CODE_SEL ; selector 15:0
834 db 0 ; 0 for interrupt gate
835 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
838 ; IRQ 15 (Primary IDE) - (INT 77h)
839 IRQ15_SEL equ $-IDT_BASE
841 dw SYS_CODE_SEL ; selector 15:0
842 db 0 ; 0 for interrupt gate
843 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
851 MemoryMap dd 0,0,0,0,0,0,0,0
882 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
883 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
887 ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
888 ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
889 ; known low address (20f00) so it can be set up by PlMapIrqToVect in