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