1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006-2007 Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
28 #include <sys/types.h>
32 #include "sansapatcher.h"
34 /* The offset of the MI4 image header in the firmware partition */
35 #define PPMI_OFFSET 0x80000
36 #define NVPARAMS_OFFSET 0x780000
37 #define NVPARAMS_SIZE (0x80000-0x200)
39 int sansa_verbose
= 0;
41 /* Windows requires the buffer for disk I/O to be aligned in memory on a
42 multiple of the disk volume size - so we use a single global variable
43 and initialise it with sansa_alloc_buf() in main().
46 unsigned char* sansa_sectorbuf
= NULL
;
48 static off_t
filesize(int fd
) {
51 if (fstat(fd
,&buf
) < 0) {
52 perror("[ERR] Checking filesize of input file");
59 /* Partition table parsing code taken from Rockbox */
61 #define MAX_SECTOR_SIZE 2048
62 #define SECTOR_SIZE 512
64 static inline int32_t le2int(const unsigned char* buf
)
66 int32_t res
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
71 static inline uint32_t le2uint(const unsigned char* buf
)
73 uint32_t res
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
78 static inline void int2le(unsigned int val
, unsigned char* addr
)
81 addr
[1] = (val
>> 8) & 0xff;
82 addr
[2] = (val
>> 16) & 0xff;
83 addr
[3] = (val
>> 24) & 0xff;
86 #define BYTES2INT32(array,pos)\
87 ((long)array[pos] | ((long)array[pos+1] << 8 ) |\
88 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
90 int sansa_read_partinfo(struct sansa_t
* sansa
, int silent
)
95 count
= sansa_read(sansa
,sansa_sectorbuf
, sansa
->sector_size
);
98 sansa_print_error(" Error reading from disk: ");
102 if ((sansa_sectorbuf
[510] == 0x55) && (sansa_sectorbuf
[511] == 0xaa)) {
103 /* parse partitions */
104 for ( i
= 0; i
< 4; i
++ ) {
105 unsigned char* ptr
= sansa_sectorbuf
+ 0x1be + 16*i
;
106 sansa
->pinfo
[i
].type
= ptr
[4];
107 sansa
->pinfo
[i
].start
= BYTES2INT32(ptr
, 8);
108 sansa
->pinfo
[i
].size
= BYTES2INT32(ptr
, 12);
111 if ( sansa
->pinfo
[i
].type
== 5 ) {
112 /* not handled yet */
115 } else if ((sansa_sectorbuf
[0] == 'E') && (sansa_sectorbuf
[1] == 'R')) {
116 if (!silent
) fprintf(stderr
,"[ERR] Bad boot sector signature\n");
120 /* Calculate the starting position of the firmware partition */
121 sansa
->start
= (loff_t
)sansa
->pinfo
[1].start
*(loff_t
)sansa
->sector_size
;
125 /* NOTE: memmem implementation copied from glibc-2.2.4 - it's a GNU
126 extension and is not universally. In addition, early versions of
127 memmem had a serious bug - the meaning of needle and haystack were
130 /* Copyright (C) 1991,92,93,94,96,97,98,2000 Free Software Foundation, Inc.
131 This file is part of the GNU C Library.
133 The GNU C Library is free software; you can redistribute it and/or
134 modify it under the terms of the GNU Lesser General Public
135 License as published by the Free Software Foundation; either
136 version 2.1 of the License, or (at your option) any later version.
138 The GNU C Library is distributed in the hope that it will be useful,
139 but WITHOUT ANY WARRANTY; without even the implied warranty of
140 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
141 Lesser General Public License for more details.
143 You should have received a copy of the GNU Lesser General Public
144 License along with the GNU C Library; if not, write to the Free
145 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
148 /* Return the first occurrence of NEEDLE in HAYSTACK. */
150 sansa_memmem (haystack
, haystack_len
, needle
, needle_len
)
151 const void *haystack
;
157 const char *const last_possible
158 = (const char *) haystack
+ haystack_len
- needle_len
;
161 /* The first occurrence of the empty string is deemed to occur at
162 the beginning of the string. */
163 return (void *) haystack
;
165 /* Sanity check, otherwise the loop might search through the whole
167 if (__builtin_expect (haystack_len
< needle_len
, 0))
170 for (begin
= (const char *) haystack
; begin
<= last_possible
; ++begin
)
171 if (begin
[0] == ((const char *) needle
)[0] &&
172 !memcmp ((const void *) &begin
[1],
173 (const void *) ((const char *) needle
+ 1),
175 return (void *) begin
;
181 * CRC32 implementation taken from:
183 * efone - Distributed internet phone system.
185 * (c) 1999,2000 Krzysztof Dabrowski
186 * (c) 1999,2000 ElysiuM deeZine
188 * This program is free software; you can redistribute it and/or
189 * modify it under the terms of the GNU General Public License
190 * as published by the Free Software Foundation; either version
191 * 2 of the License, or (at your option) any later version.
195 /* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab().
196 * so make sure, you call it before using the other
199 static unsigned int crc_tab
[256];
201 /* chksum_crc() -- to a given block, this one calculates the
202 * crc32-checksum until the length is
203 * reached. the crc32-checksum will be
206 static unsigned int chksum_crc32 (const unsigned char *block
, unsigned int length
)
208 register unsigned long crc
;
212 for (i
= 0; i
< length
; i
++)
214 crc
= ((crc
>> 8) & 0x00FFFFFF) ^ crc_tab
[(crc
^ *block
++) & 0xFF];
219 /* chksum_crc32gentab() -- to a global crc_tab[256], this one will
220 * calculate the crcTable for crc32-checksums.
221 * it is generated to the polynom [..]
224 static void chksum_crc32gentab (void)
226 unsigned long crc
, poly
;
230 for (i
= 0; i
< 256; i
++)
233 for (j
= 8; j
> 0; j
--)
237 crc
= (crc
>> 1) ^ poly
;
248 /* Known keys for Sansa E200 and C200 firmwares: */
249 #define NUM_KEYS ((int)(sizeof(keys)/sizeof(keys[0])))
250 static const uint32_t keys
[][4] = {
251 { 0xe494e96e, 0x3ee32966, 0x6f48512b, 0xa93fbb42 }, /* "sansa" */
252 { 0xd7b10538, 0xc662945b, 0x1b3fce68, 0xf389c0e6 }, /* "sansa_gh" */
253 { 0x1d29ddc0, 0x2579c2cd, 0xce339e1a, 0x75465dfe }, /* sansa 103 */
255 { 0x2a7968de, 0x15127979, 0x142e60a7, 0xe49c1893 }, /* c200 1.00.03 */
256 { 0xbf2d06fa, 0xf0e23d59, 0x29738132, 0xe2d04ca7 }, /* c200 1.00.04 and up*/
257 { 0xa913d139, 0xf842f398, 0x3e03f1a6, 0x060ee012 }, /* c200 1.01.05 and up*/
258 { 0x0fe92902, 0xe8cc0f89, 0x6ff568ba, 0x1eff5161 }, /* c200 1.01.07 */
263 tea_decrypt() from http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
265 "Following is an adaptation of the reference encryption and decryption
266 routines in C, released into the public domain by David Wheeler and
271 /* NOTE: The mi4 version of TEA uses a different initial value to sum compared
272 to the reference implementation and the main loop is 8 iterations, not
276 static void tea_decrypt(uint32_t* v0
, uint32_t* v1
, const uint32_t* k
) {
277 uint32_t sum
=0xF1BBCDC8, i
; /* set up */
278 uint32_t delta
=0x9E3779B9; /* a key schedule constant */
279 uint32_t k0
=k
[0], k1
=k
[1], k2
=k
[2], k3
=k
[3]; /* cache key */
280 for(i
=0; i
<8; i
++) { /* basic cycle start */
281 *v1
-= ((*v0
<<4) + k2
) ^ (*v0
+ sum
) ^ ((*v0
>>5) + k3
);
282 *v0
-= ((*v1
<<4) + k0
) ^ (*v1
+ sum
) ^ ((*v1
>>5) + k1
);
283 sum
-= delta
; /* end cycle */
287 /* mi4 files are encrypted in 64-bit blocks (two little-endian 32-bit
288 integers) and the key is incremented after each block
291 static void tea_decrypt_buf(const unsigned char* src
, unsigned char* dest
,
292 size_t n
, const uint32_t * initial_key
)
298 memcpy(key
, initial_key
, sizeof(key
));
299 for (i
= 0; i
< (n
/ 8); i
++) {
303 tea_decrypt(&v0
, &v1
, key
);
311 /* Now increment the key */
325 static int get_mi4header(const unsigned char* buf
,struct mi4header_t
* mi4header
)
327 if (memcmp(buf
,"PPOS",4)!=0)
330 mi4header
->version
= le2int(buf
+0x04);
331 mi4header
->length
= le2int(buf
+0x08);
332 mi4header
->crc32
= le2int(buf
+0x0c);
333 mi4header
->enctype
= le2int(buf
+0x10);
334 mi4header
->mi4size
= le2int(buf
+0x14);
335 mi4header
->plaintext
= le2int(buf
+0x18);
340 static int set_mi4header(unsigned char* buf
,const struct mi4header_t
* mi4header
)
342 if (memcmp(buf
,"PPOS",4)!=0)
345 int2le(mi4header
->version
,buf
+0x04);
346 int2le(mi4header
->length
,buf
+0x08);
347 int2le(mi4header
->crc32
,buf
+0x0c);
348 int2le(mi4header
->enctype
,buf
+0x10);
349 int2le(mi4header
->mi4size
,buf
+0x14);
350 int2le(mi4header
->plaintext
,buf
+0x18);
352 /* Add a dummy DSA signature */
353 memset(buf
+0x1c,0,40);
359 static int sansa_seek_and_read(struct sansa_t
* sansa
, loff_t pos
, unsigned char* buf
, int nbytes
)
363 if (sansa_seek(sansa
, pos
) < 0) {
367 if ((n
= sansa_read(sansa
,buf
,nbytes
)) < 0) {
372 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n",
381 /* We identify an E200 based on the following criteria:
383 1) Exactly two partitions;
384 2) First partition is type "W95 FAT32" (0x0b or 0x0c);
385 3) Second partition is type "OS/2 hidden C: drive" (0x84);
386 4) The "PPBL" string appears at offset 0 in the 2nd partition;
387 5) The "PPMI" string appears at offset PPMI_OFFSET in the 2nd partition.
390 int is_sansa(struct sansa_t
* sansa
)
392 struct mi4header_t mi4header
;
396 /* Check partition layout */
397 if (((sansa
->pinfo
[0].type
!= 0x06) &&
398 (sansa
->pinfo
[0].type
!= 0x0b) &&
399 (sansa
->pinfo
[0].type
!= 0x0c) &&
400 (sansa
->pinfo
[0].type
!= 0x0e)) ||
401 (sansa
->pinfo
[1].type
!= 0x84) ||
402 (sansa
->pinfo
[2].type
!= 0x00) ||
403 (sansa
->pinfo
[3].type
!= 0x00)) {
404 /* Bad partition layout, abort */
408 /* Check Bootloader header */
409 if (sansa_seek_and_read(sansa
, sansa
->start
, sansa_sectorbuf
, 0x200) < 0) {
412 if (memcmp(sansa_sectorbuf
,"PPBL",4)!=0) {
413 /* No bootloader header, abort */
416 ppbl_length
= (le2int(sansa_sectorbuf
+4) + 0x1ff) & ~0x1ff;
418 /* Sanity/safety check - the bootloader can't be larger than PPMI_OFFSET */
419 if (ppbl_length
> PPMI_OFFSET
)
424 /* Load Sansa bootloader and check for "Sansa C200" magic string */
425 if (sansa_seek_and_read(sansa
, sansa
->start
+ 0x200, sansa_sectorbuf
, ppbl_length
) < 0) {
426 fprintf(stderr
,"[ERR] Seek and read to 0x%08llx in is_sansa failed.\n",
430 if (sansa_memmem(sansa_sectorbuf
, ppbl_length
, "Sansa C200", 10) != NULL
) {
432 sansa
->targetname
="c200";
435 sansa
->targetname
="e200";
438 /* Check Main firmware header */
439 if (sansa_seek_and_read(sansa
, sansa
->start
+PPMI_OFFSET
, sansa_sectorbuf
, 0x200) < 0) {
440 fprintf(stderr
,"[ERR] Seek to 0x%08llx in is_sansa failed.\n",
441 sansa
->start
+PPMI_OFFSET
);
444 if (memcmp(sansa_sectorbuf
,"PPMI",4)!=0) {
445 /* No bootloader header, abort */
448 ppmi_length
= le2int(sansa_sectorbuf
+4);
450 /* Check main mi4 file header */
451 if (sansa_seek_and_read(sansa
, sansa
->start
+PPMI_OFFSET
+0x200, sansa_sectorbuf
, 0x200) < 0) {
452 fprintf(stderr
,"[ERR] Seek to 0x%08llx in is_sansa failed.\n",
453 sansa
->start
+PPMI_OFFSET
+0x200);
457 if (get_mi4header(sansa_sectorbuf
,&mi4header
) < 0) {
458 fprintf(stderr
,"[ERR] Invalid mi4header\n");
462 /* Some sanity checks:
464 1) Main MI4 image without RBBL and < 100000 bytes -> old install
465 2) Main MI4 image with RBBL but no second image -> old install
468 sansa
->hasoldbootloader
= 0;
469 if (memcmp(sansa_sectorbuf
+0x1f8,"RBBL",4)==0) {
470 /* Look for an original firmware after the first image */
471 if (sansa_seek_and_read(sansa
,
472 sansa
->start
+ PPMI_OFFSET
+ 0x200 + ppmi_length
,
473 sansa_sectorbuf
, 512) < 0) {
477 if (get_mi4header(sansa_sectorbuf
,&mi4header
)!=0) {
478 fprintf(stderr
,"[ERR] No original firmware found\n");
479 sansa
->hasoldbootloader
= 1;
481 } else if (mi4header
.mi4size
< 100000) {
482 fprintf(stderr
,"[ERR] Old bootloader found\n");
483 sansa
->hasoldbootloader
= 1;
489 int sansa_scan(struct sansa_t
* sansa
)
493 char last_disk
[4096];
497 printf("[INFO] Scanning disk devices...\n");
499 for (i
= 0; i
<= 25 ; i
++) {
501 sprintf(sansa
->diskname
,"\\\\.\\PhysicalDrive%d",i
);
502 #elif defined(linux) || defined (__linux)
503 sprintf(sansa
->diskname
,"/dev/sd%c",'a'+i
);
504 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
505 || defined(__bsdi__) || defined(__DragonFly__)
506 sprintf(sansa
->diskname
,"/dev/da%d",i
);
507 #elif defined(__APPLE__) && defined(__MACH__)
508 sprintf(sansa
->diskname
,"/dev/disk%d",i
);
510 #error No disk paths defined for this platform
512 if ((result
= sansa_open(sansa
, 1)) < 0) {
520 if (sansa_read_partinfo(sansa
,1) < 0) {
525 if (is_sansa(sansa
) < 0) {
531 printf("[INFO] %s found - disk device %d\n",sansa
->targetname
, i
);
533 printf("[INFO] %s found - %s\n",sansa
->targetname
, sansa
->diskname
);
536 strcpy(last_disk
,sansa
->diskname
);
541 /* Remember the disk name */
542 strcpy(sansa
->diskname
,last_disk
);
544 else if (n
== 0 && denied
) {
545 printf("[ERR] FATAL: Permission denied on %d device(s) and no sansa detected.\n", denied
);
547 printf("[ERR] You need to run this program with administrator priviledges!\n");
549 printf("[ERR] You need permissions for raw disc access for this program to work!\n");
553 return (n
== 0 && denied
) ? -1 : n
;
556 /* Prepare original firmware for writing to the firmware partition by decrypting
557 and updating the header */
558 static int prepare_original_firmware(struct sansa_t
* sansa
, unsigned char* buf
, struct mi4header_t
* mi4header
)
560 unsigned char* tmpbuf
;
564 get_mi4header(buf
,mi4header
);
567 printf("mi4header->version =0x%08x\n",mi4header
->version
);
568 printf("mi4header->length =0x%08x\n",mi4header
->length
);
569 printf("mi4header->crc32 =0x%08x\n",mi4header
->crc32
);
570 printf("mi4header->enctype =0x%08x\n",mi4header
->enctype
);
571 printf("mi4header->mi4size =0x%08x\n",mi4header
->mi4size
);
572 printf("mi4header->plaintext =0x%08x\n",mi4header
->plaintext
);
575 /* Decrypt anything that needs decrypting. */
576 if (mi4header
->plaintext
< mi4header
->mi4size
- 0x200) {
577 /* TODO: Check different keys */
578 tmpbuf
=malloc(mi4header
->mi4size
-(mi4header
->plaintext
+0x200));
580 fprintf(stderr
,"[ERR] Can not allocate memory\n");
585 for (i
=0; i
< NUM_KEYS
&& !key_found
; i
++) {
586 tea_decrypt_buf(buf
+(mi4header
->plaintext
+0x200),
588 mi4header
->mi4size
-(mi4header
->plaintext
+0x200),
590 key_found
= (le2uint(tmpbuf
+mi4header
->length
-mi4header
->plaintext
-4) == 0xaa55aa55);
594 memcpy(buf
+(mi4header
->plaintext
+0x200),tmpbuf
,mi4header
->mi4size
-(mi4header
->plaintext
+0x200));
597 fprintf(stderr
,"[ERR] Failed to decrypt image, aborting\n");
603 /* Increase plaintext value to full file */
604 mi4header
->plaintext
= mi4header
->mi4size
- 0x200;
606 /* Update CRC checksum */
607 chksum_crc32gentab ();
608 mi4header
->crc32
= chksum_crc32(buf
+0x200,mi4header
->mi4size
-0x200);
610 set_mi4header(buf
,mi4header
);
612 /* Add Rockbox-specific header */
613 memcpy(buf
+0x1f8,"RBOF",4);
614 memcpy(buf
+0x1fc,sansa
->targetname
,4);
619 static int load_original_firmware(struct sansa_t
* sansa
, unsigned char* buf
, struct mi4header_t
* mi4header
)
624 /* Read 512 bytes from PPMI_OFFSET - the PPMI header plus the mi4 header */
625 if (sansa_seek_and_read(sansa
, sansa
->start
+ PPMI_OFFSET
, buf
, 512) < 0) {
629 /* No need to check PPMI magic - it's done during init to confirm
631 ppmi_length
= le2int(buf
+4);
633 /* Firstly look for an original firmware after the first image */
634 if (sansa_seek_and_read(sansa
, sansa
->start
+ PPMI_OFFSET
+ 0x200 + ppmi_length
, buf
, 512) < 0) {
638 if (get_mi4header(buf
,mi4header
)==0) {
639 /* We have a valid MI4 file after a bootloader, so we use this. */
640 if ((n
= sansa_seek_and_read(sansa
,
641 sansa
->start
+ PPMI_OFFSET
+ 0x200 + ppmi_length
,
642 buf
, mi4header
->mi4size
)) < 0) {
646 /* No valid MI4 file, so read the first image. */
647 if ((n
= sansa_seek_and_read(sansa
,
648 sansa
->start
+ PPMI_OFFSET
+ 0x200,
649 buf
, ppmi_length
)) < 0) {
653 return prepare_original_firmware(sansa
, buf
, mi4header
);
656 int sansa_read_firmware(struct sansa_t
* sansa
, const char* filename
)
660 struct mi4header_t mi4header
;
662 res
= load_original_firmware(sansa
,sansa_sectorbuf
,&mi4header
);
666 outfile
= open(filename
,O_CREAT
|O_TRUNC
|O_WRONLY
|O_BINARY
,0666);
668 fprintf(stderr
,"[ERR] Couldn't open file %s\n",filename
);
672 res
= write(outfile
,sansa_sectorbuf
,mi4header
.mi4size
);
673 if (res
!= (int)mi4header
.mi4size
) {
674 fprintf(stderr
,"[ERR] Write error - %d\n", res
);
682 unsigned int sansa_read_bootloader(struct sansa_t
* sansa
, const char* filename
, unsigned char** bl_buffer
)
684 /* Step 1 - read bootloader into RAM. */
688 infile
=open(filename
,O_RDONLY
|O_BINARY
);
690 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
694 len
= filesize(infile
);
696 unsigned char* b
= malloc(len
);
698 fprintf(stderr
,"[ERR] Could not allocate memory for bootloader\n");
703 n
= read(infile
,b
,len
);
706 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n"
711 if (memcmp(b
+0x1f8,"RBBL",4)!=0) {
712 fprintf(stderr
,"[ERR] %s is not a Rockbox bootloader, aborting.\n",
716 if (memcmp(b
+0x1fc,sansa
->targetname
,4)!=0) {
717 fprintf(stderr
,"[ERR] %s is not a Rockbox bootloader for %s, aborting.\n",
718 filename
, sansa
->targetname
);
725 int sansa_add_bootloader(struct sansa_t
* sansa
, const unsigned char* bootloader
, const unsigned int bl_length
)
728 struct mi4header_t mi4header
;
732 /* Create PPMI header */
733 memset(sansa_sectorbuf
,0,0x200);
734 memcpy(sansa_sectorbuf
,"PPMI",4);
735 int2le(bl_length
, sansa_sectorbuf
+4);
736 int2le(0x00020000, sansa_sectorbuf
+8);
738 /* copy bootloader to sansa_sectorbuf+0x200 */
739 memcpy(sansa_sectorbuf
+0x200,bootloader
,bl_length
);
741 /* Load original firmware from Sansa to the space after the bootloader */
742 res
= load_original_firmware(sansa
,sansa_sectorbuf
+0x200+bl_length
,&mi4header
);
746 /* Now write the whole thing back to the Sansa */
748 if (sansa_seek(sansa
, sansa
->start
+PPMI_OFFSET
) < 0) {
749 fprintf(stderr
,"[ERR] Seek to 0x%08llx in add_bootloader failed.\n",
750 sansa
->start
+PPMI_OFFSET
);
754 length
= 0x200 + bl_length
+ mi4header
.mi4size
;
756 n
=sansa_write(sansa
, sansa_sectorbuf
, length
);
758 fprintf(stderr
,"[ERR] Short write in add_bootloader\n");
765 int sansa_delete_bootloader(struct sansa_t
* sansa
)
768 struct mi4header_t mi4header
;
772 /* Load original firmware from Sansa to sansa_sectorbuf+0x200 */
773 res
= load_original_firmware(sansa
,sansa_sectorbuf
+0x200,&mi4header
);
777 /* Create PPMI header */
778 memset(sansa_sectorbuf
,0,0x200);
779 memcpy(sansa_sectorbuf
,"PPMI",4);
780 int2le(mi4header
.mi4size
, sansa_sectorbuf
+4);
781 int2le(0x00020000, sansa_sectorbuf
+8);
783 /* Now write the whole thing back to the Sansa */
785 if (sansa_seek(sansa
, sansa
->start
+PPMI_OFFSET
) < 0) {
786 fprintf(stderr
,"[ERR] Seek to 0x%08llx in add_bootloader failed.\n",
787 sansa
->start
+PPMI_OFFSET
);
791 length
= 0x200 + mi4header
.mi4size
;
793 n
=sansa_write(sansa
, sansa_sectorbuf
, length
);
795 fprintf(stderr
,"[ERR] Short write in delete_bootloader\n");
802 /** List number of MI4 images on the player, return number.
804 int sansa_list_images(struct sansa_t
* sansa
)
806 struct mi4header_t mi4header
;
810 /* Check Main firmware header */
811 if (sansa_seek_and_read(sansa
, sansa
->start
+PPMI_OFFSET
, sansa_sectorbuf
, 0x200) < 0) {
815 ppmi_length
= le2int(sansa_sectorbuf
+4);
817 printf("[INFO] Image 1 - %llu bytes\n",ppmi_length
);
820 /* Look for an original firmware after the first image */
821 if (sansa_seek_and_read(sansa
, sansa
->start
+ PPMI_OFFSET
+ 0x200 + ppmi_length
, sansa_sectorbuf
, 512) < 0) {
825 if (get_mi4header(sansa_sectorbuf
,&mi4header
)==0) {
826 printf("[INFO] Image 2 - %d bytes\n",mi4header
.mi4size
);
832 int sansa_update_of(struct sansa_t
* sansa
, const char* filename
)
835 int infile
= -1; /* Prevent an erroneous "may be used uninitialised" gcc warning */
836 int of_length
= 0; /* Keep gcc happy when building for rbutil */
838 struct mi4header_t mi4header
;
839 unsigned char buf
[512];
841 /* Step 1 - check we have an OF on the Sansa to upgrade. We expect the
842 Rockbox bootloader to be installed and the OF to be after it on disk. */
844 /* Read 512 bytes from PPMI_OFFSET - the PPMI header */
845 if (sansa_seek_and_read(sansa
, sansa
->start
+ PPMI_OFFSET
,
850 /* No need to check PPMI magic - it's done during init to confirm
852 ppmi_length
= le2int(buf
+4);
854 /* Look for an original firmware after the first image */
855 if (sansa_seek_and_read(sansa
, sansa
->start
+PPMI_OFFSET
+0x200+ppmi_length
,
860 if (get_mi4header(buf
,&mi4header
)!=0) {
861 /* We don't have a valid MI4 file after a bootloader, so do nothing. */
862 fprintf(stderr
,"[ERR] No original firmware found at 0x%08llx\n",
863 sansa
->start
+PPMI_OFFSET
+0x200+ppmi_length
);
867 /* Step 2 - read OF into RAM. */
868 infile
=open(filename
,O_RDONLY
|O_BINARY
);
870 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
874 of_length
= filesize(infile
);
876 /* Load original firmware from file */
877 memset(sansa_sectorbuf
,0,0x200);
878 n
= read(infile
,sansa_sectorbuf
,of_length
);
881 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n"
886 /* Check we have a valid MI4 file. */
887 if (get_mi4header(sansa_sectorbuf
,&mi4header
)!=0) {
888 fprintf(stderr
,"[ERR] %s is not a valid mi4 file\n",filename
);
892 /* Decrypt and build the header */
893 if(prepare_original_firmware(sansa
, sansa_sectorbuf
, &mi4header
)!=0){
894 fprintf(stderr
,"[ERR] Unable to build decrypted mi4 from %s\n"
899 /* Step 3 - write the OF to the Sansa */
900 if (sansa_seek(sansa
, sansa
->start
+PPMI_OFFSET
+0x200+ppmi_length
) < 0) {
901 fprintf(stderr
,"[ERR] Seek to 0x%08llx in sansa_update_of failed.\n",
902 sansa
->start
+PPMI_OFFSET
+0x200+ppmi_length
);
906 n
=sansa_write(sansa
, sansa_sectorbuf
, of_length
);
908 fprintf(stderr
,"[ERR] Short write in sansa_update_of\n");
912 /* Step 4 - zero out the nvparams section - we have to do this or we end up
913 with multiple copies of the nvparams data and don't know which one to
914 work with for the database rebuild disabling trick in our bootloader */
915 if (strcmp(sansa
->targetname
,"e200") == 0) {
916 printf("[INFO] Resetting Original Firmware settings\n");
917 if (sansa_seek(sansa
, sansa
->start
+NVPARAMS_OFFSET
+0x200) < 0) {
918 fprintf(stderr
,"[ERR] Seek to 0x%08llx in sansa_update_of failed.\n",
919 sansa
->start
+NVPARAMS_OFFSET
+0x200);
923 memset(sansa_sectorbuf
,0,NVPARAMS_SIZE
);
924 n
=sansa_write(sansa
, sansa_sectorbuf
, NVPARAMS_SIZE
);
925 if (n
< NVPARAMS_SIZE
) {
926 fprintf(stderr
,"[ERR] Short write in sansa_update_of\n");
934 /* Update the PPBL (bootloader) image in the hidden firmware partition */
935 int sansa_update_ppbl(struct sansa_t
* sansa
, const char* filename
)
938 int infile
= -1; /* Prevent an erroneous "may be used uninitialised" gcc warning */
939 int ppbl_length
= 0; /* Keep gcc happy when building for rbutil */
941 /* Step 1 - read bootloader into RAM. */
942 infile
=open(filename
,O_RDONLY
|O_BINARY
);
944 fprintf(stderr
,"[ERR] Couldn't open input file %s\n",filename
);
948 ppbl_length
= filesize(infile
);
950 n
= read(infile
,sansa_sectorbuf
+0x200,ppbl_length
);
952 if (n
< ppbl_length
) {
953 fprintf(stderr
,"[ERR] Short read - requested %d bytes, received %d\n", ppbl_length
, n
);
957 /* Step 2 - Build the header */
958 memset(sansa_sectorbuf
,0,0x200);
959 memcpy(sansa_sectorbuf
,"PPBL",4);
960 int2le(ppbl_length
, sansa_sectorbuf
+4);
961 int2le(0x00010000, sansa_sectorbuf
+8);
963 /* Step 3 - write the bootloader to the Sansa */
964 if (sansa_seek(sansa
, sansa
->start
) < 0) {
965 fprintf(stderr
,"[ERR] Seek to 0x%08llx in sansa_update_ppbl failed.\n", sansa
->start
);
969 n
=sansa_write(sansa
, sansa_sectorbuf
, ppbl_length
+ 0x200);
970 if (n
< (ppbl_length
+0x200)) {
971 fprintf(stderr
,"[ERR] Short write in sansa_update_ppbl\n");