17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier enum
67dd7cddfSDavid du Colombier {
77dd7cddfSDavid du Colombier Doff= 4, /* offset into Cpline.bytes of data */
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier Memsize= 1<<16, /* max size of 186 memory */
107dd7cddfSDavid du Colombier };
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier int dump, image, noload, nostart;
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier typedef struct
157dd7cddfSDavid du Colombier {
167dd7cddfSDavid du Colombier int type;
177dd7cddfSDavid du Colombier int dlen;
187dd7cddfSDavid du Colombier ulong addr;
197dd7cddfSDavid du Colombier uchar bytes[256+4];
207dd7cddfSDavid du Colombier uchar csum;
217dd7cddfSDavid du Colombier } Cpline;
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier char* rdcpline(Biobuf*, Cpline*);
247dd7cddfSDavid du Colombier void clearmem(int);
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier void
usage(void)277dd7cddfSDavid du Colombier usage(void)
287dd7cddfSDavid du Colombier {
297dd7cddfSDavid du Colombier fprint(2, "usage: %s [-0123] file\n", argv0);
307dd7cddfSDavid du Colombier exits("usage");
317dd7cddfSDavid du Colombier }
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier static void
loadimage(char * file,int mfd)347dd7cddfSDavid du Colombier loadimage(char* file, int mfd)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier uchar buf[256];
377dd7cddfSDavid du Colombier int fd, n, r;
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier if((fd = open(file, OREAD)) < 0)
409a747e4fSDavid du Colombier sysfatal("opening %s: %r", file);
417dd7cddfSDavid du Colombier
427dd7cddfSDavid du Colombier seek(mfd, 0, 0);
437dd7cddfSDavid du Colombier do{
447dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf));
457dd7cddfSDavid du Colombier if(n < 0)
469a747e4fSDavid du Colombier sysfatal("read %s: %r", file);
477dd7cddfSDavid du Colombier if(n > 0)
487dd7cddfSDavid du Colombier if((r = write(mfd, buf, n)) != n)
499a747e4fSDavid du Colombier sysfatal("write %s: %d != %d: %r", file, n, r);
507dd7cddfSDavid du Colombier }while(n > 0);
517dd7cddfSDavid du Colombier close(fd);
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier static void
loadhex(char * file,int mfd)557dd7cddfSDavid du Colombier loadhex(char* file, int mfd)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier int done;
587dd7cddfSDavid du Colombier Cpline c;
597dd7cddfSDavid du Colombier Biobuf *b;
607dd7cddfSDavid du Colombier char *err;
617dd7cddfSDavid du Colombier ulong addr, seg;
627dd7cddfSDavid du Colombier int lineno;
637dd7cddfSDavid du Colombier uchar buf[1024];
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier b = Bopen(file, OREAD);
667dd7cddfSDavid du Colombier if(b == 0)
679a747e4fSDavid du Colombier sysfatal("opening %s: %r", file);
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier lineno = 1;
707dd7cddfSDavid du Colombier seg = 0;
717dd7cddfSDavid du Colombier for(done = 0; !done; lineno++){
727dd7cddfSDavid du Colombier err = rdcpline(b, &c);
737dd7cddfSDavid du Colombier if(err)
749a747e4fSDavid du Colombier sysfatal("%s line %d: %s", file, lineno, err);
757dd7cddfSDavid du Colombier switch(c.type){
767dd7cddfSDavid du Colombier case 0: /* data */
777dd7cddfSDavid du Colombier addr = seg + c.addr;
787dd7cddfSDavid du Colombier if(addr + c.dlen > Memsize)
799a747e4fSDavid du Colombier sysfatal("addr out of range: %lux-%lux", addr, addr+c.dlen);
807dd7cddfSDavid du Colombier if(seek(mfd, addr, 0) < 0)
819a747e4fSDavid du Colombier sysfatal("seeking to %lud: %r", addr);
827dd7cddfSDavid du Colombier if(write(mfd, c.bytes+Doff, c.dlen) != c.dlen)
839a747e4fSDavid du Colombier sysfatal("writing: %r");
847dd7cddfSDavid du Colombier if(seek(mfd, addr, 0) < 0)
859a747e4fSDavid du Colombier sysfatal("seeking to %lud: %r", addr);
867dd7cddfSDavid du Colombier if(read(mfd, buf, c.dlen) != c.dlen)
879a747e4fSDavid du Colombier sysfatal("reading: %r");
887dd7cddfSDavid du Colombier if(memcmp(buf, c.bytes+Doff, c.dlen) != 0)
897dd7cddfSDavid du Colombier print("readback error at %lux\n", addr);
907dd7cddfSDavid du Colombier if(dump)
917dd7cddfSDavid du Colombier print("%8.8lux: %d\n", addr, c.dlen);
927dd7cddfSDavid du Colombier break;
937dd7cddfSDavid du Colombier case 1: /* termination */
947dd7cddfSDavid du Colombier done = 1;
957dd7cddfSDavid du Colombier break;
967dd7cddfSDavid du Colombier case 2: /* segment */
977dd7cddfSDavid du Colombier seg = ((c.bytes[Doff]<<8) | c.bytes[Doff+1]) <<4;
987dd7cddfSDavid du Colombier if(seg >= Memsize)
999a747e4fSDavid du Colombier sysfatal("seg out of range: %lux", seg);
1007dd7cddfSDavid du Colombier if(dump)
1017dd7cddfSDavid du Colombier print("seg %8.8lux\n", seg);
1027dd7cddfSDavid du Colombier break;
1037dd7cddfSDavid du Colombier default: /* ignore */
1047dd7cddfSDavid du Colombier if(dump)
1057dd7cddfSDavid du Colombier print("bad type %d\n", c.type);
1067dd7cddfSDavid du Colombier break;
1077dd7cddfSDavid du Colombier }
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier Bterm(b);
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier
1127dd7cddfSDavid du Colombier void
main(int argc,char ** argv)1137dd7cddfSDavid du Colombier main(int argc, char **argv)
1147dd7cddfSDavid du Colombier {
1157dd7cddfSDavid du Colombier int unit;
1167dd7cddfSDavid du Colombier int cfd, mfd;
1177dd7cddfSDavid du Colombier char file[128];
1187dd7cddfSDavid du Colombier
1197dd7cddfSDavid du Colombier unit = 0;
1207dd7cddfSDavid du Colombier ARGBEGIN{
1217dd7cddfSDavid du Colombier case 'd':
1227dd7cddfSDavid du Colombier dump = 1;
1237dd7cddfSDavid du Colombier break;
1247dd7cddfSDavid du Colombier case 'i':
1257dd7cddfSDavid du Colombier image = 1;
1267dd7cddfSDavid du Colombier break;
1277dd7cddfSDavid du Colombier case 'n':
1287dd7cddfSDavid du Colombier noload = 1;
1297dd7cddfSDavid du Colombier break;
1307dd7cddfSDavid du Colombier case 's':
1317dd7cddfSDavid du Colombier nostart = 1;
1327dd7cddfSDavid du Colombier break;
1337dd7cddfSDavid du Colombier case '0':
1347dd7cddfSDavid du Colombier unit = 0;
1357dd7cddfSDavid du Colombier break;
1367dd7cddfSDavid du Colombier case '1':
1377dd7cddfSDavid du Colombier unit = 1;
1387dd7cddfSDavid du Colombier break;
1397dd7cddfSDavid du Colombier case '2':
1407dd7cddfSDavid du Colombier unit = 2;
1417dd7cddfSDavid du Colombier break;
1427dd7cddfSDavid du Colombier case '3':
1437dd7cddfSDavid du Colombier unit = 3;
1447dd7cddfSDavid du Colombier break;
1457dd7cddfSDavid du Colombier }ARGEND;
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier if(argc == 0)
1487dd7cddfSDavid du Colombier usage();
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier if(noload == 0){
1517dd7cddfSDavid du Colombier sprint(file, "#G/astar%dctl", unit);
1527dd7cddfSDavid du Colombier cfd = open(file, ORDWR);
1537dd7cddfSDavid du Colombier if(cfd < 0)
154*14cc0f53SDavid du Colombier sysfatal("opening %s", file);
1557dd7cddfSDavid du Colombier sprint(file, "#G/astar%dmem", unit);
1567dd7cddfSDavid du Colombier mfd = open(file, ORDWR);
1577dd7cddfSDavid du Colombier if(mfd < 0)
158*14cc0f53SDavid du Colombier sysfatal("opening %s", file);
1597dd7cddfSDavid du Colombier
1607dd7cddfSDavid du Colombier if(write(cfd, "download", 8) != 8)
1619a747e4fSDavid du Colombier sysfatal("requesting download: %r");
1627dd7cddfSDavid du Colombier } else {
1637dd7cddfSDavid du Colombier cfd = -1;
1647dd7cddfSDavid du Colombier mfd = create("/tmp/astarmem", ORDWR, 0664);
1657dd7cddfSDavid du Colombier if(mfd < 0)
1669a747e4fSDavid du Colombier sysfatal("creating /tmp/astarmem: %r");
1677dd7cddfSDavid du Colombier }
1687dd7cddfSDavid du Colombier
1697dd7cddfSDavid du Colombier if(image)
1707dd7cddfSDavid du Colombier loadimage(argv[0], mfd);
1717dd7cddfSDavid du Colombier else{
1727dd7cddfSDavid du Colombier /* zero out the memory */
1737dd7cddfSDavid du Colombier clearmem(mfd);
1747dd7cddfSDavid du Colombier loadhex(argv[0], mfd);
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier close(mfd);
1777dd7cddfSDavid du Colombier
1787dd7cddfSDavid du Colombier if(noload == 0 && nostart == 0)
1797dd7cddfSDavid du Colombier if(write(cfd, "run", 3) != 3)
1809a747e4fSDavid du Colombier sysfatal("requesting run: %r");
1817dd7cddfSDavid du Colombier close(cfd);
1827dd7cddfSDavid du Colombier
1837dd7cddfSDavid du Colombier exits(0);
1847dd7cddfSDavid du Colombier }
1857dd7cddfSDavid du Colombier
1867dd7cddfSDavid du Colombier void
clearmem(int fd)1877dd7cddfSDavid du Colombier clearmem(int fd)
1887dd7cddfSDavid du Colombier {
1897dd7cddfSDavid du Colombier char buf[4096];
1907dd7cddfSDavid du Colombier char buf2[4096];
1917dd7cddfSDavid du Colombier int i, n;
1927dd7cddfSDavid du Colombier
1937dd7cddfSDavid du Colombier memset(buf, 0, sizeof buf);
1947dd7cddfSDavid du Colombier for(i = 0; i < Memsize; i += n){
1957dd7cddfSDavid du Colombier if(seek(fd, i, 0) < 0)
1969a747e4fSDavid du Colombier sysfatal("seeking to %ux: %r", i);
1977dd7cddfSDavid du Colombier n = write(fd, buf, sizeof buf);
1987dd7cddfSDavid du Colombier if(n <= 0)
1997dd7cddfSDavid du Colombier break;
2007dd7cddfSDavid du Colombier if(seek(fd, i, 0) < 0)
2019a747e4fSDavid du Colombier sysfatal("seeking to %ux: %r", i);
2027dd7cddfSDavid du Colombier n = read(fd, buf2, sizeof buf2);
2037dd7cddfSDavid du Colombier if(n <= 0)
2047dd7cddfSDavid du Colombier break;
2057dd7cddfSDavid du Colombier if(memcmp(buf, buf2, sizeof buf) != 0)
2067dd7cddfSDavid du Colombier print("error zeroing mem at %ux\n", i);
2077dd7cddfSDavid du Colombier }
2087dd7cddfSDavid du Colombier print("zero'd %d bytes\n", i);
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier
2117dd7cddfSDavid du Colombier int
hex(char c)2127dd7cddfSDavid du Colombier hex(char c)
2137dd7cddfSDavid du Colombier {
2147dd7cddfSDavid du Colombier if(c <= '9' && c >= '0')
2157dd7cddfSDavid du Colombier return c - '0';
2167dd7cddfSDavid du Colombier if(c <= 'f' && c >= 'a')
2177dd7cddfSDavid du Colombier return (c - 'a') + 10;
2187dd7cddfSDavid du Colombier if(c <= 'F' && c >= 'A')
2197dd7cddfSDavid du Colombier return (c - 'A') + 10;
2207dd7cddfSDavid du Colombier return -1;
2217dd7cddfSDavid du Colombier }
2227dd7cddfSDavid du Colombier
2237dd7cddfSDavid du Colombier char*
rdcpline(Biobuf * b,Cpline * cpl)2247dd7cddfSDavid du Colombier rdcpline(Biobuf *b, Cpline *cpl)
2257dd7cddfSDavid du Colombier {
2267dd7cddfSDavid du Colombier char *cp, *ep, *p;
2277dd7cddfSDavid du Colombier uchar *up;
2287dd7cddfSDavid du Colombier uchar csum;
2297dd7cddfSDavid du Colombier int c;
2307dd7cddfSDavid du Colombier
2317dd7cddfSDavid du Colombier cp = Brdline(b, '\n');
2327dd7cddfSDavid du Colombier if(cp == 0)
2337dd7cddfSDavid du Colombier return "early eof";
2347dd7cddfSDavid du Colombier ep = cp + Blinelen(b);
2357dd7cddfSDavid du Colombier
2367dd7cddfSDavid du Colombier if(*cp++ != ':')
2377dd7cddfSDavid du Colombier return "bad load line";
2387dd7cddfSDavid du Colombier
2397dd7cddfSDavid du Colombier csum = 0;
2407dd7cddfSDavid du Colombier up = cpl->bytes;
2417dd7cddfSDavid du Colombier for(p = cp; p < ep;){
2427dd7cddfSDavid du Colombier c = hex(*p++)<<4;
2437dd7cddfSDavid du Colombier c |= hex(*p++);
2447dd7cddfSDavid du Colombier if(c < 0)
2457dd7cddfSDavid du Colombier break;
2467dd7cddfSDavid du Colombier csum += c;
2477dd7cddfSDavid du Colombier *up++ = c;
2487dd7cddfSDavid du Colombier }
2497dd7cddfSDavid du Colombier
2507dd7cddfSDavid du Colombier cpl->csum = csum;
2517dd7cddfSDavid du Colombier if(csum != 0){
2527dd7cddfSDavid du Colombier fprint(2, "checksum %ux\n", csum);
2537dd7cddfSDavid du Colombier return "bad checksum";
2547dd7cddfSDavid du Colombier }
2557dd7cddfSDavid du Colombier
2567dd7cddfSDavid du Colombier cpl->dlen = cpl->bytes[0];
2577dd7cddfSDavid du Colombier if(cpl->dlen + 5 != up - cpl->bytes){
2587dd7cddfSDavid du Colombier fprint(2, "%d %ld\n", cpl->dlen + 5, up - cpl->bytes);
2597dd7cddfSDavid du Colombier return "bad data length";
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier
2627dd7cddfSDavid du Colombier cpl->addr = (cpl->bytes[1]<<8) | cpl->bytes[2];
2637dd7cddfSDavid du Colombier cpl->type = cpl->bytes[3];
2647dd7cddfSDavid du Colombier return 0;
2657dd7cddfSDavid du Colombier }
266