13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <bio.h> 47dd7cddfSDavid du Colombier #include <mach.h> 53e12c5d1SDavid du Colombier 6*16941224SDavid du Colombier void record(uchar*, long); 73e12c5d1SDavid du Colombier void usage(void); 8*16941224SDavid du Colombier void segment(vlong, vlong); 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier enum 113e12c5d1SDavid du Colombier { 123e12c5d1SDavid du Colombier Recordsize = 32, 133e12c5d1SDavid du Colombier }; 143e12c5d1SDavid du Colombier 153e12c5d1SDavid du Colombier int dsegonly; 163e12c5d1SDavid du Colombier int supressend; 17219b2ee8SDavid du Colombier int binary; 187dd7cddfSDavid du Colombier int halfswap; 197dd7cddfSDavid du Colombier int srec = 2; 20*16941224SDavid du Colombier uvlong addr; 213e12c5d1SDavid du Colombier ulong psize = 4096; 223e12c5d1SDavid du Colombier Biobuf stdout; 237dd7cddfSDavid du Colombier Fhdr exech; 243e12c5d1SDavid du Colombier Biobuf *bio; 253e12c5d1SDavid du Colombier 263e12c5d1SDavid du Colombier void 273e12c5d1SDavid du Colombier main(int argc, char **argv) 283e12c5d1SDavid du Colombier { 299a747e4fSDavid du Colombier Dir *dir; 30*16941224SDavid du Colombier uvlong totsz; 313e12c5d1SDavid du Colombier 323e12c5d1SDavid du Colombier ARGBEGIN{ 333e12c5d1SDavid du Colombier case 'd': 343e12c5d1SDavid du Colombier dsegonly++; 353e12c5d1SDavid du Colombier break; 363e12c5d1SDavid du Colombier case 's': 373e12c5d1SDavid du Colombier supressend++; 383e12c5d1SDavid du Colombier break; 393e12c5d1SDavid du Colombier case 'a': 40*16941224SDavid du Colombier addr = strtoull(ARGF(), 0, 0); 413e12c5d1SDavid du Colombier break; 423e12c5d1SDavid du Colombier case 'p': 433e12c5d1SDavid du Colombier psize = strtoul(ARGF(), 0, 0); 443e12c5d1SDavid du Colombier break; 45219b2ee8SDavid du Colombier case 'b': 46219b2ee8SDavid du Colombier binary++; 47219b2ee8SDavid du Colombier break; 487dd7cddfSDavid du Colombier case 'h': 497dd7cddfSDavid du Colombier halfswap++; 507dd7cddfSDavid du Colombier break; 517dd7cddfSDavid du Colombier case '1': 527dd7cddfSDavid du Colombier srec = 1; 537dd7cddfSDavid du Colombier break; 547dd7cddfSDavid du Colombier case '2': 557dd7cddfSDavid du Colombier srec = 2; 567dd7cddfSDavid du Colombier break; 577dd7cddfSDavid du Colombier case '3': 587dd7cddfSDavid du Colombier srec = 3; 597dd7cddfSDavid du Colombier break; 603e12c5d1SDavid du Colombier default: 613e12c5d1SDavid du Colombier usage(); 623e12c5d1SDavid du Colombier }ARGEND 633e12c5d1SDavid du Colombier 643e12c5d1SDavid du Colombier if(argc != 1) 653e12c5d1SDavid du Colombier usage(); 663e12c5d1SDavid du Colombier 673e12c5d1SDavid du Colombier Binit(&stdout, 1, OWRITE); 683e12c5d1SDavid du Colombier 693e12c5d1SDavid du Colombier bio = Bopen(argv[0], OREAD); 703e12c5d1SDavid du Colombier if(bio == 0) { 713e12c5d1SDavid du Colombier fprint(2, "ms2: open %s: %r\n", argv[0]); 723e12c5d1SDavid du Colombier exits("open"); 733e12c5d1SDavid du Colombier } 743e12c5d1SDavid du Colombier 75219b2ee8SDavid du Colombier if(binary) { 769a747e4fSDavid du Colombier if((dir = dirfstat(Bfildes(bio))) == nil) { 77219b2ee8SDavid du Colombier fprint(2, "ms2: stat failed %r"); 78219b2ee8SDavid du Colombier exits("dirfstat"); 79219b2ee8SDavid du Colombier } 809a747e4fSDavid du Colombier segment(0, dir->length); 81219b2ee8SDavid du Colombier Bprint(&stdout, "S9030000FC\n"); 82219b2ee8SDavid du Colombier Bterm(&stdout); 83219b2ee8SDavid du Colombier Bterm(bio); 849a747e4fSDavid du Colombier free(dir); 85219b2ee8SDavid du Colombier exits(0); 86219b2ee8SDavid du Colombier } 87219b2ee8SDavid du Colombier 887dd7cddfSDavid du Colombier if(!crackhdr(Bfildes(bio), &exech)) { 897dd7cddfSDavid du Colombier fprint(2, "ms2: can't decode file header\n"); 907dd7cddfSDavid du Colombier return; 913e12c5d1SDavid du Colombier } 923e12c5d1SDavid du Colombier 937dd7cddfSDavid du Colombier totsz = exech.txtsz + exech.datsz + exech.bsssz; 94*16941224SDavid du Colombier fprint(2, "%s: %lud+%lud+%lud=%llud\n", 957dd7cddfSDavid du Colombier exech.name, exech.txtsz, exech.datsz, exech.bsssz, totsz); 963e12c5d1SDavid du Colombier 973e12c5d1SDavid du Colombier if(dsegonly) 987dd7cddfSDavid du Colombier segment(exech.datoff, exech.datsz); 993e12c5d1SDavid du Colombier else { 1007dd7cddfSDavid du Colombier segment(exech.txtoff, exech.txtsz); 1013e12c5d1SDavid du Colombier addr = (addr+(psize-1))&~(psize-1); 1027dd7cddfSDavid du Colombier segment(exech.datoff, exech.datsz); 1033e12c5d1SDavid du Colombier } 1043e12c5d1SDavid du Colombier 1057dd7cddfSDavid du Colombier if(supressend == 0) { 1067dd7cddfSDavid du Colombier switch(srec) { 1077dd7cddfSDavid du Colombier case 1: 1087dd7cddfSDavid du Colombier case 2: 1093e12c5d1SDavid du Colombier Bprint(&stdout, "S9030000FC\n"); 1107dd7cddfSDavid du Colombier break; 1117dd7cddfSDavid du Colombier case 3: 1127dd7cddfSDavid du Colombier Bprint(&stdout, "S705000000FA\n"); 1137dd7cddfSDavid du Colombier break; 1147dd7cddfSDavid du Colombier } 1157dd7cddfSDavid du Colombier } 1163e12c5d1SDavid du Colombier 117219b2ee8SDavid du Colombier Bterm(&stdout); 118219b2ee8SDavid du Colombier Bterm(bio); 1193e12c5d1SDavid du Colombier exits(0); 1203e12c5d1SDavid du Colombier } 1213e12c5d1SDavid du Colombier 1223e12c5d1SDavid du Colombier void 123*16941224SDavid du Colombier segment(vlong foff, vlong len) 1243e12c5d1SDavid du Colombier { 125*16941224SDavid du Colombier int i; 126*16941224SDavid du Colombier long l, n; 1277dd7cddfSDavid du Colombier uchar t, buf[2*Recordsize]; 1283e12c5d1SDavid du Colombier 1293e12c5d1SDavid du Colombier Bseek(bio, foff, 0); 1303e12c5d1SDavid du Colombier for(;;) { 1313e12c5d1SDavid du Colombier l = len; 1323e12c5d1SDavid du Colombier if(l > Recordsize) 1333e12c5d1SDavid du Colombier l = Recordsize; 1343e12c5d1SDavid du Colombier n = Bread(bio, buf, l); 1353e12c5d1SDavid du Colombier if(n == 0) 1363e12c5d1SDavid du Colombier break; 1373e12c5d1SDavid du Colombier if(n < 0) { 1383e12c5d1SDavid du Colombier fprint(2, "ms2: read error: %r\n"); 1393e12c5d1SDavid du Colombier exits("read"); 1403e12c5d1SDavid du Colombier } 1417dd7cddfSDavid du Colombier if(halfswap) { 1427dd7cddfSDavid du Colombier if(n & 1) { 1437dd7cddfSDavid du Colombier fprint(2, "ms2: data must be even length\n"); 1447dd7cddfSDavid du Colombier exits("even"); 1457dd7cddfSDavid du Colombier } 1467dd7cddfSDavid du Colombier for(i = 0; i < n; i += 2) { 1477dd7cddfSDavid du Colombier t = buf[i]; 1487dd7cddfSDavid du Colombier buf[i] = buf[i+1]; 1497dd7cddfSDavid du Colombier buf[i+1] = t; 1507dd7cddfSDavid du Colombier } 1517dd7cddfSDavid du Colombier } 1523e12c5d1SDavid du Colombier record(buf, l); 1533e12c5d1SDavid du Colombier len -= l; 1543e12c5d1SDavid du Colombier } 1553e12c5d1SDavid du Colombier } 1563e12c5d1SDavid du Colombier 1573e12c5d1SDavid du Colombier void 158*16941224SDavid du Colombier record(uchar *s, long l) 1593e12c5d1SDavid du Colombier { 1603e12c5d1SDavid du Colombier int i; 1617dd7cddfSDavid du Colombier ulong cksum = 0; 1623e12c5d1SDavid du Colombier 1637dd7cddfSDavid du Colombier switch(srec) { 1647dd7cddfSDavid du Colombier case 1: 1657dd7cddfSDavid du Colombier cksum = l+3; 166*16941224SDavid du Colombier Bprint(&stdout, "S1%.2lX%.4lluX", l+3, addr); 1677dd7cddfSDavid du Colombier cksum += addr&0xff; 1687dd7cddfSDavid du Colombier cksum += (addr>>8)&0xff; 1697dd7cddfSDavid du Colombier break; 1707dd7cddfSDavid du Colombier case 2: 1713e12c5d1SDavid du Colombier cksum = l+4; 172*16941224SDavid du Colombier Bprint(&stdout, "S2%.2lX%.6lluX", l+4, addr); 1733e12c5d1SDavid du Colombier cksum += addr&0xff; 1743e12c5d1SDavid du Colombier cksum += (addr>>8)&0xff; 1753e12c5d1SDavid du Colombier cksum += (addr>>16)&0xff; 1767dd7cddfSDavid du Colombier break; 1777dd7cddfSDavid du Colombier case 3: 1787dd7cddfSDavid du Colombier cksum = l+5; 179*16941224SDavid du Colombier Bprint(&stdout, "S3%.2lX%.8lluX", l+5, addr); 1807dd7cddfSDavid du Colombier cksum += addr&0xff; 1817dd7cddfSDavid du Colombier cksum += (addr>>8)&0xff; 1827dd7cddfSDavid du Colombier cksum += (addr>>16)&0xff; 1837dd7cddfSDavid du Colombier cksum += (addr>>24)&0xff; 1847dd7cddfSDavid du Colombier break; 1857dd7cddfSDavid du Colombier } 1863e12c5d1SDavid du Colombier 1873e12c5d1SDavid du Colombier for(i = 0; i < l; i++) { 1883e12c5d1SDavid du Colombier cksum += *s; 1893e12c5d1SDavid du Colombier Bprint(&stdout, "%.2X", *s++); 1903e12c5d1SDavid du Colombier } 1917dd7cddfSDavid du Colombier Bprint(&stdout, "%.2luX\n", (~cksum)&0xff); 1923e12c5d1SDavid du Colombier addr += l; 1933e12c5d1SDavid du Colombier } 1943e12c5d1SDavid du Colombier 1953e12c5d1SDavid du Colombier void 1963e12c5d1SDavid du Colombier usage(void) 1973e12c5d1SDavid du Colombier { 1987dd7cddfSDavid du Colombier fprint(2, "usage: ms2 [-dsbh] [-a address] [-p pagesize] ?.out\n"); 1993e12c5d1SDavid du Colombier exits("usage"); 2003e12c5d1SDavid du Colombier } 201