comparison packages/redboot/current/src/flash.c @ 132:0ae0bc38e387 ecos-sw-2000-10-31

Merge from eCos master repository on 2000-10-31-00:30:36-GMT
author jlarmour
date Tue, 31 Oct 2000 20:53:09 +0000
parents eb9fd8c04db3
children 289bf90c6a9b
comparison
equal deleted inserted replaced
131:8461114e4f19 132:0ae0bc38e387
68 fis_init, 68 fis_init,
69 FIS_cmds 69 FIS_cmds
70 ); 70 );
71 local_cmd_entry("list", 71 local_cmd_entry("list",
72 "Display contents of FLASH Image System [FIS]", 72 "Display contents of FLASH Image System [FIS]",
73 "", 73 "[-c]",
74 fis_list, 74 fis_list,
75 FIS_cmds 75 FIS_cmds
76 ); 76 );
77 local_cmd_entry("free", 77 local_cmd_entry("free",
78 "Display free [available] locations within FLASH Image System [FIS]", 78 "Display free [available] locations within FLASH Image System [FIS]",
106 fis_delete, 106 fis_delete,
107 FIS_cmds 107 FIS_cmds
108 ); 108 );
109 local_cmd_entry("load", 109 local_cmd_entry("load",
110 "Load image from FLASH Image System [FIS] into RAM", 110 "Load image from FLASH Image System [FIS] into RAM",
111 "name", 111 "[-b <memory_load_address>] [-c] name",
112 fis_load, 112 fis_load,
113 FIS_cmds 113 FIS_cmds
114 ); 114 );
115 local_cmd_entry("create", 115 local_cmd_entry("create",
116 "Create an image", 116 "Create an image",
127 127
128 // Local data used by these routines 128 // Local data used by these routines
129 static void *flash_start, *flash_end; 129 static void *flash_start, *flash_end;
130 static int block_size, blocks; 130 static int block_size, blocks;
131 static void *fis_work_block; 131 static void *fis_work_block;
132
133 // Simple XOR style checksum
134 static unsigned long
135 _cksum(unsigned long *buf, int len)
136 {
137 unsigned long cksum = 0;
138
139 // Round 'len' up to multiple of longwords
140 len = (len + (sizeof(unsigned long)-1)) / sizeof(unsigned long);
141 while (len-- > 0) {
142 cksum ^= *buf++;
143 }
144 return cksum;
145 }
146
147 struct fis_image_desc *
148 fis_lookup(char *name)
149 {
150 int i;
151 void *fis_addr;
152 struct fis_image_desc *img;
153
154 fis_addr = (void *)((unsigned long)flash_end - block_size);
155 memcpy(fis_work_block, fis_addr, block_size);
156 img = (struct fis_image_desc *)fis_work_block;
157 for (i = 0; i < block_size/sizeof(*img); i++, img++) {
158 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
159 return img;
160 }
161 }
162 return (struct fis_image_desc *)0;
163 }
132 164
133 static void 165 static void
134 fis_usage(char *why) 166 fis_usage(char *why)
135 { 167 {
136 printf("*** invalid 'fis' command: %s\n", why); 168 printf("*** invalid 'fis' command: %s\n", why);
203 fis_base = (void *)((unsigned long)flash_end - block_size); 235 fis_base = (void *)((unsigned long)flash_end - block_size);
204 img->flash_base = (unsigned long)fis_base; 236 img->flash_base = (unsigned long)fis_base;
205 img->mem_base = (unsigned long)fis_base; 237 img->mem_base = (unsigned long)fis_base;
206 img->size = block_size; 238 img->size = block_size;
207 img++; img_count++; 239 img++; img_count++;
240 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
241 // Insure [quietly] that the directory is unlocked before trying to update
242 flash_unlock((void *)fis_base, block_size, (void **)&err_addr);
243 #endif
208 if ((stat = flash_erase(fis_base, block_size, (void **)&err_addr)) != 0) { 244 if ((stat = flash_erase(fis_base, block_size, (void **)&err_addr)) != 0) {
209 printf(" initialization failed %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); 245 printf(" initialization failed %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
210 } else { 246 } else {
211 if ((stat = flash_program(fis_base, fis_work_block, 247 if ((stat = flash_program(fis_base, fis_work_block,
212 img_count*sizeof(*img), (void **)&err_addr)) != 0) { 248 img_count*sizeof(*img), (void **)&err_addr)) != 0) {
213 printf("Error writing image descriptors at %p: %x(%s)\n", 249 printf("Error writing image descriptors at %p: %x(%s)\n",
214 err_addr, stat, flash_errmsg(stat)); 250 err_addr, stat, flash_errmsg(stat));
215 } 251 }
216 } 252 }
253 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
254 // Insure [quietly] that the directory is locked after the update
255 flash_lock((void *)fis_base, block_size, (void **)&err_addr);
256 #endif
217 } 257 }
218 258
219 static void 259 static void
220 fis_list(int argc, char *argv[]) 260 fis_list(int argc, char *argv[])
221 { 261 {
222 struct fis_image_desc *img; 262 struct fis_image_desc *img;
223 int i; 263 int i;
264 bool show_cksums = false;
265 struct option_info opts[1];
266
267 init_opts(&opts[0], 'c', false, OPTION_ARG_TYPE_FLG,
268 (void **)&show_cksums, (bool *)0, "display checksums");
269 if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, ""))
270 {
271 return;
272 }
224 273
225 img = (struct fis_image_desc *)((unsigned long)flash_end - block_size); 274 img = (struct fis_image_desc *)((unsigned long)flash_end - block_size);
226 printf("Name FLASH addr Mem addr Length Entry point\n"); 275 printf("Name FLASH addr %s Length Entry point\n",
276 show_cksums ? "Checksum" : "Mem addr");
227 for (i = 0; i < block_size/sizeof(*img); i++, img++) { 277 for (i = 0; i < block_size/sizeof(*img); i++, img++) {
228 if (img->name[0] != (unsigned char)0xFF) { 278 if (img->name[0] != (unsigned char)0xFF) {
229 printf("%-16s 0x%08lX 0x%08lX 0x%06lX 0x%08lX\n", img->name, 279 printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", img->name,
230 img->flash_base, img->mem_base, img->size, img->entry_point); 280 img->flash_base,
281 show_cksums ? img->file_cksum : img->mem_base,
282 img->size, img->entry_point);
231 } 283 }
232 } 284 }
233 } 285 }
234 286
235 static void 287 static void
438 strcpy(img->name, name); 490 strcpy(img->name, name);
439 img->flash_base = flash_addr; 491 img->flash_base = flash_addr;
440 img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr); 492 img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr);
441 img->entry_point = entry_addr_set ? entry_addr : (unsigned long)entry_address; // Hope it's been set 493 img->entry_point = entry_addr_set ? entry_addr : (unsigned long)entry_address; // Hope it's been set
442 img->size = length; 494 img->size = length;
495 img->data_length = img_size;
496 img->file_cksum = _cksum((unsigned long *)mem_addr, img_size);
497 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
498 // Insure [quietly] that the directory is unlocked before trying to update
499 flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
500 #endif
443 if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) { 501 if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
444 printf("Error erasing at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); 502 printf("Error erasing at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
445 // Don't try to program if the erase failed 503 // Don't try to program if the erase failed
446 } else { 504 } else {
447 // Now program it 505 // Now program it
448 if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) { 506 if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) {
449 printf("Error programming at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); 507 printf("Error programming at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
450 } 508 }
451 } 509 }
510 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
511 // Insure [quietly] that the directory is locked after the update
512 flash_lock((void *)fis_addr, block_size, (void **)&err_addr);
513 #endif
452 } 514 }
453 515
454 static void 516 static void
455 fis_erase(int argc, char *argv[]) 517 fis_erase(int argc, char *argv[])
456 { 518 {
603 } 665 }
604 // Erase Data blocks (free space) 666 // Erase Data blocks (free space)
605 if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) { 667 if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
606 printf("Error erasing at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); 668 printf("Error erasing at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
607 } 669 }
670 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
671 // Insure [quietly] that the directory is unlocked before trying to update
672 flash_unlock((void *)fis_addr, block_size, (void **)&err_addr);
673 #endif
608 // Update directory 674 // Update directory
609 memset(img, 0xFF, sizeof(*img)); 675 memset(img, 0xFF, sizeof(*img));
610 if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) { 676 if ((stat = flash_erase((void *)fis_addr, block_size, (void **)&err_addr)) != 0) {
611 printf("Error erasing at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); 677 printf("Error erasing at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
612 // Don't try to program if the erase failed 678 // Don't try to program if the erase failed
614 // Now program it 680 // Now program it
615 if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) { 681 if ((stat = flash_program((void *)fis_addr, (void *)fis_work_block, block_size, (void **)&err_addr)) != 0) {
616 printf("Error programming at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); 682 printf("Error programming at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
617 } 683 }
618 } 684 }
685 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
686 // Insure [quietly] that the directory is locked after the update
687 flash_lock((void *)fis_addr, block_size, (void **)&err_addr);
688 #endif
619 } 689 }
620 690
621 static void 691 static void
622 fis_load(int argc, char *argv[]) 692 fis_load(int argc, char *argv[])
623 { 693 {
624 char *name; 694 char *name;
625 int i;
626 void *fis_addr;
627 struct fis_image_desc *img; 695 struct fis_image_desc *img;
628 bool slot_found; 696 unsigned long mem_addr;
629 697 bool mem_addr_set = false;
630 if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) 698 bool show_cksum = false;
699 struct option_info opts[2];
700
701 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
702 (void **)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
703 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
704 (void **)&show_cksum, (bool *)0, "display checksum");
705 if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
631 { 706 {
632 fis_usage("invalid arguments"); 707 fis_usage("invalid arguments");
633 return; 708 return;
634 } 709 }
635 710 if ((img = fis_lookup(name)) == (struct fis_image_desc *)0) {
636 slot_found = false;
637 fis_addr = (void *)((unsigned long)flash_end - block_size);
638 memcpy(fis_work_block, fis_addr, block_size);
639 img = (struct fis_image_desc *)fis_work_block;
640 for (i = 0; i < block_size/sizeof(*img); i++, img++) {
641 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) {
642 slot_found = true;
643 break;
644 }
645 }
646 if (!slot_found) {
647 printf("No image '%s' found\n", name); 711 printf("No image '%s' found\n", name);
648 return; 712 return;
649 } 713 }
714 if (!mem_addr_set) {
715 mem_addr = img->mem_base;
716 }
650 // Load image from FLASH into RAM 717 // Load image from FLASH into RAM
651 if ((img->mem_base < (unsigned long)ram_start) || 718 if ((mem_addr < (unsigned long)ram_start) ||
652 ((img->mem_base+img->size) >= (unsigned long)ram_end)) { 719 ((mem_addr+img->size) >= (unsigned long)ram_end)) {
653 printf("Not a loadable image\n"); 720 printf("Not a loadable image\n");
654 return; 721 return;
655 } 722 }
656 memcpy((void *)img->mem_base, (void *)img->flash_base, img->size); 723 memcpy((void *)mem_addr, (void *)img->flash_base, img->size);
657 entry_address = (unsigned long *)img->entry_point; 724 entry_address = (unsigned long *)img->entry_point;
725 if (img->file_cksum) {
726 unsigned long cksum = _cksum((unsigned long *)mem_addr, img->data_length);
727 if (cksum != img->file_cksum) {
728 printf("** Warning - checksum failure. stored: %08lx, computed: %08lx\n",
729 img->file_cksum, cksum);
730 }
731 if (show_cksum) {
732 printf("Checksum: %08lx\n", cksum);
733 }
734 }
658 } 735 }
659 736
660 static bool 737 static bool
661 do_flash_init(void) 738 do_flash_init(void)
662 { 739 {
670 printf("FLASH: driver init failed!, status: %x\n", stat); 747 printf("FLASH: driver init failed!, status: %x\n", stat);
671 return false; 748 return false;
672 } 749 }
673 flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end); 750 flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
674 flash_get_block_info(&block_size, &blocks); 751 flash_get_block_info(&block_size, &blocks);
675 printf("FLASH: %p - %p, %d blocks of %p bytes ea.\n", 752 printf("FLASH: %p - %p, %d blocks of %p bytes each.\n",
676 flash_start, flash_end, blocks, (void *)block_size); 753 flash_start, flash_end, blocks, (void *)block_size);
677 fis_work_block = (unsigned char *)(ram_end-FLASH_MIN_WORKSPACE-block_size); 754 fis_work_block = (unsigned char *)(ram_end-FLASH_MIN_WORKSPACE-block_size);
678 } 755 }
679 return true; 756 return true;
680 } 757 }
902 // be somewhat careful when accepting it. Also, the [strange] addition 979 // be somewhat careful when accepting it. Also, the [strange] addition
903 // of shifted data helps make this work even if the data layout changes 980 // of shifted data helps make this work even if the data layout changes
904 // over time. 981 // over time.
905 982
906 static unsigned long 983 static unsigned long
907 _cksum(unsigned long *buf, int len) 984 _fconfig_cksum(unsigned long *buf, int len)
908 { 985 {
909 unsigned long cksum = 0; 986 unsigned long cksum = 0;
910 int shift = 0; 987 int shift = 0;
911 988
912 // Round 'len' up to multiple of longwords 989 // Round 'len' up to multiple of longwords
991 } 1068 }
992 1069
993 done: 1070 done:
994 if (!need_update) return; 1071 if (!need_update) return;
995 config.key1 = CONFIG_KEY1; config.key2 = CONFIG_KEY2; 1072 config.key1 = CONFIG_KEY1; config.key2 = CONFIG_KEY2;
996 config.cksum = _cksum((unsigned long *)&config, sizeof(config)-sizeof(config.cksum)); 1073 config.cksum = _fconfig_cksum((unsigned long *)&config, sizeof(config)-sizeof(config.cksum));
997 cfg_base = (void *)((unsigned long)flash_end - (2*block_size)); 1074 cfg_base = (void *)((unsigned long)flash_end - (2*block_size));
998 if (verify_action("Update RedBoot non-volatile configuration")) { 1075 if (verify_action("Update RedBoot non-volatile configuration")) {
1076 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
1077 // Insure [quietly] that the config page is unlocked before trying to update
1078 flash_unlock((void *)cfg_base, block_size, (void **)&err_addr);
1079 #endif
999 if ((stat = flash_erase(cfg_base, block_size, (void **)&err_addr)) != 0) { 1080 if ((stat = flash_erase(cfg_base, block_size, (void **)&err_addr)) != 0) {
1000 printf(" initialization failed %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); 1081 printf(" initialization failed %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat));
1001 } else { 1082 } else {
1002 if ((stat = flash_program(cfg_base, (void *)&config, 1083 if ((stat = flash_program(cfg_base, (void *)&config,
1003 sizeof(config), (void **)&err_addr)) != 0) { 1084 sizeof(config), (void **)&err_addr)) != 0) {
1004 printf("Error writing config data at %p: %x(%s)\n", 1085 printf("Error writing config data at %p: %x(%s)\n",
1005 err_addr, stat, flash_errmsg(stat)); 1086 err_addr, stat, flash_errmsg(stat));
1006 } 1087 }
1007 } 1088 }
1089 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
1090 // Insure [quietly] that the config data is locked after the update
1091 flash_lock((void *)cfg_base, block_size, (void **)&err_addr);
1092 #endif
1008 } 1093 }
1009 } 1094 }
1010 1095
1011 void 1096 void
1012 flash_get_config(char *key, void *val, int type) 1097 flash_get_config(char *key, void *val, int type)
1070 config_ok = false; 1155 config_ok = false;
1071 script = (unsigned char *)0; 1156 script = (unsigned char *)0;
1072 if (!do_flash_init()) return; 1157 if (!do_flash_init()) return;
1073 cfg_base = (void *)((unsigned long)flash_end - (2*block_size)); 1158 cfg_base = (void *)((unsigned long)flash_end - (2*block_size));
1074 memcpy(&config, cfg_base, sizeof(config)); 1159 memcpy(&config, cfg_base, sizeof(config));
1075 if ((_cksum((unsigned long *)&config, sizeof(config)-sizeof(config.cksum)) != config.cksum) || 1160 if ((_fconfig_cksum((unsigned long *)&config, sizeof(config)-sizeof(config.cksum)) != config.cksum) ||
1076 (config.key1 != CONFIG_KEY1)|| (config.key2 != CONFIG_KEY2)) { 1161 (config.key1 != CONFIG_KEY1)|| (config.key2 != CONFIG_KEY2)) {
1077 printf("FLASH configuration checksum error or invalid key\n"); 1162 printf("FLASH configuration checksum error or invalid key\n");
1078 memset(&config, 0, sizeof(config)); 1163 memset(&config, 0, sizeof(config));
1079 return; 1164 return;
1080 } 1165 }