[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