A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 975 lines 30 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2006-2007 Dave Chapman 11 * 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. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21 22#include <stdio.h> 23#include <unistd.h> 24#include <fcntl.h> 25#include <string.h> 26#include <stdlib.h> 27#include <inttypes.h> 28#include <sys/types.h> 29#include <sys/stat.h> 30 31#include "sansaio.h" 32#include "sansapatcher.h" 33 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) 38 39int sansa_verbose = 0; 40 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(). 44*/ 45 46static off_t filesize(int fd) { 47 struct stat buf; 48 49 if (fstat(fd,&buf) < 0) { 50 perror("[ERR] Checking filesize of input file"); 51 return -1; 52 } else { 53 return(buf.st_size); 54 } 55} 56 57/* Partition table parsing code taken from Rockbox */ 58 59#define MAX_SECTOR_SIZE 2048 60#define SECTOR_SIZE 512 61 62static inline int32_t le2int(const unsigned char* buf) 63{ 64 int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; 65 66 return res; 67} 68 69static inline uint32_t le2uint(const unsigned char* buf) 70{ 71 uint32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; 72 73 return res; 74} 75 76static inline void int2le(unsigned int val, unsigned char* addr) 77{ 78 addr[0] = val & 0xFF; 79 addr[1] = (val >> 8) & 0xff; 80 addr[2] = (val >> 16) & 0xff; 81 addr[3] = (val >> 24) & 0xff; 82} 83 84#define BYTES2INT32(array,pos)\ 85 ((long)array[pos] | ((long)array[pos+1] << 8 ) |\ 86 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) 87 88int sansa_read_partinfo(struct sansa_t* sansa, int silent) 89{ 90 int i; 91 unsigned long count; 92 93 count = sansa_read(sansa,sansa->sectorbuf, sansa->sector_size); 94 95 if (count <= 0) { 96 sansa_print_error(" Error reading from disk: "); 97 return -1; 98 } 99 100 if ((sansa->sectorbuf[510] == 0x55) && (sansa->sectorbuf[511] == 0xaa)) { 101 /* parse partitions */ 102 for ( i = 0; i < 4; i++ ) { 103 unsigned char* ptr = sansa->sectorbuf + 0x1be + 16*i; 104 sansa->pinfo[i].type = ptr[4]; 105 sansa->pinfo[i].start = BYTES2INT32(ptr, 8); 106 sansa->pinfo[i].size = BYTES2INT32(ptr, 12); 107 108 /* extended? */ 109 if ( sansa->pinfo[i].type == 5 ) { 110 /* not handled yet */ 111 } 112 } 113 } else if ((sansa->sectorbuf[0] == 'E') && (sansa->sectorbuf[1] == 'R')) { 114 if (!silent) fprintf(stderr,"[ERR] Bad boot sector signature\n"); 115 return -1; 116 } 117 118 /* Calculate the starting position of the firmware partition */ 119 sansa->start = (loff_t)sansa->pinfo[1].start*(loff_t)sansa->sector_size; 120 return 0; 121} 122 123/* NOTE: memmem implementation copied from glibc-2.2.4 - it's a GNU 124 extension and is not universally. In addition, early versions of 125 memmem had a serious bug - the meaning of needle and haystack were 126 reversed. */ 127 128/* Copyright (C) 1991,92,93,94,96,97,98,2000 Free Software Foundation, Inc. 129 This file is part of the GNU C Library. 130 131 The GNU C Library is free software; you can redistribute it and/or 132 modify it under the terms of the GNU Lesser General Public 133 License as published by the Free Software Foundation; either 134 version 2.1 of the License, or (at your option) any later version. 135 136 The GNU C Library is distributed in the hope that it will be useful, 137 but WITHOUT ANY WARRANTY; without even the implied warranty of 138 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 139 Lesser General Public License for more details. 140 141 You should have received a copy of the GNU Lesser General Public 142 License along with the GNU C Library; if not, write to the Free 143 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 144 02111-1307 USA. */ 145 146/* Return the first occurrence of NEEDLE in HAYSTACK. */ 147static void * 148sansa_memmem (haystack, haystack_len, needle, needle_len) 149 const void *haystack; 150 size_t haystack_len; 151 const void *needle; 152 size_t needle_len; 153{ 154 const char *begin; 155 const char *const last_possible 156 = (const char *) haystack + haystack_len - needle_len; 157 158 if (needle_len == 0) 159 /* The first occurrence of the empty string is deemed to occur at 160 the beginning of the string. */ 161 return (void *) haystack; 162 163 /* Sanity check, otherwise the loop might search through the whole 164 memory. */ 165 if (__builtin_expect (haystack_len < needle_len, 0)) 166 return NULL; 167 168 for (begin = (const char *) haystack; begin <= last_possible; ++begin) 169 if (begin[0] == ((const char *) needle)[0] && 170 !memcmp ((const void *) &begin[1], 171 (const void *) ((const char *) needle + 1), 172 needle_len - 1)) 173 return (void *) begin; 174 175 return NULL; 176} 177 178/* 179 * CRC32 implementation taken from: 180 * 181 * efone - Distributed internet phone system. 182 * 183 * (c) 1999,2000 Krzysztof Dabrowski 184 * (c) 1999,2000 ElysiuM deeZine 185 * 186 * This program is free software; you can redistribute it and/or 187 * modify it under the terms of the GNU General Public License 188 * as published by the Free Software Foundation; either version 189 * 2 of the License, or (at your option) any later version. 190 * 191 */ 192 193/* crc_tab[] -- this crcTable is being build by chksum_crc32GenTab(). 194 * so make sure, you call it before using the other 195 * functions! 196 */ 197static unsigned int crc_tab[256]; 198 199/* chksum_crc() -- to a given block, this one calculates the 200 * crc32-checksum until the length is 201 * reached. the crc32-checksum will be 202 * the result. 203 */ 204static unsigned int chksum_crc32 (const unsigned char *block, unsigned int length) 205{ 206 register unsigned long crc; 207 unsigned long i; 208 209 crc = 0; 210 for (i = 0; i < length; i++) 211 { 212 crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF]; 213 } 214 return (crc); 215} 216 217/* chksum_crc32gentab() -- to a global crc_tab[256], this one will 218 * calculate the crcTable for crc32-checksums. 219 * it is generated to the polynom [..] 220 */ 221 222static void chksum_crc32gentab (void) 223{ 224 unsigned long crc, poly; 225 int i, j; 226 227 poly = 0xEDB88320L; 228 for (i = 0; i < 256; i++) 229 { 230 crc = i; 231 for (j = 8; j > 0; j--) 232 { 233 if (crc & 1) 234 { 235 crc = (crc >> 1) ^ poly; 236 } 237 else 238 { 239 crc >>= 1; 240 } 241 } 242 crc_tab[i] = crc; 243 } 244} 245 246/* Known keys for Sansa E200 and C200 firmwares: */ 247#define NUM_KEYS ((int)(sizeof(keys)/sizeof(keys[0]))) 248static const uint32_t keys[][4] = { 249 { 0xe494e96e, 0x3ee32966, 0x6f48512b, 0xa93fbb42 }, /* "sansa" */ 250 { 0xd7b10538, 0xc662945b, 0x1b3fce68, 0xf389c0e6 }, /* "sansa_gh" */ 251 { 0x1d29ddc0, 0x2579c2cd, 0xce339e1a, 0x75465dfe }, /* sansa 103 */ 252 253 { 0x2a7968de, 0x15127979, 0x142e60a7, 0xe49c1893 }, /* c200 1.00.03 */ 254 { 0xbf2d06fa, 0xf0e23d59, 0x29738132, 0xe2d04ca7 }, /* c200 1.00.04 and up*/ 255 { 0xa913d139, 0xf842f398, 0x3e03f1a6, 0x060ee012 }, /* c200 1.01.05 and up*/ 256 { 0x0fe92902, 0xe8cc0f89, 0x6ff568ba, 0x1eff5161 }, /* c200 1.01.07 */ 257}; 258 259/* 260 261tea_decrypt() from http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm 262 263"Following is an adaptation of the reference encryption and decryption 264routines in C, released into the public domain by David Wheeler and 265Roger Needham:" 266 267*/ 268 269/* NOTE: The mi4 version of TEA uses a different initial value to sum compared 270 to the reference implementation and the main loop is 8 iterations, not 271 32. 272*/ 273 274static void tea_decrypt(uint32_t* v0, uint32_t* v1, const uint32_t* k) { 275 uint32_t sum=0xF1BBCDC8, i; /* set up */ 276 uint32_t delta=0x9E3779B9; /* a key schedule constant */ 277 uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ 278 for(i=0; i<8; i++) { /* basic cycle start */ 279 *v1 -= ((*v0<<4) + k2) ^ (*v0 + sum) ^ ((*v0>>5) + k3); 280 *v0 -= ((*v1<<4) + k0) ^ (*v1 + sum) ^ ((*v1>>5) + k1); 281 sum -= delta; /* end cycle */ 282 } 283} 284 285/* mi4 files are encrypted in 64-bit blocks (two little-endian 32-bit 286 integers) and the key is incremented after each block 287 */ 288 289static void tea_decrypt_buf(const unsigned char* src, unsigned char* dest, 290 size_t n, const uint32_t * initial_key) 291{ 292 uint32_t v0, v1; 293 unsigned int i; 294 uint32_t key[4]; 295 296 memcpy(key, initial_key, sizeof(key)); 297 for (i = 0; i < (n / 8); i++) { 298 v0 = le2int(src); 299 v1 = le2int(src+4); 300 301 tea_decrypt(&v0, &v1, key); 302 303 int2le(v0, dest); 304 int2le(v1, dest+4); 305 306 src += 8; 307 dest += 8; 308 309 /* Now increment the key */ 310 key[0]++; 311 if (key[0]==0) { 312 key[1]++; 313 if (key[1]==0) { 314 key[2]++; 315 if (key[2]==0) { 316 key[3]++; 317 } 318 } 319 } 320 } 321} 322 323static int get_mi4header(const unsigned char* buf,struct mi4header_t* mi4header) 324{ 325 if (memcmp(buf,"PPOS",4)!=0) 326 return -1; 327 328 mi4header->version = le2int(buf+0x04); 329 mi4header->length = le2int(buf+0x08); 330 mi4header->crc32 = le2int(buf+0x0c); 331 mi4header->enctype = le2int(buf+0x10); 332 mi4header->mi4size = le2int(buf+0x14); 333 mi4header->plaintext = le2int(buf+0x18); 334 335 return 0; 336} 337 338static int set_mi4header(unsigned char* buf,const struct mi4header_t* mi4header) 339{ 340 if (memcmp(buf,"PPOS",4)!=0) 341 return -1; 342 343 int2le(mi4header->version ,buf+0x04); 344 int2le(mi4header->length ,buf+0x08); 345 int2le(mi4header->crc32 ,buf+0x0c); 346 int2le(mi4header->enctype ,buf+0x10); 347 int2le(mi4header->mi4size ,buf+0x14); 348 int2le(mi4header->plaintext ,buf+0x18); 349 350 /* Add a dummy DSA signature */ 351 memset(buf+0x1c,0,40); 352 buf[0x2f] = 1; 353 354 return 0; 355} 356 357static int sansa_seek_and_read(struct sansa_t* sansa, loff_t pos, unsigned char* buf, int nbytes) 358{ 359 int n; 360 361 if (sansa_seek(sansa, pos) < 0) { 362 return -1; 363 } 364 365 if ((n = sansa_read(sansa,buf,nbytes)) < 0) { 366 return -1; 367 } 368 369 if (n < nbytes) { 370 fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", 371 nbytes,n); 372 return -1; 373 } 374 375 return 0; 376} 377 378 379/* We identify an E200 based on the following criteria: 380 381 1) Exactly two partitions; 382 2) First partition is type "W95 FAT32" (0x0b or 0x0c); 383 3) Second partition is type "OS/2 hidden C: drive" (0x84); 384 4) The "PPBL" string appears at offset 0 in the 2nd partition; 385 5) The "PPMI" string appears at offset PPMI_OFFSET in the 2nd partition. 386*/ 387 388int is_sansa(struct sansa_t* sansa) 389{ 390 struct mi4header_t mi4header; 391 int ppmi_length; 392 int ppbl_length; 393 394 /* Check partition layout */ 395 if (((sansa->pinfo[0].type != 0x06) && 396 (sansa->pinfo[0].type != 0x0b) && 397 (sansa->pinfo[0].type != 0x0c) && 398 (sansa->pinfo[0].type != 0x0e)) || 399 (sansa->pinfo[1].type != 0x84) || 400 (sansa->pinfo[2].type != 0x00) || 401 (sansa->pinfo[3].type != 0x00)) { 402 /* Bad partition layout, abort */ 403 return -1; 404 } 405 406 /* Check Bootloader header */ 407 if (sansa_seek_and_read(sansa, sansa->start, sansa->sectorbuf, 0x200) < 0) { 408 return -2; 409 } 410 if (memcmp(sansa->sectorbuf,"PPBL",4)!=0) { 411 /* No bootloader header, abort */ 412 return -4; 413 } 414 ppbl_length = (le2int(sansa->sectorbuf+4) + 0x1ff) & ~0x1ff; 415 416 /* Sanity/safety check - the bootloader can't be larger than PPMI_OFFSET */ 417 if (ppbl_length > PPMI_OFFSET) 418 { 419 return -5; 420 } 421 422 /* Load Sansa bootloader and check for "Sansa C200" magic string */ 423 if (sansa_seek_and_read(sansa, sansa->start + 0x200, sansa->sectorbuf, ppbl_length) < 0) { 424 fprintf(stderr,"[ERR] Seek and read to 0x%08"PRIx64" in is_sansa failed.\n", 425 sansa->start+0x200); 426 return -6; 427 } 428 if (sansa_memmem(sansa->sectorbuf, ppbl_length, "Sansa C200", 10) != NULL) { 429 /* C200 */ 430 sansa->targetname="c200"; 431 } else { 432 /* E200 */ 433 sansa->targetname="e200"; 434 } 435 436 /* Check Main firmware header */ 437 if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sansa->sectorbuf, 0x200) < 0) { 438 fprintf(stderr,"[ERR] Seek to 0x%"PRIx64" in is_sansa failed.\n", 439 sansa->start+PPMI_OFFSET); 440 return -5; 441 } 442 if (memcmp(sansa->sectorbuf,"PPMI",4)!=0) { 443 /* No bootloader header, abort */ 444 return -7; 445 } 446 ppmi_length = le2int(sansa->sectorbuf+4); 447 448 /* Check main mi4 file header */ 449 if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200, sansa->sectorbuf, 0x200) < 0) { 450 fprintf(stderr,"[ERR] Seek to 0x%"PRIx64" in is_sansa failed.\n", 451 sansa->start+PPMI_OFFSET+0x200); 452 return -5; 453 } 454 455 if (get_mi4header(sansa->sectorbuf,&mi4header) < 0) { 456 fprintf(stderr,"[ERR] Invalid mi4header\n"); 457 return -6; 458 } 459 460 /* Some sanity checks: 461 462 1) Main MI4 image without RBBL and < 100000 bytes -> old install 463 2) Main MI4 image with RBBL but no second image -> old install 464 */ 465 466 sansa->hasoldbootloader = 0; 467 if (memcmp(sansa->sectorbuf+0x1f8,"RBBL",4)==0) { 468 /* Look for an original firmware after the first image */ 469 if (sansa_seek_and_read(sansa, 470 sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, 471 sansa->sectorbuf, 512) < 0) { 472 return -7; 473 } 474 475 if (get_mi4header(sansa->sectorbuf,&mi4header)!=0) { 476 fprintf(stderr,"[ERR] No original firmware found\n"); 477 sansa->hasoldbootloader = 1; 478 } 479 } else if (mi4header.mi4size < 100000) { 480 fprintf(stderr,"[ERR] Old bootloader found\n"); 481 sansa->hasoldbootloader = 1; 482 } 483 484 return 0; 485} 486 487int sansa_scan(struct sansa_t* sansa) 488{ 489 int i; 490 int n = 0; 491 char last_disk[4096]; 492 int denied = 0; 493 int result; 494 495 printf("[INFO] Scanning disk devices...\n"); 496 497 for (i = 0; i <= 25 ; i++) { 498#ifdef __WIN32__ 499 sprintf(sansa->diskname,"\\\\.\\PhysicalDrive%d",i); 500#elif defined(linux) || defined (__linux) 501 sprintf(sansa->diskname,"/dev/sd%c",'a'+i); 502#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ 503 || defined(__bsdi__) || defined(__DragonFly__) 504 sprintf(sansa->diskname,"/dev/da%d",i); 505#elif defined(__APPLE__) && defined(__MACH__) 506 sprintf(sansa->diskname,"/dev/disk%d",i); 507#else 508#error No disk paths defined for this platform 509#endif 510 if ((result = sansa_open(sansa, 1)) < 0) { 511 if(result == -2) { 512 denied++; 513 } 514 sansa_close(sansa); 515 continue; 516 } 517 518 if (sansa_read_partinfo(sansa,1) < 0) { 519 sansa_close(sansa); 520 continue; 521 } 522 523 if (is_sansa(sansa) < 0) { 524 sansa_close(sansa); 525 continue; 526 } 527 528#ifdef __WIN32__ 529 printf("[INFO] %s found - disk device %d\n",sansa->targetname, i); 530#else 531 printf("[INFO] %s found - %s\n",sansa->targetname, sansa->diskname); 532#endif 533 n++; 534 strcpy(last_disk,sansa->diskname); 535 sansa_close(sansa); 536 } 537 538 if (n==1) { 539 /* Remember the disk name */ 540 strcpy(sansa->diskname,last_disk); 541 } 542 else if (n == 0 && denied) { 543 printf("[ERR] FATAL: Permission denied on %d device(s) and no sansa detected.\n", denied); 544#ifdef __WIN32__ 545 printf("[ERR] You need to run this program with administrator priviledges!\n"); 546#else 547 printf("[ERR] You need permissions for raw disc access for this program to work!\n"); 548#endif 549 } 550 551 return (n == 0 && denied) ? -1 : n; 552} 553 554/* Prepare original firmware for writing to the firmware partition by decrypting 555 and updating the header */ 556static int prepare_original_firmware(struct sansa_t* sansa, unsigned char* buf, struct mi4header_t* mi4header) 557{ 558 unsigned char* tmpbuf; 559 int i; 560 int key_found; 561 562 get_mi4header(buf,mi4header); 563 564#if 0 565 printf("mi4header->version =0x%08x\n",mi4header->version); 566 printf("mi4header->length =0x%08x\n",mi4header->length); 567 printf("mi4header->crc32 =0x%08x\n",mi4header->crc32); 568 printf("mi4header->enctype =0x%08x\n",mi4header->enctype); 569 printf("mi4header->mi4size =0x%08x\n",mi4header->mi4size); 570 printf("mi4header->plaintext =0x%08x\n",mi4header->plaintext); 571#endif 572 573 /* Decrypt anything that needs decrypting. */ 574 if (mi4header->plaintext < mi4header->mi4size - 0x200) { 575 /* TODO: Check different keys */ 576 tmpbuf=malloc(mi4header->mi4size-(mi4header->plaintext+0x200)); 577 if (tmpbuf==NULL) { 578 fprintf(stderr,"[ERR] Can not allocate memory\n"); 579 return -1; 580 } 581 582 key_found=0; 583 for (i=0; i < NUM_KEYS && !key_found ; i++) { 584 tea_decrypt_buf(buf+(mi4header->plaintext+0x200), 585 tmpbuf, 586 mi4header->mi4size-(mi4header->plaintext+0x200), 587 keys[i]); 588 key_found = (le2uint(tmpbuf+mi4header->length-mi4header->plaintext-4) == 0xaa55aa55); 589 } 590 591 if (key_found) { 592 memcpy(buf+(mi4header->plaintext+0x200),tmpbuf,mi4header->mi4size-(mi4header->plaintext+0x200)); 593 free(tmpbuf); 594 } else { 595 fprintf(stderr,"[ERR] Failed to decrypt image, aborting\n"); 596 free(tmpbuf); 597 return -1; 598 } 599 } 600 601 /* Increase plaintext value to full file */ 602 mi4header->plaintext = mi4header->mi4size - 0x200; 603 604 /* Update CRC checksum */ 605 chksum_crc32gentab (); 606 mi4header->crc32 = chksum_crc32(buf+0x200,mi4header->mi4size-0x200); 607 608 set_mi4header(buf,mi4header); 609 610 /* Add Rockbox-specific header */ 611 memcpy(buf+0x1f8,"RBOF",4); 612 memcpy(buf+0x1fc,sansa->targetname,4); 613 614 return 0; 615} 616 617static int load_original_firmware(struct sansa_t* sansa, unsigned char* buf, struct mi4header_t* mi4header) 618{ 619 int ppmi_length; 620 int n; 621 622 /* Read 512 bytes from PPMI_OFFSET - the PPMI header plus the mi4 header */ 623 if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET, buf, 512) < 0) { 624 return -1; 625 } 626 627 /* No need to check PPMI magic - it's done during init to confirm 628 this is an E200 */ 629 ppmi_length = le2int(buf+4); 630 631 /* Firstly look for an original firmware after the first image */ 632 if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, buf, 512) < 0) { 633 return -1; 634 } 635 636 if (get_mi4header(buf,mi4header)==0) { 637 /* We have a valid MI4 file after a bootloader, so we use this. */ 638 if ((n = sansa_seek_and_read(sansa, 639 sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, 640 buf, mi4header->mi4size)) < 0) { 641 return -1; 642 } 643 } else { 644 /* No valid MI4 file, so read the first image. */ 645 if ((n = sansa_seek_and_read(sansa, 646 sansa->start + PPMI_OFFSET + 0x200, 647 buf, ppmi_length)) < 0) { 648 return -1; 649 } 650 } 651 return prepare_original_firmware(sansa, buf, mi4header); 652} 653 654int sansa_read_firmware(struct sansa_t* sansa, const char* filename) 655{ 656 int res; 657 int outfile; 658 struct mi4header_t mi4header; 659 660 res = load_original_firmware(sansa,sansa->sectorbuf,&mi4header); 661 if (res < 0) 662 return res; 663 664 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666); 665 if (outfile < 0) { 666 fprintf(stderr,"[ERR] Couldn't open file %s\n",filename); 667 return -1; 668 } 669 670 res = write(outfile,sansa->sectorbuf,mi4header.mi4size); 671 if (res != (int)mi4header.mi4size) { 672 fprintf(stderr,"[ERR] Write error - %d\n", res); 673 return -1; 674 } 675 close(outfile); 676 677 return 0; 678} 679 680unsigned int sansa_read_bootloader(struct sansa_t* sansa, const char* filename, unsigned char** bl_buffer) 681{ 682 /* Step 1 - read bootloader into RAM. */ 683 int infile; 684 unsigned int n; 685 unsigned int len; 686 infile=open(filename,O_RDONLY|O_BINARY); 687 if (infile < 0) { 688 fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); 689 return 0; 690 } 691 692 len = filesize(infile); 693 694 unsigned char* b = malloc(len); 695 if (b == NULL) { 696 fprintf(stderr,"[ERR] Could not allocate memory for bootloader\n"); 697 close(infile); 698 return 0; 699 } 700 701 n = read(infile,b,len); 702 close(infile); 703 if (n < len) { 704 fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n" 705 ,len,n); 706 return 0; 707 } 708 709 if (memcmp(b+0x1f8,"RBBL",4)!=0) { 710 fprintf(stderr,"[ERR] %s is not a Rockbox bootloader, aborting.\n", 711 filename); 712 return 0; 713 } 714 if (memcmp(b+0x1fc,sansa->targetname,4)!=0) { 715 fprintf(stderr,"[ERR] %s is not a Rockbox bootloader for %s, aborting.\n", 716 filename, sansa->targetname); 717 return 0; 718 } 719 *bl_buffer = b; 720 return len; 721} 722 723int sansa_add_bootloader(struct sansa_t* sansa, const unsigned char* bootloader, const unsigned int bl_length) 724{ 725 int res; 726 struct mi4header_t mi4header; 727 int length; 728 int n; 729 730 /* Create PPMI header */ 731 memset(sansa->sectorbuf,0,0x200); 732 memcpy(sansa->sectorbuf,"PPMI",4); 733 int2le(bl_length, sansa->sectorbuf+4); 734 int2le(0x00020000, sansa->sectorbuf+8); 735 736 /* copy bootloader to sansa->sectorbuf+0x200 */ 737 memcpy(sansa->sectorbuf+0x200,bootloader,bl_length); 738 739 /* Load original firmware from Sansa to the space after the bootloader */ 740 res = load_original_firmware(sansa,sansa->sectorbuf+0x200+bl_length,&mi4header); 741 if (res < 0) 742 return res; 743 744 /* Now write the whole thing back to the Sansa */ 745 746 if (sansa_seek(sansa, sansa->start+PPMI_OFFSET) < 0) { 747 fprintf(stderr,"[ERR] Seek to 0x%08"PRIx64" in add_bootloader failed.\n", 748 sansa->start+PPMI_OFFSET); 749 return -5; 750 } 751 752 length = 0x200 + bl_length + mi4header.mi4size; 753 754 n=sansa_write(sansa, length); 755 if (n < length) { 756 fprintf(stderr,"[ERR] Short write in add_bootloader\n"); 757 return -6; 758 } 759 760 return 0; 761} 762 763int sansa_delete_bootloader(struct sansa_t* sansa) 764{ 765 int res; 766 struct mi4header_t mi4header; 767 int n; 768 int length; 769 770 /* Load original firmware from Sansa to sansa->sectorbuf+0x200 */ 771 res = load_original_firmware(sansa,sansa->sectorbuf+0x200,&mi4header); 772 if (res < 0) 773 return res; 774 775 /* Create PPMI header */ 776 memset(sansa->sectorbuf,0,0x200); 777 memcpy(sansa->sectorbuf,"PPMI",4); 778 int2le(mi4header.mi4size, sansa->sectorbuf+4); 779 int2le(0x00020000, sansa->sectorbuf+8); 780 781 /* Now write the whole thing back to the Sansa */ 782 783 if (sansa_seek(sansa, sansa->start+PPMI_OFFSET) < 0) { 784 fprintf(stderr,"[ERR] Seek to 0x%08"PRIx64" in add_bootloader failed.\n", 785 sansa->start+PPMI_OFFSET); 786 return -5; 787 } 788 789 length = 0x200 + mi4header.mi4size; 790 791 n=sansa_write(sansa, length); 792 if (n < length) { 793 fprintf(stderr,"[ERR] Short write in delete_bootloader\n"); 794 return -6; 795 } 796 797 return 0; 798} 799 800/** List number of MI4 images on the player, return number. 801 */ 802int sansa_list_images(struct sansa_t* sansa) 803{ 804 struct mi4header_t mi4header; 805 loff_t ppmi_length; 806 int num = 0; 807 808 /* Check Main firmware header */ 809 if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sansa->sectorbuf, 0x200) < 0) { 810 return 0; 811 } 812 813 ppmi_length = le2int(sansa->sectorbuf+4); 814 815 printf("[INFO] Image 1 - %"PRIu64" bytes\n",ppmi_length); 816 num = 1; 817 818 /* Look for an original firmware after the first image */ 819 if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, sansa->sectorbuf, 512) < 0) { 820 return 0; 821 } 822 823 if (get_mi4header(sansa->sectorbuf,&mi4header)==0) { 824 printf("[INFO] Image 2 - %d bytes\n",mi4header.mi4size); 825 num = 2; 826 } 827 return num; 828} 829 830int sansa_update_of(struct sansa_t* sansa, const char* filename) 831{ 832 int n; 833 int infile = -1; /* Prevent an erroneous "may be used uninitialised" gcc warning */ 834 int of_length = 0; /* Keep gcc happy when building for rbutil */ 835 int ppmi_length; 836 struct mi4header_t mi4header; 837 unsigned char buf[512]; 838 839 /* Step 1 - check we have an OF on the Sansa to upgrade. We expect the 840 Rockbox bootloader to be installed and the OF to be after it on disk. */ 841 842 /* Read 512 bytes from PPMI_OFFSET - the PPMI header */ 843 if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET, 844 buf, 512) < 0) { 845 return -1; 846 } 847 848 /* No need to check PPMI magic - it's done during init to confirm 849 this is an E200 */ 850 ppmi_length = le2int(buf+4); 851 852 /* Look for an original firmware after the first image */ 853 if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200+ppmi_length, 854 buf, 512) < 0) { 855 return -1; 856 } 857 858 if (get_mi4header(buf,&mi4header)!=0) { 859 /* We don't have a valid MI4 file after a bootloader, so do nothing. */ 860 fprintf(stderr,"[ERR] No original firmware found at 0x%08"PRIx64"\n", 861 sansa->start+PPMI_OFFSET+0x200+ppmi_length); 862 return -1; 863 } 864 865 /* Step 2 - read OF into RAM. */ 866 infile=open(filename,O_RDONLY|O_BINARY); 867 if (infile < 0) { 868 fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); 869 return -1; 870 } 871 872 of_length = filesize(infile); 873 874 /* Load original firmware from file */ 875 memset(sansa->sectorbuf,0,0x200); 876 n = read(infile,sansa->sectorbuf,of_length); 877 close(infile); 878 if (n < of_length) { 879 fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n" 880 , of_length, n); 881 return -1; 882 } 883 884 /* Check we have a valid MI4 file. */ 885 if (get_mi4header(sansa->sectorbuf,&mi4header)!=0) { 886 fprintf(stderr,"[ERR] %s is not a valid mi4 file\n",filename); 887 return -1; 888 } 889 890 /* Decrypt and build the header */ 891 if(prepare_original_firmware(sansa, sansa->sectorbuf, &mi4header)!=0){ 892 fprintf(stderr,"[ERR] Unable to build decrypted mi4 from %s\n" 893 ,filename); 894 return -1; 895 } 896 897 /* Step 3 - write the OF to the Sansa */ 898 if (sansa_seek(sansa, sansa->start+PPMI_OFFSET+0x200+ppmi_length) < 0) { 899 fprintf(stderr,"[ERR] Seek to 0x%08"PRIx64" in sansa_update_of failed.\n", 900 sansa->start+PPMI_OFFSET+0x200+ppmi_length); 901 return -1; 902 } 903 904 n=sansa_write(sansa, of_length); 905 if (n < of_length) { 906 fprintf(stderr,"[ERR] Short write in sansa_update_of\n"); 907 return -1; 908 } 909 910 /* Step 4 - zero out the nvparams section - we have to do this or we end up 911 with multiple copies of the nvparams data and don't know which one to 912 work with for the database rebuild disabling trick in our bootloader */ 913 if (strcmp(sansa->targetname,"e200") == 0) { 914 printf("[INFO] Resetting Original Firmware settings\n"); 915 if (sansa_seek(sansa, sansa->start+NVPARAMS_OFFSET+0x200) < 0) { 916 fprintf(stderr,"[ERR] Seek to 0x%08"PRIx64" in sansa_update_of failed.\n", 917 sansa->start+NVPARAMS_OFFSET+0x200); 918 return -1; 919 } 920 921 memset(sansa->sectorbuf,0,NVPARAMS_SIZE); 922 n=sansa_write(sansa, NVPARAMS_SIZE); 923 if (n < NVPARAMS_SIZE) { 924 fprintf(stderr,"[ERR] Short write in sansa_update_of\n"); 925 return -1; 926 } 927 } 928 929 return 0; 930} 931 932/* Update the PPBL (bootloader) image in the hidden firmware partition */ 933int sansa_update_ppbl(struct sansa_t* sansa, const char* filename) 934{ 935 int n; 936 int infile = -1; /* Prevent an erroneous "may be used uninitialised" gcc warning */ 937 int ppbl_length = 0; /* Keep gcc happy when building for rbutil */ 938 939 /* Step 1 - read bootloader into RAM. */ 940 infile=open(filename,O_RDONLY|O_BINARY); 941 if (infile < 0) { 942 fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); 943 return -1; 944 } 945 946 ppbl_length = filesize(infile); 947 948 n = read(infile,sansa->sectorbuf+0x200,ppbl_length); 949 close(infile); 950 if (n < ppbl_length) { 951 fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", ppbl_length, n); 952 return -1; 953 } 954 955 /* Step 2 - Build the header */ 956 memset(sansa->sectorbuf,0,0x200); 957 memcpy(sansa->sectorbuf,"PPBL",4); 958 int2le(ppbl_length, sansa->sectorbuf+4); 959 int2le(0x00010000, sansa->sectorbuf+8); 960 961 /* Step 3 - write the bootloader to the Sansa */ 962 if (sansa_seek(sansa, sansa->start) < 0) { 963 fprintf(stderr,"[ERR] Seek to 0x%08"PRIx64" in sansa_update_ppbl failed.\n", sansa->start); 964 return -1; 965 } 966 967 n=sansa_write(sansa, ppbl_length + 0x200); 968 if (n < (ppbl_length+0x200)) { 969 fprintf(stderr,"[ERR] Short write in sansa_update_ppbl\n"); 970 return -1; 971 } 972 973 return 0; 974} 975