summaryrefslogtreecommitdiff
path: root/rbutil
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil')
-rw-r--r--rbutil/ipodpatcher/Makefile18
-rw-r--r--rbutil/ipodpatcher/fat32format.c527
-rw-r--r--rbutil/ipodpatcher/ipodio-posix.c43
-rw-r--r--rbutil/ipodpatcher/ipodio-win32.c12
-rw-r--r--rbutil/ipodpatcher/ipodio.h5
-rw-r--r--rbutil/ipodpatcher/main.c27
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
22NATIVECC = gcc 22NATIVECC = gcc
23CC = $(CROSS)gcc 23CC = $(CROSS)gcc
24 24
25SRC = main.c ipodpatcher.c fat32format.c parttypes.h
26
25all: $(OUTPUT) 27all: $(OUTPUT)
26 28
27ipodpatcher: main.c ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) 29ipodpatcher: $(SRC) ipodio-posix.c $(BOOTSRC)
28 gcc $(CFLAGS) -o ipodpatcher main.c ipodpatcher.c ipodio-posix.c $(BOOTSRC) 30 gcc $(CFLAGS) -o ipodpatcher $(SRC) ipodio-posix.c $(BOOTSRC)
29 strip ipodpatcher 31 strip ipodpatcher
30 32
31ipodpatcher.exe: main.c ipodpatcher.c ipodio-win32.c parttypes.h $(BOOTSRC) 33ipodpatcher.exe: $(SRC) ipodio-win32.c $(BOOTSRC)
32 $(CC) $(CFLAGS) -o ipodpatcher.exe main.c ipodpatcher.c ipodio-win32.c $(BOOTSRC) 34 $(CC) $(CFLAGS) -o ipodpatcher.exe $(SRC) ipodio-win32.c $(BOOTSRC)
33 $(CROSS)strip ipodpatcher.exe 35 $(CROSS)strip ipodpatcher.exe
34 36
35ipodpatcher-mac: ipodpatcher-i386 ipodpatcher-ppc 37ipodpatcher-mac: ipodpatcher-i386 ipodpatcher-ppc
36 lipo -create ipodpatcher-ppc ipodpatcher-i386 -output ipodpatcher-mac 38 lipo -create ipodpatcher-ppc ipodpatcher-i386 -output ipodpatcher-mac
37 39
38ipodpatcher-i386: main.c ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) 40ipodpatcher-i386: $(SRC) ipodio-posix.c $(BOOTSRC)
39 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) 41 gcc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -o bin/i386/program -arch i386 $(CFLAGS) -o ipodpatcher-i386 $(SRC) ipodio-posix.c $(BOOTSRC)
40 strip ipodpatcher-i386 42 strip ipodpatcher-i386
41 43
42ipodpatcher-ppc: main.c ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) 44ipodpatcher-ppc: $(SRC) ipodio-posix.c $(BOOTSRC)
43 gcc -arch ppc $(CFLAGS) -o ipodpatcher-ppc main.c ipodpatcher.c ipodio-posix.c $(BOOTSRC) 45 gcc -arch ppc $(CFLAGS) -o ipodpatcher-ppc $(SRC) ipodio-posix.c $(BOOTSRC)
44 strip ipodpatcher-ppc 46 strip ipodpatcher-ppc
45 47
46ipod2c: ipod2c.c 48ipod2c: 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 *
11 * FAT32 formatting functions. Based on:
12 *
13 * Fat32 formatter version 1.03
14 * (c) Tom Thornhill 2005
15 * This software is covered by the GPL.
16 * By using this tool, you agree to absolve Ridgecrop of an liabilities for
17 * lost data.
18 * Please backup any data you value before using this tool.
19 *
20 *
21 * Modified June 2007 by Dave Chapman for use in ipodpatcher
22 *
23 *
24 * All files in this archive are subject to the GNU General Public License.
25 * See the file COPYING in the source tree root for full license agreement.
26 *
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
28 * KIND, either express or implied.
29 *
30 ****************************************************************************/
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <stdbool.h>
36#include <stdint.h>
37
38#include "ipodio.h"
39
40static inline uint16_t swap16(uint16_t value)
41{
42 return (value >> 8) | (value << 8);
43}
44
45static inline uint32_t swap32(uint32_t value)
46{
47 uint32_t hi = swap16(value >> 16);
48 uint32_t lo = swap16(value & 0xffff);
49 return (lo << 16) | hi;
50}
51
52/* The following functions are not the most efficient, but are
53 self-contained and don't require needing to know endianness of CPU
54 at compile-time.
55*/
56
57uint16_t htole16(uint16_t x)
58{
59 uint16_t test = 0x1234;
60 unsigned char* p = (unsigned char*)&test;
61
62 if (p[0]==0x12) {
63 /* Big-endian */
64 return swap16(x);
65 } else {
66 return x;
67 }
68}
69
70uint32_t htole32(uint32_t x)
71{
72 uint32_t test = 0x12345678;
73 unsigned char* p = (unsigned char*)&test;
74
75 if (p[0]==0x12) {
76 /* Big-endian */
77 return swap32(x);
78 } else {
79 return x;
80 }
81}
82
83
84/* A large aligned buffer for disk I/O */
85extern unsigned char* sectorbuf;
86
87/* TODO: Pass these as parameters to the various create_ functions */
88
89/* can be zero for default or 1,2,4,8,16,32 or 64 */
90static int sectors_per_cluster = 0;
91
92/* Recommended values */
93static uint32_t ReservedSectCount = 32;
94static uint32_t NumFATs = 2;
95static uint32_t BackupBootSect = 6;
96static uint32_t VolumeId=0; /* calculated before format */
97
98/* Calculated later */
99static uint32_t FatSize=0;
100static uint32_t BytesPerSect=0;
101static uint32_t SectorsPerCluster=0;
102static uint32_t TotalSectors=0;
103static uint32_t SystemAreaSize=0;
104static uint32_t UserAreaSize=0;
105static uint8_t VolId[12] = "NO NAME ";
106
107
108struct FAT_BOOTSECTOR32
109{
110 /* Common fields. */
111 uint8_t sJmpBoot[3];
112 char sOEMName[8];
113 uint16_t wBytsPerSec;
114 uint8_t bSecPerClus;
115 uint16_t wRsvdSecCnt;
116 uint8_t bNumFATs;
117 uint16_t wRootEntCnt;
118 uint16_t wTotSec16; /* if zero, use dTotSec32 instead */
119 uint8_t bMedia;
120 uint16_t wFATSz16;
121 uint16_t wSecPerTrk;
122 uint16_t wNumHeads;
123 uint32_t dHiddSec;
124 uint32_t dTotSec32;
125
126 /* Fat 32/16 only */
127 uint32_t dFATSz32;
128 uint16_t wExtFlags;
129 uint16_t wFSVer;
130 uint32_t dRootClus;
131 uint16_t wFSInfo;
132 uint16_t wBkBootSec;
133 uint8_t Reserved[12];
134 uint8_t bDrvNum;
135 uint8_t Reserved1;
136 uint8_t bBootSig; /* == 0x29 if next three fields are ok */
137 uint32_t dBS_VolID;
138 uint8_t sVolLab[11];
139 uint8_t sBS_FilSysType[8];
140} __attribute__((packed));
141
142struct FAT_FSINFO {
143 uint32_t dLeadSig; // 0x41615252
144 uint8_t sReserved1[480]; // zeros
145 uint32_t dStrucSig; // 0x61417272
146 uint32_t dFree_Count; // 0xFFFFFFFF
147 uint32_t dNxt_Free; // 0xFFFFFFFF
148 uint8_t sReserved2[12]; // zeros
149 uint32_t dTrailSig; // 0xAA550000
150} __attribute__((packed));
151
152
153/* Write "count" zero sectors, starting at sector "sector" */
154static int zero_sectors(struct ipod_t* ipod, uint64_t sector, int count)
155{
156 int n;
157
158 if (ipod_seek(ipod, sector * ipod->sector_size) < 0) {
159 fprintf(stderr,"[ERR] Seek failed\n");
160 return -1;
161 }
162
163 memset(sectorbuf, 0, 128 * ipod->sector_size);
164
165 /* Write 128 sectors at a time */
166 while (count) {
167 if (count >= 128)
168 n = 128;
169 else
170 n = count;
171
172 if (ipod_write(ipod,sectorbuf,n * ipod->sector_size) < 0) {
173 perror("[ERR] Write failed in zero_sectors\n");
174 return -1;
175 }
176
177 count -= n;
178 }
179
180 return 0;
181}
182
183
184/*
18528.2 CALCULATING THE VOLUME SERIAL NUMBER
186
187For example, say a disk was formatted on 26 Dec 95 at 9:55 PM and 41.94
188seconds. DOS takes the date and time just before it writes it to the
189disk.
190
191Low order word is calculated: Volume Serial Number is:
192 Month & Day 12/26 0c1ah
193 Sec & Hundrenths 41:94 295eh 3578:1d02
194 -----
195 3578h
196
197High order word is calculated:
198 Hours & Minutes 21:55 1537h
199 Year 1995 07cbh
200 -----
201 1d02h
202*/
203static uint32_t get_volume_id ( )
204{
205 /* TODO */
206#if 0
207 SYSTEMTIME s;
208 uint32_t d;
209 uint16_t lo,hi,tmp;
210
211 GetLocalTime( &s );
212
213 lo = s.wDay + ( s.wMonth << 8 );
214 tmp = (s.wMilliseconds/10) + (s.wSecond << 8 );
215 lo += tmp;
216
217 hi = s.wMinute + ( s.wHour << 8 );
218 hi += s.wYear;
219
220 d = lo + (hi << 16);
221 return(d);
222#endif
223 return(0);
224}
225
226/*
227This is the Microsoft calculation from FATGEN
228
229 uint32_t RootDirSectors = 0;
230 uint32_t TmpVal1, TmpVal2, FATSz;
231
232 TmpVal1 = DskSize - ( ReservedSecCnt + RootDirSectors);
233 TmpVal2 = (256 * SecPerClus) + NumFATs;
234 TmpVal2 = TmpVal2 / 2;
235 FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
236
237 return( FatSz );
238*/
239
240
241static uint32_t get_fat_size_sectors(uint32_t DskSize, uint32_t ReservedSecCnt,
242 uint32_t SecPerClus, uint32_t NumFATs,
243 uint32_t BytesPerSect)
244{
245 uint64_t Numerator, Denominator;
246 uint64_t FatElementSize = 4;
247 uint64_t FatSz;
248
249 /* This is based on
250 http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html
251 I've made the obvious changes for FAT32
252 */
253
254 Numerator = FatElementSize * ( DskSize - ReservedSecCnt );
255 Denominator = ( SecPerClus * BytesPerSect ) + ( FatElementSize * NumFATs );
256 FatSz = Numerator / Denominator;
257
258 /* round up */
259 FatSz += 1;
260
261 return((uint32_t)FatSz);
262}
263
264static uint8_t get_spc(uint32_t ClusterSizeKB, uint32_t BytesPerSect)
265{
266 uint32_t spc = ( ClusterSizeKB * 1024 ) / BytesPerSect;
267 return( (uint8_t) spc );
268}
269
270static uint8_t get_sectors_per_cluster(uint32_t DiskSizeSectors,
271 uint32_t BytesPerSect)
272{
273 uint8_t ret = 0x01; /* 1 sector per cluster */
274 uint64_t DiskSizeBytes = (uint64_t)DiskSizeSectors * (uint64_t)BytesPerSect;
275 int64_t DiskSizeMB = DiskSizeBytes / ( 1024*1024 );
276
277 /* 512 MB to 8,191 MB 4 KB */
278 if ( DiskSizeMB > 512 )
279 ret = get_spc( 4, BytesPerSect ); /* ret = 0x8; */
280
281 /* 8,192 MB to 16,383 MB 8 KB */
282 if ( DiskSizeMB > 8192 )
283 ret = get_spc( 8, BytesPerSect ); /* ret = 0x10; */
284
285 /* 16,384 MB to 32,767 MB 16 KB */
286 if ( DiskSizeMB > 16384 )
287 ret = get_spc( 16, BytesPerSect ); /* ret = 0x20; */
288
289 /* Larger than 32,768 MB 32 KB */
290 if ( DiskSizeMB > 32768 )
291 ret = get_spc( 32, BytesPerSect ); /* ret = 0x40; */
292
293 return( ret );
294
295}
296
297static void create_boot_sector(unsigned char* buf,
298 struct ipod_t* ipod, int partition)
299{
300 struct FAT_BOOTSECTOR32* pFAT32BootSect = (struct FAT_BOOTSECTOR32*)buf;
301
302 /* fill out the boot sector and fs info */
303 pFAT32BootSect->sJmpBoot[0]=0xEB;
304 pFAT32BootSect->sJmpBoot[1]=0x5A;
305 pFAT32BootSect->sJmpBoot[2]=0x90;
306 strcpy( pFAT32BootSect->sOEMName, "MSWIN4.1" );
307 pFAT32BootSect->wBytsPerSec = htole16(BytesPerSect);
308 pFAT32BootSect->bSecPerClus = SectorsPerCluster ;
309 pFAT32BootSect->wRsvdSecCnt = htole16(ReservedSectCount);
310 pFAT32BootSect->bNumFATs = NumFATs;
311 pFAT32BootSect->wRootEntCnt = htole16(0);
312 pFAT32BootSect->wTotSec16 = htole16(0);
313 pFAT32BootSect->bMedia = 0xF8;
314 pFAT32BootSect->wFATSz16 = htole16(0);
315 pFAT32BootSect->wSecPerTrk = htole16(ipod->sectors_per_track);
316 pFAT32BootSect->wNumHeads = htole16(ipod->num_heads);
317 pFAT32BootSect->dHiddSec = htole16(ipod->pinfo[partition].start);
318 pFAT32BootSect->dTotSec32 = htole32(TotalSectors);
319 pFAT32BootSect->dFATSz32 = htole32(FatSize);
320 pFAT32BootSect->wExtFlags = htole16(0);
321 pFAT32BootSect->wFSVer = htole16(0);
322 pFAT32BootSect->dRootClus = htole32(2);
323 pFAT32BootSect->wFSInfo = htole16(1);
324 pFAT32BootSect->wBkBootSec = htole16(BackupBootSect);
325 pFAT32BootSect->bDrvNum = 0x80;
326 pFAT32BootSect->Reserved1 = 0;
327 pFAT32BootSect->bBootSig = 0x29;
328 pFAT32BootSect->dBS_VolID = htole32(VolumeId);
329 memcpy(pFAT32BootSect->sVolLab, VolId, 11);
330 memcpy(pFAT32BootSect->sBS_FilSysType, "FAT32 ", 8 );
331
332 buf[510] = 0x55;
333 buf[511] = 0xaa;
334}
335
336static void create_fsinfo(unsigned char* buf,
337 struct ipod_t* ipod, int partition)
338{
339 struct FAT_FSINFO* pFAT32FsInfo = (struct FAT_FSINFO*)buf;
340
341 /* FSInfo sect */
342 pFAT32FsInfo->dLeadSig = htole32(0x41615252);
343 pFAT32FsInfo->dStrucSig = htole32(0x61417272);
344 pFAT32FsInfo->dFree_Count = htole32((uint32_t) -1);
345 pFAT32FsInfo->dNxt_Free = htole32((uint32_t) -1);
346 pFAT32FsInfo->dTrailSig = htole32(0xaa550000);
347 pFAT32FsInfo->dFree_Count = htole32((UserAreaSize/SectorsPerCluster)-1);
348
349 /* clusters 0-1 reserved, we used cluster 2 for the root dir */
350 pFAT32FsInfo->dNxt_Free = htole32(3);
351}
352
353static void create_firstfatsector(unsigned char* buf,
354 struct ipod_t* ipod, int partition)
355{
356 uint32_t* p = (uint32_t*)buf; /* We know the buffer is aligned */
357
358 /* First FAT Sector */
359 p[0] = htole32(0x0ffffff8); /* Reserved cluster 1 media id in low byte */
360 p[1] = htole32(0x0fffffff); /* Reserved cluster 2 EOC */
361 p[2] = htole32(0x0fffffff); /* end of cluster chain for root dir */
362}
363
364int format_partition(struct ipod_t* ipod, int partition)
365{
366 uint32_t i;
367 uint64_t qTotalSectors=0;
368 uint64_t FatNeeded;
369
370 VolumeId = get_volume_id( );
371
372 /* Only support hard disks at the moment */
373 if ( ipod->sector_size != 512 )
374 {
375 fprintf(stderr,"[ERR] Only disks with 512 bytes per sector are supported.\n");
376 return -1;
377 }
378 BytesPerSect = ipod->sector_size;
379
380 /* Checks on Disk Size */
381 qTotalSectors = ipod->pinfo[partition].size;
382
383 /* low end limit - 65536 sectors */
384 if ( qTotalSectors < 65536 )
385 {
386 /* I suspect that most FAT32 implementations would mount this
387 volume just fine, but the spec says that we shouldn't do
388 this, so we won't */
389
390 fprintf(stderr,"[ERR] This drive is too small for FAT32 - there must be at least 64K clusters\n" );
391 return -1;
392 }
393
394 if ( qTotalSectors >= 0xffffffff )
395 {
396 /* This is a more fundamental limitation on FAT32 - the total
397 sector count in the root dir ­s 32bit. With a bit of
398 creativity, FAT32 could be extended to handle at least 2^28
399 clusters There would need to be an extra field in the
400 FSInfo sector, and the old sector count could be set to
401 0xffffffff. This is non standard though, the Windows FAT
402 driver FASTFAT.SYS won't understand this. Perhaps a future
403 version of FAT32 and FASTFAT will handle this. */
404
405 fprintf(stderr,"[ERR] This drive is too big for FAT32 - max 2TB supported\n");
406 }
407
408 if ( sectors_per_cluster ) {
409 SectorsPerCluster = sectors_per_cluster;
410 } else {
411 SectorsPerCluster = get_sectors_per_cluster(ipod->pinfo[partition].size,
412 BytesPerSect );
413 }
414
415 TotalSectors = (uint32_t) qTotalSectors;
416
417 FatSize = get_fat_size_sectors(TotalSectors, ReservedSectCount,
418 SectorsPerCluster, NumFATs, BytesPerSect );
419
420 UserAreaSize = TotalSectors - ReservedSectCount - (NumFATs*FatSize);
421
422 /* First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster */
423 SystemAreaSize = (ReservedSectCount+(NumFATs*FatSize) + SectorsPerCluster);
424
425 /* Work out the Cluster count */
426 FatNeeded = UserAreaSize/SectorsPerCluster;
427
428 /* check for a cluster count of >2^28, since the upper 4 bits of
429 the cluster values in the FAT are reserved. */
430 if (FatNeeded > 0x0FFFFFFF) {
431 fprintf(stderr,"[ERR] This drive has more than 2^28 clusters, try to specify a larger cluster size\n" );
432 return -1;
433 }
434
435 /* Sanity check, make sure the fat is big enough.
436 Convert the cluster count into a Fat sector count, and check
437 the fat size value we calculated earlier is OK. */
438
439 FatNeeded *=4;
440 FatNeeded += (BytesPerSect-1);
441 FatNeeded /= BytesPerSect;
442
443 if ( FatNeeded > FatSize ) {
444 fprintf(stderr,"[ERR] Drive too big to format\n");
445 return -1;
446 }
447
448 /*
449 Write boot sector, fats
450 Sector 0 Boot Sector
451 Sector 1 FSInfo
452 Sector 2 More boot code - we write zeros here
453 Sector 3 unused
454 Sector 4 unused
455 Sector 5 unused
456 Sector 6 Backup boot sector
457 Sector 7 Backup FSInfo sector
458 Sector 8 Backup 'more boot code'
459 zero'd sectors upto ReservedSectCount
460 FAT1 ReservedSectCount to ReservedSectCount + FatSize
461 ...
462 FATn ReservedSectCount to ReservedSectCount + FatSize
463 RootDir - allocated to cluster2
464 */
465
466 fprintf(stderr,"[INFO] Heads - %d, sectors/track = %d\n",ipod->num_heads,ipod->sectors_per_track);
467 fprintf(stderr,"[INFO] Size : %lluGB %u sectors\n", ((uint64_t)ipod->pinfo[partition].size * (uint64_t)ipod->sector_size) / (1000*1000*1000), TotalSectors );
468 fprintf(stderr,"[INFO] %d Bytes Per Sector, Cluster size %d bytes\n", BytesPerSect, SectorsPerCluster*BytesPerSect );
469 fprintf(stderr,"[INFO] Volume ID is %x:%x\n", VolumeId>>16, VolumeId&0xffff );
470 fprintf(stderr,"[INFO] %d Reserved Sectors, %d Sectors per FAT, %d fats\n", ReservedSectCount, FatSize, NumFATs );
471 fprintf (stderr,"[INFO] %d Total clusters\n", UserAreaSize/SectorsPerCluster );
472
473 fprintf(stderr,"[INFO] Formatting partition %d:...\n",partition);
474
475 /* Once zero_sectors has run, any data on the drive is basically lost... */
476 fprintf(stderr,"[INFO] Clearing out %d sectors for Reserved sectors, fats and root cluster...\n", SystemAreaSize );
477
478 zero_sectors(ipod, ipod->pinfo[partition].start, SystemAreaSize);
479
480 fprintf(stderr,"[INFO] Initialising reserved sectors and FATs...\n" );
481
482 /* Create the boot sector structure */
483 create_boot_sector(sectorbuf, ipod, partition);
484 create_fsinfo(sectorbuf + 512, ipod, partition);
485
486 /* Write boot sector and fsinfo at start of partition */
487 if (ipod_seek(ipod, ipod->pinfo[partition].start * ipod->sector_size) < 0) {
488 fprintf(stderr,"[ERR] Seek failed\n");
489 return -1;
490 }
491 if (ipod_write(ipod,sectorbuf,512 * 2) < 0) {
492 perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n");
493 return -1;
494 }
495
496 /* Write backup copy of boot sector and fsinfo */
497 if (ipod_seek(ipod, (ipod->pinfo[partition].start + BackupBootSect) * ipod->sector_size) < 0) {
498 fprintf(stderr,"[ERR] Seek failed\n");
499 return -1;
500 }
501 if (ipod_write(ipod,sectorbuf,512 * 2) < 0) {
502 perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n");
503 return -1;
504 }
505
506 /* Create the first FAT sector */
507 create_firstfatsector(sectorbuf, ipod, partition);
508
509 /* Write the first fat sector in the right places */
510 for ( i=0; i<NumFATs; i++ ) {
511 int SectorStart = ReservedSectCount + (i * FatSize );
512
513 if (ipod_seek(ipod, (ipod->pinfo[partition].start + SectorStart) * ipod->sector_size) < 0) {
514 fprintf(stderr,"[ERR] Seek failed\n");
515 return -1;
516 }
517
518 if (ipod_write(ipod,sectorbuf,512) < 0) {
519 perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n");
520 return -1;
521 }
522 }
523
524 fprintf(stderr,"[INFO] Format successful\n");
525
526 return 0;
527}
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 @@
26#include <sys/stat.h> 26#include <sys/stat.h>
27#include <sys/ioctl.h> 27#include <sys/ioctl.h>
28 28
29#include "ipodio.h"
30
29#if defined(linux) || defined (__linux) 31#if defined(linux) || defined (__linux)
30#include <sys/mount.h> 32#include <sys/mount.h>
33#include <linux/hdreg.h>
31#define IPOD_SECTORSIZE_IOCTL BLKSSZGET 34#define IPOD_SECTORSIZE_IOCTL BLKSSZGET
35
36static void get_geometry(struct ipod_t* ipod)
37{
38 struct hd_geometry geometry;
39
40 if (!ioctl(ipod->dh, HDIO_GETGEO, &geometry)) {
41 /* never use geometry.cylinders - it is truncated */
42 ipod->num_heads = geometry.heads;
43 ipod->sectors_per_track = geometry.sectors;
44 } else {
45 ipod->num_heads = 0;
46 ipod->sectors_per_track = 0;
47 }
48}
49
32#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ 50#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
33 || defined(__bsdi__) || defined(__DragonFly__) 51 || defined(__bsdi__) || defined(__DragonFly__)
34#include <sys/disk.h> 52#include <sys/disk.h>
35#define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE 53#define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE
54
55/* TODO: Implement this function for BSD */
56static void get_geometry(struct ipod_t* ipod)
57{
58 /* Are these universal for all ipods? */
59 ipod->num_heads = 255;
60 ipod->sectors_per_track = 63;
61}
62
36#elif defined(__APPLE__) && defined(__MACH__) 63#elif defined(__APPLE__) && defined(__MACH__)
37#include <sys/disk.h> 64#include <sys/disk.h>
38#define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE 65#define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE
66
67/* TODO: Implement this function for Mac OS X */
68static void get_geometry(struct ipod_t* ipod)
69{
70 /* Are these universal for all ipods? */
71 ipod->num_heads = 255;
72 ipod->sectors_per_track = 63;
73}
74
39#else 75#else
40 #error No sector-size detection implemented for this platform 76 #error No sector-size detection implemented for this platform
41#endif 77#endif
42 78
43#include "ipodio.h"
44
45void print_error(char* msg) 79void print_error(char* msg)
46{ 80{
47 perror(msg); 81 perror(msg);
@@ -55,6 +89,8 @@ int ipod_open(struct ipod_t* ipod, int silent)
55 return -1; 89 return -1;
56 } 90 }
57 91
92 /* Read information about the disk */
93
58 if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) { 94 if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) {
59 ipod->sector_size=512; 95 ipod->sector_size=512;
60 if (!silent) { 96 if (!silent) {
@@ -62,6 +98,9 @@ int ipod_open(struct ipod_t* ipod, int silent)
62 ,ipod->sector_size); 98 ,ipod->sector_size);
63 } 99 }
64 } 100 }
101
102 get_geometry(ipod);
103
65 return 0; 104 return 0;
66} 105}
67 106
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)
86 return -1; 86 return -1;
87 } 87 }
88 88
89 /* Defaults */
90 ipod->num_heads = 0;
91 ipod->sectors_per_track = 0;
92
89 if (!DeviceIoControl(ipod->dh, 93 if (!DeviceIoControl(ipod->dh,
90 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 94 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
91 NULL, 95 NULL,
@@ -105,10 +109,14 @@ int ipod_open(struct ipod_t* ipod, int silent)
105 if (!silent) print_error(" Error reading disk geometry: "); 109 if (!silent) print_error(" Error reading disk geometry: ");
106 return -1; 110 return -1;
107 } else { 111 } else {
108 ipod->sector_size=diskgeometry.BytesPerSector; 112 ipod->sector_size = diskgeometry.BytesPerSector;
113 ipod->num_heads = diskgeometry.TracksPerCylinder;
114 ipod->sectors_per_track = diskgeometry.SectorsPerTrack;
109 } 115 }
110 } else { 116 } else {
111 ipod->sector_size=diskgeometry_ex.Geometry.BytesPerSector; 117 ipod->sector_size = diskgeometry_ex.Geometry.BytesPerSector;
118 ipod->num_heads = diskgeometry_ex.Geometry.TracksPerCylinder;
119 ipod->sectors_per_track = diskgeometry_ex.Geometry.SectorsPerTrack;
112 } 120 }
113 121
114 return 0; 122 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 {
62 HANDLE dh; 62 HANDLE dh;
63 char diskname[4096]; 63 char diskname[4096];
64 int sector_size; 64 int sector_size;
65 int sectors_per_track;
66 int num_heads;
65 struct ipod_directory_t ipod_directory[MAX_IMAGES]; 67 struct ipod_directory_t ipod_directory[MAX_IMAGES];
66 int nimages; 68 int nimages;
67 off_t diroffset; 69 off_t diroffset;
@@ -88,4 +90,7 @@ int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes);
88int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes); 90int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes);
89int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize); 91int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize);
90 92
93/* In fat32format.c */
94int format_partition(struct ipod_t* ipod, int partition);
95
91#endif 96#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 {
46 READ_FIRMWARE, 46 READ_FIRMWARE,
47 WRITE_FIRMWARE, 47 WRITE_FIRMWARE,
48 READ_PARTITION, 48 READ_PARTITION,
49 WRITE_PARTITION 49 WRITE_PARTITION,
50 FORMAT_PARTITION
50}; 51};
51 52
52void print_macpod_warning(void) 53void print_macpod_warning(void)
@@ -85,6 +86,7 @@ void print_usage(void)
85 fprintf(stderr," -a, --add-bootloader filename.ipod\n"); 86 fprintf(stderr," -a, --add-bootloader filename.ipod\n");
86 fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n"); 87 fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n");
87 fprintf(stderr," -d, --delete-bootloader\n"); 88 fprintf(stderr," -d, --delete-bootloader\n");
89 fprintf(stderr," -f, --format\n");
88 fprintf(stderr,"\n"); 90 fprintf(stderr,"\n");
89 91
90#ifdef __WIN32__ 92#ifdef __WIN32__
@@ -128,9 +130,7 @@ void display_partinfo(struct ipod_t* ipod)
128 130
129int main(int argc, char* argv[]) 131int main(int argc, char* argv[])
130{ 132{
131#ifdef WITH_BOOTOBJS
132 char yesno[4]; 133 char yesno[4];
133#endif
134 int i; 134 int i;
135 int n; 135 int n;
136 int infile, outfile; 136 int infile, outfile;
@@ -293,6 +293,10 @@ int main(int argc, char* argv[])
293 (strcmp(argv[i],"--verbose")==0)) { 293 (strcmp(argv[i],"--verbose")==0)) {
294 verbose++; 294 verbose++;
295 i++; 295 i++;
296 } else if ((strcmp(argv[i],"-f")==0) ||
297 (strcmp(argv[i],"--format")==0)) {
298 action = FORMAT_PARTITION;
299 i++;
296 } else { 300 } else {
297 print_usage(); return 1; 301 print_usage(); return 1;
298 } 302 }
@@ -465,6 +469,23 @@ int main(int argc, char* argv[])
465 } 469 }
466 470
467 close(infile); 471 close(infile);
472 } else if (action==FORMAT_PARTITION) {
473 printf("WARNING!!! YOU ARE ABOUT TO USE AN EXPERIMENTAL FORMATTING FEATURE.\n");
474 printf("Are you sure you want to continue? (y/n):");
475
476 if (fgets(yesno,4,stdin)) {
477 if (yesno[0]=='y') {
478 if (ipod_reopen_rw(&ipod) < 0) {
479 return 5;
480 }
481
482 if (format_partition(&ipod,1) < 0) {
483 fprintf(stderr,"[ERR] Format failed.\n");
484 }
485 } else {
486 fprintf(stderr,"[INFO] Format cancelled.\n");
487 }
488 }
468 } 489 }
469 490
470 ipod_close(&ipod); 491 ipod_close(&ipod);