blob: 30d690ed75dfff29c41f3de0553aa48bfffe972d [file] [log] [blame]
#include "alloc.h"
#include "io.h"
#include "kint.h"
#include "log.h"
#include "vfs.h"
#include <initrd/initrd.h>
struct initrd_fs_entry
{
char *name;
uchar *data;
uint size;
};
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,
uint name_len)
{
if (node != &real_initrd)
return NULL;
for (int i = 0; i < num_initrd_files; i++)
{
if (strncmp(entries[i].name, name,
MIN(FS_MAX_NAME_LEN, name_len))
== 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_i].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(ERROR "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 = 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");
}