Beispiel #1
0
/*
 * Erase environment sector
 */
int do_default_env(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
	int	rc, rcode = 0;
#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
	unsigned char env_buffer[CFG_ENV_SECT_SIZE];
#endif

#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
	/* copy whole env sector to temporary buffer */
	memcpy(env_buffer, (void *)CFG_ENV_ADDR, CFG_ENV_SECT_SIZE);

	/* clear env part */
	memset(env_buffer, 0xFF, CFG_ENV_SIZE);
#endif

	/* erase whole env sector */
	if(flash_sect_erase(CFG_ENV_ADDR, CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1)){
		rcode = 1;
	}

#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
	/* restore data from buffer in FLASH */
	rc = flash_write((char *)env_buffer, CFG_ENV_ADDR, CFG_ENV_SECT_SIZE);

	if(rc != 0){
		flash_perror(rc);
		rcode = 1;
	}
#endif

	return(rcode);
}
Beispiel #2
0
static inline int
part_write(char *partition)
{
    unsigned long begin = part_begin(partition);
    unsigned long end   = begin + partool_size - 1;
    byte *tmp;
    int err;
    
    if (ADDR_BAD==begin) {
        return -EINVAL8;
    }
    
    err = flash_sect_erase(begin, end);
    if (err) {
        debug_error("flash erase(begin:0x%x end:0x%x size:0x%x) failed(%d)", 
            begin, end, partool_size, err);
        return err;
    }

    err = flash_write(part_tmp, begin, partool_size);
    if (err) {
        debug_error("flash write(begin:0x%x end:0x%x size:0x%x) failed(%d)", 
            begin, end, partool_size, err);
        return err;
    }

	return 0;
}
Beispiel #3
0
void do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
	flash_info_t *info;
	ulong bank, addr_first, addr_last;
	int n, sect_first, sect_last;

	if (argc < 2) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return;
	}

	if (strcmp(argv[1], "all") == 0) {
		for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
			printf ("Erase Flash Bank # %ld ", bank);
			info = &flash_info[bank-1];
			flash_erase (info, 0, info->sector_count-1);
		}
		return;
	}

	if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
		if (n < 0) {
			printf("Bad sector specification\n");
			return;
		}
		printf ("Erase Flash Sectors %d-%d in Bank # %d ",
			sect_first, sect_last, (info-flash_info)+1);
		flash_erase(info, sect_first, sect_last);
		return;
	}

	if (argc != 3) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return;
	}

	if (strcmp(argv[1], "bank") == 0) {
		bank = simple_strtoul(argv[2], NULL, 16);
		if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
			printf ("Only FLASH Banks # 1 ... # %d supported\n",
				CFG_MAX_FLASH_BANKS);
			return;
		}
		printf ("Erase Flash Bank # %ld ", bank);
		info = &flash_info[bank-1];
		flash_erase (info, 0, info->sector_count-1);
		return;
	}

	addr_first = simple_strtoul(argv[1], NULL, 16);
	addr_last  = simple_strtoul(argv[2], NULL, 16);

	if (addr_first >= addr_last) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return;
	}

	printf ("Erase Flash from 0x%08lx to 0x%08lx ", addr_first, addr_last);
	flash_sect_erase(addr_first, addr_last);
}
Beispiel #4
0
int do_install ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	int rc;
	size_t sect_top;

	if (argc != 1) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	for(sect_top=0; sect_top<sizeof(u_boot_bin_data); sect_top+=PHYS_FLASH_SECT_SIZE) continue;
	sect_top--;
	flash_sect_protect(0, CFG_FLASH_BASE, sect_top);
	flash_sect_erase(CFG_FLASH_BASE, sect_top);

	puts ("Copying to Flash... ");

	rc = flash_write ((uchar *)u_boot_bin_data, CFG_FLASH_BASE, sizeof(u_boot_bin_data));
	if (rc != 0) {
		flash_perror (rc);
		return (1);
	}
	puts ("done\n");
	return 0;
}
Beispiel #5
0
Datei: env.c Projekt: qgp/armboot
/*
 * save environment buffer back to flash
 * returns -1 on error, 0 if ok
 */
int board_env_save(bd_t *bd, env_t *env, int size)
{
    int rc;
    ulong start_addr, end_addr;

#if CFG_ENV_SIZE <= CFG_ENV_SECT_SIZE
#error Make sure that CFG_ENV_SIZE <= CFG_ENV_SECT_SIZE
#endif    

    start_addr = CFG_ENV_ADDR;
    end_addr   = start_addr + CFG_ENV_SIZE - 1;

    rc = flash_sect_protect(0, CFG_ENV_ADDR, end_addr);
    if (rc < 0)
      return rc;

    rc = flash_sect_erase(start_addr, end_addr);
    if (rc < 0)
    {
	flash_sect_protect(1, start_addr, end_addr);
	flash_perror(rc);
	return rc;
    }
    
    printf("Saving Environment to Flash...");
    rc = flash_write((uchar*)env, start_addr, size);
    if (rc < 0)
      flash_perror(rc);
    else 
      printf("done.\n");

    (void)flash_sect_protect(1, start_addr, end_addr);

    return 0;
}
Beispiel #6
0
static void prepare_flash(char **buff_ptr,long **val) 
{
	if((long)*buff_ptr % 4)
		*buff_ptr = *buff_ptr + ((long)*buff_ptr % 4);
        memcpy(*buff_ptr,(void *)((long)UBOOT_ENV_SEC_START),CFG_FLASH_SECTOR_SIZE);
	flash_sect_erase(UBOOT_ENV_SEC_START,UBOOT_ENV_SEC_START + (CFG_FLASH_SECTOR_SIZE - 1));
	*val = (long *)(*buff_ptr + CFG_FLASH_SECTOR_SIZE - 0x30);
}
Beispiel #7
0
int saveenv(void){
	char *saved_data = NULL;
	int rc = 1;
	char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
#if CFG_ENV_SECT_SIZE > CFG_ENV_SIZE
	ulong up_data = 0;

	up_data = (end_addr_new + 1 - ((long)flash_addr_new + CFG_ENV_SIZE));

	if(up_data){
		if((saved_data = malloc(up_data)) == NULL){
			printf("## Error: unable to save the rest of sector (%ld)\n", up_data);
			goto Done;
		}

		memcpy(saved_data, (void *)((long)flash_addr_new + CFG_ENV_SIZE), up_data);
	}
#endif
	if(flash_sect_erase((ulong)flash_addr_new, end_addr_new)){
		goto Done;
	}

	if((rc = flash_write((char *)env_ptr->data, (ulong)&(flash_addr_new->data), sizeof(env_ptr->data))) ||
	   (rc = flash_write((char *)&(env_ptr->crc), (ulong)&(flash_addr_new->crc), sizeof(env_ptr->crc))) ||
	   (rc = flash_write(&flag, (ulong)&(flash_addr->flags), sizeof(flash_addr->flags))) ||
	   (rc = flash_write(&new_flag, (ulong)&(flash_addr_new->flags), sizeof(flash_addr_new->flags)))){
		flash_perror(rc);
		goto Done;
	}

#if CFG_ENV_SECT_SIZE > CFG_ENV_SIZE
	if(up_data){ /* restore the rest of sector */
		if(flash_write(saved_data, (long)flash_addr_new + CFG_ENV_SIZE, up_data)){
			flash_perror(rc);
			goto Done;
		}
	}
#endif
	env_t * etmp = flash_addr;
	ulong ltmp = end_addr;

	flash_addr = flash_addr_new;
	flash_addr_new = etmp;

	end_addr = end_addr_new;
	end_addr_new = ltmp;

	rc = 0;

Done:

	if(saved_data){
		free(saved_data);
	}

	return(rc);
}
Beispiel #8
0
/*-----------------------------------------------------------------------
 * Copy memory to flash.
 * Make sure all target addresses are within Flash bounds,
 * and no protected sectors are hit.
 * Returns:
 * ERR_OK          0 - OK
 * ERR_TIMOUT      1 - write timeout
 * ERR_NOT_ERASED  2 - Flash not erased
 * ERR_PROTECTED   4 - target range includes protected sectors
 * ERR_INVAL       8 - target address not in Flash memory
 * ERR_ALIGN       16 - target address not aligned on boundary
 *			(only some targets require alignment)
 */
