|
@@ -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)
|