|
@@ -45,8 +45,7 @@
|
|
|
|
|
|
#include "fw_env.h"
|
|
#include "fw_env.h"
|
|
|
|
|
|
-#define CMD_GETENV "fw_printenv"
|
|
|
|
-#define CMD_SETENV "fw_setenv"
|
|
|
|
|
|
+#define WHITESPACE(c) ((c == '\t') || (c == ' '))
|
|
|
|
|
|
#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;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * 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
|
|
* 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)
|
|
|
|
- goto WRITE_FLASH;
|
|
|
|
|
|
+ if (!value || !strlen(value))
|
|
|
|
+ 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 (argv[i]) + 1;
|
|
|
|
- }
|
|
|
|
|
|
+ len += strlen(value) + 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++;
|
|
|
|
+ *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) {
|
|
for (i = 2; i < argc; ++i) {
|
|
char *val = argv[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 -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
|
|
* 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;
|