summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/astarld.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/astarld.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/astarld.c')
-rwxr-xr-xsys/src/cmd/aux/astarld.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/astarld.c b/sys/src/cmd/aux/astarld.c
new file mode 100755
index 000000000..b1b45ad67
--- /dev/null
+++ b/sys/src/cmd/aux/astarld.c
@@ -0,0 +1,265 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+enum
+{
+ Doff= 4, /* offset into Cpline.bytes of data */
+
+ Memsize= 1<<16, /* max size of 186 memory */
+};
+
+int dump, image, noload, nostart;
+
+typedef struct
+{
+ int type;
+ int dlen;
+ ulong addr;
+ uchar bytes[256+4];
+ uchar csum;
+} Cpline;
+
+char* rdcpline(Biobuf*, Cpline*);
+void clearmem(int);
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-0123] file\n", argv0);
+ exits("usage");
+}
+
+static void
+loadimage(char* file, int mfd)
+{
+ uchar buf[256];
+ int fd, n, r;
+
+ if((fd = open(file, OREAD)) < 0)
+ sysfatal("opening %s: %r", file);
+
+ seek(mfd, 0, 0);
+ do{
+ n = read(fd, buf, sizeof(buf));
+ if(n < 0)
+ sysfatal("read %s: %r", file);
+ if(n > 0)
+ if((r = write(mfd, buf, n)) != n)
+ sysfatal("write %s: %d != %d: %r", file, n, r);
+ }while(n > 0);
+ close(fd);
+}
+
+static void
+loadhex(char* file, int mfd)
+{
+ int done;
+ Cpline c;
+ Biobuf *b;
+ char *err;
+ ulong addr, seg;
+ int lineno;
+ uchar buf[1024];
+
+ b = Bopen(file, OREAD);
+ if(b == 0)
+ sysfatal("opening %s: %r", file);
+
+ lineno = 1;
+ seg = 0;
+ for(done = 0; !done; lineno++){
+ err = rdcpline(b, &c);
+ if(err)
+ sysfatal("%s line %d: %s", file, lineno, err);
+ switch(c.type){
+ case 0: /* data */
+ addr = seg + c.addr;
+ if(addr + c.dlen > Memsize)
+ sysfatal("addr out of range: %lux-%lux", addr, addr+c.dlen);
+ if(seek(mfd, addr, 0) < 0)
+ sysfatal("seeking to %lud: %r", addr);
+ if(write(mfd, c.bytes+Doff, c.dlen) != c.dlen)
+ sysfatal("writing: %r");
+ if(seek(mfd, addr, 0) < 0)
+ sysfatal("seeking to %lud: %r", addr);
+ if(read(mfd, buf, c.dlen) != c.dlen)
+ sysfatal("reading: %r");
+ if(memcmp(buf, c.bytes+Doff, c.dlen) != 0)
+ print("readback error at %lux\n", addr);
+ if(dump)
+ print("%8.8lux: %d\n", addr, c.dlen);
+ break;
+ case 1: /* termination */
+ done = 1;
+ break;
+ case 2: /* segment */
+ seg = ((c.bytes[Doff]<<8) | c.bytes[Doff+1]) <<4;
+ if(seg >= Memsize)
+ sysfatal("seg out of range: %lux", seg);
+ if(dump)
+ print("seg %8.8lux\n", seg);
+ break;
+ default: /* ignore */
+ if(dump)
+ print("bad type %d\n", c.type);
+ break;
+ }
+ }
+ Bterm(b);
+}
+
+void
+main(int argc, char **argv)
+{
+ int unit;
+ int cfd, mfd;
+ char file[128];
+
+ unit = 0;
+ ARGBEGIN{
+ case 'd':
+ dump = 1;
+ break;
+ case 'i':
+ image = 1;
+ break;
+ case 'n':
+ noload = 1;
+ break;
+ case 's':
+ nostart = 1;
+ break;
+ case '0':
+ unit = 0;
+ break;
+ case '1':
+ unit = 1;
+ break;
+ case '2':
+ unit = 2;
+ break;
+ case '3':
+ unit = 3;
+ break;
+ }ARGEND;
+
+ if(argc == 0)
+ usage();
+
+ if(noload == 0){
+ sprint(file, "#G/astar%dctl", unit);
+ cfd = open(file, ORDWR);
+ if(cfd < 0)
+ sysfatal("opening %s", file);
+ sprint(file, "#G/astar%dmem", unit);
+ mfd = open(file, ORDWR);
+ if(mfd < 0)
+ sysfatal("opening %s", file);
+
+ if(write(cfd, "download", 8) != 8)
+ sysfatal("requesting download: %r");
+ } else {
+ cfd = -1;
+ mfd = create("/tmp/astarmem", ORDWR, 0664);
+ if(mfd < 0)
+ sysfatal("creating /tmp/astarmem: %r");
+ }
+
+ if(image)
+ loadimage(argv[0], mfd);
+ else{
+ /* zero out the memory */
+ clearmem(mfd);
+ loadhex(argv[0], mfd);
+ }
+ close(mfd);
+
+ if(noload == 0 && nostart == 0)
+ if(write(cfd, "run", 3) != 3)
+ sysfatal("requesting run: %r");
+ close(cfd);
+
+ exits(0);
+}
+
+void
+clearmem(int fd)
+{
+ char buf[4096];
+ char buf2[4096];
+ int i, n;
+
+ memset(buf, 0, sizeof buf);
+ for(i = 0; i < Memsize; i += n){
+ if(seek(fd, i, 0) < 0)
+ sysfatal("seeking to %ux: %r", i);
+ n = write(fd, buf, sizeof buf);
+ if(n <= 0)
+ break;
+ if(seek(fd, i, 0) < 0)
+ sysfatal("seeking to %ux: %r", i);
+ n = read(fd, buf2, sizeof buf2);
+ if(n <= 0)
+ break;
+ if(memcmp(buf, buf2, sizeof buf) != 0)
+ print("error zeroing mem at %ux\n", i);
+ }
+ print("zero'd %d bytes\n", i);
+}
+
+int
+hex(char c)
+{
+ if(c <= '9' && c >= '0')
+ return c - '0';
+ if(c <= 'f' && c >= 'a')
+ return (c - 'a') + 10;
+ if(c <= 'F' && c >= 'A')
+ return (c - 'A') + 10;
+ return -1;
+}
+
+char*
+rdcpline(Biobuf *b, Cpline *cpl)
+{
+ char *cp, *ep, *p;
+ uchar *up;
+ uchar csum;
+ int c;
+
+ cp = Brdline(b, '\n');
+ if(cp == 0)
+ return "early eof";
+ ep = cp + Blinelen(b);
+
+ if(*cp++ != ':')
+ return "bad load line";
+
+ csum = 0;
+ up = cpl->bytes;
+ for(p = cp; p < ep;){
+ c = hex(*p++)<<4;
+ c |= hex(*p++);
+ if(c < 0)
+ break;
+ csum += c;
+ *up++ = c;
+ }
+
+ cpl->csum = csum;
+ if(csum != 0){
+ fprint(2, "checksum %ux\n", csum);
+ return "bad checksum";
+ }
+
+ cpl->dlen = cpl->bytes[0];
+ if(cpl->dlen + 5 != up - cpl->bytes){
+ fprint(2, "%d %ld\n", cpl->dlen + 5, up - cpl->bytes);
+ return "bad data length";
+ }
+
+ cpl->addr = (cpl->bytes[1]<<8) | cpl->bytes[2];
+ cpl->type = cpl->bytes[3];
+ return 0;
+}