9os

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

commit 113dc9ac8eb9cfde463b8e01a2ec53812ba82286
parent 815b5e32ee7609910ef01e75daa86e881a8b1dc2
Author: Roberto Vargas <roberto.vargas@arm.com>
Date:   Fri, 30 Nov 2018 16:10:01 +0000

[dev] Add initial version plan9 version alike system

Change-Id: Id2d41a424103710fc4a68a63e49be9cc50215e8a

Diffstat:
Mdrivers/dev.c | 359++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mdrivers/dev.h | 44++++++++++++++++++++++++++++++++++++++++----
Mdrivers/devroot.c | 41++++++++++++++++++++++++++++++++++++++++-
Mdrivers/devuart.c | 2+-
Mdrivers/mkdevc | 2+-
Minclude/rcode.h | 12++++++++----
Minclude/romfw.h | 6+++++-
Mtarget/hosted/Makefile | 3++-
Mtarget/hosted/rom.c | 34+++++++++++++++++++++++++++++-----
Mtarget/native/.gitignore | 2++
Mtarget/native/rom.c | 15++++++++-------
11 files changed, 494 insertions(+), 26 deletions(-)

diff --git a/drivers/dev.c b/drivers/dev.c @@ -1,12 +1,36 @@ #include <errno.h> +#include <string.h> + #include <rcode.h> +#include <romfw.h> #include "dev.h" struct devdata { - Chan fd[NR_CHANS]; + Chan fds[NR_CHANS]; + Chan slash; + Chan dot; }; +/* + * FIXME: NODEV has the same type than rootdir + */ +static Chan * +newchan(void) +{ + Chan *c, *lim; + struct devdata *dinfo = bss->devinfo; + + lim = &dinfo->fds[NR_CHANS]; + for (c = dinfo->fds; c < lim; c++) { + if (c->type == NODEV) + return c; + } + + errno = ENOMEM; + return NULL; +} + static Chan * fd2chan(int fd) { @@ -14,5 +38,338 @@ fd2chan(int fd) errno = EBADF; return NULL; } + return &bss->devinfo->fds[fd]; +} + +static int +chan2fd(Chan *c) +{ + return (c == NULL) ? -1 : (c - bss->devinfo->fds); +} + +static int +validmode(int mode) +{ + if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR))) + goto err; + if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR))) + goto err; + if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE))) + goto err; + if ((mode & O_DIR) && (mode & (O_TRUNC))) + goto err; + return 1; + +err: + errno = EINVAL; + return 0; +} + +static const char * +next(const char *s, char *elem) +{ + int n; + const char *t; + + while (*s == '/') + ++s; + if (*s == '\0') + return s; + + n = 0; + for (t = s; *t != '/' && *t != '\0'; t++) { + if (n == NAMELEN) { + errno = ENAMETOOLONG; + return NULL; + } + elem[n++] = *t; + } + elem[n] = '\0'; + + return t; +} + +static int +devtype(int c) +{ + int i; + Dev * const *dp; + + for (i = 0, dp = devtab; *dp && (*dp)->id != c; ++dp) + i++; + if (*dp == NULL) { + errno = ENODEV; + return -1; + } + return i; +} + +static Chan * +clone(Chan *c, Chan *nc) +{ + return devtab[c->type]->clone(c, nc); +} + +static int +walk(Chan *c, char *name) +{ + return devtab[c->type]->walk(c, name); +} + +static void +chanclose(Chan *c) +{ + c->qid = 0; + c->type = NODEV; + c->dev = 0; + c->offset = 0; +} + +Chan * +namec(const char *name, int mode) +{ + int type; + const char *s; + Chan *c; + struct devdata *dinfo = bss->devinfo; + char elem[NAMELEN]; + + switch (name[0]) { + case '/': + c = clone(&dinfo->slash, NULL); + s = name; + break; + case '#': + if ((s = next(name+1, elem)) == NULL) + return NULL; + if (elem[1] != '\0') { + errno = ENODEV; + return NULL; + } + if ((type = devtype(elem[0])) < 0) + return NULL; + c = devtab[type]->attach(NULL); + break; + default: + c = clone(&dinfo->dot, NULL); + s = name; + break; + } + + if (!c) + return NULL; + + for (s = next(s, elem); s && *s; s = next(s, elem)) { + if (walk(c, elem) < 0) + break; + } + if (*s == '\0') + return c; + + chanclose(c); + errno = ENOENT; return NULL; } + +Chan * +devclone(Chan *c, Chan *nc) +{ + if (!nc && (nc = newchan()) == NULL) + return NULL; + + nc->qid = c->qid; + nc->type = c->type; + nc->dev = c->dev; + nc->mode = c->mode; + nc->offset = c->offset; + + return nc; +} + +Chan * +devattach(const char *spec, int id) +{ + Chan *c; + int type; + + if ((type = devtype(id)) < 0) + return NULL; + c = newchan(); + c->qid = CHDIR; + c->type = devtype(id); + return c; +} + +int +devwalk(Chan *c, const char *name, const Dirtab *tab, int ntab, Devgen *gen) +{ + int i; + Dir dir; + + if (name[0] == '.' && name[1] == '\0') + return 1; + for (i = 0; ;i++) { + switch ((*gen)(c, tab, ntab, i, &dir)) { + case -1: + errno = ENOENT; + return 0; + case 0: + continue; + case 1: + if (strcmp(name, dir.name)) + continue; + c->qid = dir.qid; + return 1; + } + } + + return 0; +} + +int +devdirread(Chan *c, char *buf, int nbytes, const Dirtab *tab, int ntab, Devgen *gen) +{ + int n, cnt, i; + Dir dir; + + for (i = c->offset/DIRLEN; nbytes >= DIRLEN; i++) { + switch ((*gen)(c, tab, ntab, i, &dir)) { + case -1: + return cnt; + case 0: + c->offset += DIRLEN; + break; + case 1: + memcpy(buf + cnt, &dir, DIRLEN); + nbytes -= n; + cnt += n; + } + } + + return cnt; +} + +int +devgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) +{ + const Dirtab *dp; + + if (!tab || n >= ntab) + return -1; + + dp = &tab[n]; + strcpy(dir->name, dp->name); + dir->length = dp->length; + dir->qid = dp->qid; + dir->mode = dp->perm; + if (dp->qid & CHDIR) + dir->mode |= O_DIR; + dir->type = c->type; + dir->dev = c->dev; + + return 1; +} + +int +open(const char *fname, int mode) +{ + Chan *c; + + if (!validmode(mode)) + return -1; + c = namec(fname, mode); + + return chan2fd(c); +} + +int +close(int fd) +{ + Chan *c; + + if ((c = fd2chan(fd)) == NULL) + return -1; + chanclose(c); + return 0; +} + +int +read(int fd, void *buf, int n) +{ + Chan *c; + + if ((c = fd2chan(fd)) == NULL) + return -1; + + if ((c->qid & CHDIR) && (n < DIRLEN)) { + errno = EINVAL; + return -1; + } + n = devtab[c->type]->read(c, buf, n); + c->offset += n; + return n; +} + +int +write(int fd, void *buf, int n) +{ + Chan *c; + + if ((c = fd2chan(fd)) == NULL) + return -1; + + if (c->qid & CHDIR) { + errno = EISDIR; + return -1; + } + + n = devtab[c->type]->write(c, buf, n); + c->offset += n; + return n; +} + +int +seek(int fd, long long off, int whence) +{ + Chan *c; + + if ((c = fd2chan(fd)) == NULL) + return -1; + + if (c->qid & CHDIR) { + errno = EISDIR; + return -1; + } + + switch (whence) { + case 0: + c->offset = off; + break; + case 1: + c->offset += off; + break; + case 2: + panic("seek"); /* TODO */ + break; + } + + return 0; +} + +void +idev(void) +{ + struct devdata *dinfo; + Chan *c; + + dinfo = alloc(sizeof(*dinfo)); + bss->devinfo = dinfo; + + if ((c = devattach(NULL, '/')) == NULL) + panic("idev:attach"); + + if (!clone(c, &dinfo->slash) || !clone(c, &dinfo->dot)) + panic("idev:clone"); + + chanclose(c); +} diff --git a/drivers/dev.h b/drivers/dev.h @@ -1,22 +1,58 @@ #include <stddef.h> #define NR_CHANS 4 +#define NODEV 0 +#define NAMELEN 8 +#define DIRLEN sizeof(Dir) +#define CHDIR (1 << 15) typedef struct dev Dev; typedef struct chan Chan; +typedef struct dirtab Dirtab; +typedef struct dir Dir; +typedef int Devgen(Chan *, const Dirtab *, int, int, Dir *); +typedef short Qid; + +struct dir { + char name[NAMELEN]; + unsigned long long length; + unsigned char mode; + unsigned char type; + unsigned char dev; + Qid qid; +}; + +struct dirtab { + char name[NAMELEN]; + Qid qid; + unsigned long long length; + unsigned char perm; +}; struct dev { char id; - char *name; + char name[NAMELEN]; + Chan * (*clone)(Chan *c, Chan *nc); + int (*walk)(Chan *c, const char *name); + Chan * (*attach)(const char *spec); + int (*read)(Chan *c, void *buf, int n); + int (*write)(Chan *c, void *buf, int n); }; struct chan { + Qid qid; unsigned char type; unsigned char dev; - unsigned short qid; unsigned char mode; - unsigned char iref; - unsigned long long offset; /* 2 bytes of padding here */ + + unsigned long long offset; /* 3 bytes of padding here */ }; extern Dev *const devtab[]; + +extern Chan *devclone(Chan *c, Chan *nc); +extern Chan *devattach(const char *spec, int id); +extern Chan *devclone(Chan *c, Chan *nc); +extern int devgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir); +extern int devwalk(Chan *c, const char *name, const Dirtab *tab, int ntab, Devgen *gen); +extern int devdirread(Chan *c, char *buf, int nbytes, const Dirtab *tab, int ntab, Devgen *gen); diff --git a/drivers/devroot.c b/drivers/devroot.c @@ -1,6 +1,45 @@ +#include <rcode.h> + #include "dev.h" -const Dev devroot = { +#define NELEM(tab) (sizeof(tab) / sizeof(tab[0])) + +enum Orootqid { + Qslash, + Qdev, + Qrealm, +}; + +static const Dirtab rootdirtab[] = { + {"dev", CHDIR | Qdev, 0, O_READ}, + {"realm", CHDIR | Qrealm, 0, O_READ}, +}; + +static int +rootwalk(Chan *c, const char *name) +{ + return devwalk(c, name, rootdirtab, NELEM(rootdirtab), devgen); +} + +static Chan * +rootattach(const char *spec) +{ + return devattach(spec, '/'); +} + +static int +rootread(Chan *c, void *buf, int n) +{ + if (c->qid & CHDIR) + return devdirread(c, buf, n, rootdirtab, NELEM(rootdirtab), devgen); + return -1; +} + +const Dev rootdevtab = { .id = '/', .name = "root", + .clone = devclone, + .attach = rootattach, + .walk = rootwalk, + .read = rootread, }; diff --git a/drivers/devuart.c b/drivers/devuart.c @@ -1,6 +1,6 @@ #include "dev.h" -const Dev devuart = { +const Dev uartdevtab = { .id = 't', .name = "uart", }; diff --git a/drivers/mkdevc b/drivers/mkdevc @@ -7,7 +7,7 @@ awk ' BEGIN {print "#include \"dev.h\"\n"} /^dev/ {dev = 1; next} /^[^ \t]/ {dev = 0; next} -dev && /^[ \t]/ {devs["dev" $1] = 1} +dev && /^[ \t]/ {devs[$1 "devtab"] = 1} END {for (i in devs) printf "extern Dev %s;\n", i print "\nDev *const devtab[] = {" diff --git a/include/rcode.h b/include/rcode.h @@ -14,10 +14,12 @@ #define IDISABLE 0 enum devflags { - OCREATE = 1 << 0, - OREAD = 1 << 1, - OWRITE = 1 << 2, - ODIR = 1 << 3, + O_CREATE = 1 << 0, + O_READ = 1 << 1, + O_WRITE = 1 << 2, + O_RDWR = 1 << 3, + O_DIR = 1 << 4, + O_TRUNC = 1 << 5, }; typedef struct rmucmd Rmucmd; @@ -68,6 +70,7 @@ extern noreturn void trap(struct trapframe *fp); extern noreturn void badcmd(int error); extern void rmc(Rmucmd *cmd); extern int debug(void); +extern void idev(void); /* driver functions */ extern int create(const char *name, int flags); @@ -79,6 +82,7 @@ extern int seek(int fd, long long off, int whence); extern int bind(const char *path, char *where); /* architectural functions */ +extern void *alloc(size_t size); extern noreturn void dohalt(void); extern noreturn void dopanic(void); extern noreturn void doswtch(struct trapframe *fp); diff --git a/include/romfw.h b/include/romfw.h @@ -4,6 +4,8 @@ struct rmctab; struct trapframe; +struct rmucmd; +struct Fgrp; struct bssmap { unsigned char in_panic; @@ -19,12 +21,14 @@ struct bssmap { jmp_buf dbgrecover; struct rmctab *rmctab; struct trapframe *fp; - Rmucmd *cmd; + struct rmucmd *cmd; unsigned char enable; /* System realm enablement */ unsigned char hascrypto; /* System-wide memory encryption */ int errno_; + + struct devdata *devinfo; }; extern struct bssmap *bss(void); diff --git a/target/hosted/Makefile b/target/hosted/Makefile @@ -15,7 +15,7 @@ RAMOBJS = arch.o \ ramtab.o \ $(SRCDIR)/ramfw/builtin.o \ -TARGET = $(BINDIR)/romfw.elf $(BINDIR)/ramfw.elf +TARGET = $(BINDIR)/romfw.elf DIRS = crt all: $(TARGET) @@ -39,3 +39,4 @@ $(BINDIR)/ramfw.elf: $(RAMOBJS) $(LIBDEP) clean: $(FORALL) + rm -f romtab.c ramtab.c diff --git a/target/hosted/rom.c b/target/hosted/rom.c @@ -1,20 +1,44 @@ #include <setjmp.h> +#include <stdlib.h> #include <string.h> #include <rcode.h> #include <romfw.h> -int -main(int argc, char *argv[]) +#include "hosted.h" + +struct bssmap bssmap; + +void * +alloc(size_t size) { - extern jmp_buf recover; + void * p; + if ((p = malloc(size)) == NULL) + panic("alloc"); + return p; +} + +static void +imach(void) +{ if (setjmp(recover)) - return 1; + exit(EXIT_FAILURE); +} - memset(bss, 0, sizeof(struct bssmap)); +static void +ibss(void) +{ bss->rmctab = &romtab; bss->fp = &(struct trapframe) {0}; +} + +int +main(int argc, char *argv[]) +{ + imach(); + ibss(); + idev(); return debug(); } diff --git a/target/native/.gitignore b/target/native/.gitignore @@ -1,3 +1,5 @@ sysreg.h sysreg.s version.h +romtab.c +ramtab.c diff --git a/target/native/rom.c b/target/native/rom.c @@ -44,6 +44,12 @@ getenviron(void) return bss->environ; } +void * +alloc(size_t size) +{ + return NULL; +} + static void imach(Mach *mp, void *txt, size_t txtsiz, void *ram, size_t ramsiz) { @@ -105,12 +111,6 @@ ibss(Mach *mp) } static void -idev(Mach *mp) -{ - uartinit(UARTCLK, UARTBAUDRATE); -} - -static void info(Mach *mp) { dbg("romfw: version %s\n" @@ -134,7 +134,8 @@ main(void *txt, size_t txtsiz, void *ram, size_t ramsiz) imach(&mach, txt, txtsiz, ram, ramsiz); ibss(&mach); - idev(&mach); + idev(); + uartinit(UARTCLK, UARTBAUDRATE); intr(IENABLE); barrier(ISB); info(&mach);