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 #ifndef IRIVER_H100_SERIES
31 #error this platform is not (yet) flashable
34 #if CONFIG_KEYPAD == IRIVER_H100_PAD
35 #define KEY1 BUTTON_OFF
36 #define KEY2 BUTTON_ON
37 #define KEY3 BUTTON_SELECT
38 #define KEYNAME1 "[Stop]"
39 #define KEYNAME2 "[On]"
40 #define KEYNAME3 "[Select]"
51 #ifdef IRIVER_H100_SERIES
53 #define BOOTLOADER_ERASEGUARD (BOOTLOADER_ENTRYPOINT / SEC_SIZE)
59 static volatile uint16_t* FB
= (uint16_t*)0x00000000; /* Flash base address */
62 /* read the manufacturer and device ID */
63 bool cfi_read_id(volatile uint16_t* pBase
, uint8_t* pManufacturerID
, uint8_t* pDeviceID
)
65 uint8_t not_manu
, not_id
; /* read values before switching to ID mode */
66 uint8_t manu
, id
; /* read values when in ID mode */
68 pBase
= (uint16_t*)((uint32_t)pBase
& 0xFFF80000); /* down to 512k align */
70 /* read the normal content */
71 not_manu
= pBase
[0]; /* should be 'A' (0x41) and 'R' (0x52) */
72 not_id
= pBase
[1]; /* from the "ARCH" marker */
74 pBase
[0x5555] = 0xAA; /* enter command mode */
76 pBase
[0x5555] = 0x90; /* ID command */
77 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
82 pBase
[0] = 0xF0; /* reset flash (back to normal read mode) */
83 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
85 /* I assume success if the obtained values are different from
86 the normal flash content. This is not perfectly bulletproof, they
87 could theoretically be the same by chance, causing us to fail. */
88 if (not_manu
!= manu
|| not_id
!= id
) /* a value has changed */
90 *pManufacturerID
= manu
; /* return the results */
92 return true; /* success */
94 return false; /* fail */
98 /* erase the sector which contains the given address */
99 bool cfi_erase_sector(volatile uint16_t* pAddr
)
101 unsigned timeout
= 430000; /* the timeout loop should be no less than 25ms */
103 FB
[0x5555] = 0xAA; /* enter command mode */
105 FB
[0x5555] = 0x80; /* erase command */
106 FB
[0x5555] = 0xAA; /* enter command mode */
108 *pAddr
= 0x30; /* erase the sector */
110 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
111 /* Plus memory waitstates it will be much more, gives margin */
112 while (*pAddr
!= 0xFFFF && --timeout
); /* poll for erased */
114 return (timeout
!= 0);
118 /* address must be in an erased location */
119 static inline bool cfi_program_word(volatile uint16_t* pAddr
, uint16_t data
)
121 unsigned timeout
= 85; /* the timeout loop should be no less than 20us */
123 if (~*pAddr
& data
) /* just a safety feature, not really necessary */
124 return false; /* can't set any bit from 0 to 1 */
126 FB
[0x5555] = 0xAA; /* enter command mode */
128 FB
[0x5555] = 0xA0; /* byte program command */
132 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
133 /* Plus memory waitstates it will be much more, gives margin */
134 while (*pAddr
!= data
&& --timeout
); /* poll for programmed */
136 return (timeout
!= 0);
140 /* this returns true if supported and fills the info struct */
141 bool cfi_get_flash_info(struct flash_info
* pInfo
)
143 rb
->memset(pInfo
, 0, sizeof(struct flash_info
));
145 if (!cfi_read_id(FB
, &pInfo
->manufacturer
, &pInfo
->id
))
148 if (pInfo
->manufacturer
== 0xBF) /* SST */
150 if (pInfo
->id
== 0xD6)
152 pInfo
->size
= 256* 1024; /* 256k */
153 rb
->strcpy(pInfo
->name
, "SST39VF020");
156 else if (pInfo
->id
== 0xD7)
158 pInfo
->size
= 512* 1024; /* 512k */
159 rb
->strcpy(pInfo
->name
, "SST39VF040");
162 else if (pInfo
->id
== 0x82)
164 pInfo
->size
= 2048* 1024; /* 2 MiB */
165 rb
->strcpy(pInfo
->name
, "SST39VF160");
174 /***************** User Interface Functions *****************/
175 int wait_for_button(void)
181 button
= rb
->button_get(true);
182 } while (IS_SYSEVENT(button
) || (button
& BUTTON_REL
));
187 /* helper for DoUserDialog() */
188 void ShowFlashInfo(struct flash_info
* pInfo
)
190 if (!pInfo
->manufacturer
)
192 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
193 rb
->lcd_puts(0, 1, "Impossible to program");
197 rb
->lcd_putsf(0, 0, "Flash: M=%02x D=%02x",
198 pInfo
->manufacturer
, pInfo
->id
);
203 rb
->lcd_puts(0, 1, pInfo
->name
);
204 rb
->lcd_putsf(0, 2, "Size: %d KB", pInfo
->size
/ 1024);
208 rb
->lcd_puts(0, 1, "Unsupported chip");
218 struct flash_info fi
;
220 rb
->lcd_clear_display();
221 cfi_get_flash_info(&fi
);
223 if (fi
.size
== 0) /* no valid chip */
225 rb
->splash(HZ
*3, "Sorry!");
226 return false; /* exit */
232 bool confirm(const char *msg
)
236 rb
->splashf(0, "%s ([PLAY] to CONFIRM)", msg
);
238 ret
= (wait_for_button() == BUTTON_ON
);
244 int load_firmware_file(const char *filename
, uint32_t *checksum
)
251 fd
= rb
->open(filename
, O_RDONLY
);
255 len
= rb
->filesize(fd
);
257 if (audiobuf_size
< len
)
259 rb
->splash(HZ
*3, "Aborting: Out of memory!");
264 rb
->read(fd
, checksum
, 4);
265 rb
->lseek(fd
, FIRMWARE_OFFSET_FILE_DATA
, SEEK_SET
);
266 len
-= FIRMWARE_OFFSET_FILE_DATA
;
268 rc
= rb
->read(fd
, audiobuf
, len
);
272 rb
->splash(HZ
*3, "Aborting: Read failure");
276 /* Verify the checksum */
278 for (i
= 0; i
< len
; i
++)
281 if (sum
!= *checksum
)
283 rb
->splash(HZ
*3, "Aborting: Checksums mismatch!");
290 unsigned long valid_bootloaders
[][2] = {
292 #ifdef IRIVER_H120 /* Iriver H120/H140 checksums */
293 { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */
294 { 48764, 0xc674323e }, /* 7-pre4. Fixed audio thump & remote bootup */
297 { 48760, 0x2efc3323 }, /* 7-pre4 */
303 bool detect_valid_bootloader(const unsigned char *addr
, int len
)
308 /* Try to scan through all valid bootloaders. */
309 for (i
= 0; valid_bootloaders
[i
][0]; i
++)
311 if (len
> 0 && len
!= (long)valid_bootloaders
[i
][0])
314 crc32
= rb
->crc_32(addr
, valid_bootloaders
[i
][0], 0xffffffff);
315 if (crc32
== valid_bootloaders
[i
][1])
322 static int get_section_address(int section
)
324 if (section
== SECT_RAMIMAGE
)
325 return FLASH_RAMIMAGE_ENTRY
;
326 else if (section
== SECT_ROMIMAGE
)
327 return FLASH_ROMIMAGE_ENTRY
;
332 int flash_rockbox(const char *filename
, int section
)
334 struct flash_header hdr
;
336 unsigned long checksum
, sum
;
340 if (get_section_address(section
) < 0)
343 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
344 if (!detect_valid_bootloader(p8
, 0))
346 rb
->splash(HZ
*3, "Incompatible bootloader");
350 if (!rb
->detect_original_firmware())
352 if (!confirm("Update Rockbox flash image?"))
357 if (!confirm("Erase original firmware?"))
361 len
= load_firmware_file(filename
, &checksum
);
365 pos
= get_section_address(section
);
367 /* Check if image relocation seems to be sane. */
368 if (section
== SECT_ROMIMAGE
)
370 uint32_t *p32
= (uint32_t *)audiobuf
;
372 if (pos
+sizeof(struct flash_header
) != *p32
)
374 rb
->splashf(HZ
*10, "Incorrect relocation: 0x%08lx/0x%08lx",
375 *p32
, pos
+sizeof(struct flash_header
));
381 /* Erase the program flash. */
382 for (i
= 0; i
+ pos
< BOOTLOADER_ENTRYPOINT
&& i
< len
+ 32; i
+= SEC_SIZE
)
384 /* Additional safety check. */
385 if (i
+ pos
< SEC_SIZE
)
388 rb
->lcd_putsf(0, 3, "Erasing... %d%%", (i
+SEC_SIZE
)*100/len
);
391 rc
= cfi_erase_sector(FB
+ (i
+ pos
)/2);
394 /* Write the magic and size. */
395 rb
->memset(&hdr
, 0, sizeof(struct flash_header
));
396 hdr
.magic
= FLASH_MAGIC
;
398 // rb->strncpy(hdr.version, rb->rbversion , sizeof(hdr.version)-1);
399 p16
= (uint16_t *)&hdr
;
401 rb
->lcd_puts(0, 4, "Programming...");
404 pos
= get_section_address(section
)/2;
405 for (i
= 0; i
< (long)sizeof(struct flash_header
)/2; i
++)
407 cfi_program_word(FB
+ pos
, p16
[i
]);
411 p16
= (uint16_t *)audiobuf
;
412 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
414 if (i
% SEC_SIZE
== 0)
416 rb
->lcd_putsf(0, 4, "Programming... %d%%", (i
+1)*100/(len
/2));
420 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
424 rb
->lcd_puts(0, 5, "Verifying");
427 p8
= (char *)get_section_address(section
);
428 p8
+= sizeof(struct flash_header
);
430 for (i
= 0; i
< len
; i
++)
435 rb
->splash(HZ
*3, "Verify failed!");
436 /* Erase the magic sector so bootloader does not try to load
437 * rockbox from flash and crash. */
438 if (section
== SECT_RAMIMAGE
)
439 cfi_erase_sector(FB
+ FLASH_RAMIMAGE_ENTRY
/2);
441 cfi_erase_sector(FB
+ FLASH_ROMIMAGE_ENTRY
/2);
445 rb
->splash(HZ
*2, "Success");
450 void show_fatal_error(void)
452 rb
->splash(HZ
*30, "Disable idle poweroff, connect AC power and DON'T TURN PLAYER OFF!!");
453 rb
->splash(HZ
*30, "Contact Rockbox developers as soon as possible!");
454 rb
->splash(HZ
*30, "Your device won't be bricked unless you turn off the power");
455 rb
->splash(HZ
*30, "Don't use the device before further instructions from Rockbox developers");
458 int flash_bootloader(const char *filename
)
462 unsigned long checksum
, sum
;
466 bootsector
= audiobuf
;
467 audiobuf
+= SEC_SIZE
;
468 audiobuf_size
-= SEC_SIZE
;
470 if (!confirm("Update bootloader?"))
473 len
= load_firmware_file(filename
, &checksum
);
479 rb
->splash(HZ
*3, "Too big bootloader");
483 /* Verify the crc32 checksum also. */
484 if (!detect_valid_bootloader(audiobuf
, len
))
486 rb
->splash(HZ
*3, "Incompatible/Untested bootloader");
490 rb
->lcd_puts(0, 3, "Flashing...");
493 /* Backup the bootloader sector first. */
495 rb
->memcpy(bootsector
, p8
, SEC_SIZE
);
497 /* Erase the boot sector and write a proper reset vector. */
498 cfi_erase_sector(FB
);
499 p16
= (uint16_t *)audiobuf
;
500 for (i
= 0; i
< 8/2; i
++)
501 cfi_program_word(FB
+ i
, p16
[i
]);
503 /* And restore original content for original FW to function. */
504 p16
= (uint16_t *)bootsector
;
505 for (i
= 8/2; i
< SEC_SIZE
/2; i
++)
506 cfi_program_word(FB
+ i
, p16
[i
]);
508 /* Erase the bootloader flash section. */
509 for (i
= BOOTLOADER_ENTRYPOINT
/SEC_SIZE
; i
< 0x200; i
++)
510 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
512 pos
= BOOTLOADER_ENTRYPOINT
/2;
513 p16
= (uint16_t *)audiobuf
;
514 for (i
= 0; i
< len
/2; i
++)
515 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
518 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
520 for (i
= 0; i
< len
; i
++)
525 rb
->splash(HZ
*3, "Verify failed!");
531 for (i
= 0; i
< 8; i
++)
533 if (p8
[i
] != audiobuf
[i
])
535 rb
->splash(HZ
*3, "Bootvector corrupt!");
541 rb
->splash(HZ
*2, "Success");
546 int flash_original_fw(int len
)
548 unsigned char reset_vector
[8];
553 rb
->lcd_puts(0, 3, "Critical section...");
557 rb
->memcpy(reset_vector
, p8
, sizeof reset_vector
);
559 /* Erase the boot sector and write back the reset vector. */
560 cfi_erase_sector(FB
);
561 p16
= (uint16_t *)reset_vector
;
562 for (i
= 0; i
< (long)sizeof(reset_vector
)/2; i
++)
563 cfi_program_word(FB
+ i
, p16
[i
]);
565 rb
->lcd_puts(0, 4, "Flashing orig. FW");
568 /* Erase the program flash. */
569 for (i
= 1; i
< BOOTLOADER_ERASEGUARD
&& (i
-1)*4096 < len
; i
++)
571 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
572 rb
->lcd_putsf(0, 5, "Erase: 0x%03x (%d)", i
, rc
);
576 rb
->lcd_puts(0, 6, "Programming");
580 p16
= (uint16_t *)audiobuf
;
581 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
582 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
584 rb
->lcd_puts(0, 7, "Verifying");
587 /* Verify reset vectors. */
589 for (i
= 0; i
< 8; i
++)
591 if (p8
[i
] != reset_vector
[i
])
593 rb
->splash(HZ
*3, "Bootvector corrupt!");
600 p8
= (char *)0x00000008;
601 for (i
= 0; i
< len
; i
++)
603 if (p8
[i
] != audiobuf
[i
])
605 rb
->splash(HZ
*3, "Verify failed!");
606 rb
->splashf(HZ
*10, "at: 0x%08x", i
);
611 rb
->splash(HZ
*2, "Success");
616 int load_original_bin(const char *filename
)
618 unsigned long magic
[2];
622 if (!confirm("Restore original firmware (bootloader will be kept)?"))
625 fd
= rb
->open(filename
, O_RDONLY
);
629 len
= rb
->filesize(fd
) - 0x228;
630 rb
->lseek(fd
, 0x220, SEEK_SET
);
631 rb
->read(fd
, magic
, 8);
632 if (magic
[1] != 0x00000008 || len
<= 0 || len
> audiobuf_size
)
634 rb
->splash(HZ
*2, "Not an original firmware file");
639 rc
= rb
->read(fd
, audiobuf
, len
);
644 rb
->splash(HZ
*2, "Read error");
651 return flash_original_fw(len
);
654 int load_romdump(const char *filename
)
659 if (!confirm("Restore firmware section (bootloader will be kept)?"))
662 fd
= rb
->open(filename
, O_RDONLY
);
666 len
= rb
->filesize(fd
) - 8;
670 rb
->lseek(fd
, 8, SEEK_SET
);
671 rc
= rb
->read(fd
, audiobuf
, len
);
676 rb
->splash(HZ
*2, "Read error");
683 if (len
> BOOTLOADER_ENTRYPOINT
- 8)
684 len
= BOOTLOADER_ENTRYPOINT
- 8;
686 return flash_original_fw(len
);
689 /* Kind of our main function, defines the application flow. */
690 void DoUserDialog(char* filename
)
692 /* this can only work if Rockbox runs in DRAM, not flash ROM */
693 if ((uint16_t*)rb
>= FB
&& (uint16_t*)rb
< FB
+ 4096*1024) /* 4 MB max */
694 { /* we're running from flash */
695 rb
->splash(HZ
*3, "Not from ROM");
699 /* refuse to work if the power may fail meanwhile */
700 if (!rb
->battery_level_safe())
702 rb
->splash(HZ
*3, "Battery too low!");
706 rb
->lcd_setfont(FONT_SYSFIXED
);
710 if (filename
== NULL
)
712 rb
->splash(HZ
*3, "Please use this plugin with \"Open with...\"");
716 audiobuf
= rb
->plugin_get_audio_buffer((size_t *)&audiobuf_size
);
718 if (rb
->strcasestr(filename
, "/rockbox.iriver"))
719 flash_rockbox(filename
, SECT_RAMIMAGE
);
720 else if (rb
->strcasestr(filename
, "/rombox.iriver"))
721 flash_rockbox(filename
, SECT_ROMIMAGE
);
722 else if (rb
->strcasestr(filename
, "/bootloader.iriver"))
723 flash_bootloader(filename
);
724 else if (rb
->strcasestr(filename
, "/ihp_120.bin"))
725 load_original_bin(filename
);
726 else if (rb
->strcasestr(filename
, "/internal_rom_000000-1FFFFF.bin"))
727 load_romdump(filename
);
729 rb
->splash(HZ
*3, "Unknown file type");
733 /***************** Plugin Entry Point *****************/
735 enum plugin_status
plugin_start(const void* parameter
)
739 /* now go ahead and have fun! */
740 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
741 DoUserDialog((char*) parameter
);
742 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */