All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default
@ 2011-11-18 16:49 Gerlando Falauto
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance Gerlando Falauto
                   ` (16 more replies)
  0 siblings, 17 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-11-18 16:49 UTC (permalink / raw)
  To: u-boot

This patchset modifies the handling of all the operations on the environment
(set/import/default) so to unify handling of special variables.
On top of that we implement a selective "env default".

A selective "env import" would imply a user API change and should therefore
be discussed separately.

Changes in the syntax (user API):
- "env default" -f: override write-once variables, -a means all

First patch is a cosmetic prerequisite to the second patch
which constifies serial_assign().

Changes from v0:
- checkpatch cleanup
- removed himport_ex()
- removed warning for serial_assign()
- env import NOT implemented here

Gerlando Falauto (5):
  serial: cosmetic checkpatch compliance
  serial: constify serial_assign()
  env: unify logic to check and apply changes
  env: check and apply changes on delete/destroy
  env: make "env default" selective, check and apply

 README                   |    2 +
 common/cmd_nvedit.c      |  209 +++++++++++++++++++++++++++++++---------------
 common/env_common.c      |   35 +++++++-
 common/serial.c          |   51 ++++++------
 include/config_cmd_all.h |    1 +
 include/environment.h    |   12 +++
 include/search.h         |   23 +++++-
 include/serial.h         |   19 ++--
 lib/hashtable.c          |   61 ++++++++++++--
 9 files changed, 300 insertions(+), 113 deletions(-)

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
@ 2011-11-18 16:49 ` Gerlando Falauto
  2011-11-18 20:04   ` Mike Frysinger
  2011-12-05 21:47   ` Wolfgang Denk
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 2/5] serial: constify serial_assign() Gerlando Falauto
                   ` (15 subsequent siblings)
  16 siblings, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-11-18 16:49 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/serial.c  |   51 +++++++++++++++++++++++++--------------------------
 include/serial.h |   19 ++++++++++---------
 2 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/common/serial.c b/common/serial.c
index 5b83d6a..03bbb19 100644
--- a/common/serial.c
+++ b/common/serial.c
@@ -29,8 +29,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static struct serial_device *serial_devices = NULL;
-static struct serial_device *serial_current = NULL;
+static struct serial_device *serial_devices;
+static struct serial_device *serial_current;
 
 void serial_register(struct serial_device *dev)
 {
@@ -47,14 +47,14 @@ void serial_register(struct serial_device *dev)
 	serial_devices = dev;
 }
 
-void serial_initialize (void)
+void serial_initialize(void)
 {
 #if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2)
-	serial_register (&serial_smc_device);
+	serial_register(&serial_smc_device);
 #endif
-#if defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) \
- || defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
-	serial_register (&serial_scc_device);
+#if	defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) || \
+	defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
+	serial_register(&serial_scc_device);
 #endif
 
 #if defined(CONFIG_SYS_NS16550_SERIAL)
@@ -71,13 +71,13 @@ void serial_initialize (void)
 	serial_register(&eserial4_device);
 #endif
 #endif /* CONFIG_SYS_NS16550_SERIAL */
-#if defined (CONFIG_FFUART)
+#if defined(CONFIG_FFUART)
 	serial_register(&serial_ffuart_device);
 #endif
-#if defined (CONFIG_BTUART)
+#if defined(CONFIG_BTUART)
 	serial_register(&serial_btuart_device);
 #endif
-#if defined (CONFIG_STUART)
+#if defined(CONFIG_STUART)
 	serial_register(&serial_stuart_device);
 #endif
 #if defined(CONFIG_S3C2410)
@@ -122,18 +122,18 @@ void serial_initialize (void)
 	serial_register(&uartlite_serial3_device);
 # endif /* XILINX_UARTLITE_BASEADDR3 */
 #endif /* CONFIG_XILINX_UARTLITE */
-	serial_assign (default_serial_console ()->name);
+	serial_assign(default_serial_console()->name);
 }
 
-void serial_stdio_init (void)
+void serial_stdio_init(void)
 {
 	struct stdio_dev dev;
 	struct serial_device *s = serial_devices;
 
 	while (s) {
-		memset (&dev, 0, sizeof (dev));
+		memset(&dev, 0, sizeof(dev));
 
-		strcpy (dev.name, s->name);
+		strcpy(dev.name, s->name);
 		dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
 
 		dev.start = s->init;
@@ -143,18 +143,18 @@ void serial_stdio_init (void)
 		dev.getc = s->getc;
 		dev.tstc = s->tstc;
 
-		stdio_register (&dev);
+		stdio_register(&dev);
 
 		s = s->next;
 	}
 }
 
-int serial_assign (char *name)
+int serial_assign(char *name)
 {
 	struct serial_device *s;
 
 	for (s = serial_devices; s; s = s->next) {
-		if (strcmp (s->name, name) == 0) {
+		if (strcmp(s->name, name) == 0) {
 			serial_current = s;
 			return 0;
 		}
@@ -163,13 +163,12 @@ int serial_assign (char *name)
 	return 1;
 }
 
-void serial_reinit_all (void)
+void serial_reinit_all(void)
 {
 	struct serial_device *s;
 
-	for (s = serial_devices; s; s = s->next) {
-		s->init ();
-	}
+	for (s = serial_devices; s; s = s->next)
+		s->init();
 }
 
 static struct serial_device *get_current(void)
@@ -192,27 +191,27 @@ int serial_init(void)
 	return get_current()->init();
 }
 
-void serial_setbrg (void)
+void serial_setbrg(void)
 {
 	get_current()->setbrg();
 }
 
-int serial_getc (void)
+int serial_getc(void)
 {
 	return get_current()->getc();
 }
 
-int serial_tstc (void)
+int serial_tstc(void)
 {
 	return get_current()->tstc();
 }
 
-void serial_putc (const char c)
+void serial_putc(const char c)
 {
 	get_current()->putc(c);
 }
 
-void serial_puts (const char *s)
+void serial_puts(const char *s)
 {
 	get_current()->puts(s);
 }
diff --git a/include/serial.h b/include/serial.h
index 5926244..9d623ca 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -24,14 +24,15 @@ struct serial_device {
 
 extern struct serial_device serial_smc_device;
 extern struct serial_device serial_scc_device;
-extern struct serial_device * default_serial_console (void);
-
-#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || \
-    defined(CONFIG_405EP) || defined(CONFIG_405EZ) || defined(CONFIG_405EX) || \
-    defined(CONFIG_MB86R0x) || defined(CONFIG_MPC5xxx) || \
-    defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) || \
-    defined(CONFIG_MPC86xx) || defined(CONFIG_SYS_SC520) || \
-    defined(CONFIG_TEGRA2)
+extern struct serial_device *default_serial_console(void);
+
+#if	defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+	defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+	defined(CONFIG_405EX) || defined(CONFIG_440) || \
+	defined(CONFIG_MB86R0x) || defined(CONFIG_MPC5xxx) || \
+	defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) || \
+	defined(CONFIG_MPC86xx) || defined(CONFIG_SYS_SC520) || \
+	defined(CONFIG_TEGRA2)
 extern struct serial_device serial0_device;
 extern struct serial_device serial1_device;
 #if defined(CONFIG_SYS_NS16550_SERIAL)
@@ -92,7 +93,7 @@ extern struct serial_device bfin_serial3_device;
 extern void serial_register(struct serial_device *);
 extern void serial_initialize(void);
 extern void serial_stdio_init(void);
-extern int serial_assign(char * name);
+extern int serial_assign(char *name);
 extern void serial_reinit_all(void);
 
 /* For usbtty */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 2/5] serial: constify serial_assign()
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance Gerlando Falauto
@ 2011-11-18 16:49 ` Gerlando Falauto
  2011-11-18 20:03   ` Mike Frysinger
  2011-12-05 21:48   ` Wolfgang Denk
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 3/5] env: unify logic to check and apply changes Gerlando Falauto
                   ` (14 subsequent siblings)
  16 siblings, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-11-18 16:49 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/serial.c  |    2 +-
 include/serial.h |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/serial.c b/common/serial.c
index 03bbb19..75cc1bb 100644
--- a/common/serial.c
+++ b/common/serial.c
@@ -149,7 +149,7 @@ void serial_stdio_init(void)
 	}
 }
 
-int serial_assign(char *name)
+int serial_assign(const char *name)
 {
 	struct serial_device *s;
 
diff --git a/include/serial.h b/include/serial.h
index 9d623ca..fbc1036 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -93,7 +93,7 @@ extern struct serial_device bfin_serial3_device;
 extern void serial_register(struct serial_device *);
 extern void serial_initialize(void);
 extern void serial_stdio_init(void);
-extern int serial_assign(char *name);
+extern int serial_assign(const char *name);
 extern void serial_reinit_all(void);
 
 /* For usbtty */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 3/5] env: unify logic to check and apply changes
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance Gerlando Falauto
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 2/5] serial: constify serial_assign() Gerlando Falauto
@ 2011-11-18 16:49 ` Gerlando Falauto
  2011-12-07  1:50   ` Simon Glass
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 4/5] env: check and apply changes on delete/destroy Gerlando Falauto
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2011-11-18 16:49 UTC (permalink / raw)
  To: u-boot

The logic of checking special parameters (e.g. baudrate, stdin, stdout,
for a valid value and/or whether can be overwritten) and applying the
new value to the running system is now all within a single function
env_check_apply() which can be called whenever changes are made
to the environment, no matter if by set, default or import.

With this patch env_check_apply() is only called by "env set",
retaining previous behavior.

Also allow for selectively importing/resetting variables.

So add 3 new arguments to himport_r():
o "nvars", "vars":, number and list of variables to take into account
   (0 means ALL)

o "apply" callback function to check whether a variable can be
  overwritten, and possibly immediately apply the changes;
  when NULL, no check is performed.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c   |  163 +++++++++++++++++++++++++++++++-----------------
 common/env_common.c   |    6 +-
 include/environment.h |    7 ++
 include/search.h      |   17 +++++-
 lib/hashtable.c       |   43 +++++++++++++-
 5 files changed, 174 insertions(+), 62 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 7194ade..d6ea25d 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -196,32 +196,23 @@ static int do_env_grep (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
 #endif
 
 /*
- * Set a new environment variable,
- * or replace or delete an existing one.
+ * Performs consistency checking before setting, replacing,
+ * or deleting an environment variable, then (if successful)
+ * apply the changes to internals so to make them effective.
+ * Code for this function was taken out of _do_env_set(),
+ * which now calls it.
+ * Also called as a callback function by himport_r().
+ * Returns 0 in case of success, 1 in case of failure.
+ * When (flag & H_FORCE) is set, force overwriting of
+ * write-once variables.
  */
 
-int _do_env_set (int flag, int argc, char * const argv[])
+int env_check_apply(const char *name, const char *oldval,
+			const char *newval, int flag)
 {
 	bd_t  *bd = gd->bd;
-	int   i, len;
+	int   i;
 	int   console = -1;
-	char  *name, *value, *s;
-	ENTRY e, *ep;
-
-	name = argv[1];
-
-	if (strchr(name, '=')) {
-		printf("## Error: illegal character '=' in variable name \"%s\"\n", name);
-		return 1;
-	}
-
-	env_id++;
-	/*
-	 * search if variable with this name already exists
-	 */
-	e.key = name;
-	e.data = NULL;
-	hsearch_r(e, FIND, &ep, &env_htab);
 
 	/* Check for console redirection */
 	if (strcmp(name, "stdin") == 0)
@@ -232,22 +223,23 @@ int _do_env_set (int flag, int argc, char * const argv[])
 		console = stderr;
 
 	if (console != -1) {
-		if (argc < 3) {		/* Cannot delete it! */
+		if ((newval == NULL) || (*newval == '\0')) {
+			/* We cannot delete stdin/stdout/stderr */
 			printf("Can't delete \"%s\"\n", name);
 			return 1;
 		}
 
 #ifdef CONFIG_CONSOLE_MUX
-		i = iomux_doenv(console, argv[2]);
+		i = iomux_doenv(console, newval);
 		if (i)
 			return i;
 #else
 		/* Try assigning specified device */
-		if (console_assign(console, argv[2]) < 0)
+		if (console_assign(console, newval) < 0)
 			return 1;
 
 #ifdef CONFIG_SERIAL_MULTI
-		if (serial_assign(argv[2]) < 0)
+		if (serial_assign(newval) < 0)
 			return 1;
 #endif
 #endif /* CONFIG_CONSOLE_MUX */
@@ -255,25 +247,35 @@ int _do_env_set (int flag, int argc, char * const argv[])
 
 	/*
 	 * Some variables like "ethaddr" and "serial#" can be set only
-	 * once and cannot be deleted; also, "ver" is readonly.
+	 * once and cannot be deleted, unless CONFIG_ENV_OVERWRITE
+	 * is defined.
 	 */
-	if (ep) {		/* variable exists */
 #ifndef CONFIG_ENV_OVERWRITE
+	if (oldval != NULL &&			/* variable exists */
+		(flag & H_FORCE) == 0) {	/* and we are not forced */
 		if ((strcmp(name, "serial#") == 0) ||
 		    ((strcmp(name, "ethaddr") == 0)
 #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
-		     && (strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0)
+		     && (strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0)
 #endif	/* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
 		    ) ) {
 			printf("Can't overwrite \"%s\"\n", name);
 			return 1;
 		}
+	}
 #endif
+	/*
+	 * When we change baudrate, or we are doing an env default -a
+	 * (which will erase all variables prior to calling this),
+	 * we want the baudrate to actually change - for real.
+	 */
+	if (oldval != NULL ||			/* variable exists */
+		(flag & H_NOCLEAR) == 0) {	/* or env is clear */
 		/*
 		 * Switch to new baudrate if new baudrate is supported
 		 */
 		if (strcmp(name, "baudrate") == 0) {
-			int baudrate = simple_strtoul(argv[2], NULL, 10);
+			int baudrate = simple_strtoul(newval, NULL, 10);
 			int i;
 			for (i = 0; i < N_BAUDRATES; ++i) {
 				if (baudrate == baudrate_table[i])
@@ -284,6 +286,10 @@ int _do_env_set (int flag, int argc, char * const argv[])
 					baudrate);
 				return 1;
 			}
+			if (gd->baudrate == baudrate) {
+				/* If unchanged, we just say it's OK */
+				return 0;
+			}
 			printf ("## Switch baudrate to %d bps and press ENTER ...\n",
 				baudrate);
 			udelay(50000);
@@ -301,6 +307,74 @@ int _do_env_set (int flag, int argc, char * const argv[])
 		}
 	}
 
+	/*
+	 * Some variables should be updated when the corresponding
+	 * entry in the environment is changed
+	 */
+
+	if (strcmp(name, "ipaddr") == 0) {
+		const char *s = newval;
+		char *e;
+		unsigned long addr;
+		bd->bi_ip_addr = 0;
+		for (addr = 0, i = 0; i < 4; ++i) {
+			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
+			addr <<= 8;
+			addr  |= (val & 0xFF);
+			if (s)
+				s = (*e) ? e+1 : e;
+		}
+		bd->bi_ip_addr = htonl(addr);
+		return 0;
+	} else if (strcmp(newval, "loadaddr") == 0) {
+		load_addr = simple_strtoul(newval, NULL, 16);
+		return 0;
+	}
+#if defined(CONFIG_CMD_NET)
+	else if (strcmp(newval, "bootfile") == 0) {
+		copy_filename(BootFile, newval, sizeof(BootFile));
+		return 0;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Set a new environment variable,
+ * or replace or delete an existing one.
+*/
+int _do_env_set(int flag, int argc, char * const argv[])
+{
+	int   i, len;
+	char  *name, *value, *s;
+	ENTRY e, *ep;
+
+	name = argv[1];
+	value = argv[2];
+
+	if (strchr(name, '=')) {
+		printf("## Error: illegal character '='"
+		       "in variable name \"%s\"\n", name);
+		return 1;
+	}
+
+	env_id++;
+	/*
+	 * search if variable with this name already exists
+	 */
+	e.key = name;
+	e.data = NULL;
+	hsearch_r(e, FIND, &ep, &env_htab);
+
+	/*
+	 * Perform requested checks. Notice how since we are overwriting
+	 * a single variable, we need to set H_NOCLEAR
+	 */
+	if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
+		debug("check function did not approve, refusing\n");
+		return 1;
+	}
+
 	/* Delete only ? */
 	if ((argc < 3) || argv[2] == NULL) {
 		int rc = hdelete_r(name, &env_htab);
@@ -338,34 +412,6 @@ int _do_env_set (int flag, int argc, char * const argv[])
 		return 1;
 	}
 
-	/*
-	 * Some variables should be updated when the corresponding
-	 * entry in the environment is changed
-	 */
-
-	if (strcmp(name, "ipaddr") == 0) {
-		char *s = argv[2];	/* always use only one arg */
-		char *e;
-		unsigned long addr;
-		bd->bi_ip_addr = 0;
-		for (addr = 0, i = 0; i < 4; ++i) {
-			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
-			addr <<= 8;
-			addr  |= (val & 0xFF);
-			if (s) s = (*e) ? e+1 : e;
-		}
-		bd->bi_ip_addr = htonl(addr);
-		return 0;
-	} else if (strcmp(argv[1], "loadaddr") == 0) {
-		load_addr = simple_strtoul(argv[2], NULL, 16);
-		return 0;
-	}
-#if defined(CONFIG_CMD_NET)
-	else if (strcmp(argv[1], "bootfile") == 0) {
-		copy_filename(BootFile, argv[2], sizeof(BootFile));
-		return 0;
-	}
-#endif
 	return 0;
 }
 
@@ -888,7 +934,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
 		addr = (char *)ep->data;
 	}
 
-	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
+	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
+			0, NULL, NULL) == 0) {
 		error("Environment import failed: errno = %d\n", errno);
 		return 1;
 	}
diff --git a/common/env_common.c b/common/env_common.c
index c7e9bea..9d8c59e 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -190,7 +190,8 @@ void set_default_env(const char *s)
 	}
 
 	if (himport_r(&env_htab, (char *)default_environment,
-		    sizeof(default_environment), '\0', 0) == 0) {
+			sizeof(default_environment), '\0', 0,
+			0, NULL, NULL) == 0) {
 		error("Environment import failed: errno = %d\n", errno);
 	}
 	gd->flags |= GD_FLG_ENV_READY;
@@ -215,7 +216,8 @@ int env_import(const char *buf, int check)
 		}
 	}
 
-	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
+	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
+			0, NULL, NULL)) {
 		gd->flags |= GD_FLG_ENV_READY;
 		return 1;
 	}
diff --git a/include/environment.h b/include/environment.h
index 6394a96..1936411 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -174,6 +174,13 @@ void set_default_env(const char *s);
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
+/*
+ * Check if variable "name" can be changed from oldval to newval,
+ * and if so, apply the changes (e.g. baudrate)
+ */
+int env_check_apply(const char *name, const char *oldval,
+			const char *newval, int flag);
+
 #endif
 
 #endif	/* _ENVIRONMENT_H_ */
diff --git a/include/search.h b/include/search.h
index ef53edb..2a59e03 100644
--- a/include/search.h
+++ b/include/search.h
@@ -47,6 +47,13 @@ typedef struct entry {
 struct _ENTRY;
 
 /*
+ * Callback function to be called for checking whether the given change may
+ * be applied or not. Must return 0 for approval, 1 for denial.
+ */
+typedef int (*apply_cb)(const char *name, const char *oldval,
+			const char *newval, int flag);
+
+/*
  * Family of hash table handling functions.  The functions also
  * have reentrant counterparts ending with _r.  The non-reentrant
  * functions all work on a signle internal hashing table.
@@ -94,11 +101,19 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, char **__resp, size_t __size,
 		     int argc, char * const argv[]);
 
+/*
+ * nvars, vars: variables to import (nvars == 0 means all)
+ * apply_cb: callback function to check validity of the new argument,
+ * and possibly apply changes (NULL means accept everything)
+ */
 extern int himport_r(struct hsearch_data *__htab,
 		     const char *__env, size_t __size, const char __sep,
-		     int __flag);
+		     int __flag,
+		     int nvars, char * const vars[],
+		     apply_cb apply);
 
 /* Flags for himport_r() */
 #define	H_NOCLEAR	1	/* do not clear hash table before importing */
+#define H_FORCE		2	/* overwrite read-only/write-once variables */
 
 #endif /* search.h */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index b7ba341..22421f9 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  * himport()
  */
 
+/* Check whether variable name is amongst vars[] */
+static int process_var(const char *name, int nvars, char * const vars[])
+{
+	int i = 0;
+	/* No variables specified means process all of them */
+	if (nvars == 0)
+		return 1;
+
+	for (i = 0; i < nvars; i++) {
+		if (!strcmp(name, vars[i]))
+			return 1;
+	}
+	debug("Skipping non-listed variable %s\n", name);
+	return 0;
+}
+
 /*
  * Import linearized data into hash table.
  *
@@ -639,7 +655,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  */
 
 int himport_r(struct hsearch_data *htab,
-	      const char *env, size_t size, const char sep, int flag)
+		const char *env, size_t size, const char sep, int flag,
+		int nvars, char * const vars[],
+		apply_cb apply)
 {
 	char *data, *sp, *dp, *name, *value;
 
@@ -726,6 +744,8 @@ int himport_r(struct hsearch_data *htab,
 			*dp++ = '\0';	/* terminate name */
 
 			debug("DELETE CANDIDATE: \"%s\"\n", name);
+			if (!process_var(name, nvars, vars))
+				continue;
 
 			if (hdelete_r(name, htab) == 0)
 				debug("DELETE ERROR ##############################\n");
@@ -743,10 +763,31 @@ int himport_r(struct hsearch_data *htab,
 		*sp++ = '\0';	/* terminate value */
 		++dp;
 
+		/* Skip variables which are not supposed to be treated */
+		if (!process_var(name, nvars, vars))
+			continue;
+
 		/* enter into hash table */
 		e.key = name;
 		e.data = value;
 
+		/* if there is an apply function, check what it has to say */
+		if (apply != NULL) {
+			debug("searching before calling cb function"
+				" for  %s\n", name);
+			/*
+			 * Search for variable in existing env, so to pass
+			 * its previous value to the apply callback
+			 */
+			hsearch_r(e, FIND, &rv, htab);
+			debug("previous value was %s\n", rv ? rv->data : "");
+			if (apply(name, rv ? rv->data : NULL, value, flag)) {
+				debug("callback function refused to set"
+					" variable %s, skipping it!\n", name);
+				continue;
+			}
+		}
+
 		hsearch_r(e, ENTER, &rv, htab);
 		if (rv == NULL) {
 			printf("himport_r: can't insert \"%s=%s\" into hash table\n",
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 4/5] env: check and apply changes on delete/destroy
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (2 preceding siblings ...)
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 3/5] env: unify logic to check and apply changes Gerlando Falauto
@ 2011-11-18 16:49 ` Gerlando Falauto
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 5/5] env: make "env default" selective, check and apply Gerlando Falauto
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-11-18 16:49 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |    2 +-
 include/search.h    |    6 ++++--
 lib/hashtable.c     |   18 ++++++++++++------
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index d6ea25d..128b334 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -377,7 +377,7 @@ int _do_env_set(int flag, int argc, char * const argv[])
 
 	/* Delete only ? */
 	if ((argc < 3) || argv[2] == NULL) {
-		int rc = hdelete_r(name, &env_htab);
+		int rc = hdelete_r(name, &env_htab, NULL);
 		return !rc;
 	}
 
diff --git a/include/search.h b/include/search.h
index 2a59e03..7ad4261 100644
--- a/include/search.h
+++ b/include/search.h
@@ -70,7 +70,8 @@ struct hsearch_data {
 extern int hcreate_r(size_t __nel, struct hsearch_data *__htab);
 
 /* Destroy current internal hashing table.  */
-extern void hdestroy_r(struct hsearch_data *__htab);
+extern void hdestroy_r(struct hsearch_data *__htab,
+			apply_cb apply);
 
 /*
  * Search for entry matching ITEM.key in internal hash table.  If
@@ -95,7 +96,8 @@ extern int hstrstr_r(const char *__match, int __last_idx, ENTRY ** __retval,
 		    struct hsearch_data *__htab);
 
 /* Search and delete entry matching ITEM.key in internal hash table. */
-extern int hdelete_r(const char *__key, struct hsearch_data *__htab);
+extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
+			apply_cb apply);
 
 extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, char **__resp, size_t __size,
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 22421f9..fa292e3 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -142,7 +142,8 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
  * be freed and the local static variable can be marked as not used.
  */
 
-void hdestroy_r(struct hsearch_data *htab)
+void hdestroy_r(struct hsearch_data *htab,
+		int(*apply)(const char *, const char *, const char *, int))
 {
 	int i;
 
@@ -156,7 +157,10 @@ void hdestroy_r(struct hsearch_data *htab)
 	for (i = 1; i <= htab->size; ++i) {
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-
+			if (apply != NULL) {
+				/* deletion is always forced */
+				apply(ep->key, ep->data, NULL, H_FORCE);
+			}
 			free((void *)ep->key);
 			free(ep->data);
 		}
@@ -401,7 +405,8 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
  * do that.
  */
 
-int hdelete_r(const char *key, struct hsearch_data *htab)
+int hdelete_r(const char *key, struct hsearch_data *htab,
+		int(*apply)(const char *, const char *, const char *, int))
 {
 	ENTRY e, *ep;
 	int idx;
@@ -417,7 +422,8 @@ int hdelete_r(const char *key, struct hsearch_data *htab)
 
 	/* free used ENTRY */
 	debug("hdelete: DELETING key \"%s\"\n", key);
-
+	if (apply != NULL)
+		apply(ep->key, ep->data, NULL, H_FORCE);
 	free((void *)ep->key);
 	free(ep->data);
 	htab->table[idx].used = -1;
@@ -681,7 +687,7 @@ int himport_r(struct hsearch_data *htab,
 		debug("Destroy Hash Table: %p table = %p\n", htab,
 		       htab->table);
 		if (htab->table)
-			hdestroy_r(htab);
+			hdestroy_r(htab, apply);
 	}
 
 	/*
@@ -747,7 +753,7 @@ int himport_r(struct hsearch_data *htab,
 			if (!process_var(name, nvars, vars))
 				continue;
 
-			if (hdelete_r(name, htab) == 0)
+			if (hdelete_r(name, htab, apply) == 0)
 				debug("DELETE ERROR ##############################\n");
 
 			continue;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 5/5] env: make "env default" selective, check and apply
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (3 preceding siblings ...)
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 4/5] env: check and apply changes on delete/destroy Gerlando Falauto
@ 2011-11-18 16:49 ` Gerlando Falauto
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 0/3] env: handle special variables and selective env default Gerlando Falauto
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-11-18 16:49 UTC (permalink / raw)
  To: u-boot

Changes in the syntax (user API) for "env default":
  -f: override write-once variables
  -a: all (resetting the whole env is NOT the default behavior)

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
NOTE: Since the impact in code size is really negligible, 
      I would rather remove this #ifdef CONFIG_CMD_DEFAULTENV_VARS
      conditional.

 README                   |    2 ++
 common/cmd_nvedit.c      |   44 +++++++++++++++++++++++++++++++++++++-------
 common/env_common.c      |   31 ++++++++++++++++++++++++++++++-
 include/config_cmd_all.h |    1 +
 include/environment.h    |    5 +++++
 5 files changed, 75 insertions(+), 8 deletions(-)

diff --git a/README b/README
index 07f1d11..d2b4071 100644
--- a/README
+++ b/README
@@ -724,6 +724,8 @@ The following options need to be configured:
 		CONFIG_CMD_CONSOLE	  coninfo
 		CONFIG_CMD_CRC32	* crc32
 		CONFIG_CMD_DATE		* support for RTC, date/time...
+		CONFIG_CMD_DEFAULTENV_VARS
+					* Reset individual variables to default
 		CONFIG_CMD_DHCP		* DHCP support
 		CONFIG_CMD_DIAG		* Diagnostics
 		CONFIG_CMD_DS4510	* ds4510 I2C gpio commands
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 128b334..5c57117 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -676,13 +676,40 @@ int envmatch(uchar *s1, int i2)
 	return -1;
 }
 
-static int do_env_default(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_env_default(cmd_tbl_t *cmdtp, int __flag, int argc,
+				char * const argv[])
 {
-	if ((argc != 2) || (strcmp(argv[1], "-f") != 0))
-		return cmd_usage(cmdtp);
-
-	set_default_env("## Resetting to default environment\n");
-	return 0;
+	int all = 0, flag = 0;
+	debug("Initial value for argc=%d\n", argc);
+	while (--argc > 0 && **++argv == '-') {
+		char *arg = *argv;
+		while (*++arg) {
+			switch (*arg) {
+			case 'a':		/* default all */
+				all = 1;
+				break;
+			case 'f':		/* force */
+				flag |= H_FORCE;
+				break;
+			default:
+				return cmd_usage(cmdtp);
+			}
+		}
+	}
+	debug("Final value for argc=%d\n", argc);
+	if (all && (argc == 0)) {
+		/* Reset the whole environment */
+		set_default_env("## Resetting to default environment\n");
+		return 0;
+	}
+#ifdef CONFIG_CMD_DEFAULTENV_VARS
+	if (!all && (argc > 0)) {
+		/* Reset individual variables */
+		env_default_vars(argc, argv);
+		return 0;
+	}
+#endif
+	return cmd_usage(cmdtp);
 }
 
 static int do_env_delete(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -1017,7 +1044,10 @@ U_BOOT_CMD(
 #if defined(CONFIG_CMD_ASKENV)
 	"ask name [message] [size] - ask for environment variable\nenv "
 #endif
-	"default -f - reset default environment\n"
+	"default [-f] -a - [forcibly] reset default environment\n"
+#if defined(CONFIG_CMD_DEFAULTENV_VARS)
+	"env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
+#endif
 #if defined(CONFIG_CMD_EDITENV)
 	"env edit name - edit environment variable\n"
 #endif
diff --git a/common/env_common.c b/common/env_common.c
index 9d8c59e..eca3280 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -172,6 +172,11 @@ const uchar *env_get_addr (int index)
 
 void set_default_env(const char *s)
 {
+	/*
+	 * By default, do not apply changes as they will eventually
+	 * be applied by someone else
+	 */
+	apply_cb apply_function = NULL;
 	if (sizeof(default_environment) > ENV_SIZE) {
 		puts("*** Error - default environment is too large\n\n");
 		return;
@@ -183,6 +188,14 @@ void set_default_env(const char *s)
 				"using default environment\n\n",
 				s+1);
 		} else {
+			/*
+			 * This set_to_default was explicitly asked for
+			 * by the user, as opposed to being a recovery
+			 * mechanism. Therefore we chack every single
+			 * variable and apply changes to the system
+			 * right away (e.g. baudrate, console).
+			 */
+			apply_function = env_check_apply;
 			puts(s);
 		}
 	} else {
@@ -191,12 +204,28 @@ void set_default_env(const char *s)
 
 	if (himport_r(&env_htab, (char *)default_environment,
 			sizeof(default_environment), '\0', 0,
-			0, NULL, NULL) == 0) {
+			0, NULL, apply_function) == 0) {
 		error("Environment import failed: errno = %d\n", errno);
 	}
 	gd->flags |= GD_FLG_ENV_READY;
 }
 
+#ifdef CONFIG_CMD_DEFAULTENV_VARS
+
+/* [re]set individual variables to their value in the default environment */
+int env_default_vars(int nvars, char * const vars[])
+{
+	/*
+	 * Special use-case: import from default environment
+	 * (and use \0 as a separator)
+	 */
+	return himport_r(&env_htab, (const char *)default_environment,
+				sizeof(default_environment), '\0', H_NOCLEAR,
+				nvars, vars, env_check_apply);
+}
+
+#endif /* CONFIG_CMD_DEFAULTENV_VARS */
+
 /*
  * Check if CRC is valid and (if yes) import the environment.
  * Note that "buf" may or may not be aligned.
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index 9716f9c..e728eae 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -25,6 +25,7 @@
 #define CONFIG_CMD_CDP		/* Cisco Discovery Protocol	*/
 #define CONFIG_CMD_CONSOLE	/* coninfo			*/
 #define CONFIG_CMD_DATE		/* support for RTC, date/time...*/
+#define CONFIG_CMD_DEFAULTENV_VARS /* default individ variables */
 #define CONFIG_CMD_DHCP		/* DHCP Support			*/
 #define CONFIG_CMD_DIAG		/* Diagnostics			*/
 #define CONFIG_CMD_DISPLAY	/* Display support		*/
diff --git a/include/environment.h b/include/environment.h
index 1936411..b594e67 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -171,6 +171,11 @@ void env_crc_update (void);
 /* [re]set to the default environment */
 void set_default_env(const char *s);
 
+#ifdef CONFIG_CMD_DEFAULTENV_VARS
+/* [re]set individual variables to their value in the default environment */
+int env_default_vars(int nvars, char * const vars[]);
+#endif
+
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 2/5] serial: constify serial_assign()
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 2/5] serial: constify serial_assign() Gerlando Falauto
@ 2011-11-18 20:03   ` Mike Frysinger
  2011-12-05 21:48   ` Wolfgang Denk
  1 sibling, 0 replies; 104+ messages in thread
From: Mike Frysinger @ 2011-11-18 20:03 UTC (permalink / raw)
  To: u-boot

Acked-by: Mike Frysinger <vapier@gentoo.org>
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20111118/d23faabf/attachment.pgp>

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance Gerlando Falauto
@ 2011-11-18 20:04   ` Mike Frysinger
  2011-12-05 21:47   ` Wolfgang Denk
  1 sibling, 0 replies; 104+ messages in thread
From: Mike Frysinger @ 2011-11-18 20:04 UTC (permalink / raw)
  To: u-boot

Acked-by: Mike Frysinger <vapier@gentoo.org>
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20111118/c85d4385/attachment.pgp>

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance Gerlando Falauto
  2011-11-18 20:04   ` Mike Frysinger
@ 2011-12-05 21:47   ` Wolfgang Denk
  1 sibling, 0 replies; 104+ messages in thread
From: Wolfgang Denk @ 2011-12-05 21:47 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <1321634955-5561-2-git-send-email-gerlando.falauto@keymile.com> you wrote:
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/serial.c  |   51 +++++++++++++++++++++++++--------------------------
>  include/serial.h |   19 ++++++++++---------
>  2 files changed, 35 insertions(+), 35 deletions(-)

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
You can't evaluate a man by logic alone.
	-- McCoy, "I, Mudd", stardate 4513.3

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 2/5] serial: constify serial_assign()
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 2/5] serial: constify serial_assign() Gerlando Falauto
  2011-11-18 20:03   ` Mike Frysinger
@ 2011-12-05 21:48   ` Wolfgang Denk
  1 sibling, 0 replies; 104+ messages in thread
From: Wolfgang Denk @ 2011-12-05 21:48 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <1321634955-5561-3-git-send-email-gerlando.falauto@keymile.com> you wrote:
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/serial.c  |    2 +-
>  include/serial.h |    2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)

Applied, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The human mind  ordinarily  operates  at  only  ten  percent  of  its
capacity. The rest is overhead for the operating system.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v1 3/5] env: unify logic to check and apply changes
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 3/5] env: unify logic to check and apply changes Gerlando Falauto
@ 2011-12-07  1:50   ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2011-12-07  1:50 UTC (permalink / raw)
  To: u-boot

Hi,

On Fri, Nov 18, 2011 at 8:49 AM, Gerlando Falauto
<gerlando.falauto@keymile.com> wrote:
> The logic of checking special parameters (e.g. baudrate, stdin, stdout,
> for a valid value and/or whether can be overwritten) and applying the
> new value to the running system is now all within a single function
> env_check_apply() which can be called whenever changes are made
> to the environment, no matter if by set, default or import.
>
> With this patch env_check_apply() is only called by "env set",
> retaining previous behavior.
>
> Also allow for selectively importing/resetting variables.
>
> So add 3 new arguments to himport_r():
> o "nvars", "vars":, number and list of variables to take into account
> ? (0 means ALL)
>
> o "apply" callback function to check whether a variable can be
> ?overwritten, and possibly immediately apply the changes;
> ?when NULL, no check is performed.
>
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

I haven't seen any comments on this series, but it seems good to me.
However it no longer applies - can you please rebase and resend?

Regards,
Simon

> ---
> ?common/cmd_nvedit.c ? | ?163 +++++++++++++++++++++++++++++++-----------------
> ?common/env_common.c ? | ? ?6 +-
> ?include/environment.h | ? ?7 ++
> ?include/search.h ? ? ?| ? 17 +++++-
> ?lib/hashtable.c ? ? ? | ? 43 +++++++++++++-
> ?5 files changed, 174 insertions(+), 62 deletions(-)
>
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 7194ade..d6ea25d 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -196,32 +196,23 @@ static int do_env_grep (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
> ?#endif
>
> ?/*
> - * Set a new environment variable,
> - * or replace or delete an existing one.
> + * Performs consistency checking before setting, replacing,
> + * or deleting an environment variable, then (if successful)
> + * apply the changes to internals so to make them effective.
> + * Code for this function was taken out of _do_env_set(),
> + * which now calls it.
> + * Also called as a callback function by himport_r().
> + * Returns 0 in case of success, 1 in case of failure.
> + * When (flag & H_FORCE) is set, force overwriting of
> + * write-once variables.
> ?*/
>
> -int _do_env_set (int flag, int argc, char * const argv[])
> +int env_check_apply(const char *name, const char *oldval,
> + ? ? ? ? ? ? ? ? ? ? ? const char *newval, int flag)
> ?{
> ? ? ? ?bd_t ?*bd = gd->bd;
> - ? ? ? int ? i, len;
> + ? ? ? int ? i;
> ? ? ? ?int ? console = -1;
> - ? ? ? char ?*name, *value, *s;
> - ? ? ? ENTRY e, *ep;
> -
> - ? ? ? name = argv[1];
> -
> - ? ? ? if (strchr(name, '=')) {
> - ? ? ? ? ? ? ? printf("## Error: illegal character '=' in variable name \"%s\"\n", name);
> - ? ? ? ? ? ? ? return 1;
> - ? ? ? }
> -
> - ? ? ? env_id++;
> - ? ? ? /*
> - ? ? ? ?* search if variable with this name already exists
> - ? ? ? ?*/
> - ? ? ? e.key = name;
> - ? ? ? e.data = NULL;
> - ? ? ? hsearch_r(e, FIND, &ep, &env_htab);
>
> ? ? ? ?/* Check for console redirection */
> ? ? ? ?if (strcmp(name, "stdin") == 0)
> @@ -232,22 +223,23 @@ int _do_env_set (int flag, int argc, char * const argv[])
> ? ? ? ? ? ? ? ?console = stderr;
>
> ? ? ? ?if (console != -1) {
> - ? ? ? ? ? ? ? if (argc < 3) { ? ? ? ? /* Cannot delete it! */
> + ? ? ? ? ? ? ? if ((newval == NULL) || (*newval == '\0')) {
> + ? ? ? ? ? ? ? ? ? ? ? /* We cannot delete stdin/stdout/stderr */
> ? ? ? ? ? ? ? ? ? ? ? ?printf("Can't delete \"%s\"\n", name);
> ? ? ? ? ? ? ? ? ? ? ? ?return 1;
> ? ? ? ? ? ? ? ?}
>
> ?#ifdef CONFIG_CONSOLE_MUX
> - ? ? ? ? ? ? ? i = iomux_doenv(console, argv[2]);
> + ? ? ? ? ? ? ? i = iomux_doenv(console, newval);
> ? ? ? ? ? ? ? ?if (i)
> ? ? ? ? ? ? ? ? ? ? ? ?return i;
> ?#else
> ? ? ? ? ? ? ? ?/* Try assigning specified device */
> - ? ? ? ? ? ? ? if (console_assign(console, argv[2]) < 0)
> + ? ? ? ? ? ? ? if (console_assign(console, newval) < 0)
> ? ? ? ? ? ? ? ? ? ? ? ?return 1;
>
> ?#ifdef CONFIG_SERIAL_MULTI
> - ? ? ? ? ? ? ? if (serial_assign(argv[2]) < 0)
> + ? ? ? ? ? ? ? if (serial_assign(newval) < 0)
> ? ? ? ? ? ? ? ? ? ? ? ?return 1;
> ?#endif
> ?#endif /* CONFIG_CONSOLE_MUX */
> @@ -255,25 +247,35 @@ int _do_env_set (int flag, int argc, char * const argv[])
>
> ? ? ? ?/*
> ? ? ? ? * Some variables like "ethaddr" and "serial#" can be set only
> - ? ? ? ?* once and cannot be deleted; also, "ver" is readonly.
> + ? ? ? ?* once and cannot be deleted, unless CONFIG_ENV_OVERWRITE
> + ? ? ? ?* is defined.
> ? ? ? ? */
> - ? ? ? if (ep) { ? ? ? ? ? ? ? /* variable exists */
> ?#ifndef CONFIG_ENV_OVERWRITE
> + ? ? ? if (oldval != NULL && ? ? ? ? ? ? ? ? ? /* variable exists */
> + ? ? ? ? ? ? ? (flag & H_FORCE) == 0) { ? ? ? ?/* and we are not forced */
> ? ? ? ? ? ? ? ?if ((strcmp(name, "serial#") == 0) ||
> ? ? ? ? ? ? ? ? ? ?((strcmp(name, "ethaddr") == 0)
> ?#if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
> - ? ? ? ? ? ? ? ? ? ?&& (strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0)
> + ? ? ? ? ? ? ? ? ? ?&& (strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0)
> ?#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
> ? ? ? ? ? ? ? ? ? ?) ) {
> ? ? ? ? ? ? ? ? ? ? ? ?printf("Can't overwrite \"%s\"\n", name);
> ? ? ? ? ? ? ? ? ? ? ? ?return 1;
> ? ? ? ? ? ? ? ?}
> + ? ? ? }
> ?#endif
> + ? ? ? /*
> + ? ? ? ?* When we change baudrate, or we are doing an env default -a
> + ? ? ? ?* (which will erase all variables prior to calling this),
> + ? ? ? ?* we want the baudrate to actually change - for real.
> + ? ? ? ?*/
> + ? ? ? if (oldval != NULL || ? ? ? ? ? ? ? ? ? /* variable exists */
> + ? ? ? ? ? ? ? (flag & H_NOCLEAR) == 0) { ? ? ?/* or env is clear */
> ? ? ? ? ? ? ? ?/*
> ? ? ? ? ? ? ? ? * Switch to new baudrate if new baudrate is supported
> ? ? ? ? ? ? ? ? */
> ? ? ? ? ? ? ? ?if (strcmp(name, "baudrate") == 0) {
> - ? ? ? ? ? ? ? ? ? ? ? int baudrate = simple_strtoul(argv[2], NULL, 10);
> + ? ? ? ? ? ? ? ? ? ? ? int baudrate = simple_strtoul(newval, NULL, 10);
> ? ? ? ? ? ? ? ? ? ? ? ?int i;
> ? ? ? ? ? ? ? ? ? ? ? ?for (i = 0; i < N_BAUDRATES; ++i) {
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (baudrate == baudrate_table[i])
> @@ -284,6 +286,10 @@ int _do_env_set (int flag, int argc, char * const argv[])
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?baudrate);
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return 1;
> ? ? ? ? ? ? ? ? ? ? ? ?}
> + ? ? ? ? ? ? ? ? ? ? ? if (gd->baudrate == baudrate) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* If unchanged, we just say it's OK */
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return 0;
> + ? ? ? ? ? ? ? ? ? ? ? }
> ? ? ? ? ? ? ? ? ? ? ? ?printf ("## Switch baudrate to %d bps and press ENTER ...\n",
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?baudrate);
> ? ? ? ? ? ? ? ? ? ? ? ?udelay(50000);
> @@ -301,6 +307,74 @@ int _do_env_set (int flag, int argc, char * const argv[])
> ? ? ? ? ? ? ? ?}
> ? ? ? ?}
>
> + ? ? ? /*
> + ? ? ? ?* Some variables should be updated when the corresponding
> + ? ? ? ?* entry in the environment is changed
> + ? ? ? ?*/
> +
> + ? ? ? if (strcmp(name, "ipaddr") == 0) {
> + ? ? ? ? ? ? ? const char *s = newval;
> + ? ? ? ? ? ? ? char *e;
> + ? ? ? ? ? ? ? unsigned long addr;
> + ? ? ? ? ? ? ? bd->bi_ip_addr = 0;
> + ? ? ? ? ? ? ? for (addr = 0, i = 0; i < 4; ++i) {
> + ? ? ? ? ? ? ? ? ? ? ? ulong val = s ? simple_strtoul(s, &e, 10) : 0;
> + ? ? ? ? ? ? ? ? ? ? ? addr <<= 8;
> + ? ? ? ? ? ? ? ? ? ? ? addr ?|= (val & 0xFF);
> + ? ? ? ? ? ? ? ? ? ? ? if (s)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? s = (*e) ? e+1 : e;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? bd->bi_ip_addr = htonl(addr);
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? } else if (strcmp(newval, "loadaddr") == 0) {
> + ? ? ? ? ? ? ? load_addr = simple_strtoul(newval, NULL, 16);
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? }
> +#if defined(CONFIG_CMD_NET)
> + ? ? ? else if (strcmp(newval, "bootfile") == 0) {
> + ? ? ? ? ? ? ? copy_filename(BootFile, newval, sizeof(BootFile));
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? }
> +#endif
> + ? ? ? return 0;
> +}
> +
> +/*
> + * Set a new environment variable,
> + * or replace or delete an existing one.
> +*/
> +int _do_env_set(int flag, int argc, char * const argv[])
> +{
> + ? ? ? int ? i, len;
> + ? ? ? char ?*name, *value, *s;
> + ? ? ? ENTRY e, *ep;
> +
> + ? ? ? name = argv[1];
> + ? ? ? value = argv[2];
> +
> + ? ? ? if (strchr(name, '=')) {
> + ? ? ? ? ? ? ? printf("## Error: illegal character '='"
> + ? ? ? ? ? ? ? ? ? ? ?"in variable name \"%s\"\n", name);
> + ? ? ? ? ? ? ? return 1;
> + ? ? ? }
> +
> + ? ? ? env_id++;
> + ? ? ? /*
> + ? ? ? ?* search if variable with this name already exists
> + ? ? ? ?*/
> + ? ? ? e.key = name;
> + ? ? ? e.data = NULL;
> + ? ? ? hsearch_r(e, FIND, &ep, &env_htab);
> +
> + ? ? ? /*
> + ? ? ? ?* Perform requested checks. Notice how since we are overwriting
> + ? ? ? ?* a single variable, we need to set H_NOCLEAR
> + ? ? ? ?*/
> + ? ? ? if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
> + ? ? ? ? ? ? ? debug("check function did not approve, refusing\n");
> + ? ? ? ? ? ? ? return 1;
> + ? ? ? }
> +
> ? ? ? ?/* Delete only ? */
> ? ? ? ?if ((argc < 3) || argv[2] == NULL) {
> ? ? ? ? ? ? ? ?int rc = hdelete_r(name, &env_htab);
> @@ -338,34 +412,6 @@ int _do_env_set (int flag, int argc, char * const argv[])
> ? ? ? ? ? ? ? ?return 1;
> ? ? ? ?}
>
> - ? ? ? /*
> - ? ? ? ?* Some variables should be updated when the corresponding
> - ? ? ? ?* entry in the environment is changed
> - ? ? ? ?*/
> -
> - ? ? ? if (strcmp(name, "ipaddr") == 0) {
> - ? ? ? ? ? ? ? char *s = argv[2]; ? ? ?/* always use only one arg */
> - ? ? ? ? ? ? ? char *e;
> - ? ? ? ? ? ? ? unsigned long addr;
> - ? ? ? ? ? ? ? bd->bi_ip_addr = 0;
> - ? ? ? ? ? ? ? for (addr = 0, i = 0; i < 4; ++i) {
> - ? ? ? ? ? ? ? ? ? ? ? ulong val = s ? simple_strtoul(s, &e, 10) : 0;
> - ? ? ? ? ? ? ? ? ? ? ? addr <<= 8;
> - ? ? ? ? ? ? ? ? ? ? ? addr ?|= (val & 0xFF);
> - ? ? ? ? ? ? ? ? ? ? ? if (s) s = (*e) ? e+1 : e;
> - ? ? ? ? ? ? ? }
> - ? ? ? ? ? ? ? bd->bi_ip_addr = htonl(addr);
> - ? ? ? ? ? ? ? return 0;
> - ? ? ? } else if (strcmp(argv[1], "loadaddr") == 0) {
> - ? ? ? ? ? ? ? load_addr = simple_strtoul(argv[2], NULL, 16);
> - ? ? ? ? ? ? ? return 0;
> - ? ? ? }
> -#if defined(CONFIG_CMD_NET)
> - ? ? ? else if (strcmp(argv[1], "bootfile") == 0) {
> - ? ? ? ? ? ? ? copy_filename(BootFile, argv[2], sizeof(BootFile));
> - ? ? ? ? ? ? ? return 0;
> - ? ? ? }
> -#endif
> ? ? ? ?return 0;
> ?}
>
> @@ -888,7 +934,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
> ? ? ? ? ? ? ? ?addr = (char *)ep->data;
> ? ? ? ?}
>
> - ? ? ? if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
> + ? ? ? if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
> + ? ? ? ? ? ? ? ? ? ? ? 0, NULL, NULL) == 0) {
> ? ? ? ? ? ? ? ?error("Environment import failed: errno = %d\n", errno);
> ? ? ? ? ? ? ? ?return 1;
> ? ? ? ?}
> diff --git a/common/env_common.c b/common/env_common.c
> index c7e9bea..9d8c59e 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -190,7 +190,8 @@ void set_default_env(const char *s)
> ? ? ? ?}
>
> ? ? ? ?if (himport_r(&env_htab, (char *)default_environment,
> - ? ? ? ? ? ? ? ? ? sizeof(default_environment), '\0', 0) == 0) {
> + ? ? ? ? ? ? ? ? ? ? ? sizeof(default_environment), '\0', 0,
> + ? ? ? ? ? ? ? ? ? ? ? 0, NULL, NULL) == 0) {
> ? ? ? ? ? ? ? ?error("Environment import failed: errno = %d\n", errno);
> ? ? ? ?}
> ? ? ? ?gd->flags |= GD_FLG_ENV_READY;
> @@ -215,7 +216,8 @@ int env_import(const char *buf, int check)
> ? ? ? ? ? ? ? ?}
> ? ? ? ?}
>
> - ? ? ? if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
> + ? ? ? if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
> + ? ? ? ? ? ? ? ? ? ? ? 0, NULL, NULL)) {
> ? ? ? ? ? ? ? ?gd->flags |= GD_FLG_ENV_READY;
> ? ? ? ? ? ? ? ?return 1;
> ? ? ? ?}
> diff --git a/include/environment.h b/include/environment.h
> index 6394a96..1936411 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -174,6 +174,13 @@ void set_default_env(const char *s);
> ?/* Import from binary representation into hash table */
> ?int env_import(const char *buf, int check);
>
> +/*
> + * Check if variable "name" can be changed from oldval to newval,
> + * and if so, apply the changes (e.g. baudrate)
> + */
> +int env_check_apply(const char *name, const char *oldval,
> + ? ? ? ? ? ? ? ? ? ? ? const char *newval, int flag);
> +
> ?#endif
>
> ?#endif /* _ENVIRONMENT_H_ */
> diff --git a/include/search.h b/include/search.h
> index ef53edb..2a59e03 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -47,6 +47,13 @@ typedef struct entry {
> ?struct _ENTRY;
>
> ?/*
> + * Callback function to be called for checking whether the given change may
> + * be applied or not. Must return 0 for approval, 1 for denial.
> + */
> +typedef int (*apply_cb)(const char *name, const char *oldval,
> + ? ? ? ? ? ? ? ? ? ? ? const char *newval, int flag);
> +
> +/*
> ?* Family of hash table handling functions. ?The functions also
> ?* have reentrant counterparts ending with _r. ?The non-reentrant
> ?* functions all work on a signle internal hashing table.
> @@ -94,11 +101,19 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
> ? ? ? ? ? ? ? ? ? ? const char __sep, char **__resp, size_t __size,
> ? ? ? ? ? ? ? ? ? ? int argc, char * const argv[]);
>
> +/*
> + * nvars, vars: variables to import (nvars == 0 means all)
> + * apply_cb: callback function to check validity of the new argument,
> + * and possibly apply changes (NULL means accept everything)
> + */
> ?extern int himport_r(struct hsearch_data *__htab,
> ? ? ? ? ? ? ? ? ? ? const char *__env, size_t __size, const char __sep,
> - ? ? ? ? ? ? ? ? ? ?int __flag);
> + ? ? ? ? ? ? ? ? ? ?int __flag,
> + ? ? ? ? ? ? ? ? ? ?int nvars, char * const vars[],
> + ? ? ? ? ? ? ? ? ? ?apply_cb apply);
>
> ?/* Flags for himport_r() */
> ?#define ? ? ? ?H_NOCLEAR ? ? ? 1 ? ? ? /* do not clear hash table before importing */
> +#define H_FORCE ? ? ? ? ? ? ? ?2 ? ? ? /* overwrite read-only/write-once variables */
>
> ?#endif /* search.h */
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index b7ba341..22421f9 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
> ?* himport()
> ?*/
>
> +/* Check whether variable name is amongst vars[] */
> +static int process_var(const char *name, int nvars, char * const vars[])
> +{
> + ? ? ? int i = 0;
> + ? ? ? /* No variables specified means process all of them */
> + ? ? ? if (nvars == 0)
> + ? ? ? ? ? ? ? return 1;
> +
> + ? ? ? for (i = 0; i < nvars; i++) {
> + ? ? ? ? ? ? ? if (!strcmp(name, vars[i]))
> + ? ? ? ? ? ? ? ? ? ? ? return 1;
> + ? ? ? }
> + ? ? ? debug("Skipping non-listed variable %s\n", name);
> + ? ? ? return 0;
> +}
> +
> ?/*
> ?* Import linearized data into hash table.
> ?*
> @@ -639,7 +655,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
> ?*/
>
> ?int himport_r(struct hsearch_data *htab,
> - ? ? ? ? ? ? const char *env, size_t size, const char sep, int flag)
> + ? ? ? ? ? ? ? const char *env, size_t size, const char sep, int flag,
> + ? ? ? ? ? ? ? int nvars, char * const vars[],
> + ? ? ? ? ? ? ? apply_cb apply)
> ?{
> ? ? ? ?char *data, *sp, *dp, *name, *value;
>
> @@ -726,6 +744,8 @@ int himport_r(struct hsearch_data *htab,
> ? ? ? ? ? ? ? ? ? ? ? ?*dp++ = '\0'; ? /* terminate name */
>
> ? ? ? ? ? ? ? ? ? ? ? ?debug("DELETE CANDIDATE: \"%s\"\n", name);
> + ? ? ? ? ? ? ? ? ? ? ? if (!process_var(name, nvars, vars))
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
>
> ? ? ? ? ? ? ? ? ? ? ? ?if (hdelete_r(name, htab) == 0)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?debug("DELETE ERROR ##############################\n");
> @@ -743,10 +763,31 @@ int himport_r(struct hsearch_data *htab,
> ? ? ? ? ? ? ? ?*sp++ = '\0'; ? /* terminate value */
> ? ? ? ? ? ? ? ?++dp;
>
> + ? ? ? ? ? ? ? /* Skip variables which are not supposed to be treated */
> + ? ? ? ? ? ? ? if (!process_var(name, nvars, vars))
> + ? ? ? ? ? ? ? ? ? ? ? continue;
> +
> ? ? ? ? ? ? ? ?/* enter into hash table */
> ? ? ? ? ? ? ? ?e.key = name;
> ? ? ? ? ? ? ? ?e.data = value;
>
> + ? ? ? ? ? ? ? /* if there is an apply function, check what it has to say */
> + ? ? ? ? ? ? ? if (apply != NULL) {
> + ? ? ? ? ? ? ? ? ? ? ? debug("searching before calling cb function"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " for ?%s\n", name);
> + ? ? ? ? ? ? ? ? ? ? ? /*
> + ? ? ? ? ? ? ? ? ? ? ? ?* Search for variable in existing env, so to pass
> + ? ? ? ? ? ? ? ? ? ? ? ?* its previous value to the apply callback
> + ? ? ? ? ? ? ? ? ? ? ? ?*/
> + ? ? ? ? ? ? ? ? ? ? ? hsearch_r(e, FIND, &rv, htab);
> + ? ? ? ? ? ? ? ? ? ? ? debug("previous value was %s\n", rv ? rv->data : "");
> + ? ? ? ? ? ? ? ? ? ? ? if (apply(name, rv ? rv->data : NULL, value, flag)) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? debug("callback function refused to set"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " variable %s, skipping it!\n", name);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? }
> +
> ? ? ? ? ? ? ? ?hsearch_r(e, ENTER, &rv, htab);
> ? ? ? ? ? ? ? ?if (rv == NULL) {
> ? ? ? ? ? ? ? ? ? ? ? ?printf("himport_r: can't insert \"%s=%s\" into hash table\n",
> --
> 1.7.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 0/3] env: handle special variables and selective env default
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (4 preceding siblings ...)
  2011-11-18 16:49 ` [U-Boot] [PATCH v1 5/5] env: make "env default" selective, check and apply Gerlando Falauto
@ 2011-12-07 13:30 ` Gerlando Falauto
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes Gerlando Falauto
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-07 13:30 UTC (permalink / raw)
  To: u-boot

This patchset modifies the handling of all the operations on the environment
(set/import/default) so to unify handling of special variables.
On top of that we implement a selective "env default".

A selective "env import" would imply a user API change and should therefore
be discussed separately.

Changes in the syntax (user API):
- "env default" -f: override write-once variables, -a means all

Changes from v1:
- removed cosmetic patches (now mainstream)
- rebased to latest trunk
- removed subtle error in env_check_apply
  (comparing {loadaddr, bootfile} to values instead
  of variable names)
- changed env_check_apply so not to display warnings
  in case of H_FORCE flag being set

Changes from v0
- checkpatch cleanup
- removed himport_ex()
- removed warning for serial_assign()
- env import NOT implemented here

Gerlando Falauto (3):
  env: unify logic to check and apply changes
  env: check and apply changes on delete/destroy
  env: make "env default" selective, check and apply

 README                   |    2 +
 common/cmd_nvedit.c      |  219 +++++++++++++++++++++++++++++++---------------
 common/env_common.c      |   35 +++++++-
 include/config_cmd_all.h |    1 +
 include/environment.h    |   12 +++
 include/search.h         |   23 ++++-
 lib/hashtable.c          |   61 +++++++++++--
 7 files changed, 270 insertions(+), 83 deletions(-)

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (5 preceding siblings ...)
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 0/3] env: handle special variables and selective env default Gerlando Falauto
@ 2011-12-07 13:30 ` Gerlando Falauto
  2011-12-07 22:02   ` Simon Glass
  2012-03-29 20:19   ` Marek Vasut
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy Gerlando Falauto
                   ` (9 subsequent siblings)
  16 siblings, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-07 13:30 UTC (permalink / raw)
  To: u-boot

The logic of checking special parameters (e.g. baudrate, stdin, stdout,
for a valid value and/or whether can be overwritten) and applying the
new value to the running system is now all within a single function
env_check_apply() which can be called whenever changes are made
to the environment, no matter if by set, default or import.

With this patch env_check_apply() is only called by "env set",
retaining previous behavior.

Also allow for selectively importing/resetting variables.

So add 3 new arguments to himport_r():
o "nvars", "vars":, number and list of variables to take into account
   (0 means ALL)

o "apply" callback function to check whether a variable can be
  overwritten, and possibly immediately apply the changes;
  when NULL, no check is performed.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c   |  174 +++++++++++++++++++++++++++++++------------------
 common/env_common.c   |    6 +-
 include/environment.h |    7 ++
 include/search.h      |   17 +++++-
 lib/hashtable.c       |   43 ++++++++++++-
 5 files changed, 180 insertions(+), 67 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 5995354..a31d413 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -197,32 +197,23 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 #endif
 
 /*
- * Set a new environment variable,
- * or replace or delete an existing one.
+ * Performs consistency checking before setting, replacing,
+ * or deleting an environment variable, then (if successful)
+ * apply the changes to internals so to make them effective.
+ * Code for this function was taken out of _do_env_set(),
+ * which now calls it.
+ * Also called as a callback function by himport_r().
+ * Returns 0 in case of success, 1 in case of failure.
+ * When (flag & H_FORCE) is set, force overwriting of
+ * write-once variables.
  */
-int _do_env_set(int flag, int argc, char * const argv[])
+
+int env_check_apply(const char *name, const char *oldval,
+			const char *newval, int flag)
 {
 	bd_t  *bd = gd->bd;
-	int   i, len;
+	int   i;
 	int   console = -1;
-	char  *name, *value, *s;
-	ENTRY e, *ep;
-
-	name = argv[1];
-
-	if (strchr(name, '=')) {
-		printf("## Error: illegal character '=' in variable name"
-		       "\"%s\"\n", name);
-		return 1;
-	}
-
-	env_id++;
-	/*
-	 * search if variable with this name already exists
-	 */
-	e.key = name;
-	e.data = NULL;
-	hsearch_r(e, FIND, &ep, &env_htab);
 
 	/* Check for console redirection */
 	if (strcmp(name, "stdin") == 0)
@@ -233,22 +224,24 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		console = stderr;
 
 	if (console != -1) {
-		if (argc < 3) {		/* Cannot delete it! */
-			printf("Can't delete \"%s\"\n", name);
+		if ((newval == NULL) || (*newval == '\0')) {
+			/* We cannot delete stdin/stdout/stderr */
+			if ((flag & H_FORCE) == 0)
+				printf("Can't delete \"%s\"\n", name);
 			return 1;
 		}
 
 #ifdef CONFIG_CONSOLE_MUX
-		i = iomux_doenv(console, argv[2]);
+		i = iomux_doenv(console, newval);
 		if (i)
 			return i;
 #else
 		/* Try assigning specified device */
-		if (console_assign(console, argv[2]) < 0)
+		if (console_assign(console, newval) < 0)
 			return 1;
 
 #ifdef CONFIG_SERIAL_MULTI
-		if (serial_assign(argv[2]) < 0)
+		if (serial_assign(newval) < 0)
 			return 1;
 #endif
 #endif /* CONFIG_CONSOLE_MUX */
@@ -256,37 +249,52 @@ int _do_env_set(int flag, int argc, char * const argv[])
 
 	/*
 	 * Some variables like "ethaddr" and "serial#" can be set only
-	 * once and cannot be deleted; also, "ver" is readonly.
+	 * once and cannot be deleted, unless CONFIG_ENV_OVERWRITE
+	 * is defined.
 	 */
-	if (ep) {		/* variable exists */
 #ifndef CONFIG_ENV_OVERWRITE
+	if (oldval != NULL &&			/* variable exists */
+		(flag & H_FORCE) == 0) {	/* and we are not forced */
 		if (strcmp(name, "serial#") == 0 ||
 		    (strcmp(name, "ethaddr") == 0
 #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
-		     && strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0
+		     && strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0
 #endif	/* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
 			)) {
 			printf("Can't overwrite \"%s\"\n", name);
 			return 1;
 		}
+	}
 #endif
+	/*
+	 * When we change baudrate, or we are doing an env default -a
+	 * (which will erase all variables prior to calling this),
+	 * we want the baudrate to actually change - for real.
+	 */
+	if (oldval != NULL ||			/* variable exists */
+		(flag & H_NOCLEAR) == 0) {	/* or env is clear */
 		/*
 		 * Switch to new baudrate if new baudrate is supported
 		 */
 		if (strcmp(name, "baudrate") == 0) {
-			int baudrate = simple_strtoul(argv[2], NULL, 10);
+			int baudrate = simple_strtoul(newval, NULL, 10);
 			int i;
 			for (i = 0; i < N_BAUDRATES; ++i) {
 				if (baudrate == baudrate_table[i])
 					break;
 			}
 			if (i == N_BAUDRATES) {
-				printf("## Baudrate %d bps not supported\n",
-					baudrate);
+				if ((flag & H_FORCE) == 0)
+					printf("## Baudrate %d bps not "
+						"supported\n", baudrate);
 				return 1;
 			}
+			if (gd->baudrate == baudrate) {
+				/* If unchanged, we just say it's OK */
+				return 0;
+			}
 			printf("## Switch baudrate to %d bps and"
-			       "press ENTER ...\n", baudrate);
+				"press ENTER ...\n", baudrate);
 			udelay(50000);
 			gd->baudrate = baudrate;
 #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
@@ -300,6 +308,73 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		}
 	}
 
+	/*
+	 * Some variables should be updated when the corresponding
+	 * entry in the environment is changed
+	 */
+	if (strcmp(name, "ipaddr") == 0) {
+		const char *s = newval;
+		char *e;
+		unsigned long addr;
+		bd->bi_ip_addr = 0;
+		for (addr = 0, i = 0; i < 4; ++i) {
+			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
+			addr <<= 8;
+			addr  |= val & 0xFF;
+			if (s)
+				s = *e ? e + 1 : e;
+		}
+		bd->bi_ip_addr = htonl(addr);
+		return 0;
+	} else if (strcmp(name, "loadaddr") == 0) {
+		load_addr = simple_strtoul(newval, NULL, 16);
+		return 0;
+	}
+#if defined(CONFIG_CMD_NET)
+	else if (strcmp(name, "bootfile") == 0) {
+		copy_filename(BootFile, newval, sizeof(BootFile));
+		return 0;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Set a new environment variable,
+ * or replace or delete an existing one.
+*/
+int _do_env_set(int flag, int argc, char * const argv[])
+{
+	int   i, len;
+	char  *name, *value, *s;
+	ENTRY e, *ep;
+
+	name = argv[1];
+	value = argv[2];
+
+	if (strchr(name, '=')) {
+		printf("## Error: illegal character '='"
+		       "in variable name \"%s\"\n", name);
+		return 1;
+	}
+
+	env_id++;
+	/*
+	 * search if variable with this name already exists
+	 */
+	e.key = name;
+	e.data = NULL;
+	hsearch_r(e, FIND, &ep, &env_htab);
+
+	/*
+	 * Perform requested checks. Notice how since we are overwriting
+	 * a single variable, we need to set H_NOCLEAR
+	 */
+	if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
+		debug("check function did not approve, refusing\n");
+		return 1;
+	}
+
 	/* Delete only ? */
 	if (argc < 3 || argv[2] == NULL) {
 		int rc = hdelete_r(name, &env_htab);
@@ -337,34 +412,6 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		return 1;
 	}
 
-	/*
-	 * Some variables should be updated when the corresponding
-	 * entry in the environment is changed
-	 */
-	if (strcmp(name, "ipaddr") == 0) {
-		char *s = argv[2];	/* always use only one arg */
-		char *e;
-		unsigned long addr;
-		bd->bi_ip_addr = 0;
-		for (addr = 0, i = 0; i < 4; ++i) {
-			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
-			addr <<= 8;
-			addr  |= val & 0xFF;
-			if (s)
-				s = *e ? e + 1 : e;
-		}
-		bd->bi_ip_addr = htonl(addr);
-		return 0;
-	} else if (strcmp(argv[1], "loadaddr") == 0) {
-		load_addr = simple_strtoul(argv[2], NULL, 16);
-		return 0;
-	}
-#if defined(CONFIG_CMD_NET)
-	else if (strcmp(argv[1], "bootfile") == 0) {
-		copy_filename(BootFile, argv[2], sizeof(BootFile));
-		return 0;
-	}
-#endif
 	return 0;
 }
 
@@ -886,7 +933,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
 		addr = (char *)ep->data;
 	}
 
-	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
+	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
+			0, NULL, NULL) == 0) {
 		error("Environment import failed: errno = %d\n", errno);
 		return 1;
 	}
diff --git a/common/env_common.c b/common/env_common.c
index 8a71096..7e2bb2f 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -175,7 +175,8 @@ void set_default_env(const char *s)
 	}
 
 	if (himport_r(&env_htab, (char *)default_environment,
-			sizeof(default_environment), '\0', 0) == 0)
+			sizeof(default_environment), '\0', 0,
+			0, NULL, NULL) == 0)
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
@@ -200,7 +201,8 @@ int env_import(const char *buf, int check)
 		}
 	}
 
-	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
+	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
+			0, NULL, NULL)) {
 		gd->flags |= GD_FLG_ENV_READY;
 		return 1;
 	}
diff --git a/include/environment.h b/include/environment.h
index 3c145af..3a3e6b8 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -193,6 +193,13 @@ void set_default_env(const char *s);
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
+/*
+ * Check if variable "name" can be changed from oldval to newval,
+ * and if so, apply the changes (e.g. baudrate)
+ */
+int env_check_apply(const char *name, const char *oldval,
+			const char *newval, int flag);
+
 #endif /* DO_DEPS_ONLY */
 
 #endif /* _ENVIRONMENT_H_ */
diff --git a/include/search.h b/include/search.h
index ef53edb..2a59e03 100644
--- a/include/search.h
+++ b/include/search.h
@@ -47,6 +47,13 @@ typedef struct entry {
 struct _ENTRY;
 
 /*
+ * Callback function to be called for checking whether the given change may
+ * be applied or not. Must return 0 for approval, 1 for denial.
+ */
+typedef int (*apply_cb)(const char *name, const char *oldval,
+			const char *newval, int flag);
+
+/*
  * Family of hash table handling functions.  The functions also
  * have reentrant counterparts ending with _r.  The non-reentrant
  * functions all work on a signle internal hashing table.
@@ -94,11 +101,19 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, char **__resp, size_t __size,
 		     int argc, char * const argv[]);
 
+/*
+ * nvars, vars: variables to import (nvars == 0 means all)
+ * apply_cb: callback function to check validity of the new argument,
+ * and possibly apply changes (NULL means accept everything)
+ */
 extern int himport_r(struct hsearch_data *__htab,
 		     const char *__env, size_t __size, const char __sep,
-		     int __flag);
+		     int __flag,
+		     int nvars, char * const vars[],
+		     apply_cb apply);
 
 /* Flags for himport_r() */
 #define	H_NOCLEAR	1	/* do not clear hash table before importing */
+#define H_FORCE		2	/* overwrite read-only/write-once variables */
 
 #endif /* search.h */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index abd61c8..75b9b07 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  * himport()
  */
 
+/* Check whether variable name is amongst vars[] */
+static int process_var(const char *name, int nvars, char * const vars[])
+{
+	int i = 0;
+	/* No variables specified means process all of them */
+	if (nvars == 0)
+		return 1;
+
+	for (i = 0; i < nvars; i++) {
+		if (!strcmp(name, vars[i]))
+			return 1;
+	}
+	debug("Skipping non-listed variable %s\n", name);
+	return 0;
+}
+
 /*
  * Import linearized data into hash table.
  *
@@ -639,7 +655,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  */
 
 int himport_r(struct hsearch_data *htab,
-	      const char *env, size_t size, const char sep, int flag)
+		const char *env, size_t size, const char sep, int flag,
+		int nvars, char * const vars[],
+		apply_cb apply)
 {
 	char *data, *sp, *dp, *name, *value;
 
@@ -726,6 +744,8 @@ int himport_r(struct hsearch_data *htab,
 			*dp++ = '\0';	/* terminate name */
 
 			debug("DELETE CANDIDATE: \"%s\"\n", name);
+			if (!process_var(name, nvars, vars))
+				continue;
 
 			if (hdelete_r(name, htab) == 0)
 				debug("DELETE ERROR ##############################\n");
@@ -743,10 +763,31 @@ int himport_r(struct hsearch_data *htab,
 		*sp++ = '\0';	/* terminate value */
 		++dp;
 
+		/* Skip variables which are not supposed to be treated */
+		if (!process_var(name, nvars, vars))
+			continue;
+
 		/* enter into hash table */
 		e.key = name;
 		e.data = value;
 
+		/* if there is an apply function, check what it has to say */
+		if (apply != NULL) {
+			debug("searching before calling cb function"
+				" for  %s\n", name);
+			/*
+			 * Search for variable in existing env, so to pass
+			 * its previous value to the apply callback
+			 */
+			hsearch_r(e, FIND, &rv, htab);
+			debug("previous value was %s\n", rv ? rv->data : "");
+			if (apply(name, rv ? rv->data : NULL, value, flag)) {
+				debug("callback function refused to set"
+					" variable %s, skipping it!\n", name);
+				continue;
+			}
+		}
+
 		hsearch_r(e, ENTER, &rv, htab);
 		if (rv == NULL) {
 			printf("himport_r: can't insert \"%s=%s\" into hash table\n",
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (6 preceding siblings ...)
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes Gerlando Falauto
@ 2011-12-07 13:30 ` Gerlando Falauto
  2011-12-07 22:02   ` Simon Glass
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply Gerlando Falauto
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-07 13:30 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |    2 +-
 include/search.h    |    6 ++++--
 lib/hashtable.c     |   18 ++++++++++++------
 3 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index a31d413..871b3b1 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -377,7 +377,7 @@ int _do_env_set(int flag, int argc, char * const argv[])
 
 	/* Delete only ? */
 	if (argc < 3 || argv[2] == NULL) {
-		int rc = hdelete_r(name, &env_htab);
+		int rc = hdelete_r(name, &env_htab, NULL);
 		return !rc;
 	}
 
diff --git a/include/search.h b/include/search.h
index 2a59e03..7ad4261 100644
--- a/include/search.h
+++ b/include/search.h
@@ -70,7 +70,8 @@ struct hsearch_data {
 extern int hcreate_r(size_t __nel, struct hsearch_data *__htab);
 
 /* Destroy current internal hashing table.  */
-extern void hdestroy_r(struct hsearch_data *__htab);
+extern void hdestroy_r(struct hsearch_data *__htab,
+			apply_cb apply);
 
 /*
  * Search for entry matching ITEM.key in internal hash table.  If
@@ -95,7 +96,8 @@ extern int hstrstr_r(const char *__match, int __last_idx, ENTRY ** __retval,
 		    struct hsearch_data *__htab);
 
 /* Search and delete entry matching ITEM.key in internal hash table. */
-extern int hdelete_r(const char *__key, struct hsearch_data *__htab);
+extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
+			apply_cb apply);
 
 extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, char **__resp, size_t __size,
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 75b9b07..87adc01 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -142,7 +142,8 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
  * be freed and the local static variable can be marked as not used.
  */
 
-void hdestroy_r(struct hsearch_data *htab)
+void hdestroy_r(struct hsearch_data *htab,
+		int(*apply)(const char *, const char *, const char *, int))
 {
 	int i;
 
@@ -156,7 +157,10 @@ void hdestroy_r(struct hsearch_data *htab)
 	for (i = 1; i <= htab->size; ++i) {
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-
+			if (apply != NULL) {
+				/* deletion is always forced */
+				apply(ep->key, ep->data, NULL, H_FORCE);
+			}
 			free((void *)ep->key);
 			free(ep->data);
 		}
@@ -401,7 +405,8 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
  * do that.
  */
 
-int hdelete_r(const char *key, struct hsearch_data *htab)
+int hdelete_r(const char *key, struct hsearch_data *htab,
+		int(*apply)(const char *, const char *, const char *, int))
 {
 	ENTRY e, *ep;
 	int idx;
@@ -417,7 +422,8 @@ int hdelete_r(const char *key, struct hsearch_data *htab)
 
 	/* free used ENTRY */
 	debug("hdelete: DELETING key \"%s\"\n", key);
-
+	if (apply != NULL)
+		apply(ep->key, ep->data, NULL, H_FORCE);
 	free((void *)ep->key);
 	free(ep->data);
 	htab->table[idx].used = -1;
@@ -681,7 +687,7 @@ int himport_r(struct hsearch_data *htab,
 		debug("Destroy Hash Table: %p table = %p\n", htab,
 		       htab->table);
 		if (htab->table)
-			hdestroy_r(htab);
+			hdestroy_r(htab, apply);
 	}
 
 	/*
@@ -747,7 +753,7 @@ int himport_r(struct hsearch_data *htab,
 			if (!process_var(name, nvars, vars))
 				continue;
 
-			if (hdelete_r(name, htab) == 0)
+			if (hdelete_r(name, htab, apply) == 0)
 				debug("DELETE ERROR ##############################\n");
 
 			continue;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (7 preceding siblings ...)
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy Gerlando Falauto
@ 2011-12-07 13:30 ` Gerlando Falauto
  2011-12-07 22:02   ` Simon Glass
  2012-03-29 20:25   ` Marek Vasut
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default Gerlando Falauto
                   ` (7 subsequent siblings)
  16 siblings, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-07 13:30 UTC (permalink / raw)
  To: u-boot

Changes in the syntax (user API) for "env default":
  -f: override write-once variables
  -a: all (resetting the whole env is NOT the default behavior)

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 README                   |    2 ++
 common/cmd_nvedit.c      |   43 ++++++++++++++++++++++++++++++++++++-------
 common/env_common.c      |   31 ++++++++++++++++++++++++++++++-
 include/config_cmd_all.h |    1 +
 include/environment.h    |    5 +++++
 5 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/README b/README
index fda0190..e924575 100644
--- a/README
+++ b/README
@@ -724,6 +724,8 @@ The following options need to be configured:
 		CONFIG_CMD_CONSOLE	  coninfo
 		CONFIG_CMD_CRC32	* crc32
 		CONFIG_CMD_DATE		* support for RTC, date/time...
+		CONFIG_CMD_DEFAULTENV_VARS
+					* Reset individual variables to default
 		CONFIG_CMD_DHCP		* DHCP support
 		CONFIG_CMD_DIAG		* Diagnostics
 		CONFIG_CMD_DS4510	* ds4510 I2C gpio commands
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 871b3b1..317bd1c 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -674,14 +674,40 @@ int envmatch(uchar *s1, int i2)
 	return -1;
 }
 
-static int do_env_default(cmd_tbl_t *cmdtp, int flag,
+static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
 			  int argc, char * const argv[])
 {
-	if (argc != 2 || strcmp(argv[1], "-f") != 0)
-		return cmd_usage(cmdtp);
-
-	set_default_env("## Resetting to default environment\n");
-	return 0;
+	int all = 0, flag = 0;
+	debug("Initial value for argc=%d\n", argc);
+	while (--argc > 0 && **++argv == '-') {
+		char *arg = *argv;
+		while (*++arg) {
+			switch (*arg) {
+			case 'a':		/* default all */
+				all = 1;
+				break;
+			case 'f':		/* force */
+				flag |= H_FORCE;
+				break;
+			default:
+				return cmd_usage(cmdtp);
+			}
+		}
+	}
+	debug("Final value for argc=%d\n", argc);
+	if (all && (argc == 0)) {
+		/* Reset the whole environment */
+		set_default_env("## Resetting to default environment\n");
+		return 0;
+	}
+#ifdef CONFIG_CMD_DEFAULTENV_VARS
+	if (!all && (argc > 0)) {
+		/* Reset individual variables */
+		env_default_vars(argc, argv);
+		return 0;
+	}
+#endif
+	return cmd_usage(cmdtp);
 }
 
 static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
@@ -1012,7 +1038,10 @@ U_BOOT_CMD(
 #if defined(CONFIG_CMD_ASKENV)
 	"ask name [message] [size] - ask for environment variable\nenv "
 #endif
-	"default -f - reset default environment\n"
+	"default [-f] -a - [forcibly] reset default environment\n"
+#if defined(CONFIG_CMD_DEFAULTENV_VARS)
+	"env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
+#endif
 #if defined(CONFIG_CMD_EDITENV)
 	"env edit name - edit environment variable\n"
 #endif
diff --git a/common/env_common.c b/common/env_common.c
index 7e2bb2f..56719a6 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -157,6 +157,11 @@ const uchar *env_get_addr(int index)
 
 void set_default_env(const char *s)
 {
+	/*
+	 * By default, do not apply changes as they will eventually
+	 * be applied by someone else
+	 */
+	apply_cb apply_function = NULL;
 	if (sizeof(default_environment) > ENV_SIZE) {
 		puts("*** Error - default environment is too large\n\n");
 		return;
@@ -168,6 +173,14 @@ void set_default_env(const char *s)
 				"using default environment\n\n",
 				s + 1);
 		} else {
+			/*
+			 * This set_to_default was explicitly asked for
+			 * by the user, as opposed to being a recovery
+			 * mechanism. Therefore we chack every single
+			 * variable and apply changes to the system
+			 * right away (e.g. baudrate, console).
+			 */
+			apply_function = env_check_apply;
 			puts(s);
 		}
 	} else {
@@ -176,12 +189,28 @@ void set_default_env(const char *s)
 
 	if (himport_r(&env_htab, (char *)default_environment,
 			sizeof(default_environment), '\0', 0,
-			0, NULL, NULL) == 0)
+			0, NULL, apply_function) == 0)
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
 }
 
+#ifdef CONFIG_CMD_DEFAULTENV_VARS
+
+/* [re]set individual variables to their value in the default environment */
+int env_default_vars(int nvars, char * const vars[])
+{
+	/*
+	 * Special use-case: import from default environment
+	 * (and use \0 as a separator)
+	 */
+	return himport_r(&env_htab, (const char *)default_environment,
+				sizeof(default_environment), '\0', H_NOCLEAR,
+				nvars, vars, env_check_apply);
+}
+
+#endif /* CONFIG_CMD_DEFAULTENV_VARS */
+
 /*
  * Check if CRC is valid and (if yes) import the environment.
  * Note that "buf" may or may not be aligned.
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index 9716f9c..e728eae 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -25,6 +25,7 @@
 #define CONFIG_CMD_CDP		/* Cisco Discovery Protocol	*/
 #define CONFIG_CMD_CONSOLE	/* coninfo			*/
 #define CONFIG_CMD_DATE		/* support for RTC, date/time...*/
+#define CONFIG_CMD_DEFAULTENV_VARS /* default individ variables */
 #define CONFIG_CMD_DHCP		/* DHCP Support			*/
 #define CONFIG_CMD_DIAG		/* Diagnostics			*/
 #define CONFIG_CMD_DISPLAY	/* Display support		*/
diff --git a/include/environment.h b/include/environment.h
index 3a3e6b8..8f0d4db 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -190,6 +190,11 @@ void env_crc_update(void);
 /* [re]set to the default environment */
 void set_default_env(const char *s);
 
+#ifdef CONFIG_CMD_DEFAULTENV_VARS
+/* [re]set individual variables to their value in the default environment */
+int env_default_vars(int nvars, char * const vars[]);
+#endif
+
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes Gerlando Falauto
@ 2011-12-07 22:02   ` Simon Glass
  2011-12-08  5:45     ` Mike Frysinger
  2011-12-12  9:32     ` Gerlando Falauto
  2012-03-29 20:19   ` Marek Vasut
  1 sibling, 2 replies; 104+ messages in thread
From: Simon Glass @ 2011-12-07 22:02 UTC (permalink / raw)
  To: u-boot

Hi,

On Wed, Dec 7, 2011 at 5:30 AM, Gerlando Falauto
<gerlando.falauto@keymile.com> wrote:
> The logic of checking special parameters (e.g. baudrate, stdin, stdout,
> for a valid value and/or whether can be overwritten) and applying the
> new value to the running system is now all within a single function
> env_check_apply() which can be called whenever changes are made
> to the environment, no matter if by set, default or import.

Thanks for the rebase - I was able to try this out.

>
> With this patch env_check_apply() is only called by "env set",
> retaining previous behavior.
>
> Also allow for selectively importing/resetting variables.
>
> So add 3 new arguments to himport_r():
> o "nvars", "vars":, number and list of variables to take into account
> ? (0 means ALL)
>
> o "apply" callback function to check whether a variable can be
> ?overwritten, and possibly immediately apply the changes;
> ?when NULL, no check is performed.
>
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

Tested-by: Simon Glass <sjg@chromium.org>

> ---
> ?common/cmd_nvedit.c ? | ?174 +++++++++++++++++++++++++++++++------------------
> ?common/env_common.c ? | ? ?6 +-
> ?include/environment.h | ? ?7 ++
> ?include/search.h ? ? ?| ? 17 +++++-
> ?lib/hashtable.c ? ? ? | ? 43 ++++++++++++-
> ?5 files changed, 180 insertions(+), 67 deletions(-)
>
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 5995354..a31d413 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -197,32 +197,23 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
> ?#endif
>
> ?/*
> - * Set a new environment variable,
> - * or replace or delete an existing one.
> + * Performs consistency checking before setting, replacing,
> + * or deleting an environment variable, then (if successful)
> + * apply the changes to internals so to make them effective.
> + * Code for this function was taken out of _do_env_set(),
> + * which now calls it.
> + * Also called as a callback function by himport_r().
> + * Returns 0 in case of success, 1 in case of failure.
> + * When (flag & H_FORCE) is set, force overwriting of
> + * write-once variables.

can you word-wrap that to 72 columns perhaps?

> diff --git a/include/environment.h b/include/environment.h
> index 3c145af..3a3e6b8 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -193,6 +193,13 @@ void set_default_env(const char *s);
> ?/* Import from binary representation into hash table */
> ?int env_import(const char *buf, int check);
>
> +/*
> + * Check if variable "name" can be changed from oldval to newval,
> + * and if so, apply the changes (e.g. baudrate)

Can you document flag here also please?

> @@ -47,6 +47,13 @@ typedef struct entry {
> ?struct _ENTRY;
>
> ?/*
> + * Callback function to be called for checking whether the given change may
> + * be applied or not. Must return 0 for approval, 1 for denial.
> + */
> +typedef int (*apply_cb)(const char *name, const char *oldval,
> + ? ? ? ? ? ? ? ? ? ? ? const char *newval, int flag);

can you document args also?

> +
> +/*
> ?* Family of hash table handling functions. ?The functions also
> ?* have reentrant counterparts ending with _r. ?The non-reentrant
> ?* functions all work on a signle internal hashing table.
> @@ -94,11 +101,19 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
> ? ? ? ? ? ? ? ? ? ? const char __sep, char **__resp, size_t __size,
> ? ? ? ? ? ? ? ? ? ? int argc, char * const argv[]);
>
> +/*
> + * nvars, vars: variables to import (nvars == 0 means all)
> + * apply_cb: callback function to check validity of the new argument,
> + * and possibly apply changes (NULL means accept everything)
> + */

What is vars? Is it a NULL terminated list of string pointers? Please
document. But actually you already have function comments in the C
file so I think you should either add your comments there or (better
in my view but I may be alone) move the comments to the header file.

> ?extern int himport_r(struct hsearch_data *__htab,
> ? ? ? ? ? ? ? ? ? ? const char *__env, size_t __size, const char __sep,
> - ? ? ? ? ? ? ? ? ? ?int __flag);
> + ? ? ? ? ? ? ? ? ? ?int __flag,
> + ? ? ? ? ? ? ? ? ? ?int nvars, char * const vars[],
> + ? ? ? ? ? ? ? ? ? ?apply_cb apply);


> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index abd61c8..75b9b07 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
> ?* himport()
> ?*/
>
> +/* Check whether variable name is amongst vars[] */
> +static int process_var(const char *name, int nvars, char * const vars[])
> +{
> + ? ? ? int i = 0;

blank line here. Can part of this function be #ifdefed to reduce code
size when the feature is not required?

> + ? ? ? /* No variables specified means process all of them */
> + ? ? ? if (nvars == 0)
> + ? ? ? ? ? ? ? return 1;
> +
> + ? ? ? for (i = 0; i < nvars; i++) {
> + ? ? ? ? ? ? ? if (!strcmp(name, vars[i]))
> + ? ? ? ? ? ? ? ? ? ? ? return 1;
> + ? ? ? }
> + ? ? ? debug("Skipping non-listed variable %s\n", name);

and here I think according to Mike

> + ? ? ? return 0;
> +}
> +
> ?/*
> ?* Import linearized data into hash table.
> ?*

> @@ -743,10 +763,31 @@ int himport_r(struct hsearch_data *htab,
> ? ? ? ? ? ? ? ?*sp++ = '\0'; ? /* terminate value */
> ? ? ? ? ? ? ? ?++dp;
>
> + ? ? ? ? ? ? ? /* Skip variables which are not supposed to be treated */

s/treated/processed/ ?

+                       if (!process_var(name, nvars, vars))
+                               continue;

                       if (hdelete_r(name, htab) == 0)
                               debug("DELETE ERROR
##############################\n");

perhaps:

if (process_var(name, nvars, vars) &&
           hdelete_r(name, htab) == 0)
     debug("DELETE ERROR ##############################\n");

himport_r() is getting a bit overloaded, and it's a shame but I can't
think of an easy way to refactor it to reduce the number of args. In a
way you are adding a processing option and so you could put the three
extra args in a structure and pass a pointer to it (or NULL to skip
this feature). Not sure though...

Also, for me this patch adds 500 bytes. I wonder if more of the code
could made optional?

Regards,
Simon

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy Gerlando Falauto
@ 2011-12-07 22:02   ` Simon Glass
  2011-12-12  9:32     ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Simon Glass @ 2011-12-07 22:02 UTC (permalink / raw)
  To: u-boot

Hi Gerlando,

On Wed, Dec 7, 2011 at 5:30 AM, Gerlando Falauto
<gerlando.falauto@keymile.com> wrote:
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

Tested-by: Simon Glass <sjg@chromium.org>

> ---
> ?common/cmd_nvedit.c | ? ?2 +-
> ?include/search.h ? ?| ? ?6 ++++--
> ?lib/hashtable.c ? ? | ? 18 ++++++++++++------
> ?3 files changed, 17 insertions(+), 9 deletions(-)
>


> diff --git a/include/search.h b/include/search.h
> index 2a59e03..7ad4261 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -142,7 +142,8 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
> ?* be freed and the local static variable can be marked as not used.
> ?*/
>
> -void hdestroy_r(struct hsearch_data *htab)
> +void hdestroy_r(struct hsearch_data *htab,
> + ? ? ? ? ? ? ? int(*apply)(const char *, const char *, const char *, int))\

You could just use 'apply_cb apply' for that param I think.

> ?{
> ? ? ? ?int i;
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply Gerlando Falauto
@ 2011-12-07 22:02   ` Simon Glass
  2011-12-12  9:33     ` Gerlando Falauto
  2012-03-29 20:25   ` Marek Vasut
  1 sibling, 1 reply; 104+ messages in thread
From: Simon Glass @ 2011-12-07 22:02 UTC (permalink / raw)
  To: u-boot

Hi Gerlando,

On Wed, Dec 7, 2011 at 5:30 AM, Gerlando Falauto
<gerlando.falauto@keymile.com> wrote:
> Changes in the syntax (user API) for "env default":
> ?-f: override write-once variables
> ?-a: all (resetting the whole env is NOT the default behavior)
>
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

Tested-by: Simon Glass <sjg@chromium.org>

> ---
> ?README ? ? ? ? ? ? ? ? ? | ? ?2 ++
> ?common/cmd_nvedit.c ? ? ?| ? 43 ++++++++++++++++++++++++++++++++++++-------
> ?common/env_common.c ? ? ?| ? 31 ++++++++++++++++++++++++++++++-
> ?include/config_cmd_all.h | ? ?1 +
> ?include/environment.h ? ?| ? ?5 +++++
> ?5 files changed, 74 insertions(+), 8 deletions(-)
>


> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 871b3b1..317bd1c 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -674,14 +674,40 @@ int envmatch(uchar *s1, int i2)
> ? ? ? ?return -1;
> ?}
>
> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
> ? ? ? ? ? ? ? ? ? ? ? ? ?int argc, char * const argv[])
> ?{
> - ? ? ? if (argc != 2 || strcmp(argv[1], "-f") != 0)
> - ? ? ? ? ? ? ? return cmd_usage(cmdtp);
> -
> - ? ? ? set_default_env("## Resetting to default environment\n");
> - ? ? ? return 0;
> + ? ? ? int all = 0, flag = 0;

blank line here

> + ? ? ? debug("Initial value for argc=%d\n", argc);
> + ? ? ? while (--argc > 0 && **++argv == '-') {
> + ? ? ? ? ? ? ? char *arg = *argv;

blank line here

> + ? ? ? ? ? ? ? while (*++arg) {
> + ? ? ? ? ? ? ? ? ? ? ? switch (*arg) {
> + ? ? ? ? ? ? ? ? ? ? ? case 'a': ? ? ? ? ? ? ? /* default all */
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? all = 1;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? ? ? ? case 'f': ? ? ? ? ? ? ? /* force */
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? flag |= H_FORCE;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? ? ? ? default:
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return cmd_usage(cmdtp);
> + ? ? ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> + ? ? ? debug("Final value for argc=%d\n", argc);
> + ? ? ? if (all && (argc == 0)) {
> + ? ? ? ? ? ? ? /* Reset the whole environment */
> + ? ? ? ? ? ? ? set_default_env("## Resetting to default environment\n");
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? }
> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> + ? ? ? if (!all && (argc > 0)) {
> + ? ? ? ? ? ? ? /* Reset individual variables */
> + ? ? ? ? ? ? ? env_default_vars(argc, argv);
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? }
> +#endif

blank line here


> + ? ? ? return cmd_usage(cmdtp);
> ?}
>
> ?static int do_env_delete(cmd_tbl_t *cmdtp, int flag,

> diff --git a/include/environment.h b/include/environment.h
> index 3a3e6b8..8f0d4db 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -190,6 +190,11 @@ void env_crc_update(void);
> ?/* [re]set to the default environment */
> ?void set_default_env(const char *s);
>
> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> +/* [re]set individual variables to their value in the default environment */
> +int env_default_vars(int nvars, char * const vars[]);

How about env_set_vars_to_default?

Regards,
Simon

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-12-07 22:02   ` Simon Glass
@ 2011-12-08  5:45     ` Mike Frysinger
  2011-12-12  9:32     ` Gerlando Falauto
  1 sibling, 0 replies; 104+ messages in thread
From: Mike Frysinger @ 2011-12-08  5:45 UTC (permalink / raw)
  To: u-boot

On Wednesday 07 December 2011 17:02:06 Simon Glass wrote:
> Also, for me this patch adds 500 bytes. I wonder if more of the code
> could made optional?

yeah, it seems like these new params are only used when 
CONFIG_CMD_DEFAULTENV_VARS is defined.  which means for most people i think, 
this is unused bloat :(.  i wonder if we can do better somehow without having 
to resort to putting these behind #ifdef's.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20111208/72d0c9b0/attachment.pgp>

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-12-07 22:02   ` Simon Glass
  2011-12-08  5:45     ` Mike Frysinger
@ 2011-12-12  9:32     ` Gerlando Falauto
  2011-12-12 12:18       ` Wolfgang Denk
  2011-12-12 16:24       ` Simon Glass
  1 sibling, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-12  9:32 UTC (permalink / raw)
  To: u-boot

On 12/07/2011 11:02 PM, Simon Glass wrote:

[...]
>>   /*
>> - * Set a new environment variable,
>> - * or replace or delete an existing one.
>> + * Performs consistency checking before setting, replacing,
>> + * or deleting an environment variable, then (if successful)
>> + * apply the changes to internals so to make them effective.
>> + * Code for this function was taken out of _do_env_set(),
>> + * which now calls it.
>> + * Also called as a callback function by himport_r().
>> + * Returns 0 in case of success, 1 in case of failure.
>> + * When (flag&  H_FORCE) is set, force overwriting of
>> + * write-once variables.
>
> can you word-wrap that to 72 columns perhaps?

Sorry, I am little confused now. What is the maximum line length?

[...]

>> +/* Check whether variable name is amongst vars[] */
>> +static int process_var(const char *name, int nvars, char * const vars[])
>> +{
>> +       int i = 0;
>
> blank line here.

Thanks, I didn't know about this.

> Can part of this function be #ifdefed to reduce code
> size when the feature is not required?

Uhm, I don't think so. This would be a common feature for selectively 
importing & setting back to default. Unless we want to #ifdef both of 
them. Personally, I would #ifdef neither.

[...]
>
> +                       if (!process_var(name, nvars, vars))
> +                               continue;
>
>                         if (hdelete_r(name, htab) == 0)
>                                 debug("DELETE ERROR
> ##############################\n");
>
> perhaps:
>
> if (process_var(name, nvars, vars)&&
>             hdelete_r(name, htab) == 0)
>       debug("DELETE ERROR ##############################\n");


I think it's easier to read it the original way, and it should not make 
any difference as far as code size is concerned.

> himport_r() is getting a bit overloaded,

Actually, I believe it makes no longer sense to have it called "_r", as 
it was the original reference to the function being recursively 
calleable (i.e. reentrant) as opposed to other versions which were not.

> and it's a shame but I can't
> think of an easy way to refactor it to reduce the number of args. In a
> way you are adding a processing option and so you could put the three
> extra args in a structure and pass a pointer to it (or NULL to skip
> this feature). Not sure though...

Can't think of any other way either, except maybe renaming it and 
re-implementing the shorter version as a wrapper around the newly named 
function. I had already done that, but there would be very few places 
where the old syntax would be kept, so it just didn't make much sense.

> Also, for me this patch adds 500 bytes. I wonder if more of the code
> could made optional?

Frankly, I'm surprised to hear this adds that much overhead.
Actually, I can't see this increase in code size as you mention.
What architecture are you referring to?
In my workspace (ppc_6xx) u-boot.bin and a stripped u-boot ELF file are 
surprisingly unchanged in size, even with debug #defined!
Only place I can experience such growth is within unstripped u-boot ELF, 
which I believe shouldn't really matter... or should it?

Best,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy
  2011-12-07 22:02   ` Simon Glass
@ 2011-12-12  9:32     ` Gerlando Falauto
  2011-12-12 13:08       ` Wolfgang Denk
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-12  9:32 UTC (permalink / raw)
  To: u-boot

On 12/07/2011 11:02 PM, Simon Glass wrote:
>> diff --git a/include/search.h b/include/search.h
>> index 2a59e03..7ad4261 100644
>> --- a/include/search.h
>> +++ b/include/search.h
>> @@ -142,7 +142,8 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
>>   * be freed and the local static variable can be marked as not used.
>>   */
>>
>> -void hdestroy_r(struct hsearch_data *htab)
>> +void hdestroy_r(struct hsearch_data *htab,
>> +               int(*apply)(const char *, const char *, const char *, int))\
>
> You could just use 'apply_cb apply' for that param I think.

Absolutely. I introduced the typedef at a later stage and forgot to 
update it there too. Good catch, thanks!

Best,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply
  2011-12-07 22:02   ` Simon Glass
@ 2011-12-12  9:33     ` Gerlando Falauto
  2011-12-12 13:10       ` Wolfgang Denk
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-12  9:33 UTC (permalink / raw)
  To: u-boot

On 12/07/2011 11:02 PM, Simon Glass wrote:
> Hi Gerlando,

[...]

>> diff --git a/include/environment.h b/include/environment.h
>> index 3a3e6b8..8f0d4db 100644
>> --- a/include/environment.h
>> +++ b/include/environment.h
>> @@ -190,6 +190,11 @@ void env_crc_update(void);
>>   /* [re]set to the default environment */
>>   void set_default_env(const char *s);
>>
>> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
>> +/* [re]set individual variables to their value in the default environment */
>> +int env_default_vars(int nvars, char * const vars[]);
>
> How about env_set_vars_to_default?

Hmm... sounds too long to me. But if you insist...

Best,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-12-12  9:32     ` Gerlando Falauto
@ 2011-12-12 12:18       ` Wolfgang Denk
  2011-12-12 13:38         ` Gerlando Falauto
  2011-12-12 16:24       ` Simon Glass
  1 sibling, 1 reply; 104+ messages in thread
From: Wolfgang Denk @ 2011-12-12 12:18 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <4EE5CA38.6090807@keymile.com> you wrote:
>
> > if (process_var(name, nvars, vars)&&
> >             hdelete_r(name, htab) == 0)
> >       debug("DELETE ERROR ##############################\n");

This is incorrect indentation.

> I think it's easier to read it the original way, and it should not make 
> any difference as far as code size is concerned.

The Coding Style makes an explicit exception regarding the line length
for user visible strings:

 83 Statements longer than 80 columns will be broken into sensible chunks, unless
 84 exceeding 80 columns significantly increases readability and does not hide
 85 information. Descendants are always substantially shorter than the parent and
 86 are placed substantially to the right. The same applies to function headers
 87 with a long argument list. However, never break user-visible strings such as
 88 printk messages, because that breaks the ability to grep for them.

> > himport_r() is getting a bit overloaded,
> 
> Actually, I believe it makes no longer sense to have it called "_r", as 
> it was the original reference to the function being recursively 
> calleable (i.e. reentrant) as opposed to other versions which were not.

Has this changed?

> > Also, for me this patch adds 500 bytes. I wonder if more of the code
> > could made optional?
> 
> Frankly, I'm surprised to hear this adds that much overhead.
> Actually, I can't see this increase in code size as you mention.
> What architecture are you referring to?
> In my workspace (ppc_6xx) u-boot.bin and a stripped u-boot ELF file are 
> surprisingly unchanged in size, even with debug #defined!

Don't look at file size. Use the "size" command and compare code /
data / bss sizes.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
As of 1992, they're called European Economic Community fries.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy
  2011-12-12  9:32     ` Gerlando Falauto
@ 2011-12-12 13:08       ` Wolfgang Denk
  2011-12-12 13:52         ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Wolfgang Denk @ 2011-12-12 13:08 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <4EE5CA4A.8050601@keymile.com> you wrote:
>
> > You could just use 'apply_cb apply' for that param I think.
> 
> Absolutely. I introduced the typedef at a later stage and forgot to 
> update it there too. Good catch, thanks!

Run checkpatch, and mind the CodingStyle section about typedefs!

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"I can call spirits from the vasty deep."
"Why so can I, or so can any man; but will they come when you do call
for them?"          - Shakespeare, 1 King Henry IV, Act III, Scene I.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply
  2011-12-12  9:33     ` Gerlando Falauto
@ 2011-12-12 13:10       ` Wolfgang Denk
  0 siblings, 0 replies; 104+ messages in thread
From: Wolfgang Denk @ 2011-12-12 13:10 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <4EE5CA57.6070807@keymile.com> you wrote:
>
> >>   /* [re]set to the default environment */
> >>   void set_default_env(const char *s);
> >>
> >> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> >> +/* [re]set individual variables to their value in the default environment */
> >> +int env_default_vars(int nvars, char * const vars[]);
> >
> > How about env_set_vars_to_default?
> 
> Hmm... sounds too long to me. But if you insist...

Too long, indeed.

We already have set_default_env() for the whole environment, so maybe
set_default_vars() for a set of variables?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I paid too much for it, but its worth it.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-12-12 12:18       ` Wolfgang Denk
@ 2011-12-12 13:38         ` Gerlando Falauto
  2011-12-12 13:50           ` Wolfgang Denk
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-12 13:38 UTC (permalink / raw)
  To: u-boot

On 12/12/2011 01:18 PM, Wolfgang Denk wrote:
> Dear Gerlando Falauto,
>
>> I think it's easier to read it the original way, and it should not make
>> any difference as far as code size is concerned.
>
> The Coding Style makes an explicit exception regarding the line length
> for user visible strings:
>
>   83 Statements longer than 80 columns will be broken into sensible chunks, unless
>   84 exceeding 80 columns significantly increases readability and does not hide
>   85 information. Descendants are always substantially shorter than the parent and
>   86 are placed substantially to the right. The same applies to function headers
>   87 with a long argument list. However, never break user-visible strings such as
>   88 printk messages, because that breaks the ability to grep for them.

I don't understand: why are you quoting this here and now? The chunk we 
are referring to doesn't change a bit about the printable string.

>>> himport_r() is getting a bit overloaded,
>>
>> Actually, I believe it makes no longer sense to have it called "_r", as
>> it was the original reference to the function being recursively
>> calleable (i.e. reentrant) as opposed to other versions which were not.
>
> Has this changed?

Of course it hasn't. But I don't see any point in keeping this notation 
anyway.

>>> Also, for me this patch adds 500 bytes. I wonder if more of the code
>>> could made optional?
>>
>> Frankly, I'm surprised to hear this adds that much overhead.
>> Actually, I can't see this increase in code size as you mention.
>> What architecture are you referring to?
>> In my workspace (ppc_6xx) u-boot.bin and a stripped u-boot ELF file are
>> surprisingly unchanged in size, even with debug #defined!
>
> Don't look at file size. Use the "size" command and compare code /
> data / bss sizes.

Yep, sorry, I'll look into that to see what part is mostly reponsible 
for this.

Best,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-12-12 13:38         ` Gerlando Falauto
@ 2011-12-12 13:50           ` Wolfgang Denk
  0 siblings, 0 replies; 104+ messages in thread
From: Wolfgang Denk @ 2011-12-12 13:50 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <4EE603D0.5010109@keymile.com> you wrote:
>
> I don't understand: why are you quoting this here and now? The chunk we 
> are referring to doesn't change a bit about the printable string.

Please use proper indentation for it, even if it exceeds the line
length then - although I wonder if the string actually makes any sense
or is needed / useful as is.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
e-credibility: the non-guaranteeable likelihood that  the  electronic
data you're seeing is genuine rather than somebody's made-up crap.
- Karl Lehenbauer

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy
  2011-12-12 13:08       ` Wolfgang Denk
@ 2011-12-12 13:52         ` Gerlando Falauto
  2011-12-12 19:19           ` Wolfgang Denk
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2011-12-12 13:52 UTC (permalink / raw)
  To: u-boot

On 12/12/2011 02:08 PM, Wolfgang Denk wrote:
> Dear Gerlando Falauto,
>
> In message<4EE5CA4A.8050601@keymile.com>  you wrote:
>>
>>> You could just use 'apply_cb apply' for that param I think.
>>
>> Absolutely. I introduced the typedef at a later stage and forgot to
>> update it there too. Good catch, thanks!
>
> Run checkpatch, and mind the CodingStyle section about typedefs!

I did run checkpatch, it didn't say a word about this.

What is your recommendation about typedef'ining a function pointer?
I immediately suspected that using a callback function might sound like 
heresy, so if you have any better suggestion please put it forward 
before I rework this changeset for the fifth time... please.

I just think having the whole, expanded signature as the type for a 
function-pointer parameter or local variable would just make things too 
long and redundant.
Just off the top of my head: perhaps a struct with a single function 
pointer element might look better than a typedef?

Thanks,
Gerlando Falauto

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-12-12  9:32     ` Gerlando Falauto
  2011-12-12 12:18       ` Wolfgang Denk
@ 2011-12-12 16:24       ` Simon Glass
  1 sibling, 0 replies; 104+ messages in thread
From: Simon Glass @ 2011-12-12 16:24 UTC (permalink / raw)
  To: u-boot

Hi Gerlando,

On Mon, Dec 12, 2011 at 1:32 AM, Gerlando Falauto
<gerlando.falauto@keymile.com> wrote:
> On 12/07/2011 11:02 PM, Simon Glass wrote:
>
> [...]
>>>
>>> ?/*
>>> - * Set a new environment variable,
>>> - * or replace or delete an existing one.
>>> + * Performs consistency checking before setting, replacing,
>>> + * or deleting an environment variable, then (if successful)
>>> + * apply the changes to internals so to make them effective.
>>> + * Code for this function was taken out of _do_env_set(),
>>> + * which now calls it.
>>> + * Also called as a callback function by himport_r().
>>> + * Returns 0 in case of success, 1 in case of failure.
>>> + * When (flag& ?H_FORCE) is set, force overwriting of
>>> + * write-once variables.
>>
>>
>> can you word-wrap that to 72 columns perhaps?
>
>
> Sorry, I am little confused now. What is the maximum line length?

What I meant was that it seems like it you could put more characters
on each line, and then would take up less vertical space. You could
also use the doxygen @param formal to make it quicker for people to
read.

>
> [...]
>
>
>>> +/* Check whether variable name is amongst vars[] */
>>> +static int process_var(const char *name, int nvars, char * const vars[])
>>> +{
>>> + ? ? ? int i = 0;
>>
>>
>> blank line here.
>
>
> Thanks, I didn't know about this.
>
>
>> Can part of this function be #ifdefed to reduce code
>> size when the feature is not required?
>
>
> Uhm, I don't think so. This would be a common feature for selectively
> importing & setting back to default. Unless we want to #ifdef both of them.
> Personally, I would #ifdef neither.

OK, just a thought, it is up to you.

>
> [...]
>
>>
>> + ? ? ? ? ? ? ? ? ? ? ? if (!process_var(name, nvars, vars))
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
>>
>> ? ? ? ? ? ? ? ? ? ? ? ?if (hdelete_r(name, htab) == 0)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?debug("DELETE ERROR
>> ##############################\n");
>>
>> perhaps:
>>
>> if (process_var(name, nvars, vars)&&
>> ? ? ? ? ? ?hdelete_r(name, htab) == 0)
>> ? ? ?debug("DELETE ERROR ##############################\n");
>
>
>
> I think it's easier to read it the original way, and it should not make any
> difference as far as code size is concerned.

OK
>
>
>> himport_r() is getting a bit overloaded,
>
>
> Actually, I believe it makes no longer sense to have it called "_r", as it
> was the original reference to the function being recursively calleable (i.e.
> reentrant) as opposed to other versions which were not.

OK I'm not sure about that.
>
>
>> and it's a shame but I can't
>> think of an easy way to refactor it to reduce the number of args. In a
>> way you are adding a processing option and so you could put the three
>> extra args in a structure and pass a pointer to it (or NULL to skip
>> this feature). Not sure though...
>
>
> Can't think of any other way either, except maybe renaming it and
> re-implementing the shorter version as a wrapper around the newly named
> function. I had already done that, but there would be very few places where
> the old syntax would be kept, so it just didn't make much sense.

Packaging up a lot of zero arguments to a function does chew up code space.

>
>
>> Also, for me this patch adds 500 bytes. I wonder if more of the code
>> could made optional?
>
>
> Frankly, I'm surprised to hear this adds that much overhead.
> Actually, I can't see this increase in code size as you mention.
> What architecture are you referring to?

ARMv7. Ideally if your feature is optional it shouldn't add much size
when it is turned off.

> In my workspace (ppc_6xx) u-boot.bin and a stripped u-boot ELF file are
> surprisingly unchanged in size, even with debug #defined!
> Only place I can experience such growth is within unstripped u-boot ELF,
> which I believe shouldn't really matter... or should it?

As Wolfgang says, use your tool chain's size tool for this.

Regards,
Simon

>
> Best,
> Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy
  2011-12-12 13:52         ` Gerlando Falauto
@ 2011-12-12 19:19           ` Wolfgang Denk
  0 siblings, 0 replies; 104+ messages in thread
From: Wolfgang Denk @ 2011-12-12 19:19 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <4EE60729.4020401@keymile.com> you wrote:
>
> > Run checkpatch, and mind the CodingStyle section about typedefs!
> 
> I did run checkpatch, it didn't say a word about this.

If you add new tyedef's, it will complain.

> What is your recommendation about typedef'ining a function pointer?
> I immediately suspected that using a callback function might sound like 
> heresy, so if you have any better suggestion please put it forward 
> before I rework this changeset for the fifth time... please.

Sorry, I'm in the middle of -rc1 release work and testing, and also
right in the final steps of releasing the next version of our ELDK
(v5.1). Plus a few other tasks, including trips to customers.  I don't
have time for a thorough review now.

I understand this is very bad for you, but I cannot change it.

> I just think having the whole, expanded signature as the type for a 
> function-pointer parameter or local variable would just make things too 
> long and redundant.

Hm... probbaly.

> Just off the top of my head: perhaps a struct with a single function 
> pointer element might look better than a typedef?

I'm not convinced. I'd have to see the code, and compare.  But to do
so, I'd need a bit of time...

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A supercomputer is a machine that runs an endless loop in 2 seconds.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes Gerlando Falauto
  2011-12-07 22:02   ` Simon Glass
@ 2012-03-29 20:19   ` Marek Vasut
  2012-03-30 13:00     ` Gerlando Falauto
  1 sibling, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-03-29 20:19 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

WD prodded me too long to review this patchset ;-D

> The logic of checking special parameters (e.g. baudrate, stdin, stdout,
> for a valid value and/or whether can be overwritten) and applying the
> new value to the running system is now all within a single function
> env_check_apply() which can be called whenever changes are made
> to the environment, no matter if by set, default or import.
> 
> With this patch env_check_apply() is only called by "env set",
> retaining previous behavior.
> 
> Also allow for selectively importing/resetting variables.
> 
> So add 3 new arguments to himport_r():
> o "nvars", "vars":, number and list of variables to take into account
>    (0 means ALL)
> 
> o "apply" callback function to check whether a variable can be
>   overwritten, and possibly immediately apply the changes;
>   when NULL, no check is performed.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

[...]

> +	}
> +#if defined(CONFIG_CMD_NET)
> +	else if (strcmp(name, "bootfile") == 0) {
> +		copy_filename(BootFile, newval, sizeof(BootFile));

Can you remove the camel-case here please?

> +		return 0;
> +	}
> +#endif
> +	return 0;
> +}
> +
> +/*
> + * Set a new environment variable,
> + * or replace or delete an existing one.
> +*/
> +int _do_env_set(int flag, int argc, char * const argv[])
> +{
> +	int   i, len;
> +	char  *name, *value, *s;
> +	ENTRY e, *ep;
> +
> +	name = argv[1];
> +	value = argv[2];
> +
> +	if (strchr(name, '=')) {
> +		printf("## Error: illegal character '='"
> +		       "in variable name \"%s\"\n", name);
> +		return 1;
> +	}
> +
> +	env_id++;
> +	/*
> +	 * search if variable with this name already exists
> +	 */
> +	e.key = name;
> +	e.data = NULL;
> +	hsearch_r(e, FIND, &ep, &env_htab);
> +
> +	/*
> +	 * Perform requested checks. Notice how since we are overwriting
> +	 * a single variable, we need to set H_NOCLEAR
> +	 */
> +	if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
> +		debug("check function did not approve, refusing\n");
> +		return 1;
> +	}
> +
>  	/* Delete only ? */
>  	if (argc < 3 || argv[2] == NULL) {
>  		int rc = hdelete_r(name, &env_htab);
> @@ -337,34 +412,6 @@ int _do_env_set(int flag, int argc, char * const
> argv[]) return 1;
>  	}
> 
> -	/*
> -	 * Some variables should be updated when the corresponding
> -	 * entry in the environment is changed
> -	 */
> -	if (strcmp(name, "ipaddr") == 0) {
> -		char *s = argv[2];	/* always use only one arg */
> -		char *e;
> -		unsigned long addr;
> -		bd->bi_ip_addr = 0;
> -		for (addr = 0, i = 0; i < 4; ++i) {
> -			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
> -			addr <<= 8;
> -			addr  |= val & 0xFF;
> -			if (s)
> -				s = *e ? e + 1 : e;
> -		}
> -		bd->bi_ip_addr = htonl(addr);
> -		return 0;
> -	} else if (strcmp(argv[1], "loadaddr") == 0) {
> -		load_addr = simple_strtoul(argv[2], NULL, 16);
> -		return 0;
> -	}
> -#if defined(CONFIG_CMD_NET)
> -	else if (strcmp(argv[1], "bootfile") == 0) {
> -		copy_filename(BootFile, argv[2], sizeof(BootFile));
> -		return 0;
> -	}
> -#endif
>  	return 0;
>  }
> 
> @@ -886,7 +933,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
>  		addr = (char *)ep->data;
>  	}
> 
> -	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
> +	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
> +			0, NULL, NULL) == 0) {
>  		error("Environment import failed: errno = %d\n", errno);
>  		return 1;
>  	}
> diff --git a/common/env_common.c b/common/env_common.c
> index 8a71096..7e2bb2f 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -175,7 +175,8 @@ void set_default_env(const char *s)
>  	}
> 
>  	if (himport_r(&env_htab, (char *)default_environment,
> -			sizeof(default_environment), '\0', 0) == 0)
> +			sizeof(default_environment), '\0', 0,
> +			0, NULL, NULL) == 0)
>  		error("Environment import failed: errno = %d\n", errno);
> 
>  	gd->flags |= GD_FLG_ENV_READY;
> @@ -200,7 +201,8 @@ int env_import(const char *buf, int check)
>  		}
>  	}
> 
> -	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
> +	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
> +			0, NULL, NULL)) {
>  		gd->flags |= GD_FLG_ENV_READY;
>  		return 1;
>  	}
> diff --git a/include/environment.h b/include/environment.h
> index 3c145af..3a3e6b8 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -193,6 +193,13 @@ void set_default_env(const char *s);
>  /* Import from binary representation into hash table */
>  int env_import(const char *buf, int check);
> 
> +/*
> + * Check if variable "name" can be changed from oldval to newval,
> + * and if so, apply the changes (e.g. baudrate)
> + */
> +int env_check_apply(const char *name, const char *oldval,
> +			const char *newval, int flag);
> +
>  #endif /* DO_DEPS_ONLY */
> 
>  #endif /* _ENVIRONMENT_H_ */
> diff --git a/include/search.h b/include/search.h
> index ef53edb..2a59e03 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -47,6 +47,13 @@ typedef struct entry {
>  struct _ENTRY;
> 
>  /*
> + * Callback function to be called for checking whether the given change
> may + * be applied or not. Must return 0 for approval, 1 for denial.
> + */
> +typedef int (*apply_cb)(const char *name, const char *oldval,
> +			const char *newval, int flag);

Is the typedef really necessary ?

> +
> +/*
>   * Family of hash table handling functions.  The functions also
>   * have reentrant counterparts ending with _r.  The non-reentrant
>   * functions all work on a signle internal hashing table.
> @@ -94,11 +101,19 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
>  		     const char __sep, char **__resp, size_t __size,
>  		     int argc, char * const argv[]);
> 
> +/*
> + * nvars, vars: variables to import (nvars == 0 means all)
> + * apply_cb: callback function to check validity of the new argument,
> + * and possibly apply changes (NULL means accept everything)
> + */
>  extern int himport_r(struct hsearch_data *__htab,
>  		     const char *__env, size_t __size, const char __sep,
> -		     int __flag);
> +		     int __flag,
> +		     int nvars, char * const vars[],
> +		     apply_cb apply);
> 
>  /* Flags for himport_r() */
>  #define	H_NOCLEAR	1	/* do not clear hash table before 
importing */
> +#define H_FORCE		2	/* overwrite read-only/write-once 
variables */

Make this 1 << x please.

> 
>  #endif /* search.h */
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index abd61c8..75b9b07 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> char sep, * himport()
>   */
> 
> +/* Check whether variable name is amongst vars[] */
> +static int process_var(const char *name, int nvars, char * const vars[])

You mean check_var()?

> +{
> +	int i = 0;
> +	/* No variables specified means process all of them */
> +	if (nvars == 0)
> +		return 1;
> +
> +	for (i = 0; i < nvars; i++) {
> +		if (!strcmp(name, vars[i]))
> +			return 1;
> +	}
> +	debug("Skipping non-listed variable %s\n", name);
> +	return 0;
> +}
> +
>  /*
>   * Import linearized data into hash table.
>   *
> @@ -639,7 +655,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char
> sep, */
> 
>  int himport_r(struct hsearch_data *htab,
> -	      const char *env, size_t size, const char sep, int flag)
> +		const char *env, size_t size, const char sep, int flag,
> +		int nvars, char * const vars[],
> +		apply_cb apply)
>  {
>  	char *data, *sp, *dp, *name, *value;
> 
> @@ -726,6 +744,8 @@ int himport_r(struct hsearch_data *htab,
>  			*dp++ = '\0';	/* terminate name */
> 
>  			debug("DELETE CANDIDATE: \"%s\"\n", name);
> +			if (!process_var(name, nvars, vars))
> +				continue;
> 
>  			if (hdelete_r(name, htab) == 0)
>  				debug("DELETE ERROR 
##############################\n");
> @@ -743,10 +763,31 @@ int himport_r(struct hsearch_data *htab,
>  		*sp++ = '\0';	/* terminate value */
>  		++dp;
> 
> +		/* Skip variables which are not supposed to be treated */
> +		if (!process_var(name, nvars, vars))
> +			continue;
> +
>  		/* enter into hash table */
>  		e.key = name;
>  		e.data = value;

Do you need to do this if you eventually later figure out you have no apply() 
callback and you did this for no reason?

> 
> +		/* if there is an apply function, check what it has to say */
> +		if (apply != NULL) {
> +			debug("searching before calling cb function"
> +				" for  %s\n", name);
> +			/*
> +			 * Search for variable in existing env, so to pass
> +			 * its previous value to the apply callback
> +			 */
> +			hsearch_r(e, FIND, &rv, htab);
> +			debug("previous value was %s\n", rv ? rv->data : "");
> +			if (apply(name, rv ? rv->data : NULL, value, flag)) {
> +				debug("callback function refused to set"
> +					" variable %s, skipping it!\n", name);
> +				continue;
> +			}
> +		}
> +
>  		hsearch_r(e, ENTER, &rv, htab);
>  		if (rv == NULL) {
>  			printf("himport_r: can't insert \"%s=%s\" into hash 
table\n",

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply Gerlando Falauto
  2011-12-07 22:02   ` Simon Glass
@ 2012-03-29 20:25   ` Marek Vasut
  2012-03-30 13:00     ` Gerlando Falauto
  1 sibling, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-03-29 20:25 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Changes in the syntax (user API) for "env default":
>   -f: override write-once variables
>   -a: all (resetting the whole env is NOT the default behavior)
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

I have to admit I'm not much of a fan of how you use this apply() callback, is 
it really necessary?

Also, do we need special command for default env?

M

> ---
>  README                   |    2 ++
>  common/cmd_nvedit.c      |   43
> ++++++++++++++++++++++++++++++++++++------- common/env_common.c      |  
> 31 ++++++++++++++++++++++++++++++-
>  include/config_cmd_all.h |    1 +
>  include/environment.h    |    5 +++++
>  5 files changed, 74 insertions(+), 8 deletions(-)
> 
> diff --git a/README b/README
> index fda0190..e924575 100644
> --- a/README
> +++ b/README
> @@ -724,6 +724,8 @@ The following options need to be configured:
>  		CONFIG_CMD_CONSOLE	  coninfo
>  		CONFIG_CMD_CRC32	* crc32
>  		CONFIG_CMD_DATE		* support for RTC, date/time...
> +		CONFIG_CMD_DEFAULTENV_VARS
> +					* Reset individual variables to default
>  		CONFIG_CMD_DHCP		* DHCP support
>  		CONFIG_CMD_DIAG		* Diagnostics
>  		CONFIG_CMD_DS4510	* ds4510 I2C gpio commands
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 871b3b1..317bd1c 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -674,14 +674,40 @@ int envmatch(uchar *s1, int i2)
>  	return -1;
>  }
> 
> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
>  			  int argc, char * const argv[])
>  {
> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
> -		return cmd_usage(cmdtp);
> -
> -	set_default_env("## Resetting to default environment\n");
> -	return 0;
> +	int all = 0, flag = 0;
> +	debug("Initial value for argc=%d\n", argc);
> +	while (--argc > 0 && **++argv == '-') {
> +		char *arg = *argv;
> +		while (*++arg) {
> +			switch (*arg) {
> +			case 'a':		/* default all */
> +				all = 1;
> +				break;
> +			case 'f':		/* force */
> +				flag |= H_FORCE;
> +				break;
> +			default:
> +				return cmd_usage(cmdtp);
> +			}
> +		}
> +	}
> +	debug("Final value for argc=%d\n", argc);
> +	if (all && (argc == 0)) {
> +		/* Reset the whole environment */
> +		set_default_env("## Resetting to default environment\n");
> +		return 0;
> +	}
> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> +	if (!all && (argc > 0)) {
> +		/* Reset individual variables */
> +		env_default_vars(argc, argv);
> +		return 0;
> +	}
> +#endif
> +	return cmd_usage(cmdtp);
>  }
> 
>  static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
> @@ -1012,7 +1038,10 @@ U_BOOT_CMD(
>  #if defined(CONFIG_CMD_ASKENV)
>  	"ask name [message] [size] - ask for environment variable\nenv "
>  #endif
> -	"default -f - reset default environment\n"
> +	"default [-f] -a - [forcibly] reset default environment\n"
> +#if defined(CONFIG_CMD_DEFAULTENV_VARS)
> +	"env default [-f] var [...] - [forcibly] reset variable(s) to their
> default values\n" +#endif
>  #if defined(CONFIG_CMD_EDITENV)
>  	"env edit name - edit environment variable\n"
>  #endif
> diff --git a/common/env_common.c b/common/env_common.c
> index 7e2bb2f..56719a6 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -157,6 +157,11 @@ const uchar *env_get_addr(int index)
> 
>  void set_default_env(const char *s)
>  {
> +	/*
> +	 * By default, do not apply changes as they will eventually
> +	 * be applied by someone else
> +	 */
> +	apply_cb apply_function = NULL;
>  	if (sizeof(default_environment) > ENV_SIZE) {
>  		puts("*** Error - default environment is too large\n\n");
>  		return;
> @@ -168,6 +173,14 @@ void set_default_env(const char *s)
>  				"using default environment\n\n",
>  				s + 1);
>  		} else {
> +			/*
> +			 * This set_to_default was explicitly asked for
> +			 * by the user, as opposed to being a recovery
> +			 * mechanism. Therefore we chack every single
> +			 * variable and apply changes to the system
> +			 * right away (e.g. baudrate, console).
> +			 */
> +			apply_function = env_check_apply;
>  			puts(s);
>  		}
>  	} else {
> @@ -176,12 +189,28 @@ void set_default_env(const char *s)
> 
>  	if (himport_r(&env_htab, (char *)default_environment,
>  			sizeof(default_environment), '\0', 0,
> -			0, NULL, NULL) == 0)
> +			0, NULL, apply_function) == 0)
>  		error("Environment import failed: errno = %d\n", errno);
> 
>  	gd->flags |= GD_FLG_ENV_READY;
>  }
> 
> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> +
> +/* [re]set individual variables to their value in the default environment
> */ +int env_default_vars(int nvars, char * const vars[])
> +{
> +	/*
> +	 * Special use-case: import from default environment
> +	 * (and use \0 as a separator)
> +	 */
> +	return himport_r(&env_htab, (const char *)default_environment,
> +				sizeof(default_environment), '\0', H_NOCLEAR,
> +				nvars, vars, env_check_apply);
> +}
> +
> +#endif /* CONFIG_CMD_DEFAULTENV_VARS */
> +
>  /*
>   * Check if CRC is valid and (if yes) import the environment.
>   * Note that "buf" may or may not be aligned.
> diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
> index 9716f9c..e728eae 100644
> --- a/include/config_cmd_all.h
> +++ b/include/config_cmd_all.h
> @@ -25,6 +25,7 @@
>  #define CONFIG_CMD_CDP		/* Cisco Discovery Protocol	*/
>  #define CONFIG_CMD_CONSOLE	/* coninfo			*/
>  #define CONFIG_CMD_DATE		/* support for RTC, date/time...*/
> +#define CONFIG_CMD_DEFAULTENV_VARS /* default individ variables */
>  #define CONFIG_CMD_DHCP		/* DHCP Support			*/
>  #define CONFIG_CMD_DIAG		/* Diagnostics			*/
>  #define CONFIG_CMD_DISPLAY	/* Display support		*/
> diff --git a/include/environment.h b/include/environment.h
> index 3a3e6b8..8f0d4db 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -190,6 +190,11 @@ void env_crc_update(void);
>  /* [re]set to the default environment */
>  void set_default_env(const char *s);
> 
> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> +/* [re]set individual variables to their value in the default environment
> */ +int env_default_vars(int nvars, char * const vars[]);
> +#endif
> +
>  /* Import from binary representation into hash table */
>  int env_import(const char *buf, int check);

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2012-03-29 20:19   ` Marek Vasut
@ 2012-03-30 13:00     ` Gerlando Falauto
  2012-03-30 13:08       ` Marek Vasut
  2012-03-30 17:00       ` Gerlando Falauto
  0 siblings, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-03-30 13:00 UTC (permalink / raw)
  To: u-boot

On 03/29/2012 10:19 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
> WD prodded me too long to review this patchset ;-D

Well, better late than never! ;-)

[...]
>> +#if defined(CONFIG_CMD_NET)
>> +	else if (strcmp(name, "bootfile") == 0) {
>> +		copy_filename(BootFile, newval, sizeof(BootFile));
>
> Can you remove the camel-case here please?
>

That's code I just moved around... Will do, sir.

>> +		return 0;
>> +	}
>> +#endif
>> +	return 0;
>> +}
>> +

[...]

>> --- a/include/search.h
>> +++ b/include/search.h
>> @@ -47,6 +47,13 @@ typedef struct entry {
>>   struct _ENTRY;
>>
>>   /*
>> + * Callback function to be called for checking whether the given change
>> may + * be applied or not. Must return 0 for approval, 1 for denial.
>> + */
>> +typedef int (*apply_cb)(const char *name, const char *oldval,
>> +			const char *newval, int flag);
>
> Is the typedef really necessary ?

 >[From your other email]
 >
 > I have to admit I'm not much of a fan of how you use this apply()
 > callback, is it really necessary?
 >

Why ask, if you already know the answer? :-)

I'm not a big fan either, seemed like the easiest approach at the time.
The idea was to keep the hastable (struct hsearch_data) as decoupled as 
possible from the environment (env_htab which is, in fact, the only 
instance of struct hsearch_data).

What if the function pointer was stored within the hastable itself?
Sort of a virtual method.
This way we get rid of the typedef and the function pointer as a 
parameter altogether.
The callback parameter then just becomes a boolean value (meaning, 
do/don't call the callback function stored within the hashtable itself).
I like that much better. What do you think?

[...]
>>
>>   /* Flags for himport_r() */
>>   #define	H_NOCLEAR	1	/* do not clear hash table before
> importing */
>> +#define H_FORCE		2	/* overwrite read-only/write-once
> variables */
>
> Make this 1<<  x please.

OK.

>
>>
>>   #endif /* search.h */
>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>> index abd61c8..75b9b07 100644
>> --- a/lib/hashtable.c
>> +++ b/lib/hashtable.c
>> @@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab, const
>> char sep, * himport()
>>    */
>>
>> +/* Check whether variable name is amongst vars[] */
>> +static int process_var(const char *name, int nvars, char * const vars[])
>
> You mean check_var()?

I mean is_var_in_set_or_is_set_empty().
Sorry, I'm very, very bad at picking function names.
Any suggestion?

>> +{
>> +	int i = 0;
>> +	/* No variables specified means process all of them */
>> +	if (nvars == 0)
>> +		return 1;
>> +
>> +	for (i = 0; i<  nvars; i++) {
>> +		if (!strcmp(name, vars[i]))
>> +			return 1;
>> +	}
>> +	debug("Skipping non-listed variable %s\n", name);
>> +	return 0;
>> +}
>> +
>>   /*
>>    * Import linearized data into hash table.
>>    *
>> @@ -639,7 +655,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char
>> sep, */
>>
>>   int himport_r(struct hsearch_data *htab,
>> -	      const char *env, size_t size, const char sep, int flag)
>> +		const char *env, size_t size, const char sep, int flag,
>> +		int nvars, char * const vars[],
>> +		apply_cb apply)
>>   {
>>   	char *data, *sp, *dp, *name, *value;
>>
>> @@ -726,6 +744,8 @@ int himport_r(struct hsearch_data *htab,
>>   			*dp++ = '\0';	/* terminate name */
>>
>>   			debug("DELETE CANDIDATE: \"%s\"\n", name);
>> +			if (!process_var(name, nvars, vars))
>> +				continue;
>>
>>   			if (hdelete_r(name, htab) == 0)
>>   				debug("DELETE ERROR
> ##############################\n");
>> @@ -743,10 +763,31 @@ int himport_r(struct hsearch_data *htab,
>>   		*sp++ = '\0';	/* terminate value */
>>   		++dp;
>>
>> +		/* Skip variables which are not supposed to be treated */
>> +		if (!process_var(name, nvars, vars))
>> +			continue;
>> +
>>   		/* enter into hash table */
>>   		e.key = name;
>>   		e.data = value;
>
> Do you need to do this if you eventually later figure out you have no apply()
> callback and you did this for no reason?

You mean calling process_var()? It's two separate things.

One, filter out the variables that were not asked to be processed, if 
there were any (call to process_var())
Two, check whether the new value is acceptable and/or apply it (call 
apply())
You could have none, either, or both.

Or else, if you mean moving the e.key = name, e.data = value 
assignments, you're right, they should be moved down (but in that case 
it would be because the apply function fails, not because it's not 
present -- default case is always successful).

>>
>> +		/* if there is an apply function, check what it has to say */
>> +		if (apply != NULL) {
>> +			debug("searching before calling cb function"
>> +				" for  %s\n", name);
>> +			/*
>> +			 * Search for variable in existing env, so to pass
>> +			 * its previous value to the apply callback
>> +			 */
>> +			hsearch_r(e, FIND,&rv, htab);
>> +			debug("previous value was %s\n", rv ? rv->data : "");
>> +			if (apply(name, rv ? rv->data : NULL, value, flag)) {
>> +				debug("callback function refused to set"
>> +					" variable %s, skipping it!\n", name);
>> +				continue;
>> +			}
>> +		}
>> +
>>   		hsearch_r(e, ENTER,&rv, htab);
>>   		if (rv == NULL) {
>>   			printf("himport_r: can't insert \"%s=%s\" into hash
> table\n",

Thank you,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply
  2012-03-29 20:25   ` Marek Vasut
@ 2012-03-30 13:00     ` Gerlando Falauto
  2012-03-30 13:09       ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-03-30 13:00 UTC (permalink / raw)
  To: u-boot

On 03/29/2012 10:25 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> Changes in the syntax (user API) for "env default":
>>    -f: override write-once variables
>>    -a: all (resetting the whole env is NOT the default behavior)
>>
>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>
> I have to admit I'm not much of a fan of how you use this apply() callback, is
> it really necessary?

See my previous email.

> Also, do we need special command for default env?

I am sorry, I don't get the question. What do you mean?
It's always the same "env import" with an augmented command line.
If you're referring to CONFIG_CMD_DEFAULTENV_VARS, I don't think it's 
neeed either, but it was requested at some previous time.
I also think it's misleading to have some syntax for the same command 
conditionally enabled. Has it ever been done before?

Thank you,
Gerlando

> M
>
>> ---
>>   README                   |    2 ++
>>   common/cmd_nvedit.c      |   43
>> ++++++++++++++++++++++++++++++++++++------- common/env_common.c      |
>> 31 ++++++++++++++++++++++++++++++-
>>   include/config_cmd_all.h |    1 +
>>   include/environment.h    |    5 +++++
>>   5 files changed, 74 insertions(+), 8 deletions(-)
>>
>> diff --git a/README b/README
>> index fda0190..e924575 100644
>> --- a/README
>> +++ b/README
>> @@ -724,6 +724,8 @@ The following options need to be configured:
>>   		CONFIG_CMD_CONSOLE	  coninfo
>>   		CONFIG_CMD_CRC32	* crc32
>>   		CONFIG_CMD_DATE		* support for RTC, date/time...
>> +		CONFIG_CMD_DEFAULTENV_VARS
>> +					* Reset individual variables to default
>>   		CONFIG_CMD_DHCP		* DHCP support
>>   		CONFIG_CMD_DIAG		* Diagnostics
>>   		CONFIG_CMD_DS4510	* ds4510 I2C gpio commands
>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
>> index 871b3b1..317bd1c 100644
>> --- a/common/cmd_nvedit.c
>> +++ b/common/cmd_nvedit.c
>> @@ -674,14 +674,40 @@ int envmatch(uchar *s1, int i2)
>>   	return -1;
>>   }
>>
>> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
>> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
>>   			  int argc, char * const argv[])
>>   {
>> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
>> -		return cmd_usage(cmdtp);
>> -
>> -	set_default_env("## Resetting to default environment\n");
>> -	return 0;
>> +	int all = 0, flag = 0;
>> +	debug("Initial value for argc=%d\n", argc);
>> +	while (--argc>  0&&  **++argv == '-') {
>> +		char *arg = *argv;
>> +		while (*++arg) {
>> +			switch (*arg) {
>> +			case 'a':		/* default all */
>> +				all = 1;
>> +				break;
>> +			case 'f':		/* force */
>> +				flag |= H_FORCE;
>> +				break;
>> +			default:
>> +				return cmd_usage(cmdtp);
>> +			}
>> +		}
>> +	}
>> +	debug("Final value for argc=%d\n", argc);
>> +	if (all&&  (argc == 0)) {
>> +		/* Reset the whole environment */
>> +		set_default_env("## Resetting to default environment\n");
>> +		return 0;
>> +	}
>> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
>> +	if (!all&&  (argc>  0)) {
>> +		/* Reset individual variables */
>> +		env_default_vars(argc, argv);
>> +		return 0;
>> +	}
>> +#endif
>> +	return cmd_usage(cmdtp);
>>   }
>>
>>   static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
>> @@ -1012,7 +1038,10 @@ U_BOOT_CMD(
>>   #if defined(CONFIG_CMD_ASKENV)
>>   	"ask name [message] [size] - ask for environment variable\nenv "
>>   #endif
>> -	"default -f - reset default environment\n"
>> +	"default [-f] -a - [forcibly] reset default environment\n"
>> +#if defined(CONFIG_CMD_DEFAULTENV_VARS)
>> +	"env default [-f] var [...] - [forcibly] reset variable(s) to their
>> default values\n" +#endif
>>   #if defined(CONFIG_CMD_EDITENV)
>>   	"env edit name - edit environment variable\n"
>>   #endif
>> diff --git a/common/env_common.c b/common/env_common.c
>> index 7e2bb2f..56719a6 100644
>> --- a/common/env_common.c
>> +++ b/common/env_common.c
>> @@ -157,6 +157,11 @@ const uchar *env_get_addr(int index)
>>
>>   void set_default_env(const char *s)
>>   {
>> +	/*
>> +	 * By default, do not apply changes as they will eventually
>> +	 * be applied by someone else
>> +	 */
>> +	apply_cb apply_function = NULL;
>>   	if (sizeof(default_environment)>  ENV_SIZE) {
>>   		puts("*** Error - default environment is too large\n\n");
>>   		return;
>> @@ -168,6 +173,14 @@ void set_default_env(const char *s)
>>   				"using default environment\n\n",
>>   				s + 1);
>>   		} else {
>> +			/*
>> +			 * This set_to_default was explicitly asked for
>> +			 * by the user, as opposed to being a recovery
>> +			 * mechanism. Therefore we chack every single
>> +			 * variable and apply changes to the system
>> +			 * right away (e.g. baudrate, console).
>> +			 */
>> +			apply_function = env_check_apply;
>>   			puts(s);
>>   		}
>>   	} else {
>> @@ -176,12 +189,28 @@ void set_default_env(const char *s)
>>
>>   	if (himport_r(&env_htab, (char *)default_environment,
>>   			sizeof(default_environment), '\0', 0,
>> -			0, NULL, NULL) == 0)
>> +			0, NULL, apply_function) == 0)
>>   		error("Environment import failed: errno = %d\n", errno);
>>
>>   	gd->flags |= GD_FLG_ENV_READY;
>>   }
>>
>> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
>> +
>> +/* [re]set individual variables to their value in the default environment
>> */ +int env_default_vars(int nvars, char * const vars[])
>> +{
>> +	/*
>> +	 * Special use-case: import from default environment
>> +	 * (and use \0 as a separator)
>> +	 */
>> +	return himport_r(&env_htab, (const char *)default_environment,
>> +				sizeof(default_environment), '\0', H_NOCLEAR,
>> +				nvars, vars, env_check_apply);
>> +}
>> +
>> +#endif /* CONFIG_CMD_DEFAULTENV_VARS */
>> +
>>   /*
>>    * Check if CRC is valid and (if yes) import the environment.
>>    * Note that "buf" may or may not be aligned.
>> diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
>> index 9716f9c..e728eae 100644
>> --- a/include/config_cmd_all.h
>> +++ b/include/config_cmd_all.h
>> @@ -25,6 +25,7 @@
>>   #define CONFIG_CMD_CDP		/* Cisco Discovery Protocol	*/
>>   #define CONFIG_CMD_CONSOLE	/* coninfo			*/
>>   #define CONFIG_CMD_DATE		/* support for RTC, date/time...*/
>> +#define CONFIG_CMD_DEFAULTENV_VARS /* default individ variables */
>>   #define CONFIG_CMD_DHCP		/* DHCP Support			*/
>>   #define CONFIG_CMD_DIAG		/* Diagnostics			*/
>>   #define CONFIG_CMD_DISPLAY	/* Display support		*/
>> diff --git a/include/environment.h b/include/environment.h
>> index 3a3e6b8..8f0d4db 100644
>> --- a/include/environment.h
>> +++ b/include/environment.h
>> @@ -190,6 +190,11 @@ void env_crc_update(void);
>>   /* [re]set to the default environment */
>>   void set_default_env(const char *s);
>>
>> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
>> +/* [re]set individual variables to their value in the default environment
>> */ +int env_default_vars(int nvars, char * const vars[]);
>> +#endif
>> +
>>   /* Import from binary representation into hash table */
>>   int env_import(const char *buf, int check);

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2012-03-30 13:00     ` Gerlando Falauto
@ 2012-03-30 13:08       ` Marek Vasut
  2012-03-30 13:22         ` Gerlando Falauto
  2012-03-30 17:00       ` Gerlando Falauto
  1 sibling, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-03-30 13:08 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 03/29/2012 10:19 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> > WD prodded me too long to review this patchset ;-D
> 
> Well, better late than never! ;-)
> 
> [...]
> 
> >> +#if defined(CONFIG_CMD_NET)
> >> +	else if (strcmp(name, "bootfile") == 0) {
> >> +		copy_filename(BootFile, newval, sizeof(BootFile));
> > 
> > Can you remove the camel-case here please?
> 
> That's code I just moved around... Will do, sir.

Don't call me that way, makes me feel old :D

> >> +		return 0;
> >> +	}
> >> +#endif
> >> +	return 0;
> >> +}
> >> +
> 
> [...]
> 
> >> --- a/include/search.h
> >> +++ b/include/search.h
> >> @@ -47,6 +47,13 @@ typedef struct entry {
> >> 
> >>   struct _ENTRY;
> >>   
> >>   /*
> >> 
> >> + * Callback function to be called for checking whether the given change
> >> may + * be applied or not. Must return 0 for approval, 1 for denial.
> >> + */
> >> +typedef int (*apply_cb)(const char *name, const char *oldval,
> >> +			const char *newval, int flag);
> > 
> > Is the typedef really necessary ?
> > 
>  >[From your other email]
>  >
>  > I have to admit I'm not much of a fan of how you use this apply()
>  > callback, is it really necessary?
> 
> Why ask, if you already know the answer? :-)
> 
> I'm not a big fan either, seemed like the easiest approach at the time.
> The idea was to keep the hastable (struct hsearch_data) as decoupled as
> possible from the environment (env_htab which is, in fact, the only
> instance of struct hsearch_data).
> 
> What if the function pointer was stored within the hastable itself?
> Sort of a virtual method.
> This way we get rid of the typedef and the function pointer as a
> parameter altogether.
> The callback parameter then just becomes a boolean value (meaning,
> do/don't call the callback function stored within the hashtable itself).
> I like that much better. What do you think?

Don't we always use only one (this callback) function?

> 
> [...]
> 
> >>   /* Flags for himport_r() */
> >>   #define	H_NOCLEAR	1	/* do not clear hash table before
> > 
> > importing */
> > 
> >> +#define H_FORCE		2	/* overwrite read-only/write-once
> > 
> > variables */
> > 
> > Make this 1<<  x please.
> 
> OK.
> 
> >>   #endif /* search.h */
> >> 
> >> diff --git a/lib/hashtable.c b/lib/hashtable.c
> >> index abd61c8..75b9b07 100644
> >> --- a/lib/hashtable.c
> >> +++ b/lib/hashtable.c
> >> @@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> >> char sep, * himport()
> >> 
> >>    */
> >> 
> >> +/* Check whether variable name is amongst vars[] */
> >> +static int process_var(const char *name, int nvars, char * const
> >> vars[])
> > 
> > You mean check_var()?
> 
> I mean is_var_in_set_or_is_set_empty().

Nice name :)

> Sorry, I'm very, very bad at picking function names.
> Any suggestion?

The above is quite descriptive ... maybe is_var_in_set() ? And hey, don't be 
sorry, you're doing very good job!

> 
> >> +{
> >> +	int i = 0;
> >> +	/* No variables specified means process all of them */
> >> +	if (nvars == 0)
> >> +		return 1;
> >> +
> >> +	for (i = 0; i<  nvars; i++) {
> >> +		if (!strcmp(name, vars[i]))
> >> +			return 1;
> >> +	}
> >> +	debug("Skipping non-listed variable %s\n", name);
> >> +	return 0;
> >> +}
> >> +
> >> 
> >>   /*
> >>   
> >>    * Import linearized data into hash table.
> >>    *
> >> 
> >> @@ -639,7 +655,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> >> char sep, */
> >> 
> >>   int himport_r(struct hsearch_data *htab,
> >> 
> >> -	      const char *env, size_t size, const char sep, int flag)
> >> +		const char *env, size_t size, const char sep, int flag,
> >> +		int nvars, char * const vars[],
> >> +		apply_cb apply)
> >> 
> >>   {
> >>   
> >>   	char *data, *sp, *dp, *name, *value;
> >> 
> >> @@ -726,6 +744,8 @@ int himport_r(struct hsearch_data *htab,
> >> 
> >>   			*dp++ = '\0';	/* terminate name */
> >>   			
> >>   			debug("DELETE CANDIDATE: \"%s\"\n", name);
> >> 
> >> +			if (!process_var(name, nvars, vars))
> >> +				continue;
> >> 
> >>   			if (hdelete_r(name, htab) == 0)
> >>   			
> >>   				debug("DELETE ERROR
> > 
> > ##############################\n");
> > 
> >> @@ -743,10 +763,31 @@ int himport_r(struct hsearch_data *htab,
> >> 
> >>   		*sp++ = '\0';	/* terminate value */
> >>   		++dp;
> >> 
> >> +		/* Skip variables which are not supposed to be treated */
> >> +		if (!process_var(name, nvars, vars))
> >> +			continue;
> >> +
> >> 
> >>   		/* enter into hash table */
> >>   		e.key = name;
> >>   		e.data = value;
> > 
> > Do you need to do this if you eventually later figure out you have no
> > apply() callback and you did this for no reason?
> 
> You mean calling process_var()? It's two separate things.
> 
> One, filter out the variables that were not asked to be processed, if
> there were any (call to process_var())
> Two, check whether the new value is acceptable and/or apply it (call
> apply())
> You could have none, either, or both.
> 
> Or else, if you mean moving the e.key = name, e.data = value
> assignments, you're right, they should be moved down (but in that case
> it would be because the apply function fails, not because it's not
> present -- default case is always successful).

Yep, that's what I meant. OK

> 
> >> +		/* if there is an apply function, check what it has to say */
> >> +		if (apply != NULL) {
> >> +			debug("searching before calling cb function"
> >> +				" for  %s\n", name);
> >> +			/*
> >> +			 * Search for variable in existing env, so to pass
> >> +			 * its previous value to the apply callback
> >> +			 */
> >> +			hsearch_r(e, FIND,&rv, htab);
> >> +			debug("previous value was %s\n", rv ? rv->data : "");
> >> +			if (apply(name, rv ? rv->data : NULL, value, flag)) {
> >> +				debug("callback function refused to set"
> >> +					" variable %s, skipping it!\n", name);
> >> +				continue;
> >> +			}
> >> +		}
> >> +
> >> 
> >>   		hsearch_r(e, ENTER,&rv, htab);
> >>   		if (rv == NULL) {
> >>   		
> >>   			printf("himport_r: can't insert \"%s=%s\" into hash
> > 
> > table\n",
> 
> Thank you,
> Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply
  2012-03-30 13:00     ` Gerlando Falauto
@ 2012-03-30 13:09       ` Marek Vasut
  2012-03-30 13:25         ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-03-30 13:09 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 03/29/2012 10:25 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> >> Changes in the syntax (user API) for "env default":
> >>    -f: override write-once variables
> >>    -a: all (resetting the whole env is NOT the default behavior)
> >> 
> >> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
> > 
> > I have to admit I'm not much of a fan of how you use this apply()
> > callback, is it really necessary?
> 
> See my previous email.
> 
> > Also, do we need special command for default env?
> 
> I am sorry, I don't get the question. What do you mean?
> It's always the same "env import" with an augmented command line.
> If you're referring to CONFIG_CMD_DEFAULTENV_VARS, I don't think it's
> neeed either, but it was requested at some previous time.

Hmm.

> I also think it's misleading to have some syntax for the same command
> conditionally enabled. Has it ever been done before?

Yes it was, but this is creepy -- is this command displaying the compiled-in set 
of env vars?

> 
> Thank you,
> Gerlando
> 
> > M
> > 
> >> ---
> >> 
> >>   README                   |    2 ++
> >>   common/cmd_nvedit.c      |   43
> >> 
> >> ++++++++++++++++++++++++++++++++++++------- common/env_common.c      |
> >> 31 ++++++++++++++++++++++++++++++-
> >> 
> >>   include/config_cmd_all.h |    1 +
> >>   include/environment.h    |    5 +++++
> >>   5 files changed, 74 insertions(+), 8 deletions(-)
> >> 
> >> diff --git a/README b/README
> >> index fda0190..e924575 100644
> >> --- a/README
> >> +++ b/README
> >> 
> >> @@ -724,6 +724,8 @@ The following options need to be configured:
> >>   		CONFIG_CMD_CONSOLE	  coninfo
> >>   		CONFIG_CMD_CRC32	* crc32
> >>   		CONFIG_CMD_DATE		* support for RTC, date/time...
> >> 
> >> +		CONFIG_CMD_DEFAULTENV_VARS
> >> +					* Reset individual variables to default
> >> 
> >>   		CONFIG_CMD_DHCP		* DHCP support
> >>   		CONFIG_CMD_DIAG		* Diagnostics
> >>   		CONFIG_CMD_DS4510	* ds4510 I2C gpio commands
> >> 
> >> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> >> index 871b3b1..317bd1c 100644
> >> --- a/common/cmd_nvedit.c
> >> +++ b/common/cmd_nvedit.c
> >> @@ -674,14 +674,40 @@ int envmatch(uchar *s1, int i2)
> >> 
> >>   	return -1;
> >>   
> >>   }
> >> 
> >> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
> >> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
> >> 
> >>   			  int argc, char * const argv[])
> >>   
> >>   {
> >> 
> >> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
> >> -		return cmd_usage(cmdtp);
> >> -
> >> -	set_default_env("## Resetting to default environment\n");
> >> -	return 0;
> >> +	int all = 0, flag = 0;
> >> +	debug("Initial value for argc=%d\n", argc);
> >> +	while (--argc>  0&&  **++argv == '-') {
> >> +		char *arg = *argv;
> >> +		while (*++arg) {
> >> +			switch (*arg) {
> >> +			case 'a':		/* default all */
> >> +				all = 1;
> >> +				break;
> >> +			case 'f':		/* force */
> >> +				flag |= H_FORCE;
> >> +				break;
> >> +			default:
> >> +				return cmd_usage(cmdtp);
> >> +			}
> >> +		}
> >> +	}
> >> +	debug("Final value for argc=%d\n", argc);
> >> +	if (all&&  (argc == 0)) {
> >> +		/* Reset the whole environment */
> >> +		set_default_env("## Resetting to default environment\n");
> >> +		return 0;
> >> +	}
> >> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> >> +	if (!all&&  (argc>  0)) {
> >> +		/* Reset individual variables */
> >> +		env_default_vars(argc, argv);
> >> +		return 0;
> >> +	}
> >> +#endif
> >> +	return cmd_usage(cmdtp);
> >> 
> >>   }
> >>   
> >>   static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
> >> 
> >> @@ -1012,7 +1038,10 @@ U_BOOT_CMD(
> >> 
> >>   #if defined(CONFIG_CMD_ASKENV)
> >>   
> >>   	"ask name [message] [size] - ask for environment variable\nenv "
> >>   
> >>   #endif
> >> 
> >> -	"default -f - reset default environment\n"
> >> +	"default [-f] -a - [forcibly] reset default environment\n"
> >> +#if defined(CONFIG_CMD_DEFAULTENV_VARS)
> >> +	"env default [-f] var [...] - [forcibly] reset variable(s) to their
> >> default values\n" +#endif
> >> 
> >>   #if defined(CONFIG_CMD_EDITENV)
> >>   
> >>   	"env edit name - edit environment variable\n"
> >>   
> >>   #endif
> >> 
> >> diff --git a/common/env_common.c b/common/env_common.c
> >> index 7e2bb2f..56719a6 100644
> >> --- a/common/env_common.c
> >> +++ b/common/env_common.c
> >> @@ -157,6 +157,11 @@ const uchar *env_get_addr(int index)
> >> 
> >>   void set_default_env(const char *s)
> >>   {
> >> 
> >> +	/*
> >> +	 * By default, do not apply changes as they will eventually
> >> +	 * be applied by someone else
> >> +	 */
> >> +	apply_cb apply_function = NULL;
> >> 
> >>   	if (sizeof(default_environment)>  ENV_SIZE) {
> >>   	
> >>   		puts("*** Error - default environment is too large\n\n");
> >>   		return;
> >> 
> >> @@ -168,6 +173,14 @@ void set_default_env(const char *s)
> >> 
> >>   				"using default environment\n\n",
> >>   				s + 1);
> >>   		
> >>   		} else {
> >> 
> >> +			/*
> >> +			 * This set_to_default was explicitly asked for
> >> +			 * by the user, as opposed to being a recovery
> >> +			 * mechanism. Therefore we chack every single
> >> +			 * variable and apply changes to the system
> >> +			 * right away (e.g. baudrate, console).
> >> +			 */
> >> +			apply_function = env_check_apply;
> >> 
> >>   			puts(s);
> >>   		
> >>   		}
> >>   	
> >>   	} else {
> >> 
> >> @@ -176,12 +189,28 @@ void set_default_env(const char *s)
> >> 
> >>   	if (himport_r(&env_htab, (char *)default_environment,
> >>   	
> >>   			sizeof(default_environment), '\0', 0,
> >> 
> >> -			0, NULL, NULL) == 0)
> >> +			0, NULL, apply_function) == 0)
> >> 
> >>   		error("Environment import failed: errno = %d\n", errno);
> >>   	
> >>   	gd->flags |= GD_FLG_ENV_READY;
> >>   
> >>   }
> >> 
> >> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> >> +
> >> +/* [re]set individual variables to their value in the default
> >> environment */ +int env_default_vars(int nvars, char * const vars[])
> >> +{
> >> +	/*
> >> +	 * Special use-case: import from default environment
> >> +	 * (and use \0 as a separator)
> >> +	 */
> >> +	return himport_r(&env_htab, (const char *)default_environment,
> >> +				sizeof(default_environment), '\0', H_NOCLEAR,
> >> +				nvars, vars, env_check_apply);
> >> +}
> >> +
> >> +#endif /* CONFIG_CMD_DEFAULTENV_VARS */
> >> +
> >> 
> >>   /*
> >>   
> >>    * Check if CRC is valid and (if yes) import the environment.
> >>    * Note that "buf" may or may not be aligned.
> >> 
> >> diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
> >> index 9716f9c..e728eae 100644
> >> --- a/include/config_cmd_all.h
> >> +++ b/include/config_cmd_all.h
> >> @@ -25,6 +25,7 @@
> >> 
> >>   #define CONFIG_CMD_CDP		/* Cisco Discovery Protocol	*/
> >>   #define CONFIG_CMD_CONSOLE	/* coninfo			*/
> >>   #define CONFIG_CMD_DATE		/* support for RTC, date/time...*/
> >> 
> >> +#define CONFIG_CMD_DEFAULTENV_VARS /* default individ variables */
> >> 
> >>   #define CONFIG_CMD_DHCP		/* DHCP Support			*/
> >>   #define CONFIG_CMD_DIAG		/* Diagnostics			*/
> >>   #define CONFIG_CMD_DISPLAY	/* Display support		*/
> >> 
> >> diff --git a/include/environment.h b/include/environment.h
> >> index 3a3e6b8..8f0d4db 100644
> >> --- a/include/environment.h
> >> +++ b/include/environment.h
> >> @@ -190,6 +190,11 @@ void env_crc_update(void);
> >> 
> >>   /* [re]set to the default environment */
> >>   void set_default_env(const char *s);
> >> 
> >> +#ifdef CONFIG_CMD_DEFAULTENV_VARS
> >> +/* [re]set individual variables to their value in the default
> >> environment */ +int env_default_vars(int nvars, char * const vars[]);
> >> +#endif
> >> +
> >> 
> >>   /* Import from binary representation into hash table */
> >>   int env_import(const char *buf, int check);

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2012-03-30 13:08       ` Marek Vasut
@ 2012-03-30 13:22         ` Gerlando Falauto
  2012-03-30 13:55           ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-03-30 13:22 UTC (permalink / raw)
  To: u-boot

On 03/30/2012 03:08 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> On 03/29/2012 10:19 PM, Marek Vasut wrote:
>>> Dear Gerlando Falauto,
>>>
>>> WD prodded me too long to review this patchset ;-D
>>
>> Well, better late than never! ;-)
>>
>> [...]
>>
>>>> +#if defined(CONFIG_CMD_NET)
>>>> +	else if (strcmp(name, "bootfile") == 0) {
>>>> +		copy_filename(BootFile, newval, sizeof(BootFile));
>>>
>>> Can you remove the camel-case here please?
>>
>> That's code I just moved around... Will do, sir.
>
> Don't call me that way, makes me feel old :D

Was more of a way to remark authority than age. :-)

>
>>>> +		return 0;
>>>> +	}
>>>> +#endif
>>>> +	return 0;
>>>> +}
>>>> +
>>
>> [...]
>>
>>>> --- a/include/search.h
>>>> +++ b/include/search.h
>>>> @@ -47,6 +47,13 @@ typedef struct entry {
>>>>
>>>>    struct _ENTRY;
>>>>
>>>>    /*
>>>>
>>>> + * Callback function to be called for checking whether the given change
>>>> may + * be applied or not. Must return 0 for approval, 1 for denial.
>>>> + */
>>>> +typedef int (*apply_cb)(const char *name, const char *oldval,
>>>> +			const char *newval, int flag);
>>>
>>> Is the typedef really necessary ?
>>>
>>   >[From your other email]
>>   >
>>   >  I have to admit I'm not much of a fan of how you use this apply()
>>   >  callback, is it really necessary?
>>
>> Why ask, if you already know the answer? :-)
>>
>> I'm not a big fan either, seemed like the easiest approach at the time.
>> The idea was to keep the hastable (struct hsearch_data) as decoupled as
>> possible from the environment (env_htab which is, in fact, the only
>> instance of struct hsearch_data).
>>
>> What if the function pointer was stored within the hastable itself?
>> Sort of a virtual method.
>> This way we get rid of the typedef and the function pointer as a
>> parameter altogether.
>> The callback parameter then just becomes a boolean value (meaning,
>> do/don't call the callback function stored within the hashtable itself).
>> I like that much better. What do you think?
>
> Don't we always use only one (this callback) function?

Yes, but only because env is the only hashtable present.
Is that a yes or a no, then?

>
>>
>> [...]
>>
>>>>    /* Flags for himport_r() */
>>>>    #define	H_NOCLEAR	1	/* do not clear hash table before
>>>
>>> importing */
>>>
>>>> +#define H_FORCE		2	/* overwrite read-only/write-once
>>>
>>> variables */
>>>
>>> Make this 1<<   x please.
>>
>> OK.
>>
>>>>    #endif /* search.h */
>>>>
>>>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>>>> index abd61c8..75b9b07 100644
>>>> --- a/lib/hashtable.c
>>>> +++ b/lib/hashtable.c
>>>> @@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab, const
>>>> char sep, * himport()
>>>>
>>>>     */
>>>>
>>>> +/* Check whether variable name is amongst vars[] */
>>>> +static int process_var(const char *name, int nvars, char * const
>>>> vars[])
>>>
>>> You mean check_var()?
>>
>> I mean is_var_in_set_or_is_set_empty().
>
> Nice name :)
>
>> Sorry, I'm very, very bad at picking function names.
>> Any suggestion?
>
> The above is quite descriptive ... maybe is_var_in_set() ? And hey, don't be
> sorry, you're doing very good job!

I like is_var_in_set().

Thanks,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply
  2012-03-30 13:09       ` Marek Vasut
@ 2012-03-30 13:25         ` Gerlando Falauto
  0 siblings, 0 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-03-30 13:25 UTC (permalink / raw)
  To: u-boot

On 03/30/2012 03:09 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> On 03/29/2012 10:25 PM, Marek Vasut wrote:
>>> Dear Gerlando Falauto,
>>>
>>>> Changes in the syntax (user API) for "env default":
>>>>     -f: override write-once variables
>>>>     -a: all (resetting the whole env is NOT the default behavior)
>>>>
>>>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>>>
>>> I have to admit I'm not much of a fan of how you use this apply()
>>> callback, is it really necessary?
>>
>> See my previous email.
>>
>>> Also, do we need special command for default env?
>>
>> I am sorry, I don't get the question. What do you mean?
>> It's always the same "env import" with an augmented command line.
>> If you're referring to CONFIG_CMD_DEFAULTENV_VARS, I don't think it's
>> neeed either, but it was requested at some previous time.
>
> Hmm.
>
>> I also think it's misleading to have some syntax for the same command
>> conditionally enabled. Has it ever been done before?
>
> Yes it was, but this is creepy -- is this command displaying the compiled-in set
> of env vars?

Nope, "env default" will reset the environment to the default.
I just made it selective, so that you can specify a subset of variables 
to be restored to default. I also changed the meaning of "-f", which 
used to mean "all", and now means "force", and added "-a" which now 
means "all".

Thank you,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2012-03-30 13:22         ` Gerlando Falauto
@ 2012-03-30 13:55           ` Marek Vasut
  2012-03-30 14:03             ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-03-30 13:55 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 03/30/2012 03:08 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> >> On 03/29/2012 10:19 PM, Marek Vasut wrote:
> >>> Dear Gerlando Falauto,
> >>> 
> >>> WD prodded me too long to review this patchset ;-D
> >> 
> >> Well, better late than never! ;-)
> >> 
> >> [...]
> >> 
> >>>> +#if defined(CONFIG_CMD_NET)
> >>>> +	else if (strcmp(name, "bootfile") == 0) {
> >>>> +		copy_filename(BootFile, newval, sizeof(BootFile));
> >>> 
> >>> Can you remove the camel-case here please?
> >> 
> >> That's code I just moved around... Will do, sir.
> > 
> > Don't call me that way, makes me feel old :D
> 
> Was more of a way to remark authority than age. :-)

;-)

> >>>> +		return 0;
> >>>> +	}
> >>>> +#endif
> >>>> +	return 0;
> >>>> +}
> >>>> +
> >> 
> >> [...]
> >> 
> >>>> --- a/include/search.h
> >>>> +++ b/include/search.h
> >>>> @@ -47,6 +47,13 @@ typedef struct entry {
> >>>> 
> >>>>    struct _ENTRY;
> >>>>    
> >>>>    /*
> >>>> 
> >>>> + * Callback function to be called for checking whether the given
> >>>> change may + * be applied or not. Must return 0 for approval, 1 for
> >>>> denial. + */
> >>>> +typedef int (*apply_cb)(const char *name, const char *oldval,
> >>>> +			const char *newval, int flag);
> >>> 
> >>> Is the typedef really necessary ?
> >>> 
> >>   >[From your other email]
> >>   >
> >>   >  I have to admit I'm not much of a fan of how you use this apply()
> >>   >  callback, is it really necessary?
> >> 
> >> Why ask, if you already know the answer? :-)
> >> 
> >> I'm not a big fan either, seemed like the easiest approach at the time.
> >> The idea was to keep the hastable (struct hsearch_data) as decoupled as
> >> possible from the environment (env_htab which is, in fact, the only
> >> instance of struct hsearch_data).
> >> 
> >> What if the function pointer was stored within the hastable itself?
> >> Sort of a virtual method.
> >> This way we get rid of the typedef and the function pointer as a
> >> parameter altogether.
> >> The callback parameter then just becomes a boolean value (meaning,
> >> do/don't call the callback function stored within the hashtable itself).
> >> I like that much better. What do you think?
> > 
> > Don't we always use only one (this callback) function?
> 
> Yes, but only because env is the only hashtable present.
> Is that a yes or a no, then?

Do we expect any more hashtables in the near future ?

> >> [...]
> >> 
> >>>>    /* Flags for himport_r() */
> >>>>    #define	H_NOCLEAR	1	/* do not clear hash table 
before
> >>> 
> >>> importing */
> >>> 
> >>>> +#define H_FORCE		2	/* overwrite read-only/write-once
> >>> 
> >>> variables */
> >>> 
> >>> Make this 1<<   x please.
> >> 
> >> OK.
> >> 
> >>>>    #endif /* search.h */
> >>>> 
> >>>> diff --git a/lib/hashtable.c b/lib/hashtable.c
> >>>> index abd61c8..75b9b07 100644
> >>>> --- a/lib/hashtable.c
> >>>> +++ b/lib/hashtable.c
> >>>> @@ -603,6 +603,22 @@ ssize_t hexport_r(struct hsearch_data *htab,
> >>>> const char sep, * himport()
> >>>> 
> >>>>     */
> >>>> 
> >>>> +/* Check whether variable name is amongst vars[] */
> >>>> +static int process_var(const char *name, int nvars, char * const
> >>>> vars[])
> >>> 
> >>> You mean check_var()?
> >> 
> >> I mean is_var_in_set_or_is_set_empty().
> > 
> > Nice name :)
> > 
> >> Sorry, I'm very, very bad at picking function names.
> >> Any suggestion?
> > 
> > The above is quite descriptive ... maybe is_var_in_set() ? And hey, don't
> > be sorry, you're doing very good job!
> 
> I like is_var_in_set().

So be it then ;-)

Thanks!

> Thanks,
> Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2012-03-30 13:55           ` Marek Vasut
@ 2012-03-30 14:03             ` Gerlando Falauto
  2012-03-30 14:28               ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-03-30 14:03 UTC (permalink / raw)
  To: u-boot

On 03/30/2012 03:55 PM, Marek Vasut wrote:

> Dear Gerlando Falauto,
>
>> On 03/30/2012 03:08 PM, Marek Vasut wrote:
>>> Dear Gerlando Falauto,
>>>
>>>> On 03/29/2012 10:19 PM, Marek Vasut wrote:
[...]
>>>>>> +		return 0;
>>>>>> +	}
>>>>>> +#endif
>>>>>> +	return 0;
>>>>>> +}
>>>>>> +
>>>>
>>>> [...]
>>>>
>>>>>> --- a/include/search.h
>>>>>> +++ b/include/search.h
>>>>>> @@ -47,6 +47,13 @@ typedef struct entry {
>>>>>>
>>>>>>     struct _ENTRY;
>>>>>>
>>>>>>     /*
>>>>>>
>>>>>> + * Callback function to be called for checking whether the given
>>>>>> change may + * be applied or not. Must return 0 for approval, 1 for
>>>>>> denial. + */
>>>>>> +typedef int (*apply_cb)(const char *name, const char *oldval,
>>>>>> +			const char *newval, int flag);
>>>>>
>>>>> Is the typedef really necessary ?
>>>>>
>>>>    >[From your other email]
>>>>    >
>>>>    >   I have to admit I'm not much of a fan of how you use this apply()
>>>>    >   callback, is it really necessary?
>>>>
>>>> Why ask, if you already know the answer? :-)
>>>>
>>>> I'm not a big fan either, seemed like the easiest approach at the time.
>>>> The idea was to keep the hastable (struct hsearch_data) as decoupled as
>>>> possible from the environment (env_htab which is, in fact, the only
>>>> instance of struct hsearch_data).
>>>>
>>>> What if the function pointer was stored within the hastable itself?
>>>> Sort of a virtual method.
>>>> This way we get rid of the typedef and the function pointer as a
>>>> parameter altogether.
>>>> The callback parameter then just becomes a boolean value (meaning,
>>>> do/don't call the callback function stored within the hashtable itself).
>>>> I like that much better. What do you think?
>>>
>>> Don't we always use only one (this callback) function?
>>
>> Yes, but only because env is the only hashtable present.
>> Is that a yes or a no, then?
>
> Do we expect any more hashtables in the near future ?

I don't think so. Anyway I would rather avoid calling functions 
belonging to the environment domain from the hastable domain directly.
For that matter, we have a single "struct hsearch_data" instance in the 
whole project, but we keep passing it around as an argument to the 
hashtable functions.

Best,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2012-03-30 14:03             ` Gerlando Falauto
@ 2012-03-30 14:28               ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-03-30 14:28 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 03/30/2012 03:55 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> >> On 03/30/2012 03:08 PM, Marek Vasut wrote:
> >>> Dear Gerlando Falauto,
> >>> 
> >>>> On 03/29/2012 10:19 PM, Marek Vasut wrote:
> [...]
> 
> >>>>>> +		return 0;
> >>>>>> +	}
> >>>>>> +#endif
> >>>>>> +	return 0;
> >>>>>> +}
> >>>>>> +
> >>>> 
> >>>> [...]
> >>>> 
> >>>>>> --- a/include/search.h
> >>>>>> +++ b/include/search.h
> >>>>>> @@ -47,6 +47,13 @@ typedef struct entry {
> >>>>>> 
> >>>>>>     struct _ENTRY;
> >>>>>>     
> >>>>>>     /*
> >>>>>> 
> >>>>>> + * Callback function to be called for checking whether the given
> >>>>>> change may + * be applied or not. Must return 0 for approval, 1 for
> >>>>>> denial. + */
> >>>>>> +typedef int (*apply_cb)(const char *name, const char *oldval,
> >>>>>> +			const char *newval, int flag);
> >>>>> 
> >>>>> Is the typedef really necessary ?
> >>>>> 
> >>>>    >[From your other email]
> >>>>    >
> >>>>    >   I have to admit I'm not much of a fan of how you use this
> >>>>    >   apply() callback, is it really necessary?
> >>>> 
> >>>> Why ask, if you already know the answer? :-)
> >>>> 
> >>>> I'm not a big fan either, seemed like the easiest approach at the
> >>>> time. The idea was to keep the hastable (struct hsearch_data) as
> >>>> decoupled as possible from the environment (env_htab which is, in
> >>>> fact, the only instance of struct hsearch_data).
> >>>> 
> >>>> What if the function pointer was stored within the hastable itself?
> >>>> Sort of a virtual method.
> >>>> This way we get rid of the typedef and the function pointer as a
> >>>> parameter altogether.
> >>>> The callback parameter then just becomes a boolean value (meaning,
> >>>> do/don't call the callback function stored within the hashtable
> >>>> itself). I like that much better. What do you think?
> >>> 
> >>> Don't we always use only one (this callback) function?
> >> 
> >> Yes, but only because env is the only hashtable present.
> >> Is that a yes or a no, then?
> > 
> > Do we expect any more hashtables in the near future ?
> 
> I don't think so. Anyway I would rather avoid calling functions
> belonging to the environment domain from the hastable domain directly.
> For that matter, we have a single "struct hsearch_data" instance in the
> whole project, but we keep passing it around as an argument to the
> hashtable functions.

Ah, it just came to me.

On the other hand, I have this strange feeling lib/hashtable.c is so modified 
for uboot it can't be used (in a generic way) for any other storage than env ... 
or am I wrong?

WD, can you comment please?

> Best,
> Gerlando

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes
  2012-03-30 13:00     ` Gerlando Falauto
  2012-03-30 13:08       ` Marek Vasut
@ 2012-03-30 17:00       ` Gerlando Falauto
  1 sibling, 0 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-03-30 17:00 UTC (permalink / raw)
  To: u-boot

On 03/30/2012 03:00 PM, Gerlando Falauto wrote:
> On 03/29/2012 10:19 PM, Marek Vasut wrote:
[...]
>>> +#if defined(CONFIG_CMD_NET)
>>> + else if (strcmp(name, "bootfile") == 0) {
>>> + copy_filename(BootFile, newval, sizeof(BootFile));
>>
>> Can you remove the camel-case here please?
>>
>
> That's code I just moved around... Will do, sir.

Can't do that, sorry. The global symbol "BootFile" has been defined 
somewhere else and it's used all over the place.

[...]
>>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>>> index abd61c8..75b9b07 100644
>>> --- a/lib/hashtable.c
>>> +++ b/lib/hashtable.c
[...]
>>> @@ -726,6 +744,8 @@ int himport_r(struct hsearch_data *htab,
>>> *dp++ = '\0'; /* terminate name */
>>>
>>> debug("DELETE CANDIDATE: \"%s\"\n", name);
>>> + if (!process_var(name, nvars, vars))
>>> + continue;
>>>
>>> if (hdelete_r(name, htab) == 0)
>>> debug("DELETE ERROR
>> ##############################\n");
>>> @@ -743,10 +763,31 @@ int himport_r(struct hsearch_data *htab,
>>> *sp++ = '\0'; /* terminate value */
>>> ++dp;
>>>
>>> + /* Skip variables which are not supposed to be treated */
>>> + if (!process_var(name, nvars, vars))
>>> + continue;
>>> +
>>> /* enter into hash table */
>>> e.key = name;
>>> e.data = value;
>>
>> Do you need to do this if you eventually later figure out you have no
>> apply()
>> callback and you did this for no reason?
>
> You mean calling process_var()? It's two separate things.
>
> One, filter out the variables that were not asked to be processed, if
> there were any (call to process_var())
> Two, check whether the new value is acceptable and/or apply it (call
> apply())
> You could have none, either, or both.
>
> Or else, if you mean moving the e.key = name, e.data = value
> assignments, you're right, they should be moved down (but in that case
> it would be because the apply function fails, not because it's not
> present -- default case is always successful).

Hhmm... sorry, the assignments need to stay where they are.
Values in e.key and e.data are used by hsearch_r() within the if statement.

>
>>>
>>> + /* if there is an apply function, check what it has to say */
>>> + if (apply != NULL) {
>>> + debug("searching before calling cb function"
>>> + " for %s\n", name);
>>> + /*
>>> + * Search for variable in existing env, so to pass
>>> + * its previous value to the apply callback
>>> + */
>>> + hsearch_r(e, FIND,&rv, htab);
>>> + debug("previous value was %s\n", rv ? rv->data : "");
>>> + if (apply(name, rv ? rv->data : NULL, value, flag)) {
>>> + debug("callback function refused to set"
>>> + " variable %s, skipping it!\n", name);
>>> + continue;
>>> + }
>>> + }
>>> +
>>> hsearch_r(e, ENTER,&rv, htab);
>>> if (rv == NULL) {
>>> printf("himport_r: can't insert \"%s=%s\" into hash
>> table\n",
>
> Thank you,
> Gerlando

Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (8 preceding siblings ...)
  2011-12-07 13:30 ` [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply Gerlando Falauto
@ 2012-04-02 18:26 ` Gerlando Falauto
  2012-08-09 20:17   ` Wolfgang Denk
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 1/6] env: unify logic to check and apply changes Gerlando Falauto
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 18:26 UTC (permalink / raw)
  To: u-boot

This patchset modifies the handling of all the operations on the environment
(set/import/default) so to unify handling of special variables.
On top of that we implement a selective "env default".

A selective "env import" would imply a user API change and should therefore
be discussed separately.

NOTE:
The entire patchset generates an increase in code size of about 1200 bytes
on a PowerPC target. 
As much as I would like to get rid of the set_default_vars() function in 
env_common.c, I have not found a nice way to do so.

Changes in the syntax (user API):
- "env default" -f: override write-once variables, -a means all
- display a warning when trying to set to default variables not
  present in the default env.

Changes from v2:
- removed typedef for callback, moved to the hashtable (struct hsearch_data)
- refactored patchset into smaller patches
  (only patch 5 and 6 should have any visible effect)
- added handling of selected variables not present in the imported env
- removed CONFIG_CMD_DEFAULTENV_VARS
- cosmetic formatting

Changes from v1:
- removed cosmetic patches (now mainstream)
- rebased to latest trunk
- removed subtle error in env_check_apply
  (comparing {loadaddr, bootfile} to values instead
  of variable names)
- changed env_check_apply so not to display warnings
  in case of H_FORCE flag being set

Changes from v0
- checkpatch cleanup
- removed himport_ex()
- removed warning for serial_assign()
- env import NOT implemented here

Gerlando Falauto (6):
  env: unify logic to check and apply changes
  env: make himport_r() selective on variables
  env: add check/apply logic to himport_r()
  env: check and apply changes on delete/destroy
  env: make "env default" selective, check and apply
  env: delete selected vars not present in imported env

 common/cmd_nvedit.c   |  216 +++++++++++++++++++++++++++++++++----------------
 common/env_common.c   |   36 ++++++++-
 include/environment.h |   12 +++
 include/search.h      |   26 +++++-
 lib/hashtable.c       |   95 ++++++++++++++++++++--
 5 files changed, 300 insertions(+), 85 deletions(-)

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 1/6] env: unify logic to check and apply changes
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (9 preceding siblings ...)
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default Gerlando Falauto
@ 2012-04-02 18:26 ` Gerlando Falauto
  2012-04-02 18:56   ` Marek Vasut
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 2/6] env: make himport_r() selective on variables Gerlando Falauto
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 18:26 UTC (permalink / raw)
  To: u-boot

The logic of checking special parameters (e.g. baudrate, stdin, stdout,
for a valid value and/or whether can be overwritten) and applying the
new value to the running system is now all within a single function
env_check_apply() which can be called whenever changes are made
to the environment, no matter if by set, default or import.

With this patch env_check_apply() is only called by "env set",
retaining previous behavior.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |  170 ++++++++++++++++++++++++++++++++-------------------
 include/search.h    |    3 +-
 2 files changed, 109 insertions(+), 64 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 22f9821..e762e76 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -197,32 +197,21 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 #endif
 
 /*
- * Set a new environment variable,
- * or replace or delete an existing one.
+ * Perform consistency checking before setting, replacing, or deleting an
+ * environment variable, then (if successful) apply the changes to internals so
+ * to make them effective.  Code for this function was taken out of
+ * _do_env_set(), which now calls it instead.
+ * Returns 0 in case of success, 1 in case of failure.
+ * When (flag & H_FORCE) is set, do not print out any error message and force
+ * overwriting of write-once variables.
  */
-int _do_env_set(int flag, int argc, char * const argv[])
+
+int env_check_apply(const char *name, const char *oldval,
+			const char *newval, int flag)
 {
 	bd_t  *bd = gd->bd;
-	int   i, len;
+	int   i;
 	int   console = -1;
-	char  *name, *value, *s;
-	ENTRY e, *ep;
-
-	name = argv[1];
-
-	if (strchr(name, '=')) {
-		printf("## Error: illegal character '=' in variable name"
-		       "\"%s\"\n", name);
-		return 1;
-	}
-
-	env_id++;
-	/*
-	 * search if variable with this name already exists
-	 */
-	e.key = name;
-	e.data = NULL;
-	hsearch_r(e, FIND, &ep, &env_htab);
 
 	/* Check for console redirection */
 	if (strcmp(name, "stdin") == 0)
@@ -233,60 +222,76 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		console = stderr;
 
 	if (console != -1) {
-		if (argc < 3) {		/* Cannot delete it! */
-			printf("Can't delete \"%s\"\n", name);
+		if ((newval == NULL) || (*newval == '\0')) {
+			/* We cannot delete stdin/stdout/stderr */
+			if ((flag & H_FORCE) == 0)
+				printf("Can't delete \"%s\"\n", name);
 			return 1;
 		}
 
 #ifdef CONFIG_CONSOLE_MUX
-		i = iomux_doenv(console, argv[2]);
+		i = iomux_doenv(console, newval);
 		if (i)
 			return i;
 #else
 		/* Try assigning specified device */
-		if (console_assign(console, argv[2]) < 0)
+		if (console_assign(console, newval) < 0)
 			return 1;
 
 #ifdef CONFIG_SERIAL_MULTI
-		if (serial_assign(argv[2]) < 0)
+		if (serial_assign(newval) < 0)
 			return 1;
 #endif
 #endif /* CONFIG_CONSOLE_MUX */
 	}
 
 	/*
-	 * Some variables like "ethaddr" and "serial#" can be set only
-	 * once and cannot be deleted; also, "ver" is readonly.
+	 * Some variables like "ethaddr" and "serial#" can be set only once and
+	 * cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined.
 	 */
-	if (ep) {		/* variable exists */
 #ifndef CONFIG_ENV_OVERWRITE
+	if (oldval != NULL &&			/* variable exists */
+		(flag & H_FORCE) == 0) {	/* and we are not forced */
 		if (strcmp(name, "serial#") == 0 ||
 		    (strcmp(name, "ethaddr") == 0
 #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
-		     && strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0
+		     && strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0
 #endif	/* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
 			)) {
 			printf("Can't overwrite \"%s\"\n", name);
 			return 1;
 		}
+	}
 #endif
+	/*
+	 * When we change baudrate, or we are doing an env default -a
+	 * (which will erase all variables prior to calling this),
+	 * we want the baudrate to actually change - for real.
+	 */
+	if (oldval != NULL ||			/* variable exists */
+		(flag & H_NOCLEAR) == 0) {	/* or env is clear */
 		/*
 		 * Switch to new baudrate if new baudrate is supported
 		 */
 		if (strcmp(name, "baudrate") == 0) {
-			int baudrate = simple_strtoul(argv[2], NULL, 10);
+			int baudrate = simple_strtoul(newval, NULL, 10);
 			int i;
 			for (i = 0; i < N_BAUDRATES; ++i) {
 				if (baudrate == baudrate_table[i])
 					break;
 			}
 			if (i == N_BAUDRATES) {
-				printf("## Baudrate %d bps not supported\n",
-					baudrate);
+				if ((flag & H_FORCE) == 0)
+					printf("## Baudrate %d bps not "
+						"supported\n", baudrate);
 				return 1;
 			}
+			if (gd->baudrate == baudrate) {
+				/* If unchanged, we just say it's OK */
+				return 0;
+			}
 			printf("## Switch baudrate to %d bps and"
-			       "press ENTER ...\n", baudrate);
+				"press ENTER ...\n", baudrate);
 			udelay(50000);
 			gd->baudrate = baudrate;
 #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
@@ -300,6 +305,73 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		}
 	}
 
+	/*
+	 * Some variables should be updated when the corresponding
+	 * entry in the environment is changed
+	 */
+	if (strcmp(name, "ipaddr") == 0) {
+		const char *s = newval;
+		char *e;
+		unsigned long addr;
+		bd->bi_ip_addr = 0;
+		for (addr = 0, i = 0; i < 4; ++i) {
+			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
+			addr <<= 8;
+			addr  |= val & 0xFF;
+			if (s)
+				s = *e ? e + 1 : e;
+		}
+		bd->bi_ip_addr = htonl(addr);
+		return 0;
+	} else if (strcmp(name, "loadaddr") == 0) {
+		load_addr = simple_strtoul(newval, NULL, 16);
+		return 0;
+	}
+#if defined(CONFIG_CMD_NET)
+	else if (strcmp(name, "bootfile") == 0) {
+		copy_filename(BootFile, newval, sizeof(BootFile));
+		return 0;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Set a new environment variable,
+ * or replace or delete an existing one.
+*/
+int _do_env_set(int flag, int argc, char * const argv[])
+{
+	int   i, len;
+	char  *name, *value, *s;
+	ENTRY e, *ep;
+
+	name = argv[1];
+	value = argv[2];
+
+	if (strchr(name, '=')) {
+		printf("## Error: illegal character '='"
+		       "in variable name \"%s\"\n", name);
+		return 1;
+	}
+
+	env_id++;
+	/*
+	 * search if variable with this name already exists
+	 */
+	e.key = name;
+	e.data = NULL;
+	hsearch_r(e, FIND, &ep, &env_htab);
+
+	/*
+	 * Perform requested checks. Notice how since we are overwriting
+	 * a single variable, we need to set H_NOCLEAR
+	 */
+	if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
+		debug("check function did not approve, refusing\n");
+		return 1;
+	}
+
 	/* Delete only ? */
 	if (argc < 3 || argv[2] == NULL) {
 		int rc = hdelete_r(name, &env_htab);
@@ -337,34 +409,6 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		return 1;
 	}
 
-	/*
-	 * Some variables should be updated when the corresponding
-	 * entry in the environment is changed
-	 */
-	if (strcmp(name, "ipaddr") == 0) {
-		char *s = argv[2];	/* always use only one arg */
-		char *e;
-		unsigned long addr;
-		bd->bi_ip_addr = 0;
-		for (addr = 0, i = 0; i < 4; ++i) {
-			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
-			addr <<= 8;
-			addr  |= val & 0xFF;
-			if (s)
-				s = *e ? e + 1 : e;
-		}
-		bd->bi_ip_addr = htonl(addr);
-		return 0;
-	} else if (strcmp(argv[1], "loadaddr") == 0) {
-		load_addr = simple_strtoul(argv[2], NULL, 16);
-		return 0;
-	}
-#if defined(CONFIG_CMD_NET)
-	else if (strcmp(argv[1], "bootfile") == 0) {
-		copy_filename(BootFile, argv[2], sizeof(BootFile));
-		return 0;
-	}
-#endif
 	return 0;
 }
 
diff --git a/include/search.h b/include/search.h
index ef53edb..a4a5ef4 100644
--- a/include/search.h
+++ b/include/search.h
@@ -99,6 +99,7 @@ extern int himport_r(struct hsearch_data *__htab,
 		     int __flag);
 
 /* Flags for himport_r() */
-#define	H_NOCLEAR	1	/* do not clear hash table before importing */
+#define	H_NOCLEAR	(1 << 0) /* do not clear hash table before importing */
+#define	H_FORCE		(1 << 1) /* overwrite read-only/write-once variables */
 
 #endif /* search.h */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 2/6] env: make himport_r() selective on variables
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (10 preceding siblings ...)
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 1/6] env: unify logic to check and apply changes Gerlando Falauto
@ 2012-04-02 18:26 ` Gerlando Falauto
  2012-04-02 18:57   ` Marek Vasut
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r() Gerlando Falauto
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 18:26 UTC (permalink / raw)
  To: u-boot

Add 2 new arguments to himport_r():

 o "nvars", "vars": number and list of variables to take into account
   (0 means ALL)

NOTE: This patch does not change the current behaviour.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |    3 ++-
 common/env_common.c |    6 ++++--
 include/search.h    |    6 +++++-
 lib/hashtable.c     |   27 ++++++++++++++++++++++++++-
 4 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index e762e76..59668a6 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -930,7 +930,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
 		addr = (char *)ep->data;
 	}
 
-	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
+	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
+			0, NULL) == 0) {
 		error("Environment import failed: errno = %d\n", errno);
 		return 1;
 	}
diff --git a/common/env_common.c b/common/env_common.c
index c33d22d..a93c062 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -182,7 +182,8 @@ void set_default_env(const char *s)
 	}
 
 	if (himport_r(&env_htab, (char *)default_environment,
-			sizeof(default_environment), '\0', 0) == 0)
+			sizeof(default_environment), '\0', 0,
+			0, NULL) == 0)
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
@@ -207,7 +208,8 @@ int env_import(const char *buf, int check)
 		}
 	}
 
-	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
+	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
+			0, NULL)) {
 		gd->flags |= GD_FLG_ENV_READY;
 		return 1;
 	}
diff --git a/include/search.h b/include/search.h
index a4a5ef4..94d75fc 100644
--- a/include/search.h
+++ b/include/search.h
@@ -94,9 +94,13 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, char **__resp, size_t __size,
 		     int argc, char * const argv[]);
 
+/*
+ * nvars: length of vars array
+ * vars: array of strings (variable names) to import (nvars == 0 means all)
+ */
 extern int himport_r(struct hsearch_data *__htab,
 		     const char *__env, size_t __size, const char __sep,
-		     int __flag);
+		     int __flag, int nvars, char * const vars[]);
 
 /* Flags for himport_r() */
 #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before importing */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index abd61c8..0610e86 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -603,6 +603,24 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  * himport()
  */
 
+/* Check whether variable name is amongst vars[] */
+static int is_var_in_set(const char *name, int nvars, char * const vars[])
+{
+	int i = 0;
+
+	/* No variables specified means process all of them */
+	if (nvars == 0)
+		return 1;
+
+	for (i = 0; i < nvars; i++) {
+		if (!strcmp(name, vars[i]))
+			return 1;
+	}
+	debug("Skipping non-listed variable %s\n", name);
+
+	return 0;
+}
+
 /*
  * Import linearized data into hash table.
  *
@@ -639,7 +657,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  */
 
 int himport_r(struct hsearch_data *htab,
-	      const char *env, size_t size, const char sep, int flag)
+		const char *env, size_t size, const char sep, int flag,
+		int nvars, char * const vars[])
 {
 	char *data, *sp, *dp, *name, *value;
 
@@ -726,6 +745,8 @@ int himport_r(struct hsearch_data *htab,
 			*dp++ = '\0';	/* terminate name */
 
 			debug("DELETE CANDIDATE: \"%s\"\n", name);
+			if (!is_var_in_set(name, nvars, vars))
+				continue;
 
 			if (hdelete_r(name, htab) == 0)
 				debug("DELETE ERROR ##############################\n");
@@ -743,6 +764,10 @@ int himport_r(struct hsearch_data *htab,
 		*sp++ = '\0';	/* terminate value */
 		++dp;
 
+		/* Skip variables which are not supposed to be processed */
+		if (!is_var_in_set(name, nvars, vars))
+			continue;
+
 		/* enter into hash table */
 		e.key = name;
 		e.data = value;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r()
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (11 preceding siblings ...)
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 2/6] env: make himport_r() selective on variables Gerlando Falauto
@ 2012-04-02 18:26 ` Gerlando Falauto
  2012-04-02 19:00   ` Marek Vasut
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 4/6] env: check and apply changes on delete/destroy Gerlando Falauto
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 18:26 UTC (permalink / raw)
  To: u-boot

Change hashtable so that a callback function will decide whether a
variable can be overwritten, and possibly apply the changes.

So add a new field to struct hsearch_data:

 o "apply" callback function to check whether a variable can be
    overwritten, and possibly immediately apply the changes;
    when NULL, no check is performed.

And a new argument to himport_r():
 o "do_apply": whether to call the apply callback function

NOTE: This patch does not change the current behavior.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c   |    3 ++-
 common/env_common.c   |    8 +++++---
 include/environment.h |    9 +++++++++
 include/search.h      |   14 +++++++++++++-
 lib/hashtable.c       |   20 +++++++++++++++++++-
 5 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 59668a6..fc6165f 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -201,6 +201,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
  * environment variable, then (if successful) apply the changes to internals so
  * to make them effective.  Code for this function was taken out of
  * _do_env_set(), which now calls it instead.
+ * Also called as a callback function by himport_r().
  * Returns 0 in case of success, 1 in case of failure.
  * When (flag & H_FORCE) is set, do not print out any error message and force
  * overwriting of write-once variables.
@@ -931,7 +932,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
 	}
 
 	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
-			0, NULL) == 0) {
+			0, NULL, 0 /* do_apply */) == 0) {
 		error("Environment import failed: errno = %d\n", errno);
 		return 1;
 	}
diff --git a/common/env_common.c b/common/env_common.c
index a93c062..5558c1c 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -122,7 +122,9 @@ const uchar default_environment[] = {
 	"\0"
 };
 
-struct hsearch_data env_htab;
+struct hsearch_data env_htab = {
+	.apply = env_check_apply,
+};
 
 static uchar __env_get_char_spec(int index)
 {
@@ -183,7 +185,7 @@ void set_default_env(const char *s)
 
 	if (himport_r(&env_htab, (char *)default_environment,
 			sizeof(default_environment), '\0', 0,
-			0, NULL) == 0)
+			0, NULL, 0 /* do_apply */) == 0)
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
@@ -209,7 +211,7 @@ int env_import(const char *buf, int check)
 	}
 
 	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
-			0, NULL)) {
+			0, NULL, 0 /* do_apply */)) {
 		gd->flags |= GD_FLG_ENV_READY;
 		return 1;
 	}
diff --git a/include/environment.h b/include/environment.h
index 1ef44f3..236e179 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -193,6 +193,15 @@ void set_default_env(const char *s);
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
+/*
+ * Check if variable "name" can be changed from oldval to newval,
+ * and if so, apply the changes (e.g. baudrate).
+ * When (flag & H_FORCE) is set, it does not print out any error
+ * message and forces overwriting of write-once variables.
+ */
+int env_check_apply(const char *name, const char *oldval,
+			const char *newval, int flag);
+
 #endif /* DO_DEPS_ONLY */
 
 #endif /* _ENVIRONMENT_H_ */
diff --git a/include/search.h b/include/search.h
index 94d75fc..721c8ac 100644
--- a/include/search.h
+++ b/include/search.h
@@ -57,6 +57,16 @@ struct hsearch_data {
 	struct _ENTRY *table;
 	unsigned int size;
 	unsigned int filled;
+/*
+ * Callback function which will check whether the given change for variable
+ * "name" from "oldval" to "newval" may be applied or not, and possibly apply
+ * such change.
+ * When (flag & H_FORCE) is set, it shall not print out any error message and
+ * shall force overwriting of write-once variables.
+.* Must return 0 for approval, 1 for denial.
+ */
+	int (*apply)(const char *name, const char *oldval,
+			const char *newval, int flag);
 };
 
 /* Create a new hashing table which will at most contain NEL elements.  */
@@ -97,10 +107,12 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
 /*
  * nvars: length of vars array
  * vars: array of strings (variable names) to import (nvars == 0 means all)
+ * do_apply: whether to call callback function to check the new argument,
+ * and possibly apply changes (false means accept everything)
  */
 extern int himport_r(struct hsearch_data *__htab,
 		     const char *__env, size_t __size, const char __sep,
-		     int __flag, int nvars, char * const vars[]);
+		     int __flag, int nvars, char * const vars[], int do_apply);
 
 /* Flags for himport_r() */
 #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before importing */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 0610e86..6cfba56 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -658,7 +658,7 @@ static int is_var_in_set(const char *name, int nvars, char * const vars[])
 
 int himport_r(struct hsearch_data *htab,
 		const char *env, size_t size, const char sep, int flag,
-		int nvars, char * const vars[])
+		int nvars, char * const vars[], int do_apply)
 {
 	char *data, *sp, *dp, *name, *value;
 
@@ -772,6 +772,24 @@ int himport_r(struct hsearch_data *htab,
 		e.key = name;
 		e.data = value;
 
+		/* if there is an apply function, check what it has to say */
+		if (do_apply && htab->apply != NULL) {
+			debug("searching before calling cb function"
+				" for  %s\n", name);
+			/*
+			 * Search for variable in existing env, so to pass
+			 * its previous value to the apply callback
+			 */
+			hsearch_r(e, FIND, &rv, htab);
+			debug("previous value was %s\n", rv ? rv->data : "");
+			if (htab->apply(name, rv ? rv->data : NULL,
+				value, flag)) {
+				debug("callback function refused to set"
+					" variable %s, skipping it!\n", name);
+				continue;
+			}
+		}
+
 		hsearch_r(e, ENTER, &rv, htab);
 		if (rv == NULL) {
 			printf("himport_r: can't insert \"%s=%s\" into hash table\n",
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 4/6] env: check and apply changes on delete/destroy
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (12 preceding siblings ...)
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r() Gerlando Falauto
@ 2012-04-02 18:26 ` Gerlando Falauto
  2012-04-02 19:01   ` Marek Vasut
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 5/6] env: make "env default" selective, check and apply Gerlando Falauto
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 18:26 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |    2 +-
 include/search.h    |    5 +++--
 lib/hashtable.c     |   16 ++++++++++------
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index fc6165f..091cd46 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -375,7 +375,7 @@ int _do_env_set(int flag, int argc, char * const argv[])
 
 	/* Delete only ? */
 	if (argc < 3 || argv[2] == NULL) {
-		int rc = hdelete_r(name, &env_htab);
+		int rc = hdelete_r(name, &env_htab, 0);
 		return !rc;
 	}
 
diff --git a/include/search.h b/include/search.h
index 721c8ac..93e1cbc 100644
--- a/include/search.h
+++ b/include/search.h
@@ -73,7 +73,7 @@ struct hsearch_data {
 extern int hcreate_r(size_t __nel, struct hsearch_data *__htab);
 
 /* Destroy current internal hashing table.  */
-extern void hdestroy_r(struct hsearch_data *__htab);
+extern void hdestroy_r(struct hsearch_data *__htab, int do_apply);
 
 /*
  * Search for entry matching ITEM.key in internal hash table.  If
@@ -98,7 +98,8 @@ extern int hstrstr_r(const char *__match, int __last_idx, ENTRY ** __retval,
 		    struct hsearch_data *__htab);
 
 /* Search and delete entry matching ITEM.key in internal hash table. */
-extern int hdelete_r(const char *__key, struct hsearch_data *__htab);
+extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
+			int do_apply);
 
 extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, char **__resp, size_t __size,
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 6cfba56..f3f47de 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -142,7 +142,7 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
  * be freed and the local static variable can be marked as not used.
  */
 
-void hdestroy_r(struct hsearch_data *htab)
+void hdestroy_r(struct hsearch_data *htab, int do_apply)
 {
 	int i;
 
@@ -156,7 +156,10 @@ void hdestroy_r(struct hsearch_data *htab)
 	for (i = 1; i <= htab->size; ++i) {
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-
+			if (do_apply && htab->apply != NULL) {
+				/* deletion is always forced */
+				htab->apply(ep->key, ep->data, NULL, H_FORCE);
+			}
 			free((void *)ep->key);
 			free(ep->data);
 		}
@@ -401,7 +404,7 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
  * do that.
  */
 
-int hdelete_r(const char *key, struct hsearch_data *htab)
+int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)
 {
 	ENTRY e, *ep;
 	int idx;
@@ -417,7 +420,8 @@ int hdelete_r(const char *key, struct hsearch_data *htab)
 
 	/* free used ENTRY */
 	debug("hdelete: DELETING key \"%s\"\n", key);
-
+	if (do_apply && htab->apply != NULL)
+		htab->apply(ep->key, ep->data, NULL, H_FORCE);
 	free((void *)ep->key);
 	free(ep->data);
 	htab->table[idx].used = -1;
@@ -682,7 +686,7 @@ int himport_r(struct hsearch_data *htab,
 		debug("Destroy Hash Table: %p table = %p\n", htab,
 		       htab->table);
 		if (htab->table)
-			hdestroy_r(htab);
+			hdestroy_r(htab, do_apply);
 	}
 
 	/*
@@ -748,7 +752,7 @@ int himport_r(struct hsearch_data *htab,
 			if (!is_var_in_set(name, nvars, vars))
 				continue;
 
-			if (hdelete_r(name, htab) == 0)
+			if (hdelete_r(name, htab, do_apply) == 0)
 				debug("DELETE ERROR ##############################\n");
 
 			continue;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 5/6] env: make "env default" selective, check and apply
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (13 preceding siblings ...)
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 4/6] env: check and apply changes on delete/destroy Gerlando Falauto
@ 2012-04-02 18:26 ` Gerlando Falauto
  2012-04-02 19:04   ` Marek Vasut
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 6/6] env: delete selected vars not present in imported env Gerlando Falauto
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 18:26 UTC (permalink / raw)
  To: u-boot

Change the syntax (user API) for "env default":
  -f: override write-once variables
  var... : accept individual variable(s)
  -a: all (resetting the whole env is NOT the default behavior)

Enable variable checking and make changes effective by
enabling do_apply argument to himport_r().

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c   |   40 ++++++++++++++++++++++++++++++++++------
 common/env_common.c   |   28 +++++++++++++++++++++++++++-
 include/environment.h |    3 +++
 3 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 091cd46..d8e233b 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -672,14 +672,41 @@ int envmatch(uchar *s1, int i2)
 	return -1;
 }
 
-static int do_env_default(cmd_tbl_t *cmdtp, int flag,
+static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
 			  int argc, char * const argv[])
 {
-	if (argc != 2 || strcmp(argv[1], "-f") != 0)
-		return CMD_RET_USAGE;
+	int all = 0, flag = 0;
 
-	set_default_env("## Resetting to default environment\n");
-	return 0;
+	debug("Initial value for argc=%d\n", argc);
+	while (--argc > 0 && **++argv == '-') {
+		char *arg = *argv;
+
+		while (*++arg) {
+			switch (*arg) {
+			case 'a':		/* default all */
+				all = 1;
+				break;
+			case 'f':		/* force */
+				flag |= H_FORCE;
+				break;
+			default:
+				return cmd_usage(cmdtp);
+			}
+		}
+	}
+	debug("Final value for argc=%d\n", argc);
+	if (all && (argc == 0)) {
+		/* Reset the whole environment */
+		set_default_env("## Resetting to default environment\n");
+		return 0;
+	}
+	if (!all && (argc > 0)) {
+		/* Reset individual variables */
+		set_default_vars(argc, argv);
+		return 0;
+	}
+
+	return cmd_usage(cmdtp);
 }
 
 static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
@@ -1010,7 +1037,8 @@ U_BOOT_CMD(
 #if defined(CONFIG_CMD_ASKENV)
 	"ask name [message] [size] - ask for environment variable\nenv "
 #endif
-	"default -f - reset default environment\n"
+	"default [-f] -a - [forcibly] reset default environment\n"
+	"env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
 #if defined(CONFIG_CMD_EDITENV)
 	"env edit name - edit environment variable\n"
 #endif
diff --git a/common/env_common.c b/common/env_common.c
index 5558c1c..5104402 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -166,6 +166,11 @@ const uchar *env_get_addr(int index)
 
 void set_default_env(const char *s)
 {
+	/*
+	 * By default, do not apply changes as they will eventually
+	 * be applied by someone else
+	 */
+	int do_apply = 0;
 	if (sizeof(default_environment) > ENV_SIZE) {
 		puts("*** Error - default environment is too large\n\n");
 		return;
@@ -177,6 +182,14 @@ void set_default_env(const char *s)
 				"using default environment\n\n",
 				s + 1);
 		} else {
+			/*
+			 * This set_to_default was explicitly asked for
+			 * by the user, as opposed to being a recovery
+			 * mechanism.  Therefore we check every single
+			 * variable and apply changes to the system
+			 * right away (e.g. baudrate, console).
+			 */
+			do_apply = 1;
 			puts(s);
 		}
 	} else {
@@ -185,12 +198,25 @@ void set_default_env(const char *s)
 
 	if (himport_r(&env_htab, (char *)default_environment,
 			sizeof(default_environment), '\0', 0,
-			0, NULL, 0 /* do_apply */) == 0)
+			0, NULL, do_apply) == 0)
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
 }
 
+
+/* [re]set individual variables to their value in the default environment */
+int set_default_vars(int nvars, char * const vars[])
+{
+	/*
+	 * Special use-case: import from default environment
+	 * (and use \0 as a separator)
+	 */
+	return himport_r(&env_htab, (const char *)default_environment,
+				sizeof(default_environment), '\0', H_NOCLEAR,
+				nvars, vars, 1 /* do_apply */);
+}
+
 /*
  * Check if CRC is valid and (if yes) import the environment.
  * Note that "buf" may or may not be aligned.
diff --git a/include/environment.h b/include/environment.h
index 236e179..8b80220 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -190,6 +190,9 @@ void env_crc_update(void);
 /* [re]set to the default environment */
 void set_default_env(const char *s);
 
+/* [re]set individual variables to their value in the default environment */
+int set_default_vars(int nvars, char * const vars[]);
+
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 6/6] env: delete selected vars not present in imported env
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (14 preceding siblings ...)
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 5/6] env: make "env default" selective, check and apply Gerlando Falauto
@ 2012-04-02 18:26 ` Gerlando Falauto
  2012-04-02 19:06   ` Marek Vasut
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
  16 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 18:26 UTC (permalink / raw)
  To: u-boot

When variables explicitly specified on the command line are not present
in the imported env, delete them from the running env.
If the variable is also missing from the running env, issue a warning.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 lib/hashtable.c |   48 +++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/lib/hashtable.c b/lib/hashtable.c
index f3f47de..b3d0b64 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  * himport()
  */
 
-/* Check whether variable name is amongst vars[] */
-static int is_var_in_set(const char *name, int nvars, char * const vars[])
+/*
+ * Check whether variable 'name' is amongst vars[],
+ * and remove all instances by setting the pointer to NULL
+ */
+static int is_var_in_set(const char *name, int nvars, char * vars[])
 {
 	int i = 0;
+	int res = 0;
 
 	/* No variables specified means process all of them */
 	if (nvars == 0)
 		return 1;
 
 	for (i = 0; i < nvars; i++) {
-		if (!strcmp(name, vars[i]))
-			return 1;
+		if (vars[i] == NULL)
+			continue;
+		/* If we found it, delete all of them */
+		if (!strcmp(name, vars[i])) {
+			vars[i] = NULL;
+			res = 1;
+		}
 	}
-	debug("Skipping non-listed variable %s\n", name);
+	if (!res)
+		debug("Skipping non-listed variable %s\n", name);
 
-	return 0;
+	return res;
 }
 
 /*
@@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int nvars, char * const vars[])
 
 int himport_r(struct hsearch_data *htab,
 		const char *env, size_t size, const char sep, int flag,
-		int nvars, char * const vars[], int do_apply)
+		int nvars, char * const __vars[], int do_apply)
 {
 	char *data, *sp, *dp, *name, *value;
+	char *vars[nvars];
+	int i;
 
 	/* Test for correct arguments.  */
 	if (htab == NULL) {
@@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
 	memcpy(data, env, size);
 	dp = data;
 
+	/* make a local copy of the list of variables */
+	if (nvars)
+		memcpy(vars, __vars, sizeof(__vars[0]) * nvars);
+
 	if ((flag & H_NOCLEAR) == 0) {
 		/* Destroy old hash table if one exists */
 		debug("Destroy Hash Table: %p table = %p\n", htab,
@@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
 	debug("INSERT: free(data = %p)\n", data);
 	free(data);
 
+	/* process variables which were not considered */
+	for (i = 0; i < nvars; i++) {
+		if (vars[i] == NULL)
+			continue;
+		/*
+		 * All variables which were not deleted from the variable list
+		 * were not present in the imported env
+		 * This could mean two things:
+		 * a) if the variable was present in current env, we delete it
+		 * b) if the variable was not present in current env, we notify
+		 *    it might be a typo
+		 */
+		if (hdelete_r(vars[i], htab, do_apply) == 0)
+			printf("WARNING: '%s' neither in running nor in imported env!\n", vars[i]);
+		else
+			printf("WARNING: '%s' not in imported env, deleting it!\n", vars[i]);
+	}
+
 	debug("INSERT: done\n");
 	return 1;		/* everything OK */
 }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 1/6] env: unify logic to check and apply changes
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 1/6] env: unify logic to check and apply changes Gerlando Falauto
@ 2012-04-02 18:56   ` Marek Vasut
  2012-04-02 20:39     ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 18:56 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> The logic of checking special parameters (e.g. baudrate, stdin, stdout,
> for a valid value and/or whether can be overwritten) and applying the
> new value to the running system is now all within a single function
> env_check_apply() which can be called whenever changes are made
> to the environment, no matter if by set, default or import.
> 
> With this patch env_check_apply() is only called by "env set",
> retaining previous behavior.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/cmd_nvedit.c |  170
> ++++++++++++++++++++++++++++++++------------------- include/search.h    | 
>   3 +-
>  2 files changed, 109 insertions(+), 64 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 22f9821..e762e76 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -197,32 +197,21 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
>  #endif
> 
>  /*
> - * Set a new environment variable,
> - * or replace or delete an existing one.
> + * Perform consistency checking before setting, replacing, or deleting an
> + * environment variable, then (if successful) apply the changes to
> internals so + * to make them effective.  Code for this function was taken
> out of + * _do_env_set(), which now calls it instead.
> + * Returns 0 in case of success, 1 in case of failure.
> + * When (flag & H_FORCE) is set, do not print out any error message and
> force + * overwriting of write-once variables.
>   */
> -int _do_env_set(int flag, int argc, char * const argv[])
> +
> +int env_check_apply(const char *name, const char *oldval,
> +			const char *newval, int flag)
>  {
>  	bd_t  *bd = gd->bd;
> -	int   i, len;
> +	int   i;
>  	int   console = -1;
> -	char  *name, *value, *s;
> -	ENTRY e, *ep;
> -
> -	name = argv[1];
> -
> -	if (strchr(name, '=')) {
> -		printf("## Error: illegal character '=' in variable name"
> -		       "\"%s\"\n", name);
> -		return 1;
> -	}
> -
> -	env_id++;
> -	/*
> -	 * search if variable with this name already exists
> -	 */
> -	e.key = name;
> -	e.data = NULL;
> -	hsearch_r(e, FIND, &ep, &env_htab);
> 
>  	/* Check for console redirection */
>  	if (strcmp(name, "stdin") == 0)
> @@ -233,60 +222,76 @@ int _do_env_set(int flag, int argc, char * const
> argv[]) console = stderr;
> 
>  	if (console != -1) {
> -		if (argc < 3) {		/* Cannot delete it! */
> -			printf("Can't delete \"%s\"\n", name);
> +		if ((newval == NULL) || (*newval == '\0')) {
> +			/* We cannot delete stdin/stdout/stderr */
> +			if ((flag & H_FORCE) == 0)

Given H_FORCE isn't set on any env var yet, won't this break bisectability?

> +				printf("Can't delete \"%s\"\n", name);
>  			return 1;
>  		}
> 
>  #ifdef CONFIG_CONSOLE_MUX
> -		i = iomux_doenv(console, argv[2]);
> +		i = iomux_doenv(console, newval);
>  		if (i)
>  			return i;
>  #else
>  		/* Try assigning specified device */
> -		if (console_assign(console, argv[2]) < 0)
> +		if (console_assign(console, newval) < 0)
>  			return 1;
> 
>  #ifdef CONFIG_SERIAL_MULTI
> -		if (serial_assign(argv[2]) < 0)
> +		if (serial_assign(newval) < 0)
>  			return 1;
>  #endif
>  #endif /* CONFIG_CONSOLE_MUX */
>  	}
> 
>  	/*
> -	 * Some variables like "ethaddr" and "serial#" can be set only
> -	 * once and cannot be deleted; also, "ver" is readonly.
> +	 * Some variables like "ethaddr" and "serial#" can be set only once and
> +	 * cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined.
>  	 */
> -	if (ep) {		/* variable exists */
>  #ifndef CONFIG_ENV_OVERWRITE
> +	if (oldval != NULL &&			/* variable exists */
> +		(flag & H_FORCE) == 0) {	/* and we are not forced */
>  		if (strcmp(name, "serial#") == 0 ||
>  		    (strcmp(name, "ethaddr") == 0
>  #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
> -		     && strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0
> +		     && strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0
>  #endif	/* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
>  			)) {
>  			printf("Can't overwrite \"%s\"\n", name);
>  			return 1;
>  		}
> +	}
>  #endif
> +	/*
> +	 * When we change baudrate, or we are doing an env default -a
> +	 * (which will erase all variables prior to calling this),
> +	 * we want the baudrate to actually change - for real.
> +	 */
> +	if (oldval != NULL ||			/* variable exists */
> +		(flag & H_NOCLEAR) == 0) {	/* or env is clear */
>  		/*
>  		 * Switch to new baudrate if new baudrate is supported
>  		 */
>  		if (strcmp(name, "baudrate") == 0) {
> -			int baudrate = simple_strtoul(argv[2], NULL, 10);
> +			int baudrate = simple_strtoul(newval, NULL, 10);
>  			int i;
>  			for (i = 0; i < N_BAUDRATES; ++i) {
>  				if (baudrate == baudrate_table[i])
>  					break;
>  			}
>  			if (i == N_BAUDRATES) {
> -				printf("## Baudrate %d bps not supported\n",
> -					baudrate);
> +				if ((flag & H_FORCE) == 0)
> +					printf("## Baudrate %d bps not "
> +						"supported\n", baudrate);
>  				return 1;
>  			}
> +			if (gd->baudrate == baudrate) {
> +				/* If unchanged, we just say it's OK */
> +				return 0;
> +			}
>  			printf("## Switch baudrate to %d bps and"
> -			       "press ENTER ...\n", baudrate);
> +				"press ENTER ...\n", baudrate);

What changed above?

>  			udelay(50000);
>  			gd->baudrate = baudrate;
>  #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
> @@ -300,6 +305,73 @@ int _do_env_set(int flag, int argc, char * const
> argv[]) }
>  	}
> 
> +	/*
> +	 * Some variables should be updated when the corresponding
> +	 * entry in the environment is changed
> +	 */
> +	if (strcmp(name, "ipaddr") == 0) {
> +		const char *s = newval;
> +		char *e;
> +		unsigned long addr;
> +		bd->bi_ip_addr = 0;
> +		for (addr = 0, i = 0; i < 4; ++i) {
> +			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
> +			addr <<= 8;
> +			addr  |= val & 0xFF;
> +			if (s)
> +				s = *e ? e + 1 : e;
> +		}
> +		bd->bi_ip_addr = htonl(addr);
> +		return 0;
> +	} else if (strcmp(name, "loadaddr") == 0) {
> +		load_addr = simple_strtoul(newval, NULL, 16);
> +		return 0;
> +	}
> +#if defined(CONFIG_CMD_NET)
> +	else if (strcmp(name, "bootfile") == 0) {
> +		copy_filename(BootFile, newval, sizeof(BootFile));
> +		return 0;
> +	}
> +#endif
> +	return 0;
> +}
> +
> +/*
> + * Set a new environment variable,
> + * or replace or delete an existing one.
> +*/
> +int _do_env_set(int flag, int argc, char * const argv[])
> +{
> +	int   i, len;
> +	char  *name, *value, *s;
> +	ENTRY e, *ep;
> +
> +	name = argv[1];
> +	value = argv[2];
> +
> +	if (strchr(name, '=')) {
> +		printf("## Error: illegal character '='"
> +		       "in variable name \"%s\"\n", name);
> +		return 1;
> +	}
> +
> +	env_id++;
> +	/*
> +	 * search if variable with this name already exists
> +	 */
> +	e.key = name;
> +	e.data = NULL;
> +	hsearch_r(e, FIND, &ep, &env_htab);
> +
> +	/*
> +	 * Perform requested checks. Notice how since we are overwriting
> +	 * a single variable, we need to set H_NOCLEAR
> +	 */
> +	if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
> +		debug("check function did not approve, refusing\n");
> +		return 1;
> +	}
> +
>  	/* Delete only ? */

Shouldn't delete-only be handled before env_check_apply() to make it faster?

>  	if (argc < 3 || argv[2] == NULL) {
>  		int rc = hdelete_r(name, &env_htab);
> @@ -337,34 +409,6 @@ int _do_env_set(int flag, int argc, char * const
> argv[]) return 1;
>  	}
> 
> -	/*
> -	 * Some variables should be updated when the corresponding
> -	 * entry in the environment is changed
> -	 */
> -	if (strcmp(name, "ipaddr") == 0) {
> -		char *s = argv[2];	/* always use only one arg */
> -		char *e;
> -		unsigned long addr;
> -		bd->bi_ip_addr = 0;
> -		for (addr = 0, i = 0; i < 4; ++i) {
> -			ulong val = s ? simple_strtoul(s, &e, 10) : 0;
> -			addr <<= 8;
> -			addr  |= val & 0xFF;
> -			if (s)
> -				s = *e ? e + 1 : e;
> -		}
> -		bd->bi_ip_addr = htonl(addr);
> -		return 0;
> -	} else if (strcmp(argv[1], "loadaddr") == 0) {
> -		load_addr = simple_strtoul(argv[2], NULL, 16);
> -		return 0;
> -	}
> -#if defined(CONFIG_CMD_NET)
> -	else if (strcmp(argv[1], "bootfile") == 0) {
> -		copy_filename(BootFile, argv[2], sizeof(BootFile));
> -		return 0;
> -	}
> -#endif
>  	return 0;
>  }
> 
> diff --git a/include/search.h b/include/search.h
> index ef53edb..a4a5ef4 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -99,6 +99,7 @@ extern int himport_r(struct hsearch_data *__htab,
>  		     int __flag);
> 
>  /* Flags for himport_r() */
> -#define	H_NOCLEAR	1	/* do not clear hash table before 
importing */
> +#define	H_NOCLEAR	(1 << 0) /* do not clear hash table before 
importing */
> +#define	H_FORCE		(1 << 1) /* overwrite read-only/write-once 
variables */
> 
>  #endif /* search.h */

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 2/6] env: make himport_r() selective on variables
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 2/6] env: make himport_r() selective on variables Gerlando Falauto
@ 2012-04-02 18:57   ` Marek Vasut
  2012-04-02 20:43     ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 18:57 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Add 2 new arguments to himport_r():
> 
>  o "nvars", "vars": number and list of variables to take into account
>    (0 means ALL)
> 

Looks nice and clean. But man, these patches are tough to review (not because 
you made bad job, just because they're hard code), lot of headache from them ;-)

> NOTE: This patch does not change the current behaviour.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/cmd_nvedit.c |    3 ++-
>  common/env_common.c |    6 ++++--
>  include/search.h    |    6 +++++-
>  lib/hashtable.c     |   27 ++++++++++++++++++++++++++-
>  4 files changed, 37 insertions(+), 5 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index e762e76..59668a6 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -930,7 +930,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
>  		addr = (char *)ep->data;
>  	}
> 
> -	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
> +	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
> +			0, NULL) == 0) {
>  		error("Environment import failed: errno = %d\n", errno);
>  		return 1;
>  	}
> diff --git a/common/env_common.c b/common/env_common.c
> index c33d22d..a93c062 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -182,7 +182,8 @@ void set_default_env(const char *s)
>  	}
> 
>  	if (himport_r(&env_htab, (char *)default_environment,
> -			sizeof(default_environment), '\0', 0) == 0)
> +			sizeof(default_environment), '\0', 0,
> +			0, NULL) == 0)
>  		error("Environment import failed: errno = %d\n", errno);
> 
>  	gd->flags |= GD_FLG_ENV_READY;
> @@ -207,7 +208,8 @@ int env_import(const char *buf, int check)
>  		}
>  	}
> 
> -	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
> +	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
> +			0, NULL)) {
>  		gd->flags |= GD_FLG_ENV_READY;
>  		return 1;
>  	}
> diff --git a/include/search.h b/include/search.h
> index a4a5ef4..94d75fc 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -94,9 +94,13 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
>  		     const char __sep, char **__resp, size_t __size,
>  		     int argc, char * const argv[]);
> 
> +/*
> + * nvars: length of vars array
> + * vars: array of strings (variable names) to import (nvars == 0 means
> all) + */
>  extern int himport_r(struct hsearch_data *__htab,
>  		     const char *__env, size_t __size, const char __sep,
> -		     int __flag);
> +		     int __flag, int nvars, char * const vars[]);
> 
>  /* Flags for himport_r() */
>  #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before 
importing */
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index abd61c8..0610e86 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -603,6 +603,24 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> char sep, * himport()
>   */
> 
> +/* Check whether variable name is amongst vars[] */
> +static int is_var_in_set(const char *name, int nvars, char * const vars[])
> +{
> +	int i = 0;
> +
> +	/* No variables specified means process all of them */
> +	if (nvars == 0)
> +		return 1;
> +
> +	for (i = 0; i < nvars; i++) {
> +		if (!strcmp(name, vars[i]))
> +			return 1;
> +	}
> +	debug("Skipping non-listed variable %s\n", name);
> +
> +	return 0;
> +}
> +
>  /*
>   * Import linearized data into hash table.
>   *
> @@ -639,7 +657,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const char
> sep, */
> 
>  int himport_r(struct hsearch_data *htab,
> -	      const char *env, size_t size, const char sep, int flag)
> +		const char *env, size_t size, const char sep, int flag,
> +		int nvars, char * const vars[])
>  {
>  	char *data, *sp, *dp, *name, *value;
> 
> @@ -726,6 +745,8 @@ int himport_r(struct hsearch_data *htab,
>  			*dp++ = '\0';	/* terminate name */
> 
>  			debug("DELETE CANDIDATE: \"%s\"\n", name);
> +			if (!is_var_in_set(name, nvars, vars))
> +				continue;
> 
>  			if (hdelete_r(name, htab) == 0)
>  				debug("DELETE ERROR 
##############################\n");
> @@ -743,6 +764,10 @@ int himport_r(struct hsearch_data *htab,
>  		*sp++ = '\0';	/* terminate value */
>  		++dp;
> 
> +		/* Skip variables which are not supposed to be processed */
> +		if (!is_var_in_set(name, nvars, vars))
> +			continue;
> +
>  		/* enter into hash table */
>  		e.key = name;
>  		e.data = value;

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r()
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r() Gerlando Falauto
@ 2012-04-02 19:00   ` Marek Vasut
  2012-04-02 19:01     ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 19:00 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Change hashtable so that a callback function will decide whether a
> variable can be overwritten, and possibly apply the changes.
> 
> So add a new field to struct hsearch_data:
> 
>  o "apply" callback function to check whether a variable can be
>     overwritten, and possibly immediately apply the changes;
>     when NULL, no check is performed.
> 
> And a new argument to himport_r():
>  o "do_apply": whether to call the apply callback function
> 
> NOTE: This patch does not change the current behavior.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/cmd_nvedit.c   |    3 ++-
>  common/env_common.c   |    8 +++++---
>  include/environment.h |    9 +++++++++
>  include/search.h      |   14 +++++++++++++-
>  lib/hashtable.c       |   20 +++++++++++++++++++-
>  5 files changed, 48 insertions(+), 6 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 59668a6..fc6165f 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -201,6 +201,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
>   * environment variable, then (if successful) apply the changes to
> internals so * to make them effective.  Code for this function was taken
> out of * _do_env_set(), which now calls it instead.
> + * Also called as a callback function by himport_r().
>   * Returns 0 in case of success, 1 in case of failure.
>   * When (flag & H_FORCE) is set, do not print out any error message and
> force * overwriting of write-once variables.
> @@ -931,7 +932,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
>  	}
> 
>  	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
> -			0, NULL) == 0) {
> +			0, NULL, 0 /* do_apply */) == 0) {
>  		error("Environment import failed: errno = %d\n", errno);
>  		return 1;
>  	}
> diff --git a/common/env_common.c b/common/env_common.c
> index a93c062..5558c1c 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -122,7 +122,9 @@ const uchar default_environment[] = {
>  	"\0"
>  };
> 
> -struct hsearch_data env_htab;
> +struct hsearch_data env_htab = {
> +	.apply = env_check_apply,
> +};
> 
>  static uchar __env_get_char_spec(int index)
>  {
> @@ -183,7 +185,7 @@ void set_default_env(const char *s)
> 
>  	if (himport_r(&env_htab, (char *)default_environment,
>  			sizeof(default_environment), '\0', 0,
> -			0, NULL) == 0)
> +			0, NULL, 0 /* do_apply */) == 0)

Please replace that 0 /*...*/ stuff with simple NULL

>  		error("Environment import failed: errno = %d\n", errno);
> 
>  	gd->flags |= GD_FLG_ENV_READY;
> @@ -209,7 +211,7 @@ int env_import(const char *buf, int check)
>  	}
> 
>  	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
> -			0, NULL)) {
> +			0, NULL, 0 /* do_apply */)) {

DTTO, otherwise looks fine.

>  		gd->flags |= GD_FLG_ENV_READY;
>  		return 1;
>  	}
> diff --git a/include/environment.h b/include/environment.h
> index 1ef44f3..236e179 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -193,6 +193,15 @@ void set_default_env(const char *s);
>  /* Import from binary representation into hash table */
>  int env_import(const char *buf, int check);
> 
> +/*
> + * Check if variable "name" can be changed from oldval to newval,
> + * and if so, apply the changes (e.g. baudrate).
> + * When (flag & H_FORCE) is set, it does not print out any error
> + * message and forces overwriting of write-once variables.
> + */
> +int env_check_apply(const char *name, const char *oldval,
> +			const char *newval, int flag);
> +
>  #endif /* DO_DEPS_ONLY */
> 
>  #endif /* _ENVIRONMENT_H_ */
> diff --git a/include/search.h b/include/search.h
> index 94d75fc..721c8ac 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -57,6 +57,16 @@ struct hsearch_data {
>  	struct _ENTRY *table;
>  	unsigned int size;
>  	unsigned int filled;
> +/*
> + * Callback function which will check whether the given change for
> variable + * "name" from "oldval" to "newval" may be applied or not, and
> possibly apply + * such change.
> + * When (flag & H_FORCE) is set, it shall not print out any error message
> and + * shall force overwriting of write-once variables.
> +.* Must return 0 for approval, 1 for denial.
> + */
> +	int (*apply)(const char *name, const char *oldval,
> +			const char *newval, int flag);
>  };
> 
>  /* Create a new hashing table which will at most contain NEL elements.  */
> @@ -97,10 +107,12 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
>  /*
>   * nvars: length of vars array
>   * vars: array of strings (variable names) to import (nvars == 0 means
> all) + * do_apply: whether to call callback function to check the new
> argument, + * and possibly apply changes (false means accept everything)
>   */
>  extern int himport_r(struct hsearch_data *__htab,
>  		     const char *__env, size_t __size, const char __sep,
> -		     int __flag, int nvars, char * const vars[]);
> +		     int __flag, int nvars, char * const vars[], int do_apply);
> 
>  /* Flags for himport_r() */
>  #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before 
importing */
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index 0610e86..6cfba56 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -658,7 +658,7 @@ static int is_var_in_set(const char *name, int nvars,
> char * const vars[])
> 
>  int himport_r(struct hsearch_data *htab,
>  		const char *env, size_t size, const char sep, int flag,
> -		int nvars, char * const vars[])
> +		int nvars, char * const vars[], int do_apply)
>  {
>  	char *data, *sp, *dp, *name, *value;
> 
> @@ -772,6 +772,24 @@ int himport_r(struct hsearch_data *htab,
>  		e.key = name;
>  		e.data = value;
> 
> +		/* if there is an apply function, check what it has to say */
> +		if (do_apply && htab->apply != NULL) {
> +			debug("searching before calling cb function"
> +				" for  %s\n", name);
> +			/*
> +			 * Search for variable in existing env, so to pass
> +			 * its previous value to the apply callback
> +			 */
> +			hsearch_r(e, FIND, &rv, htab);
> +			debug("previous value was %s\n", rv ? rv->data : "");
> +			if (htab->apply(name, rv ? rv->data : NULL,
> +				value, flag)) {
> +				debug("callback function refused to set"
> +					" variable %s, skipping it!\n", name);
> +				continue;
> +			}
> +		}
> +
>  		hsearch_r(e, ENTER, &rv, htab);
>  		if (rv == NULL) {
>  			printf("himport_r: can't insert \"%s=%s\" into hash 
table\n",

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r()
  2012-04-02 19:00   ` Marek Vasut
@ 2012-04-02 19:01     ` Marek Vasut
  2012-04-02 20:44       ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 19:01 UTC (permalink / raw)
  To: u-boot

Dear Marek Vasut,

> Dear Gerlando Falauto,
> 
> > Change hashtable so that a callback function will decide whether a
> > variable can be overwritten, and possibly apply the changes.
> > 
> > So add a new field to struct hsearch_data:
> >  o "apply" callback function to check whether a variable can be
> >  
> >     overwritten, and possibly immediately apply the changes;
> >     when NULL, no check is performed.
> > 
> > And a new argument to himport_r():
> >  o "do_apply": whether to call the apply callback function
> > 
> > NOTE: This patch does not change the current behavior.
> > 
> > Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> > ---
> > 
> >  common/cmd_nvedit.c   |    3 ++-
> >  common/env_common.c   |    8 +++++---
> >  include/environment.h |    9 +++++++++
> >  include/search.h      |   14 +++++++++++++-
> >  lib/hashtable.c       |   20 +++++++++++++++++++-
> >  5 files changed, 48 insertions(+), 6 deletions(-)
> > 
> > diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> > index 59668a6..fc6165f 100644
> > --- a/common/cmd_nvedit.c
> > +++ b/common/cmd_nvedit.c
> > @@ -201,6 +201,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
> > 
> >   * environment variable, then (if successful) apply the changes to
> > 
> > internals so * to make them effective.  Code for this function was taken
> > out of * _do_env_set(), which now calls it instead.
> > + * Also called as a callback function by himport_r().
> > 
> >   * Returns 0 in case of success, 1 in case of failure.
> >   * When (flag & H_FORCE) is set, do not print out any error message and
> > 
> > force * overwriting of write-once variables.
> > @@ -931,7 +932,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
> > 
> >  	}
> >  	
> >  	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
> > 
> > -			0, NULL) == 0) {
> > +			0, NULL, 0 /* do_apply */) == 0) {
> > 
> >  		error("Environment import failed: errno = %d\n", errno);
> >  		return 1;
> >  	
> >  	}
> > 
> > diff --git a/common/env_common.c b/common/env_common.c
> > index a93c062..5558c1c 100644
> > --- a/common/env_common.c
> > +++ b/common/env_common.c
> > @@ -122,7 +122,9 @@ const uchar default_environment[] = {
> > 
> >  	"\0"
> >  
> >  };
> > 
> > -struct hsearch_data env_htab;
> > +struct hsearch_data env_htab = {
> > +	.apply = env_check_apply,
> > +};
> > 
> >  static uchar __env_get_char_spec(int index)
> >  {
> > 
> > @@ -183,7 +185,7 @@ void set_default_env(const char *s)
> > 
> >  	if (himport_r(&env_htab, (char *)default_environment,
> >  	
> >  			sizeof(default_environment), '\0', 0,
> > 
> > -			0, NULL) == 0)
> > +			0, NULL, 0 /* do_apply */) == 0)
> 
> Please replace that 0 /*...*/ stuff with simple NULL

Oh, it's integer ... so just remove the comment, sorry.

> 
> >  		error("Environment import failed: errno = %d\n", errno);
> >  	
> >  	gd->flags |= GD_FLG_ENV_READY;
> > 
> > @@ -209,7 +211,7 @@ int env_import(const char *buf, int check)
> > 
> >  	}
> >  	
> >  	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
> > 
> > -			0, NULL)) {
> > +			0, NULL, 0 /* do_apply */)) {
> 
> DTTO, otherwise looks fine.
> 
> >  		gd->flags |= GD_FLG_ENV_READY;
> >  		return 1;
> >  	
> >  	}
> > 
> > diff --git a/include/environment.h b/include/environment.h
> > index 1ef44f3..236e179 100644
> > --- a/include/environment.h
> > +++ b/include/environment.h
> > @@ -193,6 +193,15 @@ void set_default_env(const char *s);
> > 
> >  /* Import from binary representation into hash table */
> >  int env_import(const char *buf, int check);
> > 
> > +/*
> > + * Check if variable "name" can be changed from oldval to newval,
> > + * and if so, apply the changes (e.g. baudrate).
> > + * When (flag & H_FORCE) is set, it does not print out any error
> > + * message and forces overwriting of write-once variables.
> > + */
> > +int env_check_apply(const char *name, const char *oldval,
> > +			const char *newval, int flag);
> > +
> > 
> >  #endif /* DO_DEPS_ONLY */
> >  
> >  #endif /* _ENVIRONMENT_H_ */
> > 
> > diff --git a/include/search.h b/include/search.h
> > index 94d75fc..721c8ac 100644
> > --- a/include/search.h
> > +++ b/include/search.h
> > @@ -57,6 +57,16 @@ struct hsearch_data {
> > 
> >  	struct _ENTRY *table;
> >  	unsigned int size;
> >  	unsigned int filled;
> > 
> > +/*
> > + * Callback function which will check whether the given change for
> > variable + * "name" from "oldval" to "newval" may be applied or not, and
> > possibly apply + * such change.
> > + * When (flag & H_FORCE) is set, it shall not print out any error
> > message and + * shall force overwriting of write-once variables.
> > +.* Must return 0 for approval, 1 for denial.
> > + */
> > +	int (*apply)(const char *name, const char *oldval,
> > +			const char *newval, int flag);
> > 
> >  };
> >  
> >  /* Create a new hashing table which will at most contain NEL elements. 
> >  */
> > 
> > @@ -97,10 +107,12 @@ extern ssize_t hexport_r(struct hsearch_data
> > *__htab,
> > 
> >  /*
> >  
> >   * nvars: length of vars array
> >   * vars: array of strings (variable names) to import (nvars == 0 means
> > 
> > all) + * do_apply: whether to call callback function to check the new
> > argument, + * and possibly apply changes (false means accept everything)
> > 
> >   */
> >  
> >  extern int himport_r(struct hsearch_data *__htab,
> >  
> >  		     const char *__env, size_t __size, const char __sep,
> > 
> > -		     int __flag, int nvars, char * const vars[]);
> > +		     int __flag, int nvars, char * const vars[], int do_apply);
> > 
> >  /* Flags for himport_r() */
> >  #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before
> 
> importing */
> 
> > diff --git a/lib/hashtable.c b/lib/hashtable.c
> > index 0610e86..6cfba56 100644
> > --- a/lib/hashtable.c
> > +++ b/lib/hashtable.c
> > @@ -658,7 +658,7 @@ static int is_var_in_set(const char *name, int nvars,
> > char * const vars[])
> > 
> >  int himport_r(struct hsearch_data *htab,
> >  
> >  		const char *env, size_t size, const char sep, int flag,
> > 
> > -		int nvars, char * const vars[])
> > +		int nvars, char * const vars[], int do_apply)
> > 
> >  {
> >  
> >  	char *data, *sp, *dp, *name, *value;
> > 
> > @@ -772,6 +772,24 @@ int himport_r(struct hsearch_data *htab,
> > 
> >  		e.key = name;
> >  		e.data = value;
> > 
> > +		/* if there is an apply function, check what it has to say */
> > +		if (do_apply && htab->apply != NULL) {
> > +			debug("searching before calling cb function"
> > +				" for  %s\n", name);
> > +			/*
> > +			 * Search for variable in existing env, so to pass
> > +			 * its previous value to the apply callback
> > +			 */
> > +			hsearch_r(e, FIND, &rv, htab);
> > +			debug("previous value was %s\n", rv ? rv->data : "");
> > +			if (htab->apply(name, rv ? rv->data : NULL,
> > +				value, flag)) {
> > +				debug("callback function refused to set"
> > +					" variable %s, skipping it!\n", name);
> > +				continue;
> > +			}
> > +		}
> > +
> > 
> >  		hsearch_r(e, ENTER, &rv, htab);
> >  		if (rv == NULL) {
> >  		
> >  			printf("himport_r: can't insert \"%s=%s\" into hash
> 
> table\n",

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 4/6] env: check and apply changes on delete/destroy
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 4/6] env: check and apply changes on delete/destroy Gerlando Falauto
@ 2012-04-02 19:01   ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 19:01 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

Looks ok

> ---
>  common/cmd_nvedit.c |    2 +-
>  include/search.h    |    5 +++--
>  lib/hashtable.c     |   16 ++++++++++------
>  3 files changed, 14 insertions(+), 9 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index fc6165f..091cd46 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -375,7 +375,7 @@ int _do_env_set(int flag, int argc, char * const
> argv[])
> 
>  	/* Delete only ? */
>  	if (argc < 3 || argv[2] == NULL) {
> -		int rc = hdelete_r(name, &env_htab);
> +		int rc = hdelete_r(name, &env_htab, 0);
>  		return !rc;
>  	}
> 
> diff --git a/include/search.h b/include/search.h
> index 721c8ac..93e1cbc 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -73,7 +73,7 @@ struct hsearch_data {
>  extern int hcreate_r(size_t __nel, struct hsearch_data *__htab);
> 
>  /* Destroy current internal hashing table.  */
> -extern void hdestroy_r(struct hsearch_data *__htab);
> +extern void hdestroy_r(struct hsearch_data *__htab, int do_apply);
> 
>  /*
>   * Search for entry matching ITEM.key in internal hash table.  If
> @@ -98,7 +98,8 @@ extern int hstrstr_r(const char *__match, int __last_idx,
> ENTRY ** __retval, struct hsearch_data *__htab);
> 
>  /* Search and delete entry matching ITEM.key in internal hash table. */
> -extern int hdelete_r(const char *__key, struct hsearch_data *__htab);
> +extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
> +			int do_apply);
> 
>  extern ssize_t hexport_r(struct hsearch_data *__htab,
>  		     const char __sep, char **__resp, size_t __size,
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index 6cfba56..f3f47de 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -142,7 +142,7 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
>   * be freed and the local static variable can be marked as not used.
>   */
> 
> -void hdestroy_r(struct hsearch_data *htab)
> +void hdestroy_r(struct hsearch_data *htab, int do_apply)
>  {
>  	int i;
> 
> @@ -156,7 +156,10 @@ void hdestroy_r(struct hsearch_data *htab)
>  	for (i = 1; i <= htab->size; ++i) {
>  		if (htab->table[i].used > 0) {
>  			ENTRY *ep = &htab->table[i].entry;
> -
> +			if (do_apply && htab->apply != NULL) {
> +				/* deletion is always forced */
> +				htab->apply(ep->key, ep->data, NULL, H_FORCE);
> +			}
>  			free((void *)ep->key);
>  			free(ep->data);
>  		}
> @@ -401,7 +404,7 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY **
> retval, * do that.
>   */
> 
> -int hdelete_r(const char *key, struct hsearch_data *htab)
> +int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)
>  {
>  	ENTRY e, *ep;
>  	int idx;
> @@ -417,7 +420,8 @@ int hdelete_r(const char *key, struct hsearch_data
> *htab)
> 
>  	/* free used ENTRY */
>  	debug("hdelete: DELETING key \"%s\"\n", key);
> -
> +	if (do_apply && htab->apply != NULL)
> +		htab->apply(ep->key, ep->data, NULL, H_FORCE);
>  	free((void *)ep->key);
>  	free(ep->data);
>  	htab->table[idx].used = -1;
> @@ -682,7 +686,7 @@ int himport_r(struct hsearch_data *htab,
>  		debug("Destroy Hash Table: %p table = %p\n", htab,
>  		       htab->table);
>  		if (htab->table)
> -			hdestroy_r(htab);
> +			hdestroy_r(htab, do_apply);
>  	}
> 
>  	/*
> @@ -748,7 +752,7 @@ int himport_r(struct hsearch_data *htab,
>  			if (!is_var_in_set(name, nvars, vars))
>  				continue;
> 
> -			if (hdelete_r(name, htab) == 0)
> +			if (hdelete_r(name, htab, do_apply) == 0)
>  				debug("DELETE ERROR 
##############################\n");
> 
>  			continue;

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 5/6] env: make "env default" selective, check and apply
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 5/6] env: make "env default" selective, check and apply Gerlando Falauto
@ 2012-04-02 19:04   ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 19:04 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Change the syntax (user API) for "env default":
>   -f: override write-once variables
>   var... : accept individual variable(s)
>   -a: all (resetting the whole env is NOT the default behavior)
> 

Looks fine.

> Enable variable checking and make changes effective by
> enabling do_apply argument to himport_r().
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/cmd_nvedit.c   |   40 ++++++++++++++++++++++++++++++++++------
>  common/env_common.c   |   28 +++++++++++++++++++++++++++-
>  include/environment.h |    3 +++
>  3 files changed, 64 insertions(+), 7 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 091cd46..d8e233b 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -672,14 +672,41 @@ int envmatch(uchar *s1, int i2)
>  	return -1;
>  }
> 
> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
>  			  int argc, char * const argv[])
>  {
> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
> -		return CMD_RET_USAGE;
> +	int all = 0, flag = 0;
> 
> -	set_default_env("## Resetting to default environment\n");
> -	return 0;
> +	debug("Initial value for argc=%d\n", argc);
> +	while (--argc > 0 && **++argv == '-') {
> +		char *arg = *argv;
> +
> +		while (*++arg) {
> +			switch (*arg) {
> +			case 'a':		/* default all */
> +				all = 1;
> +				break;
> +			case 'f':		/* force */
> +				flag |= H_FORCE;
> +				break;
> +			default:
> +				return cmd_usage(cmdtp);
> +			}
> +		}
> +	}
> +	debug("Final value for argc=%d\n", argc);
> +	if (all && (argc == 0)) {
> +		/* Reset the whole environment */
> +		set_default_env("## Resetting to default environment\n");
> +		return 0;
> +	}
> +	if (!all && (argc > 0)) {
> +		/* Reset individual variables */
> +		set_default_vars(argc, argv);
> +		return 0;
> +	}
> +
> +	return cmd_usage(cmdtp);
>  }
> 
>  static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
> @@ -1010,7 +1037,8 @@ U_BOOT_CMD(
>  #if defined(CONFIG_CMD_ASKENV)
>  	"ask name [message] [size] - ask for environment variable\nenv "
>  #endif
> -	"default -f - reset default environment\n"
> +	"default [-f] -a - [forcibly] reset default environment\n"
> +	"env default [-f] var [...] - [forcibly] reset variable(s) to their
> default values\n" #if defined(CONFIG_CMD_EDITENV)
>  	"env edit name - edit environment variable\n"
>  #endif
> diff --git a/common/env_common.c b/common/env_common.c
> index 5558c1c..5104402 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -166,6 +166,11 @@ const uchar *env_get_addr(int index)
> 
>  void set_default_env(const char *s)
>  {
> +	/*
> +	 * By default, do not apply changes as they will eventually
> +	 * be applied by someone else
> +	 */
> +	int do_apply = 0;
>  	if (sizeof(default_environment) > ENV_SIZE) {
>  		puts("*** Error - default environment is too large\n\n");
>  		return;
> @@ -177,6 +182,14 @@ void set_default_env(const char *s)
>  				"using default environment\n\n",
>  				s + 1);
>  		} else {
> +			/*
> +			 * This set_to_default was explicitly asked for
> +			 * by the user, as opposed to being a recovery
> +			 * mechanism.  Therefore we check every single
> +			 * variable and apply changes to the system
> +			 * right away (e.g. baudrate, console).
> +			 */
> +			do_apply = 1;
>  			puts(s);
>  		}
>  	} else {
> @@ -185,12 +198,25 @@ void set_default_env(const char *s)
> 
>  	if (himport_r(&env_htab, (char *)default_environment,
>  			sizeof(default_environment), '\0', 0,
> -			0, NULL, 0 /* do_apply */) == 0)
> +			0, NULL, do_apply) == 0)
>  		error("Environment import failed: errno = %d\n", errno);
> 
>  	gd->flags |= GD_FLG_ENV_READY;
>  }
> 
> +
> +/* [re]set individual variables to their value in the default environment
> */ +int set_default_vars(int nvars, char * const vars[])
> +{
> +	/*
> +	 * Special use-case: import from default environment
> +	 * (and use \0 as a separator)
> +	 */
> +	return himport_r(&env_htab, (const char *)default_environment,
> +				sizeof(default_environment), '\0', H_NOCLEAR,
> +				nvars, vars, 1 /* do_apply */);
> +}
> +
>  /*
>   * Check if CRC is valid and (if yes) import the environment.
>   * Note that "buf" may or may not be aligned.
> diff --git a/include/environment.h b/include/environment.h
> index 236e179..8b80220 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -190,6 +190,9 @@ void env_crc_update(void);
>  /* [re]set to the default environment */
>  void set_default_env(const char *s);
> 
> +/* [re]set individual variables to their value in the default environment
> */ +int set_default_vars(int nvars, char * const vars[]);
> +
>  /* Import from binary representation into hash table */
>  int env_import(const char *buf, int check);

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 6/6] env: delete selected vars not present in imported env
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 6/6] env: delete selected vars not present in imported env Gerlando Falauto
@ 2012-04-02 19:06   ` Marek Vasut
  2012-04-02 20:45     ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 19:06 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> When variables explicitly specified on the command line are not present
> in the imported env, delete them from the running env.
> If the variable is also missing from the running env, issue a warning.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  lib/hashtable.c |   48 +++++++++++++++++++++++++++++++++++++++++-------
>  1 files changed, 41 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index f3f47de..b3d0b64 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> char sep, * himport()
>   */
> 
> -/* Check whether variable name is amongst vars[] */
> -static int is_var_in_set(const char *name, int nvars, char * const vars[])
> +/*
> + * Check whether variable 'name' is amongst vars[],
> + * and remove all instances by setting the pointer to NULL
> + */
> +static int is_var_in_set(const char *name, int nvars, char * vars[])
>  {
>  	int i = 0;
> +	int res = 0;
> 
>  	/* No variables specified means process all of them */
>  	if (nvars == 0)
>  		return 1;
> 
>  	for (i = 0; i < nvars; i++) {
> -		if (!strcmp(name, vars[i]))
> -			return 1;
> +		if (vars[i] == NULL)
> +			continue;
> +		/* If we found it, delete all of them */
> +		if (!strcmp(name, vars[i])) {
> +			vars[i] = NULL;
> +			res = 1;
> +		}
>  	}
> -	debug("Skipping non-listed variable %s\n", name);
> +	if (!res)
> +		debug("Skipping non-listed variable %s\n", name);
> 
> -	return 0;
> +	return res;
>  }
> 
>  /*
> @@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int nvars,
> char * const vars[])
> 
>  int himport_r(struct hsearch_data *htab,
>  		const char *env, size_t size, const char sep, int flag,
> -		int nvars, char * const vars[], int do_apply)
> +		int nvars, char * const __vars[], int do_apply)
>  {
>  	char *data, *sp, *dp, *name, *value;
> +	char *vars[nvars];
> +	int i;
> 
>  	/* Test for correct arguments.  */
>  	if (htab == NULL) {
> @@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
>  	memcpy(data, env, size);
>  	dp = data;
> 
> +	/* make a local copy of the list of variables */
> +	if (nvars)
> +		memcpy(vars, __vars, sizeof(__vars[0]) * nvars);

Stupid question -- do you need the local copy at all? Why?

> +
>  	if ((flag & H_NOCLEAR) == 0) {
>  		/* Destroy old hash table if one exists */
>  		debug("Destroy Hash Table: %p table = %p\n", htab,
> @@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
>  	debug("INSERT: free(data = %p)\n", data);
>  	free(data);
> 
> +	/* process variables which were not considered */
> +	for (i = 0; i < nvars; i++) {
> +		if (vars[i] == NULL)
> +			continue;
> +		/*
> +		 * All variables which were not deleted from the variable list
> +		 * were not present in the imported env
> +		 * This could mean two things:
> +		 * a) if the variable was present in current env, we delete it
> +		 * b) if the variable was not present in current env, we notify
> +		 *    it might be a typo
> +		 */
> +		if (hdelete_r(vars[i], htab, do_apply) == 0)
> +			printf("WARNING: '%s' neither in running nor in imported 
env!\n",
> vars[i]); +		else
> +			printf("WARNING: '%s' not in imported env, deleting it!
\n", vars[i]);
> +	}
> +
>  	debug("INSERT: done\n");
>  	return 1;		/* everything OK */
>  }

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 1/6] env: unify logic to check and apply changes
  2012-04-02 18:56   ` Marek Vasut
@ 2012-04-02 20:39     ` Gerlando Falauto
  2012-04-02 20:50       ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 20:39 UTC (permalink / raw)
  To: u-boot

On 04/02/2012 08:56 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> The logic of checking special parameters (e.g. baudrate, stdin, stdout,
>> for a valid value and/or whether can be overwritten) and applying the
>> new value to the running system is now all within a single function
>> env_check_apply() which can be called whenever changes are made
>> to the environment, no matter if by set, default or import.
>>
>> With this patch env_check_apply() is only called by "env set",
>> retaining previous behavior.
>>
>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>> ---
>>   common/cmd_nvedit.c |  170
>> ++++++++++++++++++++++++++++++++------------------- include/search.h    |
>>    3 +-
>>   2 files changed, 109 insertions(+), 64 deletions(-)
>>
>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
>> index 22f9821..e762e76 100644
>> --- a/common/cmd_nvedit.c
>> +++ b/common/cmd_nvedit.c
>> @@ -197,32 +197,21 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
>>   #endif
>>
>>   /*
>> - * Set a new environment variable,
>> - * or replace or delete an existing one.
>> + * Perform consistency checking before setting, replacing, or deleting an
>> + * environment variable, then (if successful) apply the changes to
>> internals so + * to make them effective.  Code for this function was taken
>> out of + * _do_env_set(), which now calls it instead.
>> + * Returns 0 in case of success, 1 in case of failure.
>> + * When (flag&  H_FORCE) is set, do not print out any error message and
>> force + * overwriting of write-once variables.
>>    */
>> -int _do_env_set(int flag, int argc, char * const argv[])
>> +
>> +int env_check_apply(const char *name, const char *oldval,
>> +			const char *newval, int flag)
>>   {
>>   	bd_t  *bd = gd->bd;
>> -	int   i, len;
>> +	int   i;
>>   	int   console = -1;
>> -	char  *name, *value, *s;
>> -	ENTRY e, *ep;
>> -
>> -	name = argv[1];
>> -
>> -	if (strchr(name, '=')) {
>> -		printf("## Error: illegal character '=' in variable name"
>> -		       "\"%s\"\n", name);
>> -		return 1;
>> -	}
>> -
>> -	env_id++;
>> -	/*
>> -	 * search if variable with this name already exists
>> -	 */
>> -	e.key = name;
>> -	e.data = NULL;
>> -	hsearch_r(e, FIND,&ep,&env_htab);
>>
>>   	/* Check for console redirection */
>>   	if (strcmp(name, "stdin") == 0)
>> @@ -233,60 +222,76 @@ int _do_env_set(int flag, int argc, char * const
>> argv[]) console = stderr;
>>
>>   	if (console != -1) {
>> -		if (argc<  3) {		/* Cannot delete it! */
>> -			printf("Can't delete \"%s\"\n", name);
>> +		if ((newval == NULL) || (*newval == '\0')) {
>> +			/* We cannot delete stdin/stdout/stderr */
>> +			if ((flag&  H_FORCE) == 0)
>
> Given H_FORCE isn't set on any env var yet, won't this break bisectability?

What do you mean? We are defining (and checking on) a new flag which is 
not set yet. It's like adding a new feature which nobody uses yet.
Of course this patch alone doesn't make any sense on its own, it just 
sets the ground for features to be used later. But otherwise it should 
compile (and work) fine, you just can't test it yet.

See, the whole thing started as a single task which kept growing up by 
adding features which are somehow intertwined. So I tried to break it up 
into smaller pieces so to at make reviews easier. But logicallly, it's a 
big fat patch.

>> +				printf("Can't delete \"%s\"\n", name);
>>   			return 1;
>>   		}
>>
>>   #ifdef CONFIG_CONSOLE_MUX
>> -		i = iomux_doenv(console, argv[2]);
>> +		i = iomux_doenv(console, newval);
>>   		if (i)
>>   			return i;
>>   #else
>>   		/* Try assigning specified device */
>> -		if (console_assign(console, argv[2])<  0)
>> +		if (console_assign(console, newval)<  0)
>>   			return 1;
>>
>>   #ifdef CONFIG_SERIAL_MULTI
>> -		if (serial_assign(argv[2])<  0)
>> +		if (serial_assign(newval)<  0)
>>   			return 1;
>>   #endif
>>   #endif /* CONFIG_CONSOLE_MUX */
>>   	}
>>
>>   	/*
>> -	 * Some variables like "ethaddr" and "serial#" can be set only
>> -	 * once and cannot be deleted; also, "ver" is readonly.
>> +	 * Some variables like "ethaddr" and "serial#" can be set only once and
>> +	 * cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined.
>>   	 */
>> -	if (ep) {		/* variable exists */
>>   #ifndef CONFIG_ENV_OVERWRITE
>> +	if (oldval != NULL&&			/* variable exists */
>> +		(flag&  H_FORCE) == 0) {	/* and we are not forced */
>>   		if (strcmp(name, "serial#") == 0 ||
>>   		    (strcmp(name, "ethaddr") == 0
>>   #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE)&&  defined(CONFIG_ETHADDR)
>> -		&&  strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0
>> +		&&  strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0
>>   #endif	/* CONFIG_OVERWRITE_ETHADDR_ONCE&&  CONFIG_ETHADDR */
>>   			)) {
>>   			printf("Can't overwrite \"%s\"\n", name);
>>   			return 1;
>>   		}
>> +	}
>>   #endif
>> +	/*
>> +	 * When we change baudrate, or we are doing an env default -a
>> +	 * (which will erase all variables prior to calling this),
>> +	 * we want the baudrate to actually change - for real.
>> +	 */
>> +	if (oldval != NULL ||			/* variable exists */
>> +		(flag&  H_NOCLEAR) == 0) {	/* or env is clear */
>>   		/*
>>   		 * Switch to new baudrate if new baudrate is supported
>>   		 */
>>   		if (strcmp(name, "baudrate") == 0) {
>> -			int baudrate = simple_strtoul(argv[2], NULL, 10);
>> +			int baudrate = simple_strtoul(newval, NULL, 10);
>>   			int i;
>>   			for (i = 0; i<  N_BAUDRATES; ++i) {
>>   				if (baudrate == baudrate_table[i])
>>   					break;
>>   			}
>>   			if (i == N_BAUDRATES) {
>> -				printf("## Baudrate %d bps not supported\n",
>> -					baudrate);
>> +				if ((flag&  H_FORCE) == 0)
>> +					printf("## Baudrate %d bps not "
>> +						"supported\n", baudrate);
>>   				return 1;
>>   			}
>> +			if (gd->baudrate == baudrate) {
>> +				/* If unchanged, we just say it's OK */
>> +				return 0;
>> +			}
>>   			printf("## Switch baudrate to %d bps and"
>> -			       "press ENTER ...\n", baudrate);
>> +				"press ENTER ...\n", baudrate);
>
> What changed above?

Replaced spaces with a tab, so to obey a previously mentioned formatting 
rule.

>
>>   			udelay(50000);
>>   			gd->baudrate = baudrate;
>>   #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
>> @@ -300,6 +305,73 @@ int _do_env_set(int flag, int argc, char * const
>> argv[]) }
>>   	}
>>
>> +	/*
>> +	 * Some variables should be updated when the corresponding
>> +	 * entry in the environment is changed
>> +	 */
>> +	if (strcmp(name, "ipaddr") == 0) {
>> +		const char *s = newval;
>> +		char *e;
>> +		unsigned long addr;
>> +		bd->bi_ip_addr = 0;
>> +		for (addr = 0, i = 0; i<  4; ++i) {
>> +			ulong val = s ? simple_strtoul(s,&e, 10) : 0;
>> +			addr<<= 8;
>> +			addr  |= val&  0xFF;
>> +			if (s)
>> +				s = *e ? e + 1 : e;
>> +		}
>> +		bd->bi_ip_addr = htonl(addr);
>> +		return 0;
>> +	} else if (strcmp(name, "loadaddr") == 0) {
>> +		load_addr = simple_strtoul(newval, NULL, 16);
>> +		return 0;
>> +	}
>> +#if defined(CONFIG_CMD_NET)
>> +	else if (strcmp(name, "bootfile") == 0) {
>> +		copy_filename(BootFile, newval, sizeof(BootFile));
>> +		return 0;
>> +	}
>> +#endif
>> +	return 0;
>> +}
>> +
>> +/*
>> + * Set a new environment variable,
>> + * or replace or delete an existing one.
>> +*/
>> +int _do_env_set(int flag, int argc, char * const argv[])
>> +{
>> +	int   i, len;
>> +	char  *name, *value, *s;
>> +	ENTRY e, *ep;
>> +
>> +	name = argv[1];
>> +	value = argv[2];
>> +
>> +	if (strchr(name, '=')) {
>> +		printf("## Error: illegal character '='"
>> +		       "in variable name \"%s\"\n", name);
>> +		return 1;
>> +	}
>> +
>> +	env_id++;
>> +	/*
>> +	 * search if variable with this name already exists
>> +	 */
>> +	e.key = name;
>> +	e.data = NULL;
>> +	hsearch_r(e, FIND,&ep,&env_htab);
>> +
>> +	/*
>> +	 * Perform requested checks. Notice how since we are overwriting
>> +	 * a single variable, we need to set H_NOCLEAR
>> +	 */
>> +	if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
>> +		debug("check function did not approve, refusing\n");
>> +		return 1;
>> +	}
>> +
>>   	/* Delete only ? */
>
> Shouldn't delete-only be handled before env_check_apply() to make it faster?

Why? If you try to unset a variable (e.g. stdin, console), you should 
*first* check whether that's a sane thing to do, and *then*, that being 
the case, delete it.

>
>>   	if (argc<  3 || argv[2] == NULL) {
>>   		int rc = hdelete_r(name,&env_htab);
>> @@ -337,34 +409,6 @@ int _do_env_set(int flag, int argc, char * const
>> argv[]) return 1;
>>   	}
>>
>> -	/*
>> -	 * Some variables should be updated when the corresponding
>> -	 * entry in the environment is changed
>> -	 */
>> -	if (strcmp(name, "ipaddr") == 0) {
>> -		char *s = argv[2];	/* always use only one arg */
>> -		char *e;
>> -		unsigned long addr;
>> -		bd->bi_ip_addr = 0;
>> -		for (addr = 0, i = 0; i<  4; ++i) {
>> -			ulong val = s ? simple_strtoul(s,&e, 10) : 0;
>> -			addr<<= 8;
>> -			addr  |= val&  0xFF;
>> -			if (s)
>> -				s = *e ? e + 1 : e;
>> -		}
>> -		bd->bi_ip_addr = htonl(addr);
>> -		return 0;
>> -	} else if (strcmp(argv[1], "loadaddr") == 0) {
>> -		load_addr = simple_strtoul(argv[2], NULL, 16);
>> -		return 0;
>> -	}
>> -#if defined(CONFIG_CMD_NET)
>> -	else if (strcmp(argv[1], "bootfile") == 0) {
>> -		copy_filename(BootFile, argv[2], sizeof(BootFile));
>> -		return 0;
>> -	}
>> -#endif
>>   	return 0;
>>   }
>>
>> diff --git a/include/search.h b/include/search.h
>> index ef53edb..a4a5ef4 100644
>> --- a/include/search.h
>> +++ b/include/search.h
>> @@ -99,6 +99,7 @@ extern int himport_r(struct hsearch_data *__htab,
>>   		     int __flag);
>>
>>   /* Flags for himport_r() */
>> -#define	H_NOCLEAR	1	/* do not clear hash table before
> importing */
>> +#define	H_NOCLEAR	(1<<  0) /* do not clear hash table before
> importing */
>> +#define	H_FORCE		(1<<  1) /* overwrite read-only/write-once
> variables */
>>
>>   #endif /* search.h */

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 2/6] env: make himport_r() selective on variables
  2012-04-02 18:57   ` Marek Vasut
@ 2012-04-02 20:43     ` Gerlando Falauto
  2012-04-04  7:41       ` Simon Glass
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 20:43 UTC (permalink / raw)
  To: u-boot

On 04/02/2012 08:57 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> Add 2 new arguments to himport_r():
>>
>>   o "nvars", "vars": number and list of variables to take into account
>>     (0 means ALL)
>>
>
> Looks nice and clean. But man, these patches are tough to review (not because
> you made bad job, just because they're hard code), lot of headache from them ;-)

Tell me about it. I've been reworking them several times, usually after 
several weeks from posting them. Long enough to have forgotten 
everything, and to give you a bad headache.
So I really appreciate your prompt feedback, thanks!

Gerlando

P.S. For the whole process I am using interactive rebase, which is 
painful enough. If anyone knows of any other way to "patch the patches", 
some advice would be very much appreciated... :-)

>> NOTE: This patch does not change the current behaviour.
>>
>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>> ---
>>   common/cmd_nvedit.c |    3 ++-
>>   common/env_common.c |    6 ++++--
>>   include/search.h    |    6 +++++-
>>   lib/hashtable.c     |   27 ++++++++++++++++++++++++++-
>>   4 files changed, 37 insertions(+), 5 deletions(-)
>>
>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
>> index e762e76..59668a6 100644
>> --- a/common/cmd_nvedit.c
>> +++ b/common/cmd_nvedit.c
>> @@ -930,7 +930,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
>>   		addr = (char *)ep->data;
>>   	}
>>
>> -	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
>> +	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
>> +			0, NULL) == 0) {
>>   		error("Environment import failed: errno = %d\n", errno);
>>   		return 1;
>>   	}
>> diff --git a/common/env_common.c b/common/env_common.c
>> index c33d22d..a93c062 100644
>> --- a/common/env_common.c
>> +++ b/common/env_common.c
>> @@ -182,7 +182,8 @@ void set_default_env(const char *s)
>>   	}
>>
>>   	if (himport_r(&env_htab, (char *)default_environment,
>> -			sizeof(default_environment), '\0', 0) == 0)
>> +			sizeof(default_environment), '\0', 0,
>> +			0, NULL) == 0)
>>   		error("Environment import failed: errno = %d\n", errno);
>>
>>   	gd->flags |= GD_FLG_ENV_READY;
>> @@ -207,7 +208,8 @@ int env_import(const char *buf, int check)
>>   		}
>>   	}
>>
>> -	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
>> +	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
>> +			0, NULL)) {
>>   		gd->flags |= GD_FLG_ENV_READY;
>>   		return 1;
>>   	}
>> diff --git a/include/search.h b/include/search.h
>> index a4a5ef4..94d75fc 100644
>> --- a/include/search.h
>> +++ b/include/search.h
>> @@ -94,9 +94,13 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
>>   		     const char __sep, char **__resp, size_t __size,
>>   		     int argc, char * const argv[]);
>>
>> +/*
>> + * nvars: length of vars array
>> + * vars: array of strings (variable names) to import (nvars == 0 means
>> all) + */
>>   extern int himport_r(struct hsearch_data *__htab,
>>   		     const char *__env, size_t __size, const char __sep,
>> -		     int __flag);
>> +		     int __flag, int nvars, char * const vars[]);
>>
>>   /* Flags for himport_r() */
>>   #define	H_NOCLEAR	(1<<  0) /* do not clear hash table before
> importing */
>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>> index abd61c8..0610e86 100644
>> --- a/lib/hashtable.c
>> +++ b/lib/hashtable.c
>> @@ -603,6 +603,24 @@ ssize_t hexport_r(struct hsearch_data *htab, const
>> char sep, * himport()
>>    */
>>
>> +/* Check whether variable name is amongst vars[] */
>> +static int is_var_in_set(const char *name, int nvars, char * const vars[])
>> +{
>> +	int i = 0;
>> +
>> +	/* No variables specified means process all of them */
>> +	if (nvars == 0)
>> +		return 1;
>> +
>> +	for (i = 0; i<  nvars; i++) {
>> +		if (!strcmp(name, vars[i]))
>> +			return 1;
>> +	}
>> +	debug("Skipping non-listed variable %s\n", name);
>> +
>> +	return 0;
>> +}
>> +
>>   /*
>>    * Import linearized data into hash table.
>>    *
>> @@ -639,7 +657,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const char
>> sep, */
>>
>>   int himport_r(struct hsearch_data *htab,
>> -	      const char *env, size_t size, const char sep, int flag)
>> +		const char *env, size_t size, const char sep, int flag,
>> +		int nvars, char * const vars[])
>>   {
>>   	char *data, *sp, *dp, *name, *value;
>>
>> @@ -726,6 +745,8 @@ int himport_r(struct hsearch_data *htab,
>>   			*dp++ = '\0';	/* terminate name */
>>
>>   			debug("DELETE CANDIDATE: \"%s\"\n", name);
>> +			if (!is_var_in_set(name, nvars, vars))
>> +				continue;
>>
>>   			if (hdelete_r(name, htab) == 0)
>>   				debug("DELETE ERROR
> ##############################\n");
>> @@ -743,6 +764,10 @@ int himport_r(struct hsearch_data *htab,
>>   		*sp++ = '\0';	/* terminate value */
>>   		++dp;
>>
>> +		/* Skip variables which are not supposed to be processed */
>> +		if (!is_var_in_set(name, nvars, vars))
>> +			continue;
>> +
>>   		/* enter into hash table */
>>   		e.key = name;
>>   		e.data = value;

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r()
  2012-04-02 19:01     ` Marek Vasut
@ 2012-04-02 20:44       ` Gerlando Falauto
  2012-04-02 20:51         ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 20:44 UTC (permalink / raw)
  To: u-boot

On 04/02/2012 09:01 PM, Marek Vasut wrote:
> Dear Marek Vasut,
>
>> Dear Gerlando Falauto,
>>
>>> Change hashtable so that a callback function will decide whether a
>>> variable can be overwritten, and possibly apply the changes.
>>>
>>> So add a new field to struct hsearch_data:
>>>   o "apply" callback function to check whether a variable can be
>>>
>>>      overwritten, and possibly immediately apply the changes;
>>>      when NULL, no check is performed.
>>>
>>> And a new argument to himport_r():
>>>   o "do_apply": whether to call the apply callback function
>>>
>>> NOTE: This patch does not change the current behavior.
>>>
>>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>>> ---
>>>
>>>   common/cmd_nvedit.c   |    3 ++-
>>>   common/env_common.c   |    8 +++++---
>>>   include/environment.h |    9 +++++++++
>>>   include/search.h      |   14 +++++++++++++-
>>>   lib/hashtable.c       |   20 +++++++++++++++++++-
>>>   5 files changed, 48 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
>>> index 59668a6..fc6165f 100644
>>> --- a/common/cmd_nvedit.c
>>> +++ b/common/cmd_nvedit.c
>>> @@ -201,6 +201,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
>>>
>>>    * environment variable, then (if successful) apply the changes to
>>>
>>> internals so * to make them effective.  Code for this function was taken
>>> out of * _do_env_set(), which now calls it instead.
>>> + * Also called as a callback function by himport_r().
>>>
>>>    * Returns 0 in case of success, 1 in case of failure.
>>>    * When (flag&  H_FORCE) is set, do not print out any error message and
>>>
>>> force * overwriting of write-once variables.
>>> @@ -931,7 +932,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
>>>
>>>   	}
>>>   	
>>>   	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
>>>
>>> -			0, NULL) == 0) {
>>> +			0, NULL, 0 /* do_apply */) == 0) {
>>>
>>>   		error("Environment import failed: errno = %d\n", errno);
>>>   		return 1;
>>>   	
>>>   	}
>>>
>>> diff --git a/common/env_common.c b/common/env_common.c
>>> index a93c062..5558c1c 100644
>>> --- a/common/env_common.c
>>> +++ b/common/env_common.c
>>> @@ -122,7 +122,9 @@ const uchar default_environment[] = {
>>>
>>>   	"\0"
>>>
>>>   };
>>>
>>> -struct hsearch_data env_htab;
>>> +struct hsearch_data env_htab = {
>>> +	.apply = env_check_apply,
>>> +};
>>>
>>>   static uchar __env_get_char_spec(int index)
>>>   {
>>>
>>> @@ -183,7 +185,7 @@ void set_default_env(const char *s)
>>>
>>>   	if (himport_r(&env_htab, (char *)default_environment,
>>>   	
>>>   			sizeof(default_environment), '\0', 0,
>>>
>>> -			0, NULL) == 0)
>>> +			0, NULL, 0 /* do_apply */) == 0)
>>
>> Please replace that 0 /*...*/ stuff with simple NULL
>
> Oh, it's integer ... so just remove the comment, sorry.

The comment would have been a way to shed some light on one of the 8 
arguments the function takes.
But if it's against some coding style guideline, I'll simply remove it.

>
>>
>>>   		error("Environment import failed: errno = %d\n", errno);
>>>   	
>>>   	gd->flags |= GD_FLG_ENV_READY;
>>>
>>> @@ -209,7 +211,7 @@ int env_import(const char *buf, int check)
>>>
>>>   	}
>>>   	
>>>   	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
>>>
>>> -			0, NULL)) {
>>> +			0, NULL, 0 /* do_apply */)) {
>>
>> DTTO, otherwise looks fine.
>>
>>>   		gd->flags |= GD_FLG_ENV_READY;
>>>   		return 1;
>>>   	
>>>   	}
>>>
>>> diff --git a/include/environment.h b/include/environment.h
>>> index 1ef44f3..236e179 100644
>>> --- a/include/environment.h
>>> +++ b/include/environment.h
>>> @@ -193,6 +193,15 @@ void set_default_env(const char *s);
>>>
>>>   /* Import from binary representation into hash table */
>>>   int env_import(const char *buf, int check);
>>>
>>> +/*
>>> + * Check if variable "name" can be changed from oldval to newval,
>>> + * and if so, apply the changes (e.g. baudrate).
>>> + * When (flag&  H_FORCE) is set, it does not print out any error
>>> + * message and forces overwriting of write-once variables.
>>> + */
>>> +int env_check_apply(const char *name, const char *oldval,
>>> +			const char *newval, int flag);
>>> +
>>>
>>>   #endif /* DO_DEPS_ONLY */
>>>
>>>   #endif /* _ENVIRONMENT_H_ */
>>>
>>> diff --git a/include/search.h b/include/search.h
>>> index 94d75fc..721c8ac 100644
>>> --- a/include/search.h
>>> +++ b/include/search.h
>>> @@ -57,6 +57,16 @@ struct hsearch_data {
>>>
>>>   	struct _ENTRY *table;
>>>   	unsigned int size;
>>>   	unsigned int filled;
>>>
>>> +/*
>>> + * Callback function which will check whether the given change for
>>> variable + * "name" from "oldval" to "newval" may be applied or not, and
>>> possibly apply + * such change.
>>> + * When (flag&  H_FORCE) is set, it shall not print out any error
>>> message and + * shall force overwriting of write-once variables.
>>> +.* Must return 0 for approval, 1 for denial.
>>> + */
>>> +	int (*apply)(const char *name, const char *oldval,
>>> +			const char *newval, int flag);
>>>
>>>   };
>>>
>>>   /* Create a new hashing table which will at most contain NEL elements.
>>>   */
>>>
>>> @@ -97,10 +107,12 @@ extern ssize_t hexport_r(struct hsearch_data
>>> *__htab,
>>>
>>>   /*
>>>
>>>    * nvars: length of vars array
>>>    * vars: array of strings (variable names) to import (nvars == 0 means
>>>
>>> all) + * do_apply: whether to call callback function to check the new
>>> argument, + * and possibly apply changes (false means accept everything)
>>>
>>>    */
>>>
>>>   extern int himport_r(struct hsearch_data *__htab,
>>>
>>>   		     const char *__env, size_t __size, const char __sep,
>>>
>>> -		     int __flag, int nvars, char * const vars[]);
>>> +		     int __flag, int nvars, char * const vars[], int do_apply);
>>>
>>>   /* Flags for himport_r() */
>>>   #define	H_NOCLEAR	(1<<  0) /* do not clear hash table before
>>
>> importing */
>>
>>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>>> index 0610e86..6cfba56 100644
>>> --- a/lib/hashtable.c
>>> +++ b/lib/hashtable.c
>>> @@ -658,7 +658,7 @@ static int is_var_in_set(const char *name, int nvars,
>>> char * const vars[])
>>>
>>>   int himport_r(struct hsearch_data *htab,
>>>
>>>   		const char *env, size_t size, const char sep, int flag,
>>>
>>> -		int nvars, char * const vars[])
>>> +		int nvars, char * const vars[], int do_apply)
>>>
>>>   {
>>>
>>>   	char *data, *sp, *dp, *name, *value;
>>>
>>> @@ -772,6 +772,24 @@ int himport_r(struct hsearch_data *htab,
>>>
>>>   		e.key = name;
>>>   		e.data = value;
>>>
>>> +		/* if there is an apply function, check what it has to say */
>>> +		if (do_apply&&  htab->apply != NULL) {
>>> +			debug("searching before calling cb function"
>>> +				" for  %s\n", name);
>>> +			/*
>>> +			 * Search for variable in existing env, so to pass
>>> +			 * its previous value to the apply callback
>>> +			 */
>>> +			hsearch_r(e, FIND,&rv, htab);
>>> +			debug("previous value was %s\n", rv ? rv->data : "");
>>> +			if (htab->apply(name, rv ? rv->data : NULL,
>>> +				value, flag)) {
>>> +				debug("callback function refused to set"
>>> +					" variable %s, skipping it!\n", name);
>>> +				continue;
>>> +			}
>>> +		}
>>> +
>>>
>>>   		hsearch_r(e, ENTER,&rv, htab);
>>>   		if (rv == NULL) {
>>>   		
>>>   			printf("himport_r: can't insert \"%s=%s\" into hash
>>
>> table\n",

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 6/6] env: delete selected vars not present in imported env
  2012-04-02 19:06   ` Marek Vasut
@ 2012-04-02 20:45     ` Gerlando Falauto
  2012-04-02 21:00       ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-04-02 20:45 UTC (permalink / raw)
  To: u-boot

On 04/02/2012 09:06 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> When variables explicitly specified on the command line are not present
>> in the imported env, delete them from the running env.
>> If the variable is also missing from the running env, issue a warning.
>>
>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>> ---
>>   lib/hashtable.c |   48 +++++++++++++++++++++++++++++++++++++++++-------
>>   1 files changed, 41 insertions(+), 7 deletions(-)
>>
>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>> index f3f47de..b3d0b64 100644
>> --- a/lib/hashtable.c
>> +++ b/lib/hashtable.c
>> @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const
>> char sep, * himport()
>>    */
>>
>> -/* Check whether variable name is amongst vars[] */
>> -static int is_var_in_set(const char *name, int nvars, char * const vars[])
>> +/*
>> + * Check whether variable 'name' is amongst vars[],
>> + * and remove all instances by setting the pointer to NULL
>> + */
>> +static int is_var_in_set(const char *name, int nvars, char * vars[])
>>   {
>>   	int i = 0;
>> +	int res = 0;
>>
>>   	/* No variables specified means process all of them */
>>   	if (nvars == 0)
>>   		return 1;
>>
>>   	for (i = 0; i<  nvars; i++) {
>> -		if (!strcmp(name, vars[i]))
>> -			return 1;
>> +		if (vars[i] == NULL)
>> +			continue;
>> +		/* If we found it, delete all of them */
>> +		if (!strcmp(name, vars[i])) {
>> +			vars[i] = NULL;
>> +			res = 1;
>> +		}
>>   	}
>> -	debug("Skipping non-listed variable %s\n", name);
>> +	if (!res)
>> +		debug("Skipping non-listed variable %s\n", name);
>>
>> -	return 0;
>> +	return res;
>>   }
>>
>>   /*
>> @@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int nvars,
>> char * const vars[])
>>
>>   int himport_r(struct hsearch_data *htab,
>>   		const char *env, size_t size, const char sep, int flag,
>> -		int nvars, char * const vars[], int do_apply)
>> +		int nvars, char * const __vars[], int do_apply)
>>   {
>>   	char *data, *sp, *dp, *name, *value;
>> +	char *vars[nvars];
>> +	int i;
>>
>>   	/* Test for correct arguments.  */
>>   	if (htab == NULL) {
>> @@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
>>   	memcpy(data, env, size);
>>   	dp = data;
>>
>> +	/* make a local copy of the list of variables */
>> +	if (nvars)
>> +		memcpy(vars, __vars, sizeof(__vars[0]) * nvars);
>
> Stupid question -- do you need the local copy at all? Why?

Because I need some way to keep track of what variables have already 
been taken into account, and it seemed the easiest way to do it without 
touching the original array (which is BTW passed as a const, at least 
pointer-wise).
I should have written that in the commit message but I forgot.

I'm not particularly fond of it either, but I'd rather do that than 
overwrite the original array. Not that it's needed afterwards by the 
caller...
Of course the same information (variables "used") could be tracked in 
some other way (e.g. a bitmask array). I'm not sure about the binary 
code size, but it would just make things much more complicated to 
read... and it's not like this feature (selective importing) is the core 
of the bootloader, I guess.

We can of course argue whether going through the hassle of deleting a 
variable specified on the command line which is not defined in the 
default/imported env is really the right thing to do (in other words, 
whether the whole patch has the right to exist!), but that's a different 
story. That's why I enqueued it as a separate patch.

>
>> +
>>   	if ((flag&  H_NOCLEAR) == 0) {
>>   		/* Destroy old hash table if one exists */
>>   		debug("Destroy Hash Table: %p table = %p\n", htab,
>> @@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
>>   	debug("INSERT: free(data = %p)\n", data);
>>   	free(data);
>>
>> +	/* process variables which were not considered */
>> +	for (i = 0; i<  nvars; i++) {
>> +		if (vars[i] == NULL)
>> +			continue;
>> +		/*
>> +		 * All variables which were not deleted from the variable list
>> +		 * were not present in the imported env
>> +		 * This could mean two things:
>> +		 * a) if the variable was present in current env, we delete it
>> +		 * b) if the variable was not present in current env, we notify
>> +		 *    it might be a typo
>> +		 */
>> +		if (hdelete_r(vars[i], htab, do_apply) == 0)
>> +			printf("WARNING: '%s' neither in running nor in imported
> env!\n",
>> vars[i]); +		else
>> +			printf("WARNING: '%s' not in imported env, deleting it!
> \n", vars[i]);
>> +	}
>> +
>>   	debug("INSERT: done\n");
>>   	return 1;		/* everything OK */
>>   }

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 1/6] env: unify logic to check and apply changes
  2012-04-02 20:39     ` Gerlando Falauto
@ 2012-04-02 20:50       ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 20:50 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 04/02/2012 08:56 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> >> The logic of checking special parameters (e.g. baudrate, stdin, stdout,
> >> for a valid value and/or whether can be overwritten) and applying the
> >> new value to the running system is now all within a single function
> >> env_check_apply() which can be called whenever changes are made
> >> to the environment, no matter if by set, default or import.
> >> 
> >> With this patch env_check_apply() is only called by "env set",
> >> retaining previous behavior.
> >> 
> >> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
> >> ---
> >> 
> >>   common/cmd_nvedit.c |  170
> >> 
> >> ++++++++++++++++++++++++++++++++------------------- include/search.h   
> >> |
> >> 
> >>    3 +-
> >>   
> >>   2 files changed, 109 insertions(+), 64 deletions(-)
> >> 
> >> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> >> index 22f9821..e762e76 100644
> >> --- a/common/cmd_nvedit.c
> >> +++ b/common/cmd_nvedit.c
> >> @@ -197,32 +197,21 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
> >> 
> >>   #endif
> >>   
> >>   /*
> >> 
> >> - * Set a new environment variable,
> >> - * or replace or delete an existing one.
> >> + * Perform consistency checking before setting, replacing, or deleting
> >> an + * environment variable, then (if successful) apply the changes to
> >> internals so + * to make them effective.  Code for this function was
> >> taken out of + * _do_env_set(), which now calls it instead.
> >> + * Returns 0 in case of success, 1 in case of failure.
> >> + * When (flag&  H_FORCE) is set, do not print out any error message and
> >> force + * overwriting of write-once variables.
> >> 
> >>    */
> >> 
> >> -int _do_env_set(int flag, int argc, char * const argv[])
> >> +
> >> +int env_check_apply(const char *name, const char *oldval,
> >> +			const char *newval, int flag)
> >> 
> >>   {
> >>   
> >>   	bd_t  *bd = gd->bd;
> >> 
> >> -	int   i, len;
> >> +	int   i;
> >> 
> >>   	int   console = -1;
> >> 
> >> -	char  *name, *value, *s;
> >> -	ENTRY e, *ep;
> >> -
> >> -	name = argv[1];
> >> -
> >> -	if (strchr(name, '=')) {
> >> -		printf("## Error: illegal character '=' in variable name"
> >> -		       "\"%s\"\n", name);
> >> -		return 1;
> >> -	}
> >> -
> >> -	env_id++;
> >> -	/*
> >> -	 * search if variable with this name already exists
> >> -	 */
> >> -	e.key = name;
> >> -	e.data = NULL;
> >> -	hsearch_r(e, FIND,&ep,&env_htab);
> >> 
> >>   	/* Check for console redirection */
> >>   	if (strcmp(name, "stdin") == 0)
> >> 
> >> @@ -233,60 +222,76 @@ int _do_env_set(int flag, int argc, char * const
> >> argv[]) console = stderr;
> >> 
> >>   	if (console != -1) {
> >> 
> >> -		if (argc<  3) {		/* Cannot delete it! */
> >> -			printf("Can't delete \"%s\"\n", name);
> >> +		if ((newval == NULL) || (*newval == '\0')) {
> >> +			/* We cannot delete stdin/stdout/stderr */
> >> +			if ((flag&  H_FORCE) == 0)
> > 
> > Given H_FORCE isn't set on any env var yet, won't this break
> > bisectability?
> 
> What do you mean? We are defining (and checking on) a new flag which is
> not set yet. It's like adding a new feature which nobody uses yet.
> Of course this patch alone doesn't make any sense on its own, it just
> sets the ground for features to be used later. But otherwise it should
> compile (and work) fine, you just can't test it yet.
> 
> See, the whole thing started as a single task which kept growing up by
> adding features which are somehow intertwined. So I tried to break it up
> into smaller pieces so to at make reviews easier. But logicallly, it's a
> big fat patch.

I groked that down later in the series, OK :)

> 
> >> +				printf("Can't delete \"%s\"\n", name);
> >> 
> >>   			return 1;
> >>   		
> >>   		}
> >>   
> >>   #ifdef CONFIG_CONSOLE_MUX
> >> 
> >> -		i = iomux_doenv(console, argv[2]);
> >> +		i = iomux_doenv(console, newval);
> >> 
> >>   		if (i)
> >>   		
> >>   			return i;
> >>   
> >>   #else
> >>   
> >>   		/* Try assigning specified device */
> >> 
> >> -		if (console_assign(console, argv[2])<  0)
> >> +		if (console_assign(console, newval)<  0)
> >> 
> >>   			return 1;
> >>   
> >>   #ifdef CONFIG_SERIAL_MULTI
> >> 
> >> -		if (serial_assign(argv[2])<  0)
> >> +		if (serial_assign(newval)<  0)
> >> 
> >>   			return 1;
> >>   
> >>   #endif
> >>   #endif /* CONFIG_CONSOLE_MUX */
> >>   
> >>   	}
> >>   	
> >>   	/*
> >> 
> >> -	 * Some variables like "ethaddr" and "serial#" can be set only
> >> -	 * once and cannot be deleted; also, "ver" is readonly.
> >> +	 * Some variables like "ethaddr" and "serial#" can be set only once
> >> and +	 * cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined.
> >> 
> >>   	 */
> >> 
> >> -	if (ep) {		/* variable exists */
> >> 
> >>   #ifndef CONFIG_ENV_OVERWRITE
> >> 
> >> +	if (oldval != NULL&&			/* variable exists */
> >> +		(flag&  H_FORCE) == 0) {	/* and we are not forced */
> >> 
> >>   		if (strcmp(name, "serial#") == 0 ||
> >>   		
> >>   		    (strcmp(name, "ethaddr") == 0
> >>   
> >>   #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE)&&  defined(CONFIG_ETHADDR)
> >> 
> >> -		&&  strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0
> >> +		&&  strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0
> >> 
> >>   #endif	/* CONFIG_OVERWRITE_ETHADDR_ONCE&&  CONFIG_ETHADDR */
> >>   
> >>   			)) {
> >>   			printf("Can't overwrite \"%s\"\n", name);
> >>   			return 1;
> >>   		
> >>   		}
> >> 
> >> +	}
> >> 
> >>   #endif
> >> 
> >> +	/*
> >> +	 * When we change baudrate, or we are doing an env default -a
> >> +	 * (which will erase all variables prior to calling this),
> >> +	 * we want the baudrate to actually change - for real.
> >> +	 */
> >> +	if (oldval != NULL ||			/* variable exists */
> >> +		(flag&  H_NOCLEAR) == 0) {	/* or env is clear */
> >> 
> >>   		/*
> >>   		
> >>   		 * Switch to new baudrate if new baudrate is supported
> >>   		 */
> >>   		
> >>   		if (strcmp(name, "baudrate") == 0) {
> >> 
> >> -			int baudrate = simple_strtoul(argv[2], NULL, 10);
> >> +			int baudrate = simple_strtoul(newval, NULL, 10);
> >> 
> >>   			int i;
> >>   			for (i = 0; i<  N_BAUDRATES; ++i) {
> >>   			
> >>   				if (baudrate == baudrate_table[i])
> >>   				
> >>   					break;
> >>   			
> >>   			}
> >>   			if (i == N_BAUDRATES) {
> >> 
> >> -				printf("## Baudrate %d bps not supported\n",
> >> -					baudrate);
> >> +				if ((flag&  H_FORCE) == 0)
> >> +					printf("## Baudrate %d bps not "
> >> +						"supported\n", baudrate);
> >> 
> >>   				return 1;
> >>   			
> >>   			}
> >> 
> >> +			if (gd->baudrate == baudrate) {
> >> +				/* If unchanged, we just say it's OK */
> >> +				return 0;
> >> +			}
> >> 
> >>   			printf("## Switch baudrate to %d bps and"
> >> 
> >> -			       "press ENTER ...\n", baudrate);
> >> +				"press ENTER ...\n", baudrate);
> > 
> > What changed above?
> 
> Replaced spaces with a tab, so to obey a previously mentioned formatting
> rule.

Good :)

> 
> >>   			udelay(50000);
> >>   			gd->baudrate = baudrate;
> >>   
> >>   #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
> >> 
> >> @@ -300,6 +305,73 @@ int _do_env_set(int flag, int argc, char * const
> >> argv[]) }
> >> 
> >>   	}
> >> 
> >> +	/*
> >> +	 * Some variables should be updated when the corresponding
> >> +	 * entry in the environment is changed
> >> +	 */
> >> +	if (strcmp(name, "ipaddr") == 0) {
> >> +		const char *s = newval;
> >> +		char *e;
> >> +		unsigned long addr;
> >> +		bd->bi_ip_addr = 0;
> >> +		for (addr = 0, i = 0; i<  4; ++i) {
> >> +			ulong val = s ? simple_strtoul(s,&e, 10) : 0;
> >> +			addr<<= 8;
> >> +			addr  |= val&  0xFF;
> >> +			if (s)
> >> +				s = *e ? e + 1 : e;
> >> +		}
> >> +		bd->bi_ip_addr = htonl(addr);
> >> +		return 0;
> >> +	} else if (strcmp(name, "loadaddr") == 0) {
> >> +		load_addr = simple_strtoul(newval, NULL, 16);
> >> +		return 0;
> >> +	}
> >> +#if defined(CONFIG_CMD_NET)
> >> +	else if (strcmp(name, "bootfile") == 0) {
> >> +		copy_filename(BootFile, newval, sizeof(BootFile));
> >> +		return 0;
> >> +	}
> >> +#endif
> >> +	return 0;
> >> +}
> >> +
> >> +/*
> >> + * Set a new environment variable,
> >> + * or replace or delete an existing one.
> >> +*/
> >> +int _do_env_set(int flag, int argc, char * const argv[])
> >> +{
> >> +	int   i, len;
> >> +	char  *name, *value, *s;
> >> +	ENTRY e, *ep;
> >> +
> >> +	name = argv[1];
> >> +	value = argv[2];
> >> +
> >> +	if (strchr(name, '=')) {
> >> +		printf("## Error: illegal character '='"
> >> +		       "in variable name \"%s\"\n", name);
> >> +		return 1;
> >> +	}
> >> +
> >> +	env_id++;
> >> +	/*
> >> +	 * search if variable with this name already exists
> >> +	 */
> >> +	e.key = name;
> >> +	e.data = NULL;
> >> +	hsearch_r(e, FIND,&ep,&env_htab);
> >> +
> >> +	/*
> >> +	 * Perform requested checks. Notice how since we are overwriting
> >> +	 * a single variable, we need to set H_NOCLEAR
> >> +	 */
> >> +	if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
> >> +		debug("check function did not approve, refusing\n");
> >> +		return 1;
> >> +	}
> >> +
> >> 
> >>   	/* Delete only ? */
> > 
> > Shouldn't delete-only be handled before env_check_apply() to make it
> > faster?
> 
> Why? If you try to unset a variable (e.g. stdin, console), you should
> *first* check whether that's a sane thing to do, and *then*, that being
> the case, delete it.

Ah, good point.

> 
> >>   	if (argc<  3 || argv[2] == NULL) {
> >>   	
> >>   		int rc = hdelete_r(name,&env_htab);
> >> 
> >> @@ -337,34 +409,6 @@ int _do_env_set(int flag, int argc, char * const
> >> argv[]) return 1;
> >> 
> >>   	}
> >> 
> >> -	/*
> >> -	 * Some variables should be updated when the corresponding
> >> -	 * entry in the environment is changed
> >> -	 */
> >> -	if (strcmp(name, "ipaddr") == 0) {
> >> -		char *s = argv[2];	/* always use only one arg */
> >> -		char *e;
> >> -		unsigned long addr;
> >> -		bd->bi_ip_addr = 0;
> >> -		for (addr = 0, i = 0; i<  4; ++i) {
> >> -			ulong val = s ? simple_strtoul(s,&e, 10) : 0;
> >> -			addr<<= 8;
> >> -			addr  |= val&  0xFF;
> >> -			if (s)
> >> -				s = *e ? e + 1 : e;
> >> -		}
> >> -		bd->bi_ip_addr = htonl(addr);
> >> -		return 0;
> >> -	} else if (strcmp(argv[1], "loadaddr") == 0) {
> >> -		load_addr = simple_strtoul(argv[2], NULL, 16);
> >> -		return 0;
> >> -	}
> >> -#if defined(CONFIG_CMD_NET)
> >> -	else if (strcmp(argv[1], "bootfile") == 0) {
> >> -		copy_filename(BootFile, argv[2], sizeof(BootFile));
> >> -		return 0;
> >> -	}
> >> -#endif
> >> 
> >>   	return 0;
> >>   
> >>   }
> >> 
> >> diff --git a/include/search.h b/include/search.h
> >> index ef53edb..a4a5ef4 100644
> >> --- a/include/search.h
> >> +++ b/include/search.h
> >> @@ -99,6 +99,7 @@ extern int himport_r(struct hsearch_data *__htab,
> >> 
> >>   		     int __flag);
> >>   
> >>   /* Flags for himport_r() */
> >> 
> >> -#define	H_NOCLEAR	1	/* do not clear hash table before
> > 
> > importing */
> > 
> >> +#define	H_NOCLEAR	(1<<  0) /* do not clear hash table before
> > 
> > importing */
> > 
> >> +#define	H_FORCE		(1<<  1) /* overwrite read-only/write-once
> > 
> > variables */
> > 
> >>   #endif /* search.h */

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r()
  2012-04-02 20:44       ` Gerlando Falauto
@ 2012-04-02 20:51         ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 20:51 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 04/02/2012 09:01 PM, Marek Vasut wrote:
> > Dear Marek Vasut,
> > 
> >> Dear Gerlando Falauto,
> >> 
> >>> Change hashtable so that a callback function will decide whether a
> >>> variable can be overwritten, and possibly apply the changes.
> >>> 
> >>> So add a new field to struct hsearch_data:
> >>>   o "apply" callback function to check whether a variable can be
> >>>   
> >>>      overwritten, and possibly immediately apply the changes;
> >>>      when NULL, no check is performed.
> >>> 
> >>> And a new argument to himport_r():
> >>>   o "do_apply": whether to call the apply callback function
> >>> 
> >>> NOTE: This patch does not change the current behavior.
> >>> 
> >>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
> >>> ---
> >>> 
> >>>   common/cmd_nvedit.c   |    3 ++-
> >>>   common/env_common.c   |    8 +++++---
> >>>   include/environment.h |    9 +++++++++
> >>>   include/search.h      |   14 +++++++++++++-
> >>>   lib/hashtable.c       |   20 +++++++++++++++++++-
> >>>   5 files changed, 48 insertions(+), 6 deletions(-)
> >>> 
> >>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> >>> index 59668a6..fc6165f 100644
> >>> --- a/common/cmd_nvedit.c
> >>> +++ b/common/cmd_nvedit.c
> >>> @@ -201,6 +201,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
> >>> 
> >>>    * environment variable, then (if successful) apply the changes to
> >>> 
> >>> internals so * to make them effective.  Code for this function was
> >>> taken out of * _do_env_set(), which now calls it instead.
> >>> + * Also called as a callback function by himport_r().
> >>> 
> >>>    * Returns 0 in case of success, 1 in case of failure.
> >>>    * When (flag&  H_FORCE) is set, do not print out any error message
> >>>    and
> >>> 
> >>> force * overwriting of write-once variables.
> >>> @@ -931,7 +932,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int
> >>> flag,
> >>> 
> >>>   	}
> >>>   	
> >>>   	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
> >>> 
> >>> -			0, NULL) == 0) {
> >>> +			0, NULL, 0 /* do_apply */) == 0) {
> >>> 
> >>>   		error("Environment import failed: errno = %d\n", errno);
> >>>   		return 1;
> >>>   	
> >>>   	}
> >>> 
> >>> diff --git a/common/env_common.c b/common/env_common.c
> >>> index a93c062..5558c1c 100644
> >>> --- a/common/env_common.c
> >>> +++ b/common/env_common.c
> >>> @@ -122,7 +122,9 @@ const uchar default_environment[] = {
> >>> 
> >>>   	"\0"
> >>>   
> >>>   };
> >>> 
> >>> -struct hsearch_data env_htab;
> >>> +struct hsearch_data env_htab = {
> >>> +	.apply = env_check_apply,
> >>> +};
> >>> 
> >>>   static uchar __env_get_char_spec(int index)
> >>>   {
> >>> 
> >>> @@ -183,7 +185,7 @@ void set_default_env(const char *s)
> >>> 
> >>>   	if (himport_r(&env_htab, (char *)default_environment,
> >>>   	
> >>>   			sizeof(default_environment), '\0', 0,
> >>> 
> >>> -			0, NULL) == 0)
> >>> +			0, NULL, 0 /* do_apply */) == 0)
> >> 
> >> Please replace that 0 /*...*/ stuff with simple NULL
> > 
> > Oh, it's integer ... so just remove the comment, sorry.
> 
> The comment would have been a way to shed some light on one of the 8
> arguments the function takes.
> But if it's against some coding style guideline, I'll simply remove it.

Not really, I don't really care ;-)

> 
> >>>   		error("Environment import failed: errno = %d\n", errno);
> >>>   	
> >>>   	gd->flags |= GD_FLG_ENV_READY;
> >>> 
> >>> @@ -209,7 +211,7 @@ int env_import(const char *buf, int check)
> >>> 
> >>>   	}
> >>>   	
> >>>   	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
> >>> 
> >>> -			0, NULL)) {
> >>> +			0, NULL, 0 /* do_apply */)) {
> >> 
> >> DTTO, otherwise looks fine.
> >> 
> >>>   		gd->flags |= GD_FLG_ENV_READY;
> >>>   		return 1;
> >>>   	
> >>>   	}
> >>> 
> >>> diff --git a/include/environment.h b/include/environment.h
> >>> index 1ef44f3..236e179 100644
> >>> --- a/include/environment.h
> >>> +++ b/include/environment.h
> >>> @@ -193,6 +193,15 @@ void set_default_env(const char *s);
> >>> 
> >>>   /* Import from binary representation into hash table */
> >>>   int env_import(const char *buf, int check);
> >>> 
> >>> +/*
> >>> + * Check if variable "name" can be changed from oldval to newval,
> >>> + * and if so, apply the changes (e.g. baudrate).
> >>> + * When (flag&  H_FORCE) is set, it does not print out any error
> >>> + * message and forces overwriting of write-once variables.
> >>> + */
> >>> +int env_check_apply(const char *name, const char *oldval,
> >>> +			const char *newval, int flag);
> >>> +
> >>> 
> >>>   #endif /* DO_DEPS_ONLY */
> >>>   
> >>>   #endif /* _ENVIRONMENT_H_ */
> >>> 
> >>> diff --git a/include/search.h b/include/search.h
> >>> index 94d75fc..721c8ac 100644
> >>> --- a/include/search.h
> >>> +++ b/include/search.h
> >>> @@ -57,6 +57,16 @@ struct hsearch_data {
> >>> 
> >>>   	struct _ENTRY *table;
> >>>   	unsigned int size;
> >>>   	unsigned int filled;
> >>> 
> >>> +/*
> >>> + * Callback function which will check whether the given change for
> >>> variable + * "name" from "oldval" to "newval" may be applied or not,
> >>> and possibly apply + * such change.
> >>> + * When (flag&  H_FORCE) is set, it shall not print out any error
> >>> message and + * shall force overwriting of write-once variables.
> >>> +.* Must return 0 for approval, 1 for denial.
> >>> + */
> >>> +	int (*apply)(const char *name, const char *oldval,
> >>> +			const char *newval, int flag);
> >>> 
> >>>   };
> >>>   
> >>>   /* Create a new hashing table which will at most contain NEL
> >>>   elements. */
> >>> 
> >>> @@ -97,10 +107,12 @@ extern ssize_t hexport_r(struct hsearch_data
> >>> *__htab,
> >>> 
> >>>   /*
> >>>   
> >>>    * nvars: length of vars array
> >>>    * vars: array of strings (variable names) to import (nvars == 0
> >>>    means
> >>> 
> >>> all) + * do_apply: whether to call callback function to check the new
> >>> argument, + * and possibly apply changes (false means accept
> >>> everything)
> >>> 
> >>>    */
> >>>   
> >>>   extern int himport_r(struct hsearch_data *__htab,
> >>>   
> >>>   		     const char *__env, size_t __size, const char __sep,
> >>> 
> >>> -		     int __flag, int nvars, char * const vars[]);
> >>> +		     int __flag, int nvars, char * const vars[], int do_apply);
> >>> 
> >>>   /* Flags for himport_r() */
> >>>   #define	H_NOCLEAR	(1<<  0) /* do not clear hash table before
> >> 
> >> importing */
> >> 
> >>> diff --git a/lib/hashtable.c b/lib/hashtable.c
> >>> index 0610e86..6cfba56 100644
> >>> --- a/lib/hashtable.c
> >>> +++ b/lib/hashtable.c
> >>> @@ -658,7 +658,7 @@ static int is_var_in_set(const char *name, int
> >>> nvars, char * const vars[])
> >>> 
> >>>   int himport_r(struct hsearch_data *htab,
> >>>   
> >>>   		const char *env, size_t size, const char sep, int flag,
> >>> 
> >>> -		int nvars, char * const vars[])
> >>> +		int nvars, char * const vars[], int do_apply)
> >>> 
> >>>   {
> >>>   
> >>>   	char *data, *sp, *dp, *name, *value;
> >>> 
> >>> @@ -772,6 +772,24 @@ int himport_r(struct hsearch_data *htab,
> >>> 
> >>>   		e.key = name;
> >>>   		e.data = value;
> >>> 
> >>> +		/* if there is an apply function, check what it has to say */
> >>> +		if (do_apply&&  htab->apply != NULL) {
> >>> +			debug("searching before calling cb function"
> >>> +				" for  %s\n", name);
> >>> +			/*
> >>> +			 * Search for variable in existing env, so to pass
> >>> +			 * its previous value to the apply callback
> >>> +			 */
> >>> +			hsearch_r(e, FIND,&rv, htab);
> >>> +			debug("previous value was %s\n", rv ? rv->data : "");
> >>> +			if (htab->apply(name, rv ? rv->data : NULL,
> >>> +				value, flag)) {
> >>> +				debug("callback function refused to set"
> >>> +					" variable %s, skipping it!\n", name);
> >>> +				continue;
> >>> +			}
> >>> +		}
> >>> +
> >>> 
> >>>   		hsearch_r(e, ENTER,&rv, htab);
> >>>   		if (rv == NULL) {
> >>>   		
> >>>   			printf("himport_r: can't insert \"%s=%s\" into 
hash
> >> 
> >> table\n",

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 6/6] env: delete selected vars not present in imported env
  2012-04-02 20:45     ` Gerlando Falauto
@ 2012-04-02 21:00       ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-04-02 21:00 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 04/02/2012 09:06 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> >> When variables explicitly specified on the command line are not present
> >> in the imported env, delete them from the running env.
> >> If the variable is also missing from the running env, issue a warning.
> >> 
> >> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
> >> ---
> >> 
> >>   lib/hashtable.c |   48
> >>   +++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 41
> >>   insertions(+), 7 deletions(-)
> >> 
> >> diff --git a/lib/hashtable.c b/lib/hashtable.c
> >> index f3f47de..b3d0b64 100644
> >> --- a/lib/hashtable.c
> >> +++ b/lib/hashtable.c
> >> @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> >> char sep, * himport()
> >> 
> >>    */
> >> 
> >> -/* Check whether variable name is amongst vars[] */
> >> -static int is_var_in_set(const char *name, int nvars, char * const
> >> vars[]) +/*
> >> + * Check whether variable 'name' is amongst vars[],
> >> + * and remove all instances by setting the pointer to NULL
> >> + */
> >> +static int is_var_in_set(const char *name, int nvars, char * vars[])
> >> 
> >>   {
> >>   
> >>   	int i = 0;
> >> 
> >> +	int res = 0;
> >> 
> >>   	/* No variables specified means process all of them */
> >>   	if (nvars == 0)
> >>   	
> >>   		return 1;
> >>   	
> >>   	for (i = 0; i<  nvars; i++) {
> >> 
> >> -		if (!strcmp(name, vars[i]))
> >> -			return 1;
> >> +		if (vars[i] == NULL)
> >> +			continue;
> >> +		/* If we found it, delete all of them */
> >> +		if (!strcmp(name, vars[i])) {
> >> +			vars[i] = NULL;
> >> +			res = 1;
> >> +		}
> >> 
> >>   	}
> >> 
> >> -	debug("Skipping non-listed variable %s\n", name);
> >> +	if (!res)
> >> +		debug("Skipping non-listed variable %s\n", name);
> >> 
> >> -	return 0;
> >> +	return res;
> >> 
> >>   }
> >>   
> >>   /*
> >> 
> >> @@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int
> >> nvars, char * const vars[])
> >> 
> >>   int himport_r(struct hsearch_data *htab,
> >>   
> >>   		const char *env, size_t size, const char sep, int flag,
> >> 
> >> -		int nvars, char * const vars[], int do_apply)
> >> +		int nvars, char * const __vars[], int do_apply)
> >> 
> >>   {
> >>   
> >>   	char *data, *sp, *dp, *name, *value;
> >> 
> >> +	char *vars[nvars];
> >> +	int i;
> >> 
> >>   	/* Test for correct arguments.  */
> >>   	if (htab == NULL) {
> >> 
> >> @@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
> >> 
> >>   	memcpy(data, env, size);
> >>   	dp = data;
> >> 
> >> +	/* make a local copy of the list of variables */
> >> +	if (nvars)
> >> +		memcpy(vars, __vars, sizeof(__vars[0]) * nvars);
> > 
> > Stupid question -- do you need the local copy at all? Why?
> 
> Because I need some way to keep track of what variables have already
> been taken into account, and it seemed the easiest way to do it without
> touching the original array (which is BTW passed as a const, at least
> pointer-wise).
> I should have written that in the commit message but I forgot.
> 
> I'm not particularly fond of it either, but I'd rather do that than
> overwrite the original array. Not that it's needed afterwards by the
> caller...
> Of course the same information (variables "used") could be tracked in
> some other way (e.g. a bitmask array).

Well won't bitfield suffice then?

> I'm not sure about the binary
> code size, but it would just make things much more complicated to
> read... and it's not like this feature (selective importing) is the core
> of the bootloader, I guess.
> 
> We can of course argue whether going through the hassle of deleting a
> variable specified on the command line which is not defined in the
> default/imported env is really the right thing to do (in other words,
> whether the whole patch has the right to exist!), but that's a different
> story. That's why I enqueued it as a separate patch.

Honestly, I'm not in the position to properly argue here because I'm still 
making myself familiar with the env part of uboot ;-)

> 
> >> +
> >> 
> >>   	if ((flag&  H_NOCLEAR) == 0) {
> >>   	
> >>   		/* Destroy old hash table if one exists */
> >>   		debug("Destroy Hash Table: %p table = %p\n", htab,
> >> 
> >> @@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
> >> 
> >>   	debug("INSERT: free(data = %p)\n", data);
> >>   	free(data);
> >> 
> >> +	/* process variables which were not considered */
> >> +	for (i = 0; i<  nvars; i++) {
> >> +		if (vars[i] == NULL)
> >> +			continue;
> >> +		/*
> >> +		 * All variables which were not deleted from the variable list
> >> +		 * were not present in the imported env
> >> +		 * This could mean two things:
> >> +		 * a) if the variable was present in current env, we delete it
> >> +		 * b) if the variable was not present in current env, we notify
> >> +		 *    it might be a typo
> >> +		 */
> >> +		if (hdelete_r(vars[i], htab, do_apply) == 0)
> >> +			printf("WARNING: '%s' neither in running nor in imported
> > 
> > env!\n",
> > 
> >> vars[i]); +		else
> >> +			printf("WARNING: '%s' not in imported env, deleting it!
> > 
> > \n", vars[i]);
> > 
> >> +	}
> >> +
> >> 
> >>   	debug("INSERT: done\n");
> >>   	return 1;		/* everything OK */
> >>   
> >>   }

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 2/6] env: make himport_r() selective on variables
  2012-04-02 20:43     ` Gerlando Falauto
@ 2012-04-04  7:41       ` Simon Glass
  0 siblings, 0 replies; 104+ messages in thread
From: Simon Glass @ 2012-04-04  7:41 UTC (permalink / raw)
  To: u-boot

Hi Gerlando,

On Mon, Apr 2, 2012 at 1:43 PM, Gerlando Falauto
<gerlando.falauto@keymile.com> wrote:
> On 04/02/2012 08:57 PM, Marek Vasut wrote:
>>
>> Dear Gerlando Falauto,
>>
>>> Add 2 new arguments to himport_r():
>>>
>>> ?o "nvars", "vars": number and list of variables to take into account
>>> ? ?(0 means ALL)
>>>
>>
>> Looks nice and clean. But man, these patches are tough to review (not
>> because
>> you made bad job, just because they're hard code), lot of headache from
>> them ;-)

I certainly agree with that - I still remember this from last time :-)

>
>
> Tell me about it. I've been reworking them several times, usually after
> several weeks from posting them. Long enough to have forgotten everything,
> and to give you a bad headache.
> So I really appreciate your prompt feedback, thanks!
>
> Gerlando
>
> P.S. For the whole process I am using interactive rebase, which is painful
> enough. If anyone knows of any other way to "patch the patches", some advice
> would be very much appreciated... :-)

I don't know if this helps, but I'll say it anyway. I do a lot of this :-)

Normally if there is a lot of stuff I mess around with the patches on
the top of the branch, with a 'wip' commit. That way I can test
easily. I often have setup commits before the series and a wip one on
top (patman makes it easy to skip these when sending to the mailing
list). Then when I am ready to put the new changes back into the
correct commits, I do a 'git rebase -i' and edit each commit.

For each commit I diff if against the top of the branch but only on
files changed by the *current* commit. So in the case where 25 files
were changed, but only 2 were mentioned in this commit, it is likely
that I only want to bring over changes in those two files into the
current commit.

I have an alias that does this:

function next_commit_changes()
{
	out=$(git log --numstat --pretty=format: -n1 | tail -n+2)
	echo "$out" | awk '{printf("%s ", $3)}'
}

function diff_branch()
{
	echo "Changes in this commit:"
	echo
	git log --stat --oneline -n1

	echo
	echo "Now performing diff against branch on those files only"

	# print a stat list first
	echo $(next_commit_changes)
	git diff $1 --stat -- $(next_commit_changes)

	# now run meld on each diff
	git diff $1 -- $(next_commit_changes)
}

# db <branch>

# this is for splitting a large commit into multiple ones

# Usage:
# git checkout mmc2
# git rebase -i HEAD~4
# on a commit use:
# db mmc2
# this will print a list of changes to the files used by THIS commit
# which have been made at mmc2
alias db='diff_branch'


Basically I then just use the arrows in meld to move over the changes
I made into the right commit. Then 'git add -u' and 'git rebase
--continue' and a line or two to the commit change log. Although I
actually have two character aliases for nearly everything now...

Regards,
Simon

>
>
>>> NOTE: This patch does not change the current behaviour.
>>>
>>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>>> ---
>>> ?common/cmd_nvedit.c | ? ?3 ++-
>>> ?common/env_common.c | ? ?6 ++++--
>>> ?include/search.h ? ?| ? ?6 +++++-
>>> ?lib/hashtable.c ? ? | ? 27 ++++++++++++++++++++++++++-
>>> ?4 files changed, 37 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
>>> index e762e76..59668a6 100644
>>> --- a/common/cmd_nvedit.c
>>> +++ b/common/cmd_nvedit.c
>>> @@ -930,7 +930,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
>>> ? ? ? ? ? ? ? ?addr = (char *)ep->data;
>>> ? ? ? ?}
>>>
>>> - ? ? ? if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) ==
>>> 0) {
>>> + ? ? ? if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
>>> + ? ? ? ? ? ? ? ? ? ? ? 0, NULL) == 0) {
>>> ? ? ? ? ? ? ? ?error("Environment import failed: errno = %d\n", errno);
>>> ? ? ? ? ? ? ? ?return 1;
>>> ? ? ? ?}
>>> diff --git a/common/env_common.c b/common/env_common.c
>>> index c33d22d..a93c062 100644
>>> --- a/common/env_common.c
>>> +++ b/common/env_common.c
>>> @@ -182,7 +182,8 @@ void set_default_env(const char *s)
>>> ? ? ? ?}
>>>
>>> ? ? ? ?if (himport_r(&env_htab, (char *)default_environment,
>>> - ? ? ? ? ? ? ? ? ? ? ? sizeof(default_environment), '\0', 0) == 0)
>>> + ? ? ? ? ? ? ? ? ? ? ? sizeof(default_environment), '\0', 0,
>>> + ? ? ? ? ? ? ? ? ? ? ? 0, NULL) == 0)
>>> ? ? ? ? ? ? ? ?error("Environment import failed: errno = %d\n", errno);
>>>
>>> ? ? ? ?gd->flags |= GD_FLG_ENV_READY;
>>> @@ -207,7 +208,8 @@ int env_import(const char *buf, int check)
>>> ? ? ? ? ? ? ? ?}
>>> ? ? ? ?}
>>>
>>> - ? ? ? if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
>>> + ? ? ? if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
>>> + ? ? ? ? ? ? ? ? ? ? ? 0, NULL)) {
>>> ? ? ? ? ? ? ? ?gd->flags |= GD_FLG_ENV_READY;
>>> ? ? ? ? ? ? ? ?return 1;
>>> ? ? ? ?}
>>> diff --git a/include/search.h b/include/search.h
>>> index a4a5ef4..94d75fc 100644
>>> --- a/include/search.h
>>> +++ b/include/search.h
>>> @@ -94,9 +94,13 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
>>> ? ? ? ? ? ? ? ? ? ? const char __sep, char **__resp, size_t __size,
>>> ? ? ? ? ? ? ? ? ? ? int argc, char * const argv[]);
>>>
>>> +/*
>>> + * nvars: length of vars array
>>> + * vars: array of strings (variable names) to import (nvars == 0 means
>>> all) + */
>>> ?extern int himport_r(struct hsearch_data *__htab,
>>> ? ? ? ? ? ? ? ? ? ? const char *__env, size_t __size, const char __sep,
>>> - ? ? ? ? ? ? ? ? ? ?int __flag);
>>> + ? ? ? ? ? ? ? ? ? ?int __flag, int nvars, char * const vars[]);
>>>
>>> ?/* Flags for himport_r() */
>>> ?#define ? ? ? H_NOCLEAR ? ? ? (1<< ?0) /* do not clear hash table before
>>
>> importing */
>>>
>>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>>> index abd61c8..0610e86 100644
>>> --- a/lib/hashtable.c
>>> +++ b/lib/hashtable.c
>>> @@ -603,6 +603,24 @@ ssize_t hexport_r(struct hsearch_data *htab, const
>>> char sep, * himport()
>>> ? */
>>>
>>> +/* Check whether variable name is amongst vars[] */
>>> +static int is_var_in_set(const char *name, int nvars, char * const
>>> vars[])
>>> +{
>>> + ? ? ? int i = 0;
>>> +
>>> + ? ? ? /* No variables specified means process all of them */
>>> + ? ? ? if (nvars == 0)
>>> + ? ? ? ? ? ? ? return 1;
>>> +
>>> + ? ? ? for (i = 0; i< ?nvars; i++) {
>>> + ? ? ? ? ? ? ? if (!strcmp(name, vars[i]))
>>> + ? ? ? ? ? ? ? ? ? ? ? return 1;
>>> + ? ? ? }
>>> + ? ? ? debug("Skipping non-listed variable %s\n", name);
>>> +
>>> + ? ? ? return 0;
>>> +}
>>> +
>>> ?/*
>>> ? * Import linearized data into hash table.
>>> ? *
>>> @@ -639,7 +657,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const
>>> char
>>> sep, */
>>>
>>> ?int himport_r(struct hsearch_data *htab,
>>> - ? ? ? ? ? ? const char *env, size_t size, const char sep, int flag)
>>> + ? ? ? ? ? ? ? const char *env, size_t size, const char sep, int flag,
>>> + ? ? ? ? ? ? ? int nvars, char * const vars[])
>>> ?{
>>> ? ? ? ?char *data, *sp, *dp, *name, *value;
>>>
>>> @@ -726,6 +745,8 @@ int himport_r(struct hsearch_data *htab,
>>> ? ? ? ? ? ? ? ? ? ? ? ?*dp++ = '\0'; ? /* terminate name */
>>>
>>> ? ? ? ? ? ? ? ? ? ? ? ?debug("DELETE CANDIDATE: \"%s\"\n", name);
>>> + ? ? ? ? ? ? ? ? ? ? ? if (!is_var_in_set(name, nvars, vars))
>>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
>>>
>>> ? ? ? ? ? ? ? ? ? ? ? ?if (hdelete_r(name, htab) == 0)
>>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?debug("DELETE ERROR
>>
>> ##############################\n");
>>>
>>> @@ -743,6 +764,10 @@ int himport_r(struct hsearch_data *htab,
>>> ? ? ? ? ? ? ? ?*sp++ = '\0'; ? /* terminate value */
>>> ? ? ? ? ? ? ? ?++dp;
>>>
>>> + ? ? ? ? ? ? ? /* Skip variables which are not supposed to be processed
>>> */
>>> + ? ? ? ? ? ? ? if (!is_var_in_set(name, nvars, vars))
>>> + ? ? ? ? ? ? ? ? ? ? ? continue;
>>> +
>>> ? ? ? ? ? ? ? ?/* enter into hash table */
>>> ? ? ? ? ? ? ? ?e.key = name;
>>> ? ? ? ? ? ? ? ?e.data = value;
>
>

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default Gerlando Falauto
@ 2012-08-09 20:17   ` Wolfgang Denk
  2012-08-09 22:19     ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Wolfgang Denk @ 2012-08-09 20:17 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <1333391204-16318-1-git-send-email-gerlando.falauto@keymile.com> you wrote:
> This patchset modifies the handling of all the operations on the environment
> (set/import/default) so to unify handling of special variables.
> On top of that we implement a selective "env default".
> 
> A selective "env import" would imply a user API change and should therefore
> be discussed separately.
> 
> NOTE:
> The entire patchset generates an increase in code size of about 1200 bytes
> on a PowerPC target. 
> As much as I would like to get rid of the set_default_vars() function in 
> env_common.c, I have not found a nice way to do so.

It appears we are stuch with this patch set.  Last thing I remember
was that Marek reviewed thes epatches, and had a few comments /
requests for changes.  But I cannot remember having seen any more
eplies from you.

Is this correct?  So what is the current state?  Will there be any
resubmission, or should these be applied as is, or should they be
dropped altogether?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
[War] is instinctive. But the instinct can  be  fought.  We're  human
beings  with the blood of a million savage years on our hands! But we
can stop it. We can admit that we're killers ... but we're not  going
to  kill  today. That's all it takes! Knowing that we're not going to
kill today!
	-- Kirk, "A Taste of Armageddon", stardate 3193.0

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-08-09 20:17   ` Wolfgang Denk
@ 2012-08-09 22:19     ` Gerlando Falauto
  2012-08-09 22:26       ` Wolfgang Denk
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-09 22:19 UTC (permalink / raw)
  To: u-boot

On 08/09/2012 10:17 PM, Wolfgang Denk wrote:
> Dear Gerlando Falauto,
>
> In message<1333391204-16318-1-git-send-email-gerlando.falauto@keymile.com>  you wrote:
>> This patchset modifies the handling of all the operations on the environment
>> (set/import/default) so to unify handling of special variables.
>> On top of that we implement a selective "env default".
>>
>> A selective "env import" would imply a user API change and should therefore
>> be discussed separately.
>>
>> NOTE:
>> The entire patchset generates an increase in code size of about 1200 bytes
>> on a PowerPC target.
>> As much as I would like to get rid of the set_default_vars() function in
>> env_common.c, I have not found a nice way to do so.
>
> It appears we are stuch with this patch set.  Last thing I remember
> was that Marek reviewed thes epatches, and had a few comments /
> requests for changes.  But I cannot remember having seen any more
> eplies from you.

As far as I can remember (or rather, as far as I can understand reading 
the whole thread once again), I had managed to persuade Marek to 
"accept" the first 5 patches out of 6 (I guess more by means of 
confusion than real arguments :-) )
Then on patch 6 we got stuck on:

 >> [me]
>> I'm not particularly fond of it either, but I'd rather do that than
>> overwrite the original array. Not that it's needed afterwards by the
>> caller...
>> Of course the same information (variables "used") could be tracked in
>> some other way (e.g. a bitmask array).

 > [Marek]
> Well won't bitfield suffice then?

[what I failed to reply]
I get the impression that would probably bloat the code even more, but I 
haven't checked that.

>> I'm not sure about the binary
>> code size, but it would just make things much more complicated to
>> read... and it's not like this feature (selective importing) is the core
>> of the bootloader, I guess.
>>
>> We can of course argue whether going through the hassle of deleting a
>> variable specified on the command line which is not defined in the
>> default/imported env is really the right thing to do (in other words,
>> whether the whole patch has the right to exist!), but that's a different
>> story. That's why I enqueued it as a separate patch.
> Honestly, I'm not in the position to properly argue here because I'm still
> making myself familiar with the env part of uboot
>

Which I remember interpreting as "I will follow up later"

>
> Is this correct?  So what is the current state?  Will there be any
> resubmission, or should these be applied as is,

I don't remember having any more leads to follow except for the bitfield 
part on the last (6th) patch. But I wouldn't call my memory a reliable 
source of information.
So please step forward if there's any suggestion.

> or should they be dropped altogether?

If anyone's counting hands, I'm voting against this latest action... :-)

Just so I know, are we talking about the merge window closing on August 
11th anyway?

Thanks,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-08-09 22:19     ` Gerlando Falauto
@ 2012-08-09 22:26       ` Wolfgang Denk
  2012-08-10  8:53         ` Holger Brunck
  0 siblings, 1 reply; 104+ messages in thread
From: Wolfgang Denk @ 2012-08-09 22:26 UTC (permalink / raw)
  To: u-boot

Dear Gerlando,

In message <5024377A.8090905@keymile.com> you wrote:
>
> > It appears we are stuch with this patch set.  Last thing I remember
> > was that Marek reviewed thes epatches, and had a few comments /
> > requests for changes.  But I cannot remember having seen any more
> > eplies from you.
> 
> As far as I can remember (or rather, as far as I can understand reading 
> the whole thread once again), I had managed to persuade Marek to 
> "accept" the first 5 patches out of 6 (I guess more by means of 
> confusion than real arguments :-) )

Heh. Nobody asks for the actual reasons for a decision, later...

> So please step forward if there's any suggestion.

I don't have the time now for a real review, and I fear a bit we might
break somthing.  I would suggest to proceed similar as with the ext4
file system code: add your patches to a separate branch, so it can be
tested easily, and if everybody feels confident with it we can merge
it around the time when we will have a -rc1

> > or should they be dropped altogether?
> 
> If anyone's counting hands, I'm voting against this latest action... :-)

I do count :-)

> Just so I know, are we talking about the merge window closing on August 
> 11th anyway?

Yes, but this is actually irrelevant here, as your patches are way older;
they should go in now, unless there is good reason to reject them.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Emotions are alien to me.  I'm a scientist.
	-- Spock, "This Side of Paradise", stardate 3417.3

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-08-09 22:26       ` Wolfgang Denk
@ 2012-08-10  8:53         ` Holger Brunck
  2012-08-10 18:08           ` Wolfgang Denk
  0 siblings, 1 reply; 104+ messages in thread
From: Holger Brunck @ 2012-08-10  8:53 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

On 08/10/2012 12:26 AM, Wolfgang Denk wrote:
> In message <5024377A.8090905@keymile.com> you wrote:
>> So please step forward if there's any suggestion.
> 
> I don't have the time now for a real review, and I fear a bit we might
> break somthing.  I would suggest to proceed similar as with the ext4
> file system code: add your patches to a separate branch, so it can be
> tested easily, and if everybody feels confident with it we can merge
> it around the time when we will have a -rc1
> 

due to the fact that Gerlando is in his vacations and has therefore only little
time to do updates here I propose the following. I could prepare a branch as you
suggested based on current denx master with this changeset. But where and how
should I push it to git.denx.de? Or will you prepare this branch?

Afterwards we can see if it sufficient to go in for rc1. If not we have to wait
until Gerlando is back at end of august and shift the patch series to the next
merge window.

Regards
Holger Brunck

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-08-10  8:53         ` Holger Brunck
@ 2012-08-10 18:08           ` Wolfgang Denk
  2012-08-13  7:23             ` Holger Brunck
  0 siblings, 1 reply; 104+ messages in thread
From: Wolfgang Denk @ 2012-08-10 18:08 UTC (permalink / raw)
  To: u-boot

Dear Holger,

In message <5024CC15.8010602@keymile.com> you wrote:
> 
> due to the fact that Gerlando is in his vacations and has therefore only little
> time to do updates here I propose the following. I could prepare a branch as you
> suggested based on current denx master with this changeset. But where and how
> should I push it to git.denx.de? Or will you prepare this branch?

I already did.

I guess we will not have -rc1 before end of week 36, if not even
later, so this should work out nicely.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
There are two ways to write error-free programs. Only the  third  one
works.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-08-10 18:08           ` Wolfgang Denk
@ 2012-08-13  7:23             ` Holger Brunck
  2012-08-13 10:11               ` Wolfgang Denk
  0 siblings, 1 reply; 104+ messages in thread
From: Holger Brunck @ 2012-08-13  7:23 UTC (permalink / raw)
  To: u-boot

On 08/10/2012 08:08 PM, Wolfgang Denk wrote:
> In message <5024CC15.8010602@keymile.com> you wrote:
>>
>> due to the fact that Gerlando is in his vacations and has therefore only little
>> time to do updates here I propose the following. I could prepare a branch as you
>> suggested based on current denx master with this changeset. But where and how
>> should I push it to git.denx.de? Or will you prepare this branch?
> 
> I already did.
> 

is this branch public available? I don't find this branch on git.denx.de.

Regards
Holger

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-08-13  7:23             ` Holger Brunck
@ 2012-08-13 10:11               ` Wolfgang Denk
  2012-08-24 10:18                 ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Wolfgang Denk @ 2012-08-13 10:11 UTC (permalink / raw)
  To: u-boot

Dear Holger Brunck,

In message <5028AB80.5030803@keymile.com> you wrote:
>
> >> time to do updates here I propose the following. I could prepare a branch as you
> >> suggested based on current denx master with this changeset. But where and how
> >> should I push it to git.denx.de? Or will you prepare this branch?
> > 
> > I already did.
> 
> is this branch public available? I don't find this branch on git.denx.de.

Oops.  Please try again now.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"The value of marriage is not that adults produce children, but  that
children produce adults."                            - Peter De Vries

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default
  2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
                   ` (15 preceding siblings ...)
  2012-04-02 18:26 ` [U-Boot] [PATCH v3 6/6] env: delete selected vars not present in imported env Gerlando Falauto
@ 2012-08-24 10:11 ` Gerlando Falauto
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 1/7] env: cosmetic: drop assignment i = iomux_doenv() Gerlando Falauto
                     ` (7 more replies)
  16 siblings, 8 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:11 UTC (permalink / raw)
  To: u-boot

This patchset modifies the handling of all the operations on the environment
(set/import/default) so to unify handling of special variables.
On top of that we implement a selective "env default".

A selective "env import" would imply a user API change and should therefore
be discussed separately.

NOTE:
The entire patchset generates an increase in code size of about 1200 bytes
on a PowerPC target. 
As much as I would like to get rid of the set_default_vars() function in 
env_common.c, I have not found a nice way to do so.

Changes in the syntax (user API):
- "env default" -f: override write-once variables, -a means all
- display a warning when trying to set to default variables not
  present in the default env.

Changes from v3:
- rebased to current trunk (was not compilable)
- removed compiler warnings
- added an independent cosmetic patch on top of the series (from which only
  a later patch would actually benefit)

Changes from v2:
- removed typedef for callback, moved to the hashtable (struct hsearch_data)
- refactored patchset into smaller patches
  (only patch 5 and 6 should have any visible effect)
- added handling of selected variables not present in the imported env
- removed CONFIG_CMD_DEFAULTENV_VARS
- cosmetic formatting

Changes from v1:
- removed cosmetic patches (now mainstream)
- rebased to latest trunk
- removed subtle error in env_check_apply
  (comparing {loadaddr, bootfile} to values instead
  of variable names)
- changed env_check_apply so not to display warnings
  in case of H_FORCE flag being set

Changes from v0
- checkpatch cleanup
- removed himport_ex()
- removed warning for serial_assign()
- env import NOT implemented here

Gerlando Falauto (7):
  env: cosmetic: drop assignment i = iomux_doenv()
  env: unify logic to check and apply changes
  env: make himport_r() selective on variables
  env: add check/apply logic to himport_r()
  env: check and apply changes on delete/destroy
  env: make "env default" selective, check and apply
  env: delete selected vars not present in imported env

 common/cmd_nvedit.c   |  190 ++++++++++++++++++++++++++++++++++---------------
 common/env_common.c   |   36 +++++++++-
 include/environment.h |   12 ++++
 include/search.h      |   26 +++++--
 lib/hashtable.c       |   95 +++++++++++++++++++++++--
 5 files changed, 286 insertions(+), 73 deletions(-)

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 1/7] env: cosmetic: drop assignment i = iomux_doenv()
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
@ 2012-08-24 10:11   ` Gerlando Falauto
  2012-08-24 14:44     ` Marek Vasut
  2012-09-18 19:05     ` [U-Boot] [U-Boot, v4, " Tom Rini
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 2/7] env: unify logic to check and apply changes Gerlando Falauto
                     ` (6 subsequent siblings)
  7 siblings, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:11 UTC (permalink / raw)
  To: u-boot

iomux_doenv() can only return 0 or 1.
So there is no need to save its return value in variable i, as checking
its truth value within an if statement is enough.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index fd05e72..b8c7676 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -239,9 +239,8 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		}
 
 #ifdef CONFIG_CONSOLE_MUX
-		i = iomux_doenv(console, argv[2]);
-		if (i)
-			return i;
+		if (iomux_doenv(console, argv[2]))
+			return 1;
 #else
 		/* Try assigning specified device */
 		if (console_assign(console, argv[2]) < 0)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 2/7] env: unify logic to check and apply changes
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 1/7] env: cosmetic: drop assignment i = iomux_doenv() Gerlando Falauto
@ 2012-08-24 10:11   ` Gerlando Falauto
  2012-08-24 14:48     ` Marek Vasut
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 3/7] env: make himport_r() selective on variables Gerlando Falauto
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:11 UTC (permalink / raw)
  To: u-boot

The logic of checking special parameters (e.g. baudrate, stdin, stdout,
for a valid value and/or whether can be overwritten) and applying the
new value to the running system is now all within a single function
env_check_apply() which can be called whenever changes are made
to the environment, no matter if by set, default or import.

With this patch env_check_apply() is only called by "env set",
retaining previous behavior.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |  141 +++++++++++++++++++++++++++++++++------------------
 include/search.h    |    3 +-
 2 files changed, 94 insertions(+), 50 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index b8c7676..2f5dcbc 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -198,31 +198,19 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 #endif
 
 /*
- * Set a new environment variable,
- * or replace or delete an existing one.
+ * Perform consistency checking before setting, replacing, or deleting an
+ * environment variable, then (if successful) apply the changes to internals so
+ * to make them effective.  Code for this function was taken out of
+ * _do_env_set(), which now calls it instead.
+ * Returns 0 in case of success, 1 in case of failure.
+ * When (flag & H_FORCE) is set, do not print out any error message and force
+ * overwriting of write-once variables.
  */
-int _do_env_set(int flag, int argc, char * const argv[])
+
+int env_check_apply(const char *name, const char *oldval,
+			const char *newval, int flag)
 {
-	int   i, len;
 	int   console = -1;
-	char  *name, *value, *s;
-	ENTRY e, *ep;
-
-	name = argv[1];
-
-	if (strchr(name, '=')) {
-		printf("## Error: illegal character '=' in variable name"
-		       "\"%s\"\n", name);
-		return 1;
-	}
-
-	env_id++;
-	/*
-	 * search if variable with this name already exists
-	 */
-	e.key = name;
-	e.data = NULL;
-	hsearch_r(e, FIND, &ep, &env_htab);
 
 	/* Check for console redirection */
 	if (strcmp(name, "stdin") == 0)
@@ -233,59 +221,75 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		console = stderr;
 
 	if (console != -1) {
-		if (argc < 3) {		/* Cannot delete it! */
-			printf("Can't delete \"%s\"\n", name);
+		if ((newval == NULL) || (*newval == '\0')) {
+			/* We cannot delete stdin/stdout/stderr */
+			if ((flag & H_FORCE) == 0)
+				printf("Can't delete \"%s\"\n", name);
 			return 1;
 		}
 
 #ifdef CONFIG_CONSOLE_MUX
-		if (iomux_doenv(console, argv[2]))
+		if (iomux_doenv(console, newval))
 			return 1;
 #else
 		/* Try assigning specified device */
-		if (console_assign(console, argv[2]) < 0)
+		if (console_assign(console, newval) < 0)
 			return 1;
 
 #ifdef CONFIG_SERIAL_MULTI
-		if (serial_assign(argv[2]) < 0)
+		if (serial_assign(newval) < 0)
 			return 1;
 #endif
 #endif /* CONFIG_CONSOLE_MUX */
 	}
 
 	/*
-	 * Some variables like "ethaddr" and "serial#" can be set only
-	 * once and cannot be deleted; also, "ver" is readonly.
+	 * Some variables like "ethaddr" and "serial#" can be set only once and
+	 * cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined.
 	 */
-	if (ep) {		/* variable exists */
 #ifndef CONFIG_ENV_OVERWRITE
+	if (oldval != NULL &&			/* variable exists */
+		(flag & H_FORCE) == 0) {	/* and we are not forced */
 		if (strcmp(name, "serial#") == 0 ||
 		    (strcmp(name, "ethaddr") == 0
 #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
-		     && strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0
+		     && strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0
 #endif	/* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
 			)) {
 			printf("Can't overwrite \"%s\"\n", name);
 			return 1;
 		}
+	}
 #endif
+	/*
+	 * When we change baudrate, or we are doing an env default -a
+	 * (which will erase all variables prior to calling this),
+	 * we want the baudrate to actually change - for real.
+	 */
+	if (oldval != NULL ||			/* variable exists */
+		(flag & H_NOCLEAR) == 0) {	/* or env is clear */
 		/*
 		 * Switch to new baudrate if new baudrate is supported
 		 */
 		if (strcmp(name, "baudrate") == 0) {
-			int baudrate = simple_strtoul(argv[2], NULL, 10);
+			int baudrate = simple_strtoul(newval, NULL, 10);
 			int i;
 			for (i = 0; i < N_BAUDRATES; ++i) {
 				if (baudrate == baudrate_table[i])
 					break;
 			}
 			if (i == N_BAUDRATES) {
-				printf("## Baudrate %d bps not supported\n",
-					baudrate);
+				if ((flag & H_FORCE) == 0)
+					printf("## Baudrate %d bps not "
+						"supported\n", baudrate);
 				return 1;
 			}
+			if (gd->baudrate == baudrate) {
+				/* If unchanged, we just say it's OK */
+				return 0;
+			}
 			printf("## Switch baudrate to %d bps and"
-			       "press ENTER ...\n", baudrate);
+				"press ENTER ...\n", baudrate);
 			udelay(50000);
 			gd->baudrate = baudrate;
 #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2)
@@ -299,6 +303,59 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		}
 	}
 
+	/*
+	 * Some variables should be updated when the corresponding
+	 * entry in the environment is changed
+	 */
+	if (strcmp(name, "loadaddr") == 0) {
+		load_addr = simple_strtoul(newval, NULL, 16);
+		return 0;
+	}
+#if defined(CONFIG_CMD_NET)
+	else if (strcmp(name, "bootfile") == 0) {
+		copy_filename(BootFile, newval, sizeof(BootFile));
+		return 0;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Set a new environment variable,
+ * or replace or delete an existing one.
+*/
+int _do_env_set(int flag, int argc, char * const argv[])
+{
+	int   i, len;
+	char  *name, *value, *s;
+	ENTRY e, *ep;
+
+	name = argv[1];
+	value = argv[2];
+
+	if (strchr(name, '=')) {
+		printf("## Error: illegal character '='"
+		       "in variable name \"%s\"\n", name);
+		return 1;
+	}
+
+	env_id++;
+	/*
+	 * search if variable with this name already exists
+	 */
+	e.key = name;
+	e.data = NULL;
+	hsearch_r(e, FIND, &ep, &env_htab);
+
+	/*
+	 * Perform requested checks. Notice how since we are overwriting
+	 * a single variable, we need to set H_NOCLEAR
+	 */
+	if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) {
+		debug("check function did not approve, refusing\n");
+		return 1;
+	}
+
 	/* Delete only ? */
 	if (argc < 3 || argv[2] == NULL) {
 		int rc = hdelete_r(name, &env_htab);
@@ -336,20 +393,6 @@ int _do_env_set(int flag, int argc, char * const argv[])
 		return 1;
 	}
 
-	/*
-	 * Some variables should be updated when the corresponding
-	 * entry in the environment is changed
-	 */
-	if (strcmp(argv[1], "loadaddr") == 0) {
-		load_addr = simple_strtoul(argv[2], NULL, 16);
-		return 0;
-	}
-#if defined(CONFIG_CMD_NET)
-	else if (strcmp(argv[1], "bootfile") == 0) {
-		copy_filename(BootFile, argv[2], sizeof(BootFile));
-		return 0;
-	}
-#endif
 	return 0;
 }
 
diff --git a/include/search.h b/include/search.h
index ef53edb..a4a5ef4 100644
--- a/include/search.h
+++ b/include/search.h
@@ -99,6 +99,7 @@ extern int himport_r(struct hsearch_data *__htab,
 		     int __flag);
 
 /* Flags for himport_r() */
-#define	H_NOCLEAR	1	/* do not clear hash table before importing */
+#define	H_NOCLEAR	(1 << 0) /* do not clear hash table before importing */
+#define	H_FORCE		(1 << 1) /* overwrite read-only/write-once variables */
 
 #endif /* search.h */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 3/7] env: make himport_r() selective on variables
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 1/7] env: cosmetic: drop assignment i = iomux_doenv() Gerlando Falauto
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 2/7] env: unify logic to check and apply changes Gerlando Falauto
@ 2012-08-24 10:11   ` Gerlando Falauto
  2012-08-24 14:50     ` Marek Vasut
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 4/7] env: add check/apply logic to himport_r() Gerlando Falauto
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:11 UTC (permalink / raw)
  To: u-boot

Add 2 new arguments to himport_r():

 o "nvars", "vars": number and list of variables to take into account
   (0 means ALL)

NOTE: This patch does not change the current behaviour.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |    3 ++-
 common/env_common.c |    6 ++++--
 include/search.h    |    6 +++++-
 lib/hashtable.c     |   27 ++++++++++++++++++++++++++-
 4 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 2f5dcbc..493aecc 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -914,7 +914,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
 		addr = (char *)ep->data;
 	}
 
-	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
+	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
+			0, NULL) == 0) {
 		error("Environment import failed: errno = %d\n", errno);
 		return 1;
 	}
diff --git a/common/env_common.c b/common/env_common.c
index d9e990d..8f142ed 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -193,7 +193,8 @@ void set_default_env(const char *s)
 	}
 
 	if (himport_r(&env_htab, (char *)default_environment,
-			sizeof(default_environment), '\0', 0) == 0)
+			sizeof(default_environment), '\0', 0,
+			0, NULL) == 0)
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
@@ -218,7 +219,8 @@ int env_import(const char *buf, int check)
 		}
 	}
 
-	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
+	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
+			0, NULL)) {
 		gd->flags |= GD_FLG_ENV_READY;
 		return 1;
 	}
diff --git a/include/search.h b/include/search.h
index a4a5ef4..94d75fc 100644
--- a/include/search.h
+++ b/include/search.h
@@ -94,9 +94,13 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, char **__resp, size_t __size,
 		     int argc, char * const argv[]);
 
+/*
+ * nvars: length of vars array
+ * vars: array of strings (variable names) to import (nvars == 0 means all)
+ */
 extern int himport_r(struct hsearch_data *__htab,
 		     const char *__env, size_t __size, const char __sep,
-		     int __flag);
+		     int __flag, int nvars, char * const vars[]);
 
 /* Flags for himport_r() */
 #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before importing */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index abd61c8..0610e86 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -603,6 +603,24 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  * himport()
  */
 
+/* Check whether variable name is amongst vars[] */
+static int is_var_in_set(const char *name, int nvars, char * const vars[])
+{
+	int i = 0;
+
+	/* No variables specified means process all of them */
+	if (nvars == 0)
+		return 1;
+
+	for (i = 0; i < nvars; i++) {
+		if (!strcmp(name, vars[i]))
+			return 1;
+	}
+	debug("Skipping non-listed variable %s\n", name);
+
+	return 0;
+}
+
 /*
  * Import linearized data into hash table.
  *
@@ -639,7 +657,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  */
 
 int himport_r(struct hsearch_data *htab,
-	      const char *env, size_t size, const char sep, int flag)
+		const char *env, size_t size, const char sep, int flag,
+		int nvars, char * const vars[])
 {
 	char *data, *sp, *dp, *name, *value;
 
@@ -726,6 +745,8 @@ int himport_r(struct hsearch_data *htab,
 			*dp++ = '\0';	/* terminate name */
 
 			debug("DELETE CANDIDATE: \"%s\"\n", name);
+			if (!is_var_in_set(name, nvars, vars))
+				continue;
 
 			if (hdelete_r(name, htab) == 0)
 				debug("DELETE ERROR ##############################\n");
@@ -743,6 +764,10 @@ int himport_r(struct hsearch_data *htab,
 		*sp++ = '\0';	/* terminate value */
 		++dp;
 
+		/* Skip variables which are not supposed to be processed */
+		if (!is_var_in_set(name, nvars, vars))
+			continue;
+
 		/* enter into hash table */
 		e.key = name;
 		e.data = value;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 4/7] env: add check/apply logic to himport_r()
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
                     ` (2 preceding siblings ...)
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 3/7] env: make himport_r() selective on variables Gerlando Falauto
@ 2012-08-24 10:11   ` Gerlando Falauto
  2012-08-24 14:52     ` Marek Vasut
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 5/7] env: check and apply changes on delete/destroy Gerlando Falauto
                     ` (3 subsequent siblings)
  7 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:11 UTC (permalink / raw)
  To: u-boot

Change hashtable so that a callback function will decide whether a
variable can be overwritten, and possibly apply the changes.

So add a new field to struct hsearch_data:

 o "apply" callback function to check whether a variable can be
    overwritten, and possibly immediately apply the changes;
    when NULL, no check is performed.

And a new argument to himport_r():
 o "do_apply": whether to call the apply callback function

NOTE: This patch does not change the current behavior.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c   |    3 ++-
 common/env_common.c   |    8 +++++---
 include/environment.h |    9 +++++++++
 include/search.h      |   14 +++++++++++++-
 lib/hashtable.c       |   20 +++++++++++++++++++-
 5 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 493aecc..983e747 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -202,6 +202,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
  * environment variable, then (if successful) apply the changes to internals so
  * to make them effective.  Code for this function was taken out of
  * _do_env_set(), which now calls it instead.
+ * Also called as a callback function by himport_r().
  * Returns 0 in case of success, 1 in case of failure.
  * When (flag & H_FORCE) is set, do not print out any error message and force
  * overwriting of write-once variables.
@@ -915,7 +916,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
 	}
 
 	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
-			0, NULL) == 0) {
+			0, NULL, 0 /* do_apply */) == 0) {
 		error("Environment import failed: errno = %d\n", errno);
 		return 1;
 	}
diff --git a/common/env_common.c b/common/env_common.c
index 8f142ed..c6e7c4c 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -133,7 +133,9 @@ const uchar default_environment[] = {
 	"\0"
 };
 
-struct hsearch_data env_htab;
+struct hsearch_data env_htab = {
+	.apply = env_check_apply,
+};
 
 static uchar __env_get_char_spec(int index)
 {
@@ -194,7 +196,7 @@ void set_default_env(const char *s)
 
 	if (himport_r(&env_htab, (char *)default_environment,
 			sizeof(default_environment), '\0', 0,
-			0, NULL) == 0)
+			0, NULL, 0 /* do_apply */) == 0)
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
@@ -220,7 +222,7 @@ int env_import(const char *buf, int check)
 	}
 
 	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
-			0, NULL)) {
+			0, NULL, 0 /* do_apply */)) {
 		gd->flags |= GD_FLG_ENV_READY;
 		return 1;
 	}
diff --git a/include/environment.h b/include/environment.h
index ae3f7b6..90fb130 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -184,6 +184,15 @@ void set_default_env(const char *s);
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
+/*
+ * Check if variable "name" can be changed from oldval to newval,
+ * and if so, apply the changes (e.g. baudrate).
+ * When (flag & H_FORCE) is set, it does not print out any error
+ * message and forces overwriting of write-once variables.
+ */
+int env_check_apply(const char *name, const char *oldval,
+			const char *newval, int flag);
+
 #endif /* DO_DEPS_ONLY */
 
 #endif /* _ENVIRONMENT_H_ */
diff --git a/include/search.h b/include/search.h
index 94d75fc..721c8ac 100644
--- a/include/search.h
+++ b/include/search.h
@@ -57,6 +57,16 @@ struct hsearch_data {
 	struct _ENTRY *table;
 	unsigned int size;
 	unsigned int filled;
+/*
+ * Callback function which will check whether the given change for variable
+ * "name" from "oldval" to "newval" may be applied or not, and possibly apply
+ * such change.
+ * When (flag & H_FORCE) is set, it shall not print out any error message and
+ * shall force overwriting of write-once variables.
+.* Must return 0 for approval, 1 for denial.
+ */
+	int (*apply)(const char *name, const char *oldval,
+			const char *newval, int flag);
 };
 
 /* Create a new hashing table which will at most contain NEL elements.  */
@@ -97,10 +107,12 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
 /*
  * nvars: length of vars array
  * vars: array of strings (variable names) to import (nvars == 0 means all)
+ * do_apply: whether to call callback function to check the new argument,
+ * and possibly apply changes (false means accept everything)
  */
 extern int himport_r(struct hsearch_data *__htab,
 		     const char *__env, size_t __size, const char __sep,
-		     int __flag, int nvars, char * const vars[]);
+		     int __flag, int nvars, char * const vars[], int do_apply);
 
 /* Flags for himport_r() */
 #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before importing */
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 0610e86..6cfba56 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -658,7 +658,7 @@ static int is_var_in_set(const char *name, int nvars, char * const vars[])
 
 int himport_r(struct hsearch_data *htab,
 		const char *env, size_t size, const char sep, int flag,
-		int nvars, char * const vars[])
+		int nvars, char * const vars[], int do_apply)
 {
 	char *data, *sp, *dp, *name, *value;
 
@@ -772,6 +772,24 @@ int himport_r(struct hsearch_data *htab,
 		e.key = name;
 		e.data = value;
 
+		/* if there is an apply function, check what it has to say */
+		if (do_apply && htab->apply != NULL) {
+			debug("searching before calling cb function"
+				" for  %s\n", name);
+			/*
+			 * Search for variable in existing env, so to pass
+			 * its previous value to the apply callback
+			 */
+			hsearch_r(e, FIND, &rv, htab);
+			debug("previous value was %s\n", rv ? rv->data : "");
+			if (htab->apply(name, rv ? rv->data : NULL,
+				value, flag)) {
+				debug("callback function refused to set"
+					" variable %s, skipping it!\n", name);
+				continue;
+			}
+		}
+
 		hsearch_r(e, ENTER, &rv, htab);
 		if (rv == NULL) {
 			printf("himport_r: can't insert \"%s=%s\" into hash table\n",
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 5/7] env: check and apply changes on delete/destroy
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
                     ` (3 preceding siblings ...)
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 4/7] env: add check/apply logic to himport_r() Gerlando Falauto
@ 2012-08-24 10:11   ` Gerlando Falauto
  2012-08-24 14:53     ` Marek Vasut
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply Gerlando Falauto
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:11 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c |    2 +-
 include/search.h    |    5 +++--
 lib/hashtable.c     |   16 ++++++++++------
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 983e747..b0860f3 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -359,7 +359,7 @@ int _do_env_set(int flag, int argc, char * const argv[])
 
 	/* Delete only ? */
 	if (argc < 3 || argv[2] == NULL) {
-		int rc = hdelete_r(name, &env_htab);
+		int rc = hdelete_r(name, &env_htab, 0);
 		return !rc;
 	}
 
diff --git a/include/search.h b/include/search.h
index 721c8ac..93e1cbc 100644
--- a/include/search.h
+++ b/include/search.h
@@ -73,7 +73,7 @@ struct hsearch_data {
 extern int hcreate_r(size_t __nel, struct hsearch_data *__htab);
 
 /* Destroy current internal hashing table.  */
-extern void hdestroy_r(struct hsearch_data *__htab);
+extern void hdestroy_r(struct hsearch_data *__htab, int do_apply);
 
 /*
  * Search for entry matching ITEM.key in internal hash table.  If
@@ -98,7 +98,8 @@ extern int hstrstr_r(const char *__match, int __last_idx, ENTRY ** __retval,
 		    struct hsearch_data *__htab);
 
 /* Search and delete entry matching ITEM.key in internal hash table. */
-extern int hdelete_r(const char *__key, struct hsearch_data *__htab);
+extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
+			int do_apply);
 
 extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, char **__resp, size_t __size,
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 6cfba56..f3f47de 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -142,7 +142,7 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)
  * be freed and the local static variable can be marked as not used.
  */
 
-void hdestroy_r(struct hsearch_data *htab)
+void hdestroy_r(struct hsearch_data *htab, int do_apply)
 {
 	int i;
 
@@ -156,7 +156,10 @@ void hdestroy_r(struct hsearch_data *htab)
 	for (i = 1; i <= htab->size; ++i) {
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-
+			if (do_apply && htab->apply != NULL) {
+				/* deletion is always forced */
+				htab->apply(ep->key, ep->data, NULL, H_FORCE);
+			}
 			free((void *)ep->key);
 			free(ep->data);
 		}
@@ -401,7 +404,7 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
  * do that.
  */
 
-int hdelete_r(const char *key, struct hsearch_data *htab)
+int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)
 {
 	ENTRY e, *ep;
 	int idx;
@@ -417,7 +420,8 @@ int hdelete_r(const char *key, struct hsearch_data *htab)
 
 	/* free used ENTRY */
 	debug("hdelete: DELETING key \"%s\"\n", key);
-
+	if (do_apply && htab->apply != NULL)
+		htab->apply(ep->key, ep->data, NULL, H_FORCE);
 	free((void *)ep->key);
 	free(ep->data);
 	htab->table[idx].used = -1;
@@ -682,7 +686,7 @@ int himport_r(struct hsearch_data *htab,
 		debug("Destroy Hash Table: %p table = %p\n", htab,
 		       htab->table);
 		if (htab->table)
-			hdestroy_r(htab);
+			hdestroy_r(htab, do_apply);
 	}
 
 	/*
@@ -748,7 +752,7 @@ int himport_r(struct hsearch_data *htab,
 			if (!is_var_in_set(name, nvars, vars))
 				continue;
 
-			if (hdelete_r(name, htab) == 0)
+			if (hdelete_r(name, htab, do_apply) == 0)
 				debug("DELETE ERROR ##############################\n");
 
 			continue;
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
                     ` (4 preceding siblings ...)
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 5/7] env: check and apply changes on delete/destroy Gerlando Falauto
@ 2012-08-24 10:11   ` Gerlando Falauto
  2012-08-24 14:56     ` Marek Vasut
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env Gerlando Falauto
  2012-09-02 11:59   ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Wolfgang Denk
  7 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:11 UTC (permalink / raw)
  To: u-boot

Change the syntax (user API) for "env default":
  -f: override write-once variables
  var... : accept individual variable(s)
  -a: all (resetting the whole env is NOT the default behavior)

Enable variable checking and make changes effective by
enabling do_apply argument to himport_r().

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 common/cmd_nvedit.c   |   40 ++++++++++++++++++++++++++++++++++------
 common/env_common.c   |   28 +++++++++++++++++++++++++++-
 include/environment.h |    3 +++
 3 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index b0860f3..ac2b985 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -656,14 +656,41 @@ int envmatch(uchar *s1, int i2)
 	return -1;
 }
 
-static int do_env_default(cmd_tbl_t *cmdtp, int flag,
+static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
 			  int argc, char * const argv[])
 {
-	if (argc != 2 || strcmp(argv[1], "-f") != 0)
-		return CMD_RET_USAGE;
+	int all = 0, flag = 0;
 
-	set_default_env("## Resetting to default environment\n");
-	return 0;
+	debug("Initial value for argc=%d\n", argc);
+	while (--argc > 0 && **++argv == '-') {
+		char *arg = *argv;
+
+		while (*++arg) {
+			switch (*arg) {
+			case 'a':		/* default all */
+				all = 1;
+				break;
+			case 'f':		/* force */
+				flag |= H_FORCE;
+				break;
+			default:
+				return cmd_usage(cmdtp);
+			}
+		}
+	}
+	debug("Final value for argc=%d\n", argc);
+	if (all && (argc == 0)) {
+		/* Reset the whole environment */
+		set_default_env("## Resetting to default environment\n");
+		return 0;
+	}
+	if (!all && (argc > 0)) {
+		/* Reset individual variables */
+		set_default_vars(argc, argv);
+		return 0;
+	}
+
+	return cmd_usage(cmdtp);
 }
 
 static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
@@ -994,7 +1021,8 @@ U_BOOT_CMD(
 #if defined(CONFIG_CMD_ASKENV)
 	"ask name [message] [size] - ask for environment variable\nenv "
 #endif
-	"default -f - reset default environment\n"
+	"default [-f] -a - [forcibly] reset default environment\n"
+	"env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n"
 #if defined(CONFIG_CMD_EDITENV)
 	"env edit name - edit environment variable\n"
 #endif
diff --git a/common/env_common.c b/common/env_common.c
index c6e7c4c..482d715 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -177,6 +177,11 @@ const uchar *env_get_addr(int index)
 
 void set_default_env(const char *s)
 {
+	/*
+	 * By default, do not apply changes as they will eventually
+	 * be applied by someone else
+	 */
+	int do_apply = 0;
 	if (sizeof(default_environment) > ENV_SIZE) {
 		puts("*** Error - default environment is too large\n\n");
 		return;
@@ -188,6 +193,14 @@ void set_default_env(const char *s)
 				"using default environment\n\n",
 				s + 1);
 		} else {
+			/*
+			 * This set_to_default was explicitly asked for
+			 * by the user, as opposed to being a recovery
+			 * mechanism.  Therefore we check every single
+			 * variable and apply changes to the system
+			 * right away (e.g. baudrate, console).
+			 */
+			do_apply = 1;
 			puts(s);
 		}
 	} else {
@@ -196,12 +209,25 @@ void set_default_env(const char *s)
 
 	if (himport_r(&env_htab, (char *)default_environment,
 			sizeof(default_environment), '\0', 0,
-			0, NULL, 0 /* do_apply */) == 0)
+			0, NULL, do_apply) == 0)
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
 }
 
+
+/* [re]set individual variables to their value in the default environment */
+int set_default_vars(int nvars, char * const vars[])
+{
+	/*
+	 * Special use-case: import from default environment
+	 * (and use \0 as a separator)
+	 */
+	return himport_r(&env_htab, (const char *)default_environment,
+				sizeof(default_environment), '\0', H_NOCLEAR,
+				nvars, vars, 1 /* do_apply */);
+}
+
 /*
  * Check if CRC is valid and (if yes) import the environment.
  * Note that "buf" may or may not be aligned.
diff --git a/include/environment.h b/include/environment.h
index 90fb130..e8ab703 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -181,6 +181,9 @@ void env_crc_update(void);
 /* [re]set to the default environment */
 void set_default_env(const char *s);
 
+/* [re]set individual variables to their value in the default environment */
+int set_default_vars(int nvars, char * const vars[]);
+
 /* Import from binary representation into hash table */
 int env_import(const char *buf, int check);
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
                     ` (5 preceding siblings ...)
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply Gerlando Falauto
@ 2012-08-24 10:11   ` Gerlando Falauto
  2012-08-24 14:58     ` Marek Vasut
  2012-08-27  7:53     ` [U-Boot] [PATCH v5 " Gerlando Falauto
  2012-09-02 11:59   ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Wolfgang Denk
  7 siblings, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:11 UTC (permalink / raw)
  To: u-boot

When variables explicitly specified on the command line are not present
in the imported env, delete them from the running env.
If the variable is also missing from the running env, issue a warning.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
 lib/hashtable.c |   48 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 41 insertions(+), 7 deletions(-)

diff --git a/lib/hashtable.c b/lib/hashtable.c
index f3f47de..b3d0b64 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  * himport()
  */
 
-/* Check whether variable name is amongst vars[] */
-static int is_var_in_set(const char *name, int nvars, char * const vars[])
+/*
+ * Check whether variable 'name' is amongst vars[],
+ * and remove all instances by setting the pointer to NULL
+ */
+static int is_var_in_set(const char *name, int nvars, char * vars[])
 {
 	int i = 0;
+	int res = 0;
 
 	/* No variables specified means process all of them */
 	if (nvars == 0)
 		return 1;
 
 	for (i = 0; i < nvars; i++) {
-		if (!strcmp(name, vars[i]))
-			return 1;
+		if (vars[i] == NULL)
+			continue;
+		/* If we found it, delete all of them */
+		if (!strcmp(name, vars[i])) {
+			vars[i] = NULL;
+			res = 1;
+		}
 	}
-	debug("Skipping non-listed variable %s\n", name);
+	if (!res)
+		debug("Skipping non-listed variable %s\n", name);
 
-	return 0;
+	return res;
 }
 
 /*
@@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int nvars, char * const vars[])
 
 int himport_r(struct hsearch_data *htab,
 		const char *env, size_t size, const char sep, int flag,
-		int nvars, char * const vars[], int do_apply)
+		int nvars, char * const __vars[], int do_apply)
 {
 	char *data, *sp, *dp, *name, *value;
+	char *vars[nvars];
+	int i;
 
 	/* Test for correct arguments.  */
 	if (htab == NULL) {
@@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
 	memcpy(data, env, size);
 	dp = data;
 
+	/* make a local copy of the list of variables */
+	if (nvars)
+		memcpy(vars, __vars, sizeof(__vars[0]) * nvars);
+
 	if ((flag & H_NOCLEAR) == 0) {
 		/* Destroy old hash table if one exists */
 		debug("Destroy Hash Table: %p table = %p\n", htab,
@@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
 	debug("INSERT: free(data = %p)\n", data);
 	free(data);
 
+	/* process variables which were not considered */
+	for (i = 0; i < nvars; i++) {
+		if (vars[i] == NULL)
+			continue;
+		/*
+		 * All variables which were not deleted from the variable list
+		 * were not present in the imported env
+		 * This could mean two things:
+		 * a) if the variable was present in current env, we delete it
+		 * b) if the variable was not present in current env, we notify
+		 *    it might be a typo
+		 */
+		if (hdelete_r(vars[i], htab, do_apply) == 0)
+			printf("WARNING: '%s' neither in running nor in imported env!\n", vars[i]);
+		else
+			printf("WARNING: '%s' not in imported env, deleting it!\n", vars[i]);
+	}
+
 	debug("INSERT: done\n");
 	return 1;		/* everything OK */
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-08-13 10:11               ` Wolfgang Denk
@ 2012-08-24 10:18                 ` Gerlando Falauto
  2012-08-24 15:11                   ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 10:18 UTC (permalink / raw)
  To: u-boot

On 08/13/2012 12:11 PM, Wolfgang Denk wrote:
> Dear Holger Brunck,
>
> In message<5028AB80.5030803@keymile.com>  you wrote:
>>
>>>> time to do updates here I propose the following. I could prepare a branch as you
>>>> suggested based on current denx master with this changeset. But where and how
>>>> should I push it to git.denx.de? Or will you prepare this branch?
>>>
>>> I already did.
>>
>> is this branch public available? I don't find this branch on git.denx.de.
>
> Oops.  Please try again now.

Actually, the branch does not currently compile due to some changes to 
the trunk introduced in the meantime. So I am sending a new v4 patch 
series based on the current master. Please note that the first patch of 
the new series is cosmetic only and independent from all others.

Thanks,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 1/7] env: cosmetic: drop assignment i = iomux_doenv()
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 1/7] env: cosmetic: drop assignment i = iomux_doenv() Gerlando Falauto
@ 2012-08-24 14:44     ` Marek Vasut
  2012-09-18 19:05     ` [U-Boot] [U-Boot, v4, " Tom Rini
  1 sibling, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 14:44 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> iomux_doenv() can only return 0 or 1.
> So there is no need to save its return value in variable i, as checking
> its truth value within an if statement is enough.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

Reviewed-by: Marek Vasut <marex@denx.de>

> ---
>  common/cmd_nvedit.c |    5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index fd05e72..b8c7676 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -239,9 +239,8 @@ int _do_env_set(int flag, int argc, char * const
> argv[]) }
> 
>  #ifdef CONFIG_CONSOLE_MUX
> -		i = iomux_doenv(console, argv[2]);
> -		if (i)
> -			return i;
> +		if (iomux_doenv(console, argv[2]))
> +			return 1;
>  #else
>  		/* Try assigning specified device */
>  		if (console_assign(console, argv[2]) < 0)

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 2/7] env: unify logic to check and apply changes
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 2/7] env: unify logic to check and apply changes Gerlando Falauto
@ 2012-08-24 14:48     ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 14:48 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> The logic of checking special parameters (e.g. baudrate, stdin, stdout,
> for a valid value and/or whether can be overwritten) and applying the
> new value to the running system is now all within a single function
> env_check_apply() which can be called whenever changes are made
> to the environment, no matter if by set, default or import.
> 
> With this patch env_check_apply() is only called by "env set",
> retaining previous behavior.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
[...]

Reviewed-by: Marek Vasut <marex@denx.de>

but whew, you're giving me a tough time here with such change :-) At least now I 
see how env works ;-)

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 3/7] env: make himport_r() selective on variables
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 3/7] env: make himport_r() selective on variables Gerlando Falauto
@ 2012-08-24 14:50     ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 14:50 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Add 2 new arguments to himport_r():
> 
>  o "nvars", "vars": number and list of variables to take into account
>    (0 means ALL)
> 
> NOTE: This patch does not change the current behaviour.

Reviewed-by: Marek Vasut <marex@denx.de>

> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/cmd_nvedit.c |    3 ++-
>  common/env_common.c |    6 ++++--
>  include/search.h    |    6 +++++-
>  lib/hashtable.c     |   27 ++++++++++++++++++++++++++-
>  4 files changed, 37 insertions(+), 5 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 2f5dcbc..493aecc 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -914,7 +914,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
>  		addr = (char *)ep->data;
>  	}
> 
> -	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) {
> +	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
> +			0, NULL) == 0) {
>  		error("Environment import failed: errno = %d\n", errno);
>  		return 1;
>  	}
> diff --git a/common/env_common.c b/common/env_common.c
> index d9e990d..8f142ed 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -193,7 +193,8 @@ void set_default_env(const char *s)
>  	}
> 
>  	if (himport_r(&env_htab, (char *)default_environment,
> -			sizeof(default_environment), '\0', 0) == 0)
> +			sizeof(default_environment), '\0', 0,
> +			0, NULL) == 0)
>  		error("Environment import failed: errno = %d\n", errno);
> 
>  	gd->flags |= GD_FLG_ENV_READY;
> @@ -218,7 +219,8 @@ int env_import(const char *buf, int check)
>  		}
>  	}
> 
> -	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) {
> +	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
> +			0, NULL)) {
>  		gd->flags |= GD_FLG_ENV_READY;
>  		return 1;
>  	}
> diff --git a/include/search.h b/include/search.h
> index a4a5ef4..94d75fc 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -94,9 +94,13 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
>  		     const char __sep, char **__resp, size_t __size,
>  		     int argc, char * const argv[]);
> 
> +/*
> + * nvars: length of vars array
> + * vars: array of strings (variable names) to import (nvars == 0 means
> all) + */
>  extern int himport_r(struct hsearch_data *__htab,
>  		     const char *__env, size_t __size, const char __sep,
> -		     int __flag);
> +		     int __flag, int nvars, char * const vars[]);
> 
>  /* Flags for himport_r() */
>  #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before 
importing */
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index abd61c8..0610e86 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -603,6 +603,24 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> char sep, * himport()
>   */
> 
> +/* Check whether variable name is amongst vars[] */
> +static int is_var_in_set(const char *name, int nvars, char * const vars[])
> +{
> +	int i = 0;
> +
> +	/* No variables specified means process all of them */
> +	if (nvars == 0)
> +		return 1;
> +
> +	for (i = 0; i < nvars; i++) {
> +		if (!strcmp(name, vars[i]))
> +			return 1;
> +	}
> +	debug("Skipping non-listed variable %s\n", name);
> +
> +	return 0;
> +}
> +
>  /*
>   * Import linearized data into hash table.
>   *
> @@ -639,7 +657,8 @@ ssize_t hexport_r(struct hsearch_data *htab, const char
> sep, */
> 
>  int himport_r(struct hsearch_data *htab,
> -	      const char *env, size_t size, const char sep, int flag)
> +		const char *env, size_t size, const char sep, int flag,
> +		int nvars, char * const vars[])
>  {
>  	char *data, *sp, *dp, *name, *value;
> 
> @@ -726,6 +745,8 @@ int himport_r(struct hsearch_data *htab,
>  			*dp++ = '\0';	/* terminate name */
> 
>  			debug("DELETE CANDIDATE: \"%s\"\n", name);
> +			if (!is_var_in_set(name, nvars, vars))
> +				continue;
> 
>  			if (hdelete_r(name, htab) == 0)
>  				debug("DELETE ERROR 
##############################\n");
> @@ -743,6 +764,10 @@ int himport_r(struct hsearch_data *htab,
>  		*sp++ = '\0';	/* terminate value */
>  		++dp;
> 
> +		/* Skip variables which are not supposed to be processed */
> +		if (!is_var_in_set(name, nvars, vars))
> +			continue;
> +
>  		/* enter into hash table */
>  		e.key = name;
>  		e.data = value;

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 4/7] env: add check/apply logic to himport_r()
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 4/7] env: add check/apply logic to himport_r() Gerlando Falauto
@ 2012-08-24 14:52     ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 14:52 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Change hashtable so that a callback function will decide whether a
> variable can be overwritten, and possibly apply the changes.
> 
> So add a new field to struct hsearch_data:
> 
>  o "apply" callback function to check whether a variable can be
>     overwritten, and possibly immediately apply the changes;
>     when NULL, no check is performed.
> 
> And a new argument to himport_r():
>  o "do_apply": whether to call the apply callback function
> 
> NOTE: This patch does not change the current behavior.

Reviewed-by: Marek Vasut <marex@denx.de>

> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/cmd_nvedit.c   |    3 ++-
>  common/env_common.c   |    8 +++++---
>  include/environment.h |    9 +++++++++
>  include/search.h      |   14 +++++++++++++-
>  lib/hashtable.c       |   20 +++++++++++++++++++-
>  5 files changed, 48 insertions(+), 6 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index 493aecc..983e747 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -202,6 +202,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
>   * environment variable, then (if successful) apply the changes to
> internals so * to make them effective.  Code for this function was taken
> out of * _do_env_set(), which now calls it instead.
> + * Also called as a callback function by himport_r().
>   * Returns 0 in case of success, 1 in case of failure.
>   * When (flag & H_FORCE) is set, do not print out any error message and
> force * overwriting of write-once variables.
> @@ -915,7 +916,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
>  	}
> 
>  	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR,
> -			0, NULL) == 0) {
> +			0, NULL, 0 /* do_apply */) == 0) {
>  		error("Environment import failed: errno = %d\n", errno);
>  		return 1;
>  	}
> diff --git a/common/env_common.c b/common/env_common.c
> index 8f142ed..c6e7c4c 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -133,7 +133,9 @@ const uchar default_environment[] = {
>  	"\0"
>  };
> 
> -struct hsearch_data env_htab;
> +struct hsearch_data env_htab = {
> +	.apply = env_check_apply,
> +};
> 
>  static uchar __env_get_char_spec(int index)
>  {
> @@ -194,7 +196,7 @@ void set_default_env(const char *s)
> 
>  	if (himport_r(&env_htab, (char *)default_environment,
>  			sizeof(default_environment), '\0', 0,
> -			0, NULL) == 0)
> +			0, NULL, 0 /* do_apply */) == 0)
>  		error("Environment import failed: errno = %d\n", errno);
> 
>  	gd->flags |= GD_FLG_ENV_READY;
> @@ -220,7 +222,7 @@ int env_import(const char *buf, int check)
>  	}
> 
>  	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
> -			0, NULL)) {
> +			0, NULL, 0 /* do_apply */)) {
>  		gd->flags |= GD_FLG_ENV_READY;
>  		return 1;
>  	}
> diff --git a/include/environment.h b/include/environment.h
> index ae3f7b6..90fb130 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -184,6 +184,15 @@ void set_default_env(const char *s);
>  /* Import from binary representation into hash table */
>  int env_import(const char *buf, int check);
> 
> +/*
> + * Check if variable "name" can be changed from oldval to newval,
> + * and if so, apply the changes (e.g. baudrate).
> + * When (flag & H_FORCE) is set, it does not print out any error
> + * message and forces overwriting of write-once variables.
> + */
> +int env_check_apply(const char *name, const char *oldval,
> +			const char *newval, int flag);
> +
>  #endif /* DO_DEPS_ONLY */
> 
>  #endif /* _ENVIRONMENT_H_ */
> diff --git a/include/search.h b/include/search.h
> index 94d75fc..721c8ac 100644
> --- a/include/search.h
> +++ b/include/search.h
> @@ -57,6 +57,16 @@ struct hsearch_data {
>  	struct _ENTRY *table;
>  	unsigned int size;
>  	unsigned int filled;
> +/*
> + * Callback function which will check whether the given change for
> variable + * "name" from "oldval" to "newval" may be applied or not, and
> possibly apply + * such change.
> + * When (flag & H_FORCE) is set, it shall not print out any error message
> and + * shall force overwriting of write-once variables.
> +.* Must return 0 for approval, 1 for denial.
> + */
> +	int (*apply)(const char *name, const char *oldval,
> +			const char *newval, int flag);
>  };
> 
>  /* Create a new hashing table which will at most contain NEL elements.  */
> @@ -97,10 +107,12 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,
>  /*
>   * nvars: length of vars array
>   * vars: array of strings (variable names) to import (nvars == 0 means
> all) + * do_apply: whether to call callback function to check the new
> argument, + * and possibly apply changes (false means accept everything)
>   */
>  extern int himport_r(struct hsearch_data *__htab,
>  		     const char *__env, size_t __size, const char __sep,
> -		     int __flag, int nvars, char * const vars[]);
> +		     int __flag, int nvars, char * const vars[], int do_apply);
> 
>  /* Flags for himport_r() */
>  #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before 
importing */
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index 0610e86..6cfba56 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -658,7 +658,7 @@ static int is_var_in_set(const char *name, int nvars,
> char * const vars[])
> 
>  int himport_r(struct hsearch_data *htab,
>  		const char *env, size_t size, const char sep, int flag,
> -		int nvars, char * const vars[])
> +		int nvars, char * const vars[], int do_apply)
>  {
>  	char *data, *sp, *dp, *name, *value;
> 
> @@ -772,6 +772,24 @@ int himport_r(struct hsearch_data *htab,
>  		e.key = name;
>  		e.data = value;
> 
> +		/* if there is an apply function, check what it has to say */
> +		if (do_apply && htab->apply != NULL) {
> +			debug("searching before calling cb function"
> +				" for  %s\n", name);
> +			/*
> +			 * Search for variable in existing env, so to pass
> +			 * its previous value to the apply callback
> +			 */
> +			hsearch_r(e, FIND, &rv, htab);
> +			debug("previous value was %s\n", rv ? rv->data : "");
> +			if (htab->apply(name, rv ? rv->data : NULL,
> +				value, flag)) {
> +				debug("callback function refused to set"
> +					" variable %s, skipping it!\n", name);
> +				continue;
> +			}
> +		}
> +
>  		hsearch_r(e, ENTER, &rv, htab);
>  		if (rv == NULL) {
>  			printf("himport_r: can't insert \"%s=%s\" into hash 
table\n",

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 5/7] env: check and apply changes on delete/destroy
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 5/7] env: check and apply changes on delete/destroy Gerlando Falauto
@ 2012-08-24 14:53     ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 14:53 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/cmd_nvedit.c |    2 +-
>  include/search.h    |    5 +++--
>  lib/hashtable.c     |   16 ++++++++++------
>  3 files changed, 14 insertions(+), 9 deletions(-)
> 
[...]

Reviewed-by: Marek Vasut <marex@denx.de>

but I'm starting to get a bit lost around this time ;-)

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply Gerlando Falauto
@ 2012-08-24 14:56     ` Marek Vasut
  2012-08-24 15:10       ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 14:56 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> Change the syntax (user API) for "env default":
>   -f: override write-once variables
>   var... : accept individual variable(s)
>   -a: all (resetting the whole env is NOT the default behavior)
> 
> Enable variable checking and make changes effective by
> enabling do_apply argument to himport_r().
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> ---
>  common/cmd_nvedit.c   |   40 ++++++++++++++++++++++++++++++++++------
>  common/env_common.c   |   28 +++++++++++++++++++++++++++-
>  include/environment.h |    3 +++
>  3 files changed, 64 insertions(+), 7 deletions(-)
> 
> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> index b0860f3..ac2b985 100644
> --- a/common/cmd_nvedit.c
> +++ b/common/cmd_nvedit.c
> @@ -656,14 +656,41 @@ int envmatch(uchar *s1, int i2)
>  	return -1;
>  }
> 
> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
>  			  int argc, char * const argv[])
>  {
> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
> -		return CMD_RET_USAGE;
> +	int all = 0, flag = 0;
> 
> -	set_default_env("## Resetting to default environment\n");
> -	return 0;
> +	debug("Initial value for argc=%d\n", argc);
> +	while (--argc > 0 && **++argv == '-') {

mmmmm ... **++argv, yummy :) This might use some cleanup, to make more readable. 
Don't we have some getopt or something too ?

> +		char *arg = *argv;
> +
> +		while (*++arg) {
> +			switch (*arg) {
> +			case 'a':		/* default all */
> +				all = 1;
> +				break;
> +			case 'f':		/* force */
> +				flag |= H_FORCE;
> +				break;
> +			default:
> +				return cmd_usage(cmdtp);
> +			}
> +		}
> +	}
> +	debug("Final value for argc=%d\n", argc);
> +	if (all && (argc == 0)) {
> +		/* Reset the whole environment */
> +		set_default_env("## Resetting to default environment\n");
> +		return 0;
> +	}
> +	if (!all && (argc > 0)) {
> +		/* Reset individual variables */
> +		set_default_vars(argc, argv);
> +		return 0;
> +	}
> +
> +	return cmd_usage(cmdtp);
>  }
> 
>  static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
> @@ -994,7 +1021,8 @@ U_BOOT_CMD(
>  #if defined(CONFIG_CMD_ASKENV)
>  	"ask name [message] [size] - ask for environment variable\nenv "
>  #endif
> -	"default -f - reset default environment\n"
> +	"default [-f] -a - [forcibly] reset default environment\n"
> +	"env default [-f] var [...] - [forcibly] reset variable(s) to their
> default values\n" #if defined(CONFIG_CMD_EDITENV)
>  	"env edit name - edit environment variable\n"
>  #endif
> diff --git a/common/env_common.c b/common/env_common.c
> index c6e7c4c..482d715 100644
> --- a/common/env_common.c
> +++ b/common/env_common.c
> @@ -177,6 +177,11 @@ const uchar *env_get_addr(int index)
> 
>  void set_default_env(const char *s)
>  {
> +	/*
> +	 * By default, do not apply changes as they will eventually
> +	 * be applied by someone else
> +	 */
> +	int do_apply = 0;
>  	if (sizeof(default_environment) > ENV_SIZE) {
>  		puts("*** Error - default environment is too large\n\n");
>  		return;
> @@ -188,6 +193,14 @@ void set_default_env(const char *s)
>  				"using default environment\n\n",
>  				s + 1);
>  		} else {
> +			/*
> +			 * This set_to_default was explicitly asked for
> +			 * by the user, as opposed to being a recovery
> +			 * mechanism.  Therefore we check every single
> +			 * variable and apply changes to the system
> +			 * right away (e.g. baudrate, console).
> +			 */
> +			do_apply = 1;
>  			puts(s);
>  		}
>  	} else {
> @@ -196,12 +209,25 @@ void set_default_env(const char *s)
> 
>  	if (himport_r(&env_htab, (char *)default_environment,
>  			sizeof(default_environment), '\0', 0,
> -			0, NULL, 0 /* do_apply */) == 0)
> +			0, NULL, do_apply) == 0)
>  		error("Environment import failed: errno = %d\n", errno);
> 
>  	gd->flags |= GD_FLG_ENV_READY;
>  }
> 
> +
> +/* [re]set individual variables to their value in the default environment
> */ +int set_default_vars(int nvars, char * const vars[])
> +{
> +	/*
> +	 * Special use-case: import from default environment
> +	 * (and use \0 as a separator)
> +	 */
> +	return himport_r(&env_htab, (const char *)default_environment,
> +				sizeof(default_environment), '\0', H_NOCLEAR,
> +				nvars, vars, 1 /* do_apply */);
> +}
> +
>  /*
>   * Check if CRC is valid and (if yes) import the environment.
>   * Note that "buf" may or may not be aligned.
> diff --git a/include/environment.h b/include/environment.h
> index 90fb130..e8ab703 100644
> --- a/include/environment.h
> +++ b/include/environment.h
> @@ -181,6 +181,9 @@ void env_crc_update(void);
>  /* [re]set to the default environment */
>  void set_default_env(const char *s);
> 
> +/* [re]set individual variables to their value in the default environment
> */ +int set_default_vars(int nvars, char * const vars[]);
> +
>  /* Import from binary representation into hash table */
>  int env_import(const char *buf, int check);

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env Gerlando Falauto
@ 2012-08-24 14:58     ` Marek Vasut
  2012-08-24 15:16       ` Gerlando Falauto
  2012-08-27  7:53     ` [U-Boot] [PATCH v5 " Gerlando Falauto
  1 sibling, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 14:58 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> When variables explicitly specified on the command line are not present
> in the imported env, delete them from the running env.
> If the variable is also missing from the running env, issue a warning.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

Whew! I made it through ... it wasn't that scary in the end ;-)

> ---
>  lib/hashtable.c |   48 +++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 41 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index f3f47de..b3d0b64 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> char sep, * himport()
>   */
> 
> -/* Check whether variable name is amongst vars[] */
> -static int is_var_in_set(const char *name, int nvars, char * const vars[])
> +/*
> + * Check whether variable 'name' is amongst vars[],
> + * and remove all instances by setting the pointer to NULL
> + */
> +static int is_var_in_set(const char *name, int nvars, char * vars[])
>  {
>  	int i = 0;
> +	int res = 0;
> 
>  	/* No variables specified means process all of them */
>  	if (nvars == 0)
>  		return 1;
> 
>  	for (i = 0; i < nvars; i++) {
> -		if (!strcmp(name, vars[i]))
> -			return 1;
> +		if (vars[i] == NULL)
> +			continue;
> +		/* If we found it, delete all of them */
> +		if (!strcmp(name, vars[i])) {
> +			vars[i] = NULL;
> +			res = 1;

break here ?

> +		}
>  	}
> -	debug("Skipping non-listed variable %s\n", name);
> +	if (!res)
> +		debug("Skipping non-listed variable %s\n", name);
> 
> -	return 0;
> +	return res;
>  }
> 
>  /*
> @@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int nvars,
> char * const vars[])
> 
>  int himport_r(struct hsearch_data *htab,
>  		const char *env, size_t size, const char sep, int flag,
> -		int nvars, char * const vars[], int do_apply)
> +		int nvars, char * const __vars[], int do_apply)

Two underscores are reserved, use something else ;-)

>  {
>  	char *data, *sp, *dp, *name, *value;
> +	char *vars[nvars];
> +	int i;
> 
>  	/* Test for correct arguments.  */
>  	if (htab == NULL) {
> @@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
>  	memcpy(data, env, size);
>  	dp = data;
> 
> +	/* make a local copy of the list of variables */
> +	if (nvars)
> +		memcpy(vars, __vars, sizeof(__vars[0]) * nvars);
> +
>  	if ((flag & H_NOCLEAR) == 0) {
>  		/* Destroy old hash table if one exists */
>  		debug("Destroy Hash Table: %p table = %p\n", htab,
> @@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
>  	debug("INSERT: free(data = %p)\n", data);
>  	free(data);
> 
> +	/* process variables which were not considered */
> +	for (i = 0; i < nvars; i++) {
> +		if (vars[i] == NULL)
> +			continue;
> +		/*
> +		 * All variables which were not deleted from the variable list
> +		 * were not present in the imported env
> +		 * This could mean two things:
> +		 * a) if the variable was present in current env, we delete it
> +		 * b) if the variable was not present in current env, we notify
> +		 *    it might be a typo
> +		 */
> +		if (hdelete_r(vars[i], htab, do_apply) == 0)
> +			printf("WARNING: '%s' neither in running nor in imported 
env!\n",
> vars[i]); +		else
> +			printf("WARNING: '%s' not in imported env, deleting it!
\n", vars[i]);
> +	}
> +
>  	debug("INSERT: done\n");
>  	return 1;		/* everything OK */
>  }

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply
  2012-08-24 14:56     ` Marek Vasut
@ 2012-08-24 15:10       ` Gerlando Falauto
  2012-08-24 21:10         ` Marek Vasut
  0 siblings, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 15:10 UTC (permalink / raw)
  To: u-boot

On 08/24/2012 04:56 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> Change the syntax (user API) for "env default":
>>    -f: override write-once variables
>>    var... : accept individual variable(s)
>>    -a: all (resetting the whole env is NOT the default behavior)
>>
>> Enable variable checking and make changes effective by
>> enabling do_apply argument to himport_r().
>>
>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>> ---
>>   common/cmd_nvedit.c   |   40 ++++++++++++++++++++++++++++++++++------
>>   common/env_common.c   |   28 +++++++++++++++++++++++++++-
>>   include/environment.h |    3 +++
>>   3 files changed, 64 insertions(+), 7 deletions(-)
>>
>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
>> index b0860f3..ac2b985 100644
>> --- a/common/cmd_nvedit.c
>> +++ b/common/cmd_nvedit.c
>> @@ -656,14 +656,41 @@ int envmatch(uchar *s1, int i2)
>>   	return -1;
>>   }
>>
>> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
>> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
>>   			  int argc, char * const argv[])
>>   {
>> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
>> -		return CMD_RET_USAGE;
>> +	int all = 0, flag = 0;
>>
>> -	set_default_env("## Resetting to default environment\n");
>> -	return 0;
>> +	debug("Initial value for argc=%d\n", argc);
>> +	while (--argc>  0&&  **++argv == '-') {
>
> mmmmm ... **++argv, yummy :) This might use some cleanup, to make more readable.

Uhm, this pattern is being used all over the place on that file (that's 
where I copied it from).

> Don't we have some getopt or something too ?

Not that I (or "git grep") know of.

>
>> +		char *arg = *argv;
>> +
>> +		while (*++arg) {
>> +			switch (*arg) {
>> +			case 'a':		/* default all */
>> +				all = 1;
>> +				break;
>> +			case 'f':		/* force */
>> +				flag |= H_FORCE;
>> +				break;
>> +			default:
>> +				return cmd_usage(cmdtp);
>> +			}
>> +		}
>> +	}
>> +	debug("Final value for argc=%d\n", argc);
>> +	if (all&&  (argc == 0)) {
>> +		/* Reset the whole environment */
>> +		set_default_env("## Resetting to default environment\n");
>> +		return 0;
>> +	}
>> +	if (!all&&  (argc>  0)) {
>> +		/* Reset individual variables */
>> +		set_default_vars(argc, argv);
>> +		return 0;
>> +	}
>> +
>> +	return cmd_usage(cmdtp);
>>   }
>>
>>   static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
>> @@ -994,7 +1021,8 @@ U_BOOT_CMD(
>>   #if defined(CONFIG_CMD_ASKENV)
>>   	"ask name [message] [size] - ask for environment variable\nenv "
>>   #endif
>> -	"default -f - reset default environment\n"
>> +	"default [-f] -a - [forcibly] reset default environment\n"
>> +	"env default [-f] var [...] - [forcibly] reset variable(s) to their
>> default values\n" #if defined(CONFIG_CMD_EDITENV)
>>   	"env edit name - edit environment variable\n"
>>   #endif
>> diff --git a/common/env_common.c b/common/env_common.c
>> index c6e7c4c..482d715 100644
>> --- a/common/env_common.c
>> +++ b/common/env_common.c
>> @@ -177,6 +177,11 @@ const uchar *env_get_addr(int index)
>>
>>   void set_default_env(const char *s)
>>   {
>> +	/*
>> +	 * By default, do not apply changes as they will eventually
>> +	 * be applied by someone else
>> +	 */
>> +	int do_apply = 0;
>>   	if (sizeof(default_environment)>  ENV_SIZE) {
>>   		puts("*** Error - default environment is too large\n\n");
>>   		return;
>> @@ -188,6 +193,14 @@ void set_default_env(const char *s)
>>   				"using default environment\n\n",
>>   				s + 1);
>>   		} else {
>> +			/*
>> +			 * This set_to_default was explicitly asked for
>> +			 * by the user, as opposed to being a recovery
>> +			 * mechanism.  Therefore we check every single
>> +			 * variable and apply changes to the system
>> +			 * right away (e.g. baudrate, console).
>> +			 */
>> +			do_apply = 1;
>>   			puts(s);
>>   		}
>>   	} else {
>> @@ -196,12 +209,25 @@ void set_default_env(const char *s)
>>
>>   	if (himport_r(&env_htab, (char *)default_environment,
>>   			sizeof(default_environment), '\0', 0,
>> -			0, NULL, 0 /* do_apply */) == 0)
>> +			0, NULL, do_apply) == 0)
>>   		error("Environment import failed: errno = %d\n", errno);
>>
>>   	gd->flags |= GD_FLG_ENV_READY;
>>   }
>>
>> +
>> +/* [re]set individual variables to their value in the default environment
>> */ +int set_default_vars(int nvars, char * const vars[])
>> +{
>> +	/*
>> +	 * Special use-case: import from default environment
>> +	 * (and use \0 as a separator)
>> +	 */
>> +	return himport_r(&env_htab, (const char *)default_environment,
>> +				sizeof(default_environment), '\0', H_NOCLEAR,
>> +				nvars, vars, 1 /* do_apply */);
>> +}
>> +
>>   /*
>>    * Check if CRC is valid and (if yes) import the environment.
>>    * Note that "buf" may or may not be aligned.
>> diff --git a/include/environment.h b/include/environment.h
>> index 90fb130..e8ab703 100644
>> --- a/include/environment.h
>> +++ b/include/environment.h
>> @@ -181,6 +181,9 @@ void env_crc_update(void);
>>   /* [re]set to the default environment */
>>   void set_default_env(const char *s);
>>
>> +/* [re]set individual variables to their value in the default environment
>> */ +int set_default_vars(int nvars, char * const vars[]);
>> +
>>   /* Import from binary representation into hash table */
>>   int env_import(const char *buf, int check);
>
> Best regards,
> Marek Vasut

Best regards,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default
  2012-08-24 10:18                 ` Gerlando Falauto
@ 2012-08-24 15:11                   ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 15:11 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 08/13/2012 12:11 PM, Wolfgang Denk wrote:
> > Dear Holger Brunck,
> > 
> > In message<5028AB80.5030803@keymile.com>  you wrote:
> >>>> time to do updates here I propose the following. I could prepare a
> >>>> branch as you suggested based on current denx master with this
> >>>> changeset. But where and how should I push it to git.denx.de? Or will
> >>>> you prepare this branch?
> >>> 
> >>> I already did.
> >> 
> >> is this branch public available? I don't find this branch on
> >> git.denx.de.
> > 
> > Oops.  Please try again now.
> 
> Actually, the branch does not currently compile due to some changes to
> the trunk introduced in the meantime. So I am sending a new v4 patch
> series based on the current master. Please note that the first patch of
> the new series is cosmetic only and independent from all others.

I did some review :)

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env
  2012-08-24 14:58     ` Marek Vasut
@ 2012-08-24 15:16       ` Gerlando Falauto
  2012-08-24 21:12         ` Marek Vasut
  2012-09-02 12:01         ` Wolfgang Denk
  0 siblings, 2 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-24 15:16 UTC (permalink / raw)
  To: u-boot

On 08/24/2012 04:58 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> When variables explicitly specified on the command line are not present
>> in the imported env, delete them from the running env.
>> If the variable is also missing from the running env, issue a warning.
>>
>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>
> Whew! I made it through ... it wasn't that scary in the end ;-)
>
>> ---
>>   lib/hashtable.c |   48 +++++++++++++++++++++++++++++++++++++++++-------
>>   1 file changed, 41 insertions(+), 7 deletions(-)
>>
>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>> index f3f47de..b3d0b64 100644
>> --- a/lib/hashtable.c
>> +++ b/lib/hashtable.c
>> @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const
>> char sep, * himport()
>>    */
>>
>> -/* Check whether variable name is amongst vars[] */
>> -static int is_var_in_set(const char *name, int nvars, char * const vars[])
>> +/*
>> + * Check whether variable 'name' is amongst vars[],
>> + * and remove all instances by setting the pointer to NULL
>> + */
>> +static int is_var_in_set(const char *name, int nvars, char * vars[])
>>   {
>>   	int i = 0;
>> +	int res = 0;
>>
>>   	/* No variables specified means process all of them */
>>   	if (nvars == 0)
>>   		return 1;
>>
>>   	for (i = 0; i<  nvars; i++) {
>> -		if (!strcmp(name, vars[i]))
>> -			return 1;
>> +		if (vars[i] == NULL)
>> +			continue;
>> +		/* If we found it, delete all of them */
>> +		if (!strcmp(name, vars[i])) {
>> +			vars[i] = NULL;
>> +			res = 1;
>
> break here ?

Nope, if we find it, we should delete all of them (see comment above).

>
>> +		}
>>   	}
>> -	debug("Skipping non-listed variable %s\n", name);
>> +	if (!res)
>> +		debug("Skipping non-listed variable %s\n", name);
>>
>> -	return 0;
>> +	return res;
>>   }
>>
>>   /*
>> @@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int nvars,
>> char * const vars[])
>>
>>   int himport_r(struct hsearch_data *htab,
>>   		const char *env, size_t size, const char sep, int flag,
>> -		int nvars, char * const vars[], int do_apply)
>> +		int nvars, char * const __vars[], int do_apply)
>
> Two underscores are reserved, use something else ;-)

Like... one? three? ;-)

>
>>   {
>>   	char *data, *sp, *dp, *name, *value;
>> +	char *vars[nvars];
>> +	int i;
>>
>>   	/* Test for correct arguments.  */
>>   	if (htab == NULL) {
>> @@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
>>   	memcpy(data, env, size);
>>   	dp = data;
>>
>> +	/* make a local copy of the list of variables */
>> +	if (nvars)
>> +		memcpy(vars, __vars, sizeof(__vars[0]) * nvars);
>> +
>>   	if ((flag&  H_NOCLEAR) == 0) {
>>   		/* Destroy old hash table if one exists */
>>   		debug("Destroy Hash Table: %p table = %p\n", htab,
>> @@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
>>   	debug("INSERT: free(data = %p)\n", data);
>>   	free(data);
>>
>> +	/* process variables which were not considered */
>> +	for (i = 0; i<  nvars; i++) {
>> +		if (vars[i] == NULL)
>> +			continue;
>> +		/*
>> +		 * All variables which were not deleted from the variable list
>> +		 * were not present in the imported env
>> +		 * This could mean two things:
>> +		 * a) if the variable was present in current env, we delete it
>> +		 * b) if the variable was not present in current env, we notify
>> +		 *    it might be a typo
>> +		 */
>> +		if (hdelete_r(vars[i], htab, do_apply) == 0)
>> +			printf("WARNING: '%s' neither in running nor in imported
> env!\n",
>> vars[i]); +		else
>> +			printf("WARNING: '%s' not in imported env, deleting it!
> \n", vars[i]);
>> +	}
>> +
>>   	debug("INSERT: done\n");
>>   	return 1;		/* everything OK */
>>   }
>
> Best regards,
> Marek Vasut

Best regards,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply
  2012-08-24 15:10       ` Gerlando Falauto
@ 2012-08-24 21:10         ` Marek Vasut
  2012-08-27  7:36           ` Gerlando Falauto
  2012-09-02 11:58           ` Wolfgang Denk
  0 siblings, 2 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 21:10 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 08/24/2012 04:56 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> >> Change the syntax (user API) for "env default":
> >>    -f: override write-once variables
> >>    var... : accept individual variable(s)
> >>    -a: all (resetting the whole env is NOT the default behavior)
> >> 
> >> Enable variable checking and make changes effective by
> >> enabling do_apply argument to himport_r().
> >> 
> >> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
> >> ---
> >> 
> >>   common/cmd_nvedit.c   |   40 ++++++++++++++++++++++++++++++++++------
> >>   common/env_common.c   |   28 +++++++++++++++++++++++++++-
> >>   include/environment.h |    3 +++
> >>   3 files changed, 64 insertions(+), 7 deletions(-)
> >> 
> >> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> >> index b0860f3..ac2b985 100644
> >> --- a/common/cmd_nvedit.c
> >> +++ b/common/cmd_nvedit.c
> >> @@ -656,14 +656,41 @@ int envmatch(uchar *s1, int i2)
> >> 
> >>   	return -1;
> >>   
> >>   }
> >> 
> >> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
> >> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
> >> 
> >>   			  int argc, char * const argv[])
> >>   
> >>   {
> >> 
> >> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
> >> -		return CMD_RET_USAGE;
> >> +	int all = 0, flag = 0;
> >> 
> >> -	set_default_env("## Resetting to default environment\n");
> >> -	return 0;
> >> +	debug("Initial value for argc=%d\n", argc);
> >> +	while (--argc>  0&&  **++argv == '-') {
> > 
> > mmmmm ... **++argv, yummy :) This might use some cleanup, to make more
> > readable.
> 
> Uhm, this pattern is being used all over the place on that file (that's
> where I copied it from).

That doesn't mean it's right, it just means the codebase is in a very sad state 
:-C

> > Don't we have some getopt or something too ?
> 
> Not that I (or "git grep") know of.

Even more :-C

> >> +		char *arg = *argv;
> >> +
> >> +		while (*++arg) {
> >> +			switch (*arg) {
> >> +			case 'a':		/* default all */
> >> +				all = 1;
> >> +				break;
> >> +			case 'f':		/* force */
> >> +				flag |= H_FORCE;
> >> +				break;
> >> +			default:
> >> +				return cmd_usage(cmdtp);
> >> +			}
> >> +		}
> >> +	}
> >> +	debug("Final value for argc=%d\n", argc);
> >> +	if (all&&  (argc == 0)) {
> >> +		/* Reset the whole environment */
> >> +		set_default_env("## Resetting to default environment\n");
> >> +		return 0;
> >> +	}
> >> +	if (!all&&  (argc>  0)) {
> >> +		/* Reset individual variables */
> >> +		set_default_vars(argc, argv);
> >> +		return 0;
> >> +	}
> >> +
> >> +	return cmd_usage(cmdtp);
> >> 
> >>   }
> >>   
> >>   static int do_env_delete(cmd_tbl_t *cmdtp, int flag,
> >> 
> >> @@ -994,7 +1021,8 @@ U_BOOT_CMD(
> >> 
> >>   #if defined(CONFIG_CMD_ASKENV)
> >>   
> >>   	"ask name [message] [size] - ask for environment variable\nenv "
> >>   
> >>   #endif
> >> 
> >> -	"default -f - reset default environment\n"
> >> +	"default [-f] -a - [forcibly] reset default environment\n"
> >> +	"env default [-f] var [...] - [forcibly] reset variable(s) to their
> >> default values\n" #if defined(CONFIG_CMD_EDITENV)
> >> 
> >>   	"env edit name - edit environment variable\n"
> >>   
> >>   #endif
> >> 
> >> diff --git a/common/env_common.c b/common/env_common.c
> >> index c6e7c4c..482d715 100644
> >> --- a/common/env_common.c
> >> +++ b/common/env_common.c
> >> @@ -177,6 +177,11 @@ const uchar *env_get_addr(int index)
> >> 
> >>   void set_default_env(const char *s)
> >>   {
> >> 
> >> +	/*
> >> +	 * By default, do not apply changes as they will eventually
> >> +	 * be applied by someone else
> >> +	 */
> >> +	int do_apply = 0;
> >> 
> >>   	if (sizeof(default_environment)>  ENV_SIZE) {
> >>   	
> >>   		puts("*** Error - default environment is too large\n\n");
> >>   		return;
> >> 
> >> @@ -188,6 +193,14 @@ void set_default_env(const char *s)
> >> 
> >>   				"using default environment\n\n",
> >>   				s + 1);
> >>   		
> >>   		} else {
> >> 
> >> +			/*
> >> +			 * This set_to_default was explicitly asked for
> >> +			 * by the user, as opposed to being a recovery
> >> +			 * mechanism.  Therefore we check every single
> >> +			 * variable and apply changes to the system
> >> +			 * right away (e.g. baudrate, console).
> >> +			 */
> >> +			do_apply = 1;
> >> 
> >>   			puts(s);
> >>   		
> >>   		}
> >>   	
> >>   	} else {
> >> 
> >> @@ -196,12 +209,25 @@ void set_default_env(const char *s)
> >> 
> >>   	if (himport_r(&env_htab, (char *)default_environment,
> >>   	
> >>   			sizeof(default_environment), '\0', 0,
> >> 
> >> -			0, NULL, 0 /* do_apply */) == 0)
> >> +			0, NULL, do_apply) == 0)
> >> 
> >>   		error("Environment import failed: errno = %d\n", errno);
> >>   	
> >>   	gd->flags |= GD_FLG_ENV_READY;
> >>   
> >>   }
> >> 
> >> +
> >> +/* [re]set individual variables to their value in the default
> >> environment */ +int set_default_vars(int nvars, char * const vars[])
> >> +{
> >> +	/*
> >> +	 * Special use-case: import from default environment
> >> +	 * (and use \0 as a separator)
> >> +	 */
> >> +	return himport_r(&env_htab, (const char *)default_environment,
> >> +				sizeof(default_environment), '\0', H_NOCLEAR,
> >> +				nvars, vars, 1 /* do_apply */);
> >> +}
> >> +
> >> 
> >>   /*
> >>   
> >>    * Check if CRC is valid and (if yes) import the environment.
> >>    * Note that "buf" may or may not be aligned.
> >> 
> >> diff --git a/include/environment.h b/include/environment.h
> >> index 90fb130..e8ab703 100644
> >> --- a/include/environment.h
> >> +++ b/include/environment.h
> >> @@ -181,6 +181,9 @@ void env_crc_update(void);
> >> 
> >>   /* [re]set to the default environment */
> >>   void set_default_env(const char *s);
> >> 
> >> +/* [re]set individual variables to their value in the default
> >> environment */ +int set_default_vars(int nvars, char * const vars[]);
> >> +
> >> 
> >>   /* Import from binary representation into hash table */
> >>   int env_import(const char *buf, int check);
> > 
> > Best regards,
> > Marek Vasut
> 
> Best regards,
> Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env
  2012-08-24 15:16       ` Gerlando Falauto
@ 2012-08-24 21:12         ` Marek Vasut
  2012-08-27  7:45           ` Gerlando Falauto
  2012-09-02 12:01         ` Wolfgang Denk
  1 sibling, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-08-24 21:12 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 08/24/2012 04:58 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> >> When variables explicitly specified on the command line are not present
> >> in the imported env, delete them from the running env.
> >> If the variable is also missing from the running env, issue a warning.
> >> 
> >> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
> > 
> > Whew! I made it through ... it wasn't that scary in the end ;-)
> > 
> >> ---
> >> 
> >>   lib/hashtable.c |   48
> >>   +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41
> >>   insertions(+), 7 deletions(-)
> >> 
> >> diff --git a/lib/hashtable.c b/lib/hashtable.c
> >> index f3f47de..b3d0b64 100644
> >> --- a/lib/hashtable.c
> >> +++ b/lib/hashtable.c
> >> @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> >> char sep, * himport()
> >> 
> >>    */
> >> 
> >> -/* Check whether variable name is amongst vars[] */
> >> -static int is_var_in_set(const char *name, int nvars, char * const
> >> vars[]) +/*
> >> + * Check whether variable 'name' is amongst vars[],
> >> + * and remove all instances by setting the pointer to NULL
> >> + */
> >> +static int is_var_in_set(const char *name, int nvars, char * vars[])
> >> 
> >>   {
> >>   
> >>   	int i = 0;
> >> 
> >> +	int res = 0;
> >> 
> >>   	/* No variables specified means process all of them */
> >>   	if (nvars == 0)
> >>   	
> >>   		return 1;
> >>   	
> >>   	for (i = 0; i<  nvars; i++) {
> >> 
> >> -		if (!strcmp(name, vars[i]))
> >> -			return 1;
> >> +		if (vars[i] == NULL)
> >> +			continue;
> >> +		/* If we found it, delete all of them */
> >> +		if (!strcmp(name, vars[i])) {
> >> +			vars[i] = NULL;
> >> +			res = 1;
> > 
> > break here ?
> 
> Nope, if we find it, we should delete all of them (see comment above).

Stupid me, of course now I see the logic! Sorry!

> >> +		}
> >> 
> >>   	}
> >> 
> >> -	debug("Skipping non-listed variable %s\n", name);
> >> +	if (!res)
> >> +		debug("Skipping non-listed variable %s\n", name);
> >> 
> >> -	return 0;
> >> +	return res;
> >> 
> >>   }
> >>   
> >>   /*
> >> 
> >> @@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int
> >> nvars, char * const vars[])
> >> 
> >>   int himport_r(struct hsearch_data *htab,
> >>   
> >>   		const char *env, size_t size, const char sep, int flag,
> >> 
> >> -		int nvars, char * const vars[], int do_apply)
> >> +		int nvars, char * const __vars[], int do_apply)
> > 
> > Two underscores are reserved, use something else ;-)
> 
> Like... one? three? ;-)

I think one is the way to go ... http://lwn.net/Articles/509149/ definitelly not 
like this ;-)

[...]


Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply
  2012-08-24 21:10         ` Marek Vasut
@ 2012-08-27  7:36           ` Gerlando Falauto
  2012-08-27  9:57             ` Marek Vasut
  2012-09-02 11:58           ` Wolfgang Denk
  1 sibling, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-27  7:36 UTC (permalink / raw)
  To: u-boot

On 08/24/2012 11:10 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> On 08/24/2012 04:56 PM, Marek Vasut wrote:
>>> Dear Gerlando Falauto,
>>>
>>>> Change the syntax (user API) for "env default":
>>>>     -f: override write-once variables
>>>>     var... : accept individual variable(s)
>>>>     -a: all (resetting the whole env is NOT the default behavior)
>>>>
>>>> Enable variable checking and make changes effective by
>>>> enabling do_apply argument to himport_r().
>>>>
>>>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>>>> ---
>>>>
>>>>    common/cmd_nvedit.c   |   40 ++++++++++++++++++++++++++++++++++------
>>>>    common/env_common.c   |   28 +++++++++++++++++++++++++++-
>>>>    include/environment.h |    3 +++
>>>>    3 files changed, 64 insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
>>>> index b0860f3..ac2b985 100644
>>>> --- a/common/cmd_nvedit.c
>>>> +++ b/common/cmd_nvedit.c
>>>> @@ -656,14 +656,41 @@ int envmatch(uchar *s1, int i2)
>>>>
>>>>    	return -1;
>>>>
>>>>    }
>>>>
>>>> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
>>>> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
>>>>
>>>>    			  int argc, char * const argv[])
>>>>
>>>>    {
>>>>
>>>> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
>>>> -		return CMD_RET_USAGE;
>>>> +	int all = 0, flag = 0;
>>>>
>>>> -	set_default_env("## Resetting to default environment\n");
>>>> -	return 0;
>>>> +	debug("Initial value for argc=%d\n", argc);
>>>> +	while (--argc>   0&&   **++argv == '-') {
>>>
>>> mmmmm ... **++argv, yummy :) This might use some cleanup, to make more
>>> readable.
>>
>> Uhm, this pattern is being used all over the place on that file (that's
>> where I copied it from).
>
> That doesn't mean it's right, it just means the codebase is in a very sad state
> :-C
>
>>> Don't we have some getopt or something too ?
>>
>> Not that I (or "git grep") know of.
>
> Even more :-C
>
You're absolutely right, but this patchset has been around for almost a 
year and we've gotten nowhere with it. I'm afraid that if we keep adding 
new (somewhat unrelated) improvement requests we'll get stuck with it 
for quite some time once again.
Could we keep this getopt topic in mind as an open point for a later, 
overall review of how command line options are parsed?

Thank you,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env
  2012-08-24 21:12         ` Marek Vasut
@ 2012-08-27  7:45           ` Gerlando Falauto
  0 siblings, 0 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-27  7:45 UTC (permalink / raw)
  To: u-boot

On 08/24/2012 11:12 PM, Marek Vasut wrote:
> Dear Gerlando Falauto,
>
>> On 08/24/2012 04:58 PM, Marek Vasut wrote:
>>> Dear Gerlando Falauto,
>>>
>>>> When variables explicitly specified on the command line are not present
>>>> in the imported env, delete them from the running env.
>>>> If the variable is also missing from the running env, issue a warning.
>>>>
>>>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
>>>
>>> Whew! I made it through ... it wasn't that scary in the end ;-)
>>>
>>>> ---
>>>>
>>>>    lib/hashtable.c |   48
>>>>    +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41
>>>>    insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/lib/hashtable.c b/lib/hashtable.c
>>>> index f3f47de..b3d0b64 100644
>>>> --- a/lib/hashtable.c
>>>> +++ b/lib/hashtable.c
>>>> @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const
>>>> char sep, * himport()
>>>>
>>>>     */
>>>>
>>>> -/* Check whether variable name is amongst vars[] */
>>>> -static int is_var_in_set(const char *name, int nvars, char * const
>>>> vars[]) +/*
>>>> + * Check whether variable 'name' is amongst vars[],
>>>> + * and remove all instances by setting the pointer to NULL
>>>> + */
>>>> +static int is_var_in_set(const char *name, int nvars, char * vars[])
>>>>
>>>>    {
>>>>
>>>>    	int i = 0;
>>>>
>>>> +	int res = 0;
>>>>
>>>>    	/* No variables specified means process all of them */
>>>>    	if (nvars == 0)
>>>>    	
>>>>    		return 1;
>>>>    	
>>>>    	for (i = 0; i<   nvars; i++) {
>>>>
>>>> -		if (!strcmp(name, vars[i]))
>>>> -			return 1;
>>>> +		if (vars[i] == NULL)
>>>> +			continue;
>>>> +		/* If we found it, delete all of them */
>>>> +		if (!strcmp(name, vars[i])) {
>>>> +			vars[i] = NULL;
>>>> +			res = 1;
>>>
>>> break here ?
>>
>> Nope, if we find it, we should delete all of them (see comment above).
>
> Stupid me, of course now I see the logic! Sorry!
>
>>>> +		}
>>>>
>>>>    	}
>>>>
>>>> -	debug("Skipping non-listed variable %s\n", name);
>>>> +	if (!res)
>>>> +		debug("Skipping non-listed variable %s\n", name);
>>>>
>>>> -	return 0;
>>>> +	return res;
>>>>
>>>>    }
>>>>
>>>>    /*
>>>>
>>>> @@ -662,9 +672,11 @@ static int is_var_in_set(const char *name, int
>>>> nvars, char * const vars[])
>>>>
>>>>    int himport_r(struct hsearch_data *htab,
>>>>
>>>>    		const char *env, size_t size, const char sep, int flag,
>>>>
>>>> -		int nvars, char * const vars[], int do_apply)
>>>> +		int nvars, char * const __vars[], int do_apply)
>>>
>>> Two underscores are reserved, use something else ;-)
>>
>> Like... one? three? ;-)
>
> I think one is the way to go ... http://lwn.net/Articles/509149/ definitelly not
> like this ;-)
>
> [...]

The way I understand it, two underscores are reserved for the compiler's 
internal use, whereas a single underscore is usually reserved for 
library function names.
So I'm sending a v5 of this patch (not the whole set) with some new 
naming altogether (is_var_in_set also deserves some better naming as the 
new implementation would otherwise make it very misleading).

Best regards,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v5 7/7] env: delete selected vars not present in imported env
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env Gerlando Falauto
  2012-08-24 14:58     ` Marek Vasut
@ 2012-08-27  7:53     ` Gerlando Falauto
  2012-08-27 10:02       ` Marek Vasut
  1 sibling, 1 reply; 104+ messages in thread
From: Gerlando Falauto @ 2012-08-27  7:53 UTC (permalink / raw)
  To: u-boot

When variables explicitly specified on the command line are not present
in the imported env, delete them from the running env.
If the variable is also missing from the running env, issue a warning.

Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
---
Changes from v4:
- renamed is_var_in_set to drop_var_from_set
- removed leading double underscore from vars[] variable name
---
 lib/hashtable.c |   50 ++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 42 insertions(+), 8 deletions(-)

diff --git a/lib/hashtable.c b/lib/hashtable.c
index f3f47de..670a704 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
  * himport()
  */
 
-/* Check whether variable name is amongst vars[] */
-static int is_var_in_set(const char *name, int nvars, char * const vars[])
+/*
+ * Check whether variable 'name' is amongst vars[],
+ * and remove all instances by setting the pointer to NULL
+ */
+static int drop_var_from_set(const char *name, int nvars, char * vars[])
 {
 	int i = 0;
+	int res = 0;
 
 	/* No variables specified means process all of them */
 	if (nvars == 0)
 		return 1;
 
 	for (i = 0; i < nvars; i++) {
-		if (!strcmp(name, vars[i]))
-			return 1;
+		if (vars[i] == NULL)
+			continue;
+		/* If we found it, delete all of them */
+		if (!strcmp(name, vars[i])) {
+			vars[i] = NULL;
+			res = 1;
+		}
 	}
-	debug("Skipping non-listed variable %s\n", name);
+	if (!res)
+		debug("Skipping non-listed variable %s\n", name);
 
-	return 0;
+	return res;
 }
 
 /*
@@ -665,6 +675,8 @@ int himport_r(struct hsearch_data *htab,
 		int nvars, char * const vars[], int do_apply)
 {
 	char *data, *sp, *dp, *name, *value;
+	char *localvars[nvars];
+	int i;
 
 	/* Test for correct arguments.  */
 	if (htab == NULL) {
@@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
 	memcpy(data, env, size);
 	dp = data;
 
+	/* make a local copy of the list of variables */
+	if (nvars)
+		memcpy(localvars, vars, sizeof(vars[0]) * nvars);
+
 	if ((flag & H_NOCLEAR) == 0) {
 		/* Destroy old hash table if one exists */
 		debug("Destroy Hash Table: %p table = %p\n", htab,
@@ -749,7 +765,7 @@ int himport_r(struct hsearch_data *htab,
 			*dp++ = '\0';	/* terminate name */
 
 			debug("DELETE CANDIDATE: \"%s\"\n", name);
-			if (!is_var_in_set(name, nvars, vars))
+			if (!drop_var_from_set(name, nvars, localvars))
 				continue;
 
 			if (hdelete_r(name, htab, do_apply) == 0)
@@ -769,7 +785,7 @@ int himport_r(struct hsearch_data *htab,
 		++dp;
 
 		/* Skip variables which are not supposed to be processed */
-		if (!is_var_in_set(name, nvars, vars))
+		if (!drop_var_from_set(name, nvars, localvars))
 			continue;
 
 		/* enter into hash table */
@@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
 	debug("INSERT: free(data = %p)\n", data);
 	free(data);
 
+	/* process variables which were not considered */
+	for (i = 0; i < nvars; i++) {
+		if (localvars[i] == NULL)
+			continue;
+		/*
+		 * All variables which were not deleted from the variable list
+		 * were not present in the imported env
+		 * This could mean two things:
+		 * a) if the variable was present in current env, we delete it
+		 * b) if the variable was not present in current env, we notify
+		 *    it might be a typo
+		 */
+		if (hdelete_r(localvars[i], htab, do_apply) == 0)
+			printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);
+		else
+			printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
+	}
+
 	debug("INSERT: done\n");
 	return 1;		/* everything OK */
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply
  2012-08-27  7:36           ` Gerlando Falauto
@ 2012-08-27  9:57             ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-27  9:57 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> On 08/24/2012 11:10 PM, Marek Vasut wrote:
> > Dear Gerlando Falauto,
> > 
> >> On 08/24/2012 04:56 PM, Marek Vasut wrote:
> >>> Dear Gerlando Falauto,
> >>> 
> >>>> Change the syntax (user API) for "env default":
> >>>>     -f: override write-once variables
> >>>>     var... : accept individual variable(s)
> >>>>     -a: all (resetting the whole env is NOT the default behavior)
> >>>> 
> >>>> Enable variable checking and make changes effective by
> >>>> enabling do_apply argument to himport_r().
> >>>> 
> >>>> Signed-off-by: Gerlando Falauto<gerlando.falauto@keymile.com>
> >>>> ---
> >>>> 
> >>>>    common/cmd_nvedit.c   |   40
> >>>>    ++++++++++++++++++++++++++++++++++------ common/env_common.c   |  
> >>>>    28 +++++++++++++++++++++++++++-
> >>>>    include/environment.h |    3 +++
> >>>>    3 files changed, 64 insertions(+), 7 deletions(-)
> >>>> 
> >>>> diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
> >>>> index b0860f3..ac2b985 100644
> >>>> --- a/common/cmd_nvedit.c
> >>>> +++ b/common/cmd_nvedit.c
> >>>> @@ -656,14 +656,41 @@ int envmatch(uchar *s1, int i2)
> >>>> 
> >>>>    	return -1;
> >>>>    
> >>>>    }
> >>>> 
> >>>> -static int do_env_default(cmd_tbl_t *cmdtp, int flag,
> >>>> +static int do_env_default(cmd_tbl_t *cmdtp, int __flag,
> >>>> 
> >>>>    			  int argc, char * const argv[])
> >>>>    
> >>>>    {
> >>>> 
> >>>> -	if (argc != 2 || strcmp(argv[1], "-f") != 0)
> >>>> -		return CMD_RET_USAGE;
> >>>> +	int all = 0, flag = 0;
> >>>> 
> >>>> -	set_default_env("## Resetting to default environment\n");
> >>>> -	return 0;
> >>>> +	debug("Initial value for argc=%d\n", argc);
> >>>> +	while (--argc>   0&&   **++argv == '-') {
> >>> 
> >>> mmmmm ... **++argv, yummy :) This might use some cleanup, to make more
> >>> readable.
> >> 
> >> Uhm, this pattern is being used all over the place on that file (that's
> >> where I copied it from).
> > 
> > That doesn't mean it's right, it just means the codebase is in a very sad
> > state
> > 
> > :-C
> > :
> >>> Don't we have some getopt or something too ?
> >> 
> >> Not that I (or "git grep") know of.
> > 
> > Even more :-C
> 
> You're absolutely right, but this patchset has been around for almost a
> year and we've gotten nowhere with it. I'm afraid that if we keep adding
> new (somewhat unrelated) improvement requests we'll get stuck with it
> for quite some time once again.

Definitelly, it was just a remark that it's sad state of the codebase, not that 
you should start implementing it !

> Could we keep this getopt topic in mind as an open point for a later,
> overall review of how command line options are parsed?

Yes!

> Thank you,
> Gerlando

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v5 7/7] env: delete selected vars not present in imported env
  2012-08-27  7:53     ` [U-Boot] [PATCH v5 " Gerlando Falauto
@ 2012-08-27 10:02       ` Marek Vasut
  0 siblings, 0 replies; 104+ messages in thread
From: Marek Vasut @ 2012-08-27 10:02 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

> When variables explicitly specified on the command line are not present
> in the imported env, delete them from the running env.
> If the variable is also missing from the running env, issue a warning.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>

Looks reasonable ...

Reviewed-by: Marek Vasut <marex@denx.de>

> ---
> Changes from v4:
> - renamed is_var_in_set to drop_var_from_set
> - removed leading double underscore from vars[] variable name
> ---
>  lib/hashtable.c |   50 ++++++++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 42 insertions(+), 8 deletions(-)
> 
> diff --git a/lib/hashtable.c b/lib/hashtable.c
> index f3f47de..670a704 100644
> --- a/lib/hashtable.c
> +++ b/lib/hashtable.c
> @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const
> char sep, * himport()
>   */
> 
> -/* Check whether variable name is amongst vars[] */
> -static int is_var_in_set(const char *name, int nvars, char * const vars[])
> +/*
> + * Check whether variable 'name' is amongst vars[],
> + * and remove all instances by setting the pointer to NULL
> + */
> +static int drop_var_from_set(const char *name, int nvars, char * vars[])
>  {
>  	int i = 0;
> +	int res = 0;
> 
>  	/* No variables specified means process all of them */
>  	if (nvars == 0)
>  		return 1;
> 
>  	for (i = 0; i < nvars; i++) {
> -		if (!strcmp(name, vars[i]))
> -			return 1;
> +		if (vars[i] == NULL)
> +			continue;
> +		/* If we found it, delete all of them */
> +		if (!strcmp(name, vars[i])) {
> +			vars[i] = NULL;
> +			res = 1;
> +		}
>  	}
> -	debug("Skipping non-listed variable %s\n", name);
> +	if (!res)
> +		debug("Skipping non-listed variable %s\n", name);
> 
> -	return 0;
> +	return res;
>  }
> 
>  /*
> @@ -665,6 +675,8 @@ int himport_r(struct hsearch_data *htab,
>  		int nvars, char * const vars[], int do_apply)
>  {
>  	char *data, *sp, *dp, *name, *value;
> +	char *localvars[nvars];
> +	int i;
> 
>  	/* Test for correct arguments.  */
>  	if (htab == NULL) {
> @@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab,
>  	memcpy(data, env, size);
>  	dp = data;
> 
> +	/* make a local copy of the list of variables */
> +	if (nvars)
> +		memcpy(localvars, vars, sizeof(vars[0]) * nvars);
> +
>  	if ((flag & H_NOCLEAR) == 0) {
>  		/* Destroy old hash table if one exists */
>  		debug("Destroy Hash Table: %p table = %p\n", htab,
> @@ -749,7 +765,7 @@ int himport_r(struct hsearch_data *htab,
>  			*dp++ = '\0';	/* terminate name */
> 
>  			debug("DELETE CANDIDATE: \"%s\"\n", name);
> -			if (!is_var_in_set(name, nvars, vars))
> +			if (!drop_var_from_set(name, nvars, localvars))
>  				continue;
> 
>  			if (hdelete_r(name, htab, do_apply) == 0)
> @@ -769,7 +785,7 @@ int himport_r(struct hsearch_data *htab,
>  		++dp;
> 
>  		/* Skip variables which are not supposed to be processed */
> -		if (!is_var_in_set(name, nvars, vars))
> +		if (!drop_var_from_set(name, nvars, localvars))
>  			continue;
> 
>  		/* enter into hash table */
> @@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab,
>  	debug("INSERT: free(data = %p)\n", data);
>  	free(data);
> 
> +	/* process variables which were not considered */
> +	for (i = 0; i < nvars; i++) {
> +		if (localvars[i] == NULL)
> +			continue;
> +		/*
> +		 * All variables which were not deleted from the variable list
> +		 * were not present in the imported env
> +		 * This could mean two things:
> +		 * a) if the variable was present in current env, we delete it
> +		 * b) if the variable was not present in current env, we notify
> +		 *    it might be a typo
> +		 */
> +		if (hdelete_r(localvars[i], htab, do_apply) == 0)
> +			printf("WARNING: '%s' neither in running nor in imported 
env!\n",
> localvars[i]); +		else
> +			printf("WARNING: '%s' not in imported env, deleting it!
\n",
> localvars[i]); +	}
> +
>  	debug("INSERT: done\n");
>  	return 1;		/* everything OK */
>  }

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply
  2012-08-24 21:10         ` Marek Vasut
  2012-08-27  7:36           ` Gerlando Falauto
@ 2012-09-02 11:58           ` Wolfgang Denk
  1 sibling, 0 replies; 104+ messages in thread
From: Wolfgang Denk @ 2012-09-02 11:58 UTC (permalink / raw)
  To: u-boot

Dear Marek Vasut,

In message <201208242310.05189.marek.vasut@gmail.com> you wrote:
>
> > >> +	while (--argc>  0&&  **++argv == '-') {
> > > 
> > > mmmmm ... **++argv, yummy :) This might use some cleanup, to make more
> > > readable.
> > 
> > Uhm, this pattern is being used all over the place on that file (that's
> > where I copied it from).
> 
> That doesn't mean it's right, it just means the codebase is in a very sad state 
> :-C

Define "right".

And what makes you think the way K&R implemented such stuff would be
a "very sad state"? See for example the code from Unix Version 6:

"ls" command:

	if (--argc > 0 && *argv[1] == '-') {

or "grep":

	while (--argc > 0 && (++argv)[0][0]=='-')

etc. etc.

Any C beginner's class is supposed to be able to parse this...

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Conceptual integrity in turn dictates that the  design  must  proceed
from  one  mind,  or  from  a  very small number of agreeing resonant
minds.               - Frederick Brooks Jr., "The Mythical Man Month"

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default
  2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
                     ` (6 preceding siblings ...)
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env Gerlando Falauto
@ 2012-09-02 11:59   ` Wolfgang Denk
  2012-09-02 16:13     ` Marek Vasut
  7 siblings, 1 reply; 104+ messages in thread
From: Wolfgang Denk @ 2012-09-02 11:59 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <1345803102-21110-1-git-send-email-gerlando.falauto@keymile.com> you wrote:
> This patchset modifies the handling of all the operations on the environment
> (set/import/default) so to unify handling of special variables.
> On top of that we implement a selective "env default".
> 
> A selective "env import" would imply a user API change and should therefore
> be discussed separately.
> 
> NOTE:
> The entire patchset generates an increase in code size of about 1200 bytes
> on a PowerPC target. 
> As much as I would like to get rid of the set_default_vars() function in 
> env_common.c, I have not found a nice way to do so.
> 
> Changes in the syntax (user API):
> - "env default" -f: override write-once variables, -a means all
> - display a warning when trying to set to default variables not
>   present in the default env.
> 
> Changes from v3:
> - rebased to current trunk (was not compilable)
> - removed compiler warnings
> - added an independent cosmetic patch on top of the series (from which only
>   a later patch would actually benefit)

In which way are these changes related to the code I checked in for
testing into the "env" branch?

Is this patch series supposed to replace this stuff?


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
PoB = "Prisoner of Bill" -- those held captive, unwillingly or other-
wise, by the contemptible Microsoft monopoly.
         -- Tom Christiansen in <6abo45$3lc$2@csnews.cs.colorado.edu>

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env
  2012-08-24 15:16       ` Gerlando Falauto
  2012-08-24 21:12         ` Marek Vasut
@ 2012-09-02 12:01         ` Wolfgang Denk
  2012-09-03  7:34           ` Gerlando Falauto
  1 sibling, 1 reply; 104+ messages in thread
From: Wolfgang Denk @ 2012-09-02 12:01 UTC (permalink / raw)
  To: u-boot

Dear Gerlando Falauto,

In message <50379AD5.6030709@keymile.com> you wrote:
>
> >>   int himport_r(struct hsearch_data *htab,
> >>   		const char *env, size_t size, const char sep, int flag,
> >> -		int nvars, char * const vars[], int do_apply)
> >> +		int nvars, char * const __vars[], int do_apply)
> >
> > Two underscores are reserved, use something else ;-)
> 
> Like... one? three? ;-)

Neither of these.  Use another name.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Your csh still thinks true is false. Write to your vendor  today  and
tell them that next year Configure ought to "rm /bin/csh" unless they
fix  their blasted shell. :-)
                 - Larry Wall in Configure from the perl distribution

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default
  2012-09-02 11:59   ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Wolfgang Denk
@ 2012-09-02 16:13     ` Marek Vasut
  2012-09-03  7:33       ` Gerlando Falauto
  0 siblings, 1 reply; 104+ messages in thread
From: Marek Vasut @ 2012-09-02 16:13 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Denk,

> Dear Gerlando Falauto,
> 
> In message <1345803102-21110-1-git-send-email-gerlando.falauto@keymile.com> 
you wrote:
> > This patchset modifies the handling of all the operations on the
> > environment (set/import/default) so to unify handling of special
> > variables.
> > On top of that we implement a selective "env default".
> > 
> > A selective "env import" would imply a user API change and should
> > therefore be discussed separately.
> > 
> > NOTE:
> > The entire patchset generates an increase in code size of about 1200
> > bytes on a PowerPC target.
> > As much as I would like to get rid of the set_default_vars() function in
> > env_common.c, I have not found a nice way to do so.
> > 
> > Changes in the syntax (user API):
> > - "env default" -f: override write-once variables, -a means all
> > - display a warning when trying to set to default variables not
> > 
> >   present in the default env.
> > 
> > Changes from v3:
> > - rebased to current trunk (was not compilable)
> > - removed compiler warnings
> > - added an independent cosmetic patch on top of the series (from which
> > only
> > 
> >   a later patch would actually benefit)
> 
> In which way are these changes related to the code I checked in for
> testing into the "env" branch?
> 
> Is this patch series supposed to replace this stuff?

Yes, looks to me that way

> 
> Best regards,
> 
> Wolfgang Denk

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default
  2012-09-02 16:13     ` Marek Vasut
@ 2012-09-03  7:33       ` Gerlando Falauto
  0 siblings, 0 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-09-03  7:33 UTC (permalink / raw)
  To: u-boot

On 09/02/2012 06:13 PM, Marek Vasut wrote:
> Dear Wolfgang Denk,
>
>> Dear Gerlando Falauto,
>>
>> In message<1345803102-21110-1-git-send-email-gerlando.falauto@keymile.com>
> you wrote:
>>> This patchset modifies the handling of all the operations on the
>>> environment (set/import/default) so to unify handling of special
>>> variables.
>>> On top of that we implement a selective "env default".
>>>
>>> A selective "env import" would imply a user API change and should
>>> therefore be discussed separately.
>>>
>>> NOTE:
>>> The entire patchset generates an increase in code size of about 1200
>>> bytes on a PowerPC target.
>>> As much as I would like to get rid of the set_default_vars() function in
>>> env_common.c, I have not found a nice way to do so.
>>>
>>> Changes in the syntax (user API):
>>> - "env default" -f: override write-once variables, -a means all
>>> - display a warning when trying to set to default variables not
>>>
>>>    present in the default env.
>>>
>>> Changes from v3:
>>> - rebased to current trunk (was not compilable)
>>> - removed compiler warnings
>>> - added an independent cosmetic patch on top of the series (from which
>>> only
>>>
>>>    a later patch would actually benefit)
>>
>> In which way are these changes related to the code I checked in for
>> testing into the "env" branch?
>>
>> Is this patch series supposed to replace this stuff?
>
> Yes, looks to me that way
>

Yes, as we (Holger and I) think it would make no sense to "patch the 
patch". But please correct me if I'm wrong.

Thank you,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env
  2012-09-02 12:01         ` Wolfgang Denk
@ 2012-09-03  7:34           ` Gerlando Falauto
  0 siblings, 0 replies; 104+ messages in thread
From: Gerlando Falauto @ 2012-09-03  7:34 UTC (permalink / raw)
  To: u-boot

On 09/02/2012 02:01 PM, Wolfgang Denk wrote:
> Dear Gerlando Falauto,
>
> In message<50379AD5.6030709@keymile.com>  you wrote:
>>
>>>>    int himport_r(struct hsearch_data *htab,
>>>>    		const char *env, size_t size, const char sep, int flag,
>>>> -		int nvars, char * const vars[], int do_apply)
>>>> +		int nvars, char * const __vars[], int do_apply)
>>>
>>> Two underscores are reserved, use something else ;-)
>>
>> Like... one? three? ;-)
>
> Neither of these.  Use another name.

That was more of a joke. :-)
Anyway, please see patch v5 (for this patch only).

Thank you,
Gerlando

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [U-Boot] [U-Boot, v4, 1/7] env: cosmetic: drop assignment i = iomux_doenv()
  2012-08-24 10:11   ` [U-Boot] [PATCH v4 1/7] env: cosmetic: drop assignment i = iomux_doenv() Gerlando Falauto
  2012-08-24 14:44     ` Marek Vasut
@ 2012-09-18 19:05     ` Tom Rini
  1 sibling, 0 replies; 104+ messages in thread
From: Tom Rini @ 2012-09-18 19:05 UTC (permalink / raw)
  To: u-boot

On Fri, Aug 24, 2012 at 12:11:36AM -0000, Gerlando Falauto wrote:

> iomux_doenv() can only return 0 or 1.
> So there is no need to save its return value in variable i, as checking
> its truth value within an if statement is enough.
> 
> Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com>
> Reviewed-by: Marek Vasut <marex@denx.de>

Along with the rest of the series, applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120918/1e8aeee7/attachment.pgp>

^ permalink raw reply	[flat|nested] 104+ messages in thread

end of thread, other threads:[~2012-09-18 19:05 UTC | newest]

Thread overview: 104+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-18 16:49 [U-Boot] [PATCH v1 0/5] env: handle special variables and selective env default Gerlando Falauto
2011-11-18 16:49 ` [U-Boot] [PATCH v1 1/5] serial: cosmetic checkpatch compliance Gerlando Falauto
2011-11-18 20:04   ` Mike Frysinger
2011-12-05 21:47   ` Wolfgang Denk
2011-11-18 16:49 ` [U-Boot] [PATCH v1 2/5] serial: constify serial_assign() Gerlando Falauto
2011-11-18 20:03   ` Mike Frysinger
2011-12-05 21:48   ` Wolfgang Denk
2011-11-18 16:49 ` [U-Boot] [PATCH v1 3/5] env: unify logic to check and apply changes Gerlando Falauto
2011-12-07  1:50   ` Simon Glass
2011-11-18 16:49 ` [U-Boot] [PATCH v1 4/5] env: check and apply changes on delete/destroy Gerlando Falauto
2011-11-18 16:49 ` [U-Boot] [PATCH v1 5/5] env: make "env default" selective, check and apply Gerlando Falauto
2011-12-07 13:30 ` [U-Boot] [PATCH v2 0/3] env: handle special variables and selective env default Gerlando Falauto
2011-12-07 13:30 ` [U-Boot] [PATCH v2 1/3] env: unify logic to check and apply changes Gerlando Falauto
2011-12-07 22:02   ` Simon Glass
2011-12-08  5:45     ` Mike Frysinger
2011-12-12  9:32     ` Gerlando Falauto
2011-12-12 12:18       ` Wolfgang Denk
2011-12-12 13:38         ` Gerlando Falauto
2011-12-12 13:50           ` Wolfgang Denk
2011-12-12 16:24       ` Simon Glass
2012-03-29 20:19   ` Marek Vasut
2012-03-30 13:00     ` Gerlando Falauto
2012-03-30 13:08       ` Marek Vasut
2012-03-30 13:22         ` Gerlando Falauto
2012-03-30 13:55           ` Marek Vasut
2012-03-30 14:03             ` Gerlando Falauto
2012-03-30 14:28               ` Marek Vasut
2012-03-30 17:00       ` Gerlando Falauto
2011-12-07 13:30 ` [U-Boot] [PATCH v2 2/3] env: check and apply changes on delete/destroy Gerlando Falauto
2011-12-07 22:02   ` Simon Glass
2011-12-12  9:32     ` Gerlando Falauto
2011-12-12 13:08       ` Wolfgang Denk
2011-12-12 13:52         ` Gerlando Falauto
2011-12-12 19:19           ` Wolfgang Denk
2011-12-07 13:30 ` [U-Boot] [PATCH v2 3/3] env: make "env default" selective, check and apply Gerlando Falauto
2011-12-07 22:02   ` Simon Glass
2011-12-12  9:33     ` Gerlando Falauto
2011-12-12 13:10       ` Wolfgang Denk
2012-03-29 20:25   ` Marek Vasut
2012-03-30 13:00     ` Gerlando Falauto
2012-03-30 13:09       ` Marek Vasut
2012-03-30 13:25         ` Gerlando Falauto
2012-04-02 18:26 ` [U-Boot] [PATCH v3 0/6] env: handle special variables and selective env default Gerlando Falauto
2012-08-09 20:17   ` Wolfgang Denk
2012-08-09 22:19     ` Gerlando Falauto
2012-08-09 22:26       ` Wolfgang Denk
2012-08-10  8:53         ` Holger Brunck
2012-08-10 18:08           ` Wolfgang Denk
2012-08-13  7:23             ` Holger Brunck
2012-08-13 10:11               ` Wolfgang Denk
2012-08-24 10:18                 ` Gerlando Falauto
2012-08-24 15:11                   ` Marek Vasut
2012-04-02 18:26 ` [U-Boot] [PATCH v3 1/6] env: unify logic to check and apply changes Gerlando Falauto
2012-04-02 18:56   ` Marek Vasut
2012-04-02 20:39     ` Gerlando Falauto
2012-04-02 20:50       ` Marek Vasut
2012-04-02 18:26 ` [U-Boot] [PATCH v3 2/6] env: make himport_r() selective on variables Gerlando Falauto
2012-04-02 18:57   ` Marek Vasut
2012-04-02 20:43     ` Gerlando Falauto
2012-04-04  7:41       ` Simon Glass
2012-04-02 18:26 ` [U-Boot] [PATCH v3 3/6] env: add check/apply logic to himport_r() Gerlando Falauto
2012-04-02 19:00   ` Marek Vasut
2012-04-02 19:01     ` Marek Vasut
2012-04-02 20:44       ` Gerlando Falauto
2012-04-02 20:51         ` Marek Vasut
2012-04-02 18:26 ` [U-Boot] [PATCH v3 4/6] env: check and apply changes on delete/destroy Gerlando Falauto
2012-04-02 19:01   ` Marek Vasut
2012-04-02 18:26 ` [U-Boot] [PATCH v3 5/6] env: make "env default" selective, check and apply Gerlando Falauto
2012-04-02 19:04   ` Marek Vasut
2012-04-02 18:26 ` [U-Boot] [PATCH v3 6/6] env: delete selected vars not present in imported env Gerlando Falauto
2012-04-02 19:06   ` Marek Vasut
2012-04-02 20:45     ` Gerlando Falauto
2012-04-02 21:00       ` Marek Vasut
2012-08-24 10:11 ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Gerlando Falauto
2012-08-24 10:11   ` [U-Boot] [PATCH v4 1/7] env: cosmetic: drop assignment i = iomux_doenv() Gerlando Falauto
2012-08-24 14:44     ` Marek Vasut
2012-09-18 19:05     ` [U-Boot] [U-Boot, v4, " Tom Rini
2012-08-24 10:11   ` [U-Boot] [PATCH v4 2/7] env: unify logic to check and apply changes Gerlando Falauto
2012-08-24 14:48     ` Marek Vasut
2012-08-24 10:11   ` [U-Boot] [PATCH v4 3/7] env: make himport_r() selective on variables Gerlando Falauto
2012-08-24 14:50     ` Marek Vasut
2012-08-24 10:11   ` [U-Boot] [PATCH v4 4/7] env: add check/apply logic to himport_r() Gerlando Falauto
2012-08-24 14:52     ` Marek Vasut
2012-08-24 10:11   ` [U-Boot] [PATCH v4 5/7] env: check and apply changes on delete/destroy Gerlando Falauto
2012-08-24 14:53     ` Marek Vasut
2012-08-24 10:11   ` [U-Boot] [PATCH v4 6/7] env: make "env default" selective, check and apply Gerlando Falauto
2012-08-24 14:56     ` Marek Vasut
2012-08-24 15:10       ` Gerlando Falauto
2012-08-24 21:10         ` Marek Vasut
2012-08-27  7:36           ` Gerlando Falauto
2012-08-27  9:57             ` Marek Vasut
2012-09-02 11:58           ` Wolfgang Denk
2012-08-24 10:11   ` [U-Boot] [PATCH v4 7/7] env: delete selected vars not present in imported env Gerlando Falauto
2012-08-24 14:58     ` Marek Vasut
2012-08-24 15:16       ` Gerlando Falauto
2012-08-24 21:12         ` Marek Vasut
2012-08-27  7:45           ` Gerlando Falauto
2012-09-02 12:01         ` Wolfgang Denk
2012-09-03  7:34           ` Gerlando Falauto
2012-08-27  7:53     ` [U-Boot] [PATCH v5 " Gerlando Falauto
2012-08-27 10:02       ` Marek Vasut
2012-09-02 11:59   ` [U-Boot] [PATCH v4 0/7] env: handle special variables and selective env default Wolfgang Denk
2012-09-02 16:13     ` Marek Vasut
2012-09-03  7:33       ` Gerlando Falauto

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.