diff options
Diffstat (limited to 'initrd')
-rw-r--r-- | initrd/initrd.c | 84 | ||||
-rw-r--r-- | initrd/tar.h | 18 |
2 files changed, 102 insertions, 0 deletions
diff --git a/initrd/initrd.c b/initrd/initrd.c new file mode 100644 index 0000000..8fe0f01 --- /dev/null +++ b/initrd/initrd.c @@ -0,0 +1,84 @@ +#include "initrd.h" +#include "tar.h" +#include "string.h" +#include "commandline.h" +#include "memory.h" +#include "print.h" +#include "klib/rbtree.h" +#include "klib/hash.h" +#include "boot.h" + +static rbtree_t s_initrd_files; + +static size_t +s_tar_oct_dec(const char *oct) +{ + size_t value = 0; + while(*oct != 0) { + value *= 8; + value += (*oct) - '0'; + oct++; + } + return value; +} + +static void +s_initrd_parse(struct BootModule *module) +{ + struct tar_block *sector = (struct tar_block*)module->addr; + while(true) { + tar_header_t *header = (tar_header_t*)sector; + if(header->name[0] == 0) break; + + initrd_file_t file_tmp; + initrd_file_t *file = rbtree_insert( + &s_initrd_files, + string_hash(header->name), + &file_tmp); + + *file = (initrd_file_t){ + .header = header, + .name = header->name, + .size = s_tar_oct_dec(header->size), + .data = §or[1] + }; + kdbgf("File %s size %i\n", file->name, file->size); + + sector = §or[(file->size / 512) + 1]; + if(file->size % 512 > 0) sector = §or[1]; + } +} + +initrd_file_t * +ird_getfile(const char *path) +{ + initrd_file_t *file = rbtree_find(&s_initrd_files, string_hash(path)); + return file; +} + +void +initrd_setup(void) +{ + const char *initrd_path = cmdline_get("initrd"); + if(initrd_path == 0) { + kerrf("No initrd loaded!\n"); + return; + } + kdbgf("Initrd located in module path %s\n", initrd_path); + struct BootModule *initrd_module = NULL; + for(size_t i = 0; i < boot_module_count; i++) { + struct BootModule *module = &boot_modules[i]; + if(strcmp(module->path, initrd_path) == 0) { + initrd_module = module; + break; + } + } + + if(initrd_module == NULL) { + klogf("Initrd not found in modules!\n"); + return; + } + + rbtree_new(&s_initrd_files, initrd_file_t); + s_initrd_parse(initrd_module); +} diff --git a/initrd/tar.h b/initrd/tar.h new file mode 100644 index 0000000..5325a51 --- /dev/null +++ b/initrd/tar.h @@ -0,0 +1,18 @@ +#ifndef JOVE_INITRD_TAR_H +#define JOVE_INITRD_TAR_H 1 + +struct tar_block { char data[512]; }; + +typedef struct tar_header { + char name[100]; + char mode[8]; + char owner[8]; + char group[8]; + char size[12]; + char modified[12]; + char checksum[8]; + char link; + char linkname[100]; +} tar_header_t; + +#endif |