A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 867 lines 24 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * !!! DON'T MESS WITH THIS CODE UNLESS YOU'RE ABSOLUTELY SURE WHAT YOU DO !!! 11 * 12 * Copyright (C) 2020 by James Buren (refactor + H300 support) 13 * Copyright (C) 2006 by Miika Pekkarinen (original + H100/H120 support) 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License 17 * as published by the Free Software Foundation; either version 2 18 * of the License, or (at your option) any later version. 19 * 20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 * KIND, either express or implied. 22 * 23 ****************************************************************************/ 24#include "plugin.h" 25#include "lib/helper.h" 26#include "checksum.h" 27 28/* 29 * Flash commands may rely on null pointer dereferences to work correctly. 30 * Disable this feature of GCC that may interfere with proper code generation. 31 */ 32#pragma GCC optimize "no-delete-null-pointer-checks" 33 34enum firmware 35{ 36 FIRMWARE_ROCKBOX, /* all .iriver firmwares */ 37 FIRMWARE_ROMDUMP, /* a debug romdump */ 38 FIRMWARE_ORIGINAL, /* an unscrambled original firmware */ 39}; 40 41#define WORD_SIZE 2 42#define BOOT_VECTOR_SIZE 8 43#define BOOT_SECTOR_OFFSET 0 44#define FLASH_SECTOR_SIZE 4096 45#define BOOTLOADER_MAX_SIZE 65536 46#define BOOTLOADER_SECTORS (BOOTLOADER_MAX_SIZE / FLASH_SECTOR_SIZE) 47#define RAM_IMAGE_RAW_SIZE (FLASH_ROMIMAGE_ENTRY - FLASH_RAMIMAGE_ENTRY) 48#define RAM_IMAGE_MAX_SIZE (RAM_IMAGE_RAW_SIZE - sizeof(struct flash_header)) 49#define RAM_IMAGE_SECTORS (RAM_IMAGE_RAW_SIZE / FLASH_SECTOR_SIZE) 50#define ROM_IMAGE_RAW_SIZE (BOOTLOADER_ENTRYPOINT - FLASH_ROMIMAGE_ENTRY) 51#define ROM_IMAGE_MAX_SIZE (ROM_IMAGE_RAW_SIZE - sizeof(struct flash_header)) 52#define ROM_IMAGE_SECTORS (ROM_IMAGE_RAW_SIZE / FLASH_SECTOR_SIZE) 53#define ROM_IMAGE_RELOCATION (FLASH_ROMIMAGE_ENTRY + sizeof(struct flash_header)) 54#define WHOLE_FIRMWARE_SECTORS (BOOTLOADER_ENTRYPOINT / FLASH_SECTOR_SIZE) 55#define FIRMWARE_OFFSET 544 56 57#if BOOTLOADER_ENTRYPOINT + BOOTLOADER_MAX_SIZE != FLASH_SIZE 58#error "Bootloader is not located at the end of flash." 59#endif 60 61#if FLASH_ROMIMAGE_ENTRY < FLASH_RAMIMAGE_ENTRY 62#error "RAM image must be located before the ROM image." 63#endif 64 65#if BOOTLOADER_ENTRYPOINT < FLASH_ROMIMAGE_ENTRY 66#error "ROM image must be located before the bootloader." 67#endif 68 69#if FLASH_SIZE == 2048 * 1024 70#define ROMDUMP "/internal_rom_000000-1FFFFF.bin" 71#elif FLASH_SIZE == 4096 * 1024 72#define ROMDUMP "/internal_rom_000000-3FFFFF.bin" 73#endif 74 75#ifdef IRIVER_H100 76#define MODEL (const uint8_t[]) { 'h', '1', '0', '0' } 77#define ORIGINAL "/ihp_100.bin" 78#elif defined(IRIVER_H120) 79#define MODEL (const uint8_t[]) { 'h', '1', '2', '0' } 80#define ORIGINAL "/ihp_120.bin" 81#elif defined(IRIVER_H300) 82#define MODEL (const uint8_t[]) { 'h', '3', '0', '0' } 83#define ORIGINAL "/H300.bin" 84#else 85#error "Unsupported target." 86#endif 87 88struct flash_info 89{ 90 uint16_t vendor; 91 uint16_t product; 92 uint32_t size; 93 char name[16]; 94}; 95 96/* checks if the region has a valid bootloader */ 97static bool detect_valid_bootloader(const void* ptr, uint32_t size) 98{ 99 static const struct 100 { 101 uint32_t size; 102 uint32_t crc32; 103 } 104 bootloaders[] = 105 { 106#ifdef IRIVER_H100 107 { 53556, 0x76541ebd }, /* 8 */ 108#elif defined(IRIVER_H120) 109 { 53556, 0xd262b12b }, /* 8 */ 110#elif defined(IRIVER_H300) 111 { 57048, 0x59ba2459 }, /* 8 */ 112#endif 113 {0} 114 }; 115 116 for (size_t i = 0; bootloaders[i].size != 0; i++) 117 { 118 uint32_t crc32; 119 120 if (size != 0 && size != bootloaders[i].size) 121 continue; 122 123 crc32 = rb->crc_32(ptr, bootloaders[i].size, 0xFFFFFFFF); 124 if (crc32 == bootloaders[i].crc32) 125 return true; 126 } 127 128 return false; 129} 130 131/* get read-only access to flash at the given offset */ 132static const void* flash(uint32_t offset) 133{ 134 const uint16_t* FB = (uint16_t*) FLASH_BASE; 135 return &FB[offset / WORD_SIZE]; 136} 137 138/* queries the rom for information and returns it if it is known */ 139static bool flash_get_info(const struct flash_info** out_info) 140{ 141 static const struct flash_info roms[] = 142 { 143#if FLASH_SIZE == 2048 * 1024 144 { 0x00BF, 0x2782, 2048 * 1024, "SST39VF160" }, 145#elif FLASH_SIZE == 4096 * 1024 146 { 0x00BF, 0x235B, 4096 * 1024, "SST39VF3201" }, 147#else 148#error "Unsupported rom chip." 149#endif 150 {0} 151 }; 152 static struct flash_info unknown_rom = {0}; 153 volatile uint16_t* FB = (uint16_t*) FLASH_BASE; 154 uint16_t vendor; 155 uint16_t product; 156 157 /* execute the software ID entry command */ 158 FB[0x5555] = 0xAA; 159 FB[0x2AAA] = 0x55; 160 FB[0x5555] = 0x90; 161 rb->sleep(HZ / 100); 162 163 /* copy the IDs from the previous command */ 164 vendor = FB[0]; 165 product = FB[1]; 166 167 /* execute the software ID exit command */ 168 FB[0x5555] = 0xAA; 169 FB[0x2AAA] = 0x55; 170 FB[0x5555] = 0xF0; 171 rb->sleep(HZ / 100); 172 173 /* search for a known match */ 174 for (size_t i = 0; roms[i].size != 0; i++) 175 { 176 if (roms[i].vendor == vendor && roms[i].product == product) 177 { 178 *out_info = &roms[i]; 179 return true; 180 } 181 } 182 183 /* return only the vendor / product ids if unknown */ 184 unknown_rom.vendor = vendor; 185 unknown_rom.product = product; 186 *out_info = &unknown_rom; 187 return false; 188} 189 190/* wait until the rom signals completion of an operation */ 191static bool flash_wait_for_rom(uint32_t offset) 192{ 193 const size_t MAX_TIMEOUT = 0xFFFFFF; /* should be sufficient for most targets */ 194 const size_t RECOVERY_TIME = 64; /* based on 140MHz MCF 5249 */ 195 volatile uint16_t* FB = (uint16_t*) FLASH_BASE; 196 uint16_t old_data = FB[offset / WORD_SIZE] & 0x0040; /* we only want DQ6 */ 197 volatile size_t i; /* disables certain optimizations */ 198 bool result; 199 200 /* repeat up to MAX_TIMEOUT times or until DQ6 stops flipping */ 201 for (i = 0; i < MAX_TIMEOUT; i++) 202 { 203 uint16_t new_data = FB[offset / WORD_SIZE] & 0x0040; /* we only want DQ6 */ 204 if (old_data == new_data) 205 break; 206 old_data = new_data; 207 } 208 209 result = i != MAX_TIMEOUT; 210 211 /* delay at least 1us to give the bus time to recover */ 212 for (i = 0; i < RECOVERY_TIME; i++); 213 214 return result; 215} 216 217/* erase the sector at the given offset */ 218static bool flash_erase_sector(uint32_t offset) 219{ 220 volatile uint16_t* FB = (uint16_t*) FLASH_BASE; 221 222 /* execute the sector erase command */ 223 FB[0x5555] = 0xAA; 224 FB[0x2AAA] = 0x55; 225 FB[0x5555] = 0x80; 226 FB[0x5555] = 0xAA; 227 FB[0x2AAA] = 0x55; 228 FB[offset / WORD_SIZE] = 0x30; 229 230 return flash_wait_for_rom(offset); 231} 232 233/* program a word at the given offset */ 234static bool flash_program_word(uint32_t offset, uint16_t word) 235{ 236 volatile uint16_t* FB = (uint16_t*) FLASH_BASE; 237 238 /* execute the word program command */ 239 FB[0x5555] = 0xAA; 240 FB[0x2AAA] = 0x55; 241 FB[0x5555] = 0xA0; 242 FB[offset / WORD_SIZE] = word; 243 244 return flash_wait_for_rom(offset); 245} 246 247/* bulk erase of adjacent sectors */ 248static void flash_erase_sectors(uint32_t offset, uint32_t sectors, 249 bool progress) 250{ 251 for (uint32_t i = 0; i < sectors; i++) 252 { 253 flash_erase_sector(offset + i * FLASH_SECTOR_SIZE); 254 255 /* display a progress report if requested */ 256 if (progress) 257 { 258 rb->lcd_putsf(0, 3, "Erasing... %u%%", (i + 1) * 100 / sectors); 259 rb->lcd_update(); 260 } 261 } 262} 263 264/* bulk program of bytes */ 265static void flash_program_bytes(uint32_t offset, const void* ptr, 266 uint32_t len, bool progress) 267{ 268 const uint8_t* data = ptr; 269 270 for (uint32_t i = 0; i < len; i += WORD_SIZE) 271 { 272 uint32_t j = i + 1; 273 uint32_t k = ((j < len) ? j : i) + 1; 274 uint16_t word = (data[i] << 8) | (j < len ? data[j] : 0xFF); 275 276 flash_program_word(offset + i, word); 277 278 /* display a progress report if requested */ 279 if (progress && ((i % FLASH_SECTOR_SIZE) == 0 || k == len)) 280 { 281 rb->lcd_putsf(0, 4, "Programming... %u%%", k * 100 / len); 282 rb->lcd_update(); 283 } 284 } 285} 286 287/* bulk verify of programmed bytes */ 288static bool flash_verify_bytes(uint32_t offset, const void* ptr, 289 uint32_t len, bool progress) 290{ 291 const uint8_t* FB = flash(offset); 292 const uint8_t* data = ptr; 293 294 /* don't use memcmp so we can provide progress updates */ 295 for (uint32_t i = 0; i < len; i++) 296 { 297 uint32_t j = i + 1; 298 299 if (FB[i] != data[i]) 300 return false; 301 302 /* display a progress report if requested */ 303 if (progress && ((i % FLASH_SECTOR_SIZE) == 0 || j == len)) 304 { 305 rb->lcd_putsf(0, 5, "Verifying... %u%%", j * 100 / len); 306 rb->lcd_update(); 307 } 308 } 309 310 return true; 311} 312 313/* print information about the flash chip */ 314static bool show_info(void) 315{ 316 static const struct flash_info* fi = NULL; 317 318 rb->lcd_clear_display(); 319 320 if (fi == NULL) 321 flash_get_info(&fi); 322 323 rb->lcd_putsf(0, 0, "Flash: V=%04x P=%04x", fi->vendor, fi->product); 324 325 if (fi->size != 0) 326 { 327 rb->lcd_puts(0, 1, fi->name); 328 rb->lcd_putsf(0, 2, "Size: %u KB", fi->size / 1024); 329 } 330 else 331 { 332 rb->lcd_puts(0, 1, "Unknown chip"); 333 } 334 335 rb->lcd_update(); 336 337 if (fi->size == 0) 338 { 339 rb->splash(HZ * 3, "Sorry!"); 340 return false; 341 } 342 343 return true; 344} 345 346/* confirm a user's choice */ 347static bool confirm_choice(const char* msg) 348{ 349 long button; 350 rb->splashf(0, "%s ([PLAY] to CONFIRM)", msg); 351 do 352 button = rb->button_get(true); 353 while (IS_SYSEVENT(button) || (button & BUTTON_REL)); 354 show_info(); 355 return (button == BUTTON_ON); 356} 357 358/* all-in-one firmware loader */ 359static bool load_firmware(const char* filename, enum firmware firmware, 360 const void** data, size_t* data_len) 361{ 362 bool result = false; 363 const char* msg = NULL; 364 int fd = -1; 365 off_t fd_len; 366 uint8_t* buffer; 367 size_t buffer_len; 368 369 fd = rb->open(filename, O_RDONLY); 370 if (fd < 0) 371 { 372 msg = "Aborting: open failure"; 373 goto bail; 374 } 375 376 /* get file and buffer lengths and acquire the buffer */ 377 fd_len = rb->filesize(fd); 378 buffer = rb->plugin_get_audio_buffer(&buffer_len); 379 380 /* ensure there's enough space in the buffer */ 381 if ((size_t) fd_len > buffer_len) 382 { 383 msg = "Aborting: out of memory"; 384 goto bail; 385 } 386 387 /* all known firmwares are less than or equal to FLASH_SIZE */ 388 if (fd_len > FLASH_SIZE) 389 { 390 msg = "Aborting: firmware too big"; 391 goto bail; 392 } 393 394 /* rockbox firmware specific code */ 395 if (firmware == FIRMWARE_ROCKBOX) 396 { 397 uint32_t checksum; 398 uint8_t model[4]; 399 400 /* subtract the header length */ 401 fd_len -= sizeof(checksum) + sizeof(model); 402 403 /* sanity check the length */ 404 if (fd_len < WORD_SIZE) 405 { 406 msg = "Aborting: firmware too small"; 407 goto bail; 408 } 409 410 /* read the various parts */ 411 if ( 412 rb->read(fd, &checksum, sizeof(checksum)) != sizeof(checksum) || 413 rb->read(fd, model, sizeof(model)) != sizeof(model) || 414 rb->read(fd, buffer, fd_len) != fd_len 415 ) 416 { 417 msg = "Aborting: read failure"; 418 goto bail; 419 } 420 421 /* verify the checksum */ 422 if (!verify_checksum(checksum, buffer, fd_len)) 423 { 424 msg = "Aborting: checksum mismatch"; 425 goto bail; 426 } 427 428 /* verify the model */ 429 if (rb->memcmp(model, MODEL, sizeof(model)) != 0) 430 { 431 msg = "Aborting: model mismatch"; 432 goto bail; 433 } 434 } 435 436 /* romdump specific code */ 437 if (firmware == FIRMWARE_ROMDUMP) 438 { 439 /* the romdump should be exactly the same size as the flash */ 440 if (fd_len != FLASH_SIZE) 441 { 442 msg = "Aborting: firmware size incorrect"; 443 goto bail; 444 } 445 446 /* exclude boot vector and boot loader regions */ 447 fd_len = BOOTLOADER_ENTRYPOINT - BOOT_VECTOR_SIZE; 448 449 /* skip the boot vector */ 450 if (rb->lseek(fd, BOOT_VECTOR_SIZE, SEEK_SET) != BOOT_VECTOR_SIZE) 451 { 452 msg = "Aborting: lseek failure"; 453 goto bail; 454 } 455 456 /* read everything up to the boot loader */ 457 if (rb->read(fd, buffer, fd_len) != fd_len) 458 { 459 msg = "Aborting: read failure"; 460 goto bail; 461 } 462 } 463 464 /* original firmware specific code */ 465 if (firmware == FIRMWARE_ORIGINAL) 466 { 467 uint32_t boot_vector[2]; 468 469 /* subtract the offset and the size of the boot vector */ 470 fd_len -= FIRMWARE_OFFSET + sizeof(boot_vector); 471 472 /* sanity check the length */ 473 if (fd_len < WORD_SIZE) 474 { 475 msg = "Aborting: firmware too small"; 476 goto bail; 477 } 478 479 /* skip the leading bytes, whatever they are */ 480 if (rb->lseek(fd, FIRMWARE_OFFSET, SEEK_SET) != FIRMWARE_OFFSET) 481 { 482 msg = "Aborting: lseek failure"; 483 goto bail; 484 } 485 486 /* read the various parts */ 487 if ( 488 rb->read(fd, boot_vector, sizeof(boot_vector)) != sizeof(boot_vector) || 489 rb->read(fd, buffer, fd_len) != fd_len 490 ) 491 { 492 msg = "Aborting: read failure"; 493 goto bail; 494 } 495 496 /* verify the boot vector */ 497 if (boot_vector[0] != 0x10017ff0 || boot_vector[1] != 0x00000008) 498 { 499 msg = "Aborting: not an original firmware"; 500 goto bail; 501 } 502 } 503 504 /* write the resulting buffer and length in the output parameters */ 505 *data = buffer; 506 *data_len = fd_len; 507 508 /* mark success */ 509 result = true; 510 511bail: /* common exit code */ 512 if (fd >= 0) 513 rb->close(fd); 514 if (msg != NULL) 515 rb->splash(HZ * 3, msg); 516 return result; 517} 518 519/* prints fatal error if a critical failure occurs */ 520static void show_fatal_error(void) 521{ 522 rb->splash(HZ * 30, "Disable idle poweroff, connect AC power and DON'T TURN PLAYER OFF!"); 523 rb->splash(HZ * 30, "Contact Rockbox developers as soon as possible!"); 524 rb->splash(HZ * 30, "Your device won't be bricked unless you turn off the power!"); 525 rb->splash(HZ * 30, "Don't use the device before further instructions from Rockbox developers!"); 526} 527 528/* flash a bootloader */ 529static bool flash_bootloader(const char* filename) 530{ 531 bool result = false; 532 const char* msg = NULL; 533 bool show_fatal = false; 534 const void* data; 535 size_t data_len; 536 static uint8_t boot_sector[FLASH_SECTOR_SIZE]; 537 538 /* load the firmware */ 539 if (!load_firmware(filename, FIRMWARE_ROCKBOX, &data, &data_len)) 540 goto bail; 541 542 /* the bootloader can only be so big */ 543 if (data_len > BOOTLOADER_MAX_SIZE) 544 { 545 msg = "Aborting: bootloader too large"; 546 goto bail; 547 } 548 549 /* only support known bootloaders */ 550 if (!detect_valid_bootloader(data, data_len)) 551 { 552 msg = "Aborting: bootloader is invalid"; 553 goto bail; 554 } 555 556 /* ask before doing anything dangerous */ 557 if (!confirm_choice("Update bootloader?")) 558 goto bail; 559 560 /* copy the original boot sector */ 561 rb->memcpy(boot_sector, flash(BOOT_SECTOR_OFFSET), FLASH_SECTOR_SIZE); 562 563 /* update the boot vector */ 564 rb->memcpy(boot_sector, data, BOOT_VECTOR_SIZE); 565 566 /* erase the boot sector */ 567 flash_erase_sector(BOOT_SECTOR_OFFSET); 568 569 /* erase the bootloader sectors */ 570 flash_erase_sectors(BOOTLOADER_ENTRYPOINT, BOOTLOADER_SECTORS, false); 571 572 /* program the new boot sector */ 573 flash_program_bytes(BOOT_SECTOR_OFFSET, boot_sector, FLASH_SECTOR_SIZE, false); 574 575 /* program the new bootloader */ 576 flash_program_bytes(BOOTLOADER_ENTRYPOINT, data, data_len, false); 577 578 /* verify the new boot sector */ 579 if (!flash_verify_bytes(BOOT_SECTOR_OFFSET, boot_sector, FLASH_SECTOR_SIZE, false)) 580 { 581 msg = "Boot sector corrupt!"; 582 show_fatal = true; 583 goto bail; 584 } 585 586 /* verify the new bootloader */ 587 if (!flash_verify_bytes(BOOTLOADER_ENTRYPOINT, data, data_len, false)) 588 { 589 msg = "Verify failed!"; 590 show_fatal = true; 591 goto bail; 592 } 593 594 /* report success */ 595 rb->splash(HZ * 3, "Success!"); 596 597 /* mark success */ 598 result = true; 599 600bail: /* common exit code */ 601 if (msg != NULL) 602 rb->splash(HZ * 3, msg); 603 if (show_fatal) 604 show_fatal_error(); 605 return result; 606} 607 608/* flash a rockbox ram / rom image */ 609static bool flash_rockbox(const char* filename, uint32_t offset) 610{ 611 bool result = false; 612 const char* msg = NULL; 613 const void* data; 614 size_t data_len; 615 struct flash_header header; 616 617 /* load the firmware */ 618 if (!load_firmware(filename, FIRMWARE_ROCKBOX, &data, &data_len)) 619 goto bail; 620 621 /* sanity check that the offset was set correctly */ 622 if (offset != FLASH_RAMIMAGE_ENTRY && offset != FLASH_ROMIMAGE_ENTRY) 623 { 624 msg = "Aborting: invalid image offset"; 625 goto bail; 626 } 627 628 /* ensure there's enough room for the ram / rom image */ 629 if ( 630 (offset == FLASH_RAMIMAGE_ENTRY && data_len > RAM_IMAGE_MAX_SIZE) || 631 (offset == FLASH_ROMIMAGE_ENTRY && data_len > ROM_IMAGE_MAX_SIZE) 632 ) 633 { 634 msg = "Aborting: ram / rom image too large"; 635 goto bail; 636 } 637 638 /* check for bootloader that can load rockbox from ram / rom */ 639 if (!detect_valid_bootloader(flash(BOOTLOADER_ENTRYPOINT), 0)) 640 { 641 msg = "Aborting: incompatible bootloader"; 642 goto bail; 643 } 644 645 /* rom image specific checks */ 646 if (offset == FLASH_ROMIMAGE_ENTRY) 647 { 648 uint32_t relocation = *((const uint32_t*) data); 649 650 /* sanity check of the image relocation */ 651 if (relocation != ROM_IMAGE_RELOCATION) 652 { 653 msg = "Aborting: invalid image relocation"; 654 goto bail; 655 } 656 } 657 658 /* ask before doing anything dangerous */ 659 if (!rb->detect_original_firmware()) 660 { 661 if (!confirm_choice("Update Rockbox flash image?")) 662 goto bail; 663 } 664 else 665 { 666 if (!confirm_choice("Erase original firmware?")) 667 goto bail; 668 } 669 670 /* erase all ram / rom image sectors */ 671 if (offset == FLASH_RAMIMAGE_ENTRY) 672 flash_erase_sectors(offset, RAM_IMAGE_SECTORS, true); 673 else if (offset == FLASH_ROMIMAGE_ENTRY) 674 flash_erase_sectors(offset, ROM_IMAGE_SECTORS, true); 675 676 /* prepare the header */ 677 header.magic = FLASH_MAGIC; 678 header.length = data_len; 679 rb->memset(&header.version, 0x00, sizeof(header.version)); 680 681 /* program the header */ 682 flash_program_bytes(offset, &header, sizeof(header), false); 683 684 /* program the ram / rom image */ 685 flash_program_bytes(offset + sizeof(header), data, data_len, true); 686 687 /* verify the header and ram / rom image */ 688 if ( 689 !flash_verify_bytes(offset, &header, sizeof(header), false) || 690 !flash_verify_bytes(offset + sizeof(header), data, data_len, true) 691 ) 692 { 693 msg = "Verify failed!"; 694 /* 695 * erase the ram / rom image header to prevent the bootloader 696 * from trying to boot from it 697 */ 698 flash_erase_sector(offset); 699 goto bail; 700 } 701 702 /* report success */ 703 rb->splash(HZ * 3, "Success!"); 704 705 /* mark success */ 706 result = true; 707 708bail: /* common exit code */ 709 if (msg != NULL) 710 rb->splash(HZ * 3, msg); 711 return result; 712} 713 714/* flash whole firmware; common code for romdump / original */ 715static bool flash_whole_firmware(const void* data, size_t data_len) 716{ 717 bool result = false; 718 const char* msg = NULL; 719 bool show_fatal = false; 720 uint8_t boot_vector[BOOT_VECTOR_SIZE]; 721 722 /* copy the original boot vector */ 723 rb->memcpy(boot_vector, flash(BOOT_SECTOR_OFFSET), BOOT_VECTOR_SIZE); 724 725 /* erase everything except the bootloader */ 726 flash_erase_sectors(BOOT_SECTOR_OFFSET, WHOLE_FIRMWARE_SECTORS, true); 727 728 /* program the original boot vector */ 729 flash_program_bytes(BOOT_SECTOR_OFFSET, boot_vector, BOOT_VECTOR_SIZE, false); 730 731 /* program the whole firmware */ 732 flash_program_bytes(BOOT_SECTOR_OFFSET + BOOT_VECTOR_SIZE, data, data_len, true); 733 734 /* verify the new boot vector */ 735 if (!flash_verify_bytes(BOOT_SECTOR_OFFSET, boot_vector, BOOT_VECTOR_SIZE, false)) 736 { 737 msg = "Boot vector corrupt!"; 738 show_fatal = true; 739 goto bail; 740 } 741 742 /* verify the new firmware */ 743 if (!flash_verify_bytes(BOOT_SECTOR_OFFSET + BOOT_VECTOR_SIZE, data, data_len, true)) 744 { 745 msg = "Verify failed!"; 746 goto bail; 747 } 748 749 /* report success */ 750 rb->splash(HZ * 3, "Success!"); 751 752 /* mark success */ 753 result = true; 754 755bail: /* common exit code */ 756 if (msg != NULL) 757 rb->splash(HZ * 3, msg); 758 if (show_fatal) 759 show_fatal_error(); 760 return result; 761} 762 763/* flash rom dumps */ 764static bool flash_romdump(const char* filename) 765{ 766 const void* data; 767 size_t data_len; 768 769 /* load the firmware */ 770 if (!load_firmware(filename, FIRMWARE_ROMDUMP, &data, &data_len)) 771 return false; 772 773 /* ask before doing anything dangerous */ 774 if (!confirm_choice("Restore firmware section (bootloader will be kept)?")) 775 return false; 776 777 return flash_whole_firmware(data, data_len); 778} 779 780/* flash original firmware */ 781static bool flash_original(const char* filename) 782{ 783 const void* data; 784 size_t data_len; 785 786 /* load the firmware */ 787 if (!load_firmware(filename, FIRMWARE_ORIGINAL, &data, &data_len)) 788 return false; 789 790 /* ask before doing anything dangerous */ 791 if (!confirm_choice("Restore original firmware (bootloader will be kept)?")) 792 return false; 793 794 return flash_whole_firmware(data, data_len); 795} 796 797/* main function of plugin */ 798static void iriver_flash(const char* filename) 799{ 800 /* refuse to run from ROM */ 801 const uint8_t* RB = (uint8_t*) rb; 802 const uint8_t* FB = (uint8_t*) flash(0); 803 if (RB >= FB && RB < FB + FLASH_SIZE) 804 { 805 rb->splash(HZ * 3, "Refusing to run from ROM"); 806 return; 807 } 808 809 /* refuse to run with low battery */ 810 if (!rb->battery_level_safe()) 811 { 812 rb->splash(HZ * 3, "Refusing to run with low battery"); 813 return; 814 } 815 816 /* print information about flash; exit if not supported */ 817 if (!show_info()) 818 return; 819 820 /* exit if no filename was provided */ 821 if (filename == NULL) 822 { 823 rb->splash(HZ * 3, "Please use this plugin with \"Open with...\""); 824 return; 825 } 826 827 /* choose what to do with the file */ 828 if (rb->strcasestr(filename, "/bootloader.iriver") != NULL) 829 flash_bootloader(filename); 830 else if (rb->strcasestr(filename, "/rockbox.iriver") != NULL) 831 flash_rockbox(filename, FLASH_RAMIMAGE_ENTRY); 832 else if (rb->strcasestr(filename, "/rombox.iriver") != NULL) 833 flash_rockbox(filename, FLASH_ROMIMAGE_ENTRY); 834 else if (rb->strcasestr(filename, ROMDUMP) != NULL) 835 flash_romdump(filename); 836 else if (rb->strcasestr(filename, ORIGINAL) != NULL) 837 flash_original(filename); 838 else 839 rb->splash(HZ * 3, "Unknown file type"); 840} 841 842/* plugin entry point */ 843enum plugin_status plugin_start(const void* parameter) 844{ 845 /* need to disable memguard to write to flash */ 846 int mode = rb->system_memory_guard(MEMGUARD_NONE); 847 848 /* setup LCD font */ 849 rb->lcd_setfont(FONT_SYSFIXED); 850 851 /* don't let the backlight turn off or it might scare people */ 852 backlight_ignore_timeout(); 853 854 /* run the main entry function */ 855 iriver_flash(parameter); 856 857 /* restore the original backlight settings */ 858 backlight_use_settings(); 859 860 /* restore LCD font */ 861 rb->lcd_setfont(FONT_UI); 862 863 /* restore original memory guard setting */ 864 rb->system_memory_guard(mode); 865 866 return PLUGIN_OK; 867}