Mercurial > flash_v2
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 } |
