xref: /plan9/sys/src/cmd/aux/ms2.c (revision 1936bb650459bace06c38a45b60888b47e5cd459)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 
6 void	record(uchar*, long);
7 void	usage(void);
8 void	segment(vlong, vlong);
9 
10 enum
11 {
12 	Recordsize = 32,
13 };
14 
15 int	dsegonly;
16 int	supressend;
17 int	binary;
18 int	halfswap;
19 int	srec = 2;
20 uvlong	addr;
21 uvlong 	psize = 4096;
22 Biobuf 	stdout;
23 Fhdr	exech;
24 Biobuf *bio;
25 
26 void
main(int argc,char ** argv)27 main(int argc, char **argv)
28 {
29 	Dir *dir;
30 	uvlong totsz;
31 
32 	ARGBEGIN{
33 	case 'd':
34 		dsegonly++;
35 		break;
36 	case 's':
37 		supressend++;
38 		break;
39 	case 'a':
40 		addr = strtoull(ARGF(), 0, 0);
41 		break;
42 	case 'p':
43 		psize = strtoul(ARGF(), 0, 0);
44 		break;
45 	case 'b':
46 		binary++;
47 		break;
48 	case 'h':
49 		halfswap++;
50 		break;
51 	case '1':
52 		srec = 1;
53 		break;
54 	case '2':
55 		srec = 2;
56 		break;
57 	case '3':
58 		srec = 3;
59 		break;
60 	default:
61 		usage();
62 	}ARGEND
63 
64 	if(argc != 1)
65 		usage();
66 
67 	Binit(&stdout, 1, OWRITE);
68 
69 	bio = Bopen(argv[0], OREAD);
70 	if(bio == 0) {
71 		fprint(2, "ms2: open %s: %r\n", argv[0]);
72 		exits("open");
73 	}
74 
75 	if(binary) {
76 		if((dir = dirfstat(Bfildes(bio))) == nil) {
77 			fprint(2, "ms2: stat failed %r");
78 			exits("dirfstat");
79 		}
80 		segment(0, dir->length);
81 		Bprint(&stdout, "S9030000FC\n");
82 		Bterm(&stdout);
83 		Bterm(bio);
84 		free(dir);
85 		exits(0);
86 	}
87 
88 	if(!crackhdr(Bfildes(bio), &exech)) {
89 		fprint(2, "ms2: can't decode file header\n");
90 		return;
91 	}
92 
93 	totsz = exech.txtsz + exech.datsz + exech.bsssz;
94 	fprint(2, "%s: %lud+%lud+%lud=%llud\n",
95 		exech.name, exech.txtsz, exech.datsz, exech.bsssz, totsz);
96 
97 	if(dsegonly)
98 		segment(exech.datoff, exech.datsz);
99 	else {
100 		segment(exech.txtoff, exech.txtsz);
101 		addr = (addr+(psize-1))&~(psize-1);
102 		segment(exech.datoff, exech.datsz);
103 	}
104 
105 	if(supressend == 0) {
106 		switch(srec) {
107 		case 1:
108 		case 2:
109 			Bprint(&stdout, "S9030000FC\n");
110 			break;
111 		case 3:
112 			Bprint(&stdout, "S705000000FA\n");
113 			break;
114 		}
115 	}
116 
117 	Bterm(&stdout);
118 	Bterm(bio);
119 	exits(0);
120 }
121 
122 void
segment(vlong foff,vlong len)123 segment(vlong foff, vlong len)
124 {
125 	int i;
126 	long l, n;
127 	uchar t, buf[2*Recordsize];
128 
129 	Bseek(bio, foff, 0);
130 	for(;;) {
131 		l = len;
132 		if(l > Recordsize)
133 			l = Recordsize;
134 		n = Bread(bio, buf, l);
135 		if(n == 0)
136 			break;
137 		if(n < 0) {
138 			fprint(2, "ms2: read error: %r\n");
139 			exits("read");
140 		}
141 		if(halfswap) {
142 			if(n & 1) {
143 				fprint(2, "ms2: data must be even length\n");
144 				exits("even");
145 			}
146 			for(i = 0; i < n; i += 2) {
147 				t = buf[i];
148 				buf[i] = buf[i+1];
149 				buf[i+1] = t;
150 			}
151 		}
152 		record(buf, l);
153 		len -= l;
154 	}
155 }
156 
157 void
record(uchar * s,long l)158 record(uchar *s, long l)
159 {
160 	int i;
161 	ulong cksum = 0;
162 
163 	switch(srec) {
164 	case 1:
165 		cksum = l+3;
166 		Bprint(&stdout, "S1%.2lX%.4lluX", l+3, addr);
167 		cksum += addr&0xff;
168 		cksum += (addr>>8)&0xff;
169 		break;
170 	case 2:
171 		cksum = l+4;
172 		Bprint(&stdout, "S2%.2lX%.6lluX", l+4, addr);
173 		cksum += addr&0xff;
174 		cksum += (addr>>8)&0xff;
175 		cksum += (addr>>16)&0xff;
176 		break;
177 	case 3:
178 		cksum = l+5;
179 		Bprint(&stdout, "S3%.2lX%.8lluX", l+5, addr);
180 		cksum += addr&0xff;
181 		cksum += (addr>>8)&0xff;
182 		cksum += (addr>>16)&0xff;
183 		cksum += (addr>>24)&0xff;
184 		break;
185 	}
186 
187 	for(i = 0; i < l; i++) {
188 		cksum += *s;
189 		Bprint(&stdout, "%.2X", *s++);
190 	}
191 	Bprint(&stdout, "%.2luX\n", (~cksum)&0xff);
192 	addr += l;
193 }
194 
195 void
usage(void)196 usage(void)
197 {
198 	fprint(2, "usage: ms2 [-dsbh] [-a address] [-p pagesize] ?.out\n");
199 	exits("usage");
200 }
201