]> git.dujemihanovic.xyz Git - nameless-os.git/blob - boot/x86/stage3/paging.c
Load ELF kernel instead of flat binary
[nameless-os.git] / boot / x86 / stage3 / paging.c
1 /* Code for enabling paging */
2
3 #include <stdint.h>
4 #include <paging.h>
5
6 /* Preallocated page tables. */
7 static uint32_t page_directory[1024] __attribute__((aligned(4096))) __attribute__((section(".data")));
8 static uint32_t page_table_firstmb[1024] __attribute__((aligned(4096))) __attribute__((section(".data")));
9 static uint32_t page_table_kernel[1024] __attribute__((aligned(4096))) __attribute__((section(".data")));
10
11 void enable_paging()
12 {
13 int cr3;
14 asm ("mov %0, %%cr3": : "a" (page_directory));
15 asm ("mov %%cr0, %0": "=a" (cr3));
16 cr3 |= 0x80000000;
17 asm ("mov %0, %%cr0": : "a" (cr3));
18 }
19
20 int map_address(void *physical, void *virtual, int flags)
21 {
22 if ((uint32_t) physical & 0xfff || (uint32_t) virtual & 0xfff)
23 return ADDRESS_NOT_ALIGNED;
24
25 uint32_t pdir_index = (uint32_t) virtual >> 22;
26 if (pdir_index != 0 && pdir_index != 0x300)
27 return INVL_ADDRESS;
28
29 uint32_t ptbl_index = ((uint32_t) virtual >> 12) & 0x3ff;
30 switch (pdir_index) {
31 case 0:
32 if (page_table_firstmb[ptbl_index] & 1 == 1)
33 return ADDRESS_ALREADY_MAPPED;
34 page_table_firstmb[ptbl_index] = ((uint32_t) physical & ~0xfff) | (flags & 0xfff) | 1;
35 break;
36 case 0x300:
37 if (page_table_kernel[ptbl_index] & 1 == 1)
38 return ADDRESS_ALREADY_MAPPED;
39 page_table_kernel[ptbl_index] = ((uint32_t) physical & ~0xfff) | (flags & 0xfff) | 1;
40 }
41
42 return 0;
43 }
44
45 int map_range(void *phys_start, void *phys_end, void *virt_start, void *virt_end, int flags)
46 {
47 if ((uint32_t) phys_start & 0xfff || (uint32_t) phys_end & 0xfff ||
48 (uint32_t) virt_start & 0xfff || (uint32_t) virt_end & 0xfff)
49 return ADDRESS_NOT_ALIGNED;
50
51 if ((uint32_t) phys_end - (uint32_t) phys_start != (uint32_t) virt_end - (uint32_t) virt_start)
52 return ADDRESS_RANGE_MISMATCHED;
53
54 int loops = ((uint32_t) phys_end - (uint32_t) phys_start) / 4096;
55 for (int i=0; i<loops; i++) {
56 int ret = map_address(phys_start + i*4096, virt_start + i*4096, flags);
57 if (ret)
58 return ret;
59 }
60 return 0;
61 }
62
63 void set_up_page_directory()
64 {
65 page_directory[0] = (uint32_t) page_table_firstmb | 3;
66 page_directory[0x300] = (uint32_t) page_table_kernel | 3;
67 }