summaryrefslogtreecommitdiff
path: root/appl/cmd/mpc
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/mpc
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/cmd/mpc')
-rw-r--r--appl/cmd/mpc/mkfile14
-rw-r--r--appl/cmd/mpc/qconfig.b193
-rw-r--r--appl/cmd/mpc/qflash.b188
3 files changed, 395 insertions, 0 deletions
diff --git a/appl/cmd/mpc/mkfile b/appl/cmd/mpc/mkfile
new file mode 100644
index 00000000..17d7ab37
--- /dev/null
+++ b/appl/cmd/mpc/mkfile
@@ -0,0 +1,14 @@
+<../../../mkconfig
+
+TARG=\
+ qconfig.dis\
+ qflash.dis\
+
+SYSMODULES=\
+ sys.m\
+ draw.m\
+ string.m\
+
+DISBIN=$ROOT/dis/mpc
+
+<$ROOT/mkfiles/mkdis
diff --git a/appl/cmd/mpc/qconfig.b b/appl/cmd/mpc/qconfig.b
new file mode 100644
index 00000000..dbff19b7
--- /dev/null
+++ b/appl/cmd/mpc/qconfig.b
@@ -0,0 +1,193 @@
+implement Configflash;
+
+#
+# this isn't a proper config program: it's currently just
+# enough to set important parameters such as ethernet address.
+# an extension is in the works.
+# --chf
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "string.m";
+ str: String;
+
+Configflash: module
+{
+ init: fn(nil: ref Draw->Context, args: list of string);
+};
+
+Region: adt {
+ base: int;
+ limit: int;
+};
+
+#
+# structure of allocation descriptor
+#
+Fcheck: con 0;
+Fbase: con 4;
+Flen: con 8;
+Ftag: con 11;
+Fsig: con 12;
+Fasize: con 3*4+3+1;
+
+Tdead: con byte 0;
+Tboot: con byte 16r01;
+Tconf: con byte 16r02;
+Tnone: con byte 16rFF;
+
+flashsig := array[] of {byte 16rF1, byte 16rA5, byte 16r5A, byte 16r1F};
+noval := array[] of {0 to 3 =>byte 16rFF}; #
+
+Ctag, Cscreen, Cconsole, Cbaud, Cether, Cea, Cend: con iota;
+config := array[] of {
+ Ctag => "#plan9.ini\n", # current flag for qboot, don't change
+ Cscreen => "vgasize=640x480x8\n",
+ Cconsole => "console=0 lcd\n",
+ Cbaud => "baud=9600\n",
+ Cether => "ether0=type=SCC port=2 ", # note missing \n
+ Cea => "ea=08003e400080\n",
+ Cend => "\0" # qboot currently requires it but shouldn't
+};
+
+Param: adt {
+ name: string;
+ index: int;
+};
+
+params := array[] of {
+ Param("vgasize", Cscreen),
+ Param("console", Cconsole),
+ Param("ea", Cea),
+ Param("baud", Cbaud)
+};
+
+# could come from file or #F/flash/flashctl
+FLASHSEG: con 256*1024;
+bootregion := Region(0, FLASHSEG);
+
+stderr: ref Sys->FD;
+prog := "qconfig";
+damaged := 0;
+debug := 0;
+
+usage()
+{
+ sys->fprint(stderr, "Usage: %s [-D] [-f flash] [-param value ...]\n", prog);
+ exit;
+}
+
+err(s: string)
+{
+ sys->fprint(stderr, "%s: %s", prog, s);
+ if(!damaged)
+ sys->fprint(stderr, "; flash not modified\n");
+ else
+ sys->fprint(stderr, "; flash might now be invalid\n");
+ exit;
+}
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ sys->pctl(Sys->FORKFD|Sys->NEWPGRP, nil);
+ stderr = sys->fildes(2);
+ if(args != nil){
+ prog = hd args;
+ args = tl args;
+ }
+ str = load String String->PATH;
+ if(str == nil)
+ err(sys->sprint("can't load %s: %r", String->PATH));
+ flash := "#F/flash/flash";
+ offset := 0;
+ region := bootregion;
+
+ for(; args != nil && (hd args)[0] == '-'; args = tl args)
+ case a := hd args {
+ "-f" =>
+ (flash, args) = argf(tl args);
+ "-D" =>
+ debug = 1;
+ * =>
+ p := lookparam(params, a[1:]);
+ if(p.index < 0)
+ err(sys->sprint("unknown config parameter: %s", a));
+ v: string;
+ (v, args) = argf(tl args);
+ config[p.index] = a[1:]+"="+v+"\n"; # would be nice to check it
+ }
+ if(len args > 0)
+ usage();
+ out := sys->open(flash, Sys->ORDWR);
+ if(out == nil)
+ err(sys->sprint("can't open %s for read/write: %r", flash));
+ # TO DO: hunt for free space and add new entry
+ plonk(out, FLASHSEG-Fasize, mkdesc(0, 128*1024, Tboot));
+ c := flatten(config);
+ if(debug)
+ sys->print("%s", c);
+ bconf := array of byte c;
+ plonk(out, FLASHSEG-Fasize*2, mkdesc(128*1024, len bconf, Tconf));
+ plonk(out, 128*1024, bconf);
+}
+
+argf(args: list of string): (string, list of string)
+{
+ if(args == nil)
+ usage();
+ return (hd args, args);
+}
+
+lookparam(options: array of Param, s: string): Param
+{
+ for(i := 0; i < len options; i++)
+ if(options[i].name == s)
+ return options[i];
+ return Param(nil, -1);
+}
+
+flatten(a: array of string): string
+{
+ s := "";
+ for(i := 0; i < len a; i++)
+ s += a[i];
+ return s;
+}
+
+plonk(out: ref Sys->FD, where: int, val: array of byte)
+{
+ if(debug){
+ sys->print("write #%ux [%d]:", where, len val);
+ for(i:=0; i<len val; i++)
+ sys->print(" %.2ux", int val[i]);
+ sys->print("\n");
+ }
+ sys->seek(out, big where, 0);
+ if(sys->write(out, val, len val) != len val)
+ err(sys->sprint("bad flash write: %r"));
+}
+
+cvt(v: int): array of byte
+{
+ a := array[4] of byte;
+ a[0] = byte (v>>24);
+ a[1] = byte (v>>16);
+ a[2] = byte (v>>8);
+ a[3] = byte (v & 16rff);
+ return a;
+}
+
+mkdesc(base: int, length: int, tag: byte): array of byte
+{
+ a := array[Fasize] of byte;
+ a[Fcheck:] = noval;
+ a[Fbase:] = cvt(base);
+ a[Flen:] = cvt(length)[1:]; # it's three bytes
+ a[Ftag] = tag;
+ a[Fsig:] = flashsig;
+ return a;
+}
diff --git a/appl/cmd/mpc/qflash.b b/appl/cmd/mpc/qflash.b
new file mode 100644
index 00000000..13c77ce8
--- /dev/null
+++ b/appl/cmd/mpc/qflash.b
@@ -0,0 +1,188 @@
+implement Writeflash;
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "string.m";
+ str: String;
+
+Writeflash: module
+{
+ init: fn(nil: ref Draw->Context, args: list of string);
+};
+
+Region: adt {
+ base: int;
+ limit: int;
+};
+
+# could come from file or #F/flash/flashctl
+FLASHSEG: con 256*1024;
+kernelregion := Region(FLASHSEG, FLASHSEG+2*FLASHSEG);
+bootregion := Region(0, FLASHSEG);
+
+stderr: ref Sys->FD;
+prog := "qflash";
+damaged := 0;
+
+usage()
+{
+ sys->fprint(stderr, "Usage: %s [-b] [-o offset] [-f flashdev] file\n", prog);
+ exit;
+}
+
+err(s: string)
+{
+ sys->fprint(stderr, "%s: %s", prog, s);
+ if(!damaged)
+ sys->fprint(stderr, "; flash not modified\n");
+ else
+ sys->fprint(stderr, "; flash might now be invalid\n");
+ exit;
+}
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ sys->pctl(Sys->FORKFD|Sys->NEWPGRP, nil);
+ stderr = sys->fildes(2);
+ if(args != nil){
+ prog = hd args;
+ args = tl args;
+ }
+ str = load String String->PATH;
+ if(str == nil)
+ err(sys->sprint("can't load %s: %r", String->PATH));
+ region := kernelregion;
+ flash := "#F/flash/flash";
+ offset := 0;
+ save := 0;
+
+ for(; args != nil && (hd args)[0] == '-'; args = tl args)
+ case hd args {
+ "-b" =>
+ region = bootregion;
+ offset = 16r100 - 8*4; # size of exec header
+ save = 1;
+ "-h" =>
+ region.limit += FLASHSEG;
+ "-f" =>
+ if(tl args == nil)
+ usage();
+ flash = hd args;
+ args = tl args;
+ "-o" =>
+ if(tl args == nil)
+ usage();
+ args = tl args;
+ s := hd args;
+ v: int;
+ rs: string;
+ if(str->prefix("16r", s))
+ (v, rs) = str->toint(s[3:], 16);
+ else if(str->prefix("0x", s))
+ (v, rs) = str->toint(s[2:], 16);
+ else if(str->prefix("0", s))
+ (v, rs) = str->toint(s[1:], 8);
+ else
+ (v, rs) = str->toint(s, 10);
+ if(v < 0 || len rs != 0)
+ err(sys->sprint("bad offset: %s", s));
+ offset = v;
+ "-s" =>
+ save = 1;
+ * =>
+ usage();
+ }
+ if(args == nil)
+ usage();
+ fname := hd args;
+ fd := sys->open(fname, Sys->OREAD);
+ if(fd == nil)
+ err(sys->sprint("can't open %s: %r", fname));
+ (r, dir) := sys->fstat(fd);
+ if(r < 0)
+ err(sys->sprint("can't stat %s: %r", fname));
+ length := int dir.length;
+ avail := region.limit - (region.base+offset);
+ if(length > avail)
+ err(sys->sprint("%s contents %ud bytes, exceeds flash region %ud bytes", fname, length, avail));
+ # check fname's contents...
+ where := region.base+offset;
+ saved: list of (int, array of byte);
+ if(save){
+ saved = saveflash(flash, region.base, where) :: saved;
+ saved = saveflash(flash, where+length, region.limit) :: saved;
+ }
+ for(i := (region.base+offset)/FLASHSEG; i < region.limit/FLASHSEG; i++)
+ erase(flash, i);
+ out := sys->open(flash, Sys->OWRITE);
+ if(out == nil)
+ err(sys->sprint("can't open %s for writing: %r", flash));
+ if(sys->seek(out, big where, 0) != big where)
+ err(sys->sprint("can't seek to #%6.6ux on flash: %r", where));
+ if(length)
+ sys->print("writing %ud bytes to %s at #%6.6ux\n", length, flash, where);
+ buf := array[Sys->ATOMICIO] of byte;
+ total := 0;
+ while((n := sys->read(fd, buf, len buf)) > 0) {
+ if(total+n > avail)
+ err(sys->sprint("file %s too big for region of %ud bytes", fname, avail));
+ r = sys->write(out, buf, n);
+ damaged = 1;
+ if(r != n){
+ if(r < 0)
+ err(sys->sprint("error writing %s at byte %ud: %r", flash, total));
+ else
+ err(sys->sprint("short write on %s at byte %ud", flash, total));
+ }
+ total += n;
+ }
+ if(n < 0)
+ err(sys->sprint("error reading %s: %r", fname));
+ sys->print("wrote %ud bytes from %s to flash %s (#%6.6ux-#%6.6ux)\n", total, fname, flash, region.base, region.base+total);
+ for(l := saved; l != nil; l = tl l){
+ (addr, data) := hd l;
+ n = len data;
+ if(n == 0)
+ continue;
+ sys->print("restoring %ud bytes at #%6.6ux\n", n, addr);
+ if(sys->seek(out, big addr, 0) != big addr)
+ err(sys->sprint("can't seek to #%6.6ux on %s: %r", addr, flash));
+ r = sys->write(out, data, n);
+ if(r < 0)
+ err(sys->sprint("error writing %s: %r", flash));
+ else if(r != n)
+ err(sys->sprint("short write on %s at byte %ud/%ud", flash, r, n));
+ else
+ sys->print("restored %ud bytes at #%6.6ux\n", n, addr);
+ }
+}
+
+erase(flash: string, seg: int)
+{
+ ctl := sys->open(flash+"ctl", Sys->OWRITE);
+ if(ctl == nil)
+ err(sys->sprint("can't open %sctl: %r\n", flash));
+ if(sys->fprint(ctl, "erase %ud", seg*FLASHSEG) < 0)
+ err(sys->sprint("can't erase flash %s segment %d: %r\n", flash, seg));
+}
+
+saveflash(flash: string, base: int, limit: int): (int, array of byte)
+{
+ fd := sys->open(flash, Sys->OREAD);
+ if(fd == nil)
+ err(sys->sprint("can't open %s for reading: %r", flash));
+ nb := limit - base;
+ if(nb <= 0)
+ return (base, nil);
+ if(sys->seek(fd, big base, 0) != big base)
+ err(sys->sprint("can't seek to #%6.6ux to save flash contents: %r", base));
+ saved := array[nb] of byte;
+ if(sys->read(fd, saved, len saved) != len saved)
+ err(sys->sprint("can't read flash #%6.6ux to #%6.6ux: %r", base, limit));
+ sys->print("saved %ud bytes at #%6.6ux\n", len saved, base);
+ return (base, saved);
+}