start64.S revision 9811c39250d3598b02b7f39bbec5a51c803f8f6a
1#------------------------------------------------------------------------------ 2#* 3#* Copyright 2006 - 2007, Intel Corporation 4#* All rights reserved. This program and the accompanying materials 5#* are licensed and made available under the terms and conditions of the BSD License 6#* which accompanies this distribution. The full text of the license may be found at 7#* http://opensource.org/licenses/bsd-license.php 8#* 9#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11#* 12#* start64.asm 13#* 14#* Abstract: 15#* 16#------------------------------------------------------------------------------ 17 18 19 .stack: 20 .486p: 21 .code16 22 23.equ FAT_DIRECTORY_ENTRY_SIZE, 0x020 24.equ FAT_DIRECTORY_ENTRY_SHIFT, 5 25.equ BLOCK_SIZE, 0x0200 26.equ BLOCK_MASK, 0x01ff 27.equ BLOCK_SHIFT, 9 28 29 .org 0x0 30Ia32Jump: 31 jmp BootSectorEntryPoint # JMP inst - 3 bytes 32 nop 33 34OemId: .ascii "INTEL " # OemId - 8 bytes 35 36SectorSize: .word 0 # Sector Size - 16 bits 37SectorsPerCluster: .byte 0 # Sector Per Cluster - 8 bits 38ReservedSectors: .word 0 # Reserved Sectors - 16 bits 39NoFats: .byte 0 # Number of FATs - 8 bits 40RootEntries: .word 0 # Root Entries - 16 bits 41Sectors: .word 0 # Number of Sectors - 16 bits 42Media: .byte 0 # Media - 8 bits - ignored 43SectorsPerFat: .word 0 # Sectors Per FAT - 16 bits 44SectorsPerTrack: .word 0 # Sectors Per Track - 16 bits - ignored 45Heads: .word 0 # Heads - 16 bits - ignored 46HiddenSectors: .long 0 # Hidden Sectors - 32 bits - ignored 47LargeSectors: .long 0 # Large Sectors - 32 bits 48PhysicalDrive: .byte 0 # PhysicalDriveNumber - 8 bits - ignored 49CurrentHead: .byte 0 # Current Head - 8 bits 50Signature: .byte 0 # Signature - 8 bits - ignored 51VolId: .ascii " " # Volume Serial Number- 4 bytes 52FatLabel: .ascii " " # Label - 11 bytes 53SystemId: .ascii "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 movw $0x7c00,%bp 64 65 pushw %cx 66# Read Efivar.bin 67# 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already 68 movw $0x1900,%ax 69 movw %ax,%es 70 testw %dx,%dx 71 jnz CheckVarStoreSize 72 73 movb $1,%al 74NoVarStore: 75 pushw %es 76# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl 77 movb %al, %es:(4) 78 jmp SaveVolumeId 79 80CheckVarStoreSize: 81 movw %dx,%di 82 cmpl $0x4000, %ds:2(%di) 83 movb $2,%al 84 jne NoVarStore 85 86LoadVarStore: 87 movb $0,%al 88 movb %al, %es:(4) 89 movw (%di), %cx 90# ES:DI = 1500:0 91 xorw %di,%di 92 pushw %es 93 movw $0x1500,%ax 94 movw %ax,%es 95 call ReadFile 96SaveVolumeId: 97 popw %es 98 movw VolId(%bp), %ax 99 movw %ax, %es:(0) 100 movw VolId+2(%bp), %ax 101 movw %ax, %es:(2) 102 103# Read Efildr 104 popw %cx 105# cx = Start Cluster of Efildr -> BS.com has filled already 106# ES:DI = 2000:0, first cluster will be read again 107 xorw %di,%di # di = 0 108 movw $0x2000,%ax 109 movw %ax,%es 110 call ReadFile 111 movw %cs,%ax 112 movw %ax, %cs:JumpSegment 113 114CheckEm64T: 115 movl $0x80000001,%eax 116# cpuid 117 .word 0xA20F 118 btl $29,%edx 119 jc CheckEm64TPass 120 pushw %cs 121 popw %ds 122 leaw Em64String,%si 123 movw $18,%cx 124 jmp PrintStringAndHalt 125CheckEm64TPass: 126jumpFarInstruction: 127 .byte 0xea 128jumpOffset: 129 .word 0x200 130jumpSegment: 131 .word 0x2000 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 movw $1,%si # NumberOfClusters = 1 155 pushw %cx # Push Start Cluster onto stack 156 movw $0xfff,%dx # CachedFatSectorNumber = 0xfff 157FatChainLoop: 158 movw %cx,%ax # ax = ClusterNumber 159 andw $0xff8,%ax # ax = ax & 0xff8 160 cmpw $0xff8,%ax # See if this is the last cluster 161 je FoundLastCluster # Jump if last cluster found 162 movw %cx,%ax # ax = ClusterNumber 163 shlw %ax # ax = ClusterNumber * 2 164 addw %cx,%ax # ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3 165 shrw %ax # FatOffset = ClusterNumber*3 / 2 166 pushw %si # Save si 167 movw %ax,%si # si = FatOffset 168 shrw $BLOCK_SHIFT, %ax # ax = FatOffset >> BLOCK_SHIFT 169 addw ReservedSectors(%bp), %ax # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET) 170 andw $BLOCK_MASK, %si # si = FatOffset & BLOCK_MASK 171 cmpw %dx,%ax # Compare FatSectorNumber to CachedFatSectorNumber 172 je SkipFatRead 173 movw $2,%bx 174 pushw %es 175 pushw %ds 176 popw %es 177 call ReadBlocks # Read 2 blocks starting at AX storing at ES:DI 178 popw %es 179 movw %ax,%dx # CachedFatSectorNumber = FatSectorNumber 180SkipFatRead: 181 movw (%si), %bx # bx = NextClusterNumber 182 movw %cx,%ax # ax = ClusterNumber 183 andw $1,%ax # See if this is an odd cluster number 184 je EvenFatEntry 185 shrw $4,%bx # NextClusterNumber = NextClusterNumber >> 4 186EvenFatEntry: 187 andw $0xfff,%bx # Strip upper 4 bits of NextClusterNumber 188 popw %si # Restore si 189 decw %bx # bx = NextClusterNumber - 1 190 cmpw %cx,%bx # See if (NextClusterNumber-1)==ClusterNumber 191 jne ReadClusters 192 incw %bx # bx = NextClusterNumber 193 incw %si # NumberOfClusters++ 194 movw %bx,%cx # ClusterNumber = NextClusterNumber 195 jmp FatChainLoop 196ReadClusters: 197 incw %bx 198 popw %ax # ax = StartCluster 199 pushw %bx # StartCluster = NextClusterNumber 200 movw %bx,%cx # ClusterNumber = NextClusterNumber 201 subw $2,%ax # ax = StartCluster - 2 202 xorb %bh,%bh 203 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster 204 mulw %bx # ax = (StartCluster - 2) * SectorsPerCluster 205 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster 206 pushw %ax # save start sector 207 movw %si,%ax # ax = NumberOfClusters 208 mulw %bx # ax = NumberOfClusters * SectorsPerCluster 209 movw %ax,%bx # bx = Number of Sectors 210 popw %ax # ax = Start Sector 211 call ReadBlocks 212 movw $1,%si # NumberOfClusters = 1 213 jmp FatChainLoop 214FoundLastCluster: 215 popw %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 addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA 235 addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA 236 movl %eax,%esi # esi = Start LBA 237 movw %bx,%cx # cx = Number of blocks to read 238ReadCylinderLoop: 239 movw $0x7bfc,%bp # bp = 0x7bfc 240 movl %esi,%eax # eax = Start LBA 241 xorl %edx,%edx # edx = 0 242 movzwl (%bp), %ebx # bx = MaxSector 243 divl %ebx # ax = StartLBA / MaxSector 244 incw %dx # dx = (StartLBA % MaxSector) + 1 245 246 movw (%bp), %bx # bx = MaxSector 247 subw %dx,%bx # bx = MaxSector - Sector 248 incw %bx # bx = MaxSector - Sector + 1 249 cmpw %bx,%cx # Compare (Blocks) to (MaxSector - Sector + 1) 250 jg LimitTransfer 251 movw %cx,%bx # bx = Blocks 252LimitTransfer: 253 pushw %ax # save ax 254 movw %es,%ax # ax = es 255 shrw $(BLOCK_SHIFT-4), %ax # ax = Number of blocks into mem system 256 andw $0x7f,%ax # ax = Number of blocks into current seg 257 addw %bx,%ax # ax = End Block number of transfer 258 cmpw $0x80,%ax # See if it crosses a 64K boundry 259 jle NotCrossing64KBoundry # Branch if not crossing 64K boundry 260 subw $0x80,%ax # ax = Number of blocks past 64K boundry 261 subw %ax,%bx # Decrease transfer size by block overage 262NotCrossing64KBoundry: 263 popw %ax # restore ax 264 265 pushw %cx 266 movb %dl,%cl # cl = (StartLBA % MaxSector) + 1 = Sector 267 xorw %dx,%dx # dx = 0 268 divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder 269 # dx = ax % (MaxHead + 1) = Head 270 271 pushw %bx # Save number of blocks to transfer 272 movb %dl,%dh # dh = Head 273 movw $0x7c00,%bp # bp = 0x7c00 274 movb PhysicalDrive(%bp), %dl # dl = Drive Number 275 movb %al,%ch # ch = Cylinder 276 movb %bl,%al # al = Blocks 277 movb $2,%ah # ah = Function 2 278 movw %di,%bx # es:bx = Buffer address 279 int $0x13 280 jc DiskError 281 popw %bx 282 popw %cx 283 movzwl %bx,%ebx 284 addl %ebx,%esi # StartLBA = StartLBA + NumberOfBlocks 285 subw %bx,%cx # Blocks = Blocks - NumberOfBlocks 286 movw %es,%ax 287 shlw $(BLOCK_SHIFT-4), %bx 288 addw %bx,%ax 289 movw %ax,%es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE 290 cmpw $0,%cx 291 jne ReadCylinderLoop 292 popa 293 ret 294 295DiskError: 296 pushw %cs 297 popw %ds 298 leaw ErrorString,%si 299 movw $7,%cx 300 jmp PrintStringAndHalt 301 302PrintStringAndHalt: 303 movw $0xb800,%ax 304 movw %ax,%es 305 movw $160,%di 306 rep 307 movsw 308Halt: 309 jmp Halt 310 311ErrorString: 312 .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c 313 314 .org 0x01fa 315LBAOffsetForBootSector: 316 .long 0x0 317 318 .org 0x01fe 319 .word 0xaa55 320 321#****************************************************************************** 322#****************************************************************************** 323#****************************************************************************** 324 325.equ DELAY_PORT, 0x0ed # Port to use for 1uS delay 326.equ KBD_CONTROL_PORT, 0x060 # 8042 control port 327.equ KBD_STATUS_PORT, 0x064 # 8042 status port 328.equ WRITE_DATA_PORT_CMD, 0x0d1 # 8042 command to write the data port 329.equ ENABLE_A20_CMD, 0x0df # 8042 command to enable A20 330 331 .org 0x200 332 jmp start 333Em64String: 334.byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c 335 336start: 337 movw %cs,%ax 338 movw %ax,%ds 339 movw %ax,%es 340 movw %ax,%ss 341 movw $MyStack, %sp 342 343# mov ax,0b800h 344# mov es,ax 345# mov byte ptr es:[160],'a' 346# mov ax,cs 347# mov es,ax 348 349 movl $0,%ebx 350 leal MemoryMap, %edi 351MemMapLoop: 352 movl $0xe820,%eax 353 movl $20,%ecx 354 movl $0x534d4150, %edx # SMAP 355 int $0x15 356 jc MemMapDone 357 addl $20,%edi 358 cmpl $0,%ebx 359 je MemMapDone 360 jmp MemMapLoop 361MemMapDone: 362 leal MemoryMap, %eax 363 subl %eax,%edi # Get the address of the memory map 364 movl %edi, MemoryMapSize # Save the size of the memory map 365 366 xorl %ebx,%ebx 367 movw %cs,%bx # BX=segment 368 shll $4,%ebx # BX="linear" address of segment base 369 leal GDT_BASE(%ebx), %eax # EAX=PHYSICAL address of gdt 370 movl %eax, (gdtr + 2) # Put address of gdt into the gdtr 371 leal IDT_BASE(%ebx), %eax # EAX=PHYSICAL address of idt 372 movl %eax, (idtr + 2) # Put address of idt into the idtr 373 leal MemoryMapSize(%ebx), %edx # Physical base address of the memory map 374 375# mov ax,0b800h 376# mov es,ax 377# mov byte ptr es:[162],'b' 378# mov ax,cs 379# mov es,ax 380 381# 382# Enable A20 Gate 383# 384 385 movw $0x2401,%ax # Enable A20 Gate 386 int $0x15 387 jnc A20GateEnabled # Jump if it suceeded 388 389# 390# If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually. 391# 392 393 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller 394 jnz Timeout8042 # Jump if the 8042 timed out 395 outw %ax, $DELAY_PORT # Delay 1 uS 396 movb $WRITE_DATA_PORT_CMD, %al # 8042 cmd to write output port 397 outb %al, $KBD_STATUS_PORT # Send command to the 8042 398 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller 399 jnz Timeout8042 # Jump if the 8042 timed out 400 movb $ENABLE_A20_CMD, %al # gate address bit 20 on 401 outb %al, $KBD_CONTROL_PORT # Send command to thre 8042 402 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller 403 movw $25,%cx # Delay 25 uS for the command to complete on the 8042 404Delay25uS: 405 outw %ax, $DELAY_PORT # Delay 1 uS 406 loop Delay25uS 407Timeout8042: 408 409 410A20GateEnabled: 411 412# 413# DISABLE INTERRUPTS - Entering Protected Mode 414# 415 416 cli 417 418# mov ax,0b800h 419# mov es,ax 420# mov byte ptr es:[164],'c' 421# mov ax,cs 422# mov es,ax 423 424 leal OffsetIn32BitProtectedMode, %eax 425 addl $0x20000+0x6,%eax 426 movl %eax, OffsetIn32BitProtectedMode 427 428 leal OffsetInLongMode, %eax 429 addl $0x20000+0x6,%eax 430 movl %eax, OffsetInLongMode 431 432 # 433 # load GDT 434 # 435 .byte 0x66 436 lgdt gdtr 437 438 # 439 # Enable Protect Mode (set CR0.PE=1) 440 # 441 movl %cr0, %eax # Read CR0. 442 orl $0x1,%eax # Set PE=1 443 movl %eax, %cr0 # Write CR0. 444 .byte 0x66 445 .byte 0xea # jmp far 16:32 446OffsetIn32BitProtectedMode: 447 .long 0x0000000 # offset $+8 (In32BitProtectedMode) 448 .word 0x10 # selector (flat CS) 449In32BitProtectedMode: 450 451# 452# Entering Long Mode 453# 454 .byte 0x66 455 movw $8,%ax 456 movw %ax,%ds 457 movw %ax,%es 458 movw %ax,%ss 459 460 # 461 # Enable the 64-bit page-translation-table entries by 462 # setting CR4.PAE=1 (this is _required_ before activating 463 # long mode). Paging is not enabled until after long mode 464 # is enabled. 465 # 466 .byte 0xf 467 .byte 0x20 468 .byte 0xe0 469# mov eax, cr4 470 btsl $5,%eax 471 .byte 0xf 472 .byte 0x22 473 .byte 0xe0 474# mov cr4, eax 475 476 # 477 # This is the Trapolean Page Tables that are guarenteed 478 # under 4GB. 479 # 480 # Address Map: 481 # 10000 ~ 12000 - efildr (loaded) 482 # 20000 ~ 21000 - start64.com 483 # 21000 ~ 22000 - efi64.com 484 # 22000 ~ 90000 - efildr 485 # 90000 ~ 96000 - 4G pagetable (will be reload later) 486 # 487 .byte 0xb8 488 .long 0x90000 489# mov eax, 90000h 490 movl %eax, %cr3 491 492 # 493 # Enable long mode (set EFER.LME=1). 494 # 495 .byte 0xb9 496 .long 0xc0000080 497# mov ecx, 0c0000080h ; EFER MSR number. 498 .byte 0xf 499 .byte 0x32 500# rdmsr ; Read EFER. 501 .byte 0xf 502 .byte 0xba 503 .byte 0xe8 504 .byte 0x8 505# bts eax, 8 ; Set LME=1. 506 .byte 0xf 507 .byte 0x30 508# wrmsr ; Write EFER. 509 510 # 511 # Enable paging to activate long mode (set CR0.PG=1) 512 # 513 movl $cr0, %eax # Read CR0. 514 .byte 0xf 515 .byte 0xba 516 .byte 0xe8 517 .byte 0x1f 518# bts eax, 31 ; Set PG=1. 519 movl %eax, %cr0 # Write CR0. 520 jmp GoToLongMode 521GoToLongMode: 522 523 .byte 0x67 524 .byte 0xea # Far Jump $+9:Selector to reload CS 525OffsetInLongMode: 526 .long 00000000 # $+9 Offset is ensuing instruction boundary 527 .word 0x38 # Selector is our code selector, 38h 528 529InLongMode: 530 .byte 0x66 531 movw $0x30,%ax 532 movw %ax,%ds 533 534 .byte 0x66 535 movw $0x18,%ax 536 movw %ax,%es 537 movw %ax,%ss 538 movw %ax,%ds 539 540 .byte 0xbd 541 .long 0x400000 542# mov ebp,000400000h ; Destination of EFILDR32 543 .byte 0xbb 544 .long 0x70000 545# mov ebx,000070000h ; Length of copy 546 547 # 548 # load idt later 549 # 550 .byte 0x48 551 .byte 0x33 552 .byte 0xc0 553# xor rax, rax 554 .byte 0x66 555 movw $idtr, %ax 556 .byte 0x48 557 .byte 0x5 558 .long 0x20000 559# add rax, 20000h 560 561 .byte 0xf 562 .byte 0x1 563 .byte 0x18 564# lidt fword ptr [rax] 565 566 .byte 0x48 567 .byte 0xc7 568 .byte 0xc0 569 .long 0x21000 570# mov rax, 21000h 571 .byte 0x50 572# push rax 573 574# ret 575 .byte 0xc3 576 577Empty8042InputBuffer: 578 movw $0,%cx 579Empty8042Loop: 580 outw %ax, $DELAY_PORT # Delay 1us 581 inb $KBD_STATUS_PORT, %al # Read the 8042 Status Port 582 andb $0x2,%al # Check the Input Buffer Full Flag 583 loopnz Empty8042Loop # Loop until the input buffer is empty or a timout of 65536 uS 584 ret 585 586############################################################################## 587# data 588############################################################################## 589 590 .p2align 1 591 592 gdtr: .long GDT_END - GDT_BASE - 1 # GDT limit 593 .long 0 # (GDT base gets set above) 594############################################################################## 595# global descriptor table (GDT) 596############################################################################## 597 598 .p2align 1 599 600GDT_BASE: 601# null descriptor 602.equ NULL_SEL, .-GDT_BASE # Selector [0x0] 603 .word 0 # limit 15:0 604 .word 0 # base 15:0 605 .byte 0 # base 23:16 606 .byte 0 # type 607 .byte 0 # limit 19:16, flags 608 .byte 0 # base 31:24 609 610# linear data segment descriptor 611.equ LINEAR_SEL, .-GDT_BASE # Selector [0x8] 612 .word 0xFFFF # limit 0xFFFFF 613 .word 0 # base 0 614 .byte 0 615 .byte 0x92 # present, ring 0, data, expand-up, writable 616 .byte 0xCF # page-granular, 32-bit 617 .byte 0 618 619# linear code segment descriptor 620.equ LINEAR_CODE_SEL, .-GDT_BASE # Selector [0x10] 621 .word 0xFFFF # limit 0xFFFFF 622 .word 0 # base 0 623 .byte 0 624 .byte 0x9A # present, ring 0, data, expand-up, writable 625 .byte 0xCF # page-granular, 32-bit 626 .byte 0 627 628# system data segment descriptor 629.equ SYS_DATA_SEL, .-GDT_BASE # Selector [0x18] 630 .word 0xFFFF # limit 0xFFFFF 631 .word 0 # base 0 632 .byte 0 633 .byte 0x92 # present, ring 0, data, expand-up, writable 634 .byte 0xCF # page-granular, 32-bit 635 .byte 0 636 637# system code segment descriptor 638.equ SYS_CODE_SEL, .-GDT_BASE # Selector [0x20] 639 .word 0xFFFF # limit 0xFFFFF 640 .word 0 # base 0 641 .byte 0 642 .byte 0x9A # present, ring 0, data, expand-up, writable 643 .byte 0xCF # page-granular, 32-bit 644 .byte 0 645 646# spare segment descriptor 647.equ SPARE3_SEL, .-GDT_BASE # Selector [0x28] 648 .word 0 # limit 0xFFFFF 649 .word 0 # base 0 650 .byte 0 651 .byte 0 # present, ring 0, data, expand-up, writable 652 .byte 0 # page-granular, 32-bit 653 .byte 0 654 655# 656# system data segment descriptor 657# 658.equ SYS_DATA64_SEL, .-GDT_BASE # Selector [0x30] 659 .word 0xFFFF # limit 0xFFFFF 660 .word 0 # base 0 661 .byte 0 662 .byte 0x92 # P | DPL [1..2] | 1 | 1 | C | R | A 663 .byte 0xCF # G | D | L | AVL | Segment [19..16] 664 .byte 0 665 666# 667# system code segment descriptor 668# 669.equ SYS_CODE64_SEL, .-GDT_BASE # Selector [0x38] 670 .word 0xFFFF # limit 0xFFFFF 671 .word 0 # base 0 672 .byte 0 673 .byte 0x9A # P | DPL [1..2] | 1 | 1 | C | R | A 674 .byte 0xAF # G | D | L | AVL | Segment [19..16] 675 .byte 0 676 677# spare segment descriptor 678.equ SPARE4_SEL, .-GDT_BASE # Selector [0x40] 679 .word 0 # limit 0xFFFFF 680 .word 0 # base 0 681 .byte 0 682 .byte 0 # present, ring 0, data, expand-up, writable 683 .byte 0 # page-granular, 32-bit 684 .byte 0 685 686GDT_END: 687 688 .p2align 1 689 690 691 692idtr: .long IDT_END - IDT_BASE - 1 # IDT limit 693 .quad 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 .p2align 1 706 707 708IDT_BASE: 709# divide by zero (INT 0) 710.equ DIV_ZERO_SEL, .-IDT_BASE 711 .word 0 # offset 15:0 712 .long SYS_CODE64_SEL # selector 15:0 713 .byte 0 # 0 for interrupt gate 714 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 715 .word 0 # offset 31:16 716 .long 0 # offset 63:32 717 .long 0 # 0 for reserved 718 719# debug exception (INT 1) 720.equ DEBUG_EXCEPT_SEL, .-IDT_BASE 721 .word 0 # offset 15:0 722 .long SYS_CODE64_SEL # selector 15:0 723 .byte 0 # 0 for interrupt gate 724 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 725 .word 0 # offset 31:16 726 .long 0 # offset 63:32 727 .long 0 # 0 for reserved 728 729# NMI (INT 2) 730.equ NMI_SEL, .-IDT_BASE 731 .word 0 # offset 15:0 732 .long SYS_CODE64_SEL # selector 15:0 733 .byte 0 # 0 for interrupt gate 734 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 735 .word 0 # offset 31:16 736 .long 0 # offset 63:32 737 .long 0 # 0 for reserved 738 739# soft breakpoint (INT 3) 740.equ BREAKPOINT_SEL, .-IDT_BASE 741 .word 0 # offset 15:0 742 .long SYS_CODE64_SEL # selector 15:0 743 .byte 0 # 0 for interrupt gate 744 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 745 .word 0 # offset 31:16 746 .long 0 # offset 63:32 747 .long 0 # 0 for reserved 748 749# overflow (INT 4) 750.equ OVERFLOW_SEL, .-IDT_BASE 751 .word 0 # offset 15:0 752 .long SYS_CODE64_SEL # selector 15:0 753 .byte 0 # 0 for interrupt gate 754 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 755 .word 0 # offset 31:16 756 .long 0 # offset 63:32 757 .long 0 # 0 for reserved 758 759# bounds check (INT 5) 760.equ BOUNDS_CHECK_SEL, .-IDT_BASE 761 .word 0 # offset 15:0 762 .long SYS_CODE64_SEL # selector 15:0 763 .byte 0 # 0 for interrupt gate 764 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 765 .word 0 # offset 31:16 766 .long 0 # offset 63:32 767 .long 0 # 0 for reserved 768 769# invalid opcode (INT 6) 770.equ INVALID_OPCODE_SEL, .-IDT_BASE 771 .word 0 # offset 15:0 772 .long SYS_CODE64_SEL # selector 15:0 773 .byte 0 # 0 for interrupt gate 774 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 775 .word 0 # offset 31:16 776 .long 0 # offset 63:32 777 .long 0 # 0 for reserved 778 779# device not available (INT 7) 780.equ DEV_NOT_AVAIL_SEL, .-IDT_BASE 781 .word 0 # offset 15:0 782 .long SYS_CODE64_SEL # selector 15:0 783 .byte 0 # 0 for interrupt gate 784 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 785 .word 0 # offset 31:16 786 .long 0 # offset 63:32 787 .long 0 # 0 for reserved 788 789# double fault (INT 8) 790.equ DOUBLE_FAULT_SEL, .-IDT_BASE 791 .word 0 # offset 15:0 792 .long SYS_CODE64_SEL # selector 15:0 793 .byte 0 # 0 for interrupt gate 794 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 795 .word 0 # offset 31:16 796 .long 0 # offset 63:32 797 .long 0 # 0 for reserved 798 799# Coprocessor segment overrun - reserved (INT 9) 800.equ RSVD_INTR_SEL1, .-IDT_BASE 801 .word 0 # offset 15:0 802 .long SYS_CODE64_SEL # selector 15:0 803 .byte 0 # 0 for interrupt gate 804 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 805 .word 0 # offset 31:16 806 .long 0 # offset 63:32 807 .long 0 # 0 for reserved 808 809# invalid TSS (INT 0ah) 810.equ INVALID_TSS_SEL, .-IDT_BASE 811 .word 0 # offset 15:0 812 .long SYS_CODE64_SEL # selector 15:0 813 .byte 0 # 0 for interrupt gate 814 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 815 .word 0 # offset 31:16 816 .long 0 # offset 63:32 817 .long 0 # 0 for reserved 818 819# segment not present (INT 0bh) 820.equ SEG_NOT_PRESENT_SEL, .-IDT_BASE 821 .word 0 # offset 15:0 822 .long SYS_CODE64_SEL # selector 15:0 823 .byte 0 # 0 for interrupt gate 824 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 825 .word 0 # offset 31:16 826 .long 0 # offset 63:32 827 .long 0 # 0 for reserved 828 829# stack fault (INT 0ch) 830.equ STACK_FAULT_SEL, .-IDT_BASE 831 .word 0 # offset 15:0 832 .long SYS_CODE64_SEL # selector 15:0 833 .byte 0 # 0 for interrupt gate 834 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 835 .word 0 # offset 31:16 836 .long 0 # offset 63:32 837 .long 0 # 0 for reserved 838 839# general protection (INT 0dh) 840.equ GP_FAULT_SEL, .-IDT_BASE 841 .word 0 # offset 15:0 842 .long SYS_CODE64_SEL # selector 15:0 843 .byte 0 # 0 for interrupt gate 844 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 845 .word 0 # offset 31:16 846 .long 0 # offset 63:32 847 .long 0 # 0 for reserved 848 849# page fault (INT 0eh) 850.equ PAGE_FAULT_SEL, .-IDT_BASE 851 .word 0 # offset 15:0 852 .long SYS_CODE64_SEL # selector 15:0 853 .byte 0 # 0 for interrupt gate 854 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 855 .word 0 # offset 31:16 856 .long 0 # offset 63:32 857 .long 0 # 0 for reserved 858 859# Intel reserved - do not use (INT 0fh) 860.equ RSVD_INTR_SEL2, .-IDT_BASE 861 .word 0 # offset 15:0 862 .long SYS_CODE64_SEL # selector 15:0 863 .byte 0 # 0 for interrupt gate 864 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 865 .word 0 # offset 31:16 866 .long 0 # offset 63:32 867 .long 0 # 0 for reserved 868 869# floating point error (INT 10h) 870.equ FLT_POINT_ERR_SEL, .-IDT_BASE 871 .word 0 # offset 15:0 872 .long SYS_CODE64_SEL # selector 15:0 873 .byte 0 # 0 for interrupt gate 874 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 875 .word 0 # offset 31:16 876 .long 0 # offset 63:32 877 .long 0 # 0 for reserved 878 879# alignment check (INT 11h) 880.equ ALIGNMENT_CHECK_SEL, .-IDT_BASE 881 .word 0 # offset 15:0 882 .long SYS_CODE64_SEL # selector 15:0 883 .byte 0 # 0 for interrupt gate 884 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 885 .word 0 # offset 31:16 886 .long 0 # offset 63:32 887 .long 0 # 0 for reserved 888 889# machine check (INT 12h) 890.equ MACHINE_CHECK_SEL, .-IDT_BASE 891 .word 0 # offset 15:0 892 .long SYS_CODE64_SEL # selector 15:0 893 .byte 0 # 0 for interrupt gate 894 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 895 .word 0 # offset 31:16 896 .long 0 # offset 63:32 897 .long 0 # 0 for reserved 898 899# SIMD floating-point exception (INT 13h) 900.equ SIMD_EXCEPTION_SEL, .-IDT_BASE 901 .word 0 # offset 15:0 902 .long SYS_CODE64_SEL # selector 15:0 903 .byte 0 # 0 for interrupt gate 904 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 905 .word 0 # offset 31:16 906 .long 0 # offset 63:32 907 .long 0 # 0 for reserved 908 909# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail 910 .fill 85 * 16, 1, 0 # db (85 * 16) dup(0) 911 912# IRQ 0 (System timer) - (INT 68h) 913.equ IRQ0_SEL, .-IDT_BASE 914 .word 0 # offset 15:0 915 .long SYS_CODE64_SEL # selector 15:0 916 .byte 0 # 0 for interrupt gate 917 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 918 .word 0 # offset 31:16 919 .long 0 # offset 63:32 920 .long 0 # 0 for reserved 921 922# IRQ 1 (8042 Keyboard controller) - (INT 69h) 923.equ IRQ1_SEL, .-IDT_BASE 924 .word 0 # offset 15:0 925 .long SYS_CODE64_SEL # selector 15:0 926 .byte 0 # 0 for interrupt gate 927 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 928 .word 0 # offset 31:16 929 .long 0 # offset 63:32 930 .long 0 # 0 for reserved 931 932# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah) 933.equ IRQ2_SEL, .-IDT_BASE 934 .word 0 # offset 15:0 935 .long SYS_CODE64_SEL # selector 15:0 936 .byte 0 # 0 for interrupt gate 937 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 938 .word 0 # offset 31:16 939 .long 0 # offset 63:32 940 .long 0 # 0 for reserved 941 942# IRQ 3 (COM 2) - (INT 6bh) 943.equ IRQ3_SEL, .-IDT_BASE 944 .word 0 # offset 15:0 945 .long SYS_CODE64_SEL # selector 15:0 946 .byte 0 # 0 for interrupt gate 947 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 948 .word 0 # offset 31:16 949 .long 0 # offset 63:32 950 .long 0 # 0 for reserved 951 952# IRQ 4 (COM 1) - (INT 6ch) 953.equ IRQ4_SEL, .-IDT_BASE 954 .word 0 # offset 15:0 955 .long SYS_CODE64_SEL # selector 15:0 956 .byte 0 # 0 for interrupt gate 957 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 958 .word 0 # offset 31:16 959 .long 0 # offset 63:32 960 .long 0 # 0 for reserved 961 962# IRQ 5 (LPT 2) - (INT 6dh) 963.equ IRQ5_SEL, .-IDT_BASE 964 .word 0 # offset 15:0 965 .long SYS_CODE64_SEL # selector 15:0 966 .byte 0 # 0 for interrupt gate 967 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 968 .word 0 # offset 31:16 969 .long 0 # offset 63:32 970 .long 0 # 0 for reserved 971 972# IRQ 6 (Floppy controller) - (INT 6eh) 973.equ IRQ6_SEL, .-IDT_BASE 974 .word 0 # offset 15:0 975 .long SYS_CODE64_SEL # selector 15:0 976 .byte 0 # 0 for interrupt gate 977 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 978 .word 0 # offset 31:16 979 .long 0 # offset 63:32 980 .long 0 # 0 for reserved 981 982# IRQ 7 (LPT 1) - (INT 6fh) 983.equ IRQ7_SEL, .-IDT_BASE 984 .word 0 # offset 15:0 985 .long SYS_CODE64_SEL # selector 15:0 986 .byte 0 # 0 for interrupt gate 987 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 988 .word 0 # offset 31:16 989 .long 0 # offset 63:32 990 .long 0 # 0 for reserved 991 992# IRQ 8 (RTC Alarm) - (INT 70h) 993.equ IRQ8_SEL, .-IDT_BASE 994 .word 0 # offset 15:0 995 .long SYS_CODE64_SEL # selector 15:0 996 .byte 0 # 0 for interrupt gate 997 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 998 .word 0 # offset 31:16 999 .long 0 # offset 63:32 1000 .long 0 # 0 for reserved 1001 1002# IRQ 9 - (INT 71h) 1003.equ IRQ9_SEL, .-IDT_BASE 1004 .word 0 # offset 15:0 1005 .long SYS_CODE64_SEL # selector 15:0 1006 .byte 0 # 0 for interrupt gate 1007 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 1008 .word 0 # offset 31:16 1009 .long 0 # offset 63:32 1010 .long 0 # 0 for reserved 1011 1012# IRQ 10 - (INT 72h) 1013.equ IRQ10_SEL, .-IDT_BASE 1014 .word 0 # offset 15:0 1015 .long SYS_CODE64_SEL # selector 15:0 1016 .byte 0 # 0 for interrupt gate 1017 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 1018 .word 0 # offset 31:16 1019 .long 0 # offset 63:32 1020 .long 0 # 0 for reserved 1021 1022# IRQ 11 - (INT 73h) 1023.equ IRQ11_SEL, .-IDT_BASE 1024 .word 0 # offset 15:0 1025 .long SYS_CODE64_SEL # selector 15:0 1026 .byte 0 # 0 for interrupt gate 1027 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 1028 .word 0 # offset 31:16 1029 .long 0 # offset 63:32 1030 .long 0 # 0 for reserved 1031 1032# IRQ 12 (PS/2 mouse) - (INT 74h) 1033.equ IRQ12_SEL, .-IDT_BASE 1034 .word 0 # offset 15:0 1035 .long SYS_CODE64_SEL # selector 15:0 1036 .byte 0 # 0 for interrupt gate 1037 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 1038 .word 0 # offset 31:16 1039 .long 0 # offset 63:32 1040 .long 0 # 0 for reserved 1041 1042# IRQ 13 (Floating point error) - (INT 75h) 1043.equ IRQ13_SEL, .-IDT_BASE 1044 .word 0 # offset 15:0 1045 .long SYS_CODE64_SEL # selector 15:0 1046 .byte 0 # 0 for interrupt gate 1047 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 1048 .word 0 # offset 31:16 1049 .long 0 # offset 63:32 1050 .long 0 # 0 for reserved 1051 1052# IRQ 14 (Secondary IDE) - (INT 76h) 1053.equ IRQ14_SEL, .-IDT_BASE 1054 .word 0 # offset 15:0 1055 .long SYS_CODE64_SEL # selector 15:0 1056 .byte 0 # 0 for interrupt gate 1057 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 1058 .word 0 # offset 31:16 1059 .long 0 # offset 63:32 1060 .long 0 # 0 for reserved 1061 1062# IRQ 15 (Primary IDE) - (INT 77h) 1063.equ IRQ15_SEL, .-IDT_BASE 1064 .word 0 # offset 15:0 1065 .long SYS_CODE64_SEL # selector 15:0 1066 .byte 0 # 0 for interrupt gate 1067 .byte 0x0e | 0x80 # type = 386 interrupt gate, present 1068 .word 0 # offset 31:16 1069 .long 0 # offset 63:32 1070 .long 0 # 0 for reserved 1071 1072IDT_END: 1073 1074 .p2align 1 1075 1076MemoryMapSize: .long 0 1077MemoryMap: .long 0,0,0,0,0,0,0,0 1078 .long 0,0,0,0,0,0,0,0 1079 .long 0,0,0,0,0,0,0,0 1080 .long 0,0,0,0,0,0,0,0 1081 .long 0,0,0,0,0,0,0,0 1082 .long 0,0,0,0,0,0,0,0 1083 .long 0,0,0,0,0,0,0,0 1084 .long 0,0,0,0,0,0,0,0 1085 .long 0,0,0,0,0,0,0,0 1086 .long 0,0,0,0,0,0,0,0 1087 .long 0,0,0,0,0,0,0,0 1088 .long 0,0,0,0,0,0,0,0 1089 .long 0,0,0,0,0,0,0,0 1090 .long 0,0,0,0,0,0,0,0 1091 .long 0,0,0,0,0,0,0,0 1092 .long 0,0,0,0,0,0,0,0 1093 .long 0,0,0,0,0,0,0,0 1094 .long 0,0,0,0,0,0,0,0 1095 .long 0,0,0,0,0,0,0,0 1096 .long 0,0,0,0,0,0,0,0 1097 .long 0,0,0,0,0,0,0,0 1098 .long 0,0,0,0,0,0,0,0 1099 .long 0,0,0,0,0,0,0,0 1100 .long 0,0,0,0,0,0,0,0 1101 .long 0,0,0,0,0,0,0,0 1102 .long 0,0,0,0,0,0,0,0 1103 .long 0,0,0,0,0,0,0,0 1104 .long 0,0,0,0,0,0,0,0 1105 .long 0,0,0,0,0,0,0,0 1106 .long 0,0,0,0,0,0,0,0 1107 1108 .long 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 .long 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 0x0fe0 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 0x0ffe 1144BlockSignature: 1145 .word 0xaa55 1146 1147