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