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;* st32_64.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 35SectorSize dw 0 ; Sector Size - 2 bytes 36SectorsPerCluster db 0 ; Sector Per Cluster - 1 byte 37ReservedSectors dw 0 ; Reserved Sectors - 2 bytes 38NoFats db 0 ; Number of FATs - 1 byte 39RootEntries dw 0 ; Root Entries - 2 bytes 40Sectors dw 0 ; Number of Sectors - 2 bytes 41Media db 0 ; Media - 1 byte 42SectorsPerFat16 dw 0 ; Sectors Per FAT for FAT12/FAT16 - 2 byte 43SectorsPerTrack dw 0 ; Sectors Per Track - 2 bytes 44Heads dw 0 ; Heads - 2 bytes 45HiddenSectors dd 0 ; Hidden Sectors - 4 bytes 46LargeSectors 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 55SectorsPerFat32 dd 0 ; Sectors Per FAT for FAT32 - 4 bytes 56ExtFlags dw 0 ; Mirror Flag - 2 bytes 57FSVersion dw 0 ; File System Version - 2 bytes 58RootCluster dd 0 ; 1st Cluster Number of Root Dir - 4 bytes 59FSInfo dw 0 ; Sector Number of FSINFO - 2 bytes 60BkBootSector dw 0 ; Sector Number of Bk BootSector - 2 bytes 61Reserved db 12 dup(0) ; Reserved Field - 12 bytes 62PhysicalDrive db 0 ; Physical Drive Number - 1 byte 63Reserved1 db 0 ; Reserved Field - 1 byte 64Signature db 0 ; Extended Boot Signature - 1 byte 65VolId db " " ; Volume Serial Number - 4 bytes 66FatLabel db " " ; Volume Label - 11 bytes 67FileSystemType db "FAT32 " ; File System Type - 8 bytes 68 69BootSectorEntryPoint: 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 89NoVarStore: 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 95CheckVarStoreSize: 96 mov di,dx 97 cmp dword ptr ds:[di+2], 04000h 98 mov al,2 99 jne NoVarStore 100 101LoadVarStore: 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 111SaveVolumeId: 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 129CheckEm64T: 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 140CheckEm64TPass: 141JumpFarInstruction: 142 db 0eah 143JumpOffset: 144 dw 0200h 145JumpSegment: 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; **************************************************************************** 162ReadFile: 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 173FatChainLoop: 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 194SkipFatRead: 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 205ReadClusters: 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 223FoundLastCluster: 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 241ReadBlocks: 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 247ReadCylinderLoop: 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 261LimitTransfer: 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 271NotCrossing64KBoundry: 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 304DiskError: 305 push cs 306 pop ds 307 lea si, [ErrorString] 308 mov cx, 7 309 jmp PrintStringAndHalt 310 311PrintStringAndHalt: 312 mov ax,0b800h 313 mov es,ax 314 mov di,160 315 rep movsw 316Halt: 317 jmp Halt 318 319ErrorString: 320 db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch 321 322 org 01fah 323LBAOffsetForBootSector: 324 dd 0h 325 326 org 01feh 327 dw 0aa55h 328 329;****************************************************************************** 330;****************************************************************************** 331;****************************************************************************** 332 333DELAY_PORT equ 0edh ; Port to use for 1uS delay 334KBD_CONTROL_PORT equ 060h ; 8042 control port 335KBD_STATUS_PORT equ 064h ; 8042 status port 336WRITE_DATA_PORT_CMD equ 0d1h ; 8042 command to write the data port 337ENABLE_A20_CMD equ 0dfh ; 8042 command to enable A20 338 339 org 200h 340 jmp start 341Em64String: 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 344start: 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 359MemMapLoop: 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 369MemMapDone: 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 412Delay25uS: 413 out DELAY_PORT,ax ; Delay 1 uS 414 loop Delay25uS 415Timeout8042: 416 417 418A20GateEnabled: 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 454OffsetIn32BitProtectedMode: 455 dd 00000000h ; offset $+8 (In32BitProtectedMode) 456 dw 10h ; selector (flat CS) 457In32BitProtectedMode: 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 529GoToLongMode: 530 531 db 067h 532 db 0eah ; Far Jump $+9:Selector to reload CS 533OffsetInLongMode: 534 dd 00000000 ; $+9 Offset is ensuing instruction boundary 535 dw 038h ; Selector is our code selector, 38h 536 537InLongMode: 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 585Empty8042InputBuffer: 586 mov cx,0 587Empty8042Loop: 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 600gdtr 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 608public GDT_BASE 609GDT_BASE: 610; null descriptor 611NULL_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 620LINEAR_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 629LINEAR_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 638SYS_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 647SYS_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 656SPARE3_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; 667SYS_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; 678SYS_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 687SPARE4_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 695GDT_END: 696 697 align 02h 698 699 700 701idtr 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 716public IDT_BASE 717IDT_BASE: 718; divide by zero (INT 0) 719DIV_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) 729DEBUG_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) 739NMI_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) 749BREAKPOINT_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) 759OVERFLOW_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) 769BOUNDS_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) 779INVALID_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) 789DEV_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) 799DOUBLE_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) 809RSVD_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) 819INVALID_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) 829SEG_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) 839STACK_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) 849GP_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) 859PAGE_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) 869RSVD_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) 879FLT_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) 889ALIGNMENT_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) 899MACHINE_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) 909SIMD_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) 922IRQ0_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) 932IRQ1_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) 942IRQ2_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) 952IRQ3_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) 962IRQ4_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) 972IRQ5_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) 982IRQ6_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) 992IRQ7_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) 1002IRQ8_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) 1012IRQ9_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) 1022IRQ10_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) 1032IRQ11_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) 1042IRQ12_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) 1052IRQ13_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) 1062IRQ14_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) 1072IRQ15_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 1081IDT_END: 1082 1083 align 02h 1084 1085MemoryMapSize dd 0 1086MemoryMap 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 1121MyStack: 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 1153BlockSignature: 1154 dw 0aa55h 1155 1156 end 1157