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