9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 25d8177f547c9ff8acf80948f309c0314e1e20a6
parent b7d1ae79887456cb1901d648497ad60d36411db1
Author: Roberto Vargas <roberto.vargas@arm.com>
Date:   Fri, 16 Nov 2018 09:58:08 +0000

[fs] Add initial version of the namespace framework

Change-Id: Ifabf930948abffb57aaf9944dec6c9e9cc757cad

Diffstat:
March/amd64/rom.c | 9+++++++++
Minclude/rcode.h | 60+++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/dlang/dlang.c | 25+++++++++++++++++++++++++
Msrc/ramfw/Makefile | 1+
Asrc/ramfw/fs.c | 10++++++++++
Msrc/romfw/Makefile | 3+++
Asrc/romfw/dirfs.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/romfw/drvfs.c | 13+++++++++++++
Asrc/romfw/fs.c | 326+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/romfw/fs.h | 25+++++++++++++++++++++++++
10 files changed, 562 insertions(+), 5 deletions(-)

diff --git a/arch/amd64/rom.c b/arch/amd64/rom.c @@ -2,10 +2,19 @@ #include <rcode.h> +struct tree tree[] = { + {"/dev", FSDIR | FSCREATE | FSREAD}, + {"/dev/uart", FSDIR | FSREAD}, + {"/realms", FSDIR | FSREAD}, + {NULL} +}; + int main(int argc, char *argv[]) { memset(bss, 0, sizeof(struct bssmap)); bss->fp = &(struct trapframe) {0}; + + initfs(tree); return debug(); } diff --git a/include/rcode.h b/include/rcode.h @@ -19,13 +19,23 @@ #ifndef NDEBUG #define dbg kprint +#define NR_EC_STR NR_EC_VALS #else #define dbg +#define NR_EC_STR 0 #endif #define PAGESIZE 4096 +#define NR_ENTS 20 /* TODO: This must go away of here */ +#define NR_FILS 8 /* TODO: This must go away of here */ +#define DIRLEN 10 + typedef struct rmucmd Rmucmd; +typedef int off_t; +typedef struct entry Entry; /* TODO: This must go away of here */ +typedef struct file File; /* TODO: This must go away of here */ +typedef struct fs Filsys; /* TODO: This must go away of here */ enum ecvals { UNKNOWN = 0x00, /* unknown reason */ @@ -73,11 +83,28 @@ enum ecvals { NR_EC_VALS }; -#ifdef NDEBUG -#define NR_EC_STR 0 -#else -#define NR_EC_STR NR_EC_VALS -#endif +enum fsflags { + FSCREATE = 1 << 0, + FSREAD = 1 << 1, + FSWRITE = 1 << 2, + FSDIR = 1 << 3, +}; + +struct entry { + const char *name; + const Filsys *fs; + void *arg; + size_t size; + unsigned short flags; + Entry *next; +}; + +struct file { + off_t off; + const Filsys *fs; + Entry *entry; + unsigned short flags; +}; struct bssmap { unsigned char in_panic; @@ -93,6 +120,15 @@ struct bssmap { unsigned char enable; /* System realm enablement */ unsigned char hascrypto; /* System-wide memory encryption */ + + int errno; + int ndir; + int nfil; + Entry root; + Entry driver; + Entry *cwd; + Entry enttbl[NR_ENTS]; + File filtbl[NR_FILS]; }; struct rowidx { @@ -130,6 +166,11 @@ struct rmucmd { unsigned class, func; }; +struct tree { + char *name; + int flags; +}; + extern _Noreturn void halt(void); extern _Noreturn void panic(const char *msg); extern _Noreturn void swtch(struct trapframe *fp); @@ -137,6 +178,15 @@ extern _Noreturn void trap(struct trapframe *fp); extern _Noreturn void badcmd(int error); extern void rmc(Rmucmd *cmd); extern int debug(void); +extern void initfs(const struct tree *tree); +extern int create(const char *name, int flags); +extern int open(const char *name, int flags); +extern int close(int fd); +extern int read(int fd, void *buf, int n); +extern int write(int fd, void *buf, int n); +extern int seek(int fd, off_t off, int whence); +extern int chdir(const char *path); +extern int bind(const char *path, char *where); /* libk */ extern struct bssmap *bss(void); diff --git a/src/dlang/dlang.c b/src/dlang/dlang.c @@ -239,6 +239,24 @@ do_help(const struct cmd *cmd, struct args *args) return 0; } +static int +do_cat(const struct cmd *cmd, struct args *args) +{ + int fd, n; + char buf[100]; + + if ((fd = open(args->argv[1], FSREAD)) < 0) + return -1; + + while ((n = read(fd, buf, sizeof(buf))) > 0) + kprint(PREFIX "%s\n", buf); + + if (close(fd) < 0 || n < 0) + return -1; + + return 0; +} + static const struct cmd * parse_cmd(char *buf, struct args *args) { @@ -374,6 +392,13 @@ static const struct cmd cmds[] = { .helpmsg = "Print this help menu: help", }, { + .name = "cat", + .eval = do_cat, + .min = 2, + .max = 2, + .helpmsg = "Print the content of an entry: cat path", + }, + { .name = NULL } }; diff --git a/src/ramfw/Makefile b/src/ramfw/Makefile @@ -4,6 +4,7 @@ include $(PROJECTDIR)/scripts/rules.mk OBJS = ../rmc.o \ ../ecstr.o \ + fs.o \ rmctbl.o \ all: builtin.o diff --git a/src/ramfw/fs.c b/src/ramfw/fs.c @@ -0,0 +1,10 @@ +#include <rcode.h> + +int create(const char *name, int flags){return 0;} +int open(const char *name, int flags){return 0;} +int close(int fd){return 0;} +int read(int fd, void *buf, int n){return 0;} +int write(int fd, void *buf, int n){return 0;} +int seek(int fd, off_t off, int whence){return 0;} +int chdir(const char *path){return 0;} +int bind(const char *path, char *where){return 0;} diff --git a/src/romfw/Makefile b/src/romfw/Makefile @@ -5,6 +5,9 @@ include $(PROJECTDIR)/scripts/rules.mk OBJS = ../rmc.o \ ../ecstr.o \ rmctbl.o \ + fs.o \ + drvfs.o \ + dirfs.o \ all: builtin.o diff --git a/src/romfw/dirfs.c b/src/romfw/dirfs.c @@ -0,0 +1,95 @@ +#include <string.h> +#include <rcode.h> + +#include "fs.h" + +static int +dirfs_open(File *fp, Walk *wp, int flags) +{ + fp->entry->arg = wp->entry->arg; + return 0; +} + +static int +dirfs_walk(Walk *wp, const char *name, int len) +{ + Entry *ep; + + for (ep = wp->entry->arg; ep; ep = ep->next) { + if (!strncmp(name, ep->name, len)) + break; + } + if (!ep) + return 0; + wp->fs = ep->fs; + wp->entry = ep; + + return 1; +} + +static int +dirfs_write(File *fp, void *buf, int n) +{ + Entry *ep; + + ep = fp->entry->arg; + if (!ep) + return 0; + + if ((ep->flags & FSWRITE) == 0) { + bss->errno = 1; + return -1; + } + return 0; +} + +static int +dirfs_read(File *fp, void *buf, int n) +{ + int len; + Entry *ep; + off_t off; + + ep = fp->entry; + if ((fp->flags & FSREAD) == 0) { + bss->errno = 1; + return -1; + } + + if ((ep->flags & FSDIR) == 0) { + len = 0; + } else { + off = 0; + for (ep = ep->arg; ep; ep = ep->next) { + if (fp->off == off) + break; + off++; + } + + if (!ep) + return 0; + + len = ksnprint(buf, n, + "%c%c%c %s %llu", + (ep->flags & FSDIR) ? 'd' : '-', + (ep->flags & FSREAD) ? 'r' : '-', + (ep->flags & FSWRITE) ? 'r' : '-', + ep->name, + (unsigned long long) ep->size); + if (len >= n) { + bss->errno = 1; + return -1; + } + fp->off++; + } + + return len; +} + +const Filsys dirfs = { + .flags = FSCREATE | FSREAD | FSWRITE, + .open = dirfs_open, + .read = dirfs_read, + .write = dirfs_write, + .walk = dirfs_walk, +}; diff --git a/src/romfw/drvfs.c b/src/romfw/drvfs.c @@ -0,0 +1,13 @@ +#include <rcode.h> + +#include "fs.h" + +int +drvfs_walk(Walk *wp, const char *name, int len) +{ + return 0; +} + +const Filsys drvfs = { + .walk = drvfs_walk, +}; diff --git a/src/romfw/fs.c b/src/romfw/fs.c @@ -0,0 +1,326 @@ +#include <string.h> +#include <rcode.h> + +#include "fs.h" + +static File * +validfd(int fd) +{ + if (fd < 0 || fd >= NR_FILS) { + bss->errno = 1; + return NULL; + } + return &bss->filtbl[fd]; +} + +static const char * +dentry(const char *s, int *len) +{ + const char *t; + + while (*s == '/') + ++s; + + if (*s == '\0') + return NULL; + + for (t = s; *t != '/' && *t != '\0'; t++) + ; + *len = t - s; + + return s; +} + +void +walk(const char *name, Walk *wp) +{ + const char *s; + int len; + + switch (*name) { + case '/': + wp->fs = bss->root.fs; + wp->entry = &bss->root; + s = name + 1; + break; + case '#': + wp->fs = bss->root.fs; + wp->entry = &bss->driver; + s = name + 1; + break; + default: + wp->fs = bss->cwd->fs; + wp->entry = bss->cwd; + s = name; + if (s[0] == '.' && s[1] == '\0') + s++; + break; + } + + while ((s = dentry(s, &len)) != NULL) { + if (!(*wp->fs->walk)(wp, s, len )) + break; + s += len; + } + wp->remaning = s; +} + +int +bind(const char *name, char *where) +{ + Walk w1, w2; + Entry *e1, *e2; + + walk(name, &w1); + if (!w1.entry) { + bss->errno = 1; + return -1; + } + + walk(where, &w2); + if (!w2.entry || (w2.entry->flags & FSDIR) == 0) { + bss->errno = 1; + return -1; + } + + e1 = w1.entry; + e2 = w2.entry; + e2->fs = w1.fs; + e2->arg = e1->arg; + e2->flags = e1->flags; + + return 0; +} + +int +chdir(const char *name) +{ + Walk w; + Entry *ep; + + walk(name, &w); + ep = w.entry; + if (!ep || (ep->flags & FSDIR) == 0) { + bss->errno = 1; + return -1; + } + bss->cwd = ep; + + return 0; +} + +int +open(const char *name, int flags) +{ + Walk w; + File *fp, *lim; + int (*fn)(File *fp, Walk *wp, int flags); + + if (flags == 0 || (flags & ~(FSREAD|FSWRITE)) != 0) { + bss->errno = 1; + return -1; + } + + walk(name, &w); + if (w.remaning) { + bss->errno = 1; + return -1; + } + + if ((w.fs->flags & flags) != flags) { + bss->errno = 1; + return 1; + } + + lim = &bss->filtbl[NR_FILS]; + for (fp = bss->filtbl; fp < lim && fp->entry; fp++) + ; + + if (fp == lim) { + bss->errno = 1; + return -1; + } + + fp->off = 0; + fp->entry = w.entry; + fp->fs = w.fs; + fp->flags = flags; + + fn = w.entry->fs->open; + if (fn && (*fn)(fp, &w, flags) < 0) + return -1; + + return fp - bss->filtbl; +} + +int +close(int fd) +{ + File *fp; + int (*fn)(File *fp); + + if ((fp = validfd(fd)) == NULL) + return -1; + + fn = fp->fs->close; + if (fn && (*fn)(fp) < 0) + return -1; + + fp->entry = NULL; + fp->off = 0; + + return 0; +} + +int +read(int fd, void *buf, int n) +{ + File *fp; + int (*fn)(File *fp, void *buf, int n); + + if ((fp = validfd(fd)) == NULL) + return -1; + + if ((fp->flags & FSREAD) == 0) { + bss->errno = 1; + return -1; + } + + fn = fp->fs->read; + if (!fn) { + bss->errno = 1; + return -1; + } + + return (*fn)(fp, buf, n); +} + +int +write(int fd, void *buf, int n) +{ + File *fp; + int (*fn)(File *fp, void *buf, int n); + + if ((fp = validfd(fd)) == NULL) + return -1; + + if ((fp->flags & FSWRITE) == 0) { + bss->errno = 1; + return -1; + } + + fn = fp->fs->write; + if (!fn) { + bss->errno = 1; + return -1; + } + + return (*fn)(fp, buf, n); +} + +int +seek(int fd, off_t off, int whence) +{ + File *fp; + int (*fn)(File *fp, off_t off, int whence); + + if ((fp = validfd(fd)) == NULL) + return -1; + + fn = fp->fs->seek; + if (!fn) { + bss->errno = 1; + return -1; + } + + return (*fn)(fp, off, whence); +} + +static int +validname(const char *name) +{ + const char *s; + size_t len; + + if (!name) + return 0; + + len = strlen(name); + if (len == 0 || len >= DIRLEN) + return 0; + + for (s = name; *s; ++s) { + switch (*s) { + case '/': + case ' ': + case '\n': + case '\t': + return 0; + } + } + return 1; +} + +int +create(const char *name, int flags) +{ + Entry *ep, *lim; + Walk w; + int mode; + + mode = flags & (FSREAD|FSWRITE); + if (mode == 0) { + bss->errno = 1; + return -1; + } + + walk(name, &w); + if (!validname(w.remaning)) { + bss->errno = 2; + return -1; + } + + if ((w.entry->flags & FSCREATE) == 0) { + bss->errno = 3; + return -1; + } + + lim = &bss->enttbl[NR_ENTS]; + for (ep = bss->enttbl; ep < lim && ep->fs ; ep++) + ; + if (ep == lim) { + bss->errno = 4; + return -1; + } + + ep->size = 0; + ep->flags = flags; + ep->arg = NULL; + ep->name = w.remaning; + ep->fs = w.fs; + ep->next = w.entry->arg; + w.entry->arg = ep; + return 0; +} + +void +initfs(const struct tree *tree) +{ + const struct tree *p; + Entry *ep; + + ep = &bss->root; + ep->fs = &dirfs; + ep->arg = NULL; + ep->flags = FSDIR | FSCREATE | FSREAD; + + ep = &bss->driver; + ep->fs = &drvfs; + ep->arg = NULL; + ep->flags = FSREAD; + + for (p = tree; p->name; ++p) { + if (create(p->name, p->flags) < 0) + panic("initfs"); + } +} diff --git a/src/romfw/fs.h b/src/romfw/fs.h @@ -0,0 +1,25 @@ +#include <stddef.h> + +typedef struct fs Filsys; +typedef struct walk Walk; + +struct walk { + const Filsys *fs; + Entry *entry; + const char *remaning; +}; + +struct fs { + unsigned short flags; + int (*open)(File *fp, Walk *wp, int flags); + int (*close)(File *fp); + int (*read)(File *fp, void *buf, int n); + int (*write)(File *fp, void *buf, int n); + int (*seek)(File *fp, off_t off, int whence); + int (*walk)(Walk *wp, const char *name, int len); +}; + +extern void walk(const char *name, Walk *wp); + +extern const Filsys drvfs; +extern const Filsys dirfs;