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