[U-Boot] [PATCH] new tool mkenvimage: generates an env image from an arbitrary config file

David Wagner david.wagner at free-electrons.com
Tue Aug 9 12:31:29 CEST 2011


This tool takes a key=value configuration file (same as would a `printenv' show)
and generates the corresponding environnment image, ready to be flashed.

Signed-off-by: David Wagner <david.wagner at free-electrons.com>
---

	Hi Mike,

This 3rd version should address what you pointed out.

I had troubles testing it on my IGEP board: I couldn't compile from the official
git (I think it's because of my toolchain ... a more recent toolchain might be
able to compile but won't compile IGEP's uboot version ... weird stuff above my
head involved).  And the IGEP uboot seems broken wrt environnment in onenand:
when computing the CRC, it only takes the 4092 (4096 minus the header) bytes
of the environment into account ...

So, someone else should probably test it.

	David.

 tools/Makefile     |    5 ++
 tools/mkenvimage.c |  205 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 210 insertions(+), 0 deletions(-)
 create mode 100644 tools/mkenvimage.c

diff --git a/tools/Makefile b/tools/Makefile
index e813e1d..db8522f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -69,6 +69,7 @@ BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX)
 BIN_FILES-y += mkimage$(SFX)
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
+BIN_FILES-y += mkenvimage$(SFX)
 
 # Source files which exist outside the tools directory
 EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o
@@ -93,6 +94,7 @@ OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
 NOPED_OBJ_FILES-y += os_support.o
 OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
 NOPED_OBJ_FILES-y += ublimage.o
+NOPED_OBJ_FILES-y += mkenvimage.o
 
 # Don't build by default
 #ifeq ($(ARCH),ppc)
@@ -171,6 +173,9 @@ $(obj)bmp_logo$(SFX):	$(obj)bmp_logo.o
 $(obj)envcrc$(SFX):	$(obj)crc32.o $(obj)env_embedded.o $(obj)envcrc.o $(obj)sha1.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 
+$(obj)mkenvimage$(SFX):	$(obj)crc32.o $(obj)mkenvimage.o
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+
 $(obj)gen_eth_addr$(SFX):	$(obj)gen_eth_addr.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
diff --git a/tools/mkenvimage.c b/tools/mkenvimage.c
new file mode 100644
index 0000000..fe91bc4
--- /dev/null
+++ b/tools/mkenvimage.c
@@ -0,0 +1,205 @@
+/*
+ * (C) Copyright 2011 Free Electrons
+ * David Wagner <david.wagner at free-electrons.com>
+ * 
+ * Inspired from envcrc.c:
+ * (C) Copyright 2001
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio at tin.it
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <compiler.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+extern uint32_t crc32 (uint32_t, const unsigned char *, unsigned int);
+
+#define CRC_SIZE sizeof(uint32_t)
+
+static void usage(char *exec_name)
+{
+	printf("%s [-h] [-r] [-b] [-p <byte>] "
+	       "-s <envrionment partition size> -o <output> <input file>\n"
+	       "\n"
+	       "\tThe input file is in format:\n"
+	       "\t\tkey1=value1\n"
+	       "\t\tkey2=value2\n"
+	       "\t\t...\n"
+	       "\t-r : the environment has two copies in flash\n"
+	       "\t-b : the target is big endian (default is little endian)\n"
+	       "\t-p <byte> : fill the image with <byte> bytes instead of 0xff bytes\n",
+	       exec_name);
+}
+
+int main(int argc, char **argv)
+{
+	uint32_t crc, targetendian_crc;
+	char *txt_filename = NULL, *bin_filename = NULL;
+	FILE *txt_file, *bin_file;
+	unsigned char *dataptr, *envptr;
+	unsigned int envsize, datasize = 0;
+	int bigendian = 0;
+	int redundant = 0;
+	unsigned char padbyte = 0xff;
+
+	int option;
+	int ret = EXIT_SUCCESS;
+
+	struct stat txt_file_stat;
+
+	int i;
+
+
+	/* Parse the cmdline */
+	while ((option = getopt(argc, argv, "s:o:rbp:h")) != -1) {
+		switch (option) {
+		case 's':
+			datasize = strtol(optarg, NULL, 0);
+			break;
+		case 'o':
+			bin_filename = strdup(optarg);
+			if (!bin_filename) {
+				fprintf(stderr, "Can't strdup() the output filename\n");
+				return EXIT_FAILURE;
+			}
+			break;
+		case 'r':
+			redundant = 1;
+			break;
+		case 'b':
+			bigendian = 1;
+			break;
+		case 'p':
+			padbyte = strtol(optarg, NULL, 0);
+			break;
+		case 'h':
+			usage(argv[0]);
+			return EXIT_SUCCESS;
+		default:
+			fprintf(stderr, "Wrong option -%c\n", option);
+			usage(argv[0]);
+			return EXIT_FAILURE;
+		}
+	}
+
+
+	/* Check datasize and allocate the data */
+	if (datasize == 0) {
+		fprintf(stderr,
+			"Please specify the size of the envrionnment partition.\n");
+		usage(argv[0]);
+		return EXIT_FAILURE;
+	}
+
+	dataptr = calloc(datasize, sizeof(*dataptr));
+	if (!dataptr) {
+		fprintf(stderr, "Can't alloc dataptr.\n");
+		return EXIT_FAILURE;
+	}
+
+	/* envptr points to the beginning of the actual environment (after the
+	 * crc and possible `redundant' bit */
+	envsize = datasize - (CRC_SIZE + redundant);
+	envptr = dataptr + CRC_SIZE + redundant;
+
+	/* Pad the environnment with the padding byte */
+	memset(envptr, padbyte, envsize);
+
+	/* Open the configuration file ... */
+	txt_filename = argv[optind];
+	if (!txt_filename) {
+		fprintf(stderr, "Can't strdup() the configuration filename\n");
+		return EXIT_FAILURE;
+	}
+	txt_file = fopen(txt_filename, "rb");
+	if (!txt_file) {
+		fprintf(stderr, "Can't open configuration file: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+	/* ... and check it */
+	ret = fstat(fileno(txt_file), &txt_file_stat);
+	if (ret == -1) {
+		fprintf(stderr, "Can't stat() on configuration file: %s\n",
+				strerror(errno));
+		return EXIT_FAILURE;
+	}
+	if (txt_file_stat.st_size > envsize) {
+		fprintf(stderr, "The configuration file is larger than the "
+				"envrionnment partition size\n");
+		return EXIT_FAILURE;
+	}
+		
+
+	/* Read the raw configuration file and transform it */
+	ret = fread(envptr, sizeof(*envptr), txt_file_stat.st_size, txt_file);
+	if (ret != txt_file_stat.st_size) {
+		fprintf(stderr, "Can't read the whole configuration file\n");
+		return EXIT_FAILURE;
+	}
+	ret = fclose(txt_file);
+
+	for (i = 0 ; i < txt_file_stat.st_size ; i++)
+		if (envptr[i] == '\n')
+			envptr[i] = '\0';
+	/* 
+	 * Make sure there is a final '\0' (necessary if the padding byte isn't
+	 * 0x00 or if there wasn't a newline at the end of the configuration
+	 * file) Also, don't add it if the configuration file size is exactly
+	 * the size of the environnment.
+	 *
+	 * And do it again on the next byte to mark the end of the environment.
+	 */
+	if (i < envsize && envptr[i-1] != '\0') {
+		envptr[i] = '\0';
+		i++;
+		envptr[i] = '\0';
+	} else if (i < envsize) {
+		envptr[i] = '\0';
+	}
+
+
+	/* Computes the CRC and put it at the beginning of the data */
+	crc = crc32(0, envptr, envsize);
+	targetendian_crc = bigendian ? cpu_to_be32(crc) : cpu_to_le32(crc);
+
+	memcpy((uint32_t*) dataptr, &targetendian_crc, sizeof(uint32_t));
+
+	bin_file = fopen(bin_filename, "wb");
+	if (!bin_file) {
+		fprintf(stderr, "Can't open output file: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	if (fwrite(dataptr, sizeof(*dataptr), datasize, bin_file) != datasize) {
+		fprintf(stderr, "fwrite() failed: %s\n", strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	ret = fclose(bin_file);
+
+
+	return ret;
+}
-- 
1.7.0.4



More information about the U-Boot mailing list