diff options
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/arch/amd64/driver/fsroot.c | 103 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/pata.c | 13 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/ps2.c | 10 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/video.c | 6 | ||||
-rw-r--r-- | src/kernel/vfs/mount.c | 5 |
5 files changed, 87 insertions, 50 deletions
diff --git a/src/kernel/arch/amd64/driver/fsroot.c b/src/kernel/arch/amd64/driver/fsroot.c index ed7e88c..0eef12f 100644 --- a/src/kernel/arch/amd64/driver/fsroot.c +++ b/src/kernel/arch/amd64/driver/fsroot.c @@ -2,59 +2,90 @@ #include <camellia/fsutil.h> #include <kernel/arch/amd64/driver/driver.h> #include <kernel/arch/amd64/driver/util.h> +#include <kernel/malloc.h> #include <kernel/panic.h> #include <kernel/proc.h> #include <kernel/util.h> +#include <kernel/vfs/mount.h> #include <kernel/vfs/request.h> #include <shared/mem.h> -static long handle(VfsReq *req) { - // TODO document directory read format - // TODO don't hardcode - static const char base[] = "kdev/"; - static const char dir[] = - "com1\0" - "ps2/\0" - "ata/\0" - "eth\0" - "video/"; - const char *id; - int len; +enum { + Hbase, + Hkdev, +}; + +static int +get_kdev(char *lst) +{ + int len = 0; + for (VfsMount *m = vfs_mount_seed(); m; m = m->prev) { + if (m->prefix_len == 0) { + continue; /* that's us */ + } + assert(m->prefix_len > 6); + assert(memcmp(m->prefix, "/kdev/", 6) == 0); + len += m->prefix_len - 6 + 1; + if (lst) { + memcpy(lst, m->prefix + 6, m->prefix_len - 6); + lst += m->prefix_len - 6; + *lst++ = '\0'; + } + } + return len; +} + +static long +handle(VfsReq *req) +{ + static char *kdev = NULL; + static int kdev_len = 0; + const char *lst = NULL; + int len = 0; if (!req->caller) return -1; if (req->type != VFSOP_OPEN) { - /* otherwise, uninitialized, to cause compiler warnings if used */ - /* this operates under the assumption that base and dir never change - * but even if they do, that will just result in a crash. */ - id = (void *__force)req->id; - if (id == base) { - len = sizeof base; - } else if (id == dir) { - len = sizeof dir; - } else { - kprintf("%p %p %p\n", base, dir, id); + switch ((uintptr_t __force)req->id) { + case Hbase: + lst = "kdev/"; + len = strlen(lst) + 1; + break; + case Hkdev: + if (!kdev) { + kdev_len = get_kdev(NULL); + kdev = kmalloc(kdev_len); + get_kdev(kdev); + } + lst = kdev; + len = kdev_len; + break; + default: assert(false); } } switch (req->type) { - case VFSOP_OPEN: - if (reqpathcmp(req, "/")) return (long)base; - if (reqpathcmp(req, "/kdev/")) return (long)dir; - return -ENOENT; - - case VFSOP_READ: - return req_readcopy(req, id, len); - // TODO getsize for the other kernel provided directories - case VFSOP_GETSIZE: - return len; - default: - return -ENOSYS; + case VFSOP_OPEN: + if (reqpathcmp(req, "/")) return Hbase; + if (reqpathcmp(req, "/kdev/")) return Hkdev; + return -ENOENT; + case VFSOP_READ: + return req_readcopy(req, lst, len); + case VFSOP_GETSIZE: + return len; + default: + return -ENOSYS; } } -static void accept(VfsReq *req) { +static void +accept(VfsReq *req) +{ vfsreq_finish_short(req, handle(req)); } -void vfs_root_init(void) { vfs_root_register("", accept); } +void +vfs_root_init(void) +{ + vfs_root_register("", accept); +} diff --git a/src/kernel/arch/amd64/driver/pata.c b/src/kernel/arch/amd64/driver/pata.c index b0058f8..da8b541 100644 --- a/src/kernel/arch/amd64/driver/pata.c +++ b/src/kernel/arch/amd64/driver/pata.c @@ -13,7 +13,7 @@ static const int root_id = 100; static void accept(VfsReq *req); void pata_init(void) { ata_init(); - vfs_root_register("/kdev/ata", accept); + vfs_root_register("/kdev/ata/", accept); } static void accept(VfsReq *req) { @@ -23,11 +23,11 @@ static void accept(VfsReq *req) { size_t len; switch (req->type) { case VFSOP_OPEN: - if (reqpathcmp(req, "/")) ret = root_id; - else if (reqpathcmp(req, "/0")) ret = 0; - else if (reqpathcmp(req, "/1")) ret = 1; - else if (reqpathcmp(req, "/2")) ret = 2; - else if (reqpathcmp(req, "/3")) ret = 3; + if (reqpathcmp(req, "")) ret = root_id; + else if (reqpathcmp(req, "0")) ret = 0; + else if (reqpathcmp(req, "1")) ret = 1; + else if (reqpathcmp(req, "2")) ret = 2; + else if (reqpathcmp(req, "3")) ret = 3; else ret = -ENOENT; // TODO don't allow opening nonexistent drives vfsreq_finish_short(req, ret); @@ -70,6 +70,7 @@ static void accept(VfsReq *req) { case VFSOP_GETSIZE: if (id == root_id) { + // TODO getsize for all kernel provided directories panic_unimplemented(); } vfsreq_finish_short(req, ata_size(id)); diff --git a/src/kernel/arch/amd64/driver/ps2.c b/src/kernel/arch/amd64/driver/ps2.c index e314477..f2a98a2 100644 --- a/src/kernel/arch/amd64/driver/ps2.c +++ b/src/kernel/arch/amd64/driver/ps2.c @@ -58,7 +58,7 @@ void ps2_init(void) { irq_fn[IRQ_PS2KB] = ps2_irq; irq_fn[IRQ_PS2MOUSE] = ps2_irq; - vfs_root_register("/kdev/ps2", accept); + vfs_root_register("/kdev/ps2/", accept); } static void ps2_irq(void) { @@ -86,10 +86,10 @@ static void accept(VfsReq *req) { int ret; switch (req->type) { case VFSOP_OPEN: - if (reqpathcmp(req, "/")) ret = H_ROOT; - else if (reqpathcmp(req, "/kb")) ret = H_KB; - else if (reqpathcmp(req, "/mouse")) ret = H_MOUSE; - else ret = -ENOENT; + if (reqpathcmp(req, "")) ret = H_ROOT; + else if (reqpathcmp(req, "kb")) ret = H_KB; + else if (reqpathcmp(req, "mouse")) ret = H_MOUSE; + else ret = -ENOENT; vfsreq_finish_short(req, ret); break; case VFSOP_READ: diff --git a/src/kernel/arch/amd64/driver/video.c b/src/kernel/arch/amd64/driver/video.c index 5a7fc8f..390e8dd 100644 --- a/src/kernel/arch/amd64/driver/video.c +++ b/src/kernel/arch/amd64/driver/video.c @@ -21,9 +21,9 @@ static int handle(VfsReq *req) { switch (req->type) { case VFSOP_OPEN: if (!req->input.kern) panic_invalid_state(); - if (req->input.len == 1) { + if (req->input.len == 0) { return H_ROOT; - } else if (req->input.len == namelen + 1 && !memcmp(req->input.buf_kern + 1, namebuf, namelen)) { + } else if (req->input.len == namelen && !memcmp(req->input.buf_kern, namebuf, namelen)) { return H_FB; } else { return -1; @@ -65,5 +65,5 @@ void video_init(GfxInfo fb_) { fb = fb_; snprintf(namebuf, sizeof namebuf, "%ux%ux%u", fb.width, fb.height, fb.bpp); namelen = strlen(namebuf); - vfs_root_register("/kdev/video", accept); + vfs_root_register("/kdev/video/", accept); } diff --git a/src/kernel/vfs/mount.c b/src/kernel/vfs/mount.c index b4f5b0f..c153c69 100644 --- a/src/kernel/vfs/mount.c +++ b/src/kernel/vfs/mount.c @@ -45,6 +45,11 @@ VfsMount *vfs_mount_resolve( break; if (path[top->prefix_len] == '/') break; + + /* Also valid if prefix ends with '/'. Can only happen with kernel- + * provided mounts. */ + if (top->prefix_len != 0 && path[top->prefix_len-1] == '/') + break; } return top; } |