From 41541c5c31c5cd4f1a6dbbd7354046cfd5cfa13f Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Sun, 30 Sep 2007 12:49:43 +0000 Subject: Add support for the generic Telechips firmware format checksums - use -tcc=sum if the header just contains a single checksum, or -tcc=crc if the header contains two 32-bit CRCs. Credit goes to Hein-Pieter van Braam for his work on identifying the (reverse) CRC32 algorithm used when calculating the two CRCs git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14917 a1c6a512-1295-4272-9138-f99709370657 --- docs/CREDITS | 1 + tools/Makefile | 5 +- tools/scramble.c | 39 ++++++++++++-- tools/telechips.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/telechips.h | 26 +++++++++ 5 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 tools/telechips.c create mode 100644 tools/telechips.h diff --git a/docs/CREDITS b/docs/CREDITS index 83967930d8..0f09162eaf 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -336,6 +336,7 @@ Alexander Eickhoff Pinitnun Shanasabang Ken Fazzone David Bishop +Hein-Pieter van Braam The libmad team The wavpack team diff --git a/tools/Makefile b/tools/Makefile index 74d82affab..bbb9b0d9b0 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -16,15 +16,16 @@ CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \ all: @echo "Run make in your build directory!" -scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o +scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o descramble: descramble.o iriver.o gigabeat.o -scramble.o: scramble.c iriver.h mi4.h gigabeat.h +scramble.o: scramble.c iriver.h mi4.h gigabeat.h telechips.h descramble.o: descramble.c iriver.h gigabeat.h iriver.o: iriver.c iriver.h gigabeat.o: gigabeat.c gigabeat.h gigabeats.o: gigabeats.c gigabeats.h mi4.o: mi4.c mi4.h +telechips.o: telechips.c telechips.h sh2d: sh2d.c diff --git a/tools/scramble.c b/tools/scramble.c index 8534d41832..ad128835c5 100644 --- a/tools/scramble.c +++ b/tools/scramble.c @@ -25,6 +25,7 @@ #include "gigabeat.h" #include "gigabeats.h" #include "mi4.h" +#include "telechips.h" int iaudio_encode(char *iname, char *oname, char *idstring); int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc); @@ -102,6 +103,7 @@ void usage(void) "\t -model=XXXX where XXXX is the model id string\n" "\t -type=XXXX where XXXX is a string indicating the \n" "\t type of binary, eg. RBOS, RBBL\n" + "\t-tcc=X Telechips generic firmware format (X values: sum, crc)\n" "\t-add=X Rockbox generic \"add-up\" checksum format\n" "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd, mn2g\n" "\t ip3g, ip4g, mini, iax5, h10, h10_5gb, tpj2,\n" @@ -127,7 +129,7 @@ int main (int argc, char** argv) unsigned long modelnum; char modelname[5]; int model_id; - enum { none, scramble, xor, add } method = scramble; + enum { none, scramble, xor, tcc_sum, tcc_crc, add } method = scramble; model_id = ARCHOS_PLAYER; @@ -186,6 +188,20 @@ int main (int argc, char** argv) return -1; } } + else if(!strncmp(argv[1], "-tcc=", 4)) { + headerlen = 0; + iname = argv[2]; + oname = argv[3]; + + if(!strcmp(&argv[1][5], "sum")) + method = tcc_sum; + else if(!strcmp(&argv[1][5], "crc")) + method = tcc_crc; + else { + fprintf(stderr, "unsupported TCC method: %s\n", &argv[1][5]); + return 2; + } + } else if(!strncmp(argv[1], "-add=", 5)) { iname = argv[2]; oname = argv[3]; @@ -409,7 +425,7 @@ int main (int argc, char** argv) break; } - if(method != add) { + if((method == none) || (method == scramble) || (method == xor)) { /* calculate checksum */ for (i=0;i 0) { + if ( !fwrite(header,headerlen,1,file) ) { + perror(oname); + return -1; + } } if ( !fwrite(outbuf,length,1,file) ) { perror(oname); diff --git a/tools/telechips.c b/tools/telechips.c new file mode 100644 index 0000000000..5b6f3c23b3 --- /dev/null +++ b/tools/telechips.c @@ -0,0 +1,156 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Telechips firmware checksum support for scramble + * + * Copyright (C) 2007 Dave Chapman + * + * Thanks to Hein-Pieter van Braam for his work in identifying the + * CRC algorithm used. + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +static uint32_t crctable[256]; + +/* Simple implementation of a function to reverse the bottom n bits in x */ +static uint32_t bitreverse(uint32_t x,int n) +{ + int i; + uint32_t mask = 1<<(n-1); + uint32_t res = 0; + + for (i=0; i>= 1; + mask >>= 1; + } + return res; +} + +/* Generate a lookup table for a reverse CRC32 */ +static void gentable(uint32_t poly) +{ + int i; + uint32_t r; + uint32_t index; + + for (index = 0; index < 256; index++) + { + r = bitreverse(index,8) << 24; + for (i=0; i<8; i++) + { + if (r & (1 << 31)) + r = (r << 1) ^ poly; + else + r<<=1; + } + crctable[index] = bitreverse(r,32); + } +} + +/* Perform a reverse CRC32 */ +static uint32_t calc_crc(unsigned char *message, int size) +{ + uint32_t crc = 0; + int i; + + for (i=0; i < size; i++){ + if ((i < 0x10) || (i >= 0x18)) { + crc = crctable[((crc ^ (message[i])) & 0xff)] ^ (crc >> 8); + } + } + + return crc; +} + +/* Endian-safe functions to read/write a 32-bit little-endian integer */ + +static uint32_t get_uint32le(unsigned char* p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + +static void put_uint32le(unsigned char* p, uint32_t x) +{ + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} + +/* A simple checksum - seems to be used by the TCC76x firmwares */ +void telechips_encode_sum(unsigned char* buf, int length) +{ + uint32_t sum; + int i; + + /* Set checksum field to 0 */ + put_uint32le(buf + 0x10, 0); + + /* Perform a simple sum, treating the file as a series of 32-bit + little-endian integers */ + sum = 0; + for (i=0; i < length; i+=4) { + sum += get_uint32le(buf + i); + } + /* Negate the sum - this means that the sum of the whole file + (including this value) will be equal to zero */ + sum = -sum; + + /* Set the checksum field */ + put_uint32le(buf + 0x10, sum); +} + + +/* Two reverse CRC32 checksums - seems to be used by the TCC77x firmwares */ +void telechips_encode_crc(unsigned char* buf, int length) +{ + uint32_t crc1,crc2; + + /* Generate the CRC table */ + gentable(0x8001801BL); + + /* Clear the existing CRC values */ + put_uint32le(buf+0x10, 0); + put_uint32le(buf+0x18, 0); + + /* Write the length */ + put_uint32le(buf+0x1c, length); + + /* Calculate the first CRC - over the entire file */ + crc1 = calc_crc(buf, length); + + /* What happens next depends on the filesize */ + if (length >= 128*1024) + { + put_uint32le(buf+0x18, crc1); + + crc2 = calc_crc(buf, 128*1024); + put_uint32le(buf+0x10, crc2); + } else { + put_uint32le(buf+0x10, crc1); + } +} diff --git a/tools/telechips.h b/tools/telechips.h new file mode 100644 index 0000000000..7854da0294 --- /dev/null +++ b/tools/telechips.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 Dave Chapman + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _TELECHIPS_H +#define _TELECHIPS_H + +void telechips_encode_sum(unsigned char* buf, int length); +void telechips_encode_crc(unsigned char* buf, int length); + +#endif -- cgit v1.2.3