int
flash_write (char *src, ulong addr, ulong cnt)
{
#ifdef CONFIG_SPD823TS
	return (ERR_TIMOUT);	/* any other error codes are possible as well */
#else
	int i;
	ulong         end        = addr + cnt - 1;
	flash_info_t *info_first = addr2info (addr);
	flash_info_t *info_last  = addr2info (end );
	flash_info_t *info;

	if (cnt == 0) {
		return (ERR_OK);
	}

	if (!info_first || !info_last) {
		return (ERR_INVAL);
	}

	for (info = info_first; info <= info_last; ++info) {
		ulong b_end = info->start[0] + info->size;	/* bank end addr */
		short s_end = info->sector_count - 1;
		for (i=0; i<info->sector_count; ++i) {
			ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];

			if ((end >= info->start[i]) && (addr < e_addr) &&
			    (info->protect[i] != 0) ) {
				return (ERR_PROTECTED);
			}
		}
	}

	flash_sect_erase(addr, end);

	/* finally write data to flash */
	for (info = info_first; info <= info_last && cnt>0; ++info) {
		ulong len;

		len = info->start[0] + info->size - addr;
		if (len > cnt)
			len = cnt;
		if ((i = write_buff(info, (uchar *)src, addr, len)) != 0) {
			return (i);
		}
		cnt  -= len;
		addr += len;
		src  += len;
	}
	return (ERR_OK);
#endif /* CONFIG_SPD823TS */
}
Beispiel #9
0
int saveenv(void){
	int	len, rc;
	ulong end_addr, flash_sect_addr;
#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
	ulong flash_offset;
	uchar env_buffer[CFG_ENV_SECT_SIZE];
#else
	uchar *env_buffer = (uchar *)env_ptr;
#endif /* CFG_ENV_SECT_SIZE */
	int rcode = 0;

#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)

	flash_offset    = ((ulong)flash_addr) & (CFG_ENV_SECT_SIZE-1);
	flash_sect_addr = ((ulong)flash_addr) & ~(CFG_ENV_SECT_SIZE-1);

	//debug("copy old content: sect_addr: %08lX  env_addr: %08lX  offset: %08lX\n", flash_sect_addr, (ulong)flash_addr, flash_offset);

	/* copy old contents to temporary buffer */
	memcpy(env_buffer, (void *)flash_sect_addr, CFG_ENV_SECT_SIZE);

	/* copy current environment to temporary buffer */
	memcpy((uchar *)((unsigned long)env_buffer + flash_offset), env_ptr, CFG_ENV_SIZE);

	len	 = CFG_ENV_SECT_SIZE;
#else
	flash_sect_addr = (ulong)flash_addr;
	len = CFG_ENV_SIZE;
#endif	/* CFG_ENV_SECT_SIZE */

	end_addr = flash_sect_addr + len - 1;

	if(flash_sect_erase(flash_sect_addr, end_addr)){
		return(1);
	}

	rc = flash_write((char *)env_buffer, flash_sect_addr, len);

	if(rc != 0){
		flash_perror(rc);
		rcode = 1;
	} else {
		//debug("done\n");
	}

	return(rcode);
}
Beispiel #10
0
static int update_flash(ulong addr_source, ulong addr_first, ulong size)
{
#ifndef CONFIG_SYS_NO_FLASH
	ulong addr_last = addr_first + size - 1;

	/* round last address to the sector boundary */
	if (flash_sect_roundb(&addr_last) > 0)
		return 1;

	if (addr_first >= addr_last) {
		printf("Error: end address exceeds addressing space\n");
		return 1;
	}

	/* remove protection on processed sectors */
	if (update_flash_protect(0, addr_first, addr_last) > 0) {
		printf("Error: could not unprotect flash sectors\n");
		return 1;
	}

	printf("Erasing 0x%08lx - 0x%08lx", addr_first, addr_last);
	if (flash_sect_erase(addr_first, addr_last) > 0) {
		printf("Error: could not erase flash\n");
		return 1;
	}

	printf("Copying to flash...");
	if (flash_write((char *)addr_source, addr_first, size) > 0) {
		printf("Error: could not copy to flash\n");
		return 1;
	}
	printf("done\n");

	/* enable protection on processed sectors */
	if (update_flash_protect(1, addr_first, addr_last) > 0) {
		printf("Error: could not protect flash sectors\n");
		return 1;
	}
#endif
	return 0;
}
int do_katinstall ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	ulong	*addr, *src, count;
	char	*s;

	if (argc !=2 && argc != 3) {
		printf ("%d Usage:\n%s\n", argc, cmdtp->usage);
		return 1;
	}

	if(argc == 3) {
		src = (ulong *)simple_strtoul(argv[2], NULL, 16);
	} else {
		if ((s = getenv("loadaddr")) != NULL) {
			src = (ulong *)simple_strtoul(s, NULL, 16);
		} else {
			src = CFG_LOAD_ADDR;
		}
	}

	count = simple_strtoul(argv[1], NULL, 16);

	addr = (ulong *)(flash_info[0].size - count);

	if (count == 0) {
		puts ("Zero length ???\n");
		return 1;
	}

	printf("Copying kernel from 0x%08x to 0x%08x (length 0x%08x)...", src, addr, count);

	printf("Erasing...");
	flash_sect_erase(addr,flash_info[0].size-1);
	printf("Writing...");
	flash_write(src, addr, count);

	printf("done\n");
	return 0;
}
Beispiel #12
0
int saveenv(void)
{
	env_t	env_new;
	int	rc = 1;
	char	*saved_data = NULL;
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	ulong	up_data = 0;

	up_data = end_addr + 1 - ((long)flash_addr + CONFIG_ENV_SIZE);
	debug("Data to save 0x%lx\n", up_data);
	if (up_data) {
		saved_data = malloc(up_data);
		if (saved_data == NULL) {
			printf("Unable to save the rest of sector (%ld)\n",
				up_data);
			goto done;
		}
		memcpy(saved_data,
			(void *)((long)flash_addr + CONFIG_ENV_SIZE), up_data);
		debug("Data (start 0x%lx, len 0x%lx) saved at 0x%lx\n",
			(ulong)flash_addr + CONFIG_ENV_SIZE,
			up_data,
			(ulong)saved_data);
	}
#endif	/* CONFIG_ENV_SECT_SIZE */

	debug("Protect off %08lX ... %08lX\n", (ulong)flash_addr, end_addr);

	if (flash_sect_protect(0, (long)flash_addr, end_addr))
		goto done;

	rc = env_export(&env_new);
	if (rc)
		goto done;

	puts("Erasing Flash...");
	if (flash_sect_erase((long)flash_addr, end_addr))
		goto done;

	puts("Writing to Flash... ");
	rc = flash_write((char *)&env_new, (long)flash_addr, CONFIG_ENV_SIZE);
	if (rc != 0)
		goto perror;

#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	if (up_data) {	/* restore the rest of sector */
		debug("Restoring the rest of data to 0x%lx len 0x%lx\n",
			(ulong)flash_addr + CONFIG_ENV_SIZE, up_data);
		if (flash_write(saved_data,
				(long)flash_addr + CONFIG_ENV_SIZE,
				up_data))
			goto perror;
	}
#endif
	puts("done\n");
	rc = 0;
	goto done;
perror:
	flash_perror(rc);
done:
	if (saved_data)
		free(saved_data);
	/* try to re-protect */
	flash_sect_protect(1, (long)flash_addr, end_addr);
	return rc;
}
int do_flerase(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) {
	flash_info_t *info;
	ulong bank, addr_first, addr_last;
	int n, sect_first, sect_last;
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
	struct mtd_device *dev;
	struct part_info *part;
	u8 dev_type, dev_num, pnum;
#endif
	int rcode = 0;

	if (argc < 2) {
#ifdef  CFG_LONGHELP
		if(cmdtp->help != NULL) {
			printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->help);
		} else {
			printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
		}
#else
		printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
#endif
		return 1;
	}

	// erase whole flash?
	if (strcmp(argv[1], "all") == 0) {
		for (bank = 1; bank <= CFG_MAX_FLASH_BANKS; ++bank) {
			printf("Erase flash bank #%ld ", bank);
			info = &flash_info[bank - 1];
			rcode = flash_erase(info, 0, info->sector_count - 1);
		}
		return rcode;
	}

	if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
		if (n < 0) {
			puts("## Error: bad sector spec\n");
			return 1;
		}
		printf("Erase flash sectors %d-%d in bank #%d ", sect_first, sect_last, (info - flash_info) + 1);
		rcode = flash_erase(info, sect_first, sect_last);
		return rcode;
	}

#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
	/* erase <part-id> - erase partition */
	if ((argc == 2) && (id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
		mtdparts_init();
		if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) {
			if (dev->id->type == MTD_DEV_TYPE_NOR) {
				bank = dev->id->num;
				info = &flash_info[bank];
				addr_first = part->offset + info->start[0];
				addr_last = addr_first + part->size - 1;

				printf("Erase flash parition %s, bank %d, 0x%08lx - 0x%08lx ", argv[1], bank, addr_first, addr_last);

				rcode = flash_sect_erase(addr_first, addr_last);
				return rcode;
			}

			printf("## Error: cannot erase, not a NOR device\n");
			return 1;
		}
	}
