uBoot recursive variables, have I simply misunderstood

103 views Asked by At

This feels like I've just misunderstood a basic concept:

My real-world case looks like:

setenv nbootcmd .....various options
setenv fbootcmd ..... various options
setenv bootcmd \${nbootcmd}


But, as I don't want to reboot every attempt, I reduced it to:

 U-Boot 1.1.4 (Oct 27 2010 - 16:50:30) Marvell version: 3.4.4
Marvell>> setenv cmd printenv cmd\;printenv icmd\;version
Marvell>> setenv icmd \${cmd}
Marvell>> run cmd
cmd=printenv cmd;printenv icmd;version
icmd=${cmd}

U-Boot 1.1.4 (Oct 27 2010 - 16:50:30) Marvell version: 3.4.4
Marvell>> run icmd
## Error: "cmd;printenv" not defined
## Error: "icmd;version" not defined

Now I'm expecting run cmd and run icmd to behave the same.

Now I gather I can achieve the same effect with:

Marvell>> setenv icmd run cmd
Marvell>> run icmd
cmd=printenv cmd;printenv icmd;version
icmd=run cmd

U-Boot 1.1.4 (Oct 27 2010 - 16:50:30) Marvell version: 3.4.4

but I can't see why the first form does not work. I'm asking to learn what I've misunderstood about uBoot rather than find a hack that works?

1

There are 1 answers

0
sawdust On BEST ANSWER

A recursive variable in U-Boot is handled as simple string substitution in a manner similar to a #define macro with the C preprocessor. There is no shell involved, or any execution layering. The string substitution has precedence, and the replacement (of the recursive variable) is performed before the command (operating on that recursive variable) is executed.

So run icmd (in your first version) will first perform expansion of the recursive variable

run ${cmd}

and then tries to perform

run printenv cmd;printenv icmd;version

which is invalid.
The operand of the run command should be an environment variable, and not another command. printenv is a U-Boot command, rather than a variable.
U-Boot's CLI seems to get confused sometimes by such malformed compound commands, and may display less-than-perfect diagnostic messages.

Similarly, printenv icmd is a command with a valid operand that is a variable, whereas printenv ${cmd} is not (after the string substitution).