flash.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,397 行 · 第 1/4 页

C
1,397
字号
    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 voidfis_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 voidfis_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 + =
减小字号Ctrl + -
显示快捷键?