diff options
Diffstat (limited to 'src/kernel/fs')
-rw-r--r-- | src/kernel/fs/initrd.c | 104 | ||||
-rw-r--r-- | src/kernel/fs/initrd.h | 20 | ||||
-rw-r--r-- | src/kernel/fs/vfs.c | 43 | ||||
-rw-r--r-- | src/kernel/fs/vfs.h | 65 |
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 |