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