#endif

	if (argc != 3) {
#ifdef  CFG_LONGHELP
		if(cmdtp->help != NULL) {
			printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->help);
		} else {
			printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
		}
#else
		printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
#endif
		return 1;
	}

	if (strcmp(argv[1], "bank") == 0) {
		bank = simple_strtoul(argv[2], NULL, 16);
		if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
			printf("## Error: only flash banks #1...#%d supported\n", CFG_MAX_FLASH_BANKS);
			return 1;
		}
		printf("Erase flash bank #%ld ", bank);
		info = &flash_info[bank - 1];
		rcode = flash_erase(info, 0, info->sector_count - 1);
		return rcode;
	}

	if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0) {
		printf("## Error: bad address format\n");
		return 1;
	}

	if (addr_first >= addr_last) {
#ifdef  CFG_LONGHELP
		if(cmdtp->help != NULL) {
			printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->help);
		} else {
			printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
		}
#else
		printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
#endif
		return 1;
	}

	rcode = flash_sect_erase(addr_first, addr_last);
	return rcode;
}
Beispiel #14
0
int saveenv(void)
{
	env_t	env_new;
	char	*saved_data = NULL;
	char	flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
	int	rc = 1;
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	ulong	up_data = 0;
#endif

	debug("Protect off %08lX ... %08lX\n", (ulong)flash_addr, end_addr);

	if (flash_sect_protect(0, (ulong)flash_addr, end_addr))
		goto done;

	debug("Protect off %08lX ... %08lX\n",
		(ulong)flash_addr_new, end_addr_new);

	if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new))
		goto done;

	rc = env_export(&env_new);
	if (rc)
		return rc;
	env_new.flags	= new_flag;

#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	up_data = end_addr_new + 1 - ((long)flash_addr_new + CONFIG_ENV_SIZE);
	debug("Data to save 0x%lX\n", up_data);
	if (up_data) {
		saved_data = malloc(up_data);
		if (saved_data == NULL) {
			printf("Unable to save the rest of sector (%ld)\n",
				up_data);
			goto done;
		}
		memcpy(saved_data,
			(void *)((long)flash_addr_new + CONFIG_ENV_SIZE),
			up_data);
		debug("Data (start 0x%lX, len 0x%lX) saved at 0x%p\n",
			(long)flash_addr_new + CONFIG_ENV_SIZE,
			up_data, saved_data);
	}
#endif
	puts("Erasing Flash...");
	debug(" %08lX ... %08lX ...", (ulong)flash_addr_new, end_addr_new);

	if (flash_sect_erase((ulong)flash_addr_new, end_addr_new))
		goto done;

	puts("Writing to Flash... ");
	debug(" %08lX ... %08lX ...",
		(ulong)&(flash_addr_new->data),
		sizeof(env_ptr->data) + (ulong)&(flash_addr_new->data));
	rc = flash_write((char *)&env_new, (ulong)flash_addr_new,
			 sizeof(env_new));
	if (rc)
		goto perror;

	rc = flash_write(&flag, (ulong)&(flash_addr->flags),
			 sizeof(flash_addr->flags));
	if (rc)
		goto perror;

#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	if (up_data) { /* restore the rest of sector */
		debug("Restoring the rest of data to 0x%lX len 0x%lX\n",
			(long)flash_addr_new + CONFIG_ENV_SIZE, up_data);
		if (flash_write(saved_data,
				(long)flash_addr_new + CONFIG_ENV_SIZE,
				up_data))
			goto perror;
	}
#endif
	puts("done\n");

	{
		env_t *etmp = flash_addr;
		ulong ltmp = end_addr;

		flash_addr = flash_addr_new;
		flash_addr_new = etmp;

		end_addr = end_addr_new;
		end_addr_new = ltmp;
	}

	rc = 0;
	goto done;
perror:
	flash_perror(rc);
done:
	if (saved_data)
		free(saved_data);
	/* try to re-protect */
	flash_sect_protect(1, (ulong)flash_addr, end_addr);
	flash_sect_protect(1, (ulong)flash_addr_new, end_addr_new);

	return rc;
}
Beispiel #15
0
int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	flash_info_t *info;
	ulong bank, addr_first, addr_last;
	int n, sect_first, sect_last;
#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
	struct mtd_device *dev;
	struct part_info *part;
	u8 dev_type, dev_num, pnum;
#endif
	int rcode = 0;
	int jffs2erase = 0;

	if (argc < 2) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	// Special JFFS2 erase which will write a JFFS2 "clean" header after the erase
	if('j' == argv[0][0])
	{
		jffs2erase = 1;
	}
	
	if (strcmp(argv[1], "all") == 0) {
		for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
			printf ("Erase Flash Bank # %ld ", bank);
			info = &flash_info[bank-1];
			rcode = flash_erase (info, 0, info->sector_count-1);
			if(jffs2erase) jffs2_write_header(info, 0, info->sector_count-1);
		}
		return rcode;
	}

	if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
		if (n < 0) {
			puts ("Bad sector specification\n");
			return 1;
		}
		printf ("Erase Flash Sectors %d-%d in Bank # %d ",
			sect_first, sect_last, (info-flash_info)+1);
		rcode = flash_erase(info, sect_first, sect_last);
		if(jffs2erase) jffs2_write_header(info, sect_first, sect_last);
		return rcode;
	}

#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CONFIG_JFFS2_CMDLINE)
	/* erase <part-id> - erase partition */
	if ((argc == 2) && (id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
		mtdparts_init();
		if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) {
			if (dev->id->type == MTD_DEV_TYPE_NOR) {
				bank = dev->id->num;
				info = &flash_info[bank];
				addr_first = part->offset + info->start[0];
				addr_last = addr_first + part->size - 1;

				printf ("Erase Flash Parition %s, "
						"bank %d, 0x%08lx - 0x%08lx ",
						argv[1], bank, addr_first,
						addr_last);

				rcode = flash_sect_erase(addr_first, addr_last);
				return rcode;
			}

			printf("cannot erase, not a NOR device\n");
			return 1;
		}
	}
