Add basic devfs
This commit is contained in:
+2
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
+15
-5
@@ -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;
|
||||
|
||||
@@ -46,6 +46,7 @@ mkdirs:
|
||||
mkdir -p $(DIRS)
|
||||
|
||||
mkstage-etc:
|
||||
mkdir -p $(STAGE)/dev
|
||||
cp -r etc $(STAGE)
|
||||
|
||||
# Application building
|
||||
|
||||
+19
-1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user