diff --git a/etc/make/conf.mk b/etc/make/conf.mk index 88c6535..4928f37 100644 --- a/etc/make/conf.mk +++ b/etc/make/conf.mk @@ -64,7 +64,8 @@ OBJS+=$(O)/sys/debug.o \ $(O)/sys/net/eth.o \ $(O)/sys/net/arp.o \ $(O)/sys/net/in.o \ - $(O)/sys/net/netdev.o + $(O)/sys/net/netdev.o \ + $(O)/sys/vfs/devfs.o DIRS+=$(O)/sys/vfs/ext2 \ $(O)/sys/net \ $(O)/sys/blk diff --git a/include/sys/dev.h b/include/sys/dev.h index b209ab1..343c477 100644 --- a/include/sys/dev.h +++ b/include/sys/dev.h @@ -1,6 +1,9 @@ #pragma once #include "sys/types.h" +// TODO: something like device name alias +// for example, /dev/root aliased to +// /dev/ramN or /dev/sdXN enum dev_class { DEV_CLASS_BLOCK, DEV_CLASS_CHAR diff --git a/include/sys/fs/devfs.h b/include/sys/fs/devfs.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/include/sys/fs/devfs.h @@ -0,0 +1 @@ +#pragma once diff --git a/sys/amd64/mm/heap.c b/sys/amd64/mm/heap.c index 88e4dcf..659a96d 100644 --- a/sys/amd64/mm/heap.c +++ b/sys/amd64/mm/heap.c @@ -44,7 +44,7 @@ void *heap_alloc(heap_t *heap, size_t count) { heap_block_t *begin = (heap_block_t *) MM_VIRTUALIZE(heap->phys_base); // Some alignment fuck ups led me to this - count = (count + 31) & ~31; + count = (count + 15) & ~15; for (heap_block_t *block = begin; block; block = block->next) { if ((block->magic & HEAP_MAGIC) != HEAP_MAGIC) { diff --git a/sys/amd64/sys/sched.c b/sys/amd64/sys/sched.c index 28b52f4..775a3dc 100644 --- a/sys/amd64/sys/sched.c +++ b/sys/amd64/sys/sched.c @@ -56,6 +56,11 @@ void init_func(void *arg) { panic("mount rootfs: %s\n", kstrerror(res)); } + // Mount devfs + if ((res = vfs_mount(&ioctx, "/dev", NULL, "devfs", NULL)) != 0) { + panic("mount devfs: %s\n", kstrerror(res)); + } + if ((res = vfs_stat(&ioctx, "/init", &st)) != 0) { panic("/init: %s\n", kstrerror(res)); } diff --git a/sys/vfs/devfs.c b/sys/vfs/devfs.c new file mode 100644 index 0000000..7b93070 --- /dev/null +++ b/sys/vfs/devfs.c @@ -0,0 +1,84 @@ +#include "sys/fs/devfs.h" +#include "sys/fs/vfs.h" +#include "sys/string.h" +#include "sys/fs/fs.h" +#include "sys/debug.h" +#include "sys/panic.h" +#include "sys/attr.h" +#include "sys/heap.h" + +static int devfs_node_mapper(fs_t *devfs, struct vfs_node **root); + +static struct fs_class _devfs = { + .name = "devfs", + .opt = FS_NODE_MAPPER, + .mapper = devfs_node_mapper +}; + +static struct vnode_operations _devfs_vnode_op = { +}; + +static vnode_t *devfs_create_vnode(fs_t *fs, struct vfs_node *node) { + vnode_t *res = (vnode_t *) kmalloc(sizeof(vnode_t)); + res->tree_node = node; + res->fs = fs; + res->fs_data = NULL; + res->refcount = 0; + res->op = &_devfs_vnode_op; + res->type = VN_DIR; + return res; +} + +// TODO: handle devices added post-mapper + +static int devfs_node_mapper(fs_t *devfs, struct vfs_node **root) { + struct vfs_node *_root; + struct dev_entry *it; + + // Make a root node + _root = (struct vfs_node *) kmalloc(sizeof(struct vfs_node)); + _root->child = NULL; + _root->cdr = NULL; + _root->ismount = 0; + _root->parent = NULL; + _root->real_vnode = NULL; + _root->vnode = NULL; + + // TODO: directory-categories (like "by-uuid" or something) + for (it = dev_iter(); it; it = it->cdr) { + struct vfs_node *ent_node = kmalloc(sizeof(struct vfs_node)); + ent_node->child = NULL; + ent_node->ismount = 0; + ent_node->real_vnode = NULL; + strcpy(ent_node->name, it->dev_name); + + // Create a vnode for device + vnode_t *ent_vnode = devfs_create_vnode(devfs, ent_node); + if (it->dev_class == DEV_CLASS_BLOCK) { + ent_vnode->type = VN_BLK; + } else if (it->dev_class == DEV_CLASS_CHAR) { + ent_vnode->type = VN_CHR; + } else { + panic("Unsupported device class\n"); + } + ent_vnode->fs_data = it; + ent_vnode->dev = it->dev; + + ent_node->vnode = ent_vnode; + + ent_node->parent = _root; + ent_node->cdr = _root->child; + _root->child = ent_node; + } + + vnode_t *vnode = devfs_create_vnode(devfs, _root); + _root->vnode = vnode; + + *root = _root; + + return 0; +} + +static __init void devfs_init(void) { + fs_class_register(&_devfs); +} diff --git a/sys/vfs/vfs.c b/sys/vfs/vfs.c index fa44d17..20922fe 100644 --- a/sys/vfs/vfs.c +++ b/sys/vfs/vfs.c @@ -829,9 +829,6 @@ int vfs_open_node(struct vfs_ioctx *ctx, struct ofile *of, vnode_t *vn, int opt) if (vn->type == VN_DIR) { return -EISDIR; } - if (vn->type != VN_REG) { - panic("Not implemented\n"); - } of->vnode = vn; of->flags = opt; @@ -938,6 +935,8 @@ ssize_t vfs_read(struct vfs_ioctx *ctx, struct ofile *fd, void *buf, size_t coun vnode_t *vn = fd->vnode; _assert(vn); + ssize_t nr; + switch (vn->type) { case VN_REG: _assert(vn->op); @@ -956,7 +955,7 @@ ssize_t vfs_read(struct vfs_ioctx *ctx, struct ofile *fd, void *buf, size_t coun return -EINVAL; } - ssize_t nr = vn->op->read(fd, buf, count); + nr = vn->op->read(fd, buf, count); if (nr > 0) { fd->pos += nr; @@ -967,7 +966,12 @@ ssize_t vfs_read(struct vfs_ioctx *ctx, struct ofile *fd, void *buf, size_t coun // We don't need filesystem at all to read from devices case VN_BLK: _assert(vn->dev); - return blk_read((struct blkdev *) vn->dev, buf, fd->pos, count); + + if ((nr = blk_read((struct blkdev *) vn->dev, buf, fd->pos, count)) > 0) { + fd->pos += nr; + } + + return nr; case VN_CHR: _assert(vn->dev); return chr_read((struct chrdev *) vn->dev, buf, fd->pos, count); @@ -1227,6 +1231,12 @@ struct dirent *vfs_readdir(struct vfs_ioctx *ctx, struct ofile *fd) { case VN_DIR: ent_buf->d_type = DT_DIR; break; + case VN_BLK: + ent_buf->d_type = DT_BLK; + break; + case VN_CHR: + ent_buf->d_type = DT_CHR; + break; default: kwarn("Unsupported vnode type: %d\n", item_node->vnode->type); ent_buf->d_type = DT_UNKNOWN; diff --git a/usr/Makefile b/usr/Makefile index 87fb99a..8b94c1e 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -46,6 +46,7 @@ mkdirs: mkdir -p $(DIRS) mkstage-etc: + mkdir -p $(STAGE)/dev cp -r etc $(STAGE) # Application building diff --git a/usr/init.c b/usr/init.c index 43a273e..bca1f35 100644 --- a/usr/init.c +++ b/usr/init.c @@ -86,7 +86,25 @@ static int cmd_exec(const char *cmd) { } while ((ent = readdir(dir))) { - printf("%c %s\n", ent->d_type == DT_DIR ? 'D' : '-', ent->d_name); + char type; + switch (ent->d_type) { + case DT_REG: + type = '-'; + break; + case DT_DIR: + type = 'D'; + break; + case DT_BLK: + type = 'b'; + break; + case DT_CHR: + type = 'c'; + break; + default: + type = '?'; + break; + } + printf("%c %s\n", type, ent->d_name); } closedir(dir);