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

📄 flash.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif
        footer_p->infoBase = NULL;
        footer_p->signature = FLASH_FOOTER_SIGNATURE;
        footer_p->type = TYPE_REDHAT_REDBOOT;

        // and compute its checksum
        for ( ; count > 0; count--) {
            if (*check_ptr > ~check)
                check++;
            check += *check_ptr++;
        }
        footer_p->checksum = ~check;
    }
#endif

    // Do this after creating the initialized table because that inherently
    // calculates where the high water mark of default RedBoot images is.

    if (full_init) {
        unsigned long erase_size;
        CYG_ADDRESS erase_start;
        // Erase everything except default RedBoot images, fis block, 
        // and config block.
        // First deal with the possible first part, before RedBoot images:
#if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE)
        erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
        erase_size =  (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
        if ( erase_size > erase_start ) {
            erase_size -= erase_start;
            if ((stat = flash_erase((void *)erase_start, erase_size,
                                    (void **)&err_addr)) != 0) {
                diag_printf("   initialization failed at %p: %s\n",
                            err_addr, flash_errmsg(stat));
            }
        }
#endif
        // second deal with the larger part in the main:
        erase_start = redboot_flash_start; // high water of created images
        // Now the empty bits between the end of Redboot and the cfg and dir 
        // blocks. 
#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \    defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) && \    !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
        if (fis_addr > cfg_base) {
          erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data
        } else {
          erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
        }
        if ((stat = flash_erase((void *)erase_start, erase_size,
                                (void **)&err_addr)) != 0) {
          diag_printf("   initialization failed %p: %s\n",
                 err_addr, flash_errmsg(stat));
        }
        erase_start += (erase_size + flash_block_size);
        if (fis_addr > cfg_base) {
          erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data
        } else {
          erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data
        }
        if ((stat = flash_erase((void *)erase_start, erase_size,
                                (void **)&err_addr)) != 0) {
          diag_printf("   initialization failed %p: %s\n",
                 err_addr, flash_errmsg(stat));
        }
        erase_start += (erase_size + flash_block_size);
#else  // !CYGSEM_REDBOOT_FLASH_CONFIG        
        erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
        if ((stat = flash_erase((void *)erase_start, erase_size,
                                (void **)&err_addr)) != 0) {
          diag_printf("   initialization failed %p: %s\n",
                 err_addr, flash_errmsg(stat));
        }
        erase_start += (erase_size + flash_block_size);          
#endif
        // Lastly, anything at the end
        erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1;
        if ((stat = flash_erase((void *)erase_start, erase_size,
                                (void **)&err_addr)) != 0) {
            diag_printf("   initialization failed at %p: %s\n",
                        err_addr, flash_errmsg(stat));
        }
#ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
    // In this case, 'fis free' works by scanning for erased blocks.  Since the
    // "-f" option was not supplied, there may be areas which are not used but
    // don't appear to be free since they are not erased - thus the warning
    } else {
        diag_printf("    Warning: device contents not erased, some blocks may not be usable\n");
#endif
    }
    fis_update_directory();
}

static void
fis_list(int argc, char *argv[])
{
    struct fis_image_desc *img;
    int i, image_indx;
    bool show_cksums = false;
    bool show_datalen = false;
    struct option_info opts[2];
    void *err_addr;
    unsigned long last_addr, lowest_addr;
    bool image_found;

#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;
    }
    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
    // 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->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->name, 
                        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
                        img->entry_point);
        }
        last_addr = lowest_addr;
    } 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;
    void *err_addr;
    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 + 
                              CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
    fis_end = (CYG_ADDRESS *)flash_end;
    chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr;
    chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end;
    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
    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) {
            // 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];
                            }
                            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) {
                            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 + 
                                CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
    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", chunks[idx].start, 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 + 
                                CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
    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;

⌨️ 快捷键说明

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