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 27 usage(void) 28 { 29 fprint(2, "usage: %s [-0123] file\n", argv0); 30 exits("usage"); 31 } 32 33 static void 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 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 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 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 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* 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