-
Notifications
You must be signed in to change notification settings - Fork 0
/
boot.S
189 lines (155 loc) · 3.37 KB
/
boot.S
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* boot.S - bootstrap the kernel
* vim:et:ts=4:sts=4:sw=4
*/
#define ASM_FILE 1
#include "multiboot.h"
#include "constants.h"
/* The flags for the Multiboot header. */
#ifdef __ELF__
# define MULTIBOOT_HEADER_FLAGS 0x00000003
#else
# define MULTIBOOT_HEADER_FLAGS 0x00010003
#endif
.text
.code32
.globl start, _start
start:
_start:
jmp multiboot_entry
/* Align 32 bits boundary. */
.align 4
/* Multiboot header. */
multiboot_header:
/* magic */
.long MULTIBOOT_HEADER_MAGIC
/* flags */
.long MULTIBOOT_HEADER_FLAGS
/* checksum */
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
#ifndef __ELF__
/* header_addr */
.long multiboot_header
/* load_addr */
.long _start
/* load_end_addr */
.long _edata
/* bss_end_addr */
.long _end
/* entry_addr */
.long multiboot_entry
#endif /* ! __ELF__ */
multiboot_entry:
pushfl
pop %eax
mov %eax, %ecx
btc $21, %eax
push %eax
popfl
pushfl
pop %eax
push %ecx
popfl
xor %eax, %ecx
jz fail
mov $0x80000000, %eax
cpuid
cmp $0x80000001, %eax
jb fail
mov $0x80000001, %eax
cpuid
bt $29, %edx
jae fail
golong:
cli
movl %ebx, %esi
movl %eax, %edi
# create a long mode page table
movl $pml4, %eax
movl %eax, %cr3
# enable 64-bit page table with CR4.PAE
movl %cr4, %eax
bts $5, %eax
movl %eax, %cr4
# enable long mode
movl $0xc0000080, %ecx
rdmsr
bts $8, %eax
wrmsr
movl %cr0, %eax
bts $31, %eax
movl %eax, %cr0
lgdt (pGDT)
lidt (pIDT)
# enable paging and jump to long mode
ljmp $CS_KERNEL, $_load64
fail:
mov $0xb8000,%edi
mov $(80*25 / 2),%ecx
xor %eax,%eax
rep stosl
mov $0xb8000,%edi
mov $nolong,%esi
mov $0x10,%ecx
mov $0x0c00,%eax
rep movsl
hang:
hlt
jmp hang
.code64
_load64:
movq $(bootstack_end - KERNEL_VMA_BASE), %rsp
call start64
hlt
# GDT and IDT
.align 4096
GDT_START:
.quad 0 # NULL descriptor
GDT_CSK:
.short 0xffff # code segment limit - ignored
.short 0 # code base low - ignored
.byte 0 # code base middle - ignored
.byte 0x9A # code access
.byte 0xaf # granularity (L=1)
.byte 0 # code base high - ignored
GDT_DSK:
.short 0xffff # code segment limit - ignored
.short 0 # code base low - ignored
.byte 0 # code base middle - ignored
.byte 0x92 # code access
.byte 0xcf # granularity (L=1)
.byte 0 # code base high - ignored
GDT_END:
.word 0 # padding
pGDT:
.word GDT_END - GDT_START - 1
.quad GDT_START
.word 0 #padding
pIDT:
.word 0
.quad 0
.align 4096 # tables MUST be aligned
# PML4
pml4:
.quad (pml3a + 3)
.fill 510, 8, 0
.quad (pml3b + 3)
# PML3
pml3a:
.quad (pml2 + 3)
.fill 511, 8, 0
pml3b:
.fill 510, 8, 0
.quad (pml2 + 3)
.quad 0
# identity-map lower 2MB
pml2:
.quad (pml1 + 3)
.fill 511, 8, 0
pml1:
i = 0
.rept 512
.quad (i + 3)
i = i + 0x1000
.endr
nolong:
.asciz "N\7o\7 \7l\7o\7n\7g\7 \7m\7o\7d\7e\7 \7s\7u\7p\7p\7o\7r\7t\7e\7d\7.\7 \7H\14a\14l\14t\14e\14d\14.\14\0\0"