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");
258 /*********** Firmware File Functions + helpers ************/
260 /* test if the version number is consistent with the platform */
261 bool CheckPlatform(int platform_id
, UINT16 version
)
264 { /* for my very first firmwares, I foolishly changed it to 200 */
265 return (platform_id
== ID_RECORDER
|| platform_id
== ID_FM
);
267 else if (version
== 123)
268 { /* it can be a FM or V2 recorder */
269 return (platform_id
== ID_FM
|| platform_id
== ID_REC_V2
);
271 else if (version
== 132)
272 { /* newer Ondio, and seen on a V2 recorder */
273 return (platform_id
== ID_ONDIO_SP
|| platform_id
== ID_ONDIO_FM
274 || platform_id
== ID_REC_V2
);
276 else if (version
== 104)
277 { /* classic Ondio128 */
278 return (platform_id
== ID_ONDIO_FM
);
280 else if (version
>= 115 && version
<= 129)
281 { /* the range of Recorders seen so far */
282 return (platform_id
== ID_RECORDER
);
284 else if (version
== 0 || (version
>= 300 && version
<= 508))
285 { /* for very old players, I've seen zero */
286 return (platform_id
== ID_PLAYER
);
289 return false; /* unknown */
293 tCheckResult
CheckFirmwareFile(char* filename
, int chipsize
, bool is_romless
)
297 int fileleft
; /* size info, how many left for reading */
298 int fileread
= 0; /* total size as read from the file */
299 int read_now
; /* how many to read for this sector */
300 int got_now
; /* how many gotten for this sector */
301 unsigned crc32
= 0xFFFFFFFF; /* CCITT init value */
302 unsigned file_crc
; /* CRC value read from file */
305 fd
= rb
->open(filename
, O_RDONLY
);
307 return eFileNotFound
;
309 fileleft
= rb
->filesize(fd
);
310 if (fileleft
> chipsize
)
315 else if (fileleft
< 20000) /* give it some reasonable lower limit */
321 if (fileleft
== 256*1024)
322 { /* original dumped firmware file has no CRC nor platform ID */
328 fileleft
-= sizeof(unsigned); /* exclude the last 4 bytes */
331 /* do some sanity checks */
333 got_now
= rb
->read(fd
, sector
, SEC_SIZE
); /* read first sector */
336 if (got_now
!= SEC_SIZE
)
342 /* version number in file plausible with this hardware? */
343 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(sector
+ VERSION_ADR
)))
351 crc32
= rb
->crc_32(sector
, SEC_SIZE
, crc32
); /* checksum */
353 /* in addition to the CRC, my files also have a platform ID */
354 if (sector
[PLATFORM_ADR
] != PLATFORM_ID
) /* for our hardware? */
362 { /* in this case, there is not much we can check */
363 if (*(UINT32
*)sector
!= 0x00000200) /* reset vector */
371 /* compare some bytes which have to be identical */
372 if (*(UINT32
*)sector
!= 0x41524348) /* "ARCH" */
378 for (i
= 0x30; i
<MASK_ADR
-2; i
++) /* leave two bytes for me */
380 if (sector
[i
] != FB
[i
])
388 /* check if we can read the whole file, and do checksum */
391 read_now
= MIN(SEC_SIZE
, fileleft
);
392 got_now
= rb
->read(fd
, sector
, read_now
);
396 if (read_now
!= got_now
)
404 crc32
= rb
->crc_32(sector
, got_now
, crc32
); /* checksum */
410 got_now
= rb
->read(fd
, &file_crc
, sizeof(file_crc
));
411 if (got_now
!= sizeof(file_crc
))
418 /* must be EOF now */
419 got_now
= rb
->read(fd
, sector
, SEC_SIZE
);
424 if (has_crc
&& file_crc
!= crc32
)
431 /* returns the # of failures, 0 on success */
432 unsigned ProgramFirmwareFile(char* filename
, int chipsize
)
436 int read
= SEC_SIZE
; /* how many for this sector */
437 UINT16 keep
= *(UINT16
*)(FB
+ KEEP
); /* we must keep this! */
438 unsigned failures
= 0;
440 fd
= rb
->open(filename
, O_RDONLY
);
444 for (i
=0; i
<chipsize
; i
+=SEC_SIZE
)
446 if (!EraseSector(FB
+ i
))
448 /* nothing we can do, let the programming count the errors */
451 if (read
== SEC_SIZE
) /* not EOF yet */
453 read
= rb
->read(fd
, sector
, SEC_SIZE
);
455 { /* put original value back in */
456 *(UINT16
*)(sector
+ KEEP
) = keep
;
459 for (j
=0; j
<read
; j
++)
461 if (!ProgramByte(FB
+ i
+ j
, sector
[j
]))
475 /* returns the # of failures, 0 on success */
476 unsigned VerifyFirmwareFile(char* filename
)
480 int read
= SEC_SIZE
; /* how many for this sector */
481 unsigned failures
= 0;
483 fd
= rb
->open(filename
, O_RDONLY
);
489 read
= rb
->read(fd
, sector
, SEC_SIZE
);
491 for (j
=0; j
<read
; j
++)
493 /* position of keep value is no error */
494 if (FB
[i
] != sector
[j
] && i
!= KEEP
&& i
!= (KEEP
+1))
501 while (read
== SEC_SIZE
);
509 /***************** Support Functions *****************/
511 /* check if we have "normal" boot ROM or flash mirrored to zero */
512 tCheckROM
CheckBootROM(void)
515 unsigned* pFlash
= (unsigned*)FB
;
516 unsigned* pRom
= (unsigned*)0x0;
519 boot_crc
= rb
->crc_32((unsigned char*)0x0, 64*1024, 0xFFFFFFFF);
520 if (boot_crc
== 0x56DBA4EE /* the known boot ROM */
521 #if PLATFORM_ID == ID_PLAYER
522 /* alternative boot ROM found in one single player so far */
523 || boot_crc
== 0x358099E8
528 /* check if ROM is a flash mirror */
529 for (i
=0; i
<256*1024/sizeof(unsigned); i
++)
531 if (*pRom
++ != *pFlash
++)
532 { /* difference means no mirror */
541 /***************** User Interface Functions *****************/
543 int WaitForButton(void)
549 button
= rb
->button_get(true);
550 } while (IS_SYSEVENT(button
) || (button
& BUTTON_REL
));
555 #ifdef HAVE_LCD_BITMAP
556 /* Recorder implementation */
558 /* helper for DoUserDialog() */
559 void ShowFlashInfo(tFlashInfo
* pInfo
)
563 if (!pInfo
->manufacturer
)
565 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
566 rb
->lcd_puts(0, 1, "Impossible to program");
570 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
571 pInfo
->manufacturer
, pInfo
->id
);
572 rb
->lcd_puts(0, 0, buf
);
577 rb
->lcd_puts(0, 1, pInfo
->name
);
578 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
579 rb
->lcd_puts(0, 2, buf
);
583 rb
->lcd_puts(0, 1, "Unsupported chip");
592 /* Kind of our main function, defines the application flow. */
593 void DoUserDialog(char* filename
)
595 tFlashInfo FlashInfo
;
597 char default_filename
[32];
599 int rc
; /* generic return code */
604 /* this can only work if Rockbox runs in DRAM, not flash ROM */
605 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
606 { /* we're running from flash */
607 rb
->splash(HZ
*3, "Not from ROM");
611 /* test if the user is running the correct plugin for this box */
612 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
614 rb
->splash(HZ
*3, "Wrong plugin");
618 /* refuse to work if the power may fail meanwhile */
619 if (!rb
->battery_level_safe())
621 rb
->splash(HZ
*3, "Battery too low!");
626 result
= CheckBootROM();
627 if (result
== eUnknown
)
628 { /* no support for any other yet */
629 rb
->splash(HZ
*3, "Wrong boot ROM");
632 is_romless
= (result
== eROMless
);
634 /* compose filename if none given */
635 if (filename
== NULL
)
639 sizeof(default_filename
),
640 "/firmware_%s%s.bin",
642 is_romless
? "_norom" : "");
643 filename
= default_filename
;
646 /* "allocate" memory */
647 sector
= rb
->plugin_get_buffer(&memleft
);
648 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
650 rb
->splash(HZ
*3, "Out of memory");
654 rb
->lcd_setfont(FONT_SYSFIXED
);
656 rc
= GetFlashInfo(&FlashInfo
);
657 ShowFlashInfo(&FlashInfo
);
658 if (FlashInfo
.size
== 0) /* no valid chip */
660 rb
->splash(HZ
*3, "Sorry!");
664 rb
->lcd_puts(0, 3, "using file:");
665 rb
->lcd_puts_scroll(0, 4, filename
);
666 rb
->lcd_puts(0, 6, KEYNAME1
" to check file");
667 rb
->lcd_puts(0, 7, "other key to exit");
670 button
= WaitForButton();
676 rb
->lcd_clear_display();
677 rb
->lcd_puts(0, 0, "checking...");
680 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
681 rb
->lcd_puts(0, 0, "checked:");
685 rb
->lcd_puts(0, 1, "File OK.");
688 rb
->lcd_puts(0, 1, "File not found.");
689 rb
->lcd_puts(0, 2, "Put this in root:");
690 rb
->lcd_puts_scroll(0, 4, filename
);
693 rb
->lcd_puts(0, 1, "File too big,");
694 rb
->lcd_puts(0, 2, "larger than chip.");
697 rb
->lcd_puts(0, 1, "File too small.");
698 rb
->lcd_puts(0, 2, "Incomplete?");
701 rb
->lcd_puts(0, 1, "Read error.");
704 rb
->lcd_puts(0, 1, "File invalid.");
705 rb
->lcd_puts(0, 2, "Sanity check fail.");
708 rb
->lcd_puts(0, 1, "File invalid.");
709 rb
->lcd_puts(0, 2, "CRC check failed,");
710 rb
->lcd_puts(0, 3, "checksum mismatch.");
713 rb
->lcd_puts(0, 1, "Wrong file for");
714 rb
->lcd_puts(0, 2, "this hardware.");
717 rb
->lcd_puts(0, 1, "Check failed.");
723 rb
->lcd_puts(0, 6, KEYNAME2
" to program");
724 rb
->lcd_puts(0, 7, "other key to exit");
727 { /* error occured */
728 rb
->lcd_puts(0, 6, "Any key to exit");
733 button
= WaitForButton();
734 if (button
!= KEY2
|| rc
!= eOK
)
739 rb
->lcd_clear_display();
740 rb
->lcd_puts(0, 0, "Program all Flash?");
741 rb
->lcd_puts(0, 1, "Are you sure?");
742 rb
->lcd_puts(0, 2, "If it goes wrong,");
743 rb
->lcd_puts(0, 3, "it kills your box!");
744 rb
->lcd_puts(0, 4, "See documentation.");
746 rb
->lcd_puts(0, 6, KEYNAME3
" to proceed");
747 rb
->lcd_puts(0, 7, "other key to exit");
750 button
= WaitForButton();
756 rb
->lcd_clear_display();
757 rb
->lcd_puts(0, 0, "Programming...");
760 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
763 rb
->lcd_clear_display();
764 rb
->lcd_puts(0, 0, "Panic:");
765 rb
->lcd_puts(0, 1, "Programming fail!");
766 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
767 rb
->lcd_puts(0, 2, buf
);
769 button
= WaitForButton();
772 rb
->lcd_clear_display();
773 rb
->lcd_puts(0, 0, "Verifying...");
776 rc
= VerifyFirmwareFile(filename
);
778 rb
->lcd_clear_display();
781 rb
->lcd_puts(0, 0, "Verify OK.");
785 rb
->lcd_puts(0, 0, "Panic:");
786 rb
->lcd_puts(0, 1, "Verify fail!");
787 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
788 rb
->lcd_puts(0, 2, buf
);
790 rb
->lcd_puts(0, 7, "Any key to exit");
793 button
= WaitForButton();
796 #else /* HAVE_LCD_BITMAP */
797 /* Player implementation */
799 /* helper for DoUserDialog() */
800 void ShowFlashInfo(tFlashInfo
* pInfo
)
804 if (!pInfo
->manufacturer
)
806 rb
->lcd_puts_scroll(0, 0, "Flash: M=? D=?");
807 rb
->lcd_puts_scroll(0, 1, "Impossible to program");
813 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
814 pInfo
->manufacturer
, pInfo
->id
);
815 rb
->lcd_puts_scroll(0, 0, buf
);
819 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
820 rb
->lcd_puts_scroll(0, 1, buf
);
825 rb
->lcd_puts_scroll(0, 1, "Unsupported chip");
833 void DoUserDialog(char* filename
)
835 tFlashInfo FlashInfo
;
837 char default_filename
[32];
839 int rc
; /* generic return code */
844 /* this can only work if Rockbox runs in DRAM, not flash ROM */
845 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
846 { /* we're running from flash */
847 rb
->splash(HZ
*3, "Not from ROM");
851 /* test if the user is running the correct plugin for this box */
852 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
854 rb
->splash(HZ
*3, "Wrong version");
858 /* refuse to work if the power may fail meanwhile */
859 if (!rb
->battery_level_safe())
861 rb
->splash(HZ
*3, "Batt. too low!");
866 result
= CheckBootROM();
867 if (result
== eUnknown
)
868 { /* no support for any other yet */
869 rb
->splash(HZ
*3, "Wrong boot ROM");
872 is_romless
= (result
== eROMless
);
874 /* compose filename if none given */
875 if (filename
== NULL
)
879 sizeof(default_filename
),
880 "/firmware_%s%s.bin",
882 is_romless
? "_norom" : "");
883 filename
= default_filename
;
886 /* "allocate" memory */
887 sector
= rb
->plugin_get_buffer(&memleft
);
888 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
890 rb
->splash(HZ
*3, "Out of memory");
894 rc
= GetFlashInfo(&FlashInfo
);
895 ShowFlashInfo(&FlashInfo
);
897 if (FlashInfo
.size
== 0) /* no valid chip */
902 rb
->lcd_puts_scroll(0, 0, filename
);
903 rb
->lcd_puts_scroll(0, 1, "[Menu] to check");
906 button
= WaitForButton();
907 if (button
!= BUTTON_MENU
)
912 rb
->lcd_clear_display();
913 rb
->lcd_puts(0, 0, "Checking...");
916 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
917 rb
->lcd_puts(0, 0, "Checked:");
921 rb
->lcd_puts(0, 1, "File OK.");
924 rb
->lcd_puts_scroll(0, 0, "File not found:");
925 rb
->lcd_puts_scroll(0, 1, filename
);
928 rb
->lcd_puts_scroll(0, 0, "File too big,");
929 rb
->lcd_puts_scroll(0, 1, "larger than chip.");
932 rb
->lcd_puts_scroll(0, 0, "File too small.");
933 rb
->lcd_puts_scroll(0, 1, "Incomplete?");
936 rb
->lcd_puts_scroll(0, 0, "Read error.");
939 rb
->lcd_puts_scroll(0, 0, "File invalid.");
940 rb
->lcd_puts_scroll(0, 1, "Sanity check failed.");
943 rb
->lcd_puts_scroll(0, 0, "File invalid.");
944 rb
->lcd_puts_scroll(0, 1, "CRC check failed.");
947 rb
->lcd_puts_scroll(0, 0, "Wrong file for");
948 rb
->lcd_puts_scroll(0, 1, "this hardware.");
951 rb
->lcd_puts_scroll(0, 0, "Check failed.");
960 rb
->lcd_puts_scroll(0, 0, "[On] to program,");
961 rb
->lcd_puts_scroll(0, 1, "other key to exit.");
965 { /* error occured */
969 button
= WaitForButton();
971 if (button
!= BUTTON_ON
)
976 rb
->lcd_clear_display();
977 rb
->lcd_puts_scroll(0, 0, "Are you sure?");
978 rb
->lcd_puts_scroll(0, 1, "[+] to proceed.");
981 button
= WaitForButton();
983 if (button
!= BUTTON_RIGHT
)
988 rb
->lcd_clear_display();
989 rb
->lcd_puts_scroll(0, 0, "Programming...");
992 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
996 rb
->lcd_clear_display();
997 rb
->lcd_puts_scroll(0, 0, "Programming failed!");
998 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
999 rb
->lcd_puts_scroll(0, 1, buf
);
1004 rb
->lcd_clear_display();
1005 rb
->lcd_puts_scroll(0, 0, "Verifying...");
1008 rc
= VerifyFirmwareFile(filename
);
1010 rb
->lcd_clear_display();
1014 rb
->lcd_puts_scroll(0, 0, "Verify OK.");
1018 rb
->snprintf(buf
, sizeof(buf
), "Verify failed! %d errors", rc
);
1019 rb
->lcd_puts_scroll(0, 0, buf
);
1022 rb
->lcd_puts_scroll(0, 1, "Press any key to exit.");
1027 #endif /* not HAVE_LCD_BITMAP */
1030 /***************** Plugin Entry Point *****************/
1032 enum plugin_status
plugin_start(const void* parameter
)
1036 /* now go ahead and have fun! */
1037 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
1038 DoUserDialog((char*) parameter
);
1039 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
1044 #endif /* ifdef PLATFORM_ID */