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
|
#include "types.h"
#include "multiboot.h"
extern void addr_phys;
extern void addr_virt;
extern void addr_virt_end;
extern void addr_load_virt;
extern void addr_load_virt_end;
extern void entry_stack;
extern uint32_t entry_pagedir[];
extern uint32_t entry_pagetable_low[];
extern uint32_t entry_pagetable_high[];
extern void main();
asm(
".globl entry\n"
"entry:\n"
"mov $entry_stack_top, %esp\n"
"push %ebx\n"
"push %eax\n"
"call entry_main\n"
);
void entry_serial_out(char* str);
void entry_serial_out_hex(uint32_t x);
void entry_main(uint32_t mb_magic, multiboot_info* mb_info) {
entry_serial_out("entry_main()\n");
if(mb_magic != 0x2badb002) {
entry_serial_out("Multiboot magic word is wrong!\n");
goto stop;
}
entry_serial_out("Multiboot ok\n");
// TODO: Copy multiboot information.
entry_serial_out("Flags: ");
entry_serial_out_hex(mb_info->flags);
if(mb_info->flags & (1 << 2)) {
entry_serial_out(mb_info->cmdline);
entry_serial_out("\n");
} else {
entry_serial_out("No cmdline.\n");
}
// Create initial page tables.
for(unsigned int i = 0; i < 1024; i++) {
// Clear page directory.
entry_pagedir[i] = 0;
// Identity mapping of the current code.
entry_pagetable_low[i] = ((uint32_t)&addr_phys & 0xffc00000) | (i << 12) | 0x003;
// Map kernelspace.
if((i << 12) < ((uint32_t)&addr_virt_end & 0x003fffff)) {
entry_pagetable_high[i] = ((uint32_t)&addr_load_virt + (i << 12)) | 0x003;
} else {
entry_pagetable_high[i] = 0;
}
}
entry_pagedir[(uint32_t)&addr_phys >> 22] = (uint32_t)&entry_pagetable_low | 0x003;
entry_pagedir[(uint32_t)&addr_virt >> 22] = (uint32_t)&entry_pagetable_high | 0x003;
// Mapping stack to top without creating another page directory.
entry_pagetable_high[1023] = (uint32_t)&entry_stack | 0x003;
entry_pagedir[1023] = (uint32_t)&entry_pagetable_high | 0x003;
// Enable paging.
asm volatile(
"mov %0, %%cr3\n"
"mov %%cr0, %0\n"
"or $0x80000000, %0\n"
"mov %0, %%cr0\n"
: : "r" (&entry_pagedir) : "%0"
);
// TODO: Check that segments are loaded and mapped right.
// Call main() in virtual memory.
asm volatile("mov $0, %esp");
main();
stop:
entry_serial_out("Halting.\n");
asm volatile(
"cli\n"
"hlt\n"
);
while(1);
}
#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port));
void entry_serial_out(char* str) {
while(*str) {
if(*str == '\n') {
outb(0x3f8, '\r');
}
outb(0x3f8, *str++);
}
}
void entry_serial_out_hex(uint32_t x) {
char str[] = "00000000\n";
for(int i = 0; i < 8; i++) {
int z = (x >> (28 - i * 4)) & 0xf;
str[i] = z < 10 ? '0' + z : 'a' - 10 + z;
}
entry_serial_out(str);
}
|