summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--menu_cdrom.lst1
-rw-r--r--src/kernel/Makefile2
-rw-r--r--src/kernel/core/kmain.cpp23
-rw-r--r--src/kernel/lib/std.cpp2
-rw-r--r--src/kernel/vfs/initrd.cpp67
-rw-r--r--src/kernel/vfs/initrd.h22
-rw-r--r--src/kernel/vfs/vdir.cpp4
-rw-r--r--src/kernel/vfs/vdir.h2
-rw-r--r--src/kernel/vfs/vfile.cpp34
-rw-r--r--src/kernel/vfs/vfile.h23
-rw-r--r--src/tools/makeinitrd/Makefile30
-rw-r--r--src/tools/makeinitrd/main.cpp95
-rwxr-xr-xsrc/tools/makeinitrd/makeinitrdbin0 -> 16457 bytes
14 files changed, 302 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 29ae6c3..ab689c0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
.PHONY: clean, mrproper, Init.rfs, floppy, commit
-Projects = kernel user/lib user/test
+Projects = tools/makeinitrd kernel user/lib user/test
QemuCmd = qemu-system-i386
BasePath = $(shell pwd)
@@ -42,6 +42,9 @@ $(Cdrom): menu_cdrom.lst src/kernel/kernel.elf src/user/test/test.elf
echo "Please copy grub's stage2_eltorito to cdrom/boot/grub."; \
exit -1; \
fi
+ src/tools/makeinitrd/makeinitrd cdrom/initrd \
+ src/user/test/test.elf:/bin/test \
+ README:/readme
cp menu_cdrom.lst cdrom/boot/grub/menu.lst
cp src/kernel/kernel.elf cdrom
cp src/user/test/test.elf cdrom
diff --git a/menu_cdrom.lst b/menu_cdrom.lst
index 4bbe812..1b99614 100644
--- a/menu_cdrom.lst
+++ b/menu_cdrom.lst
@@ -3,3 +3,4 @@ timeout 10
title T/CE
kernel /kernel.elf
module /test.elf
+module /initrd
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index 5c09e80..a6ad58a 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -4,7 +4,7 @@ Obj = core/loader_.o core/kmain.o core/sys.o \
lib/bitset.o lib/std.o lib/cpp.o lib/sched.o \
mem/mem.o mem/paging.o mem/gdt.o mem/_dlmalloc.o mem/seg.o \
linker/elf.o \
- vfs/node.o vfs/vdir.o \
+ vfs/node.o vfs/vdir.o vfs/vfile.o vfs/initrd.o \
dev/vgatxt.o dev/keyboard.o dev/ps2keyboard.o \
ui/vt.o
diff --git a/src/kernel/core/kmain.cpp b/src/kernel/core/kmain.cpp
index 9ec06df..58a3c48 100644
--- a/src/kernel/core/kmain.cpp
+++ b/src/kernel/core/kmain.cpp
@@ -8,6 +8,7 @@
#include <mem/mem.h>
#include <vfs/node.h>
+#include <vfs/initrd.h>
#include <task/idt.h>
#include <task/timer.h>
@@ -76,16 +77,30 @@ extern "C" void kmain(multiboot_info_t* mbd, int32_t magic) {
// Load modules
*ke_vt << "Loading modules :\n";
for (unsigned i = 0; i < mbd->mods_count; i++) {
- *ke_vt << " * " << (char*)mods[i].string;
+ char* cmd = (char*)mods[i].string;
+ *ke_vt << " * " << cmd << " \t";
if (elf_check((uint8_t*)mods[i].mod_start) == 0) {
process *pr = elf_exec((uint8_t*)mods[i].mod_start, PL_USER);
if (pr == 0) {
- *ke_vt << " : Error loading\n";
+ *ke_vt << "Error loading\n";
} else {
- *ke_vt << " : OK, pid=" << (int)pr->pid << "\n";
+ *ke_vt << "OK, pid=" << (int)pr->pid << "\n";
+ }
+ } else if (initrd_check((uint8_t*)mods[i].mod_start) == 0) {
+ vdir* fs = new vdir(root);
+ int e = initrd_load((uint8_t*)mods[i].mod_start, fs);
+ if (e == 0) {
+ char* name = cmd;
+ for (char* i = name; *i != 0; i++) {
+ if (*i == '/' || *i == ' ') name = i + 1;
+ }
+ root->add_child(name, fs);
+ *ke_vt << "OK, initrd as /" << name << "/\n";
+ } else {
+ *ke_vt << "initrd but error " << e << "\n";
}
} else {
- *ke_vt << " : Invalid ELF file\n";
+ *ke_vt << "Invalid file, neither ELF nor initrd.\n";
}
}
diff --git a/src/kernel/lib/std.cpp b/src/kernel/lib/std.cpp
index 4407f55..c25f59c 100644
--- a/src/kernel/lib/std.cpp
+++ b/src/kernel/lib/std.cpp
@@ -16,7 +16,7 @@ void abort() {
int strlen(const char *str) {
int i = 0;
while (str[i++]);
- return i;
+ return i-1;
}
char *strchr(const char *str, char c) {
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;
+}
diff --git a/src/kernel/vfs/initrd.h b/src/kernel/vfs/initrd.h
new file mode 100644
index 0000000..0cabccf
--- /dev/null
+++ b/src/kernel/vfs/initrd.h
@@ -0,0 +1,22 @@
+#ifndef DEF_VFS_INITRD_H
+#define DEF_VFS_INITRD_H
+
+#include "node.h"
+#include "vdir.h"
+
+struct initrd_header {
+ unsigned int magic; //For error checking
+ unsigned int files;
+};
+
+struct initrd_file_header {
+ unsigned int name_length;
+ unsigned int file_length;
+};
+
+#define INITRD_MAGIC 0x12379846
+
+int initrd_check(uint8_t *data); // returns 0 if initrd file, -1 otherwise
+int initrd_load(uint8_t *data, vdir *root);
+
+#endif
diff --git a/src/kernel/vfs/vdir.cpp b/src/kernel/vfs/vdir.cpp
index 299c0e7..00b67cb 100644
--- a/src/kernel/vfs/vdir.cpp
+++ b/src/kernel/vfs/vdir.cpp
@@ -10,6 +10,10 @@ vdir::vdir(node* parent) : node(parent, FT_DIR), children(8, 64) {
}
}
+vdir::~vdir() {
+ //TODO : free children
+}
+
node* vdir::get_child(char* name) {
for (unsigned i = 0; i < child_count; i++) {
vdir_child *c = children.at(i);
diff --git a/src/kernel/vfs/vdir.h b/src/kernel/vfs/vdir.h
index 7ac1b2a..366b3f1 100644
--- a/src/kernel/vfs/vdir.h
+++ b/src/kernel/vfs/vdir.h
@@ -20,7 +20,7 @@ class vdir : public node {
public:
vdir(node* parent);
- virtual ~vdir() {}
+ virtual ~vdir();
virtual int read(size_t offset, size_t len, char* buffer);
virtual int write(size_t offset, size_t len, char* buffer); // rename file
diff --git a/src/kernel/vfs/vfile.cpp b/src/kernel/vfs/vfile.cpp
new file mode 100644
index 0000000..ff57c9e
--- /dev/null
+++ b/src/kernel/vfs/vfile.cpp
@@ -0,0 +1,34 @@
+#include "vfile.h"
+
+vfile::vfile(node* parent, char* d, size_t s) : node(parent, FT_FILE) {
+ size = 0;
+ own_data = false;
+
+ data = d;
+ if (d != 0) size = s;
+}
+
+vfile::~vfile() {
+ if (own_data) kfree(data);
+}
+
+int vfile::read(size_t offset, size_t len, char* buffer) {
+ if (offset + len > size) len = size - offset;
+ memcpy(buffer, data + offset, len);
+ return len;
+}
+
+int vfile::write(size_t offset, size_t len, char* buffer) {
+ size_t new_size = MAX(offset + len, size);
+ if (!own_data || new_size > size) {
+ char* new_data = (char*)kmalloc(new_size);
+ memcpy(new_data, data, size);
+ if (new_size > size) memset(new_data + size, 0, new_size - size);
+ if (own_data) kfree(data);
+ data = new_data;
+ size = new_size;
+ own_data = true;
+ }
+ memcpy(data + offset, buffer, len);
+ return len;
+}
diff --git a/src/kernel/vfs/vfile.h b/src/kernel/vfs/vfile.h
new file mode 100644
index 0000000..9b68b68
--- /dev/null
+++ b/src/kernel/vfs/vfile.h
@@ -0,0 +1,23 @@
+#ifndef DEF_VFS_VFILE_H
+#define DEF_VFS_VFILE_H
+
+#include <lib/std.h>
+#include "node.h"
+
+class vfile : public node {
+ char *data;
+ size_t size;
+ bool own_data; // did WE malloc the content of data ?
+
+ public:
+ vfile(node* parent, char* data = 0, size_t size = 0);
+ virtual ~vfile();
+
+ // TODO: handle open(TRUNC)
+ virtual int read(size_t offset, size_t len, char* buffer);
+ virtual int write(size_t offset, size_t len, char* buffer);
+ virtual size_t get_size() { return size; }
+
+};
+
+#endif
diff --git a/src/tools/makeinitrd/Makefile b/src/tools/makeinitrd/Makefile
new file mode 100644
index 0000000..3ac993c
--- /dev/null
+++ b/src/tools/makeinitrd/Makefile
@@ -0,0 +1,30 @@
+.PHONY: clean, mrproper
+
+CC = gcc
+CXX = g++
+LD = gcc
+LDFLAGS = -lstdc++
+CFLAGS =
+CXXFLAGS =
+
+OutFile = makeinitrd
+Objects = main.o
+
+all: $(OutFile)
+
+rebuild: mrproper all
+
+$(OutFile): $(Objects)
+ $(LD) -o $(OutFile) $(LDFLAGS) $^
+
+%.o: %.c
+ $(CC) -c $< -o $@ $(CFLAGS)
+
+%.o: %.cpp
+ $(CXX) -c $< -o $@ $(CXXFLAGS)
+
+clean:
+ rm -rf *.o
+
+mrproper: clean
+ rm -rf $(OutFile)
diff --git a/src/tools/makeinitrd/main.cpp b/src/tools/makeinitrd/main.cpp
new file mode 100644
index 0000000..ea8966b
--- /dev/null
+++ b/src/tools/makeinitrd/main.cpp
@@ -0,0 +1,95 @@
+#include <iostream>
+#include <fstream>
+#include <string>
+
+using namespace std;
+
+struct ramfs_header {
+ unsigned int magic; //For error checking
+ unsigned int files;
+};
+
+struct ramfs_file_header {
+ unsigned int name_length;
+ unsigned int file_length;
+};
+
+#define INITRD_MAGIC 0x12379846
+
+int main(int argc, char *argv[]) {
+ if (argc < 2) {
+ cerr << "Error : no output file specified." << endl;
+ cerr << "Usage : MakeRamFS <output.img> [<filename>:<ramfs filename> [...] ]" << endl;
+ return 1;
+ }
+
+ ofstream output(argv[1], ios::out | ios::binary);
+
+ ramfs_header hdr;
+ hdr.magic = INITRD_MAGIC;
+ hdr.files = argc - 2;
+
+ output.write((char*)&hdr, sizeof(ramfs_header));
+
+ for (int i = 2; i < argc; i++) {
+ string name(argv[i]);
+ string file;
+ while (!name.empty()) {
+ if (name[0] == ':') {
+ name = name.substr(1, name.size() - 1);
+ break;
+ }
+ file += name[0];
+ name = name.substr(1, name.size() - 1);
+ }
+
+ ramfs_file_header fhdr;
+
+ if (file == "") { //This is a directory
+ fhdr.name_length = name.size();
+ fhdr.file_length = 0; //File length of 0 means directory
+ output.write((char*)&fhdr, sizeof(ramfs_file_header));
+ output << name;
+ output << '\0';
+ continue;
+ }
+
+ ifstream infile(file.c_str(), ios::in | ios::binary);
+
+ if (!infile) {
+ fhdr.name_length = 0; //Name and length = 0 means invalid file
+ fhdr.file_length = 0;
+ output.write((char*)&fhdr, sizeof(ramfs_file_header));
+ continue;
+ }
+
+ fhdr.name_length = name.size();
+ fhdr.file_length = 0;
+ while (!infile.eof()) {
+ char c;
+ infile.read(&c, 1);
+ fhdr.file_length++;
+ }
+
+ infile.close(); infile.open(file.c_str(), ios::in | ios::binary); //Rewind file
+
+ output.write((char*)&fhdr, sizeof(ramfs_file_header));
+
+ output << name;
+ output << '\0';
+
+ char *c = new char[fhdr.file_length];
+ for (int i = 0; i < fhdr.file_length; i++) {
+ char ch;
+ infile.read(&ch, 1);
+ output.write(&ch, 1);
+ }
+ delete [] c;
+
+ infile.close();
+ }
+
+ output.close();
+
+ return 0;
+}
diff --git a/src/tools/makeinitrd/makeinitrd b/src/tools/makeinitrd/makeinitrd
new file mode 100755
index 0000000..afb042c
--- /dev/null
+++ b/src/tools/makeinitrd/makeinitrd
Binary files differ