1
;------------------------------------------------------------------------------
3
;* Copyright (c) 2006 - 2011, 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 "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
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,0fff8h ; ax = ax & 0xfff8
148
cmp ax,0fff8h ; 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 ; FatOffset = ClusterNumber * 2
153
mov si,ax ; si = FatOffset
154
shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT
155
add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
156
and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK
157
cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber
163
call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
165
mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
167
mov bx,word ptr [si] ; bx = NextClusterNumber
168
mov ax,cx ; ax = ClusterNumber
170
dec bx ; bx = NextClusterNumber - 1
171
cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
173
inc bx ; bx = NextClusterNumber
174
inc si ; NumberOfClusters++
175
mov cx,bx ; ClusterNumber = NextClusterNumber
179
pop ax ; ax = StartCluster
180
push bx ; StartCluster = NextClusterNumber
181
mov cx,bx ; ClusterNumber = NextClusterNumber
182
sub ax,2 ; ax = StartCluster - 2
184
mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster
185
mul bx ; ax = (StartCluster - 2) * SectorsPerCluster
186
add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
187
push ax ; save start sector
188
mov ax,si ; ax = NumberOfClusters
189
mul bx ; ax = NumberOfClusters * SectorsPerCluster
190
mov bx,ax ; bx = Number of Sectors
191
pop ax ; ax = Start Sector
193
mov si,1 ; NumberOfClusters = 1
201
; ****************************************************************************
202
; ReadBlocks - Reads a set of blocks from a block device
205
; BX = Number of Blocks to Read
206
; ES:DI = Buffer to store sectors read from disk
207
; ****************************************************************************
210
; bx = NumberOfBlocks
215
add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA
216
add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA
217
mov esi,eax ; esi = Start LBA
218
mov cx,bx ; cx = Number of blocks to read
220
mov bp,07bfch ; bp = 0x7bfc
221
mov eax,esi ; eax = Start LBA
222
xor edx,edx ; edx = 0
223
movzx ebx,word ptr [bp] ; bx = MaxSector
224
div ebx ; ax = StartLBA / MaxSector
225
inc dx ; dx = (StartLBA % MaxSector) + 1
227
mov bx,word ptr [bp] ; bx = MaxSector
228
sub bx,dx ; bx = MaxSector - Sector
229
inc bx ; bx = MaxSector - Sector + 1
230
cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)
232
mov bx,cx ; bx = Blocks
236
shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system
237
and ax,07fh ; ax = Number of blocks into current seg
238
add ax,bx ; ax = End Block number of transfer
239
cmp ax,080h ; See if it crosses a 64K boundry
240
jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry
241
sub ax,080h ; ax = Number of blocks past 64K boundry
242
sub bx,ax ; Decrease transfer size by block overage
243
NotCrossing64KBoundry:
247
mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
249
div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
250
; dx = ax % (MaxHead + 1) = Head
252
push bx ; Save number of blocks to transfer
253
mov dh,dl ; dh = Head
254
mov bp,07c00h ; bp = 0x7c00
255
mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number
256
mov ch,al ; ch = Cylinder
257
mov al,bl ; al = Blocks
258
mov ah,2 ; ah = Function 2
259
mov bx,di ; es:bx = Buffer address
265
add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
266
sub cx,bx ; Blocks = Blocks - NumberOfBlocks
268
shl bx,(BLOCK_SHIFT-4)
270
mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
279
lea si, [ErrorString]
281
jmp PrintStringAndHalt
292
db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
295
LBAOffsetForBootSector:
301
;******************************************************************************
302
;******************************************************************************
303
;******************************************************************************
305
DELAY_PORT equ 0edh ; Port to use for 1uS delay
306
KBD_CONTROL_PORT equ 060h ; 8042 control port
307
KBD_STATUS_PORT equ 064h ; 8042 status port
308
WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port
309
ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20
314
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
325
; mov byte ptr es:[160],'a'
343
sub edi,eax ; Get the address of the memory map
344
mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
347
mov bx,cs ; BX=segment
348
shl ebx,4 ; BX="linear" address of segment base
349
lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt
350
mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr
351
lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt
352
mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr
353
lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map
355
add ebx,01000h ; Source of EFI32
356
mov dword ptr [JUMP+2],ebx
358
mov esi,ebx ; Source of EFILDR32
362
; mov byte ptr es:[162],'b'
370
mov ax,2401h ; Enable A20 Gate
372
jnc A20GateEnabled ; Jump if it suceeded
375
; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
378
call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
379
jnz Timeout8042 ; Jump if the 8042 timed out
380
out DELAY_PORT,ax ; Delay 1 uS
381
mov al,WRITE_DATA_PORT_CMD ; 8042 cmd to write output port
382
out KBD_STATUS_PORT,al ; Send command to the 8042
383
call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
384
jnz Timeout8042 ; Jump if the 8042 timed out
385
mov al,ENABLE_A20_CMD ; gate address bit 20 on
386
out KBD_CONTROL_PORT,al ; Send command to thre 8042
387
call Empty8042InputBuffer ; Empty the Input Buffer on the 8042 controller
388
mov cx,25 ; Delay 25 uS for the command to complete on the 8042
390
out DELAY_PORT,ax ; Delay 1 uS
396
mov bx,0008h ; Flat data descriptor
398
; DISABLE INTERRUPTS - Entering Protected Mode
405
; mov byte ptr es:[164],'c'
410
lgdt fword ptr [gdtr]
412
lidt fword ptr [idtr]
418
; jmp far 0010:00020000
424
Empty8042InputBuffer:
427
out DELAY_PORT,ax ; Delay 1us
428
in al,KBD_STATUS_PORT ; Read the 8042 Status Port
429
and al,02h ; Check the Input Buffer Full Flag
430
loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
433
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
435
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
439
gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
440
dd 0 ; (GDT base gets set above)
441
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
442
; global descriptor table (GDT)
443
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
450
NULL_SEL equ $-GDT_BASE
455
db 0 ; limit 19:16, flags
458
; linear data segment descriptor
459
LINEAR_SEL equ $-GDT_BASE
460
dw 0FFFFh ; limit 0xFFFFF
463
db 092h ; present, ring 0, data, expand-up, writable
464
db 0CFh ; page-granular, 32-bit
467
; linear code segment descriptor
468
LINEAR_CODE_SEL equ $-GDT_BASE
469
dw 0FFFFh ; limit 0xFFFFF
472
db 09Ah ; present, ring 0, data, expand-up, writable
473
db 0CFh ; page-granular, 32-bit
476
; system data segment descriptor
477
SYS_DATA_SEL equ $-GDT_BASE
478
dw 0FFFFh ; limit 0xFFFFF
481
db 092h ; present, ring 0, data, expand-up, writable
482
db 0CFh ; page-granular, 32-bit
485
; system code segment descriptor
486
SYS_CODE_SEL equ $-GDT_BASE
487
dw 0FFFFh ; limit 0xFFFFF
490
db 09Ah ; present, ring 0, data, expand-up, writable
491
db 0CFh ; page-granular, 32-bit
494
; spare segment descriptor
495
SPARE3_SEL equ $-GDT_BASE
499
db 0 ; present, ring 0, data, expand-up, writable
500
db 0 ; page-granular, 32-bit
503
; spare segment descriptor
504
SPARE4_SEL equ $-GDT_BASE
508
db 0 ; present, ring 0, data, expand-up, writable
509
db 0 ; page-granular, 32-bit
512
; spare segment descriptor
513
SPARE5_SEL equ $-GDT_BASE
517
db 0 ; present, ring 0, data, expand-up, writable
518
db 0 ; page-granular, 32-bit
527
idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
528
dd 0 ; (IDT base gets set above)
529
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
530
; interrupt descriptor table (IDT)
532
; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
533
; mappings. This implementation only uses the system timer and all other
534
; IRQs will remain masked. The descriptors for vectors 33+ are provided
536
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
543
; divide by zero (INT 0)
544
DIV_ZERO_SEL equ $-IDT_BASE
546
dw SYS_CODE_SEL ; selector 15:0
547
db 0 ; 0 for interrupt gate
548
db 0eh OR 80h ; type = 386 interrupt gate, present
551
; debug exception (INT 1)
552
DEBUG_EXCEPT_SEL equ $-IDT_BASE
554
dw SYS_CODE_SEL ; selector 15:0
555
db 0 ; 0 for interrupt gate
556
db 0eh OR 80h ; type = 386 interrupt gate, present
560
NMI_SEL equ $-IDT_BASE
562
dw SYS_CODE_SEL ; selector 15:0
563
db 0 ; 0 for interrupt gate
564
db 0eh OR 80h ; type = 386 interrupt gate, present
567
; soft breakpoint (INT 3)
568
BREAKPOINT_SEL equ $-IDT_BASE
570
dw SYS_CODE_SEL ; selector 15:0
571
db 0 ; 0 for interrupt gate
572
db 0eh OR 80h ; type = 386 interrupt gate, present
576
OVERFLOW_SEL equ $-IDT_BASE
578
dw SYS_CODE_SEL ; selector 15:0
579
db 0 ; 0 for interrupt gate
580
db 0eh OR 80h ; type = 386 interrupt gate, present
583
; bounds check (INT 5)
584
BOUNDS_CHECK_SEL equ $-IDT_BASE
586
dw SYS_CODE_SEL ; selector 15:0
587
db 0 ; 0 for interrupt gate
588
db 0eh OR 80h ; type = 386 interrupt gate, present
591
; invalid opcode (INT 6)
592
INVALID_OPCODE_SEL equ $-IDT_BASE
594
dw SYS_CODE_SEL ; selector 15:0
595
db 0 ; 0 for interrupt gate
596
db 0eh OR 80h ; type = 386 interrupt gate, present
599
; device not available (INT 7)
600
DEV_NOT_AVAIL_SEL equ $-IDT_BASE
602
dw SYS_CODE_SEL ; selector 15:0
603
db 0 ; 0 for interrupt gate
604
db 0eh OR 80h ; type = 386 interrupt gate, present
607
; double fault (INT 8)
608
DOUBLE_FAULT_SEL equ $-IDT_BASE
610
dw SYS_CODE_SEL ; selector 15:0
611
db 0 ; 0 for interrupt gate
612
db 0eh OR 80h ; type = 386 interrupt gate, present
615
; Coprocessor segment overrun - reserved (INT 9)
616
RSVD_INTR_SEL1 equ $-IDT_BASE
618
dw SYS_CODE_SEL ; selector 15:0
619
db 0 ; 0 for interrupt gate
620
db 0eh OR 80h ; type = 386 interrupt gate, present
623
; invalid TSS (INT 0ah)
624
INVALID_TSS_SEL equ $-IDT_BASE
626
dw SYS_CODE_SEL ; selector 15:0
627
db 0 ; 0 for interrupt gate
628
db 0eh OR 80h ; type = 386 interrupt gate, present
631
; segment not present (INT 0bh)
632
SEG_NOT_PRESENT_SEL equ $-IDT_BASE
634
dw SYS_CODE_SEL ; selector 15:0
635
db 0 ; 0 for interrupt gate
636
db 0eh OR 80h ; type = 386 interrupt gate, present
639
; stack fault (INT 0ch)
640
STACK_FAULT_SEL equ $-IDT_BASE
642
dw SYS_CODE_SEL ; selector 15:0
643
db 0 ; 0 for interrupt gate
644
db 0eh OR 80h ; type = 386 interrupt gate, present
647
; general protection (INT 0dh)
648
GP_FAULT_SEL equ $-IDT_BASE
650
dw SYS_CODE_SEL ; selector 15:0
651
db 0 ; 0 for interrupt gate
652
db 0eh OR 80h ; type = 386 interrupt gate, present
655
; page fault (INT 0eh)
656
PAGE_FAULT_SEL equ $-IDT_BASE
658
dw SYS_CODE_SEL ; selector 15:0
659
db 0 ; 0 for interrupt gate
660
db 0eh OR 80h ; type = 386 interrupt gate, present
663
; Intel reserved - do not use (INT 0fh)
664
RSVD_INTR_SEL2 equ $-IDT_BASE
666
dw SYS_CODE_SEL ; selector 15:0
667
db 0 ; 0 for interrupt gate
668
db 0eh OR 80h ; type = 386 interrupt gate, present
671
; floating point error (INT 10h)
672
FLT_POINT_ERR_SEL equ $-IDT_BASE
674
dw SYS_CODE_SEL ; selector 15:0
675
db 0 ; 0 for interrupt gate
676
db 0eh OR 80h ; type = 386 interrupt gate, present
679
; alignment check (INT 11h)
680
ALIGNMENT_CHECK_SEL equ $-IDT_BASE
682
dw SYS_CODE_SEL ; selector 15:0
683
db 0 ; 0 for interrupt gate
684
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
687
; machine check (INT 12h)
688
MACHINE_CHECK_SEL equ $-IDT_BASE
690
dw SYS_CODE_SEL ; selector 15:0
691
db 0 ; 0 for interrupt gate
692
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
695
; SIMD floating-point exception (INT 13h)
696
SIMD_EXCEPTION_SEL equ $-IDT_BASE
698
dw SYS_CODE_SEL ; selector 15:0
699
db 0 ; 0 for interrupt gate
700
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
703
; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
706
; IRQ 0 (System timer) - (INT 68h)
707
IRQ0_SEL equ $-IDT_BASE
709
dw SYS_CODE_SEL ; selector 15:0
710
db 0 ; 0 for interrupt gate
711
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
714
; IRQ 1 (8042 Keyboard controller) - (INT 69h)
715
IRQ1_SEL equ $-IDT_BASE
717
dw SYS_CODE_SEL ; selector 15:0
718
db 0 ; 0 for interrupt gate
719
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
722
; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
723
IRQ2_SEL equ $-IDT_BASE
725
dw SYS_CODE_SEL ; selector 15:0
726
db 0 ; 0 for interrupt gate
727
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
730
; IRQ 3 (COM 2) - (INT 6bh)
731
IRQ3_SEL equ $-IDT_BASE
733
dw SYS_CODE_SEL ; selector 15:0
734
db 0 ; 0 for interrupt gate
735
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
738
; IRQ 4 (COM 1) - (INT 6ch)
739
IRQ4_SEL equ $-IDT_BASE
741
dw SYS_CODE_SEL ; selector 15:0
742
db 0 ; 0 for interrupt gate
743
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
746
; IRQ 5 (LPT 2) - (INT 6dh)
747
IRQ5_SEL equ $-IDT_BASE
749
dw SYS_CODE_SEL ; selector 15:0
750
db 0 ; 0 for interrupt gate
751
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
754
; IRQ 6 (Floppy controller) - (INT 6eh)
755
IRQ6_SEL equ $-IDT_BASE
757
dw SYS_CODE_SEL ; selector 15:0
758
db 0 ; 0 for interrupt gate
759
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
762
; IRQ 7 (LPT 1) - (INT 6fh)
763
IRQ7_SEL equ $-IDT_BASE
765
dw SYS_CODE_SEL ; selector 15:0
766
db 0 ; 0 for interrupt gate
767
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
770
; IRQ 8 (RTC Alarm) - (INT 70h)
771
IRQ8_SEL equ $-IDT_BASE
773
dw SYS_CODE_SEL ; selector 15:0
774
db 0 ; 0 for interrupt gate
775
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
779
IRQ9_SEL equ $-IDT_BASE
781
dw SYS_CODE_SEL ; selector 15:0
782
db 0 ; 0 for interrupt gate
783
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
787
IRQ10_SEL equ $-IDT_BASE
789
dw SYS_CODE_SEL ; selector 15:0
790
db 0 ; 0 for interrupt gate
791
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
795
IRQ11_SEL equ $-IDT_BASE
797
dw SYS_CODE_SEL ; selector 15:0
798
db 0 ; 0 for interrupt gate
799
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
802
; IRQ 12 (PS/2 mouse) - (INT 74h)
803
IRQ12_SEL equ $-IDT_BASE
805
dw SYS_CODE_SEL ; selector 15:0
806
db 0 ; 0 for interrupt gate
807
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
810
; IRQ 13 (Floating point error) - (INT 75h)
811
IRQ13_SEL equ $-IDT_BASE
813
dw SYS_CODE_SEL ; selector 15:0
814
db 0 ; 0 for interrupt gate
815
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
818
; IRQ 14 (Secondary IDE) - (INT 76h)
819
IRQ14_SEL equ $-IDT_BASE
821
dw SYS_CODE_SEL ; selector 15:0
822
db 0 ; 0 for interrupt gate
823
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
826
; IRQ 15 (Primary IDE) - (INT 77h)
827
IRQ15_SEL equ $-IDT_BASE
829
dw SYS_CODE_SEL ; selector 15:0
830
db 0 ; 0 for interrupt gate
831
db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
839
MemoryMap dd 0,0,0,0,0,0,0,0
870
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
871
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
875
; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
876
; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
877
; known low address (20f00) so it can be set up by PlMapIrqToVect in