feat: a better boot command line parser
[lunaix-os.git] / lunaix-os / kernel / boot_helper.c
1 #include <klibc/string.h>
2 #include <lunaix/boot_generic.h>
3 #include <lunaix/mm/page.h>
4 #include <lunaix/mm/pmm.h>
5 #include <lunaix/mm/vmm.h>
6 #include <lunaix/spike.h>
7 #include <lunaix/kcmd.h>
8 #include <sys/mm/mempart.h>
9
10 /**
11  * @brief Reserve memory for kernel bootstrapping initialization
12  *
13  * @param bhctx
14  */
15 void
16 boot_begin(struct boot_handoff* bhctx)
17 {
18     bhctx->prepare(bhctx);
19
20     struct boot_mmapent *mmap = bhctx->mem.mmap, *mmapent;
21     for (size_t i = 0; i < bhctx->mem.mmap_len; i++) {
22         mmapent = &mmap[i];
23         size_t size_pg = PN(ROUNDUP(mmapent->size, PG_SIZE));
24
25         if (mmapent->type == BOOT_MMAP_FREE) {
26             pmm_mark_chunk_free(PN(mmapent->start), size_pg);
27             continue;
28         }
29
30         ptr_t pa = PG_ALIGN(mmapent->start);
31         for (size_t j = 0; j < size_pg && pa < KERNEL_EXEC;
32              j++, pa += PM_PAGE_SIZE) {
33             vmm_set_mapping(VMS_SELF, pa, pa, PG_PREM_RW, VMAP_IGNORE);
34         }
35     }
36
37     /* Reserve region for all loaded modules */
38     for (size_t i = 0; i < bhctx->mods.mods_num; i++) {
39         struct boot_modent* mod = &bhctx->mods.entries[i];
40         pmm_mark_chunk_occupied(KERNEL_PID,
41                                 PN(mod->start),
42                                 CEIL(mod->end - mod->start, PG_SIZE_BITS),
43                                 PP_FGLOCKED);
44     }
45 }
46
47 extern u8_t __kexec_boot_end; /* link/linker.ld */
48
49 /**
50  * @brief Release memory for kernel bootstrapping initialization
51  *
52  * @param bhctx
53  */
54 void
55 boot_end(struct boot_handoff* bhctx)
56 {
57     struct boot_mmapent *mmap = bhctx->mem.mmap, *mmapent;
58     for (size_t i = 0; i < bhctx->mem.mmap_len; i++) {
59         mmapent = &mmap[i];
60         size_t size_pg = PN(ROUNDUP(mmapent->size, PG_SIZE));
61
62         if (mmapent->start >= KERNEL_EXEC || mmapent->type == BOOT_MMAP_FREE) {
63             continue;
64         }
65
66         if (mmapent->type == BOOT_MMAP_RCLM) {
67             pmm_mark_chunk_free(PN(mmapent->start), size_pg);
68         }
69
70         ptr_t pa = PG_ALIGN(mmapent->start);
71         for (size_t j = 0; j < size_pg && pa < KERNEL_EXEC;
72              j++, pa += PM_PAGE_SIZE) {
73             vmm_del_mapping(VMS_SELF, pa);
74         }
75     }
76
77     bhctx->release(bhctx);
78 }
79
80 /**
81  * @brief Clean up the boot stage code and data
82  *
83  */
84 void
85 boot_cleanup()
86 {
87     // clean up
88     for (size_t i = 0; i < (ptr_t)(&__kexec_boot_end); i += PG_SIZE) {
89         vmm_del_mapping(VMS_SELF, (ptr_t)i);
90         pmm_free_page(KERNEL_PID, (ptr_t)i);
91     }
92 }
93
94 void
95 boot_parse_cmdline(struct boot_handoff* bhctx) {
96     if (!bhctx->kexec.len) {
97         return;
98     }
99
100     kcmd_parse_cmdline(bhctx->kexec.cmdline);
101 }