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