commit a73d314881fdc996e2649e6154e6f6d6654bb05d
parent 7e6205016c51cfd5ee86c1ca4b7b2492ddcc989c
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Thu, 28 Feb 2019 10:28:04 +0000
[dev] Add devblob
This device exports in #b a filesystem that presents
blobs as files. The blobs can be incorporated to the
binary using a new section in the config file called
blobs. Anyway, a blob can be exported without linking
the program with the actual blob, but it requires
a phy with the data of the blob. When blobs are generated
and linked in the program using the config file then
the phy is automatically created. The device also
presents a ctl file to inspect and add new blobs.
Change-Id: Id0530c074afae7e7e55b80384556fb5651ca94d0
Diffstat:
15 files changed, 272 insertions(+), 24 deletions(-)
diff --git a/drivers/.gitignore b/drivers/.gitignore
@@ -1,2 +1,3 @@
devs.mk
devc.c
+blobs.mk
diff --git a/drivers/Makefile b/drivers/Makefile
@@ -2,8 +2,11 @@
PROJECTDIR=..
include $(PROJECTDIR)/scripts/rules.mk
-all clean: devs.mk
+all clean: devs.mk blobs.mk
$(MAKE) -f Makefile.drv $@
devs.mk: $(TARGETDIR)/rcode
mkdev $(TARGETDIR)/rcode
+
+blobs.mk: $(TARGETDIR)/rcode
+ mkblob $(TARGETDIR)/rcode
diff --git a/drivers/Makefile.drv b/drivers/Makefile.drv
@@ -2,6 +2,7 @@
PROJECTDIR=..
include $(PROJECTDIR)/scripts/rules.mk
include devs.mk
+include blobs.mk
OBJS = $(DEVS) \
devc.o \
@@ -15,4 +16,4 @@ devc.c: $(TARGETDIR)/rcode
mkdevc $(TARGETDIR)/rcode
clean:
- rm -f devs.mk devc.c
+ rm -f $(BLOBS) blobs.mk devs.mk devc.c
diff --git a/drivers/blob.h b/drivers/blob.h
@@ -0,0 +1,10 @@
+typedef struct blobphy Blobphy;
+
+struct attr;
+
+struct blobphy {
+ void *addr;
+ size_t size;
+};
+
+extern void bloblink(Blobphy *phy, struct attr *attr);
diff --git a/drivers/devblob.c b/drivers/devblob.c
@@ -0,0 +1,163 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include <libk.h>
+
+#include <rcode/rcode.h>
+#include <rcode/9p.h>
+
+#include "dev.h"
+#include "blob.h"
+
+#define NR_BLOBS 2
+
+enum Orootqid {
+ Qblobfs,
+ Qctl,
+};
+
+static Dirtab blobfstab[NR_BLOBS+1] = {
+ {"ctl", Qctl, 0, O_READ | O_WRITE},
+};
+
+static void *addrtab[NR_BLOBS+1];
+static int nblobs;
+
+static int
+blobwalk(Chan *c, const char *name)
+{
+ if ((c->qid & ~CHDIR) != Qblobfs)
+ return 0;
+ return devwalk(c, name, blobfstab, nblobs+1, devgen);
+}
+
+static Chan *
+blobattach(int dev)
+{
+ return devattach('b', dev);
+}
+
+static int
+blobread(Chan *c, void *buf, int n)
+{
+ Qid qid;
+ int i;
+ size_t length;
+ char *addr;
+ Dirtab *dp;
+ char info[NR_BLOBS * (NAMELEN + 20)];
+
+ switch (c->qid & ~CHDIR) {
+ case Qblobfs:
+ return dirread(c, buf, n, blobfstab, nblobs+1, devgen);
+ case Qctl:
+ for (length = i = 0; i < nblobs; i++) {
+ dp = &blobfstab[i+1];
+ length += ksnprint(info+length,
+ sizeof(info) - length,
+ "%s 0x%p %llu\n",
+ dp->name,
+ addrtab[i],
+ dp->length);
+ }
+ addr = info;
+ break;
+ default:
+ qid = c->qid;
+ if (qid - (Qctl + 1) > nblobs)
+ panic("bioread");
+ qid -= 1;
+ dp = &blobfstab[qid];
+ qid -= Qctl;
+ addr = addrtab[qid];
+
+ length = dp->length;
+ break;
+ }
+
+ if (c->offset >= length)
+ return 0;
+
+ if (c->offset + n > length)
+ n = length - c->offset;
+
+ memcpy(buf, addr + c->offset, n);
+
+ c->offset += n;
+
+ return n;
+}
+
+static int
+newblob(char *name, void *addr, size_t len)
+{
+ Qid qid;
+ Dirtab *dp;
+
+ if (nblobs == NR_BLOBS || strlen(name) >= NAMELEN)
+ return 0;
+
+ addrtab[nblobs] = addr;
+ qid = nblobs + Qctl + 1;
+ dp = &blobfstab[qid-1];
+ dp->qid = qid;
+ dp->perm = O_READ;
+ dp->length = len;
+ strcpy(dp->name, name);
+ nblobs++;
+
+ return 1;
+}
+
+void
+bloblink(Blobphy *phy, Attr *attr)
+{
+ Attr *p;
+
+ for (p = attr; p->key && strcmp(p->key, "file"); p++)
+ ;
+
+ if (!p->key || !newblob(p->value, phy->addr, phy->size))
+ panic("bloblink");
+}
+
+static int
+blobwrite(Chan *c, void *buf, int n)
+{
+ char line[100], *name, *addr, *size;
+ void *p;
+ size_t s;
+
+ if (c->qid != Qctl)
+ return -1;
+
+ if (n > sizeof(buf)-1)
+ return -1;
+ memcpy(line, buf, n);
+ line[n] = '\0';
+
+ name = strtok(buf, " \t\r");
+ addr = strtok(NULL, " \t\r");
+ size = strtok(NULL, " \t\r");
+
+ if (!name || !addr || !size)
+ return -1;
+
+ p = (void *) strtoll(addr, NULL, 0);
+ s = strtoll(size, NULL, 0);
+ if (!newblob(name, p, s))
+ return -1;
+
+ return n;
+}
+
+const Dev blobdevtab = {
+ .id = 'b',
+ .name = "blob",
+ .clone = devclone,
+ .attach = blobattach,
+ .walk = blobwalk,
+ .read = blobread,
+ .write = blobwrite,
+ .bind = devbind,
+};
diff --git a/drivers/devroot.c b/drivers/devroot.c
@@ -8,12 +8,14 @@ enum Orootqid {
Qdev,
Qdevuart,
Qrealm,
+ Qblobs,
Qmax,
};
static const Dirtab dirtab[] = {
{"dev", CHDIR | Qdev, 0, O_READ},
{"realm", CHDIR | Qrealm, 0, O_READ},
+ {"blobs", CHDIR | Qblobs, 0, O_READ},
};
static const Dirtab devfstab[] = {
@@ -34,6 +36,7 @@ rootgen(Chan *c, const Dirtab *tab, int ntab, int n, Dir *dir)
tab = devfstab;
ntab = NELEM(devfstab);
break;
+ case Qblobs:
case Qdevuart:
case Qrealm:
return 0;
diff --git a/drivers/dump b/drivers/dump
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+set -e
+trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM
+
+file=$1
+sym=$2
+
+cat <<EOF > $$.tmp && mv $$.tmp $sym.c
+#include <stddef.h>
+
+#include "blob.h"
+
+`od -td1 -v -A n $file |
+tr ' \t' '\n' |
+awk -v sym=$sym '
+BEGIN {printf "char %s[] = {\n", sym}
+NF == 1 {printf "\t%d,\n", $1}
+END {print "};"}'`
+
+Blobphy ${sym}phy = {
+ .addr = $sym,
+ .size = sizeof($sym),
+};
+EOF
diff --git a/drivers/mkblob b/drivers/mkblob
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM
+
+section blob $@ |
+awk '{blobs[$1] = $2}
+END {mkvar()
+ mkrules()}
+
+function mkvar()
+{
+ print "BLOBS = \\"
+ for (i in blobs)
+ printf "\t%s.c\n", i
+}
+
+function mkrules()
+{
+ for (i in blobs) {
+ printf "%s.c: %s\n", i, blobs[i]
+ printf "\tdump %s %s\n", blobs[i], i
+ }
+}
+' > $$.tmp && mv $$.tmp blobs.mk
diff --git a/drivers/mkdev b/drivers/mkdev
@@ -2,13 +2,11 @@
trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM
-sed 's/#.*//' $@ |
+section dev $@ |
awk '
-BEGIN {print "DEVS = dev.o\\"}
-/^[ \t]*$/ {next}
-/^dev/ {indev = 1; next}
-/^\t\t/ {objs[$1 ".o"] = 1; next}
-indev && /^\t/ {objs["dev" $1 ".o"] = 1; next}
-END {for (i in objs)
- printf "\t%s\\\n", i}' > $$.tmp &&
+BEGIN {print "DEVS = dev.o\\"}
+/^\t\t/ {objs[$1 ".o"] = 1; next}
+/^\t/ {objs["dev" $1 ".o"] = 1; next}
+END {for (i in objs)
+ printf "\t%s\\\n", i}' > $$.tmp &&
mv $$.tmp devs.mk
diff --git a/drivers/mkdevc b/drivers/mkdevc
@@ -2,19 +2,17 @@
trap 'r=$?; rm -f $$.tmp; exit $r' EXIT HUP INT QUIT TERM
-sed -e 's/^#.*//' -e '/^[ \t]*$/d' $@ |
+section dev $@ |
awk '
-/^[ \t]*$/ {next}
-/^dev/ {indev = 1; next}
-indev && /^\t\t/ {devs[dev]++
- phys[$1] = dev
- drivers[n++] = dev FS $1 FS $2}
-indev && /^\t[^\t]/ {dev = $1
- devs[dev] = 0}
-END {typedef()
- extern()
- devtab()
- devlink()}
+/^\t\t/ {devs[dev]++
+ phys[$1] = dev
+ drivers[n++] = dev FS $1 FS $2
+ next}
+/^\t/ {devs[dev = $1] = 0}
+END {typedef()
+ extern()
+ devtab()
+ devlink()}
function capital(x)
{
diff --git a/drivers/section b/drivers/section
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+sect=$1
+shift
+
+sed -n 's/^#.*//
+ /^[ ]*$/d
+ /^'$sect'/,/^[^ ]/ {
+ /^ /p
+ }' $@
diff --git a/include/rcode/9p.h b/include/rcode/9p.h
@@ -1,7 +1,7 @@
#ifndef LIBK_H_
#define LIBK_H_
-#define NAMELEN 8
+#define NAMELEN 14
#define STATLEN 41
#define ROOTLEN (2 + 4)
#define FILNAMLEN (2 + NAMELEN)
diff --git a/target/hosted/rcode b/target/hosted/rcode
@@ -3,3 +3,8 @@ dev
uart
pl011 base=0x1c0c0000,clk=24000000,cfg=b115200 l8
pl011 base=0x1c0c0100,clk=24000000
+ blob
+ example file=example.tar
+blob
+ example ../target/hosted/example.tar
+end
diff --git a/target/hosted/rom.c b/target/hosted/rom.c
@@ -43,7 +43,13 @@ static void
namespace(void)
{
if (bind("#t0", "/dev/uart") < 0)
- kerror("namespace");
+ goto error;
+ if (bind("#b", "/blobs") < 0)
+ goto error;
+ return;
+
+error:
+ kerror("namespace");
}
int
diff --git a/target/native/rcode b/target/native/rcode
@@ -3,3 +3,4 @@ dev
uart
pl011 base=0x1c0c0000,clk=24000000,rate=115200
pl011 base=0x1c0c0100,clk=24000000,rate=115200
+end