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");
181 /*********** Utility Functions ************/
184 /* Tool function to calculate a CRC32 across some buffer */
185 /* third argument is either 0xFFFFFFFF to start or value from last piece */
186 unsigned crc_32(const unsigned char* buf
, unsigned len
, unsigned crc32
)
188 /* CCITT standard polynomial 0x04C11DB7 */
189 static const unsigned crc32_lookup
[16] =
190 { /* lookup table for 4 bits at a time is affordable */
191 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
192 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
193 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
194 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
202 byte
= *buf
++; /* get one byte of data */
204 /* upper nibble of our data */
205 t
= crc32
>> 28; /* extract the 4 most significant bits */
206 t
^= byte
>> 4; /* XOR in 4 bits of data into the extracted bits */
207 crc32
<<= 4; /* shift the CRC register left 4 bits */
208 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
210 /* lower nibble of our data */
211 t
= crc32
>> 28; /* extract the 4 most significant bits */
212 t
^= byte
& 0x0F; /* XOR in 4 bits of data into the extracted bits */
213 crc32
<<= 4; /* shift the CRC register left 4 bits */
214 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
221 /***************** User Interface Functions *****************/
222 int wait_for_button(void)
228 button
= rb
->button_get(true);
229 } while (IS_SYSEVENT(button
) || (button
& BUTTON_REL
));
234 /* helper for DoUserDialog() */
235 void ShowFlashInfo(struct flash_info
* pInfo
)
239 if (!pInfo
->manufacturer
)
241 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
242 rb
->lcd_puts(0, 1, "Impossible to program");
246 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
247 pInfo
->manufacturer
, pInfo
->id
);
248 rb
->lcd_puts(0, 0, buf
);
253 rb
->lcd_puts(0, 1, pInfo
->name
);
254 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
255 rb
->lcd_puts(0, 2, buf
);
259 rb
->lcd_puts(0, 1, "Unsupported chip");
269 struct flash_info fi
;
271 rb
->lcd_clear_display();
272 cfi_get_flash_info(&fi
);
274 if (fi
.size
== 0) /* no valid chip */
276 rb
->splash(HZ
*3, "Sorry!");
277 return false; /* exit */
283 bool confirm(const char *msg
)
288 rb
->snprintf(buf
, sizeof buf
, "%s ([PLAY] to CONFIRM)", msg
);
291 ret
= (wait_for_button() == BUTTON_ON
);
297 int load_firmware_file(const char *filename
, uint32_t *checksum
)
304 fd
= rb
->open(filename
, O_RDONLY
);
308 len
= rb
->filesize(fd
);
310 if (audiobuf_size
< len
)
312 rb
->splash(HZ
*3, "Aborting: Out of memory!");
317 rb
->read(fd
, checksum
, 4);
318 rb
->lseek(fd
, FIRMWARE_OFFSET_FILE_DATA
, SEEK_SET
);
319 len
-= FIRMWARE_OFFSET_FILE_DATA
;
321 rc
= rb
->read(fd
, audiobuf
, len
);
325 rb
->splash(HZ
*3, "Aborting: Read failure");
329 /* Verify the checksum */
331 for (i
= 0; i
< len
; i
++)
334 if (sum
!= *checksum
)
336 rb
->splash(HZ
*3, "Aborting: Checksums mismatch!");
343 unsigned long valid_bootloaders
[][2] = {
345 #ifdef IRIVER_H120 /* Iriver H120/H140 checksums */
346 { 63788, 0x08ff01a9 }, /* 7-pre3, improved failsafe functions */
347 { 48764, 0xc674323e }, /* 7-pre4. Fixed audio thump & remote bootup */
350 { 48760, 0x2efc3323 }, /* 7-pre4 */
356 bool detect_valid_bootloader(const unsigned char *addr
, int len
)
361 /* Try to scan through all valid bootloaders. */
362 for (i
= 0; valid_bootloaders
[i
][0]; i
++)
364 if (len
> 0 && len
!= (long)valid_bootloaders
[i
][0])
367 crc32
= crc_32(addr
, valid_bootloaders
[i
][0], 0xffffffff);
368 if (crc32
== valid_bootloaders
[i
][1])
375 static int get_section_address(int section
)
377 if (section
== SECT_RAMIMAGE
)
378 return FLASH_RAMIMAGE_ENTRY
;
379 else if (section
== SECT_ROMIMAGE
)
380 return FLASH_ROMIMAGE_ENTRY
;
385 int flash_rockbox(const char *filename
, int section
)
387 struct flash_header hdr
;
390 unsigned long checksum
, sum
;
394 if (get_section_address(section
) < 0)
397 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
398 if (!detect_valid_bootloader(p8
, 0))
400 rb
->splash(HZ
*3, "Incompatible bootloader");
404 if (!rb
->detect_original_firmware())
406 if (!confirm("Update Rockbox flash image?"))
411 if (!confirm("Erase original firmware?"))
415 len
= load_firmware_file(filename
, &checksum
);
419 pos
= get_section_address(section
);
421 /* Check if image relocation seems to be sane. */
422 if (section
== SECT_ROMIMAGE
)
424 uint32_t *p32
= (uint32_t *)audiobuf
;
426 if (pos
+sizeof(struct flash_header
) != *p32
)
428 rb
->snprintf(buf
, sizeof(buf
), "Incorrect relocation: 0x%08lx/0x%08lx",
429 *p32
, pos
+sizeof(struct flash_header
));
430 rb
->splash(HZ
*10, buf
);
436 /* Erase the program flash. */
437 for (i
= 0; i
+ pos
< BOOTLOADER_ENTRYPOINT
&& i
< len
+ 32; i
+= SEC_SIZE
)
439 /* Additional safety check. */
440 if (i
+ pos
< SEC_SIZE
)
443 rb
->snprintf(buf
, sizeof(buf
), "Erasing... %d%%",
444 (i
+SEC_SIZE
)*100/len
);
445 rb
->lcd_puts(0, 3, buf
);
448 rc
= cfi_erase_sector(FB
+ (i
+ pos
)/2);
451 /* Write the magic and size. */
452 rb
->memset(&hdr
, 0, sizeof(struct flash_header
));
453 hdr
.magic
= FLASH_MAGIC
;
455 // rb->strncpy(hdr.version, APPSVERSION, sizeof(hdr.version)-1);
456 p16
= (uint16_t *)&hdr
;
458 rb
->snprintf(buf
, sizeof(buf
), "Programming...");
459 rb
->lcd_puts(0, 4, buf
);
462 pos
= get_section_address(section
)/2;
463 for (i
= 0; i
< (long)sizeof(struct flash_header
)/2; i
++)
465 cfi_program_word(FB
+ pos
, p16
[i
]);
469 p16
= (uint16_t *)audiobuf
;
470 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
472 if (i
% SEC_SIZE
== 0)
474 rb
->snprintf(buf
, sizeof(buf
), "Programming... %d%%",
476 rb
->lcd_puts(0, 4, buf
);
480 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
484 rb
->snprintf(buf
, sizeof(buf
), "Verifying");
485 rb
->lcd_puts(0, 5, buf
);
488 p8
= (char *)get_section_address(section
);
489 p8
+= sizeof(struct flash_header
);
491 for (i
= 0; i
< len
; i
++)
496 rb
->splash(HZ
*3, "Verify failed!");
497 /* Erase the magic sector so bootloader does not try to load
498 * rockbox from flash and crash. */
499 if (section
== SECT_RAMIMAGE
)
500 cfi_erase_sector(FB
+ FLASH_RAMIMAGE_ENTRY
/2);
502 cfi_erase_sector(FB
+ FLASH_ROMIMAGE_ENTRY
/2);
506 rb
->splash(HZ
*2, "Success");
511 void show_fatal_error(void)
513 rb
->splash(HZ
*30, "Disable idle poweroff, connect AC power and DON'T TURN PLAYER OFF!!");
514 rb
->splash(HZ
*30, "Contact Rockbox developers as soon as possible!");
515 rb
->splash(HZ
*30, "Your device won't be bricked unless you turn off the power");
516 rb
->splash(HZ
*30, "Don't use the device before further instructions from Rockbox developers");
519 int flash_bootloader(const char *filename
)
523 unsigned long checksum
, sum
;
527 bootsector
= audiobuf
;
528 audiobuf
+= SEC_SIZE
;
529 audiobuf_size
-= SEC_SIZE
;
531 if (!confirm("Update bootloader?"))
534 len
= load_firmware_file(filename
, &checksum
);
540 rb
->splash(HZ
*3, "Too big bootloader");
544 /* Verify the crc32 checksum also. */
545 if (!detect_valid_bootloader(audiobuf
, len
))
547 rb
->splash(HZ
*3, "Incompatible/Untested bootloader");
551 rb
->lcd_puts(0, 3, "Flashing...");
554 /* Backup the bootloader sector first. */
556 rb
->memcpy(bootsector
, p8
, SEC_SIZE
);
558 /* Erase the boot sector and write a proper reset vector. */
559 cfi_erase_sector(FB
);
560 p16
= (uint16_t *)audiobuf
;
561 for (i
= 0; i
< 8/2; i
++)
562 cfi_program_word(FB
+ i
, p16
[i
]);
564 /* And restore original content for original FW to function. */
565 p16
= (uint16_t *)bootsector
;
566 for (i
= 8/2; i
< SEC_SIZE
/2; i
++)
567 cfi_program_word(FB
+ i
, p16
[i
]);
569 /* Erase the bootloader flash section. */
570 for (i
= BOOTLOADER_ENTRYPOINT
/SEC_SIZE
; i
< 0x200; i
++)
571 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
573 pos
= BOOTLOADER_ENTRYPOINT
/2;
574 p16
= (uint16_t *)audiobuf
;
575 for (i
= 0; i
< len
/2; i
++)
576 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
579 p8
= (char *)BOOTLOADER_ENTRYPOINT
;
581 for (i
= 0; i
< len
; i
++)
586 rb
->splash(HZ
*3, "Verify failed!");
592 for (i
= 0; i
< 8; i
++)
594 if (p8
[i
] != audiobuf
[i
])
596 rb
->splash(HZ
*3, "Bootvector corrupt!");
602 rb
->splash(HZ
*2, "Success");
607 int flash_original_fw(int len
)
609 unsigned char reset_vector
[8];
617 rb
->lcd_puts(0, 3, "Critical section...");
621 rb
->memcpy(reset_vector
, p8
, sizeof reset_vector
);
623 /* Erase the boot sector and write back the reset vector. */
624 cfi_erase_sector(FB
);
625 p16
= (uint16_t *)reset_vector
;
626 for (i
= 0; i
< (long)sizeof(reset_vector
)/2; i
++)
627 cfi_program_word(FB
+ i
, p16
[i
]);
629 rb
->lcd_puts(0, 4, "Flashing orig. FW");
632 /* Erase the program flash. */
633 for (i
= 1; i
< BOOTLOADER_ERASEGUARD
&& (i
-1)*4096 < len
; i
++)
635 rc
= cfi_erase_sector(FB
+ (SEC_SIZE
/2) * i
);
636 rb
->snprintf(buf
, sizeof(buf
), "Erase: 0x%03x (%d)", i
, rc
);
637 rb
->lcd_puts(0, 5, buf
);
641 rb
->snprintf(buf
, sizeof(buf
), "Programming");
642 rb
->lcd_puts(0, 6, buf
);
646 p16
= (uint16_t *)audiobuf
;
647 for (i
= 0; i
< len
/2 && pos
+ i
< (BOOTLOADER_ENTRYPOINT
/2); i
++)
648 cfi_program_word(FB
+ pos
+ i
, p16
[i
]);
650 rb
->snprintf(buf
, sizeof(buf
), "Verifying");
651 rb
->lcd_puts(0, 7, buf
);
654 /* Verify reset vectors. */
656 for (i
= 0; i
< 8; i
++)
658 if (p8
[i
] != reset_vector
[i
])
660 rb
->splash(HZ
*3, "Bootvector corrupt!");
667 p8
= (char *)0x00000008;
668 for (i
= 0; i
< len
; i
++)
670 if (p8
[i
] != audiobuf
[i
])
672 rb
->splash(HZ
*3, "Verify failed!");
673 rb
->snprintf(buf
, sizeof buf
, "at: 0x%08x", i
);
674 rb
->splash(HZ
*10, buf
);
679 rb
->splash(HZ
*2, "Success");
684 int load_original_bin(const char *filename
)
686 unsigned long magic
[2];
690 if (!confirm("Restore original firmware (bootloader will be kept)?"))
693 fd
= rb
->open(filename
, O_RDONLY
);
697 len
= rb
->filesize(fd
) - 0x228;
698 rb
->lseek(fd
, 0x220, SEEK_SET
);
699 rb
->read(fd
, magic
, 8);
700 if (magic
[1] != 0x00000008 || len
<= 0 || len
> audiobuf_size
)
702 rb
->splash(HZ
*2, "Not an original firmware file");
707 rc
= rb
->read(fd
, audiobuf
, len
);
712 rb
->splash(HZ
*2, "Read error");
719 return flash_original_fw(len
);
722 int load_romdump(const char *filename
)
727 if (!confirm("Restore firmware section (bootloader will be kept)?"))
730 fd
= rb
->open(filename
, O_RDONLY
);
734 len
= rb
->filesize(fd
) - 8;
738 rb
->lseek(fd
, 8, SEEK_SET
);
739 rc
= rb
->read(fd
, audiobuf
, len
);
744 rb
->splash(HZ
*2, "Read error");
751 if (len
> BOOTLOADER_ENTRYPOINT
- 8)
752 len
= BOOTLOADER_ENTRYPOINT
- 8;
754 return flash_original_fw(len
);
757 /* Kind of our main function, defines the application flow. */
758 void DoUserDialog(char* filename
)
760 /* this can only work if Rockbox runs in DRAM, not flash ROM */
761 if ((uint16_t*)rb
>= FB
&& (uint16_t*)rb
< FB
+ 4096*1024) /* 4 MB max */
762 { /* we're running from flash */
763 rb
->splash(HZ
*3, "Not from ROM");
767 /* refuse to work if the power may fail meanwhile */
768 if (!rb
->battery_level_safe())
770 rb
->splash(HZ
*3, "Battery too low!");
774 rb
->lcd_setfont(FONT_SYSFIXED
);
778 if (filename
== NULL
)
780 rb
->splash(HZ
*3, "Please use this plugin with \"Open with...\"");
784 audiobuf
= rb
->plugin_get_audio_buffer((size_t *)&audiobuf_size
);
786 if (rb
->strcasestr(filename
, "/rockbox.iriver"))
787 flash_rockbox(filename
, SECT_RAMIMAGE
);
788 else if (rb
->strcasestr(filename
, "/rombox.iriver"))
789 flash_rockbox(filename
, SECT_ROMIMAGE
);
790 else if (rb
->strcasestr(filename
, "/bootloader.iriver"))
791 flash_bootloader(filename
);
792 else if (rb
->strcasestr(filename
, "/ihp_120.bin"))
793 load_original_bin(filename
);
794 else if (rb
->strcasestr(filename
, "/internal_rom_000000-1FFFFF.bin"))
795 load_romdump(filename
);
797 rb
->splash(HZ
*3, "Unknown file type");
801 /***************** Plugin Entry Point *****************/
803 enum plugin_status
plugin_start(const void* parameter
)
807 /* now go ahead and have fun! */
808 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
809 DoUserDialog((char*) parameter
);
810 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
815 #endif /* ifdef PLATFORM_ID */