comparison packages/redboot/current/src/flash.c @ 162:2395031e7a66

Merge from eCos master repository on 2001-06-15-06:43:03-BST
author jlarmour
date Fri, 15 Jun 2001 22:45:04 +0000
parents ac086aa3217e
children d63db767121d
comparison
equal deleted inserted replaced
161:ac086aa3217e 162:2395031e7a66
45 45
46 #include <redboot.h> 46 #include <redboot.h>
47 #include <cyg/io/flash.h> 47 #include <cyg/io/flash.h>
48 #include <fis.h> 48 #include <fis.h>
49 49
50 // Exported CLI functions 50 // CLI function
51 static cmd_fun do_fis; 51 static cmd_fun do_fis;
52 RedBoot_cmd("fis", 52 RedBoot_cmd("fis",
53 "Manage FLASH images", 53 "Manage FLASH images",
54 "{cmds}", 54 "{cmds}",
55 do_fis 55 do_fis
56 ); 56 );
57 57
58 // Internal commands 58 #ifdef CYGOPT_REDBOOT_FIS
59 // Image management functions
59 local_cmd_entry("init", 60 local_cmd_entry("init",
60 "Initialize FLASH Image System [FIS]", 61 "Initialize FLASH Image System [FIS]",
61 "[-f]", 62 "[-f]",
62 fis_init, 63 fis_init,
63 FIS_cmds 64 FIS_cmds
64 ); 65 );
65
66 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK 66 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
67 # define FIS_LIST_OPTS "[-c] [-d]" 67 # define FIS_LIST_OPTS "[-c] [-d]"
68 #else 68 #else
69 # define FIS_LIST_OPTS "[-d]" 69 # define FIS_LIST_OPTS "[-d]"
70 #endif 70 #endif
71
72 local_cmd_entry("list", 71 local_cmd_entry("list",
73 "Display contents of FLASH Image System [FIS]", 72 "Display contents of FLASH Image System [FIS]",
74 FIS_LIST_OPTS, 73 FIS_LIST_OPTS,
75 fis_list, 74 fis_list,
76 FIS_cmds 75 FIS_cmds
79 "Display free [available] locations within FLASH Image System [FIS]", 78 "Display free [available] locations within FLASH Image System [FIS]",
80 "", 79 "",
81 fis_free, 80 fis_free,
82 FIS_cmds 81 FIS_cmds
83 ); 82 );
83 local_cmd_entry("delete",
84 "Display an image from FLASH Image System [FIS]",
85 "name",
86 fis_delete,
87 FIS_cmds
88 );
89
90 static char fis_load_usage[] =
91 #ifdef CYGPKG_COMPRESS_ZLIB
92 "[-d] "
93 #endif
94 "[-b <memory_load_address>] [-c] name";
95
96 local_cmd_entry("load",
97 "Load image from FLASH Image System [FIS] into RAM",
98 fis_load_usage,
99 fis_load,
100 FIS_cmds
101 );
102 local_cmd_entry("create",
103 "Create an image",
104 "-b <mem_base> -l <image_length> [-s <data_length>]\n"
105 " [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
106 fis_create,
107 FIS_cmds
108 );
109 #endif
110
111 // Raw flash access functions
84 local_cmd_entry("erase", 112 local_cmd_entry("erase",
85 "Erase FLASH contents", 113 "Erase FLASH contents",
86 "-f <flash_addr> -l <length>", 114 "-f <flash_addr> -l <length>",
87 fis_erase, 115 fis_erase,
88 FIS_cmds 116 FIS_cmds
99 "-f <flash_addr> -l <length>", 127 "-f <flash_addr> -l <length>",
100 fis_unlock, 128 fis_unlock,
101 FIS_cmds 129 FIS_cmds
102 ); 130 );
103 #endif 131 #endif
104 local_cmd_entry("delete",
105 "Display an image from FLASH Image System [FIS]",
106 "name",
107 fis_delete,
108 FIS_cmds
109 );
110
111 static char fis_load_usage[] =
112 #ifdef CYGPKG_COMPRESS_ZLIB
113 "[-d] "
114 #endif
115 "[-b <memory_load_address>] [-c] name";
116
117 local_cmd_entry("load",
118 "Load image from FLASH Image System [FIS] into RAM",
119 fis_load_usage,
120 fis_load,
121 FIS_cmds
122 );
123 local_cmd_entry("create",
124 "Create an image",
125 "-b <mem_base> -l <image_length> [-s <data_length>]\n"
126 " [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
127 fis_create,
128 FIS_cmds
129 );
130 local_cmd_entry("write", 132 local_cmd_entry("write",
131 "Write raw data directly to FLASH", 133 "Write raw data directly to FLASH",
132 "-f <flash_addr> -b <mem_base> -l <image_length>", 134 "-f <flash_addr> -b <mem_base> -l <image_length>",
133 fis_write, 135 fis_write,
134 FIS_cmds 136 FIS_cmds
143 // Local data used by these routines 145 // Local data used by these routines
144 static void *flash_start, *flash_end; 146 static void *flash_start, *flash_end;
145 static int block_size, blocks; 147 static int block_size, blocks;
146 static void *fis_work_block; 148 static void *fis_work_block;
147 149
150 static void
151 fis_usage(char *why)
152 {
153 printf("*** invalid 'fis' command: %s\n", why);
154 cmd_usage(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, "fis ");
155 }
156
157 #ifdef CYGOPT_REDBOOT_FIS
148 struct fis_image_desc * 158 struct fis_image_desc *
149 fis_lookup(char *name) 159 fis_lookup(char *name)
150 { 160 {
151 int i; 161 int i;
152 void *fis_addr; 162 void *fis_addr;
159 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) { 169 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
160 return img; 170 return img;
161 } 171 }
162 } 172 }
163 return (struct fis_image_desc *)0; 173 return (struct fis_image_desc *)0;
164 }
165
166 static void
167 fis_usage(char *why)
168 {
169 printf("*** invalid 'fis' command: %s\n", why);
170 cmd_usage(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, "fis ");
171 } 174 }
172 175
173 static void 176 static void
174 fis_init(int argc, char *argv[]) 177 fis_init(int argc, char *argv[])
175 { 178 {
492 if (!length_set) { 495 if (!length_set) {
493 length_set = true; 496 length_set = true;
494 length = img->size; 497 length = img->size;
495 defaults_assumed = true; 498 defaults_assumed = true;
496 } 499 }
497 // img_size can also be handled below, set from length
498 if (!img_size_set && 0 < img->data_length) {
499 img_size_set = true;
500 img_size = img->data_length;
501 defaults_assumed = true;
502 }
503 if (!exec_addr_set) { 500 if (!exec_addr_set) {
504 // Preserve "normal" behaviour 501 // Preserve "normal" behaviour
505 exec_addr_set = true; 502 exec_addr_set = true;
506 exec_addr = flash_addr_set ? flash_addr : mem_addr; 503 exec_addr = flash_addr_set ? flash_addr : mem_addr;
507 } 504 }
646 flash_lock((void *)fis_addr, block_size, (void **)&err_addr); 643 flash_lock((void *)fis_addr, block_size, (void **)&err_addr);
647 #endif 644 #endif
648 } 645 }
649 646
650 static void 647 static void
648 fis_delete(int argc, char *argv[])
649 {
650 char *name;
651 int i, stat;
652 void *fis_addr, *err_addr;
653 struct fis_image_desc *img;
654 bool slot_found;
655
656 if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
657 {
658 fis_usage("invalid arguments");
659 return;
660 }
661
662 slot_found = false;
663 fis_addr = (void *)((unsigned long)flash_end - block_size);
664 memcpy(fis_work_block, fis_addr, block_size);
665 img = (struct fis_image_desc *)fis_work_block;
666 i = 0;
667 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
668 i++;
669 #endif
670 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
671 i++;
672 #endif
673 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
674 i++;
675 #endif
676 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
677 i++;
678 #endif
679 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
680 i++;
681 #endif
682 #if 1 // And the descriptor for the descriptor table itself
683 i++;
684 #endif
685 img += i; // Skip reserved files
686
687 for ( /* i, img */; i < block_size/sizeof(*img); i++, img++) {
688 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
689 if (!verify_action("Delete image '%s'", name)) {
690 return;
691 } else {
692 slot_found = true;
693 break;
694 }
695 }
696 }
697 if (!slot_found) {
698 printf("No image '%s' found\n", name);
699 return;
700 }
701 // Erase Data blocks (free space)
702 if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
703 printf("Error erasing at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
704 }
705 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
706 // Insure [quietly] that the directory is unlocked before trying to update
707 flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
708 #endif
709 // Update directory
710 memset(img, 0xFF, sizeof(*img));
711 if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
712 printf("Error erasing at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
713 // Don't try to program if the erase failed
714 } else {
715 // Now program it
716 if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) {
717 printf("Error programming at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
718 }
719 }
720 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
721 // Insure [quietly] that the directory is locked after the update
722 flash_lock((void *)fis_addr, block_size, (void **)&err_addr);
723 #endif
724 }
725
726 static void
727 fis_load(int argc, char *argv[])
728 {
729 char *name;
730 struct fis_image_desc *img;
731 unsigned long mem_addr;
732 bool mem_addr_set = false;
733 bool show_cksum = false;
734 struct option_info opts[3];
735 #ifdef CYGPKG_REDBOOT_FIS_CRC_CHECK
736 unsigned long cksum;
737 #endif
738 int num_options;
739 #ifdef CYGPKG_COMPRESS_ZLIB
740 bool decompress = false;
741 #endif
742
743 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
744 (void **)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
745 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
746 (void **)&show_cksum, (bool *)0, "display checksum");
747 num_options = 2;
748 #ifdef CYGPKG_COMPRESS_ZLIB
749 init_opts(&opts[2], 'd', false, OPTION_ARG_TYPE_FLG,
750 (void **)&decompress, 0, "decompress");
751 num_options++;
752 #endif
753
754 if (!scan_opts(argc, argv, 2, opts, num_options, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
755 {
756 fis_usage("invalid arguments");
757 return;
758 }
759 if ((img = fis_lookup(name)) == (struct fis_image_desc *)0) {
760 printf("No image '%s' found\n", name);
761 return;
762 }
763 if (!mem_addr_set) {
764 mem_addr = img->mem_base;
765 }
766 // Load image from FLASH into RAM
767 if ((mem_addr < (unsigned long)user_ram_start) ||
768 ((mem_addr+img->size) >= (unsigned long)user_ram_end)) {
769 printf("Not a loadable image\n");
770 return;
771 }
772 #ifdef CYGPKG_COMPRESS_ZLIB
773 if (decompress) {
774 int err;
775 _pipe_t fis_load_pipe;
776 _pipe_t* p = &fis_load_pipe;
777 p->out_buf = (unsigned char*) mem_addr;
778 p->out_size = -1;
779 p->in_buf = (unsigned char*) img->flash_base;
780 p->in_avail = img->data_length;
781
782 err = (*_dc_init)(p);
783
784 if (0 == err)
785 err = (*_dc_inflate)(p);
786
787 // Free used resources, do final translation of
788 // error value.
789 err = (*_dc_close)(p, err);
790
791 if (0 != err && p->msg) {
792 printf("decompression error: %s\n", p->msg);
793 } else {
794 printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf);
795 }
796
797 } else // dangling block
798 #endif
799 {
800 memcpy((void *)mem_addr, (void *)img->flash_base, img->data_length);
801 }
802 entry_address = (unsigned long *)img->entry_point;
803 #ifdef CYGPKG_REDBOOT_FIS_CRC_CHECK
804 cksum = crc32((unsigned char *)mem_addr, img->data_length);
805 if (show_cksum) {
806 printf("Checksum: 0x%08lx\n", cksum);
807 }
808 // When decompressing, leave CRC checking to decompressor
809 if (!decompress && img->file_cksum) {
810 if (cksum != img->file_cksum) {
811 printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n",
812 img->file_cksum, cksum);
813 }
814 }
815 #endif
816 }
817 #endif // CYGOPT_REDBOOT_FIS
818
819 static void
651 fis_write(int argc, char *argv[]) 820 fis_write(int argc, char *argv[])
652 { 821 {
653 int stat; 822 int stat;
654 unsigned long mem_addr, flash_addr, length; 823 unsigned long mem_addr, flash_addr, length;
655 bool mem_addr_set = false; 824 bool mem_addr_set = false;
669 { 838 {
670 fis_usage("invalid arguments"); 839 fis_usage("invalid arguments");
671 return; 840 return;
672 } 841 }
673 842
674 if (!mem_addr_set || !flash_addr_set || !length_set) 843 if (!mem_addr_set || !flash_addr_set || !length_set) {
675 fis_usage("required parameter missing"); 844 fis_usage("required parameter missing");
845 return;
846 }
676 847
677 // Round up length to FLASH block size 848 // Round up length to FLASH block size
678 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken 849 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
679 length = ((length + block_size - 1) / block_size) * block_size; 850 length = ((length + block_size - 1) / block_size) * block_size;
680 #endif 851 #endif
831 printf("Error unlocking at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat)); 1002 printf("Error unlocking at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
832 } 1003 }
833 } 1004 }
834 #endif 1005 #endif
835 1006
836 static void
837 fis_delete(int argc, char *argv[])
838 {
839 char *name;
840 int i, stat;
841 void *fis_addr, *err_addr;
842 struct fis_image_desc *img;
843 bool slot_found;
844
845 if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
846 {
847 fis_usage("invalid arguments");
848 return;
849 }
850
851 slot_found = false;
852 fis_addr = (void *)((unsigned long)flash_end - block_size);
853 memcpy(fis_work_block, fis_addr, block_size);
854 img = (struct fis_image_desc *)fis_work_block;
855 i = 0;
856 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
857 i++;
858 #endif
859 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
860 i++;
861 #endif
862 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
863 i++;
864 #endif
865 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
866 i++;
867 #endif
868 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
869 i++;
870 #endif
871 #if 1 // And the descriptor for the descriptor table itself
872 i++;
873 #endif
874 img += i; // Skip reserved files
875
876 for ( /* i, img */; i < block_size/sizeof(*img); i++, img++) {
877 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
878 if (!verify_action("Delete image '%s'", name)) {
879 return;
880 } else {
881 slot_found = true;
882 break;
883 }
884 }
885 }
886 if (!slot_found) {
887 printf("No image '%s' found\n", name);
888 return;
889 }
890 // Erase Data blocks (free space)
891 if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
892 printf("Error erasing at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
893 }
894 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
895 // Insure [quietly] that the directory is unlocked before trying to update
896 flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
897 #endif
898 // Update directory
899 memset(img, 0xFF, sizeof(*img));
900 if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
901 printf("Error erasing at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
902 // Don't try to program if the erase failed
903 } else {
904 // Now program it
905 if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) {
906 printf("Error programming at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat));
907 }
908 }
909 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
910 // Insure [quietly] that the directory is locked after the update
911 flash_lock((void *)fis_addr, block_size, (void **)&err_addr);
912 #endif
913 }
914
915 static void
916 fis_load(int argc, char *argv[])
917 {
918 char *name;
919 struct fis_image_desc *img;
920 unsigned long mem_addr;
921 bool mem_addr_set = false;
922 bool show_cksum = false;
923 struct option_info opts[3];
924 #ifdef CYGPKG_REDBOOT_FIS_CRC_CHECK
925 unsigned long cksum;
926 #endif
927 int num_options;
928 #ifdef CYGPKG_COMPRESS_ZLIB
929 bool decompress = false;
930 #endif
931
932 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
933 (void **)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
934 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
935 (void **)&show_cksum, (bool *)0, "display checksum");
936 num_options = 2;
937 #ifdef CYGPKG_COMPRESS_ZLIB
938 init_opts(&opts[2], 'd', false, OPTION_ARG_TYPE_FLG,
939 (void **)&decompress, 0, "decompress");
940 num_options++;
941 #endif
942
943 if (!scan_opts(argc, argv, 2, opts, num_options, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
944 {
945 fis_usage("invalid arguments");
946 return;
947 }
948 if ((img = fis_lookup(name)) == (struct fis_image_desc *)0) {
949 printf("No image '%s' found\n", name);
950 return;
951 }
952 if (!mem_addr_set) {
953 mem_addr = img->mem_base;
954 }
955 // Load image from FLASH into RAM
956 if ((mem_addr < (unsigned long)user_ram_start) ||
957 ((mem_addr+img->size) >= (unsigned long)user_ram_end)) {
958 printf("Not a loadable image\n");
959 return;
960 }
961 #ifdef CYGPKG_COMPRESS_ZLIB
962 if (decompress) {
963 int err;
964 _pipe_t fis_load_pipe;
965 _pipe_t* p = &fis_load_pipe;
966 p->out_buf = (unsigned char*) mem_addr;
967 p->out_size = -1;
968 p->in_buf = (unsigned char*) img->flash_base;
969 p->in_avail = img->data_length;
970
971 err = (*_dc_init)(p);
972
973 if (0 == err)
974 err = (*_dc_inflate)(p);
975
976 // Free used resources, do final translation of
977 // error value.
978 err = (*_dc_close)(p, err);
979
980 if (0 != err && p->msg) {
981 printf("decompression error: %s\n", p->msg);
982 } else {
983 printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf);
984 }
985
986 } else // dangling block
987 #endif
988 {
989 memcpy((void *)mem_addr, (void *)img->flash_base, img->data_length);
990 }
991 entry_address = (unsigned long *)img->entry_point;
992 #ifdef CYGPKG_REDBOOT_FIS_CRC_CHECK
993 cksum = crc32((unsigned char *)mem_addr, img->data_length);
994 if (show_cksum) {
995 printf("Checksum: 0x%08lx\n", cksum);
996 }
997 // When decompressing, leave CRC checking to decompressor
998 if (!decompress && img->file_cksum) {
999 if (cksum != img->file_cksum) {
1000 printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n",
1001 img->file_cksum, cksum);
1002 }
1003 }
1004 #endif
1005 }
1006
1007 static bool 1007 static bool
1008 do_flash_init(void) 1008 do_flash_init(void)
1009 { 1009 {
1010 int stat; 1010 int stat;
1011 static int init = 0; 1011 static int init = 0;
1012 1012
1013 if (!init) { 1013 if (!init) {
1014 init = 1; 1014 init = 1;
1015 if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE), 1015 if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE),
1016 FLASH_MIN_WORKSPACE)) != 0) { 1016 FLASH_MIN_WORKSPACE, printf)) != 0) {
1017 printf("FLASH: driver init failed!, status: 0x%x\n", stat); 1017 printf("FLASH: driver init failed!, status: 0x%x\n", stat);
1018 return false; 1018 return false;
1019 } 1019 }
1020 flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end); 1020 flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
1021 flash_get_block_info(&block_size, &blocks); 1021 flash_get_block_info(&block_size, &blocks);