xref: /plan9/sys/src/cmd/aux/astarld.c (revision 14cc0f535177405a84c5b73603a98e5db6674719)
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