From 87207136edcc91c08b7e27cb052765795e2f7c90 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 1 Mar 2024 20:29:45 -0500 Subject: kernel: initramfs: Add support with VFS + USTAR Signed-off-by: Ian Moffett --- sys/fs/initramfs.c | 145 +++++++++++++++++++++++++++++++++++++++------ sys/fs/initramfs_vfsops.c | 42 ------------- sys/include/fs/initramfs.h | 2 + 3 files changed, 129 insertions(+), 60 deletions(-) delete mode 100644 sys/fs/initramfs_vfsops.c (limited to 'sys') 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 #include #include +#include #include +#include +#include +#include #include __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 -#include -#include - -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 +#include extern struct vfsops g_initramfs_ops; +extern struct vops g_initramfs_vops; const char *initramfs_open(const char *path); -- cgit v1.2.3