[U-Boot-Users] Dynamic location of the environment sector

I have a board that comes in three flash confirurations: - 32MB - 64MB - 128MB
The cfi code can safely detect the flash sizes, banks and widths at boot time. I have however the problem that the flash chips are "top" type and the small sectors are at the end of the address space. So I want to make the last sector (a small sector) to contain the environment. The last sector though is in a different address (and has a different size) depending on the flash configuration.
Currently the defines for the environment expect raw numerical values. Is there an infrastructure somewhere to define the flash size at runtime? I tried to print the flash sizes in the board specific codes, for instance:
extern flash_info_t flash_info[];
printf("flash 0 : %d %x\n", flash_info[0].size, flash_info[0].start[flash_info[0].sector_count-1]); ...
prints:
Flash: 64 MB In: serial Out: serial Err: serial flash 0 : 67108864 3ff0000
(the second number is the address of the last sector)
And all sizes are detected correctly. I want to use these values to calculate the location of the environment dynamically at runtime. This way I can have a single u-boot image for all flash configurations!
-- Angelos Manousaridis

In message 448FF915.5060306@inaccessnetworks.com you wrote:
I have a board that comes in three flash confirurations:
...
the last sector (a small sector) to contain the environment. The last sector though is in a different address (and has a different size) depending on the flash configuration.
OK.
Currently the defines for the environment expect raw numerical values.
What makes you think so?
I didn't try it, but I see no reason why something like
#define CFG_ENV_ADDR my_env_params(1) #define CFG_ENV_SIZE my_env_params(2) #define CFG_ENV_SECT_SIZE my_env_params(3)
would be impossible. But this probably does not solve your problem - see below.
Is there an infrastructure somewhere to define the flash size at runtime? I tried to print the flash sizes in the board specific codes, for instance:
You have all the powers of the C preprocessor and compiler at your hands. Just use them.
And all sizes are detected correctly. I want to use these values to calculate the location of the environment dynamically at runtime. This way I can have a single u-boot image for all flash configurations!
There is one problem which you probably did not realize yet: U-Boot will access the environment (for example, to read the console baudrate) *long* before the flash detection code is running (which actually happens very late in the init sequence, after relocation to RAM). So you cannot rely on values filled in the flash_info[] array, as such data does not exist yet when you need it. You will need some other way (like configuration registers of jumpers on the board) to figure out which configuration to use.
Or you simply chose a definition that works on all boards, even if this means that you will waste some flashmemory on 2 of the board configurations.
Best regards,
Wolfgang Denk

On Wed, Jun 14, 2006 at 04:31:04PM +0200, Wolfgang Denk wrote:
Currently the defines for the environment expect raw numerical values.
What makes you think so?
I didn't try it, but I see no reason why something like
#define CFG_ENV_ADDR my_env_params(1) #define CFG_ENV_SIZE my_env_params(2) #define CFG_ENV_SECT_SIZE my_env_params(3)
would be impossible. But this probably does not solve your problem - see below.
Indeed it does not. The problem however, just for the record is code like the following segment:
# if (CFG_ENV_ADDR >= CFG_MONITOR_BASE) && \ (CFG_ENV_ADDR+CFG_ENV_SIZE) <= (CFG_MONITOR_BASE + CFG_MONITOR_LEN) # define ENV_IS_EMBEDDED 1 # endif
The preprocessor cannot obviously perform checks and do arithmetic with C variables and constructs:
include/environment.h:64:20: token "[" is not validin preprocessor expressions
And all sizes are detected correctly. I want to use these values to calculate the location of the environment dynamically at runtime. This way I can have a single u-boot image for all flash configurations!
There is one problem which you probably did not realize yet: U-Boot will access the environment (for example, to read the console baudrate) *long* before the flash detection code is running (which actually happens very late in the init sequence, after relocation to RAM). So you cannot rely on values filled in the flash_info[] array, as such data does not exist yet when you need it. You will need some other way (like configuration registers of jumpers on the board) to figure out which configuration to use.
Or you simply chose a definition that works on all boards, even if this means that you will waste some flashmemory on 2 of the board configurations.
This is the solution I will follow, although I was trying to avoid it. The second block, right after the u-boot will hold the environment. I have an issue though with the environment sector size. I have three configurations, two of which have a sector size 0x40000 and one has 0x20000. The problem I mentioned above with the static declarations appears here. If I declare the env size to be the smaller sector, An error occurs during the environment saving : "flash sector size is not equal to the environment size" or something like that.
Another note not related to the ones above. A couple of days ago I sent some patches for the arm architecture, but I did not received any replies. Have you seen them (it was on the 6th of June)?
Regards,
Angelos Manousaridis

