summaryrefslogtreecommitdiffstats
path: root/utils/ipod/flashsplit/flashsplit.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ipod/flashsplit/flashsplit.c')
-rw-r--r--utils/ipod/flashsplit/flashsplit.c230
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;
+}