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