⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:

#ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
    // FIXME: this is somewhat half-baked
    extern void arm_fis_list(void);
    arm_fis_list();
    return;
#endif

    init_opts(&opts[0], 'd', false, OPTION_ARG_TYPE_FLG, 
              (void *)&show_datalen, (bool *)0, "display data length");
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
    init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, 
              (void *)&show_cksums, (bool *)0, "display checksums");
    i = 2;
#else
    i = 1;
#endif
    if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) {
        return;
    }
    fis_read_directory();

    // Let diag_printf do the formatting in both cases, rather than counting
    // cols by hand....
    diag_printf("%-16s  %-10s  %-10s  %-10s  %-s\n",
                "Name","FLASH addr",
                show_cksums ? "Checksum" : "Mem addr",
                show_datalen ? "Datalen" : "Length",
                "Entry point" );
    last_addr = 0;
    image_indx = 0;
    do {
        image_found = false;
        lowest_addr = 0xFFFFFFFF;
        img = (struct fis_image_desc *) fis_work_block;
        for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
            if (img->u.name[0] != (unsigned char)0xFF) {
                if ((img->flash_base >= last_addr) && (img->flash_base < lowest_addr)) {
                    lowest_addr = img->flash_base;
                    image_found = true;
                    image_indx = i;
                }
            }
        }
        if (image_found) {
            img = (struct fis_image_desc *) fis_work_block;
            img += image_indx;
            diag_printf("%-16s  0x%08lX  0x%08lX  0x%08lX  0x%08lX\n", img->u.name,
                        (unsigned long)img->flash_base, 
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
                        show_cksums ? img->file_cksum : img->mem_base, 
                        show_datalen ? img->data_length : img->size, 
#else
                        img->mem_base, 
                        img->size, 
#endif
                        (unsigned long)img->entry_point);
        }
        last_addr = lowest_addr + 1;
    } while (image_found == true);
}

#ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
struct free_chunk {
    CYG_ADDRESS start, end;
};

static int
find_free(struct free_chunk *chunks)
{
    CYG_ADDRESS *fis_ptr, *fis_end;
    struct fis_image_desc *img;
    int i, idx;
    int num_chunks = 1;

    // Do not search the area reserved for pre-RedBoot systems:
    fis_ptr = (CYG_ADDRESS *)((CYG_ADDRESS)flash_start + 
                              CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
    fis_end = (CYG_ADDRESS *)flash_end;
    chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr;
    chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end;
    fis_read_directory();
    img = (struct fis_image_desc *) fis_work_block;
    for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
        if (img->u.name[0] != (unsigned char)0xFF) {
            // Figure out which chunk this is in and split it
            for (idx = 0;  idx < num_chunks;  idx++) {
                if ((img->flash_base >= chunks[idx].start) && 
                    (img->flash_base <= chunks[idx].end)) {
                    if (img->flash_base == chunks[idx].start) {
                        chunks[idx].start += img->size;
                        if (chunks[idx].start >= chunks[idx].end) {
                            // This free chunk has collapsed
                            while (idx < (num_chunks-1)) {
                                chunks[idx] = chunks[idx+1];
                                idx++;
                            }
                            num_chunks--;
                        }
                    } else if ((img->flash_base+img->size) == chunks[idx].end) {
                        chunks[idx].end = img->flash_base;
                    } else {
                        // Split chunk into two parts
                        if ((img->flash_base+img->size) < (CYG_ADDRESS)fis_end) {
                            int j;
                            // make room for new chunk
                            for (j = num_chunks; j > (idx+1); j--)
                                chunks[j] = chunks[j-1];
                            chunks[idx+1].start = img->flash_base + img->size;
                            chunks[idx+1].end = chunks[idx].end;
                            if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) {
                                diag_printf("Warning: too many free chunks\n");
                                return num_chunks;
                            }
                        }
                        chunks[idx].end = img->flash_base;
                    }
                    break;
                }
            }
        }
    }
    return num_chunks;
}
#endif // CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS

static void
fis_free(int argc, char *argv[])
{
#ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
    unsigned long *fis_ptr, *fis_end, flash_data;
    unsigned long *area_start;
    void *err_addr;

    // Do not search the area reserved for pre-RedBoot systems:
    fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + 
                                CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
    fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
    area_start = fis_ptr;
    while (fis_ptr < fis_end) {
        flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr);
        if (flash_data != (unsigned long)0xFFFFFFFF) {
            if (area_start != fis_ptr) {
                // Assume that this is something
                diag_printf("  0x%08lX .. 0x%08lX\n",
                            (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
            }
            // Find next blank block
            area_start = fis_ptr;
            while (area_start < fis_end) {
                flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr);
                if (flash_data == (unsigned long)0xFFFFFFFF) {
                    break;
                }
                area_start += flash_block_size / sizeof(CYG_ADDRESS);
            }
            fis_ptr = area_start;
        } else {
            fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
        }
    }
    if (area_start != fis_ptr) {
        diag_printf("  0x%08lX .. 0x%08lX\n", 
                    (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
    }
#else
    struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
    int idx, num_chunks;

    num_chunks = find_free(chunks);
    for (idx = 0;  idx < num_chunks;  idx++) {
        diag_printf("  0x%08lX .. 0x%08lX\n", 
		    (unsigned long)chunks[idx].start,
		    (unsigned long)chunks[idx].end);
    }
#endif
}

// Find the first unused area of flash which is long enough
static bool
fis_find_free(CYG_ADDRESS *addr, unsigned long length)
{
#ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
    unsigned long *fis_ptr, *fis_end, flash_data;
    unsigned long *area_start;
    void *err_addr;

    // Do not search the area reserved for pre-RedBoot systems:
    fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + 
                                CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
    fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
    area_start = fis_ptr;
    while (fis_ptr < fis_end) {
        flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr);
        if (flash_data != (unsigned long)0xFFFFFFFF) {
            if (area_start != fis_ptr) {
                // Assume that this is something
                if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
                    *addr = (CYG_ADDRESS)area_start;
                    return true;
                }
            }
            // Find next blank block
            area_start = fis_ptr;
            while (area_start < fis_end) {
                flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr);
                if (flash_data == (unsigned long)0xFFFFFFFF) {
                    break;
                }
                area_start += flash_block_size / sizeof(CYG_ADDRESS);
            }
            fis_ptr = area_start;
        } else {
            fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
        }
    }
    if (area_start != fis_ptr) {
        if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
            *addr = (CYG_ADDRESS)area_start;
            return true;
        }
    }
    return false;
#else
    struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
    int idx, num_chunks;

    num_chunks = find_free(chunks);
    for (idx = 0;  idx < num_chunks;  idx++) {
        if ((chunks[idx].end - chunks[idx].start) >= length) {
            *addr = (CYG_ADDRESS)chunks[idx].start;
            return true;
        }
    }
    return false;
#endif
}

static void
fis_create(int argc, char *argv[])
{
    int i, stat;
    unsigned long length, img_size;
    CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr;
    char *name;
    bool mem_addr_set = false;
    bool exec_addr_set = false;
    bool entry_addr_set = false;
    bool flash_addr_set = false;
    bool length_set = false;
    bool img_size_set = false;
    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;
    }

    fis_read_directory();
    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 &&

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -