Mercurial > ecos
comparison packages/redboot/current/src/flash.c @ 130:eb9fd8c04db3 ecos-sw-2000-10-23
Merge from eCos master repository on 2000-10-23-17:01:37-BST
| author | jlarmour |
|---|---|
| date | Mon, 23 Oct 2000 17:10:57 +0000 |
| parents | 518f42066aba |
| children | 0ae0bc38e387 |
comparison
equal
deleted
inserted
replaced
| 129:605a0fc6f385 | 130:eb9fd8c04db3 |
|---|---|
| 43 // | 43 // |
| 44 //========================================================================== | 44 //========================================================================== |
| 45 | 45 |
| 46 #include <redboot.h> | 46 #include <redboot.h> |
| 47 #include <cyg/io/flash.h> | 47 #include <cyg/io/flash.h> |
| 48 | 48 #include <fis.h> |
| 49 struct image_desc { | |
| 50 unsigned char name[16]; // Null terminated name | |
| 51 unsigned long flash_base; // Address within FLASH of image | |
| 52 unsigned long mem_base; // Address in memory where it executes | |
| 53 unsigned long size; // Length of image | |
| 54 unsigned long entry_point; // Execution entry point | |
| 55 unsigned char _pad[256-40]; | |
| 56 unsigned long desc_cksum; // Checksum over image descriptor | |
| 57 unsigned long file_cksum; // Checksum over image data | |
| 58 }; | |
| 59 | 49 |
| 60 // Exported CLI functions | 50 // Exported CLI functions |
| 61 RedBoot_cmd("fis", | 51 RedBoot_cmd("fis", |
| 62 "Manage FLASH images", | 52 "Manage FLASH images", |
| 63 "{cmds}", | 53 "{cmds}", |
| 122 fis_load, | 112 fis_load, |
| 123 FIS_cmds | 113 FIS_cmds |
| 124 ); | 114 ); |
| 125 local_cmd_entry("create", | 115 local_cmd_entry("create", |
| 126 "Create an image", | 116 "Create an image", |
| 127 "-b <mem_base> -l <length> [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] <name>", | 117 "-b <mem_base> -l <image_length> [-s <data_length>] [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] <name>", |
| 128 fis_create, | 118 fis_create, |
| 129 FIS_cmds | 119 FIS_cmds |
| 130 ); | 120 ); |
| 131 | 121 |
| 132 // Define table boundaries | 122 // Define table boundaries |
| 149 | 139 |
| 150 static void | 140 static void |
| 151 fis_init(int argc, char *argv[]) | 141 fis_init(int argc, char *argv[]) |
| 152 { | 142 { |
| 153 int stat, img_count = 0; | 143 int stat, img_count = 0; |
| 154 struct image_desc *img; | 144 struct fis_image_desc *img; |
| 155 void *fis_base, *err_addr; | 145 void *fis_base, *err_addr; |
| 156 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG | 146 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG |
| 157 void *cfg_base; | 147 void *cfg_base; |
| 158 #endif | 148 #endif |
| 159 bool full_init = false; | 149 bool full_init = false; |
| 160 struct option_info opts[1]; | 150 struct option_info opts[1]; |
| 151 unsigned long redboot_image_size; | |
| 161 | 152 |
| 162 init_opts(&opts[0], 'f', false, OPTION_ARG_TYPE_FLG, | 153 init_opts(&opts[0], 'f', false, OPTION_ARG_TYPE_FLG, |
| 163 (void **)&full_init, (bool *)0, "full initialization, erases all of flash"); | 154 (void **)&full_init, (bool *)0, "full initialization, erases all of flash"); |
| 164 if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, "")) | 155 if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, "")) |
| 165 { | 156 { |
| 178 } | 169 } |
| 179 } else { | 170 } else { |
| 180 printf(" Warning: device contents not erased, some blocks may not be usable\n"); | 171 printf(" Warning: device contents not erased, some blocks may not be usable\n"); |
| 181 } | 172 } |
| 182 // Create a pseudo image for RedBoot | 173 // Create a pseudo image for RedBoot |
| 183 img = (struct image_desc *)fis_work_block; | 174 #define MIN_REDBOOT_IMAGE_SIZE 0x20000 |
| 175 redboot_image_size = block_size > MIN_REDBOOT_IMAGE_SIZE ? block_size : MIN_REDBOOT_IMAGE_SIZE; | |
| 176 img = (struct fis_image_desc *)fis_work_block; | |
| 184 memset(img, 0, sizeof(*img)); | 177 memset(img, 0, sizeof(*img)); |
| 185 strcpy(img->name, "RedBoot"); | 178 strcpy(img->name, "RedBoot"); |
| 186 img->flash_base = (unsigned long)flash_start; | 179 img->flash_base = (unsigned long)flash_start; |
| 187 img->mem_base = (unsigned long)flash_start; | 180 img->mem_base = (unsigned long)flash_start; |
| 188 img->size = block_size; | 181 img->size = redboot_image_size; |
| 189 img++; img_count++; | 182 img++; img_count++; |
| 190 // And a backup image | 183 // And a backup image |
| 191 memset(img, 0, sizeof(*img)); | 184 memset(img, 0, sizeof(*img)); |
| 192 strcpy(img->name, "RedBoot[backup]"); | 185 strcpy(img->name, "RedBoot[backup]"); |
| 193 img->flash_base = (unsigned long)flash_start+block_size; | 186 img->flash_base = (unsigned long)flash_start+redboot_image_size; |
| 194 img->mem_base = (unsigned long)flash_start+block_size; | 187 img->mem_base = (unsigned long)flash_start+redboot_image_size; |
| 195 img->size = block_size; | 188 img->size = redboot_image_size; |
| 196 img++; img_count++; | 189 img++; img_count++; |
| 197 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG | 190 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG |
| 198 // And a descriptor for the configuration data | 191 // And a descriptor for the configuration data |
| 199 memset(img, 0, sizeof(*img)); | 192 memset(img, 0, sizeof(*img)); |
| 200 strcpy(img->name, "RedBoot config"); | 193 strcpy(img->name, "RedBoot config"); |
| 224 } | 217 } |
| 225 | 218 |
| 226 static void | 219 static void |
| 227 fis_list(int argc, char *argv[]) | 220 fis_list(int argc, char *argv[]) |
| 228 { | 221 { |
| 229 struct image_desc *img; | 222 struct fis_image_desc *img; |
| 230 int i; | 223 int i; |
| 231 | 224 |
| 232 img = (struct image_desc *)((unsigned long)flash_end - block_size); | 225 img = (struct fis_image_desc *)((unsigned long)flash_end - block_size); |
| 233 printf("Name FLASH addr Mem addr Length Entry point\n"); | 226 printf("Name FLASH addr Mem addr Length Entry point\n"); |
| 234 for (i = 0; i < block_size/sizeof(*img); i++, img++) { | 227 for (i = 0; i < block_size/sizeof(*img); i++, img++) { |
| 235 if (img->name[0] != (unsigned char)0xFF) { | 228 if (img->name[0] != (unsigned char)0xFF) { |
| 236 printf("%-16s 0x%08lX 0x%08lX 0x%06lX 0x%08lX\n", img->name, | 229 printf("%-16s 0x%08lX 0x%08lX 0x%06lX 0x%08lX\n", img->name, |
| 237 img->flash_base, img->mem_base, img->size, img->entry_point); | 230 img->flash_base, img->mem_base, img->size, img->entry_point); |
| 318 | 311 |
| 319 static void | 312 static void |
| 320 fis_create(int argc, char *argv[]) | 313 fis_create(int argc, char *argv[]) |
| 321 { | 314 { |
| 322 int i, stat; | 315 int i, stat; |
| 323 unsigned long mem_addr, exec_addr, flash_addr, entry_addr, length; | 316 unsigned long mem_addr, exec_addr, flash_addr, entry_addr, length, img_size; |
| 324 char *name; | 317 char *name; |
| 325 bool mem_addr_set = false; | 318 bool mem_addr_set = false; |
| 326 bool exec_addr_set = false; | 319 bool exec_addr_set = false; |
| 327 bool entry_addr_set = false; | 320 bool entry_addr_set = false; |
| 328 bool flash_addr_set = false; | 321 bool flash_addr_set = false; |
| 329 bool length_set = false; | 322 bool length_set = false; |
| 323 bool img_size_set = false; | |
| 330 void *fis_addr, *err_addr; | 324 void *fis_addr, *err_addr; |
| 331 struct image_desc *img; | 325 struct fis_image_desc *img; |
| 332 bool slot_found; | 326 bool slot_found; |
| 333 struct option_info opts[5]; | 327 struct option_info opts[6]; |
| 334 bool prog_ok; | 328 bool prog_ok; |
| 335 | 329 |
| 336 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, | 330 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, |
| 337 (void **)&mem_addr, (bool *)&mem_addr_set, "memory base address"); | 331 (void **)&mem_addr, (bool *)&mem_addr_set, "memory base address"); |
| 338 init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM, | 332 init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM, |
| 340 init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM, | 334 init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM, |
| 341 (void **)&entry_addr, (bool *)&entry_addr_set, "entry point address"); | 335 (void **)&entry_addr, (bool *)&entry_addr_set, "entry point address"); |
| 342 init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM, | 336 init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM, |
| 343 (void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); | 337 (void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); |
| 344 init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, | 338 init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, |
| 345 (void **)&length, (bool *)&length_set, "length"); | 339 (void **)&length, (bool *)&length_set, "image length [in FLASH]"); |
| 346 if (!scan_opts(argc, argv, 2, opts, 5, (void *)&name, OPTION_ARG_TYPE_STR, "file name")) | 340 init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM, |
| 341 (void **)&img_size, (bool *)&img_size_set, "image size [actual data]"); | |
| 342 if (!scan_opts(argc, argv, 2, opts, 6, (void *)&name, OPTION_ARG_TYPE_STR, "file name")) | |
| 347 { | 343 { |
| 348 fis_usage("invalid arguments"); | 344 fis_usage("invalid arguments"); |
| 349 return; | 345 return; |
| 350 } | 346 } |
| 351 | 347 |
| 352 if (!mem_addr_set || !length_set || !name) { | 348 if (!mem_addr_set || !length_set || !name) { |
| 353 fis_usage("required parameter missing"); | 349 fis_usage("required parameter missing"); |
| 354 return; | 350 return; |
| 355 } | 351 } |
| 352 if (!img_size_set) { | |
| 353 img_size = length; | |
| 354 } | |
| 355 // 'length' is size of FLASH image, 'img_size' is actual data size | |
| 356 // Round up length to FLASH block size | |
| 357 length = ((length + block_size - 1) / block_size) * block_size; | |
| 358 if (length < img_size) { | |
| 359 printf("Invalid FLASH image size/length combination"); | |
| 360 return; | |
| 361 } | |
| 356 if (flash_addr_set && | 362 if (flash_addr_set && |
| 357 ((stat = flash_verify_addr((void *)flash_addr)) || | 363 ((stat = flash_verify_addr((void *)flash_addr)) || |
| 358 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { | 364 (stat = flash_verify_addr((void *)(flash_addr+img_size-1))))) { |
| 359 printf("Invalid FLASH address: %p (%s)\n", (void *)flash_addr, flash_errmsg(stat)); | 365 printf("Invalid FLASH address: %p (%s)\n", (void *)flash_addr, flash_errmsg(stat)); |
| 360 printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end); | 366 printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end); |
| 361 return; | 367 return; |
| 362 } | 368 } |
| 363 if ((mem_addr < (unsigned long)ram_start) || | 369 if ((mem_addr < (unsigned long)ram_start) || |
| 364 ((mem_addr+length) >= (unsigned long)ram_end)) { | 370 ((mem_addr+img_size) >= (unsigned long)ram_end)) { |
| 365 printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); | 371 printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); |
| 366 printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); | 372 printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); |
| 367 } | 373 } |
| 368 if (strlen(name) >= sizeof(img->name)) { | 374 if (strlen(name) >= sizeof(img->name)) { |
| 369 printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name)); | 375 printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name)); |
| 376 // Find a slot in the directory for this entry | 382 // Find a slot in the directory for this entry |
| 377 // First, see if an image by this name is already present | 383 // First, see if an image by this name is already present |
| 378 slot_found = false; | 384 slot_found = false; |
| 379 fis_addr = (void *)((unsigned long)flash_end - block_size); | 385 fis_addr = (void *)((unsigned long)flash_end - block_size); |
| 380 memcpy(fis_work_block, fis_addr, block_size); | 386 memcpy(fis_work_block, fis_addr, block_size); |
| 381 img = (struct image_desc *)fis_work_block; | 387 img = (struct fis_image_desc *)fis_work_block; |
| 382 for (i = 0; i < block_size/sizeof(*img); i++, img++) { | 388 for (i = 0; i < block_size/sizeof(*img); i++, img++) { |
| 383 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) { | 389 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) { |
| 384 if (flash_addr_set && (img->flash_base != flash_addr)) { | 390 if (flash_addr_set && (img->flash_base != flash_addr)) { |
| 385 printf("Image found, but FLASH address incorrect\n"); | 391 printf("Image found, but FLASH address incorrect\n"); |
| 386 return; | 392 return; |
| 397 } | 403 } |
| 398 } | 404 } |
| 399 } | 405 } |
| 400 // If not found, try and find an empty slot | 406 // If not found, try and find an empty slot |
| 401 if (!slot_found) { | 407 if (!slot_found) { |
| 402 img = (struct image_desc *)fis_work_block; | 408 img = (struct fis_image_desc *)fis_work_block; |
| 403 for (i = 0; i < block_size/sizeof(*img); i++, img++) { | 409 for (i = 0; i < block_size/sizeof(*img); i++, img++) { |
| 404 if (img->name[0] == (unsigned char)0xFF) { | 410 if (img->name[0] == (unsigned char)0xFF) { |
| 405 slot_found = true; | 411 slot_found = true; |
| 406 break; | 412 break; |
| 407 } | 413 } |
| 408 } | 414 } |
| 409 } | 415 } |
| 410 // Safety check - make sure the address range is not within the code we're running | 416 // Safety check - make sure the address range is not within the code we're running |
| 411 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) { | 417 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+img_size-1))) { |
| 412 printf("Can't program this region - contains code in use!\n"); | 418 printf("Can't program this region - contains code in use!\n"); |
| 413 return; | 419 return; |
| 414 } | 420 } |
| 415 prog_ok = true; | 421 prog_ok = true; |
| 416 if (prog_ok) { | 422 if (prog_ok) { |
| 420 prog_ok = false; | 426 prog_ok = false; |
| 421 } | 427 } |
| 422 } | 428 } |
| 423 if (prog_ok) { | 429 if (prog_ok) { |
| 424 // Now program it | 430 // Now program it |
| 425 if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { | 431 if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) { |
| 426 printf("Can't program region at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); | 432 printf("Can't program region at %p: %x(%s)\n", err_addr, stat, flash_errmsg(stat)); |
| 427 prog_ok = false; | 433 prog_ok = false; |
| 428 } | 434 } |
| 429 } | 435 } |
| 430 // Update directory | 436 // Update directory |
| 565 fis_delete(int argc, char *argv[]) | 571 fis_delete(int argc, char *argv[]) |
| 566 { | 572 { |
| 567 char *name; | 573 char *name; |
| 568 int i, stat; | 574 int i, stat; |
| 569 void *fis_addr, *err_addr; | 575 void *fis_addr, *err_addr; |
| 570 struct image_desc *img; | 576 struct fis_image_desc *img; |
| 571 bool slot_found; | 577 bool slot_found; |
| 572 | 578 |
| 573 if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) | 579 if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) |
| 574 { | 580 { |
| 575 fis_usage("invalid arguments"); | 581 fis_usage("invalid arguments"); |
| 577 } | 583 } |
| 578 | 584 |
| 579 slot_found = false; | 585 slot_found = false; |
| 580 fis_addr = (void *)((unsigned long)flash_end - block_size); | 586 fis_addr = (void *)((unsigned long)flash_end - block_size); |
| 581 memcpy(fis_work_block, fis_addr, block_size); | 587 memcpy(fis_work_block, fis_addr, block_size); |
| 582 img = (struct image_desc *)fis_work_block; | 588 img = (struct fis_image_desc *)fis_work_block; |
| 583 img += 2; // Skip reserved files | 589 img += 2; // Skip reserved files |
| 584 for (i = 2; i < block_size/sizeof(*img); i++, img++) { | 590 for (i = 2; i < block_size/sizeof(*img); i++, img++) { |
| 585 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) { | 591 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) { |
| 586 if (!verify_action("Delete image '%s'", name)) { | 592 if (!verify_action("Delete image '%s'", name)) { |
| 587 return; | 593 return; |
| 616 fis_load(int argc, char *argv[]) | 622 fis_load(int argc, char *argv[]) |
| 617 { | 623 { |
| 618 char *name; | 624 char *name; |
| 619 int i; | 625 int i; |
| 620 void *fis_addr; | 626 void *fis_addr; |
| 621 struct image_desc *img; | 627 struct fis_image_desc *img; |
| 622 bool slot_found; | 628 bool slot_found; |
| 623 | 629 |
| 624 if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) | 630 if (!scan_opts(argc, argv, 2, 0, 0, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) |
| 625 { | 631 { |
| 626 fis_usage("invalid arguments"); | 632 fis_usage("invalid arguments"); |
| 628 } | 634 } |
| 629 | 635 |
| 630 slot_found = false; | 636 slot_found = false; |
| 631 fis_addr = (void *)((unsigned long)flash_end - block_size); | 637 fis_addr = (void *)((unsigned long)flash_end - block_size); |
| 632 memcpy(fis_work_block, fis_addr, block_size); | 638 memcpy(fis_work_block, fis_addr, block_size); |
| 633 img = (struct image_desc *)fis_work_block; | 639 img = (struct fis_image_desc *)fis_work_block; |
| 634 for (i = 0; i < block_size/sizeof(*img); i++, img++) { | 640 for (i = 0; i < block_size/sizeof(*img); i++, img++) { |
| 635 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) { | 641 if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) { |
| 636 slot_found = true; | 642 slot_found = true; |
| 637 break; | 643 break; |
| 638 } | 644 } |
| 726 RedBoot_config_option("Boot script", | 732 RedBoot_config_option("Boot script", |
| 727 boot_script_data, | 733 boot_script_data, |
| 728 "boot_script", true, | 734 "boot_script", true, |
| 729 CONFIG_SCRIPT | 735 CONFIG_SCRIPT |
| 730 ); | 736 ); |
| 731 RedBoot_config_option("Boot script timeout", | 737 // Some preprocessor magic for building the [constant] prompt string |
| 738 #define __cat(s1,c2,s3) s1 ## #c2 ## s3 | |
| 739 #define _cat(s1,c2,s3) __cat(s1,c2,s3) | |
| 740 RedBoot_config_option(_cat("Boot script timeout (", | |
| 741 CYGNUM_REDBOOT_FLASH_SCRIPT_TIMEOUT_RESOLUTION, | |
| 742 "ms resolution)"), | |
| 732 boot_script_timeout, | 743 boot_script_timeout, |
| 733 "boot_script", true, | 744 "boot_script", true, |
| 734 CONFIG_INT | 745 CONFIG_INT |
| 735 ); | 746 ); |
| 747 #undef __cat | |
| 748 #undef _cat | |
| 736 | 749 |
| 737 CYG_HAL_TABLE_BEGIN( __CONFIG_options_TAB__, RedBoot_config_options); | 750 CYG_HAL_TABLE_BEGIN( __CONFIG_options_TAB__, RedBoot_config_options); |
| 738 CYG_HAL_TABLE_END( __CONFIG_options_TAB_END__, RedBoot_config_options); | 751 CYG_HAL_TABLE_END( __CONFIG_options_TAB_END__, RedBoot_config_options); |
| 739 | 752 |
| 740 extern struct config_option __CONFIG_options_TAB__[], __CONFIG_options_TAB_END__[]; | 753 extern struct config_option __CONFIG_options_TAB__[], __CONFIG_options_TAB_END__[]; |
