summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-03-01 20:29:45 -0500
committerIan Moffett <ian@osmora.org>2024-03-01 20:41:36 -0500
commit87207136edcc91c08b7e27cb052765795e2f7c90 (patch)
tree34e25a66557e7901398a24828fc343706f619e32 /sys
parentdaa727a83fff0160cbd9e13fd4d831fb869ea8a8 (diff)
kernel: initramfs: Add support with VFS + USTAR
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/initramfs.c145
-rw-r--r--sys/fs/initramfs_vfsops.c42
-rw-r--r--sys/include/fs/initramfs.h2
3 files changed, 129 insertions, 60 deletions
diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c
index 7812b9c..c0eaa0c 100644
--- a/sys/fs/initramfs.c
+++ b/sys/fs/initramfs.c
@@ -31,7 +31,11 @@
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/limine.h>
+#include <sys/errno.h>
#include <sys/panic.h>
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+#include <vm/dynalloc.h>
#include <string.h>
__MODULE_NAME("initramfs");
@@ -46,6 +50,10 @@ static volatile struct limine_module_request mod_req = {
static const char *initramfs = NULL;
static size_t initramfs_size = 0;
+#define TAR_TYPEFLAG_NORMAL '0'
+#define TAR_TYPEFLAG_HARDLINK '1'
+#define TAR_TYPEFLAG_DIR '5'
+
struct tar_hdr {
char filename[100];
char mode[8];
@@ -53,10 +61,90 @@ struct tar_hdr {
char gid[8];
char size[12];
char mtime[12];
- char chksum[8];
- char typeflag[1];
+ char checksum[8];
+ char type;
+ char link_name[100];
+ char magic[6];
+ char version[2];
+ char uname[32];
+ char gname[32];
+ char dev_major[8];
+ char dev_minor[8];
+ char prefix[155];
};
+static struct tar_hdr *initramfs_from_path(struct tar_hdr *hdr,
+ const char *path);
+
+static size_t
+getsize(const char *in);
+
+static inline char *
+hdr_to_contents(struct tar_hdr *hdr)
+{
+ return ((char*)hdr) + 0x200;
+}
+
+static int
+vop_vget(struct vnode *parent, const char *name, struct vnode **vp)
+{
+ struct tar_hdr *hdr;
+ struct vnode *vnode;
+ int status;
+ int vtype = VREG;
+
+ if (initramfs == NULL) {
+ return -EIO;
+ }
+
+ hdr = initramfs_from_path((void *)initramfs, name);
+
+ if (hdr == NULL) {
+ return -ENOENT;
+ }
+
+ if (hdr->type != TAR_TYPEFLAG_DIR) {
+ vtype = VDIR;
+ }
+
+ /* Allocate vnode for this file */
+ if ((status = vfs_alloc_vnode(&vnode, NULL, vtype)) != 0) {
+ return status;
+ }
+
+ vnode->parent = parent;
+ vnode->data = hdr;
+
+ vnode->vops = &g_initramfs_vops;
+ *vp = vnode;
+ return 0;
+}
+
+static int
+vop_read(struct vnode *vp, char *buf, size_t count)
+{
+ struct tar_hdr *hdr;
+ size_t size;
+ char *contents;
+
+ if (vp->data == NULL) {
+ return -EIO;
+ }
+
+ hdr = vp->data;
+ size = getsize(hdr->size);
+ contents = hdr_to_contents(hdr);
+
+ for (size_t i = 0; i < count; ++i) {
+ if (i >= size) {
+ break;
+ }
+ buf[i] = contents[i];
+ }
+
+ return size;
+}
+
static char *
get_module(const char *path, uint64_t *size) {
for (uint64_t i = 0; i < mod_req.response->module_count; ++i) {
@@ -82,7 +170,7 @@ getsize(const char *in)
}
static int
-initramfs_init(void)
+initramfs_init(struct fs_info *info)
{
initramfs = get_module("/boot/initramfs.tar", &initramfs_size);
@@ -93,33 +181,54 @@ initramfs_init(void)
return 0;
}
-const char *
-initramfs_open(const char *path)
+static struct tar_hdr *
+initramfs_from_path(struct tar_hdr *hdr, const char *path)
{
- uintptr_t addr, size;
- struct tar_hdr *hdr;
- if (initramfs == NULL) {
- initramfs_init();
- }
+ uintptr_t addr = (uintptr_t)hdr;
+ size_t size;
- if (strlen(path) > 99) {
+ if (*path != '/') {
return NULL;
}
+ ++path;
- addr = (uintptr_t)initramfs + 0x200;
- hdr = (struct tar_hdr *)addr;
-
- while (hdr->filename[0] != '\0') {
- hdr = (struct tar_hdr *)addr;
+ while (strcmp(hdr->magic, "ustar") == 0) {
size = getsize(hdr->size);
if (strcmp(hdr->filename, path) == 0) {
- return ((char*)addr) + 0x200;
+ return hdr;
}
- addr += (((size + 511) / 512) + 1) * 512;
+ addr += 512 + __ALIGN_UP(size, 512);
+ hdr = (struct tar_hdr *)addr;
}
return NULL;
}
+
+const char *
+initramfs_open(const char *path)
+{
+ struct tar_hdr *hdr;
+
+ if (initramfs == NULL) {
+ return NULL;
+ }
+
+ if (strlen(path) > 99) {
+ return NULL;
+ }
+
+ hdr = initramfs_from_path((void *)initramfs, path);
+ return hdr_to_contents(hdr);
+}
+
+struct vfsops g_initramfs_ops = {
+ .init = initramfs_init,
+};
+
+struct vops g_initramfs_vops = {
+ .vget = vop_vget,
+ .read = vop_read
+};
diff --git a/sys/fs/initramfs_vfsops.c b/sys/fs/initramfs_vfsops.c
deleted file mode 100644
index 780315d..0000000
--- a/sys/fs/initramfs_vfsops.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Hyra nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <fs/initramfs.h>
-#include <sys/mount.h>
-#include <string.h>
-
-static int
-initramfs_init(struct fs_info *info)
-{
- return 0;
-}
-
-struct vfsops g_initramfs_ops = {
- .init = initramfs_init,
-};
diff --git a/sys/include/fs/initramfs.h b/sys/include/fs/initramfs.h
index c507e3d..223e962 100644
--- a/sys/include/fs/initramfs.h
+++ b/sys/include/fs/initramfs.h
@@ -31,8 +31,10 @@
#define _FS_INITRAMFS_H_
#include <sys/mount.h>
+#include <sys/vnode.h>
extern struct vfsops g_initramfs_ops;
+extern struct vops g_initramfs_vops;
const char *initramfs_open(const char *path);