xref: /plan9/sys/src/cmd/aux/ms2.c (revision 1936bb650459bace06c38a45b60888b47e5cd459)
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