]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/BootSector/st16_64.asm
Remove exit from batch file
[mirror_edk2.git] / DuetPkg / BootSector / st16_64.asm
CommitLineData
c69dd9df 1;------------------------------------------------------------------------------\r
2;*\r
3;* Copyright 2006 - 2007, Intel Corporation \r
4;* All rights reserved. This program and the accompanying materials \r
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;* st16_64.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
114CheckEm64T:\r
115 mov eax, 080000001h\r
116; cpuid\r
117 dw 0A20Fh\r
118 bt edx, 29\r
119 jc CheckEm64TPass\r
120 push cs\r
121 pop ds\r
122 lea si, [Em64String]\r
123 mov cx, 18\r
124 jmp PrintStringAndHalt\r
125CheckEm64TPass:\r
126JumpFarInstruction:\r
127 db 0eah\r
128JumpOffset:\r
129 dw 0200h\r
130JumpSegment:\r
131 dw 2000h\r
132\r
133\r
134\r
135; ****************************************************************************\r
136; ReadFile\r
137;\r
138; Arguments:\r
139; CX = Start Cluster of File\r
140; ES:DI = Buffer to store file content read from disk\r
141;\r
142; Return:\r
143; (ES << 4 + DI) = end of file content Buffer\r
144;\r
145; ****************************************************************************\r
146ReadFile:\r
147; si = NumberOfClusters\r
148; cx = ClusterNumber\r
149; dx = CachedFatSectorNumber\r
150; ds:0000 = CacheFatSectorBuffer\r
151; es:di = Buffer to load file\r
152; bx = NextClusterNumber\r
153 pusha\r
154 mov si,1 ; NumberOfClusters = 1\r
155 push cx ; Push Start Cluster onto stack\r
156 mov dx,0fffh ; CachedFatSectorNumber = 0xfff\r
157FatChainLoop:\r
158 mov ax,cx ; ax = ClusterNumber \r
159 and ax,0fff8h ; ax = ax & 0xfff8\r
160 cmp ax,0fff8h ; See if this is the last cluster\r
161 je FoundLastCluster ; Jump if last cluster found\r
162 mov ax,cx ; ax = ClusterNumber\r
163 shl ax,1 ; FatOffset = ClusterNumber * 2\r
164 push si ; Save si\r
165 mov si,ax ; si = FatOffset\r
166 shr ax,BLOCK_SHIFT ; ax = FatOffset >> BLOCK_SHIFT\r
167 add ax,word ptr [bp+ReservedSectors] ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)\r
168 and si,BLOCK_MASK ; si = FatOffset & BLOCK_MASK\r
169 cmp ax,dx ; Compare FatSectorNumber to CachedFatSectorNumber\r
170 je SkipFatRead\r
171 mov bx,2 \r
172 push es\r
173 push ds\r
174 pop es\r
175 call ReadBlocks ; Read 2 blocks starting at AX storing at ES:DI\r
176 pop es\r
177 mov dx,ax ; CachedFatSectorNumber = FatSectorNumber\r
178SkipFatRead:\r
179 mov bx,word ptr [si] ; bx = NextClusterNumber\r
180 mov ax,cx ; ax = ClusterNumber\r
181 pop si ; Restore si\r
182 dec bx ; bx = NextClusterNumber - 1\r
183 cmp bx,cx ; See if (NextClusterNumber-1)==ClusterNumber\r
184 jne ReadClusters\r
185 inc bx ; bx = NextClusterNumber\r
186 inc si ; NumberOfClusters++\r
187 mov cx,bx ; ClusterNumber = NextClusterNumber\r
188 jmp FatChainLoop\r
189ReadClusters:\r
190 inc bx\r
191 pop ax ; ax = StartCluster\r
192 push bx ; StartCluster = NextClusterNumber\r
193 mov cx,bx ; ClusterNumber = NextClusterNumber\r
194 sub ax,2 ; ax = StartCluster - 2\r
195 xor bh,bh \r
196 mov bl,byte ptr [bp+SectorsPerCluster] ; bx = SectorsPerCluster\r
197 mul bx ; ax = (StartCluster - 2) * SectorsPerCluster\r
198 add ax, word ptr [bp] ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster\r
199 push ax ; save start sector\r
200 mov ax,si ; ax = NumberOfClusters\r
201 mul bx ; ax = NumberOfClusters * SectorsPerCluster\r
202 mov bx,ax ; bx = Number of Sectors\r
203 pop ax ; ax = Start Sector\r
204 call ReadBlocks\r
205 mov si,1 ; NumberOfClusters = 1\r
206 jmp FatChainLoop\r
207FoundLastCluster:\r
208 pop cx\r
209 popa\r
210 ret\r
211\r
212\r
213; ****************************************************************************\r
214; ReadBlocks - Reads a set of blocks from a block device\r
215;\r
216; AX = Start LBA\r
217; BX = Number of Blocks to Read\r
218; ES:DI = Buffer to store sectors read from disk\r
219; ****************************************************************************\r
220\r
221; cx = Blocks\r
222; bx = NumberOfBlocks\r
223; si = StartLBA\r
224\r
225ReadBlocks:\r
226 pusha\r
227 add eax,dword ptr [bp+LBAOffsetForBootSector] ; Add LBAOffsetForBootSector to Start LBA\r
228 add eax,dword ptr [bp+HiddenSectors] ; Add HiddenSectors to Start LBA\r
229 mov esi,eax ; esi = Start LBA\r
230 mov cx,bx ; cx = Number of blocks to read\r
231ReadCylinderLoop:\r
232 mov bp,07bfch ; bp = 0x7bfc\r
233 mov eax,esi ; eax = Start LBA\r
234 xor edx,edx ; edx = 0\r
235 movzx ebx,word ptr [bp] ; bx = MaxSector\r
236 div ebx ; ax = StartLBA / MaxSector\r
237 inc dx ; dx = (StartLBA % MaxSector) + 1\r
238\r
239 mov bx,word ptr [bp] ; bx = MaxSector\r
240 sub bx,dx ; bx = MaxSector - Sector\r
241 inc bx ; bx = MaxSector - Sector + 1\r
242 cmp cx,bx ; Compare (Blocks) to (MaxSector - Sector + 1)\r
243 jg LimitTransfer\r
244 mov bx,cx ; bx = Blocks\r
245LimitTransfer:\r
246 push ax ; save ax\r
247 mov ax,es ; ax = es\r
248 shr ax,(BLOCK_SHIFT-4) ; ax = Number of blocks into mem system\r
249 and ax,07fh ; ax = Number of blocks into current seg\r
250 add ax,bx ; ax = End Block number of transfer\r
251 cmp ax,080h ; See if it crosses a 64K boundry\r
252 jle NotCrossing64KBoundry ; Branch if not crossing 64K boundry\r
253 sub ax,080h ; ax = Number of blocks past 64K boundry\r
254 sub bx,ax ; Decrease transfer size by block overage\r
255NotCrossing64KBoundry:\r
256 pop ax ; restore ax\r
257\r
258 push cx\r
259 mov cl,dl ; cl = (StartLBA % MaxSector) + 1 = Sector\r
260 xor dx,dx ; dx = 0\r
261 div word ptr [bp+2] ; ax = ax / (MaxHead + 1) = Cylinder \r
262 ; dx = ax % (MaxHead + 1) = Head\r
263\r
264 push bx ; Save number of blocks to transfer\r
265 mov dh,dl ; dh = Head\r
266 mov bp,07c00h ; bp = 0x7c00\r
267 mov dl,byte ptr [bp+PhysicalDrive] ; dl = Drive Number\r
268 mov ch,al ; ch = Cylinder\r
269 mov al,bl ; al = Blocks\r
270 mov ah,2 ; ah = Function 2\r
271 mov bx,di ; es:bx = Buffer address\r
272 int 013h\r
273 jc DiskError\r
274 pop bx\r
275 pop cx\r
276 movzx ebx,bx\r
277 add esi,ebx ; StartLBA = StartLBA + NumberOfBlocks\r
278 sub cx,bx ; Blocks = Blocks - NumberOfBlocks\r
279 mov ax,es\r
280 shl bx,(BLOCK_SHIFT-4)\r
281 add ax,bx\r
282 mov es,ax ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE\r
283 cmp cx,0\r
284 jne ReadCylinderLoop\r
285 popa\r
286 ret\r
287\r
288DiskError:\r
289 push cs\r
290 pop ds\r
291 lea si, [ErrorString]\r
292 mov cx, 7\r
293 jmp PrintStringAndHalt\r
294\r
295PrintStringAndHalt:\r
296 mov ax,0b800h\r
297 mov es,ax\r
298 mov di,160\r
299 rep movsw\r
300Halt:\r
301 jmp Halt\r
302\r
303ErrorString:\r
304 db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch\r
305\r
306 org 01fah\r
307LBAOffsetForBootSector:\r
308 dd 0h\r
309\r
310 org 01feh\r
311 dw 0aa55h\r
312\r
313;******************************************************************************\r
314;******************************************************************************\r
315;******************************************************************************\r
316\r
317DELAY_PORT equ 0edh ; Port to use for 1uS delay\r
318KBD_CONTROL_PORT equ 060h ; 8042 control port \r
319KBD_STATUS_PORT equ 064h ; 8042 status port \r
320WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port\r
321ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20\r
322\r
323 org 200h\r
324 jmp start\r
325Em64String:\r
326 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
327\r
328start: \r
329 mov ax,cs\r
330 mov ds,ax\r
331 mov es,ax\r
332 mov ss,ax\r
333 mov sp,MyStack\r
334\r
335; mov ax,0b800h\r
336; mov es,ax\r
337; mov byte ptr es:[160],'a'\r
338; mov ax,cs\r
339; mov es,ax\r
340\r
341 mov ebx,0\r
342 lea edi,MemoryMap\r
343MemMapLoop:\r
344 mov eax,0e820h\r
345 mov ecx,20\r
346 mov edx,'SMAP'\r
347 int 15h\r
348 jc MemMapDone\r
349 add edi,20\r
350 cmp ebx,0\r
351 je MemMapDone\r
352 jmp MemMapLoop\r
353MemMapDone:\r
354 lea eax,MemoryMap\r
355 sub edi,eax ; Get the address of the memory map\r
356 mov dword ptr [MemoryMapSize],edi ; Save the size of the memory map\r
357\r
358 xor ebx,ebx\r
359 mov bx,cs ; BX=segment\r
360 shl ebx,4 ; BX="linear" address of segment base\r
361 lea eax,[GDT_BASE + ebx] ; EAX=PHYSICAL address of gdt\r
362 mov dword ptr [gdtr + 2],eax ; Put address of gdt into the gdtr\r
363 lea eax,[IDT_BASE + ebx] ; EAX=PHYSICAL address of idt\r
364 mov dword ptr [idtr + 2],eax ; Put address of idt into the idtr\r
365 lea edx,[MemoryMapSize + ebx] ; Physical base address of the memory map\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
403\r
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 lea eax, OffsetIn32BitProtectedMode\r
417 add eax, 20000h + 6h\r
418 mov dword ptr[OffsetIn32BitProtectedMode], eax\r
419\r
420 lea eax, OffsetInLongMode\r
421 add eax, 20000h + 6h\r
422 mov dword ptr[OffsetInLongMode], eax\r
423\r
424 ;\r
425 ; load GDT\r
426 ;\r
427 db 66h \r
428 lgdt fword ptr [gdtr]\r
429\r
430 ;\r
431 ; Enable Protect Mode (set CR0.PE=1)\r
432 ;\r
433 mov eax, cr0 ; Read CR0.\r
434 or eax, 1h ; Set PE=1\r
435 mov cr0, eax ; Write CR0.\r
436 db 066h\r
437 db 0eah ; jmp far 16:32\r
438OffsetIn32BitProtectedMode:\r
439 dd 00000000h ; offset $+8 (In32BitProtectedMode)\r
440 dw 10h ; selector (flat CS)\r
441In32BitProtectedMode:\r
442\r
443;\r
444; Entering Long Mode\r
445;\r
446 db 66h\r
447 mov ax, 8\r
448 mov ds, ax\r
449 mov es, ax\r
450 mov ss, ax\r
451\r
452 ;\r
453 ; Enable the 64-bit page-translation-table entries by\r
454 ; setting CR4.PAE=1 (this is _required_ before activating\r
455 ; long mode). Paging is not enabled until after long mode\r
456 ; is enabled.\r
457 ;\r
458 db 0fh\r
459 db 20h\r
460 db 0e0h\r
461; mov eax, cr4\r
462 bts eax, 5\r
463 db 0fh\r
464 db 22h\r
465 db 0e0h\r
466; mov cr4, eax\r
467\r
468 ;\r
469 ; This is the Trapolean Page Tables that are guarenteed\r
470 ; under 4GB.\r
471 ;\r
472 ; Address Map:\r
473 ; 10000 ~ 12000 - efildr (loaded)\r
474 ; 20000 ~ 21000 - start64.com\r
475 ; 21000 ~ 22000 - efi64.com\r
476 ; 22000 ~ 90000 - efildr\r
477 ; 90000 ~ 96000 - 4G pagetable (will be reload later)\r
478 ;\r
479 db 0b8h\r
480 dd 90000h\r
481; mov eax, 90000h\r
482 mov cr3, eax\r
483\r
484 ;\r
485 ; Enable long mode (set EFER.LME=1).\r
486 ;\r
487 db 0b9h\r
488 dd 0c0000080h\r
489; mov ecx, 0c0000080h ; EFER MSR number.\r
490 db 0fh\r
491 db 32h\r
492; rdmsr ; Read EFER.\r
493 db 0fh\r
494 db 0bah\r
495 db 0e8h\r
496 db 08h\r
497; bts eax, 8 ; Set LME=1.\r
498 db 0fh\r
499 db 30h\r
500; wrmsr ; Write EFER.\r
501\r
502 ;\r
503 ; Enable paging to activate long mode (set CR0.PG=1)\r
504 ;\r
505 mov eax, cr0 ; Read CR0.\r
506 db 0fh\r
507 db 0bah\r
508 db 0e8h\r
509 db 01fh\r
510; bts eax, 31 ; Set PG=1.\r
511 mov cr0, eax ; Write CR0.\r
512 jmp GoToLongMode\r
513GoToLongMode:\r
514\r
515 db 067h\r
516 db 0eah ; Far Jump $+9:Selector to reload CS\r
517OffsetInLongMode:\r
518 dd 00000000 ; $+9 Offset is ensuing instruction boundary\r
519 dw 038h ; Selector is our code selector, 38h\r
520\r
521InLongMode:\r
522 db 66h\r
523 mov ax, 30h\r
524 mov ds, ax\r
525\r
526 db 66h\r
527 mov ax, 18h\r
528 mov es, ax\r
529 mov ss, ax\r
530 mov ds, ax\r
531\r
532 db 0bdh\r
533 dd 400000h\r
534; mov ebp,000400000h ; Destination of EFILDR32\r
535 db 0bbh\r
536 dd 70000h\r
537; mov ebx,000070000h ; Length of copy\r
538\r
539 ;\r
540 ; load idt later\r
541 ;\r
542 db 48h\r
543 db 33h\r
544 db 0c0h\r
545; xor rax, rax\r
546 db 66h\r
547 mov ax, offset idtr\r
548 db 48h\r
549 db 05h\r
550 dd 20000h\r
551; add rax, 20000h\r
552\r
553 db 0fh\r
554 db 01h\r
555 db 18h\r
556; lidt fword ptr [rax]\r
557\r
558 db 48h\r
559 db 0c7h\r
560 db 0c0h\r
561 dd 21000h\r
562; mov rax, 21000h\r
563 db 50h\r
564; push rax\r
565\r
566; ret\r
567 db 0c3h\r
568\r
569Empty8042InputBuffer:\r
570 mov cx,0\r
571Empty8042Loop:\r
572 out DELAY_PORT,ax ; Delay 1us\r
573 in al,KBD_STATUS_PORT ; Read the 8042 Status Port\r
574 and al,02h ; Check the Input Buffer Full Flag\r
575 loopnz Empty8042Loop ; Loop until the input buffer is empty or a timout of 65536 uS\r
576 ret\r
577\r
578;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
579; data\r
580;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
581\r
582 align 02h\r
583\r
584gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit\r
585 dd 0 ; (GDT base gets set above)\r
586;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
587; global descriptor table (GDT)\r
588;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
589\r
590 align 02h\r
591\r
592public GDT_BASE\r
593GDT_BASE:\r
594; null descriptor\r
595NULL_SEL equ $-GDT_BASE ; Selector [0x0]\r
596 dw 0 ; limit 15:0\r
597 dw 0 ; base 15:0\r
598 db 0 ; base 23:16\r
599 db 0 ; type\r
600 db 0 ; limit 19:16, flags\r
601 db 0 ; base 31:24\r
602\r
603; linear data segment descriptor\r
604LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]\r
605 dw 0FFFFh ; limit 0xFFFFF\r
606 dw 0 ; base 0\r
607 db 0\r
608 db 092h ; present, ring 0, data, expand-up, writable\r
609 db 0CFh ; page-granular, 32-bit\r
610 db 0\r
611\r
612; linear code segment descriptor\r
613LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]\r
614 dw 0FFFFh ; limit 0xFFFFF\r
615 dw 0 ; base 0\r
616 db 0\r
617 db 09Ah ; present, ring 0, data, expand-up, writable\r
618 db 0CFh ; page-granular, 32-bit\r
619 db 0\r
620\r
621; system data segment descriptor\r
622SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]\r
623 dw 0FFFFh ; limit 0xFFFFF\r
624 dw 0 ; base 0\r
625 db 0\r
626 db 092h ; present, ring 0, data, expand-up, writable\r
627 db 0CFh ; page-granular, 32-bit\r
628 db 0\r
629\r
630; system code segment descriptor\r
631SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20]\r
632 dw 0FFFFh ; limit 0xFFFFF\r
633 dw 0 ; base 0\r
634 db 0\r
635 db 09Ah ; present, ring 0, data, expand-up, writable\r
636 db 0CFh ; page-granular, 32-bit\r
637 db 0\r
638\r
639; spare segment descriptor\r
640SPARE3_SEL equ $-GDT_BASE ; Selector [0x28]\r
641 dw 0 ; limit 0xFFFFF\r
642 dw 0 ; base 0\r
643 db 0\r
644 db 0 ; present, ring 0, data, expand-up, writable\r
645 db 0 ; page-granular, 32-bit\r
646 db 0\r
647\r
648;\r
649; system data segment descriptor\r
650;\r
651SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30]\r
652 dw 0FFFFh ; limit 0xFFFFF\r
653 dw 0 ; base 0\r
654 db 0\r
655 db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A\r
656 db 0CFh ; G | D | L | AVL | Segment [19..16]\r
657 db 0\r
658\r
659;\r
660; system code segment descriptor\r
661;\r
662SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38]\r
663 dw 0FFFFh ; limit 0xFFFFF\r
664 dw 0 ; base 0\r
665 db 0\r
666 db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A\r
667 db 0AFh ; G | D | L | AVL | Segment [19..16]\r
668 db 0\r
669\r
670; spare segment descriptor\r
671SPARE4_SEL equ $-GDT_BASE ; Selector [0x40]\r
672 dw 0 ; limit 0xFFFFF\r
673 dw 0 ; base 0\r
674 db 0\r
675 db 0 ; present, ring 0, data, expand-up, writable\r
676 db 0 ; page-granular, 32-bit\r
677 db 0\r
678\r
679GDT_END:\r
680\r
681 align 02h\r
682\r
683\r
684\r
685idtr dw IDT_END - IDT_BASE - 1 ; IDT limit\r
686 dq 0 ; (IDT base gets set above)\r
687\r
688;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
689; interrupt descriptor table (IDT)\r
690;\r
691; Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ\r
692; mappings. This implementation only uses the system timer and all other\r
693; IRQs will remain masked. The descriptors for vectors 33+ are provided\r
694; for convenience.\r
695;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
696\r
697;idt_tag db "IDT",0 \r
698 align 02h\r
699\r
700public IDT_BASE\r
701IDT_BASE:\r
702; divide by zero (INT 0)\r
703DIV_ZERO_SEL equ $-IDT_BASE\r
704 dw 0 ; offset 15:0\r
705 dw SYS_CODE64_SEL ; selector 15:0\r
706 db 0 ; 0 for interrupt gate\r
707 db 0eh OR 80h ; type = 386 interrupt gate, present\r
708 dw 0 ; offset 31:16\r
709 dd 0 ; offset 63:32\r
710 dd 0 ; 0 for reserved\r
711\r
712; debug exception (INT 1)\r
713DEBUG_EXCEPT_SEL equ $-IDT_BASE\r
714 dw 0 ; offset 15:0\r
715 dw SYS_CODE64_SEL ; selector 15:0\r
716 db 0 ; 0 for interrupt gate\r
717 db 0eh OR 80h ; type = 386 interrupt gate, present\r
718 dw 0 ; offset 31:16\r
719 dd 0 ; offset 63:32\r
720 dd 0 ; 0 for reserved\r
721\r
722; NMI (INT 2)\r
723NMI_SEL equ $-IDT_BASE\r
724 dw 0 ; offset 15:0\r
725 dw SYS_CODE64_SEL ; selector 15:0\r
726 db 0 ; 0 for interrupt gate\r
727 db 0eh OR 80h ; type = 386 interrupt gate, present\r
728 dw 0 ; offset 31:16\r
729 dd 0 ; offset 63:32\r
730 dd 0 ; 0 for reserved\r
731\r
732; soft breakpoint (INT 3)\r
733BREAKPOINT_SEL equ $-IDT_BASE\r
734 dw 0 ; offset 15:0\r
735 dw SYS_CODE64_SEL ; selector 15:0\r
736 db 0 ; 0 for interrupt gate\r
737 db 0eh OR 80h ; type = 386 interrupt gate, present\r
738 dw 0 ; offset 31:16\r
739 dd 0 ; offset 63:32\r
740 dd 0 ; 0 for reserved\r
741\r
742; overflow (INT 4)\r
743OVERFLOW_SEL equ $-IDT_BASE\r
744 dw 0 ; offset 15:0\r
745 dw SYS_CODE64_SEL ; selector 15:0\r
746 db 0 ; 0 for interrupt gate\r
747 db 0eh OR 80h ; type = 386 interrupt gate, present\r
748 dw 0 ; offset 31:16\r
749 dd 0 ; offset 63:32\r
750 dd 0 ; 0 for reserved\r
751\r
752; bounds check (INT 5)\r
753BOUNDS_CHECK_SEL equ $-IDT_BASE\r
754 dw 0 ; offset 15:0\r
755 dw SYS_CODE64_SEL ; selector 15:0\r
756 db 0 ; 0 for interrupt gate\r
757 db 0eh OR 80h ; type = 386 interrupt gate, present\r
758 dw 0 ; offset 31:16\r
759 dd 0 ; offset 63:32\r
760 dd 0 ; 0 for reserved\r
761\r
762; invalid opcode (INT 6)\r
763INVALID_OPCODE_SEL equ $-IDT_BASE\r
764 dw 0 ; offset 15:0\r
765 dw SYS_CODE64_SEL ; selector 15:0\r
766 db 0 ; 0 for interrupt gate\r
767 db 0eh OR 80h ; type = 386 interrupt gate, present\r
768 dw 0 ; offset 31:16\r
769 dd 0 ; offset 63:32\r
770 dd 0 ; 0 for reserved\r
771\r
772; device not available (INT 7)\r
773DEV_NOT_AVAIL_SEL equ $-IDT_BASE\r
774 dw 0 ; offset 15:0\r
775 dw SYS_CODE64_SEL ; selector 15:0\r
776 db 0 ; 0 for interrupt gate\r
777 db 0eh OR 80h ; type = 386 interrupt gate, present\r
778 dw 0 ; offset 31:16\r
779 dd 0 ; offset 63:32\r
780 dd 0 ; 0 for reserved\r
781\r
782; double fault (INT 8)\r
783DOUBLE_FAULT_SEL equ $-IDT_BASE\r
784 dw 0 ; offset 15:0\r
785 dw SYS_CODE64_SEL ; selector 15:0\r
786 db 0 ; 0 for interrupt gate\r
787 db 0eh OR 80h ; type = 386 interrupt gate, present\r
788 dw 0 ; offset 31:16\r
789 dd 0 ; offset 63:32\r
790 dd 0 ; 0 for reserved\r
791\r
792; Coprocessor segment overrun - reserved (INT 9)\r
793RSVD_INTR_SEL1 equ $-IDT_BASE\r
794 dw 0 ; offset 15:0\r
795 dw SYS_CODE64_SEL ; selector 15:0\r
796 db 0 ; 0 for interrupt gate\r
797 db 0eh OR 80h ; type = 386 interrupt gate, present\r
798 dw 0 ; offset 31:16\r
799 dd 0 ; offset 63:32\r
800 dd 0 ; 0 for reserved\r
801\r
802; invalid TSS (INT 0ah)\r
803INVALID_TSS_SEL equ $-IDT_BASE\r
804 dw 0 ; offset 15:0\r
805 dw SYS_CODE64_SEL ; selector 15:0\r
806 db 0 ; 0 for interrupt gate\r
807 db 0eh OR 80h ; type = 386 interrupt gate, present\r
808 dw 0 ; offset 31:16\r
809 dd 0 ; offset 63:32\r
810 dd 0 ; 0 for reserved\r
811\r
812; segment not present (INT 0bh)\r
813SEG_NOT_PRESENT_SEL equ $-IDT_BASE\r
814 dw 0 ; offset 15:0\r
815 dw SYS_CODE64_SEL ; selector 15:0\r
816 db 0 ; 0 for interrupt gate\r
817 db 0eh OR 80h ; type = 386 interrupt gate, present\r
818 dw 0 ; offset 31:16\r
819 dd 0 ; offset 63:32\r
820 dd 0 ; 0 for reserved\r
821\r
822; stack fault (INT 0ch)\r
823STACK_FAULT_SEL equ $-IDT_BASE\r
824 dw 0 ; offset 15:0\r
825 dw SYS_CODE64_SEL ; selector 15:0\r
826 db 0 ; 0 for interrupt gate\r
827 db 0eh OR 80h ; type = 386 interrupt gate, present\r
828 dw 0 ; offset 31:16\r
829 dd 0 ; offset 63:32\r
830 dd 0 ; 0 for reserved\r
831\r
832; general protection (INT 0dh)\r
833GP_FAULT_SEL equ $-IDT_BASE\r
834 dw 0 ; offset 15:0\r
835 dw SYS_CODE64_SEL ; selector 15:0\r
836 db 0 ; 0 for interrupt gate\r
837 db 0eh OR 80h ; type = 386 interrupt gate, present\r
838 dw 0 ; offset 31:16\r
839 dd 0 ; offset 63:32\r
840 dd 0 ; 0 for reserved\r
841\r
842; page fault (INT 0eh)\r
843PAGE_FAULT_SEL equ $-IDT_BASE\r
844 dw 0 ; offset 15:0\r
845 dw SYS_CODE64_SEL ; selector 15:0\r
846 db 0 ; 0 for interrupt gate\r
847 db 0eh OR 80h ; type = 386 interrupt gate, present\r
848 dw 0 ; offset 31:16\r
849 dd 0 ; offset 63:32\r
850 dd 0 ; 0 for reserved\r
851\r
852; Intel reserved - do not use (INT 0fh)\r
853RSVD_INTR_SEL2 equ $-IDT_BASE\r
854 dw 0 ; offset 15:0\r
855 dw SYS_CODE64_SEL ; selector 15:0\r
856 db 0 ; 0 for interrupt gate\r
857 db 0eh OR 80h ; type = 386 interrupt gate, present\r
858 dw 0 ; offset 31:16\r
859 dd 0 ; offset 63:32\r
860 dd 0 ; 0 for reserved\r
861\r
862; floating point error (INT 10h)\r
863FLT_POINT_ERR_SEL equ $-IDT_BASE\r
864 dw 0 ; offset 15:0\r
865 dw SYS_CODE64_SEL ; selector 15:0\r
866 db 0 ; 0 for interrupt gate\r
867 db 0eh OR 80h ; type = 386 interrupt gate, present\r
868 dw 0 ; offset 31:16\r
869 dd 0 ; offset 63:32\r
870 dd 0 ; 0 for reserved\r
871\r
872; alignment check (INT 11h)\r
873ALIGNMENT_CHECK_SEL equ $-IDT_BASE\r
874 dw 0 ; offset 15:0\r
875 dw SYS_CODE64_SEL ; selector 15:0\r
876 db 0 ; 0 for interrupt gate\r
877 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
878 dw 0 ; offset 31:16\r
879 dd 0 ; offset 63:32\r
880 dd 0 ; 0 for reserved\r
881\r
882; machine check (INT 12h)\r
883MACHINE_CHECK_SEL equ $-IDT_BASE\r
884 dw 0 ; offset 15:0\r
885 dw SYS_CODE64_SEL ; selector 15:0\r
886 db 0 ; 0 for interrupt gate\r
887 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
888 dw 0 ; offset 31:16\r
889 dd 0 ; offset 63:32\r
890 dd 0 ; 0 for reserved\r
891\r
892; SIMD floating-point exception (INT 13h)\r
893SIMD_EXCEPTION_SEL equ $-IDT_BASE\r
894 dw 0 ; offset 15:0\r
895 dw SYS_CODE64_SEL ; selector 15:0\r
896 db 0 ; 0 for interrupt gate\r
897 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
898 dw 0 ; offset 31:16\r
899 dd 0 ; offset 63:32\r
900 dd 0 ; 0 for reserved\r
901\r
902; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail\r
903 db (85 * 16) dup(0)\r
904 \r
905; IRQ 0 (System timer) - (INT 68h)\r
906IRQ0_SEL equ $-IDT_BASE\r
907 dw 0 ; offset 15:0\r
908 dw SYS_CODE64_SEL ; selector 15:0\r
909 db 0 ; 0 for interrupt gate\r
910 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
911 dw 0 ; offset 31:16\r
912 dd 0 ; offset 63:32\r
913 dd 0 ; 0 for reserved\r
914\r
915; IRQ 1 (8042 Keyboard controller) - (INT 69h)\r
916IRQ1_SEL equ $-IDT_BASE\r
917 dw 0 ; offset 15:0\r
918 dw SYS_CODE64_SEL ; selector 15:0\r
919 db 0 ; 0 for interrupt gate\r
920 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
921 dw 0 ; offset 31:16\r
922 dd 0 ; offset 63:32\r
923 dd 0 ; 0 for reserved\r
924\r
925; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)\r
926IRQ2_SEL equ $-IDT_BASE\r
927 dw 0 ; offset 15:0\r
928 dw SYS_CODE64_SEL ; selector 15:0\r
929 db 0 ; 0 for interrupt gate\r
930 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
931 dw 0 ; offset 31:16\r
932 dd 0 ; offset 63:32\r
933 dd 0 ; 0 for reserved\r
934\r
935; IRQ 3 (COM 2) - (INT 6bh)\r
936IRQ3_SEL equ $-IDT_BASE\r
937 dw 0 ; offset 15:0\r
938 dw SYS_CODE64_SEL ; selector 15:0\r
939 db 0 ; 0 for interrupt gate\r
940 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
941 dw 0 ; offset 31:16\r
942 dd 0 ; offset 63:32\r
943 dd 0 ; 0 for reserved\r
944\r
945; IRQ 4 (COM 1) - (INT 6ch)\r
946IRQ4_SEL equ $-IDT_BASE\r
947 dw 0 ; offset 15:0\r
948 dw SYS_CODE64_SEL ; selector 15:0\r
949 db 0 ; 0 for interrupt gate\r
950 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
951 dw 0 ; offset 31:16\r
952 dd 0 ; offset 63:32\r
953 dd 0 ; 0 for reserved\r
954\r
955; IRQ 5 (LPT 2) - (INT 6dh)\r
956IRQ5_SEL equ $-IDT_BASE\r
957 dw 0 ; offset 15:0\r
958 dw SYS_CODE64_SEL ; selector 15:0\r
959 db 0 ; 0 for interrupt gate\r
960 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
961 dw 0 ; offset 31:16\r
962 dd 0 ; offset 63:32\r
963 dd 0 ; 0 for reserved\r
964\r
965; IRQ 6 (Floppy controller) - (INT 6eh)\r
966IRQ6_SEL equ $-IDT_BASE\r
967 dw 0 ; offset 15:0\r
968 dw SYS_CODE64_SEL ; selector 15:0\r
969 db 0 ; 0 for interrupt gate\r
970 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
971 dw 0 ; offset 31:16\r
972 dd 0 ; offset 63:32\r
973 dd 0 ; 0 for reserved\r
974\r
975; IRQ 7 (LPT 1) - (INT 6fh)\r
976IRQ7_SEL equ $-IDT_BASE\r
977 dw 0 ; offset 15:0\r
978 dw SYS_CODE64_SEL ; selector 15:0\r
979 db 0 ; 0 for interrupt gate\r
980 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
981 dw 0 ; offset 31:16\r
982 dd 0 ; offset 63:32\r
983 dd 0 ; 0 for reserved\r
984\r
985; IRQ 8 (RTC Alarm) - (INT 70h)\r
986IRQ8_SEL equ $-IDT_BASE\r
987 dw 0 ; offset 15:0\r
988 dw SYS_CODE64_SEL ; selector 15:0\r
989 db 0 ; 0 for interrupt gate\r
990 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
991 dw 0 ; offset 31:16\r
992 dd 0 ; offset 63:32\r
993 dd 0 ; 0 for reserved\r
994\r
995; IRQ 9 - (INT 71h)\r
996IRQ9_SEL equ $-IDT_BASE\r
997 dw 0 ; offset 15:0\r
998 dw SYS_CODE64_SEL ; selector 15:0\r
999 db 0 ; 0 for interrupt gate\r
1000 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
1001 dw 0 ; offset 31:16\r
1002 dd 0 ; offset 63:32\r
1003 dd 0 ; 0 for reserved\r
1004\r
1005; IRQ 10 - (INT 72h)\r
1006IRQ10_SEL equ $-IDT_BASE\r
1007 dw 0 ; offset 15:0\r
1008 dw SYS_CODE64_SEL ; selector 15:0\r
1009 db 0 ; 0 for interrupt gate\r
1010 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
1011 dw 0 ; offset 31:16\r
1012 dd 0 ; offset 63:32\r
1013 dd 0 ; 0 for reserved\r
1014\r
1015; IRQ 11 - (INT 73h)\r
1016IRQ11_SEL equ $-IDT_BASE\r
1017 dw 0 ; offset 15:0\r
1018 dw SYS_CODE64_SEL ; selector 15:0\r
1019 db 0 ; 0 for interrupt gate\r
1020 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
1021 dw 0 ; offset 31:16\r
1022 dd 0 ; offset 63:32\r
1023 dd 0 ; 0 for reserved\r
1024\r
1025; IRQ 12 (PS/2 mouse) - (INT 74h)\r
1026IRQ12_SEL equ $-IDT_BASE\r
1027 dw 0 ; offset 15:0\r
1028 dw SYS_CODE64_SEL ; selector 15:0\r
1029 db 0 ; 0 for interrupt gate\r
1030 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
1031 dw 0 ; offset 31:16\r
1032 dd 0 ; offset 63:32\r
1033 dd 0 ; 0 for reserved\r
1034\r
1035; IRQ 13 (Floating point error) - (INT 75h)\r
1036IRQ13_SEL equ $-IDT_BASE\r
1037 dw 0 ; offset 15:0\r
1038 dw SYS_CODE64_SEL ; selector 15:0\r
1039 db 0 ; 0 for interrupt gate\r
1040 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
1041 dw 0 ; offset 31:16\r
1042 dd 0 ; offset 63:32\r
1043 dd 0 ; 0 for reserved\r
1044\r
1045; IRQ 14 (Secondary IDE) - (INT 76h)\r
1046IRQ14_SEL equ $-IDT_BASE\r
1047 dw 0 ; offset 15:0\r
1048 dw SYS_CODE64_SEL ; selector 15:0\r
1049 db 0 ; 0 for interrupt gate\r
1050 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
1051 dw 0 ; offset 31:16\r
1052 dd 0 ; offset 63:32\r
1053 dd 0 ; 0 for reserved\r
1054\r
1055; IRQ 15 (Primary IDE) - (INT 77h)\r
1056IRQ15_SEL equ $-IDT_BASE\r
1057 dw 0 ; offset 15:0\r
1058 dw SYS_CODE64_SEL ; selector 15:0\r
1059 db 0 ; 0 for interrupt gate\r
1060 db 0eh OR 80h ; (10001110)type = 386 interrupt gate, present\r
1061 dw 0 ; offset 31:16\r
1062 dd 0 ; offset 63:32\r
1063 dd 0 ; 0 for reserved\r
1064\r
1065IDT_END:\r
1066\r
1067 align 02h\r
1068\r
1069MemoryMapSize dd 0\r
1070MemoryMap dd 0,0,0,0,0,0,0,0\r
1071 dd 0,0,0,0,0,0,0,0\r
1072 dd 0,0,0,0,0,0,0,0\r
1073 dd 0,0,0,0,0,0,0,0\r
1074 dd 0,0,0,0,0,0,0,0\r
1075 dd 0,0,0,0,0,0,0,0\r
1076 dd 0,0,0,0,0,0,0,0\r
1077 dd 0,0,0,0,0,0,0,0\r
1078 dd 0,0,0,0,0,0,0,0\r
1079 dd 0,0,0,0,0,0,0,0\r
1080 dd 0,0,0,0,0,0,0,0\r
1081 dd 0,0,0,0,0,0,0,0\r
1082 dd 0,0,0,0,0,0,0,0\r
1083 dd 0,0,0,0,0,0,0,0\r
1084 dd 0,0,0,0,0,0,0,0\r
1085 dd 0,0,0,0,0,0,0,0\r
1086 dd 0,0,0,0,0,0,0,0\r
1087 dd 0,0,0,0,0,0,0,0\r
1088 dd 0,0,0,0,0,0,0,0\r
1089 dd 0,0,0,0,0,0,0,0\r
1090 dd 0,0,0,0,0,0,0,0\r
1091 dd 0,0,0,0,0,0,0,0\r
1092 dd 0,0,0,0,0,0,0,0\r
1093 dd 0,0,0,0,0,0,0,0\r
1094 dd 0,0,0,0,0,0,0,0\r
1095 dd 0,0,0,0,0,0,0,0\r
1096 dd 0,0,0,0,0,0,0,0\r
1097 dd 0,0,0,0,0,0,0,0\r
1098 dd 0,0,0,0,0,0,0,0\r
1099 dd 0,0,0,0,0,0,0,0\r
1100\r
1101 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
1102 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
1103\r
1104 org 0fe0h\r
1105MyStack: \r
1106 ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh\r
1107 ; back to INT 08h - 0fh when in real mode... It is 'org'ed to a\r
1108 ; known low address (20f00) so it can be set up by PlMapIrqToVect in\r
1109 ; 8259.c\r
1110 \r
1111 int 8\r
1112 iret\r
1113 \r
1114 int 9\r
1115 iret\r
1116 \r
1117 int 10\r
1118 iret\r
1119 \r
1120 int 11\r
1121 iret\r
1122 \r
1123 int 12\r
1124 iret\r
1125 \r
1126 int 13\r
1127 iret\r
1128 \r
1129 int 14\r
1130 iret\r
1131 \r
1132 int 15\r
1133 iret\r
1134 \r
1135 \r
1136 org 0ffeh\r
1137BlockSignature:\r
1138 dw 0aa55h\r
1139\r
1140 end \r