Boot framework rework (#45)
[lunaix-os.git] / lunaix-os / arch / x86 / boot / mb_parser.c
1 #define __BOOT_CODE__
2
3 #include <lunaix/boot_generic.h>
4 #include <lunaix/generic/bootmem.h>
5
6 #include <sys/boot/bstage.h>
7 #include <sys/boot/multiboot.h>
8 #include <sys/mm/mempart.h>
9
10 #include <klibc/string.h>
11
12 #define MEM_1M      0x100000UL
13
14 static void
15 mb_parse_cmdline(struct boot_handoff* bhctx, char* cmdline)
16 {
17     size_t slen;
18     char* cmd;
19     
20     slen = strlen(cmdline);
21     if (!slen) {
22         return;
23     }
24
25     cmd = bootmem_alloc(slen + 1);
26     strncpy(cmd, cmdline, slen);
27
28     bhctx->kexec.len = slen;
29     bhctx->kexec.cmdline = cmd;
30 }
31
32 static void
33 mb_parse_mmap(struct boot_handoff* bhctx,
34               struct multiboot_info* mb)
35 {
36     struct multiboot_mmap_entry *mb_mmap, *mb_mapent;
37     size_t mmap_len;
38     struct boot_mmapent *bmmap, *bmmapent;
39
40     mb_mmap = (struct multiboot_mmap_entry*)__ptr(mb->mmap_addr);
41     mmap_len = mb->mmap_length / sizeof(*mb_mmap);
42
43     bmmap = bootmem_alloc(sizeof(*bmmap) * mmap_len);
44     
45     for (size_t i = 0; i < mmap_len; i++) {
46         mb_mapent = &mb_mmap[i];
47         bmmapent  = &bmmap[i];
48     
49         if (mb_mapent->type == MULTIBOOT_MEMORY_AVAILABLE) 
50         {
51             bmmapent->type = BOOT_MMAP_FREE;
52         } 
53
54         else if (mb_mapent->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) 
55         {
56             bmmapent->type = BOOT_MMAP_RCLM;
57         } 
58
59         else {
60             bmmapent->type = BOOT_MMAP_RSVD;
61         }
62
63         bmmapent->start = mb_mapent->addr_low;
64         bmmapent->size = mb_mapent->len_low;
65     }
66
67     bhctx->mem.size = (mb->mem_upper << 10) + MEM_1M;
68     bhctx->mem.mmap = bmmap;
69     bhctx->mem.mmap_len = mmap_len;
70 }
71
72 static void
73 mb_parse_mods(struct boot_handoff* bhctx,
74               struct multiboot_info* mb)
75 {
76     if (!mb->mods_count) {
77         bhctx->mods.mods_num = 0;
78         return;
79     }
80
81     struct boot_modent* modents;
82     struct multiboot_mod_list* mods, *mod;
83     size_t name_len;
84     char* mod_name, *cmd;
85
86     mods = (struct multiboot_mod_list*)__ptr(mb->mods_addr);
87     modents = bootmem_alloc(sizeof(*modents) * mb->mods_count);
88
89     for (size_t i = 0; i < mb->mods_count; i++) {
90         mod = &mods[i];
91         cmd = (char*)__ptr(mod->cmdline);
92         name_len = strlen(cmd);
93         mod_name = bootmem_alloc(name_len + 1);
94
95         modents[i] = (struct boot_modent){ 
96             .start = mod->mod_start,
97             .end = mod->mod_end,
98             .str = mod_name 
99         };
100
101         strncpy(mod_name, cmd, name_len);
102     }
103
104     bhctx->mods.mods_num = mb->mods_count;
105     bhctx->mods.entries = modents;
106 }
107
108 static void
109 mb_prepare_hook(struct boot_handoff* bhctx)
110 {
111     // nothing to do
112 }
113
114 static void
115 mb_release_hook(struct boot_handoff* bhctx)
116 {
117     // nothing to do
118 }
119
120 void
121 mb_parse(struct boot_handoff* bhctx)
122 {
123     struct multiboot_info* mb;
124     
125     mb = (struct multiboot_info*)__multiboot_addr;
126
127     /* Parse memory map */
128     if ((mb->flags & MULTIBOOT_INFO_MEM_MAP)) {
129         mb_parse_mmap(bhctx, mb);
130     }
131
132     /* Parse cmdline */
133     if ((mb->flags & MULTIBOOT_INFO_CMDLINE)) {
134         mb_parse_cmdline(bhctx, (char*)__ptr(mb->cmdline));
135     }
136
137     /* Parse sys modules */
138     if ((mb->flags & MULTIBOOT_INFO_MODS)) {
139         mb_parse_mods(bhctx, mb);
140     }
141
142     bhctx->prepare = mb_prepare_hook;
143     bhctx->release = mb_release_hook;
144 }