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