diff options
Diffstat (limited to 'common/env_nand.c')
| -rw-r--r-- | common/env_nand.c | 116 | 
1 files changed, 54 insertions, 62 deletions
| diff --git a/common/env_nand.c b/common/env_nand.c index 9a6b8a6fb..75309621b 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -152,72 +152,57 @@ int writeenv(size_t offset, u_char *buf)  	return 0;  } -#ifdef CONFIG_ENV_OFFSET_REDUND -static unsigned char env_flags; +struct env_location { +	const char *name; +	const nand_erase_options_t erase_opts; +}; -int saveenv(void) +static int erase_and_write_env(const struct env_location *location, +		u_char *env_new)  { -	env_t	env_new; -	ssize_t	len; -	char	*res; -	int	ret = 0; -	nand_erase_options_t nand_erase_options; +	int ret = 0; -	memset(&nand_erase_options, 0, sizeof(nand_erase_options)); -	nand_erase_options.length = CONFIG_ENV_RANGE; - -	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"); +	printf("Erasing %s...\n", location->name); +	if (nand_erase_opts(&nand_info[0], &location->erase_opts))  		return 1; -	} - -	puts("done\n"); -	gd->env_valid = gd->env_valid == 2 ? 1 : 2; +	printf("Writing to %s... ", location->name); +	ret = writeenv(location->erase_opts.offset, env_new); +	puts(ret ? "FAILED!\n" : "OK\n");  	return ret;  } -#else /* ! CONFIG_ENV_OFFSET_REDUND */ + +#ifdef CONFIG_ENV_OFFSET_REDUND +static unsigned char env_flags; +#endif +  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; +	int	env_idx = 0; +	static const struct env_location location[] = { +		{ +			.name = "NAND", +			.erase_opts = { +				.length = CONFIG_ENV_RANGE, +				.offset = CONFIG_ENV_OFFSET, +			}, +		}, +#ifdef CONFIG_ENV_OFFSET_REDUND +		{ +			.name = "redundant NAND", +			.erase_opts = { +				.length = CONFIG_ENV_RANGE, +				.offset = CONFIG_ENV_OFFSET_REDUND, +			}, +		}, +#endif +	}; -	memset(&nand_erase_options, 0, sizeof(nand_erase_options)); -	nand_erase_options.length = CONFIG_ENV_RANGE; -	nand_erase_options.offset = CONFIG_ENV_OFFSET;  	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)  		return 1; @@ -228,22 +213,29 @@ int saveenv(void)  		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; +	env_new->crc   = crc32(0, env_new->data, ENV_SIZE); +#ifdef CONFIG_ENV_OFFSET_REDUND +	env_new->flags = ++env_flags; /* increase the serial */ +	env_idx = (gd->env_valid == 1); +#endif -	puts("Writing to Nand... "); -	if (writeenv(CONFIG_ENV_OFFSET, (u_char *)env_new)) { -		puts("FAILED!\n"); -		return 1; +	ret = erase_and_write_env(&location[env_idx], (u_char *)env_new); +#ifdef CONFIG_ENV_OFFSET_REDUND +	if (!ret) { +		/* preset other copy for next write */ +		gd->env_valid = gd->env_valid == 2 ? 1 : 2; +		return ret;  	} -	puts("done\n"); +	env_idx = (env_idx + 1) & 1; +	ret = erase_and_write_env(&location[env_idx], (u_char *)env_new); +	if (!ret) +		printf("Warning: primary env write failed," +				" redundancy is lost!\n"); +#endif +  	return ret;  } -#endif /* CONFIG_ENV_OFFSET_REDUND */  #endif /* CMD_SAVEENV */  int readenv(size_t offset, u_char *buf) |