mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-08 12:45:26 -05:00
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
This commit is contained in:
parent
744f07f554
commit
6a0ec8bfa8
3 changed files with 147 additions and 36 deletions
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue