
Dear Albert ARIBAUD,
In message 4C91F659.7020607@free.fr you wrote:
Well, the main goal of -fPIC is that the code should be able to run from anywhere, so it should be able to run from anywhere in FLASH. Besides,
You misread that. We actually make no attempts that the code can be run from any arbitrary address. On contrary - we explicitly link it for a fixed address map, which is defined by the location of the reset vector, which is the one and only defined entry point into U-Boot.
[I'm giving the generic, architecture independent view of U-Boot here. Actual implementations for some processors may behave differently, but this is nothing you should build on.]
that can be useful for designs where two (possibly differently built) images of u-boot are located in FLASH and some mechanism allows booting from either.
The only reasonable use cases for such a szenario that I am aware of would be best implemented in hardware, by being able to toggle between two banks of flash memory, selecting one or the other as boot device. Then you can even use the same U-Boot binary images, which is a good thing in such setups. [eventualkly you want to store the environment somewhere else, say in some storage device on the backplane, so all instances of U-Boot refer to the same data.]
(I personally have another motive for having at least the _f part of u-boot able to run fully PIC, as I want to implement direct-to-u-boot resetting on targets that have a reset vector rather far away from the end of the addressable space but too near to fit u-boot in, e.g. the orion5x which resets as 0xffff0000: 64 KB is too small for u-boot. I have submitted a patch for this then withdrawn it because of the relocation patches; however for this conversation, we can keep this point aside)
I do not understand this what you mean by that, or what the problem might be. It is trivial to arrange the code such that no significant gaps remain. This requires just a little tuning of the linker script.
As for what would or would not work, ATM it boils down to 'access to const variables will be position-independent, access to others will not'. Non-initialized as well as initialized-but-not-const globals are always accessed at their link location before and after relocation, and thus will work only if you're running the image at its linked location.
Again, please keep in mind that (1) this depends on the linker script, and (2) that before relocation to RAM _all_ access to global variables is extremely limited as we have only a read-only data segment and no BSS segment at all.
This means that non-const data obviously can't work when the image is linked to FLASH; and they can even wreak havoc if the image linked for RAM and relocated near, but not exactly at, its linked location. The
I don't understand what you mean. Are you aware of the restrictions of the execution environment before relocation to RAM?
fact that it did not break so far in u-boot without reloc (and yes, several drivers do access globals during in-FLASH board init) is due to the fact that DRAM is already initialized when drivers access these globals at their linked location; this breaks when the image is linked for a location in FLASH.
If any drivers do such things, and if these drivers are used before relocation to RAM, these are serious bugs that must be fixed.
If you are aware of such bugs please post this information, so people can start working on fixes.
Of course solving the init data issue (by making them const) will not solve the issue of rw data. For this one I see two solutions:
- forbid using such data in drivers during _f phase if that is
This is, and has always been, the case.
possible. For instance, in the timer.c driver of orion5x, the timer_init code accesses two writable variables because it wants to have a first reference for rollover detection; this can obviously be postponed to the _r init phase.
Hm... I don;t see global variables being used in timer_init() in "arch/arm/cpu/arm926ejs/orion5x/timer.c" - which exact code are you referring to?
- in case where the _f phase *has* to store data in globals, then this
data should go to the globals space allocated below the stack, where gd also resides, and be later copied to usual globals if reqired.
It seems you really minunderstand the excution environment before relocation. Ther eis also no steck there, and of course no "globals space allocated below the stack", because we don't even have the RAM initialized yet.
BTW, the comments in board.c say that the _f init functions receive a pointer to gd; actually they dont, they're int (*) (void). Were the comments always out-of-sync with the code, or was there a removal of the gd argument for some reason?
Please read the code, and the README. Please pay special attention to section "Initial Stack, Global Data:".
In short: the pointer to the global data is passed in a register, which we reserve for this purpose.
Best regards,
Wolfgang Denk