Mercurial > flash_v2
diff packages/redboot/current/src/flash.c @ 156:b939e9cada46
Merge from eCos master repository on 2001-03-29-21:44:39-BST
| author | jlarmour |
|---|---|
| date | Fri, 06 Apr 2001 17:20:13 +0000 |
| parents | e2d866e32dac |
| children | b65ec671dd4c |
line wrap: on
line diff
--- a/packages/redboot/current/src/flash.c +++ b/packages/redboot/current/src/flash.c @@ -70,7 +70,7 @@ local_cmd_entry("init", ); local_cmd_entry("list", "Display contents of FLASH Image System [FIS]", - "[-c]", + "[-c] [-d]", fis_list, FIS_cmds ); @@ -106,9 +106,16 @@ local_cmd_entry("delete", fis_delete, FIS_cmds ); + +static char fis_load_usage[] = +#ifdef CYGPKG_COMPRESS_ZLIB + "[-d] " +#endif + "[-b <memory_load_address>] [-c] name"; + local_cmd_entry("load", "Load image from FLASH Image System [FIS] into RAM", - "[-b <memory_load_address>] [-c] name", + fis_load_usage, fis_load, FIS_cmds ); @@ -119,6 +126,12 @@ local_cmd_entry("create", fis_create, FIS_cmds ); +local_cmd_entry("write", + "Write raw data directly to FLASH", + "-f <flash_addr> -b <mem_base> -l <image_length>", + fis_write, + FIS_cmds + ); // Define table boundaries CYG_HAL_TABLE_BEGIN( __FIS_cmds_TAB__, FIS_cmds); @@ -308,24 +321,33 @@ fis_list(int argc, char *argv[]) struct fis_image_desc *img; int i; bool show_cksums = false; - struct option_info opts[1]; + bool show_datalen = false; + struct option_info opts[2]; init_opts(&opts[0], 'c', false, OPTION_ARG_TYPE_FLG, (void **)&show_cksums, (bool *)0, "display checksums"); - if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, "")) + init_opts(&opts[1], 'd', false, OPTION_ARG_TYPE_FLG, + (void **)&show_datalen, (bool *)0, "display data length"); + if (!scan_opts(argc, argv, 2, opts, 2, 0, 0, "")) { return; } - img = (struct fis_image_desc *)((unsigned long)flash_end - block_size); - printf("Name FLASH addr %s Length Entry point\n", - show_cksums ? "Checksum" : "Mem addr"); + img = (struct fis_image_desc *)((unsigned long)flash_end - block_size); + // Let printf do the formatting in both cases, rather than cnouting + // cols by hand.... + printf("%-16s %-10s %-10s %-10s %-s\n", + "Name","FLASH addr", + show_cksums ? "Checksum" : "Mem addr", + show_datalen ? "Datalen" : "Length", + "Entry point" ); for (i = 0; i < block_size/sizeof(*img); i++, img++) { if (img->name[0] != (unsigned char)0xFF) { - printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", img->name, + printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", img->name, img->flash_base, show_cksums ? img->file_cksum : img->mem_base, - img->size, img->entry_point); + show_datalen ? img->data_length : img->size, + img->entry_point); } } } @@ -423,7 +445,7 @@ fis_create(int argc, char *argv[]) bool no_copy = false; void *fis_addr, *err_addr; struct fis_image_desc *img; - bool slot_found; + bool slot_found, defaults_assumed; struct option_info opts[7]; bool prog_ok; @@ -447,7 +469,8 @@ fis_create(int argc, char *argv[]) return; } - if ( name ) { + defaults_assumed = false; + if (name) { // Search existing files to acquire defaults for params not specified: fis_addr = (void *)((unsigned long)flash_end - block_size); memcpy(fis_work_block, fis_addr, block_size); @@ -455,13 +478,26 @@ fis_create(int argc, char *argv[]) for (i = 0; i < block_size/sizeof(*img); i++, img++) { if ((img->name[0] != (unsigned char)0xFF) && (strcmp(name, img->name) == 0)) { // Found it, so get any unset but necessary params from there: - if ( !length_set ) { + if (!length_set) { length_set = true; length = img->size; + defaults_assumed = true; } - if ( !flash_addr_set ) { + // img_size can also be handled below, set from length + if (!img_size_set && 0 < img->data_length) { + img_size_set = true; + img_size = img->data_length; + defaults_assumed = true; + } + if (!exec_addr_set) { + // Preserve "normal" behaviour + exec_addr_set = true; + exec_addr = flash_addr_set ? flash_addr : mem_addr; + } + if (!flash_addr_set) { flash_addr_set = true; flash_addr = img->flash_base; + defaults_assumed = true; } break; } @@ -525,8 +561,15 @@ fis_create(int argc, char *argv[]) } if (!verify_action("An image named '%s' exists", name)) { return; - } else { + } else { slot_found = true; + if (defaults_assumed) { + if (!verify_action("* CAUTION * about to program '%s'\n at %p..%p from %p", + name, (void *)flash_addr, (void *)(flash_addr+img_size-1), + (void *)mem_addr)) { + return; // The guy gave up + } + } break; } } @@ -592,6 +635,76 @@ fis_create(int argc, char *argv[]) } static void +fis_write(int argc, char *argv[]) +{ + int stat; + unsigned long mem_addr, flash_addr, length; + bool mem_addr_set = false; + bool flash_addr_set = false; + bool length_set = false; + void *err_addr; + struct option_info opts[3]; + bool prog_ok; + + init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, + (void **)&mem_addr, (bool *)&mem_addr_set, "memory base address"); + init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM, + (void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); + init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM, + (void **)&length, (bool *)&length_set, "image length [in FLASH]"); + if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0)) + { + fis_usage("invalid arguments"); + return; + } + + if (!mem_addr_set || !flash_addr_set || !length_set) + fis_usage("required parameter missing"); + + // Round up length to FLASH block size +#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken + length = ((length + block_size - 1) / block_size) * block_size; +#endif + if (flash_addr_set && + ((stat = flash_verify_addr((void *)flash_addr)) || + (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { + printf("Invalid FLASH address: %p (%s)\n", (void *)flash_addr, flash_errmsg(stat)); + printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end); + return; + } + if ((mem_addr < (unsigned long)ram_start) || + ((mem_addr+length) >= (unsigned long)ram_end)) { + printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); + printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); + } + // Safety check - make sure the address range is not within the code we're running + if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) { + printf("Can't program this region - contains code in use!\n"); + return; + } + if (!verify_action("* CAUTION * about to program FLASH at %p..%p from %p", + (void *)flash_addr, (void *)(flash_addr+length-1), + (void *)mem_addr)) { + return; // The guy gave up + } + prog_ok = true; + if (prog_ok) { + // Erase area to be programmed + if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) { + printf("Can't erase region at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat)); + prog_ok = false; + } + } + if (prog_ok) { + // Now program it + if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { + printf("Can't program region at %p: 0x%x(%s)\n", err_addr, stat, flash_errmsg(stat)); + prog_ok = false; + } + } +} + +static void fis_erase(int argc, char *argv[]) { int stat; @@ -794,14 +907,23 @@ fis_load(int argc, char *argv[]) unsigned long mem_addr; bool mem_addr_set = false; bool show_cksum = false; - struct option_info opts[2]; + struct option_info opts[3]; unsigned long cksum; + int num_options; + bool decompress = false; init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void **)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address"); init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, (void **)&show_cksum, (bool *)0, "display checksum"); - if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) + num_options = 2; +#ifdef CYGPKG_COMPRESS_ZLIB + init_opts(&opts[2], 'd', false, OPTION_ARG_TYPE_FLG, + (void **)&decompress, 0, "decompress"); + num_options++; +#endif + + if (!scan_opts(argc, argv, 2, opts, num_options, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) { fis_usage("invalid arguments"); return; @@ -814,18 +936,45 @@ fis_load(int argc, char *argv[]) mem_addr = img->mem_base; } // Load image from FLASH into RAM - if ((mem_addr < (unsigned long)ram_start) || - ((mem_addr+img->size) >= (unsigned long)ram_end)) { + if ((mem_addr < (unsigned long)user_ram_start) || + ((mem_addr+img->size) >= (unsigned long)user_ram_end)) { printf("Not a loadable image\n"); return; } - memcpy((void *)mem_addr, (void *)img->flash_base, img->data_length); +#ifdef CYGPKG_COMPRESS_ZLIB + if (decompress) { + int err; + _pipe_t fis_load_pipe; + _pipe_t* p = &fis_load_pipe; + p->out_buf = (unsigned char*) mem_addr; + p->out_size = -1; + p->in_buf = (unsigned char*) img->flash_base; + p->in_avail = img->data_length; + + err = (*_dc_init)(p); + + if (0 == err) + err = (*_dc_inflate)(p); + + // Free used resources, do final translation of + // error value. + err = (*_dc_close)(p, err); + + if (0 != err && p->msg) + printf("zlib: %s\n", p->msg); + + } else // dangling block +#endif + { + memcpy((void *)mem_addr, (void *)img->flash_base, img->data_length); + } entry_address = (unsigned long *)img->entry_point; cksum = crc32((unsigned char *)mem_addr, img->data_length); if (show_cksum) { printf("Checksum: 0x%08lx\n", cksum); } - if (img->file_cksum) { + // When decompressing, leave CRC checking to decompressor + if (!decompress && img->file_cksum) { if (cksum != img->file_cksum) { printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n", img->file_cksum, cksum); @@ -841,7 +990,7 @@ do_flash_init(void) if (!init) { init = 1; - if ((stat = flash_init((void *)(ram_end-FLASH_MIN_WORKSPACE), + if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE), FLASH_MIN_WORKSPACE)) != 0) { printf("FLASH: driver init failed!, status: 0x%x\n", stat); return false; @@ -850,7 +999,8 @@ do_flash_init(void) flash_get_block_info(&block_size, &blocks); printf("FLASH: %p - %p, %d blocks of %p bytes each.\n", flash_start, flash_end, blocks, (void *)block_size); - fis_work_block = (unsigned char *)(ram_end-FLASH_MIN_WORKSPACE-block_size); + fis_work_block = (unsigned char *)(workspace_end-FLASH_MIN_WORKSPACE-block_size); + workspace_end = fis_work_block; } return true; }
