diff options
-rw-r--r-- | rbutil/ipodpatcher/Makefile | 18 | ||||
-rw-r--r-- | rbutil/ipodpatcher/fat32format.c | 527 | ||||
-rw-r--r-- | rbutil/ipodpatcher/ipodio-posix.c | 43 | ||||
-rw-r--r-- | rbutil/ipodpatcher/ipodio-win32.c | 12 | ||||
-rw-r--r-- | rbutil/ipodpatcher/ipodio.h | 5 | ||||
-rw-r--r-- | rbutil/ipodpatcher/main.c | 27 |
6 files changed, 617 insertions, 15 deletions
diff --git a/rbutil/ipodpatcher/Makefile b/rbutil/ipodpatcher/Makefile index 5ed171d70f..3bbdb51eb7 100644 --- a/rbutil/ipodpatcher/Makefile +++ b/rbutil/ipodpatcher/Makefile @@ -22,25 +22,27 @@ endif NATIVECC = gcc CC = $(CROSS)gcc +SRC = main.c ipodpatcher.c fat32format.c parttypes.h + all: $(OUTPUT) -ipodpatcher: main.c ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) - gcc $(CFLAGS) -o ipodpatcher main.c ipodpatcher.c ipodio-posix.c $(BOOTSRC) +ipodpatcher: $(SRC) ipodio-posix.c $(BOOTSRC) + gcc $(CFLAGS) -o ipodpatcher $(SRC) ipodio-posix.c $(BOOTSRC) strip ipodpatcher -ipodpatcher.exe: main.c ipodpatcher.c ipodio-win32.c parttypes.h $(BOOTSRC) - $(CC) $(CFLAGS) -o ipodpatcher.exe main.c ipodpatcher.c ipodio-win32.c $(BOOTSRC) +ipodpatcher.exe: $(SRC) ipodio-win32.c $(BOOTSRC) + $(CC) $(CFLAGS) -o ipodpatcher.exe $(SRC) ipodio-win32.c $(BOOTSRC) $(CROSS)strip ipodpatcher.exe ipodpatcher-mac: ipodpatcher-i386 ipodpatcher-ppc lipo -create ipodpatcher-ppc ipodpatcher-i386 -output ipodpatcher-mac -ipodpatcher-i386: main.c ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) - gcc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -o bin/i386/program -arch i386 $(CFLAGS) -o ipodpatcher-i386 main.c ipodpatcher.c ipodio-posix.c $(BOOTSRC) +ipodpatcher-i386: $(SRC) ipodio-posix.c $(BOOTSRC) + gcc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -o bin/i386/program -arch i386 $(CFLAGS) -o ipodpatcher-i386 $(SRC) ipodio-posix.c $(BOOTSRC) strip ipodpatcher-i386 -ipodpatcher-ppc: main.c ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) - gcc -arch ppc $(CFLAGS) -o ipodpatcher-ppc main.c ipodpatcher.c ipodio-posix.c $(BOOTSRC) +ipodpatcher-ppc: $(SRC) ipodio-posix.c $(BOOTSRC) + gcc -arch ppc $(CFLAGS) -o ipodpatcher-ppc $(SRC) ipodio-posix.c $(BOOTSRC) strip ipodpatcher-ppc ipod2c: ipod2c.c diff --git a/rbutil/ipodpatcher/fat32format.c b/rbutil/ipodpatcher/fat32format.c new file mode 100644 index 0000000000..6d42379124 --- /dev/null +++ b/rbutil/ipodpatcher/fat32format.c @@ -0,0 +1,527 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * + * FAT32 formatting functions. Based on: + * + * Fat32 formatter version 1.03 + * (c) Tom Thornhill 2005 + * This software is covered by the GPL. + * By using this tool, you agree to absolve Ridgecrop of an liabilities for + * lost data. + * Please backup any data you value before using this tool. + * + * + * Modified June 2007 by Dave Chapman for use in ipodpatcher + * + * + * 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> +#include <stdbool.h> +#include <stdint.h> + +#include "ipodio.h" + +static inline uint16_t swap16(uint16_t value) +{ + return (value >> 8) | (value << 8); +} + +static inline uint32_t swap32(uint32_t value) +{ + uint32_t hi = swap16(value >> 16); + uint32_t lo = swap16(value & 0xffff); + return (lo << 16) | hi; +} + +/* The following functions are not the most efficient, but are + self-contained and don't require needing to know endianness of CPU + at compile-time. +*/ + +uint16_t htole16(uint16_t x) +{ + uint16_t test = 0x1234; + unsigned char* p = (unsigned char*)&test; + + if (p[0]==0x12) { + /* Big-endian */ + return swap16(x); + } else { + return x; + } +} + +uint32_t htole32(uint32_t x) +{ + uint32_t test = 0x12345678; + unsigned char* p = (unsigned char*)&test; + + if (p[0]==0x12) { + /* Big-endian */ + return swap32(x); + } else { + return x; + } +} + + +/* A large aligned buffer for disk I/O */ +extern unsigned char* sectorbuf; + +/* TODO: Pass these as parameters to the various create_ functions */ + +/* can be zero for default or 1,2,4,8,16,32 or 64 */ +static int sectors_per_cluster = 0; + +/* Recommended values */ +static uint32_t ReservedSectCount = 32; +static uint32_t NumFATs = 2; +static uint32_t BackupBootSect = 6; +static uint32_t VolumeId=0; /* calculated before format */ + +/* Calculated later */ +static uint32_t FatSize=0; +static uint32_t BytesPerSect=0; +static uint32_t SectorsPerCluster=0; +static uint32_t TotalSectors=0; +static uint32_t SystemAreaSize=0; +static uint32_t UserAreaSize=0; +static uint8_t VolId[12] = "NO NAME "; + + +struct FAT_BOOTSECTOR32 +{ + /* Common fields. */ + uint8_t sJmpBoot[3]; + char sOEMName[8]; + uint16_t wBytsPerSec; + uint8_t bSecPerClus; + uint16_t wRsvdSecCnt; + uint8_t bNumFATs; + uint16_t wRootEntCnt; + uint16_t wTotSec16; /* if zero, use dTotSec32 instead */ + uint8_t bMedia; + uint16_t wFATSz16; + uint16_t wSecPerTrk; + uint16_t wNumHeads; + uint32_t dHiddSec; + uint32_t dTotSec32; + + /* Fat 32/16 only */ + uint32_t dFATSz32; + uint16_t wExtFlags; + uint16_t wFSVer; + uint32_t dRootClus; + uint16_t wFSInfo; + uint16_t wBkBootSec; + uint8_t Reserved[12]; + uint8_t bDrvNum; + uint8_t Reserved1; + uint8_t bBootSig; /* == 0x29 if next three fields are ok */ + uint32_t dBS_VolID; + uint8_t sVolLab[11]; + uint8_t sBS_FilSysType[8]; +} __attribute__((packed)); + +struct FAT_FSINFO { + uint32_t dLeadSig; // 0x41615252 + uint8_t sReserved1[480]; // zeros + uint32_t dStrucSig; // 0x61417272 + uint32_t dFree_Count; // 0xFFFFFFFF + uint32_t dNxt_Free; // 0xFFFFFFFF + uint8_t sReserved2[12]; // zeros + uint32_t dTrailSig; // 0xAA550000 +} __attribute__((packed)); + + +/* Write "count" zero sectors, starting at sector "sector" */ +static int zero_sectors(struct ipod_t* ipod, uint64_t sector, int count) +{ + int n; + + if (ipod_seek(ipod, sector * ipod->sector_size) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + + memset(sectorbuf, 0, 128 * ipod->sector_size); + + /* Write 128 sectors at a time */ + while (count) { + if (count >= 128) + n = 128; + else + n = count; + + if (ipod_write(ipod,sectorbuf,n * ipod->sector_size) < 0) { + perror("[ERR] Write failed in zero_sectors\n"); + return -1; + } + + count -= n; + } + + return 0; +} + + +/* +28.2 CALCULATING THE VOLUME SERIAL NUMBER + +For example, say a disk was formatted on 26 Dec 95 at 9:55 PM and 41.94 +seconds. DOS takes the date and time just before it writes it to the +disk. + +Low order word is calculated: Volume Serial Number is: + Month & Day 12/26 0c1ah + Sec & Hundrenths 41:94 295eh 3578:1d02 + ----- + 3578h + +High order word is calculated: + Hours & Minutes 21:55 1537h + Year 1995 07cbh + ----- + 1d02h +*/ +static uint32_t get_volume_id ( ) +{ + /* TODO */ +#if 0 + SYSTEMTIME s; + uint32_t d; + uint16_t lo,hi,tmp; + + GetLocalTime( &s ); + + lo = s.wDay + ( s.wMonth << 8 ); + tmp = (s.wMilliseconds/10) + (s.wSecond << 8 ); + lo += tmp; + + hi = s.wMinute + ( s.wHour << 8 ); + hi += s.wYear; + + d = lo + (hi << 16); + return(d); +#endif + return(0); +} + +/* +This is the Microsoft calculation from FATGEN + + uint32_t RootDirSectors = 0; + uint32_t TmpVal1, TmpVal2, FATSz; + + TmpVal1 = DskSize - ( ReservedSecCnt + RootDirSectors); + TmpVal2 = (256 * SecPerClus) + NumFATs; + TmpVal2 = TmpVal2 / 2; + FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2; + + return( FatSz ); +*/ + + +static uint32_t get_fat_size_sectors(uint32_t DskSize, uint32_t ReservedSecCnt, + uint32_t SecPerClus, uint32_t NumFATs, + uint32_t BytesPerSect) +{ + uint64_t Numerator, Denominator; + uint64_t FatElementSize = 4; + uint64_t FatSz; + + /* This is based on + http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html + I've made the obvious changes for FAT32 + */ + + Numerator = FatElementSize * ( DskSize - ReservedSecCnt ); + Denominator = ( SecPerClus * BytesPerSect ) + ( FatElementSize * NumFATs ); + FatSz = Numerator / Denominator; + + /* round up */ + FatSz += 1; + + return((uint32_t)FatSz); +} + +static uint8_t get_spc(uint32_t ClusterSizeKB, uint32_t BytesPerSect) +{ + uint32_t spc = ( ClusterSizeKB * 1024 ) / BytesPerSect; + return( (uint8_t) spc ); +} + +static uint8_t get_sectors_per_cluster(uint32_t DiskSizeSectors, + uint32_t BytesPerSect) +{ + uint8_t ret = 0x01; /* 1 sector per cluster */ + uint64_t DiskSizeBytes = (uint64_t)DiskSizeSectors * (uint64_t)BytesPerSect; + int64_t DiskSizeMB = DiskSizeBytes / ( 1024*1024 ); + + /* 512 MB to 8,191 MB 4 KB */ + if ( DiskSizeMB > 512 ) + ret = get_spc( 4, BytesPerSect ); /* ret = 0x8; */ + + /* 8,192 MB to 16,383 MB 8 KB */ + if ( DiskSizeMB > 8192 ) + ret = get_spc( 8, BytesPerSect ); /* ret = 0x10; */ + + /* 16,384 MB to 32,767 MB 16 KB */ + if ( DiskSizeMB > 16384 ) + ret = get_spc( 16, BytesPerSect ); /* ret = 0x20; */ + + /* Larger than 32,768 MB 32 KB */ + if ( DiskSizeMB > 32768 ) + ret = get_spc( 32, BytesPerSect ); /* ret = 0x40; */ + + return( ret ); + +} + +static void create_boot_sector(unsigned char* buf, + struct ipod_t* ipod, int partition) +{ + struct FAT_BOOTSECTOR32* pFAT32BootSect = (struct FAT_BOOTSECTOR32*)buf; + + /* fill out the boot sector and fs info */ + pFAT32BootSect->sJmpBoot[0]=0xEB; + pFAT32BootSect->sJmpBoot[1]=0x5A; + pFAT32BootSect->sJmpBoot[2]=0x90; + strcpy( pFAT32BootSect->sOEMName, "MSWIN4.1" ); + pFAT32BootSect->wBytsPerSec = htole16(BytesPerSect); + pFAT32BootSect->bSecPerClus = SectorsPerCluster ; + pFAT32BootSect->wRsvdSecCnt = htole16(ReservedSectCount); + pFAT32BootSect->bNumFATs = NumFATs; + pFAT32BootSect->wRootEntCnt = htole16(0); + pFAT32BootSect->wTotSec16 = htole16(0); + pFAT32BootSect->bMedia = 0xF8; + pFAT32BootSect->wFATSz16 = htole16(0); + pFAT32BootSect->wSecPerTrk = htole16(ipod->sectors_per_track); + pFAT32BootSect->wNumHeads = htole16(ipod->num_heads); + pFAT32BootSect->dHiddSec = htole16(ipod->pinfo[partition].start); + pFAT32BootSect->dTotSec32 = htole32(TotalSectors); + pFAT32BootSect->dFATSz32 = htole32(FatSize); + pFAT32BootSect->wExtFlags = htole16(0); + pFAT32BootSect->wFSVer = htole16(0); + pFAT32BootSect->dRootClus = htole32(2); + pFAT32BootSect->wFSInfo = htole16(1); + pFAT32BootSect->wBkBootSec = htole16(BackupBootSect); + pFAT32BootSect->bDrvNum = 0x80; + pFAT32BootSect->Reserved1 = 0; + pFAT32BootSect->bBootSig = 0x29; + pFAT32BootSect->dBS_VolID = htole32(VolumeId); + memcpy(pFAT32BootSect->sVolLab, VolId, 11); + memcpy(pFAT32BootSect->sBS_FilSysType, "FAT32 ", 8 ); + + buf[510] = 0x55; + buf[511] = 0xaa; +} + +static void create_fsinfo(unsigned char* buf, + struct ipod_t* ipod, int partition) +{ + struct FAT_FSINFO* pFAT32FsInfo = (struct FAT_FSINFO*)buf; + + /* FSInfo sect */ + pFAT32FsInfo->dLeadSig = htole32(0x41615252); + pFAT32FsInfo->dStrucSig = htole32(0x61417272); + pFAT32FsInfo->dFree_Count = htole32((uint32_t) -1); + pFAT32FsInfo->dNxt_Free = htole32((uint32_t) -1); + pFAT32FsInfo->dTrailSig = htole32(0xaa550000); + pFAT32FsInfo->dFree_Count = htole32((UserAreaSize/SectorsPerCluster)-1); + + /* clusters 0-1 reserved, we used cluster 2 for the root dir */ + pFAT32FsInfo->dNxt_Free = htole32(3); +} + +static void create_firstfatsector(unsigned char* buf, + struct ipod_t* ipod, int partition) +{ + uint32_t* p = (uint32_t*)buf; /* We know the buffer is aligned */ + + /* First FAT Sector */ + p[0] = htole32(0x0ffffff8); /* Reserved cluster 1 media id in low byte */ + p[1] = htole32(0x0fffffff); /* Reserved cluster 2 EOC */ + p[2] = htole32(0x0fffffff); /* end of cluster chain for root dir */ +} + +int format_partition(struct ipod_t* ipod, int partition) +{ + uint32_t i; + uint64_t qTotalSectors=0; + uint64_t FatNeeded; + + VolumeId = get_volume_id( ); + + /* Only support hard disks at the moment */ + if ( ipod->sector_size != 512 ) + { + fprintf(stderr,"[ERR] Only disks with 512 bytes per sector are supported.\n"); + return -1; + } + BytesPerSect = ipod->sector_size; + + /* Checks on Disk Size */ + qTotalSectors = ipod->pinfo[partition].size; + + /* low end limit - 65536 sectors */ + if ( qTotalSectors < 65536 ) + { + /* I suspect that most FAT32 implementations would mount this + volume just fine, but the spec says that we shouldn't do + this, so we won't */ + + fprintf(stderr,"[ERR] This drive is too small for FAT32 - there must be at least 64K clusters\n" ); + return -1; + } + + if ( qTotalSectors >= 0xffffffff ) + { + /* This is a more fundamental limitation on FAT32 - the total + sector count in the root dir s 32bit. With a bit of + creativity, FAT32 could be extended to handle at least 2^28 + clusters There would need to be an extra field in the + FSInfo sector, and the old sector count could be set to + 0xffffffff. This is non standard though, the Windows FAT + driver FASTFAT.SYS won't understand this. Perhaps a future + version of FAT32 and FASTFAT will handle this. */ + + fprintf(stderr,"[ERR] This drive is too big for FAT32 - max 2TB supported\n"); + } + + if ( sectors_per_cluster ) { + SectorsPerCluster = sectors_per_cluster; + } else { + SectorsPerCluster = get_sectors_per_cluster(ipod->pinfo[partition].size, + BytesPerSect ); + } + + TotalSectors = (uint32_t) qTotalSectors; + + FatSize = get_fat_size_sectors(TotalSectors, ReservedSectCount, + SectorsPerCluster, NumFATs, BytesPerSect ); + + UserAreaSize = TotalSectors - ReservedSectCount - (NumFATs*FatSize); + + /* First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster */ + SystemAreaSize = (ReservedSectCount+(NumFATs*FatSize) + SectorsPerCluster); + + /* Work out the Cluster count */ + FatNeeded = UserAreaSize/SectorsPerCluster; + + /* check for a cluster count of >2^28, since the upper 4 bits of + the cluster values in the FAT are reserved. */ + if (FatNeeded > 0x0FFFFFFF) { + fprintf(stderr,"[ERR] This drive has more than 2^28 clusters, try to specify a larger cluster size\n" ); + return -1; + } + + /* Sanity check, make sure the fat is big enough. + Convert the cluster count into a Fat sector count, and check + the fat size value we calculated earlier is OK. */ + + FatNeeded *=4; + FatNeeded += (BytesPerSect-1); + FatNeeded /= BytesPerSect; + + if ( FatNeeded > FatSize ) { + fprintf(stderr,"[ERR] Drive too big to format\n"); + return -1; + } + + /* + Write boot sector, fats + Sector 0 Boot Sector + Sector 1 FSInfo + Sector 2 More boot code - we write zeros here + Sector 3 unused + Sector 4 unused + Sector 5 unused + Sector 6 Backup boot sector + Sector 7 Backup FSInfo sector + Sector 8 Backup 'more boot code' + zero'd sectors upto ReservedSectCount + FAT1 ReservedSectCount to ReservedSectCount + FatSize + ... + FATn ReservedSectCount to ReservedSectCount + FatSize + RootDir - allocated to cluster2 + */ + + fprintf(stderr,"[INFO] Heads - %d, sectors/track = %d\n",ipod->num_heads,ipod->sectors_per_track); + fprintf(stderr,"[INFO] Size : %lluGB %u sectors\n", ((uint64_t)ipod->pinfo[partition].size * (uint64_t)ipod->sector_size) / (1000*1000*1000), TotalSectors ); + fprintf(stderr,"[INFO] %d Bytes Per Sector, Cluster size %d bytes\n", BytesPerSect, SectorsPerCluster*BytesPerSect ); + fprintf(stderr,"[INFO] Volume ID is %x:%x\n", VolumeId>>16, VolumeId&0xffff ); + fprintf(stderr,"[INFO] %d Reserved Sectors, %d Sectors per FAT, %d fats\n", ReservedSectCount, FatSize, NumFATs ); + fprintf (stderr,"[INFO] %d Total clusters\n", UserAreaSize/SectorsPerCluster ); + + fprintf(stderr,"[INFO] Formatting partition %d:...\n",partition); + + /* Once zero_sectors has run, any data on the drive is basically lost... */ + fprintf(stderr,"[INFO] Clearing out %d sectors for Reserved sectors, fats and root cluster...\n", SystemAreaSize ); + + zero_sectors(ipod, ipod->pinfo[partition].start, SystemAreaSize); + + fprintf(stderr,"[INFO] Initialising reserved sectors and FATs...\n" ); + + /* Create the boot sector structure */ + create_boot_sector(sectorbuf, ipod, partition); + create_fsinfo(sectorbuf + 512, ipod, partition); + + /* Write boot sector and fsinfo at start of partition */ + if (ipod_seek(ipod, ipod->pinfo[partition].start * ipod->sector_size) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + if (ipod_write(ipod,sectorbuf,512 * 2) < 0) { + perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n"); + return -1; + } + + /* Write backup copy of boot sector and fsinfo */ + if (ipod_seek(ipod, (ipod->pinfo[partition].start + BackupBootSect) * ipod->sector_size) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + if (ipod_write(ipod,sectorbuf,512 * 2) < 0) { + perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n"); + return -1; + } + + /* Create the first FAT sector */ + create_firstfatsector(sectorbuf, ipod, partition); + + /* Write the first fat sector in the right places */ + for ( i=0; i<NumFATs; i++ ) { + int SectorStart = ReservedSectCount + (i * FatSize ); + + if (ipod_seek(ipod, (ipod->pinfo[partition].start + SectorStart) * ipod->sector_size) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + + if (ipod_write(ipod,sectorbuf,512) < 0) { + perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n"); + return -1; + } + } + + fprintf(stderr,"[INFO] Format successful\n"); + + return 0; +} diff --git a/rbutil/ipodpatcher/ipodio-posix.c b/rbutil/ipodpatcher/ipodio-posix.c index 365bc27291..78c2dbf852 100644 --- a/rbutil/ipodpatcher/ipodio-posix.c +++ b/rbutil/ipodpatcher/ipodio-posix.c @@ -26,22 +26,56 @@ #include <sys/stat.h> #include <sys/ioctl.h> +#include "ipodio.h" + #if defined(linux) || defined (__linux) #include <sys/mount.h> +#include <linux/hdreg.h> #define IPOD_SECTORSIZE_IOCTL BLKSSZGET + +static void get_geometry(struct ipod_t* ipod) +{ + struct hd_geometry geometry; + + if (!ioctl(ipod->dh, HDIO_GETGEO, &geometry)) { + /* never use geometry.cylinders - it is truncated */ + ipod->num_heads = geometry.heads; + ipod->sectors_per_track = geometry.sectors; + } else { + ipod->num_heads = 0; + ipod->sectors_per_track = 0; + } +} + #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(__bsdi__) || defined(__DragonFly__) #include <sys/disk.h> #define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE + +/* TODO: Implement this function for BSD */ +static void get_geometry(struct ipod_t* ipod) +{ + /* Are these universal for all ipods? */ + ipod->num_heads = 255; + ipod->sectors_per_track = 63; +} + #elif defined(__APPLE__) && defined(__MACH__) #include <sys/disk.h> #define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE + +/* TODO: Implement this function for Mac OS X */ +static void get_geometry(struct ipod_t* ipod) +{ + /* Are these universal for all ipods? */ + ipod->num_heads = 255; + ipod->sectors_per_track = 63; +} + #else #error No sector-size detection implemented for this platform #endif -#include "ipodio.h" - void print_error(char* msg) { perror(msg); @@ -55,6 +89,8 @@ int ipod_open(struct ipod_t* ipod, int silent) return -1; } + /* Read information about the disk */ + if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) { ipod->sector_size=512; if (!silent) { @@ -62,6 +98,9 @@ int ipod_open(struct ipod_t* ipod, int silent) ,ipod->sector_size); } } + + get_geometry(ipod); + return 0; } diff --git a/rbutil/ipodpatcher/ipodio-win32.c b/rbutil/ipodpatcher/ipodio-win32.c index 83f00b8cd9..342a06a358 100644 --- a/rbutil/ipodpatcher/ipodio-win32.c +++ b/rbutil/ipodpatcher/ipodio-win32.c @@ -86,6 +86,10 @@ int ipod_open(struct ipod_t* ipod, int silent) return -1; } + /* Defaults */ + ipod->num_heads = 0; + ipod->sectors_per_track = 0; + if (!DeviceIoControl(ipod->dh, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, @@ -105,10 +109,14 @@ int ipod_open(struct ipod_t* ipod, int silent) if (!silent) print_error(" Error reading disk geometry: "); return -1; } else { - ipod->sector_size=diskgeometry.BytesPerSector; + ipod->sector_size = diskgeometry.BytesPerSector; + ipod->num_heads = diskgeometry.TracksPerCylinder; + ipod->sectors_per_track = diskgeometry.SectorsPerTrack; } } else { - ipod->sector_size=diskgeometry_ex.Geometry.BytesPerSector; + ipod->sector_size = diskgeometry_ex.Geometry.BytesPerSector; + ipod->num_heads = diskgeometry_ex.Geometry.TracksPerCylinder; + ipod->sectors_per_track = diskgeometry_ex.Geometry.SectorsPerTrack; } return 0; diff --git a/rbutil/ipodpatcher/ipodio.h b/rbutil/ipodpatcher/ipodio.h index f2aba267d8..dadb5f8ad4 100644 --- a/rbutil/ipodpatcher/ipodio.h +++ b/rbutil/ipodpatcher/ipodio.h @@ -62,6 +62,8 @@ struct ipod_t { HANDLE dh; char diskname[4096]; int sector_size; + int sectors_per_track; + int num_heads; struct ipod_directory_t ipod_directory[MAX_IMAGES]; int nimages; off_t diroffset; @@ -88,4 +90,7 @@ int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes); int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes); int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize); +/* In fat32format.c */ +int format_partition(struct ipod_t* ipod, int partition); + #endif diff --git a/rbutil/ipodpatcher/main.c b/rbutil/ipodpatcher/main.c index 0983af768f..a4508abf57 100644 --- a/rbutil/ipodpatcher/main.c +++ b/rbutil/ipodpatcher/main.c @@ -46,7 +46,8 @@ enum { READ_FIRMWARE, WRITE_FIRMWARE, READ_PARTITION, - WRITE_PARTITION + WRITE_PARTITION, + FORMAT_PARTITION }; void print_macpod_warning(void) @@ -85,6 +86,7 @@ void print_usage(void) fprintf(stderr," -a, --add-bootloader filename.ipod\n"); fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n"); fprintf(stderr," -d, --delete-bootloader\n"); + fprintf(stderr," -f, --format\n"); fprintf(stderr,"\n"); #ifdef __WIN32__ @@ -128,9 +130,7 @@ void display_partinfo(struct ipod_t* ipod) int main(int argc, char* argv[]) { -#ifdef WITH_BOOTOBJS char yesno[4]; -#endif int i; int n; int infile, outfile; @@ -293,6 +293,10 @@ int main(int argc, char* argv[]) (strcmp(argv[i],"--verbose")==0)) { verbose++; i++; + } else if ((strcmp(argv[i],"-f")==0) || + (strcmp(argv[i],"--format")==0)) { + action = FORMAT_PARTITION; + i++; } else { print_usage(); return 1; } @@ -465,6 +469,23 @@ 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):"); + + if (fgets(yesno,4,stdin)) { + if (yesno[0]=='y') { + if (ipod_reopen_rw(&ipod) < 0) { + return 5; + } + + if (format_partition(&ipod,1) < 0) { + fprintf(stderr,"[ERR] Format failed.\n"); + } + } else { + fprintf(stderr,"[INFO] Format cancelled.\n"); + } + } } ipod_close(&ipod); |