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
616941224SDavid du Colombier void record(uchar*, long);
73e12c5d1SDavid du Colombier void usage(void);
816941224SDavid 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;
2016941224SDavid du Colombier uvlong addr;
21*1936bb65SDavid du Colombier uvlong psize = 4096;
223e12c5d1SDavid du Colombier Biobuf stdout;
237dd7cddfSDavid du Colombier Fhdr exech;
243e12c5d1SDavid du Colombier Biobuf *bio;
253e12c5d1SDavid du Colombier
263e12c5d1SDavid du Colombier void
main(int argc,char ** argv)273e12c5d1SDavid du Colombier main(int argc, char **argv)
283e12c5d1SDavid du Colombier {
299a747e4fSDavid du Colombier Dir *dir;
3016941224SDavid 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':
4016941224SDavid 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;
9416941224SDavid 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
segment(vlong foff,vlong len)12316941224SDavid du Colombier segment(vlong foff, vlong len)
1243e12c5d1SDavid du Colombier {
12516941224SDavid du Colombier int i;
12616941224SDavid 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
record(uchar * s,long l)15816941224SDavid 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;
16616941224SDavid 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;
17216941224SDavid 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;
17916941224SDavid 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
usage(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