1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
format ELF64
extrn kmain
PML4_TABLE = 0x1000
E820_MMAP = 0xf000
MSR_EFER = 0xc0000080
include 'bios.inc'
include 'page.inc'
include 'segdesc.inc'
section '.boot' executable writeable
org 0x7c00
use16
jmp far 0x0000:@f ; ensure cs = 0x0000
@@:
xor ax, ax
mov ds, ax
mov es, ax
; put stack directly bellow bootloader
mov ss, ax
mov sp, $$
cld
mov [boot_disk], dl
bios_disk_read ($$+0x200), 0, 0, 2, 57, disk_error
bios_e820_mmap E820_MMAP, e820_error
bios_a20_enable
bios_vga_write_mode_3
page_table_init_real PML4_TABLE
; disable IRQs
mov al, 0xff
out 0xa1, al
out 0x21, al
lidt [dummy_idtr]
; enable PAE (1<<5) and PGE (1<<7)
mov eax, (1 shl 7) or (1 shl 5)
mov cr4, eax
; point cr3 at PML4
mov edx, edi
mov cr3, edx
; enable long mode
mov ecx, MSR_EFER
rdmsr
or eax, (1 shl 8)
wrmsr
; enable protected mode
mov ebx, cr0
or ebx, (1 shl 31) or (1 shl 0)
mov cr0, ebx
lgdt [gdtr]
jmp far (gdt.kcode-gdt):longmode
e820_error:
; change beginning of error message ("disk" -> "e820")
mov dword [errmsg], 0x30323865
disk_error:
mov si, errmsg
mov ah, 0x0e
jmp @f
.loop:
int 0x10
@@:
lodsb
test al, al
jnz .loop
; wait until keypress, then jump to reset vector (reboot)
xor ah, ah
int 0x16
jmp far 0xffff:0x0000
use64
longmode:
mov ax, (gdt.kdata-gdt)
mov ds, ax
mov es, ax
mov ss, ax
cli
; copy kernel to 0x100000
mov ecx, (57*0x200)/8
mov esi, 0x7e00
mov edi, 0x100000
rep movsq
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor edi, edi
xor esi, esi
; put stack at top of addressable memory
mov esp, 0x200000
mov ebp, esp
; manually encoded 'jmp rel32', fasm throws an 'invalid use of symbol'
; error when generating code for a jmp to an external symbol after
; setting code origin with 'org' directive or a 'virtual at X' block.
db 0xe9
dd kmain-$-4
align 4
dw 0
label gdtr fword
.limit dw (gdt.sizeof - 1)
.addr dd gdt
align 4
errmsg db "disk error: press any key to reboot",0
align 8
gdt:
.null dq 0
.kcode seg_desc 0, 0, (GDT_CODE_64 or SEG_PRIV0)
.kdata seg_desc 0, 0, (GDT_DATA_64 or SEG_PRIV0)
.ucode seg_desc 0, 0, (GDT_CODE_64 or SEG_PRIV3)
.udata seg_desc 0, 0, (GDT_DATA_64 or SEG_PRIV3)
.sizeof = $ - gdt
align 4
boot_disk db 0, 0
label dummy_idtr fword
.limit dw 0
.addr dd 0
if ($-$$) <= 510
db 510-($-$$) dup 0
else
display "ERR: boot sector image exceeds 512 bytes",10
assert ($-$$) <= 510
end if
db 0x55,0xaa
|