1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006-2007 Dave Chapman
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
27 #include <sys/types.h>
30 #include "parttypes.h"
32 #include "ipodpatcher.h"
39 #include "ipodmini2g.h"
40 #include "ipodcolor.h"
42 #include "ipodvideo.h"
51 unsigned char* ipod_sectorbuf
;
53 /* The following string appears at the start of the firmware partition */
54 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
71 /* Windows requires the buffer for disk I/O to be aligned in memory on a
72 multiple of the disk volume size - so we use a single global variable
73 and initialise it with ipod_alloc_buf()
76 char* get_parttype(int pt
)
79 static char unknown
[]="Unknown";
81 if (pt
== PARTTYPE_HFS
) {
86 while (parttypes
[i
].name
!= NULL
) {
87 if (parttypes
[i
].type
== pt
) {
88 return (parttypes
[i
].name
);
96 off_t
filesize(int fd
) {
99 if (fstat(fd
,&buf
) < 0) {
100 perror("[ERR] Checking filesize of input file");
107 /* Partition table parsing code taken from Rockbox */
109 #define MAX_SECTOR_SIZE 2048
110 #define SECTOR_SIZE 512
112 static inline unsigned short le2ushort(unsigned char* buf
)
114 unsigned short res
= (buf
[1] << 8) | buf
[0];
119 static inline int le2int(unsigned char* buf
)
121 int32_t res
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
126 static inline int be2int(unsigned char* buf
)
128 int32_t res
= (buf
[0] << 24) | (buf
[1] << 16) | (buf
[2] << 8) | buf
[3];
133 static inline int getint16le(char* buf
)
135 int16_t res
= (buf
[1] << 8) | buf
[0];
140 static inline void short2le(unsigned short val
, unsigned char* addr
)
142 addr
[0] = val
& 0xFF;
143 addr
[1] = (val
>> 8) & 0xff;
146 static inline void int2le(unsigned int val
, unsigned char* addr
)
148 addr
[0] = val
& 0xFF;
149 addr
[1] = (val
>> 8) & 0xff;
150 addr
[2] = (val
>> 16) & 0xff;
151 addr
[3] = (val
>> 24) & 0xff;
154 static inline void int2be(unsigned int val
, unsigned char* addr
)
156 addr
[0] = (val
>> 24) & 0xff;
157 addr
[1] = (val
>> 16) & 0xff;
158 addr
[2] = (val
>> 8) & 0xff;
159 addr
[3] = val
& 0xFF;
163 #define BYTES2INT32(array,pos)\
164 ((long)array[pos] | ((long)array[pos+1] << 8 ) |\
165 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
167 int read_partinfo(struct ipod_t
* ipod
, int silent
)
172 count
= ipod_read(ipod
,ipod_sectorbuf
, ipod
->sector_size
);
175 print_error(" Error reading from disk: ");
179 memset(ipod
->pinfo
, 0, sizeof(ipod
->pinfo
));
181 if ((ipod_sectorbuf
[510] == 0x55) && (ipod_sectorbuf
[511] == 0xaa)) {
182 /* DOS partition table */
184 /* parse partitions */
185 for ( i
= 0; i
< 4; i
++ ) {
186 unsigned char* ptr
= ipod_sectorbuf
+ 0x1be + 16*i
;
187 ipod
->pinfo
[i
].type
= ptr
[4];
188 ipod
->pinfo
[i
].start
= BYTES2INT32(ptr
, 8);
189 ipod
->pinfo
[i
].size
= BYTES2INT32(ptr
, 12);
192 if ( ipod
->pinfo
[i
].type
== 5 ) {
193 /* not handled yet */
196 } else if ((ipod_sectorbuf
[0] == 'E') && (ipod_sectorbuf
[1] == 'R')) {
197 /* Apple Partition Map */
199 /* APM parsing code based on the check_mac_partitions() function in
200 ipodloader2 - written by Thomas Tempelmann and released
204 int partBlkCount
= 1;
205 int partBlkSizMul
= ipod_sectorbuf
[2] / 2;
207 int pmMapBlkCnt
; /* # of blks in partition map */
208 int pmPyPartStart
; /* physical start blk of partition */
209 int pmPartBlkCnt
; /* # of blks in this partition */
214 memset(ipod
->pinfo
,0,sizeof(ipod
->pinfo
));
216 while (blkNo
<= partBlkCount
) {
217 if (ipod_seek(ipod
, blkNo
* partBlkSizMul
* 512) < 0) {
218 fprintf(stderr
,"[ERR] Seek failed whilst reading APM\n");
222 count
= ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
225 print_error(" Error reading from disk: ");
229 /* see if it's a partition entry */
230 if ((ipod_sectorbuf
[0] != 'P') || (ipod_sectorbuf
[1] != 'M')) {
231 /* end of partition table -> leave the loop */
235 /* Extract the interesting entries */
236 pmMapBlkCnt
= be2int(ipod_sectorbuf
+ 4);
237 pmPyPartStart
= be2int(ipod_sectorbuf
+ 8);
238 pmPartBlkCnt
= be2int(ipod_sectorbuf
+ 12);
240 /* update the number of part map blocks */
241 partBlkCount
= pmMapBlkCnt
;
243 if (strncmp((char*)(ipod_sectorbuf
+ 48), "Apple_MDFW", 32)==0) {
244 /* A Firmware partition */
245 ipod
->pinfo
[i
].start
= pmPyPartStart
;
246 ipod
->pinfo
[i
].size
= pmPartBlkCnt
;
247 ipod
->pinfo
[i
].type
= 0;
249 } else if (strncmp((char*)(ipod_sectorbuf
+ 48), "Apple_HFS", 32)==0) {
250 /* A HFS partition */
251 ipod
->pinfo
[i
].start
= pmPyPartStart
;
252 ipod
->pinfo
[i
].size
= pmPartBlkCnt
;
253 ipod
->pinfo
[i
].type
= PARTTYPE_HFS
;
257 blkNo
++; /* read next partition map entry */
260 if (!silent
) fprintf(stderr
,"[ERR] Bad boot sector signature\n");
264 /* Check that the partition table looks like an ipod:
265 1) Partition 1 is of type 0 (Empty) but isn't empty.
266 2) Partition 2 is of type 0xb or 0xc (winpod) or -1 (macpod)
268 if ((ipod
->pinfo
[0].type
!= 0) || (ipod
->pinfo
[0].size
== 0) ||
269 ((ipod
->pinfo
[1].type
!= 0xb) && (ipod
->pinfo
[1].type
!= 0xc) &&
270 (ipod
->pinfo
[1].type
!= PARTTYPE_HFS
))) {
271 if (!silent
) fprintf(stderr
,"[ERR] Partition layout is not an ipod\n");
275 ipod
->start
= ipod
->pinfo
[0].start
*ipod
->sector_size
;
279 int read_partition(struct ipod_t
* ipod
, int outfile
)
285 int count
= ipod
->pinfo
[0].size
;
287 if (ipod_seek(ipod
, ipod
->start
) < 0) {
291 fprintf(stderr
,"[INFO] Writing %d sectors to output file\n",count
);
293 bytesleft
= count
* ipod
->sector_size
;
294 while (bytesleft
> 0) {
295 if (bytesleft
> BUFFER_SIZE
) {
296 chunksize
= BUFFER_SIZE
;
298 chunksize
= bytesleft
;
301 n
= ipod_read(ipod
, ipod_sectorbuf
, chunksize
);
309 "[ERR] Short read in disk_read() - requested %d, got %d\n",
316 res
= write(outfile
,ipod_sectorbuf
,n
);
319 perror("[ERR] write in disk_read");
325 "Short write - requested %d, received %d - aborting.\n",(int)n
,res
);
330 fprintf(stderr
,"[INFO] Done.\n");
334 int write_partition(struct ipod_t
* ipod
, int infile
)
339 int byteswritten
= 0;
343 if (ipod_seek(ipod
, ipod
->start
) < 0) {
347 fprintf(stderr
,"[INFO] Writing input file to device\n");
351 n
= read(infile
,ipod_sectorbuf
,BUFFER_SIZE
);
354 perror("[ERR] read in disk_write");
358 if (n
< BUFFER_SIZE
) {
360 /* We need to pad the last write to a multiple of SECTOR_SIZE */
361 if ((n
% ipod
->sector_size
) != 0) {
362 padding
= (ipod
->sector_size
-(n
% ipod
->sector_size
));
369 res
= ipod_write(ipod
, ipod_sectorbuf
, n
);
372 print_error(" Error writing to disk: ");
373 fprintf(stderr
,"Bytes written: %d\n",byteswritten
);
378 fprintf(stderr
,"[ERR] Short write - requested %d, received %d - aborting.\n",n
,(int)res
);
385 fprintf(stderr
,"[INFO] Wrote %d bytes plus %d bytes padding.\n",
386 byteswritten
-padding
,padding
);
390 char* ftypename
[] = { "OSOS", "RSRC", "AUPD", "HIBE" };
392 int diskmove(struct ipod_t
* ipod
, int delta
)
400 src_start
= ipod
->ipod_directory
[1].devOffset
;
401 src_end
= (ipod
->ipod_directory
[ipod
->nimages
-1].devOffset
+ ipod
->sector_size
+
402 ipod
->ipod_directory
[ipod
->nimages
-1].len
+
403 (ipod
->sector_size
-1)) & ~(ipod
->sector_size
-1);
404 bytesleft
= src_end
- src_start
;
407 fprintf(stderr
,"[INFO] Need to move images 2-%d forward %08x bytes\n", ipod
->nimages
,delta
);
408 fprintf(stderr
,"[VERB] src_start = %08x\n",src_start
);
409 fprintf(stderr
,"[VERB] src_end = %08x\n",src_end
);
410 fprintf(stderr
,"[VERB] dest_start = %08x\n",src_start
+delta
);
411 fprintf(stderr
,"[VERB] dest_end = %08x\n",src_end
+delta
);
412 fprintf(stderr
,"[VERB] bytes to copy = %08x\n",bytesleft
);
415 while (bytesleft
> 0) {
416 if (bytesleft
<= BUFFER_SIZE
) {
417 chunksize
= bytesleft
;
419 chunksize
= BUFFER_SIZE
;
423 fprintf(stderr
,"[VERB] Copying %08x bytes from %08x to %08x (absolute %08x to %08x)\n",
426 src_end
-chunksize
+delta
,
427 (unsigned int)(ipod
->start
+src_end
-chunksize
),
428 (unsigned int)(ipod
->start
+src_end
-chunksize
+delta
));
432 if (ipod_seek(ipod
, ipod
->start
+src_end
-chunksize
) < 0) {
433 fprintf(stderr
,"[ERR] Seek failed\n");
437 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,chunksize
)) < 0) {
438 perror("[ERR] Write failed\n");
443 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
448 if (ipod_seek(ipod
, ipod
->start
+src_end
-chunksize
+delta
) < 0) {
449 fprintf(stderr
,"[ERR] Seek failed\n");
453 if ((n
= ipod_write(ipod
,ipod_sectorbuf
,chunksize
)) < 0) {
454 perror("[ERR] Write failed\n");
459 fprintf(stderr
,"[ERR] Short write - requested %d bytes, received %d\n"
464 src_end
-= chunksize
;
465 bytesleft
-= chunksize
;
471 int add_bootloader(struct ipod_t
* ipod
, char* filename
, int type
)
481 unsigned long chksum
=0;
482 unsigned long filechksum
=0;
483 unsigned char header
[8]; /* Header for .ipod file */
484 unsigned char* bootloader_buf
;
486 /* Calculate the position in the OSOS image where our bootloader will go. */
487 if (ipod
->ipod_directory
[0].entryOffset
>0) {
488 /* Keep the same entryOffset */
489 entryOffset
= ipod
->ipod_directory
[0].entryOffset
;
491 entryOffset
= (ipod
->ipod_directory
[0].len
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
495 if (type
== FILETYPE_INTERNAL
) {
496 fprintf(stderr
,"[INFO] Using internal bootloader - %d bytes\n",ipod
->bootloader_len
);
497 memcpy(ipod_sectorbuf
+entryOffset
,ipod
->bootloader
,ipod
->bootloader_len
);
498 length
= ipod
->bootloader_len
;
499 paddedlength
=(ipod
->bootloader_len
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
504 infile
=open(filename
,O_RDONLY
);
506 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
510 if (type
==FILETYPE_DOT_IPOD
) {
511 /* First check that the input file is the correct type for this ipod. */
512 n
= read(infile
,header
,8);
514 fprintf(stderr
,"[ERR] Failed to read header from %s\n",filename
);
519 if (memcmp(header
+4, ipod
->modelname
,4)!=0) {
520 fprintf(stderr
,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n",
521 header
[4],header
[5],header
[6],header
[7], ipod
->modelname
);
526 filechksum
= be2int(header
);
528 length
=filesize(infile
)-8;
530 length
=filesize(infile
);
532 paddedlength
=(length
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
534 bootloader_buf
= malloc(length
);
535 if (bootloader_buf
== NULL
) {
536 fprintf(stderr
,"[ERR] Can not allocate memory for bootloader\n");
539 /* Now read our bootloader - we need to check it before modifying the partition*/
540 n
= read(infile
,bootloader_buf
,length
);
544 fprintf(stderr
,"[ERR] Couldn't read input file\n");
548 if (type
==FILETYPE_DOT_IPOD
) {
549 /* Calculate and confirm bootloader checksum */
550 chksum
= ipod
->modelnum
;
551 for (i
= 0; i
< length
; i
++) {
552 /* add 8 unsigned bits but keep a 32 bit sum */
553 chksum
+= bootloader_buf
[i
];
556 if (chksum
== filechksum
) {
557 fprintf(stderr
,"[INFO] Checksum OK in %s\n",filename
);
559 fprintf(stderr
,"[ERR] Checksum in %s failed check\n",filename
);
565 if (entryOffset
+paddedlength
> BUFFER_SIZE
) {
566 fprintf(stderr
,"[ERR] Input file too big for buffer\n");
571 fprintf(stderr
,"[VERB] Original firmware begins at 0x%08x\n", ipod
->ipod_directory
[0].devOffset
+ ipod
->sector_size
);
572 fprintf(stderr
,"[VERB] New entryOffset will be 0x%08x\n",entryOffset
);
573 fprintf(stderr
,"[VERB] End of bootloader will be at 0x%08x\n",entryOffset
+paddedlength
);
576 /* Check if we have enough space */
577 /* TODO: Check the size of the partition. */
578 if (ipod
->nimages
> 1) {
579 if ((ipod
->ipod_directory
[0].devOffset
+entryOffset
+paddedlength
) >
580 ipod
->ipod_directory
[1].devOffset
) {
581 fprintf(stderr
,"[INFO] Moving images to create room for new firmware...\n");
582 delta
= ipod
->ipod_directory
[0].devOffset
+ entryOffset
+paddedlength
583 - ipod
->ipod_directory
[1].devOffset
+ ipod
->sector_size
;
585 if (diskmove(ipod
, delta
) < 0) {
586 fprintf(stderr
,"[ERR] Image movement failed.\n");
593 /* We have moved the partitions, now we can write our bootloader */
595 /* Firstly read the original firmware into ipod_sectorbuf */
596 fprintf(stderr
,"[INFO] Reading original firmware...\n");
597 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
598 fprintf(stderr
,"[ERR] Seek failed\n");
602 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,entryOffset
)) < 0) {
603 perror("[ERR] Read failed\n");
607 if (n
< entryOffset
) {
608 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n"
614 if (type
== FILETYPE_INTERNAL
) {
615 memcpy(ipod_sectorbuf
+entryOffset
,ipod
->bootloader
,ipod
->bootloader_len
);
620 memcpy(ipod_sectorbuf
+entryOffset
,bootloader_buf
,length
);
621 free(bootloader_buf
);
624 /* Calculate new checksum for combined image */
626 for (i
=0;i
<entryOffset
+ length
; i
++) {
627 chksum
+= ipod_sectorbuf
[i
];
630 /* Now write the combined firmware image to the disk */
632 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
633 fprintf(stderr
,"[ERR] Seek failed\n");
637 if ((n
= ipod_write(ipod
,ipod_sectorbuf
,entryOffset
+paddedlength
)) < 0) {
638 perror("[ERR] Write failed\n");
642 if (n
< (entryOffset
+paddedlength
)) {
643 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n"
644 ,entryOffset
+paddedlength
,n
);
648 fprintf(stderr
,"[INFO] Wrote %d bytes to firmware partition\n",entryOffset
+paddedlength
);
650 x
= ipod
->diroffset
% ipod
->sector_size
;
653 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) {
654 fprintf(stderr
,"[ERR] Seek failed\n");
658 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
660 fprintf(stderr
,"[ERR] Directory read failed\n");
664 /* Update entries for image 0 */
665 int2le(entryOffset
+length
,ipod_sectorbuf
+x
+16);
666 int2le(entryOffset
,ipod_sectorbuf
+x
+24);
667 int2le(chksum
,ipod_sectorbuf
+x
+28);
668 int2le(0xffffffff,ipod_sectorbuf
+x
+36); /* loadAddr */
670 /* Update devOffset entries for other images, if we have moved them */
672 for (i
=1;i
<ipod
->nimages
;i
++) {
673 int2le(le2int(ipod_sectorbuf
+x
+i
*40+12)+delta
,ipod_sectorbuf
+x
+i
*40+12);
677 /* Write directory */
678 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) {
679 fprintf(stderr
,"[ERR] Seek to %d failed\n", (int)(ipod
->start
+ipod
->diroffset
-x
));
682 n
=ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
684 fprintf(stderr
,"[ERR] Directory write failed\n");
691 int delete_bootloader(struct ipod_t
* ipod
)
697 unsigned long chksum
=0; /* 32 bit checksum - Rockbox .ipod style*/
699 /* Removing the bootloader involves adjusting the "length",
700 "chksum" and "entryOffset" values in the osos image's directory
703 /* Firstly check we have a bootloader... */
705 if (ipod
->ipod_directory
[0].entryOffset
== 0) {
706 fprintf(stderr
,"[ERR] No bootloader found.\n");
710 length
= ipod
->ipod_directory
[0].entryOffset
;
712 /* Read the firmware so we can calculate the checksum */
713 fprintf(stderr
,"[INFO] Reading firmware (%d bytes)\n",length
);
715 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
719 i
= (length
+ipod
->sector_size
-1) & ~(ipod
->sector_size
-1);
720 fprintf(stderr
,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n",
723 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,i
)) < 0) {
728 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
734 for (i
= 0; i
< length
; i
++) {
735 /* add 8 unsigned bits but keep a 32 bit sum */
736 chksum
+= ipod_sectorbuf
[i
];
739 /* Now write back the updated directory entry */
741 fprintf(stderr
,"[INFO] Updating firmware checksum\n");
743 x
= ipod
->diroffset
% ipod
->sector_size
;
746 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
748 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
749 if (n
< 0) { return -1; }
751 /* Update entries for image 0 */
752 int2le(length
,ipod_sectorbuf
+x
+16);
753 int2le(0,ipod_sectorbuf
+x
+24);
754 int2le(chksum
,ipod_sectorbuf
+x
+28);
756 /* Write directory */
757 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
758 n
=ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
759 if (n
< 0) { return -1; }
764 int write_firmware(struct ipod_t
* ipod
, char* filename
, int type
)
773 unsigned long chksum
=0;
774 unsigned long filechksum
=0;
775 unsigned char header
[8]; /* Header for .ipod file */
778 if (type
== FILETYPE_INTERNAL
) {
779 fprintf(stderr
,"[INFO] Using internal bootloader - %d bytes\n",ipod
->bootloader_len
);
780 length
= ipod
->bootloader_len
;
786 /* First check that the input file is the correct type for this ipod. */
787 infile
=open(filename
,O_RDONLY
);
789 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
793 if (type
==FILETYPE_DOT_IPOD
) {
794 n
= read(infile
,header
,8);
796 fprintf(stderr
,"[ERR] Failed to read header from %s\n",filename
);
801 if (memcmp(header
+4, ipod
->modelname
,4)!=0) {
802 fprintf(stderr
,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n",
803 header
[4],header
[5],header
[6],header
[7], ipod
->modelname
);
808 filechksum
= be2int(header
);
810 length
= filesize(infile
)-8;
812 length
= filesize(infile
);
816 newsize
=(length
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
818 fprintf(stderr
,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n",
821 if (newsize
> BUFFER_SIZE
) {
822 fprintf(stderr
,"[ERR] Input file too big for buffer\n");
823 if (infile
>= 0) close(infile
);
827 /* Check if we have enough space */
828 /* TODO: Check the size of the partition. */
829 if (ipod
->nimages
> 1) {
830 bytesavailable
=ipod
->ipod_directory
[1].devOffset
-ipod
->ipod_directory
[0].devOffset
;
831 if (bytesavailable
< newsize
) {
832 fprintf(stderr
,"[INFO] Moving images to create room for new firmware...\n");
834 /* TODO: Implement image movement */
835 fprintf(stderr
,"[ERR] Image movement not yet implemented.\n");
842 if (type
== FILETYPE_INTERNAL
) {
843 memcpy(ipod_sectorbuf
,ipod
->bootloader
,ipod
->bootloader_len
);
848 fprintf(stderr
,"[INFO] Reading input file...\n");
849 /* We now know we have enough space, so write it. */
850 n
= read(infile
,ipod_sectorbuf
,length
);
852 fprintf(stderr
,"[ERR] Couldn't read input file\n");
859 /* Pad the data with zeros */
860 memset(ipod_sectorbuf
+length
,0,newsize
-length
);
862 if (type
==FILETYPE_DOT_IPOD
) {
863 chksum
= ipod
->modelnum
;
864 for (i
= 0; i
< length
; i
++) {
865 /* add 8 unsigned bits but keep a 32 bit sum */
866 chksum
+= ipod_sectorbuf
[i
];
869 if (chksum
== filechksum
) {
870 fprintf(stderr
,"[INFO] Checksum OK in %s\n",filename
);
872 fprintf(stderr
,"[ERR] Checksum in %s failed check\n",filename
);
877 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
878 fprintf(stderr
,"[ERR] Seek failed\n");
882 if ((n
= ipod_write(ipod
,ipod_sectorbuf
,newsize
)) < 0) {
883 perror("[ERR] Write failed\n");
888 fprintf(stderr
,"[ERR] Short write - requested %d bytes, received %d\n"
892 fprintf(stderr
,"[INFO] Wrote %d bytes to firmware partition\n",n
);
894 /* Now we need to update the "len", "entryOffset" and "chksum" fields */
896 for (i
= 0; i
< length
; i
++) {
897 /* add 8 unsigned bits but keep a 32 bit sum */
898 chksum
+= ipod_sectorbuf
[i
];
901 x
= ipod
->diroffset
% ipod
->sector_size
;
904 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
906 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
907 if (n
< 0) { return -1; }
909 /* Update entries for image 0 */
910 int2le(length
,ipod_sectorbuf
+x
+16);
911 int2le(0,ipod_sectorbuf
+x
+24);
912 int2le(chksum
,ipod_sectorbuf
+x
+28);
914 /* Write directory */
915 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
916 n
=ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
917 if (n
< 0) { return -1; }
922 int read_firmware(struct ipod_t
* ipod
, char* filename
, int type
)
928 unsigned long chksum
=0; /* 32 bit checksum - Rockbox .ipod style*/
929 unsigned char header
[8]; /* Header for .ipod file */
931 if (ipod
->ipod_directory
[0].entryOffset
!= 0) {
932 /* We have a bootloader... */
933 length
= ipod
->ipod_directory
[0].entryOffset
;
935 length
= ipod
->ipod_directory
[0].len
;
938 fprintf(stderr
,"[INFO] Reading firmware (%d bytes)\n",length
);
940 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
944 i
= (length
+ipod
->sector_size
-1) & ~(ipod
->sector_size
-1);
945 fprintf(stderr
,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n",
948 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,i
)) < 0) {
953 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
958 outfile
= open(filename
,O_CREAT
|O_TRUNC
|O_WRONLY
|O_BINARY
,0666);
960 fprintf(stderr
,"[ERR] Couldn't open file %s\n",filename
);
964 if (type
== FILETYPE_DOT_IPOD
) {
965 chksum
= ipod
->modelnum
;
966 for (i
= 0; i
< length
; i
++) {
967 /* add 8 unsigned bits but keep a 32 bit sum */
968 chksum
+= ipod_sectorbuf
[i
];
971 int2be(chksum
,header
);
972 memcpy(header
+4, ipod
->modelname
,4);
974 n
= write(outfile
,header
,8);
976 fprintf(stderr
,"[ERR] Write error - %d\n",n
);
980 n
= write(outfile
,ipod_sectorbuf
,length
);
982 fprintf(stderr
,"[ERR] Write error - %d\n",n
);
989 int read_directory(struct ipod_t
* ipod
)
994 unsigned short version
;
998 /* Read firmware partition header (first 512 bytes of disk - but
999 let's read a whole sector) */
1001 if (ipod_seek(ipod
, ipod
->start
) < 0) {
1002 fprintf(stderr
,"[ERR] Seek to 0x%08x in read_directory() failed.\n",
1003 (unsigned int)(ipod
->start
));
1007 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1009 fprintf(stderr
,"[ERR] ipod_read(ipod,buf,0x%08x) failed in read_directory()\n", ipod
->sector_size
);
1013 if (memcmp(ipod_sectorbuf
,apple_stop_sign
,sizeof(apple_stop_sign
))!=0) {
1014 fprintf(stderr
,"[ERR] Firmware partition doesn't contain Apple copyright, aborting.\n");
1018 if (memcmp(ipod_sectorbuf
+0x100,"]ih[",4)!=0) {
1019 fprintf(stderr
,"[ERR] Bad firmware directory\n");
1023 version
= le2ushort(ipod_sectorbuf
+0x10a);
1024 if ((version
!= 2) && (version
!= 3)) {
1025 fprintf(stderr
,"[ERR] Unknown firmware format version %04x\n",
1028 ipod
->diroffset
=le2int(ipod_sectorbuf
+0x104) + 0x200;
1030 /* diroffset may not be sector-aligned */
1031 x
= ipod
->diroffset
% ipod
->sector_size
;
1033 /* Read directory */
1034 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) {
1035 fprintf(stderr
,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod
->diroffset
);
1039 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1041 fprintf(stderr
,"[ERR] Read of directory failed.\n");
1045 p
= ipod_sectorbuf
+ x
;
1047 /* A hack to detect 2nd gen Nanos - maybe there is a better way? */
1050 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1052 fprintf(stderr
,"[ERR] Read of directory failed.\n");
1058 while ((ipod
->nimages
< MAX_IMAGES
) && (p
< (ipod_sectorbuf
+ x
+ 400)) &&
1059 ((memcmp(p
,"!ATA",4)==0) || (memcmp(p
,"DNAN",4)==0))) {
1061 if (memcmp(p
,"soso",4)==0) {
1062 ipod
->ipod_directory
[ipod
->nimages
].ftype
=FTYPE_OSOS
;
1063 } else if (memcmp(p
,"crsr",4)==0) {
1064 ipod
->ipod_directory
[ipod
->nimages
].ftype
=FTYPE_RSRC
;
1065 } else if (memcmp(p
,"dpua",4)==0) {
1066 ipod
->ipod_directory
[ipod
->nimages
].ftype
=FTYPE_AUPD
;
1067 } else if (memcmp(p
,"ebih",4)==0) {
1068 ipod
->ipod_directory
[ipod
->nimages
].ftype
=FTYPE_HIBE
;
1070 fprintf(stderr
,"[ERR] Unknown image type %c%c%c%c\n",
1071 p
[0],p
[1],p
[2],p
[3]);
1074 ipod
->ipod_directory
[ipod
->nimages
].id
=le2int(p
);
1076 ipod
->ipod_directory
[ipod
->nimages
].devOffset
=le2int(p
);
1078 ipod
->ipod_directory
[ipod
->nimages
].len
=le2int(p
);
1080 ipod
->ipod_directory
[ipod
->nimages
].addr
=le2int(p
);
1082 ipod
->ipod_directory
[ipod
->nimages
].entryOffset
=le2int(p
);
1084 ipod
->ipod_directory
[ipod
->nimages
].chksum
=le2int(p
);
1086 ipod
->ipod_directory
[ipod
->nimages
].vers
=le2int(p
);
1088 ipod
->ipod_directory
[ipod
->nimages
].loadAddr
=le2int(p
);
1093 if ((ipod
->nimages
> 1) && (version
==2)) {
1094 /* The 3g firmware image doesn't appear to have a version, so
1095 let's make one up... Note that this is never written back to the
1096 ipod, so it's OK to do. */
1098 if (ipod
->ipod_directory
[0].vers
== 0) { ipod
->ipod_directory
[0].vers
= 3; }
1100 ipod
->fwoffset
= ipod
->start
;
1102 ipod
->fwoffset
= ipod
->start
+ ipod
->sector_size
;
1108 int list_images(struct ipod_t
* ipod
)
1113 printf(" Type id devOffset len addr entryOffset chksum vers loadAddr devOffset+len\n");
1114 for (i
= 0 ; i
< ipod
->nimages
; i
++) {
1115 printf("%d - %s 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",i
,
1116 ftypename
[ipod
->ipod_directory
[i
].ftype
],
1117 ipod
->ipod_directory
[i
].id
,
1118 ipod
->ipod_directory
[i
].devOffset
,
1119 ipod
->ipod_directory
[i
].len
,
1120 ipod
->ipod_directory
[i
].addr
,
1121 ipod
->ipod_directory
[i
].entryOffset
,
1122 ipod
->ipod_directory
[i
].chksum
,
1123 ipod
->ipod_directory
[i
].vers
,
1124 ipod
->ipod_directory
[i
].loadAddr
,
1125 ipod
->ipod_directory
[i
].devOffset
+((ipod
->ipod_directory
[i
].len
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1)));
1130 printf("Listing firmware partition contents:\n");
1133 for (i
= 0 ; i
< ipod
->nimages
; i
++) {
1134 printf("Image %d:\n",i
+1);
1135 switch(ipod
->ipod_directory
[i
].ftype
) {
1137 if (ipod
->ipod_directory
[i
].entryOffset
==0) {
1138 printf(" Main firmware - %d bytes\n",
1139 ipod
->ipod_directory
[i
].len
);
1141 printf(" Main firmware - %d bytes\n",
1142 ipod
->ipod_directory
[i
].entryOffset
);
1143 printf(" Third-party bootloader - %d bytes\n",
1144 ipod
->ipod_directory
[i
].len
-ipod
->ipod_directory
[i
].entryOffset
);
1148 printf(" %s - %d bytes\n",
1149 ftypename
[ipod
->ipod_directory
[i
].ftype
],
1150 ipod
->ipod_directory
[i
].len
);
1158 int getmodel(struct ipod_t
* ipod
, int ipod_version
)
1160 switch (ipod_version
) {
1162 ipod
->modelstr
="1st or 2nd Generation";
1163 ipod
->modelnum
= 19;
1164 ipod
->modelname
= "1g2g";
1165 ipod
->targetname
= "ipod1g2g";
1166 #ifdef WITH_BOOTOBJS
1167 ipod
->bootloader
= ipod1g2g
;
1168 ipod
->bootloader_len
= LEN_ipod1g2g
;
1172 ipod
->modelstr
="3rd Generation";
1174 ipod
->modelname
= "ip3g";
1175 ipod
->targetname
= "ipod3g";
1176 #ifdef WITH_BOOTOBJS
1177 ipod
->bootloader
= ipod3g
;
1178 ipod
->bootloader_len
= LEN_ipod3g
;
1182 ipod
->modelstr
="1st Generation Mini";
1184 ipod
->modelname
= "mini";
1185 ipod
->targetname
= "ipodmini1g";
1186 #ifdef WITH_BOOTOBJS
1187 ipod
->bootloader
= ipodmini
;
1188 ipod
->bootloader_len
= LEN_ipodmini
;
1192 ipod
->modelstr
="4th Generation";
1194 ipod
->modelname
= "ip4g";
1195 ipod
->targetname
= "ipod4gray";
1196 #ifdef WITH_BOOTOBJS
1197 ipod
->bootloader
= ipod4g
;
1198 ipod
->bootloader_len
= LEN_ipod4g
;
1202 ipod
->modelstr
="Photo/Color";
1204 ipod
->modelname
= "ipco";
1205 ipod
->targetname
= "ipodcolor";
1206 #ifdef WITH_BOOTOBJS
1207 ipod
->bootloader
= ipodcolor
;
1208 ipod
->bootloader_len
= LEN_ipodcolor
;
1212 ipod
->modelstr
="2nd Generation Mini";
1213 ipod
->modelnum
= 11;
1214 ipod
->modelname
= "mn2g";
1215 ipod
->targetname
= "ipodmini2g";
1216 #ifdef WITH_BOOTOBJS
1217 ipod
->bootloader
= ipodmini2g
;
1218 ipod
->bootloader_len
= LEN_ipodmini2g
;
1222 ipod
->modelstr
="1st Generation Nano";
1224 ipod
->modelname
= "nano";
1225 ipod
->targetname
= "ipodnano";
1226 #ifdef WITH_BOOTOBJS
1227 ipod
->bootloader
= ipodnano
;
1228 ipod
->bootloader_len
= LEN_ipodnano
;
1232 ipod
->modelstr
="Video (aka 5th Generation)";
1234 ipod
->modelname
= "ipvd";
1235 ipod
->targetname
= "ipodvideo";
1236 #ifdef WITH_BOOTOBJS
1237 ipod
->bootloader
= ipodvideo
;
1238 ipod
->bootloader_len
= LEN_ipodvideo
;
1242 ipod
->modelstr
="2nd Generation Nano";
1244 ipod
->targetname
= NULL
;
1245 #ifdef WITH_BOOTOBJS
1246 ipod
->bootloader
= NULL
;
1247 ipod
->bootloader_len
= 0;
1251 ipod
->modelname
= NULL
;
1253 ipod
->targetname
= NULL
;
1254 #ifdef WITH_BOOTOBJS
1255 ipod
->bootloader
= NULL
;
1256 ipod
->bootloader_len
= 0;
1263 /* returns number of found ipods or -1 if no ipods found and permission
1264 * for raw disc access was denied. */
1265 int ipod_scan(struct ipod_t
* ipod
)
1270 char last_ipod
[4096];
1274 printf("[INFO] Scanning disk devices...\n");
1276 for (i
= 0; i
<= 25 ; i
++) {
1278 sprintf(ipod
->diskname
,"\\\\.\\PhysicalDrive%d",i
);
1279 #elif defined(linux) || defined (__linux)
1280 sprintf(ipod
->diskname
,"/dev/sd%c",'a'+i
);
1281 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
1282 || defined(__bsdi__) || defined(__DragonFly__)
1283 sprintf(ipod
->diskname
,"/dev/da%d",i
);
1284 #elif defined(__APPLE__) && defined(__MACH__)
1285 sprintf(ipod
->diskname
,"/dev/disk%d",i
);
1287 #error No disk paths defined for this platform
1289 if ((result
= ipod_open(ipod
, 1)) < 0) {
1296 if (read_partinfo(ipod
,1) < 0) {
1300 if ((ipod
->pinfo
[0].start
==0) || (ipod
->pinfo
[0].type
!= 0)) {
1304 if (read_directory(ipod
) < 0) {
1308 ipod_version
=(ipod
->ipod_directory
[0].vers
>>8);
1309 if (getmodel(ipod
,ipod_version
) < 0) {
1314 printf("[INFO] Ipod found - %s (\"%s\") - disk device %d\n",
1315 ipod
->modelstr
,ipod
->macpod
? "macpod" : "winpod",i
);
1317 printf("[INFO] Ipod found - %s (\"%s\") - %s\n",
1318 ipod
->modelstr
,ipod
->macpod
? "macpod" : "winpod",ipod
->diskname
);
1321 strcpy(last_ipod
,ipod
->diskname
);
1326 /* Remember the disk name */
1327 strcpy(ipod
->diskname
,last_ipod
);
1329 else if(n
== 0 && denied
) {
1330 printf("[ERR] FATAL: Permission denied on %d device(s) and no ipod detected.\n", denied
);
1332 printf("[ERR] You need to run this program with administrator priviledges!\n");
1334 printf("[ERR] You need permissions for raw disc access for this program to work!\n");
1337 return (n
== 0 && denied
) ? -1 : n
;
1340 static void put_int32le(uint32_t x
, unsigned char* p
)
1343 p
[1] = (x
>> 8) & 0xff;
1344 p
[2] = (x
>> 16) & 0xff;
1345 p
[3] = (x
>> 24) & 0xff;
1348 int write_dos_partition_table(struct ipod_t
* ipod
)
1354 /* Only support 512-byte sectors at the moment */
1355 if ( ipod
->sector_size
!= 512 )
1357 fprintf(stderr
,"[ERR] Only ipods with 512 bytes per sector are supported.\n");
1361 /* Firstly zero the entire MBR */
1362 memset(ipod_sectorbuf
, 0, ipod
->sector_size
);
1364 /* Now add the partition info */
1365 for (i
=0; i
< 4 ; i
++)
1367 p
= ipod_sectorbuf
+ 0x1be + i
*16;
1369 /* Ensure first partition is type 0, and second is 0xb */
1370 if (i
==0) { type
= 0; }
1371 else if (i
==1) { type
= 0xb; }
1372 else { type
= ipod
->pinfo
[i
].type
; }
1374 put_int32le(type
, p
+ 4);
1375 put_int32le(ipod
->pinfo
[i
].start
, p
+ 8);
1376 put_int32le(ipod
->pinfo
[i
].size
, p
+ 12);
1379 /* Finally add the magic */
1380 ipod_sectorbuf
[0x1fe] = 0x55;
1381 ipod_sectorbuf
[0x1ff] = 0xaa;
1383 if (ipod_seek(ipod
, 0) < 0) {
1384 fprintf(stderr
,"[ERR] Seek failed writing MBR\n");
1389 if ((n
= ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
)) < 0) {
1390 perror("[ERR] Write failed\n");
1399 static inline uint32_t getuint32le(unsigned char* buf
)
1401 int32_t res
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
1406 /* testMarker and GetSecurityBlockKey based on code from BadBlocks and
1407 Kingstone, posted at http://ipodlinux.org/Flash_Decryption
1411 static bool testMarker(int marker
)
1413 int mask
, decrypt
, temp1
, temp2
;
1415 mask
= (marker
&0xff)|((marker
&0xff)<<8)|((marker
&0xff)<<16)|((marker
&0xff)<<24);
1416 decrypt
= marker
^ mask
;
1417 temp1
=(int)((unsigned int)decrypt
>>24);
1423 temp2
=(int)((unsigned int)temp2
>>24);
1424 decrypt
=decrypt
<<16;
1425 decrypt
=(int)((unsigned int)decrypt
>>24);
1427 if ((temp1
< temp2
) && (temp2
< decrypt
))
1429 temp1
= temp1
& 0xf;
1430 temp2
= temp2
& 0xf;
1431 decrypt
= decrypt
& 0xf;
1433 if ((temp1
> temp2
) && (temp2
> decrypt
) && (decrypt
!= 0))
1441 static int GetSecurityBlockKey(unsigned char *data
, unsigned char* this_key
)
1443 int constant
= 0x54c3a298;
1450 static const int offset
[8]={0x5,0x25,0x6f,0x69,0x15,0x4d,0x40,0x34};
1452 for (c
= 0; c
< 8; c
++)
1455 aMarker
= getuint32le(data
+ pos
);
1457 if (testMarker(aMarker
))
1460 pos
=(offset
[c
+1]*4)+4;
1462 pos
=(offset
[0]*4)+4;
1468 for (count
=0;count
<2;count
++){
1469 int word
= getuint32le(data
+ pos
);
1472 temp1
= temp1
^constant
;
1482 for (count
=2;count
<128;count
=count
+2){
1483 r2
=getuint32le(data
+count
*4);
1484 r12
=getuint32le(data
+(count
*4)+4);
1485 r_tmp
=(unsigned int)r12
>>16;
1486 r14
=r2
| ((int)r_tmp
);
1494 // Invert key, little endian
1495 this_key
[0] = key
& 0xff;
1496 this_key
[1] = (key
>> 8) & 0xff;
1497 this_key
[2] = (key
>> 16) & 0xff;
1498 this_key
[3] = (key
>> 24) & 0xff;
1505 static int find_key(struct ipod_t
* ipod
, int aupd
, unsigned char* key
)
1509 /* Firstly read the security block and find the RC4 key. This is
1510 in the sector preceeding the AUPD image. */
1512 fprintf(stderr
, "[INFO] Reading security block at offset 0x%08x\n",ipod
->ipod_directory
[aupd
].devOffset
-ipod
->sector_size
);
1513 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[aupd
].devOffset
-ipod
->sector_size
) < 0) {
1517 if ((n
= ipod_read(ipod
, ipod_sectorbuf
, 512)) < 0) {
1521 n
= GetSecurityBlockKey(ipod_sectorbuf
, key
);
1525 fprintf(stderr
, "[ERR] %d keys found in security block, can not continue\n",n
);
1532 int read_aupd(struct ipod_t
* ipod
, char* filename
)
1539 struct rc4_key_t rc4
;
1540 unsigned char key
[4];
1541 unsigned long chksum
=0;
1544 while ((aupd
< ipod
->nimages
) && (ipod
->ipod_directory
[aupd
].ftype
!= FTYPE_AUPD
))
1549 if (aupd
== ipod
->nimages
)
1551 fprintf(stderr
,"[ERR] No AUPD image in firmware partition.\n");
1555 length
= ipod
->ipod_directory
[aupd
].len
;
1557 fprintf(stderr
,"[INFO] Reading firmware (%d bytes)\n",length
);
1559 if (find_key(ipod
, aupd
, key
) < 0)
1564 fprintf(stderr
, "[INFO] Decrypting AUPD image with key %02x%02x%02x%02x\n",key
[0],key
[1],key
[2],key
[3]);
1566 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[aupd
].devOffset
) < 0) {
1570 i
= (length
+ipod
->sector_size
-1) & ~(ipod
->sector_size
-1);
1572 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,i
)) < 0) {
1577 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
1582 /* Perform the decryption - this is standard (A)RC4 */
1583 matrixArc4Init(&rc4
, key
, 4);
1584 matrixArc4(&rc4
, ipod_sectorbuf
, ipod_sectorbuf
, length
);
1587 for (i
= 0; i
< (int)length
; i
++) {
1588 /* add 8 unsigned bits but keep a 32 bit sum */
1589 chksum
+= ipod_sectorbuf
[i
];
1592 if (chksum
!= ipod
->ipod_directory
[aupd
].chksum
)
1594 fprintf(stderr
,"[ERR] Decryption failed - checksum error\n");
1597 fprintf(stderr
,"[INFO] Decrypted OK (checksum matches header)\n");
1599 outfile
= open(filename
,O_CREAT
|O_TRUNC
|O_WRONLY
|O_BINARY
,0666);
1601 fprintf(stderr
,"[ERR] Couldn't open file %s\n",filename
);
1605 n
= write(outfile
,ipod_sectorbuf
,length
);
1607 fprintf(stderr
,"[ERR] Write error - %d\n",n
);
1614 int write_aupd(struct ipod_t
* ipod
, char* filename
)
1616 unsigned int length
;
1623 unsigned long chksum
=0;
1624 struct rc4_key_t rc4
;
1625 unsigned char key
[4];
1627 /* First check that the input file is the correct type for this ipod. */
1628 infile
=open(filename
,O_RDONLY
);
1630 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
1634 length
= filesize(infile
);
1635 newsize
=(length
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
1637 fprintf(stderr
,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n",
1640 if (newsize
> BUFFER_SIZE
) {
1641 fprintf(stderr
,"[ERR] Input file too big for buffer\n");
1642 if (infile
>= 0) close(infile
);
1646 /* Find aupd image number */
1648 while ((aupd
< ipod
->nimages
) && (ipod
->ipod_directory
[aupd
].ftype
!= FTYPE_AUPD
))
1653 if (aupd
== ipod
->nimages
)
1655 fprintf(stderr
,"[ERR] No AUPD image in firmware partition.\n");
1659 if (length
!= ipod
->ipod_directory
[aupd
].len
)
1661 fprintf(stderr
,"[ERR] AUPD image (%d bytes) differs in size to %s (%d bytes).\n",
1662 ipod
->ipod_directory
[aupd
].len
, filename
, length
);
1666 if (find_key(ipod
, aupd
, key
) < 0)
1671 fprintf(stderr
, "[INFO] Encrypting AUPD image with key %02x%02x%02x%02x\n",key
[0],key
[1],key
[2],key
[3]);
1673 /* We now know we have enough space, so write it. */
1675 fprintf(stderr
,"[INFO] Reading input file...\n");
1676 n
= read(infile
,ipod_sectorbuf
,length
);
1678 fprintf(stderr
,"[ERR] Couldn't read input file\n");
1684 /* Pad the data with zeros */
1685 memset(ipod_sectorbuf
+length
,0,newsize
-length
);
1687 /* Calculate the new checksum (before we encrypt) */
1689 for (i
= 0; i
< (int)length
; i
++) {
1690 /* add 8 unsigned bits but keep a 32 bit sum */
1691 chksum
+= ipod_sectorbuf
[i
];
1694 /* Perform the encryption - this is standard (A)RC4 */
1695 matrixArc4Init(&rc4
, key
, 4);
1696 matrixArc4(&rc4
, ipod_sectorbuf
, ipod_sectorbuf
, length
);
1698 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[aupd
].devOffset
) < 0) {
1699 fprintf(stderr
,"[ERR] Seek failed\n");
1703 if ((n
= ipod_write(ipod
,ipod_sectorbuf
,newsize
)) < 0) {
1704 perror("[ERR] Write failed\n");
1709 fprintf(stderr
,"[ERR] Short write - requested %d bytes, received %d\n"
1713 fprintf(stderr
,"[INFO] Wrote %d bytes to firmware partition\n",n
);
1715 x
= ipod
->diroffset
% ipod
->sector_size
;
1717 /* Read directory */
1718 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
1720 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1721 if (n
< 0) { return -1; }
1723 /* Update checksum */
1724 fprintf(stderr
,"[INFO] Updating checksum to 0x%08x (was 0x%08x)\n",(unsigned int)chksum
,le2int(ipod_sectorbuf
+ x
+ aupd
*40 + 28));
1725 int2le(chksum
,ipod_sectorbuf
+x
+aupd
*40+28);
1727 /* Write directory */
1728 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
1729 n
=ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1730 if (n
< 0) { return -1; }