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
|
[BITS 32]
; Declare constants for the multiboot header.
MBALIGN equ 1 << 0 ; align loaded modules on page boundaries
MEMINFO equ 1 << 1 ; provide memory map
MBFLAGS equ MBALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + MBFLAGS) ; checksum of above, to prove we are multiboot
; Declare a multiboot header that marks the program as a kernel. These are magic
; values that are documented in the multiboot standard. The bootloader will
; search for this signature in the first 8 KiB of the kernel file, aligned at a
; 32-bit boundary. The signature is in its own section so the header can be
; forced to be within the first 8 KiB of the kernel file.
section .multiboot
align 4
dd MAGIC
dd MBFLAGS
dd CHECKSUM
section .bootstrap
present equ 1 << 7
not_sys equ 1 << 4
exec equ 1 << 3
cd equ 1 << 2
rw equ 1 << 1
access equ 1 << 0
gran_4k equ 1 << 7
sz_32 equ 1 << 6
long_m equ 1 << 5
global gdt.ptr
gdt:
.null: equ $ - gdt
dq 0
.code: equ $ - gdt
dd 0xffff
db 0
db present | not_sys | exec | rw
db gran_4k | long_m | 0xf
db 0
.data: equ $ - gdt
dd 0xffff
db 0
db present | not_sys | rw
db gran_4k | sz_32 | 0xf
db 0
.ptr:
dw $ - gdt - 1
dq gdt
global bootstrap
bootstrap:
mov dword [multiboot_magic], eax
mov dword [multiboot_header], ebx
mov eax, cr0
and eax, ~(1 << 31)
mov cr0, eax
mov edi, pml4 ;0x1000
mov cr3, edi
xor eax, eax
mov ecx, 1024
rep stosd
mov edi, 0x2000
mov ecx, 4096
rep stosd
mov edi, cr3
mov dword [edi], 0x2003
mov edi, 0x2000
mov dword [edi], 0x3003
add edi, 0x1000
mov dword [edi], 0x4003
mov dword [edi + 8], 0x5003
add edi, 0x1000
mov ebx, 0x00000003
mov ecx, 512
.set_entry:
mov dword [edi], ebx
add ebx, 0x1000
add edi, 8
loop .set_entry
mov edi, 0x5000
mov ecx, 512
.set_entry_2:
mov dword [edi], ebx
add ebx, 0x1000
add edi, 8
loop .set_entry_2
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
mov ecx, 0xc0000080
rdmsr
or eax, 1 << 8 | 1 << 0
wrmsr
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
lgdt [gdt.ptr]
mov ax, gdt.data
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
extern start
jmp gdt.code:start
global set_pml4
set_pml4:
mov ecx, 0xC000080
rdmsr
and eax, ~(1 << 8)
wrmsr
mov eax, cr0
and eax, ~(1 << 31)
mov cr0, eax
mov cr3, edi
mov ecx, 0xC000080
rdmsr
or eax, 1 << 8
wrmsr
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
retf
section .data
align 16
global multiboot_header
multiboot_header: dq 0
global multiboot_magic
multiboot_magic: dq 0
section .bss
global pml4
align 4096
pml4: resq 512
|