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
)
561 if (!pInfo
->manufacturer
)
563 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
564 rb
->lcd_puts(0, 1, "Impossible to program");
568 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
569 pInfo
->manufacturer
, pInfo
->id
);
570 rb
->lcd_puts(0, 0, buf
);
575 rb
->lcd_puts(0, 1, pInfo
->name
);
576 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
577 rb
->lcd_puts(0, 2, buf
);
581 rb
->lcd_puts(0, 1, "Unsupported chip");
590 /* Kind of our main function, defines the application flow. */
591 void DoUserDialog(char* filename
)
593 tFlashInfo FlashInfo
;
595 char default_filename
[32];
597 int rc
; /* generic return code */
602 /* this can only work if Rockbox runs in DRAM, not flash ROM */
603 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
604 { /* we're running from flash */
605 rb
->splash(HZ
*3, "Not from ROM");
609 /* test if the user is running the correct plugin for this box */
610 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
612 rb
->splash(HZ
*3, "Wrong plugin");
616 /* refuse to work if the power may fail meanwhile */
617 if (!rb
->battery_level_safe())
619 rb
->splash(HZ
*3, "Battery too low!");
624 result
= CheckBootROM();
625 if (result
== eUnknown
)
626 { /* no support for any other yet */
627 rb
->splash(HZ
*3, "Wrong boot ROM");
630 is_romless
= (result
== eROMless
);
632 /* compose filename if none given */
633 if (filename
== NULL
)
637 sizeof(default_filename
),
638 "/firmware_%s%s.bin",
640 is_romless
? "_norom" : "");
641 filename
= default_filename
;
644 /* "allocate" memory */
645 sector
= rb
->plugin_get_buffer(&memleft
);
646 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
648 rb
->splash(HZ
*3, "Out of memory");
652 rb
->lcd_setfont(FONT_SYSFIXED
);
654 rc
= GetFlashInfo(&FlashInfo
);
655 ShowFlashInfo(&FlashInfo
);
656 if (FlashInfo
.size
== 0) /* no valid chip */
658 rb
->splash(HZ
*3, "Sorry!");
662 rb
->lcd_puts(0, 3, "using file:");
663 rb
->lcd_puts_scroll(0, 4, filename
);
664 rb
->lcd_puts(0, 6, KEYNAME1
" to check file");
665 rb
->lcd_puts(0, 7, "other key to exit");
668 button
= WaitForButton();
674 rb
->lcd_clear_display();
675 rb
->lcd_puts(0, 0, "checking...");
678 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
679 rb
->lcd_puts(0, 0, "checked:");
683 rb
->lcd_puts(0, 1, "File OK.");
686 rb
->lcd_puts(0, 1, "File not found.");
687 rb
->lcd_puts(0, 2, "Put this in root:");
688 rb
->lcd_puts_scroll(0, 4, filename
);
691 rb
->lcd_puts(0, 1, "File too big,");
692 rb
->lcd_puts(0, 2, "larger than chip.");
695 rb
->lcd_puts(0, 1, "File too small.");
696 rb
->lcd_puts(0, 2, "Incomplete?");
699 rb
->lcd_puts(0, 1, "Read error.");
702 rb
->lcd_puts(0, 1, "File invalid.");
703 rb
->lcd_puts(0, 2, "Sanity check fail.");
706 rb
->lcd_puts(0, 1, "File invalid.");
707 rb
->lcd_puts(0, 2, "CRC check failed,");
708 rb
->lcd_puts(0, 3, "checksum mismatch.");
711 rb
->lcd_puts(0, 1, "Wrong file for");
712 rb
->lcd_puts(0, 2, "this hardware.");
715 rb
->lcd_puts(0, 1, "Check failed.");
721 rb
->lcd_puts(0, 6, KEYNAME2
" to program");
722 rb
->lcd_puts(0, 7, "other key to exit");
725 { /* error occured */
726 rb
->lcd_puts(0, 6, "Any key to exit");
731 button
= WaitForButton();
732 if (button
!= KEY2
|| rc
!= eOK
)
737 rb
->lcd_clear_display();
738 rb
->lcd_puts(0, 0, "Program all Flash?");
739 rb
->lcd_puts(0, 1, "Are you sure?");
740 rb
->lcd_puts(0, 2, "If it goes wrong,");
741 rb
->lcd_puts(0, 3, "it kills your box!");
742 rb
->lcd_puts(0, 4, "See documentation.");
744 rb
->lcd_puts(0, 6, KEYNAME3
" to proceed");
745 rb
->lcd_puts(0, 7, "other key to exit");
748 button
= WaitForButton();
754 rb
->lcd_clear_display();
755 rb
->lcd_puts(0, 0, "Programming...");
758 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
761 rb
->lcd_clear_display();
762 rb
->lcd_puts(0, 0, "Panic:");
763 rb
->lcd_puts(0, 1, "Programming fail!");
764 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
765 rb
->lcd_puts(0, 2, buf
);
767 button
= WaitForButton();
770 rb
->lcd_clear_display();
771 rb
->lcd_puts(0, 0, "Verifying...");
774 rc
= VerifyFirmwareFile(filename
);
776 rb
->lcd_clear_display();
779 rb
->lcd_puts(0, 0, "Verify OK.");
783 rb
->lcd_puts(0, 0, "Panic:");
784 rb
->lcd_puts(0, 1, "Verify fail!");
785 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
786 rb
->lcd_puts(0, 2, buf
);
788 rb
->lcd_puts(0, 7, "Any key to exit");
791 button
= WaitForButton();
794 #else /* HAVE_LCD_BITMAP */
795 /* Player implementation */
797 /* helper for DoUserDialog() */
798 void ShowFlashInfo(tFlashInfo
* pInfo
)
802 if (!pInfo
->manufacturer
)
804 rb
->lcd_puts_scroll(0, 0, "Flash: M=? D=?");
805 rb
->lcd_puts_scroll(0, 1, "Impossible to program");
811 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
812 pInfo
->manufacturer
, pInfo
->id
);
813 rb
->lcd_puts_scroll(0, 0, buf
);
817 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
818 rb
->lcd_puts_scroll(0, 1, buf
);
823 rb
->lcd_puts_scroll(0, 1, "Unsupported chip");
831 void DoUserDialog(char* filename
)
833 tFlashInfo FlashInfo
;
835 char default_filename
[32];
837 int rc
; /* generic return code */
842 /* this can only work if Rockbox runs in DRAM, not flash ROM */
843 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
844 { /* we're running from flash */
845 rb
->splash(HZ
*3, "Not from ROM");
849 /* test if the user is running the correct plugin for this box */
850 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
852 rb
->splash(HZ
*3, "Wrong version");
856 /* refuse to work if the power may fail meanwhile */
857 if (!rb
->battery_level_safe())
859 rb
->splash(HZ
*3, "Batt. too low!");
864 result
= CheckBootROM();
865 if (result
== eUnknown
)
866 { /* no support for any other yet */
867 rb
->splash(HZ
*3, "Wrong boot ROM");
870 is_romless
= (result
== eROMless
);
872 /* compose filename if none given */
873 if (filename
== NULL
)
877 sizeof(default_filename
),
878 "/firmware_%s%s.bin",
880 is_romless
? "_norom" : "");
881 filename
= default_filename
;
884 /* "allocate" memory */
885 sector
= rb
->plugin_get_buffer(&memleft
);
886 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
888 rb
->splash(HZ
*3, "Out of memory");
892 rc
= GetFlashInfo(&FlashInfo
);
893 ShowFlashInfo(&FlashInfo
);
895 if (FlashInfo
.size
== 0) /* no valid chip */
900 rb
->lcd_puts_scroll(0, 0, filename
);
901 rb
->lcd_puts_scroll(0, 1, "[Menu] to check");
904 button
= WaitForButton();
905 if (button
!= BUTTON_MENU
)
910 rb
->lcd_clear_display();
911 rb
->lcd_puts(0, 0, "Checking...");
914 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
915 rb
->lcd_puts(0, 0, "Checked:");
919 rb
->lcd_puts(0, 1, "File OK.");
922 rb
->lcd_puts_scroll(0, 0, "File not found:");
923 rb
->lcd_puts_scroll(0, 1, filename
);
926 rb
->lcd_puts_scroll(0, 0, "File too big,");
927 rb
->lcd_puts_scroll(0, 1, "larger than chip.");
930 rb
->lcd_puts_scroll(0, 0, "File too small.");
931 rb
->lcd_puts_scroll(0, 1, "Incomplete?");
934 rb
->lcd_puts_scroll(0, 0, "Read error.");
937 rb
->lcd_puts_scroll(0, 0, "File invalid.");
938 rb
->lcd_puts_scroll(0, 1, "Sanity check failed.");
941 rb
->lcd_puts_scroll(0, 0, "File invalid.");
942 rb
->lcd_puts_scroll(0, 1, "CRC check failed.");
945 rb
->lcd_puts_scroll(0, 0, "Wrong file for");
946 rb
->lcd_puts_scroll(0, 1, "this hardware.");
949 rb
->lcd_puts_scroll(0, 0, "Check failed.");
958 rb
->lcd_puts_scroll(0, 0, "[On] to program,");
959 rb
->lcd_puts_scroll(0, 1, "other key to exit.");
963 { /* error occured */
967 button
= WaitForButton();
969 if (button
!= BUTTON_ON
)
974 rb
->lcd_clear_display();
975 rb
->lcd_puts_scroll(0, 0, "Are you sure?");
976 rb
->lcd_puts_scroll(0, 1, "[+] to proceed.");
979 button
= WaitForButton();
981 if (button
!= BUTTON_RIGHT
)
986 rb
->lcd_clear_display();
987 rb
->lcd_puts_scroll(0, 0, "Programming...");
990 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
994 rb
->lcd_clear_display();
995 rb
->lcd_puts_scroll(0, 0, "Programming failed!");
996 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
997 rb
->lcd_puts_scroll(0, 1, buf
);
1002 rb
->lcd_clear_display();
1003 rb
->lcd_puts_scroll(0, 0, "Verifying...");
1006 rc
= VerifyFirmwareFile(filename
);
1008 rb
->lcd_clear_display();
1012 rb
->lcd_puts_scroll(0, 0, "Verify OK.");
1016 rb
->snprintf(buf
, sizeof(buf
), "Verify failed! %d errors", rc
);
1017 rb
->lcd_puts_scroll(0, 0, buf
);
1020 rb
->lcd_puts_scroll(0, 1, "Press any key to exit.");
1025 #endif /* not HAVE_LCD_BITMAP */
1028 /***************** Plugin Entry Point *****************/
1030 enum plugin_status
plugin_start(const void* parameter
)
1034 /* now go ahead and have fun! */
1035 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
1036 DoUserDialog((char*) parameter
);
1037 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */