[U-Boot] Read-only env variables

Wolfgang Denk wd at denx.de
Wed May 12 11:34:20 CEST 2010


Dear Joe Hershberger,

In message <AANLkTil26wmjRI5oq2iMFnNEc8LGoYlSjbGoQKTLxLbw at mail.gmail.com> you wrote:
>
> >> I ran into the same situation, where I needed set of environment
> >> variables for in house testing, and a different set for when products
> >> actually go out to customers. So we were erasing the flash quite often,
> >> but in this scenario, things like serial number and mac address stay
> >> with the board regardless if we replace all of the memory on the board.
> >> I wrote a mirror image of the environment variable handling routines,
> >> but used a small serial EEPROM that could hold a 100 bytes.
> 
> I don't have a separate memory to use for this purpose, but it seems
> like a good approach if you do.

In most cases the compiled-in default environment should be sufficient
for this purpose.

> > There has been discussion about such a feature in the past. I even
> > tried to define the user interface for such a command set, but
> > unfortunately I didn't have enough time myself and nobody else took
> > the bait either.
> 
> Ok... if you can dig up the user interface you were thinking of, I can
> compare it to what I've done and possibly tweak it.  As it is now, I
> intend to use the acl to define which variables are preserved.  The
> command takes no arguments and changes only the in-RAM environment.

See here:

http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/36570/focus=36861

Taking this one step further, we should then also rename "editenv"
into "env edit".

Re-reading the proposal, I still like the suggested user interface.


> I'll have to look into this.  I've noticed their existence, but
> haven't used them so far.  I can see how that would help for
> intermediate state storage (as long as they stay around through every
> context such as from preboot to bootcmd), but not for variables that
> need to be accessible to u-boot (such as network settings).

You can of course initialize environment variables from values stored
in shell variables, i. e.

	setenv ipaddr ${var}

> >> the case with "ipaddr" and family.  If the user wishes to change the
> >> static IP, then that change should be written to flash.  If the user
> >> wishes to use dhcp to configure all the network settings, those settings
> >> should not be saved to flash (and then used as though they were static
> >
> > Be careful. You are defining policy here, and actually you can do all
> > this already now.
> 
> I want the acl to be the one defining this policy.

But this is IMHO wrong. The ACl should describe properties, i. e. if a
variable can be written or not etc.  It should NEVER try to define how
the user deploys the properties of a variable.

> > Use "setenv ipaddr ...; saveenv" if the user wishes to change the
> > static IP and write it to flash.
> 
> Works great in a vacuum.

? What do you mean here?

> > Use "dhcp" (without "saveenv") to use dhcp to configure all the
> > network settings without saving this to flash.
> 
> In the case of dhcp, the key is that I want to be able to save some
> unrelated change to the environment... I shouldn't be prevented from
> doing it because I happened to configure the network already.

I don't see your problem. If you want to define a default IP address
and want to use this as "ipaddr" environment variable unless DHCP
overwrites this value, then you can easily do that:

	=> setenv default_ipaddr aa.bb.cc.dd
	=> setenv default_netmask ...
	...
	=> setenv net_default 'setenv ipaddr ${default_ipaddr};setenv netmask ${default_netmask};...'
	=> setenv preboot run net_default


How would you in your szenario, where "dhcp" can change the "ipaddr"
environment variable, but a saveenv would not save it, set a new
"ipaddr"?

Me thinks you are adding complexity here without need, plus potential
for lots of confusion.


> > Well, then just do the saveenv _before_ you use DHCP. Or be careful
> 
> Not possible for the use case... I'm using netconsole, so dhcp must be
> first to make the console accessible... so no change made to the env
> could ever be saved.

OK, then do as described above and consider the variables set by DHCP
as volatile and do not attempt to use these to store your default
settings that are supposed to be persistent.

> All of this stems from the fact that a number of env vars are magical.
>  Things like "ipaddr" and "stdin" etc. are hooked up to internals of
> u-boot.  In the case of stdin and family, the behavior (without
> CONFIG_SYS_CONSOLE_IS_IN_ENV) is that those variables only affect the
> run-time behavior and are not written to flash.  I'm certain that the
> reason for that is the same as the issue I'm having with the network

No, the reason is more likely that the one who implemented this did
just what he actually needed, without a clear concept for such a
global scope. The next one who needed different behaviour added
CONFIG_SYS_CONSOLE_IS_IN_ENV. Now we have both.

> configuration.  I think there should be a simple-to-use way to
> indicate that a magical env var should be only magical and not in
> flash or possibly initialized from flash but not saved.  Since I'm

I disagree. Please let the end user decide what we wants to do with
variable settings - wether he wants to save them or not.

> making an ACL, it seemed reasonable to implement that behavior
> generically.  The list behavior idea was an attempt at making the acl
> easier to change, since it would need to be changed (by users,
> scripts, and u-boot code) for several different use cases.

Ok, se your original intention was a scriptable "env edit" command,
which might (or might not) be based on some internal list
representation - but ther eis no need to introduce such a list to the
user interface.

> Run this command:
> 
> setenv a "\$x";printenv a;setenv b "$x";printenv b
> 
> Neither one ends up containing "$x".  I believe that the first one should.

There is some inconsistency in the environment variable subsituion,
indeed. Note that the example works with shell variables, though:

=> a="\$x"; b="$x"
=> echo a=${a} b=${b}
a=$x b=

For environment variables, you should delay/prevent variable
substitution using '...' quotes:

=> setenv a '\$x';printenv a;setenv b '$x';printenv b
a=$x
b=$x


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
Just about every computer on the market today runs Unix,  except  the
Mac (and nobody cares about it).                   - Bill Joy 6/21/85


More information about the U-Boot mailing list