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