#if defined(ENABLE_INITRD) #include #include "device/initrd.h" #include "device/processor.h" #include "object.h" #include "jove.h" #include "bootargs.h" #include "print.h" #include "string.h" #include "panic.h" struct jove_ObjectDirectory s_initrd_dir = { .entries = { [0] = (objdir_entry_t){ .type = KO_OBJECT_DIRECTORY, .data = 1 } } }; static uintptr_t s_initrd_getaddr(char *path); #if defined(__limine__) #include "boot/limine/limine.h" static struct limine_module_request s_module_request = { .id = LIMINE_MODULE_REQUEST }; static uintptr_t s_initrd_getaddr(char *path) { struct limine_module_response *response = s_module_request.response; for(size_t i = 0; i < response->module_count; i++) { struct limine_file *module = response->modules[i]; if(strcmp(path, module->path) == 0) return (uintptr_t)module->address; } kpanic("Failed to load module at path %s\n", path); } #endif static size_t s_tar_oct_dec(const char *oct) { size_t r = 0; for(; *oct; oct++) r = (r * 8) + (*oct - '0'); return r; } void tar_parse(tar_block_t *block) { while(true) { tar_header_t *header = &block->header; if(*header->name == 0) return; if(s_initrd_dir.self.data == OBJECT_DIRECTORY_MAX_ENTRIES) { klogf("More than %i files in initrd! Skipping the rest.\n", OBJECT_DIRECTORY_MAX_ENTRIES - 1); } size_t file_size = s_tar_oct_dec(header->size); s_initrd_dir.entries[s_initrd_dir.self.data++] = (objdir_entry_t) { .type = KO_INITRD_FILE, .data = (uintptr_t)block }; klogf("Load file '%s' at %p sie %x\n", block->header.name, block + 1, file_size); block = &block[(file_size / 512) + 1]; if(file_size % 512) block++; } } void initrd_setup(void) { char *initrd_path = bootargs_getarg("initrd"); if(initrd_path == 0) { kpanic("Missing kernel commandline argument for initrd."); } uintptr_t initrd_addr = s_initrd_getaddr(initrd_path); klogf("Initrd found at %p\n", initrd_addr); tar_parse((tar_block_t*)initrd_addr); _initDirectory.entries[INIT_OBJECT_INITRD_DIR] = (objdir_entry_t) { .type = KO_OBJECT_DIRECTORY, .data = (uintptr_t)&s_initrd_dir }; } int initrd_file_size(tar_header_t *file) { return s_tar_oct_dec(file->size); } tar_header_t* initrd_find_file(const char *filename) { for(size_t i = 0; i < s_initrd_dir.self.data - 1; i++) { objdir_entry_t *entry = &s_initrd_dir.entries[i+1]; tar_header_t *file = (tar_header_t*)entry->data; if(strcmp(file->name + 1, filename) == 0) return file; } return NULL; } #endif