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
|
#include "kernel.h"
#include "paging.h"
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_copy_multiboot(multiboot_info_t* mb_info);
void entry_main(uint32_t mb_magic, multiboot_info_t* mb_info) {
if(mb_magic != 0x2badb002) {
goto stop;
}
entry_copy_multiboot(mb_info);
// 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) | P1_P | P1_W;
// Map kernelspace.
if((i << 12) < ((uint32_t)&addr_virt_end & 0x003fffff)) {
entry_pagetable_high[i] = ((uint32_t)&addr_load_virt + (i << 12)) | P1_P | P1_W | P1_G;
} else {
entry_pagetable_high[i] = 0;
}
}
entry_pagetable_high[((uint32_t)&multiboot_info & 0x003ff000) >> 12] = (uint32_t)&entry_multiboot | P1_P | P1_W | P1_G;
entry_pagedir[(uint32_t)&addr_phys >> 22] = (uint32_t)&entry_pagetable_low | P2_P | P2_W;
entry_pagedir[(uint32_t)&addr_virt >> 22] = (uint32_t)&entry_pagetable_high | P2_P | P2_W | P2_G;
// Map map_p1.
entry_pagedir[1022] = (uint32_t)&entry_pagedir | P2_P | P2_W | P2_G;
// Mapping stack to top without creating another page directory.
entry_pagetable_low[1023] = (uint32_t)&entry_stack | P1_P | P1_W | P1_G;
entry_pagedir[1023] = (uint32_t)&entry_pagetable_low | P2_P | P2_W | P2_G;
// 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 $stack_top, %esp");
main();
stop:
asm volatile(
"cli\n"
"hlt\n"
);
while(1);
}
#define memcpy(source, target, size) asm volatile( \
"cld\n" \
"rep movsd\n" \
:: "S" (source), "D" (target), "c" (size / 4) \
: "flags", "memory")
unsigned int strcpy(char* source, char* target) {
unsigned int i = 0;
while(*source) {
*target++ = *source++;
i++;
}
*target = 0;
return i + 1;
}
void entry_copy_multiboot(multiboot_info_t* mb_info) {
// Copy multiboot structure.
memcpy(mb_info, &entry_multiboot, sizeof(multiboot_info_t));
uint32_t low_p = (uint32_t)&entry_multiboot + sizeof(multiboot_info_t);
uint32_t high_p = (uint32_t)&multiboot_info + sizeof(multiboot_info_t);
// Copy module structures.
memcpy(mb_info->mods_addr, low_p, mb_info->mods_count * sizeof(multiboot_module_t));
entry_multiboot.mods_addr = (multiboot_module_t*)high_p;
multiboot_module_t* mods_addr = (multiboot_module_t*)low_p;
low_p += mb_info->mods_count * sizeof(multiboot_module_t);
high_p += mb_info->mods_count * sizeof(multiboot_module_t);
// Copy strings.
unsigned int s;
s = strcpy(entry_multiboot.cmdline, (char*)low_p);
entry_multiboot.cmdline = (char*)high_p;
low_p += s;
high_p += s;
for(unsigned int i = 0; i < entry_multiboot.mods_count; i++) {
s = strcpy(mods_addr[i].string, (char*)low_p);
mods_addr[i].string = (char*)high_p;
low_p += s;
high_p += s;
}
}
|