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