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/sansapatcher/sansapatcher.c | |
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/sansapatcher/sansapatcher.c')
-rw-r--r-- | rbutil/sansapatcher/sansapatcher.c | 157 |
1 files changed, 124 insertions, 33 deletions
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 | |||