Пример #1
0
void
fis_update_directory(void)
{
    int stat;
    void *err_addr;

    fis_endian_fixup(fis_work_block);
#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
    memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
    conf_endian_fixup((char *)fis_work_block+fisdir_size);
#endif
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
    // Ensure [quietly] that the directory is unlocked before trying to update
    flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
#endif
    if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {
        diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
    } else {
        if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block,
                                  flash_block_size, (void **)&err_addr)) != 0) {
            diag_printf("Error writing FIS directory at %p: %s\n", 
                        err_addr, flash_errmsg(stat));
        }
    }
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
    // Ensure [quietly] that the directory is locked after the update
    flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
#endif
    fis_endian_fixup(fis_work_block);
}
Пример #2
0
HRESULT fis_write(CYG_ADDRESS mem_addr, uint32 length, CYG_ADDRESS flash_addr)
{
	int stat;
	void *err_addr;
	bool prog_ok;

	SYS_DEBUG(SYSDEBUG_TRACE_FIS, "fis_write(%x, %x, %x)\n\r", mem_addr, length, flash_addr);

	// Round up length to FLASH block size
	if (((stat = flash_verify_addr((void *)flash_addr)) ||
			 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) 
	{
		_show_invalid_flash_address(flash_addr, stat);
		return NO_ERROR;
	}
	if (flash_addr & (flash_block_size-1)) 
	{
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Invalid FLASH address: %p\n\r", (void *)flash_addr);
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   must be 0x%x aligned\n\r", flash_block_size);
		return NO_ERROR;
	}
	if ((mem_addr < (CYG_ADDRESS)ram_start) ||
			((mem_addr+length) >= (CYG_ADDRESS)ram_end))
	{
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "** WARNING: RAM address: %p may be invalid\n\r", (void *)mem_addr);
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   valid range is %p-%p\n\r", (void *)ram_start, (void *)ram_end);
	}
	// 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+length-1)))
	{
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Can't program this region - contains code in use!\n\r");
		return NO_ERROR;
	}
	prog_ok = true;
	if (prog_ok)
	{
		// Erase area to be programmed
		if ((stat = fis_flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0)
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Can't erase region at %p: %s\n\r", err_addr, flash_errmsg(stat));
			prog_ok = false;
		}
	}
	if (prog_ok)
	{
		// Now program it
		if ((stat = fis_flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0)
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "fis_write: can't program region at %p: %s\n\r", 
			err_addr, flash_errmsg(stat));

			//sysDebugPrintf("Can't program region at %p: %s\n\r", err_addr, stat);
			// prog_ok = false;
		}
	}
	return NO_ERROR;
}
Пример #3
0
HRESULT fis_erase(CYG_ADDRESS flash_addr, unsigned long length)
{
	int stat;
	void *err_addr;

	if (((stat = flash_verify_addr((void *)flash_addr)) ||
			 (stat = flash_verify_addr((void *)(flash_addr+length-1)))))
	{
		_show_invalid_flash_address(flash_addr, stat);
		return NO_ERROR;
	}
	if (flash_addr & (flash_block_size-1))
	{
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Invalid FLASH address: %p\n\r", (void *)flash_addr);
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   must be 0x%x aligned\n\r", flash_block_size);
		return NO_ERROR;
	}
	// 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+length-1)))
	{
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Can't erase this region - contains code in use!\n\r");
		return NO_ERROR;
	}
	if ((stat = fis_flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0)
	{
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Error erasing at %p: %s\n\r", err_addr, flash_errmsg(stat));
	}
	return NO_ERROR;
}
Пример #4
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();
    }
}
Пример #5
0
static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address, uint32_t len)
{
    int retval;
    int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/

    retval = loadDriver(info);
    if (retval != ERROR_OK)
        return retval;

    uint32_t flashErr;
    retval = runCode(info,
                     info->start_address + OFFSET_ERASE,
                     info->start_address + OFFSET_ERASE + OFFSET_ERASE_SIZE,
                     address,
                     len,
                     0,
                     &flashErr,
                     timeout
                    );
    if (retval != ERROR_OK)
        return retval;

    if (flashErr != 0x0)
    {
        LOG_ERROR("Flash erase failed with %d (%s)", (int)flashErr, flash_errmsg(flashErr));
        return ERROR_FAIL;
    }

    return ERROR_OK;
}
Пример #6
0
static void fis_update_directory(void)
{
    int stat;
    void *err_addr;
	
#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
    memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
#endif
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
    // Ensure [quietly] that the directory is unlocked before trying to update
    flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
#endif
    if ((stat = fis_flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {
		SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Error erasing FIS directory at %p: %s\n\r", err_addr, flash_errmsg(stat));
    } else {
        if ((stat = fis_flash_program(fis_addr, fis_work_block, flash_block_size,
								  (void **)&err_addr)) != 0) {
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Error writing FIS directory at %p: %s\n\r", 
							   err_addr, flash_errmsg(stat));
        }
    }
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
    // Ensure [quietly] that the directory is locked after the update
    flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
#endif
}
Пример #7
0
int eCosBoard_flash(ecosflash_flash_bank_t *info, void *data, u32 address, u32 len)
{
	target_t *target=info->target;
	const int chunk=8192;
	int retval=ERROR_OK;
	int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/

	retval=loadDriver(info);
	if (retval!=ERROR_OK)
		return retval;

	u32 buffer;
	retval=runCode(info,
			info->start_address+OFFSET_GET_WORKAREA,
			info->start_address+OFFSET_GET_WORKAREA+OFFSET_GET_WORKAREA_SIZE,
			0,
			0,
			0,
			&buffer,
			1000);
	if (retval!=ERROR_OK)
		return retval;


	int i;
	for (i=0; i<len; i+=chunk)
	{
		int t=len-i;
		if (t>chunk)
		{
			t=chunk;
		}

		int retval;
		retval=target_write_buffer(target, buffer, t, ((u8 *)data)+i);
		if (retval != ERROR_OK)
			return retval;

		u32 flashErr;
		retval=runCode(info,
				info->start_address+OFFSET_FLASH,
				info->start_address+OFFSET_FLASH+OFFSET_FLASH_SIZE,
				buffer,
				address+i,
				t,
				&flashErr,
				timeout);
		if (retval != ERROR_OK)
			return retval;

		if (flashErr != 0x0)
		{
			LOG_ERROR("Flash prog failed with %d (%s)\n", flashErr, flash_errmsg(flashErr));
			return ERROR_FAIL;
		}
	}
	return ERROR_OK;
}
Пример #8
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
    }
}
Пример #9
0
static bool do_flash_init(void)
{
	int stat;

	ram_start = (unsigned char *)CYGMEM_REGION_ram;
	ram_end = (unsigned char *)(CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE);
#ifdef CYGMEM_SECTION_heap1
	workspace_start = (unsigned char *)CYGMEM_SECTION_heap1;
	workspace_end = (unsigned char *)(CYGMEM_SECTION_heap1+CYGMEM_SECTION_heap1_SIZE);
	workspace_size = CYGMEM_SECTION_heap1_SIZE;
#endif
	if (!__flash_init) 
	{
		if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE), 
														 FLASH_MIN_WORKSPACE, (_printf *)fisPrintf)) != 0) 
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "FLASH: driver init failed: %s\n\r", flash_errmsg(stat));
			return false;
		}
		flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
		// Keep 'end' address as last valid location, to avoid wrap around problems
		flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
		flash_get_block_info(&flash_block_size, &flash_num_blocks);

		workspace_end = (unsigned char *)(workspace_end-FLASH_MIN_WORKSPACE);
