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