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