summaryrefslogblamecommitdiffstats
path: root/initrd/initrd.c
blob: 8fe0f01742844a9ba500871ccc321a677e2310a5 (plain) (tree)
1
2
3
4
5
6
7
8
9
                   







                        
 
                               















                                         
                                                               
                 
                                                     

                                       






                                            




                                                
                                                           





                                                     
               

                             

                                                                          






                                                    
                                     

               
                                                             













                                                     
                                               

                                  
#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 = &sector[1]
        };
        kdbgf("File %s size %i\n", file->name, file->size);
 
        sector = &sector[(file->size / 512) + 1];
        if(file->size % 512 > 0) sector = &sector[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);
}