diff --git a/apps/plugin.c b/apps/plugin.c index c2b697fe0b..250b4cc545 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -487,6 +487,13 @@ static const struct plugin_api rockbox_api = { pcm_record_more, #endif create_thread_on_core, + +#ifdef IRIVER_H100_SERIES + /* Routines for the iriver_flash -plugin. */ + detect_original_firmware, + detect_flashed_ramimage, + detect_flashed_romimage, +#endif }; int plugin_load(const char* plugin, void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index 16781de0c1..b2d894f0ee 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -602,11 +602,18 @@ struct plugin_api { int (*sound_default)(int setting); void (*pcm_record_more)(void *start, size_t size); #endif - + struct thread_entry*(*create_thread_on_core)( unsigned int core, void (*function)(void), void* stack, int stack_size, const char *name IF_PRIO(, int priority)); + +#ifdef IRIVER_H100_SERIES + /* Routines for the iriver_flash -plugin. */ + bool (*detect_original_firmware)(void); + bool (*detect_flashed_ramimage)(void); + bool (*detect_flashed_romimage)(void); +#endif }; /* plugin header */ 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 */ #ifdef IRIVER_H100_SERIES #define SEC_SIZE 4096 #define BOOTLOADER_ERASEGUARD (BOOTLOADER_ENTRYPOINT / SEC_SIZE) +enum sections { + SECT_RAMIMAGE = 1, + SECT_ROMIMAGE = 2, +}; static volatile uint16_t* FB = (uint16_t*)0x00000000; /* Flash base address */ #endif @@ -338,23 +342,9 @@ int load_firmware_file(const char *filename, uint32_t *checksum) return len; } -bool detect_flashed_rockbox(void) -{ - struct flash_header hdr; - uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT; - - rb->memcpy(&hdr, src, sizeof(struct flash_header)); - - if (hdr.magic != FLASH_MAGIC) - return false; - - return true; -} - unsigned long valid_bootloaders[][2] = { /* Size-8 CRC32 */ - { 62332, 0x77395351 }, /* Pre-release v7 */ - { 63340, 0xc41857b6 }, /* Pre-release v7, fixed crash unless firmware found. */ + { 63844, 0x98c5027a }, /* 7-pre3, improved failsafe functions */ { 0, 0 } }; @@ -378,15 +368,28 @@ bool detect_valid_bootloader(const unsigned char *addr, int len) return false; } -int flash_rockbox(const char *filename) +static int get_section_address(int section) +{ + if (section == SECT_RAMIMAGE) + return FLASH_RAMIMAGE_ENTRY; + else if (section == SECT_ROMIMAGE) + return FLASH_ROMIMAGE_ENTRY; + else + return -1; +} + +int flash_rockbox(const char *filename, int section) { struct flash_header hdr; - char buf[32]; + char buf[64]; int pos, i, len, rc; unsigned long checksum, sum; unsigned char *p8; uint16_t *p16; + if (get_section_address(section) < 0) + return -1; + p8 = (char *)BOOTLOADER_ENTRYPOINT; if (!detect_valid_bootloader(p8, 0)) { @@ -394,7 +397,7 @@ int flash_rockbox(const char *filename) return -1; } - if (detect_flashed_rockbox()) + if (!rb->detect_original_firmware()) { if (!confirm("Update Rockbox flash image?")) return -2; @@ -409,13 +412,36 @@ int flash_rockbox(const char *filename) if (len <= 0) return len * 10; - /* Erase the program flash. */ - for (i = 1; i < BOOTLOADER_ERASEGUARD && (i-1)*4096 < len + 32; i++) + pos = get_section_address(section); + + /* Check if image relocation seems to be sane. */ + if (section == SECT_ROMIMAGE) { - rc = cfi_erase_sector(FB + (SEC_SIZE/2) * i); - rb->snprintf(buf, sizeof(buf), "Erase: 0x%03x (%d)", i, rc); + uint32_t *p32 = (uint32_t *)audiobuf; + + if (pos+sizeof(struct flash_header) != *p32) + { + rb->snprintf(buf, sizeof(buf), "Incorrect relocation: 0x%08x/0x%08x", + *p32, pos+sizeof(struct flash_header)); + rb->splash(HZ*10, true, buf); + return -1; + } + + } + + /* Erase the program flash. */ + for (i = 0; i + pos < BOOTLOADER_ENTRYPOINT && i < len + 32; i += SEC_SIZE) + { + /* Additional safety check. */ + if (i + pos < SEC_SIZE) + return -1; + + rb->snprintf(buf, sizeof(buf), "Erasing... %d%%", + (i+SEC_SIZE)*100/len); rb->lcd_puts(0, 3, buf); rb->lcd_update(); + + rc = cfi_erase_sector(FB + (i + pos)/2); } /* Write the magic and size. */ @@ -425,11 +451,11 @@ int flash_rockbox(const char *filename) // rb->strncpy(hdr.version, APPSVERSION, sizeof(hdr.version)-1); p16 = (uint16_t *)&hdr; - rb->snprintf(buf, sizeof(buf), "Programming"); + rb->snprintf(buf, sizeof(buf), "Programming..."); rb->lcd_puts(0, 4, buf); rb->lcd_update(); - pos = FLASH_ENTRYPOINT/2; + pos = get_section_address(section)/2; for (i = 0; i < (long)sizeof(struct flash_header)/2; i++) { cfi_program_word(FB + pos, p16[i]); @@ -438,14 +464,24 @@ int flash_rockbox(const char *filename) p16 = (uint16_t *)audiobuf; for (i = 0; i < len/2 && pos + i < (BOOTLOADER_ENTRYPOINT/2); i++) + { + if (i % SEC_SIZE == 0) + { + rb->snprintf(buf, sizeof(buf), "Programming... %d%%", + (i+1)*100/(len/2)); + rb->lcd_puts(0, 4, buf); + rb->lcd_update(); + } + cfi_program_word(FB + pos + i, p16[i]); + } /* Verify */ rb->snprintf(buf, sizeof(buf), "Verifying"); rb->lcd_puts(0, 5, buf); rb->lcd_update(); - p8 = (char *)FLASH_ENTRYPOINT; + p8 = (char *)get_section_address(section); p8 += sizeof(struct flash_header); sum = 0; for (i = 0; i < len; i++) @@ -456,7 +492,10 @@ int flash_rockbox(const char *filename) rb->splash(HZ*3, true, "Verify failed!"); /* Erase the magic sector so bootloader does not try to load * rockbox from flash and crash. */ - cfi_erase_sector(FB + SEC_SIZE/2); + if (section == SECT_RAMIMAGE) + cfi_erase_sector(FB + FLASH_RAMIMAGE_ENTRY/2); + else + cfi_erase_sector(FB + FLASH_ROMIMAGE_ENTRY/2); return -5; } @@ -741,7 +780,9 @@ void DoUserDialog(char* filename) audiobuf = rb->plugin_get_audio_buffer(&audiobuf_size); if (rb->strcasestr(filename, "/rockbox.iriver")) - flash_rockbox(filename); + flash_rockbox(filename, SECT_RAMIMAGE); + else if (rb->strcasestr(filename, "/rombox.iriver")) + flash_rockbox(filename, SECT_ROMIMAGE); else if (rb->strcasestr(filename, "/bootloader.iriver")) flash_bootloader(filename); else if (rb->strcasestr(filename, "/ihp_120.bin")) diff --git a/firmware/eeprom_settings.c b/firmware/eeprom_settings.c index ad2c9c848f..f3be2ec2b3 100644 --- a/firmware/eeprom_settings.c +++ b/firmware/eeprom_settings.c @@ -36,7 +36,7 @@ static bool reset_config(void) #else firmware_settings.version = EEPROM_SETTINGS_VERSION; firmware_settings.initialized = true; - firmware_settings.boot_disk = false; + firmware_settings.bootmethod = BOOT_RECOVERY; firmware_settings.bl_version = 0; #endif @@ -51,7 +51,7 @@ bool eeprom_settings_init(void) eeprom_24cxx_init(); /* Check if player has been flashed. */ - if (!detect_flashed_rockbox()) + if (detect_original_firmware()) { memset(&firmware_settings, 0, sizeof(struct eeprom_settings)); firmware_settings.initialized = false; @@ -61,7 +61,7 @@ bool eeprom_settings_init(void) ret = eeprom_24cxx_read(0, &firmware_settings, sizeof(struct eeprom_settings)); - + if (ret < 0) { memset(&firmware_settings, 0, sizeof(struct eeprom_settings)); @@ -101,7 +101,7 @@ bool eeprom_settings_store(void) int ret; uint32_t sum; - if (!firmware_settings.initialized || !detect_flashed_rockbox()) + if (!firmware_settings.initialized || detect_original_firmware()) { logf("Rockbox in flash is required"); return false; diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h index ee3d70236a..9bfb9583dd 100644 --- a/firmware/export/config-h120.h +++ b/firmware/export/config-h120.h @@ -139,8 +139,9 @@ #define BOOTFILE "rockbox." BOOTFILE_EXT #define BOOTLOADER_ENTRYPOINT 0x001F0000 -#define FLASH_ENTRYPOINT 0x00001000 -#define FLASH_MAGIC 0xfbfbfbf1 +#define FLASH_RAMIMAGE_ENTRY 0x00001000 +#define FLASH_ROMIMAGE_ENTRY 0x00100000 +#define FLASH_MAGIC 0xfbfbfbf2 /* Define this if there is an EEPROM chip */ #define HAVE_EEPROM diff --git a/firmware/export/eeprom_settings.h b/firmware/export/eeprom_settings.h index 367e7b24e9..aade86bc0d 100644 --- a/firmware/export/eeprom_settings.h +++ b/firmware/export/eeprom_settings.h @@ -23,17 +23,26 @@ #include #include "inttypes.h" -#define EEPROM_SETTINGS_VERSION 0x24c01001 +#define EEPROM_SETTINGS_VERSION 0x24c01002 #define EEPROM_SETTINGS_BL_MINVER 7 +enum boot_methods { + BOOT_DISK = 0, + BOOT_RAM, + BOOT_ROM, + BOOT_RECOVERY, +}; + struct eeprom_settings { long version; /* Settings version number */ bool initialized; /* Is eeprom_settings ready to be used */ bool disk_clean; /* Is disk intact from last reboot */ - bool boot_disk; /* Load firmware from disk (default=FLASH) */ + uint8_t bootmethod; /* The default boot method. */ uint8_t bl_version; /* Installed bootloader version */ + long reserved; /* A few reserved bits for the future. */ + /* This must be the last entry */ uint32_t checksum; /* Checksum of this structure */ }; diff --git a/firmware/export/system.h b/firmware/export/system.h index 94922871b6..86bbefb28f 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h @@ -52,7 +52,9 @@ struct flash_header { char version[32]; }; -bool detect_flashed_rockbox(void); +bool detect_flashed_romimage(void); +bool detect_flashed_ramimage(void); +bool detect_original_firmware(void); #ifdef HAVE_ADJUSTABLE_CPU_FREQ #define FREQ cpu_frequency diff --git a/firmware/system.c b/firmware/system.c index 4ab47fac1f..c9ce086f0a 100644 --- a/firmware/system.c +++ b/firmware/system.c @@ -82,31 +82,44 @@ void cpu_idle_mode(bool on_off) #endif /* HAVE_ADJUSTABLE_CPU_FREQ */ -bool detect_flashed_rockbox(void) -{ #ifdef HAVE_FLASHED_ROCKBOX - struct flash_header hdr; - uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT; - +static bool detect_flash_header(uint8_t *addr) +{ #ifndef BOOTLOADER int oldmode = system_memory_guard(MEMGUARD_NONE); #endif - - memcpy(&hdr, src, sizeof(struct flash_header)); - + struct flash_header hdr; + memcpy(&hdr, addr, sizeof(struct flash_header)); #ifndef BOOTLOADER system_memory_guard(oldmode); +#endif + return hdr.magic == FLASH_MAGIC; +} #endif - if (hdr.magic != FLASH_MAGIC) - return false; - - return true; +bool detect_flashed_romimage(void) +{ +#ifdef HAVE_FLASHED_ROCKBOX + return detect_flash_header((uint8_t *)FLASH_ROMIMAGE_ENTRY); #else return false; #endif /* HAVE_FLASHED_ROCKBOX */ } +bool detect_flashed_ramimage(void) +{ +#ifdef HAVE_FLASHED_ROCKBOX + return detect_flash_header((uint8_t *)FLASH_RAMIMAGE_ENTRY); +#else + return false; +#endif /* HAVE_FLASHED_ROCKBOX */ +} + +bool detect_original_firmware(void) +{ + return !(detect_flashed_ramimage() || detect_flashed_romimage()); +} + #if CONFIG_CPU == SH7034 #include "led.h" #include "system.h" diff --git a/firmware/target/coldfire/crt0.S b/firmware/target/coldfire/crt0.S index 7fc389c23d..c177cd4e27 100644 --- a/firmware/target/coldfire/crt0.S +++ b/firmware/target/coldfire/crt0.S @@ -89,28 +89,40 @@ start: #endif #ifdef BOOTLOADER - /* Check if original firmware is still present */ + /* Check if we have a Rockbox ROM image */ + lea 0x00100000,%a2 + move.l (%a2),%d0 + move.l #FLASH_MAGIC,%d1 + cmp.l %d0,%d1 + beq.b .imagefound + + /* Check for RAM image */ lea 0x00001000,%a2 move.l (%a2),%d0 - move.l #0xfbfbfbf1,%d1 + move.l #FLASH_MAGIC,%d1 cmp.l %d0,%d1 - beq.b .ignorecookie + beq.b .imagefound - /* The cookie is not reset. This must mean that the boot loader - has crashed. Let's start the original firmware immediately. */ + /* Not either ROM or RAM image was found, so original firmware + should be still present. */ + + /* Check if the cookie is present. */ lea 0x10017ffc,%a2 move.l (%a2),%d0 move.l #0xc0015a17,%d1 cmp.l %d0,%d1 bne.b .nocookie - /* Clear the cookie again */ + + /* The cookie is not reset. This must mean that the boot loader + has crashed. Let's start the original firmware immediately. */ + lea 0x10017ffc,%a2 clr.l (%a2) jmp 8 .nocookie: /* Set the cookie */ move.l %d1,(%a2) -.ignorecookie: +.imagefound: /* Set up the DRAM controller. The refresh is based on the 11.2896MHz clock (5.6448MHz bus frequency). We haven't yet started the PLL */ @@ -168,6 +180,38 @@ start: move.l %d0,0x31000800 /* A12=1 means CASL=1 (a0 is not connected) */ /* DACR0[IMRS] gets deactivated by the SDRAM controller */ + + /* Check if we have a Rockbox ROM image. For RAM image only cookie is + not set at all. But we could support also RAM images loading. */ + lea 0x00100000,%a2 + move.l (%a2),%d0 + move.l #FLASH_MAGIC,%d1 + cmp.l %d0,%d1 + bne.b .noromimage + + /* Check again if the cookie is present. */ + lea 0x10017ffc,%a2 + move.l (%a2),%d0 + move.l #0xc0015a17,%d1 + cmp.l %d0,%d1 + bne.b .nocookie2 + + /* We have found Rockbox in ROM! + Clear the cookie and load the ROM image */ + lea 0x10017ffc,%a2 + clr.l (%a2) + lea 0x00100028+4,%a2 + move.l (%a2),%sp + lea 0x00100028+8,%a2 + move.l (%a2),%d0 + move.l %d0,%a2 + jmp (%a2) + +.nocookie2: + /* Set the cookie */ + move.l %d1,(%a2) +.noromimage: + #endif /* BOOTLOADER */ /* Invalicate cache */