#endif

	if (argc != 3) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	if (strcmp(argv[1], "bank") == 0) {
		bank = simple_strtoul(argv[2], NULL, 16);
		if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
			printf ("Only FLASH Banks # 1 ... # %d supported\n",
				CFG_MAX_FLASH_BANKS);
			return 1;
		}
		printf ("Erase Flash Bank # %ld ", bank);
		info = &flash_info[bank-1];
		rcode = flash_erase (info, 0, info->sector_count-1);
		if(jffs2erase) jffs2_write_header(info, 0, info->sector_count-1);
		return rcode;
	}

	if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0){
		printf ("Bad address format\n");
		return 1;
	}

	if (addr_first >= addr_last) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	if (jffs2erase)
	{
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	rcode = flash_sect_erase(addr_first, addr_last);
	return rcode;
}
int do_bootloader_update_nor(uint32_t image_addr, int length,
			     uint32_t burn_addr, int failsafe)
{
#if defined(CONFIG_SYS_NO_FLASH)
	printf("ERROR: Bootloader not compiled with NOR flash support\n");
	return 1;
#else
	uint32_t failsafe_size, failsafe_top_remapped;
	uint32_t burn_addr_remapped, image_size, normal_top_remapped;
	flash_info_t *info;
	char tmp[16] __attribute__ ((unused));	/* to hold 32 bit numbers in hex */
	int sector = 0;
	bootloader_header_t *header;
	int rc;

	header = cvmx_phys_to_ptr(image_addr);

	DBGUPD("%s(0x%x, 0x%x, 0x%x, %s)\n", __func__, image_addr, length,
	       burn_addr, failsafe ? "failsafe" : "normal");
	DBGUPD("LOOKUP_STEP                0x%x\n", LOOKUP_STEP);
	DBGUPD("CFG_FLASH_BASE             0x%x\n", CONFIG_SYS_FLASH_BASE);

	/* File with rev 1.1 headers are not relocatable, so _must_ be burned
	 * at the address that they are linked at.
	 */
	if (header->maj_rev == 1 && header->min_rev == 1) {
		if (burn_addr && burn_addr != header->address) {
			printf("ERROR: specified address (0x%x) does not match "
			       "required burn address (0x%llx\n)\n",
			       burn_addr, header->address);
			return 1;
		}
		burn_addr = header->address;
	}

	/* If we have at least one bank of non-zero size, we have some NOR */
	if (!flash_info[0].size) {
		puts("ERROR: No NOR Flash detected on board, can't burn NOR "
		     "bootloader image\n");
		return 1;
	}

	/* check the burn address allignement */
	if ((burn_addr & (LOOKUP_STEP - 1)) != 0) {
		printf("Cannot programm normal image at 0x%x: address must be\n"
		       " 0x%x bytes alligned for normal boot lookup\n",
		       burn_addr, LOOKUP_STEP);
		return 1;
	}

	/* for failsage checks are easy */
	if ((failsafe) && (burn_addr != FAILSAFE_BASE)) {
		printf("ERROR: Failsafe image must be burned to address 0x%x\n",
		       FAILSAFE_BASE);
		return 1;
	}

	if (burn_addr && (burn_addr < FAILSAFE_BASE)) {
		printf("ERROR: burn address 0x%x out of boot range\n",
		       burn_addr);
		return 1;
	}

	if (!failsafe) {
#ifndef CONFIG_OCTEON_NO_FAILSAFE
		/* find out where failsafe ends */
		failsafe_size = get_image_size((bootloader_header_t *)
					       CONFIG_SYS_FLASH_BASE);
		if (failsafe_size == 0) {
			/* failsafe does not have header - assume fixed size
			 * old image
			 */
			puts("Failsafe has no valid header, assuming old image. "
			     "Using default failsafe size\n");
			failsafe_size =
			    CONFIG_SYS_NORMAL_BOOTLOADER_BASE - FAILSAFE_BASE;

			/* must default to CONFIG_SYS_NORMAL_BOOTLOADER_BASE */
			if (!burn_addr)
				burn_addr = CONFIG_SYS_NORMAL_BOOTLOADER_BASE;
			else if (CONFIG_SYS_NORMAL_BOOTLOADER_BASE != burn_addr) {
				printf("WARNING: old failsafe image will not be able to start\n"
				       "image at any address but 0x%x\n",
				       CONFIG_SYS_NORMAL_BOOTLOADER_BASE);
#ifdef ERR_ON_OLD_BASE
				return 1;
#endif
			}
		}		/* old failsafe */
#else
		failsafe_size = 0;
#endif		/* CONFIG_OCTEON_NO_FAILSAFE */

		DBGUPD("failsafe size is 0x%x\n", failsafe_size);
		DBGUPD("%s: burn address: 0x%x\n", __func__, burn_addr);
		/* Locate the next flash sector */
		failsafe_top_remapped = CONFIG_SYS_FLASH_BASE + failsafe_size;
		DBGUPD("failsafe_top_remapped 0x%x\n", failsafe_top_remapped);
		info = &flash_info[0];	/* no need to look into any other banks */
		/* scan flash bank sectors */
		for (sector = 0; sector < info->sector_count; ++sector) {
			DBGUPD("%d: 0x%lx\n", sector, info->start[sector]);
			if (failsafe_top_remapped <= info->start[sector])
				break;
		}

		if (sector == info->sector_count) {
			puts("Failsafe takes all the flash??  Can not burn normal image\n");
			return 1;
		}

		/* Move failsafe top up to the sector boundary */
		failsafe_top_remapped = info->start[sector];

		DBGUPD("Found next sector after failsafe is at remapped addr 0x%x\n",
		       failsafe_top_remapped);
		failsafe_size = failsafe_top_remapped - CONFIG_SYS_FLASH_BASE;
		DBGUPD("Alligned up failsafe size is 0x%x\n", failsafe_size);

		/* default to the first sector after the failsafe */
		if (!burn_addr) {
			burn_addr = FAILSAFE_BASE + failsafe_size;
			DBGUPD("Setting burn address to 0x%x, failsafe size: 0x%x\n",
			       burn_addr, failsafe_size);
		/* check for overlap */
		} else if (FAILSAFE_BASE + failsafe_size > burn_addr) {
			puts("ERROR: can not burn: image overlaps with failsafe\n");
			printf("burn address is 0x%x, in-flash failsafe top is 0x%x\n",
			       burn_addr, FAILSAFE_BASE + failsafe_size);
			return 1;
		}
		/* done with failsafe checks */
	}

	if (length)
		image_size = length;
	else
		image_size = get_image_size((bootloader_header_t *)image_addr);
	if (!image_size) {
		/* this is wierd case. Should never happen with good image */
		printf("ERROR: image has size field set to 0??\n");
		return 1;
	}

	/* finally check the burn address' CKSSEG limit */
	if ((burn_addr + image_size) >= (uint64_t) CKSSEG) {
		puts("ERROR: can not burn: image exceeds KSEG1 area\n");
		printf("burnadr is 0x%x, top is 0x%x\n", burn_addr,
		       burn_addr + image_size);
		return 1;
	}
	DBGUPD("burn_addr: 0x%x, image_size: 0x%x\n", burn_addr, image_size);
	/* Look up the last sector to use by the new image */
	burn_addr_remapped = burn_addr - FAILSAFE_BASE + CONFIG_SYS_FLASH_BASE;
	DBGUPD("burn_addr_remapped 0x%x\n", burn_addr_remapped);
	normal_top_remapped = burn_addr_remapped + image_size;
	/* continue flash scan - now for normal image top */
	if (failsafe)
		sector = 0;	/* is failsafe, we start from first sector here */
	for (; sector < info->sector_count; ++sector) {
		DBGUPD("%d: 0x%lx\n", sector, info->start[sector]);
		if (normal_top_remapped <= info->start[sector])
			break;
	}
	if (sector == info->sector_count) {
		puts("ERROR: not enough room in flash bank for the image??\n");
		return 1;
	}
	/* align up for environment variable set up */
	normal_top_remapped = info->start[sector];

	DBGUPD("normal_top_remapped 0x%x\n", normal_top_remapped);
	/* if there is no header (length != 0) - check burn address and
	 * give warning
	 */
	if (length && CONFIG_SYS_NORMAL_BOOTLOADER_BASE != burn_addr) {
#ifdef ERR_ON_OLD_BASE
		puts("ERROR: burning headerless image at other that defailt address\n"
		     "Image look up will not work.\n");
		printf("Default burn address: 0x%x requested burn address: 0x%x\n",
		       CONFIG_SYS_NORMAL_BOOTLOADER_BASE, burn_addr);
		return 1;
#else
		puts("WARNING: burning headerless image at other that defailt address\n"
		     "Image look up will not work.\n");
		printf("Default burn address: 0x%x requested burn address: 0x%x\n",
		       CONFIG_SYS_NORMAL_BOOTLOADER_BASE, burn_addr);
#endif
	}

	printf("Image at 0x%x is ready for burning\n", image_addr);
	printf("           Header version: %d.%d\n", header->maj_rev,
	       header->min_rev);
	printf("           Header size %d, data size %d\n", header->hlen,
	       header->dlen);
	printf("           Header crc 0x%x, data crc 0x%x\n", header->hcrc,
	       header->dcrc);
	printf("           Image link address is 0x%llx\n", header->address);
	printf("           Image burn address on flash is 0x%x\n", burn_addr);
	printf("           Image size on flash 0x%x\n",
	       normal_top_remapped - burn_addr_remapped);

	DBGUPD("burn_addr_remapped 0x%x normal_top_remapped 0x%x\n",
	       burn_addr_remapped, normal_top_remapped);
	if (flash_sect_protect(0, burn_addr_remapped, normal_top_remapped - 1)) {
		puts("Flash unprotect failed\n");
		return 1;
	}
	if (flash_sect_erase(burn_addr_remapped, normal_top_remapped - 1)) {
		puts("Flash erase failed\n");
		return 1;
	}

	puts("Copy to Flash... ");
	/* Note: Here we copy more than we should - whatever is after the image
	 * in memory gets copied to flash.
	 */
	rc = flash_write((char *)image_addr, burn_addr_remapped,
			 normal_top_remapped - burn_addr_remapped);
	if (rc != 0) {
		flash_perror(rc);
		return 1;
	}
	puts("done\n");

#ifndef CONFIG_ENV_IS_IN_NAND
	/* Erase the environment so that older bootloader will use its default
	 * environment.  This will ensure that the default
	 * 'bootloader_flash_update' macro is there.  HOWEVER, this is only
	 * useful if a legacy sized failsafe u-boot image is present.
	 * If a new larger failsafe is present, then that macro will be incorrect
	 * and will erase part of the failsafe.
	 * The 1.9.0 u-boot needs to have its link address and
	 * normal_bootloader_size/base modified to work with this...
	 */
	if (header->maj_rev == 1 && header->min_rev == 1) {
		puts("Erasing environment due to u-boot downgrade.\n");
		flash_sect_protect(0, CONFIG_ENV_ADDR,
				   CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1);
		if (flash_sect_erase
		    (CONFIG_ENV_ADDR, CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1)) {
			puts("Environment erase failed\n");
			return 1;
		}

	}
#endif
	return 0;
#endif
}
Beispiel #17
0
int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
#ifndef CONFIG_SYS_NO_FLASH
	flash_info_t *info;
	ulong bank, addr_first, addr_last;
	int n, sect_first, sect_last;
