• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
23FAT_DIRECTORY_ENTRY_SIZE    EQU     020h
24FAT_DIRECTORY_ENTRY_SHIFT   EQU     5
25BLOCK_SIZE                  EQU     0200h
26BLOCK_MASK                  EQU     01ffh
27BLOCK_SHIFT                 EQU     9
28
29        org 0h
30Ia32Jump:
31  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes
32  nop
33
34OemId             db  "INTEL   "    ; OemId               - 8 bytes
35
36SectorSize        dw  0             ; Sector Size         - 16 bits
37SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits
38ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits
39NoFats            db  0             ; Number of FATs      - 8 bits
40RootEntries       dw  0             ; Root Entries        - 16 bits
41Sectors           dw  0             ; Number of Sectors   - 16 bits
42Media             db  0             ; Media               - 8 bits  - ignored
43SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits
44SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored
45Heads             dw  0             ; Heads               - 16 bits - ignored
46HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored
47LargeSectors      dd  0             ; Large Sectors       - 32 bits
48PhysicalDrive     db  0             ; PhysicalDriveNumber - 8 bits  - ignored
49CurrentHead       db  0             ; Current Head        - 8 bits
50Signature         db  0             ; Signature           - 8 bits  - ignored
51VolId             db  "    "        ; Volume Serial Number- 4 bytes
52FatLabel          db  "           " ; Label               - 11 bytes
53SystemId          db  "FAT16   "    ; SystemId            - 8 bytes
54
55BootSectorEntryPoint:
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
74NoVarStore:
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
80CheckVarStoreSize:
81        mov     di,dx
82        cmp     dword ptr ds:[di+2], 04000h
83        mov     al,2
84        jne     NoVarStore
85
86LoadVarStore:
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
96SaveVolumeId:
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
114JumpFarInstruction:
115        db      0eah
116JumpOffset:
117        dw      0200h
118JumpSegment:
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; ****************************************************************************
134ReadFile:
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
145FatChainLoop:
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
166SkipFatRead:
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
177ReadClusters:
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
195FoundLastCluster:
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
213ReadBlocks:
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
219ReadCylinderLoop:
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
233LimitTransfer:
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
243NotCrossing64KBoundry:
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
276DiskError:
277        push cs
278        pop  ds
279        lea  si, [ErrorString]
280        mov  cx, 7
281        jmp  PrintStringAndHalt
282
283PrintStringAndHalt:
284        mov  ax,0b800h
285        mov  es,ax
286        mov  di,160
287        rep  movsw
288Halt:
289        jmp   Halt
290
291ErrorString:
292        db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
293
294        org     01fah
295LBAOffsetForBootSector:
296        dd      0h
297
298        org     01feh
299        dw      0aa55h
300
301;******************************************************************************
302;******************************************************************************
303;******************************************************************************
304
305DELAY_PORT           equ     0edh    ; Port to use for 1uS delay
306KBD_CONTROL_PORT     equ     060h    ; 8042 control port
307KBD_STATUS_PORT      equ     064h    ; 8042 status port
308WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port
309ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20
310
311        org     200h
312        jmp start
313Em64String:
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
316start:
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
331MemMapLoop:
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
341MemMapDone:
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
389Delay25uS:
390        out     DELAY_PORT,ax               ; Delay 1 uS
391        loop    Delay25uS
392Timeout8042:
393
394
395A20GateEnabled:
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
417JUMP:
418; jmp far 0010:00020000
419        db  066h
420        db  0eah
421        dd  000020000h
422        dw  00010h
423
424Empty8042InputBuffer:
425        mov cx,0
426Empty8042Loop:
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
439gdtr    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
447public GDT_BASE
448GDT_BASE:
449; null descriptor
450NULL_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
459LINEAR_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
468LINEAR_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
477SYS_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
486SYS_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
495SPARE3_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
504SPARE4_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
513SPARE5_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
521GDT_END:
522
523        align 02h
524
525
526
527idtr            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
541public IDT_BASE
542IDT_BASE:
543; divide by zero (INT 0)
544DIV_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)
552DEBUG_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)
560NMI_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)
568BREAKPOINT_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)
576OVERFLOW_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)
584BOUNDS_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)
592INVALID_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)
600DEV_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)
608DOUBLE_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)
616RSVD_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)
624INVALID_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)
632SEG_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)
640STACK_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)
648GP_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)
656PAGE_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)
664RSVD_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)
672FLT_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)
680ALIGNMENT_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)
688MACHINE_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)
696SIMD_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)
707IRQ0_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)
715IRQ1_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)
723IRQ2_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)
731IRQ3_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)
739IRQ4_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)
747IRQ5_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)
755IRQ6_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)
763IRQ7_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)
771IRQ8_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)
779IRQ9_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)
787IRQ10_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)
795IRQ11_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)
803IRQ12_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)
811IRQ13_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)
819IRQ14_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)
827IRQ15_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
834IDT_END:
835
836        align 02h
837
838MemoryMapSize   dd  0
839MemoryMap   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
874MyStack:
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
906BlockSignature:
907        dw  0aa55h
908
909        end
910