~ubuntu-branches/ubuntu/wily/edk2/wily

« back to all changes in this revision

Viewing changes to DuetPkg/BootSector/start16.asm

  • Committer: Package Import Robot
  • Author(s): Steve Langasek
  • Date: 2013-02-10 13:11:25 UTC
  • Revision ID: package-import@ubuntu.com-20130210131125-0zwkb8f8m4ecia4m
Tags: upstream-0~20121205.edae8d2d
ImportĀ upstreamĀ versionĀ 0~20121205.edae8d2d

Show diffs side-by-side

added added

removed removed

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