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 23FAT_DIRECTORY_ENTRY_SIZE EQU 020h 24FAT_DIRECTORY_ENTRY_SHIFT EQU 5 25BLOCK_SIZE EQU 0200h 26BLOCK_MASK EQU 01ffh 27BLOCK_SHIFT EQU 9 28 29 org 0h 30Ia32Jump: 31 jmp BootSectorEntryPoint ; JMP inst - 3 bytes 32 nop 33 34OemId db "INTEL " ; OemId - 8 bytes 35 36SectorSize dw 0 ; Sector Size - 16 bits 37SectorsPerCluster db 0 ; Sector Per Cluster - 8 bits 38ReservedSectors dw 0 ; Reserved Sectors - 16 bits 39NoFats db 0 ; Number of FATs - 8 bits 40RootEntries dw 0 ; Root Entries - 16 bits 41Sectors dw 0 ; Number of Sectors - 16 bits 42Media db 0 ; Media - 8 bits - ignored 43SectorsPerFat dw 0 ; Sectors Per FAT - 16 bits 44SectorsPerTrack dw 0 ; Sectors Per Track - 16 bits - ignored 45Heads dw 0 ; Heads - 16 bits - ignored 46HiddenSectors dd 0 ; Hidden Sectors - 32 bits - ignored 47LargeSectors dd 0 ; Large Sectors - 32 bits 48PhysicalDrive db 0 ; PhysicalDriveNumber - 8 bits - ignored 49CurrentHead db 0 ; Current Head - 8 bits 50Signature db 0 ; Signature - 8 bits - ignored 51VolId db " " ; Volume Serial Number- 4 bytes 52FatLabel db " " ; Label - 11 bytes 53SystemId db "FAT12 " ; SystemId - 8 bytes 54 55BootSectorEntryPoint: 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 74NoVarStore: 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 80CheckVarStoreSize: 81 mov di,dx 82 cmp dword ptr ds:[di+2], 04000h 83 mov al,2 84 jne NoVarStore 85 86LoadVarStore: 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 96SaveVolumeId: 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 114CheckEm64T: 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 125CheckEm64TPass: 126JumpFarInstruction: 127 db 0eah 128JumpOffset: 129 dw 0200h 130JumpSegment: 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; **************************************************************************** 146ReadFile: 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 157FatChainLoop: 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 180SkipFatRead: 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 186EvenFatEntry: 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 196ReadClusters: 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 214FoundLastCluster: 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 232ReadBlocks: 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 238ReadCylinderLoop: 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 252LimitTransfer: 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 262NotCrossing64KBoundry: 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 295DiskError: 296 push cs 297 pop ds 298 lea si, [ErrorString] 299 mov cx, 7 300 jmp PrintStringAndHalt 301 302PrintStringAndHalt: 303 mov ax,0b800h 304 mov es,ax 305 mov di,160 306 rep movsw 307Halt: 308 jmp Halt 309 310ErrorString: 311 db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch 312 313 org 01fah 314LBAOffsetForBootSector: 315 dd 0h 316 317 org 01feh 318 dw 0aa55h 319 320;****************************************************************************** 321;****************************************************************************** 322;****************************************************************************** 323 324DELAY_PORT equ 0edh ; Port to use for 1uS delay 325KBD_CONTROL_PORT equ 060h ; 8042 control port 326KBD_STATUS_PORT equ 064h ; 8042 status port 327WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port 328ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20 329 330 org 200h 331 jmp start 332Em64String: 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 335start: 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 350MemMapLoop: 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 360MemMapDone: 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 403Delay25uS: 404 out DELAY_PORT,ax ; Delay 1 uS 405 loop Delay25uS 406Timeout8042: 407 408 409A20GateEnabled: 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 445OffsetIn32BitProtectedMode: 446 dd 00000000h ; offset $+8 (In32BitProtectedMode) 447 dw 10h ; selector (flat CS) 448In32BitProtectedMode: 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 520GoToLongMode: 521 522 db 067h 523 db 0eah ; Far Jump $+9:Selector to reload CS 524OffsetInLongMode: 525 dd 00000000 ; $+9 Offset is ensuing instruction boundary 526 dw 038h ; Selector is our code selector, 38h 527 528InLongMode: 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 576Empty8042InputBuffer: 577 mov cx,0 578Empty8042Loop: 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 591gdtr 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 599public GDT_BASE 600GDT_BASE: 601; null descriptor 602NULL_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 611LINEAR_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 620LINEAR_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 629SYS_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 638SYS_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 647SPARE3_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; 658SYS_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; 669SYS_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 678SPARE4_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 686GDT_END: 687 688 align 02h 689 690 691 692idtr 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 707public IDT_BASE 708IDT_BASE: 709; divide by zero (INT 0) 710DIV_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) 720DEBUG_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) 730NMI_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) 740BREAKPOINT_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) 750OVERFLOW_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) 760BOUNDS_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) 770INVALID_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) 780DEV_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) 790DOUBLE_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) 800RSVD_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) 810INVALID_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) 820SEG_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) 830STACK_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) 840GP_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) 850PAGE_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) 860RSVD_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) 870FLT_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) 880ALIGNMENT_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) 890MACHINE_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) 900SIMD_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) 913IRQ0_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) 923IRQ1_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) 933IRQ2_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) 943IRQ3_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) 953IRQ4_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) 963IRQ5_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) 973IRQ6_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) 983IRQ7_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) 993IRQ8_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) 1003IRQ9_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) 1013IRQ10_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) 1023IRQ11_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) 1033IRQ12_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) 1043IRQ13_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) 1053IRQ14_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) 1063IRQ15_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 1072IDT_END: 1073 1074 align 02h 1075 1076MemoryMapSize dd 0 1077MemoryMap 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 1112MyStack: 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 1144BlockSignature: 1145 dw 0aa55h 1146 1147 end 1148