Fix mkinitrd, add vfs_initrd stub
diff --git a/include/initrd/initrd.h b/include/initrd/initrd.h
index e095f34..c0a8d18 100644
--- a/include/initrd/initrd.h
+++ b/include/initrd/initrd.h
@@ -12,6 +12,6 @@
 {
 	char name[64];
 	unsigned long size;
-};
+} __attribute__((packed));
 
 /* that's it! */
diff --git a/src/kernel/kint.h b/src/kernel/kint.h
index 8f934fa..d892f88 100644
--- a/src/kernel/kint.h
+++ b/src/kernel/kint.h
@@ -16,3 +16,5 @@
 };
 
 #define NULL 0
+#define MIN(a, b) ((a)>(b)?(b):(a))
+#define MAX(a, b) ((a)>(b)?(a):(b))
diff --git a/src/kernel/main.c b/src/kernel/main.c
index a939238..60d40aa 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -6,6 +6,7 @@
 #include "timer.h"
 #include "vga.h"
 #include "vfs.h"
+#include "vfs_initrd.h"
 #include "multiboot.h"
 
 int kmain(struct multiboot *mboot)
@@ -33,16 +34,17 @@
 	kprintf("initrd is at 0x%x to 0x%x\n", initrd_loc);
 
 	init_vfs();
+	init_initrd_vfs(initrd_loc);
 	kprintf("VFS initialized\n");
 
 	vga_set_color(LIGHT_GREEN, BLACK);
 	vga_write("Setup complete!\n");
 	vga_set_color(WHITE, BLACK);
 
-	kprintf("fs_readdir(\"/\")\n");
+	kprintf("fs_readdir(\"/dev/initrd\")\n");
 
 	struct fs_dirent dirent;
-	for (int i = 0; fs_readdir(&root, i, &dirent); i++)
+	for (int i = 0; fs_readdir(&initrd, i, &dirent); i++)
 	{
 		kprintf("name: %s, inode: %d\n", dirent.name, dirent.inode);
 	}
diff --git a/src/kernel/vfs_initrd.c b/src/kernel/vfs_initrd.c
index 0ec48a0..cad6d0b 100644
--- a/src/kernel/vfs_initrd.c
+++ b/src/kernel/vfs_initrd.c
@@ -1,14 +1,125 @@
-#include <initrd/initrd.h>
-#include "kint.h"
-#include "vfs.h"
+#include "alloc.h"
 #include "io.h"
+#include "kint.h"
+#include "log.h"
+#include "vfs.h"
+#include <initrd/initrd.h>
 
-struct fs_node real_initrd;
-struct fs_node *initrd_content = NULL;
+struct initrd_fs_entry
+{
+	char *name;
+	uchar *data;
+	uint size;
+};
 
-void init_initrd_vfs()
+static struct fs_node real_initrd;
+static struct fs_node *initrd_content = NULL;
+static struct initrd_fs_entry *entries = NULL;
+static struct fs_vtable initrd_v;
+static uint num_initrd_files = 0;
+
+bool initrd_readdir(struct fs_node *node, uint i, struct fs_dirent *out)
+{
+	if (node != &real_initrd)
+		return false;
+
+	if (i >= num_initrd_files)
+		return false;
+
+	memcpy(out->name, entries[i].name, strlen(entries[i].name) + 1);
+	out->inode = i;
+	return true;
+}
+
+struct fs_node *initrd_finddir(struct fs_node *node, char *name)
+{
+	if (node != &real_initrd)
+		return NULL;
+
+	for (int i = 0; i < num_initrd_files; i++)
+	{
+		if (strcmp(entries[i].name, name) == 0)
+			return &initrd_content[i];
+	}
+	return NULL;
+}
+
+void initrd_open(struct fs_node *node)
+{
+}
+
+void initrd_close(struct fs_node *node)
+{
+}
+
+uint initrd_read(struct fs_node *node, size_t offset, size_t size, uchar *buffer)
+{
+	if (offset > node->size)
+		return 0;
+
+	size = MIN(size, node->size - offset);
+	memcpy(buffer, entries[node->dri_res].data, size);
+
+	return size;
+}
+
+void init_initrd_vfs(uchar *data)
 {
 	memset(&real_initrd, 0, sizeof(real_initrd));
 
 	real_initrd.flags = FS_DIRECTORY;
+	real_initrd.vtable = &initrd_v;
+
+	initrd_v.readdir = initrd_readdir;
+	initrd_v.finddir = initrd_finddir;
+	initrd_v.open = initrd_open;
+	initrd_v.close = initrd_close;
+	initrd_v.read = initrd_read;
+
+	// parse initrd
+	struct initrd_global_header *h = (struct initrd_global_header *)data;
+
+	if (h->magic != INITRD_MAGIC)
+	{
+		kprintf("initrd magic is wrong: %x should be %x\n", h->magic,
+				INITRD_MAGIC);
+		kpanic("initrd magic");
+	}
+
+	num_initrd_files = h->num_files;
+	initrd_content = malloc(sizeof(struct fs_node) * num_initrd_files);
+	entries = malloc(sizeof(struct initrd_fs_entry) * num_initrd_files);
+
+	// create fs_nodes for files
+	struct initrd_file_header *f =
+		(struct initrd_file_header *)(data +
+									  sizeof(struct initrd_global_header));
+
+	for (int i = 0; i < num_initrd_files; i++)
+	{
+		uchar *data = (uchar *)((size_t)f + sizeof(struct initrd_file_header));
+
+		entries[i].data = data;
+		entries[i].name = f->name;
+		entries[i].size = f->size;
+
+		initrd_content[i] = (struct fs_node){
+			.dri_res = i,
+			.flags = FS_FILE,
+			.mask = 0b101001001,
+			.uid = 0,
+			.gid = 0,
+			.size = f->size,
+			.vtable = &initrd_v,
+			.mount = NULL
+		};
+
+		memcpy(initrd_content[i].name, f->name, strlen(f->name));
+
+		f = (struct initrd_file_header *)((size_t)data + f->size);
+	}
+
+	// mount initrd to /dev/initrd/
+	if (fs_mount(&initrd, &real_initrd))
+		kpanic("Failed to mount initrd to /dev/initrd");
 }
diff --git a/src/kernel/vfs_initrd.h b/src/kernel/vfs_initrd.h
index 91959d6..a76288c 100644
--- a/src/kernel/vfs_initrd.h
+++ b/src/kernel/vfs_initrd.h
@@ -1,3 +1,7 @@
 #pragma once
 
-void init_initrd_vfs();
+#include "kint.h"
+
+/* Note: this requires virtual memory to be set up,
+ * this WILL call malloc() */
+void init_initrd_vfs(uchar *data);
diff --git a/src/mkinitrd/main.c b/src/mkinitrd/main.c
index f2b3f71..5e4a66d 100644
--- a/src/mkinitrd/main.c
+++ b/src/mkinitrd/main.c
@@ -54,6 +54,8 @@
 		};
 
 		strcpy(file.name, argv[i + 2]);
+		fwrite(&file, sizeof(file), 1, out);
+//		fprintf(stderr, "file name is %s, sizeof(file) = 0x%lx\n", file.name, sizeof(file));
 
 		char c;
 		while ((c = getc(in)) != EOF)