binman: Rename the main module
[oweals/u-boot.git] / tools / env / fw_env.c
index 95c99847a3af2647aef191deea2361293625a6fd..381739d28df20edf7422861bdc946cd2982d2e3f 100644 (file)
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <u-boot/crc.h>
 #include <unistd.h>
 #include <dirent.h>
 
@@ -111,6 +112,7 @@ struct environment {
        unsigned char *flags;
        char *data;
        enum flag_scheme flag_scheme;
+       int dirty;
 };
 
 static struct environment environment = {
@@ -119,13 +121,6 @@ static struct environment environment = {
 
 static int have_redund_env;
 
-static unsigned char ENV_REDUND_ACTIVE = 1;
-/*
- * ENV_REDUND_OBSOLETE must be 0 to efficiently set it on NOR flash without
- * erasing
- */
-static unsigned char ENV_REDUND_OBSOLETE;
-
 #define DEFAULT_ENV_INSTANCE_STATIC
 #include <env_default.h>
 
@@ -512,6 +507,9 @@ int fw_env_flush(struct env_opts *opts)
        if (!opts)
                opts = &default_opts;
 
+       if (!environment.dirty)
+               return 0;
+
        /*
         * Update CRC
         */
@@ -557,7 +555,8 @@ int fw_env_write(char *name, char *value)
 
        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) {
@@ -597,6 +596,7 @@ int fw_env_write(char *name, char *value)
                /* Nothing to do */
                return 0;
 
+       environment.dirty = 1;
        if (deleting || overwriting) {
                if (*++nxt == '\0') {
                        *env = '\0';
@@ -1142,6 +1142,7 @@ static int flash_flag_obsolete(int dev, int fd, off_t offset)
 {
        int rc;
        struct erase_info_user erase;
+       char tmp = ENV_REDUND_OBSOLETE;
 
        erase.start = DEVOFFSET(dev);
        erase.length = DEVESIZE(dev);
@@ -1153,7 +1154,7 @@ static int flash_flag_obsolete(int dev, int fd, off_t offset)
                return rc;
        }
        ioctl(fd, MEMUNLOCK, &erase);
-       rc = write(fd, &ENV_REDUND_OBSOLETE, sizeof(ENV_REDUND_OBSOLETE));
+       rc = write(fd, &tmp, sizeof(tmp));
        ioctl(fd, MEMLOCK, &erase);
        if (rc < 0)
                perror("Could not set obsolete flag");
@@ -1445,6 +1446,7 @@ int fw_env_open(struct env_opts *opts)
                                "Warning: Bad CRC, using default environment\n");
                        memcpy(environment.data, default_environment,
                               sizeof(default_environment));
+                       environment.dirty = 1;
                }
        } else {
                flag0 = *environment.flags;
@@ -1498,6 +1500,16 @@ int fw_env_open(struct env_opts *opts)
                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) {
@@ -1507,6 +1519,7 @@ int fw_env_open(struct env_opts *opts)
                                "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) {