]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/BootSector/start.asm
DuetPkg BootSector:
[mirror_edk2.git] / DuetPkg / BootSector / start.asm
1 ;------------------------------------------------------------------------------
2 ;*
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
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 ;* start.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 "FAT12 " ; 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,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
154 push si ; Save si
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
160 je SkipFatRead
161 mov bx,2
162 push es
163 push ds
164 pop es
165 call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI
166 pop es
167 mov dx,ax ; CachedFatSectorNumber = FatSectorNumber
168 SkipFatRead:
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
172 je EvenFatEntry
173 shr bx,4 ; NextClusterNumber = NextClusterNumber >> 4
174 EvenFatEntry:
175 and bx,0fffh ; Strip upper 4 bits of NextClusterNumber
176 pop si ; Restore si
177 dec bx ; bx = NextClusterNumber - 1
178 cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber
179 jne ReadClusters
180 inc bx ; bx = NextClusterNumber
181 inc si ; NumberOfClusters++
182 mov cx,bx ; ClusterNumber = NextClusterNumber
183 jmp FatChainLoop
184 ReadClusters:
185 inc bx
186 pop ax ; ax = StartCluster
187 push bx ; StartCluster = NextClusterNumber
188 mov cx,bx ; ClusterNumber = NextClusterNumber
189 sub ax,2 ; ax = StartCluster - 2
190 xor bh,bh
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
199 call ReadBlocks
200 mov si,1 ; NumberOfClusters = 1
201 jmp FatChainLoop
202 FoundLastCluster:
203 pop cx
204 popa
205 ret
206
207
208 ; ****************************************************************************
209 ; ReadBlocks - Reads a set of blocks from a block device
210 ;
211 ; AX = Start LBA
212 ; BX = Number of Blocks to Read
213 ; ES:DI = Buffer to store sectors read from disk
214 ; ****************************************************************************
215
216 ; cx = Blocks
217 ; bx = NumberOfBlocks
218 ; si = StartLBA
219
220 ReadBlocks:
221 pusha
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
226 ReadCylinderLoop:
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
233
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)
238 jg LimitTransfer
239 mov bx,cx ; bx = Blocks
240 LimitTransfer:
241 push ax ; save ax
242 mov ax,es ; ax = es
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:
251 pop ax ; restore ax
252
253 push cx
254 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector
255 xor dx,dx ; dx = 0
256 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder
257 ; dx = ax % (MaxHead + 1) = Head
258
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
267 int 013h
268 jc DiskError
269 pop bx
270 pop cx
271 movzx ebx,bx
272 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks
273 sub cx,bx ; Blocks = Blocks - NumberOfBlocks
274 mov ax,es
275 shl bx,(BLOCK_SHIFT-4)
276 add ax,bx
277 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
278 cmp cx,0
279 jne ReadCylinderLoop
280 popa
281 ret
282
283 DiskError:
284 push cs
285 pop ds
286 lea si, [ErrorString]
287 mov cx, 7
288 jmp PrintStringAndHalt
289
290 PrintStringAndHalt:
291 mov ax,0b800h
292 mov es,ax
293 mov di,160
294 rep movsw
295 Halt:
296 jmp Halt
297
298 ErrorString:
299 db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
300
301 org 01fah
302 LBAOffsetForBootSector:
303 dd 0h
304
305 org 01feh
306 dw 0aa55h
307
308 ;******************************************************************************
309 ;******************************************************************************
310 ;******************************************************************************
311
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
317
318 org 200h
319 jmp start
320 Em64String:
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
322
323 start:
324 mov ax,cs
325 mov ds,ax
326 mov es,ax
327 mov ss,ax
328 mov sp,MyStack
329
330 ; mov ax,0b800h
331 ; mov es,ax
332 ; mov byte ptr es:[160],'a'
333 ; mov ax,cs
334 ; mov es,ax
335
336 mov ebx,0
337 lea edi,MemoryMap
338 MemMapLoop:
339 mov eax,0e820h
340 mov ecx,20
341 mov edx,'SMAP'
342 int 15h
343 jc MemMapDone
344 add edi,20
345 cmp ebx,0
346 je MemMapDone
347 jmp MemMapLoop
348 MemMapDone:
349 lea eax,MemoryMap
350 sub edi,eax ; Get the address of the memory map
351 mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map
352
353 xor ebx,ebx
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
361
362 add ebx,01000h ; Source of EFI32
363 mov dword ptr [JUMP+2],ebx
364 add ebx,01000h
365 mov esi,ebx ; Source of EFILDR32
366
367 ; mov ax,0b800h
368 ; mov es,ax
369 ; mov byte ptr es:[162],'b'
370 ; mov ax,cs
371 ; mov es,ax
372
373 ;
374 ; Enable A20 Gate
375 ;
376
377 mov ax,2401h ; Enable A20 Gate
378 int 15h
379 jnc A20GateEnabled ; Jump if it suceeded
380
381 ;
382 ; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
383 ;
384
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
396 Delay25uS:
397 out DELAY_PORT,ax ; Delay 1 uS
398 loop Delay25uS
399 Timeout8042:
400
401
402 A20GateEnabled:
403 mov bx,0008h ; Flat data descriptor
404 ;
405 ; DISABLE INTERRUPTS - Entering Protected Mode
406 ;
407
408 cli
409
410 ; mov ax,0b800h
411 ; mov es,ax
412 ; mov byte ptr es:[164],'c'
413 ; mov ax,cs
414 ; mov es,ax
415
416 db 66h
417 lgdt fword ptr [gdtr]
418 db 66h
419 lidt fword ptr [idtr]
420
421 mov eax,cr0
422 or al,1
423 mov cr0,eax
424 JUMP:
425 ; jmp far 0010:00020000
426 db 066h
427 db 0eah
428 dd 000020000h
429 dw 00010h
430
431 Empty8042InputBuffer:
432 mov cx,0
433 Empty8042Loop:
434 out DELAY_PORT,ax ; Delay 1us
435 in al,KBD_STATUS_PORT ; Read the 8042 Status Port
436 and al,02h ; Check the Input Buffer Full Flag
437 loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS
438 ret
439
440 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
441 ; data
442 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
443
444 align 02h
445
446 gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
447 dd 0 ; (GDT base gets set above)
448 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
449 ; global descriptor table (GDT)
450 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
451
452 align 02h
453
454 public GDT_BASE
455 GDT_BASE:
456 ; null descriptor
457 NULL_SEL equ $-GDT_BASE
458 dw 0 ; limit 15:0
459 dw 0 ; base 15:0
460 db 0 ; base 23:16
461 db 0 ; type
462 db 0 ; limit 19:16, flags
463 db 0 ; base 31:24
464
465 ; linear data segment descriptor
466 LINEAR_SEL equ $-GDT_BASE
467 dw 0FFFFh ; limit 0xFFFFF
468 dw 0 ; base 0
469 db 0
470 db 092h ; present, ring 0, data, expand-up, writable
471 db 0CFh ; page-granular, 32-bit
472 db 0
473
474 ; linear code segment descriptor
475 LINEAR_CODE_SEL equ $-GDT_BASE
476 dw 0FFFFh ; limit 0xFFFFF
477 dw 0 ; base 0
478 db 0
479 db 09Ah ; present, ring 0, data, expand-up, writable
480 db 0CFh ; page-granular, 32-bit
481 db 0
482
483 ; system data segment descriptor
484 SYS_DATA_SEL equ $-GDT_BASE
485 dw 0FFFFh ; limit 0xFFFFF
486 dw 0 ; base 0
487 db 0
488 db 092h ; present, ring 0, data, expand-up, writable
489 db 0CFh ; page-granular, 32-bit
490 db 0
491
492 ; system code segment descriptor
493 SYS_CODE_SEL equ $-GDT_BASE
494 dw 0FFFFh ; limit 0xFFFFF
495 dw 0 ; base 0
496 db 0
497 db 09Ah ; present, ring 0, data, expand-up, writable
498 db 0CFh ; page-granular, 32-bit
499 db 0
500
501 ; spare segment descriptor
502 SPARE3_SEL equ $-GDT_BASE
503 dw 0 ; limit 0xFFFFF
504 dw 0 ; base 0
505 db 0
506 db 0 ; present, ring 0, data, expand-up, writable
507 db 0 ; page-granular, 32-bit
508 db 0
509
510 ; spare segment descriptor
511 SPARE4_SEL equ $-GDT_BASE
512 dw 0 ; limit 0xFFFFF
513 dw 0 ; base 0
514 db 0
515 db 0 ; present, ring 0, data, expand-up, writable
516 db 0 ; page-granular, 32-bit
517 db 0
518
519 ; spare segment descriptor
520 SPARE5_SEL equ $-GDT_BASE
521 dw 0 ; limit 0xFFFFF
522 dw 0 ; base 0
523 db 0
524 db 0 ; present, ring 0, data, expand-up, writable
525 db 0 ; page-granular, 32-bit
526 db 0
527
528 GDT_END:
529
530 align 02h
531
532
533
534 idtr dw IDT_END - IDT_BASE - 1 ; IDT limit
535 dd 0 ; (IDT base gets set above)
536 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
537 ; interrupt descriptor table (IDT)
538 ;
539 ; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
540 ; mappings. This implementation only uses the system timer and all other
541 ; IRQs will remain masked. The descriptors for vectors 33+ are provided
542 ; for convenience.
543 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
544
545 ;idt_tag db "IDT",0
546 align 02h
547
548 public IDT_BASE
549 IDT_BASE:
550 ; divide by zero (INT 0)
551 DIV_ZERO_SEL equ $-IDT_BASE
552 dw 0 ; offset 15:0
553 dw SYS_CODE_SEL ; selector 15:0
554 db 0 ; 0 for interrupt gate
555 db 0eh OR 80h ; type = 386 interrupt gate, present
556 dw 0 ; offset 31:16
557
558 ; debug exception (INT 1)
559 DEBUG_EXCEPT_SEL equ $-IDT_BASE
560 dw 0 ; offset 15:0
561 dw SYS_CODE_SEL ; selector 15:0
562 db 0 ; 0 for interrupt gate
563 db 0eh OR 80h ; type = 386 interrupt gate, present
564 dw 0 ; offset 31:16
565
566 ; NMI (INT 2)
567 NMI_SEL equ $-IDT_BASE
568 dw 0 ; offset 15:0
569 dw SYS_CODE_SEL ; selector 15:0
570 db 0 ; 0 for interrupt gate
571 db 0eh OR 80h ; type = 386 interrupt gate, present
572 dw 0 ; offset 31:16
573
574 ; soft breakpoint (INT 3)
575 BREAKPOINT_SEL equ $-IDT_BASE
576 dw 0 ; offset 15:0
577 dw SYS_CODE_SEL ; selector 15:0
578 db 0 ; 0 for interrupt gate
579 db 0eh OR 80h ; type = 386 interrupt gate, present
580 dw 0 ; offset 31:16
581
582 ; overflow (INT 4)
583 OVERFLOW_SEL equ $-IDT_BASE
584 dw 0 ; offset 15:0
585 dw SYS_CODE_SEL ; selector 15:0
586 db 0 ; 0 for interrupt gate
587 db 0eh OR 80h ; type = 386 interrupt gate, present
588 dw 0 ; offset 31:16
589
590 ; bounds check (INT 5)
591 BOUNDS_CHECK_SEL equ $-IDT_BASE
592 dw 0 ; offset 15:0
593 dw SYS_CODE_SEL ; selector 15:0
594 db 0 ; 0 for interrupt gate
595 db 0eh OR 80h ; type = 386 interrupt gate, present
596 dw 0 ; offset 31:16
597
598 ; invalid opcode (INT 6)
599 INVALID_OPCODE_SEL equ $-IDT_BASE
600 dw 0 ; offset 15:0
601 dw SYS_CODE_SEL ; selector 15:0
602 db 0 ; 0 for interrupt gate
603 db 0eh OR 80h ; type = 386 interrupt gate, present
604 dw 0 ; offset 31:16
605
606 ; device not available (INT 7)
607 DEV_NOT_AVAIL_SEL equ $-IDT_BASE
608 dw 0 ; offset 15:0
609 dw SYS_CODE_SEL ; selector 15:0
610 db 0 ; 0 for interrupt gate
611 db 0eh OR 80h ; type = 386 interrupt gate, present
612 dw 0 ; offset 31:16
613
614 ; double fault (INT 8)
615 DOUBLE_FAULT_SEL equ $-IDT_BASE
616 dw 0 ; offset 15:0
617 dw SYS_CODE_SEL ; selector 15:0
618 db 0 ; 0 for interrupt gate
619 db 0eh OR 80h ; type = 386 interrupt gate, present
620 dw 0 ; offset 31:16
621
622 ; Coprocessor segment overrun - reserved (INT 9)
623 RSVD_INTR_SEL1 equ $-IDT_BASE
624 dw 0 ; offset 15:0
625 dw SYS_CODE_SEL ; selector 15:0
626 db 0 ; 0 for interrupt gate
627 db 0eh OR 80h ; type = 386 interrupt gate, present
628 dw 0 ; offset 31:16
629
630 ; invalid TSS (INT 0ah)
631 INVALID_TSS_SEL equ $-IDT_BASE
632 dw 0 ; offset 15:0
633 dw SYS_CODE_SEL ; selector 15:0
634 db 0 ; 0 for interrupt gate
635 db 0eh OR 80h ; type = 386 interrupt gate, present
636 dw 0 ; offset 31:16
637
638 ; segment not present (INT 0bh)
639 SEG_NOT_PRESENT_SEL equ $-IDT_BASE
640 dw 0 ; offset 15:0
641 dw SYS_CODE_SEL ; selector 15:0
642 db 0 ; 0 for interrupt gate
643 db 0eh OR 80h ; type = 386 interrupt gate, present
644 dw 0 ; offset 31:16
645
646 ; stack fault (INT 0ch)
647 STACK_FAULT_SEL equ $-IDT_BASE
648 dw 0 ; offset 15:0
649 dw SYS_CODE_SEL ; selector 15:0
650 db 0 ; 0 for interrupt gate
651 db 0eh OR 80h ; type = 386 interrupt gate, present
652 dw 0 ; offset 31:16
653
654 ; general protection (INT 0dh)
655 GP_FAULT_SEL equ $-IDT_BASE
656 dw 0 ; offset 15:0
657 dw SYS_CODE_SEL ; selector 15:0
658 db 0 ; 0 for interrupt gate
659 db 0eh OR 80h ; type = 386 interrupt gate, present
660 dw 0 ; offset 31:16
661
662 ; page fault (INT 0eh)
663 PAGE_FAULT_SEL equ $-IDT_BASE
664 dw 0 ; offset 15:0
665 dw SYS_CODE_SEL ; selector 15:0
666 db 0 ; 0 for interrupt gate
667 db 0eh OR 80h ; type = 386 interrupt gate, present
668 dw 0 ; offset 31:16
669
670 ; Intel reserved - do not use (INT 0fh)
671 RSVD_INTR_SEL2 equ $-IDT_BASE
672 dw 0 ; offset 15:0
673 dw SYS_CODE_SEL ; selector 15:0
674 db 0 ; 0 for interrupt gate
675 db 0eh OR 80h ; type = 386 interrupt gate, present
676 dw 0 ; offset 31:16
677
678 ; floating point error (INT 10h)
679 FLT_POINT_ERR_SEL equ $-IDT_BASE
680 dw 0 ; offset 15:0
681 dw SYS_CODE_SEL ; selector 15:0
682 db 0 ; 0 for interrupt gate
683 db 0eh OR 80h ; type = 386 interrupt gate, present
684 dw 0 ; offset 31:16
685
686 ; alignment check (INT 11h)
687 ALIGNMENT_CHECK_SEL equ $-IDT_BASE
688 dw 0 ; offset 15:0
689 dw SYS_CODE_SEL ; selector 15:0
690 db 0 ; 0 for interrupt gate
691 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
692 dw 0 ; offset 31:16
693
694 ; machine check (INT 12h)
695 MACHINE_CHECK_SEL equ $-IDT_BASE
696 dw 0 ; offset 15:0
697 dw SYS_CODE_SEL ; selector 15:0
698 db 0 ; 0 for interrupt gate
699 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
700 dw 0 ; offset 31:16
701
702 ; SIMD floating-point exception (INT 13h)
703 SIMD_EXCEPTION_SEL equ $-IDT_BASE
704 dw 0 ; offset 15:0
705 dw SYS_CODE_SEL ; selector 15:0
706 db 0 ; 0 for interrupt gate
707 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
708 dw 0 ; offset 31:16
709
710 ; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
711 db (85 * 8) dup(0)
712
713 ; IRQ 0 (System timer) - (INT 68h)
714 IRQ0_SEL equ $-IDT_BASE
715 dw 0 ; offset 15:0
716 dw SYS_CODE_SEL ; selector 15:0
717 db 0 ; 0 for interrupt gate
718 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
719 dw 0 ; offset 31:16
720
721 ; IRQ 1 (8042 Keyboard controller) - (INT 69h)
722 IRQ1_SEL equ $-IDT_BASE
723 dw 0 ; offset 15:0
724 dw SYS_CODE_SEL ; selector 15:0
725 db 0 ; 0 for interrupt gate
726 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
727 dw 0 ; offset 31:16
728
729 ; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
730 IRQ2_SEL equ $-IDT_BASE
731 dw 0 ; offset 15:0
732 dw SYS_CODE_SEL ; selector 15:0
733 db 0 ; 0 for interrupt gate
734 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
735 dw 0 ; offset 31:16
736
737 ; IRQ 3 (COM 2) - (INT 6bh)
738 IRQ3_SEL equ $-IDT_BASE
739 dw 0 ; offset 15:0
740 dw SYS_CODE_SEL ; selector 15:0
741 db 0 ; 0 for interrupt gate
742 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
743 dw 0 ; offset 31:16
744
745 ; IRQ 4 (COM 1) - (INT 6ch)
746 IRQ4_SEL equ $-IDT_BASE
747 dw 0 ; offset 15:0
748 dw SYS_CODE_SEL ; selector 15:0
749 db 0 ; 0 for interrupt gate
750 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
751 dw 0 ; offset 31:16
752
753 ; IRQ 5 (LPT 2) - (INT 6dh)
754 IRQ5_SEL equ $-IDT_BASE
755 dw 0 ; offset 15:0
756 dw SYS_CODE_SEL ; selector 15:0
757 db 0 ; 0 for interrupt gate
758 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
759 dw 0 ; offset 31:16
760
761 ; IRQ 6 (Floppy controller) - (INT 6eh)
762 IRQ6_SEL equ $-IDT_BASE
763 dw 0 ; offset 15:0
764 dw SYS_CODE_SEL ; selector 15:0
765 db 0 ; 0 for interrupt gate
766 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
767 dw 0 ; offset 31:16
768
769 ; IRQ 7 (LPT 1) - (INT 6fh)
770 IRQ7_SEL equ $-IDT_BASE
771 dw 0 ; offset 15:0
772 dw SYS_CODE_SEL ; selector 15:0
773 db 0 ; 0 for interrupt gate
774 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
775 dw 0 ; offset 31:16
776
777 ; IRQ 8 (RTC Alarm) - (INT 70h)
778 IRQ8_SEL equ $-IDT_BASE
779 dw 0 ; offset 15:0
780 dw SYS_CODE_SEL ; selector 15:0
781 db 0 ; 0 for interrupt gate
782 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
783 dw 0 ; offset 31:16
784
785 ; IRQ 9 - (INT 71h)
786 IRQ9_SEL equ $-IDT_BASE
787 dw 0 ; offset 15:0
788 dw SYS_CODE_SEL ; selector 15:0
789 db 0 ; 0 for interrupt gate
790 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
791 dw 0 ; offset 31:16
792
793 ; IRQ 10 - (INT 72h)
794 IRQ10_SEL equ $-IDT_BASE
795 dw 0 ; offset 15:0
796 dw SYS_CODE_SEL ; selector 15:0
797 db 0 ; 0 for interrupt gate
798 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
799 dw 0 ; offset 31:16
800
801 ; IRQ 11 - (INT 73h)
802 IRQ11_SEL equ $-IDT_BASE
803 dw 0 ; offset 15:0
804 dw SYS_CODE_SEL ; selector 15:0
805 db 0 ; 0 for interrupt gate
806 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
807 dw 0 ; offset 31:16
808
809 ; IRQ 12 (PS/2 mouse) - (INT 74h)
810 IRQ12_SEL equ $-IDT_BASE
811 dw 0 ; offset 15:0
812 dw SYS_CODE_SEL ; selector 15:0
813 db 0 ; 0 for interrupt gate
814 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
815 dw 0 ; offset 31:16
816
817 ; IRQ 13 (Floating point error) - (INT 75h)
818 IRQ13_SEL equ $-IDT_BASE
819 dw 0 ; offset 15:0
820 dw SYS_CODE_SEL ; selector 15:0
821 db 0 ; 0 for interrupt gate
822 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
823 dw 0 ; offset 31:16
824
825 ; IRQ 14 (Secondary IDE) - (INT 76h)
826 IRQ14_SEL equ $-IDT_BASE
827 dw 0 ; offset 15:0
828 dw SYS_CODE_SEL ; selector 15:0
829 db 0 ; 0 for interrupt gate
830 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
831 dw 0 ; offset 31:16
832
833 ; IRQ 15 (Primary IDE) - (INT 77h)
834 IRQ15_SEL equ $-IDT_BASE
835 dw 0 ; offset 15:0
836 dw SYS_CODE_SEL ; selector 15:0
837 db 0 ; 0 for interrupt gate
838 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present
839 dw 0 ; offset 31:16
840
841 IDT_END:
842
843 align 02h
844
845 MemoryMapSize dd 0
846 MemoryMap 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 dd 0,0,0,0,0,0,0,0
875 dd 0,0,0,0,0,0,0,0
876
877 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
878 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
879
880 org 0fe0h
881 MyStack:
882 ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
883 ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a
884 ; known low address (20f00) so it can be set up by PlMapIrqToVect in
885 ; 8259.c
886
887 int 8
888 iret
889
890 int 9
891 iret
892
893 int 10
894 iret
895
896 int 11
897 iret
898
899 int 12
900 iret
901
902 int 13
903 iret
904
905 int 14
906 iret
907
908 int 15
909 iret
910
911
912 org 0ffeh
913 BlockSignature:
914 dw 0aa55h
915
916 end