1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Plugin for reprogramming the whole Flash ROM chip with a new content.
11 * !!! DON'T MESS WITH THIS CODE UNLESS YOU'RE ABSOLUTELY SURE WHAT YOU DO !!!
13 * Copyright (C) 2003 Jörg Hohensohn [IDC]Dragon
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
26 /* define DUMMY if you only want to "play" with the UI, does no harm */
30 #define UINT8 unsigned char
34 #define UINT16 unsigned short
38 #define UINT32 unsigned long
41 /* platform IDs as I have used them in my firmware templates */
49 /* Here I have to check for ARCHOS_* defines in source code, which is
50 generally strongly discouraged. But here I'm not checking for a certain
51 feature, I'm checking for the model itself. */
52 #if defined(ARCHOS_PLAYER)
53 #define FILE_TYPE "player"
54 #define KEEP VERSION_ADR /* keep the firmware version */
55 #define PLATFORM_ID ID_PLAYER
56 #elif defined(ARCHOS_RECORDER)
57 #define FILE_TYPE "rec"
58 #define KEEP MASK_ADR /* keep the mask value */
59 #define PLATFORM_ID ID_RECORDER
60 #elif defined(ARCHOS_RECORDERV2)
61 #define FILE_TYPE "v2"
62 #define KEEP MASK_ADR /* keep the mask value */
63 #define PLATFORM_ID ID_REC_V2
64 #elif defined(ARCHOS_FMRECORDER)
65 #define FILE_TYPE "fm"
66 #define KEEP MASK_ADR /* keep the mask value */
67 #define PLATFORM_ID ID_FM
68 #elif defined(ARCHOS_ONDIOFM)
69 #define FILE_TYPE "ondiofm"
70 #define KEEP MASK_ADR /* keep the mask value */
71 #define PLATFORM_ID ID_ONDIO_FM
72 #elif defined(ARCHOS_ONDIOSP)
73 #define FILE_TYPE "ondiosp"
74 #define KEEP MASK_ADR /* keep the mask value */
75 #define PLATFORM_ID ID_ONDIO_SP
77 #undef PLATFORM_ID /* this platform is not (yet) flashable */
84 #if CONFIG_KEYPAD == ONDIO_PAD /* limited keypad */
85 #define KEY1 BUTTON_LEFT
86 #define KEY2 BUTTON_UP
87 #define KEY3 BUTTON_RIGHT
88 #define KEYNAME1 "[Left]"
89 #define KEYNAME2 "[Up]"
90 #define KEYNAME3 "[Right]"
91 #else /* recorder keypad */
92 #define KEY1 BUTTON_F1
93 #define KEY2 BUTTON_F2
94 #define KEY3 BUTTON_F3
95 #define KEYNAME1 "[F1]"
96 #define KEYNAME2 "[F2]"
97 #define KEYNAME3 "[F3]"
100 /* result of the CheckFirmwareFile() function */
104 eFileNotFound
, /* errors from here on */
113 /* result of the CheckBootROM() function */
116 eBootROM
, /* the supported boot ROM(s) */
117 eUnknown
, /* unknown boot ROM */
118 eROMless
, /* flash mapped to zero */
129 #define MASK_ADR 0xFC /* position of hardware mask value in Flash */
130 #define VERSION_ADR 0xFE /* position of firmware version value in Flash */
131 #define PLATFORM_ADR 0xFB /* position of my platform ID value in Flash */
132 #define SEC_SIZE 4096 /* size of one flash sector */
133 static UINT8
* sector
; /* better not place this on the stack... */
134 static volatile UINT8
* FB
= (UINT8
*)0x02000000; /* Flash base address */
137 /***************** Flash Functions *****************/
140 /* read the manufacturer and device ID */
141 bool ReadID(volatile UINT8
* pBase
, UINT8
* pManufacturerID
, UINT8
* pDeviceID
)
143 UINT8 not_manu
, not_id
; /* read values before switching to ID mode */
144 UINT8 manu
, id
; /* read values when in ID mode */
146 pBase
= (UINT8
*)((UINT32
)pBase
& 0xFFF80000); /* down to 512k align */
148 /* read the normal content */
149 not_manu
= pBase
[0]; /* should be 'A' (0x41) and 'R' (0x52) */
150 not_id
= pBase
[1]; /* from the "ARCH" marker */
152 pBase
[0x5555] = 0xAA; /* enter command mode */
153 pBase
[0x2AAA] = 0x55;
154 pBase
[0x5555] = 0x90; /* ID command */
155 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
160 pBase
[0] = 0xF0; /* reset flash (back to normal read mode) */
161 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
163 /* I assume success if the obtained values are different from
164 the normal flash content. This is not perfectly bulletproof, they
165 could theoretically be the same by chance, causing us to fail. */
166 if (not_manu
!= manu
|| not_id
!= id
) /* a value has changed */
168 *pManufacturerID
= manu
; /* return the results */
170 return true; /* success */
172 return false; /* fail */
176 /* erase the sector which contains the given address */
177 bool EraseSector(volatile UINT8
* pAddr
)
180 (void)pAddr
; /* prevents warning */
183 volatile UINT8
* pBase
= (UINT8
*)((UINT32
)pAddr
& 0xFFF80000); /* round down to 512k align */
184 unsigned timeout
= 43000; /* the timeout loop should be no less than 25ms */
186 pBase
[0x5555] = 0xAA; /* enter command mode */
187 pBase
[0x2AAA] = 0x55;
188 pBase
[0x5555] = 0x80; /* erase command */
189 pBase
[0x5555] = 0xAA; /* enter command mode */
190 pBase
[0x2AAA] = 0x55;
191 *pAddr
= 0x30; /* erase the sector */
193 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
194 /* Plus memory waitstates it will be much more, gives margin */
195 while (*pAddr
!= 0xFF && --timeout
); /* poll for erased */
197 return (timeout
!= 0);
202 /* address must be in an erased location */
203 inline bool ProgramByte(volatile UINT8
* pAddr
, UINT8 data
)
206 (void)pAddr
; /* prevents warnings */
210 unsigned timeout
= 35; /* the timeout loop should be no less than 20us */
212 if (~*pAddr
& data
) /* just a safety feature, not really necessary */
213 return false; /* can't set any bit from 0 to 1 */
215 FB
[0x5555] = 0xAA; /* enter command mode */
217 FB
[0x5555] = 0xA0; /* byte program command */
221 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
222 /* Plus memory waitstates it will be much more, gives margin */
223 while (*pAddr
!= data
&& --timeout
); /* poll for programmed */
225 return (timeout
!= 0);
230 /* this returns true if supported and fills the info struct */
231 bool GetFlashInfo(tFlashInfo
* pInfo
)
233 rb
->memset(pInfo
, 0, sizeof(tFlashInfo
));
235 if (!ReadID(FB
, &pInfo
->manufacturer
, &pInfo
->id
))
238 if (pInfo
->manufacturer
== 0xBF) /* SST */
240 if (pInfo
->id
== 0xD6)
242 pInfo
->size
= 256* 1024; /* 256k */
243 rb
->strcpy(pInfo
->name
, "SST39VF020");
246 else if (pInfo
->id
== 0xD7)
248 pInfo
->size
= 512* 1024; /* 512k */
249 rb
->strcpy(pInfo
->name
, "SST39VF040");
259 /*********** Utility Functions ************/
262 /* Tool function to calculate a CRC32 across some buffer */
263 /* third argument is either 0xFFFFFFFF to start or value from last piece */
264 unsigned crc_32(unsigned char* buf
, unsigned len
, unsigned crc32
)
266 /* CCITT standard polynomial 0x04C11DB7 */
267 static const unsigned crc32_lookup
[16] =
268 { /* lookup table for 4 bits at a time is affordable */
269 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
270 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
271 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
272 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
280 byte
= *buf
++; /* get one byte of data */
282 /* upper nibble of our data */
283 t
= crc32
>> 28; /* extract the 4 most significant bits */
284 t
^= byte
>> 4; /* XOR in 4 bits of data into the extracted bits */
285 crc32
<<= 4; /* shift the CRC register left 4 bits */
286 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
288 /* lower nibble of our data */
289 t
= crc32
>> 28; /* extract the 4 most significant bits */
290 t
^= byte
& 0x0F; /* XOR in 4 bits of data into the extracted bits */
291 crc32
<<= 4; /* shift the CRC register left 4 bits */
292 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
299 /*********** Firmware File Functions + helpers ************/
301 /* test if the version number is consistent with the platform */
302 bool CheckPlatform(int platform_id
, UINT16 version
)
305 { /* for my very first firmwares, I foolishly changed it to 200 */
306 return (platform_id
== ID_RECORDER
|| platform_id
== ID_FM
);
308 else if (version
== 123)
309 { /* it can be a FM or V2 recorder */
310 return (platform_id
== ID_FM
|| platform_id
== ID_REC_V2
);
312 else if (version
== 132)
313 { /* newer Ondio, and seen on a V2 recorder */
314 return (platform_id
== ID_ONDIO_SP
|| platform_id
== ID_ONDIO_FM
315 || platform_id
== ID_REC_V2
);
317 else if (version
== 104)
318 { /* classic Ondio128 */
319 return (platform_id
== ID_ONDIO_FM
);
321 else if (version
>= 115 && version
<= 129)
322 { /* the range of Recorders seen so far */
323 return (platform_id
== ID_RECORDER
);
325 else if (version
== 0 || (version
>= 300 && version
<= 508))
326 { /* for very old players, I've seen zero */
327 return (platform_id
== ID_PLAYER
);
330 return false; /* unknown */
334 tCheckResult
CheckFirmwareFile(char* filename
, int chipsize
, bool is_romless
)
338 int fileleft
; /* size info, how many left for reading */
339 int fileread
= 0; /* total size as read from the file */
340 int read_now
; /* how many to read for this sector */
341 int got_now
; /* how many gotten for this sector */
342 unsigned crc32
= 0xFFFFFFFF; /* CCITT init value */
343 unsigned file_crc
; /* CRC value read from file */
346 fd
= rb
->open(filename
, O_RDONLY
);
348 return eFileNotFound
;
350 fileleft
= rb
->filesize(fd
);
351 if (fileleft
> chipsize
)
356 else if (fileleft
< 20000) /* give it some reasonable lower limit */
362 if (fileleft
== 256*1024)
363 { /* original dumped firmware file has no CRC nor platform ID */
369 fileleft
-= sizeof(unsigned); /* exclude the last 4 bytes */
372 /* do some sanity checks */
374 got_now
= rb
->read(fd
, sector
, SEC_SIZE
); /* read first sector */
377 if (got_now
!= SEC_SIZE
)
383 /* version number in file plausible with this hardware? */
384 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(sector
+ VERSION_ADR
)))
392 crc32
= crc_32(sector
, SEC_SIZE
, crc32
); /* checksum */
394 /* in addition to the CRC, my files also have a platform ID */
395 if (sector
[PLATFORM_ADR
] != PLATFORM_ID
) /* for our hardware? */
403 { /* in this case, there is not much we can check */
404 if (*(UINT32
*)sector
!= 0x00000200) /* reset vector */
412 /* compare some bytes which have to be identical */
413 if (*(UINT32
*)sector
!= 0x41524348) /* "ARCH" */
419 for (i
= 0x30; i
<MASK_ADR
-2; i
++) /* leave two bytes for me */
421 if (sector
[i
] != FB
[i
])
429 /* check if we can read the whole file, and do checksum */
432 read_now
= MIN(SEC_SIZE
, fileleft
);
433 got_now
= rb
->read(fd
, sector
, read_now
);
437 if (read_now
!= got_now
)
445 crc32
= crc_32(sector
, got_now
, crc32
); /* checksum */
451 got_now
= rb
->read(fd
, &file_crc
, sizeof(file_crc
));
452 if (got_now
!= sizeof(file_crc
))
459 /* must be EOF now */
460 got_now
= rb
->read(fd
, sector
, SEC_SIZE
);
465 if (has_crc
&& file_crc
!= crc32
)
472 /* returns the # of failures, 0 on success */
473 unsigned ProgramFirmwareFile(char* filename
, int chipsize
)
477 int read
= SEC_SIZE
; /* how many for this sector */
478 UINT16 keep
= *(UINT16
*)(FB
+ KEEP
); /* we must keep this! */
479 unsigned failures
= 0;
481 fd
= rb
->open(filename
, O_RDONLY
);
485 for (i
=0; i
<chipsize
; i
+=SEC_SIZE
)
487 if (!EraseSector(FB
+ i
))
489 /* nothing we can do, let the programming count the errors */
492 if (read
== SEC_SIZE
) /* not EOF yet */
494 read
= rb
->read(fd
, sector
, SEC_SIZE
);
496 { /* put original value back in */
497 *(UINT16
*)(sector
+ KEEP
) = keep
;
500 for (j
=0; j
<read
; j
++)
502 if (!ProgramByte(FB
+ i
+ j
, sector
[j
]))
516 /* returns the # of failures, 0 on success */
517 unsigned VerifyFirmwareFile(char* filename
)
521 int read
= SEC_SIZE
; /* how many for this sector */
522 unsigned failures
= 0;
524 fd
= rb
->open(filename
, O_RDONLY
);
530 read
= rb
->read(fd
, sector
, SEC_SIZE
);
532 for (j
=0; j
<read
; j
++)
534 /* position of keep value is no error */
535 if (FB
[i
] != sector
[j
] && i
!= KEEP
&& i
!= (KEEP
+1))
542 while (read
== SEC_SIZE
);
550 /***************** Support Functions *****************/
552 /* check if we have "normal" boot ROM or flash mirrored to zero */
553 tCheckROM
CheckBootROM(void)
556 unsigned* pFlash
= (unsigned*)FB
;
557 unsigned* pRom
= (unsigned*)0x0;
560 boot_crc
= crc_32((unsigned char*)0x0, 64*1024, 0xFFFFFFFF);
561 if (boot_crc
== 0x56DBA4EE /* the known boot ROM */
562 #if PLATFORM_ID == ID_PLAYER
563 /* alternative boot ROM found in one single player so far */
564 || boot_crc
== 0x358099E8
569 /* check if ROM is a flash mirror */
570 for (i
=0; i
<256*1024/sizeof(unsigned); i
++)
572 if (*pRom
++ != *pFlash
++)
573 { /* difference means no mirror */
582 /***************** User Interface Functions *****************/
584 int WaitForButton(void)
590 button
= rb
->button_get(true);
591 } while (IS_SYSEVENT(button
) || (button
& BUTTON_REL
));
596 #ifdef HAVE_LCD_BITMAP
597 /* Recorder implementation */
599 /* helper for DoUserDialog() */
600 void ShowFlashInfo(tFlashInfo
* pInfo
)
604 if (!pInfo
->manufacturer
)
606 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
607 rb
->lcd_puts(0, 1, "Impossible to program");
611 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
612 pInfo
->manufacturer
, pInfo
->id
);
613 rb
->lcd_puts(0, 0, buf
);
618 rb
->lcd_puts(0, 1, pInfo
->name
);
619 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
620 rb
->lcd_puts(0, 2, buf
);
624 rb
->lcd_puts(0, 1, "Unsupported chip");
633 /* Kind of our main function, defines the application flow. */
634 void DoUserDialog(char* filename
)
636 tFlashInfo FlashInfo
;
638 char default_filename
[32];
640 int rc
; /* generic return code */
645 /* this can only work if Rockbox runs in DRAM, not flash ROM */
646 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
647 { /* we're running from flash */
648 rb
->splash(HZ
*3, "Not from ROM");
652 /* test if the user is running the correct plugin for this box */
653 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
655 rb
->splash(HZ
*3, "Wrong plugin");
659 /* refuse to work if the power may fail meanwhile */
660 if (!rb
->battery_level_safe())
662 rb
->splash(HZ
*3, "Battery too low!");
667 result
= CheckBootROM();
668 if (result
== eUnknown
)
669 { /* no support for any other yet */
670 rb
->splash(HZ
*3, "Wrong boot ROM");
673 is_romless
= (result
== eROMless
);
675 /* compose filename if none given */
676 if (filename
== NULL
)
680 sizeof(default_filename
),
681 "/firmware_%s%s.bin",
683 is_romless
? "_norom" : "");
684 filename
= default_filename
;
687 /* "allocate" memory */
688 sector
= rb
->plugin_get_buffer((size_t *)&memleft
);
689 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
691 rb
->splash(HZ
*3, "Out of memory");
695 rb
->lcd_setfont(FONT_SYSFIXED
);
697 rc
= GetFlashInfo(&FlashInfo
);
698 ShowFlashInfo(&FlashInfo
);
699 if (FlashInfo
.size
== 0) /* no valid chip */
701 rb
->splash(HZ
*3, "Sorry!");
705 rb
->lcd_puts(0, 3, "using file:");
706 rb
->lcd_puts_scroll(0, 4, filename
);
707 rb
->lcd_puts(0, 6, KEYNAME1
" to check file");
708 rb
->lcd_puts(0, 7, "other key to exit");
711 button
= WaitForButton();
717 rb
->lcd_clear_display();
718 rb
->lcd_puts(0, 0, "checking...");
721 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
722 rb
->lcd_puts(0, 0, "checked:");
726 rb
->lcd_puts(0, 1, "File OK.");
729 rb
->lcd_puts(0, 1, "File not found.");
730 rb
->lcd_puts(0, 2, "Put this in root:");
731 rb
->lcd_puts_scroll(0, 4, filename
);
734 rb
->lcd_puts(0, 1, "File too big,");
735 rb
->lcd_puts(0, 2, "larger than chip.");
738 rb
->lcd_puts(0, 1, "File too small.");
739 rb
->lcd_puts(0, 2, "Incomplete?");
742 rb
->lcd_puts(0, 1, "Read error.");
745 rb
->lcd_puts(0, 1, "File invalid.");
746 rb
->lcd_puts(0, 2, "Sanity check fail.");
749 rb
->lcd_puts(0, 1, "File invalid.");
750 rb
->lcd_puts(0, 2, "CRC check failed,");
751 rb
->lcd_puts(0, 3, "checksum mismatch.");
754 rb
->lcd_puts(0, 1, "Wrong file for");
755 rb
->lcd_puts(0, 2, "this hardware.");
758 rb
->lcd_puts(0, 1, "Check failed.");
764 rb
->lcd_puts(0, 6, KEYNAME2
" to program");
765 rb
->lcd_puts(0, 7, "other key to exit");
768 { /* error occured */
769 rb
->lcd_puts(0, 6, "Any key to exit");
774 button
= WaitForButton();
775 if (button
!= KEY2
|| rc
!= eOK
)
780 rb
->lcd_clear_display();
781 rb
->lcd_puts(0, 0, "Program all Flash?");
782 rb
->lcd_puts(0, 1, "Are you sure?");
783 rb
->lcd_puts(0, 2, "If it goes wrong,");
784 rb
->lcd_puts(0, 3, "it kills your box!");
785 rb
->lcd_puts(0, 4, "See documentation.");
787 rb
->lcd_puts(0, 6, KEYNAME3
" to proceed");
788 rb
->lcd_puts(0, 7, "other key to exit");
791 button
= WaitForButton();
797 rb
->lcd_clear_display();
798 rb
->lcd_puts(0, 0, "Programming...");
801 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
804 rb
->lcd_clear_display();
805 rb
->lcd_puts(0, 0, "Panic:");
806 rb
->lcd_puts(0, 1, "Programming fail!");
807 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
808 rb
->lcd_puts(0, 2, buf
);
810 button
= WaitForButton();
813 rb
->lcd_clear_display();
814 rb
->lcd_puts(0, 0, "Verifying...");
817 rc
= VerifyFirmwareFile(filename
);
819 rb
->lcd_clear_display();
822 rb
->lcd_puts(0, 0, "Verify OK.");
826 rb
->lcd_puts(0, 0, "Panic:");
827 rb
->lcd_puts(0, 1, "Verify fail!");
828 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
829 rb
->lcd_puts(0, 2, buf
);
831 rb
->lcd_puts(0, 7, "Any key to exit");
834 button
= WaitForButton();
837 #else /* HAVE_LCD_BITMAP */
838 /* Player implementation */
840 /* helper for DoUserDialog() */
841 void ShowFlashInfo(tFlashInfo
* pInfo
)
845 if (!pInfo
->manufacturer
)
847 rb
->lcd_puts_scroll(0, 0, "Flash: M=? D=?");
848 rb
->lcd_puts_scroll(0, 1, "Impossible to program");
854 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
855 pInfo
->manufacturer
, pInfo
->id
);
856 rb
->lcd_puts_scroll(0, 0, buf
);
860 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
861 rb
->lcd_puts_scroll(0, 1, buf
);
866 rb
->lcd_puts_scroll(0, 1, "Unsupported chip");
874 void DoUserDialog(char* filename
)
876 tFlashInfo FlashInfo
;
878 char default_filename
[32];
880 int rc
; /* generic return code */
885 /* this can only work if Rockbox runs in DRAM, not flash ROM */
886 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
887 { /* we're running from flash */
888 rb
->splash(HZ
*3, "Not from ROM");
892 /* test if the user is running the correct plugin for this box */
893 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
895 rb
->splash(HZ
*3, "Wrong version");
899 /* refuse to work if the power may fail meanwhile */
900 if (!rb
->battery_level_safe())
902 rb
->splash(HZ
*3, "Batt. too low!");
907 result
= CheckBootROM();
908 if (result
== eUnknown
)
909 { /* no support for any other yet */
910 rb
->splash(HZ
*3, "Wrong boot ROM");
913 is_romless
= (result
== eROMless
);
915 /* compose filename if none given */
916 if (filename
== NULL
)
920 sizeof(default_filename
),
921 "/firmware_%s%s.bin",
923 is_romless
? "_norom" : "");
924 filename
= default_filename
;
927 /* "allocate" memory */
928 sector
= rb
->plugin_get_buffer((size_t *)&memleft
);
929 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
931 rb
->splash(HZ
*3, "Out of memory");
935 rc
= GetFlashInfo(&FlashInfo
);
936 ShowFlashInfo(&FlashInfo
);
938 if (FlashInfo
.size
== 0) /* no valid chip */
943 rb
->lcd_puts_scroll(0, 0, filename
);
944 rb
->lcd_puts_scroll(0, 1, "[Menu] to check");
947 button
= WaitForButton();
948 if (button
!= BUTTON_MENU
)
953 rb
->lcd_clear_display();
954 rb
->lcd_puts(0, 0, "Checking...");
957 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
958 rb
->lcd_puts(0, 0, "Checked:");
962 rb
->lcd_puts(0, 1, "File OK.");
965 rb
->lcd_puts_scroll(0, 0, "File not found:");
966 rb
->lcd_puts_scroll(0, 1, filename
);
969 rb
->lcd_puts_scroll(0, 0, "File too big,");
970 rb
->lcd_puts_scroll(0, 1, "larger than chip.");
973 rb
->lcd_puts_scroll(0, 0, "File too small.");
974 rb
->lcd_puts_scroll(0, 1, "Incomplete?");
977 rb
->lcd_puts_scroll(0, 0, "Read error.");
980 rb
->lcd_puts_scroll(0, 0, "File invalid.");
981 rb
->lcd_puts_scroll(0, 1, "Sanity check failed.");
984 rb
->lcd_puts_scroll(0, 0, "File invalid.");
985 rb
->lcd_puts_scroll(0, 1, "CRC check failed.");
988 rb
->lcd_puts_scroll(0, 0, "Wrong file for");
989 rb
->lcd_puts_scroll(0, 1, "this hardware.");
992 rb
->lcd_puts_scroll(0, 0, "Check failed.");
1001 rb
->lcd_puts_scroll(0, 0, "[On] to program,");
1002 rb
->lcd_puts_scroll(0, 1, "other key to exit.");
1006 { /* error occured */
1010 button
= WaitForButton();
1012 if (button
!= BUTTON_ON
)
1017 rb
->lcd_clear_display();
1018 rb
->lcd_puts_scroll(0, 0, "Are you sure?");
1019 rb
->lcd_puts_scroll(0, 1, "[+] to proceed.");
1022 button
= WaitForButton();
1024 if (button
!= BUTTON_RIGHT
)
1029 rb
->lcd_clear_display();
1030 rb
->lcd_puts_scroll(0, 0, "Programming...");
1033 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
1037 rb
->lcd_clear_display();
1038 rb
->lcd_puts_scroll(0, 0, "Programming failed!");
1039 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
1040 rb
->lcd_puts_scroll(0, 1, buf
);
1045 rb
->lcd_clear_display();
1046 rb
->lcd_puts_scroll(0, 0, "Verifying...");
1049 rc
= VerifyFirmwareFile(filename
);
1051 rb
->lcd_clear_display();
1055 rb
->lcd_puts_scroll(0, 0, "Verify OK.");
1059 rb
->snprintf(buf
, sizeof(buf
), "Verify failed! %d errors", rc
);
1060 rb
->lcd_puts_scroll(0, 0, buf
);
1063 rb
->lcd_puts_scroll(0, 1, "Press any key to exit.");
1068 #endif /* not HAVE_LCD_BITMAP */
1071 /***************** Plugin Entry Point *****************/
1073 enum plugin_status
plugin_start(const void* parameter
)
1077 /* now go ahead and have fun! */
1078 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
1079 DoUserDialog((char*) parameter
);
1080 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
1085 #endif /* ifdef PLATFORM_ID */