diff options
author | Dave Chapman <dave@dchapman.com> | 2007-02-08 18:05:50 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2007-02-08 18:05:50 +0000 |
commit | bdc27ff20c3666989cd8ba83fc9a43c25382ced4 (patch) | |
tree | fb66ef4d48bc2c2a97ac68fe78c8bb2901f296e0 | |
parent | deb83637512488b42a848ced66d039fa8df0f428 (diff) | |
download | rockbox-bdc27ff20c3666989cd8ba83fc9a43c25382ced4.tar.gz rockbox-bdc27ff20c3666989cd8ba83fc9a43c25382ced4.zip |
Work-in-progress (i.e. not well tested) changes: Add the option to build ipodpatcher with the Rockbox bootloaders embedded (see the comments in the Makefile for build instructions). This gives a new --install option which will search for an ipod, and if exactly one is found, will install the embedded bootloader. Even easier is the new interactive mode - running ipodpatcher with no command-line options (e.g. double-clicking on ipodpatcher.exe in Windows) will cause ipodpatcher to search for an ipod, and if exactly one is found, ask the user if he/she wishes to install the bootloader. Thanks to Bryan Childs for sample code to deal with prompts.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12235 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | tools/ipodpatcher/Makefile | 48 | ||||
-rw-r--r-- | tools/ipodpatcher/ipod2c.c | 139 | ||||
-rw-r--r-- | tools/ipodpatcher/ipodio.h | 4 | ||||
-rw-r--r-- | tools/ipodpatcher/ipodpatcher.c | 257 |
4 files changed, 369 insertions, 79 deletions
diff --git a/tools/ipodpatcher/Makefile b/tools/ipodpatcher/Makefile index d796f4494c..559b2f3ea5 100644 --- a/tools/ipodpatcher/Makefile +++ b/tools/ipodpatcher/Makefile | |||
@@ -1,5 +1,15 @@ | |||
1 | CFLAGS=-Wall | 1 | CFLAGS=-Wall |
2 | 2 | ||
3 | BOOT_H = ipod3g.h ipod4g.h ipodcolor.h ipodmini.h ipodmini2g.h ipodnano.h ipodvideo.h | ||
4 | |||
5 | # Uncomment the next two lines to build with embedded bootloaders and the | ||
6 | # --install option and interactive mode. You need the full set of Rockbox | ||
7 | # bootloaders in this directory - download them from | ||
8 | # http://download.rockbox.org/bootloader/ipod/bootloaders.zip | ||
9 | |||
10 | BOOTSRC = ipod3g.c ipod4g.c ipodcolor.c ipodmini.c ipodmini2g.c ipodnano.c ipodvideo.c | ||
11 | CFLAGS += -DWITH_BOOTOBJS | ||
12 | |||
3 | ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN) | 13 | ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN) |
4 | OUTPUT=ipodpatcher.exe | 14 | OUTPUT=ipodpatcher.exe |
5 | CROSS= | 15 | CROSS= |
@@ -9,15 +19,43 @@ OUTPUT=ipodpatcher | |||
9 | CROSS=i586-mingw32msvc- | 19 | CROSS=i586-mingw32msvc- |
10 | endif | 20 | endif |
11 | 21 | ||
22 | NATIVECC = gcc | ||
23 | CC = $(CROSS)gcc | ||
24 | |||
12 | all: $(OUTPUT) | 25 | all: $(OUTPUT) |
13 | 26 | ||
14 | ipodpatcher: ipodpatcher.c ipodio-posix.c parttypes.h | 27 | ipodpatcher: ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) |
15 | gcc $(CFLAGS) -o ipodpatcher ipodpatcher.c ipodio-posix.c | 28 | gcc $(CFLAGS) -o ipodpatcher ipodpatcher.c ipodio-posix.c $(BOOTSRC) |
16 | strip ipodpatcher | 29 | strip ipodpatcher |
17 | 30 | ||
18 | ipodpatcher.exe: ipodpatcher.c ipodio-win32.c parttypes.h | 31 | ipodpatcher.exe: ipodpatcher.c ipodio-win32.c parttypes.h $(BOOTSRC) |
19 | $(CROSS)gcc $(CFLAGS) -o ipodpatcher.exe ipodpatcher.c ipodio-win32.c | 32 | $(CC) $(CFLAGS) -o ipodpatcher.exe ipodpatcher.c ipodio-win32.c $(BOOTSRC) |
20 | $(CROSS)strip ipodpatcher.exe | 33 | $(CROSS)strip ipodpatcher.exe |
21 | 34 | ||
35 | ipod2c: ipod2c.c | ||
36 | $(NATIVECC) $(CFLAGS) -o ipod2c ipod2c.c | ||
37 | |||
38 | ipod3g.c: bootloader-ipod3g.ipod ipod2c | ||
39 | ./ipod2c bootloader-ipod3g.ipod ipod3g | ||
40 | |||
41 | ipod4g.c: bootloader-ipod4g.ipod ipod2c | ||
42 | ./ipod2c bootloader-ipod4g.ipod ipod4g | ||
43 | |||
44 | ipodcolor.c: bootloader-ipodcolor.ipod ipod2c | ||
45 | ./ipod2c bootloader-ipodcolor.ipod ipodcolor | ||
46 | |||
47 | ipodmini.c: bootloader-ipodmini.ipod ipod2c | ||
48 | ./ipod2c bootloader-ipodmini.ipod ipodmini | ||
49 | |||
50 | ipodmini2g.c: bootloader-ipodmini2g.ipod ipod2c | ||
51 | ./ipod2c bootloader-ipodmini2g.ipod ipodmini2g | ||
52 | |||
53 | ipodnano.c: bootloader-ipodnano.ipod ipod2c | ||
54 | ./ipod2c bootloader-ipodnano.ipod ipodnano | ||
55 | |||
56 | ipodvideo.c: bootloader-ipodvideo.ipod ipod2c | ||
57 | ./ipod2c bootloader-ipodvideo.ipod ipodvideo | ||
58 | |||
59 | |||
22 | clean: | 60 | clean: |
23 | rm -f ipodpatcher.exe ipodpatcher *~ | 61 | rm -f ipodpatcher.exe ipodpatcher ipod2c *~ $(BOOTSRC) $(BOOT_H) |
diff --git a/tools/ipodpatcher/ipod2c.c b/tools/ipodpatcher/ipod2c.c new file mode 100644 index 0000000000..af2e25dd09 --- /dev/null +++ b/tools/ipodpatcher/ipod2c.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: ipodio-win32.c 12205 2007-02-05 01:20:20Z dave $ | ||
9 | * | ||
10 | * Copyright (C) 2007 Dave Chapman | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <stdio.h> | ||
21 | #include <string.h> | ||
22 | #include <sys/types.h> | ||
23 | #include <sys/stat.h> | ||
24 | #include <unistd.h> | ||
25 | #include <fcntl.h> | ||
26 | #include <stdlib.h> | ||
27 | |||
28 | #ifndef O_BINARY | ||
29 | #define O_BINARY 0 | ||
30 | #endif | ||
31 | |||
32 | static off_t filesize(int fd) | ||
33 | { | ||
34 | struct stat buf; | ||
35 | |||
36 | fstat(fd,&buf); | ||
37 | return buf.st_size; | ||
38 | } | ||
39 | |||
40 | static int write_cfile(unsigned char* buf, off_t len, char* cname) | ||
41 | { | ||
42 | char filename[256]; | ||
43 | FILE* fp; | ||
44 | int i; | ||
45 | |||
46 | snprintf(filename,256,"%s.c",cname); | ||
47 | |||
48 | fp = fopen(filename,"w+"); | ||
49 | if (fp == NULL) { | ||
50 | fprintf(stderr,"Couldn't open %s\n",filename); | ||
51 | return -1; | ||
52 | } | ||
53 | |||
54 | fprintf(fp,"/* Generated by ipod2c */\n\n"); | ||
55 | fprintf(fp,"unsigned char %s[] = {",cname); | ||
56 | |||
57 | for (i=0;i<len;i++) { | ||
58 | if ((i % 16) == 0) { | ||
59 | fprintf(fp,"\n "); | ||
60 | } | ||
61 | if (i == (len-1)) { | ||
62 | fprintf(fp,"0x%02x",buf[i]); | ||
63 | } else { | ||
64 | fprintf(fp,"0x%02x, ",buf[i]); | ||
65 | } | ||
66 | } | ||
67 | fprintf(fp,"\n};\n"); | ||
68 | |||
69 | fclose(fp); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int write_hfile(unsigned char* buf, off_t len, char* cname) | ||
74 | { | ||
75 | char filename[256]; | ||
76 | FILE* fp; | ||
77 | |||
78 | snprintf(filename,256,"%s.h",cname); | ||
79 | fp = fopen(filename,"w+"); | ||
80 | if (fp == NULL) { | ||
81 | fprintf(stderr,"Couldn't open %s\n",filename); | ||
82 | return -1; | ||
83 | } | ||
84 | |||
85 | fprintf(fp,"/* Generated by ipod2c */\n\n"); | ||
86 | fprintf(fp,"#define LEN_%s %d\n",cname,(int)len); | ||
87 | fprintf(fp,"extern unsigned char %s[];\n",cname); | ||
88 | fclose(fp); | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | int main (int argc, char* argv[]) | ||
93 | { | ||
94 | char* infile; | ||
95 | char* cname; | ||
96 | int fd; | ||
97 | unsigned char* buf; | ||
98 | int len; | ||
99 | int n; | ||
100 | |||
101 | if (argc != 3) { | ||
102 | fprintf(stderr,"Usage: ipod2c file.bin cname\n"); | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | infile=argv[1]; | ||
107 | cname=argv[2]; | ||
108 | |||
109 | fd = open(infile,O_RDONLY); | ||
110 | if (fd < 0) { | ||
111 | fprintf(stderr,"Can not open %s\n",infile); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | len = filesize(fd) - 8; | ||
116 | |||
117 | n = lseek(fd,8,SEEK_SET); | ||
118 | if (n != 8) { | ||
119 | fprintf(stderr,"Seek failed\n"); | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | buf = malloc(len); | ||
124 | n = read(fd,buf,len); | ||
125 | if (n < len) { | ||
126 | fprintf(stderr,"Short read, aborting\n"); | ||
127 | return 0; | ||
128 | } | ||
129 | close(fd); | ||
130 | |||
131 | if (write_cfile(buf,len,cname) < 0) { | ||
132 | return -1; | ||
133 | } | ||
134 | if (write_hfile(buf,len,cname) < 0) { | ||
135 | return -1; | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | } | ||
diff --git a/tools/ipodpatcher/ipodio.h b/tools/ipodpatcher/ipodio.h index 9624849562..d0641faa2b 100644 --- a/tools/ipodpatcher/ipodio.h +++ b/tools/ipodpatcher/ipodio.h | |||
@@ -71,6 +71,10 @@ struct ipod_t { | |||
71 | char* modelname; | 71 | char* modelname; |
72 | char* modelstr; | 72 | char* modelstr; |
73 | int macpod; | 73 | int macpod; |
74 | #ifdef WITH_BOOTOBJS | ||
75 | unsigned char* bootloader; | ||
76 | int bootloader_len; | ||
77 | #endif | ||
74 | }; | 78 | }; |
75 | 79 | ||
76 | void print_error(char* msg); | 80 | void print_error(char* msg); |
diff --git a/tools/ipodpatcher/ipodpatcher.c b/tools/ipodpatcher/ipodpatcher.c index bcabe43fc8..8f8fda2e3f 100644 --- a/tools/ipodpatcher/ipodpatcher.c +++ b/tools/ipodpatcher/ipodpatcher.c | |||
@@ -29,6 +29,16 @@ | |||
29 | #include "parttypes.h" | 29 | #include "parttypes.h" |
30 | #include "ipodio.h" | 30 | #include "ipodio.h" |
31 | 31 | ||
32 | #ifdef WITH_BOOTOBJS | ||
33 | #include "ipod3g.h" | ||
34 | #include "ipod4g.h" | ||
35 | #include "ipodmini.h" | ||
36 | #include "ipodmini2g.h" | ||
37 | #include "ipodcolor.h" | ||
38 | #include "ipodnano.h" | ||
39 | #include "ipodvideo.h" | ||
40 | #endif | ||
41 | |||
32 | #define VERSION "0.8svn" | 42 | #define VERSION "0.8svn" |
33 | 43 | ||
34 | int verbose = 0; | 44 | int verbose = 0; |
@@ -401,12 +411,15 @@ void print_usage(void) | |||
401 | { | 411 | { |
402 | fprintf(stderr,"Usage: ipodpatcher --scan\n"); | 412 | fprintf(stderr,"Usage: ipodpatcher --scan\n"); |
403 | #ifdef __WIN32__ | 413 | #ifdef __WIN32__ |
404 | fprintf(stderr," or ipodpatcher DISKNO [action]\n"); | 414 | fprintf(stderr," or ipodpatcher [DISKNO] [action]\n"); |
405 | #else | 415 | #else |
406 | fprintf(stderr," or ipodpatcher device [action]\n"); | 416 | fprintf(stderr," or ipodpatcher [device] [action]\n"); |
407 | #endif | 417 | #endif |
408 | fprintf(stderr,"\n"); | 418 | fprintf(stderr,"\n"); |
409 | fprintf(stderr,"Where [action] is one of the following options:\n"); | 419 | fprintf(stderr,"Where [action] is one of the following options:\n"); |
420 | #ifdef WITH_BOOTOBJS | ||
421 | fprintf(stderr," --install\n"); | ||
422 | #endif | ||
410 | fprintf(stderr," -l, --list\n"); | 423 | fprintf(stderr," -l, --list\n"); |
411 | fprintf(stderr," -r, --read-partition bootpartition.bin\n"); | 424 | fprintf(stderr," -r, --read-partition bootpartition.bin\n"); |
412 | fprintf(stderr," -w, --write-partition bootpartition.bin\n"); | 425 | fprintf(stderr," -w, --write-partition bootpartition.bin\n"); |
@@ -439,6 +452,10 @@ void print_usage(void) | |||
439 | 452 | ||
440 | enum { | 453 | enum { |
441 | NONE, | 454 | NONE, |
455 | #ifdef WITH_BOOTOBJS | ||
456 | INSTALL, | ||
457 | #endif | ||
458 | INTERACTIVE, | ||
442 | SHOW_INFO, | 459 | SHOW_INFO, |
443 | LIST_IMAGES, | 460 | LIST_IMAGES, |
444 | DELETE_BOOTLOADER, | 461 | DELETE_BOOTLOADER, |
@@ -449,8 +466,11 @@ enum { | |||
449 | WRITE_PARTITION | 466 | WRITE_PARTITION |
450 | }; | 467 | }; |
451 | 468 | ||
452 | #define DOT_IPOD 0 | 469 | #define FILETYPE_DOT_IPOD 0 |
453 | #define DOT_BIN 1 | 470 | #define FILETYPE_DOT_BIN 1 |
471 | #ifdef WITH_BOOTOBJS | ||
472 | #define FILETYPE_INTERNAL 2 | ||
473 | #endif | ||
454 | 474 | ||
455 | char* ftypename[] = { "OSOS", "RSRC", "AUPD", "HIBE" }; | 475 | char* ftypename[] = { "OSOS", "RSRC", "AUPD", "HIBE" }; |
456 | 476 | ||
@@ -548,70 +568,82 @@ int add_bootloader(struct ipod_t* ipod, char* filename, int type) | |||
548 | unsigned long filechksum=0; | 568 | unsigned long filechksum=0; |
549 | unsigned char header[8]; /* Header for .ipod file */ | 569 | unsigned char header[8]; /* Header for .ipod file */ |
550 | 570 | ||
551 | infile=open(filename,O_RDONLY); | 571 | /* Calculate the position in the OSOS image where our bootloader will go. */ |
552 | if (infile < 0) { | 572 | if (ipod->ipod_directory[0].entryOffset>0) { |
553 | fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); | 573 | /* Keep the same entryOffset */ |
554 | return -1; | 574 | entryOffset = ipod->ipod_directory[0].entryOffset; |
575 | } else { | ||
576 | entryOffset = (ipod->ipod_directory[0].len+ipod->sector_size-1)&~(ipod->sector_size-1); | ||
555 | } | 577 | } |
556 | 578 | ||
557 | if (type==DOT_IPOD) { | 579 | #ifdef WITH_BOOTOBJS |
558 | /* First check that the input file is the correct type for this ipod. */ | 580 | if (type == FILETYPE_INTERNAL) { |
559 | n = read(infile,header,8); | 581 | fprintf(stderr,"[INFO] Using internal bootloader - %d bytes\n",ipod->bootloader_len); |
560 | if (n < 8) { | 582 | memcpy(sectorbuf+entryOffset,ipod->bootloader,ipod->bootloader_len); |
561 | fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); | 583 | length = ipod->bootloader_len; |
562 | close(infile); | 584 | paddedlength=(ipod->bootloader_len+ipod->sector_size-1)&~(ipod->sector_size-1); |
585 | } | ||
586 | else | ||
587 | #endif | ||
588 | { | ||
589 | infile=open(filename,O_RDONLY); | ||
590 | if (infile < 0) { | ||
591 | fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); | ||
563 | return -1; | 592 | return -1; |
564 | } | 593 | } |
565 | 594 | ||
566 | if (memcmp(header+4, ipod->modelname,4)!=0) { | 595 | if (type==FILETYPE_DOT_IPOD) { |
567 | fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n", | 596 | /* First check that the input file is the correct type for this ipod. */ |
568 | header[4],header[5],header[6],header[7], ipod->modelname); | 597 | n = read(infile,header,8); |
569 | close(infile); | 598 | if (n < 8) { |
570 | return -1; | 599 | fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); |
600 | close(infile); | ||
601 | return -1; | ||
602 | } | ||
603 | |||
604 | if (memcmp(header+4, ipod->modelname,4)!=0) { | ||
605 | fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n", | ||
606 | header[4],header[5],header[6],header[7], ipod->modelname); | ||
607 | close(infile); | ||
608 | return -1; | ||
609 | } | ||
610 | |||
611 | filechksum = be2int(header); | ||
612 | |||
613 | length=filesize(infile)-8; | ||
614 | } else { | ||
615 | length=filesize(infile); | ||
571 | } | 616 | } |
572 | 617 | paddedlength=(length+ipod->sector_size-1)&~(ipod->sector_size-1); | |
573 | filechksum = be2int(header); | 618 | |
574 | 619 | /* Now read our bootloader - we need to check it before modifying the partition*/ | |
575 | length=filesize(infile)-8; | 620 | n = read(infile,sectorbuf+entryOffset,length); |
576 | } else { | ||
577 | length=filesize(infile); | ||
578 | } | ||
579 | paddedlength=(length+ipod->sector_size-1)&~(ipod->sector_size-1); | ||
580 | |||
581 | /* Now read our bootloader - we need to check it before modifying the partition*/ | ||
582 | n = read(infile,sectorbuf,length); | ||
583 | if (n < 0) { | ||
584 | fprintf(stderr,"[ERR] Couldn't read input file\n"); | ||
585 | close(infile); | 621 | close(infile); |
586 | return -1; | ||
587 | } | ||
588 | |||
589 | if (type==DOT_IPOD) { | ||
590 | /* Calculate and confirm bootloader checksum */ | ||
591 | chksum = ipod->modelnum; | ||
592 | for (i = 0; i < length; i++) { | ||
593 | /* add 8 unsigned bits but keep a 32 bit sum */ | ||
594 | chksum += sectorbuf[i]; | ||
595 | } | ||
596 | 622 | ||
597 | if (chksum == filechksum) { | 623 | if (n < 0) { |
598 | fprintf(stderr,"[INFO] Checksum OK in %s\n",filename); | 624 | fprintf(stderr,"[ERR] Couldn't read input file\n"); |
599 | } else { | ||
600 | fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename); | ||
601 | return -1; | 625 | return -1; |
602 | } | 626 | } |
603 | } | 627 | |
604 | 628 | if (type==FILETYPE_DOT_IPOD) { | |
605 | if (ipod->ipod_directory[0].entryOffset>0) { | 629 | /* Calculate and confirm bootloader checksum */ |
606 | /* Keep the same entryOffset */ | 630 | chksum = ipod->modelnum; |
607 | entryOffset = ipod->ipod_directory[0].entryOffset; | 631 | for (i = entryOffset; i < entryOffset+length; i++) { |
608 | } else { | 632 | /* add 8 unsigned bits but keep a 32 bit sum */ |
609 | entryOffset = (ipod->ipod_directory[0].len+ipod->sector_size-1)&~(ipod->sector_size-1); | 633 | chksum += sectorbuf[i]; |
634 | } | ||
635 | |||
636 | if (chksum == filechksum) { | ||
637 | fprintf(stderr,"[INFO] Checksum OK in %s\n",filename); | ||
638 | } else { | ||
639 | fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename); | ||
640 | return -1; | ||
641 | } | ||
642 | } | ||
610 | } | 643 | } |
611 | 644 | ||
612 | if (entryOffset+paddedlength > BUFFER_SIZE) { | 645 | if (entryOffset+paddedlength > BUFFER_SIZE) { |
613 | fprintf(stderr,"[ERR] Input file too big for buffer\n"); | 646 | fprintf(stderr,"[ERR] Input file too big for buffer\n"); |
614 | close(infile); | ||
615 | return -1; | 647 | return -1; |
616 | } | 648 | } |
617 | 649 | ||
@@ -624,14 +656,13 @@ int add_bootloader(struct ipod_t* ipod, char* filename, int type) | |||
624 | /* Check if we have enough space */ | 656 | /* Check if we have enough space */ |
625 | /* TODO: Check the size of the partition. */ | 657 | /* TODO: Check the size of the partition. */ |
626 | if (ipod->nimages > 1) { | 658 | if (ipod->nimages > 1) { |
627 | if ((ipod->ipod_directory[0].devOffset+entryOffset+paddedlength) >= | 659 | if ((ipod->ipod_directory[0].devOffset+entryOffset+paddedlength) > |
628 | ipod->ipod_directory[1].devOffset) { | 660 | ipod->ipod_directory[1].devOffset) { |
629 | fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); | 661 | fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); |
630 | delta = ipod->ipod_directory[0].devOffset + entryOffset+paddedlength | 662 | delta = ipod->ipod_directory[0].devOffset + entryOffset+paddedlength |
631 | - ipod->ipod_directory[1].devOffset; | 663 | - ipod->ipod_directory[1].devOffset; |
632 | 664 | ||
633 | if (diskmove(ipod, delta) < 0) { | 665 | if (diskmove(ipod, delta) < 0) { |
634 | close(infile); | ||
635 | fprintf(stderr,"[ERR] Image movement failed.\n"); | 666 | fprintf(stderr,"[ERR] Image movement failed.\n"); |
636 | return -1; | 667 | return -1; |
637 | } | 668 | } |
@@ -643,7 +674,6 @@ int add_bootloader(struct ipod_t* ipod, char* filename, int type) | |||
643 | 674 | ||
644 | /* Firstly read the original firmware into sectorbuf */ | 675 | /* Firstly read the original firmware into sectorbuf */ |
645 | fprintf(stderr,"[INFO] Reading original firmware...\n"); | 676 | fprintf(stderr,"[INFO] Reading original firmware...\n"); |
646 | |||
647 | if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { | 677 | if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { |
648 | fprintf(stderr,"[ERR] Seek failed\n"); | 678 | fprintf(stderr,"[ERR] Seek failed\n"); |
649 | return -1; | 679 | return -1; |
@@ -660,16 +690,6 @@ int add_bootloader(struct ipod_t* ipod, char* filename, int type) | |||
660 | return -1; | 690 | return -1; |
661 | } | 691 | } |
662 | 692 | ||
663 | /* Now read our bootloader - we need to seek back to the start */ | ||
664 | lseek(infile,(type == DOT_IPOD ? 8 : 0),SEEK_SET); | ||
665 | n = read(infile,sectorbuf+entryOffset,length); | ||
666 | if (n < 0) { | ||
667 | fprintf(stderr,"[ERR] Couldn't read input file\n"); | ||
668 | close(infile); | ||
669 | return -1; | ||
670 | } | ||
671 | close(infile); | ||
672 | |||
673 | /* Calculate new checksum for combined image */ | 693 | /* Calculate new checksum for combined image */ |
674 | chksum = 0; | 694 | chksum = 0; |
675 | for (i=0;i<entryOffset + length; i++) { | 695 | for (i=0;i<entryOffset + length; i++) { |
@@ -830,7 +850,7 @@ int write_firmware(struct ipod_t* ipod, char* filename, int type) | |||
830 | return -1; | 850 | return -1; |
831 | } | 851 | } |
832 | 852 | ||
833 | if (type==DOT_IPOD) { | 853 | if (type==FILETYPE_DOT_IPOD) { |
834 | n = read(infile,header,8); | 854 | n = read(infile,header,8); |
835 | if (n < 8) { | 855 | if (n < 8) { |
836 | fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); | 856 | fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); |
@@ -887,7 +907,7 @@ int write_firmware(struct ipod_t* ipod, char* filename, int type) | |||
887 | } | 907 | } |
888 | close(infile); | 908 | close(infile); |
889 | 909 | ||
890 | if (type==DOT_IPOD) { | 910 | if (type==FILETYPE_DOT_IPOD) { |
891 | chksum = ipod->modelnum; | 911 | chksum = ipod->modelnum; |
892 | for (i = 0; i < length; i++) { | 912 | for (i = 0; i < length; i++) { |
893 | /* add 8 unsigned bits but keep a 32 bit sum */ | 913 | /* add 8 unsigned bits but keep a 32 bit sum */ |
@@ -1170,40 +1190,72 @@ int getmodel(struct ipod_t* ipod, int ipod_version) | |||
1170 | ipod->modelstr="3rd Generation"; | 1190 | ipod->modelstr="3rd Generation"; |
1171 | ipod->modelnum = 7; | 1191 | ipod->modelnum = 7; |
1172 | ipod->modelname = "ip3g"; | 1192 | ipod->modelname = "ip3g"; |
1193 | #ifdef WITH_BOOTOBJS | ||
1194 | ipod->bootloader = ipod3g; | ||
1195 | ipod->bootloader_len = LEN_ipod3g; | ||
1196 | #endif | ||
1173 | break; | 1197 | break; |
1174 | case 0x40: | 1198 | case 0x40: |
1175 | ipod->modelstr="1st Generation Mini"; | 1199 | ipod->modelstr="1st Generation Mini"; |
1176 | ipod->modelnum = 9; | 1200 | ipod->modelnum = 9; |
1177 | ipod->modelname = "mini"; | 1201 | ipod->modelname = "mini"; |
1202 | #ifdef WITH_BOOTOBJS | ||
1203 | ipod->bootloader = ipodmini; | ||
1204 | ipod->bootloader_len = LEN_ipodmini; | ||
1205 | #endif | ||
1178 | break; | 1206 | break; |
1179 | case 0x50: | 1207 | case 0x50: |
1180 | ipod->modelstr="4th Generation"; | 1208 | ipod->modelstr="4th Generation"; |
1181 | ipod->modelnum = 8; | 1209 | ipod->modelnum = 8; |
1182 | ipod->modelname = "ip4g"; | 1210 | ipod->modelname = "ip4g"; |
1211 | #ifdef WITH_BOOTOBJS | ||
1212 | ipod->bootloader = ipod4g; | ||
1213 | ipod->bootloader_len = LEN_ipod4g; | ||
1214 | #endif | ||
1183 | break; | 1215 | break; |
1184 | case 0x60: | 1216 | case 0x60: |
1185 | ipod->modelstr="Photo/Color"; | 1217 | ipod->modelstr="Photo/Color"; |
1186 | ipod->modelnum = 3; | 1218 | ipod->modelnum = 3; |
1187 | ipod->modelname = "ipco"; | 1219 | ipod->modelname = "ipco"; |
1220 | #ifdef WITH_BOOTOBJS | ||
1221 | ipod->bootloader = ipodcolor; | ||
1222 | ipod->bootloader_len = LEN_ipodcolor; | ||
1223 | #endif | ||
1188 | break; | 1224 | break; |
1189 | case 0x70: | 1225 | case 0x70: |
1190 | ipod->modelstr="2nd Generation Mini"; | 1226 | ipod->modelstr="2nd Generation Mini"; |
1191 | ipod->modelnum = 11; | 1227 | ipod->modelnum = 11; |
1192 | ipod->modelname = "mn2g"; | 1228 | ipod->modelname = "mn2g"; |
1229 | #ifdef WITH_BOOTOBJS | ||
1230 | ipod->bootloader = ipodmini2g; | ||
1231 | ipod->bootloader_len = LEN_ipodmini2g; | ||
1232 | #endif | ||
1193 | break; | 1233 | break; |
1194 | case 0xc0: | 1234 | case 0xc0: |
1195 | ipod->modelstr="1st Generation Nano"; | 1235 | ipod->modelstr="1st Generation Nano"; |
1196 | ipod->modelnum = 4; | 1236 | ipod->modelnum = 4; |
1197 | ipod->modelname = "nano"; | 1237 | ipod->modelname = "nano"; |
1238 | #ifdef WITH_BOOTOBJS | ||
1239 | ipod->bootloader = ipodnano; | ||
1240 | ipod->bootloader_len = LEN_ipodnano; | ||
1241 | #endif | ||
1198 | break; | 1242 | break; |
1199 | case 0xb0: | 1243 | case 0xb0: |
1200 | ipod->modelstr="Video (aka 5th Generation)"; | 1244 | ipod->modelstr="Video (aka 5th Generation)"; |
1201 | ipod->modelnum = 5; | 1245 | ipod->modelnum = 5; |
1202 | ipod->modelname = "ipvd"; | 1246 | ipod->modelname = "ipvd"; |
1247 | #ifdef WITH_BOOTOBJS | ||
1248 | ipod->bootloader = ipodvideo; | ||
1249 | ipod->bootloader_len = LEN_ipodvideo; | ||
1250 | #endif | ||
1203 | break; | 1251 | break; |
1204 | default: | 1252 | default: |
1205 | ipod->modelname = NULL; | 1253 | ipod->modelname = NULL; |
1206 | ipod->modelnum = 0; | 1254 | ipod->modelnum = 0; |
1255 | #ifdef WITH_BOOTOBJS | ||
1256 | ipod->bootloader = NULL; | ||
1257 | ipod->bootloader_len = 0; | ||
1258 | #endif | ||
1207 | return -1; | 1259 | return -1; |
1208 | } | 1260 | } |
1209 | return 0; | 1261 | return 0; |
@@ -1279,6 +1331,9 @@ int ipod_scan(struct ipod_t* ipod) | |||
1279 | 1331 | ||
1280 | int main(int argc, char* argv[]) | 1332 | int main(int argc, char* argv[]) |
1281 | { | 1333 | { |
1334 | #ifdef WITH_BOOTOBJS | ||
1335 | char yesno[4]; | ||
1336 | #endif | ||
1282 | int i; | 1337 | int i; |
1283 | int n; | 1338 | int n; |
1284 | int infile, outfile; | 1339 | int infile, outfile; |
@@ -1320,18 +1375,40 @@ int main(int argc, char* argv[]) | |||
1320 | n = ipod_scan(&ipod); | 1375 | n = ipod_scan(&ipod); |
1321 | if (n==0) { | 1376 | if (n==0) { |
1322 | fprintf(stderr,"[ERR] No ipods found, aborting\n"); | 1377 | fprintf(stderr,"[ERR] No ipods found, aborting\n"); |
1323 | return 0; | 1378 | fprintf(stderr,"[ERR] Please connect your ipod and ensure it is in disk mode\n"); |
1324 | } else if (n > 1) { | 1379 | } else if (n > 1) { |
1325 | fprintf(stderr,"[ERR] %d ipods found, aborting\n",n); | 1380 | fprintf(stderr,"[ERR] %d ipods found, aborting\n",n); |
1381 | fprintf(stderr,"[ERR] Please connect only one ipod.\n"); | ||
1382 | } | ||
1383 | |||
1384 | if (n != 1) { | ||
1385 | #ifdef WITH_BOOTOBJS | ||
1386 | if (argc==1) { | ||
1387 | printf("\nPress ENTER to exit ipodpatcher :"); | ||
1388 | fgets(yesno,4,stdin); | ||
1389 | } | ||
1390 | #endif | ||
1326 | return 0; | 1391 | return 0; |
1327 | } | 1392 | } |
1393 | |||
1328 | i = 1; | 1394 | i = 1; |
1329 | } | 1395 | } |
1330 | 1396 | ||
1397 | #ifdef WITH_BOOTOBJS | ||
1398 | action = INTERACTIVE; | ||
1399 | #else | ||
1400 | action = NONE; | ||
1401 | #endif | ||
1402 | |||
1331 | while (i < argc) { | 1403 | while (i < argc) { |
1332 | if ((strcmp(argv[i],"-l")==0) || (strcmp(argv[i],"--list")==0)) { | 1404 | if ((strcmp(argv[i],"-l")==0) || (strcmp(argv[i],"--list")==0)) { |
1333 | action = LIST_IMAGES; | 1405 | action = LIST_IMAGES; |
1334 | i++; | 1406 | i++; |
1407 | #ifdef WITH_BOOTOBJS | ||
1408 | } else if (strcmp(argv[i],"--install")==0) { | ||
1409 | action = INSTALL; | ||
1410 | i++; | ||
1411 | #endif | ||
1335 | } else if ((strcmp(argv[i],"-d")==0) || | 1412 | } else if ((strcmp(argv[i],"-d")==0) || |
1336 | (strcmp(argv[i],"--delete-bootloader")==0)) { | 1413 | (strcmp(argv[i],"--delete-bootloader")==0)) { |
1337 | action = DELETE_BOOTLOADER; | 1414 | action = DELETE_BOOTLOADER; |
@@ -1339,7 +1416,7 @@ int main(int argc, char* argv[]) | |||
1339 | } else if ((strcmp(argv[i],"-a")==0) || | 1416 | } else if ((strcmp(argv[i],"-a")==0) || |
1340 | (strcmp(argv[i],"--add-bootloader")==0)) { | 1417 | (strcmp(argv[i],"--add-bootloader")==0)) { |
1341 | action = ADD_BOOTLOADER; | 1418 | action = ADD_BOOTLOADER; |
1342 | type = DOT_IPOD; | 1419 | type = FILETYPE_DOT_IPOD; |
1343 | i++; | 1420 | i++; |
1344 | if (i == argc) { print_usage(); return 1; } | 1421 | if (i == argc) { print_usage(); return 1; } |
1345 | filename=argv[i]; | 1422 | filename=argv[i]; |
@@ -1347,7 +1424,7 @@ int main(int argc, char* argv[]) | |||
1347 | } else if ((strcmp(argv[i],"-ab")==0) || | 1424 | } else if ((strcmp(argv[i],"-ab")==0) || |
1348 | (strcmp(argv[i],"--add-bootloader-bin")==0)) { | 1425 | (strcmp(argv[i],"--add-bootloader-bin")==0)) { |
1349 | action = ADD_BOOTLOADER; | 1426 | action = ADD_BOOTLOADER; |
1350 | type = DOT_BIN; | 1427 | type = FILETYPE_DOT_BIN; |
1351 | i++; | 1428 | i++; |
1352 | if (i == argc) { print_usage(); return 1; } | 1429 | if (i == argc) { print_usage(); return 1; } |
1353 | filename=argv[i]; | 1430 | filename=argv[i]; |
@@ -1362,7 +1439,7 @@ int main(int argc, char* argv[]) | |||
1362 | } else if ((strcmp(argv[i],"-wf")==0) || | 1439 | } else if ((strcmp(argv[i],"-wf")==0) || |
1363 | (strcmp(argv[i],"--write-firmware")==0)) { | 1440 | (strcmp(argv[i],"--write-firmware")==0)) { |
1364 | action = WRITE_FIRMWARE; | 1441 | action = WRITE_FIRMWARE; |
1365 | type = DOT_IPOD; | 1442 | type = FILETYPE_DOT_IPOD; |
1366 | i++; | 1443 | i++; |
1367 | if (i == argc) { print_usage(); return 1; } | 1444 | if (i == argc) { print_usage(); return 1; } |
1368 | filename=argv[i]; | 1445 | filename=argv[i]; |
@@ -1370,7 +1447,7 @@ int main(int argc, char* argv[]) | |||
1370 | } else if ((strcmp(argv[i],"-wfb")==0) || | 1447 | } else if ((strcmp(argv[i],"-wfb")==0) || |
1371 | (strcmp(argv[i],"--write-firmware-bin")==0)) { | 1448 | (strcmp(argv[i],"--write-firmware-bin")==0)) { |
1372 | action = WRITE_FIRMWARE; | 1449 | action = WRITE_FIRMWARE; |
1373 | type = DOT_BIN; | 1450 | type = FILETYPE_DOT_BIN; |
1374 | i++; | 1451 | i++; |
1375 | if (i == argc) { print_usage(); return 1; } | 1452 | if (i == argc) { print_usage(); return 1; } |
1376 | filename=argv[i]; | 1453 | filename=argv[i]; |
@@ -1444,6 +1521,26 @@ int main(int argc, char* argv[]) | |||
1444 | 1521 | ||
1445 | if (action==LIST_IMAGES) { | 1522 | if (action==LIST_IMAGES) { |
1446 | list_images(&ipod); | 1523 | list_images(&ipod); |
1524 | #ifdef WITH_BOOTOBJS | ||
1525 | } else if (action==INTERACTIVE) { | ||
1526 | |||
1527 | printf("Do you wish to install the rockbox bootloader? (y/n) :"); | ||
1528 | if (fgets(yesno,4,stdin)) { | ||
1529 | if (yesno[0]=='y') { | ||
1530 | if (ipod_reopen_rw(&ipod) < 0) { | ||
1531 | return 5; | ||
1532 | } | ||
1533 | |||
1534 | if (add_bootloader(&ipod, NULL, FILETYPE_INTERNAL)==0) { | ||
1535 | fprintf(stderr,"[INFO] Bootloader installed successfully.\n"); | ||
1536 | } else { | ||
1537 | fprintf(stderr,"[ERR] --install failed.\n"); | ||
1538 | } | ||
1539 | printf("Press ENTER to exit ipodpatcher :"); | ||
1540 | fgets(yesno,4,stdin); | ||
1541 | } | ||
1542 | } | ||
1543 | #endif | ||
1447 | } else if (action==DELETE_BOOTLOADER) { | 1544 | } else if (action==DELETE_BOOTLOADER) { |
1448 | if (ipod_reopen_rw(&ipod) < 0) { | 1545 | if (ipod_reopen_rw(&ipod) < 0) { |
1449 | return 5; | 1546 | return 5; |
@@ -1468,6 +1565,18 @@ int main(int argc, char* argv[]) | |||
1468 | } else { | 1565 | } else { |
1469 | fprintf(stderr,"[ERR] --add-bootloader failed.\n"); | 1566 | fprintf(stderr,"[ERR] --add-bootloader failed.\n"); |
1470 | } | 1567 | } |
1568 | #ifdef WITH_BOOTOBJS | ||
1569 | } else if (action==INSTALL) { | ||
1570 | if (ipod_reopen_rw(&ipod) < 0) { | ||
1571 | return 5; | ||
1572 | } | ||
1573 | |||
1574 | if (add_bootloader(&ipod, NULL, FILETYPE_INTERNAL)==0) { | ||
1575 | fprintf(stderr,"[INFO] Bootloader installed successfully.\n"); | ||
1576 | } else { | ||
1577 | fprintf(stderr,"[ERR] --install failed.\n"); | ||
1578 | } | ||
1579 | #endif | ||
1471 | } else if (action==WRITE_FIRMWARE) { | 1580 | } else if (action==WRITE_FIRMWARE) { |
1472 | if (ipod_reopen_rw(&ipod) < 0) { | 1581 | if (ipod_reopen_rw(&ipod) < 0) { |
1473 | return 5; | 1582 | return 5; |