All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] RFC: nvedit: support doing one (extra) expansion of the value in "env set"
@ 2020-02-05  1:08 Rasmus Villemoes
  2020-02-05 17:59 ` Simon Glass
  2020-02-11 16:30 ` Wolfgang Denk
  0 siblings, 2 replies; 21+ messages in thread
From: Rasmus Villemoes @ 2020-02-05  1:08 UTC (permalink / raw)
  To: u-boot

Currently, there's no way to fetch the value of an environment
variable whose name is stored in some other variable, or generated from
such - in non-working pseudo-code,

  ${${varname}}
  ${array${index}}

This forces some scripts to needlessly duplicate logic and hardcode
assumptions. For example, in an A/B scheme with three variables

BOOT_ORDER # Either "A B" or "B A" depending on which slot was last updated
BOOT_A_LEFT # 0..3
BOOT_B_LEFT # 0..3

when one needs to determine the slot to boot from, one does something
like

setenv found
for slot in $BOOT_ORDER ; do
  if test "x$found" != "x" ; then
    # work around lack of break
  elif test "x$slot" = "xA" ; then
    if test $BOOT_A_LEFT -gt 0 ; then
      setexpr BOOT_A_LEFT $BOOT_A_LEFT - 1
      setenv found A
      setenv bootargs ${bootargs_A}
      setenv ubivol ${ubivol_A}
      # more setup based on A
    fi
  elif test "x$slot" = "xB" ; then
    if test $BOOT_B_LEFT -gt 0 ; then
      # the same ...
    fi
  fi
done

This is already bad enough, but extending that to A/B/C is tedious and
prone to copy-pastos.

So this is an attempt at allowing one to do "env set -E var value1 value2"
with the effect that, of course, normal variable expansion happens on
the command line, the valueX are joined with spaces as usual, and then
one more pass is done over that string replacing occurrences of
${foo}.

The above would become

setenv found
for slot in $BOOT_ORDER ; do
  if test "x$found" != "x" ; then
    # work around lack of break
  else
    env set -E boot_left "\${BOOT_${slot}_LEFT}"
    if test $boot_left -gt 0 ; then
      setexpr BOOT_${slot}_LEFT $boot_left - 1
      env set found $slot
      env set -E bootargs "\${bootargs_${slot}}"
      env set -E ubivol "\${ubivol_${slot}}"
    fi
  fi
done

I'm pleasantly surprised it was that easy to implement, but of course
I'm cheating a bit (cli_simple_process_macros is only available if
CONFIG_CMDLINE, though I think cli_simple.o could be unconditionally
built and then link-time GC should get rid of the excess
functions).

This has been lightly tested in the sandbox. I'll add some proper unit
tests, update the help texts and try to handle the Kconfig issue if
this is something that might be accepted.

Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
---
 cmd/nvedit.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 81d94cd193..ff6ffcb674 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -224,7 +224,7 @@ DONE:
  */
 static int _do_env_set(int flag, int argc, char * const argv[], int env_flag)
 {
-	int   i, len;
+	int   i, len, expand = 0;
 	char  *name, *value, *s;
 	struct env_entry e, *ep;
 
@@ -244,6 +244,9 @@ static int _do_env_set(int flag, int argc, char * const argv[], int env_flag)
 			case 'f':		/* force */
 				env_flag |= H_FORCE;
 				break;
+			case 'E':
+				expand = 1;
+				break;
 			default:
 				return CMD_RET_USAGE;
 			}
@@ -287,6 +290,18 @@ static int _do_env_set(int flag, int argc, char * const argv[], int env_flag)
 	if (s != value)
 		*--s = '\0';
 
+	if (expand) {
+		char *expanded = malloc(CONFIG_SYS_CBSIZE);
+
+		if (expanded == NULL) {
+			printf("## Can't malloc %d bytes\n", CONFIG_SYS_CBSIZE);
+			free(value);
+			return 1;
+		}
+		cli_simple_process_macros(value, expanded);
+		free(value);
+		value = expanded;
+	}
 	e.key	= name;
 	e.data	= value;
 	hsearch_r(e, ENV_ENTER, &ep, &env_htab, env_flag);
-- 
2.23.0

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

end of thread, other threads:[~2023-02-02 15:15 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-05  1:08 [PATCH] RFC: nvedit: support doing one (extra) expansion of the value in "env set" Rasmus Villemoes
2020-02-05 17:59 ` Simon Glass
2020-02-11 15:38   ` Rasmus Villemoes
2020-02-11 17:14     ` Simon Glass
2020-02-11 16:30 ` Wolfgang Denk
2020-02-11 21:20   ` Rasmus Villemoes
2020-02-11 21:34     ` Rasmus Villemoes
2020-02-12 11:45       ` Wolfgang Denk
2020-02-12 11:38     ` Wolfgang Denk
2020-02-13 10:41       ` Rasmus Villemoes
2020-02-13 15:55         ` Wolfgang Denk
2020-02-14 11:54           ` Rasmus Villemoes
2020-02-14 12:23             ` Rasmus Villemoes
2020-02-14 12:35             ` Martin Hundebøll
2020-02-16 15:33               ` Wolfgang Denk
2020-02-16 15:24             ` Wolfgang Denk
2020-02-16 17:25               ` Wolfgang Denk
2020-02-18  8:11                 ` Rasmus Villemoes
2020-02-21 23:32                   ` Rasmus Villemoes
2020-02-22  0:54                     ` Tom Rini
2023-02-02 15:15             ` Rasmus Villemoes

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.