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
|
.set ALIGN, 1<<0
.set MEMINFO, 1<<1
.set VIDEO_MODE, 1<<2
.set FLAGS, VIDEO_MODE|ALIGN | MEMINFO
.set MAGIC, 0x1BADB002
.set CHECKSUM, -(MAGIC + FLAGS)
#.section .multiboot
.align 16, 0
.section .multiboot.data, "aw"
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
# unused(padding)
.long 0,0,0,0,0
# Video mode
.long 0 # Linear graphics
.long 0 # Preferred width
.long 0 # Preferred height
.long 32 # Preferred pixel depth
# Allocate the initial stack.
.section .bootstrap_stack, "aw", @nobits
stack_bottom:
.skip 16384 # 16 KiB
stack_top:
.global boot_page_directory
.global boot_page_table1
.section .bss, "aw", @nobits
.align 4096
boot_page_directory:
.skip 4096
boot_page_table1:
.skip 4096
heap_table:
.skip 4096
.section .multiboot.text, "a"
.global _start
.extern _kernel_end
.type _start, @function
# Kernel entry
_start:
# edi contains the buffer we wish to modify
movl $(boot_page_table1 - 0xC0000000), %edi
# for loop
movl $0, %esi
movl $1024, %ecx
1:
# esi = address
# If we are in kernel range jump to "label 2"
cmpl $_kernel_start, %esi
jl 2f
# If we are past the kernel jump to the final stage
# "label 3"
cmpl $(_kernel_end- 0xC0000000), %esi
jge heap_start
2:
# Add permission to the pages
movl %esi, %edx
orl $0x003, %edx
movl %edx, (%edi)
# Size of page is 4096 bytes.
addl $4096, %esi
# Size of entries in boot_page_table1 is 4 bytes.
addl $4, %edi
# Loop to the next entry if we haven't finished.
loop 1b
heap_start:
# edi contains the buffer we wish to modify
movl $(heap_table - 0xC0000000), %edi
# for loop
movl $1024, %ecx
addl $4096, %esi
heap:
movl %esi, %edx
orl $0x003, %edx
movl %edx, (%edi)
# Size of page is 4096 bytes.
addl $4096, %esi
# Size of entries is 4 bytes.
addl $4, %edi
loop heap
final:
# Map the page table to both virtual addresses 0x00000000 and 0xC0000000.
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
movl $(heap_table - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 769 * 4
# Set cr3 to the address of the boot_page_directory.
movl $(boot_page_directory - 0xC0000000), %ecx
movl %ecx, %cr3
# Enable paging
movl %cr0, %ecx
orl $0x80000000, %ecx
movl %ecx, %cr0
# Jump to higher half with an absolute jump.
lea 4f, %ecx
jmp *%ecx
.size _start, . - _start
.section .text
4:
# At this point, paging is fully set up and enabled.
# Unmap the identity mapping as it is now unnecessary.
movl $0, boot_page_directory + 0
# Reload crc3 to force a TLB flush so the changes to take effect.
movl %cr3, %ecx
movl %ecx, %cr3
# Set up the stack.
mov $stack_top, %esp
# Reset EFLAGS.
pushl $0
popf
pushl %esp
/* Push the pointer to the Multiboot information structure. */
pushl %ebx
/* Push the magic value. */
pushl %eax
mov $_kernel_end, %eax
pushl %eax
# Enter the high-level kernel.
call kernel_main
# Infinite loop if the system has nothing more to do.
cli
1: hlt
jmp 1b
|