Finish up vfs_init
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;
 }