In message 20060621104820.GA23461@inaccessnetworks.com you wrote:
Indeed it does not. The problem however, just for the record is code like the following segment:
# if (CFG_ENV_ADDR >= CFG_MONITOR_BASE) && \ (CFG_ENV_ADDR+CFG_ENV_SIZE) <= (CFG_MONITOR_BASE + CFG_MONITOR_LEN) # define ENV_IS_EMBEDDED 1 # endif
This is not a real problem, me thinks.
The preprocessor cannot obviously perform checks and do arithmetic with C variables and constructs:
include/environment.h:64:20: token "[" is not validin preprocessor expressions
Well, don't use '[' in your definitions, then :-)
This is the solution I will follow, although I was trying to avoid it. The second block, right after the u-boot will hold the environment. I have an issue though with the environment sector size. I have three configurations, two of which have a sector size 0x40000 and one has 0x20000. The problem I mentioned above with the static declarations appears here. If I declare the env size to be the smaller sector, An error occurs during the environment saving : "flash sector size is not equal to the environment size" or something like that.
So don'ty do it, then. Make the size 0x40000.
Another note not related to the ones above. A couple of days ago I sent some patches for the arm architecture, but I did not received any replies. Have you seen them (it was on the 6th of June)?
Did you see them on the list? If so, OK. What sort of replies did you expect anyway?
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
In message 20060621104820.GA23461@inaccessnetworks.com you wrote:
Indeed it does not. The problem however, just for the record is code like the following segment:
# if (CFG_ENV_ADDR >= CFG_MONITOR_BASE) && \ (CFG_ENV_ADDR+CFG_ENV_SIZE) <= (CFG_MONITOR_BASE + CFG_MONITOR_LEN) # define ENV_IS_EMBEDDED 1 # endif
This is not a real problem, me thinks.
The preprocessor cannot obviously perform checks and do arithmetic with C variables and constructs:
include/environment.h:64:20: token "[" is not validin preprocessor expressions
Well, don't use '[' in your definitions, then :-)
Ok I finally decided to switch to an embedded environment in the text segment of u-boot. The documentation says it is tricky business, but I prefer to take that risk and have a single image for all the platforms, without wasting 512K of flash space.
The placement of the environment is a bit of a tricky business though in the ARM platform. Initially I tried to place it on the end of the sector but realised that after the text segment is the data segment of which the size I don't know. The other solution is to place it at the beginning right after the reset code, but this also does not have a fixed size (cpu/pxa/start.o). I decided to use the latter approach and place the environment at the 16K boundary, hoping that the object start.o will never reach this size.
Another problem I encountered has to do with the manipulation of the environment with the "saveenv" command. The image I produced was ok, I booted and the default environment was recognized. I saw that the file common/environment.c defines before the environment the env_size variable, therefore placing the environment at 0x4004 than 0x4000 that is my hard coded offset. This causes a problem with the saveenv command, since here (common/env_flash.c):
#ifdef CMD_SAVEENV /* static env_t *flash_addr = (env_t *)(&environment[0]);-broken on ARM-wd-*/ static env_t *flash_addr = (env_t *)(CFG_ENV_ADDR + sizeof(unsigned long)); #endif
the address the command uses is the initial offset (0x4000) and not the actual offset after the env_size variable.
Is this a bug introduced by the workaround for the flash_addr? Or am I doing something wrong and the env_size variable should never have appeared in my code?
Regargs,
Angelos Manousaridis

Angelos Manousarides wrote:
Another problem I encountered has to do with the manipulation of the environment with the "saveenv" command. The image I produced was ok, I booted and the default environment was recognized. I saw that the file common/environment.c defines before the environment the env_size variable, therefore placing the environment at 0x4004 than 0x4000 that is my hard coded offset. This causes a problem with the saveenv command, since here (common/env_flash.c):
#ifdef CMD_SAVEENV /* static env_t *flash_addr = (env_t *)(&environment[0]);-broken on ARM-wd-*/ static env_t *flash_addr = (env_t *)(CFG_ENV_ADDR + sizeof(unsigned long)); #endif
the address the command uses is the initial offset (0x4000) and not the actual offset after the env_size variable.
Is this a bug introduced by the workaround for the flash_addr? Or am I doing something wrong and the env_size variable should never have appeared in my code?
Ooops, sorry I forgot to mention that with the above line changed to:
static env_t *flash_addr = (env_t *)(CFG_ENV_ADDR + sizeof(unsigned long));
the saveenv command produced the desired result. I am not so sure if this is the appropriate solution, it is a bit hard-coded, but I thought I should mention it. It would be more desirable to infer the address of the environment directly, but I am not sure how this can be done for the PXA architecture (or in a unified way for all architectures for that matter).
Regards, Angelos Manousaridis

In message 44998029.9020708@inaccessnetworks.com you wrote:
Ooops, sorry I forgot to mention that with the above line changed to:
static env_t *flash_addr = (env_t *)(CFG_ENV_ADDR + sizeof(unsigned long));
This cannot be correct.
I should mention it. It would be more desirable to infer the address of the environment directly, but I am not sure how this can be done for the PXA architecture (or in a unified way for all architectures for that matter).
See the existing code examples / linker scripts.
Best regards,
Wolfgang Denk

In message 44997F0A.8010303@inaccessnetworks.com you wrote:
Is this a bug introduced by the workaround for the flash_addr? Or am I doing something wrong and the env_size variable should never have appeared in my code?
You must be doing something wrong.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
In message 44997F0A.8010303@inaccessnetworks.com you wrote:
Is this a bug introduced by the workaround for the flash_addr? Or am I doing something wrong and the env_size variable should never have appeared in my code?
You must be doing something wrong.
Ok. I found what the problem was. I was looking at the TRAB board which is a PXA board with the environment embedded and did exactly the same thing. What i did NOT notice is that it is mentioned explicitely in the common/environment.c file, and that is why it works and mine did not:
#if (defined(CONFIG_CMI) || \ defined(CONFIG_FADS) || \ defined(CONFIG_HYMOD) || \ defined(CONFIG_ICU862) || \ defined(CONFIG_R360MPI) || \ defined(CONFIG_TQM8xxL) || \ defined(CONFIG_RRVISION) || \ defined(CONFIG_TRAB) || \ defined(CONFIG_MRG110_6) || \ defined(CONFIG_PPCHAMELEONEVB) ) && \ defined(ENV_CRC) /* Environment embedded in U-Boot .ppcenv section */ /* XXX - This only works with GNU C */ # define __PPCENV__ __attribute__ ((section(".ppcenv"))) # define __PPCTEXT__ __attribute__ ((section(".text")))
#elif defined(USE_HOSTCC) /* Native for 'tools/envcrc' */ # define __PPCENV__ /*XXX DO_NOT_DEL_THIS_COMMENT*/ # define __PPCTEXT__ /*XXX DO_NOT_DEL_THIS_COMMENT*/
#else /* Environment is embedded in U-Boot's .text section */ /* XXX - This only works with GNU C */ # define __PPCENV__ __attribute__ ((section(".text"))) # define __PPCTEXT__ __attribute__ ((section(".text"))) #endif
My board is not on the first #if, so it felt back to the last #else, thus placing the env_size and environment in the wrong order.
Regards, Angelos Manousaridis

In message 449A6F42.9090509@inaccessnetworks.com you wrote:
Ok. I found what the problem was. I was looking at the TRAB board which is a PXA board with the environment embedded and did exactly the same
No, TRAB is not a PXA system. It's a s3c2400 board.
thing. What i did NOT notice is that it is mentioned explicitely in the common/environment.c file, and that is why it works and mine did not:
No, this is not correct.
#if (defined(CONFIG_CMI) || \ defined(CONFIG_FADS) || \ defined(CONFIG_HYMOD) || \ defined(CONFIG_ICU862) || \ defined(CONFIG_R360MPI) || \ defined(CONFIG_TQM8xxL) || \ defined(CONFIG_RRVISION) || \ defined(CONFIG_TRAB) || \ defined(CONFIG_MRG110_6) || \ defined(CONFIG_PPCHAMELEONEVB) ) && \ defined(ENV_CRC) /* Environment embedded in U-Boot .ppcenv section */
The only effect of this is to put the environment into a separate linker section. You can do this, but you don't have to. You can make this work without this setting es well. Just configure your linker script correctly.
My board is not on the first #if, so it felt back to the last #else, thus placing the env_size and environment in the wrong order.
This is an error in your linker script then.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
In message 449A6F42.9090509@inaccessnetworks.com you wrote:
The only effect of this is to put the environment into a separate linker section. You can do this, but you don't have to. You can make this work without this setting es well. Just configure your linker script correctly.
My board is not on the first #if, so it felt back to the last #else, thus placing the env_size and environment in the wrong order.
This is an error in your linker script then.
My linker script is :
.text : { cpu/pxa/start.o (.text) . = env_offset ; common/environment.o (.text) *(.text) /**(EXCLUDE_FILE (common/environment.o) .text)*/ }
env_offset is defined at common/environment.c, and this is the defined used by other boards as well. BUT:
$ arm-linux-objdump -d common/environment.o
common/environment.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <env_size>: 0: 00 80 00 00 ....
00000004 <environment>: 4: 85 6f 43 92 62 6f 6f 74 64 65 6c 61 79 3d 35 00 .oC.bootdelay=5. 14: 62 61 75 64 72 61 74 65 3d 31 31 35 32 30 30 00 baudrate=115200. ...
How can this be correct? All the defines are for offset 0 of this file, but at 0 is the env_size. I also did a hexedit of the u-boot.bin and the environment indeed starts at 0x4004 :
00004000 00 80 00 00 85 6F 43 92 62 6F 6F 74 64 65 6C 61
Regards, Angelos Manousaridis

Angelos Manousarides wrote:
env_offset is defined at common/environment.c, and this is the defined used by other boards as well. BUT:
$ arm-linux-objdump -d common/environment.o
common/environment.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <env_size>: 0: 00 80 00 00 ....
00000004 <environment>: 4: 85 6f 43 92 62 6f 6f 74 64 65 6c 61 79 3d 35 00 .oC.bootdelay=5. 14: 62 61 75 64 72 61 74 65 3d 31 31 35 32 30 30 00 baudrate=115200. ...
Well, I decided to change the linker script to :
cpu/pxa/start.o (.text) . = 16 * 1024 - 4; common/environment.o (.text) *(.text)
This way the environment will be alligned at the right address and I don't have to change the u-boot code.
What is the story of the env_size variable? The tools tin tools/env/* do not use this variable, the environment size is retrieved from the configuration files.
The only reference I found was in tools/envcrc.c:
#ifdef ENV_IS_EMBEDDED extern unsigned int env_size; extern unsigned char environment; #endif /* ENV_IS_EMBEDDED */
These declarations though are not used anywhere on the code that follows!
In the actual u-boot code (not the tools) there is no usage. Is it some kind of a legacy mechanism, leftover from older versions of u-boot?
-- Angelos Manousaridis

In message 449FF5D4.8050007@inaccessnetworks.com you wrote:
What is the story of the env_size variable? The tools tin tools/env/* do not use this variable, the environment size is retrieved from the configuration files.
I have no idea what's happening in your configuration. Especially, a variable like env_size should not be part of the .text segment ion the first place.
In the actual u-boot code (not the tools) there is no usage. Is it some kind of a legacy mechanism, leftover from older versions of u-boot?
I don't even remember that...
Best regards,
Wolfgang Denk

On Mon, Jun 26, 2006 at 11:10:51PM +0200, Wolfgang Denk wrote:
In message 449FF5D4.8050007@inaccessnetworks.com you wrote:
What is the story of the env_size variable? The tools tin tools/env/* do not use this variable, the environment size is retrieved from the configuration files.
I have no idea what's happening in your configuration. Especially, a variable like env_size should not be part of the .text segment ion the first place.
Could it be that I am the first to try an embedded environment in u-boot for the PXA architecture? The PXA platforms are very few, I wouldn't be suprised if that was the case.
Regards, Angelos Manousaridis
participants (2)
-
Angelos Manousarides
-
Wolfgang Denk