summaryrefslogtreecommitdiff
path: root/apps/plugins/iriver_flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/iriver_flash.c')
-rw-r--r--apps/plugins/iriver_flash.c93
1 files changed, 67 insertions, 26 deletions
diff --git a/apps/plugins/iriver_flash.c b/apps/plugins/iriver_flash.c
index 590622f6d2..44bd9c7f66 100644
--- a/apps/plugins/iriver_flash.c
+++ b/apps/plugins/iriver_flash.c
@@ -59,6 +59,10 @@ static struct plugin_api* rb; /* here is a global api struct pointer */
59#ifdef IRIVER_H100_SERIES 59#ifdef IRIVER_H100_SERIES
60#define SEC_SIZE 4096 60#define SEC_SIZE 4096
61#define BOOTLOADER_ERASEGUARD (BOOTLOADER_ENTRYPOINT / SEC_SIZE) 61#define BOOTLOADER_ERASEGUARD (BOOTLOADER_ENTRYPOINT / SEC_SIZE)
62enum sections {
63 SECT_RAMIMAGE = 1,
64 SECT_ROMIMAGE = 2,
65};
62 66
63static volatile uint16_t* FB = (uint16_t*)0x00000000; /* Flash base address */ 67static volatile uint16_t* FB = (uint16_t*)0x00000000; /* Flash base address */
64#endif 68#endif
@@ -338,23 +342,9 @@ int load_firmware_file(const char *filename, uint32_t *checksum)
338 return len; 342 return len;
339} 343}
340 344
341bool detect_flashed_rockbox(void)
342{
343 struct flash_header hdr;
344 uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT;
345
346 rb->memcpy(&hdr, src, sizeof(struct flash_header));
347
348 if (hdr.magic != FLASH_MAGIC)
349 return false;
350
351 return true;
352}
353
354unsigned long valid_bootloaders[][2] = { 345unsigned long valid_bootloaders[][2] = {
355 /* Size-8 CRC32 */ 346 /* Size-8 CRC32 */
356 { 62332, 0x77395351 }, /* Pre-release v7 */ 347 { 63844, 0x98c5027a }, /* 7-pre3, improved failsafe functions */
357 { 63340, 0xc41857b6 }, /* Pre-release v7, fixed crash unless firmware found. */
358 { 0, 0 } 348 { 0, 0 }
359}; 349};
360 350
@@ -378,15 +368,28 @@ bool detect_valid_bootloader(const unsigned char *addr, int len)
378 return false; 368 return false;
379} 369}
380 370
381int flash_rockbox(const char *filename) 371static int get_section_address(int section)
372{
373 if (section == SECT_RAMIMAGE)
374 return FLASH_RAMIMAGE_ENTRY;
375 else if (section == SECT_ROMIMAGE)
376 return FLASH_ROMIMAGE_ENTRY;
377 else
378 return -1;
379}
380
381int flash_rockbox(const char *filename, int section)
382{ 382{
383 struct flash_header hdr; 383 struct flash_header hdr;
384 char buf[32]; 384 char buf[64];
385 int pos, i, len, rc; 385 int pos, i, len, rc;
386 unsigned long checksum, sum; 386 unsigned long checksum, sum;
387 unsigned char *p8; 387 unsigned char *p8;
388 uint16_t *p16; 388 uint16_t *p16;
389 389
390 if (get_section_address(section) < 0)
391 return -1;
392
390 p8 = (char *)BOOTLOADER_ENTRYPOINT; 393 p8 = (char *)BOOTLOADER_ENTRYPOINT;
391 if (!detect_valid_bootloader(p8, 0)) 394 if (!detect_valid_bootloader(p8, 0))
392 { 395 {
@@ -394,7 +397,7 @@ int flash_rockbox(const char *filename)
394 return -1; 397 return -1;
395 } 398 }
396 399
397 if (detect_flashed_rockbox()) 400 if (!rb->detect_original_firmware())
398 { 401 {
399 if (!confirm("Update Rockbox flash image?")) 402 if (!confirm("Update Rockbox flash image?"))
400 return -2; 403 return -2;
@@ -409,13 +412,36 @@ int flash_rockbox(const char *filename)
409 if (len <= 0) 412 if (len <= 0)
410 return len * 10; 413 return len * 10;
411 414
415 pos = get_section_address(section);
416
417 /* Check if image relocation seems to be sane. */
418 if (section == SECT_ROMIMAGE)
419 {
420 uint32_t *p32 = (uint32_t *)audiobuf;
421
422 if (pos+sizeof(struct flash_header) != *p32)
423 {
424 rb->snprintf(buf, sizeof(buf), "Incorrect relocation: 0x%08x/0x%08x",
425 *p32, pos+sizeof(struct flash_header));
426 rb->splash(HZ*10, true, buf);
427 return -1;
428 }
429
430 }
431
412 /* Erase the program flash. */ 432 /* Erase the program flash. */
413 for (i = 1; i < BOOTLOADER_ERASEGUARD && (i-1)*4096 < len + 32; i++) 433 for (i = 0; i + pos < BOOTLOADER_ENTRYPOINT && i < len + 32; i += SEC_SIZE)
414 { 434 {
415 rc = cfi_erase_sector(FB + (SEC_SIZE/2) * i); 435 /* Additional safety check. */
416 rb->snprintf(buf, sizeof(buf), "Erase: 0x%03x (%d)", i, rc); 436 if (i + pos < SEC_SIZE)
437 return -1;
438
439 rb->snprintf(buf, sizeof(buf), "Erasing... %d%%",
440 (i+SEC_SIZE)*100/len);
417 rb->lcd_puts(0, 3, buf); 441 rb->lcd_puts(0, 3, buf);
418 rb->lcd_update(); 442 rb->lcd_update();
443
444 rc = cfi_erase_sector(FB + (i + pos)/2);
419 } 445 }
420 446
421 /* Write the magic and size. */ 447 /* Write the magic and size. */
@@ -425,11 +451,11 @@ int flash_rockbox(const char *filename)
425 // rb->strncpy(hdr.version, APPSVERSION, sizeof(hdr.version)-1); 451 // rb->strncpy(hdr.version, APPSVERSION, sizeof(hdr.version)-1);
426 p16 = (uint16_t *)&hdr; 452 p16 = (uint16_t *)&hdr;
427 453
428 rb->snprintf(buf, sizeof(buf), "Programming"); 454 rb->snprintf(buf, sizeof(buf), "Programming...");
429 rb->lcd_puts(0, 4, buf); 455 rb->lcd_puts(0, 4, buf);
430 rb->lcd_update(); 456 rb->lcd_update();
431 457
432 pos = FLASH_ENTRYPOINT/2; 458 pos = get_section_address(section)/2;
433 for (i = 0; i < (long)sizeof(struct flash_header)/2; i++) 459 for (i = 0; i < (long)sizeof(struct flash_header)/2; i++)
434 { 460 {
435 cfi_program_word(FB + pos, p16[i]); 461 cfi_program_word(FB + pos, p16[i]);
@@ -438,14 +464,24 @@ int flash_rockbox(const char *filename)
438 464
439 p16 = (uint16_t *)audiobuf; 465 p16 = (uint16_t *)audiobuf;
440 for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++) 466 for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++)
467 {
468 if (i % SEC_SIZE == 0)
469 {
470 rb->snprintf(buf, sizeof(buf), "Programming... %d%%",
471 (i+1)*100/(len/2));
472 rb->lcd_puts(0, 4, buf);
473 rb->lcd_update();
474 }
475
441 cfi_program_word(FB + pos + i, p16[i]); 476 cfi_program_word(FB + pos + i, p16[i]);
477 }
442 478
443 /* Verify */ 479 /* Verify */
444 rb->snprintf(buf, sizeof(buf), "Verifying"); 480 rb->snprintf(buf, sizeof(buf), "Verifying");
445 rb->lcd_puts(0, 5, buf); 481 rb->lcd_puts(0, 5, buf);
446 rb->lcd_update(); 482 rb->lcd_update();
447 483
448 p8 = (char *)FLASH_ENTRYPOINT; 484 p8 = (char *)get_section_address(section);
449 p8 += sizeof(struct flash_header); 485 p8 += sizeof(struct flash_header);
450 sum = 0; 486 sum = 0;
451 for (i = 0; i < len; i++) 487 for (i = 0; i < len; i++)
@@ -456,7 +492,10 @@ int flash_rockbox(const char *filename)
456 rb->splash(HZ*3, true, "Verify failed!"); 492 rb->splash(HZ*3, true, "Verify failed!");
457 /* Erase the magic sector so bootloader does not try to load 493 /* Erase the magic sector so bootloader does not try to load
458 * rockbox from flash and crash. */ 494 * rockbox from flash and crash. */
459 cfi_erase_sector(FB + SEC_SIZE/2); 495 if (section == SECT_RAMIMAGE)
496 cfi_erase_sector(FB + FLASH_RAMIMAGE_ENTRY/2);
497 else
498 cfi_erase_sector(FB + FLASH_ROMIMAGE_ENTRY/2);
460 return -5; 499 return -5;
461 } 500 }
462 501
@@ -741,7 +780,9 @@ void DoUserDialog(char* filename)
741 audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size); 780 audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size);
742 781
743 if (rb->strcasestr(filename, "/rockbox.iriver")) 782 if (rb->strcasestr(filename, "/rockbox.iriver"))
744 flash_rockbox(filename); 783 flash_rockbox(filename, SECT_RAMIMAGE);
784 else if (rb->strcasestr(filename, "/rombox.iriver"))
785 flash_rockbox(filename, SECT_ROMIMAGE);
745 else if (rb->strcasestr(filename, "/bootloader.iriver")) 786 else if (rb->strcasestr(filename, "/bootloader.iriver"))
746 flash_bootloader(filename); 787 flash_bootloader(filename);
747 else if (rb->strcasestr(filename, "/ihp_120.bin")) 788 else if (rb->strcasestr(filename, "/ihp_120.bin"))