forked from len0rd/rockbox
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
This commit is contained in:
parent
25371a1bfd
commit
e8c588903c
3 changed files with 254 additions and 0 deletions
16
utils/ipod/flashsplit/Makefile
Normal file
16
utils/ipod/flashsplit/Makefile
Normal file
|
@ -0,0 +1,16 @@
|
|||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
# $Id$
|
||||
#
|
||||
|
||||
all: flashsplit
|
||||
|
||||
flashsplit: flashsplit.c
|
||||
gcc -W -Wall -o flashsplit flashsplit.c
|
||||
|
||||
clean:
|
||||
rm -f flashsplit
|
8
utils/ipod/flashsplit/README
Normal file
8
utils/ipod/flashsplit/README
Normal file
|
@ -0,0 +1,8 @@
|
|||
flashsplit
|
||||
----------
|
||||
|
||||
A simple utility to split a dump of the NOR flash on an ipod.
|
||||
|
||||
Should work on all PortalPlayer-based ipods.
|
||||
|
||||
See http://www.rockbox.org/wiki/IpodFlash for more information.
|
230
utils/ipod/flashsplit/flashsplit.c
Normal file
230
utils/ipod/flashsplit/flashsplit.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue