[U-Boot] [PATCH 1/6] Convert fw_env.c to use a single environment image union
Guennadi Liakhovetski
lg at denx.de
Wed Aug 27 17:52:36 CEST 2008
Use a union to cover both with and without redundant environment cases.
Signed-off-by: Guennadi Liakhovetski <lg at denx.de>
---
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
More information about the U-Boot
mailing list