#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
	struct mtd_device *dev;
	struct part_info *part;
	u8 dev_type, dev_num, pnum;
#endif
	int rcode = 0;

	if (argc < 2) {
		cmd_usage(cmdtp);
		return 1;
	}

	if (strcmp(argv[1], "all") == 0) {
		for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
			printf ("Erase Flash Bank # %ld ", bank);
			info = &flash_info[bank-1];
			rcode = flash_erase (info, 0, info->sector_count-1);
		}
		return rcode;
	}

	if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
		if (n < 0) {
			puts ("Bad sector specification\n");
			return 1;
		}
		printf ("Erase Flash Sectors %d-%d in Bank # %zu ",
			sect_first, sect_last, (info-flash_info)+1);
		rcode = flash_erase(info, sect_first, sect_last);
		return rcode;
	}

#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
	/* erase <part-id> - erase partition */
	if ((argc == 2) && (mtd_id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
		mtdparts_init();
		if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) {
			if (dev->id->type == MTD_DEV_TYPE_NOR) {
				bank = dev->id->num;
				info = &flash_info[bank];
				addr_first = part->offset + info->start[0];
				addr_last = addr_first + part->size - 1;

				printf ("Erase Flash Partition %s, "
						"bank %ld, 0x%08lx - 0x%08lx ",
						argv[1], bank, addr_first,
						addr_last);

				rcode = flash_sect_erase(addr_first, addr_last);
				return rcode;
			}

			printf("cannot erase, not a NOR device\n");
			return 1;
		}
	}
#endif

	if (argc != 3) {
		cmd_usage(cmdtp);
		return 1;
	}

	if (strcmp(argv[1], "bank") == 0) {
		bank = simple_strtoul(argv[2], NULL, 16);
		if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) {
			printf ("Only FLASH Banks # 1 ... # %d supported\n",
				CONFIG_SYS_MAX_FLASH_BANKS);
			return 1;
		}
		printf ("Erase Flash Bank # %ld ", bank);
		info = &flash_info[bank-1];
		rcode = flash_erase (info, 0, info->sector_count-1);
		return rcode;
	}

	if (addr_spec(argv[1], argv[2], &addr_first, &addr_last) < 0){
		printf ("Bad address format\n");
		return 1;
	}

	if (addr_first >= addr_last) {
		cmd_usage(cmdtp);
		return 1;
	}

	rcode = flash_sect_erase(addr_first, addr_last);
	return rcode;
#else
	return 0;
#endif /* CONFIG_SYS_NO_FLASH */
}
Beispiel #18
0
/** Console command to display and set the software reconfigure byte
  * <pre>
  * swconfig        - display the current value of the software reconfigure byte
  * swconfig [#]    - change the software reconfigure byte to #
  * </pre>
  * @param  *cmdtp  [IN] as passed by run_command (ignored)
  * @param  flag    [IN] as passed by run_command (ignored)
  * @param  argc    [IN] as passed by run_command if 1, display, if 2 change
  * @param  *argv[] [IN] contains the parameters to use
  * @return
  * <pre>
  *      0 if passed
  *     -1 if failed
  * </pre>
  */
int do_swconfigbyte (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	unsigned char *sector_buffer = NULL;
	unsigned char input_char;
	int write_result;
	unsigned int input_uint;

	/* display value if no argument */
	if (argc < 2) {
		printf ("Software configuration byte is currently: 0x%02x\n",
			*((unsigned char *) (SW_BYTE_SECTOR_ADDR +
					     SW_BYTE_SECTOR_OFFSET)));
		return 0;
	} else if (argc > 3) {
		printf ("Too many arguments\n");
		return -1;
	}

	/* if 3 arguments, 3rd argument is the address to use */
	if (argc == 3) {
		input_uint = simple_strtoul (argv[1], NULL, 16);
		sector_buffer = (unsigned char *) input_uint;
	} else {
		sector_buffer = (unsigned char *) DEFAULT_TEMP_ADDR;
	}

	input_char = simple_strtoul (argv[1], NULL, 0);
	if ((input_char & ~SW_BYTE_MASK) != 0) {
		printf ("Input of 0x%02x will be masked to 0x%02x\n",
			input_char, (input_char & SW_BYTE_MASK));
		input_char = input_char & SW_BYTE_MASK;
	}

	memcpy (sector_buffer, (void *) SW_BYTE_SECTOR_ADDR,
		SW_BYTE_SECTOR_SIZE);
	sector_buffer[SW_BYTE_SECTOR_OFFSET] = input_char;


	printf ("Erasing Flash...");
	if (flash_sect_erase
	    (SW_BYTE_SECTOR_ADDR,
	     (SW_BYTE_SECTOR_ADDR + SW_BYTE_SECTOR_OFFSET))) {
		return -1;
	}

	printf ("Writing to Flash... ");
	write_result =
		flash_write ((char *)sector_buffer, SW_BYTE_SECTOR_ADDR,
			     SW_BYTE_SECTOR_SIZE);
	if (write_result != 0) {
		flash_perror (write_result);
		return -1;
	} else {
		printf ("done\n");
		printf ("Software configuration byte is now: 0x%02x\n",
			*((unsigned char *) (SW_BYTE_SECTOR_ADDR +
					     SW_BYTE_SECTOR_OFFSET)));
	}

	return 0;
}
Beispiel #19
0
int saveenv(void)
{
	char *saved_data = NULL;
	int rc = 1;
	char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	ulong up_data = 0;
#endif

	debug ("Protect off %08lX ... %08lX\n",
		(ulong)flash_addr, end_addr);

	if (flash_sect_protect (0, (ulong)flash_addr, end_addr)) {
		goto Done;
	}

	debug ("Protect off %08lX ... %08lX\n",
		(ulong)flash_addr_new, end_addr_new);

	if (flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new)) {
		goto Done;
	}

#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	up_data = (end_addr_new + 1 - ((long)flash_addr_new + CONFIG_ENV_SIZE));
	debug ("Data to save 0x%x\n", up_data);
	if (up_data) {
		if ((saved_data = malloc(up_data)) == NULL) {
			printf("Unable to save the rest of sector (%ld)\n",
				up_data);
			goto Done;
		}
		memcpy(saved_data,
			(void *)((long)flash_addr_new + CONFIG_ENV_SIZE), up_data);
		debug ("Data (start 0x%x, len 0x%x) saved at 0x%x\n",
			   (long)flash_addr_new + CONFIG_ENV_SIZE,
				up_data, saved_data);
	}
#endif
	puts ("Erasing Flash...");
	debug (" %08lX ... %08lX ...",
		(ulong)flash_addr_new, end_addr_new);

	if (flash_sect_erase ((ulong)flash_addr_new, end_addr_new)) {
		goto Done;
	}

	puts ("Writing to Flash... ");
	debug (" %08lX ... %08lX ...",
		(ulong)&(flash_addr_new->data),
		sizeof(env_ptr->data)+(ulong)&(flash_addr_new->data));
	if ((rc = flash_write((char *)env_ptr->data,
			(ulong)&(flash_addr_new->data),
			sizeof(env_ptr->data))) ||
	    (rc = flash_write((char *)&(env_ptr->crc),
			(ulong)&(flash_addr_new->crc),
			sizeof(env_ptr->crc))) ||
	    (rc = flash_write(&flag,
			(ulong)&(flash_addr->flags),
			sizeof(flash_addr->flags))) ||
	    (rc = flash_write(&new_flag,
			(ulong)&(flash_addr_new->flags),
			sizeof(flash_addr_new->flags))))
	{
		flash_perror (rc);
		goto Done;
	}
	puts ("done\n");

#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	if (up_data) { /* restore the rest of sector */
		debug ("Restoring the rest of data to 0x%x len 0x%x\n",
			   (long)flash_addr_new + CONFIG_ENV_SIZE, up_data);
		if (flash_write(saved_data,
				(long)flash_addr_new + CONFIG_ENV_SIZE,
				up_data)) {
			flash_perror(rc);
			goto Done;
		}
	}
#endif
	{
		env_t * etmp = flash_addr;
		ulong ltmp = end_addr;

		flash_addr = flash_addr_new;
		flash_addr_new = etmp;

		end_addr = end_addr_new;
		end_addr_new = ltmp;
	}

	rc = 0;
