summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2007-02-04 11:42:11 +0000
committerDave Chapman <dave@dchapman.com>2007-02-04 11:42:11 +0000
commit31aa4524dad1a55ecf1311ae3c89b03b1e0f43ae (patch)
tree1af822cbaa7cc219e8fb24e7015a3c187bd554c3
parent7c9f4e3a3af5721f75d8a3bff9539dd91e3d2c08 (diff)
downloadrockbox-31aa4524dad1a55ecf1311ae3c89b03b1e0f43ae.tar.gz
rockbox-31aa4524dad1a55ecf1311ae3c89b03b1e0f43ae.zip
Mainly internal changes to create a struct ipod_t instead of passing lots of parameters to all the functions. Also adds (untested) 3G support, plus a --write-firmware-bin option (requested by IPL people to write a kernel directly to the firmware partition).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12190 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--tools/ipodpatcher/ipodio-posix.c43
-rw-r--r--tools/ipodpatcher/ipodio-win32.c46
-rw-r--r--tools/ipodpatcher/ipodio.h57
-rw-r--r--tools/ipodpatcher/ipodpatcher.c640
4 files changed, 411 insertions, 375 deletions
diff --git a/tools/ipodpatcher/ipodio-posix.c b/tools/ipodpatcher/ipodio-posix.c
index 071a540017..ed3737a5ed 100644
--- a/tools/ipodpatcher/ipodio-posix.c
+++ b/tools/ipodpatcher/ipodio-posix.c
@@ -47,36 +47,39 @@ void print_error(char* msg)
47 perror(msg); 47 perror(msg);
48} 48}
49 49
50int ipod_open(HANDLE* dh, char* diskname, int* sector_size, int silent) 50int ipod_open(struct ipod_t* ipod, int silent)
51{ 51{
52 *dh=open(diskname,O_RDONLY); 52 ipod->dh=open(ipod->diskname,O_RDONLY);
53 if (*dh < 0) { 53 if (ipod->dh < 0) {
54 if (!silent) perror(diskname); 54 if (!silent) perror(ipod->diskname);
55 return -1; 55 return -1;
56 } 56 }
57 57
58 if(ioctl(*dh,IPOD_SECTORSIZE_IOCTL,sector_size) < 0) { 58 if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) {
59 *sector_size=512; 59 ipod->sector_size=512;
60 if (!silent) fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n",*sector_size); 60 if (!silent) {
61 fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n"
62 ,ipod->sector_size);
63 }
61 } 64 }
62 return 0; 65 return 0;
63} 66}
64 67
65 68
66int ipod_reopen_rw(HANDLE* dh, char* diskname) 69int ipod_reopen_rw(struct ipod_t* ipod)
67{ 70{
68 close(*dh); 71 close(ipod->dh);
69 *dh=open(diskname,O_RDWR); 72 ipod->dh=open(ipod->diskname,O_RDWR);
70 if (*dh < 0) { 73 if (ipod->dh < 0) {
71 perror(diskname); 74 perror(ipod->diskname);
72 return -1; 75 return -1;
73 } 76 }
74 return 0; 77 return 0;
75} 78}
76 79
77int ipod_close(HANDLE dh) 80int ipod_close(struct ipod_t* ipod)
78{ 81{
79 close(dh); 82 close(ipod->dh);
80 return 0; 83 return 0;
81} 84}
82 85
@@ -89,11 +92,11 @@ int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize)
89 return 0; 92 return 0;
90} 93}
91 94
92int ipod_seek(HANDLE dh, unsigned long pos) 95int ipod_seek(struct ipod_t* ipod, unsigned long pos)
93{ 96{
94 off_t res; 97 off_t res;
95 98
96 res = lseek(dh, pos, SEEK_SET); 99 res = lseek(ipod->dh, pos, SEEK_SET);
97 100
98 if (res == -1) { 101 if (res == -1) {
99 return -1; 102 return -1;
@@ -101,12 +104,12 @@ int ipod_seek(HANDLE dh, unsigned long pos)
101 return 0; 104 return 0;
102} 105}
103 106
104int ipod_read(HANDLE dh, unsigned char* buf, int nbytes) 107int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes)
105{ 108{
106 return read(dh, buf, nbytes); 109 return read(ipod->dh, buf, nbytes);
107} 110}
108 111
109int ipod_write(HANDLE dh, unsigned char* buf, int nbytes) 112int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes)
110{ 113{
111 return write(dh, buf, nbytes); 114 return write(ipod->dh, buf, nbytes);
112} 115}
diff --git a/tools/ipodpatcher/ipodio-win32.c b/tools/ipodpatcher/ipodio-win32.c
index 97e3fb6fec..5232e12719 100644
--- a/tools/ipodpatcher/ipodio-win32.c
+++ b/tools/ipodpatcher/ipodio-win32.c
@@ -66,27 +66,27 @@ void print_error(char* msg)
66 LocalFree(pMsgBuf); 66 LocalFree(pMsgBuf);
67} 67}
68 68
69int ipod_open(HANDLE* dh, char* diskname, int* sector_size, int silent) 69int ipod_open(struct ipod_t* ipod, int silent)
70{ 70{
71 DISK_GEOMETRY_EX diskgeometry_ex; 71 DISK_GEOMETRY_EX diskgeometry_ex;
72 DISK_GEOMETRY diskgeometry; 72 DISK_GEOMETRY diskgeometry;
73 unsigned long n; 73 unsigned long n;
74 74
75 *dh = CreateFile(diskname, GENERIC_READ, 75 ipod->dh = CreateFile(ipod->diskname, GENERIC_READ,
76 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 76 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
77 FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); 77 FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL);
78 78
79 if (*dh == INVALID_HANDLE_VALUE) { 79 if (ipod->dh == INVALID_HANDLE_VALUE) {
80 if (!silent) print_error(" Error opening disk: "); 80 if (!silent) print_error(" Error opening disk: ");
81 return -1; 81 return -1;
82 } 82 }
83 83
84 if (!lock_volume(*dh)) { 84 if (!lock_volume(ipod->dh)) {
85 if (!silent) print_error(" Error locking disk: "); 85 if (!silent) print_error(" Error locking disk: ");
86 return -1; 86 return -1;
87 } 87 }
88 88
89 if (!DeviceIoControl(*dh, 89 if (!DeviceIoControl(ipod->dh,
90 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 90 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
91 NULL, 91 NULL,
92 0, 92 0,
@@ -94,7 +94,7 @@ int ipod_open(HANDLE* dh, char* diskname, int* sector_size, int silent)
94 sizeof(diskgeometry_ex), 94 sizeof(diskgeometry_ex),
95 &n, 95 &n,
96 NULL)) { 96 NULL)) {
97 if (!DeviceIoControl(*dh, 97 if (!DeviceIoControl(ipod->dh,
98 IOCTL_DISK_GET_DRIVE_GEOMETRY, 98 IOCTL_DISK_GET_DRIVE_GEOMETRY,
99 NULL, 99 NULL,
100 0, 100 0,
@@ -105,31 +105,31 @@ int ipod_open(HANDLE* dh, char* diskname, int* sector_size, int silent)
105 if (!silent) print_error(" Error reading disk geometry: "); 105 if (!silent) print_error(" Error reading disk geometry: ");
106 return -1; 106 return -1;
107 } else { 107 } else {
108 *sector_size=diskgeometry.BytesPerSector; 108 ipod->sector_size=diskgeometry.BytesPerSector;
109 } 109 }
110 } else { 110 } else {
111 *sector_size=diskgeometry_ex.Geometry.BytesPerSector; 111 ipod->sector_size=diskgeometry_ex.Geometry.BytesPerSector;
112 } 112 }
113 113
114 return 0; 114 return 0;
115} 115}
116 116
117int ipod_reopen_rw(HANDLE* dh, char* diskname) 117int ipod_reopen_rw(struct ipod_t* ipod)
118{ 118{
119 /* Close existing file and re-open for writing */ 119 /* Close existing file and re-open for writing */
120 unlock_volume(*dh); 120 unlock_volume(ipod->dh);
121 CloseHandle(*dh); 121 CloseHandle(ipod->dh);
122 122
123 *dh = CreateFile(diskname, GENERIC_READ | GENERIC_WRITE, 123 ipod->dh = CreateFile(ipod->diskname, GENERIC_READ | GENERIC_WRITE,
124 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 124 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
125 FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); 125 FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL);
126 126
127 if (*dh == INVALID_HANDLE_VALUE) { 127 if (ipod->dh == INVALID_HANDLE_VALUE) {
128 print_error(" Error opening disk: "); 128 print_error(" Error opening disk: ");
129 return -1; 129 return -1;
130 } 130 }
131 131
132 if (!lock_volume(*dh)) { 132 if (!lock_volume(ipod->dh)) {
133 print_error(" Error locking disk: "); 133 print_error(" Error locking disk: ");
134 return -1; 134 return -1;
135 } 135 }
@@ -137,10 +137,10 @@ int ipod_reopen_rw(HANDLE* dh, char* diskname)
137 return 0; 137 return 0;
138} 138}
139 139
140int ipod_close(HANDLE dh) 140int ipod_close(struct ipod_t* ipod)
141{ 141{
142 unlock_volume(dh); 142 unlock_volume(ipod->dh);
143 CloseHandle(dh); 143 CloseHandle(ipod->dh);
144 return 0; 144 return 0;
145} 145}
146 146
@@ -156,20 +156,20 @@ int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize)
156 return 0; 156 return 0;
157} 157}
158 158
159int ipod_seek(HANDLE dh, unsigned long pos) 159int ipod_seek(struct ipod_t* ipod, unsigned long pos)
160{ 160{
161 if (SetFilePointer(dh, pos, NULL, FILE_BEGIN)==0xffffffff) { 161 if (SetFilePointer(ipod->dh, pos, NULL, FILE_BEGIN)==0xffffffff) {
162 print_error(" Seek error "); 162 print_error(" Seek error ");
163 return -1; 163 return -1;
164 } 164 }
165 return 0; 165 return 0;
166} 166}
167 167
168int ipod_read(HANDLE dh, unsigned char* buf, int nbytes) 168int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes)
169{ 169{
170 unsigned long count; 170 unsigned long count;
171 171
172 if (!ReadFile(dh, buf, nbytes, &count, NULL)) { 172 if (!ReadFile(ipod->dh, buf, nbytes, &count, NULL)) {
173 print_error(" Error reading from disk: "); 173 print_error(" Error reading from disk: ");
174 return -1; 174 return -1;
175 } 175 }
@@ -177,11 +177,11 @@ int ipod_read(HANDLE dh, unsigned char* buf, int nbytes)
177 return count; 177 return count;
178} 178}
179 179
180int ipod_write(HANDLE dh, unsigned char* buf, int nbytes) 180int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes)
181{ 181{
182 unsigned long count; 182 unsigned long count;
183 183
184 if (!WriteFile(dh, buf, nbytes, &count, NULL)) { 184 if (!WriteFile(ipod->dh, buf, nbytes, &count, NULL)) {
185 print_error(" Error writing to disk: "); 185 print_error(" Error writing to disk: ");
186 return -1; 186 return -1;
187 } 187 }
diff --git a/tools/ipodpatcher/ipodio.h b/tools/ipodpatcher/ipodio.h
index 585ca90e16..ba2b2e9bf9 100644
--- a/tools/ipodpatcher/ipodio.h
+++ b/tools/ipodpatcher/ipodio.h
@@ -20,6 +20,8 @@
20#ifndef __IPODIO_H 20#ifndef __IPODIO_H
21#define __IPODIO_H 21#define __IPODIO_H
22 22
23#include <stdint.h>
24
23#ifdef __WIN32__ 25#ifdef __WIN32__
24#include <windows.h> 26#include <windows.h>
25#else 27#else
@@ -27,13 +29,56 @@
27#define O_BINARY 0 29#define O_BINARY 0
28#endif 30#endif
29 31
32/* The maximum number of images in a firmware partition - a guess... */
33#define MAX_IMAGES 10
34
35enum firmwaretype_t {
36 FTYPE_OSOS = 0,
37 FTYPE_RSRC,
38 FTYPE_AUPD,
39 FTYPE_HIBE
40};
41
42struct ipod_directory_t {
43 enum firmwaretype_t ftype;
44 int id;
45 uint32_t devOffset; /* Offset of image relative to one sector into bootpart*/
46 uint32_t len;
47 uint32_t addr;
48 uint32_t entryOffset;
49 uint32_t chksum;
50 uint32_t vers;
51 uint32_t loadAddr;
52};
53
54struct partinfo_t {
55 unsigned long start; /* first sector (LBA) */
56 unsigned long size; /* number of sectors */
57 unsigned char type;
58};
59
60struct ipod_t {
61 HANDLE dh;
62 char diskname[4096];
63 int sector_size;
64 struct ipod_directory_t ipod_directory[MAX_IMAGES];
65 int nimages;
66 off_t diroffset;
67 off_t start; /* Offset in bytes of firmware partition from start of disk */
68 off_t fwoffset; /* Offset in bytes of start of firmware images from start of disk */
69 struct partinfo_t pinfo[4];
70 int modelnum;
71 char* modelname;
72 char* modelstr;
73};
74
30void print_error(char* msg); 75void print_error(char* msg);
31int ipod_open(HANDLE* dh, char* diskname, int* sector_size, int silent); 76int ipod_open(struct ipod_t* ipod, int silent);
32int ipod_reopen_rw(HANDLE* dh, char* diskname); 77int ipod_reopen_rw(struct ipod_t* ipod);
33int ipod_close(HANDLE dh); 78int ipod_close(struct ipod_t* ipod);
34int ipod_seek(HANDLE dh, unsigned long pos); 79int ipod_seek(struct ipod_t* ipod, unsigned long pos);
35int ipod_read(HANDLE dh, unsigned char* buf, int nbytes); 80int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes);
36int ipod_write(HANDLE dh, unsigned char* buf, int nbytes); 81int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes);
37int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize); 82int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize);
38 83
39#endif 84#endif
diff --git a/tools/ipodpatcher/ipodpatcher.c b/tools/ipodpatcher/ipodpatcher.c
index 28cac87c6c..7d71ac29e1 100644
--- a/tools/ipodpatcher/ipodpatcher.c
+++ b/tools/ipodpatcher/ipodpatcher.c
@@ -51,9 +51,6 @@ static const char *apple_stop_sign = "{{~~ /-----\\ "\
51 "----------------"\ 51 "----------------"\
52 "---------------"; 52 "---------------";
53 53
54/* The maximum number of images in a firmware partition - a guess... */
55#define MAX_IMAGES 10
56
57/* Windows requires the buffer for disk I/O to be aligned in memory on a 54/* Windows requires the buffer for disk I/O to be aligned in memory on a
58 multiple of the disk volume size - so we use a single global variable 55 multiple of the disk volume size - so we use a single global variable
59 and initialise it with ipod_alloc_buf() 56 and initialise it with ipod_alloc_buf()
@@ -96,11 +93,12 @@ off_t filesize(int fd) {
96#define MAX_SECTOR_SIZE 2048 93#define MAX_SECTOR_SIZE 2048
97#define SECTOR_SIZE 512 94#define SECTOR_SIZE 512
98 95
99struct partinfo_t { 96unsigned short static inline le2ushort(unsigned char* buf)
100 unsigned long start; /* first sector (LBA) */ 97{
101 unsigned long size; /* number of sectors */ 98 unsigned short res = (buf[1] << 8) | buf[0];
102 unsigned char type; 99
103}; 100 return res;
101}
104 102
105int static inline le2int(unsigned char* buf) 103int static inline le2int(unsigned char* buf)
106{ 104{
@@ -150,33 +148,32 @@ void int2be(unsigned int val, unsigned char* addr)
150 ((long)array[pos] | ((long)array[pos+1] << 8 ) |\ 148 ((long)array[pos] | ((long)array[pos+1] << 8 ) |\
151 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) 149 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
152 150
153void display_partinfo(struct partinfo_t* pinfo, int sector_size) 151void display_partinfo(struct ipod_t* ipod)
154{ 152{
155 int i; 153 int i;
156 double sectors_per_MB = (1024.0*1024.0)/sector_size; 154 double sectors_per_MB = (1024.0*1024.0)/ipod->sector_size;
157 155
158 printf("[INFO] Part Start Sector End Sector Size (MB) Type\n"); 156 printf("[INFO] Part Start Sector End Sector Size (MB) Type\n");
159 for ( i = 0; i < 4; i++ ) { 157 for ( i = 0; i < 4; i++ ) {
160 if (pinfo[i].start != 0) { 158 if (ipod->pinfo[i].start != 0) {
161 printf("[INFO] %d %10ld %10ld %10.1f %s (0x%02x)\n", 159 printf("[INFO] %d %10ld %10ld %10.1f %s (0x%02x)\n",
162 i, 160 i,
163 pinfo[i].start, 161 ipod->pinfo[i].start,
164 pinfo[i].start+pinfo[i].size-1, 162 ipod->pinfo[i].start+ipod->pinfo[i].size-1,
165 pinfo[i].size/sectors_per_MB, 163 ipod->pinfo[i].size/sectors_per_MB,
166 get_parttype(pinfo[i].type), 164 get_parttype(ipod->pinfo[i].type),
167 pinfo[i].type); 165 ipod->pinfo[i].type);
168 } 166 }
169 } 167 }
170} 168}
171 169
172 170
173int read_partinfo(HANDLE dh, int sector_size, struct partinfo_t* pinfo, 171int read_partinfo(struct ipod_t* ipod, int silent)
174 int silent)
175{ 172{
176 int i; 173 int i;
177 unsigned long count; 174 unsigned long count;
178 175
179 count = ipod_read(dh,sectorbuf,sector_size); 176 count = ipod_read(ipod,sectorbuf, ipod->sector_size);
180 177
181 if (count <= 0) { 178 if (count <= 0) {
182 print_error(" Error reading from disk: "); 179 print_error(" Error reading from disk: ");
@@ -199,36 +196,35 @@ int read_partinfo(HANDLE dh, int sector_size, struct partinfo_t* pinfo,
199 /* parse partitions */ 196 /* parse partitions */
200 for ( i = 0; i < 4; i++ ) { 197 for ( i = 0; i < 4; i++ ) {
201 unsigned char* ptr = sectorbuf + 0x1be + 16*i; 198 unsigned char* ptr = sectorbuf + 0x1be + 16*i;
202 pinfo[i].type = ptr[4]; 199 ipod->pinfo[i].type = ptr[4];
203 pinfo[i].start = BYTES2INT32(ptr, 8); 200 ipod->pinfo[i].start = BYTES2INT32(ptr, 8);
204 pinfo[i].size = BYTES2INT32(ptr, 12); 201 ipod->pinfo[i].size = BYTES2INT32(ptr, 12);
205 202
206 /* extended? */ 203 /* extended? */
207 if ( pinfo[i].type == 5 ) { 204 if ( ipod->pinfo[i].type == 5 ) {
208 /* not handled yet */ 205 /* not handled yet */
209 } 206 }
210 } 207 }
211 208
209 ipod->start = ipod->pinfo[0].start*ipod->sector_size;
212 return 0; 210 return 0;
213} 211}
214 212
215int read_partition(HANDLE dh, int outfile,unsigned long start_sector, 213int read_partition(struct ipod_t* ipod, int outfile)
216 unsigned long count, int sector_size)
217{ 214{
218 int res; 215 int res;
219 unsigned long n; 216 unsigned long n;
220 int bytesleft; 217 int bytesleft;
221 int chunksize; 218 int chunksize;
219 int count = ipod->pinfo[0].size;
222 220
223 fprintf(stderr,"[INFO] Seeking to sector %ld\n",start_sector); 221 if (ipod_seek(ipod, ipod->start) < 0) {
224
225 if (ipod_seek(dh,start_sector*sector_size) < 0) {
226 return -1; 222 return -1;
227 } 223 }
228 224
229 fprintf(stderr,"[INFO] Writing %ld sectors to output file\n",count); 225 fprintf(stderr,"[INFO] Writing %d sectors to output file\n",count);
230 226
231 bytesleft = count * sector_size; 227 bytesleft = count * ipod->sector_size;
232 while (bytesleft > 0) { 228 while (bytesleft > 0) {
233 if (bytesleft > BUFFER_SIZE) { 229 if (bytesleft > BUFFER_SIZE) {
234 chunksize = BUFFER_SIZE; 230 chunksize = BUFFER_SIZE;
@@ -236,7 +232,7 @@ int read_partition(HANDLE dh, int outfile,unsigned long start_sector,
236 chunksize = bytesleft; 232 chunksize = bytesleft;
237 } 233 }
238 234
239 n = ipod_read(dh, sectorbuf, chunksize); 235 n = ipod_read(ipod, sectorbuf, chunksize);
240 236
241 if (n < 0) { 237 if (n < 0) {
242 return -1; 238 return -1;
@@ -269,8 +265,7 @@ int read_partition(HANDLE dh, int outfile,unsigned long start_sector,
269 return 0; 265 return 0;
270} 266}
271 267
272int write_partition(HANDLE dh, int infile,unsigned long start_sector, 268int write_partition(struct ipod_t* ipod, int infile)
273 int sector_size)
274{ 269{
275 unsigned long res; 270 unsigned long res;
276 int n; 271 int n;
@@ -279,7 +274,7 @@ int write_partition(HANDLE dh, int infile,unsigned long start_sector,
279 int eof; 274 int eof;
280 int padding = 0; 275 int padding = 0;
281 276
282 if (ipod_seek(dh, start_sector*sector_size) < 0) { 277 if (ipod_seek(ipod, ipod->start) < 0) {
283 return -1; 278 return -1;
284 } 279 }
285 280
@@ -297,15 +292,15 @@ int write_partition(HANDLE dh, int infile,unsigned long start_sector,
297 if (n < BUFFER_SIZE) { 292 if (n < BUFFER_SIZE) {
298 eof = 1; 293 eof = 1;
299 /* We need to pad the last write to a multiple of SECTOR_SIZE */ 294 /* We need to pad the last write to a multiple of SECTOR_SIZE */
300 if ((n % sector_size) != 0) { 295 if ((n % ipod->sector_size) != 0) {
301 padding = (sector_size-(n % sector_size)); 296 padding = (ipod->sector_size-(n % ipod->sector_size));
302 n += padding; 297 n += padding;
303 } 298 }
304 } 299 }
305 300
306 bytesread += n; 301 bytesread += n;
307 302
308 res = ipod_write(dh, sectorbuf,n); 303 res = ipod_write(ipod, sectorbuf, n);
309 304
310 if (res < 0) { 305 if (res < 0) {
311 print_error(" Error writing to disk: "); 306 print_error(" Error writing to disk: ");
@@ -336,24 +331,31 @@ void print_usage(void) {
336#endif 331#endif
337 fprintf(stderr,"\n"); 332 fprintf(stderr,"\n");
338 fprintf(stderr,"Where [action] is one of the following options:\n"); 333 fprintf(stderr,"Where [action] is one of the following options:\n");
339 fprintf(stderr," -l, --list\n"); 334 fprintf(stderr," -l, --list\n");
340 fprintf(stderr," -r, --read-partition bootpartition.bin\n"); 335 fprintf(stderr," -r, --read-partition bootpartition.bin\n");
341 fprintf(stderr," -w, --write-partition bootpartition.bin\n"); 336 fprintf(stderr," -w, --write-partition bootpartition.bin\n");
342 fprintf(stderr," -rf, --read-firmware filename.ipod\n"); 337 fprintf(stderr," -rf, --read-firmware filename.ipod\n");
343 fprintf(stderr," -wf, --write-firmware filename.ipod\n"); 338 fprintf(stderr," -wf, --write-firmware filename.ipod\n");
344 fprintf(stderr," -a, --add-bootloader filename.ipod\n"); 339 fprintf(stderr," -wfb, --write-firmware-bin filename.bin\n");
345 fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n"); 340 fprintf(stderr," -a, --add-bootloader filename.ipod\n");
346 fprintf(stderr," -d, --delete-bootloader\n"); 341 fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n");
342 fprintf(stderr," -d, --delete-bootloader\n");
347 fprintf(stderr,"\n"); 343 fprintf(stderr,"\n");
348 344
349#ifdef __WIN32__ 345#ifdef __WIN32__
350 fprintf(stderr,"DISKNO is the number (e.g. 2) Windows has assigned to your ipod's hard disk.\n"); 346 fprintf(stderr,"DISKNO is the number (e.g. 2) Windows has assigned to your ipod's hard disk.\n");
351 fprintf(stderr,"The first hard disk in your computer (i.e. C:\\) will be disk0, the next disk\n"); 347 fprintf(stderr,"The first hard disk in your computer (i.e. C:\\) will be disk 0, the next disk\n");
352 fprintf(stderr,"will be disk 1 etc. ipodpatcher will refuse to access a disk unless it\n"); 348 fprintf(stderr,"will be disk 1 etc. ipodpatcher will refuse to access a disk unless it\n");
353 fprintf(stderr,"can identify it as being an ipod.\n"); 349 fprintf(stderr,"can identify it as being an ipod.\n");
354 fprintf(stderr,"\n"); 350 fprintf(stderr,"\n");
355#else 351#else
352#if defined(linux) || defined (__linux)
356 fprintf(stderr,"\"device\" is the device node (e.g. /dev/sda) assigned to your ipod.\n"); 353 fprintf(stderr,"\"device\" is the device node (e.g. /dev/sda) assigned to your ipod.\n");
354#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
355 fprintf(stderr,"\"device\" is the device node (e.g. /dev/da1) assigned to your ipod.\n");
356#elif defined(__APPLE__) && defined(__MACH__)
357 fprintf(stderr,"\"device\" is the device node (e.g. /dev/disk1) assigned to your ipod.\n");
358#endif
357 fprintf(stderr,"ipodpatcher will refuse to access a disk unless it can identify it as being\n"); 359 fprintf(stderr,"ipodpatcher will refuse to access a disk unless it can identify it as being\n");
358 fprintf(stderr,"an ipod.\n"); 360 fprintf(stderr,"an ipod.\n");
359#endif 361#endif
@@ -376,28 +378,7 @@ enum {
376 378
377char* ftypename[] = { "OSOS", "RSRC", "AUPD", "HIBE" }; 379char* ftypename[] = { "OSOS", "RSRC", "AUPD", "HIBE" };
378 380
379enum firmwaretype_t { 381int diskmove(struct ipod_t* ipod, int delta)
380 FTYPE_OSOS = 0,
381 FTYPE_RSRC,
382 FTYPE_AUPD,
383 FTYPE_HIBE
384};
385
386struct ipod_directory_t {
387 enum firmwaretype_t ftype;
388 int id;
389 uint32_t devOffset; /* Offset of image relative to one sector into bootpart*/
390 uint32_t len;
391 uint32_t addr;
392 uint32_t entryOffset;
393 uint32_t chksum;
394 uint32_t vers;
395 uint32_t loadAddr;
396};
397
398
399int diskmove(HANDLE dh, int start, int nimages, struct ipod_directory_t* ipod_directory,
400 int sector_size,int delta)
401{ 382{
402 int src_start; 383 int src_start;
403 int src_end; 384 int src_end;
@@ -406,12 +387,14 @@ int diskmove(HANDLE dh, int start, int nimages, struct ipod_directory_t* ipod_di
406 int i; 387 int i;
407 int n; 388 int n;
408 389
409 src_start = ipod_directory[1].devOffset + sector_size; 390 src_start = ipod->ipod_directory[1].devOffset + ipod->sector_size;
410 src_end = (ipod_directory[nimages-1].devOffset + sector_size + ipod_directory[nimages-1].len + (sector_size-1)) & ~(sector_size-1); 391 src_end = (ipod->ipod_directory[ipod->nimages-1].devOffset + ipod->sector_size +
392 ipod->ipod_directory[ipod->nimages-1].len +
393 (ipod->sector_size-1)) & ~(ipod->sector_size-1);
411 bytesleft = src_end - src_start; 394 bytesleft = src_end - src_start;
412 395
413 if (verbose) { 396 if (verbose) {
414 fprintf(stderr,"[INFO] Need to move images 2-%d forward %08x bytes\n",nimages,delta); 397 fprintf(stderr,"[INFO] Need to move images 2-%d forward %08x bytes\n", ipod->nimages,delta);
415 fprintf(stderr,"[VERB] src_start = %08x\n",src_start); 398 fprintf(stderr,"[VERB] src_start = %08x\n",src_start);
416 fprintf(stderr,"[VERB] src_end = %08x\n",src_end); 399 fprintf(stderr,"[VERB] src_end = %08x\n",src_end);
417 fprintf(stderr,"[VERB] dest_start = %08x\n",src_start+delta); 400 fprintf(stderr,"[VERB] dest_start = %08x\n",src_start+delta);
@@ -431,17 +414,17 @@ int diskmove(HANDLE dh, int start, int nimages, struct ipod_directory_t* ipod_di
431 chunksize, 414 chunksize,
432 src_end-chunksize, 415 src_end-chunksize,
433 src_end-chunksize+delta, 416 src_end-chunksize+delta,
434 start+src_end-chunksize, 417 (unsigned int)(ipod->start+src_end-chunksize),
435 start+src_end-chunksize+delta); 418 (unsigned int)(ipod->start+src_end-chunksize+delta));
436 } 419 }
437 420
438 421
439 if (ipod_seek(dh,start+src_end-chunksize) < 0) { 422 if (ipod_seek(ipod, ipod->start+src_end-chunksize) < 0) {
440 fprintf(stderr,"[ERR] Seek failed\n"); 423 fprintf(stderr,"[ERR] Seek failed\n");
441 return -1; 424 return -1;
442 } 425 }
443 426
444 if ((n = ipod_read(dh,sectorbuf,chunksize)) < 0) { 427 if ((n = ipod_read(ipod,sectorbuf,chunksize)) < 0) {
445 perror("[ERR] Write failed\n"); 428 perror("[ERR] Write failed\n");
446 return -1; 429 return -1;
447 } 430 }
@@ -452,12 +435,12 @@ int diskmove(HANDLE dh, int start, int nimages, struct ipod_directory_t* ipod_di
452 return -1; 435 return -1;
453 } 436 }
454 437
455 if (ipod_seek(dh,start+src_end-chunksize+delta) < 0) { 438 if (ipod_seek(ipod, ipod->start+src_end-chunksize+delta) < 0) {
456 fprintf(stderr,"[ERR] Seek failed\n"); 439 fprintf(stderr,"[ERR] Seek failed\n");
457 return -1; 440 return -1;
458 } 441 }
459 442
460 if ((n = ipod_write(dh,sectorbuf,chunksize)) < 0) { 443 if ((n = ipod_write(ipod,sectorbuf,chunksize)) < 0) {
461 perror("[ERR] Write failed\n"); 444 perror("[ERR] Write failed\n");
462 return -1; 445 return -1;
463 } 446 }
@@ -475,9 +458,7 @@ int diskmove(HANDLE dh, int start, int nimages, struct ipod_directory_t* ipod_di
475 return 0; 458 return 0;
476} 459}
477 460
478int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_size, 461int add_bootloader(struct ipod_t* ipod, char* filename, int type)
479 int nimages, struct ipod_directory_t* ipod_directory,
480 off_t diroffset, int modelnum, char* modelname)
481{ 462{
482 int length; 463 int length;
483 int i; 464 int i;
@@ -491,7 +472,6 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
491 unsigned long filechksum=0; 472 unsigned long filechksum=0;
492 unsigned char header[8]; /* Header for .ipod file */ 473 unsigned char header[8]; /* Header for .ipod file */
493 474
494 /* First check that the input file is the correct type for this ipod. */
495 infile=open(filename,O_RDONLY); 475 infile=open(filename,O_RDONLY);
496 if (infile < 0) { 476 if (infile < 0) {
497 fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); 477 fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename);
@@ -499,6 +479,7 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
499 } 479 }
500 480
501 if (type==DOT_IPOD) { 481 if (type==DOT_IPOD) {
482 /* First check that the input file is the correct type for this ipod. */
502 n = read(infile,header,8); 483 n = read(infile,header,8);
503 if (n < 8) { 484 if (n < 8) {
504 fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); 485 fprintf(stderr,"[ERR] Failed to read header from %s\n",filename);
@@ -506,9 +487,9 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
506 return -1; 487 return -1;
507 } 488 }
508 489
509 if (memcmp(header+4,modelname,4)!=0) { 490 if (memcmp(header+4, ipod->modelname,4)!=0) {
510 fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n", 491 fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n",
511 header[4],header[5],header[6],header[7],modelname); 492 header[4],header[5],header[6],header[7], ipod->modelname);
512 close(infile); 493 close(infile);
513 return -1; 494 return -1;
514 } 495 }
@@ -519,7 +500,7 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
519 } else { 500 } else {
520 length=filesize(infile); 501 length=filesize(infile);
521 } 502 }
522 paddedlength=(length+sector_size-1)&~(sector_size-1); 503 paddedlength=(length+ipod->sector_size-1)&~(ipod->sector_size-1);
523 504
524 /* Now read our bootloader - we need to check it before modifying the partition*/ 505 /* Now read our bootloader - we need to check it before modifying the partition*/
525 n = read(infile,sectorbuf,length); 506 n = read(infile,sectorbuf,length);
@@ -531,7 +512,7 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
531 512
532 if (type==DOT_IPOD) { 513 if (type==DOT_IPOD) {
533 /* Calculate and confirm bootloader checksum */ 514 /* Calculate and confirm bootloader checksum */
534 chksum = modelnum; 515 chksum = ipod->modelnum;
535 for (i = 0; i < length; i++) { 516 for (i = 0; i < length; i++) {
536 /* add 8 unsigned bits but keep a 32 bit sum */ 517 /* add 8 unsigned bits but keep a 32 bit sum */
537 chksum += sectorbuf[i]; 518 chksum += sectorbuf[i];
@@ -545,11 +526,11 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
545 } 526 }
546 } 527 }
547 528
548 if (ipod_directory[0].entryOffset>0) { 529 if (ipod->ipod_directory[0].entryOffset>0) {
549 /* Keep the same entryOffset */ 530 /* Keep the same entryOffset */
550 entryOffset = ipod_directory[0].entryOffset; 531 entryOffset = ipod->ipod_directory[0].entryOffset;
551 } else { 532 } else {
552 entryOffset = (ipod_directory[0].len+sector_size-1)&~(sector_size-1); 533 entryOffset = (ipod->ipod_directory[0].len+ipod->sector_size-1)&~(ipod->sector_size-1);
553 } 534 }
554 535
555 if (entryOffset+paddedlength > BUFFER_SIZE) { 536 if (entryOffset+paddedlength > BUFFER_SIZE) {
@@ -559,20 +540,20 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
559 } 540 }
560 541
561 if (verbose) { 542 if (verbose) {
562 fprintf(stderr,"[VERB] Original firmware begins at 0x%08x\n",ipod_directory[0].devOffset + sector_size); 543 fprintf(stderr,"[VERB] Original firmware begins at 0x%08x\n", ipod->ipod_directory[0].devOffset + ipod->sector_size);
563 fprintf(stderr,"[VERB] New entryOffset will be 0x%08x\n",entryOffset); 544 fprintf(stderr,"[VERB] New entryOffset will be 0x%08x\n",entryOffset);
564 fprintf(stderr,"[VERB] End of bootloader will be at 0x%08x\n",entryOffset+paddedlength); 545 fprintf(stderr,"[VERB] End of bootloader will be at 0x%08x\n",entryOffset+paddedlength);
565 } 546 }
566 547
567 /* Check if we have enough space */ 548 /* Check if we have enough space */
568 /* TODO: Check the size of the partition. */ 549 /* TODO: Check the size of the partition. */
569 if (nimages > 1) { 550 if (ipod->nimages > 1) {
570 if ((entryOffset+paddedlength) >= ipod_directory[1].devOffset) { 551 if ((entryOffset+paddedlength) >= ipod->ipod_directory[1].devOffset) {
571 fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); 552 fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n");
572 delta = ipod_directory[0].devOffset + entryOffset+paddedlength 553 delta = ipod->ipod_directory[0].devOffset + entryOffset+paddedlength
573 - ipod_directory[1].devOffset; 554 - ipod->ipod_directory[1].devOffset;
574 555
575 if (diskmove(dh,start,nimages,ipod_directory,sector_size,delta) < 0) { 556 if (diskmove(ipod, delta) < 0) {
576 close(infile); 557 close(infile);
577 fprintf(stderr,"[ERR] Image movement failed.\n"); 558 fprintf(stderr,"[ERR] Image movement failed.\n");
578 return -1; 559 return -1;
@@ -586,12 +567,12 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
586 /* Firstly read the original firmware into sectorbuf */ 567 /* Firstly read the original firmware into sectorbuf */
587 fprintf(stderr,"[INFO] Reading original firmware...\n"); 568 fprintf(stderr,"[INFO] Reading original firmware...\n");
588 569
589 if (ipod_seek(dh,start+sector_size+ipod_directory[0].devOffset) < 0) { 570 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) {
590 fprintf(stderr,"[ERR] Seek failed\n"); 571 fprintf(stderr,"[ERR] Seek failed\n");
591 return -1; 572 return -1;
592 } 573 }
593 574
594 if ((n = ipod_read(dh,sectorbuf,entryOffset)) < 0) { 575 if ((n = ipod_read(ipod,sectorbuf,entryOffset)) < 0) {
595 perror("[ERR] Read failed\n"); 576 perror("[ERR] Read failed\n");
596 return -1; 577 return -1;
597 } 578 }
@@ -620,12 +601,12 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
620 601
621 /* Now write the combined firmware image to the disk */ 602 /* Now write the combined firmware image to the disk */
622 603
623 if (ipod_seek(dh,start+sector_size+ipod_directory[0].devOffset) < 0) { 604 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) {
624 fprintf(stderr,"[ERR] Seek failed\n"); 605 fprintf(stderr,"[ERR] Seek failed\n");
625 return -1; 606 return -1;
626 } 607 }
627 608
628 if ((n = ipod_write(dh,sectorbuf,entryOffset+paddedlength)) < 0) { 609 if ((n = ipod_write(ipod,sectorbuf,entryOffset+paddedlength)) < 0) {
629 perror("[ERR] Write failed\n"); 610 perror("[ERR] Write failed\n");
630 return -1; 611 return -1;
631 } 612 }
@@ -638,36 +619,48 @@ int add_bootloader(HANDLE dh, int type, char* filename, int start, int sector_si
638 619
639 fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",entryOffset+paddedlength); 620 fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",entryOffset+paddedlength);
640 621
641 x = diroffset % sector_size; 622 x = ipod->diroffset % ipod->sector_size;
642 623
643 /* Read directory */ 624 /* Read directory */
644 if (ipod_seek(dh,start + diroffset - x) < 0) { return -1; } 625 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) {
626 fprintf(stderr,"[ERR] Seek failed\n");
627 return -1;
628 }
645 629
646 n=ipod_read(dh, sectorbuf, sector_size); 630 n=ipod_read(ipod, sectorbuf, ipod->sector_size);
647 if (n < 0) { return -1; } 631 if (n < 0) {
632 fprintf(stderr,"[ERR] Directory read failed\n");
633 return -1;
634 }
648 635
649 /* Update entries for image 0 */ 636 /* Update entries for image 0 */
650 int2le(entryOffset+length,sectorbuf+x+16); 637 int2le(entryOffset+length,sectorbuf+x+16);
651 int2le(entryOffset,sectorbuf+x+24); 638 int2le(entryOffset,sectorbuf+x+24);
652 int2le(chksum,sectorbuf+x+28); 639 int2le(chksum,sectorbuf+x+28);
640 int2le(0xffffffff,sectorbuf+x+36); /* loadAddr */
653 641
654 /* Update devOffset entries for other images, if we have moved them */ 642 /* Update devOffset entries for other images, if we have moved them */
655 if (delta > 0) { 643 if (delta > 0) {
656 for (i=1;i<nimages;i++) { 644 for (i=1;i<ipod->nimages;i++) {
657 int2le(le2int(sectorbuf+x+i*40+12)+delta,sectorbuf+x+i*40+12); 645 int2le(le2int(sectorbuf+x+i*40+12)+delta,sectorbuf+x+i*40+12);
658 } 646 }
659 } 647 }
660 648
661 /* Write directory */ 649 /* Write directory */
662 if (ipod_seek(dh,start + diroffset - x) < 0) { return -1; } 650 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) {
663 n=ipod_write(dh, sectorbuf, sector_size); 651 fprintf(stderr,"[ERR] Seek to %ld failed\n", ipod->start+ipod->diroffset-x);
664 if (n < 0) { return -1; } 652 return -1;
653 }
654 n=ipod_write(ipod, sectorbuf, ipod->sector_size);
655 if (n < 0) {
656 fprintf(stderr,"[ERR] Directory write failed\n");
657 return -1;
658 }
665 659
666 return 0; 660 return 0;
667} 661}
668 662
669int delete_bootloader(HANDLE dh, int start, int sector_size, off_t diroffset, 663int delete_bootloader(struct ipod_t* ipod)
670 struct ipod_directory_t* ipod_directory)
671{ 664{
672 int length; 665 int length;
673 int i; 666 int i;
@@ -681,25 +674,25 @@ int delete_bootloader(HANDLE dh, int start, int sector_size, off_t diroffset,
681 674
682 /* Firstly check we have a bootloader... */ 675 /* Firstly check we have a bootloader... */
683 676
684 if (ipod_directory[0].entryOffset == 0) { 677 if (ipod->ipod_directory[0].entryOffset == 0) {
685 fprintf(stderr,"[ERR] No bootloader found.\n"); 678 fprintf(stderr,"[ERR] No bootloader found.\n");
686 return -1; 679 return -1;
687 } 680 }
688 681
689 length = ipod_directory[0].entryOffset; 682 length = ipod->ipod_directory[0].entryOffset;
690 683
691 /* Read the firmware so we can calculate the checksum */ 684 /* Read the firmware so we can calculate the checksum */
692 fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length); 685 fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length);
693 686
694 if (ipod_seek(dh,start+sector_size+ipod_directory[0].devOffset) < 0) { 687 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) {
695 return -1; 688 return -1;
696 } 689 }
697 690
698 i = (length+sector_size-1) & ~(sector_size-1); 691 i = (length+ipod->sector_size-1) & ~(ipod->sector_size-1);
699 fprintf(stderr,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n", 692 fprintf(stderr,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n",
700 length,i); 693 length,i);
701 694
702 if ((n = ipod_read(dh,sectorbuf,i)) < 0) { 695 if ((n = ipod_read(ipod,sectorbuf,i)) < 0) {
703 return -1; 696 return -1;
704 } 697 }
705 698
@@ -719,12 +712,12 @@ int delete_bootloader(HANDLE dh, int start, int sector_size, off_t diroffset,
719 712
720 fprintf(stderr,"[INFO] Updating firmware checksum\n"); 713 fprintf(stderr,"[INFO] Updating firmware checksum\n");
721 714
722 x = diroffset % sector_size; 715 x = ipod->diroffset % ipod->sector_size;
723 716
724 /* Read directory */ 717 /* Read directory */
725 if (ipod_seek(dh,start + diroffset - x) < 0) { return -1; } 718 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
726 719
727 n=ipod_read(dh, sectorbuf, sector_size); 720 n=ipod_read(ipod, sectorbuf, ipod->sector_size);
728 if (n < 0) { return -1; } 721 if (n < 0) { return -1; }
729 722
730 /* Update entries for image 0 */ 723 /* Update entries for image 0 */
@@ -733,16 +726,14 @@ int delete_bootloader(HANDLE dh, int start, int sector_size, off_t diroffset,
733 int2le(chksum,sectorbuf+x+28); 726 int2le(chksum,sectorbuf+x+28);
734 727
735 /* Write directory */ 728 /* Write directory */
736 if (ipod_seek(dh,start + diroffset - x) < 0) { return -1; } 729 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
737 n=ipod_write(dh, sectorbuf, sector_size); 730 n=ipod_write(ipod, sectorbuf, ipod->sector_size);
738 if (n < 0) { return -1; } 731 if (n < 0) { return -1; }
739 732
740 return 0; 733 return 0;
741} 734}
742 735
743int write_firmware(HANDLE dh, char* filename, int start, int sector_size, 736int write_firmware(struct ipod_t* ipod, char* filename, int type)
744 int nimages, struct ipod_directory_t* ipod_directory,
745 off_t diroffset, int modelnum, char* modelname)
746{ 737{
747 int length; 738 int length;
748 int i; 739 int i;
@@ -762,24 +753,28 @@ int write_firmware(HANDLE dh, char* filename, int start, int sector_size,
762 return -1; 753 return -1;
763 } 754 }
764 755
765 n = read(infile,header,8); 756 if (type==DOT_IPOD) {
766 if (n < 8) { 757 n = read(infile,header,8);
767 fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); 758 if (n < 8) {
768 close(infile); 759 fprintf(stderr,"[ERR] Failed to read header from %s\n",filename);
769 return -1; 760 close(infile);
770 } 761 return -1;
762 }
771 763
772 if (memcmp(header+4,modelname,4)!=0) { 764 if (memcmp(header+4, ipod->modelname,4)!=0) {
773 fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n", 765 fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n",
774 header[4],header[5],header[6],header[7],modelname); 766 header[4],header[5],header[6],header[7], ipod->modelname);
775 close(infile); 767 close(infile);
776 return -1; 768 return -1;
777 } 769 }
778 770
779 filechksum = be2int(header); 771 filechksum = be2int(header);
780 772
781 length=filesize(infile)-8; 773 length = filesize(infile)-8;
782 newsize=(length+sector_size-1)&~(sector_size-1); 774 } else {
775 length = filesize(infile);
776 }
777 newsize=(length+ipod->sector_size-1)&~(ipod->sector_size-1);
783 778
784 fprintf(stderr,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n", 779 fprintf(stderr,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n",
785 length,newsize); 780 length,newsize);
@@ -792,8 +787,8 @@ int write_firmware(HANDLE dh, char* filename, int start, int sector_size,
792 787
793 /* Check if we have enough space */ 788 /* Check if we have enough space */
794 /* TODO: Check the size of the partition. */ 789 /* TODO: Check the size of the partition. */
795 if (nimages > 1) { 790 if (ipod->nimages > 1) {
796 bytesavailable=ipod_directory[1].devOffset-ipod_directory[0].devOffset; 791 bytesavailable=ipod->ipod_directory[1].devOffset-ipod->ipod_directory[0].devOffset;
797 if (bytesavailable < newsize) { 792 if (bytesavailable < newsize) {
798 fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); 793 fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n");
799 794
@@ -815,25 +810,27 @@ int write_firmware(HANDLE dh, char* filename, int start, int sector_size,
815 } 810 }
816 close(infile); 811 close(infile);
817 812
818 chksum = modelnum; 813 if (type==DOT_IPOD) {
819 for (i = 0; i < length; i++) { 814 chksum = ipod->modelnum;
820 /* add 8 unsigned bits but keep a 32 bit sum */ 815 for (i = 0; i < length; i++) {
821 chksum += sectorbuf[i]; 816 /* add 8 unsigned bits but keep a 32 bit sum */
822 } 817 chksum += sectorbuf[i];
818 }
823 819
824 if (chksum == filechksum) { 820 if (chksum == filechksum) {
825 fprintf(stderr,"[INFO] Checksum OK in %s\n",filename); 821 fprintf(stderr,"[INFO] Checksum OK in %s\n",filename);
826 } else { 822 } else {
827 fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename); 823 fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename);
828 return -1; 824 return -1;
825 }
829 } 826 }
830 827
831 if (ipod_seek(dh,start+sector_size+ipod_directory[0].devOffset) < 0) { 828 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) {
832 fprintf(stderr,"[ERR] Seek failed\n"); 829 fprintf(stderr,"[ERR] Seek failed\n");
833 return -1; 830 return -1;
834 } 831 }
835 832
836 if ((n = ipod_write(dh,sectorbuf,newsize)) < 0) { 833 if ((n = ipod_write(ipod,sectorbuf,newsize)) < 0) {
837 perror("[ERR] Write failed\n"); 834 perror("[ERR] Write failed\n");
838 return -1; 835 return -1;
839 } 836 }
@@ -852,12 +849,12 @@ int write_firmware(HANDLE dh, char* filename, int start, int sector_size,
852 chksum += sectorbuf[i]; 849 chksum += sectorbuf[i];
853 } 850 }
854 851
855 x = diroffset % sector_size; 852 x = ipod->diroffset % ipod->sector_size;
856 853
857 /* Read directory */ 854 /* Read directory */
858 if (ipod_seek(dh,start + diroffset - x) < 0) { return -1; } 855 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
859 856
860 n=ipod_read(dh, sectorbuf, sector_size); 857 n=ipod_read(ipod, sectorbuf, ipod->sector_size);
861 if (n < 0) { return -1; } 858 if (n < 0) { return -1; }
862 859
863 /* Update entries for image 0 */ 860 /* Update entries for image 0 */
@@ -866,16 +863,14 @@ int write_firmware(HANDLE dh, char* filename, int start, int sector_size,
866 int2le(chksum,sectorbuf+x+28); 863 int2le(chksum,sectorbuf+x+28);
867 864
868 /* Write directory */ 865 /* Write directory */
869 if (ipod_seek(dh,start + diroffset - x) < 0) { return -1; } 866 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
870 n=ipod_write(dh, sectorbuf, sector_size); 867 n=ipod_write(ipod, sectorbuf, ipod->sector_size);
871 if (n < 0) { return -1; } 868 if (n < 0) { return -1; }
872 869
873 return 0; 870 return 0;
874} 871}
875 872
876int read_firmware(HANDLE dh, char* filename, int start, int sector_size, 873int read_firmware(struct ipod_t* ipod, char* filename)
877 struct ipod_directory_t* ipod_directory,
878 int modelnum, char* modelname)
879{ 874{
880 int length; 875 int length;
881 int i; 876 int i;
@@ -884,24 +879,24 @@ int read_firmware(HANDLE dh, char* filename, int start, int sector_size,
884 unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/ 879 unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/
885 unsigned char header[8]; /* Header for .ipod file */ 880 unsigned char header[8]; /* Header for .ipod file */
886 881
887 if (ipod_directory[0].entryOffset != 0) { 882 if (ipod->ipod_directory[0].entryOffset != 0) {
888 /* We have a bootloader... */ 883 /* We have a bootloader... */
889 length = ipod_directory[0].entryOffset; 884 length = ipod->ipod_directory[0].entryOffset;
890 } else { 885 } else {
891 length = ipod_directory[0].len; 886 length = ipod->ipod_directory[0].len;
892 } 887 }
893 888
894 fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length); 889 fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length);
895 890
896 if (ipod_seek(dh,start+sector_size+ipod_directory[0].devOffset) < 0) { 891 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) {
897 return -1; 892 return -1;
898 } 893 }
899 894
900 i = (length+sector_size-1) & ~(sector_size-1); 895 i = (length+ipod->sector_size-1) & ~(ipod->sector_size-1);
901 fprintf(stderr,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n", 896 fprintf(stderr,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n",
902 length,i); 897 length,i);
903 898
904 if ((n = ipod_read(dh,sectorbuf,i)) < 0) { 899 if ((n = ipod_read(ipod,sectorbuf,i)) < 0) {
905 return -1; 900 return -1;
906 } 901 }
907 902
@@ -911,14 +906,14 @@ int read_firmware(HANDLE dh, char* filename, int start, int sector_size,
911 return -1; 906 return -1;
912 } 907 }
913 908
914 chksum = modelnum; 909 chksum = ipod->modelnum;
915 for (i = 0; i < length; i++) { 910 for (i = 0; i < length; i++) {
916 /* add 8 unsigned bits but keep a 32 bit sum */ 911 /* add 8 unsigned bits but keep a 32 bit sum */
917 chksum += sectorbuf[i]; 912 chksum += sectorbuf[i];
918 } 913 }
919 914
920 int2be(chksum,header); 915 int2be(chksum,header);
921 memcpy(header+4,modelname,4); 916 memcpy(header+4, ipod->modelname,4);
922 917
923 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666); 918 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666);
924 if (outfile < 0) { 919 if (outfile < 0) {
@@ -933,25 +928,25 @@ int read_firmware(HANDLE dh, char* filename, int start, int sector_size,
933 return 0; 928 return 0;
934} 929}
935 930
936int read_directory(HANDLE dh, int start, int sector_size, 931int read_directory(struct ipod_t* ipod)
937 struct ipod_directory_t* ipod_directory, off_t* diroffset)
938{ 932{
939 int n; 933 int n;
940 int x; 934 int x;
941 int nimages;
942 unsigned char* p; 935 unsigned char* p;
936 unsigned short version;
943 937
944 /* Read firmware partition header (first 512 bytes of disk - but 938 /* Read firmware partition header (first 512 bytes of disk - but
945 let's read a whole sector) */ 939 let's read a whole sector) */
946 940
947 if (ipod_seek(dh, start) < 0) { 941 if (ipod_seek(ipod, ipod->start) < 0) {
948 fprintf(stderr,"[ERR] Seek to 0x%08x in read_directory() failed.\n",start); 942 fprintf(stderr,"[ERR] Seek to 0x%08x in read_directory() failed.\n",
943 (unsigned int)(ipod->start));
949 return -1; 944 return -1;
950 } 945 }
951 946
952 n=ipod_read(dh, sectorbuf, sector_size); 947 n=ipod_read(ipod, sectorbuf, ipod->sector_size);
953 if (n < 0) { 948 if (n < 0) {
954 fprintf(stderr,"[ERR] ipod_read(dh,buf,0x%08x) failed in read_directory()\n",sector_size); 949 fprintf(stderr,"[ERR] ipod_read(ipod,buf,0x%08x) failed in read_directory()\n", ipod->sector_size);
955 return -1; 950 return -1;
956 } 951 }
957 952
@@ -965,82 +960,99 @@ int read_directory(HANDLE dh, int start, int sector_size,
965 return -1; 960 return -1;
966 } 961 }
967 962
968 *diroffset=le2int(sectorbuf+0x104) + 0x200; 963 version = le2ushort(sectorbuf+0x10a);
964 if ((version != 2) && (version != 3)) {
965 fprintf(stderr,"[ERR] Unknown firmware format version %04x\n",
966 version);
967 }
968 ipod->diroffset=le2int(sectorbuf+0x104) + 0x200;
969 969
970 /* diroffset may not be sector-aligned */ 970 /* diroffset may not be sector-aligned */
971 x = *diroffset % sector_size; 971 x = ipod->diroffset % ipod->sector_size;
972 972
973 /* Read directory */ 973 /* Read directory */
974 if (ipod_seek(dh,start + *diroffset - x) < 0) { 974 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) {
975 fprintf(stderr,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)*diroffset); 975 fprintf(stderr,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod->diroffset);
976 return -1; 976 return -1;
977 } 977 }
978 978
979 n=ipod_read(dh, sectorbuf, sector_size); 979 n=ipod_read(ipod, sectorbuf, ipod->sector_size);
980 if (n < 0) { 980 if (n < 0) {
981 fprintf(stderr,"[ERR] Read of directory failed.\n"); 981 fprintf(stderr,"[ERR] Read of directory failed.\n");
982 return -1; 982 return -1;
983 } 983 }
984 984
985 nimages=0; 985 ipod->nimages=0;
986 p = sectorbuf + x; 986 p = sectorbuf + x;
987 987
988 while ((nimages < MAX_IMAGES) && (p < (sectorbuf + x + 400)) && 988 while ((ipod->nimages < MAX_IMAGES) && (p < (sectorbuf + x + 400)) &&
989 (memcmp(p,"!ATA",4)==0)) { 989 (memcmp(p,"!ATA",4)==0)) {
990 p+=4; 990 p+=4;
991 if (memcmp(p,"soso",4)==0) { 991 if (memcmp(p,"soso",4)==0) {
992 ipod_directory[nimages].ftype=FTYPE_OSOS; 992 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_OSOS;
993 } else if (memcmp(p,"crsr",4)==0) { 993 } else if (memcmp(p,"crsr",4)==0) {
994 ipod_directory[nimages].ftype=FTYPE_RSRC; 994 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_RSRC;
995 } else if (memcmp(p,"dpua",4)==0) { 995 } else if (memcmp(p,"dpua",4)==0) {
996 ipod_directory[nimages].ftype=FTYPE_AUPD; 996 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_AUPD;
997 } else if (memcmp(p,"ebih",4)==0) { 997 } else if (memcmp(p,"ebih",4)==0) {
998 ipod_directory[nimages].ftype=FTYPE_HIBE; 998 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_HIBE;
999 } else { 999 } else {
1000 fprintf(stderr,"[ERR] Unknown image type %c%c%c%c\n", 1000 fprintf(stderr,"[ERR] Unknown image type %c%c%c%c\n",
1001 p[0],p[1],p[2],p[3]); 1001 p[0],p[1],p[2],p[3]);
1002 } 1002 }
1003 p+=4; 1003 p+=4;
1004 ipod_directory[nimages].id=le2int(p); 1004 ipod->ipod_directory[ipod->nimages].id=le2int(p);
1005 p+=4; 1005 p+=4;
1006 ipod_directory[nimages].devOffset=le2int(p); 1006 ipod->ipod_directory[ipod->nimages].devOffset=le2int(p);
1007 p+=4; 1007 p+=4;
1008 ipod_directory[nimages].len=le2int(p); 1008 ipod->ipod_directory[ipod->nimages].len=le2int(p);
1009 p+=4; 1009 p+=4;
1010 ipod_directory[nimages].addr=le2int(p); 1010 ipod->ipod_directory[ipod->nimages].addr=le2int(p);
1011 p+=4; 1011 p+=4;
1012 ipod_directory[nimages].entryOffset=le2int(p); 1012 ipod->ipod_directory[ipod->nimages].entryOffset=le2int(p);
1013 p+=4; 1013 p+=4;
1014 ipod_directory[nimages].chksum=le2int(p); 1014 ipod->ipod_directory[ipod->nimages].chksum=le2int(p);
1015 p+=4; 1015 p+=4;
1016 ipod_directory[nimages].vers=le2int(p); 1016 ipod->ipod_directory[ipod->nimages].vers=le2int(p);
1017 p+=4; 1017 p+=4;
1018 ipod_directory[nimages].loadAddr=le2int(p); 1018 ipod->ipod_directory[ipod->nimages].loadAddr=le2int(p);
1019 p+=4; 1019 p+=4;
1020 nimages++; 1020 ipod->nimages++;
1021 }
1022
1023 if ((ipod->nimages > 1) && (version==2)) {
1024 /* The 3g firmware image doesn't appear to have a version, so
1025 let's make one up... Note that this is never written back to the
1026 ipod, so it's OK to do. */
1027
1028 if (ipod->ipod_directory[0].vers == 0) { ipod->ipod_directory[0].vers = 3; }
1029
1030 ipod->fwoffset = ipod->start;
1031 } else {
1032 ipod->fwoffset = ipod->start + ipod->sector_size;
1021 } 1033 }
1022 return nimages; 1034
1035 return 0;
1023} 1036}
1024 1037
1025int list_images(int nimages, struct ipod_directory_t* ipod_directory, 1038int list_images(struct ipod_t* ipod)
1026 int sector_size)
1027{ 1039{
1028 int i; 1040 int i;
1029 1041
1030 if (verbose) { 1042 if (verbose) {
1031 printf(" Type id devOffset len addr entryOffset chksum vers loadAddr devOffset+len\n"); 1043 printf(" Type id devOffset len addr entryOffset chksum vers loadAddr devOffset+len\n");
1032 for (i = 0 ; i < nimages; i++) { 1044 for (i = 0 ; i < ipod->nimages; i++) {
1033 printf("%d - %s 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",i, 1045 printf("%d - %s 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",i,
1034 ftypename[ipod_directory[i].ftype], 1046 ftypename[ipod->ipod_directory[i].ftype],
1035 ipod_directory[i].id, 1047 ipod->ipod_directory[i].id,
1036 ipod_directory[i].devOffset, 1048 ipod->ipod_directory[i].devOffset,
1037 ipod_directory[i].len, 1049 ipod->ipod_directory[i].len,
1038 ipod_directory[i].addr, 1050 ipod->ipod_directory[i].addr,
1039 ipod_directory[i].entryOffset, 1051 ipod->ipod_directory[i].entryOffset,
1040 ipod_directory[i].chksum, 1052 ipod->ipod_directory[i].chksum,
1041 ipod_directory[i].vers, 1053 ipod->ipod_directory[i].vers,
1042 ipod_directory[i].loadAddr, 1054 ipod->ipod_directory[i].loadAddr,
1043 ipod_directory[i].devOffset+sector_size+((ipod_directory[i].len+sector_size-1)&~(sector_size-1))); 1055 ipod->ipod_directory[i].devOffset+((ipod->ipod_directory[i].len+ipod->sector_size-1)&~(ipod->sector_size-1)));
1044 } 1056 }
1045 } 1057 }
1046 1058
@@ -1048,24 +1060,24 @@ int list_images(int nimages, struct ipod_directory_t* ipod_directory,
1048 printf("Listing firmware partition contents:\n"); 1060 printf("Listing firmware partition contents:\n");
1049 printf("\n"); 1061 printf("\n");
1050 1062
1051 for (i = 0 ; i < nimages; i++) { 1063 for (i = 0 ; i < ipod->nimages; i++) {
1052 printf("Image %d:\n",i+1); 1064 printf("Image %d:\n",i+1);
1053 switch(ipod_directory[i].ftype) { 1065 switch(ipod->ipod_directory[i].ftype) {
1054 case FTYPE_OSOS: 1066 case FTYPE_OSOS:
1055 if (ipod_directory[i].entryOffset==0) { 1067 if (ipod->ipod_directory[i].entryOffset==0) {
1056 printf(" Main firmware - %d bytes\n", 1068 printf(" Main firmware - %d bytes\n",
1057 ipod_directory[i].len); 1069 ipod->ipod_directory[i].len);
1058 } else { 1070 } else {
1059 printf(" Main firmware - %d bytes\n", 1071 printf(" Main firmware - %d bytes\n",
1060 ipod_directory[i].entryOffset); 1072 ipod->ipod_directory[i].entryOffset);
1061 printf(" Third-party bootloader - %d bytes\n", 1073 printf(" Third-party bootloader - %d bytes\n",
1062 ipod_directory[i].len-ipod_directory[i].entryOffset); 1074 ipod->ipod_directory[i].len-ipod->ipod_directory[i].entryOffset);
1063 } 1075 }
1064 break; 1076 break;
1065 default: 1077 default:
1066 printf(" %s - %d bytes\n", 1078 printf(" %s - %d bytes\n",
1067 ftypename[ipod_directory[i].ftype], 1079 ftypename[ipod->ipod_directory[i].ftype],
1068 ipod_directory[i].len); 1080 ipod->ipod_directory[i].len);
1069 } 1081 }
1070 } 1082 }
1071 printf("\n"); 1083 printf("\n");
@@ -1073,111 +1085,98 @@ int list_images(int nimages, struct ipod_directory_t* ipod_directory,
1073 return 0; 1085 return 0;
1074} 1086}
1075 1087
1076int getmodel(int ipod_version, char** modelstr, char** modelname, int* modelnum) 1088int getmodel(struct ipod_t* ipod, int ipod_version)
1077{ 1089{
1078 switch (ipod_version) { 1090 switch (ipod_version) {
1079 case 0x3: 1091 case 0x02:
1080 *modelstr="3rd Generation"; 1092 ipod->modelstr="3rd Generation";
1081 *modelnum = 7; 1093 ipod->modelnum = 7;
1082 *modelname = "ip3g"; 1094 ipod->modelname = "ip3g";
1083 break; 1095 break;
1084 case 0x4: 1096 case 0x40:
1085 *modelstr="1st Generation Mini"; 1097 ipod->modelstr="1st Generation Mini";
1086 *modelnum = 9; 1098 ipod->modelnum = 9;
1087 *modelname = "mini"; 1099 ipod->modelname = "mini";
1088 break; 1100 break;
1089 case 0x5: 1101 case 0x50:
1090 *modelstr="4th Generation"; 1102 ipod->modelstr="4th Generation";
1091 *modelnum = 8; 1103 ipod->modelnum = 8;
1092 *modelname = "ip4g"; 1104 ipod->modelname = "ip4g";
1093 break; 1105 break;
1094 case 0x6: 1106 case 0x60:
1095 *modelstr="Photo/Color"; 1107 ipod->modelstr="Photo/Color";
1096 *modelnum = 3; 1108 ipod->modelnum = 3;
1097 *modelname = "ipco"; 1109 ipod->modelname = "ipco";
1098 break; 1110 break;
1099 case 0x7: 1111 case 0x70:
1100 *modelstr="2nd Generation Mini"; 1112 ipod->modelstr="2nd Generation Mini";
1101 *modelnum = 11; 1113 ipod->modelnum = 11;
1102 *modelname = "mn2g"; 1114 ipod->modelname = "mn2g";
1103 break; 1115 break;
1104 case 0xc: 1116 case 0xc0:
1105 *modelstr="1st Generation Nano"; 1117 ipod->modelstr="1st Generation Nano";
1106 *modelnum = 4; 1118 ipod->modelnum = 4;
1107 *modelname = "nano"; 1119 ipod->modelname = "nano";
1108 break; 1120 break;
1109 case 0xb: 1121 case 0xb0:
1110 *modelstr="Video (aka 5th Generation)"; 1122 ipod->modelstr="Video (aka 5th Generation)";
1111 *modelnum = 5; 1123 ipod->modelnum = 5;
1112 *modelname = "ipvd"; 1124 ipod->modelname = "ipvd";
1113 break; 1125 break;
1114 default: 1126 default:
1115 *modelname = NULL; 1127 ipod->modelname = NULL;
1116 *modelnum = 0; 1128 ipod->modelnum = 0;
1117 return -1; 1129 return -1;
1118 } 1130 }
1119 return 0; 1131 return 0;
1120} 1132}
1121 1133
1122int ipod_scan(void) 1134int ipod_scan(struct ipod_t* ipod)
1123{ 1135{
1124 int i; 1136 int i;
1125 int n = 0; 1137 int n = 0;
1126 char devicename[96];
1127 HANDLE dh;
1128 int nimages;
1129 struct partinfo_t pinfo[4]; /* space for 4 partitions on 1 drive */
1130 int ipod_version; 1138 int ipod_version;
1131 off_t diroffset;
1132 char* modelname;
1133 char* modelstr;
1134 int modelnum;
1135 struct ipod_directory_t ipod_directory[MAX_IMAGES];
1136 int sector_size;
1137 1139
1138 printf("[INFO] Scanning disk devices...\n"); 1140 printf("[INFO] Scanning disk devices...\n");
1139 1141
1140 for (i = 0; i < 25 ; i++) { 1142 for (i = 0; i < 25 ; i++) {
1141#ifdef __WIN32__ 1143#ifdef __WIN32__
1142 sprintf(devicename,"\\\\.\\PhysicalDrive%d",i); 1144 sprintf(ipod->diskname,"\\\\.\\PhysicalDrive%d",i);
1143#elif defined(linux) || defined (__linux) 1145#elif defined(linux) || defined (__linux)
1144 sprintf(devicename,"/dev/sd%c",'a'+i); 1146 sprintf(ipod->diskname,"/dev/sd%c",'a'+i);
1145#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ 1147#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
1146 || defined(__bsdi__) || defined(__DragonFly__) 1148 || defined(__bsdi__) || defined(__DragonFly__)
1147 sprintf(devicename,"/dev/da%d",i); 1149 sprintf(ipod->diskname,"/dev/da%d",i);
1148#elif defined(__APPLE__) && defined(__MACH__) 1150#elif defined(__APPLE__) && defined(__MACH__)
1149 sprintf(devicename,"/dev/disk%d",i); 1151 sprintf(ipod->diskname,"/dev/disk%d",i);
1150#else 1152#else
1151 #error No disk paths defined for this platform 1153 #error No disk paths defined for this platform
1152#endif 1154#endif
1153 if (ipod_open(&dh, devicename, &sector_size, 1) < 0) { 1155 if (ipod_open(ipod, 1) < 0) {
1154 continue; 1156 continue;
1155 } 1157 }
1156 1158
1157 if (read_partinfo(dh,sector_size,pinfo,1) < 0) { 1159 if (read_partinfo(ipod,1) < 0) {
1158 continue; 1160 continue;
1159 } 1161 }
1160 1162
1161 if ((pinfo[0].start==0) || (pinfo[0].type != 0)) { 1163 if ((ipod->pinfo[0].start==0) || (ipod->pinfo[0].type != 0)) {
1162 continue; 1164 continue;
1163 } 1165 }
1164 1166
1165 nimages=read_directory(dh, pinfo[0].start*sector_size, sector_size, 1167 if (read_directory(ipod) < 0) {
1166 ipod_directory, &diroffset);
1167
1168 if (nimages < 0) {
1169 continue; 1168 continue;
1170 } 1169 }
1171 1170
1172 ipod_version=(ipod_directory[0].vers>>12) & 0x0f; 1171 ipod_version=(ipod->ipod_directory[0].vers>>8);
1173 if (getmodel(ipod_version,&modelstr,&modelname,&modelnum) < 0) { 1172 if (getmodel(ipod,ipod_version) < 0) {
1174 continue; 1173 continue;
1175 } 1174 }
1176 1175
1177#ifdef __WIN32__ 1176#ifdef __WIN32__
1178 printf("[INFO] Ipod found - %s - disk device %d\n",modelstr,i); 1177 printf("[INFO] Ipod found - %s - disk device %d\n", ipod->modelstr,i);
1179#else 1178#else
1180 printf("[INFO] Ipod found - %s - %s\n",modelstr,devicename); 1179 printf("[INFO] Ipod found - %s - %s\n", ipod->modelstr, ipod->diskname);
1181#endif 1180#endif
1182 n++; 1181 n++;
1183 } 1182 }
@@ -1193,20 +1192,10 @@ int main(int argc, char* argv[])
1193 int i; 1192 int i;
1194 int infile, outfile; 1193 int infile, outfile;
1195 unsigned int inputsize; 1194 unsigned int inputsize;
1196 struct partinfo_t pinfo[4]; /* space for 4 partitions on 1 drive */
1197 int ipod_version;
1198 int nimages;
1199 off_t diroffset;
1200 char* modelname;
1201 char* modelstr;
1202 int modelnum;
1203 char* filename; 1195 char* filename;
1204 struct ipod_directory_t ipod_directory[MAX_IMAGES];
1205 int action = SHOW_INFO; 1196 int action = SHOW_INFO;
1206 int sector_size;
1207 int type; 1197 int type;
1208 char devicename[4096]; 1198 struct ipod_t ipod;
1209 HANDLE dh;
1210 1199
1211 fprintf(stderr,"ipodpatcher v" VERSION " - (C) Dave Chapman 2006\n"); 1200 fprintf(stderr,"ipodpatcher v" VERSION " - (C) Dave Chapman 2006\n");
1212 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n"); 1201 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
@@ -1223,17 +1212,17 @@ int main(int argc, char* argv[])
1223 } 1212 }
1224 1213
1225 if (strcmp(argv[1],"--scan")==0) { 1214 if (strcmp(argv[1],"--scan")==0) {
1226 ipod_scan(); 1215 ipod_scan(&ipod);
1227 return 0; 1216 return 0;
1228 } 1217 }
1229 1218
1230 i = 1; 1219 i = 1;
1231 devicename[0]=0; 1220 ipod.diskname[0]=0;
1232 1221
1233#ifdef __WIN32__ 1222#ifdef __WIN32__
1234 snprintf(devicename,sizeof(devicename),"\\\\.\\PhysicalDrive%s",argv[1]); 1223 snprintf(ipod.diskname,sizeof(ipod.diskname),"\\\\.\\PhysicalDrive%s",argv[1]);
1235#else 1224#else
1236 strncpy(devicename,argv[1],sizeof(devicename)); 1225 strncpy(ipod.diskname,argv[1],sizeof(ipod.diskname));
1237#endif 1226#endif
1238 1227
1239 i = 2; 1228 i = 2;
@@ -1271,6 +1260,15 @@ int main(int argc, char* argv[])
1271 } else if ((strcmp(argv[i],"-wf")==0) || 1260 } else if ((strcmp(argv[i],"-wf")==0) ||
1272 (strcmp(argv[i],"--write-firmware")==0)) { 1261 (strcmp(argv[i],"--write-firmware")==0)) {
1273 action = WRITE_FIRMWARE; 1262 action = WRITE_FIRMWARE;
1263 type = DOT_IPOD;
1264 i++;
1265 if (i == argc) { print_usage(); return 1; }
1266 filename=argv[i];
1267 i++;
1268 } else if ((strcmp(argv[i],"-wfb")==0) ||
1269 (strcmp(argv[i],"--write-firmware-bin")==0)) {
1270 action = WRITE_FIRMWARE;
1271 type = DOT_BIN;
1274 i++; 1272 i++;
1275 if (i == argc) { print_usage(); return 1; } 1273 if (i == argc) { print_usage(); return 1; }
1276 filename=argv[i]; 1274 filename=argv[i];
@@ -1298,91 +1296,83 @@ int main(int argc, char* argv[])
1298 } 1296 }
1299 } 1297 }
1300 1298
1301 if (devicename[0]==0) { 1299 if (ipod.diskname[0]==0) {
1302 print_usage(); 1300 print_usage();
1303 return 1; 1301 return 1;
1304 } 1302 }
1305 1303
1306 if (ipod_open(&dh, devicename, &sector_size, 0) < 0) { 1304 if (ipod_open(&ipod, 0) < 0) {
1307 return 1; 1305 return 1;
1308 } 1306 }
1309 1307
1310 fprintf(stderr,"[INFO] Reading partition table from %s\n",devicename); 1308 fprintf(stderr,"[INFO] Reading partition table from %s\n",ipod.diskname);
1311 fprintf(stderr,"[INFO] Sector size is %d bytes\n",sector_size); 1309 fprintf(stderr,"[INFO] Sector size is %d bytes\n",ipod.sector_size);
1312 1310
1313 if (read_partinfo(dh,sector_size,pinfo,0) < 0) { 1311 if (read_partinfo(&ipod,0) < 0) {
1314 return 2; 1312 return 2;
1315 } 1313 }
1316 1314
1317 display_partinfo(pinfo, sector_size); 1315 display_partinfo(&ipod);
1318 1316
1319 if (pinfo[0].start==0) { 1317 if (ipod.pinfo[0].start==0) {
1320 fprintf(stderr,"[ERR] No partition 0 on disk:\n"); 1318 fprintf(stderr,"[ERR] No partition 0 on disk:\n");
1321 display_partinfo(pinfo, sector_size); 1319 display_partinfo(&ipod);
1322 return 3; 1320 return 3;
1323 } 1321 }
1324 1322
1325 nimages=read_directory(dh, pinfo[0].start*sector_size, sector_size, 1323 read_directory(&ipod);
1326 ipod_directory, &diroffset); 1324
1327 if (nimages <= 0) { 1325 if (ipod.nimages <= 0) {
1328 fprintf(stderr,"[ERR] Failed to read firmware directory - nimages=%d\n",nimages); 1326 fprintf(stderr,"[ERR] Failed to read firmware directory - nimages=%d\n",ipod.nimages);
1329 return 1; 1327 return 1;
1330 } 1328 }
1331 1329
1332 ipod_version=(ipod_directory[0].vers>>12) & 0x0f; 1330 if (getmodel(&ipod,(ipod.ipod_directory[0].vers>>8)) < 0) {
1333 if (getmodel(ipod_version,&modelstr,&modelname,&modelnum) < 0) {
1334 fprintf(stderr,"[ERR] Unknown version number in firmware (%08x)\n", 1331 fprintf(stderr,"[ERR] Unknown version number in firmware (%08x)\n",
1335 ipod_version); 1332 ipod.ipod_directory[0].vers);
1336 return -1; 1333 return -1;
1337 } 1334 }
1338 1335
1339 printf("[INFO] Ipod model: %s\n",modelstr); 1336 printf("[INFO] Ipod model: %s\n",ipod.modelstr);
1340 1337
1341 if (action==LIST_IMAGES) { 1338 if (action==LIST_IMAGES) {
1342 list_images(nimages,ipod_directory,sector_size); 1339 list_images(&ipod);
1343 } else if (action==DELETE_BOOTLOADER) { 1340 } else if (action==DELETE_BOOTLOADER) {
1344 if (ipod_reopen_rw(&dh, devicename) < 0) { 1341 if (ipod_reopen_rw(&ipod) < 0) {
1345 return 5; 1342 return 5;
1346 } 1343 }
1347 1344
1348 if (ipod_directory[0].entryOffset==0) { 1345 if (ipod.ipod_directory[0].entryOffset==0) {
1349 fprintf(stderr,"[ERR] No bootloader detected.\n"); 1346 fprintf(stderr,"[ERR] No bootloader detected.\n");
1350 } else { 1347 } else {
1351 if (delete_bootloader(dh, pinfo[0].start*sector_size, sector_size, 1348 if (delete_bootloader(&ipod)==0) {
1352 diroffset, ipod_directory)==0) {
1353 fprintf(stderr,"[INFO] Bootloader removed.\n"); 1349 fprintf(stderr,"[INFO] Bootloader removed.\n");
1354 } else { 1350 } else {
1355 fprintf(stderr,"[ERR] --delete-bootloader failed.\n"); 1351 fprintf(stderr,"[ERR] --delete-bootloader failed.\n");
1356 } 1352 }
1357 } 1353 }
1358 } else if (action==ADD_BOOTLOADER) { 1354 } else if (action==ADD_BOOTLOADER) {
1359 if (ipod_reopen_rw(&dh, devicename) < 0) { 1355 if (ipod_reopen_rw(&ipod) < 0) {
1360 return 5; 1356 return 5;
1361 } 1357 }
1362 1358
1363 if (add_bootloader(dh, type, filename,pinfo[0].start*sector_size, 1359 if (add_bootloader(&ipod, filename, type)==0) {
1364 sector_size, nimages, ipod_directory, diroffset,
1365 modelnum, modelname)==0) {
1366 fprintf(stderr,"[INFO] Bootloader %s written to device.\n",filename); 1360 fprintf(stderr,"[INFO] Bootloader %s written to device.\n",filename);
1367 } else { 1361 } else {
1368 fprintf(stderr,"[ERR] --add-bootloader failed.\n"); 1362 fprintf(stderr,"[ERR] --add-bootloader failed.\n");
1369 } 1363 }
1370 } else if (action==WRITE_FIRMWARE) { 1364 } else if (action==WRITE_FIRMWARE) {
1371 if (ipod_reopen_rw(&dh, devicename) < 0) { 1365 if (ipod_reopen_rw(&ipod) < 0) {
1372 return 5; 1366 return 5;
1373 } 1367 }
1374 1368
1375 if (write_firmware(dh, filename,pinfo[0].start*sector_size, 1369 if (write_firmware(&ipod, filename,type)==0) {
1376 sector_size, nimages, ipod_directory, diroffset,
1377 modelnum, modelname)==0) {
1378 fprintf(stderr,"[INFO] Firmware %s written to device.\n",filename); 1370 fprintf(stderr,"[INFO] Firmware %s written to device.\n",filename);
1379 } else { 1371 } else {
1380 fprintf(stderr,"[ERR] --write-firmware failed.\n"); 1372 fprintf(stderr,"[ERR] --write-firmware failed.\n");
1381 } 1373 }
1382 } else if (action==READ_FIRMWARE) { 1374 } else if (action==READ_FIRMWARE) {
1383 if (read_firmware(dh, filename,pinfo[0].start*sector_size, 1375 if (read_firmware(&ipod, filename)==0) {
1384 sector_size, ipod_directory, modelnum, modelname
1385 )==0) {
1386 fprintf(stderr,"[INFO] Firmware read to file %s.\n",filename); 1376 fprintf(stderr,"[INFO] Firmware read to file %s.\n",filename);
1387 } else { 1377 } else {
1388 fprintf(stderr,"[ERR] --read-firmware failed.\n"); 1378 fprintf(stderr,"[ERR] --read-firmware failed.\n");
@@ -1394,15 +1384,14 @@ int main(int argc, char* argv[])
1394 return 4; 1384 return 4;
1395 } 1385 }
1396 1386
1397 if (read_partition(dh, outfile, pinfo[0].start, pinfo[0].size, 1387 if (read_partition(&ipod, outfile) < 0) {
1398 sector_size) < 0) {
1399 fprintf(stderr,"[ERR] --read-partition failed.\n"); 1388 fprintf(stderr,"[ERR] --read-partition failed.\n");
1400 } else { 1389 } else {
1401 fprintf(stderr,"[INFO] Partition extracted to %s.\n",filename); 1390 fprintf(stderr,"[INFO] Partition extracted to %s.\n",filename);
1402 } 1391 }
1403 close(outfile); 1392 close(outfile);
1404 } else if (action==WRITE_PARTITION) { 1393 } else if (action==WRITE_PARTITION) {
1405 if (ipod_reopen_rw(&dh, devicename) < 0) { 1394 if (ipod_reopen_rw(&ipod) < 0) {
1406 return 5; 1395 return 5;
1407 } 1396 }
1408 1397
@@ -1415,10 +1404,9 @@ int main(int argc, char* argv[])
1415 /* Check filesize is <= partition size */ 1404 /* Check filesize is <= partition size */
1416 inputsize=filesize(infile); 1405 inputsize=filesize(infile);
1417 if (inputsize > 0) { 1406 if (inputsize > 0) {
1418 if (inputsize <= (pinfo[0].size*sector_size)) { 1407 if (inputsize <= (ipod.pinfo[0].size*ipod.sector_size)) {
1419 fprintf(stderr,"[INFO] Input file is %u bytes\n",inputsize); 1408 fprintf(stderr,"[INFO] Input file is %u bytes\n",inputsize);
1420 if (write_partition(dh,infile,pinfo[0].start, 1409 if (write_partition(&ipod,infile) < 0) {
1421 sector_size) < 0) {
1422 fprintf(stderr,"[ERR] --write-partition failed.\n"); 1410 fprintf(stderr,"[ERR] --write-partition failed.\n");
1423 } else { 1411 } else {
1424 fprintf(stderr,"[INFO] %s restored to partition\n",filename); 1412 fprintf(stderr,"[INFO] %s restored to partition\n",filename);
@@ -1431,7 +1419,7 @@ int main(int argc, char* argv[])
1431 close(infile); 1419 close(infile);
1432 } 1420 }
1433 1421
1434 ipod_close(dh); 1422 ipod_close(&ipod);
1435 1423
1436 return 0; 1424 return 0;
1437} 1425}