]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/BootSector/start16.asm
Comments checked
[mirror_edk2.git] / DuetPkg / BootSector / start16.asm
1 ;------------------------------------------------------------------------------
2 ;*
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
8 ;*
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.
11 ;*
12 ;* start16.asm
13 ;*
14 ;* Abstract:
15 ;*
16 ;------------------------------------------------------------------------------
17
18 .model small
19 .stack
20 .486p
21 .code
22
23 FAT_DIRECTORY_ENTRY_SIZE EQU 020h
24 FAT_DIRECTORY_ENTRY_SHIFT EQU 5
25 BLOCK_SIZE EQU 0200h
26 BLOCK_MASK EQU 01ffh
27 BLOCK_SHIFT EQU 9
28
29 org 0h
30 Ia32Jump:
31 jmp BootSectorEntryPoint ; JMP inst - 3 bytes
32 nop
33
34 OemId db "INTEL " ; OemId - 8 bytes
35
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
54
55 BootSectorEntryPoint:
56 ASSUME ds:@code
57 ASSUME ss:@code
58 ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
59 ; cx = Start Cluster of EfiLdr
60 ; dx = Start Cluster of Efivar.bin
61
62 ; Re use the BPB data stored in Boot Sector
63 mov bp,07c00h
64
65 push cx
66 ; Read Efivar.bin
67 ; 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
68 mov ax,01900h
69 mov es,ax
70 test dx,dx
71 jnz CheckVarStoreSize
72
73 mov al,1
74 NoVarStore:
75 push es
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
78 jmp SaveVolumeId
79
80 CheckVarStoreSize:
81 mov di,dx
82 cmp dword ptr ds:[di+2], 04000h
83 mov al,2
84 jne NoVarStore
85
86 LoadVarStore:
87 mov al,0
88 mov byte ptr es:[4],al
89 mov cx,word ptr[di]
90 ; ES:DI = 1500:0
91 xor di,di
92 push es
93 mov ax,01500h
94 mov es,ax
95 call ReadFile
96 SaveVolumeId:
97 pop es
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
102
103 ; Read Efildr
104 pop cx
105 ; cx = Start Cluster of Efildr -> BS.com has filled already
106 ; ES:DI = 2000:0, first cluster will be read again
107 xor di,di ; di = 0
108 mov ax,02000h
109 mov es,ax
110 call ReadFile
111 mov ax,cs
112 mov word ptr cs:[JumpSegment],ax
113
114 JumpFarInstruction:
115 db 0eah
116 JumpOffset:
117 dw 0200h
118 JumpSegment:
119 dw 2000h
120
121
122
123 ; ****************************************************************************
124 ; ReadFile
125 ;
126 ; Arguments:
127 ; CX = Start Cluster of File
128 ; ES:DI = Buffer to store file content read from disk
129 ;
130 ; Return:
131 ; (ES << 4 + DI) = end of file content Buffer
132 ;
133 ; ****************************************************************************
134 ReadFile:
135 ; si = NumberOfClusters
136 ; cx = ClusterNumber
137 ; dx = CachedFatSectorNumber
138 ; ds:0000 = CacheFatSectorBuffer
139 ; es:di = Buffer to load file
140 ; bx = NextClusterNumber
141 pusha
142 mov si,1 ; NumberOfClusters = 1
143 push cx ; Push Start Cluster onto stack
144 mov dx,0fffh ; CachedFatSectorNumber = 0xfff
145 FatChainLoop:
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
152 push si ; Save si
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
158 je SkipFatRead
159 mov bx,2
160 push es
161 push ds
162 pop es
163 call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
164 pop es
165 mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
166 SkipFatRead:
167 mov bx,word ptr [si] ; bx = NextClusterNumber
168 mov ax,cx ; ax = ClusterNumber
169 pop si ; Restore si
170 dec bx ; bx = NextClusterNumber - 1
171 cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
172 jne ReadClusters
173 inc bx ; bx = NextClusterNumber
174 inc si ; NumberOfClusters++
175 mov cx,bx ; ClusterNumber = NextClusterNumber
176 jmp FatChainLoop
177 ReadClusters:
178 inc bx
179 pop ax ; ax = StartCluster
180 push bx ; StartCluster = NextClusterNumber
181 mov cx,bx ; ClusterNumber = NextClusterNumber
182 sub ax,2 ; ax = StartCluster - 2
183 xor bh,bh
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
192 call ReadBlocks
193 mov si,1 ; NumberOfClusters = 1
194 jmp FatChainLoop
195 FoundLastCluster:
196 pop cx
197 popa
198 ret
199
200
201 ; ****************************************************************************
202 ; ReadBlocks - Reads a set of blocks from a block device
203 ;
204 ; AX = Start LBA
205 ; BX = Number of Blocks to Read
206 ; ES:DI = Buffer to store sectors read from disk
207 ; ****************************************************************************
208
209 ; cx = Blocks
210 ; bx = NumberOfBlocks
211 ; si = StartLBA
212
213 ReadBlocks:
214 pusha
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
219 ReadCylinderLoop:
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
226
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)
231 jg LimitTransfer
232 mov bx,cx ; bx = Blocks
233 LimitTransfer:
234 push ax ; save ax
235 mov ax,es ; ax = es
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:
244 pop ax ; restore ax
245
246 push cx
247 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
248 xor dx,dx ; dx = 0
249 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
250 ; dx = ax % (MaxHead + 1) = Head
251
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
260 int 013h
261 jc DiskError
262 pop bx
263 pop cx
264 movzx ebx,bx
265 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
266 sub cx,bx ; Blocks = Blocks - NumberOfBlocks
267 mov ax,es
268 shl bx,(BLOCK_SHIFT-4)
269 add ax,bx
270 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
271 cmp cx,0
272 jne ReadCylinderLoop
273 popa
274 ret
275
276 DiskError:
277 push cs
278 pop ds
279 lea si, [ErrorString]
280 mov cx, 7
281 jmp PrintStringAndHalt
282
283 PrintStringAndHalt:
284 mov ax,0b800h
285 mov es,ax
286 mov di,160
287 rep movsw
288 Halt:
289 jmp Halt
290
291 ErrorString:
292 db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
293
294 org 01fah
295 LBAOffsetForBootSector:
296 dd 0h
297
298 org 01feh
299 dw 0aa55h
300
301 ;******************************************************************************
302 ;******************************************************************************
303 ;******************************************************************************
304
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
310
311 org 200h
312 jmp start
313 Em64String:
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
315
316 start:
317 mov ax,cs
318 mov ds,ax
319 mov es,ax
320 mov ss,ax
321 mov sp,MyStack
322
323 ; mov ax,0b800h
324 ; mov es,ax
325 ; mov byte ptr es:[160],'a'
326 ; mov ax,cs
327 ; mov es,ax
328
329 mov ebx,0
330 lea edi,MemoryMap
331 MemMapLoop:
332 mov eax,0e820h
333 mov ecx,20
334 mov edx,'SMAP'
335 int 15h
336 jc MemMapDone
337 add edi,20
338 cmp ebx,0
339 je MemMapDone
340 jmp MemMapLoop
341 MemMapDone:
342 lea eax,MemoryMap
343 sub edi,eax ; Get the address of the memory map
344 mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
345
346 xor ebx,ebx
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
354
355 add ebx,01000h ; Source of EFI32
356 mov dword ptr [JUMP+2],ebx
357 add ebx,01000h
358 mov esi,ebx ; Source of EFILDR32
359
360 ; mov ax,0b800h
361 ; mov es,ax
362 ; mov byte ptr es:[162],'b'
363 ; mov ax,cs
364 ; mov es,ax
365
366 ;
367 ; Enable A20 Gate
368 ;
369
370 mov ax,2401h ; Enable A20 Gate
371 int 15h
372 jnc A20GateEnabled ; Jump if it suceeded
373
374 ;
375 ; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
376 ;
377
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
389 Delay25uS:
390 out DELAY_PORT,ax ; Delay 1 uS
391 loop Delay25uS
392 Timeout8042:
393
394
395 A20GateEnabled:
396
397 ;
398 ; DISABLE INTERRUPTS - Entering Protected Mode
399 ;
400
401 cli
402
403 ; mov ax,0b800h
404 ; mov es,ax
405 ; mov byte ptr es:[164],'c'
406 ; mov ax,cs
407 ; mov es,ax
408
409 db 66h
410 lgdt fword ptr [gdtr]
411 db 66h
412 lidt fword ptr [idtr]
413
414 mov eax,cr0
415 or al,1
416 mov cr0,eax
417
418 mov eax,0008h ; Flat data descriptor
419 mov ebp,000400000h ; Destination of EFILDR32
420 mov ebx,000070000h ; Length of copy
421
422 JUMP:
423 ; jmp far 0010:00020000
424 db 066h
425 db 0eah
426 dd 000020000h
427 dw 00010h
428
429 Empty8042InputBuffer:
430 mov cx,0
431 Empty8042Loop:
432 out DELAY_PORT,ax ; Delay 1us
433 in al,KBD_STATUS_PORT ; Read the 8042 Status Port
434 and al,02h ; Check the Input Buffer Full Flag
435 loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
436 ret
437
438 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
439 ; data
440 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
441
442 align 02h
443
444 gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
445 dd 0 ; (GDT base gets set above)
446 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
447 ; global descriptor table (GDT)
448 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
449
450 align 02h
451
452 public GDT_BASE
453 GDT_BASE:
454 ; null descriptor
455 NULL_SEL equ $-GDT_BASE
456 dw 0 ; limit 15:0
457 dw 0 ; base 15:0
458 db 0 ; base 23:16
459 db 0 ; type
460 db 0 ; limit 19:16, flags
461 db 0 ; base 31:24
462
463 ; linear data segment descriptor
464 LINEAR_SEL equ $-GDT_BASE
465 dw 0FFFFh ; limit 0xFFFFF
466 dw 0 ; base 0
467 db 0
468 db 092h ; present, ring 0, data, expand-up, writable
469 db 0CFh ; page-granular, 32-bit
470 db 0
471
472 ; linear code segment descriptor
473 LINEAR_CODE_SEL equ $-GDT_BASE
474 dw 0FFFFh ; limit 0xFFFFF
475 dw 0 ; base 0
476 db 0
477 db 09Ah ; present, ring 0, data, expand-up, writable
478 db 0CFh ; page-granular, 32-bit
479 db 0
480
481 ; system data segment descriptor
482 SYS_DATA_SEL equ $-GDT_BASE
483 dw 0FFFFh ; limit 0xFFFFF
484 dw 0 ; base 0
485 db 0
486 db 092h ; present, ring 0, data, expand-up, writable
487 db 0CFh ; page-granular, 32-bit
488 db 0
489
490 ; system code segment descriptor
491 SYS_CODE_SEL equ $-GDT_BASE
492 dw 0FFFFh ; limit 0xFFFFF
493 dw 0 ; base 0
494 db 0
495 db 09Ah ; present, ring 0, data, expand-up, writable
496 db 0CFh ; page-granular, 32-bit
497 db 0
498
499 ; spare segment descriptor
500 SPARE3_SEL equ $-GDT_BASE
501 dw 0 ; limit 0xFFFFF
502 dw 0 ; base 0
503 db 0
504 db 0 ; present, ring 0, data, expand-up, writable
505 db 0 ; page-granular, 32-bit
506 db 0
507
508 ; spare segment descriptor
509 SPARE4_SEL equ $-GDT_BASE
510 dw 0 ; limit 0xFFFFF
511 dw 0 ; base 0
512 db 0
513 db 0 ; present, ring 0, data, expand-up, writable
514 db 0 ; page-granular, 32-bit
515 db 0
516
517 ; spare segment descriptor
518 SPARE5_SEL equ $-GDT_BASE
519 dw 0 ; limit 0xFFFFF
520 dw 0 ; base 0
521 db 0
522 db 0 ; present, ring 0, data, expand-up, writable
523 db 0 ; page-granular, 32-bit
524 db 0
525
526 GDT_END:
527
528 align 02h
529
530
531
532 idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
533 dd 0 ; (IDT base gets set above)
534 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
535 ; interrupt descriptor table (IDT)
536 ;
537 ; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
538 ; mappings. This implementation only uses the system timer and all other
539 ; IRQs will remain masked. The descriptors for vectors 33+ are provided
540 ; for convenience.
541 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
542
543 ;idt_tag db "IDT",0
544 align 02h
545
546 public IDT_BASE
547 IDT_BASE:
548 ; divide by zero (INT 0)
549 DIV_ZERO_SEL equ $-IDT_BASE
550 dw 0 ; offset 15:0
551 dw SYS_CODE_SEL ; selector 15:0
552 db 0 ; 0 for interrupt gate
553 db 0eh OR 80h ; type = 386 interrupt gate, present
554 dw 0 ; offset 31:16
555
556 ; debug exception (INT 1)
557 DEBUG_EXCEPT_SEL equ $-IDT_BASE
558 dw 0 ; offset 15:0
559 dw SYS_CODE_SEL ; selector 15:0
560 db 0 ; 0 for interrupt gate
561 db 0eh OR 80h ; type = 386 interrupt gate, present
562 dw 0 ; offset 31:16
563
564 ; NMI (INT 2)
565 NMI_SEL equ $-IDT_BASE
566 dw 0 ; offset 15:0
567 dw SYS_CODE_SEL ; selector 15:0
568 db 0 ; 0 for interrupt gate
569 db 0eh OR 80h ; type = 386 interrupt gate, present
570 dw 0 ; offset 31:16
571
572 ; soft breakpoint (INT 3)
573 BREAKPOINT_SEL equ $-IDT_BASE
574 dw 0 ; offset 15:0
575 dw SYS_CODE_SEL ; selector 15:0
576 db 0 ; 0 for interrupt gate
577 db 0eh OR 80h ; type = 386 interrupt gate, present
578 dw 0 ; offset 31:16
579
580 ; overflow (INT 4)
581 OVERFLOW_SEL equ $-IDT_BASE
582 dw 0 ; offset 15:0
583 dw SYS_CODE_SEL ; selector 15:0
584 db 0 ; 0 for interrupt gate
585 db 0eh OR 80h ; type = 386 interrupt gate, present
586 dw 0 ; offset 31:16
587
588 ; bounds check (INT 5)
589 BOUNDS_CHECK_SEL equ $-IDT_BASE
590 dw 0 ; offset 15:0
591 dw SYS_CODE_SEL ; selector 15:0
592 db 0 ; 0 for interrupt gate
593 db 0eh OR 80h ; type = 386 interrupt gate, present
594 dw 0 ; offset 31:16
595
596 ; invalid opcode (INT 6)
597 INVALID_OPCODE_SEL equ $-IDT_BASE
598 dw 0 ; offset 15:0
599 dw SYS_CODE_SEL ; selector 15:0
600 db 0 ; 0 for interrupt gate
601 db 0eh OR 80h ; type = 386 interrupt gate, present
602 dw 0 ; offset 31:16
603
604 ; device not available (INT 7)
605 DEV_NOT_AVAIL_SEL equ $-IDT_BASE
606 dw 0 ; offset 15:0
607 dw SYS_CODE_SEL ; selector 15:0
608 db 0 ; 0 for interrupt gate
609 db 0eh OR 80h ; type = 386 interrupt gate, present
610 dw 0 ; offset 31:16
611
612 ; double fault (INT 8)
613 DOUBLE_FAULT_SEL equ $-IDT_BASE
614 dw 0 ; offset 15:0
615 dw SYS_CODE_SEL ; selector 15:0
616 db 0 ; 0 for interrupt gate
617 db 0eh OR 80h ; type = 386 interrupt gate, present
618 dw 0 ; offset 31:16
619
620 ; Coprocessor segment overrun - reserved (INT 9)
621 RSVD_INTR_SEL1 equ $-IDT_BASE
622 dw 0 ; offset 15:0
623 dw SYS_CODE_SEL ; selector 15:0
624 db 0 ; 0 for interrupt gate
625 db 0eh OR 80h ; type = 386 interrupt gate, present
626 dw 0 ; offset 31:16
627
628 ; invalid TSS (INT 0ah)
629 INVALID_TSS_SEL equ $-IDT_BASE
630 dw 0 ; offset 15:0
631 dw SYS_CODE_SEL ; selector 15:0
632 db 0 ; 0 for interrupt gate
633 db 0eh OR 80h ; type = 386 interrupt gate, present
634 dw 0 ; offset 31:16
635
636 ; segment not present (INT 0bh)
637 SEG_NOT_PRESENT_SEL equ $-IDT_BASE
638 dw 0 ; offset 15:0
639 dw SYS_CODE_SEL ; selector 15:0
640 db 0 ; 0 for interrupt gate
641 db 0eh OR 80h ; type = 386 interrupt gate, present
642 dw 0 ; offset 31:16
643
644 ; stack fault (INT 0ch)
645 STACK_FAULT_SEL equ $-IDT_BASE
646 dw 0 ; offset 15:0
647 dw SYS_CODE_SEL ; selector 15:0
648 db 0 ; 0 for interrupt gate
649 db 0eh OR 80h ; type = 386 interrupt gate, present
650 dw 0 ; offset 31:16
651
652 ; general protection (INT 0dh)
653 GP_FAULT_SEL equ $-IDT_BASE
654 dw 0 ; offset 15:0
655 dw SYS_CODE_SEL ; selector 15:0
656 db 0 ; 0 for interrupt gate
657 db 0eh OR 80h ; type = 386 interrupt gate, present
658 dw 0 ; offset 31:16
659
660 ; page fault (INT 0eh)
661 PAGE_FAULT_SEL equ $-IDT_BASE
662 dw 0 ; offset 15:0
663 dw SYS_CODE_SEL ; selector 15:0
664 db 0 ; 0 for interrupt gate
665 db 0eh OR 80h ; type = 386 interrupt gate, present
666 dw 0 ; offset 31:16
667
668 ; Intel reserved - do not use (INT 0fh)
669 RSVD_INTR_SEL2 equ $-IDT_BASE
670 dw 0 ; offset 15:0
671 dw SYS_CODE_SEL ; selector 15:0
672 db 0 ; 0 for interrupt gate
673 db 0eh OR 80h ; type = 386 interrupt gate, present
674 dw 0 ; offset 31:16
675
676 ; floating point error (INT 10h)
677 FLT_POINT_ERR_SEL equ $-IDT_BASE
678 dw 0 ; offset 15:0
679 dw SYS_CODE_SEL ; selector 15:0
680 db 0 ; 0 for interrupt gate
681 db 0eh OR 80h ; type = 386 interrupt gate, present
682 dw 0 ; offset 31:16
683
684 ; alignment check (INT 11h)
685 ALIGNMENT_CHECK_SEL equ $-IDT_BASE
686 dw 0 ; offset 15:0
687 dw SYS_CODE_SEL ; selector 15:0
688 db 0 ; 0 for interrupt gate
689 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
690 dw 0 ; offset 31:16
691
692 ; machine check (INT 12h)
693 MACHINE_CHECK_SEL equ $-IDT_BASE
694 dw 0 ; offset 15:0
695 dw SYS_CODE_SEL ; selector 15:0
696 db 0 ; 0 for interrupt gate
697 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
698 dw 0 ; offset 31:16
699
700 ; SIMD floating-point exception (INT 13h)
701 SIMD_EXCEPTION_SEL equ $-IDT_BASE
702 dw 0 ; offset 15:0
703 dw SYS_CODE_SEL ; selector 15:0
704 db 0 ; 0 for interrupt gate
705 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
706 dw 0 ; offset 31:16
707
708 ; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
709 db (85 * 8) dup(0)
710
711 ; IRQ 0 (System timer) - (INT 68h)
712 IRQ0_SEL equ $-IDT_BASE
713 dw 0 ; offset 15:0
714 dw SYS_CODE_SEL ; selector 15:0
715 db 0 ; 0 for interrupt gate
716 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
717 dw 0 ; offset 31:16
718
719 ; IRQ 1 (8042 Keyboard controller) - (INT 69h)
720 IRQ1_SEL equ $-IDT_BASE
721 dw 0 ; offset 15:0
722 dw SYS_CODE_SEL ; selector 15:0
723 db 0 ; 0 for interrupt gate
724 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
725 dw 0 ; offset 31:16
726
727 ; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
728 IRQ2_SEL equ $-IDT_BASE
729 dw 0 ; offset 15:0
730 dw SYS_CODE_SEL ; selector 15:0
731 db 0 ; 0 for interrupt gate
732 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
733 dw 0 ; offset 31:16
734
735 ; IRQ 3 (COM 2) - (INT 6bh)
736 IRQ3_SEL equ $-IDT_BASE
737 dw 0 ; offset 15:0
738 dw SYS_CODE_SEL ; selector 15:0
739 db 0 ; 0 for interrupt gate
740 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
741 dw 0 ; offset 31:16
742
743 ; IRQ 4 (COM 1) - (INT 6ch)
744 IRQ4_SEL equ $-IDT_BASE
745 dw 0 ; offset 15:0
746 dw SYS_CODE_SEL ; selector 15:0
747 db 0 ; 0 for interrupt gate
748 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
749 dw 0 ; offset 31:16
750
751 ; IRQ 5 (LPT 2) - (INT 6dh)
752 IRQ5_SEL equ $-IDT_BASE
753 dw 0 ; offset 15:0
754 dw SYS_CODE_SEL ; selector 15:0
755 db 0 ; 0 for interrupt gate
756 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
757 dw 0 ; offset 31:16
758
759 ; IRQ 6 (Floppy controller) - (INT 6eh)
760 IRQ6_SEL equ $-IDT_BASE
761 dw 0 ; offset 15:0
762 dw SYS_CODE_SEL ; selector 15:0
763 db 0 ; 0 for interrupt gate
764 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
765 dw 0 ; offset 31:16
766
767 ; IRQ 7 (LPT 1) - (INT 6fh)
768 IRQ7_SEL equ $-IDT_BASE
769 dw 0 ; offset 15:0
770 dw SYS_CODE_SEL ; selector 15:0
771 db 0 ; 0 for interrupt gate
772 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
773 dw 0 ; offset 31:16
774
775 ; IRQ 8 (RTC Alarm) - (INT 70h)
776 IRQ8_SEL equ $-IDT_BASE
777 dw 0 ; offset 15:0
778 dw SYS_CODE_SEL ; selector 15:0
779 db 0 ; 0 for interrupt gate
780 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
781 dw 0 ; offset 31:16
782
783 ; IRQ 9 - (INT 71h)
784 IRQ9_SEL equ $-IDT_BASE
785 dw 0 ; offset 15:0
786 dw SYS_CODE_SEL ; selector 15:0
787 db 0 ; 0 for interrupt gate
788 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
789 dw 0 ; offset 31:16
790
791 ; IRQ 10 - (INT 72h)
792 IRQ10_SEL equ $-IDT_BASE
793 dw 0 ; offset 15:0
794 dw SYS_CODE_SEL ; selector 15:0
795 db 0 ; 0 for interrupt gate
796 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
797 dw 0 ; offset 31:16
798
799 ; IRQ 11 - (INT 73h)
800 IRQ11_SEL equ $-IDT_BASE
801 dw 0 ; offset 15:0
802 dw SYS_CODE_SEL ; selector 15:0
803 db 0 ; 0 for interrupt gate
804 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
805 dw 0 ; offset 31:16
806
807 ; IRQ 12 (PS/2 mouse) - (INT 74h)
808 IRQ12_SEL equ $-IDT_BASE
809 dw 0 ; offset 15:0
810 dw SYS_CODE_SEL ; selector 15:0
811 db 0 ; 0 for interrupt gate
812 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
813 dw 0 ; offset 31:16
814
815 ; IRQ 13 (Floating point error) - (INT 75h)
816 IRQ13_SEL equ $-IDT_BASE
817 dw 0 ; offset 15:0
818 dw SYS_CODE_SEL ; selector 15:0
819 db 0 ; 0 for interrupt gate
820 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
821 dw 0 ; offset 31:16
822
823 ; IRQ 14 (Secondary IDE) - (INT 76h)
824 IRQ14_SEL equ $-IDT_BASE
825 dw 0 ; offset 15:0
826 dw SYS_CODE_SEL ; selector 15:0
827 db 0 ; 0 for interrupt gate
828 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
829 dw 0 ; offset 31:16
830
831 ; IRQ 15 (Primary IDE) - (INT 77h)
832 IRQ15_SEL equ $-IDT_BASE
833 dw 0 ; offset 15:0
834 dw SYS_CODE_SEL ; selector 15:0
835 db 0 ; 0 for interrupt gate
836 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
837 dw 0 ; offset 31:16
838
839 IDT_END:
840
841 align 02h
842
843 MemoryMapSize dd 0
844 MemoryMap dd 0,0,0,0,0,0,0,0
845 dd 0,0,0,0,0,0,0,0
846 dd 0,0,0,0,0,0,0,0
847 dd 0,0,0,0,0,0,0,0
848 dd 0,0,0,0,0,0,0,0
849 dd 0,0,0,0,0,0,0,0
850 dd 0,0,0,0,0,0,0,0
851 dd 0,0,0,0,0,0,0,0
852 dd 0,0,0,0,0,0,0,0
853 dd 0,0,0,0,0,0,0,0
854 dd 0,0,0,0,0,0,0,0
855 dd 0,0,0,0,0,0,0,0
856 dd 0,0,0,0,0,0,0,0
857 dd 0,0,0,0,0,0,0,0
858 dd 0,0,0,0,0,0,0,0
859 dd 0,0,0,0,0,0,0,0
860 dd 0,0,0,0,0,0,0,0
861 dd 0,0,0,0,0,0,0,0
862 dd 0,0,0,0,0,0,0,0
863 dd 0,0,0,0,0,0,0,0
864 dd 0,0,0,0,0,0,0,0
865 dd 0,0,0,0,0,0,0,0
866 dd 0,0,0,0,0,0,0,0
867 dd 0,0,0,0,0,0,0,0
868 dd 0,0,0,0,0,0,0,0
869 dd 0,0,0,0,0,0,0,0
870 dd 0,0,0,0,0,0,0,0
871 dd 0,0,0,0,0,0,0,0
872 dd 0,0,0,0,0,0,0,0
873 dd 0,0,0,0,0,0,0,0
874
875 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
876 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
877
878 org 0fe0h
879 MyStack:
880 ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
881 ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
882 ; known low address (20f00) so it can be set up by PlMapIrqToVect in
883 ; 8259.c
884
885 int 8
886 iret
887
888 int 9
889 iret
890
891 int 10
892 iret
893
894 int 11
895 iret
896
897 int 12
898 iret
899
900 int 13
901 iret
902
903 int 14
904 iret
905
906 int 15
907 iret
908
909
910 org 0ffeh
911 BlockSignature:
912 dw 0aa55h
913
914 end