[U-Boot] where *precisely* is u-boot's environment stored?

kind of embarrassed that i don't know the answer to this but, short form of question, when i build a u-boot.bin and copy it to NOR flash on my target board, where is the environment stored such that user space fw_printenv and fw_setenv utilities can get at them?
longer form of question: i just used yocto project to build for my MPC8315E-RDB target board, and one of the artifacts generated was "u-boot.bin", apparently ready for copying to NOR flash on this board, NOR flash being at 0xfe000000. i poked around trying to figure out where the environment was stored in that image, and i found the following in include/env_default.h:
... snip ... const uchar default_environment[] = { #endif #ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0" #endif #ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0" #endif #ifdef CONFIG_BOOTARGS "bootargs=" CONFIG_BOOTARGS "\0" #endif #ifdef CONFIG_BOOTCOMMAND "bootcmd=" CONFIG_BOOTCOMMAND "\0" #endif ... etc etc ...
i then checked u-boot.sym and found:
fe04c920 g O .text 00000389 default_environment
and if i "hexdump -C" the "u-boot.bin" file, sure enough, there it is, the apparent beginning of the default environment at 0x0004c920:
0004c900 8d ef 02 2d 25 2e 2a 73 00 00 00 00 25 73 25 64 |...-%.*s....%s%d| 0004c910 2c 25 64 00 70 61 72 74 69 74 69 6f 6e 00 00 00 |,%d.partition...| 0004c920 62 6f 6f 74 63 6d 64 3d 73 65 74 65 6e 76 20 62 |bootcmd=setenv b| 0004c930 6f 6f 74 61 72 67 73 20 72 6f 6f 74 3d 2f 64 65 |ootargs root=/de| 0004c940 76 2f 6e 66 73 20 72 77 20 6e 66 73 72 6f 6f 74 |v/nfs rw nfsroot| 0004c950 3d 24 73 65 72 76 65 72 69 70 3a 24 72 6f 6f 74 |=$serverip:$root| ... and on and on ...
so AFAICT, the default_environment[] ends up in the executable (and, consequently, in flash) i'm assuming based on wherever the linker places it based on the "u-boot.lds" file, correct?
however, if i look at the defn file for this target board, include/configs/MPC8315ERDB.h, i can see the various config settings defining where the environment resides, things like CONFIG_ENV_IS_IN_FLASH, CONFIG_ENV_ADDR and so on:
#if !defined(CONFIG_SYS_RAMBOOT) #define CONFIG_ENV_IS_IN_FLASH 1 #define CONFIG_ENV_ADDR \ (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN) #define CONFIG_ENV_SECT_SIZE 0x10000 /* 64K(one sector) for env */ #define CONFIG_ENV_SIZE 0x2000
and if i build the package u-boot-fw-utils to get the user space utilities "fw_printenv" and "fw_setenv", that package needs to be told where the environment is stored, and that's based on what it gets from the board's header file, which in this case defines:
#define CONFIG_SYS_MONITOR_LEN (384 * 1024) /* Reserve 384 kB for Mon */
which represents an env offset of 0x00060000 into flash.
so what is the correlation between those two addresses? there's the actual address of default_environment[] based on where the linker puts it (0xfe04c920), as opposed to where fw-utils will (apparently) look for the environment (0xfe060000). what's the connection here?
rday

oh, wait, i think i just answered some of my questions based on this snippet from common/env_nvram.c:
/* * Initialize Environment use * * We are still running from ROM, so data use is limited */ int env_init(void) { #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) ulong crc; uchar data[ENV_SIZE];
nvram_read(&crc, CONFIG_ENV_ADDR, sizeof(ulong)); nvram_read(data, CONFIG_ENV_ADDR + sizeof(ulong), ENV_SIZE);
if (crc32(0, data, ENV_SIZE) == crc) { gd->env_addr = (ulong)CONFIG_ENV_ADDR + sizeof(long); #else if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { gd->env_addr = (ulong)&env_ptr->data; #endif gd->env_valid = 1; } else { gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 0; }
return 0; }
so if there is a valid environment at the address specified by the board header file, it's used, otherwise fall back to default_environment[]. i had suspected it was something like that, i just hadn't found the code yet.
is this written up somewhere?
rday
p.s. how does the default environment get to the CONFIG_ENV_ADDR defined in the board header file? is that done automatically when u-boot starts to run and notices that there is no valid environment info at that address, and therefore copies it for you?
i will keep reading the source.

"Robert P. J. Day" rpjday@crashcourse.ca writes:
oh, wait, i think i just answered some of my questions based on this snippet from common/env_nvram.c:
/*
- Initialize Environment use
- We are still running from ROM, so data use is limited
*/ int env_init(void) { #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE) ulong crc; uchar data[ENV_SIZE];
nvram_read(&crc, CONFIG_ENV_ADDR, sizeof(ulong)); nvram_read(data, CONFIG_ENV_ADDR + sizeof(ulong), ENV_SIZE); if (crc32(0, data, ENV_SIZE) == crc) { gd->env_addr = (ulong)CONFIG_ENV_ADDR + sizeof(long);
#else if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { gd->env_addr = (ulong)&env_ptr->data; #endif gd->env_valid = 1; } else { gd->env_addr = (ulong)&default_environment[0]; gd->env_valid = 0; }
return 0;
}
so if there is a valid environment at the address specified by the board header file, it's used, otherwise fall back to default_environment[]. i had suspected it was something like that, i just hadn't found the code yet.
is this written up somewhere?
Looks like you found your answer, at least in part. The environment is stored in one of many possible locations, see the various env_*.c files. Which one is used is determined by the board configuration.
p.s. how does the default environment get to the CONFIG_ENV_ADDR defined in the board header file? is that done automatically when u-boot starts to run and notices that there is no valid environment info at that address, and therefore copies it for you?
If the stored environment is invalid (e.g. uninitialised), the built-in default is used. Nothing is written until you issue a saveenv command. This saves a copy of the live environment to the configured location.

On Wed, 6 Jul 2016, Måns Rullgård wrote:
"Robert P. J. Day" rpjday@crashcourse.ca writes:
p.s. how does the default environment get to the CONFIG_ENV_ADDR defined in the board header file? is that done automatically when u-boot starts to run and notices that there is no valid environment info at that address, and therefore copies it for you?
If the stored environment is invalid (e.g. uninitialised), the built-in default is used. Nothing is written until you issue a saveenv command. This saves a copy of the live environment to the configured location.
ah, that's the final bit of the puzzle i was looking for ... the first time a "saveenv" is done is when the configured location is examined and, if uninitialized, the env is copied there and is used from then on.
and it would appear that the location of the "current" environment is stored in "gd->env_addr", does that sound about right?
i'm still going to write this up somewhere for future reference.
rday

"Robert P. J. Day" rpjday@crashcourse.ca writes:
On Wed, 6 Jul 2016, Måns Rullgård wrote:
"Robert P. J. Day" rpjday@crashcourse.ca writes:
p.s. how does the default environment get to the CONFIG_ENV_ADDR defined in the board header file? is that done automatically when u-boot starts to run and notices that there is no valid environment info at that address, and therefore copies it for you?
If the stored environment is invalid (e.g. uninitialised), the built-in default is used. Nothing is written until you issue a saveenv command. This saves a copy of the live environment to the configured location.
ah, that's the final bit of the puzzle i was looking for ... the first time a "saveenv" is done is when the configured location is examined and, if uninitialized, the env is copied there and is used from then on.
saveenv always writes whatever is in memory to the permanent location, overwriting anything that was previously there. On startup, u-boot checks if the saved environment is valid and uses it if it is. If not, the defaults (as configured for the board) are used. Only the saveenv command writes anything to nonvolatile storage.

On Wed, 6 Jul 2016, Måns Rullgård wrote:
"Robert P. J. Day" rpjday@crashcourse.ca writes:
On Wed, 6 Jul 2016, Måns Rullgård wrote:
"Robert P. J. Day" rpjday@crashcourse.ca writes:
p.s. how does the default environment get to the CONFIG_ENV_ADDR defined in the board header file? is that done automatically when u-boot starts to run and notices that there is no valid environment info at that address, and therefore copies it for you?
If the stored environment is invalid (e.g. uninitialised), the built-in default is used. Nothing is written until you issue a saveenv command. This saves a copy of the live environment to the configured location.
ah, that's the final bit of the puzzle i was looking for ... the first time a "saveenv" is done is when the configured location is examined and, if uninitialized, the env is copied there and is used from then on.
saveenv always writes whatever is in memory to the permanent location,
and by "permanent location", you mean CONFIG_ENV_ADDR as defined in the board definition file, yes?
overwriting anything that was previously there. On startup, u-boot checks if the saved environment is valid and uses it if it is. If
and, again, by "saved environment", i assume you mean what is at CONFIG_ENV_ADDR. it's all a matter of terminology -- switching back and forth can make things confusing.
not to be overly pedantic (too late!), but is there a preferred expression for the environment stored at CONFIG_ENV_ADDR? is it "permanent environment" or "saved environment" or what?
not, the defaults (as configured for the board) are used. Only the saveenv command writes anything to nonvolatile storage.
ok, i think i have a handle on this now, thanks.
rday

Dear Robert,
In message alpine.LFD.2.20.1607060625500.18179@localhost.localdomain you wrote:
not to be overly pedantic (too late!), but is there a preferred expression for the environment stored at CONFIG_ENV_ADDR? is it "permanent environment" or "saved environment" or what?
I tend to call it the "persistent copy" of the environment (resp. copies in case of redundant environment), in contrast to the in memory copy of it. Upon start, the memory copy gets initialized from the persistent one, unless this turns out to be corrupt (or uninitialized, the effect is the same), in which case the builtin default environment is used to initialize the in memory copy.
Best regards,
Wolfgang Denk

On Wed, 6 Jul 2016, Wolfgang Denk wrote:
Dear Robert,
In message alpine.LFD.2.20.1607060625500.18179@localhost.localdomain you wrote:
not to be overly pedantic (too late!), but is there a preferred expression for the environment stored at CONFIG_ENV_ADDR? is it "permanent environment" or "saved environment" or what?
I tend to call it the "persistent copy" of the environment (resp. copies in case of redundant environment), in contrast to the in memory copy of it. Upon start, the memory copy gets initialized from the persistent one, unless this turns out to be corrupt (or uninitialized, the effect is the same), in which case the builtin default environment is used to initialize the in memory copy.
ok, i'm good with that, thanks.
rday

On Wed, 6 Jul 2016, Wolfgang Denk wrote:
Dear Robert,
In message alpine.LFD.2.20.1607060625500.18179@localhost.localdomain you wrote:
not to be overly pedantic (too late!), but is there a preferred expression for the environment stored at CONFIG_ENV_ADDR? is it "permanent environment" or "saved environment" or what?
I tend to call it the "persistent copy" of the environment (resp. copies in case of redundant environment), in contrast to the in memory copy of it. Upon start, the memory copy gets initialized from the persistent one, unless this turns out to be corrupt (or uninitialized, the effect is the same), in which case the builtin default environment is used to initialize the in memory copy.
is there a way to tell whether you're getting the current environment from the persistent copy or from the default environment? i'm not sure i have a pressing need for that, i'm just curious.
rday

Dear Robert,
In message alpine.LFD.2.20.1607060759100.21373@localhost.localdomain you wrote:
is there a way to tell whether you're getting the current environment from the persistent copy or from the default environment? i'm not sure i have a pressing need for that, i'm just curious.
Programmatically? No.
From the console output it is trivial - you will see
Warning: Bad CRC, using default environment
Best regards,
Wolfgang Denk
participants (3)
-
Måns Rullgård
-
Robert P. J. Day
-
Wolfgang Denk