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 cyg_bool flash_fis_op( int op, char *name, void *val) { cyg_bool res = false; struct fis_image_desc *fis; int num; CYGARC_HAL_SAVE_GP(); fis = fis_lookup(name, &num); if(fis != NULL) { switch ( op ) { case CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE: *(CYG_ADDRESS *)val = fis->flash_base; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE: *(unsigned long *)val = fis->size; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_MEM_BASE: *(CYG_ADDRESS *)val = fis->mem_base; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_POINT: *(CYG_ADDRESS *)val = fis->entry_point; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_DATA_LENGTH: *(unsigned long *)val = fis->data_length; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_DESC_CKSUM: *(unsigned long *)val = fis->desc_cksum; res = true; break; case CYGNUM_CALL_IF_FLASH_FIS_GET_FILE_CKSUM: *(unsigned long *)val = fis->file_cksum; res = true; break; default: break; } } CYGARC_HAL_RESTORE_GP(); return res; }
static void fis_unlock(int argc, char *argv[]) { char *name; int stat; unsigned long length; CYG_ADDRESS flash_addr; bool flash_addr_set = false; bool length_set = false; void *err_addr; struct option_info opts[2]; init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length, (bool *)&length_set, "length"); if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name")) { fis_usage("invalid arguments"); return; } if (name) { struct fis_image_desc *img; if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) { diag_printf("No image '%s' found\n", name); return; } flash_addr = img->flash_base; length = img->size; } else if (!flash_addr_set || !length_set) { fis_usage("missing argument"); return; } 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 ((stat = flash_unlock((void *)flash_addr, length, (void **)&err_addr)) != 0) { diag_printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat)); } }
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 && ((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(); } }
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); } // Set load address/top load_address = mem_addr; load_address_end = (unsigned long)p->out_buf; // Reload fis directory fis_read_directory(); } else // dangling block #endif { flash_read((void *)img->flash_base, (void *)mem_addr, img->size, (void **)&err_addr); // Set load address/top load_address = mem_addr; load_address_end = mem_addr + img->size; diag_printf("load address 0x%08lx end 0x%08lx, image length 0x%08lx\n",load_address,load_address_end,img->data_length); } entry_address = (unsigned long)img->entry_point; #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK cksum = cyg_crc32((unsigned char *)mem_addr, img->data_length); if (show_cksum) { diag_printf("Checksum: 0x%08lx\n", cksum); } // When decompressing, leave CRC checking to decompressor if (!decompress && img->file_cksum) { if (cksum != img->file_cksum) { diag_printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n", img->file_cksum, cksum); entry_address = (unsigned long)NO_MEMORY; } } #endif }
HRESULT fis_delete_progress(char *name, FIS_PROGRESS_FUNC progressFunc) { int num_reserved, i, stat; void *err_addr; struct fis_image_desc *img; FIS_PROGRESS_STRUCT progress; memset (&progress,0,sizeof(progress)); 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 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG num_reserved++; #endif num_reserved++; memcpy(fis_work_block, fis_addr, fisdir_size); img = fis_lookup(name, &i); if (img) { if (i < num_reserved) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Sorry, '%s' is a reserved image and cannot be deleted\n\r", img->name); return E_FIS_ILLEGAL_IMAGE; } } else { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "No image '%s' found\n\r", name); return E_FIS_ILLEGAL_IMAGE; } if (progressFunc) { progress.func = progressFunc; progress.procur = 0; progress.promax = fis_flash_erase_progressinfo (img->size); progress.promax += 10; //to update the directory progressFunc(progress.promax, progress.procur); } // Erase Data blocks (free space) if ((stat = fis_flash_erase_progress((void *)img->flash_base, img->size, (void **)&err_addr, &progress)) != 0) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Error erasing at %p: %s\n\r", err_addr, flash_errmsg(stat)); return E_FIS_FLASH_OP_FAILED; } else { img->name[0] = (unsigned char)0xFF; fis_update_directory(); } progressFunc(progress.promax, progress.promax); return NO_ERROR; }
HRESULT fis_create_progress(CYG_ADDRESS mem_addr, uint32 length, CYG_ADDRESS exec_addr, CYG_ADDRESS entry_addr, char *name, BOOL bDeleteIfNeeded, FIS_PROGRESS_FUNC progressFunc) { int stat, i; unsigned long img_size; CYG_ADDRESS flash_addr; void *err_addr; struct fis_image_desc *img = NULL; BOOL bFlashAddrGood = FALSE; BOOL bDelOldImage = FALSE; FIS_PROGRESS_STRUCT progress; memset (&progress,0,sizeof(progress)); memcpy(fis_work_block, fis_addr, fisdir_size); img_size = length; // 'length' is size of FLASH image, 'img_size' is actual data size // Round up length to FLASH block size length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size; if (length < img_size) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Internal error in image\n\r"); return E_FIS_ILLEGAL_IMAGE; } if (!name) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Internal error in image\n\r"); return E_FIS_ILLEGAL_IMAGE; } if (strlen(name) >= sizeof(img->name)) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Internal error in image\n\r"); return E_FIS_ILLEGAL_IMAGE; } // Search existing files to acquire defaults for params not specified: img = fis_lookup(name, NULL); // If we have an image we need to check if it is any good if (img) { if (length != img->size) { //in this case we either return an error or delete the old image if (!bDeleteIfNeeded) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Image already exist with different size\n\r"); return E_FIS_ILLEGAL_IMAGE; } //We need to remember to delete the image bDelOldImage = TRUE; SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Delete old image\n\r"); } else { bFlashAddrGood = TRUE; SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Reuse old image\n\r"); } } else { //need to find a new free image 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 (img->name[0] != (unsigned char)0xFF) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "No more directory entries\n\r"); return E_FIS_NO_SPACE; } SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Using new image\n\r"); } //we definitely have an img pointer which is valid //Let's figure out the work we need to do for the progress info if (progressFunc) { progress.func = progressFunc; progress.procur = 0; progress.promax = fis_flash_program_progressinfo(img_size); if (bDelOldImage || bFlashAddrGood) progress.promax += fis_flash_erase_progressinfo (img->size); if (!bFlashAddrGood) progress.promax += fis_flash_erase_progressinfo (length); progress.promax += 10; //to update the directory progressFunc(progress.promax, progress.procur); } if (bDelOldImage || bFlashAddrGood) { if ((stat = fis_flash_erase_progress((void *)img->flash_base, img->size, &err_addr, &progress )) != 0) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Flash Erase failed\n\r"); return E_FIS_FLASH_OP_FAILED; } } if (!bFlashAddrGood) { //we need to find space if (!fis_find_free(&flash_addr, length)) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "No free space in flash\n\r"); return E_FIS_NO_SPACE; } } else { flash_addr = img->flash_base; } //at this point we have erased old stuff if needed and we are ready to program if (((stat = flash_verify_addr((void *)flash_addr)) || (stat = flash_verify_addr((void *)(flash_addr+img_size-1))))) { //this should not happen, it is an internal error SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Internal error, illegal flash address\n\r"); return E_FIS_FLASH_OP_FAILED; } if (flash_addr & (flash_block_size-1)) { //this should not happen, it is an internal error SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Internal error, illegal flash address\n\r"); return E_FIS_FLASH_OP_FAILED; } // We need to erase the new are we found but it is likely clean so we will not progress it // as it will only be a blank check if (!bFlashAddrGood) { if ((stat = fis_flash_erase_progress((void *)img->flash_base, img->size, &err_addr, &progress)) != 0) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Flash erase failed\n\r"); return E_FIS_FLASH_OP_FAILED; } } if (mem_addr!=0xffffffff) //ML:Create image without programming if addr=0xffffffff { // Now program it if ((stat = fis_flash_program_progress((void *)flash_addr, (void *)mem_addr, img_size, &err_addr,&progress)) != 0) { SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Flash program failed\n\r"); return E_FIS_FLASH_OP_FAILED; } } // Update directory memset(img, 0, sizeof(*img)); strcpy(img->name, name); img->flash_base = flash_addr; img->mem_base = exec_addr; img->entry_point = entry_addr; // Hope it's been set img->size = length; img->data_length = img_size; #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK img->file_cksum = cyg_crc32((unsigned char *)flash_addr, img_size); #endif fis_update_directory(); if (progressFunc) progressFunc(progress.promax, progress.promax); return NO_ERROR; }
int fw_check_image_wili(unsigned char *addr, unsigned long maxlen, int do_flash) { header_t *header = (header_t *) addr; fw_t fw; int len = sizeof(header_t) - 2 * sizeof(u_int32_t); unsigned int crc = crc32(0L, (unsigned char *)header, len); signature_t *sig; fw.size = maxlen; if (strncmp(header->magic, MAGIC_HEADER, 4)) { return -1; } if (htonl(crc) != header->crc) { diag_printf("WILI_FW: header crc failed\n"); return -1; } memcpy(fw.version, header->version, sizeof(fw.version)); if (do_flash) diag_printf("WILI_FW: Firmware version: '%s'\n", header->version); part_t *p; p = (part_t *) (addr + sizeof(header_t)); int i = 0; while (strncmp(p->magic, MAGIC_END, MAGIC_LENGTH) != 0) { if (do_flash) { diag_printf("Partition: %s\n", p->name); diag_printf("Partition size: 0x%X\n", ntohl(p->part_size)); diag_printf("Data size: %u\n", ntohl(p->data_size)); } if ((strncmp(p->magic, MAGIC_PART, MAGIC_LENGTH) == 0) && (i < MAX_PARTS)) { fw_part_t *fwp = &fw.parts[i]; fwp->header = p; fwp->data = (unsigned char *)p + sizeof(part_t); fwp->data_size = ntohl(p->data_size); fwp->signature = (part_crc_t *) (fwp->data + fwp->data_size); crc = htonl(crc32 (0L, (unsigned char *)p, fwp->data_size + sizeof(part_t))); if (crc != fwp->signature->crc) { diag_printf ("WILI_FW: Invalid '%s' CRC (claims: %u, but is %u)\n", fwp->header->name, fwp->signature->crc, crc); return -1; } int index; struct fis_image_desc *img = fis_lookup(fwp->header->name, &index); if (!img) { diag_printf ("WILI_FW: cannot find partition %s, not flashable!\n"); return -1; } ++i; } p = (part_t *) ((unsigned char *)p + sizeof(part_t) + ntohl(p->data_size) + sizeof(part_crc_t)); /* check bounds */ if (((unsigned char *)p - addr) >= maxlen) { return -3; } } fw.part_count = i; sig = (signature_t *) p; if (strncmp(sig->magic, MAGIC_END, MAGIC_LENGTH) != 0) { diag_printf("WILI_FW: Bad firmware signature\n"); return -4; } crc = htonl(crc32(0L, addr, (unsigned char *)sig - addr)); if (crc != sig->crc) { diag_printf ("WILI_FW: Invalid signature CRC (claims: %u, but is %u)\n", sig->crc, crc); return -5; } if (do_flash) { char *arg[] = { "fis", "init" }; fis_init(2, arg, 1); void *err_addr; flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); for (i = 0; i < fw.part_count; ++i) { fw_part_t *fwp = &fw.parts[i]; if (!strncmp(fwp->header->name, "RedBoot", 7) && ntohl(fwp->header->part_size) > 0x10000) { diag_printf("ignore %s\n", fwp->header->name); continue; } diag_printf("WILI_FW: Flashing: %s\n", fwp->header->name); int stat; int index; struct fis_image_desc *img = fis_lookup(fwp->header->name, &index); if (!img) { diag_printf ("WILI_FW: cannot find partition %s, not flashable. break\n"); return -1; } stat = erase_and_flash("WILI_FW",img->flash_base,(void *)fwp->data,ntohl(fwp->header->part_size)); img->size = ntohl(fwp->header->part_size); img->data_length = ntohl(fwp->header->data_size); } fis_update_directory(); diag_printf("WILI_FW: flashing done\n"); } return 0; }