1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006-2007 Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
29 #include <sys/types.h>
32 #include "parttypes.h"
34 #include "ipodpatcher.h"
41 #include "ipodmini2g.h"
42 #include "ipodcolor.h"
44 #include "ipodvideo.h"
53 unsigned char* ipod_sectorbuf
= NULL
;
55 /* The following string appears at the start of the firmware partition */
56 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
73 /* Windows requires the buffer for disk I/O to be aligned in memory on a
74 multiple of the disk volume size - so we use a single global variable
75 and initialise it with ipod_alloc_buf()
78 char* get_parttype(int pt
)
81 static char unknown
[]="Unknown";
83 if (pt
== PARTTYPE_HFS
) {
88 while (parttypes
[i
].name
!= NULL
) {
89 if (parttypes
[i
].type
== pt
) {
90 return (parttypes
[i
].name
);
98 off_t
filesize(int fd
) {
101 if (fstat(fd
,&buf
) < 0) {
102 perror("[ERR] Checking filesize of input file");
109 /* Partition table parsing code taken from Rockbox */
111 #define MAX_SECTOR_SIZE 2048
112 #define SECTOR_SIZE 512
114 static inline unsigned short le2ushort(unsigned char* buf
)
116 unsigned short res
= (buf
[1] << 8) | buf
[0];
121 static inline int le2int(unsigned char* buf
)
123 int32_t res
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
128 static inline int be2int(unsigned char* buf
)
130 int32_t res
= (buf
[0] << 24) | (buf
[1] << 16) | (buf
[2] << 8) | buf
[3];
135 static inline int getint16le(char* buf
)
137 int16_t res
= (buf
[1] << 8) | buf
[0];
142 static inline void short2le(unsigned short val
, unsigned char* addr
)
144 addr
[0] = val
& 0xFF;
145 addr
[1] = (val
>> 8) & 0xff;
148 static inline void int2le(unsigned int val
, unsigned char* addr
)
150 addr
[0] = val
& 0xFF;
151 addr
[1] = (val
>> 8) & 0xff;
152 addr
[2] = (val
>> 16) & 0xff;
153 addr
[3] = (val
>> 24) & 0xff;
156 static inline void int2be(unsigned int val
, unsigned char* addr
)
158 addr
[0] = (val
>> 24) & 0xff;
159 addr
[1] = (val
>> 16) & 0xff;
160 addr
[2] = (val
>> 8) & 0xff;
161 addr
[3] = val
& 0xFF;
165 #define BYTES2INT32(array,pos)\
166 ((long)array[pos] | ((long)array[pos+1] << 8 ) |\
167 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
169 int read_partinfo(struct ipod_t
* ipod
, int silent
)
174 count
= ipod_read(ipod
,ipod_sectorbuf
, ipod
->sector_size
);
177 print_error(" Error reading from disk: ");
181 memset(ipod
->pinfo
, 0, sizeof(ipod
->pinfo
));
183 if ((ipod_sectorbuf
[510] == 0x55) && (ipod_sectorbuf
[511] == 0xaa)) {
184 /* DOS partition table */
186 /* parse partitions */
187 for ( i
= 0; i
< 4; i
++ ) {
188 unsigned char* ptr
= ipod_sectorbuf
+ 0x1be + 16*i
;
189 ipod
->pinfo
[i
].type
= ptr
[4];
190 ipod
->pinfo
[i
].start
= BYTES2INT32(ptr
, 8);
191 ipod
->pinfo
[i
].size
= BYTES2INT32(ptr
, 12);
194 if ( ipod
->pinfo
[i
].type
== 5 ) {
195 /* not handled yet */
198 } else if ((ipod_sectorbuf
[0] == 'E') && (ipod_sectorbuf
[1] == 'R')) {
199 /* Apple Partition Map */
201 /* APM parsing code based on the check_mac_partitions() function in
202 ipodloader2 - written by Thomas Tempelmann and released
206 int partBlkCount
= 1;
207 int partBlkSizMul
= ipod_sectorbuf
[2] / 2;
209 int pmMapBlkCnt
; /* # of blks in partition map */
210 int pmPyPartStart
; /* physical start blk of partition */
211 int pmPartBlkCnt
; /* # of blks in this partition */
216 memset(ipod
->pinfo
,0,sizeof(ipod
->pinfo
));
218 while (blkNo
<= partBlkCount
) {
219 if (ipod_seek(ipod
, blkNo
* partBlkSizMul
* 512) < 0) {
220 fprintf(stderr
,"[ERR] Seek failed whilst reading APM\n");
224 count
= ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
227 print_error(" Error reading from disk: ");
231 /* see if it's a partition entry */
232 if ((ipod_sectorbuf
[0] != 'P') || (ipod_sectorbuf
[1] != 'M')) {
233 /* end of partition table -> leave the loop */
237 /* Extract the interesting entries */
238 pmMapBlkCnt
= be2int(ipod_sectorbuf
+ 4);
239 pmPyPartStart
= be2int(ipod_sectorbuf
+ 8);
240 pmPartBlkCnt
= be2int(ipod_sectorbuf
+ 12);
242 /* update the number of part map blocks */
243 partBlkCount
= pmMapBlkCnt
;
245 if (strncmp((char*)(ipod_sectorbuf
+ 48), "Apple_MDFW", 32)==0) {
246 /* A Firmware partition */
247 ipod
->pinfo
[i
].start
= pmPyPartStart
;
248 ipod
->pinfo
[i
].size
= pmPartBlkCnt
;
249 ipod
->pinfo
[i
].type
= 0;
251 } else if (strncmp((char*)(ipod_sectorbuf
+ 48), "Apple_HFS", 32)==0) {
252 /* A HFS partition */
253 ipod
->pinfo
[i
].start
= pmPyPartStart
;
254 ipod
->pinfo
[i
].size
= pmPartBlkCnt
;
255 ipod
->pinfo
[i
].type
= PARTTYPE_HFS
;
259 blkNo
++; /* read next partition map entry */
262 if (!silent
) fprintf(stderr
,"[ERR] Bad boot sector signature\n");
266 /* Check that the partition table looks like an ipod:
267 1) Partition 1 is of type 0 (Empty) but isn't empty.
268 2) Partition 2 is of type 0xb or 0xc (winpod) or -1 (macpod)
270 if ((ipod
->pinfo
[0].type
!= 0) || (ipod
->pinfo
[0].size
== 0) ||
271 ((ipod
->pinfo
[1].type
!= 0xb) && (ipod
->pinfo
[1].type
!= 0xc) &&
272 (ipod
->pinfo
[1].type
!= PARTTYPE_HFS
))) {
273 if (!silent
) fprintf(stderr
,"[ERR] Partition layout is not an ipod\n");
277 ipod
->start
= ipod
->pinfo
[0].start
*ipod
->sector_size
;
281 int read_partition(struct ipod_t
* ipod
, int outfile
)
287 int count
= ipod
->pinfo
[0].size
;
289 if (ipod_seek(ipod
, ipod
->start
) < 0) {
293 fprintf(stderr
,"[INFO] Writing %d sectors to output file\n",count
);
295 bytesleft
= count
* ipod
->sector_size
;
296 while (bytesleft
> 0) {
297 if (bytesleft
> BUFFER_SIZE
) {
298 chunksize
= BUFFER_SIZE
;
300 chunksize
= bytesleft
;
303 n
= ipod_read(ipod
, ipod_sectorbuf
, chunksize
);
311 "[ERR] Short read in disk_read() - requested %d, got %d\n",
318 res
= write(outfile
,ipod_sectorbuf
,n
);
321 perror("[ERR] write in disk_read");
327 "Short write - requested %d, received %d - aborting.\n",(int)n
,res
);
332 fprintf(stderr
,"[INFO] Done.\n");
336 int write_partition(struct ipod_t
* ipod
, int infile
)
341 int byteswritten
= 0;
345 if (ipod_seek(ipod
, ipod
->start
) < 0) {
349 fprintf(stderr
,"[INFO] Writing input file to device\n");
353 n
= read(infile
,ipod_sectorbuf
,BUFFER_SIZE
);
356 perror("[ERR] read in disk_write");
360 if (n
< BUFFER_SIZE
) {
362 /* We need to pad the last write to a multiple of SECTOR_SIZE */
363 if ((n
% ipod
->sector_size
) != 0) {
364 padding
= (ipod
->sector_size
-(n
% ipod
->sector_size
));
371 res
= ipod_write(ipod
, ipod_sectorbuf
, n
);
374 print_error(" Error writing to disk: ");
375 fprintf(stderr
,"Bytes written: %d\n",byteswritten
);
380 fprintf(stderr
,"[ERR] Short write - requested %d, received %d - aborting.\n",n
,(int)res
);
387 fprintf(stderr
,"[INFO] Wrote %d bytes plus %d bytes padding.\n",
388 byteswritten
-padding
,padding
);
392 char* ftypename
[] = { "OSOS", "RSRC", "AUPD", "HIBE" };
394 int diskmove(struct ipod_t
* ipod
, int delta
)
402 src_start
= ipod
->ipod_directory
[1].devOffset
;
403 src_end
= (ipod
->ipod_directory
[ipod
->nimages
-1].devOffset
+ ipod
->sector_size
+
404 ipod
->ipod_directory
[ipod
->nimages
-1].len
+
405 (ipod
->sector_size
-1)) & ~(ipod
->sector_size
-1);
406 bytesleft
= src_end
- src_start
;
409 fprintf(stderr
,"[INFO] Need to move images 2-%d forward %08x bytes\n", ipod
->nimages
,delta
);
410 fprintf(stderr
,"[VERB] src_start = %08x\n",src_start
);
411 fprintf(stderr
,"[VERB] src_end = %08x\n",src_end
);
412 fprintf(stderr
,"[VERB] dest_start = %08x\n",src_start
+delta
);
413 fprintf(stderr
,"[VERB] dest_end = %08x\n",src_end
+delta
);
414 fprintf(stderr
,"[VERB] bytes to copy = %08x\n",bytesleft
);
417 while (bytesleft
> 0) {
418 if (bytesleft
<= BUFFER_SIZE
) {
419 chunksize
= bytesleft
;
421 chunksize
= BUFFER_SIZE
;
425 fprintf(stderr
,"[VERB] Copying %08x bytes from %08x to %08x (absolute %08x to %08x)\n",
428 src_end
-chunksize
+delta
,
429 (unsigned int)(ipod
->start
+src_end
-chunksize
),
430 (unsigned int)(ipod
->start
+src_end
-chunksize
+delta
));
434 if (ipod_seek(ipod
, ipod
->start
+src_end
-chunksize
) < 0) {
435 fprintf(stderr
,"[ERR] Seek failed\n");
439 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,chunksize
)) < 0) {
440 perror("[ERR] Write failed\n");
445 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
450 if (ipod_seek(ipod
, ipod
->start
+src_end
-chunksize
+delta
) < 0) {
451 fprintf(stderr
,"[ERR] Seek failed\n");
455 if ((n
= ipod_write(ipod
,ipod_sectorbuf
,chunksize
)) < 0) {
456 perror("[ERR] Write failed\n");
461 fprintf(stderr
,"[ERR] Short write - requested %d bytes, received %d\n"
466 src_end
-= chunksize
;
467 bytesleft
-= chunksize
;
473 int add_bootloader(struct ipod_t
* ipod
, char* filename
, int type
)
483 unsigned long chksum
=0;
484 unsigned long filechksum
=0;
485 unsigned char header
[8]; /* Header for .ipod file */
486 unsigned char* bootloader_buf
;
488 /* Calculate the position in the OSOS image where our bootloader will go. */
489 if (ipod
->ipod_directory
[0].entryOffset
>0) {
490 /* Keep the same entryOffset */
491 entryOffset
= ipod
->ipod_directory
[0].entryOffset
;
493 entryOffset
= (ipod
->ipod_directory
[0].len
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
497 if (type
== FILETYPE_INTERNAL
) {
498 fprintf(stderr
,"[INFO] Using internal bootloader - %d bytes\n",ipod
->bootloader_len
);
499 memcpy(ipod_sectorbuf
+entryOffset
,ipod
->bootloader
,ipod
->bootloader_len
);
500 length
= ipod
->bootloader_len
;
501 paddedlength
=(ipod
->bootloader_len
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
506 infile
=open(filename
,O_RDONLY
);
508 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
512 if (type
==FILETYPE_DOT_IPOD
) {
513 /* First check that the input file is the correct type for this ipod. */
514 n
= read(infile
,header
,8);
516 fprintf(stderr
,"[ERR] Failed to read header from %s\n",filename
);
521 if (memcmp(header
+4, ipod
->modelname
,4)!=0) {
522 fprintf(stderr
,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n",
523 header
[4],header
[5],header
[6],header
[7], ipod
->modelname
);
528 filechksum
= be2int(header
);
530 length
=filesize(infile
)-8;
532 length
=filesize(infile
);
534 paddedlength
=(length
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
536 bootloader_buf
= malloc(length
);
537 if (bootloader_buf
== NULL
) {
538 fprintf(stderr
,"[ERR] Can not allocate memory for bootloader\n");
541 /* Now read our bootloader - we need to check it before modifying the partition*/
542 n
= read(infile
,bootloader_buf
,length
);
546 fprintf(stderr
,"[ERR] Couldn't read input file\n");
550 if (type
==FILETYPE_DOT_IPOD
) {
551 /* Calculate and confirm bootloader checksum */
552 chksum
= ipod
->modelnum
;
553 for (i
= 0; i
< length
; i
++) {
554 /* add 8 unsigned bits but keep a 32 bit sum */
555 chksum
+= bootloader_buf
[i
];
558 if (chksum
== filechksum
) {
559 fprintf(stderr
,"[INFO] Checksum OK in %s\n",filename
);
561 fprintf(stderr
,"[ERR] Checksum in %s failed check\n",filename
);
567 if (entryOffset
+paddedlength
> BUFFER_SIZE
) {
568 fprintf(stderr
,"[ERR] Input file too big for buffer\n");
573 fprintf(stderr
,"[VERB] Original firmware begins at 0x%08x\n", ipod
->ipod_directory
[0].devOffset
+ ipod
->sector_size
);
574 fprintf(stderr
,"[VERB] New entryOffset will be 0x%08x\n",entryOffset
);
575 fprintf(stderr
,"[VERB] End of bootloader will be at 0x%08x\n",entryOffset
+paddedlength
);
578 /* Check if we have enough space */
579 /* TODO: Check the size of the partition. */
580 if (ipod
->nimages
> 1) {
581 if ((ipod
->ipod_directory
[0].devOffset
+entryOffset
+paddedlength
) >
582 ipod
->ipod_directory
[1].devOffset
) {
583 fprintf(stderr
,"[INFO] Moving images to create room for new firmware...\n");
584 delta
= ipod
->ipod_directory
[0].devOffset
+ entryOffset
+paddedlength
585 - ipod
->ipod_directory
[1].devOffset
+ ipod
->sector_size
;
587 if (diskmove(ipod
, delta
) < 0) {
588 fprintf(stderr
,"[ERR] Image movement failed.\n");
595 /* We have moved the partitions, now we can write our bootloader */
597 /* Firstly read the original firmware into ipod_sectorbuf */
598 fprintf(stderr
,"[INFO] Reading original firmware...\n");
599 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
600 fprintf(stderr
,"[ERR] Seek failed\n");
604 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,entryOffset
)) < 0) {
605 perror("[ERR] Read failed\n");
609 if (n
< entryOffset
) {
610 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n"
616 if (type
== FILETYPE_INTERNAL
) {
617 memcpy(ipod_sectorbuf
+entryOffset
,ipod
->bootloader
,ipod
->bootloader_len
);
622 memcpy(ipod_sectorbuf
+entryOffset
,bootloader_buf
,length
);
623 free(bootloader_buf
);
626 /* Calculate new checksum for combined image */
628 for (i
=0;i
<entryOffset
+ length
; i
++) {
629 chksum
+= ipod_sectorbuf
[i
];
632 /* Now write the combined firmware image to the disk */
634 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
635 fprintf(stderr
,"[ERR] Seek failed\n");
639 if ((n
= ipod_write(ipod
,ipod_sectorbuf
,entryOffset
+paddedlength
)) < 0) {
640 perror("[ERR] Write failed\n");
644 if (n
< (entryOffset
+paddedlength
)) {
645 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n"
646 ,entryOffset
+paddedlength
,n
);
650 fprintf(stderr
,"[INFO] Wrote %d bytes to firmware partition\n",entryOffset
+paddedlength
);
652 x
= ipod
->diroffset
% ipod
->sector_size
;
655 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) {
656 fprintf(stderr
,"[ERR] Seek failed\n");
660 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
662 fprintf(stderr
,"[ERR] Directory read failed\n");
666 /* Update entries for image 0 */
667 int2le(entryOffset
+length
,ipod_sectorbuf
+x
+16);
668 int2le(entryOffset
,ipod_sectorbuf
+x
+24);
669 int2le(chksum
,ipod_sectorbuf
+x
+28);
670 int2le(0xffffffff,ipod_sectorbuf
+x
+36); /* loadAddr */
672 /* Update devOffset entries for other images, if we have moved them */
674 for (i
=1;i
<ipod
->nimages
;i
++) {
675 int2le(le2int(ipod_sectorbuf
+x
+i
*40+12)+delta
,ipod_sectorbuf
+x
+i
*40+12);
679 /* Write directory */
680 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) {
681 fprintf(stderr
,"[ERR] Seek to %d failed\n", (int)(ipod
->start
+ipod
->diroffset
-x
));
684 n
=ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
686 fprintf(stderr
,"[ERR] Directory write failed\n");
693 int delete_bootloader(struct ipod_t
* ipod
)
699 unsigned long chksum
=0; /* 32 bit checksum - Rockbox .ipod style*/
701 /* Removing the bootloader involves adjusting the "length",
702 "chksum" and "entryOffset" values in the osos image's directory
705 /* Firstly check we have a bootloader... */
707 if (ipod
->ipod_directory
[0].entryOffset
== 0) {
708 fprintf(stderr
,"[ERR] No bootloader found.\n");
712 length
= ipod
->ipod_directory
[0].entryOffset
;
714 /* Read the firmware so we can calculate the checksum */
715 fprintf(stderr
,"[INFO] Reading firmware (%d bytes)\n",length
);
717 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
721 i
= (length
+ipod
->sector_size
-1) & ~(ipod
->sector_size
-1);
722 fprintf(stderr
,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n",
725 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,i
)) < 0) {
730 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
736 for (i
= 0; i
< length
; i
++) {
737 /* add 8 unsigned bits but keep a 32 bit sum */
738 chksum
+= ipod_sectorbuf
[i
];
741 /* Now write back the updated directory entry */
743 fprintf(stderr
,"[INFO] Updating firmware checksum\n");
745 x
= ipod
->diroffset
% ipod
->sector_size
;
748 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
750 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
751 if (n
< 0) { return -1; }
753 /* Update entries for image 0 */
754 int2le(length
,ipod_sectorbuf
+x
+16);
755 int2le(0,ipod_sectorbuf
+x
+24);
756 int2le(chksum
,ipod_sectorbuf
+x
+28);
758 /* Write directory */
759 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
760 n
=ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
761 if (n
< 0) { return -1; }
766 int write_firmware(struct ipod_t
* ipod
, char* filename
, int type
)
775 unsigned long chksum
=0;
776 unsigned long filechksum
=0;
777 unsigned char header
[8]; /* Header for .ipod file */
780 if (type
== FILETYPE_INTERNAL
) {
781 fprintf(stderr
,"[INFO] Using internal bootloader - %d bytes\n",ipod
->bootloader_len
);
782 length
= ipod
->bootloader_len
;
788 /* First check that the input file is the correct type for this ipod. */
789 infile
=open(filename
,O_RDONLY
);
791 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
795 if (type
==FILETYPE_DOT_IPOD
) {
796 n
= read(infile
,header
,8);
798 fprintf(stderr
,"[ERR] Failed to read header from %s\n",filename
);
803 if (memcmp(header
+4, ipod
->modelname
,4)!=0) {
804 fprintf(stderr
,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n",
805 header
[4],header
[5],header
[6],header
[7], ipod
->modelname
);
810 filechksum
= be2int(header
);
812 length
= filesize(infile
)-8;
814 length
= filesize(infile
);
818 newsize
=(length
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
820 fprintf(stderr
,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n",
823 if (newsize
> BUFFER_SIZE
) {
824 fprintf(stderr
,"[ERR] Input file too big for buffer\n");
825 if (infile
>= 0) close(infile
);
829 /* Check if we have enough space */
830 /* TODO: Check the size of the partition. */
831 if (ipod
->nimages
> 1) {
832 bytesavailable
=ipod
->ipod_directory
[1].devOffset
-ipod
->ipod_directory
[0].devOffset
;
833 if (bytesavailable
< newsize
) {
834 fprintf(stderr
,"[INFO] Moving images to create room for new firmware...\n");
836 /* TODO: Implement image movement */
837 fprintf(stderr
,"[ERR] Image movement not yet implemented.\n");
844 if (type
== FILETYPE_INTERNAL
) {
845 memcpy(ipod_sectorbuf
,ipod
->bootloader
,ipod
->bootloader_len
);
850 fprintf(stderr
,"[INFO] Reading input file...\n");
851 /* We now know we have enough space, so write it. */
852 n
= read(infile
,ipod_sectorbuf
,length
);
854 fprintf(stderr
,"[ERR] Couldn't read input file\n");
861 /* Pad the data with zeros */
862 memset(ipod_sectorbuf
+length
,0,newsize
-length
);
864 if (type
==FILETYPE_DOT_IPOD
) {
865 chksum
= ipod
->modelnum
;
866 for (i
= 0; i
< length
; i
++) {
867 /* add 8 unsigned bits but keep a 32 bit sum */
868 chksum
+= ipod_sectorbuf
[i
];
871 if (chksum
== filechksum
) {
872 fprintf(stderr
,"[INFO] Checksum OK in %s\n",filename
);
874 fprintf(stderr
,"[ERR] Checksum in %s failed check\n",filename
);
879 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
880 fprintf(stderr
,"[ERR] Seek failed\n");
884 if ((n
= ipod_write(ipod
,ipod_sectorbuf
,newsize
)) < 0) {
885 perror("[ERR] Write failed\n");
890 fprintf(stderr
,"[ERR] Short write - requested %d bytes, received %d\n"
894 fprintf(stderr
,"[INFO] Wrote %d bytes to firmware partition\n",n
);
896 /* Now we need to update the "len", "entryOffset" and "chksum" fields */
898 for (i
= 0; i
< length
; i
++) {
899 /* add 8 unsigned bits but keep a 32 bit sum */
900 chksum
+= ipod_sectorbuf
[i
];
903 x
= ipod
->diroffset
% ipod
->sector_size
;
906 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
908 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
909 if (n
< 0) { return -1; }
911 /* Update entries for image 0 */
912 int2le(length
,ipod_sectorbuf
+x
+16);
913 int2le(0,ipod_sectorbuf
+x
+24);
914 int2le(chksum
,ipod_sectorbuf
+x
+28);
916 /* Write directory */
917 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
918 n
=ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
919 if (n
< 0) { return -1; }
924 int read_firmware(struct ipod_t
* ipod
, char* filename
, int type
)
930 unsigned long chksum
=0; /* 32 bit checksum - Rockbox .ipod style*/
931 unsigned char header
[8]; /* Header for .ipod file */
933 if (ipod
->ipod_directory
[0].entryOffset
!= 0) {
934 /* We have a bootloader... */
935 length
= ipod
->ipod_directory
[0].entryOffset
;
937 length
= ipod
->ipod_directory
[0].len
;
940 fprintf(stderr
,"[INFO] Reading firmware (%d bytes)\n",length
);
942 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[0].devOffset
) < 0) {
946 i
= (length
+ipod
->sector_size
-1) & ~(ipod
->sector_size
-1);
947 fprintf(stderr
,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n",
950 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,i
)) < 0) {
955 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
960 outfile
= open(filename
,O_CREAT
|O_TRUNC
|O_WRONLY
|O_BINARY
,0666);
962 fprintf(stderr
,"[ERR] Couldn't open file %s\n",filename
);
966 if (type
== FILETYPE_DOT_IPOD
) {
967 chksum
= ipod
->modelnum
;
968 for (i
= 0; i
< length
; i
++) {
969 /* add 8 unsigned bits but keep a 32 bit sum */
970 chksum
+= ipod_sectorbuf
[i
];
973 int2be(chksum
,header
);
974 memcpy(header
+4, ipod
->modelname
,4);
976 n
= write(outfile
,header
,8);
978 fprintf(stderr
,"[ERR] Write error - %d\n",n
);
982 n
= write(outfile
,ipod_sectorbuf
,length
);
984 fprintf(stderr
,"[ERR] Write error - %d\n",n
);
991 int read_directory(struct ipod_t
* ipod
)
996 unsigned short version
;
1000 /* Read firmware partition header (first 512 bytes of disk - but
1001 let's read a whole sector) */
1003 if (ipod_seek(ipod
, ipod
->start
) < 0) {
1004 fprintf(stderr
,"[ERR] Seek to 0x%08x in read_directory() failed.\n",
1005 (unsigned int)(ipod
->start
));
1009 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1011 fprintf(stderr
,"[ERR] ipod_read(ipod,buf,0x%08x) failed in read_directory()\n", ipod
->sector_size
);
1015 if (memcmp(ipod_sectorbuf
,apple_stop_sign
,sizeof(apple_stop_sign
))!=0) {
1016 fprintf(stderr
,"[ERR] Firmware partition doesn't contain Apple copyright, aborting.\n");
1020 if (memcmp(ipod_sectorbuf
+0x100,"]ih[",4)!=0) {
1021 fprintf(stderr
,"[ERR] Bad firmware directory\n");
1025 version
= le2ushort(ipod_sectorbuf
+0x10a);
1026 if ((version
!= 2) && (version
!= 3)) {
1027 fprintf(stderr
,"[ERR] Unknown firmware format version %04x\n",
1030 ipod
->diroffset
=le2int(ipod_sectorbuf
+0x104) + 0x200;
1032 /* diroffset may not be sector-aligned */
1033 x
= ipod
->diroffset
% ipod
->sector_size
;
1035 /* Read directory */
1036 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) {
1037 fprintf(stderr
,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod
->diroffset
);
1041 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1043 fprintf(stderr
,"[ERR] Read of directory failed.\n");
1047 p
= ipod_sectorbuf
+ x
;
1049 /* A hack to detect 2nd gen Nanos - maybe there is a better way? */
1052 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1054 fprintf(stderr
,"[ERR] Read of directory failed.\n");
1060 while ((ipod
->nimages
< MAX_IMAGES
) && (p
< (ipod_sectorbuf
+ x
+ 400)) &&
1061 ((memcmp(p
,"!ATA",4)==0) || (memcmp(p
,"DNAN",4)==0))) {
1063 if (memcmp(p
,"soso",4)==0) {
1064 ipod
->ipod_directory
[ipod
->nimages
].ftype
=FTYPE_OSOS
;
1065 } else if (memcmp(p
,"crsr",4)==0) {
1066 ipod
->ipod_directory
[ipod
->nimages
].ftype
=FTYPE_RSRC
;
1067 } else if (memcmp(p
,"dpua",4)==0) {
1068 ipod
->ipod_directory
[ipod
->nimages
].ftype
=FTYPE_AUPD
;
1069 } else if (memcmp(p
,"ebih",4)==0) {
1070 ipod
->ipod_directory
[ipod
->nimages
].ftype
=FTYPE_HIBE
;
1072 fprintf(stderr
,"[ERR] Unknown image type %c%c%c%c\n",
1073 p
[0],p
[1],p
[2],p
[3]);
1076 ipod
->ipod_directory
[ipod
->nimages
].id
=le2int(p
);
1078 ipod
->ipod_directory
[ipod
->nimages
].devOffset
=le2int(p
);
1080 ipod
->ipod_directory
[ipod
->nimages
].len
=le2int(p
);
1082 ipod
->ipod_directory
[ipod
->nimages
].addr
=le2int(p
);
1084 ipod
->ipod_directory
[ipod
->nimages
].entryOffset
=le2int(p
);
1086 ipod
->ipod_directory
[ipod
->nimages
].chksum
=le2int(p
);
1088 ipod
->ipod_directory
[ipod
->nimages
].vers
=le2int(p
);
1090 ipod
->ipod_directory
[ipod
->nimages
].loadAddr
=le2int(p
);
1095 if ((ipod
->nimages
> 1) && (version
==2)) {
1096 /* The 3g firmware image doesn't appear to have a version, so
1097 let's make one up... Note that this is never written back to the
1098 ipod, so it's OK to do. */
1100 if (ipod
->ipod_directory
[0].vers
== 0) { ipod
->ipod_directory
[0].vers
= 3; }
1102 ipod
->fwoffset
= ipod
->start
;
1104 ipod
->fwoffset
= ipod
->start
+ ipod
->sector_size
;
1110 int list_images(struct ipod_t
* ipod
)
1115 printf(" Type id devOffset len addr entryOffset chksum vers loadAddr devOffset+len\n");
1116 for (i
= 0 ; i
< ipod
->nimages
; i
++) {
1117 printf("%d - %s 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",i
,
1118 ftypename
[ipod
->ipod_directory
[i
].ftype
],
1119 ipod
->ipod_directory
[i
].id
,
1120 ipod
->ipod_directory
[i
].devOffset
,
1121 ipod
->ipod_directory
[i
].len
,
1122 ipod
->ipod_directory
[i
].addr
,
1123 ipod
->ipod_directory
[i
].entryOffset
,
1124 ipod
->ipod_directory
[i
].chksum
,
1125 ipod
->ipod_directory
[i
].vers
,
1126 ipod
->ipod_directory
[i
].loadAddr
,
1127 ipod
->ipod_directory
[i
].devOffset
+((ipod
->ipod_directory
[i
].len
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1)));
1132 printf("Listing firmware partition contents:\n");
1135 for (i
= 0 ; i
< ipod
->nimages
; i
++) {
1136 printf("Image %d:\n",i
+1);
1137 switch(ipod
->ipod_directory
[i
].ftype
) {
1139 if (ipod
->ipod_directory
[i
].entryOffset
==0) {
1140 printf(" Main firmware - %d bytes\n",
1141 ipod
->ipod_directory
[i
].len
);
1143 printf(" Main firmware - %d bytes\n",
1144 ipod
->ipod_directory
[i
].entryOffset
);
1145 printf(" Third-party bootloader - %d bytes\n",
1146 ipod
->ipod_directory
[i
].len
-ipod
->ipod_directory
[i
].entryOffset
);
1150 printf(" %s - %d bytes\n",
1151 ftypename
[ipod
->ipod_directory
[i
].ftype
],
1152 ipod
->ipod_directory
[i
].len
);
1160 int getmodel(struct ipod_t
* ipod
, int ipod_version
)
1162 switch (ipod_version
) {
1164 ipod
->modelstr
="1st or 2nd Generation";
1165 ipod
->modelnum
= 19;
1166 ipod
->modelname
= "1g2g";
1167 ipod
->targetname
= "ipod1g2g";
1168 #ifdef WITH_BOOTOBJS
1169 ipod
->bootloader
= ipod1g2g
;
1170 ipod
->bootloader_len
= LEN_ipod1g2g
;
1174 ipod
->modelstr
="3rd Generation";
1176 ipod
->modelname
= "ip3g";
1177 ipod
->targetname
= "ipod3g";
1178 #ifdef WITH_BOOTOBJS
1179 ipod
->bootloader
= ipod3g
;
1180 ipod
->bootloader_len
= LEN_ipod3g
;
1184 ipod
->modelstr
="1st Generation Mini";
1186 ipod
->modelname
= "mini";
1187 ipod
->targetname
= "ipodmini1g";
1188 #ifdef WITH_BOOTOBJS
1189 ipod
->bootloader
= ipodmini
;
1190 ipod
->bootloader_len
= LEN_ipodmini
;
1194 ipod
->modelstr
="4th Generation";
1196 ipod
->modelname
= "ip4g";
1197 ipod
->targetname
= "ipod4gray";
1198 #ifdef WITH_BOOTOBJS
1199 ipod
->bootloader
= ipod4g
;
1200 ipod
->bootloader_len
= LEN_ipod4g
;
1204 ipod
->modelstr
="Photo/Color";
1206 ipod
->modelname
= "ipco";
1207 ipod
->targetname
= "ipodcolor";
1208 #ifdef WITH_BOOTOBJS
1209 ipod
->bootloader
= ipodcolor
;
1210 ipod
->bootloader_len
= LEN_ipodcolor
;
1214 ipod
->modelstr
="2nd Generation Mini";
1215 ipod
->modelnum
= 11;
1216 ipod
->modelname
= "mn2g";
1217 ipod
->targetname
= "ipodmini2g";
1218 #ifdef WITH_BOOTOBJS
1219 ipod
->bootloader
= ipodmini2g
;
1220 ipod
->bootloader_len
= LEN_ipodmini2g
;
1224 ipod
->modelstr
="1st Generation Nano";
1226 ipod
->modelname
= "nano";
1227 ipod
->targetname
= "ipodnano";
1228 #ifdef WITH_BOOTOBJS
1229 ipod
->bootloader
= ipodnano
;
1230 ipod
->bootloader_len
= LEN_ipodnano
;
1234 ipod
->modelstr
="Video (aka 5th Generation)";
1236 ipod
->modelname
= "ipvd";
1237 ipod
->targetname
= "ipodvideo";
1238 #ifdef WITH_BOOTOBJS
1239 ipod
->bootloader
= ipodvideo
;
1240 ipod
->bootloader_len
= LEN_ipodvideo
;
1244 ipod
->modelstr
="2nd Generation Nano";
1246 ipod
->targetname
= NULL
;
1247 #ifdef WITH_BOOTOBJS
1248 ipod
->bootloader
= NULL
;
1249 ipod
->bootloader_len
= 0;
1253 ipod
->modelname
= NULL
;
1255 ipod
->targetname
= NULL
;
1256 #ifdef WITH_BOOTOBJS
1257 ipod
->bootloader
= NULL
;
1258 ipod
->bootloader_len
= 0;
1265 /* returns number of found ipods or -1 if no ipods found and permission
1266 * for raw disc access was denied. */
1267 int ipod_scan(struct ipod_t
* ipod
)
1272 char last_ipod
[4096];
1276 printf("[INFO] Scanning disk devices...\n");
1278 for (i
= 0; i
<= 25 ; i
++) {
1280 sprintf(ipod
->diskname
,"\\\\.\\PhysicalDrive%d",i
);
1281 #elif defined(linux) || defined (__linux)
1282 sprintf(ipod
->diskname
,"/dev/sd%c",'a'+i
);
1283 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
1284 || defined(__bsdi__) || defined(__DragonFly__)
1285 sprintf(ipod
->diskname
,"/dev/da%d",i
);
1286 #elif defined(__APPLE__) && defined(__MACH__)
1287 sprintf(ipod
->diskname
,"/dev/disk%d",i
);
1289 #error No disk paths defined for this platform
1291 if ((result
= ipod_open(ipod
, 1)) < 0) {
1299 if (read_partinfo(ipod
,1) < 0) {
1304 if ((ipod
->pinfo
[0].start
==0) || (ipod
->pinfo
[0].type
!= 0)) {
1309 if (read_directory(ipod
) < 0) {
1314 ipod_version
=(ipod
->ipod_directory
[0].vers
>>8);
1315 if (getmodel(ipod
,ipod_version
) < 0) {
1321 printf("[INFO] Ipod found - %s (\"%s\") - disk device %d\n",
1322 ipod
->modelstr
,ipod
->macpod
? "macpod" : "winpod",i
);
1324 printf("[INFO] Ipod found - %s (\"%s\") - %s\n",
1325 ipod
->modelstr
,ipod
->macpod
? "macpod" : "winpod",ipod
->diskname
);
1328 strcpy(last_ipod
,ipod
->diskname
);
1333 /* Remember the disk name */
1334 strcpy(ipod
->diskname
,last_ipod
);
1336 else if(n
== 0 && denied
) {
1337 printf("[ERR] FATAL: Permission denied on %d device(s) and no ipod detected.\n", denied
);
1339 printf("[ERR] You need to run this program with administrator priviledges!\n");
1341 printf("[ERR] You need permissions for raw disc access for this program to work!\n");
1344 return (n
== 0 && denied
) ? -1 : n
;
1347 static void put_int32le(uint32_t x
, unsigned char* p
)
1350 p
[1] = (x
>> 8) & 0xff;
1351 p
[2] = (x
>> 16) & 0xff;
1352 p
[3] = (x
>> 24) & 0xff;
1355 int write_dos_partition_table(struct ipod_t
* ipod
)
1361 /* Only support 512-byte sectors at the moment */
1362 if ( ipod
->sector_size
!= 512 )
1364 fprintf(stderr
,"[ERR] Only ipods with 512 bytes per sector are supported.\n");
1368 /* Firstly zero the entire MBR */
1369 memset(ipod_sectorbuf
, 0, ipod
->sector_size
);
1371 /* Now add the partition info */
1372 for (i
=0; i
< 4 ; i
++)
1374 p
= ipod_sectorbuf
+ 0x1be + i
*16;
1376 /* Ensure first partition is type 0, and second is 0xb */
1377 if (i
==0) { type
= 0; }
1378 else if (i
==1) { type
= 0xb; }
1379 else { type
= ipod
->pinfo
[i
].type
; }
1381 put_int32le(type
, p
+ 4);
1382 put_int32le(ipod
->pinfo
[i
].start
, p
+ 8);
1383 put_int32le(ipod
->pinfo
[i
].size
, p
+ 12);
1386 /* Finally add the magic */
1387 ipod_sectorbuf
[0x1fe] = 0x55;
1388 ipod_sectorbuf
[0x1ff] = 0xaa;
1390 if (ipod_seek(ipod
, 0) < 0) {
1391 fprintf(stderr
,"[ERR] Seek failed writing MBR\n");
1396 if ((n
= ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
)) < 0) {
1397 perror("[ERR] Write failed\n");
1404 /* Get the XML Device Information, as documented here:
1406 http://www.ipodlinux.org/wiki/Device_Information
1409 int ipod_get_xmlinfo(struct ipod_t
* ipod
)
1411 unsigned char hdr
[255];
1412 unsigned char buf
[255];
1418 if (ipod_scsi_inquiry(ipod
, 0xc0, buf
, sizeof(buf
)) < 0)
1420 fprintf(stderr
,"[ERR] Sending SCSI Command failed.\n");
1424 /* Reading directly into hdr[] causes problems (for an unknown reason) on
1426 memcpy(hdr
, buf
, sizeof(hdr
));
1430 psize
= npages
* 0xf8; /* Hopefully this is enough. */
1432 ipod
->xmlinfo
= malloc(psize
);
1433 ipod
->xmlinfo_len
= 0;
1435 if (ipod
->xmlinfo
== NULL
) {
1436 fprintf(stderr
,"[ERR] Could not allocate RAM for xmlinfo\n");
1442 for (i
=0; i
< npages
; i
++) {
1443 if (ipod_scsi_inquiry(ipod
, hdr
[i
+4], buf
, sizeof(buf
)) < 0) {
1444 fprintf(stderr
,"[ERR] Sending SCSI Command failed.\n");
1448 if ((buf
[3] + ipod
->xmlinfo_len
) > psize
) {
1449 fprintf(stderr
,"[ERR] Ran out of memory reading xmlinfo\n");
1450 free(ipod
->xmlinfo
);
1451 ipod
->xmlinfo
= NULL
;
1452 ipod
->xmlinfo_len
= 0;
1456 memcpy(p
, buf
+ 4, buf
[3]);
1458 ipod
->xmlinfo_len
+= buf
[3];
1461 /* NULL-terminate the XML info */
1464 fprintf(stderr
,"[INFO] Read XML info (%d bytes)\n",ipod
->xmlinfo_len
);
1469 void ipod_get_ramsize(struct ipod_t
* ipod
)
1471 const char needle
[] = "<key>RAM</key>\n<integer>";
1474 if (ipod
->xmlinfo
== NULL
)
1477 p
= strstr(ipod
->xmlinfo
, needle
);
1480 ipod
->ramsize
= atoi(p
+ sizeof(needle
) - 1);
1486 static inline uint32_t getuint32le(unsigned char* buf
)
1488 int32_t res
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
1493 /* testMarker and GetSecurityBlockKey based on code from BadBlocks and
1494 Kingstone, posted at http://ipodlinux.org/Flash_Decryption
1498 static bool testMarker(int marker
)
1500 int mask
, decrypt
, temp1
, temp2
;
1502 mask
= (marker
&0xff)|((marker
&0xff)<<8)|((marker
&0xff)<<16)|((marker
&0xff)<<24);
1503 decrypt
= marker
^ mask
;
1504 temp1
=(int)((unsigned int)decrypt
>>24);
1510 temp2
=(int)((unsigned int)temp2
>>24);
1511 decrypt
=decrypt
<<16;
1512 decrypt
=(int)((unsigned int)decrypt
>>24);
1514 if ((temp1
< temp2
) && (temp2
< decrypt
))
1516 temp1
= temp1
& 0xf;
1517 temp2
= temp2
& 0xf;
1518 decrypt
= decrypt
& 0xf;
1520 if ((temp1
> temp2
) && (temp2
> decrypt
) && (decrypt
!= 0))
1528 static int GetSecurityBlockKey(unsigned char *data
, unsigned char* this_key
)
1530 int constant
= 0x54c3a298;
1537 static const int offset
[8]={0x5,0x25,0x6f,0x69,0x15,0x4d,0x40,0x34};
1539 for (c
= 0; c
< 8; c
++)
1542 aMarker
= getuint32le(data
+ pos
);
1544 if (testMarker(aMarker
))
1547 pos
=(offset
[c
+1]*4)+4;
1549 pos
=(offset
[0]*4)+4;
1555 for (count
=0;count
<2;count
++){
1556 int word
= getuint32le(data
+ pos
);
1559 temp1
= temp1
^constant
;
1569 for (count
=2;count
<128;count
=count
+2){
1570 r2
=getuint32le(data
+count
*4);
1571 r12
=getuint32le(data
+(count
*4)+4);
1572 r_tmp
=(unsigned int)r12
>>16;
1573 r14
=r2
| ((int)r_tmp
);
1581 // Invert key, little endian
1582 this_key
[0] = key
& 0xff;
1583 this_key
[1] = (key
>> 8) & 0xff;
1584 this_key
[2] = (key
>> 16) & 0xff;
1585 this_key
[3] = (key
>> 24) & 0xff;
1592 static int find_key(struct ipod_t
* ipod
, int aupd
, unsigned char* key
)
1596 /* Firstly read the security block and find the RC4 key. This is
1597 in the sector preceeding the AUPD image. */
1599 fprintf(stderr
, "[INFO] Reading security block at offset 0x%08x\n",ipod
->ipod_directory
[aupd
].devOffset
-ipod
->sector_size
);
1600 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[aupd
].devOffset
-ipod
->sector_size
) < 0) {
1604 if ((n
= ipod_read(ipod
, ipod_sectorbuf
, 512)) < 0) {
1608 n
= GetSecurityBlockKey(ipod_sectorbuf
, key
);
1612 fprintf(stderr
, "[ERR] %d keys found in security block, can not continue\n",n
);
1619 int read_aupd(struct ipod_t
* ipod
, char* filename
)
1626 struct rc4_key_t rc4
;
1627 unsigned char key
[4];
1628 unsigned long chksum
=0;
1631 while ((aupd
< ipod
->nimages
) && (ipod
->ipod_directory
[aupd
].ftype
!= FTYPE_AUPD
))
1636 if (aupd
== ipod
->nimages
)
1638 fprintf(stderr
,"[ERR] No AUPD image in firmware partition.\n");
1642 length
= ipod
->ipod_directory
[aupd
].len
;
1644 fprintf(stderr
,"[INFO] Reading firmware (%d bytes)\n",length
);
1646 if (find_key(ipod
, aupd
, key
) < 0)
1651 fprintf(stderr
, "[INFO] Decrypting AUPD image with key %02x%02x%02x%02x\n",key
[0],key
[1],key
[2],key
[3]);
1653 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[aupd
].devOffset
) < 0) {
1657 i
= (length
+ipod
->sector_size
-1) & ~(ipod
->sector_size
-1);
1659 if ((n
= ipod_read(ipod
,ipod_sectorbuf
,i
)) < 0) {
1664 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
1669 /* Perform the decryption - this is standard (A)RC4 */
1670 matrixArc4Init(&rc4
, key
, 4);
1671 matrixArc4(&rc4
, ipod_sectorbuf
, ipod_sectorbuf
, length
);
1674 for (i
= 0; i
< (int)length
; i
++) {
1675 /* add 8 unsigned bits but keep a 32 bit sum */
1676 chksum
+= ipod_sectorbuf
[i
];
1679 if (chksum
!= ipod
->ipod_directory
[aupd
].chksum
)
1681 fprintf(stderr
,"[ERR] Decryption failed - checksum error\n");
1684 fprintf(stderr
,"[INFO] Decrypted OK (checksum matches header)\n");
1686 outfile
= open(filename
,O_CREAT
|O_TRUNC
|O_WRONLY
|O_BINARY
,0666);
1688 fprintf(stderr
,"[ERR] Couldn't open file %s\n",filename
);
1692 n
= write(outfile
,ipod_sectorbuf
,length
);
1694 fprintf(stderr
,"[ERR] Write error - %d\n",n
);
1701 int write_aupd(struct ipod_t
* ipod
, char* filename
)
1703 unsigned int length
;
1710 unsigned long chksum
=0;
1711 struct rc4_key_t rc4
;
1712 unsigned char key
[4];
1714 /* First check that the input file is the correct type for this ipod. */
1715 infile
=open(filename
,O_RDONLY
);
1717 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
1721 length
= filesize(infile
);
1722 newsize
=(length
+ipod
->sector_size
-1)&~(ipod
->sector_size
-1);
1724 fprintf(stderr
,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n",
1727 if (newsize
> BUFFER_SIZE
) {
1728 fprintf(stderr
,"[ERR] Input file too big for buffer\n");
1729 if (infile
>= 0) close(infile
);
1733 /* Find aupd image number */
1735 while ((aupd
< ipod
->nimages
) && (ipod
->ipod_directory
[aupd
].ftype
!= FTYPE_AUPD
))
1740 if (aupd
== ipod
->nimages
)
1742 fprintf(stderr
,"[ERR] No AUPD image in firmware partition.\n");
1746 if (length
!= ipod
->ipod_directory
[aupd
].len
)
1748 fprintf(stderr
,"[ERR] AUPD image (%d bytes) differs in size to %s (%d bytes).\n",
1749 ipod
->ipod_directory
[aupd
].len
, filename
, length
);
1753 if (find_key(ipod
, aupd
, key
) < 0)
1758 fprintf(stderr
, "[INFO] Encrypting AUPD image with key %02x%02x%02x%02x\n",key
[0],key
[1],key
[2],key
[3]);
1760 /* We now know we have enough space, so write it. */
1762 fprintf(stderr
,"[INFO] Reading input file...\n");
1763 n
= read(infile
,ipod_sectorbuf
,length
);
1765 fprintf(stderr
,"[ERR] Couldn't read input file\n");
1771 /* Pad the data with zeros */
1772 memset(ipod_sectorbuf
+length
,0,newsize
-length
);
1774 /* Calculate the new checksum (before we encrypt) */
1776 for (i
= 0; i
< (int)length
; i
++) {
1777 /* add 8 unsigned bits but keep a 32 bit sum */
1778 chksum
+= ipod_sectorbuf
[i
];
1781 /* Perform the encryption - this is standard (A)RC4 */
1782 matrixArc4Init(&rc4
, key
, 4);
1783 matrixArc4(&rc4
, ipod_sectorbuf
, ipod_sectorbuf
, length
);
1785 if (ipod_seek(ipod
, ipod
->fwoffset
+ipod
->ipod_directory
[aupd
].devOffset
) < 0) {
1786 fprintf(stderr
,"[ERR] Seek failed\n");
1790 if ((n
= ipod_write(ipod
,ipod_sectorbuf
,newsize
)) < 0) {
1791 perror("[ERR] Write failed\n");
1796 fprintf(stderr
,"[ERR] Short write - requested %d bytes, received %d\n"
1800 fprintf(stderr
,"[INFO] Wrote %d bytes to firmware partition\n",n
);
1802 x
= ipod
->diroffset
% ipod
->sector_size
;
1804 /* Read directory */
1805 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
1807 n
=ipod_read(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1808 if (n
< 0) { return -1; }
1810 /* Update checksum */
1811 fprintf(stderr
,"[INFO] Updating checksum to 0x%08x (was 0x%08x)\n",(unsigned int)chksum
,le2int(ipod_sectorbuf
+ x
+ aupd
*40 + 28));
1812 int2le(chksum
,ipod_sectorbuf
+x
+aupd
*40+28);
1814 /* Write directory */
1815 if (ipod_seek(ipod
, ipod
->start
+ ipod
->diroffset
- x
) < 0) { return -1; }
1816 n
=ipod_write(ipod
, ipod_sectorbuf
, ipod
->sector_size
);
1817 if (n
< 0) { return -1; }