diff options
author | Alex AUVOLAT <alexis211@gmail.com> | 2012-05-18 14:47:44 +0200 |
---|---|---|
committer | Alex AUVOLAT <alexis211@gmail.com> | 2012-05-18 14:47:44 +0200 |
commit | 7d5a38ada35ac196919c26675f211adb995b84ae (patch) | |
tree | 60d9733a1ca44ff873dbac610ea367863d5c648b /src/kernel/vfs/initrd.cpp | |
parent | 1ecb3fb821f49450ba4b08ad7d7a23d3acb75c47 (diff) | |
download | TCE-7d5a38ada35ac196919c26675f211adb995b84ae.tar.gz TCE-7d5a38ada35ac196919c26675f211adb995b84ae.zip |
Added initrd. Status: VFS support, totally useless shell.
Diffstat (limited to 'src/kernel/vfs/initrd.cpp')
-rw-r--r-- | src/kernel/vfs/initrd.cpp | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/kernel/vfs/initrd.cpp b/src/kernel/vfs/initrd.cpp new file mode 100644 index 0000000..50aa95c --- /dev/null +++ b/src/kernel/vfs/initrd.cpp @@ -0,0 +1,67 @@ +#include "initrd.h" +#include "vfile.h" +#include <ui/vt.h> + +int initrd_check(uint8_t *data) { + initrd_header *h = (initrd_header*)data; + if (h->magic == INITRD_MAGIC) return 0; + return -1; +} + +int initrd_load(uint8_t *data, vdir *root) { + if (root == 0) return -1; + + union { + uint8_t *c; + initrd_header *ih; + initrd_file_header *fh; + } curr; + curr.c = data; + + if (curr.ih->magic != INITRD_MAGIC) return -2; + + uint32_t files = curr.ih->files; curr.ih++; + for (unsigned i = 0; i < files; i++) { + initrd_file_header *h = curr.fh; + curr.fh++; + if (h->name_length == 0) continue; + char* path = (char*)curr.c; + curr.c += h->name_length + 1; + if (strlen(path) != (int)h->name_length) return -3; + + node* parent = root; + // parse filename + char *member = path; + while (*path != 0 && parent != 0) { + if (*path == '/') { + if (member == path) { + member++; + path++; + } else { + *path = 0; + path++; + node* n = parent->get_child(member); + if (n == 0) { + n = new vdir(parent); + parent->add_child(member, n); + } + parent = n; + member = path; + } + } else { + path++; + } + } + if (parent == 0) return -5; + if (member == path) return -6; // filename ended by '/', bad. + + // add file + if (h->file_length == 0) { + if (parent->add_child(member, new vdir(parent)) != 0) return -4; + } else { + if (parent->add_child(member, new vfile(parent, (char*)curr.c, h->file_length)) != 0) return -4; + curr.c += h->file_length; + } + } + return 0; +} |