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