Пример #1
0
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();
    }
}
Пример #2
0
//
// Write the in-memory copy of the configuration data to the flash device.
//
void
flash_write_config(bool prompt)
{
#if defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
    void *err_addr;
#if !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
    int stat;
#endif
#endif

    config->len = sizeof(struct _config);
    config->key1 = CONFIG_KEY1;  
    config->key2 = CONFIG_KEY2;
    config->cksum = flash_crc(config);
    if (!prompt || verify_action("Update RedBoot non-volatile configuration")) {
#ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
        fis_read_directory();
        fis_update_directory();
#else 
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
        // Insure [quietly] that the config page is unlocked before trying to update
        flash_unlock((void *)cfg_base, cfg_size, (void **)&err_addr);
#endif
        if ((stat = flash_erase(cfg_base, cfg_size, (void **)&err_addr)) != 0) {
            diag_printf("   initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));
        } else {
            conf_endian_fixup(config);
            if ((stat = FLASH_PROGRAM(cfg_base, config, sizeof(struct _config), (void **)&err_addr)) != 0) {
                diag_printf("Error writing config data at %p: %s\n", 
                            err_addr, flash_errmsg(stat));
            }
            conf_endian_fixup(config);
        }
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
        // Insure [quietly] that the config data is locked after the update
        flash_lock((void *)cfg_base, cfg_size, (void **)&err_addr);
#endif
#endif // CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
#else  // CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH
        write_eeprom(config, sizeof(struct _config));  // into 'config'
#endif
    }
}
Пример #3
0
static int
flash_fis_op2( int op, unsigned int index, struct fis_table_entry *entry)
{
   int res=0;
   CYGARC_HAL_SAVE_GP();
   switch ( op ) {
      case CYGNUM_CALL_IF_FLASH_FIS_GET_VERSION:
         res=CYG_REDBOOT_FIS_VERSION;
         break;
      case CYGNUM_CALL_IF_FLASH_FIS_INIT:
         __flash_init=0;  //force reinitialization
         res=do_flash_init();
         break;
      case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_COUNT:
         res=fisdir_size / sizeof(struct fis_image_desc);
         break;
      case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY:
         {
            struct fis_image_desc* img = (struct fis_image_desc *)fis_work_block;
            CYG_ASSERT(entry!=0, "fis_table_entry == 0 !");
            memcpy(entry->name, img[index].u.name, 16);
            entry->flash_base=img[index].flash_base;
            entry->mem_base=img[index].mem_base;
            entry->size=img[index].size;
            entry->entry_point=img[index].entry_point;
            entry->data_length=img[index].data_length;
            entry->desc_cksum=img[index].desc_cksum;
            entry->file_cksum=img[index].file_cksum;
            res=0;
         }
         break;
      case CYGNUM_CALL_IF_FLASH_FIS_START_UPDATE:
         fis_start_update_directory(1);
         break;
      case CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE:
         fis_update_directory(1, index);
         break;
      case CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY:
         {
            res=0;
            if (entry->name[0]!=0xff)
            {
               if ((entry->size==0)
                   || ((entry->size % flash_block_size) !=0)
                   || (flash_verify_addr((void*)entry->flash_base)!=0)
                   || (flash_verify_addr((void*)(entry->flash_base+entry->size-1))!=0)
                   || (entry->size < entry->data_length))
                  res=-1;
            }

            if (res==0)
            {
               struct fis_image_desc* img = (struct fis_image_desc *)fis_work_block;
               memcpy(img[index].u.name, entry->name, 16);
               img[index].flash_base=entry->flash_base;
               img[index].mem_base=entry->mem_base;
               img[index].size=entry->size;
               img[index].entry_point=entry->entry_point;
               img[index].data_length=entry->data_length;
               img[index].desc_cksum=entry->desc_cksum;
               img[index].file_cksum=entry->file_cksum;
            }
         }
         break;
      default:
         break;
   }
   CYGARC_HAL_RESTORE_GP();
   return res;
}
Пример #4
0
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();
    }
}
Пример #5
0
static void
fis_init(int argc, char *argv[])
{
    int stat;
    struct fis_image_desc *img;
    void *err_addr;
    bool full_init = false;
    struct option_info opts[1];
    CYG_ADDRESS redboot_flash_start;
    unsigned long redboot_image_size;

    init_opts(&opts[0], 'f', false, OPTION_ARG_TYPE_FLG, 
              (void *)&full_init, (bool *)0, "full initialization, erases all of flash");
    if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, ""))
    {
        return;
    }

    if (!verify_action("About to initialize [format] FLASH image system")) {
        diag_printf("** Aborted\n");
        return;
    }
    diag_printf("*** Initialize FLASH Image System\n");

#define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE
    redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? 
                         flash_block_size : MIN_REDBOOT_IMAGE_SIZE;

    // Create a pseudo image for RedBoot
    img = (struct fis_image_desc *)fis_work_block;
    memset(img, 0xFF, fisdir_size);  // Start with erased data
#ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
    memset(img, 0, sizeof(*img));
    strcpy(img->name, "(reserved)");
    img->flash_base = (CYG_ADDRESS)flash_start;
    img->mem_base = (CYG_ADDRESS)flash_start;
    img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
    img++;
#endif
    redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT
    memset(img, 0, sizeof(*img));
    strcpy(img->name, "RedBoot");
    img->flash_base = redboot_flash_start;
    img->mem_base = redboot_flash_start;
    img->size = redboot_image_size;
    img++;
    redboot_flash_start += redboot_image_size;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
#ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET
    // Take care to place the POST entry at the right offset:
    redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET;
#endif
    memset(img, 0, sizeof(*img));
    strcpy(img->name, "RedBoot[post]");
    img->flash_base = redboot_flash_start;
    img->mem_base = redboot_flash_start;
    img->size = redboot_image_size;
    img++;
    redboot_flash_start += redboot_image_size;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
    // And a backup image
    memset(img, 0, sizeof(*img));
    strcpy(img->name, "RedBoot[backup]");
    img->flash_base = redboot_flash_start;
    img->mem_base = redboot_flash_start;
    img->size = redboot_image_size;
    img++;
    redboot_flash_start += redboot_image_size;
#endif
#if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
    // And a descriptor for the configuration data
    memset(img, 0, sizeof(*img));
    strcpy(img->name, "RedBoot config");
    img->flash_base = (CYG_ADDRESS)cfg_base;
    img->mem_base = (CYG_ADDRESS)cfg_base;
    img->size = cfg_size;
    img++;
#endif
    // And a descriptor for the descriptor table itself
    memset(img, 0, sizeof(*img));
    strcpy(img->name, "FIS directory");
    img->flash_base = (CYG_ADDRESS)fis_addr;
    img->mem_base = (CYG_ADDRESS)fis_addr;
    img->size = fisdir_size;
    img++;

#ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID
    // FIS gets the size of a full block - note, this should be changed
    // if support is added for multi-block FIS structures.
    img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + fisdir_size);
    // Add a footer so the FIS will be recognized by the ARM Boot
    // Monitor as a reserved area.
    {
        tFooter* footer_p = (tFooter*)((CYG_ADDRESS)img - sizeof(tFooter));
        cyg_uint32 check = 0;
        cyg_uint32 *check_ptr = (cyg_uint32 *)footer_p;
        cyg_int32 count = (sizeof(tFooter) - 4) >> 2;

        // Prepare footer. Try to protect all but the reserved space
        // and the first RedBoot image (which is expected to be
        // bootable), but fall back to just protecting the FIS if it's
        // not at the default position in the flash.
#if defined(CYGOPT_REDBOOT_FIS_RESERVED_BASE) && (-1 == CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK)
        footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(flash_start);
        footer_p->blockBase += CYGNUM_REDBOOT_FLASH_RESERVED_BASE + redboot_image_size;
#else
        footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(fis_work_block);
#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, if there is any
        if ( erase_start < (((CYG_ADDRESS)flash_end)+1) ) {
            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();
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
HRESULT fis_init(void)
{
	int stat;
	struct fis_image_desc *img;
	void *err_addr;
	bool full_init = true;
	CYG_ADDRESS redboot_flash_start;
	unsigned long redboot_image_size;


	SYS_DEBUG(SYSDEBUG_TRACE_FIS, "*** Initialize FLASH Image System\n\r");

#define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE
	redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? 
	flash_block_size : MIN_REDBOOT_IMAGE_SIZE;

	// Create a pseudo image for RedBoot
	img = (struct fis_image_desc *)fis_work_block;
	memset(img, 0xFF, fisdir_size);  // Start with erased data
#ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
	memset(img, 0, sizeof(*img));
	strcpy(img->name, "(reserved)");
	img->flash_base = (CYG_ADDRESS)flash_start;
	img->mem_base = (CYG_ADDRESS)flash_start;
	img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
	img++;
#endif
	redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT
	memset(img, 0, sizeof(*img));
	strcpy(img->name, "RedBoot");
	img->flash_base = redboot_flash_start;
	img->mem_base = redboot_flash_start;
	img->size = redboot_image_size;
	img++;
	redboot_flash_start += redboot_image_size;
#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
#ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET
	// Take care to place the POST entry at the right offset:
	redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET;
#endif
	memset(img, 0, sizeof(*img));
	strcpy(img->name, "RedBoot[post]");
	img->flash_base = redboot_flash_start;
	img->mem_base = redboot_flash_start;
	img->size = redboot_image_size;
	img++;
	redboot_flash_start += redboot_image_size;

	SYS_DEBUG(SYSDEBUG_TRACE_FIS, "redboot_flash_start = %x.\n\r", redboot_flash_start);

#endif
#ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
	// And a backup image
	memset(img, 0, sizeof(*img));
	strcpy(img->name, "RedBoot[backup]");
	img->flash_base = redboot_flash_start;
	img->mem_base = redboot_flash_start;
	img->size = redboot_image_size;
	img++;
	redboot_flash_start += redboot_image_size;
#endif
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
	// And a descriptor for the configuration data
	memset(img, 0, sizeof(*img));
	strcpy(img->name, "RedBoot config");
	img->flash_base = (CYG_ADDRESS)cfg_base;
	img->mem_base = (CYG_ADDRESS)cfg_base;
	img->size = cfg_size;
	img++;
#endif
	// And a descriptor for the descriptor table itself
	memset(img, 0, sizeof(*img));
	strcpy(img->name, "FIS directory");
	img->flash_base = (CYG_ADDRESS)fis_addr;
	img->mem_base = (CYG_ADDRESS)fis_addr;
	img->size = fisdir_size;
	img++;

	// 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 = fis_flash_erase((void *)erase_start, erase_size, (void **)&err_addr)) != 0) 
			{
				SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   initialization failed at %p: %s\n\r", err_addr, flash_errmsg(stat));
			}
		}
#endif
		//zluo, hack 
		if(redboot_flash_start < 0x4020000)
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "redboot_flash_start = %p\n\r", redboot_flash_start);
			return NO_ERROR;
		}
		// 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(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 = fis_flash_erase((void *)erase_start, erase_size,
                                    (void **)&err_addr)) != 0) 
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   initialization failed %p: %s\n\r",
								 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 = fis_flash_erase((void *)erase_start, erase_size,
																(void **)&err_addr)) != 0) 
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   initialization failed %p: %s\n\r",
					 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 = fis_flash_erase((void *)erase_start, erase_size, (void **)&err_addr)) != 0) 
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   initialization failed %p: %s\n\r", 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 = fis_flash_erase((void *)erase_start, erase_size, (void **)&err_addr)) != 0) 
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   initialization failed at %p: %s\n\r",
								 err_addr, flash_errmsg(stat));
		}
	} 
	else 
	{
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "    Warning: device contents not erased, some blocks may not be usable\n\r");
	}
	fis_update_directory();
	return NO_ERROR;
}
Пример #9
0
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;
}