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