aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/fs
diff options
context:
space:
mode:
authorMarvin Borner2019-10-30 16:02:10 +0100
committerMarvin Borner2019-10-30 16:02:10 +0100
commit118898807865ba11f5d7754f6f0572a0403f8512 (patch)
tree0b69c881089d659ebb214c409b699cc06323ab3d /src/kernel/fs
parentfd4f0a11126a20e75d72f8f2e6d418598fd5f37d (diff)
Started implementation of initrd based vfs
Diffstat (limited to 'src/kernel/fs')
-rw-r--r--src/kernel/fs/initrd.c104
-rw-r--r--src/kernel/fs/initrd.h20
-rw-r--r--src/kernel/fs/vfs.c43
-rw-r--r--src/kernel/fs/vfs.h65
4 files changed, 232 insertions, 0 deletions
diff --git a/src/kernel/fs/initrd.c b/src/kernel/fs/initrd.c
new file mode 100644
index 0000000..b291801
--- /dev/null
+++ b/src/kernel/fs/initrd.c
@@ -0,0 +1,104 @@
+#include <stdint.h>
+#include <kernel/fs/initrd.h>
+#include <kernel/fs/vfs.h>
+#include <kernel/lib/lib.h>
+#include <kernel/lib/alloc.h>
+
+initrd_header_t *initrd_header;
+initrd_file_header_t *file_headers;
+fs_node_t *initrd_root;
+fs_node_t *initrd_dev;
+fs_node_t *root_nodes;
+int nroot_nodes;
+
+struct dirent dirent;
+
+static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ initrd_file_header_t header = file_headers[node->inode];
+ if (offset > header.length)
+ return 0;
+ if (offset + size > header.length)
+ size = header.length - offset;
+ memcpy(buffer, (uint8_t *) (header.offset + offset), size);
+ return size;
+}
+
+static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) {
+ if (node == initrd_root && index == 0) {
+ strcpy(dirent.name, "dev");
+ dirent.name[3] = 0;
+ dirent.ino = 0;
+ return &dirent;
+ }
+
+ if (index - 1 >= nroot_nodes)
+ return 0;
+ strcpy(dirent.name, root_nodes[index - 1].name);
+ dirent.name[strlen(root_nodes[index - 1].name)] = 0;
+ dirent.ino = root_nodes[index - 1].inode;
+ return &dirent;
+}
+
+static fs_node_t *initrd_finddir(fs_node_t *node, char *name) {
+ if (node == initrd_root &&
+ !strcmp(name, "dev"))
+ return initrd_dev;
+
+ int i;
+ for (i = 0; i < nroot_nodes; i++)
+ if (!strcmp(name, root_nodes[i].name))
+ return &root_nodes[i];
+ return 0;
+}
+
+fs_node_t *initialise_initrd(uint32_t location) {
+ initrd_header = (initrd_header_t *) location;
+ file_headers = (initrd_file_header_t *) (location + sizeof(initrd_header_t));
+
+ initrd_root = (fs_node_t *) kmalloc(sizeof(fs_node_t));
+ strcpy(initrd_root->name, "initrd");
+ initrd_root->mask = initrd_root->uid = initrd_root->gid = initrd_root->inode = initrd_root->length = 0;
+ initrd_root->flags = FS_DIRECTORY;
+ initrd_root->read = 0;
+ initrd_root->write = 0;
+ initrd_root->open = 0;
+ initrd_root->close = 0;
+ initrd_root->readdir = &initrd_readdir;
+ initrd_root->finddir = &initrd_finddir;
+ initrd_root->ptr = 0;
+ initrd_root->impl = 0;
+
+ initrd_dev = (fs_node_t *) kmalloc(sizeof(fs_node_t));
+ strcpy(initrd_dev->name, "dev");
+ initrd_dev->mask = initrd_dev->uid = initrd_dev->gid = initrd_dev->inode = initrd_dev->length = 0;
+ initrd_dev->flags = FS_DIRECTORY;
+ initrd_dev->read = 0;
+ initrd_dev->write = 0;
+ initrd_dev->open = 0;
+ initrd_dev->close = 0;
+ initrd_dev->readdir = &initrd_readdir;
+ initrd_dev->finddir = &initrd_finddir;
+ initrd_dev->ptr = 0;
+ initrd_dev->impl = 0;
+
+ root_nodes = (fs_node_t *) kmalloc(sizeof(fs_node_t) * initrd_header->nfiles);
+ nroot_nodes = initrd_header->nfiles;
+
+ for (int i = 0; i < initrd_header->nfiles; i++) {
+ file_headers[i].offset += location;
+
+ strcpy(root_nodes[i].name, &file_headers[i].name);
+ root_nodes[i].mask = root_nodes[i].uid = root_nodes[i].gid = 0;
+ root_nodes[i].length = file_headers[i].length;
+ root_nodes[i].inode = i;
+ root_nodes[i].flags = FS_FILE;
+ root_nodes[i].read = &initrd_read;
+ root_nodes[i].write = 0;
+ root_nodes[i].readdir = 0;
+ root_nodes[i].finddir = 0;
+ root_nodes[i].open = 0;
+ root_nodes[i].close = 0;
+ root_nodes[i].impl = 0;
+ }
+ return initrd_root;
+}
diff --git a/src/kernel/fs/initrd.h b/src/kernel/fs/initrd.h
new file mode 100644
index 0000000..10dec22
--- /dev/null
+++ b/src/kernel/fs/initrd.h
@@ -0,0 +1,20 @@
+#ifndef MELVIX_INITRD_H
+#define MELVIX_INITRD_H
+
+#include <stdint.h>
+#include <kernel/fs/vfs.h>
+
+typedef struct {
+ uint32_t nfiles;
+} initrd_header_t;
+
+typedef struct {
+ uint8_t magic;
+ int8_t name[64];
+ uint32_t offset;
+ uint32_t length;
+} initrd_file_header_t;
+
+fs_node_t *initialise_initrd(uint32_t location);
+
+#endif
diff --git a/src/kernel/fs/vfs.c b/src/kernel/fs/vfs.c
new file mode 100644
index 0000000..5591a60
--- /dev/null
+++ b/src/kernel/fs/vfs.c
@@ -0,0 +1,43 @@
+#include <kernel/fs/vfs.h>
+
+fs_node_t *fs_root = 0;
+
+uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ if (node->read != 0)
+ return node->read(node, offset, size, buffer);
+ else
+ return 0;
+}
+
+uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ if (node->write != 0)
+ return node->write(node, offset, size, buffer);
+ else
+ return 0;
+}
+
+void open_fs(fs_node_t *node, uint8_t read, uint8_t write) {
+ if (node->open != 0)
+ return node->open(node);
+}
+
+void close_fs(fs_node_t *node) {
+ if (node->close != 0)
+ return node->close(node);
+}
+
+struct dirent *readdir_fs(fs_node_t *node, uint32_t index) {
+ if ((node->flags & 0x7) == FS_DIRECTORY &&
+ node->readdir != 0)
+ return node->readdir(node, index);
+ else
+ return 0;
+}
+
+fs_node_t *finddir_fs(fs_node_t *node, char *name) {
+ if ((node->flags & 0x7) == FS_DIRECTORY &&
+ node->finddir != 0)
+ return node->finddir(node, name);
+ else
+ return 0;
+}
diff --git a/src/kernel/fs/vfs.h b/src/kernel/fs/vfs.h
new file mode 100644
index 0000000..5a72861
--- /dev/null
+++ b/src/kernel/fs/vfs.h
@@ -0,0 +1,65 @@
+#ifndef MELVIX_VFS_H
+#define MELVIX_VFS_H
+
+#include <stdint.h>
+
+#define FS_FILE 0x01
+#define FS_DIRECTORY 0x02
+#define FS_CHARDEVICE 0x03
+#define FS_BLOCKDEVICE 0x04
+#define FS_PIPE 0x05
+#define FS_SYMLINK 0x06
+#define FS_MOUNTPOINT 0x08
+
+struct fs_node;
+
+typedef uint32_t (*read_type_t)(struct fs_node *, uint32_t, uint32_t, uint8_t *);
+
+typedef uint32_t (*write_type_t)(struct fs_node *, uint32_t, uint32_t, uint8_t *);
+
+typedef void (*open_type_t)(struct fs_node *);
+
+typedef void (*close_type_t)(struct fs_node *);
+
+typedef struct dirent *(*readdir_type_t)(struct fs_node *, uint32_t);
+
+typedef struct fs_node *(*finddir_type_t)(struct fs_node *, char *name);
+
+typedef struct fs_node {
+ char name[128];
+ uint32_t mask;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t flags;
+ uint32_t inode;
+ uint32_t length;
+ uint32_t impl;
+ read_type_t read;
+ write_type_t write;
+ open_type_t open;
+ close_type_t close;
+ readdir_type_t readdir;
+ finddir_type_t finddir;
+ struct fs_node *ptr;
+} fs_node_t;
+
+struct dirent {
+ char name[128];
+ uint32_t ino;
+};
+
+extern fs_node_t *fs_root;
+
+uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
+
+uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
+
+void open_fs(fs_node_t *node, uint8_t read, uint8_t write);
+
+void close_fs(fs_node_t *node);
+
+struct dirent *readdir_fs(fs_node_t *node, uint32_t index);
+
+fs_node_t *finddir_fs(fs_node_t *node, char *name);
+
+#endif