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