A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd

GUI firmware patcher for windows.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6351 a1c6a512-1295-4272-9138-f99709370657

+1082
+4
tools/fwpatcher/checksums.h
··· 1 + "627d5195b56ebca3b431cccb535c3bfa", /* 1.63 eu */ 2 + "5068bf62d68fdbfcb3d8a2eaf2f4fdfe", /* 1.63 us */ 3 + "1afe2172a4d10f69069084466f7a83ce", /* 1.63 k */ 4 + "5802da654706239f2782510f6ab73b26" /* 1.65 eu */
tools/fwpatcher/favicon.ico

This is a binary file and will not be displayed.

+393
tools/fwpatcher/iriver.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2004 by Dave Hooper 11 + * 12 + * This particular source code file is licensed under the X11 license. See the 13 + * bottom of the COPYING file for details on this license. 14 + * 15 + * Original code from http://www.beermex.com/@spc/ihpfirm.src.zip 16 + * Details at http://www.rockbox.org/twiki/bin/view/Main/IriverToolsGuide 17 + * 18 + ****************************************************************************/ 19 + #include <stdio.h> 20 + #include <stdlib.h> 21 + #include <string.h> 22 + 23 + #include "iriver.h" 24 + 25 + const unsigned char munge[] = { 26 + 0x7a, 0x36, 0xc4, 0x43, 0x49, 0x6b, 0x35, 0x4e, 0xa3, 0x46, 0x25, 0x84, 27 + 0x4d, 0x73, 0x74, 0x61 28 + }; 29 + 30 + const unsigned char header_modify[] = "* IHPFIRM-DECODED "; 31 + 32 + const char * const models[] = { "iHP-100", "iHP-120/iHP-140", "H300 series", 33 + NULL }; 34 + 35 + /* aligns with models array; expected min firmware size */ 36 + const unsigned int firmware_minsize[] = { 0x100000, 0x100000, 0x200000 }; 37 + /* aligns with models array; expected max firmware size */ 38 + const unsigned int firmware_maxsize[] = { 0x200000, 0x200000, 0x400000 }; 39 + 40 + const unsigned char header[][16] = { 41 + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 42 + { 0x20, 0x03, 0x08, 0x27, 0x24, 0x00, 0x02, 0x30, 0x19, 0x17, 0x65, 0x73, 43 + 0x85, 0x32, 0x83, 0x22 }, 44 + { 0x20, 0x04, 0x03, 0x27, 0x20, 0x50, 0x01, 0x70, 0x80, 0x30, 0x80, 0x06, 45 + 0x30, 0x19, 0x17, 0x65 } 46 + }; 47 + 48 + static int testheader( const unsigned char * const data ) 49 + { 50 + const unsigned char * const d = data+16; 51 + const char * const * m = models; 52 + int index = 0; 53 + while( *m ) 54 + { 55 + if( memcmp( header[ index ], d, 16 ) == 0 ) 56 + return index; 57 + index++; 58 + m++; 59 + }; 60 + return -1; 61 + }; 62 + 63 + static void modifyheader( unsigned char * data ) 64 + { 65 + const unsigned char * h = header_modify; 66 + int i; 67 + for( i=0; i<512; i++ ) 68 + { 69 + if( *h == '\0' ) 70 + h = header_modify; 71 + *data++ ^= *h++; 72 + }; 73 + }; 74 + 75 + static FILE * openinfile( const TCHAR * filename ) 76 + { 77 + FILE * F = _tfopen( filename, TEXT("rb") ); 78 + if( F == NULL ) 79 + { 80 + fprintf( stderr, "Couldn't open input file %s\n", filename ); 81 + perror( "Error was " ); 82 + }; 83 + return F; 84 + }; 85 + 86 + static FILE * openoutfile( const TCHAR * filename ) 87 + { 88 + FILE * F = _tfopen( filename, TEXT("wb") ); 89 + if( F == NULL ) 90 + { 91 + fprintf( stderr, "Couldn't open output file %s\n", filename ); 92 + perror( "Error was " ); 93 + }; 94 + return F; 95 + }; 96 + 97 + int iriver_decode(TCHAR *infile_name, TCHAR *outfile_name, unsigned int modify, 98 + enum striptype stripmode ) 99 + { 100 + FILE * infile = NULL; 101 + FILE * outfile = NULL; 102 + int i = -1; 103 + unsigned char headerdata[512]; 104 + unsigned long dwLength1, dwLength2, dwLength3, fp = 0; 105 + unsigned char blockdata[16+16]; 106 + unsigned char out[16]; 107 + unsigned char newmunge; 108 + signed long lenread; 109 + int s = 0; 110 + unsigned char * pChecksums, * ppChecksums = 0; 111 + unsigned char ck; 112 + 113 + infile = openinfile(infile_name); 114 + outfile = openoutfile(outfile_name); 115 + if (!infile || !outfile) return -1; 116 + 117 + lenread = fread( headerdata, 1, 512, infile ); 118 + if( lenread != 512 ) 119 + { 120 + fprintf( stderr, "This doesn't look like a valid encrypted iHP " 121 + "firmware - reason: header length\n" ); 122 + goto error; 123 + }; 124 + 125 + i = testheader( headerdata ); 126 + if( i == -1 ) 127 + { 128 + fprintf( stderr, "This firmware is for an unknown model, or is not" 129 + " a valid encrypted iHP firmware\n" ); 130 + goto error; 131 + }; 132 + fprintf( stderr, "Model %s\n", models[ i ] ); 133 + 134 + dwLength1 = headerdata[0] | (headerdata[1]<<8) | 135 + (headerdata[2]<<16) | (headerdata[3]<<24); 136 + dwLength2 = headerdata[4] | (headerdata[5]<<8) | 137 + (headerdata[6]<<16) | (headerdata[7]<<24); 138 + dwLength3 = headerdata[8] | (headerdata[9]<<8) | 139 + (headerdata[10]<<16) | (headerdata[11]<<24); 140 + 141 + if( dwLength1 < firmware_minsize[ i ] || 142 + dwLength1 > firmware_maxsize[ i ] || 143 + dwLength2 < firmware_minsize[ i ] || 144 + dwLength2 > dwLength1 || 145 + dwLength3 > dwLength1 || 146 + dwLength2>>9 != dwLength3 || 147 + dwLength2+dwLength3+512 != dwLength1 ) 148 + { 149 + fprintf( stderr, "This doesn't look like a valid encrypted " 150 + "iHP firmware - reason: file 'length' data\n" ); 151 + goto error; 152 + }; 153 + 154 + pChecksums = ppChecksums = (unsigned char *)( malloc( dwLength3 ) ); 155 + 156 + if( modify ) 157 + { 158 + modifyheader( headerdata ); 159 + }; 160 + 161 + if( stripmode == STRIP_NONE ) 162 + fwrite( headerdata, 512, 1, outfile ); 163 + 164 + memset( blockdata, 0, 16 ); 165 + 166 + ck = 0; 167 + while( ( fp < dwLength2 ) && 168 + ( lenread = fread( blockdata+16, 1, 16, infile ) ) == 16 ) 169 + { 170 + fp += 16; 171 + 172 + for( i=0; i<16; ++i ) 173 + { 174 + newmunge = blockdata[16+i] ^ munge[i]; 175 + out[i] = newmunge ^ blockdata[i]; 176 + blockdata[i] = newmunge; 177 + ck += out[i]; 178 + } 179 + 180 + if( fp > ESTF_SIZE || stripmode != STRIP_HEADER_CHECKSUM_ESTF ) 181 + { 182 + fwrite( out+4, 1, 12, outfile ); 183 + fwrite( out, 1, 4, outfile ); 184 + } 185 + else 186 + { 187 + if( ESTF_SIZE - fp < 16 ) 188 + { 189 + memcpy( out+4, blockdata+16, 12 ); 190 + memcpy( out, blockdata+28, 4 ); 191 + fwrite( blockdata+16+ESTF_SIZE-fp, 1, ESTF_SIZE-fp, outfile ); 192 + } 193 + } 194 + 195 + 196 + if( s == 496 ) 197 + { 198 + s = 0; 199 + memset( blockdata, 0, 16 ); 200 + *ppChecksums++ = ck; 201 + ck = 0; 202 + } 203 + else 204 + s+=16; 205 + }; 206 + 207 + if( fp != dwLength2 ) 208 + { 209 + fprintf( stderr, "This doesn't look like a valid encrypted " 210 + "iHP firmware - reason: 'length2' mismatch\n" ); 211 + goto error; 212 + }; 213 + 214 + fp = 0; 215 + ppChecksums = pChecksums; 216 + while( ( fp < dwLength3 ) && 217 + ( lenread = fread( blockdata, 1, 32, infile ) ) > 0 ) 218 + { 219 + fp += lenread; 220 + if( stripmode == STRIP_NONE ) 221 + fwrite( blockdata, 1, lenread, outfile ); 222 + if( memcmp( ppChecksums, blockdata, lenread ) != 0 ) 223 + { 224 + fprintf( stderr, "This doesn't look like a valid encrypted " 225 + "iHP firmware - reason: Checksum mismatch!" ); 226 + goto error; 227 + }; 228 + ppChecksums += lenread; 229 + }; 230 + 231 + if( fp != dwLength3 ) 232 + { 233 + fprintf( stderr, "This doesn't look like a valid encrypted " 234 + "iHP firmware - reason: 'length3' mismatch\n" ); 235 + goto error; 236 + }; 237 + 238 + 239 + fprintf( stderr, "File decoded correctly and all checksums matched!\n" ); 240 + switch( stripmode ) 241 + { 242 + default: 243 + case STRIP_NONE: 244 + fprintf(stderr, "Output file contains all headers and " 245 + "checksums\n"); 246 + break; 247 + case STRIP_HEADER_CHECKSUM: 248 + fprintf( stderr, "NB: output file contains only ESTFBINR header" 249 + " and decoded firmware code\n" ); 250 + break; 251 + case STRIP_HEADER_CHECKSUM_ESTF: 252 + fprintf( stderr, "NB: output file contains only raw decoded " 253 + "firmware code\n" ); 254 + break; 255 + }; 256 + 257 + fclose(infile); 258 + fclose(outfile); 259 + return 0; 260 + error: 261 + fclose(infile); 262 + fclose(outfile); 263 + return -1; 264 + }; 265 + 266 + int iriver_encode(TCHAR *infile_name, TCHAR *outfile_name, unsigned int modify ) 267 + { 268 + FILE * infile = NULL; 269 + FILE * outfile = NULL; 270 + int i = -1; 271 + unsigned char headerdata[512]; 272 + unsigned long dwLength1, dwLength2, dwLength3, fp = 0; 273 + unsigned char blockdata[16+16]; 274 + unsigned char out[16]; 275 + unsigned char newmunge; 276 + signed long lenread; 277 + int s = 0; 278 + unsigned char * pChecksums, * ppChecksums; 279 + unsigned char ck; 280 + 281 + enum striptype stripmode = STRIP_NONE; 282 + 283 + infile = openinfile(infile_name); 284 + outfile = openoutfile(outfile_name); 285 + if (!infile || !outfile) return -1; 286 + 287 + lenread = fread( headerdata, 1, 512, infile ); 288 + if( lenread != 512 ) 289 + { 290 + fprintf( stderr, "This doesn't look like a valid decoded " 291 + "iHP firmware - reason: header length\n" ); 292 + goto error; 293 + }; 294 + 295 + if( modify ) 296 + { 297 + modifyheader( headerdata ); /* reversible */ 298 + }; 299 + 300 + i = testheader( headerdata ); 301 + if( i == -1 ) 302 + { 303 + fprintf( stderr, "This firmware is for an unknown model, or is not" 304 + " a valid decoded iHP firmware\n" ); 305 + goto error; 306 + }; 307 + fprintf( stderr, "Model %s\n", models[ i ] ); 308 + 309 + dwLength1 = headerdata[0] | (headerdata[1]<<8) | 310 + (headerdata[2]<<16) | (headerdata[3]<<24); 311 + dwLength2 = headerdata[4] | (headerdata[5]<<8) | 312 + (headerdata[6]<<16) | (headerdata[7]<<24); 313 + dwLength3 = headerdata[8] | (headerdata[9]<<8) | 314 + (headerdata[10]<<16) | (headerdata[11]<<24); 315 + 316 + if( dwLength1 < firmware_minsize[i] || 317 + dwLength1 > firmware_maxsize[i] || 318 + dwLength2 < firmware_minsize[i] || 319 + dwLength2 > dwLength1 || 320 + dwLength3 > dwLength1 || 321 + dwLength2+dwLength3+512 != dwLength1 ) 322 + { 323 + fprintf( stderr, "This doesn't look like a valid decoded iHP" 324 + " firmware - reason: file 'length' data\n" ); 325 + goto error; 326 + }; 327 + 328 + pChecksums = ppChecksums = (unsigned char *)( malloc( dwLength3 ) ); 329 + 330 + fwrite( headerdata, 512, 1, outfile ); 331 + 332 + memset( blockdata, 0, 16 ); 333 + ck = 0; 334 + while( ( fp < dwLength2 ) && 335 + ( lenread = fread( blockdata+16, 1, 16, infile ) ) == 16 ) 336 + { 337 + fp += 16; 338 + for( i=0; i<16; ++i ) 339 + { 340 + newmunge = blockdata[16+((12+i)&0xf)] ^ blockdata[i]; 341 + out[i] = newmunge ^ munge[i]; 342 + ck += blockdata[16+i]; 343 + blockdata[i] = newmunge; 344 + }; 345 + fwrite( out, 1, 16, outfile ); 346 + 347 + if( s == 496 ) 348 + { 349 + s = 0; 350 + memset( blockdata, 0, 16 ); 351 + *ppChecksums++ = ck; 352 + ck = 0; 353 + } 354 + else 355 + s+=16; 356 + }; 357 + 358 + if( fp != dwLength2 ) 359 + { 360 + fprintf( stderr, "This doesn't look like a valid decoded " 361 + "iHP firmware - reason: 'length1' mismatch\n" ); 362 + goto error; 363 + }; 364 + 365 + /* write out remainder w/out applying descrambler */ 366 + fp = 0; 367 + lenread = dwLength3; 368 + ppChecksums = pChecksums; 369 + while( ( fp < dwLength3) && 370 + ( lenread = fwrite( ppChecksums, 1, lenread, outfile ) ) > 0 ) 371 + { 372 + fp += lenread; 373 + ppChecksums += lenread; 374 + lenread = dwLength3 - fp; 375 + }; 376 + 377 + if( fp != dwLength3 ) 378 + { 379 + fprintf( stderr, "This doesn't look like a valid decoded " 380 + "iHP firmware - reason: 'length2' mismatch\n" ); 381 + goto error; 382 + }; 383 + 384 + fprintf( stderr, "File encoded successfully and checksum table built!\n" ); 385 + 386 + fclose(infile); 387 + fclose(outfile); 388 + return 0; 389 + error: 390 + fclose(infile); 391 + fclose(outfile); 392 + return -1; 393 + };
+40
tools/fwpatcher/iriver.h
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2005 by Daniel Stenberg 11 + * 12 + * All files in this archive are subject to the GNU General Public License. 13 + * See the file COPYING in the source tree root for full license agreement. 14 + * 15 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 16 + * KIND, either express or implied. 17 + * 18 + ****************************************************************************/ 19 + 20 + #include <tchar.h> 21 + #include <windows.h> 22 + 23 + #define TRUE 1 24 + #define FALSE 0 25 + 26 + #define BOOL unsigned int 27 + 28 + #define ESTF_SIZE 32 29 + 30 + enum striptype 31 + { 32 + STRIP_NONE, 33 + STRIP_HEADER_CHECKSUM, 34 + STRIP_HEADER_CHECKSUM_ESTF 35 + }; 36 + 37 + /* protos for iriver.c */ 38 + int iriver_decode(TCHAR *infile, TCHAR *outfile, BOOL modify, 39 + enum striptype stripmode ); 40 + int iriver_encode(TCHAR *infile_name, TCHAR *outfile_name, BOOL modify );
+367
tools/fwpatcher/main.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2005 by Thom Johansen 11 + * 12 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 13 + * KIND, either express or implied. 14 + * 15 + ****************************************************************************/ 16 + 17 + /* TODO: integrate the iriver.c and mkboot stuff better, they're pretty much 18 + * intended to be called from a command line tool, and i haven't changed that. 19 + */ 20 + 21 + #include <stdio.h> 22 + #include <string.h> 23 + #include <tchar.h> 24 + #include <windows.h> 25 + #include "iriver.h" 26 + #include "md5.h" 27 + #include "resource.h" 28 + 29 + #define WINDOW_WIDTH 280 30 + #define WINDOW_HEIGHT 130 31 + 32 + #define IDM_RESTORE 1000 33 + #define IDM_EXIT 1010 34 + 35 + #define LABEL_FILENAME 0 36 + #define EDIT_FILENAME 1 37 + #define BUTTON_BROWSE 2 38 + #define BUTTON_PATCH 3 39 + 40 + #define CTL_NUM 4 41 + 42 + /* include precalculated checksums */ 43 + static char *checksums[] = { 44 + #include "checksums.h" 45 + }; 46 + 47 + HICON rbicon; 48 + HFONT deffont; 49 + HWND controls[CTL_NUM]; 50 + 51 + /* begin mkboot.c excerpt */ 52 + 53 + char image[0x200000 + 0x220 + 0x200000/0x200]; 54 + 55 + int mkboot(TCHAR *infile, TCHAR *outfile, unsigned char *bldata, int bllen) 56 + { 57 + FILE *f; 58 + int i; 59 + int len; 60 + int actual_length, total_length, binary_length, num_chksums; 61 + 62 + memset(image, 0xff, sizeof(image)); 63 + 64 + /* First, read the iriver original firmware into the image */ 65 + f = _tfopen(infile, TEXT("rb")); 66 + if(!f) { 67 + perror(infile); 68 + return 0; 69 + } 70 + 71 + i = fread(image, 1, 16, f); 72 + if(i < 16) { 73 + perror(infile); 74 + return 0; 75 + } 76 + 77 + /* This is the length of the binary image without the scrambling 78 + overhead (but including the ESTFBINR header) */ 79 + binary_length = image[4] + (image[5] << 8) + 80 + (image[6] << 16) + (image[7] << 24); 81 + 82 + /* Read the rest of the binary data, but not the checksum block */ 83 + len = binary_length+0x200-16; 84 + i = fread(image+16, 1, len, f); 85 + if(i < len) { 86 + perror(infile); 87 + return 0; 88 + } 89 + 90 + fclose(f); 91 + 92 + memcpy(image + 0x220 + 0x1f0000, bldata, bllen); 93 + 94 + f = _tfopen(outfile, TEXT("wb")); 95 + if(!f) { 96 + perror(outfile); 97 + return 0; 98 + } 99 + 100 + /* Patch the reset vector to start the boot loader */ 101 + image[0x220 + 4] = image[0x1f0000 + 0x220 + 4]; 102 + image[0x220 + 5] = image[0x1f0000 + 0x220 + 5]; 103 + image[0x220 + 6] = image[0x1f0000 + 0x220 + 6]; 104 + image[0x220 + 7] = image[0x1f0000 + 0x220 + 7]; 105 + 106 + /* This is the actual length of the binary, excluding all headers */ 107 + actual_length = 0x1f0000 + bllen; 108 + 109 + /* Patch the ESTFBINR header */ 110 + image[0x20c] = (actual_length >> 24) & 0xff; 111 + image[0x20d] = (actual_length >> 16) & 0xff; 112 + image[0x20e] = (actual_length >> 8) & 0xff; 113 + image[0x20f] = actual_length & 0xff; 114 + 115 + image[0x21c] = (actual_length >> 24) & 0xff; 116 + image[0x21d] = (actual_length >> 16) & 0xff; 117 + image[0x21e] = (actual_length >> 8) & 0xff; 118 + image[0x21f] = actual_length & 0xff; 119 + 120 + /* This is the length of the binary, including the ESTFBINR header and 121 + rounded up to the nearest 0x200 boundary */ 122 + binary_length = (actual_length + 0x20 + 0x1ff) & 0xfffffe00; 123 + 124 + /* The number of checksums, i.e number of 0x200 byte blocks */ 125 + num_chksums = binary_length / 0x200; 126 + 127 + /* The total file length, including all headers and checksums */ 128 + total_length = binary_length + num_chksums + 0x200; 129 + 130 + /* Patch the scrambler header with the new length info */ 131 + image[0] = total_length & 0xff; 132 + image[1] = (total_length >> 8) & 0xff; 133 + image[2] = (total_length >> 16) & 0xff; 134 + image[3] = (total_length >> 24) & 0xff; 135 + 136 + image[4] = binary_length & 0xff; 137 + image[5] = (binary_length >> 8) & 0xff; 138 + image[6] = (binary_length >> 16) & 0xff; 139 + image[7] = (binary_length >> 24) & 0xff; 140 + 141 + image[8] = num_chksums & 0xff; 142 + image[9] = (num_chksums >> 8) & 0xff; 143 + image[10] = (num_chksums >> 16) & 0xff; 144 + image[11] = (num_chksums >> 24) & 0xff; 145 + 146 + i = fwrite(image, 1, total_length, f); 147 + if(i < total_length) { 148 + perror(outfile); 149 + return 0; 150 + } 151 + 152 + fclose(f); 153 + 154 + return 1; 155 + } 156 + 157 + /* end mkboot.c excerpt */ 158 + 159 + int FileMD5(TCHAR *name, char *md5) 160 + { 161 + int i, read; 162 + md5_context ctx; 163 + unsigned char md5sum[16]; 164 + unsigned char block[32768]; 165 + FILE *file; 166 + 167 + file = _tfopen(name, TEXT("rb")); 168 + if (!file) { 169 + MessageBox(NULL, 170 + TEXT("Could not open patched firmware for checksum check"), 171 + TEXT("Error"), MB_ICONERROR); 172 + return 0; 173 + } 174 + md5_starts(&ctx); 175 + while ((read = fread(block, 1, sizeof(block), file)) > 0) { 176 + md5_update(&ctx, block, read); 177 + } 178 + fclose(file); 179 + md5_finish(&ctx, md5sum); 180 + for (i = 0; i < 16; ++i) 181 + sprintf(md5 + 2*i, "%02x", md5sum[i]); 182 + return 1; 183 + } 184 + 185 + int PatchFirmware() 186 + { 187 + TCHAR fn[MAX_PATH]; 188 + TCHAR name1[MAX_PATH], name2[MAX_PATH], name3[MAX_PATH]; 189 + HRSRC res; 190 + HGLOBAL resload; 191 + unsigned char *bootloader; 192 + unsigned char md5sum_str[256]; 193 + DWORD blsize; 194 + int i; 195 + 196 + /* get pointer to bootloader.bin */ 197 + res = FindResource(NULL, MAKEINTRESOURCE(IDI_BOOTLOADER), TEXT("BIN")); 198 + resload = LoadResource(NULL, res); 199 + bootloader = (unsigned char *)LockResource(resload); 200 + blsize = SizeofResource(NULL, res); 201 + 202 + /* get filename from edit box */ 203 + GetWindowText(controls[EDIT_FILENAME], fn, MAX_PATH); 204 + /* store temp files in temp directory */ 205 + GetTempPath(MAX_PATH, name1); 206 + GetTempPath(MAX_PATH, name2); 207 + GetTempPath(MAX_PATH, name3); 208 + _tcscat(name1, TEXT("firmware.bin")); /* descrambled file */ 209 + _tcscat(name2, TEXT("new.bin")); /* patched file */ 210 + _tcscat(name3, TEXT("new.hex")); /* patched and scrambled file */ 211 + if (iriver_decode(fn, name1, FALSE, STRIP_NONE) == -1) { 212 + MessageBox(NULL, TEXT("Error in descramble"), 213 + TEXT("Error"), MB_ICONERROR); 214 + goto error; 215 + } 216 + if (!mkboot(name1, name2, bootloader, blsize)) { 217 + MessageBox(NULL, TEXT("Error in patching"), 218 + TEXT("Error"), MB_ICONERROR); 219 + goto error; 220 + } 221 + if (iriver_encode(name2, name3, FALSE) == -1) { 222 + MessageBox(NULL, TEXT("Error in scramble"), 223 + TEXT("Error"), MB_ICONERROR); 224 + goto error; 225 + } 226 + /* now md5sum it */ 227 + if (!FileMD5(name3, md5sum_str)) goto error; 228 + for (i = 0; i < sizeof(checksums)/sizeof(char *); ++i) { 229 + if (strncmp(checksums[i], md5sum_str, 32) != 0) { 230 + MessageBox(NULL, 231 + TEXT("Checksum doesn't match known good patched firmware.\n") 232 + TEXT("Download another firmware image, then try again."), 233 + TEXT("Error"), MB_ICONERROR); 234 + goto error; 235 + } 236 + } 237 + /* all is fine, rename the patched file to original name of the firmware */ 238 + MoveFileEx(name3, fn, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING); 239 + /* delete temp files */ 240 + DeleteFile(name1); 241 + DeleteFile(name2); 242 + return 1; 243 + error: 244 + /* delete all temp files, don't care if some aren't created yet */ 245 + DeleteFile(name1); 246 + DeleteFile(name2); 247 + DeleteFile(name3); 248 + return 0; 249 + } 250 + 251 + int FileDialog(TCHAR *fn) 252 + { 253 + OPENFILENAME ofn; 254 + TCHAR filename[MAX_PATH]; 255 + 256 + ZeroMemory(&ofn, sizeof(ofn)); 257 + ofn.lStructSize = sizeof(ofn); 258 + ofn.lpstrFile = filename; 259 + ofn.lpstrFile[0] = '\0'; // no default filename 260 + ofn.nMaxFile = sizeof(filename); 261 + ofn.lpstrFilter = TEXT("Firmware\0*.HEX\0"); 262 + ofn.nFilterIndex = 1; 263 + ofn.lpstrFileTitle = NULL; 264 + ofn.nMaxFileTitle = 0; 265 + ofn.lpstrInitialDir = NULL; 266 + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 267 + 268 + if (GetOpenFileName(&ofn) == TRUE) { 269 + _tcscpy(fn, filename); 270 + return 1; 271 + } 272 + return 0; 273 + } 274 + 275 + LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 276 + { 277 + int i; 278 + switch (msg) { 279 + case WM_CREATE: 280 + /* text label */ 281 + controls[LABEL_FILENAME] = 282 + CreateWindowEx(0, TEXT("STATIC"), TEXT("Firmware file name:"), 283 + WS_CHILD | WS_VISIBLE, 10, 14, 284 + 100, 32, hwnd, 0, 0, 0); 285 + /* text field for inputing file name */ 286 + controls[EDIT_FILENAME] = 287 + CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""), 288 + WS_CHILD | WS_TABSTOP | WS_VISIBLE | ES_AUTOHSCROLL, 289 + 10, 35, 180, 20, hwnd, 0, 0, 0); 290 + /* browse button */ 291 + controls[BUTTON_BROWSE] = 292 + CreateWindowEx(0, TEXT("BUTTON"), TEXT("Browse"), 293 + WS_CHILD | WS_TABSTOP | WS_VISIBLE, 200, 32, 70, 25, 294 + hwnd, 0, 0, 0); 295 + /* patch button */ 296 + controls[BUTTON_PATCH] = 297 + CreateWindowEx(0, TEXT("BUTTON"), TEXT("Patch"), 298 + WS_CHILD | WS_TABSTOP | WS_VISIBLE, 90, 70, 90, 25, 299 + hwnd, 0, 0, 0); 300 + /* set default font on all controls, will be ugly if we don't do this */ 301 + deffont = GetStockObject(DEFAULT_GUI_FONT); 302 + for (i = 0; i < CTL_NUM; ++i) 303 + SendMessage(controls[i], WM_SETFONT, (WPARAM)deffont, 304 + MAKELPARAM(FALSE, 0)); 305 + break; 306 + case WM_CLOSE: 307 + DestroyWindow(hwnd); 308 + break; 309 + case WM_DESTROY: 310 + PostQuitMessage(0); 311 + break; 312 + case WM_SIZE: 313 + break; 314 + case WM_COMMAND: 315 + /* user pressed browse button */ 316 + if (((HWND)lParam == controls[BUTTON_BROWSE])) { 317 + TCHAR buf[MAX_PATH]; 318 + if (FileDialog(buf)) 319 + SetWindowText(controls[EDIT_FILENAME], buf); 320 + } 321 + /* user pressed patch button */ 322 + if (((HWND)lParam == controls[BUTTON_PATCH])) { 323 + if (PatchFirmware()) 324 + MessageBox(NULL, TEXT("Firmware patched successfully"), 325 + TEXT("Success"), MB_OK); 326 + } 327 + break; 328 + default: 329 + return DefWindowProc(hwnd, msg, wParam, lParam); 330 + } 331 + return 0; 332 + } 333 + 334 + int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance, 335 + LPSTR command_line, int command_show) 336 + { 337 + HWND window; 338 + WNDCLASSEX wc; 339 + MSG msg; 340 + 341 + rbicon = LoadIcon(instance, MAKEINTRESOURCE(IDI_RBICON)); 342 + ZeroMemory(&wc, sizeof(wc)); 343 + wc.cbSize = sizeof(wc); 344 + wc.lpfnWndProc = WndProc; 345 + wc.hInstance = instance; 346 + wc.hIcon = rbicon; 347 + wc.hCursor = LoadCursor(0, IDC_ARROW); 348 + wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); 349 + wc.lpszClassName = TEXT("patcher"); 350 + RegisterClassEx(&wc); 351 + 352 + window = CreateWindowEx(0, TEXT("patcher"), TEXT("Rockbox firmware patcher"), 353 + WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | 354 + WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 355 + WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, instance, NULL); 356 + if (!window) return 0; 357 + 358 + ShowWindow(window, command_show); 359 + while (GetMessage(&msg, 0, 0, 0) > 0) { 360 + if (!IsDialogMessage(window, &msg)) { 361 + TranslateMessage(&msg); 362 + DispatchMessage(&msg); 363 + } 364 + } 365 + return 0; 366 + } 367 +
+246
tools/fwpatcher/md5.c
··· 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 + 41 + void 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 + 52 + void 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 + 175 + void 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 + 214 + static 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 + 222 + void 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 +
+25
tools/fwpatcher/md5.h
··· 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 + 12 + typedef struct 13 + { 14 + uint32 total[2]; 15 + uint32 state[4]; 16 + uint8 buffer[64]; 17 + } 18 + md5_context; 19 + 20 + void md5_starts( md5_context *ctx ); 21 + void md5_update( md5_context *ctx, uint8 *input, uint32 length ); 22 + void md5_finish( md5_context *ctx, uint8 digest[16] ); 23 + 24 + #endif /* md5.h */ 25 +
+3
tools/fwpatcher/resource.h
··· 1 + #define IDI_RBICON 101 2 + #define IDI_BOOTLOADER 102 3 +
+4
tools/fwpatcher/resource.rc
··· 1 + #include "resource.h" 2 + 3 + IDI_RBICON ICON "favicon.ico" 4 + IDI_BOOTLOADER BIN "bootloader.bin"