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(UNUSED_ATTR
volatile UINT8
* pAddr
)
182 volatile UINT8
* pBase
= (UINT8
*)((UINT32
)pAddr
& 0xFFF80000); /* round down to 512k align */
183 unsigned timeout
= 43000; /* the timeout loop should be no less than 25ms */
185 pBase
[0x5555] = 0xAA; /* enter command mode */
186 pBase
[0x2AAA] = 0x55;
187 pBase
[0x5555] = 0x80; /* erase command */
188 pBase
[0x5555] = 0xAA; /* enter command mode */
189 pBase
[0x2AAA] = 0x55;
190 *pAddr
= 0x30; /* erase the sector */
192 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
193 /* Plus memory waitstates it will be much more, gives margin */
194 while (*pAddr
!= 0xFF && --timeout
); /* poll for erased */
196 return (timeout
!= 0);
201 /* address must be in an erased location */
202 inline bool ProgramByte(UNUSED_ATTR
volatile UINT8
* pAddr
,
203 UNUSED_ATTR UINT8 data
)
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");
257 /*********** Utility Functions ************/
260 /* Tool function to calculate a CRC32 across some buffer */
261 /* third argument is either 0xFFFFFFFF to start or value from last piece */
262 unsigned crc_32(unsigned char* buf
, unsigned len
, unsigned crc32
)
264 /* CCITT standard polynomial 0x04C11DB7 */
265 static const unsigned crc32_lookup
[16] =
266 { /* lookup table for 4 bits at a time is affordable */
267 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
268 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
269 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
270 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
278 byte
= *buf
++; /* get one byte of data */
280 /* upper nibble of our data */
281 t
= crc32
>> 28; /* extract the 4 most significant bits */
282 t
^= byte
>> 4; /* XOR in 4 bits of data into the extracted bits */
283 crc32
<<= 4; /* shift the CRC register left 4 bits */
284 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
286 /* lower nibble of our data */
287 t
= crc32
>> 28; /* extract the 4 most significant bits */
288 t
^= byte
& 0x0F; /* XOR in 4 bits of data into the extracted bits */
289 crc32
<<= 4; /* shift the CRC register left 4 bits */
290 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
297 /*********** Firmware File Functions + helpers ************/
299 /* test if the version number is consistent with the platform */
300 bool CheckPlatform(int platform_id
, UINT16 version
)
303 { /* for my very first firmwares, I foolishly changed it to 200 */
304 return (platform_id
== ID_RECORDER
|| platform_id
== ID_FM
);
306 else if (version
== 123)
307 { /* it can be a FM or V2 recorder */
308 return (platform_id
== ID_FM
|| platform_id
== ID_REC_V2
);
310 else if (version
== 132)
311 { /* newer Ondio, and seen on a V2 recorder */
312 return (platform_id
== ID_ONDIO_SP
|| platform_id
== ID_ONDIO_FM
313 || platform_id
== ID_REC_V2
);
315 else if (version
== 104)
316 { /* classic Ondio128 */
317 return (platform_id
== ID_ONDIO_FM
);
319 else if (version
>= 115 && version
<= 129)
320 { /* the range of Recorders seen so far */
321 return (platform_id
== ID_RECORDER
);
323 else if (version
== 0 || (version
>= 300 && version
<= 508))
324 { /* for very old players, I've seen zero */
325 return (platform_id
== ID_PLAYER
);
328 return false; /* unknown */
332 tCheckResult
CheckFirmwareFile(char* filename
, int chipsize
, bool is_romless
)
336 int fileleft
; /* size info, how many left for reading */
337 int fileread
= 0; /* total size as read from the file */
338 int read_now
; /* how many to read for this sector */
339 int got_now
; /* how many gotten for this sector */
340 unsigned crc32
= 0xFFFFFFFF; /* CCITT init value */
341 unsigned file_crc
; /* CRC value read from file */
344 fd
= rb
->open(filename
, O_RDONLY
);
346 return eFileNotFound
;
348 fileleft
= rb
->filesize(fd
);
349 if (fileleft
> chipsize
)
354 else if (fileleft
< 20000) /* give it some reasonable lower limit */
360 if (fileleft
== 256*1024)
361 { /* original dumped firmware file has no CRC nor platform ID */
367 fileleft
-= sizeof(unsigned); /* exclude the last 4 bytes */
370 /* do some sanity checks */
372 got_now
= rb
->read(fd
, sector
, SEC_SIZE
); /* read first sector */
375 if (got_now
!= SEC_SIZE
)
381 /* version number in file plausible with this hardware? */
382 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(sector
+ VERSION_ADR
)))
390 crc32
= crc_32(sector
, SEC_SIZE
, crc32
); /* checksum */
392 /* in addition to the CRC, my files also have a platform ID */
393 if (sector
[PLATFORM_ADR
] != PLATFORM_ID
) /* for our hardware? */
401 { /* in this case, there is not much we can check */
402 if (*(UINT32
*)sector
!= 0x00000200) /* reset vector */
410 /* compare some bytes which have to be identical */
411 if (*(UINT32
*)sector
!= 0x41524348) /* "ARCH" */
417 for (i
= 0x30; i
<MASK_ADR
-2; i
++) /* leave two bytes for me */
419 if (sector
[i
] != FB
[i
])
427 /* check if we can read the whole file, and do checksum */
430 read_now
= MIN(SEC_SIZE
, fileleft
);
431 got_now
= rb
->read(fd
, sector
, read_now
);
435 if (read_now
!= got_now
)
443 crc32
= crc_32(sector
, got_now
, crc32
); /* checksum */
449 got_now
= rb
->read(fd
, &file_crc
, sizeof(file_crc
));
450 if (got_now
!= sizeof(file_crc
))
457 /* must be EOF now */
458 got_now
= rb
->read(fd
, sector
, SEC_SIZE
);
463 if (has_crc
&& file_crc
!= crc32
)
470 /* returns the # of failures, 0 on success */
471 unsigned ProgramFirmwareFile(char* filename
, int chipsize
)
475 int read
= SEC_SIZE
; /* how many for this sector */
476 UINT16 keep
= *(UINT16
*)(FB
+ KEEP
); /* we must keep this! */
477 unsigned failures
= 0;
479 fd
= rb
->open(filename
, O_RDONLY
);
483 for (i
=0; i
<chipsize
; i
+=SEC_SIZE
)
485 if (!EraseSector(FB
+ i
))
487 /* nothing we can do, let the programming count the errors */
490 if (read
== SEC_SIZE
) /* not EOF yet */
492 read
= rb
->read(fd
, sector
, SEC_SIZE
);
494 { /* put original value back in */
495 *(UINT16
*)(sector
+ KEEP
) = keep
;
498 for (j
=0; j
<read
; j
++)
500 if (!ProgramByte(FB
+ i
+ j
, sector
[j
]))
514 /* returns the # of failures, 0 on success */
515 unsigned VerifyFirmwareFile(char* filename
)
519 int read
= SEC_SIZE
; /* how many for this sector */
520 unsigned failures
= 0;
522 fd
= rb
->open(filename
, O_RDONLY
);
528 read
= rb
->read(fd
, sector
, SEC_SIZE
);
530 for (j
=0; j
<read
; j
++)
532 /* position of keep value is no error */
533 if (FB
[i
] != sector
[j
] && i
!= KEEP
&& i
!= (KEEP
+1))
540 while (read
== SEC_SIZE
);
548 /***************** Support Functions *****************/
550 /* check if we have "normal" boot ROM or flash mirrored to zero */
551 tCheckROM
CheckBootROM(void)
554 unsigned* pFlash
= (unsigned*)FB
;
555 unsigned* pRom
= (unsigned*)0x0;
558 boot_crc
= crc_32((unsigned char*)0x0, 64*1024, 0xFFFFFFFF);
559 if (boot_crc
== 0x56DBA4EE /* the known boot ROM */
560 #if PLATFORM_ID == ID_PLAYER
561 /* alternative boot ROM found in one single player so far */
562 || boot_crc
== 0x358099E8
567 /* check if ROM is a flash mirror */
568 for (i
=0; i
<256*1024/sizeof(unsigned); i
++)
570 if (*pRom
++ != *pFlash
++)
571 { /* difference means no mirror */
580 /***************** User Interface Functions *****************/
582 int WaitForButton(void)
588 button
= rb
->button_get(true);
589 } while (IS_SYSEVENT(button
) || (button
& BUTTON_REL
));
594 #ifdef HAVE_LCD_BITMAP
595 /* Recorder implementation */
597 /* helper for DoUserDialog() */
598 void ShowFlashInfo(tFlashInfo
* pInfo
)
602 if (!pInfo
->manufacturer
)
604 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
605 rb
->lcd_puts(0, 1, "Impossible to program");
609 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
610 pInfo
->manufacturer
, pInfo
->id
);
611 rb
->lcd_puts(0, 0, buf
);
616 rb
->lcd_puts(0, 1, pInfo
->name
);
617 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
618 rb
->lcd_puts(0, 2, buf
);
622 rb
->lcd_puts(0, 1, "Unsupported chip");
631 /* Kind of our main function, defines the application flow. */
632 void DoUserDialog(char* filename
)
634 tFlashInfo FlashInfo
;
636 char default_filename
[32];
638 int rc
; /* generic return code */
643 /* this can only work if Rockbox runs in DRAM, not flash ROM */
644 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
645 { /* we're running from flash */
646 rb
->splash(HZ
*3, "Not from ROM");
650 /* test if the user is running the correct plugin for this box */
651 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
653 rb
->splash(HZ
*3, "Wrong plugin");
657 /* refuse to work if the power may fail meanwhile */
658 if (!rb
->battery_level_safe())
660 rb
->splash(HZ
*3, "Battery too low!");
665 result
= CheckBootROM();
666 if (result
== eUnknown
)
667 { /* no support for any other yet */
668 rb
->splash(HZ
*3, "Wrong boot ROM");
671 is_romless
= (result
== eROMless
);
673 /* compose filename if none given */
674 if (filename
== NULL
)
678 sizeof(default_filename
),
679 "/firmware_%s%s.bin",
681 is_romless
? "_norom" : "");
682 filename
= default_filename
;
685 /* "allocate" memory */
686 sector
= rb
->plugin_get_buffer((size_t *)&memleft
);
687 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
689 rb
->splash(HZ
*3, "Out of memory");
693 rb
->lcd_setfont(FONT_SYSFIXED
);
695 rc
= GetFlashInfo(&FlashInfo
);
696 ShowFlashInfo(&FlashInfo
);
697 if (FlashInfo
.size
== 0) /* no valid chip */
699 rb
->splash(HZ
*3, "Sorry!");
703 rb
->lcd_puts(0, 3, "using file:");
704 rb
->lcd_puts_scroll(0, 4, filename
);
705 rb
->lcd_puts(0, 6, KEYNAME1
" to check file");
706 rb
->lcd_puts(0, 7, "other key to exit");
709 button
= WaitForButton();
715 rb
->lcd_clear_display();
716 rb
->lcd_puts(0, 0, "checking...");
719 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
720 rb
->lcd_puts(0, 0, "checked:");
724 rb
->lcd_puts(0, 1, "File OK.");
727 rb
->lcd_puts(0, 1, "File not found.");
728 rb
->lcd_puts(0, 2, "Put this in root:");
729 rb
->lcd_puts_scroll(0, 4, filename
);
732 rb
->lcd_puts(0, 1, "File too big,");
733 rb
->lcd_puts(0, 2, "larger than chip.");
736 rb
->lcd_puts(0, 1, "File too small.");
737 rb
->lcd_puts(0, 2, "Incomplete?");
740 rb
->lcd_puts(0, 1, "Read error.");
743 rb
->lcd_puts(0, 1, "File invalid.");
744 rb
->lcd_puts(0, 2, "Sanity check fail.");
747 rb
->lcd_puts(0, 1, "File invalid.");
748 rb
->lcd_puts(0, 2, "CRC check failed,");
749 rb
->lcd_puts(0, 3, "checksum mismatch.");
752 rb
->lcd_puts(0, 1, "Wrong file for");
753 rb
->lcd_puts(0, 2, "this hardware.");
756 rb
->lcd_puts(0, 1, "Check failed.");
762 rb
->lcd_puts(0, 6, KEYNAME2
" to program");
763 rb
->lcd_puts(0, 7, "other key to exit");
766 { /* error occured */
767 rb
->lcd_puts(0, 6, "Any key to exit");
772 button
= WaitForButton();
773 if (button
!= KEY2
|| rc
!= eOK
)
778 rb
->lcd_clear_display();
779 rb
->lcd_puts(0, 0, "Program all Flash?");
780 rb
->lcd_puts(0, 1, "Are you sure?");
781 rb
->lcd_puts(0, 2, "If it goes wrong,");
782 rb
->lcd_puts(0, 3, "it kills your box!");
783 rb
->lcd_puts(0, 4, "See documentation.");
785 rb
->lcd_puts(0, 6, KEYNAME3
" to proceed");
786 rb
->lcd_puts(0, 7, "other key to exit");
789 button
= WaitForButton();
795 rb
->lcd_clear_display();
796 rb
->lcd_puts(0, 0, "Programming...");
799 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
802 rb
->lcd_clear_display();
803 rb
->lcd_puts(0, 0, "Panic:");
804 rb
->lcd_puts(0, 1, "Programming fail!");
805 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
806 rb
->lcd_puts(0, 2, buf
);
808 button
= WaitForButton();
811 rb
->lcd_clear_display();
812 rb
->lcd_puts(0, 0, "Verifying...");
815 rc
= VerifyFirmwareFile(filename
);
817 rb
->lcd_clear_display();
820 rb
->lcd_puts(0, 0, "Verify OK.");
824 rb
->lcd_puts(0, 0, "Panic:");
825 rb
->lcd_puts(0, 1, "Verify fail!");
826 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
827 rb
->lcd_puts(0, 2, buf
);
829 rb
->lcd_puts(0, 7, "Any key to exit");
832 button
= WaitForButton();
835 #else /* HAVE_LCD_BITMAP */
836 /* Player implementation */
838 /* helper for DoUserDialog() */
839 void ShowFlashInfo(tFlashInfo
* pInfo
)
843 if (!pInfo
->manufacturer
)
845 rb
->lcd_puts_scroll(0, 0, "Flash: M=? D=?");
846 rb
->lcd_puts_scroll(0, 1, "Impossible to program");
852 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
853 pInfo
->manufacturer
, pInfo
->id
);
854 rb
->lcd_puts_scroll(0, 0, buf
);
858 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
859 rb
->lcd_puts_scroll(0, 1, buf
);
864 rb
->lcd_puts_scroll(0, 1, "Unsupported chip");
872 void DoUserDialog(char* filename
)
874 tFlashInfo FlashInfo
;
876 char default_filename
[32];
878 int rc
; /* generic return code */
883 /* this can only work if Rockbox runs in DRAM, not flash ROM */
884 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
885 { /* we're running from flash */
886 rb
->splash(HZ
*3, "Not from ROM");
890 /* test if the user is running the correct plugin for this box */
891 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
893 rb
->splash(HZ
*3, "Wrong version");
897 /* refuse to work if the power may fail meanwhile */
898 if (!rb
->battery_level_safe())
900 rb
->splash(HZ
*3, "Batt. too low!");
905 result
= CheckBootROM();
906 if (result
== eUnknown
)
907 { /* no support for any other yet */
908 rb
->splash(HZ
*3, "Wrong boot ROM");
911 is_romless
= (result
== eROMless
);
913 /* compose filename if none given */
914 if (filename
== NULL
)
918 sizeof(default_filename
),
919 "/firmware_%s%s.bin",
921 is_romless
? "_norom" : "");
922 filename
= default_filename
;
925 /* "allocate" memory */
926 sector
= rb
->plugin_get_buffer((size_t *)&memleft
);
927 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
929 rb
->splash(HZ
*3, "Out of memory");
933 rc
= GetFlashInfo(&FlashInfo
);
934 ShowFlashInfo(&FlashInfo
);
936 if (FlashInfo
.size
== 0) /* no valid chip */
941 rb
->lcd_puts_scroll(0, 0, filename
);
942 rb
->lcd_puts_scroll(0, 1, "[Menu] to check");
945 button
= WaitForButton();
946 if (button
!= BUTTON_MENU
)
951 rb
->lcd_clear_display();
952 rb
->lcd_puts(0, 0, "Checking...");
955 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
956 rb
->lcd_puts(0, 0, "Checked:");
960 rb
->lcd_puts(0, 1, "File OK.");
963 rb
->lcd_puts_scroll(0, 0, "File not found:");
964 rb
->lcd_puts_scroll(0, 1, filename
);
967 rb
->lcd_puts_scroll(0, 0, "File too big,");
968 rb
->lcd_puts_scroll(0, 1, "larger than chip.");
971 rb
->lcd_puts_scroll(0, 0, "File too small.");
972 rb
->lcd_puts_scroll(0, 1, "Incomplete?");
975 rb
->lcd_puts_scroll(0, 0, "Read error.");
978 rb
->lcd_puts_scroll(0, 0, "File invalid.");
979 rb
->lcd_puts_scroll(0, 1, "Sanity check failed.");
982 rb
->lcd_puts_scroll(0, 0, "File invalid.");
983 rb
->lcd_puts_scroll(0, 1, "CRC check failed.");
986 rb
->lcd_puts_scroll(0, 0, "Wrong file for");
987 rb
->lcd_puts_scroll(0, 1, "this hardware.");
990 rb
->lcd_puts_scroll(0, 0, "Check failed.");
999 rb
->lcd_puts_scroll(0, 0, "[On] to program,");
1000 rb
->lcd_puts_scroll(0, 1, "other key to exit.");
1004 { /* error occured */
1008 button
= WaitForButton();
1010 if (button
!= BUTTON_ON
)
1015 rb
->lcd_clear_display();
1016 rb
->lcd_puts_scroll(0, 0, "Are you sure?");
1017 rb
->lcd_puts_scroll(0, 1, "[+] to proceed.");
1020 button
= WaitForButton();
1022 if (button
!= BUTTON_RIGHT
)
1027 rb
->lcd_clear_display();
1028 rb
->lcd_puts_scroll(0, 0, "Programming...");
1031 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
1035 rb
->lcd_clear_display();
1036 rb
->lcd_puts_scroll(0, 0, "Programming failed!");
1037 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
1038 rb
->lcd_puts_scroll(0, 1, buf
);
1043 rb
->lcd_clear_display();
1044 rb
->lcd_puts_scroll(0, 0, "Verifying...");
1047 rc
= VerifyFirmwareFile(filename
);
1049 rb
->lcd_clear_display();
1053 rb
->lcd_puts_scroll(0, 0, "Verify OK.");
1057 rb
->snprintf(buf
, sizeof(buf
), "Verify failed! %d errors", rc
);
1058 rb
->lcd_puts_scroll(0, 0, buf
);
1061 rb
->lcd_puts_scroll(0, 1, "Press any key to exit.");
1066 #endif /* not HAVE_LCD_BITMAP */
1069 /***************** Plugin Entry Point *****************/
1071 enum plugin_status
plugin_start(UNUSED_ATTR
const void* parameter
)
1075 /* now go ahead and have fun! */
1076 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
1077 DoUserDialog((char*) parameter
);
1078 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
1083 #endif /* ifdef PLATFORM_ID */