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