Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
voxmo.c
Go to the documentation of this file.
1#include "hal/cpu/paging.h"
2#include "libk/debug/debug.h"
4#include "libk/serial.h"
5#include "memory/kalloc.h"
8#include "memory/vm_manager.h"
10#include "procc/workqueue.h"
11#include "vfs/enum.h"
12#include <modules/voxmo.h>
13#include <str.h>
14#include <string.h>
15#include <type.h>
16#include <vector.h>
17#include <vfs/dentry.h>
18#include <vfs/vnode.h>
19
23
26 auto curr_module = voxmo_modules;
27 while (curr_module != NULL) {
28 if (stringcmp(curr_module->name, name)) {
30 return curr_module;
31 }
32 curr_module = curr_module->next;
33 }
35 LOG2_ERROR("VOXMO", "module %s not found", name->c_str);
36 return nullptr;
37}
38
40 spin_acquire(&module->lock);
41 if (module->loaded) {
42 spin_release(&module->lock);
43 LOG_INFO("VOXMO", "module %s already loaded",
44 module->name->c_str);
45 return;
46 }
47
48 uint8_t* data = (uint8_t*)module->main_data;
49 size_t loaded_size = elf_count_load_size(data);
50 LOG_INFO("VOXMO", "loaded size %d (%d kb)", loaded_size,
51 loaded_size / 1024);
52
53 size_t size_4k = ALIGN_UP(1 + loaded_size, BLOCK_SIZE) / BLOCK_SIZE;
56 LOG_INFO("VOXMO", "base addr : 0x%x", base_addr);
57
58 Elf64_Ehdr ehdr;
59 memcopy(&ehdr, (void*)data, sizeof(Elf64_Ehdr));
60
61 if (ehdr.e_type != ET_DYN) {
62 spin_release(&module->lock);
63 LOG2_ERROR("VOXMO", "not shared library");
64 return;
65 }
66
67 elf_section_map sh_map = {0};
68 elf_section_map_all(data, &sh_map);
69
70 auto kernel_page = paging_get_highest_page_map();
71
72 struct elf_load_mmap_table* mmap_table =
74 sizeof(struct elf_load_mmap_table) * ehdr.e_phnum);
75
76 elf_load(kernel_page, data, base_addr, base_addr, mmap_table);
77
78 symbols_ptr_vector_t voxmo_load_syms;
79 vector_init(&voxmo_load_syms);
80 vector_push_back(&voxmo_load_syms, kernel_get_symbols());
81 LOG_INFO("VOXMO", "voxmo load external symbol count %d",
82 voxmo_load_syms.size);
83 for (size_t i = 0; i < voxmo_load_syms.size; i++) {
84 LOG_INFO("VOXMO", "external symbol [%d] name %s, item count %d",
85 i, voxmo_load_syms.data[i]->name,
86 voxmo_load_syms.data[i]->items.size);
87 }
88
89 GnuHashHeader gnu_hash;
90 Elf64_Shdr* gnu_hash_sym = sh_map.gnuhash;
91 elf_gnu_hash_parse(&gnu_hash, gnu_hash_sym, data);
92
94 if (dyn) {
95 LOG_INFO("VOXMO", "dynamic section found at 0x%x", dyn);
96 elf_dynamic_map dyn_map = {0};
97 elf_dyn_map_all(dyn, data, &dyn_map);
98
99 LOG_INFO("VOXMO", "strtab found at 0x%x", dyn_map.strtab);
100 LOG_INFO("VOXMO", "needed size %d", dyn_map.needed.size);
101
102 /*
103 * Pass mmap_table + phnum so elf_relocate_dyn can resolve
104 * r_offset to the correct kernel VA per segment.
105 * Relocation must complete before mmap_table is freed.
106 */
107 elf_relocate_dyn(&dyn_map, base_addr, base_addr, &gnu_hash,
108 &voxmo_load_syms, mmap_table, ehdr.e_phnum);
109 }
110
112
113 uintptr_t load_addr =
114 elf_find_symbol("load", &gnu_hash, base_addr, &sh_map, data);
115 LOG_INFO("VOXMO", "load : 0x%x", load_addr);
116
117 /*
118 * mmap_table is only needed during load + relocation.
119 * Free it now before we proceed to workqueue setup.
120 */
121 kfree2(mmap_table);
122
123 if (!load_addr) {
124 LOG2_ERROR("VOXMO", "load symbol not found in module %s",
125 module->name->c_str);
126 spin_release(&module->lock);
127 return;
128 }
129
130 /* Build dependency workqueue list */
131 vector(workqueue_ptr_t)* dependency_workqueue =
133 vector_init(dependency_workqueue);
134
135 for (size_t i = 0; i < module->dependency_count; i++) {
136 voxmo_loaded_module_t_ptr dep_module =
137 vxGetVoxmoModule(module->dependency[i]);
138
139 if (!dep_module) {
140 LOG2_ERROR("VOXMO",
141 "dependency module %s not found, "
142 "aborting load of %s",
143 module->dependency[i]->c_str,
144 module->name->c_str);
145 kfree2(dependency_workqueue);
146 spin_release(&module->lock);
147 return;
148 }
149
150 if (!dep_module->loaded || !dep_module->queue) {
151 LOG2_ERROR("VOXMO",
152 "dependency %s not ready (loaded=%d, "
153 "queue=0x%x), aborting load of %s",
154 dep_module->name->c_str, dep_module->loaded,
155 dep_module->queue, module->name->c_str);
156 kfree2(dependency_workqueue);
157 spin_release(&module->lock);
158 return;
159 }
160
161 vector_push_back(dependency_workqueue, dep_module->queue);
162 LOG_INFO("VOXMO", "dependency %s added to queue 0x%x",
163 dep_module->name->c_str, dep_module->queue);
164 }
165
166 LOG_INFO("VOXMO", "dependency workqueue size %d",
167 dependency_workqueue->size);
168
169 void (*load_fn)(void*) = (void (*)(void*))(void*)load_addr;
170 auto queue = vxAddWorkqueueTask(load_fn, nullptr, dependency_workqueue);
171 module->queue = queue;
172 module->loaded = true;
173
174 LOG_INFO("VOXMO", "module %s task created, queue=0x%x",
175 module->name->c_str, module->queue);
176
177 spin_release(&module->lock);
178}
179
180void vxVoxmoInstall(const char* path) {
181
183 kstring full_path_with_ext = str_concat(full_path, ".voxmo");
184 str_release(full_path);
185
186 LOG_INFO("VOXMO", "installing module from %s",
187 full_path_with_ext->c_str);
188
189 dentry_ptr dentry = 0;
190 if (resolve_dentry(full_path_with_ext->c_str, 0, &dentry, 0) !=
191 VFS_OK) {
192 LOG2_ERROR("VOXMO", "module %s not found", path);
193 str_release(full_path_with_ext);
194 return;
195 }
196
197 size_t file_size = dentry->vnode->size;
198 uint8_t* data = kalloc(file_size);
199 LOG_INFO("VOXMO", "allocated at 0x%x for size %d kb", data,
200 file_size / 1024);
201
202 auto a = ((vops_file_t*)dentry->vnode->ops)
203 ->read(dentry->vnode, data, file_size, 0);
204 if (a < 0) {
205 LOG2_ERROR("VOXMO", "failed to read module %s", path);
206 kfree(data, file_size);
207 str_release(full_path_with_ext);
208 return;
209 }
210
212
214 (voxmo_loaded_module_t_ptr)kalloc(sizeof(voxmo_loaded_module_t));
215 memset(module, 0, sizeof(*module));
216 module->next = nullptr;
217 module->lock = (spinlock_t){0};
218
221 char* module_name = (char*)((uintptr_t)data + header->nama_module.pos);
222 module->name = str(module_name);
223
224 str_trim(module->name);
225 module->path = full_path_with_ext;
226 module->loaded = false;
227 module->queue = nullptr;
228
229 char* main_file = (char*)((uintptr_t)data + header->main_file.pos);
230 LOG_INFO("VOXMO", "main file %s", main_file);
231
232 uint16_t cap_count = header->capability.count;
233 struct voxmo_metadata_string* cap_array =
235 header->capability.pos);
236
237 module->capability_count = cap_count;
238 module->capability = (kstring*)kalloc(sizeof(kstring) * cap_count);
239
240 for (uint16_t i = 0; i < cap_count; i++) {
241 struct voxmo_metadata_string* cap = &cap_array[i];
242 char* cap_name = (char*)((uintptr_t)data + cap->pos);
243 LOG_INFO("VOXMO", "capability name %s", cap_name);
244 module->capability[i] = str(cap_name);
245 }
246
247 module->dependency_count = header->dependency.count;
248 module->dependency =
249 (kstring*)kalloc(sizeof(kstring) * module->dependency_count);
250
251 uint16_t dep_count = header->dependency.count;
252 LOG_INFO("VOXMO", "dependency count %d", dep_count);
253 struct voxmo_metadata_string* dep_array =
255 header->dependency.pos);
256 for (uint16_t i = 0; i < dep_count; i++) {
257 struct voxmo_metadata_string* dep = &dep_array[i];
258 char* dep_name = (char*)((uintptr_t)data + dep->pos);
259 LOG_INFO("VOXMO", "dependency name %s", dep_name);
260 module->dependency[i] = str(dep_name);
261 }
262
263 boolean_t main_found = false;
264 for (uint32_t i = 0; i < header->file_counts; i++) {
265 struct voxmo_metadata_file* file =
266 (struct voxmo_metadata_file*)(data + header->header_len +
267 i * sizeof(struct voxmo_metadata_file));
268
269 char* file_name =
270 (char*)((uintptr_t)data + file->nama_file.pos);
271 LOG_INFO("VOXMO", "file name %s", file_name);
272 LOG_INFO("VOXMO", "main file found at offset 0x%x, size %d",
273 file->offset, file->size);
274
275 if (strncmp(file_name, main_file, header->main_file.length) ==
276 0) {
277 uint8_t* main_data = (uint8_t*)kalloc(file->size);
278 LOG_INFO("VOXMO", "main data buffer allocated at 0x%x",
279 main_data);
280 memset(main_data, 0, file->size);
281 memcopy((void*)main_data, (void*)(data + file->offset),
282 file->size);
283 module->main_data = (uintptr_t)main_data;
284
285 main_found = true;
286 break;
287 }
288 }
289
290 if (!main_found) {
291 LOG2_ERROR("VOXMO", "main file not found");
292 str_release(module->name);
293 str_release(module->path);
294 kfree(module, sizeof(voxmo_loaded_module_t));
295 kfree(data, file_size);
296 return;
297 }
298
300 auto curr_module = voxmo_modules;
301 if (!curr_module) {
302 voxmo_modules = module;
303 } else {
304 while (curr_module->next != nullptr) {
305 curr_module = curr_module->next;
306 }
307 curr_module->next = module;
308 }
310
311 KDEBUG(DEBUG_LEVEL_OK, "module %s installed\n", module->name->c_str);
312 LOG_INFO("VOXMO", "module %s installed", module->name->c_str);
313
314 kfree(data, file_size);
315}
316
318
320 LOG_INFO("VOXMO", "probing module %s", name->c_str);
322 if (!module) {
323 LOG2_ERROR("VOXMO", "module %s not found", name->c_str);
324 return;
325 }
326
327 if (module->loaded) {
328 LOG_INFO("VOXMO", "module %s already loaded", name->c_str);
329 return;
330 }
331
332 if (module->dependency_count) {
333 for (size_t i = 0; i < module->dependency_count; i++) {
334 LOG_INFO("VOXMO", "dependency %s",
335 module->dependency[i]->c_str);
336 vxVoxmoProbe(module->dependency[i]);
337 }
338 }
339
340 proccess_elf(module);
341 LOG_INFO("VOXMO", "module %s loaded", module->name->c_str);
342}
343
348
349 while (m != nullptr) {
350 if (!m->loaded) {
351 LOG_INFO("VOXMO", "load module %s", m->name->c_str);
352 vxVoxmoProbe(m->name);
353 }
354
356 m = m->next;
358 }
359 LOG_INFO("VOXMO", "all module reloaded");
360}
struct SDT header
Definition acpi.h:0
@ DEBUG_LEVEL_OK
Definition debug.h:11
#define KDEBUG(...)
Definition debug.h:16
kstring name
Definition dentry.h:5
struct dentry * dentry_ptr
Definition dentry.h:20
void dentry_put(dentry_ptr dentry)
Definition dentry.c:72
int resolve_dentry(char *path, dentry_ptr parent, dentry_ptr *out, uint8_t flag)
Resolves a path to a directory entry (dentry) with configurable start point and strictness.
volatile uint32_t cap
Definition ehci.hpp:2
void elf_section_map_all(uint8_t *data, elf_section_map *map)
Definition elf.c:160
size_t elf_load(volatile uintptr_t *page, uint8_t *data, uintptr_t temporary_base, uintptr_t base, struct elf_load_mmap_table *table)
Definition elf.c:261
uintptr_t elf_find_symbol(const char *name, GnuHashHeader *gnuhash, uintptr_t base, elf_section_map *map, uint8_t *data)
Definition elf.c:730
void elf_gnu_hash_parse(GnuHashHeader *gnu_hash, Elf64_Shdr *gnu_hash_sym, uint8_t *data)
Definition elf.c:604
void elf_call_init_array(elf_section_map *map, uintptr_t base)
Definition elf.c:680
void elf_dyn_map_all(Elf64_Dyn *dyn, uint8_t *data, elf_dynamic_map *map)
Definition elf.c:60
Elf64_Dyn * elf_get_phdr_dynamic(uint8_t *data)
Definition elf.c:45
void elf_relocate_dyn(elf_dynamic_map *map, uintptr_t kernel_base, uintptr_t user_base, GnuHashHeader *gnu_hash, symbols_ptr_vector_t *external_syms, struct elf_load_mmap_table *table, int table_count)
Definition elf.c:534
uintptr_t elf_count_load_size(uint8_t *data)
Definition elf.c:629
@ ET_DYN
Definition elf.h:208
a
Definition entry.h:6
@ VFS_OK
Definition enum.h:5
struct fs_data data
Definition filesystem.h:1
void kfree(void *ptr, size_t size)
void * kalloc(size_t size)
void kfree2(void *ptr)
symbols_ptr kernel_get_symbols()
#define ALIGN_UP(x, align)
Definition memory_utils.h:6
page_t paging_get_highest_page_map(void)
Definition paging.c:463
uint64_t base_addr
Definition pcie.h:0
#define BLOCK_SIZE
#define LOG2_ERROR(mod, fmt,...)
Definition serial.h:38
#define LOG_INFO(mod, fmt,...)
Definition serial.h:20
void spin_acquire(spinlock_t *lock)
Definition spinlock.c:8
void spin_release(spinlock_t *lock)
Definition spinlock.c:19
int strncmp(const char *s1, const char *s2, size_t n)
void memset(void *ptr, int value, size_t num)
void memcopy(void *dest, void *src, size_t size)
boolean_t stringcmp(kstring s1, kstring s2)
void str_release(kstring str)
void str_trim(kstring str)
kstring str_concat(kstring s, const char *suffix)
kstring str(const char *str)
uint16_t e_type
Definition elf.h:24
uint16_t e_phnum
Definition elf.h:33
struct vnode * vnode
Definition dentry.h:33
uint8_t * strtab
Definition elf.h:266
struct vector_uint64_t needed
Definition elf.h:267
Elf64_Shdr * gnuhash
Definition elf.h:283
Definition file.h:16
char * c_str
Definition string.h:12
struct vector_symbols_item items
Definition symbols.h:16
const char * name
Definition symbols.h:15
symbols_ptr * data
Definition symbols.h:19
size_t size
Definition elf.h:263
void * ops
Definition vnode.h:64
size_t size
Definition vnode.h:63
struct voxmo_metadata_string main_file
Definition voxmo.h:32
struct vector_symbols_ptr symbols_ptr_vector_t
Definition symbols.h:20
#define NULL
Definition type.h:76
unsigned short uint16_t
Definition type.h:13
unsigned int uint32_t
Definition type.h:19
uint8_t boolean_t
Definition type.h:89
unsigned long uintptr_t
Definition type.h:73
unsigned long uint64_t
Definition type.h:25
unsigned char uint8_t
Definition type.h:7
#define vector_push_back(v, val)
Definition vector.h:45
#define vector(T)
Definition vector.h:11
#define vector_init(v)
Definition vector.h:20
uintptr_t vma_lookup_free_vaddr(struct virtual_memory_page *page, mem_vma_region region, size_t size)
Definition vm_manager.c:156
struct virtual_memory_page * get_kernel_vmm_page()
@ VMA_REGION_KMODULE
Definition vm_manager.h:16
static void vxVoxmoProbe(kstring name)
Definition voxmo.c:319
static void proccess_elf(voxmo_loaded_module_t_ptr module)
Definition voxmo.c:39
static voxmo_loaded_module_t_ptr voxmo_modules
Definition voxmo.c:21
void vxVoxmoInstall(const char *path)
Definition voxmo.c:180
static kstring default_voxmo_path
Definition voxmo.c:20
void vxSetDefaultVoxmoPath(const char *path)
Definition voxmo.c:317
static voxmo_loaded_module_t_ptr vxGetVoxmoModule(kstring name)
Definition voxmo.c:24
static spinlock_t voxmo_list_lock
Definition voxmo.c:22
void vxVoxmoReload()
Definition voxmo.c:344
voxmo_loaded_module_t * voxmo_loaded_module_t_ptr
Definition voxmo.h:60
workqueue_t * queue
Definition voxmo.h:9
kstring path
Definition voxmo.h:7
uintptr_t main_data
Definition voxmo.h:6
workqueue_t * vxAddWorkqueueTask(void(*task)(void *), void *arg, struct vector_workqueue_ptr_t *dependency)
Definition workqueue.c:84
struct workqueue * workqueue_ptr_t
Definition workqueue.h:7