diff options
Diffstat (limited to 'ird')
-rw-r--r-- | ird/initrd.c | 88 | ||||
-rw-r--r-- | ird/initrd.d | 3 | ||||
-rw-r--r-- | ird/initrd.h | 21 | ||||
-rw-r--r-- | ird/tar.h | 18 |
4 files changed, 130 insertions, 0 deletions
diff --git a/ird/initrd.c b/ird/initrd.c new file mode 100644 index 0000000..f219243 --- /dev/null +++ b/ird/initrd.c @@ -0,0 +1,88 @@ +#include "initrd.h" +#include "lib/string.h" +#include "io/log.h" +#include "boot/boot.h" +#include "boot/cmdline.h" +#include "mem/memory.h" + +struct SlabCache s_initrd_cache; +struct SLinkedList 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 TARSector *sector = (struct TARSector*)module->addr; + while(true) { + struct TARHeader *header = (struct TARHeader*)sector; + if(header->name[0] == 0) break; + + struct InitrdFile *file = mem_slab_alloc(&s_initrd_cache); + *file = (struct InitrdFile){ + .header = header, + .name = header->name, + .size = s_tar_oct_dec(header->size), + .data = §or[1] + }; + klogf("File %s size %i\n", file->name, file->size); + sll_push(&s_initrd_files, file); + + sector = §or[(file->size / 512) + 1]; + if(file->size % 512 > 0) sector = §or[1]; + } +} + +struct InitrdFile * +ird_getfile(const char *path) +{ + for(struct SLLNode *node = s_initrd_files.head; node != NULL; node = node->next) { + struct InitrdFile *file = (struct InitrdFile*)node; + if(strcmp(file->name, path) == 0) return file; + } + return NULL; +} + +struct SLinkedList * +ird_getfiles(void) +{ + return &s_initrd_files; +} + +void +initrd_setup(void) +{ + const char *initrd_path = cmdline_get("initrd"); + if(initrd_path == 0) { + klogf("No initrd loaded!\n"); + return; + } + klogf("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; + } + + sll_new(&s_initrd_files, sizeof(struct InitrdFile)); + mem_slabcache_new(&s_initrd_cache, "initrd files", sizeof(struct InitrdFile)); + s_initrd_parse(initrd_module); +} diff --git a/ird/initrd.d b/ird/initrd.d new file mode 100644 index 0000000..b2b0e40 --- /dev/null +++ b/ird/initrd.d @@ -0,0 +1,3 @@ +ird/initrd.o: ird/initrd.c ird/initrd.h ird/tar.h lib/linkedlist.h \ + lib/string.h io/log.h boot/boot.h boot/cmdline.h lib/hashtable.h \ + lib/linkedlist.h mem/memory.h mem/slab.h diff --git a/ird/initrd.h b/ird/initrd.h new file mode 100644 index 0000000..f236fa1 --- /dev/null +++ b/ird/initrd.h @@ -0,0 +1,21 @@ +#ifndef JOVE_INITRD_H +#define JOVE_INITRD_H 1 + +#include <stddef.h> +#include "tar.h" +#include "lib/linkedlist.h" + +struct InitrdFile { + struct InitrdFile *next; + struct TARHeader *header; + const char *name; + size_t size; + const void *data; +}; + +void initrd_setup(void); + +struct InitrdFile *ird_getfile(const char *path); +struct SLinkedList *ird_getfiles(void); + +#endif diff --git a/ird/tar.h b/ird/tar.h new file mode 100644 index 0000000..5c72620 --- /dev/null +++ b/ird/tar.h @@ -0,0 +1,18 @@ +#ifndef JOVE_INITRD_TAR_H +#define JOVE_INITRD_TAR_H 1 + +struct TARSector { char data[512]; }; + +struct TARHeader { + 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]; +}; + +#endif |