summaryrefslogtreecommitdiffstats
path: root/ird/initrd.c
blob: f2192431a359267ce4aed72e022384f650efb51d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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 = &sector[1]
        };
        klogf("File %s size %i\n", file->name, file->size);
        sll_push(&s_initrd_files, file);
 
        sector = &sector[(file->size / 512) + 1];
        if(file->size % 512 > 0) sector = &sector[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);
}