Use a union to cover both with and without redundant environment cases. Signed-off-by: Guennadi Liakhovetski <[EMAIL PROTECTED]> --- tools/env/fw_env.c | 148 +++++++++++++++++++++++++++++----------------------- 1 files changed, 82 insertions(+), 66 deletions(-)
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index b8bca91..35783c5 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -63,16 +63,30 @@ static int curdev; #define ENV_SIZE getenvsize() -typedef struct environment_s { - ulong crc; /* CRC32 over data bytes */ - unsigned char flags; /* active or obsolete */ - char *data; -} env_t; +/* This union will occupy exactly CFG_ENV_SIZE bytes. */ +union env_image { + struct { + uint32_t crc; /* CRC32 over data bytes */ + char data[]; + } single; + struct { + uint32_t crc; /* CRC32 over data bytes */ + unsigned char flags; /* active or obsolete */ + char data[]; + } redund; +}; + +struct environment { + union env_image *image; + char *data; /* shortcut to data */ +}; -static env_t environment; +static struct environment environment; static int HaveRedundEnv = 0; +#define ENV_FLAGS(e) e.image->redund.flags + static unsigned char active_flag = 1; static unsigned char obsolete_flag = 0; @@ -156,7 +170,7 @@ static char default_environment[] = { #ifdef CONFIG_EXTRA_ENV_SETTINGS CONFIG_EXTRA_ENV_SETTINGS #endif - "\0" /* Termimate env_t data with 2 NULs */ + "\0" /* Termimate struct environment data with 2 NULs */ }; static int flash_io (int mode); @@ -382,8 +396,12 @@ int fw_setenv (int argc, char *argv[]) WRITE_FLASH: - /* Update CRC */ - environment.crc = crc32 (0, (uint8_t*) environment.data, ENV_SIZE); + /* + * Update CRC: it is at the same location with and without the + * redundant environment + */ + environment.image->single.crc = crc32 (0, (uint8_t *) environment.data, + ENV_SIZE); /* write environment back to flash */ if (flash_io (O_RDWR)) { @@ -396,7 +414,7 @@ int fw_setenv (int argc, char *argv[]) static int flash_io (int mode) { - int fd, fdr, rc, otherdev, len, resid; + int fd, fdr, rc, otherdev, resid; erase_info_t erase; char *data = NULL; @@ -407,11 +425,6 @@ static int flash_io (int mode) return (-1); } - len = sizeof (environment.crc); - if (HaveRedundEnv) { - len += sizeof (environment.flags); - } - if (mode == O_RDWR) { if (HaveRedundEnv) { /* switch to next partition for writing */ @@ -436,7 +449,7 @@ static int flash_io (int mode) erase.length = DEVESIZE (curdev); erase.start = DEVOFFSET (curdev); ioctl (fd, MEMUNLOCK, &erase); - environment.flags = active_flag; + ENV_FLAGS(environment) = active_flag; } printf ("Done\n"); @@ -485,18 +498,15 @@ static int flash_io (int mode) DEVNAME (otherdev), strerror (errno)); return (-1); } - if (write (fdr, &environment, len) != len) { - fprintf (stderr, - "CRC write error on %s: %s\n", - DEVNAME (otherdev), strerror (errno)); - return (-1); - } - if (write (fdr, environment.data, ENV_SIZE) != ENV_SIZE) { + + if (write (fdr, environment.image, CFG_ENV_SIZE) != + CFG_ENV_SIZE) { fprintf (stderr, "Write error on %s: %s\n", DEVNAME (otherdev), strerror (errno)); return (-1); } + if (resid) { if (write (fdr, data, resid) != resid) { fprintf (stderr, @@ -548,13 +558,8 @@ static int flash_io (int mode) DEVNAME (curdev), strerror (errno)); return (-1); } - if (read (fd, &environment, len) != len) { - fprintf (stderr, - "CRC read error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); - } - if ((rc = read (fd, environment.data, ENV_SIZE)) != ENV_SIZE) { + if (read (fd, environment.image, CFG_ENV_SIZE) != + CFG_ENV_SIZE) { fprintf (stderr, "Read error on %s: %s\n", DEVNAME (curdev), strerror (errno)); @@ -604,22 +609,24 @@ static int env_init (void) if (parse_config ()) /* should fill envdevices */ return 1; - if ((addr1 = calloc (1, ENV_SIZE)) == NULL) { + if ((addr1 = calloc (1, CFG_ENV_SIZE)) == NULL) { fprintf (stderr, "Not enough memory for environment (%ld bytes)\n", - ENV_SIZE); + CFG_ENV_SIZE); return (errno); } /* read environment from FLASH to local buffer */ - environment.data = addr1; + environment.image = (union env_image *)addr1; + environment.data = HaveRedundEnv ? environment.image->redund.data : + environment.image->single.data; curdev = 0; if (flash_io (O_RDONLY)) { return (errno); } - crc1_ok = ((crc1 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE)) - == environment.crc); + crc1 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE); + crc1_ok = (crc1 == environment.image->single.crc); if (!HaveRedundEnv) { if (!crc1_ok) { fprintf (stderr, @@ -627,74 +634,83 @@ static int env_init (void) memcpy(environment.data, default_environment, sizeof default_environment); } } else { - flag1 = environment.flags; + flag1 = ENV_FLAGS(environment); curdev = 1; - if ((addr2 = calloc (1, ENV_SIZE)) == NULL) { + if ((addr2 = calloc (1, CFG_ENV_SIZE)) == NULL) { fprintf (stderr, "Not enough memory for environment (%ld bytes)\n", - ENV_SIZE); + CFG_ENV_SIZE); return (errno); } - environment.data = addr2; + environment.image = (union env_image *)addr2; if (flash_io (O_RDONLY)) { return (errno); } - crc2_ok = ((crc2 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE)) - == environment.crc); - flag2 = environment.flags; + crc2 = crc32 (0, (uint8_t *) environment.image->redund.data, + ENV_SIZE); + crc2_ok = (crc2 == environment.image->redund.crc); + flag2 = ENV_FLAGS(environment); if (crc1_ok && !crc2_ok) { - environment.data = addr1; - environment.flags = flag1; - environment.crc = crc1; + environment.image = (union env_image *)addr1; + ENV_FLAGS(environment) = flag1; + environment.image->redund.crc = crc1; curdev = 0; free (addr2); } else if (!crc1_ok && crc2_ok) { - environment.data = addr2; - environment.flags = flag2; - environment.crc = crc2; + environment.image = (union env_image *)addr2; + ENV_FLAGS(environment) = flag2; + environment.image->redund.crc = crc2; curdev = 1; free (addr1); } else if (!crc1_ok && !crc2_ok) { fprintf (stderr, "Warning: Bad CRC, using default environment\n"); - memcpy(environment.data, default_environment, sizeof default_environment); + memcpy(environment.image->redund.data, + default_environment, sizeof default_environment); curdev = 0; free (addr1); + /* From here: both CRCs correct */ } else if (flag1 == active_flag && flag2 == obsolete_flag) { - environment.data = addr1; - environment.flags = flag1; - environment.crc = crc1; + environment.image = (union env_image *)addr1; + ENV_FLAGS(environment) = flag1; + environment.image->redund.crc = crc1; curdev = 0; free (addr2); } else if (flag1 == obsolete_flag && flag2 == active_flag) { - environment.data = addr2; - environment.flags = flag2; - environment.crc = crc2; + environment.image = (union env_image *)addr2; + ENV_FLAGS(environment) = flag2; + environment.image->redund.crc = crc2; curdev = 1; free (addr1); + /* From here: invalid flag configuration */ } else if (flag1 == flag2) { - environment.data = addr1; - environment.flags = flag1; - environment.crc = crc1; + environment.image = (union env_image *)addr1; + ENV_FLAGS(environment) = flag1; + environment.image->redund.crc = crc1; curdev = 0; free (addr2); - } else if (flag1 == 0xFF) { - environment.data = addr1; - environment.flags = flag1; - environment.crc = crc1; + } else if (flag1 == obsolete_flag || flag1 == active_flag) { + /* flag1 valid, update flag2 */ + environment.image = (union env_image *)addr1; + ENV_FLAGS(environment) = flag1; + environment.image->redund.crc = crc1; curdev = 0; free (addr2); - } else if (flag2 == 0xFF) { - environment.data = addr2; - environment.flags = flag2; - environment.crc = crc2; + } else { + if (flag2 != obsolete_flag && flag2 != active_flag) + fprintf (stderr, "Both CRCs valid, but both " + "flags invalid, will use the 1st\n"); + environment.image = (union env_image *)addr2; + ENV_FLAGS(environment) = flag2; + environment.image->redund.crc = crc2; curdev = 1; free (addr1); } + environment.data = environment.image->redund.data; } return (0); } -- 1.5.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot