#define _GNU_SOURCE
#include <compiler.h>
+#include <env.h>
#include <errno.h>
#include <env_flags.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
+#include <u-boot/crc.h>
#include <unistd.h>
#include <dirent.h>
unsigned char *flags;
char *data;
enum flag_scheme flag_scheme;
+ int dirty;
};
static struct environment environment = {
static int have_redund_env;
-static unsigned char active_flag = 1;
-/* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */
-static unsigned char obsolete_flag = 0;
-
#define DEFAULT_ENV_INSTANCE_STATIC
#include <env_default.h>
if (!opts)
opts = &default_opts;
+ if (!environment.dirty)
+ return 0;
+
/*
* Update CRC
*/
deleting = (oldval && !(value && strlen(value)));
creating = (!oldval && (value && strlen(value)));
- overwriting = (oldval && (value && strlen(value)));
+ overwriting = (oldval && (value && strlen(value) &&
+ strcmp(oldval, value)));
/* check for permission */
if (deleting) {
/* Nothing to do */
return 0;
+ environment.dirty = 1;
if (deleting || overwriting) {
if (*++nxt == '\0') {
*env = '\0';
{
int rc;
struct erase_info_user erase;
+ char tmp = ENV_REDUND_OBSOLETE;
erase.start = DEVOFFSET(dev);
erase.length = DEVESIZE(dev);
- /* This relies on the fact, that obsolete_flag == 0 */
+ /* This relies on the fact, that ENV_REDUND_OBSOLETE == 0 */
rc = lseek(fd, offset, SEEK_SET);
if (rc < 0) {
fprintf(stderr, "Cannot seek to set the flag on %s\n",
return rc;
}
ioctl(fd, MEMUNLOCK, &erase);
- rc = write(fd, &obsolete_flag, sizeof(obsolete_flag));
+ rc = write(fd, &tmp, sizeof(tmp));
ioctl(fd, MEMLOCK, &erase);
if (rc < 0)
perror("Could not set obsolete flag");
(*environment.flags)++;
break;
case FLAG_BOOLEAN:
- *environment.flags = active_flag;
+ *environment.flags = ENV_REDUND_ACTIVE;
break;
default:
fprintf(stderr, "Unimplemented flash scheme %u\n",
rc = -1;
}
- if (target_temp) {
+ if (rc >= 0 && target_temp) {
int dir_fd;
dir_fd = open(dname, O_DIRECTORY | O_RDONLY);
"Warning: Bad CRC, using default environment\n");
memcpy(environment.data, default_environment,
sizeof(default_environment));
+ environment.dirty = 1;
}
} else {
flag0 = *environment.flags;
crc1_ok = (crc1 == redundant->crc);
flag1 = redundant->flags;
+ /*
+ * environment.data still points to ((struct
+ * env_image_redundant *)addr0)->data. If the two
+ * environments differ, or one has bad crc, force a
+ * write-out by marking the environment dirty.
+ */
+ if (memcmp(environment.data, redundant->data, ENV_SIZE) ||
+ !crc0_ok || !crc1_ok)
+ environment.dirty = 1;
+
if (crc0_ok && !crc1_ok) {
dev_current = 0;
} else if (!crc0_ok && crc1_ok) {
"Warning: Bad CRC, using default environment\n");
memcpy(environment.data, default_environment,
sizeof(default_environment));
+ environment.dirty = 1;
dev_current = 0;
} else {
switch (environment.flag_scheme) {
case FLAG_BOOLEAN:
- if (flag0 == active_flag &&
- flag1 == obsolete_flag) {
+ if (flag0 == ENV_REDUND_ACTIVE &&
+ flag1 == ENV_REDUND_OBSOLETE) {
dev_current = 0;
- } else if (flag0 == obsolete_flag &&
- flag1 == active_flag) {
+ } else if (flag0 == ENV_REDUND_OBSOLETE &&
+ flag1 == ENV_REDUND_ACTIVE) {
dev_current = 1;
} else if (flag0 == flag1) {
dev_current = 0;
goto err;
}
DEVTYPE(dev) = mtdinfo.type;
+ if (DEVESIZE(dev) == 0 && ENVSECTORS(dev) == 0 &&
+ mtdinfo.type == MTD_NORFLASH)
+ DEVESIZE(dev) = mtdinfo.erasesize;
if (DEVESIZE(dev) == 0)
/* Assume the erase size is the same as the env-size */
DEVESIZE(dev) = ENVSIZE(dev);
if (ENVSIZE(0) != ENVSIZE(1)) {
fprintf(stderr,
- "Redundant environments have unequal size");
+ "Redundant environments have unequal size\n");
return -1;
}
}