Done:

	if (saved_data)
		free (saved_data);
	/* try to re-protect */
	(void) flash_sect_protect (1, (ulong)flash_addr, end_addr);
	(void) flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new);

	return rc;
}
Beispiel #20
0
void do_saveenv  (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
	int rc;
	extern void flash_sect_protect (int p, ulong addr_first, ulong addr_last);
	extern void flash_sect_erase (ulong addr_first, ulong addr_last);
#if defined(CFG_FLASH_ENV_BUF)
	uchar *sector_buffer;
#endif	/* CFG_FLASH_ENV_BUF */

#if defined(CFG_FLASH_ENV_ADDR)
	 uchar *environment = env_init();
#endif	/* CFG_FLASH_ENV_BUF */

#ifdef CONFIG_4xx
	uchar *ed_buf;

	/*
	 * On ppc4xx still saved somewhere within a flash sector (no sector
	 * reserved for the environment variables). This will be changed in a
	 * future release.
	 */
        ulong sector_flash_addr;
        ulong sector_flash_size;
        ulong sector_flash_offs;
        int i;
        flash_info_t *info;

# ifndef CFG_FLASH_ENV_ADDR
	env_init();
# endif

        /*
         * Calculate environment variables sector address and size
         */
        info = addr2info((ulong)flash_addr);
        for (i=0; i<info->sector_count; i++)
          {
            if (info->start[i] >= (ulong)flash_addr)
              break;
          }
        sector_flash_addr = info->start[i-1];
        sector_flash_size = info->start[i] - info->start[i-1];
        sector_flash_offs = (ulong)flash_addr - info->start[i-1];

	/*
	 * Allocate temp buffer to edit environment
	 */
	if ((ed_buf = malloc(sector_flash_size)) == NULL) {
		printf ("## malloc(%lu) failed\n", sector_flash_size);
		return;
	}

        /*
         * Copy sector down to ram
         */
	memcpy(ed_buf, (uchar *)sector_flash_addr, sector_flash_size);

        /*
         * Copy new environment variables to ram image of flash sector
         */
	memcpy(ed_buf+sector_flash_offs, (uchar *)environment, env_size);

	flash_sect_protect (0, sector_flash_addr, sector_flash_addr+sector_flash_size-1);

	printf ("Erasing Flash...");
	flash_sect_erase (sector_flash_addr, sector_flash_addr+sector_flash_size-1);

	printf ("Saving Environment to Flash...\n");
	switch (rc = flash_write (ed_buf, sector_flash_addr, sector_flash_size)) {
	case 0: break;
	case 1: printf ("Timeout writing to Flash\n");
		break;
	case 2: printf ("Flash not Erased\n");
		break;
	case 4: printf ("Can't write to protected Flash sectors\n");
		break;
	default:
		printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
	}

	free (ed_buf);

	flash_sect_protect (1, sector_flash_addr, sector_flash_addr+sector_flash_size-1);
#else	/* ! CONFIG_4xx */

# ifndef CFG_FLASH_ENV_ADDR
	env_init();
# endif

# if defined(CFG_FLASH_ENV_BUF)
	/* this buffer area was reserved in board_init_f() */
	sector_buffer = (uchar *)((ulong)bd - CFG_FLASH_ENV_BUF);
	/* copy the environment into the sector buffer */
	memcpy(sector_buffer, environment, env_size);
	/* override the old names */
# define environment sector_buffer
# define env_size CFG_FLASH_ENV_BUF
# endif	/* CFG_FLASH_ENV_BUF */

	flash_sect_protect (0, (ulong)flash_addr, (ulong)flash_addr+env_size-1);

	printf ("Erasing Flash...");
	flash_sect_erase ((ulong)flash_addr, (ulong)flash_addr+env_size-1);

	printf ("Saving Environment to Flash...\n");
	switch (rc = flash_write (environment, (ulong)flash_addr, env_size)) {
	case 0: break;
	case 1: printf ("Timeout writing to Flash\n");
		break;
	case 2: printf ("Flash not Erased\n");
		break;
	case 4: printf ("Can't write to protected Flash sectors\n");
		break;
	case 8: printf ("Outside available Flash\n");
		return;
	default:
		printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
	}

	flash_sect_protect (1, (ulong)flash_addr, (ulong)flash_addr+env_size-1);

# if defined(CFG_FLASH_ENV_BUF)
# undef environment
# undef env_size
# endif	/* CFG_FLASH_ENV_BUF */

#endif	/* CONFIG_4xx */
}
Beispiel #21
0
int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	flash_info_t *info;
	ulong bank, addr_first, addr_last;
	int n, sect_first, sect_last;
	int rcode = 0;

	if (argc < 2) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	if (strcmp(argv[1], "linux") == 0) 
	{
		printf("\n Erase linux kernel block !!\n");
		printf("From 0x%X To 0x%X\n", CFG_KERN_ADDR, CFG_KERN_ADDR + flash_info[0].size
				- (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE) -1);
		rcode = flash_sect_erase(CFG_KERN_ADDR, CFG_KERN_ADDR + flash_info[0].size
				-(CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE) -1);
	
		return rcode;
	}
	else if (strcmp(argv[1], "uboot") == 0) 
	{
		printf("\n Erase u-boot block !!\n");
		printf("From 0x%X To 0x%X\n", CFG_FLASH_BASE, CFG_FLASH_BASE + CFG_BOOTLOADER_SIZE - 1);
		rcode = flash_sect_erase(CFG_FLASH_BASE, CFG_FLASH_BASE + CFG_BOOTLOADER_SIZE - 1);
	
		return rcode;
	}
	else if (strcmp(argv[1], "all") == 0) {
		for (bank=1; bank<=CFG_MAX_FLASH_BANKS; ++bank) {
			printf ("Erase Flash Bank # %ld ,info->sector_count = %d", bank,info->sector_count-1);
			info = &flash_info[bank-1];
			rcode = erase_all_chip (info, 0, info->sector_count-1);
		}
		return rcode;
	}

	if ((n = abbrev_spec(argv[1], &info, &sect_first, &sect_last)) != 0) {
		if (n < 0) {
			puts ("Bad sector specification\n");
			return 1;
		}
		printf ("Erase Flash Sectors %d-%d in Bank # %d ",
			sect_first, sect_last, (info-flash_info)+1);
		rcode = flash_erase(info, sect_first, sect_last);
		return rcode;
	}

	if (argc != 3) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	if (strcmp(argv[1], "bank") == 0) {
		bank = simple_strtoul(argv[2], NULL, 16);
		if ((bank < 1) || (bank > CFG_MAX_FLASH_BANKS)) {
			printf ("Only FLASH Banks # 1 ... # %d supported\n",
				CFG_MAX_FLASH_BANKS);
			return 1;
		}
		printf ("Erase Flash Bank # %ld ", bank);
		info = &flash_info[bank-1];
		rcode = flash_erase (info, 0, info->sector_count-1);
		return rcode;
	}

	addr_first = simple_strtoul(argv[1], NULL, 16);
	addr_last  = simple_strtoul(argv[2], NULL, 16);

	if (addr_first >= addr_last) {
		printf ("Usage:\n%s\n", cmdtp->usage);
		return 1;
	}

	rcode = flash_sect_erase(addr_first, addr_last);
	return rcode;
}
int
au_do_update(int idx, long sz)
{
	image_header_t *hdr;
	char *addr;
	long start, end;
	int off, rc;
	uint nbytes;

	hdr = (image_header_t *)LOAD_ADDR;
#if defined(CONFIG_FIT)
	if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {
		puts ("Non legacy image format not supported\n");
		return -1;
	}
#endif

	/* disable the power switch */
	*CPLD_VFD_BK |= POWER_OFF;

	/* execute a script */
	if (image_check_type (hdr, IH_TYPE_SCRIPT)) {
		addr = (char *)((char *)hdr + image_get_header_size ());
		/* stick a NULL at the end of the script, otherwise */
		/* parse_string_outer() runs off the end. */
		addr[image_get_data_size (hdr)] = 0;
		addr += 8;
		parse_string_outer(addr, FLAG_PARSE_SEMICOLON);
		return 0;
	}

	start = aufl_layout[FIDX_TO_LIDX(idx)].start;
	end = aufl_layout[FIDX_TO_LIDX(idx)].end;

	/* unprotect the address range */
	/* this assumes that ONLY the firmware is protected! */
	if (idx == IDX_FIRMWARE) {
#undef AU_UPDATE_TEST
#ifdef AU_UPDATE_TEST
		/* erase it where Linux goes */
		start = aufl_layout[1].start;
		end = aufl_layout[1].end;
#endif
		flash_sect_protect(0, start, end);
	}

	/*
	 * erase the address range.
	 */
	debug ("flash_sect_erase(%lx, %lx);\n", start, end);
	flash_sect_erase(start, end);
	wait_ms(100);
	/* strip the header - except for the kernel and ramdisk */
	if (image_check_type (hdr, IH_TYPE_KERNEL) ||
			image_check_type (hdr, IH_TYPE_RAMDISK)) {
		addr = (char *)hdr;
		off = image_get_header_size ();
		nbytes = image_get_image_size (hdr);
	} else {
		addr = (char *)((char *)hdr + image_get_header_size ());
#ifdef AU_UPDATE_TEST
		/* copy it to where Linux goes */
		if (idx == IDX_FIRMWARE)
			start = aufl_layout[1].start;
#endif
		off = 0;
		nbytes = image_get_data_size (hdr);
	}

	/* copy the data from RAM to FLASH */
	debug ("flash_write(%p, %lx %x)\n", addr, start, nbytes);
	rc = flash_write(addr, start, nbytes);
	if (rc != 0) {
		printf("Flashing failed due to error %d\n", rc);
		return -1;
	}

	/* check the dcrc of the copy */
	if (crc32 (0, (uchar *)(start + off), image_get_data_size (hdr)) !=
	    image_get_dcrc (hdr)) {
		printf ("Image %s Bad Data Checksum After COPY\n", aufile[idx]);
		return -1;
	}

	/* protect the address range */
	/* this assumes that ONLY the firmware is protected! */
	if (idx == IDX_FIRMWARE)
		flash_sect_protect(1, start, end);
	return 0;
}
Beispiel #23
0
/*******************************************************************************
Reset environment variables.
********************************************************************************/
int resetenv_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
#if defined(CONFIG_ENV_IS_IN_FLASH )
        ulong stop_addr;
	ulong start_addr;

