1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * !!! DON'T MESS WITH THIS CODE UNLESS YOU'RE ABSOLUTELY SURE WHAT YOU DO !!!
12 * Copyright (C) 2006 by Miika Pekkarinen
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
25 /* All CFI flash routines are copied and ported from firmware_flash.c */
27 unsigned char *audiobuf
;
28 ssize_t audiobuf_size
;
30 #ifdef IRIVER_H100_SERIES
31 #define PLATFORM_ID ID_IRIVER_H100
33 #undef PLATFORM_ID /* this platform is not (yet) flashable */
40 #if CONFIG_KEYPAD == IRIVER_H100_PAD
41 #define KEY1 BUTTON_OFF
42 #define KEY2 BUTTON_ON
43 #define KEY3 BUTTON_SELECT
44 #define KEYNAME1 "[Stop]"
45 #define KEYNAME2 "[On]"
46 #define KEYNAME3 "[Select]"
57 #ifdef IRIVER_H100_SERIES
59 #define BOOTLOADER_ERASEGUARD (BOOTLOADER_ENTRYPOINT / SEC_SIZE)
65 static volatile uint16_t* FB
= (uint16_t*)0x00000000; /* Flash base address */
68 /* read the manufacturer and device ID */
69 bool cfi_read_id(volatile uint16_t* pBase
, uint8_t* pManufacturerID
, uint8_t* pDeviceID
)
71 uint8_t not_manu
, not_id
; /* read values before switching to ID mode */
72 uint8_t manu
, id
; /* read values when in ID mode */
74 pBase
= (uint16_t*)((uint32_t)pBase
& 0xFFF80000); /* down to 512k align */
76 /* read the normal content */
77 not_manu
= pBase
[0]; /* should be 'A' (0x41) and 'R' (0x52) */
78 not_id
= pBase
[1]; /* from the "ARCH" marker */
80 pBase
[0x5555] = 0xAA; /* enter command mode */
82 pBase
[0x5555] = 0x90; /* ID command */
83 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
88 pBase
[0] = 0xF0; /* reset flash (back to normal read mode) */
89 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
91 /* I assume success if the obtained values are different from
92 the normal flash content. This is not perfectly bulletproof, they
93 could theoretically be the same by chance, causing us to fail. */
94 if (not_manu
!= manu
|| not_id
!= id
) /* a value has changed */
96 *pManufacturerID
= manu
; /* return the results */
98 return true; /* success */
100 return false; /* fail */
104 /* erase the sector which contains the given address */
105 bool cfi_erase_sector(volatile uint16_t* pAddr
)
107 unsigned timeout
= 430000; /* the timeout loop should be no less than 25ms */
109 FB
[0x5555] = 0xAA; /* enter command mode */
111 FB
[0x5555] = 0x80; /* erase command */
112 FB
[0x5555] = 0xAA; /* enter command mode */
114 *pAddr
= 0x30; /* erase the sector */
116 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
117 /* Plus memory waitstates it will be much more, gives margin */
118 while (*pAddr
!= 0xFFFF && --timeout
); /* poll for erased */
120 return (timeout
!= 0);
124 /* address must be in an erased location */
125 inline bool cfi_program_word(volatile uint16_t* pAddr
, uint16_t data
)
127 unsigned timeout
= 85; /* the timeout loop should be no less than 20us */
129 if (~*pAddr
& data
) /* just a safety feature, not really necessary */
130 return false; /* can't set any bit from 0 to 1 */
132 FB
[0x5555] = 0xAA; /* enter command mode */
134 FB
[0x5555] = 0xA0; /* byte program command */
138 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
139 /* Plus memory waitstates it will be much more, gives margin */
140 while (*pAddr
!= data
&& --timeout
); /* poll for programmed */
142 return (timeout
!= 0);
146 /* this returns true if supported and fills the info struct */
147 bool cfi_get_flash_info(struct flash_info
* pInfo
)
149 rb
->memset(pInfo
, 0, sizeof(struct flash_info
));
151 if (!cfi_read_id(FB
, &pInfo
->manufacturer
, &pInfo
->id
))
154 if (pInfo
->manufacturer
== 0xBF) /* SST */
156 if (pInfo
->id
== 0xD6)
158 pInfo
->size
= 256* 1024; /* 256k */
159 rb
->strcpy(pInfo
->name
, "SST39VF020");
162 else if (pInfo
->id
== 0xD7)
164 pInfo
->size
= 512* 1024; /* 512k */
165 rb
->strcpy(pInfo
->name
, "SST39VF040");
168 else if (pInfo
->id
== 0x82)
170 pInfo
->size
= 2048* 1024; /* 2 MiB */
171 rb
->strcpy(pInfo
->name
, "SST39VF160");
180 /***************** User Interface Functions *****************/
181 int wait_for_button(void)
187 button
= rb
->button_get(true);
188 } while (IS_SYSEVENT(button
) || (button
& BUTTON_REL
));
193 /* helper for DoUserDialog() */
194 void ShowFlashInfo(struct flash_info
* pInfo
)
198 if (!pInfo
->manufacturer
)
200 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
201 rb
->lcd_puts(0, 1, "Impossible to program");
205 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
206 pInfo
->manufacturer
, pInfo
->id
);
207 rb
->lcd_puts(0, 0, buf
);
212 rb
->lcd_puts(0, 1, pInfo
->name
);
213 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
214 rb
->lcd_puts(0, 2, buf
);
218 rb
->lcd_puts(0, 1, "Unsupported chip");
228 struct flash_info fi
;
230 rb
->lcd_clear_display();
231 cfi_get_flash_info(&fi
);
233 if (fi
.size
== 0) /* no valid chip */
235 rb
->splash(HZ
*3, "Sorry!");
236 return false; /* exit */
242 bool confirm(const char *msg
)
247 rb
->snprintf(buf
, sizeof buf
, "%s ([PLAY] to CONFIRM)", msg
);
250 ret
= (wait_for_button() == BUTTON_ON
);
256 int load_firmware_file(const char *filename
, uint32_t *checksum
)
263 fd
= rb
->open(filename
, O_RDONLY
);
267 len
= rb
->filesize(fd
);
269 if (audiobuf_size
< len
)
271 rb
->splash(HZ
*3, "Aborting: Out of memory!");
276 rb
->read(fd
, checksum
, 4);
277 rb
->lseek(fd
, FIRMWARE_OFFSET_FILE_DATA
, SEEK_SET
);
278 len
-= FIRMWARE_OFFSET_FILE_DATA
;
280 rc
= rb
->read(fd
, audiobuf
, len
);
284 rb
->splash(HZ
*3, "Aborting: Read failure");
288 /* Verify the checksum */
290 for (i
= 0; i
< len
; i
++)
293 if (sum
!= *checksum
)
295 rb
->splash(HZ
*3, "Aborting: Checksums mismatch!");
302 unsigned long valid_bootloaders
[][2] = {
304 #ifdef IRIVER_H120 /* Iriver H120/H140 checksums */
305 { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */
306 { 48764, 0xc674323e }, /* 7-pre4. Fixed audio thump & remote bootup */
309 { 48760, 0x2efc3323 }, /* 7-pre4 */
315 bool detect_valid_bootloader(const unsigned char *addr
, int len
)
320 /* Try to scan through all valid bootloaders. */
321 for (i
= 0; valid_bootloaders
[i
][0]; i
++)
323 if (len
> 0 && len
!= (long)valid_bootloaders
[i
][0])
326 crc32
= rb
->crc_32(addr
, valid_bootloaders
[i
][0], 0xffffffff);
327 if (crc32
== valid_bootloaders
[i
][1])
334 static int get_section_address(int section
)
336 if (section
== SECT_RAMIMAGE
)
337 return FLASH_RAMIMAGE_ENTRY
;
338 else if (section
== SECT_ROMIMAGE
)
339 return FLASH_ROMIMAGE_ENTRY
;
344 int flash_rockbox(const char *filename
, int section
)
346 struct flash_header hdr
;
349 unsigned long checksum
, sum
;
353 if (get_section_address(section
) < 0)
356 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
357 if (!detect_valid_bootloader(p8
, 0))
359 rb
->splash(HZ
*3, "Incompatible bootloader");
363 if (!rb
->detect_original_firmware())
365 if (!confirm("Update Rockbox flash image?"))
370 if (!confirm("Erase original firmware?"))
374 len
= load_firmware_file(filename
, &checksum
);
378 pos
= get_section_address(section
);
380 /* Check if image relocation seems to be sane. */
381 if (section
== SECT_ROMIMAGE
)
383 uint32_t *p32
= (uint32_t *)audiobuf
;
385 if (pos
+sizeof(struct flash_header
) != *p32
)
387 rb
->snprintf(buf
, sizeof(buf
), "Incorrect relocation: 0x%08lx/0x%08lx",
388 *p32
, pos
+sizeof(struct flash_header
));
389 rb
->splash(HZ
*10, buf
);
395 /* Erase the program flash. */
396 for (i
= 0; i
+ pos
< BOOTLOADER_ENTRYPOINT
&& i
< len
+ 32; i
+= SEC_SIZE
)
398 /* Additional safety check. */
399 if (i
+ pos
< SEC_SIZE
)
402 rb
->snprintf(buf
, sizeof(buf
), "Erasing... %d%%",
403 (i
+SEC_SIZE
)*100/len
);
404 rb
->lcd_puts(0, 3, buf
);
407 rc
= cfi_erase_sector(FB
+ (i
+ pos
)/2);
410 /* Write the magic and size. */
411 rb
->memset(&hdr
, 0, sizeof(struct flash_header
));
412 hdr
.magic
= FLASH_MAGIC
;
414 // rb->strncpy(hdr.version, APPSVERSION, sizeof(hdr.version)-1);
415 p16
= (uint16_t *)&hdr
;
417 rb
->snprintf(buf
, sizeof(buf
), "Programming...");
418 rb
->lcd_puts(0, 4, buf
);
421 pos
= get_section_address(section
)/2;
422 for (i
= 0; i
< (long)sizeof(struct flash_header
)/2; i
++)
424 cfi_program_word(FB
+ pos
, p16
[i
]);
428 p16
= (uint16_t *)audiobuf
;
429 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
431 if (i
% SEC_SIZE
== 0)
433 rb
->snprintf(buf
, sizeof(buf
), "Programming... %d%%",
435 rb
->lcd_puts(0, 4, buf
);
439 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
443 rb
->snprintf(buf
, sizeof(buf
), "Verifying");
444 rb
->lcd_puts(0, 5, buf
);
447 p8
= (char *)get_section_address(section
);
448 p8
+= sizeof(struct flash_header
);
450 for (i
= 0; i
< len
; i
++)
455 rb
->splash(HZ
*3, "Verify failed!");
456 /* Erase the magic sector so bootloader does not try to load
457 * rockbox from flash and crash. */
458 if (section
== SECT_RAMIMAGE
)
459 cfi_erase_sector(FB
+ FLASH_RAMIMAGE_ENTRY
/2);
461 cfi_erase_sector(FB
+ FLASH_ROMIMAGE_ENTRY
/2);
465 rb
->splash(HZ
*2, "Success");
470 void show_fatal_error(void)
472 rb
->splash(HZ
*30, "Disable idle poweroff, connect AC power and DON'T TURN PLAYER OFF!!");
473 rb
->splash(HZ
*30, "Contact Rockbox developers as soon as possible!");
474 rb
->splash(HZ
*30, "Your device won't be bricked unless you turn off the power");
475 rb
->splash(HZ
*30, "Don't use the device before further instructions from Rockbox developers");
478 int flash_bootloader(const char *filename
)
482 unsigned long checksum
, sum
;
486 bootsector
= audiobuf
;
487 audiobuf
+= SEC_SIZE
;
488 audiobuf_size
-= SEC_SIZE
;
490 if (!confirm("Update bootloader?"))
493 len
= load_firmware_file(filename
, &checksum
);
499 rb
->splash(HZ
*3, "Too big bootloader");
503 /* Verify the crc32 checksum also. */
504 if (!detect_valid_bootloader(audiobuf
, len
))
506 rb
->splash(HZ
*3, "Incompatible/Untested bootloader");
510 rb
->lcd_puts(0, 3, "Flashing...");
513 /* Backup the bootloader sector first. */
515 rb
->memcpy(bootsector
, p8
, SEC_SIZE
);
517 /* Erase the boot sector and write a proper reset vector. */
518 cfi_erase_sector(FB
);
519 p16
= (uint16_t *)audiobuf
;
520 for (i
= 0; i
< 8/2; i
++)
521 cfi_program_word(FB
+ i
, p16
[i
]);
523 /* And restore original content for original FW to function. */
524 p16
= (uint16_t *)bootsector
;
525 for (i
= 8/2; i
< SEC_SIZE
/2; i
++)
526 cfi_program_word(FB
+ i
, p16
[i
]);
528 /* Erase the bootloader flash section. */
529 for (i
= BOOTLOADER_ENTRYPOINT
/SEC_SIZE
; i
< 0x200; i
++)
530 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
532 pos
= BOOTLOADER_ENTRYPOINT
/2;
533 p16
= (uint16_t *)audiobuf
;
534 for (i
= 0; i
< len
/2; i
++)
535 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
538 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
540 for (i
= 0; i
< len
; i
++)
545 rb
->splash(HZ
*3, "Verify failed!");
551 for (i
= 0; i
< 8; i
++)
553 if (p8
[i
] != audiobuf
[i
])
555 rb
->splash(HZ
*3, "Bootvector corrupt!");
561 rb
->splash(HZ
*2, "Success");
566 int flash_original_fw(int len
)
568 unsigned char reset_vector
[8];
576 rb
->lcd_puts(0, 3, "Critical section...");
580 rb
->memcpy(reset_vector
, p8
, sizeof reset_vector
);
582 /* Erase the boot sector and write back the reset vector. */
583 cfi_erase_sector(FB
);
584 p16
= (uint16_t *)reset_vector
;
585 for (i
= 0; i
< (long)sizeof(reset_vector
)/2; i
++)
586 cfi_program_word(FB
+ i
, p16
[i
]);
588 rb
->lcd_puts(0, 4, "Flashing orig. FW");
591 /* Erase the program flash. */
592 for (i
= 1; i
< BOOTLOADER_ERASEGUARD
&& (i
-1)*4096 < len
; i
++)
594 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
595 rb
->snprintf(buf
, sizeof(buf
), "Erase: 0x%03x (%d)", i
, rc
);
596 rb
->lcd_puts(0, 5, buf
);
600 rb
->snprintf(buf
, sizeof(buf
), "Programming");
601 rb
->lcd_puts(0, 6, buf
);
605 p16
= (uint16_t *)audiobuf
;
606 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
607 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
609 rb
->snprintf(buf
, sizeof(buf
), "Verifying");
610 rb
->lcd_puts(0, 7, buf
);
613 /* Verify reset vectors. */
615 for (i
= 0; i
< 8; i
++)
617 if (p8
[i
] != reset_vector
[i
])
619 rb
->splash(HZ
*3, "Bootvector corrupt!");
626 p8
= (char *)0x00000008;
627 for (i
= 0; i
< len
; i
++)
629 if (p8
[i
] != audiobuf
[i
])
631 rb
->splash(HZ
*3, "Verify failed!");
632 rb
->snprintf(buf
, sizeof buf
, "at: 0x%08x", i
);
633 rb
->splash(HZ
*10, buf
);
638 rb
->splash(HZ
*2, "Success");
643 int load_original_bin(const char *filename
)
645 unsigned long magic
[2];
649 if (!confirm("Restore original firmware (bootloader will be kept)?"))
652 fd
= rb
->open(filename
, O_RDONLY
);
656 len
= rb
->filesize(fd
) - 0x228;
657 rb
->lseek(fd
, 0x220, SEEK_SET
);
658 rb
->read(fd
, magic
, 8);
659 if (magic
[1] != 0x00000008 || len
<= 0 || len
> audiobuf_size
)
661 rb
->splash(HZ
*2, "Not an original firmware file");
666 rc
= rb
->read(fd
, audiobuf
, len
);
671 rb
->splash(HZ
*2, "Read error");
678 return flash_original_fw(len
);
681 int load_romdump(const char *filename
)
686 if (!confirm("Restore firmware section (bootloader will be kept)?"))
689 fd
= rb
->open(filename
, O_RDONLY
);
693 len
= rb
->filesize(fd
) - 8;
697 rb
->lseek(fd
, 8, SEEK_SET
);
698 rc
= rb
->read(fd
, audiobuf
, len
);
703 rb
->splash(HZ
*2, "Read error");
710 if (len
> BOOTLOADER_ENTRYPOINT
- 8)
711 len
= BOOTLOADER_ENTRYPOINT
- 8;
713 return flash_original_fw(len
);
716 /* Kind of our main function, defines the application flow. */
717 void DoUserDialog(char* filename
)
719 /* this can only work if Rockbox runs in DRAM, not flash ROM */
720 if ((uint16_t*)rb
>= FB
&& (uint16_t*)rb
< FB
+ 4096*1024) /* 4 MB max */
721 { /* we're running from flash */
722 rb
->splash(HZ
*3, "Not from ROM");
726 /* refuse to work if the power may fail meanwhile */
727 if (!rb
->battery_level_safe())
729 rb
->splash(HZ
*3, "Battery too low!");
733 rb
->lcd_setfont(FONT_SYSFIXED
);
737 if (filename
== NULL
)
739 rb
->splash(HZ
*3, "Please use this plugin with \"Open with...\"");
743 audiobuf
= rb
->plugin_get_audio_buffer((size_t *)&audiobuf_size
);
745 if (rb
->strcasestr(filename
, "/rockbox.iriver"))
746 flash_rockbox(filename
, SECT_RAMIMAGE
);
747 else if (rb
->strcasestr(filename
, "/rombox.iriver"))
748 flash_rockbox(filename
, SECT_ROMIMAGE
);
749 else if (rb
->strcasestr(filename
, "/bootloader.iriver"))
750 flash_bootloader(filename
);
751 else if (rb
->strcasestr(filename
, "/ihp_120.bin"))
752 load_original_bin(filename
);
753 else if (rb
->strcasestr(filename
, "/internal_rom_000000-1FFFFF.bin"))
754 load_romdump(filename
);
756 rb
->splash(HZ
*3, "Unknown file type");
760 /***************** Plugin Entry Point *****************/
762 enum plugin_status
plugin_start(const void* parameter
)
766 /* now go ahead and have fun! */
767 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
768 DoUserDialog((char*) parameter
);
769 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
774 #endif /* ifdef PLATFORM_ID */