diff options
author | Dave Chapman <dave@dchapman.com> | 2009-07-13 18:39:11 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2009-07-13 18:39:11 +0000 |
commit | e8c588903c5d1128f7cb742d3467b93c415a254d (patch) | |
tree | 1b72ce145876d0bbf92c4732958543e5fb1923de /utils/ipod/flashsplit/flashsplit.c | |
parent | 25371a1bfd9598860ce34c2f257e39589e5cd34c (diff) |
Add flashsplit utility, previously hosted on the wiki at http://www.rockbox.org/wiki/IpodFlash
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21844 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/ipod/flashsplit/flashsplit.c')
-rw-r--r-- | utils/ipod/flashsplit/flashsplit.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/utils/ipod/flashsplit/flashsplit.c b/utils/ipod/flashsplit/flashsplit.c new file mode 100644 index 0000000000..c4bb3b4255 --- /dev/null +++ b/utils/ipod/flashsplit/flashsplit.c @@ -0,0 +1,230 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 Dave Chapman + * + * 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 <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> + +static void int2be(unsigned int val, unsigned char* addr) +{ + addr[0] = (val >> 24) & 0xff; + addr[1] = (val >> 16) & 0xff; + addr[2] = (val >> 8) & 0xff; + addr[3] = val & 0xFF; +} + +static int le2int(unsigned char* buf) +{ + int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + + return res; +} + +static char* get_modelname(int version) +{ + + switch (version >> 8) { + case 0x01: + return "1g2g"; + break; + case 0x02: + return "ip3g"; + break; + case 0x40: + return "mini"; + break; + case 0x50: + return "ip4g"; + break; + case 0x60: + return "ipco"; + break; + case 0x70: + return "mn2g"; + break; + case 0xc0: + return "nano"; + break; + case 0xb0: + return "ipvd"; + break; + } + + return NULL; +} + +static int get_modelnum(int version) +{ + + switch (version >> 8) { + case 0x01: + return 19; // "1g2g"; + break; + case 0x02: + return 7; // "ip3g"; + break; + case 0x40: + return 9; // "mini"; + break; + case 0x50: + return 8; // "ip4g"; + break; + case 0x60: + return 3; // "ipco"; + break; + case 0x70: + return 11; // "mn2g"; + break; + case 0xc0: + return 4; // "nano"; + break; + case 0xb0: + return 5; // "ipvd"; + break; + } + + return -1; +} + + +static void dump_app(char* name, unsigned char* p, unsigned char* flash) +{ + char filename[64]; + unsigned char header[8]; + unsigned int i; + unsigned int sum; + int outfile; + + unsigned int unknown1; + unsigned int offset; + unsigned int length; + unsigned int loadaddr; + unsigned int unknown2; + unsigned int checksum; + unsigned int version; + unsigned int unknown3; + char* modelname; + + /* Extract variables from header */ + unknown1 = le2int(p+0x08); + offset = le2int(p+0x0c); + length = le2int(p+0x10); + loadaddr = le2int(p+0x14); + unknown2 = le2int(p+0x18); + checksum = le2int(p+0x1c); + version = le2int(p+0x20); + unknown3 = le2int(p+0x24); + + modelname = get_modelname(version); + sum = 0; + + for (i = offset; i < offset+length ; i++) { + sum += flash[i]; + } + + /* Display information: */ + printf("Image: %s\n",name); + printf("unknown1: %08x\n",unknown1); + printf("offset: %08x\n",offset); + printf("length: %08x\n",length); + printf("loadaddr: %08x\n",loadaddr); + printf("unknown2: %08x\n",unknown2); + printf("checksum: %08x (flashsplit sum: %08x)\n",checksum,sum); + printf("version: %08x (ipod model: %s)\n",version,modelname); + printf("unknown3: %08x\n",unknown3); + printf("\n"); + + if (modelname == NULL) { + printf("Unknown version, not exporting to .ipod file\n"); + return; + } else if (checksum != sum) { + printf("Checksum mismatch, not exporting to .ipod file\n"); + } else { + sum += get_modelnum(version); + int2be(sum,header); + memcpy(header+4,modelname,4); + + sprintf(filename,"%s.ipod",name); + outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY,0666); + if (outfile < 0) { + fprintf(stderr,"[ERR] Couldn't open file %s\n",filename); + return; + } + + write(outfile,header,8); + write(outfile,flash+offset,length); + close(outfile); + } + + sprintf(filename,"%s.bin",name); + outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY,0666); + if (outfile < 0) { + fprintf(stderr,"[ERR] Couldn't open file %s\n",filename); + return; + } + + write(outfile,flash+offset,length); + close(outfile); +} + +int main(int argc,char* argv[]) +{ + int fd; + unsigned char buf[1024*1024]; + unsigned char* p; + + if (argc != 2) { + fprintf(stderr,"Usage: flashsplit flash.bin\n"); + return 1; + } + + fd=open(argv[1],O_RDONLY); + if (fd < 0) { + fprintf(stderr,"Can not open %s\n",argv[1]); + return 1; + } + + read(fd,buf,sizeof(buf)); + close(fd); + + + p = buf + 0xffe00; /* Start of flash directory */ + + while (le2int(p) != 0) { + if (memcmp(p,"hslfksid",8)==0) { + dump_app("diskmode",p,buf); + } else if (memcmp(p,"hslfgaid",8)==0) { + dump_app("diagmode",p,buf); + } else if (memcmp(p,"hslfogol",8)==0) { + dump_app("logo",p,buf); + } else if (memcmp(p,"hslfnacs",8)==0) { + dump_app("diskscan",p,buf); + } else if (memcmp(p,"hslfscmv",8)==0) { + dump_app("vmcs",p,buf); + } else { + printf("Unknown image type - %c%c%c%c%c%c%c%c\n",p[3],p[2],p[1],p[0],p[7],p[6],p[5],p[4]); + } + p += 0x28; + } + + return 0; +} |