#endif

#if defined(CONFIG_ENV_IS_IN_NAND)
	size_t offset = 0;
	nand_info_t *nand = &nand_info[0];
	int sum = 0;

#if defined(CONFIG_SKIP_BAD_BLOCK)
	int i = 0;
	size_t blocksize;
	blocksize = nand_info[0].erasesize;
	while(i * blocksize < nand_info[0].size) {
		if (!nand_block_isbad(&nand_info[0], (i * blocksize)))
			sum += blocksize;
		else {
			sum = 0;
			offset = (i + 1) * blocksize;
		}
		if (sum >= CONFIG_UBOOT_SIZE)
			break;
		i++;
	}
#else
	offset = CONFIG_ENV_OFFSET;
#endif
	printf("Erasing 0x%x - 0x%x:",CONFIG_UBOOT_SIZE + offset, CONFIG_ENV_RANGE_NAND);
	nand_erase(nand, CONFIG_UBOOT_SIZE + offset, CONFIG_ENV_RANGE_NAND);
	puts ("[Done]\n");
#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH)
	u32 sector = 1;

	if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
		sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
		if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
			sector++;
	}


#ifdef CONFIG_SPI_FLASH_PROTECTION
	printf("Unprotecting flash:");
	spi_flash_protect(flash, 0);
	printf("\t\t[Done]\n");
#endif

	printf("Erasing 0x%x - 0x%x:",CONFIG_ENV_OFFSET, CONFIG_ENV_OFFSET + sector * CONFIG_ENV_SECT_SIZE);
	if(!flash) {
		flash = spi_flash_probe(0, 0, CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
		if (!flash) {
			printf("Failed to probe SPI Flash\n");
			set_default_env("!spi_flash_probe() failed");
			return 0;
		}
	}
	if (spi_flash_erase(flash, CONFIG_ENV_OFFSET, sector * CONFIG_ENV_SECT_SIZE))
		return 1;
	puts("\t[Done]\n");

#ifdef CONFIG_SPI_FLASH_PROTECTION
	printf("Protecting flash:");
	spi_flash_protect(flash, 1);
	printf("\t\t[Done]\n");
#endif


#elif defined(CONFIG_ENV_IS_IN_FLASH )
	start_addr = CONFIG_ENV_ADDR;
	stop_addr = start_addr + CONFIG_ENV_SIZE - 1;

	printf("Erasing sector 0x%x:",CONFIG_ENV_OFFSET);
	flash_sect_protect (0, start_addr, stop_addr);

	flash_sect_erase (start_addr, stop_addr);

	flash_sect_protect (1, start_addr, stop_addr);
	printf("\t[Done]\n");

#endif
	printf("Warning: Default Environment Variables will take effect Only after RESET\n");
	return 0;
}
Beispiel #24
0
int saveenv(void)
{
	int	len, rc;
	ulong	end_addr;
	ulong	flash_sect_addr;
#if defined(CONFIG_ENV_SECT_SIZE) && (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE)
	ulong	flash_offset;
	uchar	env_buffer[CONFIG_ENV_SECT_SIZE];
#else
	uchar *env_buffer = (uchar *)env_ptr;
#endif	/* CONFIG_ENV_SECT_SIZE */
	int rcode = 0;

#if defined(CONFIG_ENV_SECT_SIZE) && (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE)

	flash_offset    = ((ulong)flash_addr) & (CONFIG_ENV_SECT_SIZE-1);
	flash_sect_addr = ((ulong)flash_addr) & ~(CONFIG_ENV_SECT_SIZE-1);

	debug ( "copy old content: "
		"sect_addr: %08lX  env_addr: %08lX  offset: %08lX\n",
		flash_sect_addr, (ulong)flash_addr, flash_offset);

	/* copy old contents to temporary buffer */
	memcpy (env_buffer, (void *)flash_sect_addr, CONFIG_ENV_SECT_SIZE);

	/* copy current environment to temporary buffer */
	memcpy ((uchar *)((unsigned long)env_buffer + flash_offset),
		env_ptr,
		CONFIG_ENV_SIZE);

	len	 = CONFIG_ENV_SECT_SIZE;
#else
	flash_sect_addr = (ulong)flash_addr;
	len	 = CONFIG_ENV_SIZE;
#endif	/* CONFIG_ENV_SECT_SIZE */

#ifndef CONFIG_INFERNO
	end_addr = flash_sect_addr + len - 1;
#else
	/* this is the last sector, and the size is hardcoded here */
	/* otherwise we will get stack problems on loading 128 KB environment */
	end_addr = flash_sect_addr + CONFIG_INFERNO - 1;
#endif

	debug ("Protect off %08lX ... %08lX\n",
		(ulong)flash_sect_addr, end_addr);

	if (flash_sect_protect (0, flash_sect_addr, end_addr))
		return 1;

	puts ("Erasing Flash...");
	if (flash_sect_erase (flash_sect_addr, end_addr))
		return 1;

	puts ("Writing to Flash... ");
	rc = flash_write((char *)env_buffer, flash_sect_addr, len);
	if (rc != 0) {
		flash_perror (rc);
		rcode = 1;
	} else {
		puts ("done\n");
	}

	/* try to re-protect */
	(void) flash_sect_protect (1, flash_sect_addr, end_addr);
	return rcode;
}
/*******************************************************************************
Reset environment variables.
********************************************************************************/
int resetenv_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
#if defined(CONFIG_ENV_IS_IN_FLASH )
	ulong	stop_addr;
	ulong	start_addr;
#elif defined(CONFIG_ENV_IS_IN_MMC)
	lbaint_t	start_lba;
	lbaint_t	blk_count;
	ulong		blk_erased;
	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
	struct mmc	*mmc;
	int			err;
#endif

#if defined(CONFIG_ENV_IS_IN_NAND)
	size_t env_offset = CONFIG_ENV_OFFSET;
	nand_info_t *nand = &nand_info[0];

	printf("Erasing 0x%x - 0x%x:",env_offset, env_offset + CONFIG_ENV_RANGE);
	nand_erase(nand, env_offset, CONFIG_ENV_RANGE);
	puts ("[Done]\n");

#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH)
	u32 sector = 1;

	if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
		sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
		if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
			sector++;
	}

#ifdef CONFIG_SPI_FLASH_PROTECTION
	printf("Unprotecting flash:");
	spi_flash_protect(flash, 0);
	printf("\t\t[Done]\n");
#endif

	printf("Erasing 0x%x - 0x%x:",CONFIG_ENV_OFFSET, CONFIG_ENV_OFFSET + sector * CONFIG_ENV_SECT_SIZE);
	if(!flash) {
		flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
								CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
		if (!flash) {
			printf("Failed to probe SPI Flash\n");
			set_default_env("!spi_flash_probe() failed");
			return 0;
		}
	}
	if (spi_flash_erase(flash, CONFIG_ENV_OFFSET, sector * CONFIG_ENV_SECT_SIZE))
		return 1;
	puts("\t[Done]\n");

