From 796065411dc8fc77b87bfdb0cf9eacdab40c31dc Mon Sep 17 00:00:00 2001 From: rickard evertsson Date: Wed, 22 Sep 2010 19:52:53 +0200 Subject: 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 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/5409 Reviewed-by: Michael BRANDT --- tools/mk_envimg/Makefile | 51 +++++ tools/mk_envimg/README | 30 +++ tools/mk_envimg/mk_env_img.c | 455 +++++++++++++++++++++++++++++++++++++++++++ tools/mk_envimg/mk_env_img.h | 19 ++ 4 files changed, 555 insertions(+) create mode 100644 tools/mk_envimg/Makefile create mode 100644 tools/mk_envimg/README create mode 100644 tools/mk_envimg/mk_env_img.c create mode 100644 tools/mk_envimg/mk_env_img.h 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 +# 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 + * 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 +#include +#include +#include +#include + +#include +#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 + * 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 + -- cgit v1.2.3