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:
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;