summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorrickard evertsson <rickard.evertsson@stericsson.com>2010-09-22 19:52:53 +0200
committerMichael BRANDT <michael.brandt@stericsson.com>2010-09-27 11:25:48 +0200
commit796065411dc8fc77b87bfdb0cf9eacdab40c31dc (patch)
treea8b96cebaea0080e3904ee75099f72a08a50e22f /tools
parent0f6be09b5e6e121430dcce554bbd56b9f24c3c75 (diff)
Host tool to create an environment image
This is a host tool that creates a 4 KB environment variable image. The environment image is by default built with U8500 environment settings (file u8500.h is included in the tool) but individual variables can be removed, added and / or modified by specifying an input configuration file containing such. ST-Ericsson ID: WP272737 Change-Id: Ia5d79f72c9607ad25ed3d2e05795a7a616af9cf9 Signed-off-by: rickard evertsson <rickard.evertsson@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/5409 Reviewed-by: Michael BRANDT <michael.brandt@stericsson.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/mk_envimg/Makefile51
-rw-r--r--tools/mk_envimg/README30
-rw-r--r--tools/mk_envimg/mk_env_img.c455
-rw-r--r--tools/mk_envimg/mk_env_img.h19
4 files changed, 555 insertions, 0 deletions
diff --git a/tools/mk_envimg/Makefile b/tools/mk_envimg/Makefile
new file mode 100644
index 000000000..f76bb2a4c
--- /dev/null
+++ b/tools/mk_envimg/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) ST-Ericsson SA 2010
+# Author: Rickard Evertsson <rickard.evertsson@stericsson.com>
+# for ST-Ericsson.
+#
+# Influenced by boot/u-boot/tools/env/Makefile
+#
+# License terms: GNU General Public License (GPL) version 2
+#
+
+ifeq ($(SRCTREE),)
+SRCTREE := ../..
+endif
+
+# Set up default output
+ifeq ($(OUTPUT),)
+OUTPUT := uboot-env.img
+endif
+
+include $(SRCTREE)/config.mk
+
+ifeq ($(obj),)
+obj := $(CURDIR)/
+endif
+
+SRCS := $(obj)crc32.c mk_env_img.c
+HEADERS := mk_env_img.h
+
+.PHONY: all
+
+all: $(obj)mk_envimg create_envimg
+
+$(obj)mk_envimg: $(SRCS) $(HEADERS)
+ $(HOSTCC) -g -I$(SRCTREE)/include -DUSE_HOSTCC $(SRCS) -o $(obj)mk_envimg
+
+clean:
+ rm -f $(obj)mk_envimg $(obj)crc32.c $(OUTPUT)
+
+$(obj)crc32.c:
+ ln -s $(SRCTREE)/lib_generic/crc32.c $(obj)crc32.c
+
+create_envimg:
+ $(obj)mk_envimg $(OUTPUT) $(INPUT)
+
+#########################################################################
+
+include ../../rules.mk
+
+sinclude $(obj)depend
+
+#########################################################################
diff --git a/tools/mk_envimg/README b/tools/mk_envimg/README
new file mode 100644
index 000000000..97406ab14
--- /dev/null
+++ b/tools/mk_envimg/README
@@ -0,0 +1,30 @@
+
+This is a small tool that creates an environment image for U-boot.
+It can be compiled both as a part of U-boot (using host compiler) and
+stand alone. The tool is intended to run on the host and not the target.
+
+Syntax:
+./mk_envimg [-d] output_file [input_file]
+
+When invoking the program, input arguments can be specified.
+* -d : debug mode, adds debug printouts
+* output_file : specify the name and location of the outpout
+* input_file : input configuration file (optional)
+
+The output file is an ordinary environment binary with a crc32 sum
+followed by the environment variables
+
+By default this tool will create an image with the default environment
+variables as built-in in U-boot.
+If an input file is specified it will remove, modify and/or remove
+default environment variables.
+
+Input file examples:
+* Add a new variable:
+an_new_variable=a_new_value
+
+* Remove the variable bootargs
+bootargs
+
+* Modify the variable bootargs
+bootargs=a_new_value \ No newline at end of file
diff --git a/tools/mk_envimg/mk_env_img.c b/tools/mk_envimg/mk_env_img.c
new file mode 100644
index 000000000..669e37884
--- /dev/null
+++ b/tools/mk_envimg/mk_env_img.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Rickard Evertsson <rickard.evertsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * Parts of this code are copied and / or inspired from
+ * boot/u-boot/tools/env/fw_env.c
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <configs/u8500.h>
+#include "mk_env_img.h"
+
+#define ENV_SIZE (CONFIG_ENV_SIZE - sizeof(uint32_t))
+#define CONFIG_BUF_SIZE 200
+
+struct env_image_single {
+ uint32_t crc; /* CRC32 over data bytes */
+ char data[ENV_SIZE];
+} single_image = {.data = "\0"};
+
+#define XMK_STR(x) #x
+#define MK_STR(x) XMK_STR(x)
+static char default_environment[] = {
+#ifdef CONFIG_BOOTARGS
+ "bootargs=" CONFIG_BOOTARGS "\0"
+#endif
+#ifdef CONFIG_BOOTCOMMAND
+ "bootcmd=" CONFIG_BOOTCOMMAND "\0"
+#endif
+#ifdef CONFIG_RAMBOOTCOMMAND
+ "ramboot=" CONFIG_RAMBOOTCOMMAND "\0"
+#endif
+#ifdef CONFIG_NFSBOOTCOMMAND
+ "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0"
+#endif
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
+ "bootdelay=" MK_STR(CONFIG_BOOTDELAY) "\0"
+#endif
+#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
+ "baudrate=" MK_STR(CONFIG_BAUDRATE) "\0"
+#endif
+#ifdef CONFIG_LOADS_ECHO
+ "loads_echo=" MK_STR(CONFIG_LOADS_ECHO) "\0"
+#endif
+#ifdef CONFIG_ETHADDR
+ "ethaddr=" MK_STR(CONFIG_ETHADDR) "\0"
+#endif
+#ifdef CONFIG_ETH1ADDR
+ "eth1addr=" MK_STR(CONFIG_ETH1ADDR) "\0"
+#endif
+#ifdef CONFIG_ETH2ADDR
+ "eth2addr=" MK_STR(CONFIG_ETH2ADDR) "\0"
+#endif
+#ifdef CONFIG_ETH3ADDR
+ "eth3addr=" MK_STR(CONFIG_ETH3ADDR) "\0"
+#endif
+#ifdef CONFIG_ETH4ADDR
+ "eth4addr=" MK_STR(CONFIG_ETH4ADDR) "\0"
+#endif
+#ifdef CONFIG_ETH5ADDR
+ "eth5addr=" MK_STR(CONFIG_ETH5ADDR) "\0"
+#endif
+#ifdef CONFIG_IPADDR
+ "ipaddr=" MK_STR(CONFIG_IPADDR) "\0"
+#endif
+#ifdef CONFIG_SERVERIP
+ "serverip=" MK_STR(CONFIG_SERVERIP) "\0"
+#endif
+#ifdef CONFIG_SYS_AUTOLOAD
+ "autoload=" CONFIG_SYS_AUTOLOAD "\0"
+#endif
+#ifdef CONFIG_PREBOOT
+ "preboot=" CONFIG_PREBOOT "\0"
+#endif
+#ifdef CONFIG_ROOTPATH
+ "rootpath=" MK_STR(CONFIG_ROOTPATH) "\0"
+#endif
+#ifdef CONFIG_GATEWAYIP
+ "gatewayip=" MK_STR(CONFIG_GATEWAYIP) "\0"
+#endif
+#ifdef CONFIG_NETMASK
+ "netmask=" MK_STR(CONFIG_NETMASK) "\0"
+#endif
+#ifdef CONFIG_HOSTNAME
+ "hostname=" MK_STR(CONFIG_HOSTNAME) "\0"
+#endif
+#ifdef CONFIG_BOOTFILE
+ "bootfile=" MK_STR(CONFIG_BOOTFILE) "\0"
+#endif
+#ifdef CONFIG_LOADADDR
+ "loadaddr=" MK_STR(CONFIG_LOADADDR) "\0"
+#endif
+#ifdef CONFIG_CLOCKS_IN_MHZ
+ "clocks_in_mhz=1\0"
+#endif
+#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
+ "pcidelay=" MK_STR(CONFIG_PCI_BOOTDELAY) "\0"
+#endif
+#ifdef CONFIG_EXTRA_ENV_SETTINGS
+ CONFIG_EXTRA_ENV_SETTINGS
+#endif
+ "\0"
+};
+
+struct env_image_single *single = &single_image;
+
+static int replace_name_value_pair(char *name, char *value);
+
+static char *split_name_value_pair(char *s, char *endpos);
+
+static char *envmatch(char * s1, char * s2);
+
+static int replace_default_values(char *file_name);
+
+static int write_final_image(char *output_image);
+
+static int print_env_image(void);
+
+static void cmd_usage(void)
+{
+ fprintf(stderr, "## Usage: mk_envimg [-d] output_file [input_file]\n");
+}
+
+static int dbg_level;
+
+/*
+ * main function
+ * Creates an environment image of the size 4 kB
+ * The variables specified in the input_file
+ * overrides the U-boot default values.
+ *
+ * Syntax:
+ * mk_envimg [-d] output_file [input_file]
+ */
+int main(int argc, char *argv[])
+{
+ char *p;
+ char *cmdname = *argv;
+ int i = 0;
+
+ if (argc < 2) {
+ cmd_usage();
+ return EXIT_FAILURE;
+ }
+
+ if (strcmp(argv[1], "-d") == 0) {
+ if (argc < 3) {
+ cmd_usage();
+ return EXIT_FAILURE;
+ }
+ dbg_level = 1;
+ }
+
+ if (mk_envimg(argc, argv) != 0)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
+
+/*
+ * Create a default image and replace default values with values
+ * specified in config file
+ * Return values:
+ * OK - Success
+ * -NOK - Replace default values failure
+ * -ENOMEM - No memory available
+ * Returns 0 on success
+ */
+
+int mk_envimg(int argc, char *argv[])
+{
+ char *config_file_name = NULL;
+ char *output_image;
+
+ /* create an image with default U-boot environment settings */
+ memcpy(single->data, default_environment, sizeof default_environment);
+
+ output_image = argv[1 + dbg_level];
+
+ /* check if config_file has been specified as input */
+ if (argc > 2 + dbg_level) {
+ if (dbg_level)
+ printf("argc=%d, argv=%s\n", argc + dbg_level,
+ argv[2 + dbg_level]);
+
+ config_file_name = argv[2 + dbg_level];
+ }
+
+ if (config_file_name) {
+ /* replace with specified variables in config file */
+ if (replace_default_values(config_file_name))
+ return -NOK;
+ }
+ /* write image into file */
+ if (write_final_image(output_image))
+ return -NOK;
+
+ /* print environment variables to stdout */
+ if (dbg_level)
+ print_env_image();
+
+ return OK;
+}
+
+/*
+ * Deletes or sets environment variables.
+ * Return codes:
+ * OK - OK
+ * NOK - non-specific failure
+ * EINVAL - need at least 1 argument
+ * EROFS - certain variables ("ethaddr", "serial#") cannot be
+ * modified or deleted
+ *
+ */
+static int replace_name_value_pair(char *name, char *value)
+{
+ int len;
+ char *env, *nxt;
+ char *oldval = NULL;
+
+ /*
+ * search if variable with this name already exists
+ */
+ for (nxt = env = single->data; *env; env = nxt + 1) {
+ for (nxt = env; *nxt; ++nxt) {
+ if (nxt >= &single->data[ENV_SIZE]) {
+ fprintf(stderr, "## Error: "
+ "environment not terminated\n");
+ return -NOK;
+ }
+ }
+ oldval = envmatch(name, env);
+ if (oldval != NULL)
+ break;
+ }
+
+ /*
+ * delete any existing definition
+ */
+ if (oldval) {
+ /*
+ * ethernet Address and serial# can be set only once
+ */
+ if ((strcmp(name, "ethaddr") == 0) ||
+ (strcmp(name, "serial#") == 0)) {
+ fprintf(stderr, "Can't overwrite \"%s\"\n", name);
+ return -NOK;
+ }
+
+ if (*++nxt == '\0')
+ *env = '\0';
+ else {
+ for (;;) {
+ *env = *nxt++;
+ if ((*env == '\0') && (*nxt == '\0'))
+ break;
+ ++env;
+ }
+ }
+ *++env = '\0';
+ }
+
+ /* if value exists, append new definition at the end */
+ if (value) {
+ for (env = single->data; *env || *(env + 1); ++env)
+ ;
+ if (env > single->data)
+ ++env;
+ /*
+ * Overflow when:
+ * "name" + "=" + "val" +"\0\0" > CONFIG_ENV_SIZE -
+ * (env-environment)
+ */
+ len = strlen(name) + 2;
+ /* add '=' for first arg, ' ' for all others */
+ len += strlen(value);
+
+ if (len > (&single->data[ENV_SIZE] - env)) {
+ fprintf(stderr, "Error: environment overflow, \"%s\" \
+ deleted\n", name);
+ return -NOK;
+ }
+ while ((*env = *name++) != '\0')
+ env++;
+
+ *env = '=';
+ while ((*++env = *value++) != '\0')
+ ;
+
+ /* end is marked with double '\0' */
+ *++env = '\0';
+ }
+
+ /* update CRC */
+ single->crc = crc32(0, (uint8_t *) single->data, ENV_SIZE);
+
+ return OK;
+}
+
+/*
+ * s1 is either a simple 'name', or a 'name=value' pair.
+ * s2 is a 'name=value' pair.
+ * If the names match, return the value of s2, else NULL.
+ */
+
+static char *envmatch(char * s1, char * s2)
+{
+
+ while (*s1 == *s2++)
+ if (*s1++ == '=')
+ return s2;
+ if (*s1 == '\0' && *(s2 - 1) == '=')
+ return s2;
+ return NULL;
+}
+
+/*
+ * s is either a 'name' or a 'name=value' pair
+ * replace '=' with '\0' so that the 'name' can be printed out of s buffer
+ * replace end of line with '\0'
+ * returns value or NULL for no value
+ */
+static char *split_name_value_pair(char *s, char *endpos)
+{
+ int i;
+
+ if (s == endpos)
+ return NULL;
+ for (i = 0; i < CONFIG_BUF_SIZE; i++) {
+ s++;
+ /* if true, no value exists */
+ if (s == endpos) {
+ *s = '\0';
+ return NULL;
+ }
+ if (*s == '=') {
+ /* set endmark for 'name' */
+ *s = '\0';
+ /* if true, no value exists */
+ if (++s == endpos)
+ return NULL;
+
+ /* set endmark for 'value' (replace LR & EOF) */
+ *endpos = '\0';
+ return s;
+ }
+ }
+ fprintf(stderr, "## Error: Corrupt config file\n");
+ return NULL;
+}
+
+/*
+ * Open config file and replace environment variables in
+ * default image.
+ * Return values:
+ * OK - for success
+ * -NOK - Text string is larger than text buffer
+ * -ENOENT - File or folder does not exist
+ */
+static int replace_default_values(char *file_name)
+{
+ int ret = 0;
+ int i = 0;
+ FILE *config_file;
+ char *s;
+ char *value;
+ char s_buf[CONFIG_BUF_SIZE];
+
+ config_file = fopen(file_name, "r");
+ if (config_file == NULL) {
+ fprintf(stderr, "## Error: File does not exist\n");
+ return -ENOENT;
+ }
+
+ while (ret != EOF) {
+ for (s = &s_buf[0]; i < CONFIG_BUF_SIZE; i++) {
+ ret = fgetc(config_file);
+ *s = (char) ret;
+
+ if ((*s == '\n') || (ret == EOF)) {
+ value = split_name_value_pair(&s_buf[0], s);
+ replace_name_value_pair(&s_buf[0], value);
+ i = 0;
+ break;
+ }
+
+ s++;
+ }
+ if (i == CONFIG_BUF_SIZE) {
+ fprintf(stderr, "## Error: Buffer too small\n");
+ fclose(config_file);
+ return NOK;
+ }
+ }
+ fclose(config_file);
+ return OK;
+}
+
+/*
+ * Create and write env image into file
+ * Return values:
+ * OK - Success
+ * -NOK - Open and Write failure
+ */
+static int write_final_image(char *output_image)
+{
+ int ret = 0;
+ FILE *outfile;
+
+ single->crc = crc32(0, (uint8_t *) single->data, ENV_SIZE);
+
+ if (dbg_level) {
+ printf("crc=%x\n", single->crc);
+ printf("data=%s, image size=%d, sizeof(data)=%d\n",
+ single->data, CONFIG_ENV_SIZE, ENV_SIZE);
+ }
+ outfile = fopen(output_image, "w+");
+ if (outfile == NULL) {
+ fprintf(stderr, "## Error: Failed to open file\n");
+ return -NOK;
+ }
+
+ ret = fwrite((single), CONFIG_ENV_SIZE, 1, outfile);
+ fclose(outfile);
+ if (!ret)
+ return -NOK;
+
+ return OK;
+}
+
+static int print_env_image()
+{
+ char *env, *nxt;
+
+ /* print all env variables */
+ for (env = single->data; *env; env = nxt + 1) {
+ for (nxt = env; *nxt; ++nxt) {
+ if (nxt >= single->data + ENV_SIZE) {
+ fprintf(stderr, "## Error: "
+ "environment not terminated\n");
+ free(single);
+ return -1;
+ }
+ }
+ printf("%s\n", env);
+ }
+ return 0;
+}
diff --git a/tools/mk_envimg/mk_env_img.h b/tools/mk_envimg/mk_env_img.h
new file mode 100644
index 000000000..90d1bbfc2
--- /dev/null
+++ b/tools/mk_envimg/mk_env_img.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Rickard Evertsson <rickard.evertsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef _MK_ENV_IMG_H
+#define _MK_ENV_IMG_H
+
+/* Local return values */
+#define OK 0
+#define NOK 1
+
+extern uint32_t crc32(unsigned long, const unsigned char*, unsigned);
+
+#endif
+