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 * All files in this archive are subject to the GNU General Public License.
16 * See the file COPYING in the source tree root for full license agreement.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
24 #ifndef SIMULATOR /* only for target */
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 static struct plugin_api
* rb
; /* here is a global api struct pointer */
131 #define MASK_ADR 0xFC /* position of hardware mask value in Flash */
132 #define VERSION_ADR 0xFE /* position of firmware version value in Flash */
133 #define PLATFORM_ADR 0xFB /* position of my platform ID value in Flash */
134 #define SEC_SIZE 4096 /* size of one flash sector */
135 static UINT8
* sector
; /* better not place this on the stack... */
136 static volatile UINT8
* FB
= (UINT8
*)0x02000000; /* Flash base address */
139 /***************** Flash Functions *****************/
142 /* read the manufacturer and device ID */
143 bool ReadID(volatile UINT8
* pBase
, UINT8
* pManufacturerID
, UINT8
* pDeviceID
)
145 UINT8 not_manu
, not_id
; /* read values before switching to ID mode */
146 UINT8 manu
, id
; /* read values when in ID mode */
148 pBase
= (UINT8
*)((UINT32
)pBase
& 0xFFF80000); /* down to 512k align */
150 /* read the normal content */
151 not_manu
= pBase
[0]; /* should be 'A' (0x41) and 'R' (0x52) */
152 not_id
= pBase
[1]; /* from the "ARCH" marker */
154 pBase
[0x5555] = 0xAA; /* enter command mode */
155 pBase
[0x2AAA] = 0x55;
156 pBase
[0x5555] = 0x90; /* ID command */
157 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
162 pBase
[0] = 0xF0; /* reset flash (back to normal read mode) */
163 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
165 /* I assume success if the obtained values are different from
166 the normal flash content. This is not perfectly bulletproof, they
167 could theoretically be the same by chance, causing us to fail. */
168 if (not_manu
!= manu
|| not_id
!= id
) /* a value has changed */
170 *pManufacturerID
= manu
; /* return the results */
172 return true; /* success */
174 return false; /* fail */
178 /* erase the sector which contains the given address */
179 bool EraseSector(volatile UINT8
* pAddr
)
182 (void)pAddr
; /* prevents warning */
185 volatile UINT8
* pBase
= (UINT8
*)((UINT32
)pAddr
& 0xFFF80000); /* round down to 512k align */
186 unsigned timeout
= 43000; /* the timeout loop should be no less than 25ms */
188 pBase
[0x5555] = 0xAA; /* enter command mode */
189 pBase
[0x2AAA] = 0x55;
190 pBase
[0x5555] = 0x80; /* erase command */
191 pBase
[0x5555] = 0xAA; /* enter command mode */
192 pBase
[0x2AAA] = 0x55;
193 *pAddr
= 0x30; /* erase the sector */
195 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
196 /* Plus memory waitstates it will be much more, gives margin */
197 while (*pAddr
!= 0xFF && --timeout
); /* poll for erased */
199 return (timeout
!= 0);
204 /* address must be in an erased location */
205 inline bool ProgramByte(volatile UINT8
* pAddr
, UINT8 data
)
208 (void)pAddr
; /* prevents warnings */
212 unsigned timeout
= 35; /* the timeout loop should be no less than 20us */
214 if (~*pAddr
& data
) /* just a safety feature, not really necessary */
215 return false; /* can't set any bit from 0 to 1 */
217 FB
[0x5555] = 0xAA; /* enter command mode */
219 FB
[0x5555] = 0xA0; /* byte program command */
223 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
224 /* Plus memory waitstates it will be much more, gives margin */
225 while (*pAddr
!= data
&& --timeout
); /* poll for programmed */
227 return (timeout
!= 0);
232 /* this returns true if supported and fills the info struct */
233 bool GetFlashInfo(tFlashInfo
* pInfo
)
235 rb
->memset(pInfo
, 0, sizeof(tFlashInfo
));
237 if (!ReadID(FB
, &pInfo
->manufacturer
, &pInfo
->id
))
240 if (pInfo
->manufacturer
== 0xBF) /* SST */
242 if (pInfo
->id
== 0xD6)
244 pInfo
->size
= 256* 1024; /* 256k */
245 rb
->strcpy(pInfo
->name
, "SST39VF020");
248 else if (pInfo
->id
== 0xD7)
250 pInfo
->size
= 512* 1024; /* 512k */
251 rb
->strcpy(pInfo
->name
, "SST39VF040");
261 /*********** Utility Functions ************/
264 /* Tool function to calculate a CRC32 across some buffer */
265 /* third argument is either 0xFFFFFFFF to start or value from last piece */
266 unsigned crc_32(unsigned char* buf
, unsigned len
, unsigned crc32
)
268 /* CCITT standard polynomial 0x04C11DB7 */
269 static const unsigned crc32_lookup
[16] =
270 { /* lookup table for 4 bits at a time is affordable */
271 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
272 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
273 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
274 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
282 byte
= *buf
++; /* get one byte of data */
284 /* upper nibble of our data */
285 t
= crc32
>> 28; /* extract the 4 most significant bits */
286 t
^= byte
>> 4; /* XOR in 4 bits of data into the extracted bits */
287 crc32
<<= 4; /* shift the CRC register left 4 bits */
288 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
290 /* lower nibble of our data */
291 t
= crc32
>> 28; /* extract the 4 most significant bits */
292 t
^= byte
& 0x0F; /* XOR in 4 bits of data into the extracted bits */
293 crc32
<<= 4; /* shift the CRC register left 4 bits */
294 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
301 /*********** Firmware File Functions + helpers ************/
303 /* test if the version number is consistent with the platform */
304 bool CheckPlatform(int platform_id
, UINT16 version
)
307 { /* for my very first firmwares, I foolishly changed it to 200 */
308 return (platform_id
== ID_RECORDER
|| platform_id
== ID_FM
);
310 else if (version
== 123)
311 { /* it can be a FM or V2 recorder */
312 return (platform_id
== ID_FM
|| platform_id
== ID_REC_V2
);
314 else if (version
== 132)
315 { /* newer Ondio, and seen on a V2 recorder */
316 return (platform_id
== ID_ONDIO_SP
|| platform_id
== ID_ONDIO_FM
317 || platform_id
== ID_REC_V2
);
319 else if (version
== 104)
320 { /* classic Ondio128 */
321 return (platform_id
== ID_ONDIO_FM
);
323 else if (version
>= 115 && version
<= 129)
324 { /* the range of Recorders seen so far */
325 return (platform_id
== ID_RECORDER
);
327 else if (version
== 0 || (version
>= 300 && version
<= 508))
328 { /* for very old players, I've seen zero */
329 return (platform_id
== ID_PLAYER
);
332 return false; /* unknown */
336 tCheckResult
CheckFirmwareFile(char* filename
, int chipsize
, bool is_romless
)
340 int fileleft
; /* size info, how many left for reading */
341 int fileread
= 0; /* total size as read from the file */
342 int read_now
; /* how many to read for this sector */
343 int got_now
; /* how many gotten for this sector */
344 unsigned crc32
= 0xFFFFFFFF; /* CCITT init value */
345 unsigned file_crc
; /* CRC value read from file */
348 fd
= rb
->open(filename
, O_RDONLY
);
350 return eFileNotFound
;
352 fileleft
= rb
->filesize(fd
);
353 if (fileleft
> chipsize
)
358 else if (fileleft
< 20000) /* give it some reasonable lower limit */
364 if (fileleft
== 256*1024)
365 { /* original dumped firmware file has no CRC nor platform ID */
371 fileleft
-= sizeof(unsigned); /* exclude the last 4 bytes */
374 /* do some sanity checks */
376 got_now
= rb
->read(fd
, sector
, SEC_SIZE
); /* read first sector */
379 if (got_now
!= SEC_SIZE
)
385 /* version number in file plausible with this hardware? */
386 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(sector
+ VERSION_ADR
)))
394 crc32
= crc_32(sector
, SEC_SIZE
, crc32
); /* checksum */
396 /* in addition to the CRC, my files also have a platform ID */
397 if (sector
[PLATFORM_ADR
] != PLATFORM_ID
) /* for our hardware? */
405 { /* in this case, there is not much we can check */
406 if (*(UINT32
*)sector
!= 0x00000200) /* reset vector */
414 /* compare some bytes which have to be identical */
415 if (*(UINT32
*)sector
!= 0x41524348) /* "ARCH" */
421 for (i
= 0x30; i
<MASK_ADR
-2; i
++) /* leave two bytes for me */
423 if (sector
[i
] != FB
[i
])
431 /* check if we can read the whole file, and do checksum */
434 read_now
= MIN(SEC_SIZE
, fileleft
);
435 got_now
= rb
->read(fd
, sector
, read_now
);
439 if (read_now
!= got_now
)
447 crc32
= crc_32(sector
, got_now
, crc32
); /* checksum */
453 got_now
= rb
->read(fd
, &file_crc
, sizeof(file_crc
));
454 if (got_now
!= sizeof(file_crc
))
461 /* must be EOF now */
462 got_now
= rb
->read(fd
, sector
, SEC_SIZE
);
467 if (has_crc
&& file_crc
!= crc32
)
474 /* returns the # of failures, 0 on success */
475 unsigned ProgramFirmwareFile(char* filename
, int chipsize
)
479 int read
= SEC_SIZE
; /* how many for this sector */
480 UINT16 keep
= *(UINT16
*)(FB
+ KEEP
); /* we must keep this! */
481 unsigned failures
= 0;
483 fd
= rb
->open(filename
, O_RDONLY
);
487 for (i
=0; i
<chipsize
; i
+=SEC_SIZE
)
489 if (!EraseSector(FB
+ i
))
491 /* nothing we can do, let the programming count the errors */
494 if (read
== SEC_SIZE
) /* not EOF yet */
496 read
= rb
->read(fd
, sector
, SEC_SIZE
);
498 { /* put original value back in */
499 *(UINT16
*)(sector
+ KEEP
) = keep
;
502 for (j
=0; j
<read
; j
++)
504 if (!ProgramByte(FB
+ i
+ j
, sector
[j
]))
518 /* returns the # of failures, 0 on success */
519 unsigned VerifyFirmwareFile(char* filename
)
523 int read
= SEC_SIZE
; /* how many for this sector */
524 unsigned failures
= 0;
526 fd
= rb
->open(filename
, O_RDONLY
);
532 read
= rb
->read(fd
, sector
, SEC_SIZE
);
534 for (j
=0; j
<read
; j
++)
536 /* position of keep value is no error */
537 if (FB
[i
] != sector
[j
] && i
!= KEEP
&& i
!= (KEEP
+1))
544 while (read
== SEC_SIZE
);
552 /***************** Support Functions *****************/
554 /* check if we have "normal" boot ROM or flash mirrored to zero */
555 tCheckROM
CheckBootROM(void)
558 unsigned* pFlash
= (unsigned*)FB
;
559 unsigned* pRom
= (unsigned*)0x0;
562 boot_crc
= crc_32((unsigned char*)0x0, 64*1024, 0xFFFFFFFF);
563 if (boot_crc
== 0x56DBA4EE /* the known boot ROM */
564 #if PLATFORM_ID == ID_PLAYER
565 /* alternative boot ROM found in one single player so far */
566 || boot_crc
== 0x358099E8
571 /* check if ROM is a flash mirror */
572 for (i
=0; i
<256*1024/sizeof(unsigned); i
++)
574 if (*pRom
++ != *pFlash
++)
575 { /* difference means no mirror */
584 /***************** User Interface Functions *****************/
586 int WaitForButton(void)
592 button
= rb
->button_get(true);
593 } while (button
& BUTTON_REL
);
598 #ifdef HAVE_LCD_BITMAP
599 /* Recorder implementation */
601 /* helper for DoUserDialog() */
602 void ShowFlashInfo(tFlashInfo
* pInfo
)
606 if (!pInfo
->manufacturer
)
608 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
609 rb
->lcd_puts(0, 1, "Impossible to program");
613 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
614 pInfo
->manufacturer
, pInfo
->id
);
615 rb
->lcd_puts(0, 0, buf
);
620 rb
->lcd_puts(0, 1, pInfo
->name
);
621 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
622 rb
->lcd_puts(0, 2, buf
);
626 rb
->lcd_puts(0, 1, "Unsupported chip");
635 /* Kind of our main function, defines the application flow. */
636 void DoUserDialog(char* filename
)
638 tFlashInfo FlashInfo
;
640 char default_filename
[32];
642 int rc
; /* generic return code */
647 /* this can only work if Rockbox runs in DRAM, not flash ROM */
648 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
649 { /* we're running from flash */
650 rb
->splash(HZ
*3, "Not from ROM");
654 /* test if the user is running the correct plugin for this box */
655 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
657 rb
->splash(HZ
*3, "Wrong plugin");
661 /* refuse to work if the power may fail meanwhile */
662 if (!rb
->battery_level_safe())
664 rb
->splash(HZ
*3, "Battery too low!");
669 result
= CheckBootROM();
670 if (result
== eUnknown
)
671 { /* no support for any other yet */
672 rb
->splash(HZ
*3, "Wrong boot ROM");
675 is_romless
= (result
== eROMless
);
677 /* compose filename if none given */
678 if (filename
== NULL
)
682 sizeof(default_filename
),
683 "/firmware_%s%s.bin",
685 is_romless
? "_norom" : "");
686 filename
= default_filename
;
689 /* "allocate" memory */
690 sector
= rb
->plugin_get_buffer((size_t *)&memleft
);
691 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
693 rb
->splash(HZ
*3, "Out of memory");
697 rb
->lcd_setfont(FONT_SYSFIXED
);
699 rc
= GetFlashInfo(&FlashInfo
);
700 ShowFlashInfo(&FlashInfo
);
701 if (FlashInfo
.size
== 0) /* no valid chip */
703 rb
->splash(HZ
*3, "Sorry!");
707 rb
->lcd_puts(0, 3, "using file:");
708 rb
->lcd_puts_scroll(0, 4, filename
);
709 rb
->lcd_puts(0, 6, KEYNAME1
" to check file");
710 rb
->lcd_puts(0, 7, "other key to exit");
713 button
= WaitForButton();
719 rb
->lcd_clear_display();
720 rb
->lcd_puts(0, 0, "checking...");
723 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
724 rb
->lcd_puts(0, 0, "checked:");
728 rb
->lcd_puts(0, 1, "File OK.");
731 rb
->lcd_puts(0, 1, "File not found.");
732 rb
->lcd_puts(0, 2, "Put this in root:");
733 rb
->lcd_puts_scroll(0, 4, filename
);
736 rb
->lcd_puts(0, 1, "File too big,");
737 rb
->lcd_puts(0, 2, "larger than chip.");
740 rb
->lcd_puts(0, 1, "File too small.");
741 rb
->lcd_puts(0, 2, "Incomplete?");
744 rb
->lcd_puts(0, 1, "Read error.");
747 rb
->lcd_puts(0, 1, "File invalid.");
748 rb
->lcd_puts(0, 2, "Sanity check fail.");
751 rb
->lcd_puts(0, 1, "File invalid.");
752 rb
->lcd_puts(0, 2, "CRC check failed,");
753 rb
->lcd_puts(0, 3, "checksum mismatch.");
756 rb
->lcd_puts(0, 1, "Wrong file for");
757 rb
->lcd_puts(0, 2, "this hardware.");
760 rb
->lcd_puts(0, 1, "Check failed.");
766 rb
->lcd_puts(0, 6, KEYNAME2
" to program");
767 rb
->lcd_puts(0, 7, "other key to exit");
770 { /* error occured */
771 rb
->lcd_puts(0, 6, "Any key to exit");
776 button
= WaitForButton();
777 if (button
!= KEY2
|| rc
!= eOK
)
782 rb
->lcd_clear_display();
783 rb
->lcd_puts(0, 0, "Program all Flash?");
784 rb
->lcd_puts(0, 1, "Are you sure?");
785 rb
->lcd_puts(0, 2, "If it goes wrong,");
786 rb
->lcd_puts(0, 3, "it kills your box!");
787 rb
->lcd_puts(0, 4, "See documentation.");
789 rb
->lcd_puts(0, 6, KEYNAME3
" to proceed");
790 rb
->lcd_puts(0, 7, "other key to exit");
793 button
= WaitForButton();
799 rb
->lcd_clear_display();
800 rb
->lcd_puts(0, 0, "Programming...");
803 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
806 rb
->lcd_clear_display();
807 rb
->lcd_puts(0, 0, "Panic:");
808 rb
->lcd_puts(0, 1, "Programming fail!");
809 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
810 rb
->lcd_puts(0, 2, buf
);
812 button
= WaitForButton();
815 rb
->lcd_clear_display();
816 rb
->lcd_puts(0, 0, "Verifying...");
819 rc
= VerifyFirmwareFile(filename
);
821 rb
->lcd_clear_display();
824 rb
->lcd_puts(0, 0, "Verify OK.");
828 rb
->lcd_puts(0, 0, "Panic:");
829 rb
->lcd_puts(0, 1, "Verify fail!");
830 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
831 rb
->lcd_puts(0, 2, buf
);
833 rb
->lcd_puts(0, 7, "Any key to exit");
836 button
= WaitForButton();
839 #else /* HAVE_LCD_BITMAP */
840 /* Player implementation */
842 /* helper for DoUserDialog() */
843 void ShowFlashInfo(tFlashInfo
* pInfo
)
847 if (!pInfo
->manufacturer
)
849 rb
->lcd_puts_scroll(0, 0, "Flash: M=? D=?");
850 rb
->lcd_puts_scroll(0, 1, "Impossible to program");
856 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
857 pInfo
->manufacturer
, pInfo
->id
);
858 rb
->lcd_puts_scroll(0, 0, buf
);
862 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
863 rb
->lcd_puts_scroll(0, 1, buf
);
868 rb
->lcd_puts_scroll(0, 1, "Unsupported chip");
876 void DoUserDialog(char* filename
)
878 tFlashInfo FlashInfo
;
880 char default_filename
[32];
882 int rc
; /* generic return code */
887 /* this can only work if Rockbox runs in DRAM, not flash ROM */
888 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
889 { /* we're running from flash */
890 rb
->splash(HZ
*3, "Not from ROM");
894 /* test if the user is running the correct plugin for this box */
895 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
897 rb
->splash(HZ
*3, "Wrong version");
901 /* refuse to work if the power may fail meanwhile */
902 if (!rb
->battery_level_safe())
904 rb
->splash(HZ
*3, "Batt. too low!");
909 result
= CheckBootROM();
910 if (result
== eUnknown
)
911 { /* no support for any other yet */
912 rb
->splash(HZ
*3, "Wrong boot ROM");
915 is_romless
= (result
== eROMless
);
917 /* compose filename if none given */
918 if (filename
== NULL
)
922 sizeof(default_filename
),
923 "/firmware_%s%s.bin",
925 is_romless
? "_norom" : "");
926 filename
= default_filename
;
929 /* "allocate" memory */
930 sector
= rb
->plugin_get_buffer((size_t *)&memleft
);
931 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
933 rb
->splash(HZ
*3, "Out of memory");
937 rc
= GetFlashInfo(&FlashInfo
);
938 ShowFlashInfo(&FlashInfo
);
940 if (FlashInfo
.size
== 0) /* no valid chip */
945 rb
->lcd_puts_scroll(0, 0, filename
);
946 rb
->lcd_puts_scroll(0, 1, "[Menu] to check");
949 button
= WaitForButton();
950 if (button
!= BUTTON_MENU
)
955 rb
->lcd_clear_display();
956 rb
->lcd_puts(0, 0, "Checking...");
959 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
960 rb
->lcd_puts(0, 0, "Checked:");
964 rb
->lcd_puts(0, 1, "File OK.");
967 rb
->lcd_puts_scroll(0, 0, "File not found:");
968 rb
->lcd_puts_scroll(0, 1, filename
);
971 rb
->lcd_puts_scroll(0, 0, "File too big,");
972 rb
->lcd_puts_scroll(0, 1, "larger than chip.");
975 rb
->lcd_puts_scroll(0, 0, "File too small.");
976 rb
->lcd_puts_scroll(0, 1, "Incomplete?");
979 rb
->lcd_puts_scroll(0, 0, "Read error.");
982 rb
->lcd_puts_scroll(0, 0, "File invalid.");
983 rb
->lcd_puts_scroll(0, 1, "Sanity check failed.");
986 rb
->lcd_puts_scroll(0, 0, "File invalid.");
987 rb
->lcd_puts_scroll(0, 1, "CRC check failed.");
990 rb
->lcd_puts_scroll(0, 0, "Wrong file for");
991 rb
->lcd_puts_scroll(0, 1, "this hardware.");
994 rb
->lcd_puts_scroll(0, 0, "Check failed.");
1003 rb
->lcd_puts_scroll(0, 0, "[On] to program,");
1004 rb
->lcd_puts_scroll(0, 1, "other key to exit.");
1008 { /* error occured */
1012 button
= WaitForButton();
1014 if (button
!= BUTTON_ON
)
1019 rb
->lcd_clear_display();
1020 rb
->lcd_puts_scroll(0, 0, "Are you sure?");
1021 rb
->lcd_puts_scroll(0, 1, "[+] to proceed.");
1024 button
= WaitForButton();
1026 if (button
!= BUTTON_RIGHT
)
1031 rb
->lcd_clear_display();
1032 rb
->lcd_puts_scroll(0, 0, "Programming...");
1035 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
1039 rb
->lcd_clear_display();
1040 rb
->lcd_puts_scroll(0, 0, "Programming failed!");
1041 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
1042 rb
->lcd_puts_scroll(0, 1, buf
);
1047 rb
->lcd_clear_display();
1048 rb
->lcd_puts_scroll(0, 0, "Verifying...");
1051 rc
= VerifyFirmwareFile(filename
);
1053 rb
->lcd_clear_display();
1057 rb
->lcd_puts_scroll(0, 0, "Verify OK.");
1061 rb
->snprintf(buf
, sizeof(buf
), "Verify failed! %d errors", rc
);
1062 rb
->lcd_puts_scroll(0, 0, buf
);
1065 rb
->lcd_puts_scroll(0, 1, "Press any key to exit.");
1070 #endif /* not HAVE_LCD_BITMAP */
1073 /***************** Plugin Entry Point *****************/
1075 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
1079 rb
= api
; /* copy to global api pointer */
1081 /* now go ahead and have fun! */
1082 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
1083 DoUserDialog((char*) parameter
);
1084 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
1089 #endif /* ifdef PLATFORM_ID */
1090 #endif /* #ifndef SIMULATOR */