summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2008-10-30 00:13:29 +0000
committerDave Chapman <dave@dchapman.com>2008-10-30 00:13:29 +0000
commitc91d7873c79103f9e6ef00cedbec7ad9410c7666 (patch)
tree2f372cf9b19763446ce265d20d2f2307a2c0fac5
parente1b483848120507a909e95417e938324ed377bd5 (diff)
downloadrockbox-c91d7873c79103f9e6ef00cedbec7ad9410c7666.tar.gz
rockbox-c91d7873c79103f9e6ef00cedbec7ad9410c7666.zip
Add MD5 checksumming of the original firmware images - for extra safety, and also because some Fuze firmwares have the same ID (or what we thought was the ID) as the M200 firmwares. Plus a few minor cleanups.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18927 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--rbutil/mkamsboot/Makefile15
-rw-r--r--rbutil/mkamsboot/md5.c246
-rw-r--r--rbutil/mkamsboot/md5.h25
-rw-r--r--rbutil/mkamsboot/mkamsboot.c102
4 files changed, 368 insertions, 20 deletions
diff --git a/rbutil/mkamsboot/Makefile b/rbutil/mkamsboot/Makefile
index d643930915..ea8ca274c3 100644
--- a/rbutil/mkamsboot/Makefile
+++ b/rbutil/mkamsboot/Makefile
@@ -20,18 +20,21 @@ E200V2FILES = dualboot-e200v2.o dualboot-e200v2.elf dualboot-e200v2.o \
20 dualboot-e200v2.bin bootimg_e200v2.c bootimg_e200v2.h 20 dualboot-e200v2.bin bootimg_e200v2.c bootimg_e200v2.h
21 21
22M200V2FILES = dualboot-m200v2.o dualboot-m200v2.elf dualboot-m200v2.o \ 22M200V2FILES = dualboot-m200v2.o dualboot-m200v2.elf dualboot-m200v2.o \
23 dualboot-m200v2.bin bootimg_m200v2.c bootimg_m200v2.h 23 dualboot-m200v2.bin bootimg_m200v2.c bootimg_m200v2.h
24 24
25all: mkamsboot 25all: mkamsboot
26 26
27$(LIBUCL): 27$(LIBUCL):
28 make -C ../../tools/ucl/src libucl.a 28 make -C ../../tools/ucl/src libucl.a
29 29
30mkamsboot.o: mkamsboot.c $(BOOTHEADERS) uclimg.h 30md5.o: md5.c md5.h
31 gcc $(CFLAGS) -c -o md5.o -W -Wall md5.c
32
33mkamsboot.o: mkamsboot.c $(BOOTHEADERS) uclimg.h md5.h
31 gcc $(CFLAGS) -c -o mkamsboot.o -W -Wall mkamsboot.c 34 gcc $(CFLAGS) -c -o mkamsboot.o -W -Wall mkamsboot.c
32 35
33mkamsboot: mkamsboot.o $(BOOTIMAGES) uclimg.o $(LIBUCL) 36mkamsboot: mkamsboot.o $(BOOTIMAGES) uclimg.o md5.o $(LIBUCL)
34 gcc -o mkamsboot mkamsboot.o $(BOOTIMAGES) uclimg.o $(LIBUCL) 37 gcc -o mkamsboot mkamsboot.o $(BOOTIMAGES) uclimg.o md5.o $(LIBUCL)
35 38
36# Rules for our test ARM application - assemble, link, then extract 39# Rules for our test ARM application - assemble, link, then extract
37# the binary code 40# the binary code
@@ -110,5 +113,5 @@ bin2c: bin2c.c
110 113
111clean: 114clean:
112 rm -f mkamsboot mkamsboot.o nrv2e_d8.o nrv2e_d8.elf nrv2e_d8.bin *~ \ 115 rm -f mkamsboot mkamsboot.o nrv2e_d8.o nrv2e_d8.elf nrv2e_d8.bin *~ \
113 bin2c uclimg.c uclimg.h uclimg.o \ 116 bin2c uclimg.c uclimg.h uclimg.o md5.o \
114 $(BOOTIMAGES) $(CLIPFILES) $(E200V2FILES) $(M200V2FILES) 117 $(BOOTIMAGES) $(CLIPFILES) $(E200V2FILES) $(M200V2FILES)
diff --git a/rbutil/mkamsboot/md5.c b/rbutil/mkamsboot/md5.c
new file mode 100644
index 0000000000..6c5e8127f9
--- /dev/null
+++ b/rbutil/mkamsboot/md5.c
@@ -0,0 +1,246 @@
1/*
2 * RFC 1321 compliant MD5 implementation
3 *
4 * Copyright (C) 2001-2003 Christophe Devine
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <string.h>
22
23#include "md5.h"
24
25#define GET_UINT32(n,b,i) \
26{ \
27 (n) = ( (uint32) (b)[(i) ] ) \
28 | ( (uint32) (b)[(i) + 1] << 8 ) \
29 | ( (uint32) (b)[(i) + 2] << 16 ) \
30 | ( (uint32) (b)[(i) + 3] << 24 ); \
31}
32
33#define PUT_UINT32(n,b,i) \
34{ \
35 (b)[(i) ] = (uint8) ( (n) ); \
36 (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
37 (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
38 (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
39}
40
41void md5_starts( md5_context *ctx )
42{
43 ctx->total[0] = 0;
44 ctx->total[1] = 0;
45
46 ctx->state[0] = 0x67452301;
47 ctx->state[1] = 0xEFCDAB89;
48 ctx->state[2] = 0x98BADCFE;
49 ctx->state[3] = 0x10325476;
50}
51
52void md5_process( md5_context *ctx, uint8 data[64] )
53{
54 uint32 X[16], A, B, C, D;
55
56 GET_UINT32( X[0], data, 0 );
57 GET_UINT32( X[1], data, 4 );
58 GET_UINT32( X[2], data, 8 );
59 GET_UINT32( X[3], data, 12 );
60 GET_UINT32( X[4], data, 16 );
61 GET_UINT32( X[5], data, 20 );
62 GET_UINT32( X[6], data, 24 );
63 GET_UINT32( X[7], data, 28 );
64 GET_UINT32( X[8], data, 32 );
65 GET_UINT32( X[9], data, 36 );
66 GET_UINT32( X[10], data, 40 );
67 GET_UINT32( X[11], data, 44 );
68 GET_UINT32( X[12], data, 48 );
69 GET_UINT32( X[13], data, 52 );
70 GET_UINT32( X[14], data, 56 );
71 GET_UINT32( X[15], data, 60 );
72
73#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
74
75#define P(a,b,c,d,k,s,t) \
76{ \
77 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
78}
79
80 A = ctx->state[0];
81 B = ctx->state[1];
82 C = ctx->state[2];
83 D = ctx->state[3];
84
85#define F(x,y,z) (z ^ (x & (y ^ z)))
86
87 P( A, B, C, D, 0, 7, 0xD76AA478 );
88 P( D, A, B, C, 1, 12, 0xE8C7B756 );
89 P( C, D, A, B, 2, 17, 0x242070DB );
90 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
91 P( A, B, C, D, 4, 7, 0xF57C0FAF );
92 P( D, A, B, C, 5, 12, 0x4787C62A );
93 P( C, D, A, B, 6, 17, 0xA8304613 );
94 P( B, C, D, A, 7, 22, 0xFD469501 );
95 P( A, B, C, D, 8, 7, 0x698098D8 );
96 P( D, A, B, C, 9, 12, 0x8B44F7AF );
97 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
98 P( B, C, D, A, 11, 22, 0x895CD7BE );
99 P( A, B, C, D, 12, 7, 0x6B901122 );
100 P( D, A, B, C, 13, 12, 0xFD987193 );
101 P( C, D, A, B, 14, 17, 0xA679438E );
102 P( B, C, D, A, 15, 22, 0x49B40821 );
103
104#undef F
105
106#define F(x,y,z) (y ^ (z & (x ^ y)))
107
108 P( A, B, C, D, 1, 5, 0xF61E2562 );
109 P( D, A, B, C, 6, 9, 0xC040B340 );
110 P( C, D, A, B, 11, 14, 0x265E5A51 );
111 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
112 P( A, B, C, D, 5, 5, 0xD62F105D );
113 P( D, A, B, C, 10, 9, 0x02441453 );
114 P( C, D, A, B, 15, 14, 0xD8A1E681 );
115 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
116 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
117 P( D, A, B, C, 14, 9, 0xC33707D6 );
118 P( C, D, A, B, 3, 14, 0xF4D50D87 );
119 P( B, C, D, A, 8, 20, 0x455A14ED );
120 P( A, B, C, D, 13, 5, 0xA9E3E905 );
121 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
122 P( C, D, A, B, 7, 14, 0x676F02D9 );
123 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
124
125#undef F
126
127#define F(x,y,z) (x ^ y ^ z)
128
129 P( A, B, C, D, 5, 4, 0xFFFA3942 );
130 P( D, A, B, C, 8, 11, 0x8771F681 );
131 P( C, D, A, B, 11, 16, 0x6D9D6122 );
132 P( B, C, D, A, 14, 23, 0xFDE5380C );
133 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
134 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
135 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
136 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
137 P( A, B, C, D, 13, 4, 0x289B7EC6 );
138 P( D, A, B, C, 0, 11, 0xEAA127FA );
139 P( C, D, A, B, 3, 16, 0xD4EF3085 );
140 P( B, C, D, A, 6, 23, 0x04881D05 );
141 P( A, B, C, D, 9, 4, 0xD9D4D039 );
142 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
143 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
144 P( B, C, D, A, 2, 23, 0xC4AC5665 );
145
146#undef F
147
148#define F(x,y,z) (y ^ (x | ~z))
149
150 P( A, B, C, D, 0, 6, 0xF4292244 );
151 P( D, A, B, C, 7, 10, 0x432AFF97 );
152 P( C, D, A, B, 14, 15, 0xAB9423A7 );
153 P( B, C, D, A, 5, 21, 0xFC93A039 );
154 P( A, B, C, D, 12, 6, 0x655B59C3 );
155 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
156 P( C, D, A, B, 10, 15, 0xFFEFF47D );
157 P( B, C, D, A, 1, 21, 0x85845DD1 );
158 P( A, B, C, D, 8, 6, 0x6FA87E4F );
159 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
160 P( C, D, A, B, 6, 15, 0xA3014314 );
161 P( B, C, D, A, 13, 21, 0x4E0811A1 );
162 P( A, B, C, D, 4, 6, 0xF7537E82 );
163 P( D, A, B, C, 11, 10, 0xBD3AF235 );
164 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
165 P( B, C, D, A, 9, 21, 0xEB86D391 );
166
167#undef F
168
169 ctx->state[0] += A;
170 ctx->state[1] += B;
171 ctx->state[2] += C;
172 ctx->state[3] += D;
173}
174
175void md5_update( md5_context *ctx, uint8 *input, uint32 length )
176{
177 uint32 left, fill;
178
179 if( ! length ) return;
180
181 left = ctx->total[0] & 0x3F;
182 fill = 64 - left;
183
184 ctx->total[0] += length;
185 ctx->total[0] &= 0xFFFFFFFF;
186
187 if( ctx->total[0] < length )
188 ctx->total[1]++;
189
190 if( left && length >= fill )
191 {
192 memcpy( (void *) (ctx->buffer + left),
193 (void *) input, fill );
194 md5_process( ctx, ctx->buffer );
195 length -= fill;
196 input += fill;
197 left = 0;
198 }
199
200 while( length >= 64 )
201 {
202 md5_process( ctx, input );
203 length -= 64;
204 input += 64;
205 }
206
207 if( length )
208 {
209 memcpy( (void *) (ctx->buffer + left),
210 (void *) input, length );
211 }
212}
213
214static uint8 md5_padding[64] =
215{
216 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
220};
221
222void md5_finish( md5_context *ctx, uint8 digest[16] )
223{
224 uint32 last, padn;
225 uint32 high, low;
226 uint8 msglen[8];
227
228 high = ( ctx->total[0] >> 29 )
229 | ( ctx->total[1] << 3 );
230 low = ( ctx->total[0] << 3 );
231
232 PUT_UINT32( low, msglen, 0 );
233 PUT_UINT32( high, msglen, 4 );
234
235 last = ctx->total[0] & 0x3F;
236 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
237
238 md5_update( ctx, md5_padding, padn );
239 md5_update( ctx, msglen, 8 );
240
241 PUT_UINT32( ctx->state[0], digest, 0 );
242 PUT_UINT32( ctx->state[1], digest, 4 );
243 PUT_UINT32( ctx->state[2], digest, 8 );
244 PUT_UINT32( ctx->state[3], digest, 12 );
245}
246
diff --git a/rbutil/mkamsboot/md5.h b/rbutil/mkamsboot/md5.h
new file mode 100644
index 0000000000..71fa395548
--- /dev/null
+++ b/rbutil/mkamsboot/md5.h
@@ -0,0 +1,25 @@
1#ifndef _MD5_H
2#define _MD5_H
3
4#ifndef uint8
5#define uint8 unsigned char
6#endif
7
8#ifndef uint32
9#define uint32 unsigned long int
10#endif
11
12typedef struct
13{
14 uint32 total[2];
15 uint32 state[4];
16 uint8 buffer[64];
17}
18md5_context;
19
20void md5_starts( md5_context *ctx );
21void md5_update( md5_context *ctx, uint8 *input, uint32 length );
22void md5_finish( md5_context *ctx, uint8 digest[16] );
23
24#endif /* md5.h */
25
diff --git a/rbutil/mkamsboot/mkamsboot.c b/rbutil/mkamsboot/mkamsboot.c
index e4b6e09782..5733db5f2a 100644
--- a/rbutil/mkamsboot/mkamsboot.c
+++ b/rbutil/mkamsboot/mkamsboot.c
@@ -87,6 +87,8 @@ execution to the uncompressed firmware.
87 87
88/* Headers for ARM code binaries */ 88/* Headers for ARM code binaries */
89#include "uclimg.h" 89#include "uclimg.h"
90#include "md5.h"
91
90#include "bootimg_clip.h" 92#include "bootimg_clip.h"
91#include "bootimg_e200v2.h" 93#include "bootimg_e200v2.h"
92#include "bootimg_m200v2.h" 94#include "bootimg_m200v2.h"
@@ -165,6 +167,39 @@ static const int rb_model_num[] =
165 0 167 0
166}; 168};
167 169
170struct md5sums {
171 int model;
172 char *version;
173 int fw_version;
174 char *md5;
175};
176
177/* Checksums of unmodified original firmwares - for safety, and device
178 detection */
179static struct md5sums sansasums[] = {
180 /* NOTE: Different regional versions of the firmware normally only
181 differ in the filename - the md5sums are identical */
182 { MODEL_E200, "3.01.11", 1, "e622ca8cb6df423f54b8b39628a1f0a3" },
183 { MODEL_E200, "3.01.14", 1, "2c1d0383fc3584b2cc83ba8cc2243af6" },
184 { MODEL_E200, "3.01.16", 1, "12563ad71b25a1034cf2092d1e0218c4" },
185
186 { MODEL_FUZE, "1.01.11", 1, "cac8ffa03c599330ac02c4d41de66166" },
187 { MODEL_FUZE, "1.01.15", 1, "df0e2c1612727f722c19a3c764cff7f2" },
188
189 { MODEL_C200, "3.02.05", 1, "b6378ebd720b0ade3fad4dc7ab61c1a5" },
190
191 { MODEL_M200, "4.00.45", 1, "82e3194310d1514e3bbcd06e84c4add3" },
192 { MODEL_M200, "4.01.08-A", 1, "fc9dd6116001b3e6a150b898f1b091f0" },
193 { MODEL_M200, "4.01.08-E", 1, "d3fb7d8ec8624ee65bc99f8dab0e2369" },
194
195 { MODEL_CLIP, "1.01.17", 1, "12caad785d506219d73f538772afd99e" },
196 { MODEL_CLIP, "1.01.18", 1, "d720b266bd5afa38a198986ef0508a45" },
197 { MODEL_CLIP, "1.01.20", 1, "236d8f75189f468462c03f6d292cf2ac" },
198 { MODEL_CLIP, "1.01.29", 1, "b07fe36b338241944c241de21fb1e490" },
199 { MODEL_CLIP, "1.01.30", 1, "f2974d47c536549c9d8259170f1dbe4d" },
200};
201
202#define NUM_MD5S (sizeof(sansasums)/sizeof(sansasums[0]))
168 203
169static off_t filesize(int fd) { 204static off_t filesize(int fd) {
170 struct stat buf; 205 struct stat buf;
@@ -195,6 +230,21 @@ static void put_uint32le(unsigned char* p, uint32_t x)
195 p[3] = (x >> 24) & 0xff; 230 p[3] = (x >> 24) & 0xff;
196} 231}
197 232
233void calc_MD5(unsigned char* buf, int len, char *md5str)
234{
235 int i;
236 md5_context ctx;
237 unsigned char md5sum[16];
238
239 md5_starts(&ctx);
240 md5_update(&ctx, buf, len);
241 md5_finish(&ctx, md5sum);
242
243 for (i = 0; i < 16; ++i)
244 sprintf(md5str + 2*i, "%02x", md5sum[i]);
245}
246
247
198static uint32_t calc_checksum(unsigned char* buf, uint32_t n) 248static uint32_t calc_checksum(unsigned char* buf, uint32_t n)
199{ 249{
200 uint32_t sum = 0; 250 uint32_t sum = 0;
@@ -375,6 +425,7 @@ int main(int argc, char* argv[])
375 int totalsize; 425 int totalsize;
376 unsigned char* p; 426 unsigned char* p;
377 uint32_t checksum; 427 uint32_t checksum;
428 char md5sum[33]; /* 32 hex digits, plus terminating zero */
378 429
379 fprintf(stderr,"mkamsboot v" VERSION " - (C) Dave Chapman and Rafaël Carré 2008\n"); 430 fprintf(stderr,"mkamsboot v" VERSION " - (C) Dave Chapman and Rafaël Carré 2008\n");
380 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n"); 431 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
@@ -397,26 +448,48 @@ int main(int argc, char* argv[])
397 return 1; 448 return 1;
398 } 449 }
399 450
400 /* TODO: Do some more sanity checks on the OF image. Some images (like m200v2) dont have a checksum at the end, only padding (0xdeadbeef). */ 451 /* Calculate MD5 checksum of OF */
401 checksum = get_uint32le(buf + len - 4); 452 calc_MD5(buf, len, md5sum);
402 if (checksum != 0xefbeadde && checksum != calc_checksum(buf, len - 4)) {
403 453
404 fprintf(stderr,"[ERR] Whole file checksum failed - %s\n",infile); 454 fprintf(stderr,"[INFO] MD5 sum - %s\n",md5sum);
405 return 1; 455
406 } 456 i = 0;
457 while ((i < NUM_MD5S) && (strcmp(sansasums[i].md5, md5sum) != 0))
458 i++;
407 459
408 if (get_uint32le(&buf[0x204])==0x0000f000) { 460 if (i < NUM_MD5S) {
409 fw_version = 2; 461 model = sansasums[i].model;
410 model_id = buf[0x219]; 462 fw_version = sansasums[i].fw_version;
463 fprintf(stderr,"[INFO] Original firmware MD5 checksum match - %s %s\n",
464 model_names[model], sansasums[i].version);
411 } else { 465 } else {
412 fw_version = 1; 466 fprintf(stderr,"[WARN] ****** Original firmware unknown ******\n");
413 model_id = buf[0x215]; 467
468 if (get_uint32le(&buf[0x204])==0x0000f000) {
469 fw_version = 2;
470 model_id = buf[0x219];
471 } else {
472 fw_version = 1;
473 model_id = buf[0x215];
474 }
475
476 model = get_model(model_id);
477
478 if (model == MODEL_UNKNOWN) {
479 fprintf(stderr,"[ERR] Unknown firmware - model id 0x%02x\n",
480 model_id);
481 free(buf);
482 return 1;
483 }
414 } 484 }
485
415 486
416 model = get_model(model_id); 487 /* TODO: Do some more sanity checks on the OF image. Some images (like m200v2) dont have a checksum at the end, only padding (0xdeadbeef). */
488 checksum = get_uint32le(buf + len - 4);
489 if (checksum != 0xefbeadde && checksum != calc_checksum(buf, len - 4)) {
417 490
418 if (model == MODEL_UNKNOWN) { 491 fprintf(stderr,"[ERR] Whole file checksum failed - %s\n",infile);
419 fprintf(stderr,"[ERR] Unknown firmware - model id 0x%02x\n",model_id); 492 free(buf);
420 return 1; 493 return 1;
421 } 494 }
422 495
@@ -430,6 +503,7 @@ int main(int argc, char* argv[])
430 rb_unpacked = load_rockbox_file(bootfile, model, &bootloader_size); 503 rb_unpacked = load_rockbox_file(bootfile, model, &bootloader_size);
431 if (rb_unpacked == NULL) { 504 if (rb_unpacked == NULL) {
432 fprintf(stderr,"[ERR] Could not load %s\n",bootfile); 505 fprintf(stderr,"[ERR] Could not load %s\n",bootfile);
506 free(buf);
433 return 1; 507 return 1;
434 } 508 }
435 509