Index: tools/fwpatcher/cli.c =================================================================== RCS file: tools/fwpatcher/cli.c diff -N tools/fwpatcher/cli.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tools/fwpatcher/cli.c 30 Jan 2006 16:42:04 -0000 @@ -0,0 +1,316 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: main.c,v 1.9 2005/11/18 20:01:51 linus Exp $ + * + * Copyright (C) 2005 by Thom Johansen + * Conversion to command line by James Teh + * + * 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 "iriver.h" +#include "md5.h" + +struct sumpairs { + char *unpatched; + char *patched; +}; + +/* precalculated checksums for H110/H115 */ +static struct sumpairs h100pairs[] = { +#include "h100sums.h" +}; + +/* precalculated checksums for H120/H140 */ +static struct sumpairs h120pairs[] = { +#include "h120sums.h" +}; + +/* precalculated checksums for H320/H340 */ +static struct sumpairs h300pairs[] = { +#include "h300sums.h" +}; + +/* begin mkboot.c excerpt */ + +unsigned char image[0x400000 + 0x220 + 0x400000/0x200]; + +int mkboot(char *infile, char *outfile, unsigned char *bldata, int bllen, + int origin) +{ + FILE *f; + int i; + int len; + int actual_length, total_length, binary_length, num_chksums; + + memset(image, 0xff, sizeof(image)); + + /* First, read the iriver original firmware into the image */ + f = fopen(infile, "rb"); + if(!f) { + perror(infile); + return 0; + } + + i = fread(image, 1, 16, f); + if(i < 16) { + perror(infile); + return 0; + } + + /* This is the length of the binary image without the scrambling + overhead (but including the ESTFBINR header) */ + binary_length = image[4] + (image[5] << 8) + + (image[6] << 16) + (image[7] << 24); + + /* Read the rest of the binary data, but not the checksum block */ + len = binary_length+0x200-16; + i = fread(image+16, 1, len, f); + if(i < len) { + perror(infile); + return 0; + } + + fclose(f); + + memcpy(image + 0x220 + origin, bldata, bllen); + + f = fopen(outfile, "wb"); + if(!f) { + perror(outfile); + return 0; + } + + /* Patch the reset vector to start the boot loader */ + image[0x220 + 4] = image[origin + 0x220 + 4]; + image[0x220 + 5] = image[origin + 0x220 + 5]; + image[0x220 + 6] = image[origin + 0x220 + 6]; + image[0x220 + 7] = image[origin + 0x220 + 7]; + + /* This is the actual length of the binary, excluding all headers */ + actual_length = origin + bllen; + + /* Patch the ESTFBINR header */ + image[0x20c] = (actual_length >> 24) & 0xff; + image[0x20d] = (actual_length >> 16) & 0xff; + image[0x20e] = (actual_length >> 8) & 0xff; + image[0x20f] = actual_length & 0xff; + + image[0x21c] = (actual_length >> 24) & 0xff; + image[0x21d] = (actual_length >> 16) & 0xff; + image[0x21e] = (actual_length >> 8) & 0xff; + image[0x21f] = actual_length & 0xff; + + /* This is the length of the binary, including the ESTFBINR header and + rounded up to the nearest 0x200 boundary */ + binary_length = (actual_length + 0x20 + 0x1ff) & 0xfffffe00; + + /* The number of checksums, i.e number of 0x200 byte blocks */ + num_chksums = binary_length / 0x200; + + /* The total file length, including all headers and checksums */ + total_length = binary_length + num_chksums + 0x200; + + /* Patch the scrambler header with the new length info */ + image[0] = total_length & 0xff; + image[1] = (total_length >> 8) & 0xff; + image[2] = (total_length >> 16) & 0xff; + image[3] = (total_length >> 24) & 0xff; + + image[4] = binary_length & 0xff; + image[5] = (binary_length >> 8) & 0xff; + image[6] = (binary_length >> 16) & 0xff; + image[7] = (binary_length >> 24) & 0xff; + + image[8] = num_chksums & 0xff; + image[9] = (num_chksums >> 8) & 0xff; + image[10] = (num_chksums >> 16) & 0xff; + image[11] = (num_chksums >> 24) & 0xff; + + i = fwrite(image, 1, total_length, f); + if(i < total_length) { + perror(outfile); + return 0; + } + + fclose(f); + + return 1; +} + +/* end mkboot.c excerpt */ + +int intable(char *md5, struct sumpairs *table, int len) +{ + int i; + for (i = 0; i < len; i++) { + if (strncmp(md5, table[i].unpatched, 32) == 0) { + return i; + } + } + return -1; +} + +int FileMD5(char *name, char *md5) +{ + int i, read; + md5_context ctx; + unsigned char md5sum[16]; + unsigned char block[32768]; + FILE *file; + + file = fopen(name, "rb"); + if (!file) { + fprintf(stderr, "Error: Could not open patched firmware for checksum check\n"); + return 0; + } + md5_starts(&ctx); + while ((read = fread(block, 1, sizeof(block), file)) > 0) { + md5_update(&ctx, block, read); + } + fclose(file); + md5_finish(&ctx, md5sum); + for (i = 0; i < 16; ++i) + sprintf(md5 + 2*i, "%02x", md5sum[i]); + return 1; +} + +int PatchFirmware(int series, int table_entry, char *fn) +{ + char blfn[20]; + struct stat blfd; + FILE *blf; + char name1[FILENAME_MAX], name2[FILENAME_MAX], name3[FILENAME_MAX]; + unsigned char *bootloader; + char md5sum_str[256]; + off_t blsize; + int i; + struct sumpairs *sums; + int origin; + + /* get pointer to the correct bootloader.bin */ + switch(series) { + case 100: + strcpy(blfn, "bootloader-h100.bin"); + sums = &h100pairs[0]; + origin = 0x1f0000; + break; + case 120: + strcpy(blfn, "bootloader-h120.bin"); + sums = &h120pairs[0]; + origin = 0x1f0000; + break; + case 300: + strcpy(blfn, "bootloader-h300.bin"); + sums = &h300pairs[0]; + origin = 0x3f0000; + break; + } + if (stat(blfn, &blfd) != 0) { + perror(blfn); + return 0; + } + blsize = blfd.st_size; + /* Read the bootloader into memory. */ + if (!(blf = fopen(blfn, "rb"))) { + perror(blfn); + } + bootloader = (unsigned char*)malloc(blsize); + fread(bootloader, blsize, 1, blf); + fclose(blf); + + /* temp files */ + strcpy(name1, "firmware.bin"); /* descrambled file */ + strcpy(name2, "new.bin"); /* patched file */ + strcpy(name3, "new.hex"); /* patched and scrambled file */ + if (iriver_decode(fn, name1, FALSE, STRIP_NONE) == -1) { + fprintf(stderr, "Error in descramble\n"); + goto error; + } + if (!mkboot(name1, name2, bootloader, blsize, origin)) { + fprintf(stderr, "Error in patching\n"); + goto error; + } + if (iriver_encode(name2, name3, FALSE) == -1) { + fprintf(stderr, "Error in scramble\n"); + goto error; + } + /* now md5sum it */ + if (!FileMD5(name3, md5sum_str)) { + fprintf(stderr, "Error in checksumming\n"); + goto error; + } + if (strncmp(sums[table_entry].patched, md5sum_str, 32) == 0) { + /* delete temp files */ + remove(name1); + remove(name2); + /* all is fine, rename the patched file to original name of the firmware */ + if (remove(fn) == 0 && rename(name3, fn) == 0) { + return 1; + } + else { + remove(name3); /* Deleting a perfectly good firmware here really */ + fprintf(stderr, "Couldn't modify existing file.\n"); + fprintf(stderr, "Check if file is write protected, then try again.\n"); + return 0; + } + } + fprintf(stderr, "Checksum doesn't match known good patched firmware.\n"); + fprintf(stderr, "Download another firmware image, then try again.\n"); +error: + /* delete all temp files, don't care if some aren't created yet */ + remove(name1); + remove(name2); + remove(name3); + return 0; +} + +int main(int argc, char *argv[]) +{ + int i, series, table_entry; + char md5sum_str[256]; + char fn[FILENAME_MAX]; + + if (argc != 2) { + fprintf(stderr, "Usage: %s firmware_filename\n", argv[0]); + exit(1); + } + strncpy(fn, argv[1], FILENAME_MAX); + + if (!FileMD5(fn, md5sum_str)) { + fprintf(stderr, "Error: Couldn't open firmware\n"); + } else { + /* Check firmware against md5sums in h120sums and h100sums */ + series = 0; + table_entry = intable(md5sum_str, &h120pairs[0], sizeof(h120pairs) / sizeof(struct sumpairs)); + if (table_entry >= 0) { + series = 120; + } else { + table_entry = intable(md5sum_str, &h100pairs[0], sizeof(h100pairs) / sizeof(struct sumpairs)); + if (table_entry >= 0) { + series = 100; + } else { + table_entry = intable(md5sum_str, &h300pairs[0], sizeof(h300pairs) / sizeof(struct sumpairs)); + if (table_entry >= 0) + series = 300; + } + } + if (series == 0) { + fprintf(stderr, "Unrecognised firmware\n"); + } else if (PatchFirmware(series, table_entry, fn)) + printf("Firmware patched successfully\n"); + } +} Index: tools/fwpatcher/iriver.h =================================================================== RCS file: /cvsroot/rockbox/tools/fwpatcher/iriver.h,v retrieving revision 1.1 diff -u -r1.1 iriver.h --- tools/fwpatcher/iriver.h 25 Apr 2005 21:08:36 -0000 1.1 +++ tools/fwpatcher/iriver.h 30 Jan 2006 16:42:04 -0000 @@ -17,8 +17,14 @@ * ****************************************************************************/ +#ifdef __WIN32__ #include #include +#else +#define TCHAR char +#define TEXT +#define _tfopen fopen +#endif #define TRUE 1 #define FALSE 0