summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--rbutil/sansapatcher/main.c25
-rw-r--r--rbutil/sansapatcher/sansapatcher.c157
-rw-r--r--rbutil/sansapatcher/sansapatcher.h1
3 files changed, 147 insertions, 36 deletions
diff --git a/rbutil/sansapatcher/main.c b/rbutil/sansapatcher/main.c
index 4f2a5fe226..a675cd80b6 100644
--- a/rbutil/sansapatcher/main.c
+++ b/rbutil/sansapatcher/main.c
@@ -47,7 +47,8 @@ enum {
READ_FIRMWARE,
WRITE_FIRMWARE,
READ_PARTITION,
- WRITE_PARTITION
+ WRITE_PARTITION,
+ UPDATE_OF
};
void print_usage(void)
@@ -62,9 +63,10 @@ void print_usage(void)
fprintf(stderr,"Where [action] is one of the following options:\n");
fprintf(stderr," --install\n");
fprintf(stderr," -l, --list\n");
- fprintf(stderr," -rf, --read-firmware filename.mi4\n");
- fprintf(stderr," -a, --add-bootloader filename.mi4\n");
+ fprintf(stderr," -rf, --read-firmware filename.mi4\n");
+ fprintf(stderr," -a, --add-bootloader filename.mi4\n");
fprintf(stderr," -d, --delete-bootloader\n");
+ fprintf(stderr," -of --update-original-firmware filename.mi4\n");
fprintf(stderr,"\n");
#ifdef __WIN32__
@@ -216,6 +218,13 @@ int main(int argc, char* argv[])
if (i == argc) { print_usage(); return 1; }
filename=argv[i];
i++;
+ } else if ((strcmp(argv[i],"-of")==0) ||
+ (strcmp(argv[i],"--update-original-firmware")==0)) {
+ action = UPDATE_OF;
+ i++;
+ if (i == argc) { print_usage(); return 1; }
+ filename=argv[i];
+ i++;
} else if ((strcmp(argv[i],"-rf")==0) ||
(strcmp(argv[i],"--read-firmware")==0)) {
action = READ_FIRMWARE;
@@ -326,6 +335,16 @@ int main(int argc, char* argv[])
} else {
fprintf(stderr,"[ERR] --delete-bootloader failed.\n");
}
+ } else if (action==UPDATE_OF) {
+ if (sansa_reopen_rw(&sansa) < 0) {
+ return 5;
+ }
+
+ if (sansa_update_of(&sansa, filename)==0) {
+ fprintf(stderr,"[INFO] OF updated successfully.\n");
+ } else {
+ fprintf(stderr,"[ERR] --update-original-firmware failed.\n");
+ }
}
}
diff --git a/rbutil/sansapatcher/sansapatcher.c b/rbutil/sansapatcher/sansapatcher.c
index 9b52196a7b..c9f047f472 100644
--- a/rbutil/sansapatcher/sansapatcher.c
+++ b/rbutil/sansapatcher/sansapatcher.c
@@ -446,44 +446,14 @@ int sansa_scan(struct sansa_t* sansa)
return n;
}
-static int load_original_firmware(struct sansa_t* sansa, unsigned char* buf, struct mi4header_t* mi4header)
+/* Prepare original firmware for writing to the firmware partition by decrypting
+ and updating the header */
+static int prepare_original_firmware(unsigned char* buf, struct mi4header_t* mi4header)
{
- int ppmi_length;
- int n;
unsigned char* tmpbuf;
int i;
int key_found;
- /* Read 512 bytes from PPMI_OFFSET - the PPMI header plus the mi4 header */
- if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET, buf, 512) < 0) {
- return -1;
- }
-
- /* No need to check PPMI magic - it's done during init to confirm
- this is an E200 */
- ppmi_length = le2int(buf+4);
-
- /* Firstly look for an original firmware after the first image */
- if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, buf, 512) < 0) {
- return -1;
- }
-
- if (get_mi4header(buf,mi4header)==0) {
- /* We have a valid MI4 file after a bootloader, so we use this. */
- if ((n = sansa_seek_and_read(sansa,
- sansa->start + PPMI_OFFSET + 0x200 + ppmi_length,
- buf, mi4header->mi4size)) < 0) {
- return -1;
- }
- } else {
- /* No valid MI4 file, so read the first image. */
- if ((n = sansa_seek_and_read(sansa,
- sansa->start + PPMI_OFFSET + 0x200,
- buf, ppmi_length)) < 0) {
- return -1;
- }
- }
-
get_mi4header(buf,mi4header);
#if 0
@@ -538,6 +508,43 @@ static int load_original_firmware(struct sansa_t* sansa, unsigned char* buf, str
return 0;
}
+static int load_original_firmware(struct sansa_t* sansa, unsigned char* buf, struct mi4header_t* mi4header)
+{
+ int ppmi_length;
+ int n;
+
+ /* Read 512 bytes from PPMI_OFFSET - the PPMI header plus the mi4 header */
+ if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET, buf, 512) < 0) {
+ return -1;
+ }
+
+ /* No need to check PPMI magic - it's done during init to confirm
+ this is an E200 */
+ ppmi_length = le2int(buf+4);
+
+ /* Firstly look for an original firmware after the first image */
+ if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, buf, 512) < 0) {
+ return -1;
+ }
+
+ if (get_mi4header(buf,mi4header)==0) {
+ /* We have a valid MI4 file after a bootloader, so we use this. */
+ if ((n = sansa_seek_and_read(sansa,
+ sansa->start + PPMI_OFFSET + 0x200 + ppmi_length,
+ buf, mi4header->mi4size)) < 0) {
+ return -1;
+ }
+ } else {
+ /* No valid MI4 file, so read the first image. */
+ if ((n = sansa_seek_and_read(sansa,
+ sansa->start + PPMI_OFFSET + 0x200,
+ buf, ppmi_length)) < 0) {
+ return -1;
+ }
+ }
+ return prepare_original_firmware(buf, mi4header);
+}
+
int sansa_read_firmware(struct sansa_t* sansa, char* filename)
{
int res;
@@ -700,3 +707,87 @@ void sansa_list_images(struct sansa_t* sansa)
printf("[INFO] Image 2 - %d bytes\n",mi4header.mi4size);
}
}
+
+int sansa_update_of(struct sansa_t* sansa, char* filename)
+{
+ int n;
+ int infile = -1; /* Prevent an erroneous "may be used uninitialised" gcc warning */
+ int of_length = 0; /* Keep gcc happy when building for rbutil */
+ int ppmi_length;
+ struct mi4header_t mi4header;
+ char buf[512];
+
+ /* Step 1 - check we have an OF on the Sansa to upgrade. We expect the
+ Rockbox bootloader to be installed and the OF to be after it on disk. */
+
+ /* Read 512 bytes from PPMI_OFFSET - the PPMI header */
+ if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET,
+ buf, 512) < 0) {
+ return -1;
+ }
+
+ /* No need to check PPMI magic - it's done during init to confirm
+ this is an E200 */
+ ppmi_length = le2int(buf+4);
+
+ /* Look for an original firmware after the first image */
+ if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200+ppmi_length,
+ buf, 512) < 0) {
+ return -1;
+ }
+
+ if (get_mi4header(buf,&mi4header)!=0) {
+ /* We don't have a valid MI4 file after a bootloader, so do nothing. */
+ fprintf(stderr,"[ERR] No original firmware found at 0x%08llx\n",
+ (loff_t)(sansa->start+PPMI_OFFSET+0x200+ppmi_length));
+ return -1;
+ }
+
+ /* Step 2 - read OF into RAM. */
+ infile=open(filename,O_RDONLY|O_BINARY);
+ if (infile < 0) {
+ fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename);
+ return -1;
+ }
+
+ of_length = filesize(infile);
+
+ /* Load original firmware from file */
+ memset(sectorbuf,0,0x200);
+ n = read(infile,sectorbuf,of_length);
+ close(infile);
+ if (n < of_length) {
+ fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n"
+ , of_length, n);
+ return -1;
+ }
+
+ /* Check we have a valid MI4 file. */
+ if (get_mi4header(sectorbuf,&mi4header)!=0) {
+ fprintf(stderr,"[ERR] %s is not a valid mi4 file\n",filename);
+ return -1;
+ }
+
+ /* Decrypt and build the header */
+ if(prepare_original_firmware(sectorbuf, &mi4header)!=0){
+ fprintf(stderr,"[ERR] Unable to build decrypted mi4 from %s\n"
+ ,filename);
+ return -1;
+ }
+
+ /* Step 3 - write the OF to the Sansa */
+ if (sansa_seek(sansa, sansa->start+PPMI_OFFSET+0x200+ppmi_length) < 0) {
+ fprintf(stderr,"[ERR] Seek to 0x%08x in sansa_update_of failed.\n",
+ (unsigned int)(sansa->start+PPMI_OFFSET+0x200+ppmi_length));
+ return -1;
+ }
+
+ n=sansa_write(sansa, sectorbuf, of_length);
+ if (n < of_length) {
+ fprintf(stderr,"[ERR] Short write in sansa_update_of\n");
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/rbutil/sansapatcher/sansapatcher.h b/rbutil/sansapatcher/sansapatcher.h
index a393a86576..52c72f834c 100644
--- a/rbutil/sansapatcher/sansapatcher.h
+++ b/rbutil/sansapatcher/sansapatcher.h
@@ -36,6 +36,7 @@ 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);
int sansa_delete_bootloader(struct sansa_t* sansa);
+int sansa_update_of(struct sansa_t* sansa,char* filename);
void sansa_list_images(struct sansa_t* sansa);
#endif