diff options
author | Dave Chapman <dave@dchapman.com> | 2006-08-30 23:17:04 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2006-08-30 23:17:04 +0000 |
commit | 530f31dbe9fe404d41fd21867c8ed9cec1addd96 (patch) | |
tree | ec4caa9ead19f3e0756e4cb02bf11d6f8e4163e2 /tools | |
parent | e379225754b326806df1a037a7610e3b2c1a11bc (diff) |
Add generation of .mi4 files - the generic PortalPlayer firmware format used by the iriver H10, Sansa E200 etc. Based on the documentation available at http://daniel.haxx.se/sansa/mi4.html and examination of files produced by mkmi4.sh
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10816 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 5 | ||||
-rw-r--r-- | tools/mi4.c | 188 | ||||
-rw-r--r-- | tools/mi4.h | 25 | ||||
-rw-r--r-- | tools/scramble.c | 13 |
4 files changed, 229 insertions, 2 deletions
diff --git a/tools/Makefile b/tools/Makefile index 68fcd4b6bc..53b1200fce 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -10,17 +10,18 @@ CFLAGS := -O -ansi -g LDFLAGS := -g CLEANALL := scramble descramble iriver sh2d bmp2rb rdf2binary convbdf \ - generate_rocklatin mkboot ipod_fw codepages uclpack + generate_rocklatin mkboot ipod_fw codepages uclpack mi4 all: @echo "Run make in your build directory!" -scramble: scramble.o iriver.o +scramble: scramble.o iriver.o mi4.o descramble: descramble.o iriver.o scramble.o: scramble.c iriver.h descramble.o: descramble.c iriver.h iriver.o: iriver.c iriver.h +mi4.o: mi4.c mi4.h sh2d: sh2d.c diff --git a/tools/mi4.c b/tools/mi4.c new file mode 100644 index 0000000000..b0fff98e1c --- /dev/null +++ b/tools/mi4.c @@ -0,0 +1,188 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 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. + * + ****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * CRC32 implementation taken from: + * + * efone - Distributed internet phone system. + * + * (c) 1999,2000 Krzysztof Dabrowski + * (c) 1999,2000 ElysiuM deeZine + * + * 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. + * + */ + +/* based on implementation by Finn Yannick Jacobs */ + +#include <stdio.h> +#include <stdlib.h> + +/* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab(). + * so make sure, you call it before using the other + * functions! + */ +static unsigned int crc_tab[256]; + +/* chksum_crc() -- to a given block, this one calculates the + * crc32-checksum until the length is + * reached. the crc32-checksum will be + * the result. + */ +static unsigned int chksum_crc32 (unsigned char *block, unsigned int length) +{ + register unsigned long crc; + unsigned long i; + + crc = 0; + for (i = 0; i < length; i++) + { + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF]; + } + return (crc); +} + +/* chksum_crc32gentab() -- to a global crc_tab[256], this one will + * calculate the crcTable for crc32-checksums. + * it is generated to the polynom [..] + */ + +static void chksum_crc32gentab (void) +{ + unsigned long crc, poly; + int i, j; + + poly = 0xEDB88320L; + for (i = 0; i < 256; i++) + { + crc = i; + for (j = 8; j > 0; j--) + { + if (crc & 1) + { + crc = (crc >> 1) ^ poly; + } + else + { + crc >>= 1; + } + } + crc_tab[i] = crc; + } +} + +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 mi4_encode(char *iname, char *oname, int version) +{ + size_t len; + int length; + int mi4length; + FILE *file; + unsigned int crc = 0; + 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); + + /* Add 4 bytes to length (for magic), the 0x200 byte header and + then round to an even 0x400 bytes + */ + mi4length = (length+4+0x200+0x3ff)&~0x3ff; + + outbuf = malloc(mi4length); + + if ( !outbuf ) { + printf("out of memory!\n"); + return -1; + } + + /* Clear the buffer to zero */ + memset(outbuf, 0, mi4length); + + len = fread(outbuf+0x200, 1, length, file); + if(len < length) { + perror(iname); + return -2; + } + fclose(file); + + /* We need to write some data into the actual image - before calculating + the CRC. */ + int2le(0x00000100, &outbuf[0x2e0]); /* magic */ + int2le(0x000000ec, &outbuf[0x2e4]); /* magic */ + int2le(length+4, &outbuf[0x2e8]); /* length plus 0xaa55aa55 */ + + int2le(0xaa55aa55, &outbuf[0x200+length]); /* More Magic */ + + /* Calculate CRC32 checksum */ + chksum_crc32gentab (); + crc = chksum_crc32 (outbuf+28,mi4length-28); + + strncpy((char *)outbuf, "PPOS", 4); /* Magic */ + int2le(version, &outbuf[0x04]); /* .mi4 version */ + int2le(length+4, &outbuf[0x08]); /* Length of firmware plus magic */ + int2le(crc, &outbuf[0x0c]); /* CRC32 of mi4 file */ + int2le(0x00000002, &outbuf[0x10]); /* Encryption type: 2 = TEA */ + int2le(mi4length, &outbuf[0x14]); /* Total .mi4 length */ + int2le(mi4length-0x200, &outbuf[0x18]); /* Length of plaintext part */ + + /* v3 files require a dummy DSA signature */ + if (version == 0x00010301) { + outbuf[0x2f]=0x01; + } + + file = fopen(oname, "wb"); + if (!file) { + perror(oname); + return -3; + } + + len = fwrite(outbuf, 1, mi4length, file); + if(len < length) { + perror(oname); + return -4; + } + + fclose(file); + + fprintf(stderr, "File encoded successfully\n" ); + + return 0; +} diff --git a/tools/mi4.h b/tools/mi4.h new file mode 100644 index 0000000000..ec3a7342d0 --- /dev/null +++ b/tools/mi4.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 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 _MI4_H +#define _MI4_H + +int mi4_encode(char *iname, char *oname, int version); + +#endif diff --git a/tools/scramble.c b/tools/scramble.c index c3eb1782af..d1e3d1d341 100644 --- a/tools/scramble.c +++ b/tools/scramble.c @@ -22,6 +22,7 @@ #include <stdbool.h> #include <string.h> #include "iriver.h" +#include "mi4.h" int iaudio_encode(char *iname, char *oname, char *idstring); int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc); @@ -82,6 +83,8 @@ void usage(void) "\t-ipod3g ipod firmware partition format (3rd Gen)\n" "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n" "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n" + "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n" + "\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n" "\t-add=X Rockbox generic \"add-up\" checksum format\n" "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd\n" "\t ip3g, ip4g, mini, x5, h10, h10_5gb)\n" @@ -241,6 +244,16 @@ int main (int argc, char** argv) oname = argv[3]; return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */ } + else if(!strcmp(argv[1], "-mi4v2")) { + iname = argv[2]; + oname = argv[3]; + return mi4_encode(iname, oname, 0x00010201); + } + else if(!strcmp(argv[1], "-mi4v3")) { + iname = argv[2]; + oname = argv[3]; + return mi4_encode(iname, oname, 0x00010301); + } /* open file */ file = fopen(iname,"rb"); |