]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/BootSector/st32_64.S
Use .p2align directive instead of ambiguous .align directive.
[mirror_edk2.git] / DuetPkg / BootSector / st32_64.S
1 #------------------------------------------------------------------------------
2 #*
3 #* Copyright 2006 - 2007, Intel Corporation
4 #* All rights reserved. This program and the accompanying materials
5 #* are licensed and made available under the terms and conditions of the BSD License
6 #* which accompanies this distribution. The full text of the license may be found at
7 #* http://opensource.org/licenses/bsd-license.php
8 #*
9 #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #*
12 #* st32_64.asm
13 #*
14 #* Abstract:
15 #*
16 #------------------------------------------------------------------------------
17
18
19 .stack:
20 .486p:
21 .code16
22
23 .equ FAT_DIRECTORY_ENTRY_SIZE, 0x020
24 .equ FAT_DIRECTORY_ENTRY_SHIFT, 5
25 .equ BLOCK_SIZE, 0x0200
26 .equ BLOCK_MASK, 0x01ff
27 .equ BLOCK_SHIFT, 9
28
29 .org 0x0
30 Ia32Jump:
31 jmp BootSectorEntryPoint # JMP inst - 3 bytes
32 nop
33
34 OemId: .ascii "INTEL " # OemId - 8 bytes
35 SectorSize: .word 0 # Sector Size - 2 bytes
36 SectorsPerCluster: .byte 0 # Sector Per Cluster - 1 byte
37 ReservedSectors: .word 0 # Reserved Sectors - 2 bytes
38 NoFats: .byte 0 # Number of FATs - 1 byte
39 RootEntries: .word 0 # Root Entries - 2 bytes
40 Sectors: .word 0 # Number of Sectors - 2 bytes
41 Media: .byte 0 # Media - 1 byte
42 SectorsPerFat16: .word 0 # Sectors Per FAT for FAT12/FAT16 - 2 byte
43 SectorsPerTrack: .word 0 # Sectors Per Track - 2 bytes
44 Heads: .word 0 # Heads - 2 bytes
45 HiddenSectors: .long 0 # Hidden Sectors - 4 bytes
46 LargeSectors: .long 0 # Large Sectors - 4 bytes
47
48 #******************************************************************************
49 #
50 #The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
51 #the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
52 #
53 #******************************************************************************
54
55 SectorsPerFat32: .long 0 # Sectors Per FAT for FAT32 - 4 bytes
56 ExtFlags: .word 0 # Mirror Flag - 2 bytes
57 FSVersion: .word 0 # File System Version - 2 bytes
58 RootCluster: .long 0 # 1st Cluster Number of Root Dir - 4 bytes
59 FSInfo: .word 0 # Sector Number of FSINFO - 2 bytes
60 BkBootSector: .word 0 # Sector Number of Bk BootSector - 2 bytes
61 Reserved: .fill 12,1,0 # Reserved Field - 12 bytes
62 PhysicalDrive: .byte 0 # Physical Drive Number - 1 byte
63 Reserved1: .byte 0 # Reserved Field - 1 byte
64 Signature: .byte 0 # Extended Boot Signature - 1 byte
65 VolId: .ascii " " # Volume Serial Number - 4 bytes
66 FatLabel: .ascii " " # Volume Label - 11 bytes
67 FileSystemType: .ascii "FAT32 " # File System Type - 8 bytes
68
69
70 BootSectorEntryPoint:
71 # ASSUME ds:@code
72 # ASSUME ss:@code
73 # ds = 1000, es = 2000 + x (size of first cluster >> 4)
74 # cx = Start Cluster of EfiLdr
75 # dx = Start Cluster of Efivar.bin
76
77 # Re use the BPB data stored in Boot Sector
78 movw $0x7c00,%bp
79
80 pushw %cx
81 # Read Efivar.bin
82 # 1000:dx = DirectoryEntry of Efivar.bin -> BS.com has filled already
83 movw $0x1900,%ax
84 movw %ax,%es
85 testw %dx,%dx
86 jnz CheckVarStoreSize
87
88 movb $1,%al
89 NoVarStore:
90 pushw %es
91 # Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl
92 movb %al, %es:(4)
93 jmp SaveVolumeId
94
95 CheckVarStoreSize:
96 movw %dx,%di
97 cmpl $0x4000, %ds:2(%di)
98 movb $2,%al
99 jne NoVarStore
100
101 LoadVarStore:
102 movb $0,%al
103 movb %al, %es:(4)
104 movw (%di), %cx
105 # ES:DI = 1500:0
106 xorw %di,%di
107 pushw %es
108 movw $0x1500,%ax
109 movw %ax,%es
110 call ReadFile
111 SaveVolumeId:
112 popw %es
113 movw VolId(%bp), %ax
114 movw %ax, %es:(0) # Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId
115 movw VolId+2(%bp), %ax
116 movw %ax, %es:(2)
117
118 # Read Efildr
119 popw %cx
120 # cx = Start Cluster of Efildr -> BS.com has filled already
121 # ES:DI = 2000:0, first cluster will be read again
122 xorw %di,%di # di = 0
123 movw $0x2000,%ax
124 movw %ax,%es
125 call ReadFile
126 movw %cs,%ax
127 movw %ax, %cs:JumpSegment
128
129 CheckEm64T:
130 movl $0x80000001,%eax
131 # cpuid
132 .word 0xA20F
133 btl $29,%edx
134 jc CheckEm64TPass
135 pushw %cs
136 popw %ds
137 leaw Em64String,%si
138 movw $18,%cx
139 jmp PrintStringAndHalt
140 CheckEm64TPass:
141 jumpFarInstruction:
142 .byte 0xea
143 jumpOffset:
144 .word 0x200
145 jumpSegment:
146 .word 0x2000
147
148
149
150 # ****************************************************************************
151 # ReadFile
152 #
153 # Arguments:
154 # CX = Start Cluster of File
155 # ES:DI = Buffer to store file content read from disk
156 #
157 # Return:
158 # (ES << 4 + DI) = end of file content Buffer
159 #
160 # ****************************************************************************
161 ReadFile:
162 # si = NumberOfClusters
163 # cx = ClusterNumber
164 # dx = CachedFatSectorNumber
165 # ds:0000 = CacheFatSectorBuffer
166 # es:di = Buffer to load file
167 # bx = NextClusterNumber
168 pusha
169 movw $1,%si # NumberOfClusters = 1
170 pushw %cx # Push Start Cluster onto stack
171 movw $0xfff,%dx # CachedFatSectorNumber = 0xfff
172 FatChainLoop:
173 movw %cx,%ax # ax = ClusterNumber
174 andw $0xfff8,%ax # ax = ax & 0xfff8
175 cmpw $0xfff8,%ax # See if this is the last cluster
176 je FoundLastCluster # Jump if last cluster found
177 movw %cx,%ax # ax = ClusterNumber
178 shlw $2, %ax # FatOffset = ClusterNumber * 2
179 pushw %si # Save si
180 movw %ax,%si # si = FatOffset
181 shrw $BLOCK_SHIFT, %ax # ax = FatOffset >> BLOCK_SHIFT
182 addw ReservedSectors(%bp), %ax # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
183 andw $BLOCK_MASK, %si # si = FatOffset & BLOCK_MASK
184 cmpw %dx,%ax # Compare FatSectorNumber to CachedFatSectorNumber
185 je SkipFatRead
186 movw $2,%bx
187 pushw %es
188 pushw %ds
189 popw %es
190 call ReadBlocks # Read 2 blocks starting at AX storing at ES:DI
191 popw %es
192 movw %ax,%dx # CachedFatSectorNumber = FatSectorNumber
193 SkipFatRead:
194 movw (%si), %bx # bx = NextClusterNumber
195 movw %cx,%ax # ax = ClusterNumber
196 popw %si # Restore si
197 decw %bx # bx = NextClusterNumber - 1
198 cmpw %cx,%bx # See if (NextClusterNumber-1)==ClusterNumber
199 jne ReadClusters
200 incw %bx # bx = NextClusterNumber
201 incw %si # NumberOfClusters++
202 movw %bx,%cx # ClusterNumber = NextClusterNumber
203 jmp FatChainLoop
204 ReadClusters:
205 incw %bx
206 popw %ax # ax = StartCluster
207 pushw %bx # StartCluster = NextClusterNumber
208 movw %bx,%cx # ClusterNumber = NextClusterNumber
209 subw $2,%ax # ax = StartCluster - 2
210 xorb %bh,%bh
211 movb SectorsPerCluster(%bp), %bl # bx = SectorsPerCluster
212 mulw %bx # ax = (StartCluster - 2) * SectorsPerCluster
213 addw (%bp), %ax # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
214 pushw %ax # save start sector
215 movw %si,%ax # ax = NumberOfClusters
216 mulw %bx # ax = NumberOfClusters * SectorsPerCluster
217 movw %ax,%bx # bx = Number of Sectors
218 popw %ax # ax = Start Sector
219 call ReadBlocks
220 movw $1,%si # NumberOfClusters = 1
221 jmp FatChainLoop
222 FoundLastCluster:
223 popw %cx
224 popa
225 ret
226
227
228 # ****************************************************************************
229 # ReadBlocks - Reads a set of blocks from a block device
230 #
231 # AX = Start LBA
232 # BX = Number of Blocks to Read
233 # ES:DI = Buffer to store sectors read from disk
234 # ****************************************************************************
235
236 # cx = Blocks
237 # bx = NumberOfBlocks
238 # si = StartLBA
239
240 ReadBlocks:
241 pusha
242 addl LBAOffsetForBootSector(%bp), %eax # Add LBAOffsetForBootSector to Start LBA
243 addl HiddenSectors(%bp), %eax # Add HiddenSectors to Start LBA
244 movl %eax,%esi # esi = Start LBA
245 movw %bx,%cx # cx = Number of blocks to read
246 ReadCylinderLoop:
247 movw $0x7bfc,%bp # bp = 0x7bfc
248 movl %esi,%eax # eax = Start LBA
249 xorl %edx,%edx # edx = 0
250 movzwl (%bp), %ebx # bx = MaxSector
251 divl %ebx # ax = StartLBA / MaxSector
252 incw %dx # dx = (StartLBA % MaxSector) + 1
253
254 movw (%bp), %bx # bx = MaxSector
255 subw %dx,%bx # bx = MaxSector - Sector
256 incw %bx # bx = MaxSector - Sector + 1
257 cmpw %bx,%cx # Compare (Blocks) to (MaxSector - Sector + 1)
258 jg LimitTransfer
259 movw %cx,%bx # bx = Blocks
260 LimitTransfer:
261 pushw %ax # save ax
262 movw %es,%ax # ax = es
263 shrw $(BLOCK_SHIFT-4), %ax # ax = Number of blocks into mem system
264 andw $0x7f,%ax # ax = Number of blocks into current seg
265 addw %bx,%ax # ax = End Block number of transfer
266 cmpw $0x80,%ax # See if it crosses a 64K boundry
267 jle NotCrossing64KBoundry # Branch if not crossing 64K boundry
268 subw $0x80,%ax # ax = Number of blocks past 64K boundry
269 subw %ax,%bx # Decrease transfer size by block overage
270 NotCrossing64KBoundry:
271 popw %ax # restore ax
272
273 pushw %cx
274 movb %dl,%cl # cl = (StartLBA % MaxSector) + 1 = Sector
275 xorw %dx,%dx # dx = 0
276 divw 2(%bp) # ax = ax / (MaxHead + 1) = Cylinder
277 # dx = ax % (MaxHead + 1) = Head
278
279 pushw %bx # Save number of blocks to transfer
280 movb %dl,%dh # dh = Head
281 movw $0x7c00,%bp # bp = 0x7c00
282 movb PhysicalDrive(%bp), %dl # dl = Drive Number
283 movb %al,%ch # ch = Cylinder
284 movb %bl,%al # al = Blocks
285 movb $2,%ah # ah = Function 2
286 movw %di,%bx # es:bx = Buffer address
287 int $0x13
288 jc DiskError
289 popw %bx
290 popw %cx
291 movzwl %bx,%ebx
292 addl %ebx,%esi # StartLBA = StartLBA + NumberOfBlocks
293 subw %bx,%cx # Blocks = Blocks - NumberOfBlocks
294 movw %es,%ax
295 shlw $(BLOCK_SHIFT-4), %bx
296 addw %bx,%ax
297 movw %ax,%es # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
298 cmpw $0,%cx
299 jne ReadCylinderLoop
300 popa
301 ret
302
303 DiskError:
304 pushw %cs
305 popw %ds
306 leaw ErrorString,%si
307 movw $7,%cx
308 jmp PrintStringAndHalt
309
310 PrintStringAndHalt:
311 movw $0xb800,%ax
312 movw %ax,%es
313 movw $160,%di
314 rep
315 movsw
316 Halt:
317 jmp Halt
318
319 ErrorString:
320 .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c
321
322 .org 0x01fa
323 LBAOffsetForBootSector:
324 .long 0x0
325
326 .org 0x01fe
327 .word 0xaa55
328
329 #******************************************************************************
330 #******************************************************************************
331 #******************************************************************************
332
333 .equ DELAY_PORT, 0x0ed # Port to use for 1uS delay
334 .equ KBD_CONTROL_PORT, 0x060 # 8042 control port
335 .equ KBD_STATUS_PORT, 0x064 # 8042 status port
336 .equ WRITE_DATA_PORT_CMD, 0x0d1 # 8042 command to write the data port
337 .equ ENABLE_A20_CMD, 0x0df # 8042 command to enable A20
338
339 .org 0x200
340 jmp start
341 Em64String:
342 .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
343
344 start:
345 movw %cs,%ax
346 movw %ax,%ds
347 movw %ax,%es
348 movw %ax,%ss
349 movw $MyStack, %sp
350
351 # mov ax,0b800h
352 # mov es,ax
353 # mov byte ptr es:[160],'a'
354 # mov ax,cs
355 # mov es,ax
356
357 movl $0,%ebx
358 leal MemoryMap, %edi
359 MemMapLoop:
360 movl $0xe820,%eax
361 movl $20,%ecx
362 movl $0x534d4150, %edx # SMAP
363 int $0x15
364 jc MemMapDone
365 addl $20,%edi
366 cmpl $0,%ebx
367 je MemMapDone
368 jmp MemMapLoop
369 MemMapDone:
370 leal MemoryMap, %eax
371 subl %eax,%edi # Get the address of the memory map
372 movl %edi, MemoryMapSize # Save the size of the memory map
373
374 xorl %ebx,%ebx
375 movw %cs,%bx # BX=segment
376 shll $4,%ebx # BX="linear" address of segment base
377 leal GDT_BASE(%ebx), %eax # EAX=PHYSICAL address of gdt
378 movl %eax, (gdtr + 2) # Put address of gdt into the gdtr
379 leal IDT_BASE(%ebx), %eax # EAX=PHYSICAL address of idt
380 movl %eax, (idtr + 2) # Put address of idt into the idtr
381 leal MemoryMapSize(%ebx), %edx # Physical base address of the memory map
382
383 # mov ax,0b800h
384 # mov es,ax
385 # mov byte ptr es:[162],'b'
386 # mov ax,cs
387 # mov es,ax
388
389 #
390 # Enable A20 Gate
391 #
392
393 movw $0x2401,%ax # Enable A20 Gate
394 int $0x15
395 jnc A20GateEnabled # Jump if it suceeded
396
397 #
398 # If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.
399 #
400
401 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller
402 jnz Timeout8042 # Jump if the 8042 timed out
403 outw %ax, $DELAY_PORT # Delay 1 uS
404 movb $WRITE_DATA_PORT_CMD, %al # 8042 cmd to write output port
405 outb %al, $KBD_STATUS_PORT # Send command to the 8042
406 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller
407 jnz Timeout8042 # Jump if the 8042 timed out
408 movb $ENABLE_A20_CMD, %al # gate address bit 20 on
409 outb %al, $KBD_CONTROL_PORT # Send command to thre 8042
410 call Empty8042InputBuffer # Empty the Input Buffer on the 8042 controller
411 movw $25,%cx # Delay 25 uS for the command to complete on the 8042
412 Delay25uS:
413 outw %ax, $DELAY_PORT # Delay 1 uS
414 loop Delay25uS
415 Timeout8042:
416
417
418 A20GateEnabled:
419
420 #
421 # DISABLE INTERRUPTS - Entering Protected Mode
422 #
423
424 cli
425
426 # mov ax,0b800h
427 # mov es,ax
428 # mov byte ptr es:[164],'c'
429 # mov ax,cs
430 # mov es,ax
431
432 leal OffsetIn32BitProtectedMode, %eax
433 addl $0x20000+0x6,%eax
434 movl %eax, OffsetIn32BitProtectedMode
435
436 leal OffsetInLongMode, %eax
437 addl $0x20000+0x6,%eax
438 movl %eax, OffsetInLongMode
439
440 #
441 # load GDT
442 #
443 .byte 0x66
444 lgdt gdtr
445
446 #
447 # Enable Protect Mode (set CR0.PE=1)
448 #
449 movl $cr0, %eax # Read CR0.
450 orl $0x1,%eax # Set PE=1
451 movl %eax, %cr0 # Write CR0.
452 .byte 0x66
453 .byte 0xea # jmp far 16:32
454 OffsetIn32BitProtectedMode:
455 .long 0x0000000 # offset $+8 (In32BitProtectedMode)
456 .word 0x10 # selector (flat CS)
457 In32BitProtectedMode:
458
459 #
460 # Entering Long Mode
461 #
462 .byte 0x66
463 movw $8,%ax
464 movw %ax,%ds
465 movw %ax,%es
466 movw %ax,%ss
467
468 #
469 # Enable the 64-bit page-translation-table entries by
470 # setting CR4.PAE=1 (this is _required_ before activating
471 # long mode). Paging is not enabled until after long mode
472 # is enabled.
473 #
474 .byte 0xf
475 .byte 0x20
476 .byte 0xe0
477 # mov eax, cr4
478 btsl $5,%eax
479 .byte 0xf
480 .byte 0x22
481 .byte 0xe0
482 # mov cr4, eax
483
484 #
485 # This is the Trapolean Page Tables that are guarenteed
486 # under 4GB.
487 #
488 # Address Map:
489 # 10000 ~ 12000 - efildr (loaded)
490 # 20000 ~ 21000 - start64.com
491 # 21000 ~ 22000 - efi64.com
492 # 22000 ~ 90000 - efildr
493 # 90000 ~ 96000 - 4G pagetable (will be reload later)
494 #
495 .byte 0xb8
496 .long 0x90000
497 # mov eax, 90000h
498 movl %eax, %cr3
499
500 #
501 # Enable long mode (set EFER.LME=1).
502 #
503 .byte 0xb9
504 .long 0xc0000080
505 # mov ecx, 0c0000080h ; EFER MSR number.
506 .byte 0xf
507 .byte 0x32
508 # rdmsr ; Read EFER.
509 .byte 0xf
510 .byte 0xba
511 .byte 0xe8
512 .byte 0x8
513 # bts eax, 8 ; Set LME=1.
514 .byte 0xf
515 .byte 0x30
516 # wrmsr ; Write EFER.
517
518 #
519 # Enable paging to activate long mode (set CR0.PG=1)
520 #
521 movl $cr0, %eax # Read CR0.
522 .byte 0xf
523 .byte 0xba
524 .byte 0xe8
525 .byte 0x1f
526 # bts eax, 31 ; Set PG=1.
527 movl %eax, %cr0 # Write CR0.
528 jmp GoToLongMode
529 GoToLongMode:
530
531 .byte 0x67
532 .byte 0xea # Far Jump $+9:Selector to reload CS
533 OffsetInLongMode:
534 .long 00000000 # $+9 Offset is ensuing instruction boundary
535 .word 0x38 # Selector is our code selector, 38h
536
537 InLongMode:
538 .byte 0x66
539 movw $0x30,%ax
540 movw %ax,%ds
541
542 .byte 0x66
543 movw $0x18,%ax
544 movw %ax,%es
545 movw %ax,%ss
546 movw %ax,%ds
547
548 .byte 0xbd
549 .long 0x400000
550 # mov ebp,000400000h ; Destination of EFILDR32
551 .byte 0xbb
552 .long 0x70000
553 # mov ebx,000070000h ; Length of copy
554
555 #
556 # load idt later
557 #
558 .byte 0x48
559 .byte 0x33
560 .byte 0xc0
561 # xor rax, rax
562 .byte 0x66
563 movw $idtr, %ax
564 .byte 0x48
565 .byte 0x5
566 .long 0x20000
567 # add rax, 20000h
568
569 .byte 0xf
570 .byte 0x1
571 .byte 0x18
572 # lidt fword ptr [rax]
573
574 .byte 0x48
575 .byte 0xc7
576 .byte 0xc0
577 .long 0x21000
578 # mov rax, 21000h
579 .byte 0x50
580 # push rax
581
582 # ret
583 .byte 0xc3
584
585 Empty8042InputBuffer:
586 movw $0,%cx
587 Empty8042Loop:
588 outw %ax, $DELAY_PORT # Delay 1us
589 inb $KBD_STATUS_PORT, %al # Read the 8042 Status Port
590 andb $0x2,%al # Check the Input Buffer Full Flag
591 loopnz Empty8042Loop # Loop until the input buffer is empty or a timout of 65536 uS
592 ret
593
594 ##############################################################################
595 # data
596 ##############################################################################
597
598 .p2align 1
599
600 gdtr: .long GDT_END - GDT_BASE - 1 # GDT limit
601 .long 0 # (GDT base gets set above)
602 ##############################################################################
603 # global descriptor table (GDT)
604 ##############################################################################
605
606 .p2align 1
607
608 GDT_BASE:
609 # null descriptor
610 .equ NULL_SEL, .-GDT_BASE # Selector [0x0]
611 .word 0 # limit 15:0
612 .word 0 # base 15:0
613 .byte 0 # base 23:16
614 .byte 0 # type
615 .byte 0 # limit 19:16, flags
616 .byte 0 # base 31:24
617
618 # linear data segment descriptor
619 .equ LINEAR_SEL, .-GDT_BASE # Selector [0x8]
620 .word 0xFFFF # limit 0xFFFFF
621 .word 0 # base 0
622 .byte 0
623 .byte 0x92 # present, ring 0, data, expand-up, writable
624 .byte 0xCF # page-granular, 32-bit
625 .byte 0
626
627 # linear code segment descriptor
628 .equ LINEAR_CODE_SEL, .-GDT_BASE # Selector [0x10]
629 .word 0xFFFF # limit 0xFFFFF
630 .word 0 # base 0
631 .byte 0
632 .byte 0x9A # present, ring 0, data, expand-up, writable
633 .byte 0xCF # page-granular, 32-bit
634 .byte 0
635
636 # system data segment descriptor
637 .equ SYS_DATA_SEL, .-GDT_BASE # Selector [0x18]
638 .word 0xFFFF # limit 0xFFFFF
639 .word 0 # base 0
640 .byte 0
641 .byte 0x92 # present, ring 0, data, expand-up, writable
642 .byte 0xCF # page-granular, 32-bit
643 .byte 0
644
645 # system code segment descriptor
646 .equ SYS_CODE_SEL, .-GDT_BASE # Selector [0x20]
647 .word 0xFFFF # limit 0xFFFFF
648 .word 0 # base 0
649 .byte 0
650 .byte 0x9A # present, ring 0, data, expand-up, writable
651 .byte 0xCF # page-granular, 32-bit
652 .byte 0
653
654 # spare segment descriptor
655 .equ SPARE3_SEL, .-GDT_BASE # Selector [0x28]
656 .word 0 # limit 0xFFFFF
657 .word 0 # base 0
658 .byte 0
659 .byte 0 # present, ring 0, data, expand-up, writable
660 .byte 0 # page-granular, 32-bit
661 .byte 0
662
663 #
664 # system data segment descriptor
665 #
666 .equ SYS_DATA64_SEL, .-GDT_BASE # Selector [0x30]
667 .word 0xFFFF # limit 0xFFFFF
668 .word 0 # base 0
669 .byte 0
670 .byte 0x92 # P | DPL [1..2] | 1 | 1 | C | R | A
671 .byte 0xCF # G | D | L | AVL | Segment [19..16]
672 .byte 0
673
674 #
675 # system code segment descriptor
676 #
677 .equ SYS_CODE64_SEL, .-GDT_BASE # Selector [0x38]
678 .word 0xFFFF # limit 0xFFFFF
679 .word 0 # base 0
680 .byte 0
681 .byte 0x9A # P | DPL [1..2] | 1 | 1 | C | R | A
682 .byte 0xAF # G | D | L | AVL | Segment [19..16]
683 .byte 0
684
685 # spare segment descriptor
686 .equ SPARE4_SEL, .-GDT_BASE # Selector [0x40]
687 .word 0 # limit 0xFFFFF
688 .word 0 # base 0
689 .byte 0
690 .byte 0 # present, ring 0, data, expand-up, writable
691 .byte 0 # page-granular, 32-bit
692 .byte 0
693
694 GDT_END:
695
696 .p2align 1
697
698
699
700 idtr: .long IDT_END - IDT_BASE - 1 # IDT limit
701 .quad 0 # (IDT base gets set above)
702
703 ##############################################################################
704 # interrupt descriptor table (IDT)
705 #
706 # Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ
707 # mappings. This implementation only uses the system timer and all other
708 # IRQs will remain masked. The descriptors for vectors 33+ are provided
709 # for convenience.
710 ##############################################################################
711
712 #idt_tag db "IDT",0
713 .p2align 1
714
715
716 IDT_BASE:
717 # divide by zero (INT 0)
718 .equ DIV_ZERO_SEL, .-IDT_BASE
719 .word 0 # offset 15:0
720 .long SYS_CODE64_SEL # selector 15:0
721 .byte 0 # 0 for interrupt gate
722 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
723 .word 0 # offset 31:16
724 .long 0 # offset 63:32
725 .long 0 # 0 for reserved
726
727 # debug exception (INT 1)
728 .equ DEBUG_EXCEPT_SEL, .-IDT_BASE
729 .word 0 # offset 15:0
730 .long SYS_CODE64_SEL # selector 15:0
731 .byte 0 # 0 for interrupt gate
732 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
733 .word 0 # offset 31:16
734 .long 0 # offset 63:32
735 .long 0 # 0 for reserved
736
737 # NMI (INT 2)
738 .equ NMI_SEL, .-IDT_BASE
739 .word 0 # offset 15:0
740 .long SYS_CODE64_SEL # selector 15:0
741 .byte 0 # 0 for interrupt gate
742 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
743 .word 0 # offset 31:16
744 .long 0 # offset 63:32
745 .long 0 # 0 for reserved
746
747 # soft breakpoint (INT 3)
748 .equ BREAKPOINT_SEL, .-IDT_BASE
749 .word 0 # offset 15:0
750 .long SYS_CODE64_SEL # selector 15:0
751 .byte 0 # 0 for interrupt gate
752 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
753 .word 0 # offset 31:16
754 .long 0 # offset 63:32
755 .long 0 # 0 for reserved
756
757 # overflow (INT 4)
758 .equ OVERFLOW_SEL, .-IDT_BASE
759 .word 0 # offset 15:0
760 .long SYS_CODE64_SEL # selector 15:0
761 .byte 0 # 0 for interrupt gate
762 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
763 .word 0 # offset 31:16
764 .long 0 # offset 63:32
765 .long 0 # 0 for reserved
766
767 # bounds check (INT 5)
768 .equ BOUNDS_CHECK_SEL, .-IDT_BASE
769 .word 0 # offset 15:0
770 .long SYS_CODE64_SEL # selector 15:0
771 .byte 0 # 0 for interrupt gate
772 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
773 .word 0 # offset 31:16
774 .long 0 # offset 63:32
775 .long 0 # 0 for reserved
776
777 # invalid opcode (INT 6)
778 .equ INVALID_OPCODE_SEL, .-IDT_BASE
779 .word 0 # offset 15:0
780 .long SYS_CODE64_SEL # selector 15:0
781 .byte 0 # 0 for interrupt gate
782 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
783 .word 0 # offset 31:16
784 .long 0 # offset 63:32
785 .long 0 # 0 for reserved
786
787 # device not available (INT 7)
788 .equ DEV_NOT_AVAIL_SEL, .-IDT_BASE
789 .word 0 # offset 15:0
790 .long SYS_CODE64_SEL # selector 15:0
791 .byte 0 # 0 for interrupt gate
792 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
793 .word 0 # offset 31:16
794 .long 0 # offset 63:32
795 .long 0 # 0 for reserved
796
797 # double fault (INT 8)
798 .equ DOUBLE_FAULT_SEL, .-IDT_BASE
799 .word 0 # offset 15:0
800 .long SYS_CODE64_SEL # selector 15:0
801 .byte 0 # 0 for interrupt gate
802 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
803 .word 0 # offset 31:16
804 .long 0 # offset 63:32
805 .long 0 # 0 for reserved
806
807 # Coprocessor segment overrun - reserved (INT 9)
808 .equ RSVD_INTR_SEL1, .-IDT_BASE
809 .word 0 # offset 15:0
810 .long SYS_CODE64_SEL # selector 15:0
811 .byte 0 # 0 for interrupt gate
812 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
813 .word 0 # offset 31:16
814 .long 0 # offset 63:32
815 .long 0 # 0 for reserved
816
817 # invalid TSS (INT 0ah)
818 .equ INVALID_TSS_SEL, .-IDT_BASE
819 .word 0 # offset 15:0
820 .long SYS_CODE64_SEL # selector 15:0
821 .byte 0 # 0 for interrupt gate
822 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
823 .word 0 # offset 31:16
824 .long 0 # offset 63:32
825 .long 0 # 0 for reserved
826
827 # segment not present (INT 0bh)
828 .equ SEG_NOT_PRESENT_SEL, .-IDT_BASE
829 .word 0 # offset 15:0
830 .long SYS_CODE64_SEL # selector 15:0
831 .byte 0 # 0 for interrupt gate
832 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
833 .word 0 # offset 31:16
834 .long 0 # offset 63:32
835 .long 0 # 0 for reserved
836
837 # stack fault (INT 0ch)
838 .equ STACK_FAULT_SEL, .-IDT_BASE
839 .word 0 # offset 15:0
840 .long SYS_CODE64_SEL # selector 15:0
841 .byte 0 # 0 for interrupt gate
842 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
843 .word 0 # offset 31:16
844 .long 0 # offset 63:32
845 .long 0 # 0 for reserved
846
847 # general protection (INT 0dh)
848 .equ GP_FAULT_SEL, .-IDT_BASE
849 .word 0 # offset 15:0
850 .long SYS_CODE64_SEL # selector 15:0
851 .byte 0 # 0 for interrupt gate
852 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
853 .word 0 # offset 31:16
854 .long 0 # offset 63:32
855 .long 0 # 0 for reserved
856
857 # page fault (INT 0eh)
858 .equ PAGE_FAULT_SEL, .-IDT_BASE
859 .word 0 # offset 15:0
860 .long SYS_CODE64_SEL # selector 15:0
861 .byte 0 # 0 for interrupt gate
862 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
863 .word 0 # offset 31:16
864 .long 0 # offset 63:32
865 .long 0 # 0 for reserved
866
867 # Intel reserved - do not use (INT 0fh)
868 .equ RSVD_INTR_SEL2, .-IDT_BASE
869 .word 0 # offset 15:0
870 .long SYS_CODE64_SEL # selector 15:0
871 .byte 0 # 0 for interrupt gate
872 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
873 .word 0 # offset 31:16
874 .long 0 # offset 63:32
875 .long 0 # 0 for reserved
876
877 # floating point error (INT 10h)
878 .equ FLT_POINT_ERR_SEL, .-IDT_BASE
879 .word 0 # offset 15:0
880 .long SYS_CODE64_SEL # selector 15:0
881 .byte 0 # 0 for interrupt gate
882 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
883 .word 0 # offset 31:16
884 .long 0 # offset 63:32
885 .long 0 # 0 for reserved
886
887 # alignment check (INT 11h)
888 .equ ALIGNMENT_CHECK_SEL, .-IDT_BASE
889 .word 0 # offset 15:0
890 .long SYS_CODE64_SEL # selector 15:0
891 .byte 0 # 0 for interrupt gate
892 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
893 .word 0 # offset 31:16
894 .long 0 # offset 63:32
895 .long 0 # 0 for reserved
896
897 # machine check (INT 12h)
898 .equ MACHINE_CHECK_SEL, .-IDT_BASE
899 .word 0 # offset 15:0
900 .long SYS_CODE64_SEL # selector 15:0
901 .byte 0 # 0 for interrupt gate
902 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
903 .word 0 # offset 31:16
904 .long 0 # offset 63:32
905 .long 0 # 0 for reserved
906
907 # SIMD floating-point exception (INT 13h)
908 .equ SIMD_EXCEPTION_SEL, .-IDT_BASE
909 .word 0 # offset 15:0
910 .long SYS_CODE64_SEL # selector 15:0
911 .byte 0 # 0 for interrupt gate
912 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
913 .word 0 # offset 31:16
914 .long 0 # offset 63:32
915 .long 0 # 0 for reserved
916
917 # 85 unspecified descriptors, First 12 of them are reserved, the rest are avail
918 .fill 85 * 16, 1, 0 # db (85 * 16) dup(0)
919
920 # IRQ 0 (System timer) - (INT 68h)
921 .equ IRQ0_SEL, .-IDT_BASE
922 .word 0 # offset 15:0
923 .long SYS_CODE64_SEL # selector 15:0
924 .byte 0 # 0 for interrupt gate
925 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
926 .word 0 # offset 31:16
927 .long 0 # offset 63:32
928 .long 0 # 0 for reserved
929
930 # IRQ 1 (8042 Keyboard controller) - (INT 69h)
931 .equ IRQ1_SEL, .-IDT_BASE
932 .word 0 # offset 15:0
933 .long SYS_CODE64_SEL # selector 15:0
934 .byte 0 # 0 for interrupt gate
935 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
936 .word 0 # offset 31:16
937 .long 0 # offset 63:32
938 .long 0 # 0 for reserved
939
940 # Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)
941 .equ IRQ2_SEL, .-IDT_BASE
942 .word 0 # offset 15:0
943 .long SYS_CODE64_SEL # selector 15:0
944 .byte 0 # 0 for interrupt gate
945 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
946 .word 0 # offset 31:16
947 .long 0 # offset 63:32
948 .long 0 # 0 for reserved
949
950 # IRQ 3 (COM 2) - (INT 6bh)
951 .equ IRQ3_SEL, .-IDT_BASE
952 .word 0 # offset 15:0
953 .long SYS_CODE64_SEL # selector 15:0
954 .byte 0 # 0 for interrupt gate
955 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
956 .word 0 # offset 31:16
957 .long 0 # offset 63:32
958 .long 0 # 0 for reserved
959
960 # IRQ 4 (COM 1) - (INT 6ch)
961 .equ IRQ4_SEL, .-IDT_BASE
962 .word 0 # offset 15:0
963 .long SYS_CODE64_SEL # selector 15:0
964 .byte 0 # 0 for interrupt gate
965 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
966 .word 0 # offset 31:16
967 .long 0 # offset 63:32
968 .long 0 # 0 for reserved
969
970 # IRQ 5 (LPT 2) - (INT 6dh)
971 .equ IRQ5_SEL, .-IDT_BASE
972 .word 0 # offset 15:0
973 .long SYS_CODE64_SEL # selector 15:0
974 .byte 0 # 0 for interrupt gate
975 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
976 .word 0 # offset 31:16
977 .long 0 # offset 63:32
978 .long 0 # 0 for reserved
979
980 # IRQ 6 (Floppy controller) - (INT 6eh)
981 .equ IRQ6_SEL, .-IDT_BASE
982 .word 0 # offset 15:0
983 .long SYS_CODE64_SEL # selector 15:0
984 .byte 0 # 0 for interrupt gate
985 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
986 .word 0 # offset 31:16
987 .long 0 # offset 63:32
988 .long 0 # 0 for reserved
989
990 # IRQ 7 (LPT 1) - (INT 6fh)
991 .equ IRQ7_SEL, .-IDT_BASE
992 .word 0 # offset 15:0
993 .long SYS_CODE64_SEL # selector 15:0
994 .byte 0 # 0 for interrupt gate
995 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
996 .word 0 # offset 31:16
997 .long 0 # offset 63:32
998 .long 0 # 0 for reserved
999
1000 # IRQ 8 (RTC Alarm) - (INT 70h)
1001 .equ IRQ8_SEL, .-IDT_BASE
1002 .word 0 # offset 15:0
1003 .long SYS_CODE64_SEL # selector 15:0
1004 .byte 0 # 0 for interrupt gate
1005 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1006 .word 0 # offset 31:16
1007 .long 0 # offset 63:32
1008 .long 0 # 0 for reserved
1009
1010 # IRQ 9 - (INT 71h)
1011 .equ IRQ9_SEL, .-IDT_BASE
1012 .word 0 # offset 15:0
1013 .long SYS_CODE64_SEL # selector 15:0
1014 .byte 0 # 0 for interrupt gate
1015 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1016 .word 0 # offset 31:16
1017 .long 0 # offset 63:32
1018 .long 0 # 0 for reserved
1019
1020 # IRQ 10 - (INT 72h)
1021 .equ IRQ10_SEL, .-IDT_BASE
1022 .word 0 # offset 15:0
1023 .long SYS_CODE64_SEL # selector 15:0
1024 .byte 0 # 0 for interrupt gate
1025 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1026 .word 0 # offset 31:16
1027 .long 0 # offset 63:32
1028 .long 0 # 0 for reserved
1029
1030 # IRQ 11 - (INT 73h)
1031 .equ IRQ11_SEL, .-IDT_BASE
1032 .word 0 # offset 15:0
1033 .long SYS_CODE64_SEL # selector 15:0
1034 .byte 0 # 0 for interrupt gate
1035 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1036 .word 0 # offset 31:16
1037 .long 0 # offset 63:32
1038 .long 0 # 0 for reserved
1039
1040 # IRQ 12 (PS/2 mouse) - (INT 74h)
1041 .equ IRQ12_SEL, .-IDT_BASE
1042 .word 0 # offset 15:0
1043 .long SYS_CODE64_SEL # selector 15:0
1044 .byte 0 # 0 for interrupt gate
1045 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1046 .word 0 # offset 31:16
1047 .long 0 # offset 63:32
1048 .long 0 # 0 for reserved
1049
1050 # IRQ 13 (Floating point error) - (INT 75h)
1051 .equ IRQ13_SEL, .-IDT_BASE
1052 .word 0 # offset 15:0
1053 .long SYS_CODE64_SEL # selector 15:0
1054 .byte 0 # 0 for interrupt gate
1055 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1056 .word 0 # offset 31:16
1057 .long 0 # offset 63:32
1058 .long 0 # 0 for reserved
1059
1060 # IRQ 14 (Secondary IDE) - (INT 76h)
1061 .equ IRQ14_SEL, .-IDT_BASE
1062 .word 0 # offset 15:0
1063 .long SYS_CODE64_SEL # selector 15:0
1064 .byte 0 # 0 for interrupt gate
1065 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1066 .word 0 # offset 31:16
1067 .long 0 # offset 63:32
1068 .long 0 # 0 for reserved
1069
1070 # IRQ 15 (Primary IDE) - (INT 77h)
1071 .equ IRQ15_SEL, .-IDT_BASE
1072 .word 0 # offset 15:0
1073 .long SYS_CODE64_SEL # selector 15:0
1074 .byte 0 # 0 for interrupt gate
1075 .byte 0x0e | 0x80 # type = 386 interrupt gate, present
1076 .word 0 # offset 31:16
1077 .long 0 # offset 63:32
1078 .long 0 # 0 for reserved
1079
1080 IDT_END:
1081
1082 .p2align 1
1083
1084 MemoryMapSize: .long 0
1085 MemoryMap: .long 0,0,0,0,0,0,0,0
1086 .long 0,0,0,0,0,0,0,0
1087 .long 0,0,0,0,0,0,0,0
1088 .long 0,0,0,0,0,0,0,0
1089 .long 0,0,0,0,0,0,0,0
1090 .long 0,0,0,0,0,0,0,0
1091 .long 0,0,0,0,0,0,0,0
1092 .long 0,0,0,0,0,0,0,0
1093 .long 0,0,0,0,0,0,0,0
1094 .long 0,0,0,0,0,0,0,0
1095 .long 0,0,0,0,0,0,0,0
1096 .long 0,0,0,0,0,0,0,0
1097 .long 0,0,0,0,0,0,0,0
1098 .long 0,0,0,0,0,0,0,0
1099 .long 0,0,0,0,0,0,0,0
1100 .long 0,0,0,0,0,0,0,0
1101 .long 0,0,0,0,0,0,0,0
1102 .long 0,0,0,0,0,0,0,0
1103 .long 0,0,0,0,0,0,0,0
1104 .long 0,0,0,0,0,0,0,0
1105 .long 0,0,0,0,0,0,0,0
1106 .long 0,0,0,0,0,0,0,0
1107 .long 0,0,0,0,0,0,0,0
1108 .long 0,0,0,0,0,0,0,0
1109 .long 0,0,0,0,0,0,0,0
1110 .long 0,0,0,0,0,0,0,0
1111 .long 0,0,0,0,0,0,0,0
1112 .long 0,0,0,0,0,0,0,0
1113 .long 0,0,0,0,0,0,0,0
1114 .long 0,0,0,0,0,0,0,0
1115
1116 .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
1117 .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
1118
1119 #.org 0x0fe0 #Just for pass build
1120 MyStack:
1121 # below is the pieces of the IVT that is used to redirect INT 68h - 6fh
1122 # back to INT 08h - 0fh when in real mode... It is 'org'ed to a
1123 # known low address (20f00) so it can be set up by PlMapIrqToVect in
1124 # 8259.c
1125
1126 int $8
1127 iret
1128
1129 int $9
1130 iret
1131
1132 int $10
1133 iret
1134
1135 int $11
1136 iret
1137
1138 int $12
1139 iret
1140
1141 int $13
1142 iret
1143
1144 int $14
1145 iret
1146
1147 int $15
1148 iret
1149
1150
1151 #.org 0x0ffe #Just for pass build
1152 BlockSignature:
1153 .word 0xaa55
1154