xref: /plan9/sys/src/cmd/aux/astarld.c (revision 14cc0f535177405a84c5b73603a98e5db6674719)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 enum
6 {
7 	Doff=		4,	/* offset into Cpline.bytes of data */
8 
9 	Memsize=	1<<16,	/* max size of 186 memory */
10 };
11 
12 int dump, image, noload, nostart;
13 
14 typedef struct
15 {
16 	int	type;
17 	int	dlen;
18 	ulong	addr;
19 	uchar	bytes[256+4];
20 	uchar	csum;
21 } Cpline;
22 
23 char*	rdcpline(Biobuf*, Cpline*);
24 void	clearmem(int);
25 
26 void
usage(void)27 usage(void)
28 {
29 	fprint(2, "usage: %s [-0123] file\n", argv0);
30 	exits("usage");
31 }
32 
33 static void
loadimage(char * file,int mfd)34 loadimage(char* file, int mfd)
35 {
36 	uchar buf[256];
37 	int fd, n, r;
38 
39 	if((fd = open(file, OREAD)) < 0)
40 		sysfatal("opening %s: %r", file);
41 
42 	seek(mfd, 0, 0);
43 	do{
44 		n = read(fd, buf, sizeof(buf));
45 		if(n < 0)
46 			sysfatal("read %s: %r", file);
47 		if(n > 0)
48 			if((r = write(mfd, buf, n)) != n)
49 				sysfatal("write %s: %d != %d: %r", file, n, r);
50 	}while(n > 0);
51 	close(fd);
52 }
53 
54 static void
loadhex(char * file,int mfd)55 loadhex(char* file, int mfd)
56 {
57 	int done;
58 	Cpline c;
59 	Biobuf *b;
60 	char *err;
61 	ulong addr, seg;
62 	int lineno;
63 	uchar buf[1024];
64 
65 	b = Bopen(file, OREAD);
66 	if(b == 0)
67 		sysfatal("opening %s: %r", file);
68 
69 	lineno = 1;
70 	seg = 0;
71 	for(done = 0; !done; lineno++){
72 		err = rdcpline(b, &c);
73 		if(err)
74 			sysfatal("%s line %d: %s", file, lineno, err);
75 		switch(c.type){
76 		case 0: /* data */
77 			addr = seg + c.addr;
78 			if(addr + c.dlen > Memsize)
79 				sysfatal("addr out of range: %lux-%lux", addr, addr+c.dlen);
80 			if(seek(mfd, addr, 0) < 0)
81 				sysfatal("seeking to %lud: %r", addr);
82 			if(write(mfd, c.bytes+Doff, c.dlen) != c.dlen)
83 				sysfatal("writing: %r");
84 			if(seek(mfd, addr, 0) < 0)
85 				sysfatal("seeking to %lud: %r", addr);
86 			if(read(mfd, buf, c.dlen) != c.dlen)
87 				sysfatal("reading: %r");
88 			if(memcmp(buf, c.bytes+Doff, c.dlen) != 0)
89 				print("readback error at %lux\n", addr);
90 			if(dump)
91 				print("%8.8lux: %d\n", addr, c.dlen);
92 			break;
93 		case 1: /* termination */
94 			done = 1;
95 			break;
96 		case 2: /* segment */
97 			seg = ((c.bytes[Doff]<<8) | c.bytes[Doff+1]) <<4;
98 			if(seg >= Memsize)
99 				sysfatal("seg out of range: %lux", seg);
100 			if(dump)
101 				print("seg %8.8lux\n", seg);
102 			break;
103 		default: /* ignore */
104 			if(dump)
105 				print("bad type %d\n", c.type);
106 			break;
107 		}
108 	}
109 	Bterm(b);
110 }
111 
112 void
main(int argc,char ** argv)113 main(int argc, char **argv)
114 {
115 	int unit;
116 	int cfd, mfd;
117 	char file[128];
118 
119 	unit = 0;
120 	ARGBEGIN{
121 	case 'd':
122 		dump = 1;
123 		break;
124 	case 'i':
125 		image = 1;
126 		break;
127 	case 'n':
128 		noload = 1;
129 		break;
130 	case 's':
131 		nostart = 1;
132 		break;
133 	case '0':
134 		unit = 0;
135 		break;
136 	case '1':
137 		unit = 1;
138 		break;
139 	case '2':
140 		unit = 2;
141 		break;
142 	case '3':
143 		unit = 3;
144 		break;
145 	}ARGEND;
146 
147 	if(argc == 0)
148 		usage();
149 
150 	if(noload == 0){
151 		sprint(file, "#G/astar%dctl", unit);
152 		cfd = open(file, ORDWR);
153 		if(cfd < 0)
154 			sysfatal("opening %s", file);
155 		sprint(file, "#G/astar%dmem", unit);
156 		mfd = open(file, ORDWR);
157 		if(mfd < 0)
158 			sysfatal("opening %s", file);
159 
160 		if(write(cfd, "download", 8) != 8)
161 			sysfatal("requesting download: %r");
162 	} else {
163 		cfd = -1;
164 		mfd = create("/tmp/astarmem", ORDWR, 0664);
165 		if(mfd < 0)
166 			sysfatal("creating /tmp/astarmem: %r");
167 	}
168 
169 	if(image)
170 		loadimage(argv[0], mfd);
171 	else{
172 		/* zero out the memory */
173 		clearmem(mfd);
174 		loadhex(argv[0], mfd);
175 	}
176 	close(mfd);
177 
178 	if(noload == 0 && nostart == 0)
179 		if(write(cfd, "run", 3) != 3)
180 			sysfatal("requesting run: %r");
181 	close(cfd);
182 
183 	exits(0);
184 }
185 
186 void
clearmem(int fd)187 clearmem(int fd)
188 {
189 	char buf[4096];
190 	char buf2[4096];
191 	int i, n;
192 
193 	memset(buf, 0, sizeof buf);
194 	for(i = 0; i < Memsize; i += n){
195 		if(seek(fd, i, 0) < 0)
196 			sysfatal("seeking to %ux: %r", i);
197 		n = write(fd, buf, sizeof buf);
198 		if(n <= 0)
199 			break;
200 		if(seek(fd, i, 0) < 0)
201 			sysfatal("seeking to %ux: %r", i);
202 		n = read(fd, buf2, sizeof buf2);
203 		if(n <= 0)
204 			break;
205 		if(memcmp(buf, buf2, sizeof buf) != 0)
206 			print("error zeroing mem at %ux\n", i);
207 	}
208 	print("zero'd %d bytes\n", i);
209 }
210 
211 int
hex(char c)212 hex(char c)
213 {
214 	if(c <= '9' && c >= '0')
215 		return c - '0';
216 	if(c <= 'f' && c >= 'a')
217 		return (c - 'a') + 10;
218 	if(c <= 'F' && c >= 'A')
219 		return (c - 'A') + 10;
220 	return -1;
221 }
222 
223 char*
rdcpline(Biobuf * b,Cpline * cpl)224 rdcpline(Biobuf *b, Cpline *cpl)
225 {
226 	char *cp, *ep, *p;
227 	uchar *up;
228 	uchar csum;
229 	int c;
230 
231 	cp = Brdline(b, '\n');
232 	if(cp == 0)
233 		return "early eof";
234 	ep = cp + Blinelen(b);
235 
236 	if(*cp++ != ':')
237 		return "bad load line";
238 
239 	csum = 0;
240 	up = cpl->bytes;
241  	for(p = cp; p < ep;){
242 		c = hex(*p++)<<4;
243 		c |= hex(*p++);
244 		if(c < 0)
245 			break;
246 		csum += c;
247 		*up++ = c;
248 	}
249 
250 	cpl->csum = csum;
251 	if(csum != 0){
252 		fprint(2, "checksum %ux\n", csum);
253 		return "bad checksum";
254 	}
255 
256 	cpl->dlen = cpl->bytes[0];
257 	if(cpl->dlen + 5 != up - cpl->bytes){
258 		fprint(2, "%d %ld\n", cpl->dlen + 5, up - cpl->bytes);
259 		return "bad data length";
260 	}
261 
262 	cpl->addr = (cpl->bytes[1]<<8) | cpl->bytes[2];
263 	cpl->type = cpl->bytes[3];
264 	return 0;
265 }
266