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