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 #ifndef SIMULATOR /* only for target */
29 unsigned char *audiobuf
;
30 ssize_t audiobuf_size
;
32 #ifdef IRIVER_H100_SERIES
33 #define PLATFORM_ID ID_IRIVER_H100
35 #undef PLATFORM_ID /* this platform is not (yet) flashable */
42 #if CONFIG_KEYPAD == IRIVER_H100_PAD
43 #define KEY1 BUTTON_OFF
44 #define KEY2 BUTTON_ON
45 #define KEY3 BUTTON_SELECT
46 #define KEYNAME1 "[Stop]"
47 #define KEYNAME2 "[On]"
48 #define KEYNAME3 "[Select]"
59 static const struct plugin_api
* rb
; /* here is a global api struct pointer */
61 #ifdef IRIVER_H100_SERIES
63 #define BOOTLOADER_ERASEGUARD (BOOTLOADER_ENTRYPOINT / SEC_SIZE)
69 static volatile uint16_t* FB
= (uint16_t*)0x00000000; /* Flash base address */
72 /* read the manufacturer and device ID */
73 bool cfi_read_id(volatile uint16_t* pBase
, uint8_t* pManufacturerID
, uint8_t* pDeviceID
)
75 uint8_t not_manu
, not_id
; /* read values before switching to ID mode */
76 uint8_t manu
, id
; /* read values when in ID mode */
78 pBase
= (uint16_t*)((uint32_t)pBase
& 0xFFF80000); /* down to 512k align */
80 /* read the normal content */
81 not_manu
= pBase
[0]; /* should be 'A' (0x41) and 'R' (0x52) */
82 not_id
= pBase
[1]; /* from the "ARCH" marker */
84 pBase
[0x5555] = 0xAA; /* enter command mode */
86 pBase
[0x5555] = 0x90; /* ID command */
87 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
92 pBase
[0] = 0xF0; /* reset flash (back to normal read mode) */
93 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
95 /* I assume success if the obtained values are different from
96 the normal flash content. This is not perfectly bulletproof, they
97 could theoretically be the same by chance, causing us to fail. */
98 if (not_manu
!= manu
|| not_id
!= id
) /* a value has changed */
100 *pManufacturerID
= manu
; /* return the results */
102 return true; /* success */
104 return false; /* fail */
108 /* erase the sector which contains the given address */
109 bool cfi_erase_sector(volatile uint16_t* pAddr
)
111 unsigned timeout
= 430000; /* the timeout loop should be no less than 25ms */
113 FB
[0x5555] = 0xAA; /* enter command mode */
115 FB
[0x5555] = 0x80; /* erase command */
116 FB
[0x5555] = 0xAA; /* enter command mode */
118 *pAddr
= 0x30; /* erase the sector */
120 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
121 /* Plus memory waitstates it will be much more, gives margin */
122 while (*pAddr
!= 0xFFFF && --timeout
); /* poll for erased */
124 return (timeout
!= 0);
128 /* address must be in an erased location */
129 inline bool cfi_program_word(volatile uint16_t* pAddr
, uint16_t data
)
131 unsigned timeout
= 85; /* the timeout loop should be no less than 20us */
133 if (~*pAddr
& data
) /* just a safety feature, not really necessary */
134 return false; /* can't set any bit from 0 to 1 */
136 FB
[0x5555] = 0xAA; /* enter command mode */
138 FB
[0x5555] = 0xA0; /* byte program command */
142 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
143 /* Plus memory waitstates it will be much more, gives margin */
144 while (*pAddr
!= data
&& --timeout
); /* poll for programmed */
146 return (timeout
!= 0);
150 /* this returns true if supported and fills the info struct */
151 bool cfi_get_flash_info(struct flash_info
* pInfo
)
153 rb
->memset(pInfo
, 0, sizeof(struct flash_info
));
155 if (!cfi_read_id(FB
, &pInfo
->manufacturer
, &pInfo
->id
))
158 if (pInfo
->manufacturer
== 0xBF) /* SST */
160 if (pInfo
->id
== 0xD6)
162 pInfo
->size
= 256* 1024; /* 256k */
163 rb
->strcpy(pInfo
->name
, "SST39VF020");
166 else if (pInfo
->id
== 0xD7)
168 pInfo
->size
= 512* 1024; /* 512k */
169 rb
->strcpy(pInfo
->name
, "SST39VF040");
172 else if (pInfo
->id
== 0x82)
174 pInfo
->size
= 2048* 1024; /* 2 MiB */
175 rb
->strcpy(pInfo
->name
, "SST39VF160");
185 /*********** Utility Functions ************/
188 /* Tool function to calculate a CRC32 across some buffer */
189 /* third argument is either 0xFFFFFFFF to start or value from last piece */
190 unsigned crc_32(const unsigned char* buf
, unsigned len
, unsigned crc32
)
192 /* CCITT standard polynomial 0x04C11DB7 */
193 static const unsigned crc32_lookup
[16] =
194 { /* lookup table for 4 bits at a time is affordable */
195 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
196 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
197 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
198 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
206 byte
= *buf
++; /* get one byte of data */
208 /* upper nibble of our data */
209 t
= crc32
>> 28; /* extract the 4 most significant bits */
210 t
^= byte
>> 4; /* XOR in 4 bits of data into the extracted bits */
211 crc32
<<= 4; /* shift the CRC register left 4 bits */
212 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
214 /* lower nibble of our data */
215 t
= crc32
>> 28; /* extract the 4 most significant bits */
216 t
^= byte
& 0x0F; /* XOR in 4 bits of data into the extracted bits */
217 crc32
<<= 4; /* shift the CRC register left 4 bits */
218 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
225 /***************** User Interface Functions *****************/
226 int wait_for_button(void)
232 button
= rb
->button_get(true);
233 } while (button
& BUTTON_REL
);
238 /* helper for DoUserDialog() */
239 void ShowFlashInfo(struct flash_info
* pInfo
)
243 if (!pInfo
->manufacturer
)
245 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
246 rb
->lcd_puts(0, 1, "Impossible to program");
250 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
251 pInfo
->manufacturer
, pInfo
->id
);
252 rb
->lcd_puts(0, 0, buf
);
257 rb
->lcd_puts(0, 1, pInfo
->name
);
258 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
259 rb
->lcd_puts(0, 2, buf
);
263 rb
->lcd_puts(0, 1, "Unsupported chip");
273 struct flash_info fi
;
275 rb
->lcd_clear_display();
276 cfi_get_flash_info(&fi
);
278 if (fi
.size
== 0) /* no valid chip */
280 rb
->splash(HZ
*3, "Sorry!");
281 return false; /* exit */
287 bool confirm(const char *msg
)
292 rb
->snprintf(buf
, sizeof buf
, "%s ([PLAY] to CONFIRM)", msg
);
295 ret
= (wait_for_button() == BUTTON_ON
);
301 int load_firmware_file(const char *filename
, uint32_t *checksum
)
308 fd
= rb
->open(filename
, O_RDONLY
);
312 len
= rb
->filesize(fd
);
314 if (audiobuf_size
< len
)
316 rb
->splash(HZ
*3, "Aborting: Out of memory!");
321 rb
->read(fd
, checksum
, 4);
322 rb
->lseek(fd
, FIRMWARE_OFFSET_FILE_DATA
, SEEK_SET
);
323 len
-= FIRMWARE_OFFSET_FILE_DATA
;
325 rc
= rb
->read(fd
, audiobuf
, len
);
329 rb
->splash(HZ
*3, "Aborting: Read failure");
333 /* Verify the checksum */
335 for (i
= 0; i
< len
; i
++)
338 if (sum
!= *checksum
)
340 rb
->splash(HZ
*3, "Aborting: Checksums mismatch!");
347 unsigned long valid_bootloaders
[][2] = {
349 #ifdef IRIVER_H120 /* Iriver H120/H140 checksums */
350 { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */
351 { 48764, 0xc674323e }, /* 7-pre4. Fixed audio thump & remote bootup */
354 { 48760, 0x2efc3323 }, /* 7-pre4 */
360 bool detect_valid_bootloader(const unsigned char *addr
, int len
)
365 /* Try to scan through all valid bootloaders. */
366 for (i
= 0; valid_bootloaders
[i
][0]; i
++)
368 if (len
> 0 && len
!= (long)valid_bootloaders
[i
][0])
371 crc32
= crc_32(addr
, valid_bootloaders
[i
][0], 0xffffffff);
372 if (crc32
== valid_bootloaders
[i
][1])
379 static int get_section_address(int section
)
381 if (section
== SECT_RAMIMAGE
)
382 return FLASH_RAMIMAGE_ENTRY
;
383 else if (section
== SECT_ROMIMAGE
)
384 return FLASH_ROMIMAGE_ENTRY
;
389 int flash_rockbox(const char *filename
, int section
)
391 struct flash_header hdr
;
394 unsigned long checksum
, sum
;
398 if (get_section_address(section
) < 0)
401 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
402 if (!detect_valid_bootloader(p8
, 0))
404 rb
->splash(HZ
*3, "Incompatible bootloader");
408 if (!rb
->detect_original_firmware())
410 if (!confirm("Update Rockbox flash image?"))
415 if (!confirm("Erase original firmware?"))
419 len
= load_firmware_file(filename
, &checksum
);
423 pos
= get_section_address(section
);
425 /* Check if image relocation seems to be sane. */
426 if (section
== SECT_ROMIMAGE
)
428 uint32_t *p32
= (uint32_t *)audiobuf
;
430 if (pos
+sizeof(struct flash_header
) != *p32
)
432 rb
->snprintf(buf
, sizeof(buf
), "Incorrect relocation: 0x%08lx/0x%08lx",
433 *p32
, pos
+sizeof(struct flash_header
));
434 rb
->splash(HZ
*10, buf
);
440 /* Erase the program flash. */
441 for (i
= 0; i
+ pos
< BOOTLOADER_ENTRYPOINT
&& i
< len
+ 32; i
+= SEC_SIZE
)
443 /* Additional safety check. */
444 if (i
+ pos
< SEC_SIZE
)
447 rb
->snprintf(buf
, sizeof(buf
), "Erasing... %d%%",
448 (i
+SEC_SIZE
)*100/len
);
449 rb
->lcd_puts(0, 3, buf
);
452 rc
= cfi_erase_sector(FB
+ (i
+ pos
)/2);
455 /* Write the magic and size. */
456 rb
->memset(&hdr
, 0, sizeof(struct flash_header
));
457 hdr
.magic
= FLASH_MAGIC
;
459 // rb->strncpy(hdr.version, APPSVERSION, sizeof(hdr.version)-1);
460 p16
= (uint16_t *)&hdr
;
462 rb
->snprintf(buf
, sizeof(buf
), "Programming...");
463 rb
->lcd_puts(0, 4, buf
);
466 pos
= get_section_address(section
)/2;
467 for (i
= 0; i
< (long)sizeof(struct flash_header
)/2; i
++)
469 cfi_program_word(FB
+ pos
, p16
[i
]);
473 p16
= (uint16_t *)audiobuf
;
474 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
476 if (i
% SEC_SIZE
== 0)
478 rb
->snprintf(buf
, sizeof(buf
), "Programming... %d%%",
480 rb
->lcd_puts(0, 4, buf
);
484 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
488 rb
->snprintf(buf
, sizeof(buf
), "Verifying");
489 rb
->lcd_puts(0, 5, buf
);
492 p8
= (char *)get_section_address(section
);
493 p8
+= sizeof(struct flash_header
);
495 for (i
= 0; i
< len
; i
++)
500 rb
->splash(HZ
*3, "Verify failed!");
501 /* Erase the magic sector so bootloader does not try to load
502 * rockbox from flash and crash. */
503 if (section
== SECT_RAMIMAGE
)
504 cfi_erase_sector(FB
+ FLASH_RAMIMAGE_ENTRY
/2);
506 cfi_erase_sector(FB
+ FLASH_ROMIMAGE_ENTRY
/2);
510 rb
->splash(HZ
*2, "Success");
515 void show_fatal_error(void)
517 rb
->splash(HZ
*30, "Disable idle poweroff, connect AC power and DON'T TURN PLAYER OFF!!");
518 rb
->splash(HZ
*30, "Contact Rockbox developers as soon as possible!");
519 rb
->splash(HZ
*30, "Your device won't be bricked unless you turn off the power");
520 rb
->splash(HZ
*30, "Don't use the device before further instructions from Rockbox developers");
523 int flash_bootloader(const char *filename
)
527 unsigned long checksum
, sum
;
531 bootsector
= audiobuf
;
532 audiobuf
+= SEC_SIZE
;
533 audiobuf_size
-= SEC_SIZE
;
535 if (!confirm("Update bootloader?"))
538 len
= load_firmware_file(filename
, &checksum
);
544 rb
->splash(HZ
*3, "Too big bootloader");
548 /* Verify the crc32 checksum also. */
549 if (!detect_valid_bootloader(audiobuf
, len
))
551 rb
->splash(HZ
*3, "Incompatible/Untested bootloader");
555 rb
->lcd_puts(0, 3, "Flashing...");
558 /* Backup the bootloader sector first. */
560 rb
->memcpy(bootsector
, p8
, SEC_SIZE
);
562 /* Erase the boot sector and write a proper reset vector. */
563 cfi_erase_sector(FB
);
564 p16
= (uint16_t *)audiobuf
;
565 for (i
= 0; i
< 8/2; i
++)
566 cfi_program_word(FB
+ i
, p16
[i
]);
568 /* And restore original content for original FW to function. */
569 p16
= (uint16_t *)bootsector
;
570 for (i
= 8/2; i
< SEC_SIZE
/2; i
++)
571 cfi_program_word(FB
+ i
, p16
[i
]);
573 /* Erase the bootloader flash section. */
574 for (i
= BOOTLOADER_ENTRYPOINT
/SEC_SIZE
; i
< 0x200; i
++)
575 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
577 pos
= BOOTLOADER_ENTRYPOINT
/2;
578 p16
= (uint16_t *)audiobuf
;
579 for (i
= 0; i
< len
/2; i
++)
580 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
583 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
585 for (i
= 0; i
< len
; i
++)
590 rb
->splash(HZ
*3, "Verify failed!");
596 for (i
= 0; i
< 8; i
++)
598 if (p8
[i
] != audiobuf
[i
])
600 rb
->splash(HZ
*3, "Bootvector corrupt!");
606 rb
->splash(HZ
*2, "Success");
611 int flash_original_fw(int len
)
613 unsigned char reset_vector
[8];
621 rb
->lcd_puts(0, 3, "Critical section...");
625 rb
->memcpy(reset_vector
, p8
, sizeof reset_vector
);
627 /* Erase the boot sector and write back the reset vector. */
628 cfi_erase_sector(FB
);
629 p16
= (uint16_t *)reset_vector
;
630 for (i
= 0; i
< (long)sizeof(reset_vector
)/2; i
++)
631 cfi_program_word(FB
+ i
, p16
[i
]);
633 rb
->lcd_puts(0, 4, "Flashing orig. FW");
636 /* Erase the program flash. */
637 for (i
= 1; i
< BOOTLOADER_ERASEGUARD
&& (i
-1)*4096 < len
; i
++)
639 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
640 rb
->snprintf(buf
, sizeof(buf
), "Erase: 0x%03x (%d)", i
, rc
);
641 rb
->lcd_puts(0, 5, buf
);
645 rb
->snprintf(buf
, sizeof(buf
), "Programming");
646 rb
->lcd_puts(0, 6, buf
);
650 p16
= (uint16_t *)audiobuf
;
651 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
652 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
654 rb
->snprintf(buf
, sizeof(buf
), "Verifying");
655 rb
->lcd_puts(0, 7, buf
);
658 /* Verify reset vectors. */
660 for (i
= 0; i
< 8; i
++)
662 if (p8
[i
] != reset_vector
[i
])
664 rb
->splash(HZ
*3, "Bootvector corrupt!");
671 p8
= (char *)0x00000008;
672 for (i
= 0; i
< len
; i
++)
674 if (p8
[i
] != audiobuf
[i
])
676 rb
->splash(HZ
*3, "Verify failed!");
677 rb
->snprintf(buf
, sizeof buf
, "at: 0x%08x", i
);
678 rb
->splash(HZ
*10, buf
);
683 rb
->splash(HZ
*2, "Success");
688 int load_original_bin(const char *filename
)
690 unsigned long magic
[2];
694 if (!confirm("Restore original firmware (bootloader will be kept)?"))
697 fd
= rb
->open(filename
, O_RDONLY
);
701 len
= rb
->filesize(fd
) - 0x228;
702 rb
->lseek(fd
, 0x220, SEEK_SET
);
703 rb
->read(fd
, magic
, 8);
704 if (magic
[1] != 0x00000008 || len
<= 0 || len
> audiobuf_size
)
706 rb
->splash(HZ
*2, "Not an original firmware file");
711 rc
= rb
->read(fd
, audiobuf
, len
);
716 rb
->splash(HZ
*2, "Read error");
723 return flash_original_fw(len
);
726 int load_romdump(const char *filename
)
731 if (!confirm("Restore firmware section (bootloader will be kept)?"))
734 fd
= rb
->open(filename
, O_RDONLY
);
738 len
= rb
->filesize(fd
) - 8;
742 rb
->lseek(fd
, 8, SEEK_SET
);
743 rc
= rb
->read(fd
, audiobuf
, len
);
748 rb
->splash(HZ
*2, "Read error");
755 if (len
> BOOTLOADER_ENTRYPOINT
- 8)
756 len
= BOOTLOADER_ENTRYPOINT
- 8;
758 return flash_original_fw(len
);
761 /* Kind of our main function, defines the application flow. */
762 void DoUserDialog(char* filename
)
764 /* this can only work if Rockbox runs in DRAM, not flash ROM */
765 if ((uint16_t*)rb
>= FB
&& (uint16_t*)rb
< FB
+ 4096*1024) /* 4 MB max */
766 { /* we're running from flash */
767 rb
->splash(HZ
*3, "Not from ROM");
771 /* refuse to work if the power may fail meanwhile */
772 if (!rb
->battery_level_safe())
774 rb
->splash(HZ
*3, "Battery too low!");
778 rb
->lcd_setfont(FONT_SYSFIXED
);
782 if (filename
== NULL
)
784 rb
->splash(HZ
*3, "Please use this plugin with \"Open with...\"");
788 audiobuf
= rb
->plugin_get_audio_buffer((size_t *)&audiobuf_size
);
790 if (rb
->strcasestr(filename
, "/rockbox.iriver"))
791 flash_rockbox(filename
, SECT_RAMIMAGE
);
792 else if (rb
->strcasestr(filename
, "/rombox.iriver"))
793 flash_rockbox(filename
, SECT_ROMIMAGE
);
794 else if (rb
->strcasestr(filename
, "/bootloader.iriver"))
795 flash_bootloader(filename
);
796 else if (rb
->strcasestr(filename
, "/ihp_120.bin"))
797 load_original_bin(filename
);
798 else if (rb
->strcasestr(filename
, "/internal_rom_000000-1FFFFF.bin"))
799 load_romdump(filename
);
801 rb
->splash(HZ
*3, "Unknown file type");
805 /***************** Plugin Entry Point *****************/
807 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
811 rb
= api
; /* copy to global api pointer */
813 /* now go ahead and have fun! */
814 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
815 DoUserDialog((char*) parameter
);
816 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
821 #endif /* ifdef PLATFORM_ID */
822 #endif /* #ifndef SIMULATOR */