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