Home | History | Annotate | Download | only in BootSector
      1 ;------------------------------------------------------------------------------
      2 ;*
      3 ;*   Copyright (c) 2006 - 2011, 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 ;*    start16.asm
     13 ;*  
     14 ;*   Abstract:
     15 ;*
     16 ;------------------------------------------------------------------------------
     17 
     18         .model  small
     19         .stack
     20         .486p
     21         .code
     22 
     23 FAT_DIRECTORY_ENTRY_SIZE    EQU     020h
     24 FAT_DIRECTORY_ENTRY_SHIFT   EQU     5
     25 BLOCK_SIZE                  EQU     0200h
     26 BLOCK_MASK                  EQU     01ffh
     27 BLOCK_SHIFT                 EQU     9
     28 
     29         org 0h
     30 Ia32Jump:
     31   jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes
     32   nop
     33 
     34 OemId             db  "INTEL   "    ; OemId               - 8 bytes
     35 
     36 SectorSize        dw  0             ; Sector Size         - 16 bits
     37 SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits
     38 ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits
     39 NoFats            db  0             ; Number of FATs      - 8 bits
     40 RootEntries       dw  0             ; Root Entries        - 16 bits
     41 Sectors           dw  0             ; Number of Sectors   - 16 bits
     42 Media             db  0             ; Media               - 8 bits  - ignored
     43 SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits
     44 SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored
     45 Heads             dw  0             ; Heads               - 16 bits - ignored
     46 HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored
     47 LargeSectors      dd  0             ; Large Sectors       - 32 bits 
     48 PhysicalDrive     db  0             ; PhysicalDriveNumber - 8 bits  - ignored
     49 CurrentHead       db  0             ; Current Head        - 8 bits
     50 Signature         db  0             ; Signature           - 8 bits  - ignored
     51 VolId             db  "    "        ; Volume Serial Number- 4 bytes
     52 FatLabel          db  "           " ; Label               - 11 bytes
     53 SystemId          db  "FAT16   "    ; SystemId            - 8 bytes
     54 
     55 BootSectorEntryPoint:
     56         ASSUME  ds:@code
     57         ASSUME  ss:@code
     58       ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
     59       ; cx = Start Cluster of EfiLdr
     60       ; dx = Start Cluster of Efivar.bin
     61 
     62 ; Re use the BPB data stored in Boot Sector
     63         mov     bp,07c00h
     64 
     65         push    cx
     66 ; Read Efivar.bin
     67 ;       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already
     68         mov     ax,01900h
     69         mov     es,ax
     70         test    dx,dx
     71         jnz     CheckVarStoreSize
     72 
     73         mov     al,1
     74 NoVarStore:
     75         push    es
     76 ; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
     77         mov     byte ptr es:[4],al
     78         jmp     SaveVolumeId
     79 
     80 CheckVarStoreSize:
     81         mov     di,dx
     82         cmp     dword ptr ds:[di+2], 04000h
     83         mov     al,2
     84         jne     NoVarStore
     85 
     86 LoadVarStore:
     87         mov     al,0
     88         mov     byte ptr es:[4],al
     89         mov     cx,word ptr[di]
     90 ;       ES:DI = 1500:0
     91         xor     di,di
     92         push    es
     93         mov     ax,01500h
     94         mov     es,ax
     95         call    ReadFile
     96 SaveVolumeId:
     97         pop     es
     98         mov     ax,word ptr [bp+VolId]
     99         mov     word ptr es:[0],ax                  ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
    100         mov     ax,word ptr [bp+VolId+2]
    101         mov     word ptr es:[2],ax
    102 
    103 ; Read Efildr
    104         pop     cx
    105 ;       cx    = Start Cluster of Efildr -> BS.com has filled already
    106 ;       ES:DI = 2000:0, first cluster will be read again
    107         xor     di,di                               ; di = 0
    108         mov     ax,02000h
    109         mov     es,ax
    110         call    ReadFile
    111         mov     ax,cs
    112         mov     word ptr cs:[JumpSegment],ax
    113 
    114 JumpFarInstruction:
    115         db      0eah
    116 JumpOffset:
    117         dw      0200h
    118 JumpSegment:
    119         dw      2000h
    120 
    121 
    122 
    123 ; ****************************************************************************
    124 ; ReadFile
    125 ;
    126 ; Arguments:
    127 ;   CX    = Start Cluster of File
    128 ;   ES:DI = Buffer to store file content read from disk
    129 ;
    130 ; Return:
    131 ;   (ES << 4 + DI) = end of file content Buffer
    132 ;
    133 ; ****************************************************************************
    134 ReadFile:
    135 ; si      = NumberOfClusters
    136 ; cx      = ClusterNumber
    137 ; dx      = CachedFatSectorNumber
    138 ; ds:0000 = CacheFatSectorBuffer
    139 ; es:di   = Buffer to load file
    140 ; bx      = NextClusterNumber
    141         pusha
    142         mov     si,1                                ; NumberOfClusters = 1
    143         push    cx                                  ; Push Start Cluster onto stack
    144         mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff
    145 FatChainLoop:
    146         mov     ax,cx                               ; ax = ClusterNumber    
    147         and     ax,0fff8h                           ; ax = ax & 0xfff8
    148         cmp     ax,0fff8h                           ; See if this is the last cluster
    149         je      FoundLastCluster                    ; Jump if last cluster found
    150         mov     ax,cx                               ; ax = ClusterNumber
    151         shl     ax,1                                ; FatOffset = ClusterNumber * 2
    152         push    si                                  ; Save si
    153         mov     si,ax                               ; si = FatOffset
    154         shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT
    155         add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
    156         and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK
    157         cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber
    158         je      SkipFatRead
    159         mov     bx,2                                
    160         push    es
    161         push    ds
    162         pop     es
    163         call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI
    164         pop     es
    165         mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber
    166 SkipFatRead:
    167         mov     bx,word ptr [si]                    ; bx = NextClusterNumber
    168         mov     ax,cx                               ; ax = ClusterNumber
    169         pop     si                                  ; Restore si
    170         dec     bx                                  ; bx = NextClusterNumber - 1
    171         cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber
    172         jne     ReadClusters
    173         inc     bx                                  ; bx = NextClusterNumber
    174         inc     si                                  ; NumberOfClusters++
    175         mov     cx,bx                               ; ClusterNumber = NextClusterNumber
    176         jmp     FatChainLoop
    177 ReadClusters:
    178         inc     bx
    179         pop     ax                                  ; ax = StartCluster
    180         push    bx                                  ; StartCluster = NextClusterNumber
    181         mov     cx,bx                               ; ClusterNumber = NextClusterNumber
    182         sub     ax,2                                ; ax = StartCluster - 2
    183         xor     bh,bh                               
    184         mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster
    185         mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster
    186         add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
    187         push    ax                                  ; save start sector
    188         mov     ax,si                               ; ax = NumberOfClusters
    189         mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster
    190         mov     bx,ax                               ; bx = Number of Sectors
    191         pop     ax                                  ; ax = Start Sector
    192         call    ReadBlocks
    193         mov     si,1                                ; NumberOfClusters = 1
    194         jmp     FatChainLoop
    195 FoundLastCluster:
    196         pop     cx
    197         popa
    198         ret
    199 
    200 
    201 ; ****************************************************************************
    202 ; ReadBlocks - Reads a set of blocks from a block device
    203 ;
    204 ; AX    = Start LBA
    205 ; BX    = Number of Blocks to Read
    206 ; ES:DI = Buffer to store sectors read from disk
    207 ; ****************************************************************************
    208 
    209 ; cx = Blocks
    210 ; bx = NumberOfBlocks
    211 ; si = StartLBA
    212 
    213 ReadBlocks:
    214         pusha
    215         add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA
    216         add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA
    217         mov     esi,eax                             ; esi = Start LBA
    218         mov     cx,bx                               ; cx = Number of blocks to read
    219 ReadCylinderLoop:
    220         mov     bp,07bfch                           ; bp = 0x7bfc
    221         mov     eax,esi                             ; eax = Start LBA
    222         xor     edx,edx                             ; edx = 0
    223         movzx   ebx,word ptr [bp]                   ; bx = MaxSector
    224         div     ebx                                 ; ax = StartLBA / MaxSector
    225         inc     dx                                  ; dx = (StartLBA % MaxSector) + 1
    226 
    227         mov     bx,word ptr [bp]                    ; bx = MaxSector
    228         sub     bx,dx                               ; bx = MaxSector - Sector
    229         inc     bx                                  ; bx = MaxSector - Sector + 1
    230         cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)
    231         jg      LimitTransfer
    232         mov     bx,cx                               ; bx = Blocks
    233 LimitTransfer:
    234         push    ax                                  ; save ax
    235         mov     ax,es                               ; ax = es
    236         shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system
    237         and     ax,07fh                             ; ax = Number of blocks into current seg
    238         add     ax,bx                               ; ax = End Block number of transfer
    239         cmp     ax,080h                             ; See if it crosses a 64K boundry
    240         jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry
    241         sub     ax,080h                             ; ax = Number of blocks past 64K boundry
    242         sub     bx,ax                               ; Decrease transfer size by block overage
    243 NotCrossing64KBoundry:
    244         pop     ax                                  ; restore ax
    245 
    246         push    cx
    247         mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector
    248         xor     dx,dx                               ; dx = 0
    249         div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  
    250                                                     ; dx = ax % (MaxHead + 1) = Head
    251 
    252         push    bx                                  ; Save number of blocks to transfer
    253         mov     dh,dl                               ; dh = Head
    254         mov     bp,07c00h                           ; bp = 0x7c00
    255         mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number
    256         mov     ch,al                               ; ch = Cylinder
    257         mov     al,bl                               ; al = Blocks
    258         mov     ah,2                                ; ah = Function 2
    259         mov     bx,di                               ; es:bx = Buffer address
    260         int     013h
    261         jc      DiskError
    262         pop     bx
    263         pop     cx
    264         movzx   ebx,bx
    265         add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks
    266         sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks
    267         mov     ax,es
    268         shl     bx,(BLOCK_SHIFT-4)
    269         add     ax,bx
    270         mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
    271         cmp     cx,0
    272         jne     ReadCylinderLoop
    273         popa
    274         ret
    275 
    276 DiskError:
    277         push cs
    278         pop  ds
    279         lea  si, [ErrorString]
    280         mov  cx, 7
    281         jmp  PrintStringAndHalt
    282 
    283 PrintStringAndHalt:
    284         mov  ax,0b800h
    285         mov  es,ax
    286         mov  di,160
    287         rep  movsw
    288 Halt:
    289         jmp   Halt
    290 
    291 ErrorString:
    292         db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
    293 
    294         org     01fah
    295 LBAOffsetForBootSector:
    296         dd      0h
    297 
    298         org     01feh
    299         dw      0aa55h
    300 
    301 ;******************************************************************************
    302 ;******************************************************************************
    303 ;******************************************************************************
    304 
    305 DELAY_PORT           equ     0edh    ; Port to use for 1uS delay
    306 KBD_CONTROL_PORT     equ     060h    ; 8042 control port     
    307 KBD_STATUS_PORT      equ     064h    ; 8042 status port      
    308 WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port
    309 ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20
    310 
    311         org     200h
    312         jmp start
    313 Em64String:
    314         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
    315 
    316 start:  
    317         mov ax,cs
    318         mov ds,ax
    319         mov es,ax
    320         mov ss,ax
    321         mov sp,MyStack
    322 
    323 ;        mov ax,0b800h
    324 ;        mov es,ax
    325 ;        mov byte ptr es:[160],'a'
    326 ;        mov ax,cs
    327 ;        mov es,ax
    328 
    329         mov ebx,0
    330         lea edi,MemoryMap
    331 MemMapLoop:
    332         mov eax,0e820h
    333         mov ecx,20
    334         mov edx,'SMAP'
    335         int 15h
    336         jc  MemMapDone
    337         add edi,20
    338         cmp ebx,0
    339         je  MemMapDone
    340         jmp MemMapLoop
    341 MemMapDone:
    342         lea eax,MemoryMap
    343         sub edi,eax                         ; Get the address of the memory map
    344         mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map
    345 
    346         xor     ebx,ebx
    347         mov     bx,cs                       ; BX=segment
    348         shl     ebx,4                       ; BX="linear" address of segment base
    349         lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt
    350         mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr
    351         lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt
    352         mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr
    353         lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map
    354 
    355         add ebx,01000h                      ; Source of EFI32
    356         mov dword ptr [JUMP+2],ebx
    357         add ebx,01000h
    358         mov esi,ebx                         ; Source of EFILDR32
    359 
    360 ;        mov ax,0b800h
    361 ;        mov es,ax
    362 ;        mov byte ptr es:[162],'b'
    363 ;        mov ax,cs
    364 ;        mov es,ax
    365 
    366 ;
    367 ; Enable A20 Gate 
    368 ;
    369 
    370         mov ax,2401h                        ; Enable A20 Gate
    371         int 15h
    372         jnc A20GateEnabled                  ; Jump if it suceeded
    373 
    374 ;
    375 ; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
    376 ;
    377 
    378         call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
    379         jnz     Timeout8042                 ; Jump if the 8042 timed out
    380         out     DELAY_PORT,ax               ; Delay 1 uS
    381         mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port
    382         out     KBD_STATUS_PORT,al          ; Send command to the 8042
    383         call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
    384         jnz     Timeout8042                 ; Jump if the 8042 timed out
    385         mov     al,ENABLE_A20_CMD           ; gate address bit 20 on
    386         out     KBD_CONTROL_PORT,al         ; Send command to thre 8042
    387         call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
    388         mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042
    389 Delay25uS:
    390         out     DELAY_PORT,ax               ; Delay 1 uS
    391         loop    Delay25uS                       
    392 Timeout8042:
    393 
    394 
    395 A20GateEnabled:
    396         mov     bx,0008h                    ; Flat data descriptor
    397 ;
    398 ; DISABLE INTERRUPTS - Entering Protected Mode
    399 ;
    400 
    401         cli                             
    402 
    403 ;        mov ax,0b800h
    404 ;        mov es,ax
    405 ;        mov byte ptr es:[164],'c'
    406 ;        mov ax,cs
    407 ;        mov es,ax
    408 
    409         db      66h     
    410         lgdt    fword ptr [gdtr]
    411         db      66h     
    412         lidt    fword ptr [idtr]
    413 
    414         mov     eax,cr0
    415         or      al,1
    416         mov     cr0,eax
    417 JUMP:
    418 ; jmp far 0010:00020000
    419         db  066h
    420         db  0eah
    421         dd  000020000h
    422         dw  00010h
    423 
    424 Empty8042InputBuffer:
    425         mov cx,0
    426 Empty8042Loop:
    427         out     DELAY_PORT,ax               ; Delay 1us
    428         in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port
    429         and     al,02h                      ; Check the Input Buffer Full Flag
    430         loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS
    431         ret
    432 
    433 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    434 ; data
    435 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    436 
    437         align 02h
    438 
    439 gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit
    440         dd 0                        ; (GDT base gets set above)
    441 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    442 ;   global descriptor table (GDT)
    443 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    444 
    445         align 02h
    446 
    447 public GDT_BASE
    448 GDT_BASE:
    449 ; null descriptor
    450 NULL_SEL            equ $-GDT_BASE
    451         dw 0            ; limit 15:0
    452         dw 0            ; base 15:0
    453         db 0            ; base 23:16
    454         db 0            ; type
    455         db 0            ; limit 19:16, flags
    456         db 0            ; base 31:24
    457 
    458 ; linear data segment descriptor
    459 LINEAR_SEL      equ $-GDT_BASE
    460         dw 0FFFFh       ; limit 0xFFFFF
    461         dw 0            ; base 0
    462         db 0
    463         db 092h         ; present, ring 0, data, expand-up, writable
    464         db 0CFh                 ; page-granular, 32-bit
    465         db 0
    466 
    467 ; linear code segment descriptor
    468 LINEAR_CODE_SEL equ $-GDT_BASE
    469         dw 0FFFFh       ; limit 0xFFFFF
    470         dw 0            ; base 0
    471         db 0
    472         db 09Ah         ; present, ring 0, data, expand-up, writable
    473         db 0CFh                 ; page-granular, 32-bit
    474         db 0
    475 
    476 ; system data segment descriptor
    477 SYS_DATA_SEL    equ $-GDT_BASE
    478         dw 0FFFFh       ; limit 0xFFFFF
    479         dw 0            ; base 0
    480         db 0
    481         db 092h         ; present, ring 0, data, expand-up, writable
    482         db 0CFh                 ; page-granular, 32-bit
    483         db 0
    484 
    485 ; system code segment descriptor
    486 SYS_CODE_SEL    equ $-GDT_BASE
    487         dw 0FFFFh       ; limit 0xFFFFF
    488         dw 0            ; base 0
    489         db 0
    490         db 09Ah         ; present, ring 0, data, expand-up, writable
    491         db 0CFh                 ; page-granular, 32-bit
    492         db 0
    493 
    494 ; spare segment descriptor
    495 SPARE3_SEL  equ $-GDT_BASE
    496         dw 0            ; limit 0xFFFFF
    497         dw 0            ; base 0
    498         db 0
    499         db 0            ; present, ring 0, data, expand-up, writable
    500         db 0            ; page-granular, 32-bit
    501         db 0
    502 
    503 ; spare segment descriptor
    504 SPARE4_SEL  equ $-GDT_BASE
    505         dw 0            ; limit 0xFFFFF
    506         dw 0            ; base 0
    507         db 0
    508         db 0            ; present, ring 0, data, expand-up, writable
    509         db 0            ; page-granular, 32-bit
    510         db 0
    511 
    512 ; spare segment descriptor
    513 SPARE5_SEL  equ $-GDT_BASE
    514         dw 0            ; limit 0xFFFFF
    515         dw 0            ; base 0
    516         db 0
    517         db 0            ; present, ring 0, data, expand-up, writable
    518         db 0            ; page-granular, 32-bit
    519         db 0
    520 
    521 GDT_END:
    522 
    523         align 02h
    524 
    525 
    526 
    527 idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit
    528         dd 0                        ; (IDT base gets set above)
    529 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    530 ;   interrupt descriptor table (IDT)
    531 ;
    532 ;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
    533 ;       mappings.  This implementation only uses the system timer and all other
    534 ;       IRQs will remain masked.  The descriptors for vectors 33+ are provided
    535 ;       for convenience.
    536 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    537 
    538 ;idt_tag db "IDT",0     
    539         align 02h
    540 
    541 public IDT_BASE
    542 IDT_BASE:
    543 ; divide by zero (INT 0)
    544 DIV_ZERO_SEL        equ $-IDT_BASE
    545         dw 0            ; offset 15:0
    546         dw SYS_CODE_SEL ; selector 15:0
    547         db 0            ; 0 for interrupt gate
    548         db 0eh OR 80h   ; type = 386 interrupt gate, present
    549         dw 0            ; offset 31:16
    550 
    551 ; debug exception (INT 1)
    552 DEBUG_EXCEPT_SEL    equ $-IDT_BASE
    553         dw 0            ; offset 15:0
    554         dw SYS_CODE_SEL ; selector 15:0
    555         db 0            ; 0 for interrupt gate
    556         db 0eh OR 80h   ; type = 386 interrupt gate, present
    557         dw 0            ; offset 31:16
    558 
    559 ; NMI (INT 2)
    560 NMI_SEL             equ $-IDT_BASE
    561         dw 0            ; offset 15:0
    562         dw SYS_CODE_SEL ; selector 15:0
    563         db 0            ; 0 for interrupt gate
    564         db 0eh OR 80h   ; type = 386 interrupt gate, present
    565         dw 0            ; offset 31:16
    566 
    567 ; soft breakpoint (INT 3)
    568 BREAKPOINT_SEL      equ $-IDT_BASE
    569         dw 0            ; offset 15:0
    570         dw SYS_CODE_SEL ; selector 15:0
    571         db 0            ; 0 for interrupt gate
    572         db 0eh OR 80h   ; type = 386 interrupt gate, present
    573         dw 0            ; offset 31:16
    574 
    575 ; overflow (INT 4)
    576 OVERFLOW_SEL        equ $-IDT_BASE
    577         dw 0            ; offset 15:0
    578         dw SYS_CODE_SEL ; selector 15:0
    579         db 0            ; 0 for interrupt gate
    580         db 0eh OR 80h   ; type = 386 interrupt gate, present
    581         dw 0            ; offset 31:16
    582 
    583 ; bounds check (INT 5)
    584 BOUNDS_CHECK_SEL    equ $-IDT_BASE
    585         dw 0            ; offset 15:0
    586         dw SYS_CODE_SEL ; selector 15:0
    587         db 0            ; 0 for interrupt gate
    588         db 0eh OR 80h   ; type = 386 interrupt gate, present
    589         dw 0            ; offset 31:16
    590 
    591 ; invalid opcode (INT 6)
    592 INVALID_OPCODE_SEL  equ $-IDT_BASE
    593         dw 0            ; offset 15:0
    594         dw SYS_CODE_SEL ; selector 15:0
    595         db 0            ; 0 for interrupt gate
    596         db 0eh OR 80h   ; type = 386 interrupt gate, present
    597         dw 0            ; offset 31:16
    598 
    599 ; device not available (INT 7)
    600 DEV_NOT_AVAIL_SEL   equ $-IDT_BASE
    601         dw 0            ; offset 15:0
    602         dw SYS_CODE_SEL ; selector 15:0
    603         db 0            ; 0 for interrupt gate
    604         db 0eh OR 80h   ; type = 386 interrupt gate, present
    605         dw 0            ; offset 31:16
    606 
    607 ; double fault (INT 8)
    608 DOUBLE_FAULT_SEL    equ $-IDT_BASE
    609         dw 0            ; offset 15:0
    610         dw SYS_CODE_SEL ; selector 15:0
    611         db 0            ; 0 for interrupt gate
    612         db 0eh OR 80h   ; type = 386 interrupt gate, present
    613         dw 0            ; offset 31:16
    614 
    615 ; Coprocessor segment overrun - reserved (INT 9)
    616 RSVD_INTR_SEL1      equ $-IDT_BASE
    617         dw 0            ; offset 15:0
    618         dw SYS_CODE_SEL ; selector 15:0
    619         db 0            ; 0 for interrupt gate
    620         db 0eh OR 80h   ; type = 386 interrupt gate, present
    621         dw 0            ; offset 31:16
    622 
    623 ; invalid TSS (INT 0ah)
    624 INVALID_TSS_SEL     equ $-IDT_BASE
    625         dw 0            ; offset 15:0
    626         dw SYS_CODE_SEL ; selector 15:0
    627         db 0            ; 0 for interrupt gate
    628         db 0eh OR 80h   ; type = 386 interrupt gate, present
    629         dw 0            ; offset 31:16
    630 
    631 ; segment not present (INT 0bh)
    632 SEG_NOT_PRESENT_SEL equ $-IDT_BASE
    633         dw 0            ; offset 15:0
    634         dw SYS_CODE_SEL ; selector 15:0
    635         db 0            ; 0 for interrupt gate
    636         db 0eh OR 80h   ; type = 386 interrupt gate, present
    637         dw 0            ; offset 31:16
    638 
    639 ; stack fault (INT 0ch)
    640 STACK_FAULT_SEL     equ $-IDT_BASE
    641         dw 0            ; offset 15:0
    642         dw SYS_CODE_SEL ; selector 15:0
    643         db 0            ; 0 for interrupt gate
    644         db 0eh OR 80h   ; type = 386 interrupt gate, present
    645         dw 0            ; offset 31:16
    646 
    647 ; general protection (INT 0dh)
    648 GP_FAULT_SEL        equ $-IDT_BASE
    649         dw 0            ; offset 15:0
    650         dw SYS_CODE_SEL ; selector 15:0
    651         db 0            ; 0 for interrupt gate
    652         db 0eh OR 80h   ; type = 386 interrupt gate, present
    653         dw 0            ; offset 31:16
    654 
    655 ; page fault (INT 0eh)
    656 PAGE_FAULT_SEL      equ $-IDT_BASE
    657         dw 0            ; offset 15:0
    658         dw SYS_CODE_SEL ; selector 15:0
    659         db 0            ; 0 for interrupt gate
    660         db 0eh OR 80h   ; type = 386 interrupt gate, present
    661         dw 0            ; offset 31:16
    662 
    663 ; Intel reserved - do not use (INT 0fh)
    664 RSVD_INTR_SEL2      equ $-IDT_BASE
    665         dw 0            ; offset 15:0
    666         dw SYS_CODE_SEL ; selector 15:0
    667         db 0            ; 0 for interrupt gate
    668         db 0eh OR 80h   ; type = 386 interrupt gate, present
    669         dw 0            ; offset 31:16
    670 
    671 ; floating point error (INT 10h)
    672 FLT_POINT_ERR_SEL   equ $-IDT_BASE
    673         dw 0            ; offset 15:0
    674         dw SYS_CODE_SEL ; selector 15:0
    675         db 0            ; 0 for interrupt gate
    676         db 0eh OR 80h   ; type = 386 interrupt gate, present
    677         dw 0            ; offset 31:16
    678 
    679 ; alignment check (INT 11h)
    680 ALIGNMENT_CHECK_SEL equ $-IDT_BASE
    681         dw 0            ; offset 15:0
    682         dw SYS_CODE_SEL ; selector 15:0
    683         db 0            ; 0 for interrupt gate
    684         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    685         dw 0            ; offset 31:16
    686 
    687 ; machine check (INT 12h)
    688 MACHINE_CHECK_SEL   equ $-IDT_BASE
    689         dw 0            ; offset 15:0
    690         dw SYS_CODE_SEL ; selector 15:0
    691         db 0            ; 0 for interrupt gate
    692         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    693         dw 0            ; offset 31:16
    694 
    695 ; SIMD floating-point exception (INT 13h)
    696 SIMD_EXCEPTION_SEL  equ $-IDT_BASE
    697         dw 0            ; offset 15:0
    698         dw SYS_CODE_SEL ; selector 15:0
    699         db 0            ; 0 for interrupt gate
    700         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    701         dw 0            ; offset 31:16
    702 
    703 ; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
    704         db (85 * 8) dup(0)
    705         
    706 ; IRQ 0 (System timer) - (INT 68h)
    707 IRQ0_SEL            equ $-IDT_BASE
    708         dw 0            ; offset 15:0
    709         dw SYS_CODE_SEL ; selector 15:0
    710         db 0            ; 0 for interrupt gate
    711         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    712         dw 0            ; offset 31:16
    713 
    714 ; IRQ 1 (8042 Keyboard controller) - (INT 69h)
    715 IRQ1_SEL            equ $-IDT_BASE
    716         dw 0            ; offset 15:0
    717         dw SYS_CODE_SEL ; selector 15:0
    718         db 0            ; 0 for interrupt gate
    719         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    720         dw 0            ; offset 31:16
    721 
    722 ; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
    723 IRQ2_SEL            equ $-IDT_BASE
    724         dw 0            ; offset 15:0
    725         dw SYS_CODE_SEL ; selector 15:0
    726         db 0            ; 0 for interrupt gate
    727         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    728         dw 0            ; offset 31:16
    729 
    730 ; IRQ 3 (COM 2) - (INT 6bh)
    731 IRQ3_SEL            equ $-IDT_BASE
    732         dw 0            ; offset 15:0
    733         dw SYS_CODE_SEL ; selector 15:0
    734         db 0            ; 0 for interrupt gate
    735         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    736         dw 0            ; offset 31:16
    737 
    738 ; IRQ 4 (COM 1) - (INT 6ch)
    739 IRQ4_SEL            equ $-IDT_BASE
    740         dw 0            ; offset 15:0
    741         dw SYS_CODE_SEL ; selector 15:0
    742         db 0            ; 0 for interrupt gate
    743         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    744         dw 0            ; offset 31:16
    745 
    746 ; IRQ 5 (LPT 2) - (INT 6dh)
    747 IRQ5_SEL            equ $-IDT_BASE
    748         dw 0            ; offset 15:0
    749         dw SYS_CODE_SEL ; selector 15:0
    750         db 0            ; 0 for interrupt gate
    751         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    752         dw 0            ; offset 31:16
    753 
    754 ; IRQ 6 (Floppy controller) - (INT 6eh)
    755 IRQ6_SEL            equ $-IDT_BASE
    756         dw 0            ; offset 15:0
    757         dw SYS_CODE_SEL ; selector 15:0
    758         db 0            ; 0 for interrupt gate
    759         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    760         dw 0            ; offset 31:16
    761 
    762 ; IRQ 7 (LPT 1) - (INT 6fh)
    763 IRQ7_SEL            equ $-IDT_BASE
    764         dw 0            ; offset 15:0
    765         dw SYS_CODE_SEL ; selector 15:0
    766         db 0            ; 0 for interrupt gate
    767         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    768         dw 0            ; offset 31:16
    769 
    770 ; IRQ 8 (RTC Alarm) - (INT 70h)
    771 IRQ8_SEL            equ $-IDT_BASE
    772         dw 0            ; offset 15:0
    773         dw SYS_CODE_SEL ; selector 15:0
    774         db 0            ; 0 for interrupt gate
    775         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    776         dw 0            ; offset 31:16
    777 
    778 ; IRQ 9 - (INT 71h)
    779 IRQ9_SEL            equ $-IDT_BASE
    780         dw 0            ; offset 15:0
    781         dw SYS_CODE_SEL ; selector 15:0
    782         db 0            ; 0 for interrupt gate
    783         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    784         dw 0            ; offset 31:16
    785 
    786 ; IRQ 10 - (INT 72h)
    787 IRQ10_SEL            equ $-IDT_BASE
    788         dw 0            ; offset 15:0
    789         dw SYS_CODE_SEL ; selector 15:0
    790         db 0            ; 0 for interrupt gate
    791         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    792         dw 0            ; offset 31:16
    793 
    794 ; IRQ 11 - (INT 73h)
    795 IRQ11_SEL            equ $-IDT_BASE
    796         dw 0            ; offset 15:0
    797         dw SYS_CODE_SEL ; selector 15:0
    798         db 0            ; 0 for interrupt gate
    799         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    800         dw 0            ; offset 31:16
    801 
    802 ; IRQ 12 (PS/2 mouse) - (INT 74h)
    803 IRQ12_SEL            equ $-IDT_BASE
    804         dw 0            ; offset 15:0
    805         dw SYS_CODE_SEL ; selector 15:0
    806         db 0            ; 0 for interrupt gate
    807         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    808         dw 0            ; offset 31:16
    809 
    810 ; IRQ 13 (Floating point error) - (INT 75h)
    811 IRQ13_SEL            equ $-IDT_BASE
    812         dw 0            ; offset 15:0
    813         dw SYS_CODE_SEL ; selector 15:0
    814         db 0            ; 0 for interrupt gate
    815         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    816         dw 0            ; offset 31:16
    817 
    818 ; IRQ 14 (Secondary IDE) - (INT 76h)
    819 IRQ14_SEL            equ $-IDT_BASE
    820         dw 0            ; offset 15:0
    821         dw SYS_CODE_SEL ; selector 15:0
    822         db 0            ; 0 for interrupt gate
    823         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    824         dw 0            ; offset 31:16
    825 
    826 ; IRQ 15 (Primary IDE) - (INT 77h)
    827 IRQ15_SEL            equ $-IDT_BASE
    828         dw 0            ; offset 15:0
    829         dw SYS_CODE_SEL ; selector 15:0
    830         db 0            ; 0 for interrupt gate
    831         db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
    832         dw 0            ; offset 31:16
    833 
    834 IDT_END:
    835 
    836         align 02h
    837 
    838 MemoryMapSize   dd  0
    839 MemoryMap   dd  0,0,0,0,0,0,0,0
    840         dd  0,0,0,0,0,0,0,0
    841         dd  0,0,0,0,0,0,0,0
    842         dd  0,0,0,0,0,0,0,0
    843         dd  0,0,0,0,0,0,0,0
    844         dd  0,0,0,0,0,0,0,0
    845         dd  0,0,0,0,0,0,0,0
    846         dd  0,0,0,0,0,0,0,0
    847         dd  0,0,0,0,0,0,0,0
    848         dd  0,0,0,0,0,0,0,0
    849         dd  0,0,0,0,0,0,0,0
    850         dd  0,0,0,0,0,0,0,0
    851         dd  0,0,0,0,0,0,0,0
    852         dd  0,0,0,0,0,0,0,0
    853         dd  0,0,0,0,0,0,0,0
    854         dd  0,0,0,0,0,0,0,0
    855         dd  0,0,0,0,0,0,0,0
    856         dd  0,0,0,0,0,0,0,0
    857         dd  0,0,0,0,0,0,0,0
    858         dd  0,0,0,0,0,0,0,0
    859         dd  0,0,0,0,0,0,0,0
    860         dd  0,0,0,0,0,0,0,0
    861         dd  0,0,0,0,0,0,0,0
    862         dd  0,0,0,0,0,0,0,0
    863         dd  0,0,0,0,0,0,0,0
    864         dd  0,0,0,0,0,0,0,0
    865         dd  0,0,0,0,0,0,0,0
    866         dd  0,0,0,0,0,0,0,0
    867         dd  0,0,0,0,0,0,0,0
    868         dd  0,0,0,0,0,0,0,0
    869 
    870         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
    871         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
    872 
    873         org 0fe0h
    874 MyStack:    
    875         ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
    876         ;    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a
    877         ;    known low address (20f00) so it can be set up by PlMapIrqToVect in
    878         ;    8259.c
    879                 
    880         int 8
    881         iret
    882         
    883         int 9
    884         iret
    885         
    886         int 10
    887         iret
    888         
    889         int 11
    890         iret
    891         
    892         int 12
    893         iret
    894         
    895         int 13
    896         iret
    897         
    898         int 14
    899         iret
    900         
    901         int 15
    902         iret
    903         
    904         
    905         org 0ffeh
    906 BlockSignature:
    907         dw  0aa55h
    908 
    909         end 
    910