From 8d145a55746ed3f0c131b6677c00bb126dc086c6 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Wed, 19 Sep 2007 18:46:54 +0000 Subject: Initial attempt at c200 support - you now need both a "firmware.mi4" file (c200 bootloader) and "PP5022.mi4" file (e200 bootloader) to compile. sansapatcher should detect the device type and install the correct bootloader. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14755 a1c6a512-1295-4272-9138-f99709370657 --- rbutil/sansapatcher/Makefile | 25 +++++---- rbutil/sansapatcher/main.c | 22 ++++---- rbutil/sansapatcher/sansaio.h | 1 + rbutil/sansapatcher/sansapatcher.c | 101 ++++++++++++++++++++++++++++++++++--- 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 all: $(OUTPUT) -sansapatcher: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg.c - gcc $(CFLAGS) -o sansapatcher main.c sansapatcher.c sansaio-posix.c bootimg.c +sansapatcher: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg_c200.c bootimg_e200.c + gcc $(CFLAGS) -o sansapatcher main.c sansapatcher.c sansaio-posix.c bootimg_c200.c bootimg_e200.c strip sansapatcher -sansapatcher.exe: main.c sansapatcher.c sansaio-win32.c parttypes.h bootimg.c - $(CC) $(CFLAGS) -o sansapatcher.exe main.c sansapatcher.c sansaio-win32.c bootimg.c +sansapatcher.exe: main.c sansapatcher.c sansaio-win32.c parttypes.h bootimg_c200.c bootimg_e200.c + $(CC) $(CFLAGS) -o sansapatcher.exe main.c sansapatcher.c sansaio-win32.c bootimg_c200.c bootimg_e200.c $(CROSS)strip sansapatcher.exe sansapatcher-mac: sansapatcher-i386 sansapatcher-ppc lipo -create sansapatcher-ppc sansapatcher-i386 -output sansapatcher-mac -sansapatcher-i386: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg.c - 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 +sansapatcher-i386: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg_c200.c bootimg_e200.c + 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 strip sansapatcher-i386 -sansapatcher-ppc: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg.c - gcc -arch ppc $(CFLAGS) -o sansapatcher-ppc main.c sansapatcher.c sansaio-posix.c bootimg.c +sansapatcher-ppc: main.c sansapatcher.c sansaio-posix.c parttypes.h bootimg_c200.c bootimg_e200.c + gcc -arch ppc $(CFLAGS) -o sansapatcher-ppc main.c sansapatcher.c sansaio-posix.c bootimg_c200.c bootimg_e200.c strip sansapatcher-ppc bin2c: bin2c.c $(NATIVECC) $(CFLAGS) -o bin2c bin2c.c -bootimg.c: PP5022.mi4 bin2c - ./bin2c PP5022.mi4 bootimg +bootimg_c200.c: firmware.mi4 bin2c + ./bin2c firmware.mi4 bootimg_c200 + +bootimg_e200.c: PP5022.mi4 bin2c + ./bin2c PP5022.mi4 bootimg_e200 clean: - rm -f sansapatcher.exe sansapatcher-mac sansapatcher-i386 sansapatcher-ppc sansapatcher bin2c bootimg.c bootimg.h *~ + 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) fprintf(stderr,"DISKNO is the number (e.g. 2) Windows has assigned to your sansa's hard disk.\n"); fprintf(stderr,"The first hard disk in your computer (i.e. C:\\) will be disk 0, the next disk\n"); fprintf(stderr,"will be disk 1 etc. sansapatcher will refuse to access a disk unless it\n"); - fprintf(stderr,"can identify it as being an E200.\n"); + fprintf(stderr,"can identify it as being an E200 or C200.\n"); fprintf(stderr,"\n"); #else #if defined(linux) || defined (__linux) @@ -84,7 +84,7 @@ void print_usage(void) fprintf(stderr,"\"device\" is the device node (e.g. /dev/disk1) assigned to your sansa.\n"); #endif fprintf(stderr,"sansapatcher will refuse to access a disk unless it can identify it as being\n"); - fprintf(stderr,"an E200.\n"); + fprintf(stderr,"an E200 or C200.\n"); #endif } @@ -154,7 +154,7 @@ int main(int argc, char* argv[]) if ((argc > 1) && (strcmp(argv[1],"--scan")==0)) { if (sansa_scan(&sansa) == 0) - fprintf(stderr,"[ERR] No E200s found.\n"); + fprintf(stderr,"[ERR] No E200s or C200s found.\n"); return 0; } @@ -168,13 +168,13 @@ int main(int argc, char* argv[]) #endif i = 2; } else { - /* Autoscan for E200s */ + /* Autoscan for C200/E200s */ n = sansa_scan(&sansa); if (n==0) { - fprintf(stderr,"[ERR] No E200s found, aborting\n"); + fprintf(stderr,"[ERR] No E200s or C200s found, aborting\n"); fprintf(stderr,"[ERR] Please connect your sansa and ensure it is in UMS mode\n"); #if defined(__APPLE__) && defined(__MACH__) - fprintf(stderr,"[ERR] Also ensure that your E200's main partition is not mounted.\n"); + fprintf(stderr,"[ERR] Also ensure that your Sansa's main partition is not mounted.\n"); #elif !defined(__WIN32__) if (geteuid()!=0) { fprintf(stderr,"[ERR] You may also need to run sansapatcher as root.\n"); @@ -182,8 +182,8 @@ int main(int argc, char* argv[]) #endif fprintf(stderr,"[ERR] Please refer to the Rockbox manual if you continue to have problems.\n"); } else if (n > 1) { - fprintf(stderr,"[ERR] %d E200s found, aborting\n",n); - fprintf(stderr,"[ERR] Please connect only one E200 and re-run sansapatcher.\n"); + fprintf(stderr,"[ERR] %d Sansas found, aborting\n",n); + fprintf(stderr,"[ERR] Please connect only one Sansa and re-run sansapatcher.\n"); } if (n != 1) { @@ -253,12 +253,14 @@ int main(int argc, char* argv[]) display_partinfo(&sansa); - i = is_e200(&sansa); + i = is_sansa(&sansa); if (i < 0) { - fprintf(stderr,"[ERR] Disk is not an E200 (%d), aborting.\n",i); + fprintf(stderr,"[ERR] Disk is not an E200 or C200 (%d), aborting.\n",i); return 3; } + fprintf(stderr,"[INFO] Sansa %s detected\n",sansa.targetname); + if (sansa.hasoldbootloader) { printf("[ERR] ************************************************************************\n"); 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 { int sector_size; struct sansa_partinfo_t pinfo[4]; int hasoldbootloader; + char* targetname; /* "e200" or "c200" */ loff_t start; /* Offset in bytes of firmware partition from start of disk */ }; 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 @@ #include "sansapatcher.h" #ifndef RBUTIL - #include "bootimg.h" + #include "bootimg_c200.h" + #include "bootimg_e200.h" #endif /* The offset of the MI4 image header in the firmware partition */ #define PPMI_OFFSET 0x80000 @@ -121,6 +122,60 @@ int sansa_read_partinfo(struct sansa_t* sansa, int silent) return 0; } +/* NOTE: memmem implementation copied from glibc-2.2.4 - it's a GNU + extension and is not universally. In addition, early versions of + memmem had a serious bug - the meaning of needle and haystack were + reversed. */ + +/* Copyright (C) 1991,92,93,94,96,97,98,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return the first occurrence of NEEDLE in HAYSTACK. */ +static void * +sansa_memmem (haystack, haystack_len, needle, needle_len) + const void *haystack; + size_t haystack_len; + const void *needle; + size_t needle_len; +{ + const char *begin; + const char *const last_possible + = (const char *) haystack + haystack_len - needle_len; + + if (needle_len == 0) + /* The first occurrence of the empty string is deemed to occur at + the beginning of the string. */ + return (void *) haystack; + + /* Sanity check, otherwise the loop might search through the whole + memory. */ + if (__builtin_expect (haystack_len < needle_len, 0)) + return NULL; + + for (begin = (const char *) haystack; begin <= last_possible; ++begin) + if (begin[0] == ((const char *) needle)[0] && + !memcmp ((const void *) &begin[1], + (const void *) ((const char *) needle + 1), + needle_len - 1)) + return (void *) begin; + + return NULL; +} /* * CRC32 implementation taken from: @@ -191,7 +246,7 @@ static void chksum_crc32gentab (void) } /* Known keys for Sansa E200 and C200 firmwares: */ -#define NUM_KEYS (sizeof(keys)/sizeof(keys[0])) +#define NUM_KEYS ((int)(sizeof(keys)/sizeof(keys[0]))) static uint32_t keys[][4] = { { 0xe494e96e, 0x3ee32966, 0x6f48512b, 0xa93fbb42 }, /* "sansa" */ { 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* 5) The "PPMI" string appears at offset PPMI_OFFSET in the 2nd partition. */ -int is_e200(struct sansa_t* sansa) +int is_sansa(struct sansa_t* sansa) { struct mi4header_t mi4header; int ppmi_length; + int ppbl_length; /* Check partition layout */ @@ -354,10 +410,31 @@ int is_e200(struct sansa_t* sansa) /* No bootloader header, abort */ return -4; } + ppbl_length = (le2int(sectorbuf+4) + 0x1ff) & ~0x1ff; + /* Sanity/safety check - the bootloader can't be larger than PPMI_OFFSET */ + if (ppbl_length > PPMI_OFFSET) + { + return -5; + } + + /* Load Sansa bootloader and check for "Sansa C200" magic string */ + if (sansa_seek_and_read(sansa, sansa->start + 0x200, sectorbuf, ppbl_length) < 0) { + fprintf(stderr,"[ERR] Seek and read to 0x%08llx in is_sansa failed.\n", + sansa->start+0x200); + return -6; + } + if (sansa_memmem(sectorbuf, ppbl_length, "Sansa C200", 10) != NULL) { + /* C200 */ + sansa->targetname="c200"; + } else { + /* E200 */ + sansa->targetname="e200"; + } + /* Check Main firmware header */ if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sectorbuf, 0x200) < 0) { - fprintf(stderr,"[ERR] Seek to 0x%08llx in is_e200 failed.\n", + fprintf(stderr,"[ERR] Seek to 0x%08llx in is_sansa failed.\n", sansa->start+PPMI_OFFSET); return -5; } @@ -369,7 +446,7 @@ int is_e200(struct sansa_t* sansa) /* Check main mi4 file header */ if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200, sectorbuf, 0x200) < 0) { - fprintf(stderr,"[ERR] Seek to 0x%08llx in is_e200 failed.\n", + fprintf(stderr,"[ERR] Seek to 0x%08llx in is_sansa failed.\n", sansa->start+PPMI_OFFSET+0x200); return -5; } @@ -435,7 +512,7 @@ int sansa_scan(struct sansa_t* sansa) continue; } - if (is_e200(sansa) < 0) { + if (is_sansa(sansa) < 0) { continue; } @@ -602,7 +679,11 @@ int sansa_add_bootloader(struct sansa_t* sansa, char* filename, int type) bl_length = filesize(infile); } else { #ifndef RBUTIL - bl_length = LEN_bootimg; + if (strcmp(sansa->targetname,"c200") == 0) { + bl_length = LEN_bootimg_c200; + } else { + bl_length = LEN_bootimg_e200; + } #endif } @@ -629,7 +710,11 @@ int sansa_add_bootloader(struct sansa_t* sansa, char* filename, int type) } } else { #ifndef RBUTIL - memcpy(sectorbuf+0x200,bootimg,LEN_bootimg); + if (strcmp(sansa->targetname,"c200") == 0) { + memcpy(sectorbuf+0x200,bootimg_c200,LEN_bootimg_c200); + } else { + memcpy(sectorbuf+0x200,bootimg_e200,LEN_bootimg_e200); + } #endif } 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; #define FILETYPE_INTERNAL 1 int sansa_read_partinfo(struct sansa_t* sansa, int silent); -int is_e200(struct sansa_t* sansa); +int is_sansa(struct sansa_t* sansa); int sansa_scan(struct sansa_t* sansa); int sansa_read_firmware(struct sansa_t* sansa, char* filename); int sansa_add_bootloader(struct sansa_t* sansa, char* filename, int type); -- cgit v1.2.3