#ifdef CYGOPT_REDBOOT_FIS
#ifdef CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER
		fis_work_block = fis_zlib_common_buffer;
		if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < flash_block_size)
		{
			SYS_DEBUG(SYSDEBUG_TRACE_FIS, "FLASH: common buffer too small\n\r");
								workspace_end += FLASH_MIN_WORKSPACE;
			return false;
		}
#else
		workspace_end = (unsigned char *)(workspace_end-flash_block_size);
		fis_work_block = workspace_end;
#endif
		fisdir_size = flash_block_size;
		if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) 
		{
			fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
													(CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
		} 
		else 
		{
			fis_addr = (void *)((CYG_ADDRESS)flash_start + 
													(CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
		}
#endif
		__flash_init = 1;
	}
	return true;
}
Пример #10
0
// Program the current page into flash.
void flash_load_finish(void)
{
  cyg_uint32 retcode = FLASH_ERR_OK;
  void * err_addr;
  
  if (init_done && flash_page_init) {
    flash_page_init = false;
    
    retcode = flash_erase(current_flash_page, flash_block_size, &err_addr);
    if (retcode != FLASH_ERR_OK){
      diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode));
    } else {
      retcode = flash_program(current_flash_page, flash_buffer, 
                              flash_block_size, &err_addr);
      if (retcode != FLASH_ERR_OK){ 
        diag_printf("Error writing at %p: %s\n", 
                    err_addr, flash_errmsg(retcode));
      }
    }
  }
  flash_init(diag_printf);
}
Пример #11
0
// Write a byte into flash. We maintain a copy in RAM of the FLASH
// page we are currently "writing" into. This copy is loaded with the
// current contents of the FLASH page when the first byte is "written"
// to the page. The "writes" are then made into the RAM copy. We only
// write to FLASH when there is a "write" outside of the current page,
// or the flash_load_finish function is called.
void flash_load_write(cyg_uint8 *flash_addr, cyg_uint8 value)
{
  
  cyg_uint32 retcode = FLASH_ERR_OK;
  void * err_addr;
  cyg_uint32 addr = (cyg_uint32)flash_addr;
  cyg_uint32 offset;
  
  if (!flash_page_init) { 
    /* First Byte for the current flash block. Read the current contents */
    current_flash_page = flash_block_begin(addr);
    flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr); 
    flash_page_init = true;
  } 
  if (flash_block_begin(addr) != current_flash_page) { 
    /* We have moved into the next flash page. Write the current
       page so we can move on */
    retcode = flash_erase(current_flash_page, flash_block_size, &err_addr);
    if (retcode != FLASH_ERR_OK){ /* Flash ERROR */
      diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode));
      return;
    }
    
    retcode = flash_program(current_flash_page, flash_buffer, 
                            flash_block_size, &err_addr); 
    if (retcode != FLASH_ERR_OK){ 
      diag_printf("Error writing at %p: %s\n", 
                  err_addr, flash_errmsg(retcode));
      return;
    }
    current_flash_page = flash_block_begin(addr);
    flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr);
  }
  
  offset = flash_addr - current_flash_page;
  CYG_ASSERT(offset < flash_block_size, "offset not inside flash block");
  
  flash_buffer[offset] = value;
}
Пример #12
0
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));
    }
}
Пример #13
0
static void
fis_erase(int argc, char *argv[])
{
    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, (void **)0, 0, ""))
    {
        fis_usage("invalid arguments");
        return;
    }

    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 (flash_addr_set && flash_addr & (flash_block_size-1)) {
        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
        diag_printf("   must be 0x%x aligned\n", flash_block_size);
        return;
    }
    // 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+length-1))) {
        diag_printf("Can't erase this region - contains code in use!\n");
        return;
    }
    if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
        diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
    }
}
Пример #14
0
bool
do_flash_init(void)
{
    int stat;

    if (!__flash_init) {
        __flash_init = 1;
        if ((stat = flash_init(diag_printf)) != 0) {
            diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
            return false;
        }
        flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
        // Keep 'end' address as last valid location, to avoid wrap around problems
        flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
        flash_get_block_info(&flash_block_size, &flash_num_blocks);
#ifdef CYGOPT_REDBOOT_FIS
        fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE;
        fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
# if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
	fis_work_block = fis_zlib_common_buffer;
	if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) {
            diag_printf("FLASH: common buffer too small\n");
            return false;
	}
# else
        workspace_end = (unsigned char *)(workspace_end-fisdir_size);
        fis_work_block = workspace_end;
# endif
        if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
            fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
        } else {
            fis_addr = (void *)((CYG_ADDRESS)flash_start + 
                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
        }
        if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
            diag_printf("FIS directory doesn't fit\n");
            return false;
        }
        fis_read_directory();
#endif
    }
    return true;
}
Пример #15
0
void _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat)
{
	SYS_DEBUG(SYSDEBUG_TRACE_FIS, "Invalid FLASH address %p: %s\n\r", (void *)flash_addr, flash_errmsg(stat));
	SYS_DEBUG(SYSDEBUG_TRACE_FIS, "   valid range is %p-%p\n\r", (void *)flash_start, (void *)flash_end);
}
Пример #16
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();
    }
}
Пример #17
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();
}
Пример #18
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;
}
Пример #19
0
static void        
_show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat)
{
    diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
    diag_printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
}
Пример #20
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;
}
Пример #21
0
static void
fis_write(int argc, char *argv[])
{
    int stat;
    unsigned long length;
    CYG_ADDRESS mem_addr, flash_addr;
    bool mem_addr_set = false;
    bool flash_addr_set = false;
    bool length_set = false;
    void *err_addr;
    struct option_info opts[3];
    bool prog_ok;

    init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
              (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
    init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM, 
              (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
    init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM, 
              (void *)&length, (bool *)&length_set, "image length [in FLASH]");
    if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0))
    {
        fis_usage("invalid arguments");
        return;
    }

    if (!mem_addr_set || !flash_addr_set || !length_set) {
        fis_usage("required parameter missing");
        return;
    }

    // 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;
#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)) {
        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
        diag_printf("   must be 0x%x aligned\n", flash_block_size);
        return;
    }
    if ((mem_addr < (CYG_ADDRESS)ram_start) ||
        ((mem_addr+length) >= (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);
    }
    // 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+length-1))) {
        diag_printf("Can't program this region - contains code in use!\n");
        return;
    }
    if (!verify_action("* CAUTION * about to program FLASH\n            at %p..%p from %p", 
                       (void *)flash_addr, (void *)(flash_addr+length-1),
                       (void *)mem_addr)) {
        return;  // The guy gave up
    }
    prog_ok = true;
    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, length, (void **)&err_addr)) != 0) {
            diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
            prog_ok = false;
        }
    }
}
Пример #22
0
externC void
cyg_start( void )
{
    int stat;
    void *err_addr;
    CYG_ADDRWORD flash_start, flash_end;
    void **flash_start_addr = (void *)&flash_start;
    void **flash_end_addr = (void *)&flash_end;
    void *flash_test_start, *flash_addr;
    cyg_int32 flash_block_size, flash_num_blocks;
    CYG_ADDRWORD test_buf1, test_buf2;
    cyg_uint32 *lp1, *lp2;
    int i, len;
    cyg_bool passed, ok;

    CYG_TEST_INIT();

#if 0
    int j;
    
    diag_printf("Testing udelay: ");
    for (i = 0;  i < 30;  i++) {
        for (j = 0;  j < 1000;  j++) {
            CYGACC_CALL_IF_DELAY_US(1000);  // Should be 1 second
        }
        diag_printf(".");
    }
    diag_printf("\n");
#endif

    passed = true;

    if ((stat = flash_init(diag_printf)) != 0) {
        diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
        CYG_TEST_FAIL_FINISH("FLASH driver init failed");
    }
    flash_get_limits((void *)0, flash_start_addr, flash_end_addr);
    // Keep 'end' address as last valid location, to avoid wrap around problems
    flash_end = flash_end - 1;
    flash_get_block_info(&flash_block_size, &flash_num_blocks);

    diag_printf("FLASH: 0x%x - 0x%x, %d blocks of 0x%x bytes each.\n", 
                flash_start, flash_end + 1, flash_num_blocks, 
                flash_block_size);

    // Verify that the testing limits are within the bounds of the
    // physical device.  Also verify that the size matches with
    // the erase block size on the device
    if ((CYGNUM_IO_FLASH_TEST_OFFSET > (flash_end - flash_start)) ||
        ((CYGNUM_IO_FLASH_TEST_OFFSET + CYGNUM_IO_FLASH_TEST_LENGTH) > (flash_end - flash_start))) {
        CYG_TEST_FAIL_FINISH("FLASH test region outside physical limits");
    }
    if ((CYGNUM_IO_FLASH_TEST_LENGTH % flash_block_size) != 0) {
        CYG_TEST_FAIL_FINISH("FLASH test region must be integral multiple of erase block size");
    }

    // Allocate two buffers large enough for the test
    test_buf1 = (CYG_ADDRWORD)CYGMEM_SECTION_heap1;
    test_buf2 = test_buf1 + CYGNUM_IO_FLASH_TEST_LENGTH;
    if (CYGMEM_SECTION_heap1_SIZE < (CYGNUM_IO_FLASH_TEST_LENGTH * 2)) {
        CYG_TEST_FAIL_FINISH("FLASH not enough heap space - reduce size of test region");
    }
    diag_printf("... Using test buffers at %p and %p\n", (void *)test_buf1, (void *)test_buf2);
    flash_test_start = (void *)(flash_start + CYGNUM_IO_FLASH_TEST_OFFSET);

#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING    
    // Unlock test
    diag_printf("... Unlock test\n");
    ok = true;
    if ((stat = flash_unlock(flash_test_start, 
                             CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: unlock failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
#endif
    
    // Erase test
    diag_printf("... Erase test\n");
    ok = true;
    if ((stat = flash_erase(flash_test_start, 
                            CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: erase failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
    if (ok && (stat = flash_read(flash_test_start, (void *)test_buf1,
                           CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: read/verify after erase failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
    lp1 = (cyg_uint32 *)test_buf1;
    for (i = 0;  i < CYGNUM_IO_FLASH_TEST_LENGTH;  i += sizeof(cyg_uint32)) {
        if (*lp1++ != 0xFFFFFFFF) {
            diag_printf("FLASH: non-erased data found at offset %x\n", (CYG_ADDRWORD)(lp1-1) - test_buf1);
            diag_dump_buf((void *)(lp1-1), 32);
            ok = false;
            break;
        }
    }
    // Try reading in little pieces
    len = CYGNUM_IO_FLASH_TEST_LENGTH;
    flash_addr = flash_test_start;
    while (len > 0) {
        if ((stat = flash_read(flash_addr, (void *)test_buf1, 0x200, &err_addr)) != CYG_FLASH_ERR_OK) {
            diag_printf("FLASH: read[short]/verify after erase failed: %s\n", flash_errmsg(stat));
            ok = false;
            break;
        }    
        flash_addr = (cyg_uint8 *)flash_addr + 0x200;
        len -= 0x200;
        lp1 = (cyg_uint32 *)test_buf1;
        for (i = 0;  i < 0x200;  i += sizeof(cyg_uint32)) {
            if (*lp1++ != 0xFFFFFFFF) {
                diag_printf("FLASH: non-erased data found at offset %p\n", 
                            (cyg_uint8 *)flash_addr + (CYG_ADDRWORD)((lp1-1) - test_buf1));
                diag_dump_buf((void *)(lp1-1), 32);
                ok = false;
                len = 0;
                break;
            }
        }
    }
    
    if (!ok) {
        CYG_TEST_INFO("FLASH erase failed");
        passed = false;
    }

    // Simple write/verify test
    diag_printf("... Write/verify test\n");
    lp1 = (cyg_uint32 *)test_buf1;
    for (i = 0;  i < CYGNUM_IO_FLASH_TEST_LENGTH;  i += sizeof(cyg_uint32)) {
        *lp1 = (cyg_uint32)lp1;
        lp1++;
    }
    ok = true;
    if (ok && (stat = flash_program(flash_test_start, (void *)test_buf1,
                                    CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: write failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
    if (ok && (stat = flash_read(flash_test_start, (void *)test_buf2,
                                    CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: read/verify after write failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
    lp1 = (cyg_uint32 *)test_buf1;
    lp2 = (cyg_uint32 *)test_buf2;
    for (i = 0;  i < CYGNUM_IO_FLASH_TEST_LENGTH;  i += sizeof(cyg_uint32)) {
        if (*lp2++ != *lp1++) {
            diag_printf("FLASH: incorrect data found at offset %x\n", (CYG_ADDRWORD)(lp2-1) - test_buf2);
            diag_dump_buf((void *)(lp2-1), 32);
            ok = false;
            break;
        }
    }
    // Try reading in little pieces
    len = CYGNUM_IO_FLASH_TEST_LENGTH;
    flash_addr = flash_test_start;
    lp1 = (cyg_uint32 *)test_buf1;
    lp2 = (cyg_uint32 *)test_buf2;
    while (len > 0) {
        if ((stat = flash_read(flash_addr, lp2, 0x200, &err_addr)) != CYG_FLASH_ERR_OK) {
            diag_printf("FLASH: read[short]/verify after erase failed: %s\n", flash_errmsg(stat));
            ok = false;
            break;
        }    
        flash_addr = (cyg_uint8 *)flash_addr + 0x200;
        len -= 0x200;
        for (i = 0;  i < 0x200;  i += sizeof(cyg_uint32)) {
            if (*lp2++ != *lp1++) {
                diag_printf("FLASH: incorrect data found at offset %p\n", 
                            (cyg_uint8 *)flash_addr + (CYG_ADDRWORD)((lp2-1) - test_buf2));
                diag_dump_buf((void *)(lp2-1), 32);
                ok = false;
                len = 0;
                break;
            }
        }
    }
    
    if (!ok) {
        CYG_TEST_INFO("FLASH write/verify failed");
    }

#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
    // Lock test
    diag_printf("... Lock test\n");
    ok = true;
    if ((stat = flash_lock(flash_test_start, 
                           CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) {
        diag_printf("FLASH: unlock failed: %s\n", flash_errmsg(stat));
        ok = false;
    }    
#endif
    
    if (passed) {
        CYG_TEST_PASS_FINISH("FLASH test1");
    } else {
        CYG_TEST_FAIL_FINISH("FLASH test1");
    }
}