FreeCalypso > hg > freecalypso-reveng
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 } |