diff options
-rw-r--r-- | sys/fs/devfs.c | 190 | ||||
-rw-r--r-- | sys/include/fs/devfs.h | 40 | ||||
-rw-r--r-- | sys/include/sys/mount.h | 2 | ||||
-rw-r--r-- | sys/kern/vfs_init.c | 1 |
4 files changed, 233 insertions, 0 deletions
diff --git a/sys/fs/devfs.c b/sys/fs/devfs.c new file mode 100644 index 0000000..c1eb761 --- /dev/null +++ b/sys/fs/devfs.c @@ -0,0 +1,190 @@ +/* + * 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 <sys/types.h> +#include <sys/vnode.h> +#include <sys/errno.h> +#include <sys/mount.h> +#include <sys/device.h> +#include <fs/devfs.h> +#include <vm/dynalloc.h> +#include <string.h> + +struct devfs_node { + const char *name; + uint8_t is_block : 1; + mode_t mode; + devmajor_t major; + dev_t dev; + TAILQ_ENTRY(devfs_node) link; +}; + +static TAILQ_HEAD(, devfs_node) devlist; + +static inline int +cdevsw_read(void *devsw, dev_t dev, struct sio_txn *sio) +{ + struct cdevsw *cdevsw = devsw; + + return cdevsw->read(dev, sio, 0); +} + +/* + * Get a devfs node by name. + * + * @name: Name to lookup. + */ +static struct devfs_node * +devfs_get_node(const char *name) +{ + struct devfs_node *dnp; + + TAILQ_FOREACH(dnp, &devlist, link) { + if (strcmp(dnp->name, name) == 0) { + return dnp; + } + } + + return NULL; +} + +static int +devfs_lookup(struct vop_lookup_args *args) +{ + int vtype, error; + const char *name = args->name; + struct devfs_node *dnp; + struct vnode *vp; + + if (*name == '/') + ++name; + + /* Make sure it isn't a path */ + for (const char *p = name; *p != '\0'; ++p) { + if (*p == '/') { + return -ENOENT; + } + } + + if ((dnp = devfs_get_node(name)) == NULL) + return -ENOENT; + + /* Now, create a vnode */ + vtype = (dnp->is_block) ? VBLK : VCHR; + if ((error = vfs_alloc_vnode(&vp, vtype)) != 0) + return error; + + vp->data = dnp; + vp->vops = &g_devfs_vops; + *args->vpp = vp; + return 0; +} + +static int +devfs_reclaim(struct vnode *vp) +{ + if (vp->data != NULL) + dynfree(vp->data); + + vp->data = NULL; + return 0; +} + +static int +devfs_read(struct vnode *vp, struct sio_txn *sio) +{ + struct devfs_node *dnp; + void *devsw; + + if ((dnp = vp->data) == NULL) + return -EIO; + + devsw = dev_get(dnp->major, dnp->dev); + + if (!dnp->is_block) + return cdevsw_read(devsw, dnp->dev, sio); + + /* TODO: Block devices */ + return -EIO; +} + +static int +devfs_init(struct fs_info *fip) +{ + struct vnode *vp; + struct mount *mp; + int error; + + /* Create a new vnode for devfs */ + if ((error = vfs_alloc_vnode(&vp, VDIR)) != 0) + return error; + + vp->vops = &g_devfs_vops; + TAILQ_INIT(&devlist); + mp = vfs_alloc_mount(vp, fip); + + vfs_name_mount(mp, "dev"); + TAILQ_INSERT_TAIL(&g_mountlist, mp, mnt_list); + return 0; +} + +/* + * Create an entry within devfs. + * + * @name: Device name. + * @major: Device major. + * @dev: Device minor. + * @mode: Permissions mask + */ +int +devfs_create_entry(const char *name, devmajor_t major, dev_t dev, mode_t mode) +{ + struct devfs_node *dnp; + + dnp = dynalloc(sizeof(*dnp)); + if (dnp == NULL) + return -ENOMEM; + + dnp->name = name; + dnp->major = major; + dnp->dev = dev; + dnp->mode = mode; + TAILQ_INSERT_TAIL(&devlist, dnp, link); + return 0; +} + +const struct vops g_devfs_vops = { + .lookup = devfs_lookup, + .reclaim = devfs_reclaim, + .read = devfs_read +}; + +const struct vfsops g_devfs_vfsops = { + .init = devfs_init +}; diff --git a/sys/include/fs/devfs.h b/sys/include/fs/devfs.h new file mode 100644 index 0000000..ddc1567 --- /dev/null +++ b/sys/include/fs/devfs.h @@ -0,0 +1,40 @@ +/* + * 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 _FS_DEVFS_H_ +#define _FS_DEVFS_H_ + +#include <sys/vnode.h> +#include <sys/types.h> + +extern const struct vops g_devfs_vops; + +int devfs_create_entry(const char *name, devmajor_t major, dev_t dev, mode_t mode); + +#endif /* !_FS_DEVFS_H_ */ diff --git a/sys/include/sys/mount.h b/sys/include/sys/mount.h index e12b880..bfd0d21 100644 --- a/sys/include/sys/mount.h +++ b/sys/include/sys/mount.h @@ -45,6 +45,7 @@ * Filesystem types. */ #define MOUNT_RAMFS "initramfs" +#define MOUNT_DEVFS "devfs" struct vfsops; struct mount; @@ -55,6 +56,7 @@ extern mountlist_t g_mountlist; /* Filesystem operations */ extern const struct vfsops g_initramfs_vfsops; +extern const struct vfsops g_devfs_vfsops; struct mount { char *name; diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index aafbc00..ab18d09 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -36,6 +36,7 @@ struct vnode *g_root_vnode = NULL; static struct fs_info fs_list[] = { {MOUNT_RAMFS, &g_initramfs_vfsops, 0, 0}, + {MOUNT_DEVFS, &g_devfs_vfsops, 0, 0} }; void |