9os

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

commit 2562a5e14a4bc650bc229330b1456bac8beaf60e
parent c4507e76f2fdd3fe7aad4c8f34cbdb7b7d0e7396
Author: Roberto Vargas <roberto.vargas@arm.com>
Date:   Tue,  5 Mar 2019 12:34:07 +0000

Add initial version of devar

This device is not fully functional yet.

Change-Id: I745d88f362bee61c5a7901646ba54c19c60b19cd

Diffstat:
Adrivers/devar.c | 203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtarget/hosted/rcode | 5+++--
Mtarget/hosted/rom.c | 4++++
3 files changed, 210 insertions(+), 2 deletions(-)

diff --git a/drivers/devar.c b/drivers/devar.c @@ -0,0 +1,203 @@ +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <rcode/rcode.h> +#include <rcode/9p.h> + +#include "dev.h" + +#define NR_ARS 2 + +#define ARMAG "!<arch>\n" /* ar "magic number" */ +#define SARMAG 8 /* strlen(ARMAG); */ +#define ARFMAG "`\n" +#define SARNAM 16 + + +struct ar_hdr { + char ar_name[SARNAM]; /* name */ + char ar_date[12]; /* modification time */ + char ar_uid[6]; /* user id */ + char ar_gid[6]; /* group id */ + char ar_mode[8]; /* octal file permissions */ + char ar_size[10]; /* size in bytes */ + char ar_fmag[2]; /* consistency check */ +}; + +enum Oarqid { + Qarfs, + Qctl, +}; + +static Dirtab arfstab[NR_ARS+1] = { + {"ctl", Qctl, 0, O_READ | O_WRITE}, +}; + +static int nars; + +static int +gethdr(Chan *c, struct ar_hdr *hdr) +{ + int n, ch, i; + + n = devtab[c->type]->read(c, hdr, sizeof(*hdr)); + if (n == 0) + return 0; + if (n != sizeof(*hdr) || strncmp(hdr->ar_fmag, ARFMAG, 2) != 0) { + errno = EFAULT; /* TODO: Put correct value */ + return -1; + } + + /* TODO: Check if we do the same loop and we accept not null strings */ + for (i = SARNAM-1; i >= 0; i--) { + ch = hdr->ar_name[i]; + if (ch != ' ' && ch !='/') + break; + hdr->ar_name[i] = '\0'; + } + + return 1; +} + +/* + * TODO: This is broken, because we have a channel to + * talk with the dev, but we need an offset + * in the underlying dev. + */ +static int +argen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir) +{ + Qid qid; + int len, r; + Chan nc; + char buf[SARMAG]; + struct ar_hdr hdr; + + qid = (c->qid & ~CHDIR) - 1; + if (qid > nars) + panic("argen"); + clone(arfstab[qid].data, &nc); + nc.offset = c->offset; + + if (nc.offset == 0) { + r = devtab[nc.type]->read(&nc, buf, SARMAG); + if (r != SARMAG || strncmp(buf, ARMAG, SARMAG)) { + errno = EFAULT; + return -1; + } + } + + if ((r = gethdr(&nc, &hdr)) <= 0) + return r; + devseek(&nc, atol(hdr.ar_size), 1); + + if ((len = strlen(hdr.ar_name)) >= NAMELEN) + return 0; + memcpy(dir->name, hdr.ar_name, len); + dir->name[len] = '\0'; + dir->length = atol(hdr.ar_size); + dir->qid = (n + 1) * (NR_ARS+1) + qid; + dir->mode = O_READ; + dir->type = c->type; + dir->dev = c->dev; + c->offset = nc.offset; + + return 1; +} + +static int +arwalk(Chan *c, const char *name) +{ + switch (c->qid & ~CHDIR) { + case Qarfs: + return devwalk(c, name, arfstab, nars+1, devgen); + default: + return devwalk(c, name, NULL, 0, argen); + } +} + +static int +ardirread(Chan *c, unsigned char *buf, int nbytes) +{ + int n, cnt; + Dir dir; + + for (cnt = 0; nbytes >= DIRLEN; cnt += n) { + switch (argen(c, NULL, 0, nbytes, &dir)) { + case 0: + return cnt; + case -1: + return (cnt > 0) ? cnt : -1; + case 1: + n = dirtop9(&dir, buf + cnt, nbytes); + nbytes -= n; + } + } + + return cnt; +} + +static int +arread(Chan *c, void *buf, int n) +{ + Qid qid; + Chan nc; + + switch (c->qid & ~CHDIR) { + case Qarfs: + return dirread(c, buf, n, arfstab, nars+1, devgen); + case Qctl: + errno = EFAULT; /* TODO: Put a correct value */ + return -1; + default: + if (c->qid & CHDIR) + return ardirread(c, buf, n); + else { + qid = c->qid % (NR_ARS + 1); + clone(arfstab[qid].data, &nc); + nc.offset = c->offset; + n = devtab[nc.type]->read(&nc, buf, n); + c->offset += n; + return n; + } + } +} + +int +arnew(char *name) +{ + Qid qid; + Chan *c; + char *base, *s; + Dirtab *dp; + + base = strrchr(name, '/'); + base = (base) ? base+1 : name; + + if (nars >= NR_ARS || strlen(base) >= NAMELEN) { + errno = ENOMEM; + return -1; + } + + if ((c = namec(name, O_READ)) == NULL) + return -1; + + qid = ++nars + Qctl; + dp = &arfstab[qid-1]; + dp->qid = CHDIR | qid; + dp->perm = O_READ; + dp->length = 0; + dp->data = c; + strcpy(dp->name, base); + + return 0; +} + +const Dev ardevtab = { + .id = 'r', + .walk = arwalk, + .read = arread, + .write = devwrite, +}; diff --git a/target/hosted/rcode b/target/hosted/rcode @@ -4,7 +4,8 @@ dev pl011 base=0x1c0c0000,clk=24000000,cfg=b115200 l8 pl011 base=0x1c0c0100,clk=24000000 blob - example file=example.tar + example file=example.ar + ar blob - example ../target/hosted/example.tar + example ../target/hosted/example.ar end diff --git a/target/hosted/rom.c b/target/hosted/rom.c @@ -39,6 +39,8 @@ imach(void) framep = &trapframe; } +extern int arnew(char *file); + static void namespace(void) { @@ -46,6 +48,8 @@ namespace(void) goto error; if (bind("#b", "/blobs") < 0) goto error; + if (arnew("/blobs/example.ar") < 0) + goto error; return; error: