Esempio n. 1
0
int saveenv(void)
{
	env_t	env_new;
	ssize_t	len;
	char	*res;
	int	ret = 0;
	nand_erase_options_t nand_erase_options;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;

	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);
		return 1;
	}
	env_new.crc   = crc32(0, env_new.data, ENV_SIZE);
	env_new.flags = ++env_flags; /* increase the serial */

	if(gd->env_valid == 1) {
		puts("Erasing redundant NAND...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts("Writing to redundant NAND... ");
		ret = writeenv(CONFIG_ENV_OFFSET_REDUND,
			(u_char *)&env_new);
	} else {
		puts("Erasing NAND...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts("Writing to NAND... ");
		ret = writeenv(CONFIG_ENV_OFFSET,
			(u_char *)&env_new);
	}
	if (ret) {
		puts("FAILED!\n");
		return 1;
	}

	puts("done\n");

	gd->env_valid = (gd->env_valid == 2 ? 1 : 2);

	return ret;
}
Esempio n. 2
0
int saveenv(void)
{
	struct mtd_info * mtd=get_mtd_device_nm(NAND_NORMAL_NAME);
	if (IS_ERR(mtd))
		return 1;
	struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
	size_t total;
	size_t offset = CONFIG_ENV_OFFSET;
	int ret = 0;
	nand_erase_options_t nand_erase_options;

	offset = (1024 * aml_chip->page_size * (mtd->writesize / (aml_chip->plane_num * aml_chip->page_size)));
	if (CONFIG_ENV_OFFSET < offset)
		_debug ("env define offset must larger than 1024 page size: %d \n", mtd->writesize);
	else
		offset = CONFIG_ENV_OFFSET;

	env_ptr->flags++;
	total = CONFIG_ENV_SIZE;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;
	if(gd->env_valid == 1) {
		puts ("Erasing redundant Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
		if (nand_erase_opts(mtd, &nand_erase_options))
			return 1;

		puts ("Writing to redundant Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) env_ptr);
	} else {
		puts ("Erasing Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET;
		if (nand_erase_opts(mtd, &nand_erase_options))
			return 1;

		puts ("Writing to Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);
	}
	if (ret) {
		puts("FAILED!\n");
		return 1;
	}

	puts ("done\n");
	gd->env_valid = (gd->env_valid == 2 ? 1 : 2);
	return ret;
}
/*
 * The legacy NAND code saved the environment in the first NAND device i.e.,
 * nand_dev_desc + 0. This is also the behaviour using the new NAND code.
 */
int writeenv(size_t offset, u_char *buf)
{
	size_t end = offset + CONFIG_ENV_RANGE;
	size_t amount_saved = 0;
	size_t blocksize, len;

	u_char *char_ptr;

	blocksize = nand_info[0].erasesize;
	len = min(blocksize, CONFIG_ENV_SIZE);

	while (amount_saved < CONFIG_ENV_SIZE && offset < end) {
		if (nand_block_isbad(&nand_info[0], offset)) {
			offset += blocksize;
		} else {
			char_ptr = &buf[amount_saved];
			if (nand_write(&nand_info[0], offset, &len,
					char_ptr))
				return 1;
			offset += blocksize;
			amount_saved += len;
		}
	}
	if (amount_saved != CONFIG_ENV_SIZE)
		return 1;

	return 0;
}
#ifdef CONFIG_ENV_OFFSET_REDUND
int saveenv(void)
{
	int ret = 0;
	nand_erase_options_t nand_erase_options;

	env_ptr->flags++;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;
	if(gd->env_valid == 1) {
		puts ("Erasing redundant Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts ("Writing to redundant Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) env_ptr);
	} else {
		puts ("Erasing Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts ("Writing to Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);
	}
	if (ret) {
		puts("FAILED!\n");
		return 1;
	}

	puts ("done\n");
	gd->env_valid = (gd->env_valid == 2 ? 1 : 2);
	return ret;
}
#else /* ! CONFIG_ENV_OFFSET_REDUND */
int saveenv(void)
{
	int ret = 0;
	nand_erase_options_t nand_erase_options;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;
	nand_erase_options.offset = CONFIG_ENV_OFFSET;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;
	puts ("Erasing Nand...\n");
	if (nand_erase_opts(&nand_info[0], &nand_erase_options))
		return 1;

	puts ("Writing to Nand... ");
	if (writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr)) {
		puts("FAILED!\n");
		return 1;
	}

	puts ("done\n");
	return ret;
}
Esempio n. 4
0
static int dfu_flush_medium_nand(struct dfu_entity *dfu)
{
	int ret = 0;

	/* in case of ubi partition, erase rest of the partition */
	if (dfu->data.nand.ubi) {
		nand_info_t *nand;
		nand_erase_options_t opts;

		if (nand_curr_device < 0 ||
		    nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
		    !nand_info[nand_curr_device].name) {
			printf("%s: invalid nand device\n", __func__);
			return -1;
		}

		nand = &nand_info[nand_curr_device];

		memset(&opts, 0, sizeof(opts));
		opts.offset = dfu->data.nand.start + dfu->offset +
				dfu->bad_skip;
		opts.length = dfu->data.nand.start +
				dfu->data.nand.size - opts.offset;
		ret = nand_erase_opts(nand, &opts);
		if (ret != 0)
			printf("Failure erase: %d\n", ret);
	}

	return ret;
}
Esempio n. 5
0
/*
 * The legacy NAND code saved the environment in the first NAND device i.e.,
 * nand_dev_desc + 0. This is also the behaviour using the new NAND code.
 */
int writeenv(size_t offset, u_char *buf)
{
	size_t end = offset + CONFIG_ENV_RANGE;
	size_t amount_saved = 0;
	size_t blocksize, len;

	u_char *char_ptr;

	blocksize = nand_info[0].erasesize;
	len = min(blocksize, CONFIG_ENV_SIZE);

	while (amount_saved < CONFIG_ENV_SIZE && offset < end) {
		if (nand_block_isbad(&nand_info[0], offset)) {
			offset += blocksize;
		} else {
			char_ptr = &buf[amount_saved];
			if (nand_write(&nand_info[0], offset, &len,
					char_ptr))
				return 1;
			offset += blocksize;
			amount_saved += len;
		}
	}
	if (amount_saved != CONFIG_ENV_SIZE)
		return 1;

	return 0;
}
#ifdef CONFIG_ENV_OFFSET_REDUND
int saveenv(void)
{
	int ret = 0;
	nand_erase_options_t nand_erase_options;

	env_ptr->flags++;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;
	if(gd->env_valid == 1) {
		puts ("Erasing redundant Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts ("Writing to redundant Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) env_ptr);
	} else {
		puts ("Erasing Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts ("Writing to Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);
	}
	if (ret) {
		puts("FAILED!\n");
		return 1;
	}

	puts ("done\n");
	gd->env_valid = (gd->env_valid == 2 ? 1 : 2);
	return ret;
}
#else /* ! CONFIG_ENV_OFFSET_REDUND */
int saveenv(void)
{
	int ret = 0;
	nand_erase_options_t nand_erase_options;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;
	nand_erase_options.offset = CONFIG_ENV_OFFSET;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;

	/* we will erase the block anyway, so prevent warning */
	if (nand_erase_options.length < nand_info[0].erasesize)
		nand_erase_options.length = nand_info[0].erasesize;

	puts ("Erasing Nand...\n");
	if (nand_erase_opts(&nand_info[0], &nand_erase_options))
		return 1;

	puts ("Writing to Nand... ");
	if (writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr)) {
		puts("FAILED!\n");
		return 1;
	}

	puts ("done\n");
	return ret;
}
Esempio n. 6
0
static int upgrade_erase_nftl_part()
{
	char	str[128];
	nand_erase_options_t opts;
	int error, nand_scrub_flag = 0, i, blk_num;
	size_t pagesize, blocksize, len;
	loff_t nftl_erase_addr;
	struct mtd_info *mtd = nand_info[nand_curr_device];
	if (mtd == NULL) {
		printk("mtd name err: %s\n", mtd->name);
		return -1;
	}

	pagesize = mtd->writesize;
	blocksize = mtd->erasesize;
	len = pagesize;
	u_char temp_buf[pagesize];
	nftl_erase_addr = 0;
	blk_num = mtd->size / mtd->erasesize;
	printk("nftl_erase_addr %llx blks: %d\n", nftl_erase_addr, blk_num);

	for (i=0; i<blk_num; i++) {
		memset(temp_buf, 0xff, 16);
		error = nand_read(mtd, nftl_erase_addr + i*blocksize, &len, temp_buf);
		if ((error) && (error != -EUCLEAN)) {
			printf("read data from nand error: %d\n",error);
			//continue;
		}
		if(!strncmp(temp_buf, "amlnftl", 7) || !strncmp((temp_buf + pagesize / 2), "amlnftl", 7)) {
			nand_scrub_flag = 1;
			break;
		}
	}

	printk("nand_scrub_flag: %d\n", nand_scrub_flag);
	if (nand_scrub_flag) {
		i = 0;

		memset(&opts, 0, sizeof(opts));
		opts.offset = 0;
		opts.length = mtd->size;
		opts.quiet = 1;
		opts.scrub = 1;
		nand_erase_opts(mtd, &opts);

		sprintf(str, "fatload mmc 0:%d ${loadaddr} ${bootloader_path}", (i + 1));
		UPGRADE_DPRINT("command:    %s\n", str);
		run_command (str, 0);

		run_command ("nand rom_protect off", 0);
		run_command ("nand rom_write ${loadaddr} ${bootloader_start} ${bootloader_size}", 0);
		run_command ("nand rom_protect on", 0);
	}
	return 0;
}
int saveenv(void)
{
	int ret = 0;
	nand_erase_options_t nand_erase_options;

	env_ptr->flags++;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;
	if(gd->env_valid == 1) {
		puts ("Erasing redundant Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts ("Writing to redundant Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) env_ptr);
	} else {
		puts ("Erasing Nand...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts ("Writing to Nand... ");
		ret = writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);
	}
	if (ret) {
		puts("FAILED!\n");
		return 1;
	}

	puts ("done\n");
	gd->env_valid = (gd->env_valid == 2 ? 1 : 2);
	return ret;
}
Esempio n. 8
0
/* Write nboot loader image into the nand flash */
int nand_burn_nboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	int filesize;
	MV_U32 ret = 0;
	extern char console_buffer[];
	nand_info_t *nand = &nand_info[0];
	nand_erase_options_t er_opts;
	nand_write_options_t wr_opts;


	load_addr = CFG_LOAD_ADDR; 
	if(argc == 2) {
		copy_filename (BootFile, argv[1], sizeof(BootFile));
	}
	else { 
		copy_filename (BootFile, "nboot.bin", sizeof(BootFile));
		printf("using default file \"nboot.bin\" \n");
	}
 
	if ((filesize = NetLoop(TFTP)) < 0)
		return 0;
 
	printf("Erase %d - %d ... ",CFG_NBOOT_BASE, CFG_NBOOT_LEN);
	memset(&er_opts, 0, sizeof(er_opts));
	er_opts.offset = CFG_NBOOT_BASE;
	er_opts.length = CFG_NBOOT_LEN;
	er_opts.quiet  = 1;

	nand_erase_opts(nand, &er_opts);
	//nand_erase(nand_dev_desc + 0, CFG_NBOOT_BASE, CFG_NBOOT_LEN , 0);
	
	printf("\nCopy to Nand Flash... ");
	memset(&wr_opts, 0, sizeof(wr_opts));
	wr_opts.buffer	= (u_char*) load_addr;
	wr_opts.length	= CFG_NBOOT_LEN;
	wr_opts.offset	= CFG_NBOOT_BASE;
	/* opts.forcejffs2 = 1; */
	wr_opts.pad	= 1;
	wr_opts.blockalign = 1;
	wr_opts.quiet      = 1;
	ret = nand_write_opts(nand, &wr_opts);
	/* ret = nand_rw(nand_dev_desc + 0,
				  NANDRW_WRITE | NANDRW_JFFS2, CFG_NBOOT_BASE, CFG_NBOOT_LEN,
			      &total, (u_char*)0x100000);
	*/
  	if (ret)
		printf("Error - NAND burn faild!\n");
	else
		printf("\ndone\n");	

	return 1;
}
Esempio n. 9
0
static int eraseNandFlash(int nOffsetAddr, int nLength)
{
	int nRet = -1;
		
	nand_info_t *nand = &nand_info[nand_curr_device];
	nand_erase_options_t opts;

	memset(&opts, 0, sizeof(opts));
	opts.offset = nOffsetAddr;
	opts.length = nLength;
	opts.jffs2	= 0;
	opts.quiet	= 1;
	opts.spread = 0;

	nRet = nand_erase_opts(nand, &opts);
	printf("Erase NAND flash 0x%x 0x%x %s\n", nOffsetAddr, nLength, nRet?"ERROR":"OK");
		
	return (nRet?FALSE:TRUE );
}
Esempio n. 10
0
/*******************************************************************************
Reset environment variables.
********************************************************************************/
extern flash_info_t flash_info[];       /* info for FLASH chips */
int resetenv_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
#if defined(CFG_NAND_BOOT)
	printf("Erase Env parameters offset 0x%x... ",CFG_ENV_OFFSET);
	nand_info_t *nand = &nand_info[0];
	nand_erase_options_t er_opts;
	memset(&er_opts, 0, sizeof(er_opts));
	er_opts.offset = CFG_ENV_OFFSET;
	er_opts.length = CFG_ENV_SECT_SIZE;
	er_opts.quiet  = 1;

	nand_erase_opts(nand, &er_opts);
	//nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SECT_SIZE, 0);
	printf("done");
#else
	MV_U32 env_sec = flash_in_which_sec(&flash_info[BOOT_FLASH_INDEX], CFG_ENV_ADDR);
	
	if (env_sec == -1)
	{
		printf("Could not find ENV Sector\n");
		return 0;
	}

	printf("Un-Protect ENV Sector\n");

	flash_protect(FLAG_PROTECT_CLEAR,
				  CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
				  &flash_info[BOOT_FLASH_INDEX]);

	
	printf("Erase sector %d ... ",env_sec);
	flash_erase(&flash_info[BOOT_FLASH_INDEX], env_sec, env_sec);
	printf("done\nProtect ENV Sector\n");
	
	flash_protect(FLAG_PROTECT_SET,
				  CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1,
				  &flash_info[BOOT_FLASH_INDEX]);

#endif /* defined(CFG_NAND_BOOT) */
	printf("\nWarning: Default Environment Variables will take effect Only after RESET \n\n");
	return 1;
}
Esempio n. 11
0
static int erase_and_write_env(const struct nand_env_location *location,
		u_char *env_new)
{
	struct mtd_info *mtd;
	int ret = 0;

	mtd = get_nand_dev_by_index(0);
	if (!mtd)
		return 1;

	printf("Erasing %s...\n", location->name);
	if (nand_erase_opts(mtd, &location->erase_opts))
		return 1;

	printf("Writing to %s... ", location->name);
	ret = writeenv(location->erase_opts.offset, env_new);
	puts(ret ? "FAILED!\n" : "OK\n");

	return ret;
}
Esempio n. 12
0
static int _fb_nand_erase(struct mtd_info *mtd, struct part_info *part)
{
	nand_erase_options_t opts;
	int ret;

	memset(&opts, 0, sizeof(opts));
	opts.offset = part->offset;
	opts.length = part->size;
	opts.quiet = 1;

	printf("Erasing blocks 0x%llx to 0x%llx\n",
	       part->offset, part->offset + part->size);

	ret = nand_erase_opts(mtd, &opts);
	if (ret)
		return ret;

	printf("........ erased 0x%llx bytes from '%s'\n",
	       part->size, part->name);

	return 0;
}
Esempio n. 13
0
/*
 * The legacy NAND code saved the environment in the first NAND device i.e.,
 * nand_dev_desc + 0. This is also the behaviour using the new NAND code.
 */
int writeenv(size_t offset, u_char *buf)
{
	size_t end = offset + CONFIG_ENV_RANGE;
	size_t amount_saved = 0;
	size_t blocksize, len;

	u_char *char_ptr;

	blocksize = nand_info[0].erasesize;
	len = min(blocksize, CONFIG_ENV_SIZE);

	while (amount_saved < CONFIG_ENV_SIZE && offset < end) {
		if (nand_block_isbad(&nand_info[0], offset)) {
			offset += blocksize;
		} else {
			char_ptr = &buf[amount_saved];
			if (nand_write(&nand_info[0], offset, &len,
					char_ptr))
				return 1;
			offset += blocksize;
			amount_saved += len;
		}
	}
	if (amount_saved != CONFIG_ENV_SIZE)
		return 1;

	return 0;
}

#ifdef CONFIG_ENV_OFFSET_REDUND
static unsigned char env_flags;

int saveenv(void)
{
	env_t	env_new;
	ssize_t	len;
	char	*res;
	int	ret = 0;
	nand_erase_options_t nand_erase_options;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;

	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);
		return 1;
	}
	env_new.crc   = crc32(0, env_new.data, ENV_SIZE);
	env_new.flags = ++env_flags; /* increase the serial */

	if(gd->env_valid == 1) {
		puts("Erasing redundant NAND...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts("Writing to redundant NAND... ");
		ret = writeenv(CONFIG_ENV_OFFSET_REDUND,
			(u_char *)&env_new);
	} else {
		puts("Erasing NAND...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts("Writing to NAND... ");
		ret = writeenv(CONFIG_ENV_OFFSET,
			(u_char *)&env_new);
	}
	if (ret) {
		puts("FAILED!\n");
		return 1;
	}

	puts("done\n");

	gd->env_valid = (gd->env_valid == 2 ? 1 : 2);

	return ret;
}
#else /* ! CONFIG_ENV_OFFSET_REDUND */
int saveenv(void)
{
	int ret = 0;
	env_t	env_new;
	ssize_t	len;
	char	*res;
	nand_erase_options_t nand_erase_options;

	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 0;
	nand_erase_options.jffs2 = 0;
	nand_erase_options.scrub = 0;
	nand_erase_options.offset = CONFIG_ENV_OFFSET;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;

	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);
		return 1;
	}
	env_new.crc   = crc32(0, env_new.data, ENV_SIZE);

	puts("Erasing Nand...\n");
	if (nand_erase_opts(&nand_info[0], &nand_erase_options))
		return 1;

	puts("Writing to Nand... ");
	if (writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new)) {
		puts("FAILED!\n");
		return 1;
	}

	puts("done\n");
	return ret;
}
Esempio n. 14
0
/*
 * The legacy NAND code saved the environment in the first NAND device i.e.,
 * nand_dev_desc + 0. This is also the behaviour using the new NAND code.
 */
int writeenv(size_t offset, u_char *buf)
{
	uint64_t end = offset + CONFIG_ENV_RANGE;
	uint64_t amount_saved = 0;
	uint64_t blocksize, len;

	u_char *char_ptr;

	blocksize = nand_info[0].erasesize;
	len = min(blocksize, CONFIG_ENV_SIZE);

	offset = CONFIG_ENV_OFFSET;
	
	while (amount_saved < CONFIG_ENV_SIZE && offset < end) {
		if (nand_block_isbad(&nand_info[0], offset)) {
			offset += blocksize;
		} else {
			char_ptr = &buf[amount_saved];
			if (nand_write(&nand_info[0], offset, (size_t *)&len, char_ptr))
				return 1;

			offset += blocksize;
			amount_saved += len;
		}
	}
	if (amount_saved != CONFIG_ENV_SIZE)
		return 1;

	return 0;
}

#ifdef CONFIG_ENV_OFFSET_REDUND
static unsigned char env_flags;

int saveenv(void)
{
	env_t	env_new;
	ssize_t	len;
	char	*res;
	int	ret = 0;
	nand_erase_options_t nand_erase_options;

	memset(&nand_erase_options, 0, sizeof(nand_erase_options));
	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 1;


	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;

	res = (char *)&env_new.data;
	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
	if (len < 0) {
		error("Cannot export environment: errno = %d\n", errno);
		return 1;
	}
	env_new.crc	= crc32(0, env_new.data, ENV_SIZE);
	env_new.flags	= ++env_flags; /* increase the serial */

	if (gd->env_valid == 1) {
		puts("Erasing redundant NAND...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts("Writing to redundant NAND... ");
		ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *)&env_new);
	} else {
		puts("Erasing NAND...\n");
		nand_erase_options.offset = CONFIG_ENV_OFFSET;
		if (nand_erase_opts(&nand_info[0], &nand_erase_options))
			return 1;

		puts("Writing to NAND... ");
		ret = writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new);
	}
	if (ret) {
		puts("FAILED!\n");
		return 1;
	}

	puts("done\n");

	gd->env_valid = gd->env_valid == 2 ? 1 : 2;

	return ret;
}
#else /* ! CONFIG_ENV_OFFSET_REDUND */
int saveenv(void)
{
	int	ret = 0;
	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
	ssize_t	len;
	char	*res;
	nand_erase_options_t nand_erase_options;

	memset(&nand_erase_options, 0, sizeof(nand_erase_options));
	nand_erase_options.length = CONFIG_ENV_RANGE;
	nand_erase_options.quiet = 1;
	nand_erase_options.offset = CONFIG_ENV_OFFSET;

	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
		return 1;

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

	puts("Erasing Nand...\n");
	if (nand_erase_opts(&nand_info[0], &nand_erase_options))
		return 1;

	puts("Writing to Nand... ");
	if (writeenv(CONFIG_ENV_OFFSET, (u_char *)env_new)) {
		puts("FAILED!\n");
		return 1;
	}

	puts("done\n");
	return ret;
}
Esempio n. 15
0
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	int i, dev, ret = 0;
	ulong addr, off;
	size_t size;
	char *cmd, *s;
	nand_info_t *nand;
#ifdef CONFIG_SYS_NAND_QUIET
	int quiet = CONFIG_SYS_NAND_QUIET;
#else
	int quiet = 0;
#endif
	const char *quiet_str = getenv("quiet");

	/* at least two arguments please */
	if (argc < 2)
		goto usage;

	if (quiet_str)
		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;

	cmd = argv[1];

	if (strcmp(cmd, "info") == 0) {

		putc('\n');
		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
			if (nand_info[i].name)
				nand_print_info(i);
		}
		return 0;
	}

	if (strcmp(cmd, "device") == 0) {

		if (argc < 3) {
			putc('\n');
			if ((nand_curr_device < 0) ||
			    (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE))
				puts("no devices available\n");
			else
				nand_print_info(nand_curr_device);
			return 0;
		}
		dev = (int)simple_strtoul(argv[2], NULL, 10);
		if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) {
			puts("No such device\n");
			return 1;
		}
		printf("Device %d: %s", dev, nand_info[dev].name);
		puts("... is now current device\n");
		nand_curr_device = dev;

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
		/*
		 * Select the chip in the board/cpu specific driver
		 */
		board_nand_select_device(nand_info[dev].priv, dev);
#endif

		return 0;
	}

	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
	    strncmp(cmd, "dump", 4) != 0 &&
	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
	    strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
	    strcmp(cmd, "biterr") != 0 &&
	    strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0
#ifdef CONFIG_ENV_OFFSET_OOB
	    && strcmp(cmd, "env.oob") != 0
#endif
	    )
		goto usage;

#ifdef CONFIG_ENV_OFFSET_OOB
	/* this command operates only on the first nand device */
	if (strcmp(cmd, "env.oob") == 0) {
		return do_nand_env_oob(cmdtp, &nand_info[0],
				       argc - 1, argv + 1);
	}
#endif

	/* the following commands operate on the current device */
	if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
	    !nand_info[nand_curr_device].name) {
		puts("\nno devices available\n");
		return 1;
	}
	nand = &nand_info[nand_curr_device];

	if (strcmp(cmd, "bad") == 0) {
		printf("\nDevice %d bad blocks:\n", nand_curr_device);
		for (off = 0; off < nand->size; off += nand->erasesize)
			if (nand_block_isbad(nand, off))
				printf("  %08lx\n", off);
		return 0;
	}

	/*
	 * Syntax is:
	 *   0    1     2       3    4
	 *   nand erase [clean] [off size]
	 */
	if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
		nand_erase_options_t opts;
		/* "clean" at index 2 means request to write cleanmarker */
		int clean = argc > 2 && !strcmp("clean", argv[2]);
		int o = clean ? 3 : 2;
		int scrub = !strcmp(cmd, "scrub");

		printf("\nNAND %s: ", scrub ? "scrub" : "erase");
		/* skip first two or three arguments, look for offset and size */
		if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
			return 1;

		memset(&opts, 0, sizeof(opts));
		opts.offset = off;
		opts.length = size;
		opts.jffs2  = clean;
		opts.quiet  = quiet;

		if (scrub) {
			puts("Warning: "
			     "scrub option will erase all factory set "
			     "bad blocks!\n"
			     "         "
			     "There is no reliable way to recover them.\n"
			     "         "
			     "Use this command only for testing purposes "
			     "if you\n"
			     "         "
			     "are sure of what you are doing!\n"
			     "\nReally scrub this NAND flash? <y/N>\n");

			if (getc() == 'y') {
				puts("y");
				if (getc() == '\r')
					opts.scrub = 1;
				else {
					puts("scrub aborted\n");
					return -1;
				}
			} else {
				puts("scrub aborted\n");
				return -1;
			}
		}
		ret = nand_erase_opts(nand, &opts);
		printf("%s\n", ret ? "ERROR" : "OK");

		return ret == 0 ? 0 : 1;
	}

	if (strncmp(cmd, "dump", 4) == 0) {
		if (argc < 3)
			goto usage;

		s = strchr(cmd, '.');
		off = (int)simple_strtoul(argv[2], NULL, 16);

		if (s != NULL && strcmp(s, ".oob") == 0)
			ret = nand_dump(nand, off, 1);
		else
			ret = nand_dump(nand, off, 0);

		return ret == 0 ? 1 : 0;

	}

	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
		int read;

		if (argc < 4)
			goto usage;

		addr = (ulong)simple_strtoul(argv[2], NULL, 16);

		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
		printf("\nNAND %s: ", read ? "read" : "write");
		if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
			return 1;

		s = strchr(cmd, '.');
		if (!s || !strcmp(s, ".jffs2") ||
		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
			if (read)
				ret = nand_read_skip_bad(nand, off, &size,
							 (u_char *)addr);
			else
				ret = nand_write_skip_bad(nand, off, &size,
							  (u_char *)addr);
		} else if (!strcmp(s, ".oob")) {
			/* out-of-band data */
			mtd_oob_ops_t ops = {
				.oobbuf = (u8 *)addr,
				.ooblen = size,
				.mode = MTD_OOB_RAW
			};

			if (read)
				ret = nand->read_oob(nand, off, &ops);
			else
				ret = nand->write_oob(nand, off, &ops);
		} else {
Esempio n. 16
0
void set_env_funcptrs(void)
{
#ifdef CONFIG_SOC_HAYDN
    env_init = serialflash_env_init ;
    saveenv = serialflash_saveenv ;
    env_get_char_spec = serialflash_env_get_char_spec ;
    env_relocate_spec = serialflash_env_relocate_spec ;
#elif (defined(CONFIG_SOC_MOZART) || defined(CONFIG_SOC_BEETHOVEN))
    unsigned long val = inl(BOOTING_DEVICE_INFO);
    int sdbootSucess = 0 ;


#ifdef CONFIG_CMD_MMC
    if(val == SYSCTRL_DATA_IN_SD && SD_Card_Detect(0)) {
        printf( "  Boot Storage : SD Card\n" ) ;
        gd->env_valid = 0 ;//We always use default envs when booting from SD.
        env_init = sd_env_init ;
        saveenv = sd_saveenv ;
        env_get_char_spec = sd_env_get_char_spec ;
        env_relocate_spec = sd_env_relocate_spec ;

        //check if real sd boot
        if(SD_Read(MAGIC_SD_ADDR, MAGIC_DATA_SIZE, MAGIC_DRAM_ADDR) != 0) {
			printf("[ERR] SD-Read fails!\n") ;
			sdbootSucess = 0 ;
			goto SDBOOT_FAIL;
        }

        if((v_inl(MAGIC_DRAM_ADDR) != MAGIC_NUM0) || (v_inl(MAGIC_DRAM_ADDR+4) != MAGIC_NUM1)) {
            printf("   !! MAGIC# of SD Card is wrong\n") ;
            printf("   !! Find other Boot Storage..\n\n") ;
            sdbootSucess = 0 ;
            goto SDBOOT_FAIL ;
        }
        printf("   SD Card has correct Magic#.\n") ;
        printf("   SD Boot Sucessfully.\n\n") ;

        update_default_envs_ifsdboot() ;

        sdbootSucess = 1 ;

#ifdef SDAUTOBURN_FLOW_FROMSD
        printf("  ****** Auto Burn Flow ******\n") ;
        printf("  Step 1. Copy data(size 0x%08x) from 0x%08x of SD to 0x%08x of DRAM\n", AUTOBURN_DATASIZE, AUTOBURN_SDADDR, AUTOBURN_DRAMADDR) ;
        SD_Read(AUTOBURN_SDADDR, AUTOBURN_DATASIZE, AUTOBURN_DRAMADDR) ;

        if(AUTOBURN_FLASHTYPE == AUTOBURN_SPIFLASH) {
            printf("  Step 2. Write data from 0x%08x of DRAM to 0x%08x of SPI FLASH\n", AUTOBURN_DRAMADDR, AUTOBURN_FLASHADDR) ;
            autoburn_sf = spi_flash_probe(0, 0, CONFIG_SF_DEFAULT_SPEED, CONFIG_DEFAULT_SPI_MODE); 
            spi_flash_erase(autoburn_sf, AUTOBURN_FLASHADDR, AUTOBURN_DATASIZE, 0) ;
            spi_flash_write(autoburn_sf, AUTOBURN_FLASHADDR, AUTOBURN_DATASIZE, AUTOBURN_DRAMADDR, 0) ;
            printf("  Done\n") ;
						outl(0xFFF, 0x49000004);
        }
        else if(AUTOBURN_FLASHTYPE == AUTOBURN_NANDFLASH)
        {
            printf("  Step 3. Write data from 0x%08x of DRAM to 0x%08x of NAND FLASH\n", AUTOBURN_DRAMADDR, AUTOBURN_FLASHADDR) ;
            nand_info_t *mtd ;
            mtd = &nand_info[0] ;
            nand_erase_options_t opts;

            memset(&opts, 0, sizeof(opts));
    		opts.offset = AUTOBURN_FLASHADDR;
	    	opts.length = AUTOBURN_DATASIZE;
		    //opts.jffs2  = clean;
            opts.jffs2  = 0;//[patch] we do not allow jffs2 in our u-boot
	    	opts.quiet  = 0;
            opts.all = 1 ;

            unsigned long datasize = AUTOBURN_DATASIZE ;
            nand_erase_opts(mtd, &opts) ;
            //printf("chipsize=%d, blocksize=%d, block#=%d\n", mtd->totalsize, mtd->erasesize, (mtd->totalsize / mtd->erasesize)) ;
            nand_write_skip_bad(mtd, AUTOBURN_FLASHADDR, &datasize, AUTOBURN_DRAMADDR) ;//100 temporary
        }
#endif //SDAUTOBURN_FLOW_FROMSD
    }

    if(sdbootSucess)
        return ;

#endif //CONFIG_CMD_SD
SDBOOT_FAIL:
    if ( val == SYSCTRL_DATA_IN_SERIALFLASH) {
        printf( "  Boot Storage : Serial Flash\n" ) ;
        env_init = serialflash_env_init ;
        saveenv = serialflash_saveenv ;
        env_get_char_spec = serialflash_env_get_char_spec ;
        env_relocate_spec = serialflash_env_relocate_spec ;
    }
#if defined(CONFIG_CMD_NAND)
    else if ( val == SYSCTRL_DATA_IN_NANDFLASH) {
		update_default_envs_ifnfboot() ;
        printf( "  Boot Storage : Nand Flash\n" ) ;
        env_init = nand_env_init ;
        saveenv = nand_saveenv ;
        env_get_char_spec = nand_env_get_char_spec ;
        env_relocate_spec = nand_env_relocate_spec ;
    }
#endif

#endif //CONFIG_SOC_MOZART
}
Esempio n. 17
0
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	int i, dev, ret = 0;
	uint32_t addr, cmp_addr;
	uint64_t off;
	uint64_t size;
	char *cmd, *s;
	nand_info_t *nand;
#ifdef CONFIG_SYS_NAND_QUIET
	int quiet = CONFIG_SYS_NAND_QUIET;
#else
	int quiet = 0;
#endif
	const char *quiet_str = getenv("quiet");

	/* at least two arguments please */
	if (argc < 2)
		goto usage;

	if (quiet_str)
		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;

	cmd = argv[1];

	if (strcmp(cmd, "info") == 0) {
		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
			if (nand_info[i].name)
				nand_print_info(i);
		}
		return 0;
	}

	if (strcmp(cmd, "device") == 0) {

		if (argc < 3) {
			putc('\n');
			if ((nand_curr_device < 0) ||
			    (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE))
				puts("no devices available\n");
			else
				nand_print_info(nand_curr_device);
			return 0;
		}
		dev = (int)simple_strtoul(argv[2], NULL, 10);
		if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) {
			puts("No such device\n");
			return 1;
		}
		printf("Device %d: %s", dev, nand_info[dev].name);
		puts("... is now current device\n");
		nand_curr_device = dev;

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
		/*
		 * Select the chip in the board/cpu specific driver
		 */
		board_nand_select_device(nand_info[dev].priv, dev);
#endif

		return 0;
	}

	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
	    strncmp(cmd, "dump", 4) != 0 &&
	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
	    strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
	    strcmp(cmd, "biterr") != 0 && strcmp(cmd, "pattern") != 0 &&
	    strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
		goto usage;

	/* the following commands operate on the current device */
	if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
	    !nand_info[nand_curr_device].name) {
		puts("\nno devices available\n");
		return 1;
	}
	nand = &nand_info[nand_curr_device];

	if (strcmp(cmd, "bad") == 0) {
		printf("\nDevice %d bad blocks:\n", nand_curr_device);
		for (off = 0; off < nand->size; off += nand->erasesize)
			if (nand_block_isbad(nand, off))
				printf("  %12llx\n", off);
		return 0;
	}

	/*
	 * Syntax is:
	 *   0    1     2       3    4
	 *   nand erase [clean] [off size]
	 */
	if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
		nand_erase_options_t opts;
		/* "clean" at index 2 means request to write cleanmarker */
		int clean = argc > 2 && !strcmp("clean", argv[2]);
		int o = clean ? 3 : 2;
		int scrub = !strcmp(cmd, "scrub");

		printf("\nNAND %s: ", scrub ? "scrub" : "erase");
		/* skip first two or three arguments, look for offset and size */
		if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
			return 1;

		memset(&opts, 0, sizeof(opts));
		opts.offset = off;
		opts.length = size;
		opts.jffs2  = clean;
		opts.quiet  = quiet;

		if (scrub) {
			puts("Warning: "
			     "scrub option will erase all factory set "
			     "bad blocks!\n"
			     "         "
			     "There is no reliable way to recover them.\n"
			     "         "
			     "Use this command only for testing purposes "
			     "if you\n"
			     "         "
			     "are sure of what you are doing!\n"
			     "\nReally scrub this NAND flash? <y/N>\n");

			if (getc() == 'y' && getc() == '\r') {
				opts.scrub = 1;
			} else {
				puts("scrub aborted\n");
				return -1;
			}
		}
		ret = nand_erase_opts(nand, &opts);
		printf("%s\n", ret ? "ERROR" : "OK");

		return ret == 0 ? 0 : 1;
	}

	if (strncmp(cmd, "dump", 4) == 0) {
		if (argc < 3)
			goto usage;

		s = strchr(cmd, '.');
		off = simple_strtoull(argv[2], NULL, 16);

		if (s != NULL && strcmp(s, ".oob") == 0)
			ret = nand_dump(nand, off, 1);
		else
			ret = nand_dump(nand, off, 0);

		return ret == 0 ? 1 : 0;

	}

	if (strncmp(cmd, "pattern", 4) == 0) {
		int chunk_num;
		uint64_t offset, chunk64, cmp64;
		nand_erase_options_t opts;
		memset(&opts, 0, sizeof(opts));

		// nand pattern addr cmp_addr  chunk_size
		//  0     1      2    3          4
		if (argc < 5)
			goto usage;

		addr = simple_strtoul(argv[2], NULL, 16);
		cmp_addr = simple_strtoul(argv[3], NULL, 16);
		chunk64 = simple_strtoull(argv[4], NULL, 16);
		cmp64 = chunk64;
		chunk_num = (int) (nand->size / chunk64);
		printf("NAND size [0x%llx], chunk size [0x%llx], number of chunks [%d]\n", nand->size, chunk64, chunk_num);
		printf("Erasing all chip...\n");
		opts.offset = 0;
		opts.length = nand->size;
		opts.jffs2  = 0;
		opts.quiet  = 0;
		opts.scrub = 0;
		if (nand_erase_opts(nand, &opts) != 0) {
			printf("[FAILED]\n");
			return 1;
		} else {
			printf("[OK]\n");
		}
		offset = 0;
		while(offset < nand->size) {
			printf("0x%010llx:", offset);
// 			printf("\tB:");
// 			if (nand_block_isbad(nand, i*chunk_size & ~(nand->erasesize - 1))) {
// 				printf("[V]\n");
// 				continue;
// 			} else {
// 				printf("[X]");
// 			}
// 			size_include_bad = get_len_incl_bad (nand, offset, chunk_size);
// 			opts.offset = offset;
// 			opts.length = size_include_bad;
// 			opts.quiet  = 1;
// 			printf("\tE:");
// 			if (nand_erase_opts(nand, &opts) != 0) {
// 				printf("[X]\n");
// 				return 1;
// 			} else {
// 				printf("[V]");
// 			}
			printf("\tW:");
			chunk64 = cmp64;
			if (nand_write_skip_bad(nand, offset, &chunk64, (u_char *)addr) != 0) {
				printf("[X]\n");
				return 1;
			} else {
				printf("[V]");
			}
			printf("\tR:");
			chunk64 = cmp64;
			if (nand_read_skip_bad(nand, offset, &chunk64, (u_char *)cmp_addr) != 0) {
				printf("[X]\n");
				return 1;
			} else {
				printf("[V]");
			}
			printf("\tC:");
			if (memcmp((void *)addr, (void *)cmp_addr, cmp64) != 0) {
				printf("[X]\n");
				return 1;
			} else {
				printf("[V]");
			}
			printf("\n");
			if (ctrlc()) {
				puts ("\nAbort\n");
				return (-1);
			}
			offset += get_len_incl_bad (nand, offset, cmp64);
		}
		printf("NAND Pattern Test PASSED!\n");
		return 0;
	}

	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
		int read;

		if (argc < 4)
			goto usage;

		addr = simple_strtoul(argv[2], NULL, 16);

		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
		printf("\nNAND %s: ", read ? "read" : "write");
		if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
			return 1;

		s = strchr(cmd, '.');
		if (!s || !strcmp(s, ".jffs2") ||
		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
			if (read)
				ret = nand_read_skip_bad(nand, off, &size,
							 (u_char *)addr);
			else
				ret = nand_write_skip_bad(nand, off, &size,
							  (u_char *)addr);
		} else if (!strcmp(s, ".oob")) {
			/* out-of-band data */
			mtd_oob_ops_t ops = {
				.oobbuf = (uint8_t *)addr,
				.ooblen = size,
				.mode = MTD_OOB_RAW
			};

			if (read)
				ret = nand->read_oob(nand, off, &ops);
			else
				ret = nand->write_oob(nand, off, &ops);
		} else {
Esempio n. 18
0
/*******************************************************************************
 * mvNandReadWriteTest - Performs read-write test on NAND chip.
 *
 * DESCRIPTION:
 *		This routine writes pattern 0x55,0xaa in 16 blocks at offset immediately
 *		after ENV section and reads them back and verifies.
 *
 * INPUT:
 *		None.
 *
 * OUTPUT:
 *		None.
 *
 * RETURN:
 *		Returns 1 on failure, else 0
 *******************************************************************************/
int mvNandReadWriteTest(void)
{
	int i,j,ret;
	int testFlag;
	unsigned int pageSize;
	unsigned char rbuf[2048];
	nand_write_options_t wr_opts;
	nand_erase_options_t er_opts;
	nand_read_options_t rd_opts;
	testFlag = DIAG_PASS;

	printf("\tNAND read/write test                             ");

	do
	{
		pageSize = nand_info[0].oobblock;

		/***************** ERASE ***********************/
		memset(&er_opts, 0, sizeof(er_opts));
		er_opts.offset = CFG_ENV_OFFSET + CFG_ENV_SIZE;
		er_opts.length = pageSize * PAGES_PER_BLOCK * 16;
		er_opts.quiet = 1;
		ret = nand_erase_opts(&nand_info[0], &er_opts);
		if (ret)
		{
			printf("\tError: NAND Erase faild!\n");
			testFlag = DIAG_FAIL;
			break;
		}
		if(DIAG_PASS != testFlag)
		{
			break;
		}

		/***************** WRITE ***********************/
		memset(&wr_opts, 0, sizeof(wr_opts));
		for(i=0; i < pageSize; i=i+2)
		{
			wr_opts.buffer[i] = 0x55;
			wr_opts.buffer[i+1] = 0xaa;
		}
		wr_opts.length = pageSize;
		wr_opts.offset = CFG_ENV_OFFSET + CFG_ENV_SIZE;
		/* opts.forcejffs2 = 1; */
		wr_opts.pad = 1;
		wr_opts.blockalign = 1;
		wr_opts.quiet = 1;

		for(i=0; i < PAGES_PER_BLOCK * 16;i++)
		{
			ret = nand_write_opts(&nand_info[0], &wr_opts);
			if (ret)
			{
				printf("\tError: NAND write faild!\n");
				testFlag = DIAG_FAIL;
				break;
			}
			wr_opts.offset += pageSize;
		}
		if(DIAG_PASS != testFlag)
		{
			break;
		}

		/**************** READ *************************/
		memset(&rd_opts, 0, sizeof(rd_opts));
		rd_opts.buffer = rbuf;
		rd_opts.length = (ulong)pageSize;
		rd_opts.offset = CFG_ENV_OFFSET + CFG_ENV_SIZE;
		rd_opts.quiet = 1;

		for(i=0; i < PAGES_PER_BLOCK * 16;i++)
		{
			ret = nand_read_opts(&nand_info[0], &rd_opts);
			if (ret)
			{
				printf("\tError: NAND read faild!\n");
				testFlag = DIAG_FAIL;
				break;
			}

			for(j=0; j < pageSize; j=j+4)
			{
				if (rbuf[j] != 0x55 && rbuf[j+1] != 0xaa && rbuf[j+2] != 0x55 && rbuf[j+3] != 0xaa)
				{
					printf("\tError: Data verify failed\n");
					testFlag = DIAG_FAIL;
					break;
				}
			}
			rd_opts.offset += pageSize;
		}
		if(DIAG_PASS != testFlag)
		{
			 break;
		}

	}while(0);

	printf((testFlag==DIAG_PASS)?"PASSED\n":"FAIL\n");

	return testFlag;
}
Esempio n. 19
0
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	int i, dev, ret = 0;
	ulong addr;
	loff_t off, size;
	char *cmd, *s;
	nand_info_t *nand;
#ifdef CONFIG_SYS_NAND_QUIET
	int quiet = CONFIG_SYS_NAND_QUIET;
#else
	int quiet = 0;
#endif
	const char *quiet_str = getenv("quiet");

#if ((defined CONFIG_AML_NAND_KEY) || (defined MX_REVD) || (defined CONFIG_SECURE_NAND))
	int chip_num , tmp_chip_num, error;
	nand = nand_info[nand_curr_device];
	struct mtd_info *mtd =nand;
	struct aml_nand_chip *aml_chip = mtd_to_nand_chip(nand);
#endif

	/* at least two arguments please */
	if (argc < 2)
		goto usage;

	if (quiet_str)
		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;

	cmd = argv[1];
#ifdef CONFIG_AML_NAND_KEY
	if (strcmp(cmd, "key") == 0){
		aml_chip->key_protect = 1;		//force nand key can be erased 
		return 0;
	}
#endif
#ifdef CONFIG_SECURE_NAND
	if (strcmp(cmd, "secure") == 0){
		aml_chip->secure_protect = 1;		//force nand key can be erased
		return 0;
	}
#endif

#ifdef CONFIG_SECURE_NAND
		if (strcmp(cmd, "secure") == 0){
			aml_chip->secure_protect = 1;		//force nand key can be erased 
			return 0;
		}
#endif

	if(strcmp(cmd, "exist") == 0){
		if(nand_info[1]){
			printf("nand exist return 0\n");
			return 0;
		}
		else{
			printf("nand exist return 1\n");
			return 1;
		}
	}
#ifdef MX_REVD
	if (strcmp(cmd, "errstat") == 0){
	    printk("checking chiprev here\n");
        if(aml_chip->err_sts == NAND_CHIP_REVB_HY_ERR){
            printk("Must use RevD chip for Hynix 26nm/20nm nand boot without SPI!!!\n");
            return NAND_CHIP_REVB_HY_ERR;
        }
		return 0;
	}
#endif
#ifdef CONFIG_SECURE_NAND
		if (strcmp(cmd, "secure") == 0){
			aml_chip->secure_protect = 1;		//force nand key can be erased 
			return 0;
		}
#endif

	if (strcmp(cmd, "info") == 0) {
	#ifdef CONFIG_AML_NAND_KEY
		aml_chip->key_protect = 0;		//protect nand key can not be erased
	#endif
	#ifdef CONFIG_SECURE_NAND
		aml_chip->secure_protect = 0;		//protect nand secure can not be erased
	#endif

		putc('\n');
		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
			nand = nand_info[i];
			if (!nand) {
				nand_init();
				if (!nand)
					return -1;
			}
			if (nand->name)
				nand_print_info(i);
		}
		return 0;
	}
	if (strcmp(cmd, "init") == 0) {
		nand_init();
		return 0;
	}	
//cmd for nand test , if nand is ok , then trigger power off
	if (strcmp(cmd, "test") == 0) {
		int ret=-1;
		puts("\ntest the nand flash ***\n");
		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
			nand = nand_info[i];
			if (!nand) {
				ret=nand_test_init();
				printf("\n***nand_test_init()in NAND DEVICE %d returned:%d***\n ", i,ret);
				if (ret)
					return -1;	
			}
		}		
		return 0;
	}

	if (strcmp(cmd, "scrub_detect") == 0) {

		if (nand_curr_device < 0 || nand_curr_device >= (CONFIG_SYS_MAX_NAND_DEVICE+2)) {
			puts("\nno devices available\n");
			return 1;
		}
		nand = nand_info[nand_curr_device];

		aml_nand_stupid_dectect_badblock(nand);
		return 0;

	}

	if (strcmp(cmd, "device") == 0) {

		if (argc < 3) {
			putc('\n');
			if ((nand_curr_device < 0) ||
			    (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE))
				puts("no devices available\n");
			else
				nand_print_info(nand_curr_device);
			return 0;
		}
		dev = (int)simple_strtoul(argv[2], NULL, 10);
		if (dev < 0 || dev >= (CONFIG_SYS_MAX_NAND_DEVICE+1) || !nand_info[dev]->name) {
			puts("No such device\n");
			return 1;
		}
		printf("Device %d: %s", dev, nand_info[dev]->name);
		puts("... is now current device\n");
		nand_curr_device = dev;

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
		/*
		 * Select the chip in the board/cpu specific driver
		 */
		board_nand_select_device(nand_info[dev]->priv, dev);
#endif

		return 0;
	}

	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
	    strncmp(cmd, "dump", 4) != 0 &&
	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
	    strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
	    strcmp(cmd, "biterr") != 0 && strncmp(cmd, "rom_protect", 11) != 0 &&
	    strncmp(cmd, "wr_rd_cmp", 9) != 0 && strncmp(cmd, "rom_write", 9) != 0 && (strncmp(cmd, "rom_read", 8) != 0) &&
	    strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 &&
	    strcmp(cmd, "factory_info") != 0 && strcmp(cmd, "show_para_page")&& strncmp(cmd, "scrub_safe", 10) != 0) //my_
	
			goto usage;

	/* the following commands operate on the current device */
	if (nand_curr_device < 0 || nand_curr_device >= (CONFIG_SYS_MAX_NAND_DEVICE+2)) {
		puts("\nno devices available\n");
		return 1;
	}

	nand = nand_info[nand_curr_device];
	if (!nand)
		return -1;

	if (strcmp(cmd, "bad") == 0) {
		printf("\nDevice %d bad blocks:\n", nand_curr_device);
		for (off = 0; off < nand->size; off += nand->erasesize)
			if (nand_block_isbad(nand, off))
				printf("  %09llx\n", off);
		return 0;
	}

	/*
	 * Syntax is:
	 *   0    1     2       3    4
	 *   nand erase [clean] [off size]
	 */
	if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0 || strcmp(cmd, "scrub_safe") == 0) { 
		nand_erase_options_t opts;
		int argc_cnt = 2;
        //printk("%s\n", argv[2]);
        /*
		if (isstring(argv[2])) {
			nand = get_mtd_device_nm(argv[2]);
			if (IS_ERR(nand)){
                printf("get nand device err\n");
				return 1;
			}
			argc_cnt++;
		}
		*/
		/* "clean" at index 2 means request to write cleanmarker */
		int clean = argc > argc_cnt && !strcmp("clean", argv[argc_cnt]);
		if (clean) 
			argc_cnt++;
		int o = argc_cnt;

		int scrub = !strncmp(cmd, "scrub",10);
		int scrub_safe =  !strncmp(cmd, "scrub_safe",10);
		
		if(scrub_safe)			
			printf("\nNAND %s: ", scrub_safe ? "scrub_safe" : "erase"); 
		else
			printf("\nNAND %s: ", scrub ? "scrub" : "erase");
		
		if (argv[argc_cnt])
		{
			if(!strcmp(argv[argc_cnt], "whole"))
			{
				off = 0;
				size = nand->size;
				printf("whole chip.\n");
			}
		}
		else
		{
			/* skip first two or three arguments, look for offset and size */
			if ((strcmp(cmd, "erase") == 0) && (argc < 3))
			{
				goto usage;
			}
                    if ((arg_off_size(argc - o, argv + o, nand, &off, &size) != 0))
                    {
                        return  1;
                    }
		}

		memset(&opts, 0, sizeof(opts));
		opts.offset = off;
		opts.length = size;
		opts.jffs2  = clean;
		opts.quiet  = quiet;

		if (scrub) {
			puts("Warning: "
			     "scrub option will erase all factory set "
			     "bad blocks!\n"
			     "         "
			     "There is no reliable way to recover them.\n"
			     "         "
			     "Use this command only for testing purposes "
			     "if you\n"
			     "         "
			     "are sure of what you are doing!\n"
			     "\nReally scrub this NAND flash? <y/N>\n");
			if(nand_protect)
			{
				if (getc() == 'y') {
					puts("y");
					if (getc() == '\r')
						opts.scrub = 1;
					else {
						puts("scrub aborted\n");
						return -1;
					}
				} else {
					puts("scrub aborted\n");
					return -1;
				}
			}
			else
			{
				opts.scrub = 1;
			}
		}
		else if(scrub_safe){
			puts("Warning: "
			     "scrub_safe option will erase all "
			     "bad blocks except factory bad blocks!\n");
			opts.scrub = 2; 	// indicate scrub_safe
		}
		ret = nand_erase_opts(nand, &opts);
		printf("%s\n", ret ? "ERROR" : "OK");
	#ifdef CONFIG_AML_NAND_KEY
		aml_chip->key_protect = 0;		//protect nand key can not be erased 
	#endif
	#ifdef CONFIG_SECURE_NAND
		aml_chip->secure_protect = 0;		//protect nand secure can not be erased 
	#endif

		return ret == 0 ? 0 : 1;
	}

	if (strncmp(cmd, "dump", 4) == 0) {
		if (argc < 3)
			goto usage;

		s = strchr(cmd, '.');
		//off = (loff_t)simple_strtoul(argv[2], NULL, 16);
		if (!(str2longlong(argv[2], (unsigned long long*)(&off))))
			return -1;

		if (s != NULL && strcmp(s, ".oob") == 0)
			ret = nand_dump(nand, off, 1);
		else
			ret = nand_dump(nand, off, 0);

		return ret == 0 ? 1 : 0;

	}

	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
		int read;

		if (argc < 4)
			goto usage;

		if (isstring(argv[2])) {
			nand = get_mtd_device_nm(argv[2]);
			if (IS_ERR(nand))
				goto usage;
			addr = (ulong)simple_strtoul(argv[3], NULL, 16);
			read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
			printf("\nNAND %s: %s ", read ? "read" : "write", argv[2]);
			if (argc == 4) {
				extern unsigned int get_mtd_size(char *name);
				off = 0;
				size = get_mtd_size(argv[2]);
			} else {
				if (arg_off_size(argc - 4, argv + 4, nand, &off, &size) != 0)
					return 1;
			}
		}
		else {
			addr = (ulong)simple_strtoul(argv[2], NULL, 16);
			read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
			printf("\nNAND %s: ", read ? "read" : "write");
			if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
				return 1;
		}

#ifdef CONFIG_AMLROM_NANDBOOT
	if((read==0) && ((off)<(1024* nand->writesize)) && (nand_curr_device == 0)){
		printf("offset 0x%llx in aml-boot area ,abort\n", off);
		return -1;
	}	
#endif


		s = strchr(cmd, '.');
		if (!s || !strcmp(s, ".jffs2") ||
		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
			if (read)
				ret = nand_read_skip_bad(nand, off, &size,
							 (u_char *)addr, 0);
			else
				ret = nand_write_skip_bad(nand, off, &size,
							  (u_char *)addr, 0);
		} else if (!strcmp(s, ".oob")) {
			/* out-of-band data */
			mtd_oob_ops_t ops = {
				.oobbuf = (u8 *)addr,
				.ooblen = size,
				.mode = MTD_OOB_RAW
			};

			if (read)
				ret = nand->read_oob(nand, off, &ops);
			else
				ret = nand->write_oob(nand, off, &ops);
		} else if (!strcmp(s, ".raw")) {
Esempio n. 20
0
static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
			int read)
{
	int ret = 0;

	while (count--) {
		/* Raw access */
		mtd_oob_ops_t ops = {
			.datbuf = (u8 *)addr,
			.oobbuf = ((u8 *)addr) + nand->writesize,
			.len = nand->writesize,
			.ooblen = nand->oobsize,
			.mode = MTD_OOB_RAW
		};

		if (read)
			ret = nand->read_oob(nand, off, &ops);
		else
			ret = nand->write_oob(nand, off, &ops);

		if (ret) {
			printf("%s: error at offset %llx, ret %d\n",
				__func__, (long long)off, ret);
			break;
		}

		addr += nand->writesize + nand->oobsize;
		off += nand->writesize;
	}

	return ret;
}

int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	int i, ret = 0;
	ulong addr;
	loff_t off, size, maxsize;
	char *cmd, *s;
	nand_info_t *nand;
#ifdef CONFIG_SYS_NAND_QUIET
	int quiet = CONFIG_SYS_NAND_QUIET;
#else
	int quiet = 0;
#endif
	const char *quiet_str = getenv("quiet");
	int dev = nand_curr_device;
	int repeat = flag & CMD_FLAG_REPEAT;

	/* at least two arguments please */
	if (argc < 2)
		goto usage;

	if (quiet_str)
		quiet = simple_strtoul(quiet_str, NULL, 0) != 0;

	cmd = argv[1];

	/* Only "dump" is repeatable. */
	if (repeat && strcmp(cmd, "dump"))
		return 0;

	if (strcmp(cmd, "info") == 0) {

		putc('\n');
		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
			if (nand_info[i].name)
				nand_print_and_set_info(i);
		}
		return 0;
	}

	if (strcmp(cmd, "device") == 0) {
		if (argc < 3) {
			putc('\n');
			if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
				puts("no devices available\n");
			else
				nand_print_and_set_info(dev);
			return 0;
		}

		dev = (int)simple_strtoul(argv[2], NULL, 10);
		set_dev(dev);

		return 0;
	}

#ifdef CONFIG_ENV_OFFSET_OOB
	/* this command operates only on the first nand device */
	if (strcmp(cmd, "env.oob") == 0)
		return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
#endif

	/* The following commands operate on the current device, unless
	 * overridden by a partition specifier.  Note that if somehow the
	 * current device is invalid, it will have to be changed to a valid
	 * one before these commands can run, even if a partition specifier
	 * for another device is to be used.
	 */
	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
	    !nand_info[dev].name) {
		puts("\nno devices available\n");
		return 1;
	}
	nand = &nand_info[dev];

	if (strcmp(cmd, "bad") == 0) {
		printf("\nDevice %d bad blocks:\n", dev);
		for (off = 0; off < nand->size; off += nand->erasesize)
			if (nand_block_isbad(nand, off))
				printf("  %08llx\n", (unsigned long long)off);
		return 0;
	}

	/*
	 * Syntax is:
	 *   0    1     2       3    4
	 *   nand erase [clean] [off size]
	 */
	if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
		nand_erase_options_t opts;
		/* "clean" at index 2 means request to write cleanmarker */
		int clean = argc > 2 && !strcmp("clean", argv[2]);
		int scrub_yes = argc > 2 && !strcmp("-y", argv[2]);
		int o = (clean || scrub_yes) ? 3 : 2;
		int scrub = !strncmp(cmd, "scrub", 5);
		int spread = 0;
		int args = 2;
		const char *scrub_warn =
			"Warning: "
			"scrub option will erase all factory set bad blocks!\n"
			"         "
			"There is no reliable way to recover them.\n"
			"         "
			"Use this command only for testing purposes if you\n"
			"         "
			"are sure of what you are doing!\n"
			"\nReally scrub this NAND flash? <y/N>\n";

		if (cmd[5] != 0) {
			if (!strcmp(&cmd[5], ".spread")) {
				spread = 1;
			} else if (!strcmp(&cmd[5], ".part")) {
				args = 1;
			} else if (!strcmp(&cmd[5], ".chip")) {
				args = 0;
			} else {
				goto usage;
			}
		}

		/*
		 * Don't allow missing arguments to cause full chip/partition
		 * erases -- easy to do accidentally, e.g. with a misspelled
		 * variable name.
		 */
		if (argc != o + args)
			goto usage;

		printf("\nNAND %s: ", cmd);
		/* skip first two or three arguments, look for offset and size */
		if (arg_off_size(argc - o, argv + o, &dev, &off, &size,
					&maxsize) != 0)
			return 1;

		nand = &nand_info[dev];

		memset(&opts, 0, sizeof(opts));
		opts.offset = off;
		opts.length = size;
		opts.jffs2  = clean;
		opts.quiet  = quiet;
		opts.spread = spread;

		if (scrub) {
			if (!scrub_yes)
				puts(scrub_warn);

			if (scrub_yes)
				opts.scrub = 1;
			else if (getc() == 'y') {
				puts("y");
				if (getc() == '\r')
					opts.scrub = 1;
				else {
					puts("scrub aborted\n");
					return -1;
				}
			} else {
				puts("scrub aborted\n");
				return -1;
			}
		}
		ret = nand_erase_opts(nand, &opts);
		printf("%s\n", ret ? "ERROR" : "OK");

		return ret == 0 ? 0 : 1;
	}

	if (strncmp(cmd, "dump", 4) == 0) {
		if (argc < 3)
			goto usage;

		off = (int)simple_strtoul(argv[2], NULL, 16);
		ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);

		return ret == 0 ? 1 : 0;
	}

	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
		size_t rwsize;
		ulong pagecount = 1;
		int read;
		int raw;

		if (argc < 4)
			goto usage;

		addr = (ulong)simple_strtoul(argv[2], NULL, 16);

		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
		printf("\nNAND %s: ", read ? "read" : "write");

		nand = &nand_info[dev];

		s = strchr(cmd, '.');

		if (s && !strcmp(s, ".raw")) {
			raw = 1;

			if (arg_off(argv[3], &dev, &off, &size, &maxsize))
				return 1;

			if (argc > 4 && !str2long(argv[4], &pagecount)) {
				printf("'%s' is not a number\n", argv[4]);
				return 1;
			}

			if (pagecount * nand->writesize > size) {
				puts("Size exceeds partition or device limit\n");
				return -1;
			}

			rwsize = pagecount * (nand->writesize + nand->oobsize);
		} else {
			if (arg_off_size(argc - 3, argv + 3, &dev,
						&off, &size, &maxsize) != 0)
				return 1;

			rwsize = size;
		}

		if (!s || !strcmp(s, ".jffs2") ||
		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
			if (read)
				ret = nand_read_skip_bad(nand, off, &rwsize,
							 NULL, maxsize,
							 (u_char *)addr);
			else
				ret = nand_write_skip_bad(nand, off, &rwsize,
							  NULL, maxsize,
							  (u_char *)addr, 0);
#ifdef CONFIG_CMD_NAND_TRIMFFS
		} else if (!strcmp(s, ".trimffs")) {
			if (read) {
				printf("Unknown nand command suffix '%s'\n", s);
				return 1;
			}
			ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
						maxsize, (u_char *)addr,
						WITH_DROP_FFS);
