diff options
-rw-r--r-- | rbutil/sansapatcher/Makefile | 25 | ||||
-rw-r--r-- | rbutil/sansapatcher/main.c | 22 | ||||
-rw-r--r-- | rbutil/sansapatcher/sansaio.h | 1 | ||||
-rw-r--r-- | rbutil/sansapatcher/sansapatcher.c | 101 | ||||
-rw-r--r-- | rbutil/sansapatcher/sansapatcher.h | 2 |
5 files changed, 121 insertions, 30 deletions
diff --git a/rbutil/sansapatcher/Makefile b/rbutil/sansapatcher/Makefile index b05d8f3257..3786a41030 100644 --- a/rbutil/sansapatcher/Makefile +++ b/rbutil/sansapatcher/Makefile | |||
@@ -14,30 +14,33 @@ CC = $(CROSS)gcc | |||
14 | 14 | ||
15 | all: $(OUTPUT) | 15 | all: $(OUTPUT) |
16 | 16 | ||
17 | sansapatcher: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg.c | 17 | sansapatcher: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg_c200.c bootimg_e200.c |
18 | gcc $(CFLAGS) -o sansapatcher main.c sansapatcher.c sansaio-posix.c bootimg.c | 18 | gcc $(CFLAGS) -o sansapatcher main.c sansapatcher.c sansaio-posix.c bootimg_c200.c bootimg_e200.c |
19 | strip sansapatcher | 19 | strip sansapatcher |
20 | 20 | ||
21 | sansapatcher.exe: main.c sansapatcher.c sansaio-win32.c parttypes.h bootimg.c | 21 | sansapatcher.exe: main.c sansapatcher.c sansaio-win32.c parttypes.h bootimg_c200.c bootimg_e200.c |
22 | $(CC) $(CFLAGS) -o sansapatcher.exe main.c sansapatcher.c sansaio-win32.c bootimg.c | 22 | $(CC) $(CFLAGS) -o sansapatcher.exe main.c sansapatcher.c sansaio-win32.c bootimg_c200.c bootimg_e200.c |
23 | $(CROSS)strip sansapatcher.exe | 23 | $(CROSS)strip sansapatcher.exe |
24 | 24 | ||
25 | sansapatcher-mac: sansapatcher-i386 sansapatcher-ppc | 25 | sansapatcher-mac: sansapatcher-i386 sansapatcher-ppc |
26 | lipo -create sansapatcher-ppc sansapatcher-i386 -output sansapatcher-mac | 26 | lipo -create sansapatcher-ppc sansapatcher-i386 -output sansapatcher-mac |
27 | 27 | ||
28 | sansapatcher-i386: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg.c | 28 | sansapatcher-i386: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg_c200.c bootimg_e200.c |
29 | gcc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -o bin/i386/program -arch i386 $(CFLAGS) -o sansapatcher-i386 main.c sansapatcher.c sansaio-posix.c bootimg.c | 29 | gcc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -o bin/i386/program -arch i386 $(CFLAGS) -o sansapatcher-i386 main.c sansapatcher.c sansaio-posix.c bootimg_c200.c bootimg_e200.c |
30 | strip sansapatcher-i386 | 30 | strip sansapatcher-i386 |
31 | 31 | ||
32 | sansapatcher-ppc: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg.c | 32 | sansapatcher-ppc: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg_c200.c bootimg_e200.c |
33 | gcc -arch ppc $(CFLAGS) -o sansapatcher-ppc main.c sansapatcher.c sansaio-posix.c bootimg.c | 33 | gcc -arch ppc $(CFLAGS) -o sansapatcher-ppc main.c sansapatcher.c sansaio-posix.c bootimg_c200.c bootimg_e200.c |
34 | strip sansapatcher-ppc | 34 | strip sansapatcher-ppc |
35 | 35 | ||
36 | bin2c: bin2c.c | 36 | bin2c: bin2c.c |
37 | $(NATIVECC) $(CFLAGS) -o bin2c bin2c.c | 37 | $(NATIVECC) $(CFLAGS) -o bin2c bin2c.c |
38 | 38 | ||
39 | bootimg.c: PP5022.mi4 bin2c | 39 | bootimg_c200.c: firmware.mi4 bin2c |
40 | ./bin2c PP5022.mi4 bootimg | 40 | ./bin2c firmware.mi4 bootimg_c200 |
41 | |||
42 | bootimg_e200.c: PP5022.mi4 bin2c | ||
43 | ./bin2c PP5022.mi4 bootimg_e200 | ||
41 | 44 | ||
42 | clean: | 45 | clean: |
43 | rm -f sansapatcher.exe sansapatcher-mac sansapatcher-i386 sansapatcher-ppc sansapatcher bin2c bootimg.c bootimg.h *~ | 46 | rm -f sansapatcher.exe sansapatcher-mac sansapatcher-i386 sansapatcher-ppc sansapatcher bin2c bootimg_c200.c bootimg_c200.h bootimg_e200.c bootimg_e200.h *~ |
diff --git a/rbutil/sansapatcher/main.c b/rbutil/sansapatcher/main.c index 7321533bdf..b2b50270a7 100644 --- a/rbutil/sansapatcher/main.c +++ b/rbutil/sansapatcher/main.c | |||
@@ -73,7 +73,7 @@ void print_usage(void) | |||
73 | fprintf(stderr,"DISKNO is the number (e.g. 2) Windows has assigned to your sansa's hard disk.\n"); | 73 | fprintf(stderr,"DISKNO is the number (e.g. 2) Windows has assigned to your sansa's hard disk.\n"); |
74 | fprintf(stderr,"The first hard disk in your computer (i.e. C:\\) will be disk 0, the next disk\n"); | 74 | fprintf(stderr,"The first hard disk in your computer (i.e. C:\\) will be disk 0, the next disk\n"); |
75 | fprintf(stderr,"will be disk 1 etc. sansapatcher will refuse to access a disk unless it\n"); | 75 | fprintf(stderr,"will be disk 1 etc. sansapatcher will refuse to access a disk unless it\n"); |
76 | fprintf(stderr,"can identify it as being an E200.\n"); | 76 | fprintf(stderr,"can identify it as being an E200 or C200.\n"); |
77 | fprintf(stderr,"\n"); | 77 | fprintf(stderr,"\n"); |
78 | #else | 78 | #else |
79 | #if defined(linux) || defined (__linux) | 79 | #if defined(linux) || defined (__linux) |
@@ -84,7 +84,7 @@ void print_usage(void) | |||
84 | fprintf(stderr,"\"device\" is the device node (e.g. /dev/disk1) assigned to your sansa.\n"); | 84 | fprintf(stderr,"\"device\" is the device node (e.g. /dev/disk1) assigned to your sansa.\n"); |
85 | #endif | 85 | #endif |
86 | fprintf(stderr,"sansapatcher will refuse to access a disk unless it can identify it as being\n"); | 86 | fprintf(stderr,"sansapatcher will refuse to access a disk unless it can identify it as being\n"); |
87 | fprintf(stderr,"an E200.\n"); | 87 | fprintf(stderr,"an E200 or C200.\n"); |
88 | #endif | 88 | #endif |
89 | } | 89 | } |
90 | 90 | ||
@@ -154,7 +154,7 @@ int main(int argc, char* argv[]) | |||
154 | 154 | ||
155 | if ((argc > 1) && (strcmp(argv[1],"--scan")==0)) { | 155 | if ((argc > 1) && (strcmp(argv[1],"--scan")==0)) { |
156 | if (sansa_scan(&sansa) == 0) | 156 | if (sansa_scan(&sansa) == 0) |
157 | fprintf(stderr,"[ERR] No E200s found.\n"); | 157 | fprintf(stderr,"[ERR] No E200s or C200s found.\n"); |
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | 160 | ||
@@ -168,13 +168,13 @@ int main(int argc, char* argv[]) | |||
168 | #endif | 168 | #endif |
169 | i = 2; | 169 | i = 2; |
170 | } else { | 170 | } else { |
171 | /* Autoscan for E200s */ | 171 | /* Autoscan for C200/E200s */ |
172 | n = sansa_scan(&sansa); | 172 | n = sansa_scan(&sansa); |
173 | if (n==0) { | 173 | if (n==0) { |
174 | fprintf(stderr,"[ERR] No E200s found, aborting\n"); | 174 | fprintf(stderr,"[ERR] No E200s or C200s found, aborting\n"); |
175 | fprintf(stderr,"[ERR] Please connect your sansa and ensure it is in UMS mode\n"); | 175 | fprintf(stderr,"[ERR] Please connect your sansa and ensure it is in UMS mode\n"); |
176 | #if defined(__APPLE__) && defined(__MACH__) | 176 | #if defined(__APPLE__) && defined(__MACH__) |
177 | fprintf(stderr,"[ERR] Also ensure that your E200's main partition is not mounted.\n"); | 177 | fprintf(stderr,"[ERR] Also ensure that your Sansa's main partition is not mounted.\n"); |
178 | #elif !defined(__WIN32__) | 178 | #elif !defined(__WIN32__) |
179 | if (geteuid()!=0) { | 179 | if (geteuid()!=0) { |
180 | fprintf(stderr,"[ERR] You may also need to run sansapatcher as root.\n"); | 180 | fprintf(stderr,"[ERR] You may also need to run sansapatcher as root.\n"); |
@@ -182,8 +182,8 @@ int main(int argc, char* argv[]) | |||
182 | #endif | 182 | #endif |
183 | fprintf(stderr,"[ERR] Please refer to the Rockbox manual if you continue to have problems.\n"); | 183 | fprintf(stderr,"[ERR] Please refer to the Rockbox manual if you continue to have problems.\n"); |
184 | } else if (n > 1) { | 184 | } else if (n > 1) { |
185 | fprintf(stderr,"[ERR] %d E200s found, aborting\n",n); | 185 | fprintf(stderr,"[ERR] %d Sansas found, aborting\n",n); |
186 | fprintf(stderr,"[ERR] Please connect only one E200 and re-run sansapatcher.\n"); | 186 | fprintf(stderr,"[ERR] Please connect only one Sansa and re-run sansapatcher.\n"); |
187 | } | 187 | } |
188 | 188 | ||
189 | if (n != 1) { | 189 | if (n != 1) { |
@@ -253,12 +253,14 @@ int main(int argc, char* argv[]) | |||
253 | 253 | ||
254 | display_partinfo(&sansa); | 254 | display_partinfo(&sansa); |
255 | 255 | ||
256 | i = is_e200(&sansa); | 256 | i = is_sansa(&sansa); |
257 | if (i < 0) { | 257 | if (i < 0) { |
258 | fprintf(stderr,"[ERR] Disk is not an E200 (%d), aborting.\n",i); | 258 | fprintf(stderr,"[ERR] Disk is not an E200 or C200 (%d), aborting.\n",i); |
259 | return 3; | 259 | return 3; |
260 | } | 260 | } |
261 | 261 | ||
262 | fprintf(stderr,"[INFO] Sansa %s detected\n",sansa.targetname); | ||
263 | |||
262 | if (sansa.hasoldbootloader) { | 264 | if (sansa.hasoldbootloader) { |
263 | printf("[ERR] ************************************************************************\n"); | 265 | printf("[ERR] ************************************************************************\n"); |
264 | printf("[ERR] *** OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"); | 266 | printf("[ERR] *** OLD ROCKBOX INSTALLATION DETECTED, ABORTING.\n"); |
diff --git a/rbutil/sansapatcher/sansaio.h b/rbutil/sansapatcher/sansaio.h index 2ef88fd384..5cfb12f416 100644 --- a/rbutil/sansapatcher/sansaio.h +++ b/rbutil/sansapatcher/sansaio.h | |||
@@ -59,6 +59,7 @@ struct sansa_t { | |||
59 | int sector_size; | 59 | int sector_size; |
60 | struct sansa_partinfo_t pinfo[4]; | 60 | struct sansa_partinfo_t pinfo[4]; |
61 | int hasoldbootloader; | 61 | int hasoldbootloader; |
62 | char* targetname; /* "e200" or "c200" */ | ||
62 | loff_t start; /* Offset in bytes of firmware partition from start of disk */ | 63 | loff_t start; /* Offset in bytes of firmware partition from start of disk */ |
63 | }; | 64 | }; |
64 | 65 | ||
diff --git a/rbutil/sansapatcher/sansapatcher.c b/rbutil/sansapatcher/sansapatcher.c index d1c12852a7..b3a0289c15 100644 --- a/rbutil/sansapatcher/sansapatcher.c +++ b/rbutil/sansapatcher/sansapatcher.c | |||
@@ -30,7 +30,8 @@ | |||
30 | #include "sansapatcher.h" | 30 | #include "sansapatcher.h" |
31 | 31 | ||
32 | #ifndef RBUTIL | 32 | #ifndef RBUTIL |
33 | #include "bootimg.h" | 33 | #include "bootimg_c200.h" |
34 | #include "bootimg_e200.h" | ||
34 | #endif | 35 | #endif |
35 | /* The offset of the MI4 image header in the firmware partition */ | 36 | /* The offset of the MI4 image header in the firmware partition */ |
36 | #define PPMI_OFFSET 0x80000 | 37 | #define PPMI_OFFSET 0x80000 |
@@ -121,6 +122,60 @@ int sansa_read_partinfo(struct sansa_t* sansa, int silent) | |||
121 | return 0; | 122 | return 0; |
122 | } | 123 | } |
123 | 124 | ||
125 | /* NOTE: memmem implementation copied from glibc-2.2.4 - it's a GNU | ||
126 | extension and is not universally. In addition, early versions of | ||
127 | memmem had a serious bug - the meaning of needle and haystack were | ||
128 | reversed. */ | ||
129 | |||
130 | /* Copyright (C) 1991,92,93,94,96,97,98,2000 Free Software Foundation, Inc. | ||
131 | This file is part of the GNU C Library. | ||
132 | |||
133 | The GNU C Library is free software; you can redistribute it and/or | ||
134 | modify it under the terms of the GNU Lesser General Public | ||
135 | License as published by the Free Software Foundation; either | ||
136 | version 2.1 of the License, or (at your option) any later version. | ||
137 | |||
138 | The GNU C Library is distributed in the hope that it will be useful, | ||
139 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
140 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
141 | Lesser General Public License for more details. | ||
142 | |||
143 | You should have received a copy of the GNU Lesser General Public | ||
144 | License along with the GNU C Library; if not, write to the Free | ||
145 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
146 | 02111-1307 USA. */ | ||
147 | |||
148 | /* Return the first occurrence of NEEDLE in HAYSTACK. */ | ||
149 | static void * | ||
150 | sansa_memmem (haystack, haystack_len, needle, needle_len) | ||
151 | const void *haystack; | ||
152 | size_t haystack_len; | ||
153 | const void *needle; | ||
154 | size_t needle_len; | ||
155 | { | ||
156 | const char *begin; | ||
157 | const char *const last_possible | ||
158 | = (const char *) haystack + haystack_len - needle_len; | ||
159 | |||
160 | if (needle_len == 0) | ||
161 | /* The first occurrence of the empty string is deemed to occur at | ||
162 | the beginning of the string. */ | ||
163 | return (void *) haystack; | ||
164 | |||
165 | /* Sanity check, otherwise the loop might search through the whole | ||
166 | memory. */ | ||
167 | if (__builtin_expect (haystack_len < needle_len, 0)) | ||
168 | return NULL; | ||
169 | |||
170 | for (begin = (const char *) haystack; begin <= last_possible; ++begin) | ||
171 | if (begin[0] == ((const char *) needle)[0] && | ||
172 | !memcmp ((const void *) &begin[1], | ||
173 | (const void *) ((const char *) needle + 1), | ||
174 | needle_len - 1)) | ||
175 | return (void *) begin; | ||
176 | |||
177 | return NULL; | ||
178 | } | ||
124 | 179 | ||
125 | /* | 180 | /* |
126 | * CRC32 implementation taken from: | 181 | * CRC32 implementation taken from: |
@@ -191,7 +246,7 @@ static void chksum_crc32gentab (void) | |||
191 | } | 246 | } |
192 | 247 | ||
193 | /* Known keys for Sansa E200 and C200 firmwares: */ | 248 | /* Known keys for Sansa E200 and C200 firmwares: */ |
194 | #define NUM_KEYS (sizeof(keys)/sizeof(keys[0])) | 249 | #define NUM_KEYS ((int)(sizeof(keys)/sizeof(keys[0]))) |
195 | static uint32_t keys[][4] = { | 250 | static uint32_t keys[][4] = { |
196 | { 0xe494e96e, 0x3ee32966, 0x6f48512b, 0xa93fbb42 }, /* "sansa" */ | 251 | { 0xe494e96e, 0x3ee32966, 0x6f48512b, 0xa93fbb42 }, /* "sansa" */ |
197 | { 0xd7b10538, 0xc662945b, 0x1b3fce68, 0xf389c0e6 }, /* "sansa_gh" */ | 252 | { 0xd7b10538, 0xc662945b, 0x1b3fce68, 0xf389c0e6 }, /* "sansa_gh" */ |
@@ -328,10 +383,11 @@ static int sansa_seek_and_read(struct sansa_t* sansa, loff_t pos, unsigned char* | |||
328 | 5) The "PPMI" string appears at offset PPMI_OFFSET in the 2nd partition. | 383 | 5) The "PPMI" string appears at offset PPMI_OFFSET in the 2nd partition. |
329 | */ | 384 | */ |
330 | 385 | ||
331 | int is_e200(struct sansa_t* sansa) | 386 | int is_sansa(struct sansa_t* sansa) |
332 | { | 387 | { |
333 | struct mi4header_t mi4header; | 388 | struct mi4header_t mi4header; |
334 | int ppmi_length; | 389 | int ppmi_length; |
390 | int ppbl_length; | ||
335 | 391 | ||
336 | /* Check partition layout */ | 392 | /* Check partition layout */ |
337 | 393 | ||
@@ -354,10 +410,31 @@ int is_e200(struct sansa_t* sansa) | |||
354 | /* No bootloader header, abort */ | 410 | /* No bootloader header, abort */ |
355 | return -4; | 411 | return -4; |
356 | } | 412 | } |
413 | ppbl_length = (le2int(sectorbuf+4) + 0x1ff) & ~0x1ff; | ||
357 | 414 | ||
415 | /* Sanity/safety check - the bootloader can't be larger than PPMI_OFFSET */ | ||
416 | if (ppbl_length > PPMI_OFFSET) | ||
417 | { | ||
418 | return -5; | ||
419 | } | ||
420 | |||
421 | /* Load Sansa bootloader and check for "Sansa C200" magic string */ | ||
422 | if (sansa_seek_and_read(sansa, sansa->start + 0x200, sectorbuf, ppbl_length) < 0) { | ||
423 | fprintf(stderr,"[ERR] Seek and read to 0x%08llx in is_sansa failed.\n", | ||
424 | sansa->start+0x200); | ||
425 | return -6; | ||
426 | } | ||
427 | if (sansa_memmem(sectorbuf, ppbl_length, "Sansa C200", 10) != NULL) { | ||
428 | /* C200 */ | ||
429 | sansa->targetname="c200"; | ||
430 | } else { | ||
431 | /* E200 */ | ||
432 | sansa->targetname="e200"; | ||
433 | } | ||
434 | |||
358 | /* Check Main firmware header */ | 435 | /* Check Main firmware header */ |
359 | if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sectorbuf, 0x200) < 0) { | 436 | if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sectorbuf, 0x200) < 0) { |
360 | fprintf(stderr,"[ERR] Seek to 0x%08llx in is_e200 failed.\n", | 437 | fprintf(stderr,"[ERR] Seek to 0x%08llx in is_sansa failed.\n", |
361 | sansa->start+PPMI_OFFSET); | 438 | sansa->start+PPMI_OFFSET); |
362 | return -5; | 439 | return -5; |
363 | } | 440 | } |
@@ -369,7 +446,7 @@ int is_e200(struct sansa_t* sansa) | |||
369 | 446 | ||
370 | /* Check main mi4 file header */ | 447 | /* Check main mi4 file header */ |
371 | if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200, sectorbuf, 0x200) < 0) { | 448 | if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200, sectorbuf, 0x200) < 0) { |
372 | fprintf(stderr,"[ERR] Seek to 0x%08llx in is_e200 failed.\n", | 449 | fprintf(stderr,"[ERR] Seek to 0x%08llx in is_sansa failed.\n", |
373 | sansa->start+PPMI_OFFSET+0x200); | 450 | sansa->start+PPMI_OFFSET+0x200); |
374 | return -5; | 451 | return -5; |
375 | } | 452 | } |
@@ -435,7 +512,7 @@ int sansa_scan(struct sansa_t* sansa) | |||
435 | continue; | 512 | continue; |
436 | } | 513 | } |
437 | 514 | ||
438 | if (is_e200(sansa) < 0) { | 515 | if (is_sansa(sansa) < 0) { |
439 | continue; | 516 | continue; |
440 | } | 517 | } |
441 | 518 | ||
@@ -602,7 +679,11 @@ int sansa_add_bootloader(struct sansa_t* sansa, char* filename, int type) | |||
602 | bl_length = filesize(infile); | 679 | bl_length = filesize(infile); |
603 | } else { | 680 | } else { |
604 | #ifndef RBUTIL | 681 | #ifndef RBUTIL |
605 | bl_length = LEN_bootimg; | 682 | if (strcmp(sansa->targetname,"c200") == 0) { |
683 | bl_length = LEN_bootimg_c200; | ||
684 | } else { | ||
685 | bl_length = LEN_bootimg_e200; | ||
686 | } | ||
606 | #endif | 687 | #endif |
607 | } | 688 | } |
608 | 689 | ||
@@ -629,7 +710,11 @@ int sansa_add_bootloader(struct sansa_t* sansa, char* filename, int type) | |||
629 | } | 710 | } |
630 | } else { | 711 | } else { |
631 | #ifndef RBUTIL | 712 | #ifndef RBUTIL |
632 | memcpy(sectorbuf+0x200,bootimg,LEN_bootimg); | 713 | if (strcmp(sansa->targetname,"c200") == 0) { |
714 | memcpy(sectorbuf+0x200,bootimg_c200,LEN_bootimg_c200); | ||
715 | } else { | ||
716 | memcpy(sectorbuf+0x200,bootimg_e200,LEN_bootimg_e200); | ||
717 | } | ||
633 | #endif | 718 | #endif |
634 | } | 719 | } |
635 | 720 | ||
diff --git a/rbutil/sansapatcher/sansapatcher.h b/rbutil/sansapatcher/sansapatcher.h index 52c72f834c..bb9e0f1340 100644 --- a/rbutil/sansapatcher/sansapatcher.h +++ b/rbutil/sansapatcher/sansapatcher.h | |||
@@ -31,7 +31,7 @@ extern unsigned char* sectorbuf; | |||
31 | #define FILETYPE_INTERNAL 1 | 31 | #define FILETYPE_INTERNAL 1 |
32 | 32 | ||
33 | int sansa_read_partinfo(struct sansa_t* sansa, int silent); | 33 | int sansa_read_partinfo(struct sansa_t* sansa, int silent); |
34 | int is_e200(struct sansa_t* sansa); | 34 | int is_sansa(struct sansa_t* sansa); |
35 | int sansa_scan(struct sansa_t* sansa); | 35 | int sansa_scan(struct sansa_t* sansa); |
36 | int sansa_read_firmware(struct sansa_t* sansa, char* filename); | 36 | int sansa_read_firmware(struct sansa_t* sansa, char* filename); |
37 | int sansa_add_bootloader(struct sansa_t* sansa, char* filename, int type); | 37 | int sansa_add_bootloader(struct sansa_t* sansa, char* filename, int type); |