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 #ifndef SIMULATOR /* only for target */
28 /* define DUMMY if you only want to "play" with the UI, does no harm */
32 #define UINT8 unsigned char
36 #define UINT16 unsigned short
40 #define UINT32 unsigned long
43 /* platform IDs as I have used them in my firmware templates */
51 /* Here I have to check for ARCHOS_* defines in source code, which is
52 generally strongly discouraged. But here I'm not checking for a certain
53 feature, I'm checking for the model itself. */
54 #if defined(ARCHOS_PLAYER)
55 #define FILE_TYPE "player"
56 #define KEEP VERSION_ADR /* keep the firmware version */
57 #define PLATFORM_ID ID_PLAYER
58 #elif defined(ARCHOS_RECORDER)
59 #define FILE_TYPE "rec"
60 #define KEEP MASK_ADR /* keep the mask value */
61 #define PLATFORM_ID ID_RECORDER
62 #elif defined(ARCHOS_RECORDERV2)
63 #define FILE_TYPE "v2"
64 #define KEEP MASK_ADR /* keep the mask value */
65 #define PLATFORM_ID ID_REC_V2
66 #elif defined(ARCHOS_FMRECORDER)
67 #define FILE_TYPE "fm"
68 #define KEEP MASK_ADR /* keep the mask value */
69 #define PLATFORM_ID ID_FM
70 #elif defined(ARCHOS_ONDIOFM)
71 #define FILE_TYPE "ondiofm"
72 #define KEEP MASK_ADR /* keep the mask value */
73 #define PLATFORM_ID ID_ONDIO_FM
74 #elif defined(ARCHOS_ONDIOSP)
75 #define FILE_TYPE "ondiosp"
76 #define KEEP MASK_ADR /* keep the mask value */
77 #define PLATFORM_ID ID_ONDIO_SP
79 #undef PLATFORM_ID /* this platform is not (yet) flashable */
86 #if CONFIG_KEYPAD == ONDIO_PAD /* limited keypad */
87 #define KEY1 BUTTON_LEFT
88 #define KEY2 BUTTON_UP
89 #define KEY3 BUTTON_RIGHT
90 #define KEYNAME1 "[Left]"
91 #define KEYNAME2 "[Up]"
92 #define KEYNAME3 "[Right]"
93 #else /* recorder keypad */
94 #define KEY1 BUTTON_F1
95 #define KEY2 BUTTON_F2
96 #define KEY3 BUTTON_F3
97 #define KEYNAME1 "[F1]"
98 #define KEYNAME2 "[F2]"
99 #define KEYNAME3 "[F3]"
102 /* result of the CheckFirmwareFile() function */
106 eFileNotFound
, /* errors from here on */
115 /* result of the CheckBootROM() function */
118 eBootROM
, /* the supported boot ROM(s) */
119 eUnknown
, /* unknown boot ROM */
120 eROMless
, /* flash mapped to zero */
131 static const struct plugin_api
* rb
; /* here is a global api struct pointer */
133 #define MASK_ADR 0xFC /* position of hardware mask value in Flash */
134 #define VERSION_ADR 0xFE /* position of firmware version value in Flash */
135 #define PLATFORM_ADR 0xFB /* position of my platform ID value in Flash */
136 #define SEC_SIZE 4096 /* size of one flash sector */
137 static UINT8
* sector
; /* better not place this on the stack... */
138 static volatile UINT8
* FB
= (UINT8
*)0x02000000; /* Flash base address */
141 /***************** Flash Functions *****************/
144 /* read the manufacturer and device ID */
145 bool ReadID(volatile UINT8
* pBase
, UINT8
* pManufacturerID
, UINT8
* pDeviceID
)
147 UINT8 not_manu
, not_id
; /* read values before switching to ID mode */
148 UINT8 manu
, id
; /* read values when in ID mode */
150 pBase
= (UINT8
*)((UINT32
)pBase
& 0xFFF80000); /* down to 512k align */
152 /* read the normal content */
153 not_manu
= pBase
[0]; /* should be 'A' (0x41) and 'R' (0x52) */
154 not_id
= pBase
[1]; /* from the "ARCH" marker */
156 pBase
[0x5555] = 0xAA; /* enter command mode */
157 pBase
[0x2AAA] = 0x55;
158 pBase
[0x5555] = 0x90; /* ID command */
159 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
164 pBase
[0] = 0xF0; /* reset flash (back to normal read mode) */
165 rb
->sleep(HZ
/50); /* Atmel wants 20ms pause here */
167 /* I assume success if the obtained values are different from
168 the normal flash content. This is not perfectly bulletproof, they
169 could theoretically be the same by chance, causing us to fail. */
170 if (not_manu
!= manu
|| not_id
!= id
) /* a value has changed */
172 *pManufacturerID
= manu
; /* return the results */
174 return true; /* success */
176 return false; /* fail */
180 /* erase the sector which contains the given address */
181 bool EraseSector(volatile UINT8
* pAddr
)
184 (void)pAddr
; /* prevents warning */
187 volatile UINT8
* pBase
= (UINT8
*)((UINT32
)pAddr
& 0xFFF80000); /* round down to 512k align */
188 unsigned timeout
= 43000; /* the timeout loop should be no less than 25ms */
190 pBase
[0x5555] = 0xAA; /* enter command mode */
191 pBase
[0x2AAA] = 0x55;
192 pBase
[0x5555] = 0x80; /* erase command */
193 pBase
[0x5555] = 0xAA; /* enter command mode */
194 pBase
[0x2AAA] = 0x55;
195 *pAddr
= 0x30; /* erase the sector */
197 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
198 /* Plus memory waitstates it will be much more, gives margin */
199 while (*pAddr
!= 0xFF && --timeout
); /* poll for erased */
201 return (timeout
!= 0);
206 /* address must be in an erased location */
207 inline bool ProgramByte(volatile UINT8
* pAddr
, UINT8 data
)
210 (void)pAddr
; /* prevents warnings */
214 unsigned timeout
= 35; /* the timeout loop should be no less than 20us */
216 if (~*pAddr
& data
) /* just a safety feature, not really necessary */
217 return false; /* can't set any bit from 0 to 1 */
219 FB
[0x5555] = 0xAA; /* enter command mode */
221 FB
[0x5555] = 0xA0; /* byte program command */
225 /* I counted 7 instructions for this loop -> min. 0.58 us per round */
226 /* Plus memory waitstates it will be much more, gives margin */
227 while (*pAddr
!= data
&& --timeout
); /* poll for programmed */
229 return (timeout
!= 0);
234 /* this returns true if supported and fills the info struct */
235 bool GetFlashInfo(tFlashInfo
* pInfo
)
237 rb
->memset(pInfo
, 0, sizeof(tFlashInfo
));
239 if (!ReadID(FB
, &pInfo
->manufacturer
, &pInfo
->id
))
242 if (pInfo
->manufacturer
== 0xBF) /* SST */
244 if (pInfo
->id
== 0xD6)
246 pInfo
->size
= 256* 1024; /* 256k */
247 rb
->strcpy(pInfo
->name
, "SST39VF020");
250 else if (pInfo
->id
== 0xD7)
252 pInfo
->size
= 512* 1024; /* 512k */
253 rb
->strcpy(pInfo
->name
, "SST39VF040");
263 /*********** Utility Functions ************/
266 /* Tool function to calculate a CRC32 across some buffer */
267 /* third argument is either 0xFFFFFFFF to start or value from last piece */
268 unsigned crc_32(unsigned char* buf
, unsigned len
, unsigned crc32
)
270 /* CCITT standard polynomial 0x04C11DB7 */
271 static const unsigned crc32_lookup
[16] =
272 { /* lookup table for 4 bits at a time is affordable */
273 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
274 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
275 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
276 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
284 byte
= *buf
++; /* get one byte of data */
286 /* upper nibble of our data */
287 t
= crc32
>> 28; /* extract the 4 most significant bits */
288 t
^= byte
>> 4; /* 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 */
292 /* lower nibble of our data */
293 t
= crc32
>> 28; /* extract the 4 most significant bits */
294 t
^= byte
& 0x0F; /* XOR in 4 bits of data into the extracted bits */
295 crc32
<<= 4; /* shift the CRC register left 4 bits */
296 crc32
^= crc32_lookup
[t
]; /* do the table lookup and XOR the result */
303 /*********** Firmware File Functions + helpers ************/
305 /* test if the version number is consistent with the platform */
306 bool CheckPlatform(int platform_id
, UINT16 version
)
309 { /* for my very first firmwares, I foolishly changed it to 200 */
310 return (platform_id
== ID_RECORDER
|| platform_id
== ID_FM
);
312 else if (version
== 123)
313 { /* it can be a FM or V2 recorder */
314 return (platform_id
== ID_FM
|| platform_id
== ID_REC_V2
);
316 else if (version
== 132)
317 { /* newer Ondio, and seen on a V2 recorder */
318 return (platform_id
== ID_ONDIO_SP
|| platform_id
== ID_ONDIO_FM
319 || platform_id
== ID_REC_V2
);
321 else if (version
== 104)
322 { /* classic Ondio128 */
323 return (platform_id
== ID_ONDIO_FM
);
325 else if (version
>= 115 && version
<= 129)
326 { /* the range of Recorders seen so far */
327 return (platform_id
== ID_RECORDER
);
329 else if (version
== 0 || (version
>= 300 && version
<= 508))
330 { /* for very old players, I've seen zero */
331 return (platform_id
== ID_PLAYER
);
334 return false; /* unknown */
338 tCheckResult
CheckFirmwareFile(char* filename
, int chipsize
, bool is_romless
)
342 int fileleft
; /* size info, how many left for reading */
343 int fileread
= 0; /* total size as read from the file */
344 int read_now
; /* how many to read for this sector */
345 int got_now
; /* how many gotten for this sector */
346 unsigned crc32
= 0xFFFFFFFF; /* CCITT init value */
347 unsigned file_crc
; /* CRC value read from file */
350 fd
= rb
->open(filename
, O_RDONLY
);
352 return eFileNotFound
;
354 fileleft
= rb
->filesize(fd
);
355 if (fileleft
> chipsize
)
360 else if (fileleft
< 20000) /* give it some reasonable lower limit */
366 if (fileleft
== 256*1024)
367 { /* original dumped firmware file has no CRC nor platform ID */
373 fileleft
-= sizeof(unsigned); /* exclude the last 4 bytes */
376 /* do some sanity checks */
378 got_now
= rb
->read(fd
, sector
, SEC_SIZE
); /* read first sector */
381 if (got_now
!= SEC_SIZE
)
387 /* version number in file plausible with this hardware? */
388 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(sector
+ VERSION_ADR
)))
396 crc32
= crc_32(sector
, SEC_SIZE
, crc32
); /* checksum */
398 /* in addition to the CRC, my files also have a platform ID */
399 if (sector
[PLATFORM_ADR
] != PLATFORM_ID
) /* for our hardware? */
407 { /* in this case, there is not much we can check */
408 if (*(UINT32
*)sector
!= 0x00000200) /* reset vector */
416 /* compare some bytes which have to be identical */
417 if (*(UINT32
*)sector
!= 0x41524348) /* "ARCH" */
423 for (i
= 0x30; i
<MASK_ADR
-2; i
++) /* leave two bytes for me */
425 if (sector
[i
] != FB
[i
])
433 /* check if we can read the whole file, and do checksum */
436 read_now
= MIN(SEC_SIZE
, fileleft
);
437 got_now
= rb
->read(fd
, sector
, read_now
);
441 if (read_now
!= got_now
)
449 crc32
= crc_32(sector
, got_now
, crc32
); /* checksum */
455 got_now
= rb
->read(fd
, &file_crc
, sizeof(file_crc
));
456 if (got_now
!= sizeof(file_crc
))
463 /* must be EOF now */
464 got_now
= rb
->read(fd
, sector
, SEC_SIZE
);
469 if (has_crc
&& file_crc
!= crc32
)
476 /* returns the # of failures, 0 on success */
477 unsigned ProgramFirmwareFile(char* filename
, int chipsize
)
481 int read
= SEC_SIZE
; /* how many for this sector */
482 UINT16 keep
= *(UINT16
*)(FB
+ KEEP
); /* we must keep this! */
483 unsigned failures
= 0;
485 fd
= rb
->open(filename
, O_RDONLY
);
489 for (i
=0; i
<chipsize
; i
+=SEC_SIZE
)
491 if (!EraseSector(FB
+ i
))
493 /* nothing we can do, let the programming count the errors */
496 if (read
== SEC_SIZE
) /* not EOF yet */
498 read
= rb
->read(fd
, sector
, SEC_SIZE
);
500 { /* put original value back in */
501 *(UINT16
*)(sector
+ KEEP
) = keep
;
504 for (j
=0; j
<read
; j
++)
506 if (!ProgramByte(FB
+ i
+ j
, sector
[j
]))
520 /* returns the # of failures, 0 on success */
521 unsigned VerifyFirmwareFile(char* filename
)
525 int read
= SEC_SIZE
; /* how many for this sector */
526 unsigned failures
= 0;
528 fd
= rb
->open(filename
, O_RDONLY
);
534 read
= rb
->read(fd
, sector
, SEC_SIZE
);
536 for (j
=0; j
<read
; j
++)
538 /* position of keep value is no error */
539 if (FB
[i
] != sector
[j
] && i
!= KEEP
&& i
!= (KEEP
+1))
546 while (read
== SEC_SIZE
);
554 /***************** Support Functions *****************/
556 /* check if we have "normal" boot ROM or flash mirrored to zero */
557 tCheckROM
CheckBootROM(void)
560 unsigned* pFlash
= (unsigned*)FB
;
561 unsigned* pRom
= (unsigned*)0x0;
564 boot_crc
= crc_32((unsigned char*)0x0, 64*1024, 0xFFFFFFFF);
565 if (boot_crc
== 0x56DBA4EE /* the known boot ROM */
566 #if PLATFORM_ID == ID_PLAYER
567 /* alternative boot ROM found in one single player so far */
568 || boot_crc
== 0x358099E8
573 /* check if ROM is a flash mirror */
574 for (i
=0; i
<256*1024/sizeof(unsigned); i
++)
576 if (*pRom
++ != *pFlash
++)
577 { /* difference means no mirror */
586 /***************** User Interface Functions *****************/
588 int WaitForButton(void)
594 button
= rb
->button_get(true);
595 } while (button
& BUTTON_REL
);
600 #ifdef HAVE_LCD_BITMAP
601 /* Recorder implementation */
603 /* helper for DoUserDialog() */
604 void ShowFlashInfo(tFlashInfo
* pInfo
)
608 if (!pInfo
->manufacturer
)
610 rb
->lcd_puts(0, 0, "Flash: M=?? D=??");
611 rb
->lcd_puts(0, 1, "Impossible to program");
615 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
616 pInfo
->manufacturer
, pInfo
->id
);
617 rb
->lcd_puts(0, 0, buf
);
622 rb
->lcd_puts(0, 1, pInfo
->name
);
623 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
624 rb
->lcd_puts(0, 2, buf
);
628 rb
->lcd_puts(0, 1, "Unsupported chip");
637 /* Kind of our main function, defines the application flow. */
638 void DoUserDialog(char* filename
)
640 tFlashInfo FlashInfo
;
642 char default_filename
[32];
644 int rc
; /* generic return code */
649 /* this can only work if Rockbox runs in DRAM, not flash ROM */
650 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
651 { /* we're running from flash */
652 rb
->splash(HZ
*3, "Not from ROM");
656 /* test if the user is running the correct plugin for this box */
657 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
659 rb
->splash(HZ
*3, "Wrong plugin");
663 /* refuse to work if the power may fail meanwhile */
664 if (!rb
->battery_level_safe())
666 rb
->splash(HZ
*3, "Battery too low!");
671 result
= CheckBootROM();
672 if (result
== eUnknown
)
673 { /* no support for any other yet */
674 rb
->splash(HZ
*3, "Wrong boot ROM");
677 is_romless
= (result
== eROMless
);
679 /* compose filename if none given */
680 if (filename
== NULL
)
684 sizeof(default_filename
),
685 "/firmware_%s%s.bin",
687 is_romless
? "_norom" : "");
688 filename
= default_filename
;
691 /* "allocate" memory */
692 sector
= rb
->plugin_get_buffer((size_t *)&memleft
);
693 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
695 rb
->splash(HZ
*3, "Out of memory");
699 rb
->lcd_setfont(FONT_SYSFIXED
);
701 rc
= GetFlashInfo(&FlashInfo
);
702 ShowFlashInfo(&FlashInfo
);
703 if (FlashInfo
.size
== 0) /* no valid chip */
705 rb
->splash(HZ
*3, "Sorry!");
709 rb
->lcd_puts(0, 3, "using file:");
710 rb
->lcd_puts_scroll(0, 4, filename
);
711 rb
->lcd_puts(0, 6, KEYNAME1
" to check file");
712 rb
->lcd_puts(0, 7, "other key to exit");
715 button
= WaitForButton();
721 rb
->lcd_clear_display();
722 rb
->lcd_puts(0, 0, "checking...");
725 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
726 rb
->lcd_puts(0, 0, "checked:");
730 rb
->lcd_puts(0, 1, "File OK.");
733 rb
->lcd_puts(0, 1, "File not found.");
734 rb
->lcd_puts(0, 2, "Put this in root:");
735 rb
->lcd_puts_scroll(0, 4, filename
);
738 rb
->lcd_puts(0, 1, "File too big,");
739 rb
->lcd_puts(0, 2, "larger than chip.");
742 rb
->lcd_puts(0, 1, "File too small.");
743 rb
->lcd_puts(0, 2, "Incomplete?");
746 rb
->lcd_puts(0, 1, "Read error.");
749 rb
->lcd_puts(0, 1, "File invalid.");
750 rb
->lcd_puts(0, 2, "Sanity check fail.");
753 rb
->lcd_puts(0, 1, "File invalid.");
754 rb
->lcd_puts(0, 2, "CRC check failed,");
755 rb
->lcd_puts(0, 3, "checksum mismatch.");
758 rb
->lcd_puts(0, 1, "Wrong file for");
759 rb
->lcd_puts(0, 2, "this hardware.");
762 rb
->lcd_puts(0, 1, "Check failed.");
768 rb
->lcd_puts(0, 6, KEYNAME2
" to program");
769 rb
->lcd_puts(0, 7, "other key to exit");
772 { /* error occured */
773 rb
->lcd_puts(0, 6, "Any key to exit");
778 button
= WaitForButton();
779 if (button
!= KEY2
|| rc
!= eOK
)
784 rb
->lcd_clear_display();
785 rb
->lcd_puts(0, 0, "Program all Flash?");
786 rb
->lcd_puts(0, 1, "Are you sure?");
787 rb
->lcd_puts(0, 2, "If it goes wrong,");
788 rb
->lcd_puts(0, 3, "it kills your box!");
789 rb
->lcd_puts(0, 4, "See documentation.");
791 rb
->lcd_puts(0, 6, KEYNAME3
" to proceed");
792 rb
->lcd_puts(0, 7, "other key to exit");
795 button
= WaitForButton();
801 rb
->lcd_clear_display();
802 rb
->lcd_puts(0, 0, "Programming...");
805 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
808 rb
->lcd_clear_display();
809 rb
->lcd_puts(0, 0, "Panic:");
810 rb
->lcd_puts(0, 1, "Programming fail!");
811 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
812 rb
->lcd_puts(0, 2, buf
);
814 button
= WaitForButton();
817 rb
->lcd_clear_display();
818 rb
->lcd_puts(0, 0, "Verifying...");
821 rc
= VerifyFirmwareFile(filename
);
823 rb
->lcd_clear_display();
826 rb
->lcd_puts(0, 0, "Verify OK.");
830 rb
->lcd_puts(0, 0, "Panic:");
831 rb
->lcd_puts(0, 1, "Verify fail!");
832 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
833 rb
->lcd_puts(0, 2, buf
);
835 rb
->lcd_puts(0, 7, "Any key to exit");
838 button
= WaitForButton();
841 #else /* HAVE_LCD_BITMAP */
842 /* Player implementation */
844 /* helper for DoUserDialog() */
845 void ShowFlashInfo(tFlashInfo
* pInfo
)
849 if (!pInfo
->manufacturer
)
851 rb
->lcd_puts_scroll(0, 0, "Flash: M=? D=?");
852 rb
->lcd_puts_scroll(0, 1, "Impossible to program");
858 rb
->snprintf(buf
, sizeof(buf
), "Flash: M=%02x D=%02x",
859 pInfo
->manufacturer
, pInfo
->id
);
860 rb
->lcd_puts_scroll(0, 0, buf
);
864 rb
->snprintf(buf
, sizeof(buf
), "Size: %d KB", pInfo
->size
/ 1024);
865 rb
->lcd_puts_scroll(0, 1, buf
);
870 rb
->lcd_puts_scroll(0, 1, "Unsupported chip");
878 void DoUserDialog(char* filename
)
880 tFlashInfo FlashInfo
;
882 char default_filename
[32];
884 int rc
; /* generic return code */
889 /* this can only work if Rockbox runs in DRAM, not flash ROM */
890 if ((UINT8
*)rb
>= FB
&& (UINT8
*)rb
< FB
+ 4096*1024) /* 4 MB max */
891 { /* we're running from flash */
892 rb
->splash(HZ
*3, "Not from ROM");
896 /* test if the user is running the correct plugin for this box */
897 if (!CheckPlatform(PLATFORM_ID
, *(UINT16
*)(FB
+ VERSION_ADR
)))
899 rb
->splash(HZ
*3, "Wrong version");
903 /* refuse to work if the power may fail meanwhile */
904 if (!rb
->battery_level_safe())
906 rb
->splash(HZ
*3, "Batt. too low!");
911 result
= CheckBootROM();
912 if (result
== eUnknown
)
913 { /* no support for any other yet */
914 rb
->splash(HZ
*3, "Wrong boot ROM");
917 is_romless
= (result
== eROMless
);
919 /* compose filename if none given */
920 if (filename
== NULL
)
924 sizeof(default_filename
),
925 "/firmware_%s%s.bin",
927 is_romless
? "_norom" : "");
928 filename
= default_filename
;
931 /* "allocate" memory */
932 sector
= rb
->plugin_get_buffer((size_t *)&memleft
);
933 if (memleft
< SEC_SIZE
) /* need buffer for a flash sector */
935 rb
->splash(HZ
*3, "Out of memory");
939 rc
= GetFlashInfo(&FlashInfo
);
940 ShowFlashInfo(&FlashInfo
);
942 if (FlashInfo
.size
== 0) /* no valid chip */
947 rb
->lcd_puts_scroll(0, 0, filename
);
948 rb
->lcd_puts_scroll(0, 1, "[Menu] to check");
951 button
= WaitForButton();
952 if (button
!= BUTTON_MENU
)
957 rb
->lcd_clear_display();
958 rb
->lcd_puts(0, 0, "Checking...");
961 rc
= CheckFirmwareFile(filename
, FlashInfo
.size
, is_romless
);
962 rb
->lcd_puts(0, 0, "Checked:");
966 rb
->lcd_puts(0, 1, "File OK.");
969 rb
->lcd_puts_scroll(0, 0, "File not found:");
970 rb
->lcd_puts_scroll(0, 1, filename
);
973 rb
->lcd_puts_scroll(0, 0, "File too big,");
974 rb
->lcd_puts_scroll(0, 1, "larger than chip.");
977 rb
->lcd_puts_scroll(0, 0, "File too small.");
978 rb
->lcd_puts_scroll(0, 1, "Incomplete?");
981 rb
->lcd_puts_scroll(0, 0, "Read error.");
984 rb
->lcd_puts_scroll(0, 0, "File invalid.");
985 rb
->lcd_puts_scroll(0, 1, "Sanity check failed.");
988 rb
->lcd_puts_scroll(0, 0, "File invalid.");
989 rb
->lcd_puts_scroll(0, 1, "CRC check failed.");
992 rb
->lcd_puts_scroll(0, 0, "Wrong file for");
993 rb
->lcd_puts_scroll(0, 1, "this hardware.");
996 rb
->lcd_puts_scroll(0, 0, "Check failed.");
1005 rb
->lcd_puts_scroll(0, 0, "[On] to program,");
1006 rb
->lcd_puts_scroll(0, 1, "other key to exit.");
1010 { /* error occured */
1014 button
= WaitForButton();
1016 if (button
!= BUTTON_ON
)
1021 rb
->lcd_clear_display();
1022 rb
->lcd_puts_scroll(0, 0, "Are you sure?");
1023 rb
->lcd_puts_scroll(0, 1, "[+] to proceed.");
1026 button
= WaitForButton();
1028 if (button
!= BUTTON_RIGHT
)
1033 rb
->lcd_clear_display();
1034 rb
->lcd_puts_scroll(0, 0, "Programming...");
1037 rc
= ProgramFirmwareFile(filename
, FlashInfo
.size
);
1041 rb
->lcd_clear_display();
1042 rb
->lcd_puts_scroll(0, 0, "Programming failed!");
1043 rb
->snprintf(buf
, sizeof(buf
), "%d errors", rc
);
1044 rb
->lcd_puts_scroll(0, 1, buf
);
1049 rb
->lcd_clear_display();
1050 rb
->lcd_puts_scroll(0, 0, "Verifying...");
1053 rc
= VerifyFirmwareFile(filename
);
1055 rb
->lcd_clear_display();
1059 rb
->lcd_puts_scroll(0, 0, "Verify OK.");
1063 rb
->snprintf(buf
, sizeof(buf
), "Verify failed! %d errors", rc
);
1064 rb
->lcd_puts_scroll(0, 0, buf
);
1067 rb
->lcd_puts_scroll(0, 1, "Press any key to exit.");
1072 #endif /* not HAVE_LCD_BITMAP */
1075 /***************** Plugin Entry Point *****************/
1077 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
1081 rb
= api
; /* copy to global api pointer */
1083 /* now go ahead and have fun! */
1084 oldmode
= rb
->system_memory_guard(MEMGUARD_NONE
); /*disable memory guard */
1085 DoUserDialog((char*) parameter
);
1086 rb
->system_memory_guard(oldmode
); /* re-enable memory guard */
1091 #endif /* ifdef PLATFORM_ID */
1092 #endif /* #ifndef SIMULATOR */