[U-Boot] ARM relocation, question to Heiko

Albert ARIBAUD
2010-10-02T08:26:01Z

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,
--
Albert.