optimize the menuconfig redrawing
[lunaix-os.git] / lunaix-os / arch / x86 / boot / mb_parser.c
1 #define __BOOT_CODE__
2
3 #include <lunaix/boot_generic.h>
4 #include <sys/boot/bstage.h>
5 #include <sys/boot/multiboot.h>
6 #include <sys/mm/mempart.h>
7
8 #define BHCTX_ALLOC 4096
9 #define MEM_1M      0x100000UL
10
11
12 u8_t bhctx_buffer[BHCTX_ALLOC] boot_bss;
13
14 #define check_buffer(ptr)                                                      \
15     if ((ptr) >= ((ptr_t)bhctx_buffer + BHCTX_ALLOC)) {                        \
16         asm("ud2");                                                            \
17     }
18
19 size_t boot_text
20 mb_memcpy(u8_t* destination, u8_t* base, unsigned int size)
21 {
22     unsigned int i = 0;
23     for (; i < size; i++) {
24         *(destination + i) = *(base + i);
25     }
26     return i;
27 }
28
29 size_t boot_text
30 mb_strcpy(char* destination, char* base)
31 {
32     int i = 0;
33     char c = 0;
34     while ((c = base[i])) {
35         destination[i] = c;
36         i++;
37     }
38
39     destination[++i] = 0;
40
41     return i;
42 }
43
44 size_t boot_text
45 mb_strlen(char* s)
46 {
47     int i = 0;
48     while (s[i++])
49         ;
50     return i;
51 }
52
53 size_t boot_text
54 mb_parse_cmdline(struct boot_handoff* bhctx, void* buffer, char* cmdline)
55 {
56 #define SPACE ' '
57
58     size_t slen = mb_strlen(cmdline);
59
60     if (!slen) {
61         return 0;
62     }
63
64     mb_memcpy(buffer, (u8_t*)cmdline, slen);
65     bhctx->kexec.len = slen;
66     bhctx->kexec.cmdline = buffer;
67
68     return slen;
69 }
70
71 size_t boot_text
72 mb_parse_mmap(struct boot_handoff* bhctx,
73               struct multiboot_info* mb,
74               void* buffer)
75 {
76     struct multiboot_mmap_entry* mb_mmap =
77       (struct multiboot_mmap_entry*)__ptr(mb->mmap_addr);
78     size_t mmap_len = mb->mmap_length / sizeof(struct multiboot_mmap_entry);
79
80     struct boot_mmapent* bmmap = (struct boot_mmapent*)buffer;
81     for (size_t i = 0; i < mmap_len; i++) {
82         struct boot_mmapent* bmmapent = &bmmap[i];
83         struct multiboot_mmap_entry* mb_mapent = &mb_mmap[i];
84
85         if (mb_mapent->type == MULTIBOOT_MEMORY_AVAILABLE) {
86             bmmapent->type = BOOT_MMAP_FREE;
87         } else if (mb_mapent->type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) {
88             bmmapent->type = BOOT_MMAP_RCLM;
89         } else {
90             bmmapent->type = BOOT_MMAP_RSVD;
91         }
92
93         bmmapent->start = mb_mapent->addr_low;
94         bmmapent->size = mb_mapent->len_low;
95     }
96
97     bhctx->mem.size = (mb->mem_upper << 10) + MEM_1M;
98     bhctx->mem.mmap = bmmap;
99     bhctx->mem.mmap_len = mmap_len;
100
101     return mmap_len * sizeof(struct boot_mmapent);
102 }
103
104 size_t boot_text
105 mb_parse_mods(struct boot_handoff* bhctx,
106               struct multiboot_info* mb,
107               void* buffer)
108 {
109     if (!mb->mods_count) {
110         bhctx->mods.mods_num = 0;
111         return 0;
112     }
113
114     struct boot_modent* modents = (struct boot_modent*)buffer;
115     struct multiboot_mod_list* mods = 
116         (struct multiboot_mod_list*)__ptr(mb->mods_addr);
117
118     ptr_t mod_str_ptr = __ptr(&modents[mb->mods_count]);
119
120     for (size_t i = 0; i < mb->mods_count; i++) {
121         struct multiboot_mod_list* mod = &mods[i];
122         modents[i] = (struct boot_modent){ .start = mod->mod_start,
123                                            .end = mod->mod_end,
124                                            .str = (char*)mod_str_ptr };
125                                            
126         mod_str_ptr += mb_strcpy((char*)mod_str_ptr, 
127                                  (char*)__ptr(mod->cmdline));
128     }
129
130     bhctx->mods.mods_num = mb->mods_count;
131     bhctx->mods.entries = modents;
132
133     return mod_str_ptr - (ptr_t)buffer;
134 }
135
136 void boot_text
137 mb_prepare_hook(struct boot_handoff* bhctx)
138 {
139     // nothing to do
140 }
141
142 void boot_text
143 mb_release_hook(struct boot_handoff* bhctx)
144 {
145     // nothing to do
146 }
147
148 #define align_addr(addr) (((addr) + (sizeof(ptr_t) - 1)) & ~(sizeof(ptr_t) - 1))
149
150 struct boot_handoff* boot_text
151 mb_parse(struct multiboot_info* mb)
152 {
153     struct boot_handoff* bhctx = (struct boot_handoff*)bhctx_buffer;
154     ptr_t bhctx_ex = (ptr_t)&bhctx[1];
155     
156     *bhctx = (struct boot_handoff){ };
157
158     /* Parse memory map */
159     if ((mb->flags & MULTIBOOT_INFO_MEM_MAP)) {
160         bhctx_ex += mb_parse_mmap(bhctx, mb, (void*)bhctx_ex);
161         bhctx_ex = align_addr(bhctx_ex);
162     }
163
164     /* Parse cmdline */
165     if ((mb->flags & MULTIBOOT_INFO_CMDLINE)) {
166         bhctx_ex +=
167           mb_parse_cmdline(bhctx, (void*)bhctx_ex, (char*)__ptr(mb->cmdline));
168         bhctx_ex = align_addr(bhctx_ex);
169     }
170
171     /* Parse sys modules */
172     if ((mb->flags & MULTIBOOT_INFO_MODS)) {
173         bhctx_ex += mb_parse_mods(bhctx, mb, (void*)bhctx_ex);
174         bhctx_ex = align_addr(bhctx_ex);
175     }
176
177     check_buffer(bhctx_ex);
178
179     bhctx->prepare = mb_prepare_hook;
180     bhctx->release = mb_release_hook;
181
182     return bhctx;
183 }