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;*    start32.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
35SectorSize          dw  0             ; Sector Size                     - 2 bytes
36SectorsPerCluster   db  0             ; Sector Per Cluster              - 1 byte
37ReservedSectors     dw  0             ; Reserved Sectors                - 2 bytes
38NoFats              db  0             ; Number of FATs                  - 1 byte
39RootEntries         dw  0             ; Root Entries                    - 2 bytes
40Sectors             dw  0             ; Number of Sectors               - 2 bytes
41Media               db  0             ; Media                           - 1 byte
42SectorsPerFat16     dw  0             ; Sectors Per FAT for FAT12/FAT16 - 2 byte
43SectorsPerTrack     dw  0             ; Sectors Per Track               - 2 bytes
44Heads               dw  0             ; Heads                           - 2 bytes
45HiddenSectors       dd  0             ; Hidden Sectors                  - 4 bytes
46LargeSectors        dd  0             ; Large Sectors                   - 4 bytes
47
48;******************************************************************************
49;
50;The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
51;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
52;
53;******************************************************************************
54
55SectorsPerFat32     dd  0             ; Sectors Per FAT for FAT32       - 4 bytes
56ExtFlags            dw  0             ; Mirror Flag                     - 2 bytes
57FSVersion           dw  0             ; File System Version             - 2 bytes
58RootCluster         dd  0             ; 1st Cluster Number of Root Dir  - 4 bytes
59FSInfo              dw  0             ; Sector Number of FSINFO         - 2 bytes
60BkBootSector        dw  0             ; Sector Number of Bk BootSector  - 2 bytes
61Reserved            db  12 dup(0)     ; Reserved Field                  - 12 bytes
62PhysicalDrive       db  0             ; Physical Drive Number           - 1 byte
63Reserved1           db  0             ; Reserved Field                  - 1 byte
64Signature           db  0             ; Extended Boot Signature         - 1 byte
65VolId               db  "    "        ; Volume Serial Number            - 4 bytes
66FatLabel            db  "           " ; Volume Label                    - 11 bytes
67FileSystemType      db  "FAT32   "    ; File System Type                - 8 bytes
68
69BootSectorEntryPoint:
70        ASSUME  ds:@code
71        ASSUME  ss:@code
72      ; ds = 1000, es = 2000 + x (size of first cluster >> 4)
73      ; cx = Start Cluster of EfiLdr
74      ; dx = Start Cluster of Efivar.bin
75
76; Re use the BPB data stored in Boot Sector
77        mov     bp,07c00h
78
79
80        push    cx
81; Read Efivar.bin
82;       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already
83        mov     ax,01900h
84        mov     es,ax
85        test    dx,dx
86        jnz     CheckVarStoreSize
87
88        mov     al,1
89NoVarStore:
90        push    es
91; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
92        mov     byte ptr es:[4],al
93        jmp     SaveVolumeId
94
95CheckVarStoreSize:
96        mov     di,dx
97        cmp     dword ptr ds:[di+2], 04000h
98        mov     al,2
99        jne     NoVarStore
100
101LoadVarStore:
102        mov     al,0
103        mov     byte ptr es:[4],al
104        mov     cx,word ptr[di]
105;       ES:DI = 1500:0
106        xor     di,di
107        push    es
108        mov     ax,01500h
109        mov     es,ax
110        call    ReadFile
111SaveVolumeId:
112        pop     es
113        mov     ax,word ptr [bp+VolId]
114        mov     word ptr es:[0],ax                  ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
115        mov     ax,word ptr [bp+VolId+2]
116        mov     word ptr es:[2],ax
117
118; Read Efildr
119        pop     cx
120;       cx    = Start Cluster of Efildr -> BS.com has filled already
121;       ES:DI = 2000:0, first cluster will be read again
122        xor     di,di                               ; di = 0
123        mov     ax,02000h
124        mov     es,ax
125        call    ReadFile
126        mov     ax,cs
127        mov     word ptr cs:[JumpSegment],ax
128JumpFarInstruction:
129        db      0eah
130JumpOffset:
131        dw      0200h
132JumpSegment:
133        dw      2000h
134
135
136
137
138; ****************************************************************************
139; ReadFile
140;
141; Arguments:
142;   CX    = Start Cluster of File
143;   ES:DI = Buffer to store file content read from disk
144;
145; Return:
146;   (ES << 4 + DI) = end of file content Buffer
147;
148; ****************************************************************************
149ReadFile:
150; si      = NumberOfClusters
151; cx      = ClusterNumber
152; dx      = CachedFatSectorNumber
153; ds:0000 = CacheFatSectorBuffer
154; es:di   = Buffer to load file
155; bx      = NextClusterNumber
156        pusha
157        mov     si,1                                ; NumberOfClusters = 1
158        push    cx                                  ; Push Start Cluster onto stack
159        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff
160FatChainLoop:
161        mov     ax,cx                               ; ax = ClusterNumber
162        and     ax,0fff8h                           ; ax = ax & 0xfff8
163        cmp     ax,0fff8h                           ; See if this is the last cluster
164        je      FoundLastCluster                    ; Jump if last cluster found
165        mov     ax,cx                               ; ax = ClusterNumber
166        shl     ax,2                                ; FatOffset = ClusterNumber * 4
167        push    si                                  ; Save si
168        mov     si,ax                               ; si = FatOffset
169        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT
170        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
171        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK
172        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber
173        je      SkipFatRead
174        mov     bx,2
175        push    es
176        push    ds
177        pop     es
178        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI
179        pop     es
180        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber
181SkipFatRead:
182        mov     bx,word ptr [si]                    ; bx = NextClusterNumber
183        mov     ax,cx                               ; ax = ClusterNumber
184        pop     si                                  ; Restore si
185        dec     bx                                  ; bx = NextClusterNumber - 1
186        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber
187        jne     ReadClusters
188        inc     bx                                  ; bx = NextClusterNumber
189        inc     si                                  ; NumberOfClusters++
190        mov     cx,bx                               ; ClusterNumber = NextClusterNumber
191        jmp     FatChainLoop
192ReadClusters:
193        inc     bx
194        pop     ax                                  ; ax = StartCluster
195        push    bx                                  ; StartCluster = NextClusterNumber
196        mov     cx,bx                               ; ClusterNumber = NextClusterNumber
197        sub     ax,2                                ; ax = StartCluster - 2
198        xor     bh,bh
199        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster
200        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster
201        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
202        push    ax                                  ; save start sector
203        mov     ax,si                               ; ax = NumberOfClusters
204        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster
205        mov     bx,ax                               ; bx = Number of Sectors
206        pop     ax                                  ; ax = Start Sector
207        call    ReadBlocks
208        mov     si,1                                ; NumberOfClusters = 1
209        jmp     FatChainLoop
210FoundLastCluster:
211        pop     cx
212        popa
213        ret
214
215
216; ****************************************************************************
217; ReadBlocks - Reads a set of blocks from a block device
218;
219; AX    = Start LBA
220; BX    = Number of Blocks to Read
221; ES:DI = Buffer to store sectors read from disk
222; ****************************************************************************
223
224; cx = Blocks
225; bx = NumberOfBlocks
226; si = StartLBA
227
228ReadBlocks:
229        pusha
230        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA
231        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA
232        mov     esi,eax                             ; esi = Start LBA
233        mov     cx,bx                               ; cx = Number of blocks to read
234ReadCylinderLoop:
235        mov     bp,07bfch                           ; bp = 0x7bfc
236        mov     eax,esi                             ; eax = Start LBA
237        xor     edx,edx                             ; edx = 0
238        movzx   ebx,word ptr [bp]                   ; bx = MaxSector
239        div     ebx                                 ; ax = StartLBA / MaxSector
240        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1
241
242        mov     bx,word ptr [bp]                    ; bx = MaxSector
243        sub     bx,dx                               ; bx = MaxSector - Sector
244        inc     bx                                  ; bx = MaxSector - Sector + 1
245        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)
246        jg      LimitTransfer
247        mov     bx,cx                               ; bx = Blocks
248LimitTransfer:
249        push    ax                                  ; save ax
250        mov     ax,es                               ; ax = es
251        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system
252        and     ax,07fh                             ; ax = Number of blocks into current seg
253        add     ax,bx                               ; ax = End Block number of transfer
254        cmp     ax,080h                             ; See if it crosses a 64K boundry
255        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry
256        sub     ax,080h                             ; ax = Number of blocks past 64K boundry
257        sub     bx,ax                               ; Decrease transfer size by block overage
258NotCrossing64KBoundry:
259        pop     ax                                  ; restore ax
260
261        push    cx
262        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector
263        xor     dx,dx                               ; dx = 0
264        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder
265                                                    ; dx = ax % (MaxHead + 1) = Head
266
267        push    bx                                  ; Save number of blocks to transfer
268        mov     dh,dl                               ; dh = Head
269        mov     bp,07c00h                           ; bp = 0x7c00
270        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number
271        mov     ch,al                               ; ch = Cylinder
272        mov     al,bl                               ; al = Blocks
273        mov     ah,2                                ; ah = Function 2
274        mov     bx,di                               ; es:bx = Buffer address
275        int     013h
276        jc      DiskError
277        pop     bx
278        pop     cx
279        movzx   ebx,bx
280        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks
281        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks
282        mov     ax,es
283        shl     bx,(BLOCK_SHIFT-4)
284        add     ax,bx
285        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
286        cmp     cx,0
287        jne     ReadCylinderLoop
288        popa
289        ret
290
291DiskError:
292        push cs
293        pop  ds
294        lea  si, [ErrorString]
295        mov  cx, 7
296        jmp  PrintStringAndHalt
297
298PrintStringAndHalt:
299        mov  ax,0b800h
300        mov  es,ax
301        mov  di,160
302        rep  movsw
303Halt:
304        jmp   Halt
305
306ErrorString:
307        db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch
308
309        org     01fah
310LBAOffsetForBootSector:
311        dd      0h
312
313        org     01feh
314        dw      0aa55h
315
316;******************************************************************************
317;******************************************************************************
318;******************************************************************************
319
320DELAY_PORT           equ     0edh    ; Port to use for 1uS delay
321KBD_CONTROL_PORT     equ     060h    ; 8042 control port
322KBD_STATUS_PORT      equ     064h    ; 8042 status port
323WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port
324ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20
325
326        org     200h
327        jmp start
328Em64String:
329        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
330
331start:
332        mov ax,cs
333        mov ds,ax
334        mov es,ax
335        mov ss,ax
336        mov sp,MyStack
337
338;        mov ax,0b800h
339;        mov es,ax
340;        mov byte ptr es:[160],'a'
341;        mov ax,cs
342;        mov es,ax
343
344        mov ebx,0
345        lea edi,MemoryMap
346MemMapLoop:
347        mov eax,0e820h
348        mov ecx,20
349        mov edx,'SMAP'
350        int 15h
351        jc  MemMapDone
352        add edi,20
353        cmp ebx,0
354        je  MemMapDone
355        jmp MemMapLoop
356MemMapDone:
357        lea eax,MemoryMap
358        sub edi,eax                         ; Get the address of the memory map
359        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map
360
361        xor     ebx,ebx
362        mov     bx,cs                       ; BX=segment
363        shl     ebx,4                       ; BX="linear" address of segment base
364        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt
365        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr
366        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt
367        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr
368        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map
369
370        add ebx,01000h                      ; Source of EFI32
371        mov dword ptr [JUMP+2],ebx
372        add ebx,01000h
373        mov esi,ebx                         ; Source of EFILDR32
374
375;        mov ax,0b800h
376;        mov es,ax
377;        mov byte ptr es:[162],'b'
378;        mov ax,cs
379;        mov es,ax
380
381;
382; Enable A20 Gate
383;
384
385        mov ax,2401h                        ; Enable A20 Gate
386        int 15h
387        jnc A20GateEnabled                  ; Jump if it suceeded
388
389;
390; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
391;
392
393        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
394        jnz     Timeout8042                 ; Jump if the 8042 timed out
395        out     DELAY_PORT,ax               ; Delay 1 uS
396        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port
397        out     KBD_STATUS_PORT,al          ; Send command to the 8042
398        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
399        jnz     Timeout8042                 ; Jump if the 8042 timed out
400        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on
401        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042
402        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller
403        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042
404Delay25uS:
405        out     DELAY_PORT,ax               ; Delay 1 uS
406        loop    Delay25uS
407Timeout8042:
408
409
410A20GateEnabled:
411        mov     bx,0008h                    ; Flat data descriptor
412;
413; DISABLE INTERRUPTS - Entering Protected Mode
414;
415
416        cli
417
418;        mov ax,0b800h
419;        mov es,ax
420;        mov byte ptr es:[164],'c'
421;        mov ax,cs
422;        mov es,ax
423
424        db      66h
425        lgdt    fword ptr [gdtr]
426        db      66h
427        lidt    fword ptr [idtr]
428
429        mov     eax,cr0
430        or      al,1
431        mov     cr0,eax
432JUMP:
433; jmp far 0010:00020000
434        db  066h
435        db  0eah
436        dd  000020000h
437        dw  00010h
438
439Empty8042InputBuffer:
440        mov cx,0
441Empty8042Loop:
442        out     DELAY_PORT,ax               ; Delay 1us
443        in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port
444        and     al,02h                      ; Check the Input Buffer Full Flag
445        loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS
446        ret
447
448;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
449; data
450;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
451
452        align 02h
453
454gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit
455        dd 0                        ; (GDT base gets set above)
456;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
457;   global descriptor table (GDT)
458;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
459
460        align 02h
461
462public GDT_BASE
463GDT_BASE:
464; null descriptor
465NULL_SEL            equ $-GDT_BASE
466        dw 0            ; limit 15:0
467        dw 0            ; base 15:0
468        db 0            ; base 23:16
469        db 0            ; type
470        db 0            ; limit 19:16, flags
471        db 0            ; base 31:24
472
473; linear data segment descriptor
474LINEAR_SEL      equ $-GDT_BASE
475        dw 0FFFFh       ; limit 0xFFFFF
476        dw 0            ; base 0
477        db 0
478        db 092h         ; present, ring 0, data, expand-up, writable
479        db 0CFh                 ; page-granular, 32-bit
480        db 0
481
482; linear code segment descriptor
483LINEAR_CODE_SEL equ $-GDT_BASE
484        dw 0FFFFh       ; limit 0xFFFFF
485        dw 0            ; base 0
486        db 0
487        db 09Ah         ; present, ring 0, data, expand-up, writable
488        db 0CFh                 ; page-granular, 32-bit
489        db 0
490
491; system data segment descriptor
492SYS_DATA_SEL    equ $-GDT_BASE
493        dw 0FFFFh       ; limit 0xFFFFF
494        dw 0            ; base 0
495        db 0
496        db 092h         ; present, ring 0, data, expand-up, writable
497        db 0CFh                 ; page-granular, 32-bit
498        db 0
499
500; system code segment descriptor
501SYS_CODE_SEL    equ $-GDT_BASE
502        dw 0FFFFh       ; limit 0xFFFFF
503        dw 0            ; base 0
504        db 0
505        db 09Ah         ; present, ring 0, data, expand-up, writable
506        db 0CFh                 ; page-granular, 32-bit
507        db 0
508
509; spare segment descriptor
510SPARE3_SEL  equ $-GDT_BASE
511        dw 0            ; limit 0xFFFFF
512        dw 0            ; base 0
513        db 0
514        db 0            ; present, ring 0, data, expand-up, writable
515        db 0            ; page-granular, 32-bit
516        db 0
517
518; spare segment descriptor
519SPARE4_SEL  equ $-GDT_BASE
520        dw 0            ; limit 0xFFFFF
521        dw 0            ; base 0
522        db 0
523        db 0            ; present, ring 0, data, expand-up, writable
524        db 0            ; page-granular, 32-bit
525        db 0
526
527; spare segment descriptor
528SPARE5_SEL  equ $-GDT_BASE
529        dw 0            ; limit 0xFFFFF
530        dw 0            ; base 0
531        db 0
532        db 0            ; present, ring 0, data, expand-up, writable
533        db 0            ; page-granular, 32-bit
534        db 0
535
536GDT_END:
537
538        align 02h
539
540
541
542idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit
543        dd 0                        ; (IDT base gets set above)
544;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
545;   interrupt descriptor table (IDT)
546;
547;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
548;       mappings.  This implementation only uses the system timer and all other
549;       IRQs will remain masked.  The descriptors for vectors 33+ are provided
550;       for convenience.
551;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
552
553;idt_tag db "IDT",0
554        align 02h
555
556public IDT_BASE
557IDT_BASE:
558; divide by zero (INT 0)
559DIV_ZERO_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; debug exception (INT 1)
567DEBUG_EXCEPT_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; NMI (INT 2)
575NMI_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; soft breakpoint (INT 3)
583BREAKPOINT_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; overflow (INT 4)
591OVERFLOW_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; bounds check (INT 5)
599BOUNDS_CHECK_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; invalid opcode (INT 6)
607INVALID_OPCODE_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; device not available (INT 7)
615DEV_NOT_AVAIL_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; double fault (INT 8)
623DOUBLE_FAULT_SEL    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; Coprocessor segment overrun - reserved (INT 9)
631RSVD_INTR_SEL1      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; invalid TSS (INT 0ah)
639INVALID_TSS_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; segment not present (INT 0bh)
647SEG_NOT_PRESENT_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; stack fault (INT 0ch)
655STACK_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; general protection (INT 0dh)
663GP_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; page fault (INT 0eh)
671PAGE_FAULT_SEL      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; Intel reserved - do not use (INT 0fh)
679RSVD_INTR_SEL2      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; floating point error (INT 10h)
687FLT_POINT_ERR_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   ; type = 386 interrupt gate, present
692        dw 0            ; offset 31:16
693
694; alignment check (INT 11h)
695ALIGNMENT_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; machine check (INT 12h)
703MACHINE_CHECK_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; SIMD floating-point exception (INT 13h)
711SIMD_EXCEPTION_SEL  equ $-IDT_BASE
712        dw 0            ; offset 15:0
713        dw SYS_CODE_SEL ; selector 15:0
714        db 0            ; 0 for interrupt gate
715        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
716        dw 0            ; offset 31:16
717
718; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
719        db (85 * 8) dup(0)
720
721; IRQ 0 (System timer) - (INT 68h)
722IRQ0_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; IRQ 1 (8042 Keyboard controller) - (INT 69h)
730IRQ1_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; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
738IRQ2_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 3 (COM 2) - (INT 6bh)
746IRQ3_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 4 (COM 1) - (INT 6ch)
754IRQ4_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 5 (LPT 2) - (INT 6dh)
762IRQ5_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 6 (Floppy controller) - (INT 6eh)
770IRQ6_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 7 (LPT 1) - (INT 6fh)
778IRQ7_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 8 (RTC Alarm) - (INT 70h)
786IRQ8_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 9 - (INT 71h)
794IRQ9_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 10 - (INT 72h)
802IRQ10_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 11 - (INT 73h)
810IRQ11_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 12 (PS/2 mouse) - (INT 74h)
818IRQ12_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 13 (Floating point error) - (INT 75h)
826IRQ13_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 14 (Secondary IDE) - (INT 76h)
834IRQ14_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; IRQ 15 (Primary IDE) - (INT 77h)
842IRQ15_SEL            equ $-IDT_BASE
843        dw 0            ; offset 15:0
844        dw SYS_CODE_SEL ; selector 15:0
845        db 0            ; 0 for interrupt gate
846        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present
847        dw 0            ; offset 31:16
848
849IDT_END:
850
851        align 02h
852
853MemoryMapSize   dd  0
854MemoryMap   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        dd  0,0,0,0,0,0,0,0
877        dd  0,0,0,0,0,0,0,0
878        dd  0,0,0,0,0,0,0,0
879        dd  0,0,0,0,0,0,0,0
880        dd  0,0,0,0,0,0,0,0
881        dd  0,0,0,0,0,0,0,0
882        dd  0,0,0,0,0,0,0,0
883        dd  0,0,0,0,0,0,0,0
884
885        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
886        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
887
888        org 0fe0h
889MyStack:
890        ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh
891        ;    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a
892        ;    known low address (20f00) so it can be set up by PlMapIrqToVect in
893        ;    8259.c
894
895        int 8
896        iret
897
898        int 9
899        iret
900
901        int 10
902        iret
903
904        int 11
905        iret
906
907        int 12
908        iret
909
910        int 13
911        iret
912
913        int 14
914        iret
915
916        int 15
917        iret
918
919
920        org 0ffeh
921BlockSignature:
922        dw  0aa55h
923
924        end
925