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 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 /* All CFI flash routines are copied and ported from firmware_flash.c */
25 #ifndef SIMULATOR /* only for target */
27 unsigned char *audiobuf
;
28 ssize_t audiobuf_size
;
30 #if defined(IRIVER_H120)
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 static struct plugin_api
* rb
; /* here is a global api struct pointer */
59 #ifdef IRIVER_H100_SERIES
61 #define BOOTLOADER_ERASEGUARD (BOOTLOADER_ENTRYPOINT / SEC_SIZE)
67 static volatile uint16_t* FB
= (uint16_t*)0x00000000; /* Flash base address */
70 /* read the manufacturer and device ID */
71 bool cfi_read_id(volatile uint16_t* pBase
, uint8_t* pManufacturerID
, uint8_t* pDeviceID
)
73 uint8_t not_manu
, not_id
; /* read values before switching to ID mode */
74 uint8_t manu
, id
; /* read values when in ID mode */
76 pBase
= (uint16_t*)((uint32_t)pBase
& 0xFFF80000); /* down to 512k align */
78 /* read the normal content */
79 not_manu
= pBase
[0]; /* should be 'A' (0x41) and 'R' (0x52) */
80 not_id
= pBase
[1]; /* from the "ARCH" marker */
82 pBase
[0x5555] = 0xAA; /* enter command mode */
84 pBase
[0x5555] = 0x90; /* ID command */
85 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
90 pBase
[0] = 0xF0; /* reset flash (back to normal read mode) */
91 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
93 /* I assume success if the obtained values are different from
94 the normal flash content. This is not perfectly bulletproof, they
95 could theoretically be the same by chance, causing us to fail. */
96 if (not_manu
!= manu
|| not_id
!= id
) /* a value has changed */
98 *pManufacturerID
= manu
; /* return the results */
100 return true; /* success */
102 return false; /* fail */
106 /* erase the sector which contains the given address */
107 bool cfi_erase_sector(volatile uint16_t* pAddr
)
109 unsigned timeout
= 430000; /* the timeout loop should be no less than 25ms */
111 FB
[0x5555] = 0xAA; /* enter command mode */
113 FB
[0x5555] = 0x80; /* erase command */
114 FB
[0x5555] = 0xAA; /* enter command mode */
116 *pAddr
= 0x30; /* erase the sector */
118 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
119 /* Plus memory waitstates it will be much more, gives margin */
120 while (*pAddr
!= 0xFFFF && --timeout
); /* poll for erased */
122 return (timeout
!= 0);
126 /* address must be in an erased location */
127 inline bool cfi_program_word(volatile uint16_t* pAddr
, uint16_t data
)
129 unsigned timeout
= 85; /* the timeout loop should be no less than 20us */
131 if (~*pAddr
& data
) /* just a safety feature, not really necessary */
132 return false; /* can't set any bit from 0 to 1 */
134 FB
[0x5555] = 0xAA; /* enter command mode */
136 FB
[0x5555] = 0xA0; /* byte program command */
140 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
141 /* Plus memory waitstates it will be much more, gives margin */
142 while (*pAddr
!= data
&& --timeout
); /* poll for programmed */
144 return (timeout
!= 0);
148 /* this returns true if supported and fills the info struct */
149 bool cfi_get_flash_info(struct flash_info
* pInfo
)
151 rb
->memset(pInfo
, 0, sizeof(struct flash_info
));
153 if (!cfi_read_id(FB
, &pInfo
->manufacturer
, &pInfo
->id
))
156 if (pInfo
->manufacturer
== 0xBF) /* SST */
158 if (pInfo
->id
== 0xD6)
160 pInfo
->size
= 256* 1024; /* 256k */
161 rb
->strcpy(pInfo
->name
, "SST39VF020");
164 else if (pInfo
->id
== 0xD7)
166 pInfo
->size
= 512* 1024; /* 512k */
167 rb
->strcpy(pInfo
->name
, "SST39VF040");
170 else if (pInfo
->id
== 0x82)
172 pInfo
->size
= 2048* 1024; /* 2 MiB */
173 rb
->strcpy(pInfo
->name
, "SST39VF160");
183 /*********** Utility Functions ************/
186 /* Tool function to calculate a CRC32 across some buffer */
187 /* third argument is either 0xFFFFFFFF to start or value from last piece */
188 unsigned crc_32(const unsigned char* buf
, unsigned len
, unsigned crc32
)
190 /* CCITT standard polynomial 0x04C11DB7 */
191 static const unsigned crc32_lookup
[16] =
192 { /* lookup table for 4 bits at a time is affordable */
193 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
194 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
195 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
196 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
204 byte
= *buf
++; /* get one byte of data */
206 /* upper nibble of our data */
207 t
= crc32
>> 28; /* extract the 4 most significant bits */
208 t
^= byte
>> 4; /* XOR in 4 bits of data into the extracted bits */
209 crc32
<<= 4; /* shift the CRC register left 4 bits */
210 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
212 /* lower nibble of our data */
213 t
= crc32
>> 28; /* extract the 4 most significant bits */
214 t
^= byte
& 0x0F; /* XOR in 4 bits of data into the extracted bits */
215 crc32
<<= 4; /* shift the CRC register left 4 bits */
216 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
223 /***************** User Interface Functions *****************/
224 int wait_for_button(void)
230 button
= rb
->button_get(true);
231 } while (button
& BUTTON_REL
);
236 /* helper for DoUserDialog() */
237 void ShowFlashInfo(struct flash_info
* pInfo
)
241 if (!pInfo
->manufacturer
)
243 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
244 rb
->lcd_puts(0, 1, "Impossible to program");
248 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
249 pInfo
->manufacturer
, pInfo
->id
);
250 rb
->lcd_puts(0, 0, buf
);
255 rb
->lcd_puts(0, 1, pInfo
->name
);
256 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
257 rb
->lcd_puts(0, 2, buf
);
261 rb
->lcd_puts(0, 1, "Unsupported chip");
271 struct flash_info fi
;
273 rb
->lcd_clear_display();
274 cfi_get_flash_info(&fi
);
276 if (fi
.size
== 0) /* no valid chip */
278 rb
->splash(HZ
*3, "Sorry!");
279 return false; /* exit */
285 bool confirm(const char *msg
)
290 rb
->snprintf(buf
, sizeof buf
, "%s ([PLAY] to CONFIRM)", msg
);
293 ret
= (wait_for_button() == BUTTON_ON
);
299 int load_firmware_file(const char *filename
, uint32_t *checksum
)
306 fd
= rb
->open(filename
, O_RDONLY
);
310 len
= rb
->filesize(fd
);
312 if (audiobuf_size
< len
)
314 rb
->splash(HZ
*3, "Aborting: Out of memory!");
319 rb
->read(fd
, checksum
, 4);
320 rb
->lseek(fd
, FIRMWARE_OFFSET_FILE_DATA
, SEEK_SET
);
321 len
-= FIRMWARE_OFFSET_FILE_DATA
;
323 rc
= rb
->read(fd
, audiobuf
, len
);
327 rb
->splash(HZ
*3, "Aborting: Read failure");
331 /* Verify the checksum */
333 for (i
= 0; i
< len
; i
++)
336 if (sum
!= *checksum
)
338 rb
->splash(HZ
*3, "Aborting: Checksums mismatch!");
345 unsigned long valid_bootloaders
[][2] = {
347 { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */
352 bool detect_valid_bootloader(const unsigned char *addr
, int len
)
357 /* Try to scan through all valid bootloaders. */
358 for (i
= 0; valid_bootloaders
[i
][0]; i
++)
360 if (len
> 0 && len
!= (long)valid_bootloaders
[i
][0])
363 crc32
= crc_32(addr
, valid_bootloaders
[i
][0], 0xffffffff);
364 if (crc32
== valid_bootloaders
[i
][1])
371 static int get_section_address(int section
)
373 if (section
== SECT_RAMIMAGE
)
374 return FLASH_RAMIMAGE_ENTRY
;
375 else if (section
== SECT_ROMIMAGE
)
376 return FLASH_ROMIMAGE_ENTRY
;
381 int flash_rockbox(const char *filename
, int section
)
383 struct flash_header hdr
;
386 unsigned long checksum
, sum
;
390 if (get_section_address(section
) < 0)
393 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
394 if (!detect_valid_bootloader(p8
, 0))
396 rb
->splash(HZ
*3, "Incompatible bootloader");
400 if (!rb
->detect_original_firmware())
402 if (!confirm("Update Rockbox flash image?"))
407 if (!confirm("Erase original firmware?"))
411 len
= load_firmware_file(filename
, &checksum
);
415 pos
= get_section_address(section
);
417 /* Check if image relocation seems to be sane. */
418 if (section
== SECT_ROMIMAGE
)
420 uint32_t *p32
= (uint32_t *)audiobuf
;
422 if (pos
+sizeof(struct flash_header
) != *p32
)
424 rb
->snprintf(buf
, sizeof(buf
), "Incorrect relocation: 0x%08lx/0x%08lx",
425 *p32
, pos
+sizeof(struct flash_header
));
426 rb
->splash(HZ
*10, buf
);
432 /* Erase the program flash. */
433 for (i
= 0; i
+ pos
< BOOTLOADER_ENTRYPOINT
&& i
< len
+ 32; i
+= SEC_SIZE
)
435 /* Additional safety check. */
436 if (i
+ pos
< SEC_SIZE
)
439 rb
->snprintf(buf
, sizeof(buf
), "Erasing... %d%%",
440 (i
+SEC_SIZE
)*100/len
);
441 rb
->lcd_puts(0, 3, buf
);
444 rc
= cfi_erase_sector(FB
+ (i
+ pos
)/2);
447 /* Write the magic and size. */
448 rb
->memset(&hdr
, 0, sizeof(struct flash_header
));
449 hdr
.magic
= FLASH_MAGIC
;
451 // rb->strncpy(hdr.version, APPSVERSION, sizeof(hdr.version)-1);
452 p16
= (uint16_t *)&hdr
;
454 rb
->snprintf(buf
, sizeof(buf
), "Programming...");
455 rb
->lcd_puts(0, 4, buf
);
458 pos
= get_section_address(section
)/2;
459 for (i
= 0; i
< (long)sizeof(struct flash_header
)/2; i
++)
461 cfi_program_word(FB
+ pos
, p16
[i
]);
465 p16
= (uint16_t *)audiobuf
;
466 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
468 if (i
% SEC_SIZE
== 0)
470 rb
->snprintf(buf
, sizeof(buf
), "Programming... %d%%",
472 rb
->lcd_puts(0, 4, buf
);
476 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
480 rb
->snprintf(buf
, sizeof(buf
), "Verifying");
481 rb
->lcd_puts(0, 5, buf
);
484 p8
= (char *)get_section_address(section
);
485 p8
+= sizeof(struct flash_header
);
487 for (i
= 0; i
< len
; i
++)
492 rb
->splash(HZ
*3, "Verify failed!");
493 /* Erase the magic sector so bootloader does not try to load
494 * rockbox from flash and crash. */
495 if (section
== SECT_RAMIMAGE
)
496 cfi_erase_sector(FB
+ FLASH_RAMIMAGE_ENTRY
/2);
498 cfi_erase_sector(FB
+ FLASH_ROMIMAGE_ENTRY
/2);
502 rb
->splash(HZ
*2, "Success");
507 void show_fatal_error(void)
509 rb
->splash(HZ
*30, "Disable idle poweroff, connect AC power and DON'T TURN PLAYER OFF!!");
510 rb
->splash(HZ
*30, "Contact Rockbox developers as soon as possible!");
511 rb
->splash(HZ
*30, "Your device won't be bricked unless you turn off the power");
512 rb
->splash(HZ
*30, "Don't use the device before further instructions from Rockbox developers");
515 int flash_bootloader(const char *filename
)
519 unsigned long checksum
, sum
;
523 bootsector
= audiobuf
;
524 audiobuf
+= SEC_SIZE
;
525 audiobuf_size
-= SEC_SIZE
;
527 if (!confirm("Update bootloader?"))
530 len
= load_firmware_file(filename
, &checksum
);
536 rb
->splash(HZ
*3, "Too big bootloader");
540 /* Verify the crc32 checksum also. */
541 if (!detect_valid_bootloader(audiobuf
, len
))
543 rb
->splash(HZ
*3, "Incompatible/Untested bootloader");
547 rb
->lcd_puts(0, 3, "Flashing...");
550 /* Backup the bootloader sector first. */
552 rb
->memcpy(bootsector
, p8
, SEC_SIZE
);
554 /* Erase the boot sector and write a proper reset vector. */
555 cfi_erase_sector(FB
);
556 p16
= (uint16_t *)audiobuf
;
557 for (i
= 0; i
< 8/2; i
++)
558 cfi_program_word(FB
+ i
, p16
[i
]);
560 /* And restore original content for original FW to function. */
561 p16
= (uint16_t *)bootsector
;
562 for (i
= 8/2; i
< SEC_SIZE
/2; i
++)
563 cfi_program_word(FB
+ i
, p16
[i
]);
565 /* Erase the bootloader flash section. */
566 for (i
= BOOTLOADER_ENTRYPOINT
/SEC_SIZE
; i
< 0x200; i
++)
567 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
569 pos
= BOOTLOADER_ENTRYPOINT
/2;
570 p16
= (uint16_t *)audiobuf
;
571 for (i
= 0; i
< len
/2; i
++)
572 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
575 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
577 for (i
= 0; i
< len
; i
++)
582 rb
->splash(HZ
*3, "Verify failed!");
588 for (i
= 0; i
< 8; i
++)
590 if (p8
[i
] != audiobuf
[i
])
592 rb
->splash(HZ
*3, "Bootvector corrupt!");
598 rb
->splash(HZ
*2, "Success");
603 int flash_original_fw(int len
)
605 unsigned char reset_vector
[8];
613 rb
->lcd_puts(0, 3, "Critical section...");
617 rb
->memcpy(reset_vector
, p8
, sizeof reset_vector
);
619 /* Erase the boot sector and write back the reset vector. */
620 cfi_erase_sector(FB
);
621 p16
= (uint16_t *)reset_vector
;
622 for (i
= 0; i
< (long)sizeof(reset_vector
)/2; i
++)
623 cfi_program_word(FB
+ i
, p16
[i
]);
625 rb
->lcd_puts(0, 4, "Flashing orig. FW");
628 /* Erase the program flash. */
629 for (i
= 1; i
< BOOTLOADER_ERASEGUARD
&& (i
-1)*4096 < len
; i
++)
631 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
632 rb
->snprintf(buf
, sizeof(buf
), "Erase: 0x%03x (%d)", i
, rc
);
633 rb
->lcd_puts(0, 5, buf
);
637 rb
->snprintf(buf
, sizeof(buf
), "Programming");
638 rb
->lcd_puts(0, 6, buf
);
642 p16
= (uint16_t *)audiobuf
;
643 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
644 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
646 rb
->snprintf(buf
, sizeof(buf
), "Verifying");
647 rb
->lcd_puts(0, 7, buf
);
650 /* Verify reset vectors. */
652 for (i
= 0; i
< 8; i
++)
654 if (p8
[i
] != reset_vector
[i
])
656 rb
->splash(HZ
*3, "Bootvector corrupt!");
663 p8
= (char *)0x00000008;
664 for (i
= 0; i
< len
; i
++)
666 if (p8
[i
] != audiobuf
[i
])
668 rb
->splash(HZ
*3, "Verify failed!");
669 rb
->snprintf(buf
, sizeof buf
, "at: 0x%08x", i
);
670 rb
->splash(HZ
*10, buf
);
675 rb
->splash(HZ
*2, "Success");
680 int load_original_bin(const char *filename
)
682 unsigned long magic
[2];
686 if (!confirm("Restore original firmware (bootloader will be kept)?"))
689 fd
= rb
->open(filename
, O_RDONLY
);
693 len
= rb
->filesize(fd
) - 0x228;
694 rb
->lseek(fd
, 0x220, SEEK_SET
);
695 rb
->read(fd
, magic
, 8);
696 if (magic
[1] != 0x00000008 || len
<= 0 || len
> audiobuf_size
)
698 rb
->splash(HZ
*2, "Not an original firmware file");
703 rc
= rb
->read(fd
, audiobuf
, len
);
708 rb
->splash(HZ
*2, "Read error");
715 return flash_original_fw(len
);
718 int load_romdump(const char *filename
)
723 if (!confirm("Restore firmware section (bootloader will be kept)?"))
726 fd
= rb
->open(filename
, O_RDONLY
);
730 len
= rb
->filesize(fd
) - 8;
734 rb
->lseek(fd
, 8, SEEK_SET
);
735 rc
= rb
->read(fd
, audiobuf
, len
);
740 rb
->splash(HZ
*2, "Read error");
747 if (len
> BOOTLOADER_ENTRYPOINT
- 8)
748 len
= BOOTLOADER_ENTRYPOINT
- 8;
750 return flash_original_fw(len
);
753 /* Kind of our main function, defines the application flow. */
754 void DoUserDialog(char* filename
)
756 /* this can only work if Rockbox runs in DRAM, not flash ROM */
757 if ((uint16_t*)rb
>= FB
&& (uint16_t*)rb
< FB
+ 4096*1024) /* 4 MB max */
758 { /* we're running from flash */
759 rb
->splash(HZ
*3, "Not from ROM");
763 /* refuse to work if the power may fail meanwhile */
764 if (!rb
->battery_level_safe())
766 rb
->splash(HZ
*3, "Battery too low!");
770 rb
->lcd_setfont(FONT_SYSFIXED
);
774 if (filename
== NULL
)
776 rb
->splash(HZ
*3, "Please use this plugin with \"Open with...\"");
780 audiobuf
= rb
->plugin_get_audio_buffer((size_t *)&audiobuf_size
);
782 if (rb
->strcasestr(filename
, "/rockbox.iriver"))
783 flash_rockbox(filename
, SECT_RAMIMAGE
);
784 else if (rb
->strcasestr(filename
, "/rombox.iriver"))
785 flash_rockbox(filename
, SECT_ROMIMAGE
);
786 else if (rb
->strcasestr(filename
, "/bootloader.iriver"))
787 flash_bootloader(filename
);
788 else if (rb
->strcasestr(filename
, "/ihp_120.bin"))
789 load_original_bin(filename
);
790 else if (rb
->strcasestr(filename
, "/internal_rom_000000-1FFFFF.bin"))
791 load_romdump(filename
);
793 rb
->splash(HZ
*3, "Unknown file type");
797 /***************** Plugin Entry Point *****************/
799 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
803 rb
= api
; /* copy to global api pointer */
805 /* now go ahead and have fun! */
806 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
807 DoUserDialog((char*) parameter
);
808 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
813 #endif /* ifdef PLATFORM_ID */
814 #endif /* #ifndef SIMULATOR */