/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * * Copyright (C) 2006 by Rani Hod * * 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 #define HEADER_SIZE 0x1030 #define FLASH_START 0x00010000 #define ROCKBOX_BOOTLOADER 0x00150000 #define BOOTLOADER_LIMIT 0x00170000 void usage() { printf("Usage: mkboot-x5 \n"); } void do_patch(char *fbuf, const char *bbuf, size_t blength) { unsigned char *p; /* change jsr 0x10010 to jsr DUAL_BOOTLOADER */ p = fbuf + HEADER_SIZE + 2; *p++ = (ROCKBOX_BOOTLOADER >> 24) & 0xff; *p++ = (ROCKBOX_BOOTLOADER >> 16) & 0xff; *p++ = (ROCKBOX_BOOTLOADER >> 8) & 0xff; *p++ = (ROCKBOX_BOOTLOADER ) & 0xff; p = fbuf + HEADER_SIZE + ROCKBOX_BOOTLOADER - FLASH_START; memcpy(p, bbuf, blength); } int main(int argc, char **argv) { size_t flength, blength; unsigned char *bbuf, *fbuf; const unsigned char fsig[] = { /* jsr 10010 */ 0x4e, 0xb9, 0x00, 0x01, 0x00, 0x10 }; const unsigned char bsig[] = { /* tst.b 30000000 */ 0x4a, 0x39, 0x30, 0x00, 0x00, 0x00 }; const char *fname, *bname, *oname; FILE *ffile, *bfile, *ofile; unsigned char sum = 0; int i; if (argc != 4) { usage(); return 1; } fname = argv[1]; bname = argv[2]; oname = argv[3]; /* read input files */ if ((bfile = fopen(bname, "rb")) == NULL) { perror("Cannot open Rockbox bootloader file.\n"); return -1; } fseek(bfile, 0, SEEK_END); blength = ftell(bfile); fseek(bfile, 0, SEEK_SET); if (blength + ROCKBOX_BOOTLOADER >= BOOTLOADER_LIMIT) { perror("Rockbox bootloader is too big.\n"); return -1; } if ((ffile = fopen(fname, "rb")) == NULL) { perror("Cannot open original firmware file.\n"); return -1; } fseek(ffile, 0, SEEK_END); flength = ftell(ffile); fseek(ffile, 0, SEEK_SET); bbuf = malloc(blength); fbuf = malloc(flength); if (!bbuf || !fbuf) { perror("Out of memory.\n"); return -1; } if ( fread(bbuf, 1, blength, bfile) < blength || fread(fbuf, 1, flength, ffile) < flength) { perror("Read error.\n"); return -1; } fclose(bfile); fclose(ffile); /* verify format of input files */ if (blength < 0x10 || memcmp(bbuf, bsig, sizeof(bsig))) { perror("Rockbox bootloader format error (is it bootloader.bin?).\n"); return -1; } if (flength < 0x1030-0x10000+BOOTLOADER_LIMIT || memcmp(fbuf+0x1030, fsig, sizeof(fsig))) { perror("Original firmware format error (is it x5_fw.bin?).\n"); return -1; } /* verify firmware is not overrun */ for (i = ROCKBOX_BOOTLOADER; i < BOOTLOADER_LIMIT; i++) { if (fbuf[0x1030-0x10000+i] != 0xff) { perror("Original firmware has grown too much.\n"); return -1; } } do_patch(fbuf, bbuf, blength); /* recalc checksum */ for (i = 0x1030; i < flength; i++) sum += fbuf[i]; fbuf[0x102b] = sum; /* write output */ if ((ofile = fopen(oname, "wb")) == NULL) { perror("Cannot open output file.\n"); return -1; } if (fwrite(fbuf, 1, flength, ofile) < flength) { perror("Write error.\n"); return -1; } fclose(ofile); free(bbuf); free(fbuf); }