📄 flash.c
字号:
bool no_copy = false;
void *err_addr;
struct fis_image_desc *img = NULL;
bool defaults_assumed;
struct option_info opts[7];
bool prog_ok = true;
init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
(void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM,
(void *)&exec_addr, (bool *)&exec_addr_set, "ram base address");
init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM,
(void *)&entry_addr, (bool *)&entry_addr_set, "entry point address");
init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM,
(void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM,
(void *)&length, (bool *)&length_set, "image length [in FLASH]");
init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM,
(void *)&img_size, (bool *)&img_size_set, "image size [actual data]");
init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG,
(void *)&no_copy, (bool *)0, "don't copy from RAM to FLASH, just update directory");
if (!scan_opts(argc, argv, 2, opts, 7, (void *)&name, OPTION_ARG_TYPE_STR, "file name"))
{
fis_usage("invalid arguments");
return;
}
flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
defaults_assumed = false;
if (name) {
// Search existing files to acquire defaults for params not specified:
img = fis_lookup(name, NULL);
if (img) {
// Found it, so get image size from there
if (!length_set) {
length_set = true;
length = img->size;
defaults_assumed = true;
}
}
}
if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) &&
(load_address_end) < (CYG_ADDRESS)ram_end) {
mem_addr = load_address;
mem_addr_set = true;
defaults_assumed = true;
// Get entry address from loader, unless overridden
if (!entry_addr_set)
entry_addr = entry_address;
if (!length_set) {
length = load_address_end - load_address;
length_set = true;
} else if (defaults_assumed && !img_size_set) {
/* We got length from the FIS table, so the size of the
actual loaded image becomes img_size */
img_size = load_address_end - load_address;
img_size_set = true;
}
}
// Get the remaining fall-back values from the fis
if (img) {
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;
}
}
if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||
!length_set || !name) {
fis_usage("required parameter missing");
return;
}
if (!img_size_set) {
img_size = length;
}
// 'length' is size of FLASH image, 'img_size' is actual data size
// Round up length to FLASH block size
#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
if (length < img_size) {
diag_printf("Invalid FLASH image size/length combination\n");
return;
}
#endif
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
_show_invalid_flash_address(flash_addr, stat);
return;
}
if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) {
diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
diag_printf(" must be 0x%x aligned\n", flash_block_size);
return;
}
if (strlen(name) >= sizeof(img->name)) {
diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));
return;
}
if (!no_copy) {
if ((mem_addr < (CYG_ADDRESS)ram_start) ||
((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) {
diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
}
if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {
diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length);
return;
}
}
// First, see if the image by this name has agreable properties
if (img) {
if (flash_addr_set && (img->flash_base != flash_addr)) {
diag_printf("Image found, but flash address (%p)\n"
" is incorrect (present image location %p)\n",
flash_addr, img->flash_base);
return;
}
if (img->size != length) {
diag_printf("Image found, but length (0x%lx, necessitating image size 0x%lx)\n"
" is incorrect (present image size 0x%lx)\n",
img_size, length, img->size);
return;
}
if (!verify_action("An image named '%s' exists", name)) {
return;
} else {
if (defaults_assumed) {
if (no_copy &&
!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
}
}
}
} else {
#ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
// Make sure that any FLASH address specified directly is truly free
if (flash_addr_set && !no_copy) {
struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
int idx, num_chunks;
bool is_free = false;
num_chunks = find_free(chunks);
for (idx = 0; idx < num_chunks; idx++) {
if ((flash_addr >= chunks[idx].start) &&
((flash_addr+length-1) <= chunks[idx].end)) {
is_free = true;
}
}
if (!is_free) {
diag_printf("Invalid FLASH address - not free!\n");
return;
}
}
#endif
// If not image by that name, try and find an empty slot
img = (struct fis_image_desc *)fis_work_block;
for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
if (img->name[0] == (unsigned char)0xFF) {
break;
}
}
}
if (!no_copy) {
// 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+img_size-1))) {
diag_printf("Can't program this region - contains code in use!\n");
return;
}
if (prog_ok) {
// Erase area to be programmed
if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
prog_ok = false;
}
}
if (prog_ok) {
// Now program it
if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
prog_ok = false;
}
}
}
if (prog_ok) {
// Update directory
memset(img, 0, sizeof(*img));
strcpy(img->name, name);
img->flash_base = flash_addr;
img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr);
img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address; // Hope it's been set
img->size = length;
img->data_length = img_size;
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
if (!no_copy) {
img->file_cksum = cyg_crc32((unsigned char *)mem_addr, img_size);
} else {
// No way to compute this, sorry
img->file_cksum = 0;
}
#endif
fis_update_directory();
}
}
extern void arm_fis_delete(char *);
static void
fis_delete(int argc, char *argv[])
{
char *name;
int num_reserved, i, stat;
void *err_addr;
struct fis_image_desc *img;
if (!scan_opts(argc, argv, 2, 0, 0, (void *)&name, OPTION_ARG_TYPE_STR, "image name"))
{
fis_usage("invalid arguments");
return;
}
#ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
// FIXME: this is somewhat half-baked
arm_fis_delete(name);
return;
#endif
img = (struct fis_image_desc *)fis_work_block;
num_reserved = 0;
#ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
num_reserved++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT
num_reserved++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
num_reserved++;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
num_reserved++;
#endif
#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
num_reserved++;
#endif
#if 1 // And the descriptor for the descriptor table itself
num_reserved++;
#endif
img = fis_lookup(name, &i);
if (img) {
if (i < num_reserved) {
diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->name);
return;
}
if (!verify_action("Delete image '%s'", name)) {
return;
}
} else {
diag_printf("No image '%s' found\n", name);
return;
}
// Erase Data blocks (free space)
if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
} else {
img->name[0] = (unsigned char)0xFF;
fis_update_directory();
}
}
static void
fis_load(int argc, char *argv[])
{
char *name;
struct fis_image_desc *img;
CYG_ADDRESS mem_addr;
bool mem_addr_set = false;
bool show_cksum = false;
struct option_info opts[3];
#if defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
unsigned long cksum;
#endif
int num_options;
#if defined(CYGPRI_REDBOOT_ZLIB_FLASH) || defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
bool decompress = false;
#endif
void *err_addr;
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");
num_options = 2;
#ifdef CYGPRI_REDBOOT_ZLIB_FLASH
init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG,
(void *)&decompress, 0, "decompress");
num_options++;
#endif
CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
if (!scan_opts(argc, argv, 2, opts, num_options, (void *)&name, OPTION_ARG_TYPE_STR, "image name"))
{
fis_usage("invalid arguments");
return;
}
if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
diag_printf("No image '%s' found\n", name);
return;
}
if (!mem_addr_set) {
mem_addr = img->mem_base;
}
// Load image from FLASH into RAM
#ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
if (!valid_address((void *)mem_addr)) {
diag_printf("Not a loadable image - try using -b ADDRESS option\n");
return;
}
#endif
#ifdef CYGPRI_REDBOOT_ZLIB_FLASH
if (decompress) {
int err;
_pipe_t fis_load_pipe;
_pipe_t* p = &fis_load_pipe;
p->out_buf = (unsigned char*) mem_addr;
p->out_max = 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) {
diag_printf("decompression error: %s\n", p->msg);
} else {
diag_printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -