diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2007-01-12 18:34:00 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2007-01-12 18:34:00 +0000 |
commit | 0ea4d3197ed7e56f39c630741cb69152ac9e41de (patch) | |
tree | bc29ccef30da139df3e928fd3b8ff3801407b58c /apps/plugins | |
parent | 12ef310466937551dbedb2165769d7832b11156c (diff) | |
download | rockbox-0ea4d3197ed7e56f39c630741cb69152ac9e41de.tar.gz rockbox-0ea4d3197ed7e56f39c630741cb69152ac9e41de.zip |
Prepare core support for the iriver bootloader supporting ROM images
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11991 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/iriver_flash.c | 93 |
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) |
62 | enum sections { | ||
63 | SECT_RAMIMAGE = 1, | ||
64 | SECT_ROMIMAGE = 2, | ||
65 | }; | ||
62 | 66 | ||
63 | static volatile uint16_t* FB = (uint16_t*)0x00000000; /* Flash base address */ | 67 | static 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 | ||
341 | bool 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 | |||
354 | unsigned long valid_bootloaders[][2] = { | 345 | unsigned 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 | ||
381 | int flash_rockbox(const char *filename) | 371 | static 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 | |||
381 | int 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")) |