mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 14:41:31 +00:00
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>
This commit is contained in:
parent
3746a5e65c
commit
bd7b26f879
3 changed files with 289 additions and 53 deletions
271
tools/env/fw_env.c
vendored
271
tools/env/fw_env.c
vendored
|
@ -45,8 +45,7 @@
|
||||||
|
|
||||||
#include "fw_env.h"
|
#include "fw_env.h"
|
||||||
|
|
||||||
#define CMD_GETENV "fw_printenv"
|
#define WHITESPACE(c) ((c == '\t') || (c == ' '))
|
||||||
#define CMD_SETENV "fw_setenv"
|
|
||||||
|
|
||||||
#define min(x, y) ({ \
|
#define min(x, y) ({ \
|
||||||
typeof(x) _min1 = (x); \
|
typeof(x) _min1 = (x); \
|
||||||
|
@ -210,7 +209,6 @@ static char default_environment[] = {
|
||||||
|
|
||||||
static int flash_io (int mode);
|
static int flash_io (int mode);
|
||||||
static char *envmatch (char * s1, char * s2);
|
static char *envmatch (char * s1, char * s2);
|
||||||
static int env_init (void);
|
|
||||||
static int parse_config (void);
|
static int parse_config (void);
|
||||||
|
|
||||||
#if defined(CONFIG_FILE)
|
#if defined(CONFIG_FILE)
|
||||||
|
@ -225,6 +223,22 @@ static inline ulong getenvsize (void)
|
||||||
return rc;
|
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.
|
* Search the environment for a variable.
|
||||||
* Return the value, if found, or NULL, if not found.
|
* Return the value, if found, or NULL, if not found.
|
||||||
|
@ -233,7 +247,7 @@ char *fw_getenv (char *name)
|
||||||
{
|
{
|
||||||
char *env, *nxt;
|
char *env, *nxt;
|
||||||
|
|
||||||
if (env_init ())
|
if (fw_env_open())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (env = environment.data; *env; env = nxt + 1) {
|
for (env = environment.data; *env; env = nxt + 1) {
|
||||||
|
@ -264,7 +278,7 @@ int fw_printenv (int argc, char *argv[])
|
||||||
int i, n_flag;
|
int i, n_flag;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (env_init ())
|
if (fw_env_open())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (argc == 1) { /* Print all env variables */
|
if (argc == 1) { /* Print all env variables */
|
||||||
|
@ -327,30 +341,34 @@ int fw_printenv (int argc, char *argv[])
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int fw_env_close(void)
|
||||||
* 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 *env, *nxt;
|
* Update CRC
|
||||||
char *oldval = NULL;
|
*/
|
||||||
char *name;
|
*environment.crc = crc32(0, (uint8_t *) environment.data, ENV_SIZE);
|
||||||
|
|
||||||
if (argc < 2) {
|
/* write environment back to flash */
|
||||||
errno = EINVAL;
|
if (flash_io(O_RDWR)) {
|
||||||
return -1;
|
fprintf(stderr,
|
||||||
|
"Error: can't write fw_env to flash\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env_init ())
|
return 0;
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
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
|
* 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 = environment.data; *env; env = nxt + 1) {
|
||||||
for (nxt = env; *nxt; ++nxt) {
|
for (nxt = env; *nxt; ++nxt) {
|
||||||
if (nxt >= &environment.data[ENV_SIZE]) {
|
if (nxt >= &environment.data[ENV_SIZE]) {
|
||||||
fprintf (stderr, "## Error: "
|
fprintf(stderr, "## Error: "
|
||||||
"environment not terminated\n");
|
"environment not terminated\n");
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -396,8 +414,8 @@ int fw_setenv (int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete only ? */
|
/* Delete only ? */
|
||||||
if (argc < 3)
|
if (!value || !strlen(value))
|
||||||
goto WRITE_FLASH;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Append new definition at the end
|
* Append new definition at the end
|
||||||
|
@ -411,41 +429,202 @@ int fw_setenv (int argc, char *argv[])
|
||||||
*/
|
*/
|
||||||
len = strlen (name) + 2;
|
len = strlen (name) + 2;
|
||||||
/* add '=' for first arg, ' ' for all others */
|
/* add '=' for first arg, ' ' for all others */
|
||||||
for (i = 2; i < argc; ++i) {
|
len += strlen(value) + 1;
|
||||||
len += strlen (argv[i]) + 1;
|
|
||||||
}
|
|
||||||
if (len > (&environment.data[ENV_SIZE] - env)) {
|
if (len > (&environment.data[ENV_SIZE] - env)) {
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"Error: environment overflow, \"%s\" deleted\n",
|
"Error: environment overflow, \"%s\" deleted\n",
|
||||||
name);
|
name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((*env = *name++) != '\0')
|
while ((*env = *name++) != '\0')
|
||||||
env++;
|
env++;
|
||||||
for (i = 2; i < argc; ++i) {
|
*env = '=';
|
||||||
char *val = argv[i];
|
while ((*++env = *value++) != '\0')
|
||||||
|
;
|
||||||
*env = (i == 2) ? '=' : ' ';
|
|
||||||
while ((*++env = *val++) != '\0');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end is marked with double '\0' */
|
/* end is marked with double '\0' */
|
||||||
*++env = '\0';
|
*++env = '\0';
|
||||||
|
|
||||||
WRITE_FLASH:
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update CRC
|
* Deletes or sets environment variables. Returns -1 and sets errno error codes:
|
||||||
*/
|
* 0 - OK
|
||||||
*environment.crc = crc32 (0, (uint8_t *) environment.data, ENV_SIZE);
|
* 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;
|
||||||
|
|
||||||
/* write environment back to flash */
|
if (argc < 2) {
|
||||||
if (flash_io (O_RDWR)) {
|
errno = EINVAL;
|
||||||
fprintf (stderr, "Error: can't write fw_env to flash\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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];
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fw_env_write(name, value);
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
free(value);
|
||||||
|
|
||||||
|
return fw_env_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
* Prevent confusion if running from erased flash memory
|
||||||
*/
|
*/
|
||||||
static int env_init (void)
|
int fw_env_open(void)
|
||||||
{
|
{
|
||||||
int crc0, crc0_ok;
|
int crc0, crc0_ok;
|
||||||
char flag0;
|
char flag0;
|
||||||
|
|
4
tools/env/fw_env.h
vendored
4
tools/env/fw_env.h
vendored
|
@ -50,5 +50,9 @@
|
||||||
extern int fw_printenv(int argc, char *argv[]);
|
extern int fw_printenv(int argc, char *argv[]);
|
||||||
extern char *fw_getenv (char *name);
|
extern char *fw_getenv (char *name);
|
||||||
extern int fw_setenv (int argc, char *argv[]);
|
extern int fw_setenv (int argc, char *argv[]);
|
||||||
|
extern int fw_parse_script(char *fname);
|
||||||
|
extern int fw_env_open(void);
|
||||||
|
extern int fw_env_write(char *name, char *value);
|
||||||
|
extern int fw_env_close(void);
|
||||||
|
|
||||||
extern unsigned long crc32 (unsigned long, const unsigned char *, unsigned);
|
extern unsigned long crc32 (unsigned long, const unsigned char *, unsigned);
|
||||||
|
|
67
tools/env/fw_env_main.c
vendored
67
tools/env/fw_env_main.c
vendored
|
@ -42,34 +42,87 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <getopt.h>
|
||||||
#include "fw_env.h"
|
#include "fw_env.h"
|
||||||
|
|
||||||
#define CMD_PRINTENV "fw_printenv"
|
#define CMD_PRINTENV "fw_printenv"
|
||||||
#define CMD_SETENV "fw_setenv"
|
#define CMD_SETENV "fw_setenv"
|
||||||
|
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"script", required_argument, NULL, 's'},
|
||||||
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
{NULL, 0, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
void usage(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
fprintf(stderr, "fw_printenv/fw_setenv, "
|
||||||
|
"a command line interface to U-Boot environment\n\n"
|
||||||
|
"usage:\tfw_printenv\n"
|
||||||
|
"\tfw_setenv [variable name] [variable value]\n"
|
||||||
|
"\tfw_setenv -s [ file ]\n"
|
||||||
|
"\tfw_setenv -s - < [ file ]\n\n"
|
||||||
|
"The file passed as argument contains only pairs "
|
||||||
|
"name / value\n"
|
||||||
|
"Example:\n"
|
||||||
|
"# Any line starting with # is treated as comment\n"
|
||||||
|
"\n"
|
||||||
|
"\t netdev eth0\n"
|
||||||
|
"\t kernel_addr 400000\n"
|
||||||
|
"\t var1\n"
|
||||||
|
"\t var2 The quick brown fox jumps over the "
|
||||||
|
"lazy dog\n"
|
||||||
|
"\n"
|
||||||
|
"A variable without value will be dropped. It is possible\n"
|
||||||
|
"to put any number of spaces between the fields, but any\n"
|
||||||
|
"space inside the value is treated as part of the value "
|
||||||
|
"itself.\n\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
char *cmdname = *argv;
|
char *cmdname = *argv;
|
||||||
|
char *script_file = NULL;
|
||||||
|
int c;
|
||||||
|
|
||||||
if ((p = strrchr (cmdname, '/')) != NULL) {
|
if ((p = strrchr (cmdname, '/')) != NULL) {
|
||||||
cmdname = p + 1;
|
cmdname = p + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while ((c = getopt_long (argc, argv, "s:h",
|
||||||
|
long_options, NULL)) != EOF) {
|
||||||
|
switch (c) {
|
||||||
|
case 's':
|
||||||
|
script_file = optarg;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
usage();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (strcmp(cmdname, CMD_PRINTENV) == 0) {
|
if (strcmp(cmdname, CMD_PRINTENV) == 0) {
|
||||||
|
|
||||||
if (fw_printenv (argc, argv) != 0)
|
if (fw_printenv (argc, argv) != 0)
|
||||||
return (EXIT_FAILURE);
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
return (EXIT_SUCCESS);
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
} else if (strcmp(cmdname, CMD_SETENV) == 0) {
|
} else if (strcmp(cmdname, CMD_SETENV) == 0) {
|
||||||
|
if (!script_file) {
|
||||||
|
if (fw_setenv(argc, argv) != 0)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else {
|
||||||
|
if (fw_parse_script(script_file) != 0)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (fw_setenv (argc, argv) != 0)
|
return EXIT_SUCCESS;
|
||||||
return (EXIT_FAILURE);
|
|
||||||
|
|
||||||
return (EXIT_SUCCESS);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,5 +130,5 @@ main(int argc, char *argv[])
|
||||||
"Identity crisis - may be called as `" CMD_PRINTENV
|
"Identity crisis - may be called as `" CMD_PRINTENV
|
||||||
"' or as `" CMD_SETENV "' but not as `%s'\n",
|
"' or as `" CMD_SETENV "' but not as `%s'\n",
|
||||||
cmdname);
|
cmdname);
|
||||||
return (EXIT_FAILURE);
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue