From 35735c66e00df7951df57e81792f9fdd4823d34e Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Fri, 27 Jul 2007 20:51:36 +0000 Subject: Initial attempt at a --convert option to convert HFS formatted ipods (Macpods) to FAT32 format. This needs testing (as well as the existing --format feature) before adding as an option in the interactive mode and fully documenting. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14030 a1c6a512-1295-4272-9138-f99709370657 --- rbutil/ipodpatcher/ipodio.h | 6 ++-- rbutil/ipodpatcher/ipodpatcher.c | 59 ++++++++++++++++++++++++++++++++++++++++ rbutil/ipodpatcher/ipodpatcher.h | 1 + rbutil/ipodpatcher/main.c | 45 ++++++++++++++++++++++++++---- 4 files changed, 102 insertions(+), 9 deletions(-) diff --git a/rbutil/ipodpatcher/ipodio.h b/rbutil/ipodpatcher/ipodio.h index dadb5f8ad4..a4625f7bc7 100644 --- a/rbutil/ipodpatcher/ipodio.h +++ b/rbutil/ipodpatcher/ipodio.h @@ -53,9 +53,9 @@ struct ipod_directory_t { }; struct partinfo_t { - unsigned long start; /* first sector (LBA) */ - unsigned long size; /* number of sectors */ - int type; + uint32_t start; /* first sector (LBA) */ + uint32_t size; /* number of sectors */ + uint32_t type; }; struct ipod_t { diff --git a/rbutil/ipodpatcher/ipodpatcher.c b/rbutil/ipodpatcher/ipodpatcher.c index 395fd6953d..567c5b9cce 100644 --- a/rbutil/ipodpatcher/ipodpatcher.c +++ b/rbutil/ipodpatcher/ipodpatcher.c @@ -171,6 +171,8 @@ int read_partinfo(struct ipod_t* ipod, int silent) return -1; } + memset(ipod->pinfo, 0, sizeof(ipod->pinfo)); + if ((sectorbuf[510] == 0x55) && (sectorbuf[511] == 0xaa)) { /* DOS partition table */ ipod->macpod = 0; @@ -1289,3 +1291,60 @@ int ipod_scan(struct ipod_t* ipod) } return n; } + +static void put_int32le(uint32_t x, unsigned char* p) +{ + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} + +int write_dos_partition_table(struct ipod_t* ipod) +{ + unsigned char* p; + int i, n; + uint32_t type; + + /* Only support 512-byte sectors at the moment */ + if ( ipod->sector_size != 512 ) + { + fprintf(stderr,"[ERR] Only ipods with 512 bytes per sector are supported.\n"); + return -1; + } + + /* Firstly zero the entire MBR */ + memset(sectorbuf, 0, ipod->sector_size); + + /* Now add the partition info */ + for (i=0; i < 4 ; i++) + { + p = sectorbuf + 0x1be + i*16; + + /* Ensure first partition is type 0, and second is 0xb */ + if (i==0) { type = 0; } + else if (i==1) { type = 0xb; } + else { type = ipod->pinfo[i].type; } + + put_int32le(type, p + 4); + put_int32le(ipod->pinfo[i].start, p + 8); + put_int32le(ipod->pinfo[i].size, p + 12); + } + + /* Finally add the magic */ + sectorbuf[0x1fe] = 0x55; + sectorbuf[0x1ff] = 0xaa; + + if (ipod_seek(ipod, 0) < 0) { + fprintf(stderr,"[ERR] Seek failed writing MBR\n"); + return -1; + } + + /* Write MBR */ + if ((n = ipod_write(ipod, sectorbuf, ipod->sector_size)) < 0) { + perror("[ERR] Write failed\n"); + return -1; + } + + return 0; +} diff --git a/rbutil/ipodpatcher/ipodpatcher.h b/rbutil/ipodpatcher/ipodpatcher.h index 2339687318..d816c68724 100644 --- a/rbutil/ipodpatcher/ipodpatcher.h +++ b/rbutil/ipodpatcher/ipodpatcher.h @@ -46,6 +46,7 @@ int read_directory(struct ipod_t* ipod); int list_images(struct ipod_t* ipod); int getmodel(struct ipod_t* ipod, int ipod_version); int ipod_scan(struct ipod_t* ipod); +int write_dos_partition_table(struct ipod_t* ipod); off_t filesize(int fd); #endif diff --git a/rbutil/ipodpatcher/main.c b/rbutil/ipodpatcher/main.c index a4508abf57..24938931d6 100644 --- a/rbutil/ipodpatcher/main.c +++ b/rbutil/ipodpatcher/main.c @@ -47,7 +47,8 @@ enum { WRITE_FIRMWARE, READ_PARTITION, WRITE_PARTITION, - FORMAT_PARTITION + FORMAT_PARTITION, + CONVERT_TO_FAT32 }; void print_macpod_warning(void) @@ -87,6 +88,7 @@ void print_usage(void) fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n"); fprintf(stderr," -d, --delete-bootloader\n"); fprintf(stderr," -f, --format\n"); + fprintf(stderr," -c, --convert\n"); fprintf(stderr,"\n"); #ifdef __WIN32__ @@ -118,11 +120,11 @@ void display_partinfo(struct ipod_t* ipod) if (ipod->pinfo[i].start != 0) { printf("[INFO] %d %10ld %10ld %10.1f %s (0x%02x)\n", i, - ipod->pinfo[i].start, - ipod->pinfo[i].start+ipod->pinfo[i].size-1, + (long int)ipod->pinfo[i].start, + (long int)ipod->pinfo[i].start+ipod->pinfo[i].size-1, ipod->pinfo[i].size/sectors_per_MB, get_parttype(ipod->pinfo[i].type), - ipod->pinfo[i].type); + (int)ipod->pinfo[i].type); } } } @@ -297,6 +299,10 @@ int main(int argc, char* argv[]) (strcmp(argv[i],"--format")==0)) { action = FORMAT_PARTITION; i++; + } else if ((strcmp(argv[i],"-c")==0) || + (strcmp(argv[i],"--convert")==0)) { + action = CONVERT_TO_FAT32; + i++; } else { print_usage(); return 1; } @@ -470,8 +476,9 @@ int main(int argc, char* argv[]) close(infile); } else if (action==FORMAT_PARTITION) { - printf("WARNING!!! YOU ARE ABOUT TO USE AN EXPERIMENTAL FORMATTING FEATURE.\n"); - printf("Are you sure you want to continue? (y/n):"); + printf("WARNING!!! YOU ARE ABOUT TO USE AN EXPERIMENTAL FEATURE.\n"); + printf("ALL DATA ON YOUR IPOD WILL BE ERASED.\n"); + printf("Are you sure you want to format your ipod? (y/n):"); if (fgets(yesno,4,stdin)) { if (yesno[0]=='y') { @@ -486,6 +493,32 @@ int main(int argc, char* argv[]) fprintf(stderr,"[INFO] Format cancelled.\n"); } } + } else if (action==CONVERT_TO_FAT32) { + if (!ipod.macpod) { + printf("[ERR] Ipod is already FAT32, aborting\n"); + } else { + printf("WARNING!!! YOU ARE ABOUT TO USE AN EXPERIMENTAL FEATURE.\n"); + printf("ALL DATA ON YOUR IPOD WILL BE ERASED.\n"); + printf("Are you sure you want to convert your ipod to FAT32? (y/n):"); + + if (fgets(yesno,4,stdin)) { + if (yesno[0]=='y') { + if (ipod_reopen_rw(&ipod) < 0) { + return 5; + } + + if (write_dos_partition_table(&ipod) < 0) { + fprintf(stderr,"[ERR] Partition conversion failed.\n"); + } + + if (format_partition(&ipod,1) < 0) { + fprintf(stderr,"[ERR] Format failed.\n"); + } + } else { + fprintf(stderr,"[INFO] Format cancelled.\n"); + } + } + } } ipod_close(&ipod); -- cgit v1.2.3