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