Finish up vfs_init
diff --git a/src/kernel/io.c b/src/kernel/io.c
index 55bf7a7..0cf04b2 100644
--- a/src/kernel/io.c
+++ b/src/kernel/io.c
@@ -4,13 +4,11 @@
#include "pic.h"
bool pressed_keys[LAST_KBD_KEY];
-char special_key_mappings[LAST_KBD_KEY - FIRST_KBD_KEY] =
-{
+char special_key_mappings[LAST_KBD_KEY - FIRST_KBD_KEY] = {
[KBD_ENTER - FIRST_KBD_KEY] = '\n',
[KBD_SPACEBAR - FIRST_KBD_KEY] = ' ',
[KBD_TAB - FIRST_KBD_KEY] = '\t',
[KBD_BACKSPACE - FIRST_KBD_KEY] = '\b',
- 0
};
void outb(ushort port, uchar val)
@@ -50,6 +48,31 @@
return dest;
}
+uint strlen(char *a)
+{
+ int i = 0;
+ for (; *a; i++)
+ {
+ }
+
+ return i;
+}
+
+int strcmp(char *a, char *b)
+{
+ int al = strlen(a), bl = strlen(b);
+
+ if (al != bl)
+ return bl - al;
+
+ for (int i = 0; i < al; i++)
+ {
+ if (a[i] != b[i])
+ return -1;
+ }
+ return 0;
+}
+
void io_wait()
{
asm volatile("outb %0, $0x80" ::"a"(0));
diff --git a/src/kernel/io.h b/src/kernel/io.h
index 28af387..f251717 100644
--- a/src/kernel/io.h
+++ b/src/kernel/io.h
@@ -19,8 +19,11 @@
uchar inb(ushort port);
ushort inw(ushort port);
+/* Random string.h stuff, TODO: move to own header */
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
+int strcmp(char *a, char *b);
+uint strlen(char *a);
void io_wait();
diff --git a/src/kernel/main.c b/src/kernel/main.c
index 4e5b4ae..5bd8f87 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -5,6 +5,7 @@
#include "paging.h"
#include "timer.h"
#include "vga.h"
+#include "vfs.h"
#include "multiboot.h"
int kmain(struct multiboot *mboot)
@@ -18,10 +19,6 @@
init_allocator();
init_kbd();
- vga_set_color(LIGHT_GREEN, BLACK);
- vga_write("Setup complete!\n");
- vga_set_color(WHITE, BLACK);
-
#ifdef TEST_ALLOC
test_allocator();
#endif
@@ -35,6 +32,13 @@
kprintf("initrd is at 0x%x to 0x%x\n", initrd_loc);
+ init_vfs();
+ kprintf("VFS initialized\n");
+
+ vga_set_color(LIGHT_GREEN, BLACK);
+ vga_write("Setup complete!\n");
+ vga_set_color(WHITE, BLACK);
+
asm volatile("sti");
while (true)
diff --git a/src/kernel/vfs.c b/src/kernel/vfs.c
index 4a584eb..7b4ff0b 100644
--- a/src/kernel/vfs.c
+++ b/src/kernel/vfs.c
@@ -1,6 +1,8 @@
#include "vfs.h"
+#include "io.h"
struct fs_node root, dev, initrd;
+struct fs_vtable root_v, dev_v;
uint fs_read(struct fs_node *node, size_t offset, size_t size, uchar *buffer)
{
@@ -34,27 +36,106 @@
node->vtable->close(node);
}
-struct fs_dirent *fs_readdir(struct fs_node *node, uint index)
+uint fs_readdir(struct fs_node *node, uint index, struct fs_dirent *out)
{
- if (!node || !node->vtable || !node->vtable->readdir || (node->flags & 7) != FS_DIRECTORY)
- return NULL;
+ if (!node || !node->vtable || !node->vtable->readdir ||
+ (node->flags & 7) != FS_DIRECTORY)
+ return 1;
- return node->vtable->readdir(node, index);
+ return node->vtable->readdir(node, index, out);
}
-struct fs_node *fs_finddir(struct fs_node *node, char *name)
+uint fs_finddir(struct fs_node *node, char *name, struct fs_node *out)
{
- if (!node || !node->vtable || !node->vtable->finddir || (node->flags & 7) != FS_DIRECTORY)
- return NULL;
+ if (!node || !node->vtable || !node->vtable->finddir ||
+ (node->flags & 7) != FS_DIRECTORY)
+ return 1;
- return node->vtable->finddir(node, name);
+ return node->vtable->finddir(node, name, out);
}
-struct fs_dirent *root_readdir(struct fs_node *node, uint index)
+uint root_readdir(struct fs_node *node, uint index, struct fs_dirent *out)
{
+ if (node == &root && index == 0)
+ {
+ // devfs
+ memcpy(out->name, "dev", 4);
+ out->inode = -1;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+uint root_finddir(struct fs_node *node, char *name, struct fs_node *out)
+{
+ if (!strcmp(name, "dev"))
+ {
+ *out = dev;
+ return 0;
+ }
+
+ return 1;
+}
+
+uint dev_readdir(struct fs_node *node, uint index, struct fs_dirent *out)
+{
+ if (node == &dev && index == 0)
+ {
+ // initrd
+ memcpy(out->name, "dirent", 7);
+ out->inode = -1;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+uint dev_finddir(struct fs_node *node, char *name, struct fs_node *out)
+{
+ if (node != &dev)
+ return 1;
+
+ if (!strcmp(name, "initrd"))
+ {
+ *out = initrd;
+ return 0;
+ }
+
+ return 1;
}
void init_vfs()
{
+ memset(&root_v, 0, sizeof(root_v));
+ memset(&dev_v, 0, sizeof(root_v));
+ memset(&root, 0, sizeof(root));
+ memset(&dev, 0, sizeof(dev));
+
+ root.flags = FS_DIRECTORY;
+ root.vtable = &root_v;
+ dev.flags = FS_DIRECTORY;
+ dev.vtable = &dev_v;
+ initrd.flags = FS_DIRECTORY;
+
+ root_v.readdir = root_readdir;
+ root_v.finddir = root_finddir;
+}
+
+uint fs_mount(struct fs_node *target, struct fs_node *source)
+{
+ if (target->flags ^ FS_DIRECTORY)
+ return 1; // target is not a directory
+
+ if (target->flags & FS_MOUNT)
+ return 2; // already mounted
+
+ if (source->flags ^ FS_DIRECTORY)
+ return 3; // source is not a directory
+
+ target->flags |= FS_MOUNT;
+ target->mount = source;
+
+ return 0;
}
diff --git a/src/kernel/vfs.h b/src/kernel/vfs.h
index 3bd135e..1510566 100644
--- a/src/kernel/vfs.h
+++ b/src/kernel/vfs.h
@@ -31,9 +31,8 @@
typedef void (* fs_open_t)(struct fs_node *node);
typedef void (* fs_close_t)(struct fs_node *node);
-// Dirent should be FREED BY CALLER
-typedef struct fs_dirent *(* fs_readdir_t)(struct fs_node *node, uint index);
-typedef struct fs_node *(* fs_finddir_t)(struct fs_node *node, char *name);
+typedef uint (* fs_readdir_t)(struct fs_node *node, uint index, struct fs_dirent *dirent);
+typedef uint (* fs_finddir_t)(struct fs_node *node, char *name, struct fs_node *out);
struct fs_vtable
{
@@ -57,15 +56,29 @@
FS_MOUNT = 8, /* Can be or'd with others */
};
+extern struct fs_node root, dev, initrd;
+
/* Not to be confused normal open, close, etc functions, these operate
- * on the VFS directly */
+ * on the VFS directly
+ * read and write return the number of bytes written/read, */
uint fs_read(struct fs_node *node, size_t offset, size_t size, uchar *buffer);
uint fs_write(struct fs_node *node, size_t offset, size_t size, uchar *buffer);
void fs_open(struct fs_node *node);
void fs_close(struct fs_node *node);
-struct fs_dirent *fs_readdir(struct fs_node *node, uint index);
-struct fs_node *fs_finddir(struct fs_node *node, char *name);
+/* For all of the functions that return integers;
+ * 0 = okay
+ * non-zero = error */
+
+uint fs_readdir(struct fs_node *node, uint index, struct fs_dirent *out);
+uint fs_finddir(struct fs_node *node, char *name, struct fs_node *out);
+
+/* Returns the following error codes:
+ * 0: success
+ * 1: target is not a directory
+ * 2: target is already a mount point
+ * 3: source is not a directory */
+uint fs_mount(struct fs_node *target, struct fs_node *source);
void init_vfs();
diff --git a/src/kernel/vfs_initrd.c b/src/kernel/vfs_initrd.c
index 9298a2d..6bbfd3f 100644
--- a/src/kernel/vfs_initrd.c
+++ b/src/kernel/vfs_initrd.c
@@ -1,4 +1,4 @@
#include <initrd/initrd.h>
#include "kint.h"
-
+#include "vfs.h"
diff --git a/src/kernel/vfs_initrd.h b/src/kernel/vfs_initrd.h
index 6f70f09..91959d6 100644
--- a/src/kernel/vfs_initrd.h
+++ b/src/kernel/vfs_initrd.h
@@ -1 +1,3 @@
#pragma once
+
+void init_initrd_vfs();