flash.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,397 行 · 第 1/4 页
C
1,397 行
#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 voidfis_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_CHUNKSstruct free_chunk { CYG_ADDRESS start, end;};static intfind_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_CHUNKSstatic voidfis_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 enoughstatic boolfis_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 voidfis_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 + =
减小字号Ctrl + -
显示快捷键?