From f35e300304388c30fdeb6493ec5e5e5bd52e3aab Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Tue, 28 Feb 2012 23:36:13 +0100 Subject: [PATCH] scramble: add RKW firmware file format encoder Change-Id: I8057d6186724c3e8a319a262f45c12da7afb722e --- tools/Makefile | 5 +- tools/rkw.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++ tools/rkw.h | 26 ++++++++ tools/scramble.c | 30 +++++++-- tools/tools.make | 4 +- 5 files changed, 222 insertions(+), 9 deletions(-) create mode 100644 tools/rkw.c create mode 100644 tools/rkw.h diff --git a/tools/Makefile b/tools/Makefile index da0d3dfb8a..2b4b1ae88b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -18,10 +18,10 @@ all: scramble descramble sh2d rdf2binary mkboot mkzenboot convbdf codepages \ uclpack rbspeexenc voicefont mk500boot scramble: scramble.o iriver.o mi4.o gigabeat.o gigabeats.o telechips.o \ - iaudio_bl_flash.o creative.o hmac-sha1.o + iaudio_bl_flash.o creative.o hmac-sha1.o rkw.o descramble: descramble.o iriver.o gigabeat.o scramble.o: scramble.c iriver.h mi4.h gigabeat.h telechips.h iaudio_bl_flash.h \ - creative.h + creative.h rkw.h descramble.o: descramble.c iriver.h gigabeat.h creative.o: creative.c creative.h @@ -31,6 +31,7 @@ gigabeat.o: gigabeat.c gigabeat.h gigabeats.o: gigabeats.c gigabeats.h mi4.o: mi4.c mi4.h telechips.o: telechips.c telechips.h +rkw.o: rkw.c rkw.h iaudio_bl_flash.o: iaudio_bl_flash.c iaudio_bl_flash.h iaudio_bl_flash.c iaudio_bl_flash.h: iaudio_bl_flash.bmp bmp2rb $(SILENT)./bmp2rb -f 7 -h . $< >iaudio_bl_flash.c diff --git a/tools/rkw.c b/tools/rkw.c new file mode 100644 index 0000000000..db86b4f748 --- /dev/null +++ b/tools/rkw.c @@ -0,0 +1,166 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2012 Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include + +#define RKLD_MAGIC 0x4c44524b +#define RKW_HEADER_SIZE 0x2c + +/* slightly modified version from crc32.c in rockbox */ +static uint32_t rkw_crc32(const void *src, uint32_t len) +{ + const unsigned char *buf = (const unsigned char *)src; + + /* polynomial 0x04c10db7 */ + static const uint32_t crc32_lookup[16] = + { /* lookup table for 4 bits at a time is affordable */ + 0x00000000, 0x04C10DB7, 0x09821B6E, 0x0D4316D9, + 0x130436DC, 0x17C53B6B, 0x1A862DB2, 0x1E472005, + 0x26086DB8, 0x22C9600F, 0x2F8A76D6, 0x2B4B7B61, + 0x350C5B64, 0x31CD56D3, 0x3C8E400A, 0x384F4DBD + }; + + uint32_t crc32 = 0; + unsigned char byte; + uint32_t t; + + while (len--) + { + byte = *buf++; /* get one byte of data */ + + /* upper nibble of our data */ + t = crc32 >> 28; /* extract the 4 most significant bits */ + t ^= byte >> 4; /* XOR in 4 bits of data into the extracted bits */ + crc32 <<= 4; /* shift the CRC register left 4 bits */ + crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */ + + /* lower nibble of our data */ + t = crc32 >> 28; /* extract the 4 most significant bits */ + t ^= byte & 0x0F; /* XOR in 4 bits of data into the extracted bits */ + crc32 <<= 4; /* shift the CRC register left 4 bits */ + crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */ + } + + return crc32; +} + +static void int2le(unsigned int val, unsigned char* addr) +{ + addr[0] = val & 0xFF; + addr[1] = (val >> 8) & 0xff; + addr[2] = (val >> 16) & 0xff; + addr[3] = (val >> 24) & 0xff; +} + +int rkw_encode(char *iname, char *oname, unsigned long modelnum) +{ + size_t len; + int length; + int rkwlength; + FILE *file; + uint32_t binary_crc, header_crc; + unsigned char *outbuf; + + file = fopen(iname, "rb"); + if (!file) + { + perror(iname); + return -1; + } + + fseek(file,0,SEEK_END); + length = ftell(file); + + fseek(file,0,SEEK_SET); + + /* length of the RKW header + binary length + 4 bytes of CRC */ + rkwlength = (length + RKW_HEADER_SIZE + 4); + + outbuf = malloc(rkwlength); + + if (!outbuf) + { + printf("out of memory!\n"); + fclose(file); + return -1; + } + + /* Clear the buffer to zero */ + memset(outbuf, 0, rkwlength); + + /* Build the RKW header */ + int2le(RKLD_MAGIC, outbuf); /* magic */ + int2le(RKW_HEADER_SIZE, outbuf+0x04); /* header size */ + int2le(0x60000000, outbuf+0x08); /* base address */ + int2le(0x60000000, outbuf+0x0c); /* load address */ + int2le(0x60000000+length, outbuf+0x10); /* end address */ + int2le(0x6035a5e4, outbuf+0x14); /* points to some unknown struct */ + int2le(modelnum, outbuf+0x18); /* reserved (we abuse the format + * to store modelnum here + */ + int2le(0, outbuf+0x1c); /* reserved */ + int2le(0x60000000, outbuf+0x20); /* entry point */ + int2le(0xe0000000, outbuf+0x24); /* flags */ + + header_crc = rkw_crc32(outbuf, RKW_HEADER_SIZE - 4); + + int2le(header_crc, outbuf+0x28); /* header CRC */ + + /* Copy the binary */ + len = fread(outbuf + RKW_HEADER_SIZE, 1, length, file); + if(len < (size_t)length) + { + perror(iname); + free(outbuf); + fclose(file); + return -2; + } + fclose(file); + + /* calc binary CRC and put at the end */ + binary_crc = rkw_crc32 (outbuf + RKW_HEADER_SIZE, length); + int2le(binary_crc, outbuf + rkwlength - 4); + + file = fopen(oname, "wb"); + if (!file) + { + perror(oname); + free(outbuf); + return -3; + } + + len = fwrite(outbuf, 1, rkwlength, file); + if(len < (size_t)length) + { + perror(oname); + fclose(file); + free(outbuf); + return -4; + } + + fclose(file); + free(outbuf); + fprintf(stderr, "File encoded successfully\n" ); + + return 0; +} diff --git a/tools/rkw.h b/tools/rkw.h new file mode 100644 index 0000000000..6ec77882b1 --- /dev/null +++ b/tools/rkw.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2012 Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _RKW_H +#define _RKW_H + +int rkw_encode(char *iname, char *oname, unsigned long modelnum); + +#endif diff --git a/tools/scramble.c b/tools/scramble.c index 7c7a847ea1..c3b200c01e 100644 --- a/tools/scramble.c +++ b/tools/scramble.c @@ -30,6 +30,7 @@ #include "telechips.h" #include "creative.h" #include "iaudio_bl_flash.h" +#include "rkw.h" static int iaudio_encode(char *iname, char *oname, char *idstring); static int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc); @@ -119,11 +120,12 @@ void usage(void) "\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-rkw Rockchip RKW format\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, iam5, iam3, h10, h10_5gb,\n" - "\t tpj2, c200, e200, giga, gigs, m100, m500, d2,\n"); - printf("\t 9200, 1630, 6330, ldax, m200, c100, clip, e2v2,\n" + "\t ip3g, ip4g, mini, iax5, iam5, iam3, h10, h10_5gb,\n"); + printf("\t tpj2, c200, e200, giga, gigs, m100, m500, d2,\n" + "\t 9200, 1630, 6330, ldax, m200, c100, clip, e2v2,\n" "\t m2v4, fuze, c2v2, clv2, y820, y920, y925, x747,\n" "\t 747p, x777, nn2g, m244, cli+, fuz2, hd20, hd30,\n" "\t ip6g, rk27, clzp)\n"); @@ -148,7 +150,7 @@ int main (int argc, char** argv) unsigned long modelnum; char modelname[5]; int model_id; - enum { none, scramble, xor, tcc_sum, tcc_crc, add } method = scramble; + enum { none, scramble, xor, tcc_sum, tcc_crc, rkw, add } method = scramble; bool creative_enable_ciff; model_id = ARCHOS_PLAYER; @@ -222,6 +224,24 @@ int main (int argc, char** argv) return 2; } } + else if(!strncmp(argv[1], "-rkw", 4)) { + iname = argv[3]; + oname = argv[4]; + modelnum = 0; + + if(!strncmp(argv[2], "-modelnum=", 10)) { + modelnum = atoi(&argv[2][10]); + } + + if (!modelnum) + { + modelnum = 73; /* rk27generic */ + fprintf(stderr, "modelnum not supplied." + " using default value for rk27generic target\n"); + } + + return (rkw_encode(iname, oname, modelnum) != 0) ? -1 : 0; + } else if(!strncmp(argv[1], "-add=", 5)) { iname = argv[2]; oname = argv[3]; @@ -337,8 +357,6 @@ int main (int argc, char** argv) modelnum = 71; else if (!strcmp(&argv[1][5], "fuz+")) /* Sansa Fuze+ */ modelnum = 72; - else if (!strcmp(&argv[1][5], "rk27")) /* rockchip 27xx generic */ - modelnum = 73; else if (!strcmp(&argv[1][5], "clzp")) /* Sansa Clip Zip */ modelnum = 79; else if (!strcmp(&argv[1][5], "conn")) /* Sansa Connect */ diff --git a/tools/tools.make b/tools/tools.make index c143157dab..3350ad03bc 100644 --- a/tools/tools.make +++ b/tools/tools.make @@ -13,7 +13,9 @@ $(TOOLSDIR)/scramble: $(TOOLSDIR)/scramble.c $(TOOLSDIR)/iriver.c \ $(TOOLSDIR)/mi4.c $(TOOLSDIR)/gigabeat.c \ $(TOOLSDIR)/gigabeats.c $(TOOLSDIR)/telechips.c \ $(TOOLSDIR)/iaudio_bl_flash.c \ - $(TOOLSDIR)/creative.c $(TOOLSDIR)/hmac-sha1.c + $(TOOLSDIR)/creative.c $(TOOLSDIR)/hmac-sha1.c \ + $(TOOLSDIR)/rkw.c + $(TOOLSDIR)/rdf2binary: $(TOOLSDIR)/rdf2binary.c $(TOOLSDIR)/convbdf: $(TOOLSDIR)/convbdf.c $(TOOLSDIR)/codepages: $(TOOLSDIR)/codepages.c $(TOOLSDIR)/codepage_tables.c