#endif
#ifdef CONFIG_CMD_NAND_YAFFS
		} else if (!strcmp(s, ".yaffs")) {
			if (read) {
				printf("Unknown nand command suffix '%s'.\n", s);
				return 1;
			}
			ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
						maxsize, (u_char *)addr,
						WITH_YAFFS_OOB);
#endif
		} else if (!strcmp(s, ".oob")) {
			/* out-of-band data */
			mtd_oob_ops_t ops = {
				.oobbuf = (u8 *)addr,
				.ooblen = rwsize,
				.mode = MTD_OOB_RAW
			};

			if (read)
				ret = nand->read_oob(nand, off, &ops);
			else
				ret = nand->write_oob(nand, off, &ops);
		} else if (raw) {
Esempio n. 21
0
static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,
			u64 offset, void *buf, long *len)
{
	loff_t start, lim;
	size_t count, actual;
	int ret;
	nand_info_t *nand;

	/* if buf == NULL return total size of the area */
	if (buf == NULL) {
		*len = dfu->data.nand.size;
		return 0;
	}

	start = dfu->data.nand.start + offset + dfu->bad_skip;
	lim = dfu->data.nand.start + dfu->data.nand.size - start;
	count = *len;

	if (nand_curr_device < 0 ||
	    nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
	    !nand_info[nand_curr_device].name) {
		printf("%s: invalid nand device\n", __func__);
		return -1;
	}

	nand = &nand_info[nand_curr_device];

	if (op == DFU_OP_READ) {
		ret = nand_read_skip_bad(nand, start, &count, &actual,
				lim, buf);
	} else {
		nand_erase_options_t opts;

		memset(&opts, 0, sizeof(opts));
		opts.offset = start;
		opts.length = count;
		opts.spread = 1;
		opts.quiet = 1;
		opts.lim = lim;
		/* first erase */
		ret = nand_erase_opts(nand, &opts);
		if (ret)
			return ret;
		/* then write */
		ret = nand_write_skip_bad(nand, start, &count, &actual,
				lim, buf, 0);
	}

	if (ret != 0) {
		printf("%s: nand_%s_skip_bad call failed at %llx!\n",
		       __func__, op == DFU_OP_READ ? "read" : "write",
		       start);
		return ret;
	}

	/*
	 * Find out where we stopped writing data.  This can be deeper into
	 * the NAND than we expected due to having to skip bad blocks.  So
	 * we must take this into account for the next write, if any.
	 */
	if (actual > count)
		dfu->bad_skip += actual - count;

	return ret;
}
Esempio n. 22
0
/* Write u-boot image into the nand flash */
int nand_burn_uboot_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	int filesize;
	MV_U32 ret = 0;
	extern char console_buffer[];
	nand_info_t *nand = &nand_info[0];
	nand_erase_options_t er_opts;
	nand_write_options_t wr_opts;

	load_addr = CFG_LOAD_ADDR; 
	if(argc == 2) {
		copy_filename (BootFile, argv[1], sizeof(BootFile));
	}
	else { 
		copy_filename (BootFile, "u-boot.bin", sizeof(BootFile));
		printf("using default file \"u-boot.bin\" \n");
	}
 
	if ((filesize = NetLoop(TFTP)) < 0)
		return 0;

	printf("\n**Warning**\n");
	printf("If U-Boot Endiannes is going to change (LE->BE or BE->LE), Then Env parameters should be overriden..\n");
	printf("Override Env parameters? (y/n)");
	readline(" ");
	if( strcmp(console_buffer,"Y") == 0 || 
	    strcmp(console_buffer,"yes") == 0 ||
	    strcmp(console_buffer,"y") == 0 ) {

		printf("Erase Env parameters sector %d... ",CFG_ENV_OFFSET);
		memset(&er_opts, 0, sizeof(er_opts));
		er_opts.offset = CFG_ENV_OFFSET;
		er_opts.length = CFG_ENV_SECT_SIZE;
		er_opts.quiet  = 1;

		nand_erase_opts(nand, &er_opts);
		//nand_erase(nand_dev_desc + 0, CFG_ENV_OFFSET, CFG_ENV_SECT_SIZE, 0);
		printf("\n");
	}

	printf("Erase %d - %d ... ",CFG_MONITOR_BASE, CFG_MONITOR_LEN);
	memset(&er_opts, 0, sizeof(er_opts));
	er_opts.offset = CFG_MONITOR_BASE;
	er_opts.length = CFG_MONITOR_LEN;
	er_opts.quiet  = 1;
	nand_erase_opts(nand, &er_opts);
	//nand_erase(nand_dev_desc + 0, CFG_MONITOR_BASE, CFG_MONITOR_LEN, 0);
	
	printf("\nCopy to Nand Flash... ");
	memset(&wr_opts, 0, sizeof(wr_opts));
	wr_opts.buffer	= (u_char*) load_addr;
	wr_opts.length	= CFG_MONITOR_LEN;
	wr_opts.offset	= CFG_MONITOR_BASE;
	/* opts.forcejffs2 = 1; */
	wr_opts.pad	= 1;
	wr_opts.blockalign = 1;
	wr_opts.quiet      = 1;
	ret = nand_write_opts(nand, &wr_opts);
	/* ret = nand_rw(nand_dev_desc + 0,
				  NANDRW_WRITE | NANDRW_JFFS2, CFG_MONITOR_BASE, CFG_MONITOR_LEN,
			      &total, (u_char*)0x100000 + CFG_MONITOR_IMAGE_OFFSET);
	*/
  	if (ret)
		printf("Error - NAND burn faild!\n");
	else
		printf("\ndone\n");	

	return 1;
}
Esempio n. 23
0
static int nand_biterr(nand_info_t *nand, loff_t addr, int bit)
{
	nand_erase_options_t opts;
	struct mtd_oob_ops ops;
	uint8_t *datbuf, *pagebuf, *write_buf;
	size_t size;
	loff_t write_addr;
	int ret, pages;

	datbuf = malloc(nand->erasesize);
	if (!datbuf) {
		printf("biterr: out of memory\n");
		return 1;
	}
	pagebuf = malloc(nand->writesize + nand->oobsize);
	if (!pagebuf) {
		printf("biterr: out of memory\n");
		free(datbuf);
		return 1;
	}

	/* first read the whole erase block */
	size = nand->erasesize;
	ret = nand_read(nand, addr & ~(nand->erasesize - 1), &size, datbuf);
	if (ret < 0 && ret != -EUCLEAN) {
		printf("biterr: nand_read failed\n");
		goto err;
	}

	nand_use_ecc(nand, 0);

	/* read the affected page with oob */
	memset(&ops, 0, sizeof(ops));
	ops.datbuf = pagebuf;
	ops.oobbuf = pagebuf + nand->writesize;
	ops.len = nand->writesize;
	ops.ooblen = nand->oobsize;
	ops.mode = MTD_OOB_RAW;
	ret = nand->read_oob(nand, addr & ~(nand->writesize - 1), &ops);
	if (ret < 0) {
		printf("biterr: read_oob failed\n");
		nand_use_ecc(nand, 1);
		goto err;
	}

	/* flip the bit(s) */
	pagebuf[(addr & (nand->writesize - 1)) + (bit & ~7)] ^= 1 << (bit & 7);

	/* erase */
	memset(&opts, 0, sizeof(opts));
	opts.quiet  = 1;
	opts.offset = addr & ~(nand->erasesize - 1);
	opts.length = nand->erasesize;
	ret = nand_erase_opts(nand, &opts);
	if (ret < 0) {
		printf("biterr: erase failed\n");
		nand_use_ecc(nand, 1);
		goto err;
	}

	/* write the affected page back with oob in raw mode */
	memset(&ops, 0, sizeof(ops));
	ops.datbuf = pagebuf;
	ops.oobbuf = pagebuf + nand->writesize;
	ops.len = nand->writesize;
	ops.ooblen = nand->oobsize;
	ops.mode = MTD_OOB_RAW;
	ret = nand->write_oob(nand, addr & ~(nand->writesize - 1), &ops);
	if (ret < 0) {
		printf("biterr: write_oob failed\n");
		nand_use_ecc(nand, 1);
		goto err;
	}

	nand_use_ecc(nand, 1);

	/* write back the other pages as normal */
	write_addr = addr & ~(nand->erasesize - 1);
	write_buf = datbuf;
	for (pages = nand->erasesize / nand->writesize;
	     pages > 0;
	     pages--, write_addr += nand->writesize, write_buf += nand->writesize) {
		/* skip the block that was written back raw */
		if (write_addr == (addr & ~(nand->writesize - 1)))
			continue;

		size = nand->writesize;
		ret = nand_write(nand, write_addr, &size, write_buf);
		if (ret < 0)
			printf("biterr: error writing back page 0x%llx\n", write_addr);
	}

	free(datbuf);
	free(pagebuf);
	return 0;

err:
	free(datbuf);
	free(pagebuf);
	return 1;
}