forked from len0rd/rockbox
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
This commit is contained in:
parent
dbbc8358ce
commit
8d145a5574
5 changed files with 121 additions and 30 deletions
|
@ -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 *~
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue