
Le 02/10/2010 10:10, Reinhard Meyer a écrit :
Dear Albert ARIBAUD,
I try to understand how the relocation process could handle pointers (to functions or other data) in const or data sections. Your code cannot know what is data and what is a pointer that needs adjustment?
Best Regards, Reinhard
Hi Reinhart,
Short answer - the relocation process does not handle pointers inside data structures.
And yes, this means the content arrays of pointers such as init_sequence is not relocated. Been there, done that, can give you one of the tee-shirts I got :)
ATM I have not found a way to fix this, except making the code which uses the pointers aware that the are location-sensitive and fix them when using them.
That means that things like this cannot work (with relocation), unless adding the relocation offset before using the pointer:
const struct { const u8 shift; const u8 idcode; struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode); } flashes[] = { #ifdef CONFIG_SPI_FLASH_SPANSION { 0, 0x01, spi_flash_probe_spansion, }, #endif #ifdef CONFIG_SPI_FLASH_ATMEL { 0, 0x1F, spi_flash_probe_atmel, }, #endif #ifdef CONFIG_SPI_FLASH_MACRONIX { 0, 0xc2, spi_flash_probe_macronix, }, #endif #ifdef CONFIG_SPI_FLASH_WINBOND { 0, 0xef, spi_flash_probe_winbond, }, #endif #ifdef CONFIG_SPI_FLASH_STMICRO { 0, 0x20, spi_flash_probe_stmicro, }, { 0, 0xff, spi_flash_probe_stmicro, }, #endif #ifdef CONFIG_SPI_FLASH_SST { 0, 0xBF, spi_flash_probe_sst, }, #endif #ifdef CONFIG_SPI_FRAM_RAMTRON { 6, 0xc2, spi_fram_probe_ramtron, }, # ifdef CONFIG_SPI_FRAM_RAMTRON_NON_JEDEC { 0, 0xff, spi_fram_probe_ramtron, }, # endif # undef IDBUF_LEN # define IDBUF_LEN 9 /* we need to read 6+3 bytes */ #endif };
And I think there are more places of this type in u-boot...
Best Regards, Reinhard
If this code is intended to execute after relocation [1] then no, it will not work.
There are two ways to fix that:
The first one is to make the variable non-const and, after relocation but before use, run a fixup loop specifically for this variable. Then you can call the (now fixed) functions.
The second one is to fix on-the-fly: provide a field in gd which contains the relocation offset in gd (if not done already); in the code which calls function pointers, DECLARE_GLOBAL_DATA_PTR and call the function through a global macro (defined in some general u-boot header), e.g. FIX_RELOCATED_FUNCTION_POINTER(fp), which would offset fp to its correct location.
Thus in the code, instead of x = fp(args) you'd have x = FIX_RELOCATED_FUNCTION_POINTER(fp)(args).
[1] or, in my case, before relocation but not from the location specified at link time. This is a slightly different issue, which the first solution fails to address but the second does.
Amicalement,