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 #error this platform is not (yet) flashable
82 #if CONFIG_KEYPAD == ONDIO_PAD /* limited keypad */
83 #define KEY1 BUTTON_LEFT
84 #define KEY2 BUTTON_UP
85 #define KEY3 BUTTON_RIGHT
86 #define KEYNAME1 "[Left]"
87 #define KEYNAME2 "[Up]"
88 #define KEYNAME3 "[Right]"
89 #else /* recorder keypad */
90 #define KEY1 BUTTON_F1
91 #define KEY2 BUTTON_F2
92 #define KEY3 BUTTON_F3
93 #define KEYNAME1 "[F1]"
94 #define KEYNAME2 "[F2]"
95 #define KEYNAME3 "[F3]"
98 /* result of the CheckFirmwareFile() function */
102 eFileNotFound
, /* errors from here on */
111 /* result of the CheckBootROM() function */
114 eBootROM
, /* the supported boot ROM(s) */
115 eUnknown
, /* unknown boot ROM */
116 eROMless
, /* flash mapped to zero */
127 #define MASK_ADR 0xFC /* position of hardware mask value in Flash */
128 #define VERSION_ADR 0xFE /* position of firmware version value in Flash */
129 #define PLATFORM_ADR 0xFB /* position of my platform ID value in Flash */
130 #define SEC_SIZE 4096 /* size of one flash sector */
131 static UINT8
* sector
; /* better not place this on the stack... */
132 static volatile UINT8
* FB
= (UINT8
*)0x02000000; /* Flash base address */
135 /***************** Flash Functions *****************/
138 /* read the manufacturer and device ID */
139 bool ReadID(volatile UINT8
* pBase
, UINT8
* pManufacturerID
, UINT8
* pDeviceID
)
141 UINT8 not_manu
, not_id
; /* read values before switching to ID mode */
142 UINT8 manu
, id
; /* read values when in ID mode */
144 pBase
= (UINT8
*)((UINT32
)pBase
& 0xFFF80000); /* down to 512k align */
146 /* read the normal content */
147 not_manu
= pBase
[0]; /* should be 'A' (0x41) and 'R' (0x52) */
148 not_id
= pBase
[1]; /* from the "ARCH" marker */
150 pBase
[0x5555] = 0xAA; /* enter command mode */
151 pBase
[0x2AAA] = 0x55;
152 pBase
[0x5555] = 0x90; /* ID command */
153 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
158 pBase
[0] = 0xF0; /* reset flash (back to normal read mode) */
159 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
161 /* I assume success if the obtained values are different from
162 the normal flash content. This is not perfectly bulletproof, they
163 could theoretically be the same by chance, causing us to fail. */
164 if (not_manu
!= manu
|| not_id
!= id
) /* a value has changed */
166 *pManufacturerID
= manu
; /* return the results */
168 return true; /* success */
170 return false; /* fail */
174 /* erase the sector which contains the given address */
175 bool EraseSector(volatile UINT8
* pAddr
)
178 (void)pAddr
; /* prevents warning */
181 volatile UINT8
* pBase
= (UINT8
*)((UINT32
)pAddr
& 0xFFF80000); /* round down to 512k align */
182 unsigned timeout
= 43000; /* the timeout loop should be no less than 25ms */
184 pBase
[0x5555] = 0xAA; /* enter command mode */
185 pBase
[0x2AAA] = 0x55;
186 pBase
[0x5555] = 0x80; /* erase command */
187 pBase
[0x5555] = 0xAA; /* enter command mode */
188 pBase
[0x2AAA] = 0x55;
189 *pAddr
= 0x30; /* erase the sector */
191 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
192 /* Plus memory waitstates it will be much more, gives margin */
193 while (*pAddr
!= 0xFF && --timeout
); /* poll for erased */
195 return (timeout
!= 0);
200 /* address must be in an erased location */
201 inline bool ProgramByte(volatile UINT8
* pAddr
, UINT8 data
)
204 (void)pAddr
; /* prevents warnings */
208 unsigned timeout
= 35; /* the timeout loop should be no less than 20us */
210 if (~*pAddr
& data
) /* just a safety feature, not really necessary */
211 return false; /* can't set any bit from 0 to 1 */
213 FB
[0x5555] = 0xAA; /* enter command mode */
215 FB
[0x5555] = 0xA0; /* byte program command */
219 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
220 /* Plus memory waitstates it will be much more, gives margin */
221 while (*pAddr
!= data
&& --timeout
); /* poll for programmed */
223 return (timeout
!= 0);
228 /* this returns true if supported and fills the info struct */
229 bool GetFlashInfo(tFlashInfo
* pInfo
)
231 rb
->memset(pInfo
, 0, sizeof(tFlashInfo
));
233 if (!ReadID(FB
, &pInfo
->manufacturer
, &pInfo
->id
))
236 if (pInfo
->manufacturer
== 0xBF) /* SST */
238 if (pInfo
->id
== 0xD6)
240 pInfo
->size
= 256* 1024; /* 256k */
241 rb
->strcpy(pInfo
->name
, "SST39VF020");
244 else if (pInfo
->id
== 0xD7)
246 pInfo
->size
= 512* 1024; /* 512k */
247 rb
->strcpy(pInfo
->name
, "SST39VF040");
256 /*********** Firmware File Functions + helpers ************/
258 /* test if the version number is consistent with the platform */
259 bool CheckPlatform(int platform_id
, UINT16 version
)
262 { /* for my very first firmwares, I foolishly changed it to 200 */
263 return (platform_id
== ID_RECORDER
|| platform_id
== ID_FM
);
265 else if (version
== 123)
266 { /* it can be a FM or V2 recorder */
267 return (platform_id
== ID_FM
|| platform_id
== ID_REC_V2
);
269 else if (version
== 132)
270 { /* newer Ondio, and seen on a V2 recorder */
271 return (platform_id
== ID_ONDIO_SP
|| platform_id
== ID_ONDIO_FM
272 || platform_id
== ID_REC_V2
);
274 else if (version
== 104)
275 { /* classic Ondio128 */
276 return (platform_id
== ID_ONDIO_FM
);
278 else if (version
>= 115 && version
<= 129)
279 { /* the range of Recorders seen so far */
280 return (platform_id
== ID_RECORDER
);
282 else if (version
== 0 || (version
>= 300 && version
<= 508))
283 { /* for very old players, I've seen zero */
284 return (platform_id
== ID_PLAYER
);
287 return false; /* unknown */
291 tCheckResult
CheckFirmwareFile(char* filename
, int chipsize
, bool is_romless
)
295 int fileleft
; /* size info, how many left for reading */
296 int fileread
= 0; /* total size as read from the file */
297 int read_now
; /* how many to read for this sector */
298 int got_now
; /* how many gotten for this sector */
299 unsigned crc32
= 0xFFFFFFFF; /* CCITT init value */
300 unsigned file_crc
; /* CRC value read from file */
303 fd
= rb
->open(filename
, O_RDONLY
);
305 return eFileNotFound
;
307 fileleft
= rb
->filesize(fd
);
308 if (fileleft
> chipsize
)
313 else if (fileleft
< 20000) /* give it some reasonable lower limit */
319 if (fileleft
== 256*1024)
320 { /* original dumped firmware file has no CRC nor platform ID */
326 fileleft
-= sizeof(unsigned); /* exclude the last 4 bytes */
329 /* do some sanity checks */
331 got_now
= rb
->read(fd
, sector
, SEC_SIZE
); /* read first sector */
334 if (got_now
!= SEC_SIZE
)
340 /* version number in file plausible with this hardware? */
341 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(sector
+ VERSION_ADR
)))
349 crc32
= rb
->crc_32(sector
, SEC_SIZE
, crc32
); /* checksum */
351 /* in addition to the CRC, my files also have a platform ID */
352 if (sector
[PLATFORM_ADR
] != PLATFORM_ID
) /* for our hardware? */
360 { /* in this case, there is not much we can check */
361 if (*(UINT32
*)sector
!= 0x00000200) /* reset vector */
369 /* compare some bytes which have to be identical */
370 if (*(UINT32
*)sector
!= 0x41524348) /* "ARCH" */
376 for (i
= 0x30; i
<MASK_ADR
-2; i
++) /* leave two bytes for me */
378 if (sector
[i
] != FB
[i
])
386 /* check if we can read the whole file, and do checksum */
389 read_now
= MIN(SEC_SIZE
, fileleft
);
390 got_now
= rb
->read(fd
, sector
, read_now
);
394 if (read_now
!= got_now
)
402 crc32
= rb
->crc_32(sector
, got_now
, crc32
); /* checksum */
408 got_now
= rb
->read(fd
, &file_crc
, sizeof(file_crc
));
409 if (got_now
!= sizeof(file_crc
))
416 /* must be EOF now */
417 got_now
= rb
->read(fd
, sector
, SEC_SIZE
);
422 if (has_crc
&& file_crc
!= crc32
)
429 /* returns the # of failures, 0 on success */
430 unsigned ProgramFirmwareFile(char* filename
, int chipsize
)
434 int read
= SEC_SIZE
; /* how many for this sector */
435 UINT16 keep
= *(UINT16
*)(FB
+ KEEP
); /* we must keep this! */
436 unsigned failures
= 0;
438 fd
= rb
->open(filename
, O_RDONLY
);
442 for (i
=0; i
<chipsize
; i
+=SEC_SIZE
)
444 if (!EraseSector(FB
+ i
))
446 /* nothing we can do, let the programming count the errors */
449 if (read
== SEC_SIZE
) /* not EOF yet */
451 read
= rb
->read(fd
, sector
, SEC_SIZE
);
453 { /* put original value back in */
454 *(UINT16
*)(sector
+ KEEP
) = keep
;
457 for (j
=0; j
<read
; j
++)
459 if (!ProgramByte(FB
+ i
+ j
, sector
[j
]))
473 /* returns the # of failures, 0 on success */
474 unsigned VerifyFirmwareFile(char* filename
)
478 int read
= SEC_SIZE
; /* how many for this sector */
479 unsigned failures
= 0;
481 fd
= rb
->open(filename
, O_RDONLY
);
487 read
= rb
->read(fd
, sector
, SEC_SIZE
);
489 for (j
=0; j
<read
; j
++)
491 /* position of keep value is no error */
492 if (FB
[i
] != sector
[j
] && i
!= KEEP
&& i
!= (KEEP
+1))
499 while (read
== SEC_SIZE
);
507 /***************** Support Functions *****************/
509 /* check if we have "normal" boot ROM or flash mirrored to zero */
510 tCheckROM
CheckBootROM(void)
513 unsigned* pFlash
= (unsigned*)FB
;
514 unsigned* pRom
= (unsigned*)0x0;
517 boot_crc
= rb
->crc_32((unsigned char*)0x0, 64*1024, 0xFFFFFFFF);
518 if (boot_crc
== 0x56DBA4EE /* the known boot ROM */
519 #if PLATFORM_ID == ID_PLAYER
520 /* alternative boot ROM found in one single player so far */
521 || boot_crc
== 0x358099E8
526 /* check if ROM is a flash mirror */
527 for (i
=0; i
<256*1024/sizeof(unsigned); i
++)
529 if (*pRom
++ != *pFlash
++)
530 { /* difference means no mirror */
539 /***************** User Interface Functions *****************/
541 int WaitForButton(void)
547 button
= rb
->button_get(true);
548 } while (IS_SYSEVENT(button
) || (button
& BUTTON_REL
));
553 #ifdef HAVE_LCD_BITMAP
554 /* Recorder implementation */
556 /* helper for DoUserDialog() */
557 void ShowFlashInfo(tFlashInfo
* pInfo
)
559 if (!pInfo
->manufacturer
)
561 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
562 rb
->lcd_puts(0, 1, "Impossible to program");
566 rb
->lcd_putsf(0, 0, "Flash: M=%02x D=%02x",
567 pInfo
->manufacturer
, pInfo
->id
);
572 rb
->lcd_puts(0, 1, pInfo
->name
);
573 rb
->lcd_putsf(0, 2, "Size: %d KB", pInfo
->size
/ 1024);
577 rb
->lcd_puts(0, 1, "Unsupported chip");
586 /* Kind of our main function, defines the application flow. */
587 void DoUserDialog(char* filename
)
589 tFlashInfo FlashInfo
;
590 char default_filename
[32];
592 int rc
; /* generic return code */
597 /* this can only work if Rockbox runs in DRAM, not flash ROM */
598 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
599 { /* we're running from flash */
600 rb
->splash(HZ
*3, "Not from ROM");
604 /* test if the user is running the correct plugin for this box */
605 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
607 rb
->splash(HZ
*3, "Wrong plugin");
611 /* refuse to work if the power may fail meanwhile */
612 if (!rb
->battery_level_safe())
614 rb
->splash(HZ
*3, "Battery too low!");
619 result
= CheckBootROM();
620 if (result
== eUnknown
)
621 { /* no support for any other yet */
622 rb
->splash(HZ
*3, "Wrong boot ROM");
625 is_romless
= (result
== eROMless
);
627 /* compose filename if none given */
628 if (filename
== NULL
)
632 sizeof(default_filename
),
633 "/firmware_%s%s.bin",
635 is_romless
? "_norom" : "");
636 filename
= default_filename
;
639 /* "allocate" memory */
640 sector
= rb
->plugin_get_buffer(&memleft
);
641 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
643 rb
->splash(HZ
*3, "Out of memory");
647 rb
->lcd_setfont(FONT_SYSFIXED
);
649 rc
= GetFlashInfo(&FlashInfo
);
650 ShowFlashInfo(&FlashInfo
);
651 if (FlashInfo
.size
== 0) /* no valid chip */
653 rb
->splash(HZ
*3, "Sorry!");
657 rb
->lcd_puts(0, 3, "using file:");
658 rb
->lcd_puts_scroll(0, 4, filename
);
659 rb
->lcd_puts(0, 6, KEYNAME1
" to check file");
660 rb
->lcd_puts(0, 7, "other key to exit");
663 button
= WaitForButton();
669 rb
->lcd_clear_display();
670 rb
->lcd_puts(0, 0, "checking...");
673 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
674 rb
->lcd_puts(0, 0, "checked:");
678 rb
->lcd_puts(0, 1, "File OK.");
681 rb
->lcd_puts(0, 1, "File not found.");
682 rb
->lcd_puts(0, 2, "Put this in root:");
683 rb
->lcd_puts_scroll(0, 4, filename
);
686 rb
->lcd_puts(0, 1, "File too big,");
687 rb
->lcd_puts(0, 2, "larger than chip.");
690 rb
->lcd_puts(0, 1, "File too small.");
691 rb
->lcd_puts(0, 2, "Incomplete?");
694 rb
->lcd_puts(0, 1, "Read error.");
697 rb
->lcd_puts(0, 1, "File invalid.");
698 rb
->lcd_puts(0, 2, "Sanity check fail.");
701 rb
->lcd_puts(0, 1, "File invalid.");
702 rb
->lcd_puts(0, 2, "CRC check failed,");
703 rb
->lcd_puts(0, 3, "checksum mismatch.");
706 rb
->lcd_puts(0, 1, "Wrong file for");
707 rb
->lcd_puts(0, 2, "this hardware.");
710 rb
->lcd_puts(0, 1, "Check failed.");
716 rb
->lcd_puts(0, 6, KEYNAME2
" to program");
717 rb
->lcd_puts(0, 7, "other key to exit");
720 { /* error occured */
721 rb
->lcd_puts(0, 6, "Any key to exit");
726 button
= WaitForButton();
727 if (button
!= KEY2
|| rc
!= eOK
)
732 rb
->lcd_clear_display();
733 rb
->lcd_puts(0, 0, "Program all Flash?");
734 rb
->lcd_puts(0, 1, "Are you sure?");
735 rb
->lcd_puts(0, 2, "If it goes wrong,");
736 rb
->lcd_puts(0, 3, "it kills your box!");
737 rb
->lcd_puts(0, 4, "See documentation.");
739 rb
->lcd_puts(0, 6, KEYNAME3
" to proceed");
740 rb
->lcd_puts(0, 7, "other key to exit");
743 button
= WaitForButton();
749 rb
->lcd_clear_display();
750 rb
->lcd_puts(0, 0, "Programming...");
753 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
756 rb
->lcd_clear_display();
757 rb
->lcd_puts(0, 0, "Panic:");
758 rb
->lcd_puts(0, 1, "Programming fail!");
759 rb
->lcd_putsf(0, 2, "%d errors", rc
);
761 button
= WaitForButton();
764 rb
->lcd_clear_display();
765 rb
->lcd_puts(0, 0, "Verifying...");
768 rc
= VerifyFirmwareFile(filename
);
770 rb
->lcd_clear_display();
773 rb
->lcd_puts(0, 0, "Verify OK.");
777 rb
->lcd_puts(0, 0, "Panic:");
778 rb
->lcd_puts(0, 1, "Verify fail!");
779 rb
->lcd_putsf(0, 2, "%d errors", rc
);
781 rb
->lcd_puts(0, 7, "Any key to exit");
784 button
= WaitForButton();
787 #else /* HAVE_LCD_BITMAP */
788 /* Player implementation */
790 /* helper for DoUserDialog() */
791 void ShowFlashInfo(tFlashInfo
* pInfo
)
795 if (!pInfo
->manufacturer
)
797 rb
->lcd_puts_scroll(0, 0, "Flash: M=? D=?");
798 rb
->lcd_puts_scroll(0, 1, "Impossible to program");
804 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
805 pInfo
->manufacturer
, pInfo
->id
);
806 rb
->lcd_puts_scroll(0, 0, buf
);
810 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
811 rb
->lcd_puts_scroll(0, 1, buf
);
816 rb
->lcd_puts_scroll(0, 1, "Unsupported chip");
824 void DoUserDialog(char* filename
)
826 tFlashInfo FlashInfo
;
828 char default_filename
[32];
830 int rc
; /* generic return code */
835 /* this can only work if Rockbox runs in DRAM, not flash ROM */
836 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
837 { /* we're running from flash */
838 rb
->splash(HZ
*3, "Not from ROM");
842 /* test if the user is running the correct plugin for this box */
843 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
845 rb
->splash(HZ
*3, "Wrong version");
849 /* refuse to work if the power may fail meanwhile */
850 if (!rb
->battery_level_safe())
852 rb
->splash(HZ
*3, "Batt. too low!");
857 result
= CheckBootROM();
858 if (result
== eUnknown
)
859 { /* no support for any other yet */
860 rb
->splash(HZ
*3, "Wrong boot ROM");
863 is_romless
= (result
== eROMless
);
865 /* compose filename if none given */
866 if (filename
== NULL
)
870 sizeof(default_filename
),
871 "/firmware_%s%s.bin",
873 is_romless
? "_norom" : "");
874 filename
= default_filename
;
877 /* "allocate" memory */
878 sector
= rb
->plugin_get_buffer(&memleft
);
879 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
881 rb
->splash(HZ
*3, "Out of memory");
885 rc
= GetFlashInfo(&FlashInfo
);
886 ShowFlashInfo(&FlashInfo
);
888 if (FlashInfo
.size
== 0) /* no valid chip */
893 rb
->lcd_puts_scroll(0, 0, filename
);
894 rb
->lcd_puts_scroll(0, 1, "[Menu] to check");
897 button
= WaitForButton();
898 if (button
!= BUTTON_MENU
)
903 rb
->lcd_clear_display();
904 rb
->lcd_puts(0, 0, "Checking...");
907 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
908 rb
->lcd_puts(0, 0, "Checked:");
912 rb
->lcd_puts(0, 1, "File OK.");
915 rb
->lcd_puts_scroll(0, 0, "File not found:");
916 rb
->lcd_puts_scroll(0, 1, filename
);
919 rb
->lcd_puts_scroll(0, 0, "File too big,");
920 rb
->lcd_puts_scroll(0, 1, "larger than chip.");
923 rb
->lcd_puts_scroll(0, 0, "File too small.");
924 rb
->lcd_puts_scroll(0, 1, "Incomplete?");
927 rb
->lcd_puts_scroll(0, 0, "Read error.");
930 rb
->lcd_puts_scroll(0, 0, "File invalid.");
931 rb
->lcd_puts_scroll(0, 1, "Sanity check failed.");
934 rb
->lcd_puts_scroll(0, 0, "File invalid.");
935 rb
->lcd_puts_scroll(0, 1, "CRC check failed.");
938 rb
->lcd_puts_scroll(0, 0, "Wrong file for");
939 rb
->lcd_puts_scroll(0, 1, "this hardware.");
942 rb
->lcd_puts_scroll(0, 0, "Check failed.");
951 rb
->lcd_puts_scroll(0, 0, "[On] to program,");
952 rb
->lcd_puts_scroll(0, 1, "other key to exit.");
956 { /* error occured */
960 button
= WaitForButton();
962 if (button
!= BUTTON_ON
)
967 rb
->lcd_clear_display();
968 rb
->lcd_puts_scroll(0, 0, "Are you sure?");
969 rb
->lcd_puts_scroll(0, 1, "[+] to proceed.");
972 button
= WaitForButton();
974 if (button
!= BUTTON_RIGHT
)
979 rb
->lcd_clear_display();
980 rb
->lcd_puts_scroll(0, 0, "Programming...");
983 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
987 rb
->lcd_clear_display();
988 rb
->lcd_puts_scroll(0, 0, "Programming failed!");
989 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
990 rb
->lcd_puts_scroll(0, 1, buf
);
995 rb
->lcd_clear_display();
996 rb
->lcd_puts_scroll(0, 0, "Verifying...");
999 rc
= VerifyFirmwareFile(filename
);
1001 rb
->lcd_clear_display();
1005 rb
->lcd_puts_scroll(0, 0, "Verify OK.");
1009 rb
->snprintf(buf
, sizeof(buf
), "Verify failed! %d errors", rc
);
1010 rb
->lcd_puts_scroll(0, 0, buf
);
1013 rb
->lcd_puts_scroll(0, 1, "Press any key to exit.");
1018 #endif /* not HAVE_LCD_BITMAP */
1021 /***************** Plugin Entry Point *****************/
1023 enum plugin_status
plugin_start(const void* parameter
)
1027 /* now go ahead and have fun! */
1028 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
1029 DoUserDialog((char*) parameter
);
1030 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */