comparison miscprog/mokosrec2bin.c @ 129:597143ba1c37

miscellaneous C programs moved out of the top level directory
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 06 Apr 2014 20:20:39 +0000
parents mokosrec2bin.c@cb736d95338d
children
comparison
equal deleted inserted replaced
128:03f8a618689e 129:597143ba1c37
1 /*
2 * The *.m0 format in which the Closedmoko firmware images have been
3 * distributed is a form of SREC, but further examination quickly
4 * reveals that the data bytes are swapped: the byte order is neither
5 * the natural little-endian ARM one of the Calypso, nor a word-wise
6 * ARM BE; instead the upper and lower bytes of each 16-bit shortword
7 * are swapped relative to the natural byte/word order of the Calypso
8 * ARM processor.
9 *
10 * Before this Closedmoko firmware can be examined with any of the
11 * standard reverse eng tools (ARM disassemblers or even the good old
12 * strings), it needs to be converted from the weird byte-swapped SREC
13 * format to straight binary in the natural byte order. The present
14 * utility accomplishes that conversion.
15 *
16 * Written by Spacefalcon the Outlaw.
17 */
18
19 #include <sys/types.h>
20 #include <stdio.h>
21 #include <ctype.h>
22 #include <strings.h>
23
24 char *infname;
25 FILE *inf, *outf;
26 u_char fillbyte;
27 char srecbuf[80];
28 u_char srecbin[40];
29 int lineno, state;
30 u_long lastaddr;
31
32 u_char header[6] = {0x06, 0x00, 0x00, 'H', 'D', 'R'};
33
34 decode_hex_byte(s)
35 char *s;
36 {
37 register int u, l;
38
39 if (!isxdigit(s[0]) || !isxdigit(s[1]))
40 return(-1);
41 if (isdigit(s[0]))
42 u = s[0] - '0';
43 else if (isupper(s[0]))
44 u = s[0] - 'A' + 10;
45 else
46 u = s[0] - 'a' + 10;
47 if (isdigit(s[1]))
48 l = s[1] - '0';
49 else if (isupper(s[1]))
50 l = s[1] - 'A' + 10;
51 else
52 l = s[1] - 'a' + 10;
53 return((u << 4) | l);
54 }
55
56 srec2bin()
57 {
58 register int i, l, b;
59
60 l = decode_hex_byte(srecbuf + 2);
61 if (l < 1) {
62 fprintf(stderr, "%s line %d: S-record length octet is bad\n",
63 infname, lineno);
64 exit(1);
65 }
66 srecbin[0] = l;
67 if (l > 35) {
68 fprintf(stderr,
69 "%s line %d: S-record is longer than expected\n",
70 infname, lineno);
71 exit(1);
72 }
73 for (i = 1; i <= l; i++) {
74 b = decode_hex_byte(srecbuf + i*2 + 2);
75 if (b < 0) {
76 fprintf(stderr, "%s line %d: hex decode error\n",
77 infname, lineno);
78 exit(1);
79 }
80 srecbin[i] = b;
81 }
82 return(0);
83 }
84
85 srec_cksum()
86 {
87 u_char accum;
88 register int i, len;
89
90 len = srecbin[0] + 1;
91 accum = 0;
92 for (i = 0; i < len; i++)
93 accum += srecbin[i];
94 if (accum != 0xFF) {
95 fprintf(stderr, "%s line %d: bad checksum\n", infname, lineno);
96 exit(1);
97 }
98 return(0);
99 }
100
101 main(argc, argv)
102 char **argv;
103 {
104 register int i;
105 u_long curaddr;
106 int datalen;
107
108 if (argc < 3 || argc > 4) {
109 usage: fprintf(stderr, "usage: %s input.m0 output.bin [fill-byte]\n",
110 argv[0]);
111 exit(1);
112 }
113 infname = argv[1];
114 inf = fopen(infname, "r");
115 if (!inf) {
116 perror(infname);
117 exit(1);
118 }
119 if (argc > 3) {
120 i = decode_hex_byte(argv[3]);
121 if (i >= 0)
122 fillbyte = i;
123 else
124 goto usage;
125 } else
126 fillbyte = 0;
127
128 state = 0;
129 for (lineno = 1; ; lineno++) {
130 if (!fgets(srecbuf, sizeof srecbuf, inf)) {
131 fprintf(stderr, "%s: premature EOF\n", infname);
132 exit(1);
133 }
134 if (srecbuf[0] != 'S') {
135 fprintf(stderr, "%s line %d: not an S-record\n",
136 infname, lineno);
137 exit(1);
138 }
139 switch (srecbuf[1]) {
140 case '0':
141 if (state == 0)
142 break;
143 else
144 goto badtype;
145 case '3':
146 if (state == 0)
147 goto badtype;
148 else
149 break;
150 case '7':
151 if (state == 2)
152 break;
153 else
154 goto badtype;
155 default:
156 badtype:
157 fprintf(stderr,
158 "%s line %d: S-record type unexpected\n",
159 infname, lineno);
160 exit(1);
161 }
162 srec2bin();
163 srec_cksum();
164 if (state == 0) {
165 if (bcmp(srecbin, header, 6)) {
166 fprintf(stderr, "%s: expected header missing\n",
167 infname);
168 exit(1);
169 }
170 state = 1;
171 continue;
172 }
173 switch (srecbuf[1]) {
174 case '3':
175 if (srecbin[0] < 6) {
176 fprintf(stderr,
177 "%s line %d: S3 record is too short\n",
178 infname, lineno);
179 exit(1);
180 }
181 curaddr = (srecbin[1] << 24) | (srecbin[2] << 16) |
182 (srecbin[3] << 8) | srecbin[4];
183 if (curaddr & 1) {
184 fprintf(stderr, "%s line %d: odd address\n",
185 infname, lineno);
186 exit(1);
187 }
188 datalen = srecbin[0] - 5;
189 if (datalen & 1) {
190 fprintf(stderr, "%s line %d: odd data length\n",
191 infname, lineno);
192 exit(1);
193 }
194 if (state < 2) {
195 outf = fopen(argv[2], "w");
196 if (!outf) {
197 perror(argv[2]);
198 exit(1);
199 }
200 state = 2;
201 lastaddr = 0;
202 }
203 if (curaddr < lastaddr) {
204 fprintf(stderr,
205 "%s line %d: address going backwards\n",
206 infname, lineno);
207 exit(1);
208 }
209 while (lastaddr < curaddr) {
210 putc(fillbyte, outf);
211 lastaddr++;
212 }
213 for (i = 0; i < datalen; i += 2) {
214 putc(srecbin[i + 6], outf);
215 putc(srecbin[i + 5], outf);
216 }
217 lastaddr = curaddr + datalen;
218 continue;
219 case '7':
220 fclose(outf);
221 exit(0);
222 default:
223 abort();
224 }
225 }
226 }