-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboot.asm
191 lines (157 loc) · 4.38 KB
/
boot.asm
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
190
191
global start
global code_select
extern long_mode_start
section .text
bits 32
start:
mov esp, stack_top
call check_multiboot
call check_cpuid
call check_long_mode
call set_up_page_tables
call enable_paging
; load 64-bit GDT
lgdt [pointer]
jmp code_selector:long_mode_start
; print ok should never get here
mov dword [0xb8000], 0x2F4B2F4F
hlt
; Prints Err: and given code to scren then hangs
; param: error code (in ascii) in al
error:
mov dword [0xb8000], 0x4f524f45
mov dword [0xb8004], 0x4f3a4f52
mov dword [0xb8008], 0x4f204f20
mov byte [0xb800a], al
hlt
check_multiboot:
cmp eax, 0x36D76289
jne .no_multiboot
ret
.no_multiboot:
mov al, "0"
jmp error
check_cpuid:
; Try and flip ID bit (bit 21)
; in the FLAGS register. If we can CPUID is available
; Copy FLAGS into EAX via stack
pushfd
pop eax
; Copy to EXC for later compare
mov ecx, eax
; Flip it
xor eax, 1 << 21
; Copy EAX to FLAGS via the stack
push eax
popfd
; Copy back with flipped bit if CPUID is supported
pushfd
pop eax
; Restore FLAGS (if we were able to flip it or not)
push ecx
popfd
; Compare EAX and ECX
cmp eax, ecx
je .no_cpuid
ret
.no_cpuid:
mov al, "1"
jmp error
check_long_mode:
; is extended processor info available
mov eax, 0x80000000 ; implicit argument for cpuid
cpuid ; get highest supported arg
cmp eax, 0x80000001 ; we need atleast 0x80000001
jb .no_long_mode ; if less CPU too old
; now test if we can long mode
mov eax, 0x80000001 ; argument for extended processor info
cpuid ; feature bits in ecx and edx
test edx, 1 << 29 ; see if LM-bit is set in D-register
jz .no_long_mode ; nope :-( err
ret
.no_long_mode:
mov al, "2"
jmp error
set_up_page_tables:
; map firt p4 entry to p3 table
mov eax, p3_table
or eax, 0b11 ; present + writable
mov [p4_table], eax
; map first p3 entry to p2
mov eax, p2_table
or eax, 0b11 ; present + writable
mov [p3_table], eax
mov ecx, 0 ; counter variable
.map_p2_table:
; map ecx-th p2 to a huge page starting at address 2Mib*ecx
mov eax, 0x200000 ; 2Mib
mul ecx ;start address of ecx-th page
or eax, 0b10000011 ; present + writeable + huge
mov [p2_table + ecx * 8], eax ; map ecx-th entry
inc ecx ; increase the counter
cmp ecx, 512 ; if counter == 512, p2 table is mapped
jne .map_p2_table ; otherwise do it again
ret
enable_paging:
;; load p4 to cr3 (cpu uses this to acces p4 table)
mov eax, p4_table
mov cr3, eax
;; enable PAE-flag in cr4 (Physical Address Extension)
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
;; set long mode bit in EFER MSR
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
;; enable paging in cr0 register
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
ret
struc gdt_entry
.limit_low: resb 2
.base_low: resb 2
.base_middle: resb 1
.access: resb 1
.granularity: resb 1
.base_high: resb 1
endstruc
section .rodata
gdt64:
dq 0 ; zero entry
code_selector: equ $ - gdt64 ; cs
istruc gdt_entry
at gdt_entry.limit_low, dw 0
at gdt_entry.base_low, dw 0
at gdt_entry.base_middle, db 0
at gdt_entry.access, db 154
at gdt_entry.granularity, db 175
at gdt_entry.base_high, db 0
iend
data_selector: equ $ - gdt64 ; ds
istruc gdt_entry
at gdt_entry.limit_low, dw 0
at gdt_entry.base_low, dw 0
at gdt_entry.base_middle, db 0
at gdt_entry.access, db 146
at gdt_entry.granularity, db 0
at gdt_entry.base_high, db 0
iend
; dq (1<<43) | (1<<44) | (1<<47) | (1<<53)
; code segment
pointer:
dw $ - gdt64 - 1
dq gdt64
section .bss
align 4096
p4_table:
resb 4096
p3_table:
resb 4096
p2_table:
resb 4096
stack_bottom:
resb 64
stack_top: