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