diff options
author | Barry Wardell <rockbox@barrywardell.net> | 2007-08-02 11:39:43 +0000 |
---|---|---|
committer | Barry Wardell <rockbox@barrywardell.net> | 2007-08-02 11:39:43 +0000 |
commit | 6a0ec8bfa86e7fcf02a9179dc8adbf2f0e25e6e7 (patch) | |
tree | 6a166b874002517a623556b5fc396ac6cb967a44 /rbutil | |
parent | 744f07f55439bc4b5d99d4fe0082ab640aad476c (diff) | |
download | rockbox-6a0ec8bfa86e7fcf02a9179dc8adbf2f0e25e6e7.tar.gz rockbox-6a0ec8bfa86e7fcf02a9179dc8adbf2f0e25e6e7.zip |
Add --update-original-firmware (or -of) option to sansapatcher. This allows for changing the original firmware version when the rockbox bootloader is also present.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14138 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'rbutil')
-rw-r--r-- | rbutil/sansapatcher/main.c | 25 | ||||
-rw-r--r-- | rbutil/sansapatcher/sansapatcher.c | 157 | ||||
-rw-r--r-- | rbutil/sansapatcher/sansapatcher.h | 1 |
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 { | |||
47 | READ_FIRMWARE, | 47 | READ_FIRMWARE, |
48 | WRITE_FIRMWARE, | 48 | WRITE_FIRMWARE, |
49 | READ_PARTITION, | 49 | READ_PARTITION, |
50 | WRITE_PARTITION | 50 | WRITE_PARTITION, |
51 | UPDATE_OF | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | void print_usage(void) | 54 | void print_usage(void) |
@@ -62,9 +63,10 @@ void print_usage(void) | |||
62 | fprintf(stderr,"Where [action] is one of the following options:\n"); | 63 | fprintf(stderr,"Where [action] is one of the following options:\n"); |
63 | fprintf(stderr," --install\n"); | 64 | fprintf(stderr," --install\n"); |
64 | fprintf(stderr," -l, --list\n"); | 65 | fprintf(stderr," -l, --list\n"); |
65 | fprintf(stderr," -rf, --read-firmware filename.mi4\n"); | 66 | fprintf(stderr," -rf, --read-firmware filename.mi4\n"); |
66 | fprintf(stderr," -a, --add-bootloader filename.mi4\n"); | 67 | fprintf(stderr," -a, --add-bootloader filename.mi4\n"); |
67 | fprintf(stderr," -d, --delete-bootloader\n"); | 68 | fprintf(stderr," -d, --delete-bootloader\n"); |
69 | fprintf(stderr," -of --update-original-firmware filename.mi4\n"); | ||
68 | fprintf(stderr,"\n"); | 70 | fprintf(stderr,"\n"); |
69 | 71 | ||
70 | #ifdef __WIN32__ | 72 | #ifdef __WIN32__ |
@@ -216,6 +218,13 @@ int main(int argc, char* argv[]) | |||
216 | if (i == argc) { print_usage(); return 1; } | 218 | if (i == argc) { print_usage(); return 1; } |
217 | filename=argv[i]; | 219 | filename=argv[i]; |
218 | i++; | 220 | i++; |
221 | } else if ((strcmp(argv[i],"-of")==0) || | ||
222 | (strcmp(argv[i],"--update-original-firmware")==0)) { | ||
223 | action = UPDATE_OF; | ||
224 | i++; | ||
225 | if (i == argc) { print_usage(); return 1; } | ||
226 | filename=argv[i]; | ||
227 | i++; | ||
219 | } else if ((strcmp(argv[i],"-rf")==0) || | 228 | } else if ((strcmp(argv[i],"-rf")==0) || |
220 | (strcmp(argv[i],"--read-firmware")==0)) { | 229 | (strcmp(argv[i],"--read-firmware")==0)) { |
221 | action = READ_FIRMWARE; | 230 | action = READ_FIRMWARE; |
@@ -326,6 +335,16 @@ int main(int argc, char* argv[]) | |||
326 | } else { | 335 | } else { |
327 | fprintf(stderr,"[ERR] --delete-bootloader failed.\n"); | 336 | fprintf(stderr,"[ERR] --delete-bootloader failed.\n"); |
328 | } | 337 | } |
338 | } else if (action==UPDATE_OF) { | ||
339 | if (sansa_reopen_rw(&sansa) < 0) { | ||
340 | return 5; | ||
341 | } | ||
342 | |||
343 | if (sansa_update_of(&sansa, filename)==0) { | ||
344 | fprintf(stderr,"[INFO] OF updated successfully.\n"); | ||
345 | } else { | ||
346 | fprintf(stderr,"[ERR] --update-original-firmware failed.\n"); | ||
347 | } | ||
329 | } | 348 | } |
330 | } | 349 | } |
331 | 350 | ||
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) | |||
446 | return n; | 446 | return n; |
447 | } | 447 | } |
448 | 448 | ||
449 | static int load_original_firmware(struct sansa_t* sansa, unsigned char* buf, struct mi4header_t* mi4header) | 449 | /* Prepare original firmware for writing to the firmware partition by decrypting |
450 | and updating the header */ | ||
451 | static int prepare_original_firmware(unsigned char* buf, struct mi4header_t* mi4header) | ||
450 | { | 452 | { |
451 | int ppmi_length; | ||
452 | int n; | ||
453 | unsigned char* tmpbuf; | 453 | unsigned char* tmpbuf; |
454 | int i; | 454 | int i; |
455 | int key_found; | 455 | int key_found; |
456 | 456 | ||
457 | /* Read 512 bytes from PPMI_OFFSET - the PPMI header plus the mi4 header */ | ||
458 | if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET, buf, 512) < 0) { | ||
459 | return -1; | ||
460 | } | ||
461 | |||
462 | /* No need to check PPMI magic - it's done during init to confirm | ||
463 | this is an E200 */ | ||
464 | ppmi_length = le2int(buf+4); | ||
465 | |||
466 | /* Firstly look for an original firmware after the first image */ | ||
467 | if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, buf, 512) < 0) { | ||
468 | return -1; | ||
469 | } | ||
470 | |||
471 | if (get_mi4header(buf,mi4header)==0) { | ||
472 | /* We have a valid MI4 file after a bootloader, so we use this. */ | ||
473 | if ((n = sansa_seek_and_read(sansa, | ||
474 | sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, | ||
475 | buf, mi4header->mi4size)) < 0) { | ||
476 | return -1; | ||
477 | } | ||
478 | } else { | ||
479 | /* No valid MI4 file, so read the first image. */ | ||
480 | if ((n = sansa_seek_and_read(sansa, | ||
481 | sansa->start + PPMI_OFFSET + 0x200, | ||
482 | buf, ppmi_length)) < 0) { | ||
483 | return -1; | ||
484 | } | ||
485 | } | ||
486 | |||
487 | get_mi4header(buf,mi4header); | 457 | get_mi4header(buf,mi4header); |
488 | 458 | ||
489 | #if 0 | 459 | #if 0 |
@@ -538,6 +508,43 @@ static int load_original_firmware(struct sansa_t* sansa, unsigned char* buf, str | |||
538 | return 0; | 508 | return 0; |
539 | } | 509 | } |
540 | 510 | ||
511 | static int load_original_firmware(struct sansa_t* sansa, unsigned char* buf, struct mi4header_t* mi4header) | ||
512 | { | ||
513 | int ppmi_length; | ||
514 | int n; | ||
515 | |||
516 | /* Read 512 bytes from PPMI_OFFSET - the PPMI header plus the mi4 header */ | ||
517 | if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET, buf, 512) < 0) { | ||
518 | return -1; | ||
519 | } | ||
520 | |||
521 | /* No need to check PPMI magic - it's done during init to confirm | ||
522 | this is an E200 */ | ||
523 | ppmi_length = le2int(buf+4); | ||
524 | |||
525 | /* Firstly look for an original firmware after the first image */ | ||
526 | if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, buf, 512) < 0) { | ||
527 | return -1; | ||
528 | } | ||
529 | |||
530 | if (get_mi4header(buf,mi4header)==0) { | ||
531 | /* We have a valid MI4 file after a bootloader, so we use this. */ | ||
532 | if ((n = sansa_seek_and_read(sansa, | ||
533 | sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, | ||
534 | buf, mi4header->mi4size)) < 0) { | ||
535 | return -1; | ||
536 | } | ||
537 | } else { | ||
538 | /* No valid MI4 file, so read the first image. */ | ||
539 | if ((n = sansa_seek_and_read(sansa, | ||
540 | sansa->start + PPMI_OFFSET + 0x200, | ||
541 | buf, ppmi_length)) < 0) { | ||
542 | return -1; | ||
543 | } | ||
544 | } | ||
545 | return prepare_original_firmware(buf, mi4header); | ||
546 | } | ||
547 | |||
541 | int sansa_read_firmware(struct sansa_t* sansa, char* filename) | 548 | int sansa_read_firmware(struct sansa_t* sansa, char* filename) |
542 | { | 549 | { |
543 | int res; | 550 | int res; |
@@ -700,3 +707,87 @@ void sansa_list_images(struct sansa_t* sansa) | |||
700 | printf("[INFO] Image 2 - %d bytes\n",mi4header.mi4size); | 707 | printf("[INFO] Image 2 - %d bytes\n",mi4header.mi4size); |
701 | } | 708 | } |
702 | } | 709 | } |
710 | |||
711 | int sansa_update_of(struct sansa_t* sansa, char* filename) | ||
712 | { | ||
713 | int n; | ||
714 | int infile = -1; /* Prevent an erroneous "may be used uninitialised" gcc warning */ | ||
715 | int of_length = 0; /* Keep gcc happy when building for rbutil */ | ||
716 | int ppmi_length; | ||
717 | struct mi4header_t mi4header; | ||
718 | char buf[512]; | ||
719 | |||
720 | /* Step 1 - check we have an OF on the Sansa to upgrade. We expect the | ||
721 | Rockbox bootloader to be installed and the OF to be after it on disk. */ | ||
722 | |||
723 | /* Read 512 bytes from PPMI_OFFSET - the PPMI header */ | ||
724 | if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET, | ||
725 | buf, 512) < 0) { | ||
726 | return -1; | ||
727 | } | ||
728 | |||
729 | /* No need to check PPMI magic - it's done during init to confirm | ||
730 | this is an E200 */ | ||
731 | ppmi_length = le2int(buf+4); | ||
732 | |||
733 | /* Look for an original firmware after the first image */ | ||
734 | if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200+ppmi_length, | ||
735 | buf, 512) < 0) { | ||
736 | return -1; | ||
737 | } | ||
738 | |||
739 | if (get_mi4header(buf,&mi4header)!=0) { | ||
740 | /* We don't have a valid MI4 file after a bootloader, so do nothing. */ | ||
741 | fprintf(stderr,"[ERR] No original firmware found at 0x%08llx\n", | ||
742 | (loff_t)(sansa->start+PPMI_OFFSET+0x200+ppmi_length)); | ||
743 | return -1; | ||
744 | } | ||
745 | |||
746 | /* Step 2 - read OF into RAM. */ | ||
747 | infile=open(filename,O_RDONLY|O_BINARY); | ||
748 | if (infile < 0) { | ||
749 | fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); | ||
750 | return -1; | ||
751 | } | ||
752 | |||
753 | of_length = filesize(infile); | ||
754 | |||
755 | /* Load original firmware from file */ | ||
756 | memset(sectorbuf,0,0x200); | ||
757 | n = read(infile,sectorbuf,of_length); | ||
758 | close(infile); | ||
759 | if (n < of_length) { | ||
760 | fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n" | ||
761 | , of_length, n); | ||
762 | return -1; | ||
763 | } | ||
764 | |||
765 | /* Check we have a valid MI4 file. */ | ||
766 | if (get_mi4header(sectorbuf,&mi4header)!=0) { | ||
767 | fprintf(stderr,"[ERR] %s is not a valid mi4 file\n",filename); | ||
768 | return -1; | ||
769 | } | ||
770 | |||
771 | /* Decrypt and build the header */ | ||
772 | if(prepare_original_firmware(sectorbuf, &mi4header)!=0){ | ||
773 | fprintf(stderr,"[ERR] Unable to build decrypted mi4 from %s\n" | ||
774 | ,filename); | ||
775 | return -1; | ||
776 | } | ||
777 | |||
778 | /* Step 3 - write the OF to the Sansa */ | ||
779 | if (sansa_seek(sansa, sansa->start+PPMI_OFFSET+0x200+ppmi_length) < 0) { | ||
780 | fprintf(stderr,"[ERR] Seek to 0x%08x in sansa_update_of failed.\n", | ||
781 | (unsigned int)(sansa->start+PPMI_OFFSET+0x200+ppmi_length)); | ||
782 | return -1; | ||
783 | } | ||
784 | |||
785 | n=sansa_write(sansa, sectorbuf, of_length); | ||
786 | if (n < of_length) { | ||
787 | fprintf(stderr,"[ERR] Short write in sansa_update_of\n"); | ||
788 | return -1; | ||
789 | } | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
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); | |||
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); |
38 | int sansa_delete_bootloader(struct sansa_t* sansa); | 38 | int sansa_delete_bootloader(struct sansa_t* sansa); |
39 | int sansa_update_of(struct sansa_t* sansa,char* filename); | ||
39 | void sansa_list_images(struct sansa_t* sansa); | 40 | void sansa_list_images(struct sansa_t* sansa); |
40 | 41 | ||
41 | #endif | 42 | #endif |