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)