Skip to content
Snippets Groups Projects
Commit 2b26201a authored by Phil Sutter's avatar Phil Sutter Committed by Scott Wood
Browse files

env_nand.c: support falling back to redundant env when writing


Without this patch, when the currently chosen environment to be written
has bad blocks, saveenv fails completely. Instead, when there is
redundant environment fall back to the other copy. Environment reading
needs no adjustment, as the fallback logic for incomplete writes applies
to this case as well.

Signed-off-by: default avatarPhil Sutter <phil.sutter@viprinet.com>
parent 47b6dad3
No related branches found
No related tags found
No related merge requests found
......@@ -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)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment