summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/rockbox_flash.c292
1 files changed, 240 insertions, 52 deletions
diff --git a/apps/plugins/rockbox_flash.c b/apps/plugins/rockbox_flash.c
index a6efc249af..4644521329 100644
--- a/apps/plugins/rockbox_flash.c
+++ b/apps/plugins/rockbox_flash.c
@@ -23,7 +23,9 @@
23 23
24/* Only build for target */ 24/* Only build for target */
25#ifndef SIMULATOR 25#ifndef SIMULATOR
26#ifdef HAVE_LCD_BITMAP 26
27/* define DUMMY if you only want to "play" with the UI, does no harm */
28/* #define DUMMY */
27 29
28#ifndef UINT8 30#ifndef UINT8
29#define UINT8 unsigned char 31#define UINT8 unsigned char
@@ -123,6 +125,10 @@ bool ReadID(volatile UINT8* pBase, UINT8* pManufacturerID, UINT8* pDeviceID)
123/* erase the sector which contains the given address */ 125/* erase the sector which contains the given address */
124bool EraseSector(volatile UINT8* pAddr) 126bool EraseSector(volatile UINT8* pAddr)
125{ 127{
128#ifdef DUMMY
129 (void)pAddr; /* prevents warning */
130 return true;
131#else
126 volatile UINT8* pBase = 132 volatile UINT8* pBase =
127 (UINT8*)((UINT32)pAddr & 0xFFF80000); /* round down to 512k align */ 133 (UINT8*)((UINT32)pAddr & 0xFFF80000); /* round down to 512k align */
128 unsigned timeout = 43000; /* the timeout loop should be no less than 134 unsigned timeout = 43000; /* the timeout loop should be no less than
@@ -140,11 +146,17 @@ bool EraseSector(volatile UINT8* pAddr)
140 while (*pAddr != 0xFF && --timeout); /* poll for erased */ 146 while (*pAddr != 0xFF && --timeout); /* poll for erased */
141 147
142 return (timeout != 0); 148 return (timeout != 0);
149#endif
143} 150}
144 151
145/* address must be in an erased location */ 152/* address must be in an erased location */
146inline bool ProgramByte(volatile UINT8* pAddr, UINT8 data) 153inline bool ProgramByte(volatile UINT8* pAddr, UINT8 data)
147{ 154{
155#ifdef DUMMY
156 (void)pAddr; /* prevents warnings */
157 (void)data;
158 return true;
159#else
148 unsigned timeout = 35; /* the timeout loop should be no less than 20us */ 160 unsigned timeout = 35; /* the timeout loop should be no less than 20us */
149 161
150 if (~*pAddr & data) /* just a safety feature, not really necessary */ 162 if (~*pAddr & data) /* just a safety feature, not really necessary */
@@ -161,6 +173,7 @@ inline bool ProgramByte(volatile UINT8* pAddr, UINT8 data)
161 while (*pAddr != data && --timeout); /* poll for programmed */ 173 while (*pAddr != data && --timeout); /* poll for programmed */
162 174
163 return (timeout != 0); 175 return (timeout != 0);
176#endif
164} 177}
165 178
166/* this returns true if supported and fills the info struct */ 179/* this returns true if supported and fills the info struct */
@@ -197,10 +210,10 @@ bool GetFlashInfo(tFlashInfo* pInfo)
197/* place a 32 bit value into memory, big endian */ 210/* place a 32 bit value into memory, big endian */
198void Write32(UINT8* pByte, UINT32 value) 211void Write32(UINT8* pByte, UINT32 value)
199{ 212{
200 pByte[0] = (UINT8)(value >> 24); 213 pByte[0] = (UINT8)(value >> 24);
201 pByte[1] = (UINT8)(value >> 16); 214 pByte[1] = (UINT8)(value >> 16);
202 pByte[2] = (UINT8)(value >> 8); 215 pByte[2] = (UINT8)(value >> 8);
203 pByte[3] = (UINT8)(value); 216 pByte[3] = (UINT8)(value);
204} 217}
205 218
206/* read a 32 bit value from memory, big endian */ 219/* read a 32 bit value from memory, big endian */
@@ -220,7 +233,7 @@ UINT32 Read32(UINT8* pByte)
220tImageHeader* GetSecondImage(void) 233tImageHeader* GetSecondImage(void)
221{ 234{
222 tImageHeader* pImage1; 235 tImageHeader* pImage1;
223 UINT32 pos = 0; /* default: not found */ 236 UINT32 pos = 0; /* default: not found */
224 UINT32* pFlash = (UINT32*)FB; 237 UINT32* pFlash = (UINT32*)FB;
225 238
226 UINT16 version = *(UINT16*)(FB + VERS_ADR); 239 UINT16 version = *(UINT16*)(FB + VERS_ADR);
@@ -244,8 +257,8 @@ tImageHeader* GetSecondImage(void)
244 /* success, we have a second image */ 257 /* success, we have a second image */
245 pos = (UINT32)pImage1 + sizeof(tImageHeader) + pImage1->size; 258 pos = (UINT32)pImage1 + sizeof(tImageHeader) + pImage1->size;
246 if (((pos + SECTORSIZE-1) & ~(SECTORSIZE-1)) != pos) 259 if (((pos + SECTORSIZE-1) & ~(SECTORSIZE-1)) != pos)
247 { /* not sector-aligned */ 260 { /* not sector-aligned */
248 pos = 0; // sanity check failed 261 pos = 0; /* sanity check failed */
249 } 262 }
250 } 263 }
251 264
@@ -449,7 +462,18 @@ unsigned VerifyImageFile(char* filename, UINT8* pos,
449 462
450 463
451/***************** User Interface Functions *****************/ 464/***************** User Interface Functions *****************/
452/* (to be changed for Player) */ 465
466int WaitForButton(void)
467{
468 int button;
469
470 do
471 {
472 button = rb->button_get(true);
473 } while (button & BUTTON_REL);
474
475 return button;
476}
453 477
454/* helper for DoUserDialog() */ 478/* helper for DoUserDialog() */
455void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader) 479void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader)
@@ -458,7 +482,7 @@ void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader)
458 482
459 if (!pInfo->manufacturer) 483 if (!pInfo->manufacturer)
460 { 484 {
461 rb->lcd_puts(0, 0, "Flash: M=?? D=??"); 485 rb->lcd_puts_scroll(0, 0, "Flash: M=?? D=??");
462 } 486 }
463 else 487 else
464 { 488 {
@@ -466,11 +490,11 @@ void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader)
466 { 490 {
467 rb->snprintf(buf, sizeof(buf), "Flash size: %d KB", 491 rb->snprintf(buf, sizeof(buf), "Flash size: %d KB",
468 pInfo->size / 1024); 492 pInfo->size / 1024);
469 rb->lcd_puts(0, 0, buf); 493 rb->lcd_puts_scroll(0, 0, buf);
470 } 494 }
471 else 495 else
472 { 496 {
473 rb->lcd_puts(0, 0, "Unsupported chip"); 497 rb->lcd_puts_scroll(0, 0, "Unsupported chip");
474 } 498 }
475 499
476 } 500 }
@@ -479,23 +503,23 @@ void ShowFlashInfo(tFlashInfo* pInfo, tImageHeader* pImageHeader)
479 { 503 {
480 rb->snprintf(buf, sizeof(buf), "Image at %d KB", 504 rb->snprintf(buf, sizeof(buf), "Image at %d KB",
481 ((UINT8*)pImageHeader - FB) / 1024); 505 ((UINT8*)pImageHeader - FB) / 1024);
482 rb->lcd_puts(0, 1, buf); 506 rb->lcd_puts_scroll(0, 1, buf);
483 } 507 }
484 else 508 else
485 { 509 {
486 rb->lcd_puts(0, 1, "No image found!"); 510 rb->lcd_puts_scroll(0, 1, "No image found!");
487 } 511 }
488
489 rb->lcd_update();
490} 512}
491 513
492 514
493/* Kind of our main function, defines the application flow. */ 515/* Kind of our main function, defines the application flow. */
494void DoUserDialog(char* filename) 516#ifdef HAVE_LCD_BITMAP
517/* recorder version */
518void DoUserDialog(char* filename, bool show_greet)
495{ 519{
496 tImageHeader ImageHeader; 520 tImageHeader ImageHeader;
497 tFlashInfo FlashInfo; 521 tFlashInfo FlashInfo;
498 char buf[32]; 522 static char buf[MAX_PATH];
499 int button; 523 int button;
500 int rc; /* generic return code */ 524 int rc; /* generic return code */
501 UINT32 space, aligned_size, true_size; 525 UINT32 space, aligned_size, true_size;
@@ -516,6 +540,8 @@ void DoUserDialog(char* filename)
516 rc = GetFlashInfo(&FlashInfo); 540 rc = GetFlashInfo(&FlashInfo);
517 541
518 ShowFlashInfo(&FlashInfo, (void*)pos); 542 ShowFlashInfo(&FlashInfo, (void*)pos);
543 rb->lcd_update();
544
519 if (FlashInfo.size == 0) /* no valid chip */ 545 if (FlashInfo.size == 0) /* no valid chip */
520 { 546 {
521 rb->splash(HZ*3, 0, true, "Not flashable"); 547 rb->splash(HZ*3, 0, true, "Not flashable");
@@ -523,36 +549,42 @@ void DoUserDialog(char* filename)
523 } 549 }
524 else if (pos == 0) 550 else if (pos == 0)
525 { 551 {
526 rb->splash(HZ*3, 0, true, "No Image"); 552 rb->splash(HZ*3, 0, true, "No image");
527 return; /* exit */ 553 return; /* exit */
528 } 554 }
529 555
530 rb->lcd_puts(0, 3, "using file:"); 556 if (show_greet)
531 rb->lcd_puts_scroll(0, 4, filename);
532 rb->lcd_puts(0, 6, "[F1] to check file");
533 rb->lcd_puts(0, 7, "other key to exit");
534 rb->lcd_update();
535
536 button = rb->button_get(true);
537 button = rb->button_get(true);
538
539 if (button != BUTTON_F1)
540 { 557 {
541 return; 558 rb->lcd_puts(0, 3, "using file:");
559 rb->lcd_puts_scroll(0, 4, filename);
560 rb->lcd_puts(0, 6, "[F1] to check file");
561 rb->lcd_puts(0, 7, "other key to exit");
562 rb->lcd_update();
563
564 if (WaitForButton() != BUTTON_F1)
565 {
566 return;
567 }
568 rb->lcd_clear_display();
542 } 569 }
543 570
544 rb->lcd_clear_display(); 571 rb->lcd_puts(0, show_greet ? 0 : 3, "Checking...");
545 rb->lcd_puts(0, 0, "checking...");
546 rb->lcd_update(); 572 rb->lcd_update();
547 573
548 space = FlashInfo.size - (pos-FB + sizeof(ImageHeader)); 574 space = FlashInfo.size - (pos-FB + sizeof(ImageHeader));
549 /* size minus start */ 575 /* size minus start */
550 576
551 rc = CheckImageFile(filename, space, &ImageHeader); 577 rc = CheckImageFile(filename, space, &ImageHeader);
552 rb->lcd_puts(0, 0, "checked:"); 578 if (rc != eOK)
579 {
580 rb->lcd_clear_display(); /* make room for error message */
581 show_greet = true; /* verbose */
582 }
583
584 rb->lcd_puts(0, show_greet ? 0 : 3, "Checked:");
553 switch (rc) { 585 switch (rc) {
554 case eOK: 586 case eOK:
555 rb->lcd_puts(0, 1, "File OK."); 587 rb->lcd_puts(0, show_greet ? 0 : 4, "File OK.");
556 break; 588 break;
557 case eNotUCL: 589 case eNotUCL:
558 rb->lcd_puts(0, 1, "File not UCL "); 590 rb->lcd_puts(0, 1, "File not UCL ");
@@ -592,7 +624,7 @@ void DoUserDialog(char* filename)
592 } 624 }
593 625
594 if (rc == eOK) 626 if (rc == eOK)
595 { /* was OK */ 627 { /* was OK */
596 rb->lcd_puts(0, 6, "[F2] to program"); 628 rb->lcd_puts(0, 6, "[F2] to program");
597 rb->lcd_puts(0, 7, "other key to exit"); 629 rb->lcd_puts(0, 7, "other key to exit");
598 } 630 }
@@ -600,12 +632,9 @@ void DoUserDialog(char* filename)
600 { /* error occured */ 632 { /* error occured */
601 rb->lcd_puts(0, 6, "Any key to exit"); 633 rb->lcd_puts(0, 6, "Any key to exit");
602 } 634 }
603
604 rb->lcd_update(); 635 rb->lcd_update();
605 636
606 button = rb->button_get(true); 637 button = WaitForButton();
607 button = rb->button_get(true);
608
609 if (rc != eOK || button != BUTTON_F2) 638 if (rc != eOK || button != BUTTON_F2)
610 { 639 {
611 return; 640 return;
@@ -620,24 +649,23 @@ void DoUserDialog(char* filename)
620 the next sector */ 649 the next sector */
621 650
622 rb->lcd_clear_display(); 651 rb->lcd_clear_display();
623 rb->lcd_puts(0, 0, "Programming..."); 652 rb->lcd_puts_scroll(0, 0, "Programming...");
624 rb->lcd_update(); 653 rb->lcd_update();
625 654
626 rc = ProgramImageFile(filename, pos, &ImageHeader, UCL_HEADER, true_size); 655 rc = ProgramImageFile(filename, pos, &ImageHeader, UCL_HEADER, true_size);
627 if (rc) 656 if (rc)
628 { /* errors */ 657 { /* errors */
629 rb->lcd_clear_display(); 658 rb->lcd_clear_display();
659 rb->snprintf(buf, sizeof(buf), "%d errors", rc);
630 rb->lcd_puts(0, 0, "Error:"); 660 rb->lcd_puts(0, 0, "Error:");
631 rb->lcd_puts(0, 1, "Programming fail!"); 661 rb->lcd_puts(0, 1, "Programming fail!");
632 rb->snprintf(buf, sizeof(buf), "%d errors", rc);
633 rb->lcd_puts(0, 2, buf); 662 rb->lcd_puts(0, 2, buf);
634 rb->lcd_update(); 663 rb->lcd_update();
635 button = rb->button_get(true); 664 button = WaitForButton();
636 button = rb->button_get(true);
637 } 665 }
638 666
639 rb->lcd_clear_display(); 667 rb->lcd_clear_display();
640 rb->lcd_puts(0, 0, "Verifying..."); 668 rb->lcd_puts_scroll(0, 0, "Verifying...");
641 rb->lcd_update(); 669 rb->lcd_update();
642 670
643 rc = VerifyImageFile(filename, pos, &ImageHeader, UCL_HEADER, true_size); 671 rc = VerifyImageFile(filename, pos, &ImageHeader, UCL_HEADER, true_size);
@@ -649,9 +677,9 @@ void DoUserDialog(char* filename)
649 } 677 }
650 else 678 else
651 { 679 {
680 rb->snprintf(buf, sizeof(buf), "%d errors", rc);
652 rb->lcd_puts(0, 0, "Error:"); 681 rb->lcd_puts(0, 0, "Error:");
653 rb->lcd_puts(0, 1, "Verify fail!"); 682 rb->lcd_puts(0, 1, "Verify fail!");
654 rb->snprintf(buf, sizeof(buf), "%d errors", rc);
655 rb->lcd_puts(0, 2, buf); 683 rb->lcd_puts(0, 2, buf);
656 rb->lcd_puts(0, 3, "Use safe image"); 684 rb->lcd_puts(0, 3, "Use safe image");
657 rb->lcd_puts(0, 4, "if booting hangs:"); 685 rb->lcd_puts(0, 4, "if booting hangs:");
@@ -659,16 +687,172 @@ void DoUserDialog(char* filename)
659 } 687 }
660 rb->lcd_puts(0, 7, "Any key to exit"); 688 rb->lcd_puts(0, 7, "Any key to exit");
661 rb->lcd_update(); 689 rb->lcd_update();
690 WaitForButton();
691}
692
693#else /* #ifdef HAVE_LCD_BITMAP */
694
695/* Player version */
696void DoUserDialog(char* filename, bool show_greet)
697{
698 tImageHeader ImageHeader;
699 tFlashInfo FlashInfo;
700 static char buf[MAX_PATH];
701 int button;
702 int rc; /* generic return code */
703 UINT32 space, aligned_size, true_size;
704 UINT8* pos;
705 int memleft;
706
707 /* "allocate" memory */
708 sector = rb->plugin_get_buffer(&memleft);
709 if (memleft < SECTORSIZE) /* need buffer for a flash sector */
710 {
711 rb->splash(HZ*3, 0, true, "Out of memory");
712 return; /* exit */
713 }
714
715 pos = (void*)GetSecondImage();
716 rc = GetFlashInfo(&FlashInfo);
717
718 if (show_greet)
719 {
720 ShowFlashInfo(&FlashInfo, (void*)pos);
721 WaitForButton();
722 }
723
724 if (FlashInfo.size == 0) /* no valid chip */
725 {
726 rb->splash(HZ*3, 0, true, "Not flashable");
727 return; /* exit */
728 }
729 else if (pos == 0)
730 {
731 rb->splash(HZ*3, 0, true, "No image");
732 return; /* exit */
733 }
734
735 if (show_greet)
736 {
737 rb->snprintf(buf, sizeof(buf), "File: %s", filename);
738 rb->lcd_puts_scroll(0, 0, buf);
739 rb->lcd_puts_scroll(0, 1, "[Menu] to check file, other key to exit");
740
741 if (WaitForButton() != BUTTON_MENU)
742 {
743 return;
744 }
745 rb->lcd_clear_display();
746 }
747
748 rb->lcd_puts(0, 0, "Checking...");
749
750 space = FlashInfo.size - (pos-FB + sizeof(ImageHeader));
751 /* size minus start */
662 752
663 button = rb->button_get(true); 753 rc = CheckImageFile(filename, space, &ImageHeader);
664 button = rb->button_get(true); 754 rb->lcd_puts(0, 0, "Checked:");
755 switch (rc) {
756 case eOK:
757 rb->lcd_puts(0, 1, "File OK.");
758 rb->sleep(HZ*1);
759 break;
760 case eNotUCL:
761 rb->lcd_puts_scroll(0, 1, "File not UCL compressed.");
762 break;
763 case eWrongAlgorithm:
764 rb->lcd_puts_scroll(0, 1, "Wrong compression algorithm.");
765 break;
766 case eFileNotFound:
767 rb->lcd_puts_scroll(0, 1, "File not found.");
768 break;
769 case eTooBig:
770 rb->lcd_puts_scroll(0, 1, "File too big.");
771 break;
772 case eTooSmall:
773 rb->lcd_puts_scroll(0, 1, "File too small. Incomplete?");
774 break;
775 case eReadErr:
776 rb->lcd_puts_scroll(0, 1, "File read error.");
777 break;
778 case eMultiBlocks:
779 rb->lcd_puts_scroll(0, 1, "File invalid. Blocksize too small?");
780 break;
781 default:
782 rb->lcd_puts_scroll(0, 1, "Check failed.");
783 break;
784 }
785
786 if (rc == eOK)
787 { /* was OK */
788 rb->lcd_clear_display();
789 rb->lcd_puts_scroll(0, 0, "[ON] to program,");
790 rb->lcd_puts_scroll(0, 1, "other key to exit.");
791 }
792 else
793 { /* error occured */
794 WaitForButton();
795 rb->lcd_clear_display();
796 rb->lcd_puts_scroll(0, 0, "Flash failed.");
797 rb->lcd_puts_scroll(0, 1, "Any key to exit.");
798 }
799
800 button = WaitForButton();
801 if (rc != eOK || button != BUTTON_ON)
802 {
803 return;
804 }
805
806 true_size = ImageHeader.size;
807 aligned_size = ((sizeof(tImageHeader) + true_size + SECTORSIZE-1) &
808 ~(SECTORSIZE-1)) - sizeof(tImageHeader); /* round up to
809 next flash
810 sector */
811 ImageHeader.size = aligned_size; /* increase image size such that we reach
812 the next sector */
813
814 rb->lcd_clear_display();
815 rb->lcd_puts_scroll(0, 0, "Programming...");
816
817 rc = ProgramImageFile(filename, pos, &ImageHeader, UCL_HEADER, true_size);
818 if (rc)
819 { /* errors */
820 rb->lcd_clear_display();
821 rb->snprintf(buf, sizeof(buf), "%d errors", rc);
822 rb->lcd_puts_scroll(0, 0, "Programming failed!");
823 rb->lcd_puts_scroll(0, 1, buf);
824 button = WaitForButton();
825 }
826
827 rb->lcd_clear_display();
828 rb->lcd_puts_scroll(0, 0, "Verifying...");
829
830 rc = VerifyImageFile(filename, pos, &ImageHeader, UCL_HEADER, true_size);
831
832 rb->lcd_clear_display();
833 if (rc == 0)
834 {
835 rb->lcd_puts(0, 0, "Verify OK.");
836 }
837 else
838 {
839 rb->snprintf(buf, sizeof(buf), "Verify fail! %d errors", rc);
840 rb->lcd_puts_scroll(0, 0, buf);
841 rb->lcd_puts_scroll(0, 1, "Use safe image if booting hangs: [Menu] during power-on");
842 button = WaitForButton();
843 }
665} 844}
666 845
846#endif /* not HAVE_LCD_BITMAP */
847
848
849
667/***************** Plugin Entry Point *****************/ 850/***************** Plugin Entry Point *****************/
668 851
669enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 852enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
670{ 853{
671 char* filename; 854 char* filename;
855 bool show_greet;
672 856
673 /* this macro should be called as the first thing you do in the plugin. 857 /* this macro should be called as the first thing you do in the plugin.
674 it test that the api version and model the plugin was compiled for 858 it test that the api version and model the plugin was compiled for
@@ -676,18 +860,22 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
676 TEST_PLUGIN_API(api); 860 TEST_PLUGIN_API(api);
677 861
678 if (parameter == NULL) 862 if (parameter == NULL)
863 {
679 filename = DEFAULT_FILENAME; 864 filename = DEFAULT_FILENAME;
865 show_greet = true;
866 }
680 else 867 else
868 {
681 filename = (char*) parameter; 869 filename = (char*) parameter;
870 show_greet = false;
871 }
682 872
683 rb = api; /* copy to global api pointer */ 873 rb = api; /* copy to global api pointer */
684 874
685 /* now go ahead and have fun! */ 875 /* now go ahead and have fun! */
686 DoUserDialog(filename); 876 DoUserDialog(filename, show_greet);
687 877
688 return PLUGIN_OK; 878 return PLUGIN_OK;
689} 879}
690 880
691#endif // #ifdef HAVE_LCD_BITMAP 881#endif /* #ifndef SIMULATOR */
692
693#endif // #ifndef SIMULATOR