diff options
| author | Stefano Babic <sbabic@denx.de> | 2010-05-24 12:08:16 +0200 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2010-06-29 22:43:27 +0200 | 
| commit | bd7b26f879413aa5a662718c09dab65d3a24a201 (patch) | |
| tree | c8f9939fac2b3c1da7aae7604bedc1d344d5191e /tools/env/fw_env.c | |
| parent | 3746a5e65ceeccf7e766df6263d2994b9abcc60e (diff) | |
| download | olio-uboot-2014.01-bd7b26f879413aa5a662718c09dab65d3a24a201.tar.xz olio-uboot-2014.01-bd7b26f879413aa5a662718c09dab65d3a24a201.zip | |
Tools: set multiple variable with fw_setenv utility
Add a sort of batch mode to fw_setenv, allowing to set
multiple variables in one shot, without updating the flash after
each set as now. It is added the possibility to pass
a config file with a list of pairs <variable, value> to be set,
separated by a TAB character.
Signed-off-by: Stefano Babic <sbabic@denx.de>
Diffstat (limited to 'tools/env/fw_env.c')
| -rw-r--r-- | tools/env/fw_env.c | 269 | 
1 files changed, 224 insertions, 45 deletions
| diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index a46205d86..04f3bf0a4 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -45,8 +45,7 @@  #include "fw_env.h" -#define	CMD_GETENV	"fw_printenv" -#define	CMD_SETENV	"fw_setenv" +#define WHITESPACE(c) ((c == '\t') || (c == ' '))  #define min(x, y) ({				\  	typeof(x) _min1 = (x);			\ @@ -210,7 +209,6 @@ static char default_environment[] = {  static int flash_io (int mode);  static char *envmatch (char * s1, char * s2); -static int env_init (void);  static int parse_config (void);  #if defined(CONFIG_FILE) @@ -225,6 +223,22 @@ static inline ulong getenvsize (void)  	return rc;  } +static char *fw_string_blank(char *s, int noblank) +{ +	int i; +	int len = strlen(s); + +	for (i = 0; i < len; i++, s++) { +		if ((noblank && !WHITESPACE(*s)) || +			(!noblank && WHITESPACE(*s))) +			break; +	} +	if (i == len) +		return NULL; + +	return s; +} +  /*   * Search the environment for a variable.   * Return the value, if found, or NULL, if not found. @@ -233,7 +247,7 @@ char *fw_getenv (char *name)  {  	char *env, *nxt; -	if (env_init ()) +	if (fw_env_open())  		return NULL;  	for (env = environment.data; *env; env = nxt + 1) { @@ -264,7 +278,7 @@ int fw_printenv (int argc, char *argv[])  	int i, n_flag;  	int rc = 0; -	if (env_init ()) +	if (fw_env_open())  		return -1;  	if (argc == 1) {		/* Print all env variables  */ @@ -327,30 +341,34 @@ int fw_printenv (int argc, char *argv[])  	return rc;  } -/* - * Deletes or sets environment variables. Returns -1 and sets errno error codes: - * 0	  - OK - * EINVAL - need at least 1 argument - * EROFS  - certain variables ("ethaddr", "serial#") cannot be - *	    modified or deleted - * - */ -int fw_setenv (int argc, char *argv[]) +int fw_env_close(void)  { -	int i, len; -	char *env, *nxt; -	char *oldval = NULL; -	char *name; +	/* +	 * Update CRC +	 */ +	*environment.crc = crc32(0, (uint8_t *) environment.data, ENV_SIZE); -	if (argc < 2) { -		errno = EINVAL; -		return -1; +	/* write environment back to flash */ +	if (flash_io(O_RDWR)) { +		fprintf(stderr, +			"Error: can't write fw_env to flash\n"); +			return -1;  	} -	if (env_init ()) -		return -1; +	return 0; +} -	name = argv[1]; + +/* + * Set/Clear a single variable in the environment. + * This is called in sequence to update the environment + * in RAM without updating the copy in flash after each set + */ +int fw_env_write(char *name, char *value) +{ +	int len; +	char *env, *nxt; +	char *oldval = NULL;  	/*  	 * search if variable with this name already exists @@ -358,7 +376,7 @@ int fw_setenv (int argc, char *argv[])  	for (nxt = env = environment.data; *env; env = nxt + 1) {  		for (nxt = env; *nxt; ++nxt) {  			if (nxt >= &environment.data[ENV_SIZE]) { -				fprintf (stderr, "## Error: " +				fprintf(stderr, "## Error: "  					"environment not terminated\n");  				errno = EINVAL;  				return -1; @@ -396,8 +414,8 @@ int fw_setenv (int argc, char *argv[])  	}  	/* Delete only ? */ -	if (argc < 3) -		goto WRITE_FLASH; +	if (!value || !strlen(value)) +		return 0;  	/*  	 * Append new definition at the end @@ -411,41 +429,202 @@ int fw_setenv (int argc, char *argv[])  	 */  	len = strlen (name) + 2;  	/* add '=' for first arg, ' ' for all others */ -	for (i = 2; i < argc; ++i) { -		len += strlen (argv[i]) + 1; -	} +	len += strlen(value) + 1; +  	if (len > (&environment.data[ENV_SIZE] - env)) {  		fprintf (stderr,  			"Error: environment overflow, \"%s\" deleted\n",  			name);  		return -1;  	} +  	while ((*env = *name++) != '\0')  		env++; +	*env = '='; +	while ((*++env = *value++) != '\0') +		; + +	/* end is marked with double '\0' */ +	*++env = '\0'; + +	return 0; +} + +/* + * Deletes or sets environment variables. Returns -1 and sets errno error codes: + * 0	  - OK + * EINVAL - need at least 1 argument + * EROFS  - certain variables ("ethaddr", "serial#") cannot be + *	    modified or deleted + * + */ +int fw_setenv(int argc, char *argv[]) +{ +	int i, len; +	char *name; +	char *value = NULL; +	char *tmpval = NULL; + +	if (argc < 2) { +		errno = EINVAL; +		return -1; +	} + +	if (fw_env_open()) { +		fprintf(stderr, "Error: environment not initialized\n"); +		return -1; +	} + +	name = argv[1]; + +	len = strlen(name) + 2; +	for (i = 2; i < argc; ++i) +		len += strlen(argv[i]) + 1; + +	/* Allocate enough place to the data string */  	for (i = 2; i < argc; ++i) {  		char *val = argv[i]; - -		*env = (i == 2) ? '=' : ' '; -		while ((*++env = *val++) != '\0'); +		if (!value) { +			value = (char *)malloc(len - strlen(name)); +			if (!value) { +				fprintf(stderr, +				"Cannot malloc %u bytes: %s\n", +				len - strlen(name), strerror(errno)); +				return -1; +			} +			memset(value, 0, len - strlen(name)); +			tmpval = value; +		} +		if (i != 2) +			*tmpval++ = ' '; +		while (*val != '\0') +			*tmpval++ = *val++;  	} -	/* end is marked with double '\0' */ -	*++env = '\0'; +	fw_env_write(name, value); -  WRITE_FLASH: +	if (value) +		free(value); -	/* -	 * Update CRC -	 */ -	*environment.crc = crc32 (0, (uint8_t *) environment.data, ENV_SIZE); +	return fw_env_close(); +} -	/* write environment back to flash */ -	if (flash_io (O_RDWR)) { -		fprintf (stderr, "Error: can't write fw_env to flash\n"); +/* + * Parse  a file  and configure the u-boot variables. + * The script file has a very simple format, as follows: + * + * Each line has a couple with name, value: + * <white spaces>variable_name<white spaces>variable_value + * + * Both variable_name and variable_value are interpreted as strings. + * Any character after <white spaces> and before ending \r\n is interpreted + * as variable's value (no comment allowed on these lines !) + * + * Comments are allowed if the first character in the line is # + * + * Returns -1 and sets errno error codes: + * 0	  - OK + * -1     - Error + */ +int fw_parse_script(char *fname) +{ +	FILE *fp; +	char dump[1024];	/* Maximum line length in the file */ +	char *name; +	char *val; +	int lineno = 0; +	int len; +	int ret = 0; + +	if (fw_env_open()) { +		fprintf(stderr, "Error: environment not initialized\n");  		return -1;  	} -	return 0; +	if (strcmp(fname, "-") == 0) +		fp = stdin; +	else { +		fp = fopen(fname, "r"); +		if (fp == NULL) { +			fprintf(stderr, "I cannot open %s for reading\n", +				 fname); +			return -1; +		} +	} + +	while (fgets(dump, sizeof(dump), fp)) { +		lineno++; +		len = strlen(dump); + +		/* +		 * Read a whole line from the file. If the line is too long +		 * or is not terminated, reports an error and exit. +		 */ +		if (dump[len - 1] != '\n') { +			fprintf(stderr, +			"Line %d not corrected terminated or too long\n", +				lineno); +			ret = -1; +			break; +		} + +		/* Drop ending line feed / carriage return */ +		while (len > 0 && (dump[len - 1] == '\n' || +				dump[len - 1] == '\r')) { +			dump[len - 1] = '\0'; +			len--; +		} + +		/* Skip comment or empty lines */ +		if ((len == 0) || dump[0] == '#') +			continue; + +		/* +		 * Search for variable's name, +		 * remove leading whitespaces +		 */ +		name = fw_string_blank(dump, 1); +		if (!name) +			continue; + +		/* The first white space is the end of variable name */ +		val = fw_string_blank(name, 0); +		len = strlen(name); +		if (val) { +			*val++ = '\0'; +			if ((val - name) < len) +				val = fw_string_blank(val, 1); +			else +				val = NULL; +		} + +#ifdef DEBUG +		fprintf(stderr, "Setting %s : %s\n", +			name, val ? val : " removed"); +#endif + +		/* +		 * If there is an error setting a variable, +		 * try to save the environment and returns an error +		 */ +		if (fw_env_write(name, val)) { +			fprintf(stderr, +			"fw_env_write returns with error : %s\n", +				strerror(errno)); +			ret = -1; +			break; +		} + +	} + +	/* Close file if not stdin */ +	if (strcmp(fname, "-") != 0) +		fclose(fp); + +	ret |= fw_env_close(); + +	return ret; +  }  /* @@ -880,7 +1059,7 @@ static char *envmatch (char * s1, char * s2)  /*   * Prevent confusion if running from erased flash memory   */ -static int env_init (void) +int fw_env_open(void)  {  	int crc0, crc0_ok;  	char flag0; |