From c2056f5a365c85780dd2d2835547723f6f60c192 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 19 Jun 2024 22:18:16 -0400 Subject: kernel: Add initramfs and initial VFS code Signed-off-by: Ian Moffett --- sys/fs/initramfs.c | 263 +++++++++++++++++++++++++++++++++++++++++++++ sys/include/fs/initramfs.h | 37 +++++++ sys/include/sys/mount.h | 84 +++++++++++++++ sys/include/sys/namei.h | 44 ++++++++ sys/include/sys/vnode.h | 74 +++++++++++++ sys/kern/init_main.c | 4 + sys/kern/vfs_init.c | 70 ++++++++++++ sys/kern/vfs_lookup.c | 83 ++++++++++++++ sys/kern/vfs_subr.c | 122 +++++++++++++++++++++ 9 files changed, 781 insertions(+) create mode 100644 sys/fs/initramfs.c create mode 100644 sys/include/fs/initramfs.h create mode 100644 sys/include/sys/mount.h create mode 100644 sys/include/sys/namei.h create mode 100644 sys/include/sys/vnode.h create mode 100644 sys/kern/vfs_init.c create mode 100644 sys/kern/vfs_lookup.c create mode 100644 sys/kern/vfs_subr.c (limited to 'sys') diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c new file mode 100644 index 0000000..4c47da8 --- /dev/null +++ b/sys/fs/initramfs.c @@ -0,0 +1,263 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#define CPIO_TRAILER "TRAILER!!!" + +/* + * File or directory. + */ +struct initramfs_node { + const char *path; /* Path */ + void *data; /* File data */ + size_t size; /* File size */ + mode_t mode; /* Perms and type */ +}; + +/* + * ODC CPIO header + */ +struct cpio_hdr { + char c_magic[6]; + char c_dev[6]; + char c_ino[6]; + char c_mode[6]; + char c_uid[6]; + char c_gid[6]; + char c_nlink[6]; + char c_rdev[6]; + char c_mtime[11]; + char c_namesize[6]; + char c_filesize[11]; +}; + +static volatile struct limine_module_request mod_req = { + .id = LIMINE_MODULE_REQUEST, + .revision = 0 +}; + +static const char *initramfs = NULL; +static uint64_t initramfs_size; + +/* + * Fetch a module from the bootloader. + * This is used to fetch the ramfs image. + */ +static char * +get_module(const char *path, uint64_t *size) { + for (uint64_t i = 0; i < mod_req.response->module_count; ++i) { + if (strcmp(mod_req.response->modules[i]->path, path) == 0) { + *size = mod_req.response->modules[i]->size; + return mod_req.response->modules[i]->address; + } + } + + return NULL; +} + +/* + * Convert octal to base 10 + */ +static uint32_t +oct2dec(const char *in, size_t sz) +{ + size_t val = 0; + + for (size_t i = 0; i < sz; ++i) { + val = val * 8 + (in[i] - '0'); + } + + return val; +} + +/* + * Get a file from initramfs + * + * @path: Path of file to get. + * @res: Pointer to new resulting node. + */ +static int +initramfs_get_file(const char *path, struct initramfs_node *res) +{ + const struct cpio_hdr *hdr; + struct initramfs_node node; + uintptr_t addr; + size_t namesize, filesize; + mode_t mode; + + addr = (uintptr_t)initramfs; + for (;;) { + hdr = (void *)addr; + namesize = oct2dec(hdr->c_namesize, sizeof(hdr->c_namesize)); + filesize = oct2dec(hdr->c_filesize, sizeof(hdr->c_filesize)); + mode = oct2dec(hdr->c_mode, sizeof(hdr->c_mode)); + + /* Make sure the magic is correct */ + if (strncmp(hdr->c_magic, "070707", 6) != 0) { + return -EINVAL; + } + + addr += sizeof(struct cpio_hdr); + node.path = (const char *)addr; + + /* Is this the requested file? */ + if (strcmp(node.path, path) == 0) { + node.data = (void *)(addr + namesize); + node.size = filesize; + node.mode = mode; + *res = node; + return 0; + } + + /* Get next header and see if we are at the end */ + addr += (namesize + filesize); + if (strcmp(node.path, CPIO_TRAILER) == 0) { + break; + } + } + + return -ENOENT; +} + +static int +initramfs_lookup(struct vop_lookup_args *args) +{ + int status, vtype; + struct initramfs_node *n; + struct vnode *vp; + const char *path = args->name; + + if (*path == '/') { + ++path; + } + + n = dynalloc(sizeof(*n)); + if (n == NULL) { + return -ENOMEM; + } + + /* Now does this file exist? */ + if ((status = initramfs_get_file(path, n)) != 0) { + dynfree(n); + return status; + } + + vtype = ISSET(n->mode, 0040000) ? VDIR : VREG; + + /* Try to create a new vnode */ + if ((status = vfs_alloc_vnode(&vp, vtype)) != 0) { + dynfree(n); + return status; + } + + vp->data = n; + vp->vops = &g_initramfs_vops; + *args->vpp = vp; + return 0; +} + +static int +initramfs_read(struct vnode *vp, struct sio_txn *sio) +{ + struct initramfs_node *n = vp->data; + uint8_t *src, *dest; + uint32_t count = 0; + + /* Ensure pointers are valid */ + if (n == NULL) + return -EIO; + if (sio->buf == NULL) + return -EIO; + + src = n->data; + dest = sio->buf; + + /* Copy the file data */ + for (size_t i = 0; i < sio->len; ++i) { + if ((sio->offset + i) >= n->size) { + break; + } + dest[i] = src[sio->offset + i]; + ++count; + } + + return count; +} + +static int +initramfs_reclaim(struct vnode *vp) +{ + if (vp->data != NULL) { + dynfree(vp->data); + } + + return 0; +} + +static int +initramfs_init(struct fs_info *fip) +{ + struct mount *mp; + int status; + + initramfs = get_module("/boot/ramfs.cpio", &initramfs_size); + if (initramfs == NULL) { + panic("Failed to open initramfs cpio image\n"); + } + + status = vfs_alloc_vnode(&g_root_vnode, VDIR); + if (__unlikely(status != 0)) { + panic("Failed to create root vnode for ramfs\n"); + } + + g_root_vnode->vops = &g_initramfs_vops; + mp = vfs_alloc_mount(g_root_vnode, fip); + TAILQ_INSERT_TAIL(&g_mountlist, mp, mnt_list); + return 0; +} + +const struct vops g_initramfs_vops = { + .lookup = initramfs_lookup, + .read = initramfs_read, + .reclaim = initramfs_reclaim +}; + +const struct vfsops g_initramfs_vfsops = { + .init = initramfs_init +}; diff --git a/sys/include/fs/initramfs.h b/sys/include/fs/initramfs.h new file mode 100644 index 0000000..897079c --- /dev/null +++ b/sys/include/fs/initramfs.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#ifndef _INITRAMFS_H_ +#define _INITRAMFS_H_ + +#include + +extern const struct vops g_initramfs_vops; + +#endif /* _INITRAMFS_H_ */ diff --git a/sys/include/sys/mount.h b/sys/include/sys/mount.h new file mode 100644 index 0000000..e46cda9 --- /dev/null +++ b/sys/include/sys/mount.h @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#ifndef _SYS_MOUNT_H_ +#define _SYS_MOUNT_H_ + +#include +#include +#include +#include +#include + +#if defined(_KERNEL) + +#define FS_NAME_MAX 16 /* Length of fs name including nul */ + +/* + * Filesystem types. + */ +#define MOUNT_RAMFS "initramfs" + +struct vfsops; +struct mount; + +/* Mount list */ +typedef TAILQ_HEAD(, mount) mountlist_t; +extern mountlist_t g_mountlist; + +/* Filesystem operations */ +extern const struct vfsops g_initramfs_vfsops; + +struct mount { + struct spinlock lock; + struct vnode *vp; + const struct vfsops *mnt_ops; + void *data; + TAILQ_ENTRY(mount) mnt_list; +}; + +struct fs_info { + char name[FS_NAME_MAX]; /* FS Type name */ + const struct vfsops *vfsops; /* Operations vector */ + int flags; /* Flags for this filesystem */ + int refcount; /* Mount count of this type */ +}; + +struct vfsops { + int(*init)(struct fs_info *fip); + int(*mount)(struct mount *mp, const char *path, void *data, + struct nameidata *ndp); +}; + +void vfs_init(void); +struct mount *vfs_alloc_mount(struct vnode *vp, struct fs_info *fip); +struct fs_info *vfs_byname(const char *name); + +#endif /* _KERNEL */ +#endif /* _SYS_MOUNT_H_ */ diff --git a/sys/include/sys/namei.h b/sys/include/sys/namei.h new file mode 100644 index 0000000..bd3c0db --- /dev/null +++ b/sys/include/sys/namei.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef _SYS_NAMEI_H_ +#define _SYS_NAMEI_H_ + +#include +#include + +struct nameidata { + const char *path; /* Pathname */ + uint32_t flags; + struct vnode *vp; /* Vnode result */ +}; + +int namei(struct nameidata *ndp); + +#endif /* !_SYS_NAMEI_H_ */ diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h new file mode 100644 index 0000000..1caf2cb --- /dev/null +++ b/sys/include/sys/vnode.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +#ifndef _SYS_VNODE_H_ +#define _SYS_VNODE_H_ + +#include + +#if defined(_KERNEL) + +struct vops; + +struct vnode { + int type; + int flags; + void *data; + const struct vops *vops; +}; + +/* Vnode type flags */ +#define VNON 0x00 /* Uninitialized */ +#define VREG 0x01 /* Regular file */ +#define VDIR 0x02 /* Directory */ +#define VCHR 0x03 /* Character device */ +#define VBLK 0x04 /* Block device */ + +struct vop_lookup_args { + const char *name; /* Current path component */ + struct vnode *dirvp; /* Directory vnode */ + struct vnode **vpp; /* Result vnode */ +}; + +struct vops { + int(*lookup)(struct vop_lookup_args *args); + int(*read)(struct vnode *vp, struct sio_txn *sio); + int(*reclaim)(struct vnode *vp); +}; + +extern struct vnode *g_root_vnode; + +int vfs_alloc_vnode(struct vnode **res, int type); +int vfs_release_vnode(struct vnode *vp); + +int vfs_vop_lookup(struct vnode *vp, struct vop_lookup_args *args); +int vfs_vop_read(struct vnode *vp, struct sio_txn *sio); + +#endif /* _KERNEL */ +#endif /* !_SYS_VNODE_H_ */ diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 6018dfe..09b8d2d 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,9 @@ main(void) /* Startup the BSP */ cpu_startup(&g_bsp_ci); + /* Init the virtual file system */ + vfs_init(); + /* Start scheduler and bootstrap APs */ sched_init(); mp_bootstrap_aps(&g_bsp_ci); diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c new file mode 100644 index 0000000..aafbc00 --- /dev/null +++ b/sys/kern/vfs_init.c @@ -0,0 +1,70 @@ +/* + * 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 +#include +#include + +struct vnode *g_root_vnode = NULL; +static struct fs_info fs_list[] = { + {MOUNT_RAMFS, &g_initramfs_vfsops, 0, 0}, +}; + +void +vfs_init(void) +{ + struct fs_info *fs; + const struct vfsops *vfsops; + + TAILQ_INIT(&g_mountlist); + + for (size_t i= 0; i < NELEM(fs_list); ++i) { + fs = &fs_list[i]; + vfsops = fs->vfsops; + + /* Try to initialize the filesystem */ + if (vfsops->init != NULL) { + vfsops->init(fs); + } + } +} + +struct fs_info * +vfs_byname(const char *name) +{ + for (int i = 0; i < NELEM(fs_list); ++i) { + if (strcmp(fs_list[i].name, name) == 0) { + return &fs_list[i]; + } + } + + return NULL; +} diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c new file mode 100644 index 0000000..83924c6 --- /dev/null +++ b/sys/kern/vfs_lookup.c @@ -0,0 +1,83 @@ +/* + * 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 +#include +#include + +/* + * Convert a path to a vnode. + * + * @ndp: Nameidata containing the path and resulting + * vnode. + * + * TODO: Add support for lookups with individual + * path components + */ +int +namei(struct nameidata *ndp) +{ + struct vnode *vp; + struct vop_lookup_args lookup_args; + const char *path = ndp->path; + int status; + + if (path == NULL) { + return -EINVAL; + } + + /* Path must start with "/" */ + if (*path != '/') { + return -EINVAL; + } + + /* Just return the root vnode if we can */ + if (strcmp(path, "/") == 0) { + ndp->vp = g_root_vnode; + return 0; + } + + /* + * Some filesystems (like initramfs) may only understand + * full paths, so try passing it through. + */ + lookup_args.name = path; + lookup_args.dirvp = g_root_vnode; + lookup_args.vpp = &vp; + status = vfs_vop_lookup(lookup_args.dirvp, &lookup_args); + + if (status != 0) { + return status; + } + + ndp->vp = vp; + return 0; +} diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c new file mode 100644 index 0000000..04d64e3 --- /dev/null +++ b/sys/kern/vfs_subr.c @@ -0,0 +1,122 @@ +/* + * 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 +#include +#include + +mountlist_t g_mountlist; + +int +vfs_alloc_vnode(struct vnode **res, int type) +{ + struct vnode *vp = dynalloc(sizeof(struct vnode)); + + if (vp == NULL) { + return -ENOMEM; + } + + memset(vp, 0, sizeof(*vp)); + vp->type = type; + *res = vp; + return 0; +} + +/* + * Allocate a mount structure. + * + * @vp: Vnode this mount structure covers. + * @fip: File system information. + */ +struct mount * +vfs_alloc_mount(struct vnode *vp, struct fs_info *fip) +{ + struct mount *mp; + + mp = dynalloc(sizeof(*mp)); + + if (mp == NULL) { + return NULL; + } + + memset(mp, 0, sizeof(*mp)); + mp->vp = vp; + mp->mnt_ops = fip->vfsops; + return mp; +} + +/* + * Release a vnode and its resources from + * memory. + */ +int +vfs_release_vnode(struct vnode *vp) +{ + const struct vops *vops = vp->vops; + int status = 0; + + if (vp == NULL) { + return -EINVAL; + } + + if (vops->reclaim != NULL) { + status = vops->reclaim(vp); + } + + dynfree(vp); + return status; +} + +int +vfs_vop_lookup(struct vnode *vp, struct vop_lookup_args *args) +{ + const struct vops *vops = vp->vops; + + if (vops == NULL) + return -EIO; + if (vops->lookup == NULL) + return -EIO; + + return vops->lookup(args); +} + +int +vfs_vop_read(struct vnode *vp, struct sio_txn *sio) +{ + const struct vops *vops = vp->vops; + + if (vops == NULL) + return -EIO; + if (vops->read == NULL) + return -EIO; + + return vops->read(vp, sio); +} -- cgit v1.2.3