#ifdef CONFIG_SPI_FLASH_PROTECTION
	printf("Protecting flash:");
	spi_flash_protect(flash, 1);
	printf("\t\t[Done]\n");
#endif

#elif defined(CONFIG_ENV_IS_IN_FLASH )
	start_addr = CONFIG_ENV_ADDR;
	stop_addr = start_addr + CONFIG_ENV_SIZE - 1;

	printf("Erasing sector 0x%x:",CONFIG_ENV_OFFSET);
	flash_sect_protect (0, start_addr, stop_addr);

	flash_sect_erase (start_addr, stop_addr);

	flash_sect_protect (1, start_addr, stop_addr);
	printf("\t[Done]\n");

#elif defined(CONFIG_ENV_IS_IN_MMC)

	start_lba = CONFIG_ENV_ADDR / CONFIG_ENV_SECT_SIZE;
	blk_count = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;

	mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
	if (!mmc) {
		printf("No MMC card found\n");
		return 1;
	}

	if (mmc_init(mmc)) {
		printf("MMC(%d) init failed\n", CONFIG_SYS_MMC_ENV_DEV);
		return 1;
	}

#ifdef CONFIG_SYS_MMC_ENV_PART /* Valid for MMC/eMMC only - switch to ENV partition */
	if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) {
		if (mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV, CONFIG_SYS_MMC_ENV_PART)) {
			printf("MMC partition switch failed\n");
			return 1;
		}
	}
#endif

	printf("Erasing 0x"LBAF" blocks starting at sector 0x"LBAF" :", blk_count, start_lba);
	/* For some unknown reason the mmc_berase() fails with timeout if called
	   before any futher write to MMC/SD (for instance, right after u-boot bring up).
	   However the mmc_bwrite() always succeds.
	   Writing zeroes into SD/MMC blocks is similar operation as doing so to IDE/SATA
	   disk and therefore can be used for erasing the imformation stored on the media.
	   blk_erased = mmc_berase(CONFIG_SYS_MMC_ENV_DEV, start_lba, blk_count);
	*/
	memset(buf, 0, CONFIG_ENV_SIZE);
	blk_erased = mmc_bwrite(CONFIG_SYS_MMC_ENV_DEV, start_lba, blk_count, buf);
	if (blk_erased != blk_count) {
		printf("\t[FAIL] - erased %#lx blocks\n", blk_erased);
		err = 1;
	} else {
		printf("\t[Done]\n");
		err = 0;
	}

#ifdef CONFIG_SYS_MMC_ENV_PART /* Valid for MMC/eMMC only - restore current partition */
	if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num)
		mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV, mmc->part_num);
#endif

	if (err)
		return err;

#endif
	printf("Warning: Default Environment Variables will take effect Only after RESET\n");
	return 0;
}
Beispiel #26
0
int saveenv(void)
{
	env_t	env_new;
	ssize_t	len;
	char	*saved_data = NULL;
	char	*res;
	int	rc = 1;
	char	flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	ulong	up_data = 0;
#endif

	debug("Protect off %08lX ... %08lX\n",
		(ulong)flash_addr, end_addr);

	if (flash_sect_protect(0, (ulong)flash_addr, end_addr)) {
		goto done;
	}

	debug("Protect off %08lX ... %08lX\n",
		(ulong)flash_addr_new, end_addr_new);

	if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new)) {
		goto done;
	}

	res = (char *)&env_new.data;
	len = hexport_r(&env_htab, '\0', &res, ENV_SIZE);
	if (len < 0) {
		error("Cannot export environment: errno = %d\n", errno);
		goto done;
	}
	env_new.crc   = crc32(0, env_new.data, ENV_SIZE);
	env_new.flags = new_flag;

#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	up_data = (end_addr_new + 1 - ((long)flash_addr_new + CONFIG_ENV_SIZE));
	debug("Data to save 0x%lX\n", up_data);
	if (up_data) {
		if ((saved_data = malloc(up_data)) == NULL) {
			printf("Unable to save the rest of sector (%ld)\n",
				up_data);
			goto done;
		}
		memcpy(saved_data,
			(void *)((long)flash_addr_new + CONFIG_ENV_SIZE), up_data);
		debug("Data (start 0x%lX, len 0x%lX) saved at 0x%p\n",
			(long)flash_addr_new + CONFIG_ENV_SIZE,
			up_data, saved_data);
	}
#endif
	puts("Erasing Flash...");
	debug(" %08lX ... %08lX ...",
		(ulong)flash_addr_new, end_addr_new);

	if (flash_sect_erase((ulong)flash_addr_new, end_addr_new)) {
		goto done;
	}

	puts("Writing to Flash... ");
	debug(" %08lX ... %08lX ...",
		(ulong)&(flash_addr_new->data),
		sizeof(env_ptr->data)+(ulong)&(flash_addr_new->data));
	if ((rc = flash_write((char *)&env_new,
			(ulong)flash_addr_new,
			sizeof(env_new))) ||
	    (rc = flash_write(&flag,
			(ulong)&(flash_addr->flags),
			sizeof(flash_addr->flags))) ) {
		flash_perror(rc);
		goto done;
	}

#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	if (up_data) { /* restore the rest of sector */
		debug("Restoring the rest of data to 0x%lX len 0x%lX\n",
			(long)flash_addr_new + CONFIG_ENV_SIZE, up_data);
		if (flash_write(saved_data,
				(long)flash_addr_new + CONFIG_ENV_SIZE,
				up_data)) {
			flash_perror(rc);
			goto done;
		}
	}
#endif
	puts("done\n");

	{
		env_t * etmp = flash_addr;
		ulong ltmp = end_addr;

		flash_addr = flash_addr_new;
		flash_addr_new = etmp;

		end_addr = end_addr_new;
		end_addr_new = ltmp;
	}

	rc = 0;
done:
	if (saved_data)
		free(saved_data);
	/* try to re-protect */
	(void) flash_sect_protect(1, (ulong)flash_addr, end_addr);
	(void) flash_sect_protect(1, (ulong)flash_addr_new, end_addr_new);

	return rc;
}
Beispiel #27
0
int saveenv(void)
{
	env_t	env_new;
	ssize_t	len;
	int	rc = 1;
	char	*res;
	char	*saved_data = NULL;
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	ulong	up_data = 0;

	up_data = (end_addr + 1 - ((long)flash_addr + CONFIG_ENV_SIZE));
	debug("Data to save 0x%lx\n", up_data);
	if (up_data) {
		if ((saved_data = malloc(up_data)) == NULL) {
			printf("Unable to save the rest of sector (%ld)\n",
				up_data);
			goto done;
		}
		memcpy(saved_data,
			(void *)((long)flash_addr + CONFIG_ENV_SIZE), up_data);
		debug("Data (start 0x%lx, len 0x%lx) saved at 0x%lx\n",
			(ulong)flash_addr + CONFIG_ENV_SIZE,
			up_data,
			(ulong)saved_data);
	}
#endif	/* CONFIG_ENV_SECT_SIZE */

	debug("Protect off %08lX ... %08lX\n",
		(ulong)flash_addr, end_addr);

	if (flash_sect_protect(0, (long)flash_addr, end_addr))
		goto done;

	res = (char *)&env_new.data;
	len = hexport_r(&env_htab, '\0', &res, ENV_SIZE);
	if (len < 0) {
		error("Cannot export environment: errno = %d\n", errno);
		goto done;
	}
	env_new.crc = crc32(0, env_new.data, ENV_SIZE);

	puts("Erasing Flash...");
	if (flash_sect_erase((long)flash_addr, end_addr))
		goto done;

	puts("Writing to Flash... ");
	rc = flash_write((char *)&env_new, (long)flash_addr, CONFIG_ENV_SIZE);
	if (rc != 0) {
		flash_perror(rc);
		goto done;
	}
#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
	if (up_data) {	/* restore the rest of sector */
		debug("Restoring the rest of data to 0x%lx len 0x%lx\n",
			(ulong)flash_addr + CONFIG_ENV_SIZE, up_data);
		if (flash_write(saved_data,
				(long)flash_addr + CONFIG_ENV_SIZE,
				up_data)) {
			flash_perror(rc);
			goto done;
		}
	}
#endif
	puts("done\n");
	rc = 0;
done:
	if (saved_data)
		free(saved_data);
	/* try to re-protect */
	(void) flash_sect_protect(1, (long)flash_addr, end_addr);
	return rc;
}