1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2009 by Maurus Cuelenaere
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
27 #include "chinachip.h"
29 /* From http://www.rockbox.org/wiki/ChinaChip */
32 uint32_t signature
; /* WADF */
34 int8_t timestamp
[12]; /* 200805081100 */
38 int8_t identifier
[32]; /* Chinachip PMP firmware V1.0 */
39 } __attribute__ ((packed
));
41 static inline void int2le(unsigned char* addr
, unsigned int val
)
44 addr
[1] = (val
>> 8) & 0xff;
45 addr
[2] = (val
>> 16) & 0xff;
46 addr
[3] = (val
>> 24) & 0xff;
49 static inline unsigned int le2int(unsigned char* buf
)
51 return (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
54 static long int filesize(FILE* fd
)
57 fseek(fd
, 0, SEEK_END
);
59 fseek(fd
, 0, SEEK_SET
);
63 #define FCLOSE(fd) fclose(fd); fd = NULL;
64 #define CCPMPBIN_HEADER_SIZE (sizeof(uint32_t)*2 + sizeof(uint8_t) + 9)
65 #define TOTAL_SIZE (fsize + CCPMPBIN_HEADER_SIZE + bsize)
66 enum cc_error
chinachip_patch(const char* firmware
, const char* bootloader
,
67 const char* output
, const char* ccpmp_backup
)
72 unsigned char* buf
= NULL
;
73 FILE *fd
= NULL
, *bd
= NULL
, *od
= NULL
;
74 unsigned int ccpmp_size
= 0, i
, fsize
, bsize
;
75 signed int checksum
= 0, ccpmp_pos
;
78 fd
= fopen(firmware
, "rb");
81 fprintf(stderr
, "[ERR] Can't open file %s!\n", firmware
);
82 result
= E_OPEN_FIRMWARE
;
85 bd
= fopen(bootloader
, "rb");
88 fprintf(stderr
, "[ERR] Can't open file %s!\n", bootloader
);
89 result
= E_OPEN_BOOTLOADER
;
94 fprintf(stderr
, "[INFO] Bootloader size is %d bytes\n", bsize
);
98 fprintf(stderr
, "[INFO] Firmware size is %d bytes\n", fsize
);
100 buf
= malloc(TOTAL_SIZE
);
103 fprintf(stderr
, "[ERR] Can't allocate %d bytes!\n", fsize
);
107 memset(buf
, 0, TOTAL_SIZE
);
109 fprintf(stderr
, "[INFO] Reading %s into memory...\n", firmware
);
110 if(fread(buf
, fsize
, 1, fd
) != 1)
112 fprintf(stderr
, "[ERR] Can't read file %s to memory!\n", firmware
);
113 result
= E_LOAD_FIRMWARE
;
118 if(memcmp(buf
, "WADF", 4))
120 fprintf(stderr
, "[ERR] File %s isn't a valid ChinaChip firmware!\n", firmware
);
121 result
= E_INVALID_FILE
;
125 ccpmp_pos
= -1, i
= 0x40;
128 int filenamesize
= le2int(&buf
[i
]);
129 i
+= sizeof(uint32_t);
131 if(!strncmp((char*) &buf
[i
], "ccpmp.bin", 9))
134 ccpmp_size
= le2int(&buf
[i
+ sizeof(uint8_t) + filenamesize
]);
137 i
+= filenamesize
+ le2int(&buf
[i
+ sizeof(uint8_t) + filenamesize
])
138 + sizeof(uint32_t) + sizeof(uint8_t);
139 } while(ccpmp_pos
< 0 && i
< fsize
);
143 fprintf(stderr
, "[ERR] Couldn't find ccpmp.bin in %s!\n", firmware
);
147 fprintf(stderr
, "[INFO] Found ccpmp.bin at %d bytes\n", ccpmp_pos
);
151 int ccpmp_data_pos
= ccpmp_pos
+ 9;
152 bd
= fopen(ccpmp_backup
, "wb");
155 fprintf(stderr
, "[ERR] Can't open file %s!\n", ccpmp_backup
);
156 result
= E_OPEN_BACKUP
;
160 fprintf(stderr
, "[INFO] Writing %d bytes to %s...\n", ccpmp_size
, ccpmp_backup
);
161 if(fwrite(&buf
[ccpmp_data_pos
], ccpmp_size
, 1, bd
) != 1)
163 fprintf(stderr
, "[ERR] Can't write to file %s!\n", ccpmp_backup
);
164 result
= E_WRITE_BACKUP
;
170 fprintf(stderr
, "[INFO] Renaming it to ccpmp.old...\n");
171 buf
[ccpmp_pos
+ 6] = 'o';
172 buf
[ccpmp_pos
+ 7] = 'l';
173 buf
[ccpmp_pos
+ 8] = 'd';
175 bd
= fopen(bootloader
, "rb");
178 fprintf(stderr
, "[ERR] Can't open file %s!\n", bootloader
);
179 result
= E_OPEN_BOOTLOADER
;
183 /* Also include path size */
184 ccpmp_pos
-= sizeof(uint32_t);
186 fprintf(stderr
, "[INFO] Making place for ccpmp.bin...\n");
187 memmove(&buf
[ccpmp_pos
+ bsize
+ CCPMPBIN_HEADER_SIZE
],
188 &buf
[ccpmp_pos
], fsize
- ccpmp_pos
);
190 fprintf(stderr
, "[INFO] Reading %s into memory...\n", bootloader
);
191 if(fread(&buf
[ccpmp_pos
+ CCPMPBIN_HEADER_SIZE
],
194 fprintf(stderr
, "[ERR] Can't read file %s to memory!\n", bootloader
);
195 result
= E_LOAD_BOOTLOADER
;
200 fprintf(stderr
, "[INFO] Adding header to %s...\n", bootloader
);
201 int2le(&buf
[ccpmp_pos
], 9); /* Pathname Size */
202 memcpy(&buf
[ccpmp_pos
+ 4 ], "ccpmp.bin", 9); /* Pathname */
203 memset(&buf
[ccpmp_pos
+ 4 + 9 ], 0x20, sizeof(uint8_t)); /* File Type */
204 int2le(&buf
[ccpmp_pos
+ 4 + 9 + 1], bsize
); /* File Size */
207 time_info
= localtime(&cur_time
);
208 if(time_info
== NULL
)
210 fprintf(stderr
, "[ERR] Can't obtain current time!\n");
215 snprintf(header_time
, 13, "%04d%02d%02d%02d%02d", time_info
->tm_year
+ 1900,
221 fprintf(stderr
, "[INFO] Computing checksum...\n");
222 for(i
= sizeof(struct header
); i
< TOTAL_SIZE
; i
+=4)
223 checksum
+= le2int(&buf
[i
]);
225 fprintf(stderr
, "[INFO] Updating main header...\n");
226 memcpy(&buf
[offsetof(struct header
, timestamp
)], header_time
, 12);
227 int2le(&buf
[offsetof(struct header
, size
) ], TOTAL_SIZE
);
228 int2le(&buf
[offsetof(struct header
, checksum
) ], checksum
);
230 od
= fopen(output
, "wb");
233 fprintf(stderr
, "[ERR] Can't open file %s!\n", output
);
234 result
= E_OPEN_OUTFILE
;
238 fprintf(stderr
, "[INFO] Writing output to %s...\n", output
);
239 if(fwrite(buf
, TOTAL_SIZE
, 1, od
) != 1)
241 fprintf(stderr
, "[ERR] Can't write to file %s!\n", output
);
242 result
= E_WRITE_OUTFILE
;