xref: /plan9/sys/src/cmd/aux/ms2.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
4*7dd7cddfSDavid du Colombier #include <mach.h>
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier void	record(uchar*, int);
73e12c5d1SDavid du Colombier void	usage(void);
83e12c5d1SDavid du Colombier void	segment(long, int);
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;
18*7dd7cddfSDavid du Colombier int	halfswap;
19*7dd7cddfSDavid du Colombier int	srec = 2;
203e12c5d1SDavid du Colombier ulong	addr;
213e12c5d1SDavid du Colombier ulong 	psize = 4096;
223e12c5d1SDavid du Colombier Biobuf 	stdout;
23*7dd7cddfSDavid 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 {
29219b2ee8SDavid du Colombier 	Dir dir;
30*7dd7cddfSDavid du Colombier 	ulong 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':
403e12c5d1SDavid du Colombier 		addr = strtoul(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;
48*7dd7cddfSDavid du Colombier 	case 'h':
49*7dd7cddfSDavid du Colombier 		halfswap++;
50*7dd7cddfSDavid du Colombier 		break;
51*7dd7cddfSDavid du Colombier 	case '1':
52*7dd7cddfSDavid du Colombier 		srec = 1;
53*7dd7cddfSDavid du Colombier 		break;
54*7dd7cddfSDavid du Colombier 	case '2':
55*7dd7cddfSDavid du Colombier 		srec = 2;
56*7dd7cddfSDavid du Colombier 		break;
57*7dd7cddfSDavid du Colombier 	case '3':
58*7dd7cddfSDavid du Colombier 		srec = 3;
59*7dd7cddfSDavid 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) {
76219b2ee8SDavid du Colombier 		if(dirfstat(Bfildes(bio), &dir) < 0) {
77219b2ee8SDavid du Colombier 			fprint(2, "ms2: stat failed %r");
78219b2ee8SDavid du Colombier 			exits("dirfstat");
79219b2ee8SDavid du Colombier 		}
80219b2ee8SDavid du Colombier 		segment(0, dir.length);
81219b2ee8SDavid du Colombier 		Bprint(&stdout, "S9030000FC\n");
82219b2ee8SDavid du Colombier 		Bterm(&stdout);
83219b2ee8SDavid du Colombier 		Bterm(bio);
84219b2ee8SDavid du Colombier 		exits(0);
85219b2ee8SDavid du Colombier 	}
86219b2ee8SDavid du Colombier 
87*7dd7cddfSDavid du Colombier 	if(!crackhdr(Bfildes(bio), &exech)) {
88*7dd7cddfSDavid du Colombier 		fprint(2, "ms2: can't decode file header\n");
89*7dd7cddfSDavid du Colombier 		return;
903e12c5d1SDavid du Colombier 	}
913e12c5d1SDavid du Colombier 
92*7dd7cddfSDavid du Colombier 	totsz = exech.txtsz + exech.datsz + exech.bsssz;
93*7dd7cddfSDavid du Colombier 	fprint(2, "%s: %lud+%lud+%lud=%lud\n",
94*7dd7cddfSDavid du Colombier 		exech.name, exech.txtsz, exech.datsz, exech.bsssz, totsz);
953e12c5d1SDavid du Colombier 
963e12c5d1SDavid du Colombier 	if(dsegonly)
97*7dd7cddfSDavid du Colombier 		segment(exech.datoff, exech.datsz);
983e12c5d1SDavid du Colombier 	else {
99*7dd7cddfSDavid du Colombier 		segment(exech.txtoff, exech.txtsz);
1003e12c5d1SDavid du Colombier 		addr = (addr+(psize-1))&~(psize-1);
101*7dd7cddfSDavid du Colombier 		segment(exech.datoff, exech.datsz);
1023e12c5d1SDavid du Colombier 	}
1033e12c5d1SDavid du Colombier 
104*7dd7cddfSDavid du Colombier 	if(supressend == 0) {
105*7dd7cddfSDavid du Colombier 		switch(srec) {
106*7dd7cddfSDavid du Colombier 		case 1:
107*7dd7cddfSDavid du Colombier 		case 2:
1083e12c5d1SDavid du Colombier 			Bprint(&stdout, "S9030000FC\n");
109*7dd7cddfSDavid du Colombier 			break;
110*7dd7cddfSDavid du Colombier 		case 3:
111*7dd7cddfSDavid du Colombier 			Bprint(&stdout, "S705000000FA\n");
112*7dd7cddfSDavid du Colombier 			break;
113*7dd7cddfSDavid du Colombier 		}
114*7dd7cddfSDavid du Colombier 	}
1153e12c5d1SDavid du Colombier 
116219b2ee8SDavid du Colombier 	Bterm(&stdout);
117219b2ee8SDavid du Colombier 	Bterm(bio);
1183e12c5d1SDavid du Colombier 	exits(0);
1193e12c5d1SDavid du Colombier }
1203e12c5d1SDavid du Colombier 
1213e12c5d1SDavid du Colombier void
1223e12c5d1SDavid du Colombier segment(long foff, int len)
1233e12c5d1SDavid du Colombier {
124*7dd7cddfSDavid du Colombier 	int l, n, i;
125*7dd7cddfSDavid du Colombier 	uchar t, buf[2*Recordsize];
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier 	Bseek(bio, foff, 0);
1283e12c5d1SDavid du Colombier 	for(;;) {
1293e12c5d1SDavid du Colombier 		l = len;
1303e12c5d1SDavid du Colombier 		if(l > Recordsize)
1313e12c5d1SDavid du Colombier 			l = Recordsize;
1323e12c5d1SDavid du Colombier 		n = Bread(bio, buf, l);
1333e12c5d1SDavid du Colombier 		if(n == 0)
1343e12c5d1SDavid du Colombier 			break;
1353e12c5d1SDavid du Colombier 		if(n < 0) {
1363e12c5d1SDavid du Colombier 			fprint(2, "ms2: read error: %r\n");
1373e12c5d1SDavid du Colombier 			exits("read");
1383e12c5d1SDavid du Colombier 		}
139*7dd7cddfSDavid du Colombier 		if(halfswap) {
140*7dd7cddfSDavid du Colombier 			if(n & 1) {
141*7dd7cddfSDavid du Colombier 				fprint(2, "ms2: data must be even length\n");
142*7dd7cddfSDavid du Colombier 				exits("even");
143*7dd7cddfSDavid du Colombier 			}
144*7dd7cddfSDavid du Colombier 			for(i = 0; i < n; i += 2) {
145*7dd7cddfSDavid du Colombier 				t = buf[i];
146*7dd7cddfSDavid du Colombier 				buf[i] = buf[i+1];
147*7dd7cddfSDavid du Colombier 				buf[i+1] = t;
148*7dd7cddfSDavid du Colombier 			}
149*7dd7cddfSDavid du Colombier 		}
1503e12c5d1SDavid du Colombier 		record(buf, l);
1513e12c5d1SDavid du Colombier 		len -= l;
1523e12c5d1SDavid du Colombier 	}
1533e12c5d1SDavid du Colombier }
1543e12c5d1SDavid du Colombier 
1553e12c5d1SDavid du Colombier void
1563e12c5d1SDavid du Colombier record(uchar *s, int l)
1573e12c5d1SDavid du Colombier {
1583e12c5d1SDavid du Colombier 	int i;
159*7dd7cddfSDavid du Colombier 	ulong cksum = 0;
1603e12c5d1SDavid du Colombier 
161*7dd7cddfSDavid du Colombier 	switch(srec) {
162*7dd7cddfSDavid du Colombier 	case 1:
163*7dd7cddfSDavid du Colombier 		cksum = l+3;
164*7dd7cddfSDavid du Colombier 		Bprint(&stdout, "S1%.2X%.4luX", l+3, addr);
165*7dd7cddfSDavid du Colombier 		cksum += addr&0xff;
166*7dd7cddfSDavid du Colombier 		cksum += (addr>>8)&0xff;
167*7dd7cddfSDavid du Colombier 		break;
168*7dd7cddfSDavid du Colombier 	case 2:
1693e12c5d1SDavid du Colombier 		cksum = l+4;
170*7dd7cddfSDavid du Colombier 		Bprint(&stdout, "S2%.2X%.6luX", l+4, addr);
1713e12c5d1SDavid du Colombier 		cksum += addr&0xff;
1723e12c5d1SDavid du Colombier 		cksum += (addr>>8)&0xff;
1733e12c5d1SDavid du Colombier 		cksum += (addr>>16)&0xff;
174*7dd7cddfSDavid du Colombier 		break;
175*7dd7cddfSDavid du Colombier 	case 3:
176*7dd7cddfSDavid du Colombier 		cksum = l+5;
177*7dd7cddfSDavid du Colombier 		Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
178*7dd7cddfSDavid du Colombier 		cksum += addr&0xff;
179*7dd7cddfSDavid du Colombier 		cksum += (addr>>8)&0xff;
180*7dd7cddfSDavid du Colombier 		cksum += (addr>>16)&0xff;
181*7dd7cddfSDavid du Colombier 		cksum += (addr>>24)&0xff;
182*7dd7cddfSDavid du Colombier 		break;
183*7dd7cddfSDavid du Colombier 	}
1843e12c5d1SDavid du Colombier 
1853e12c5d1SDavid du Colombier 	for(i = 0; i < l; i++) {
1863e12c5d1SDavid du Colombier 		cksum += *s;
1873e12c5d1SDavid du Colombier 		Bprint(&stdout, "%.2X", *s++);
1883e12c5d1SDavid du Colombier 	}
189*7dd7cddfSDavid du Colombier 	Bprint(&stdout, "%.2luX\n", (~cksum)&0xff);
1903e12c5d1SDavid du Colombier 	addr += l;
1913e12c5d1SDavid du Colombier }
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier void
1943e12c5d1SDavid du Colombier usage(void)
1953e12c5d1SDavid du Colombier {
196*7dd7cddfSDavid du Colombier 	fprint(2, "usage: ms2 [-dsbh] [-a address] [-p pagesize] ?.out\n");
1973e12c5d1SDavid du Colombier 	exits("usage");
1983e12c5d1SDavid du Colombier }
199