[U-Boot] [PATCH] arm: Allow u-boot to run from offset base address

Steve Rae
2014-06-10T17:56:20Z

On 14-06-09 10:16 PM, Albert ARIBAUD wrote:
> Hi Steve,
>
> (sorry for the duplicate)
>
> On Mon, 9 Jun 2014 13:45:50 -0700, Steve Rae <srae@broadcom.com> wrote:
>
>>
>>
>> On 14-06-09 03:23 AM, Albert ARIBAUD wrote:
>>> Hi Darwin,
>>>
>>> On Mon, 2 Jun 2014 17:37:25 -0700, Darwin Rambo <drambo@broadcom.com>
>>> wrote:
>>>
>>>>
>>>>
>>>> On 14-06-02 12:26 AM, Albert ARIBAUD wrote:
>>>>> Hi Darwin,
>>>>>
>>>>> On Mon, 26 May 2014 09:11:35 -0700, Darwin Rambo <drambo@broadcom.com>
>>>>> wrote:
>>>>>
>>>>>> Hi Albert,
>>>>>>
>>>>>> The previous stage bootloader (which I had no control over) wanted it's
>>>>>> header to be aligned to a 512 byte MMC block boundary, presumably since
>>>>>> this allowed DMA operations without copy/shifting. At the same time, I
>>>>>> didn't want to hack a header into start.S because I didn't want to carry
>>>>>> another downstream patch. So I investigated if I could shift u-boot's
>>>>>> base address as a feature that would allow an aligned header to be used
>>>>>> without the start.S patch.
>>>>>>
>>>>>> I know that a custom header patch to start.S would work, and that a
>>>>>> header plus padding will also work. But I found out that you can align
>>>>>> the base on certain smaller offsets if you keep the relocation offset at
>>>>>> nice boundaries like 0x1000 and if the relocation offset is a multiple
>>>>>> of the maximum alignment requirements of the image.
>>>>>>
>>>>>> The original patch I submitted didn't handle an end condition properly,
>>>>>> was ARM64-specific (wasn't tested on other architectures), and because
>>>>>> the patch was NAK'd, I didn't bother to submit a v2 patch and consider
>>>>>> the idea to be dead. I'm happy to abandon the patch. I hope this helps.
>>>>>
>>>>> Thanks.
>>>>>
>>>>> If I understand correctly, your target has a requirement for storing
>>>>> the image on a 512-byte boundary. But how does this affect the loading
>>>>> of the image into RAM, where the requirement is only that the vectors
>>>>> table be 32-bytes aligned? I mean, if you store the image in MMC at
>>>>> offset 0x200 (thus satisfying the 512-byte boundary requirement) and
>>>>> load it to, say, offset 0x10020 in RAM, how is it a problem for
>>>>> your target?
>>>>>
>>>>> If my example above inadequately represents the issue, then can you
>>>>> please provide a similar but adequate example, a failure case scenario,
>>>>> so that I can hve a correct understanding of the problem?
>>>>
>>>> Hi Albert,
>>>>
>>>> The constraints I have that I can't change, are that
>>>> - the 32 byte header is postprocessed and prepended to the image after
>>>> the build is complete
>>>> - the header is at a 512 byte alignment in MMC
>>>> - the header and image are copied to SDRAM to an alignment like
>>>> 0x88000000. Thus the u-boot image is linked at and starts at 0x88000020.
>>>> - the vectors need to be 0x800 aligned for armv8 (.align 11 directive)
>>>
>>> So far, so good -- I understand that the link-time location of the
>>> vectors table is incorrect.
>>>
>>>> So the failure case is that when the relocation happens, it relocates to
>>>> a 0x1000 alignment, say something like 0xffffa000. The relocation offset
>>>> is not a multiple of 0x1000 (0xffffa000 - 0x88000020) and the relocation
>>>> fails.
>>>
>>> What does "relocation fails" mean exactly, i.e., where and how exactly
>>> does the relocation code behave differently from expected? I'm asking
>>> because I don't understand why the relocation offset should be a
>>> multiple of 0x1000.
>>>
>>>> Adjusting the relocation offset to a multiple of 0x1000 (by
>>>> making the relocation address end in 0xNNNNN020) fixes the issues and
>>>> allows u-boot to relocate and run from this address without failing. I
>>>> hope this helps explain it a bit better.
>>>
>>> I do understand, however, that if the relocation offset must indeed be a
>>> multiple of 0x1000, then obviously the vectors table will end up as
>>> misaligned as it was before relocation.
>>>
>>> Also, personally I would like it if the vectors table was always
>>> aligned as it should, and there are at least three other boards which
>>> require a prefix/header before their vectors table, as Masahiro (cc:)
>>> indicated recently, so that makes the problem a generic one: how to
>>> properly integrate a header in-image (as opposed to an out-of-image
>>> one, which is just a matter of doing a 'cat', so to speak.
>>>
>>> Therefore I'd like a generic solution to this, where the header is
>>> prepended *and* aligned properly without breaking the start symbol
>>> alignment constraints. This /might/ be possible by cleverly adding
>>> a '.header' or '.signature' section to the linker script, possibly
>>> doing a two-stage link; but this should not require the source code to
>>> contain ad hoc relocation tricks.
>>>
>>> Let me tinker with it in the next few days; I'll try and come up with a
>>> clean and generic solution to this "in-code header" question.
>>>
>>> Thanks again for your explanation!
>>>
>>>> Best regards,
>>>> Darwin
>>>
>>> Amicalement,
>>>
>>
>> Perhaps an oversimplified example of the current code would help to
>> explain this better:
>>
>> scenario #1:
>> CONFIG_SYS_TEXT_BASE 0x88000000
>> vectors: .align 11 /* exception vectors need to be on a 0x800 byte
>> boundary */
>> compile/linker produces (before relocation):
>> _start symbol is at 0x88000000
>> vectors symbol is at 0x88000800
>> the relocation offset is: 0x77f9b000
>> therefore, after relocation:
>> _start symbol is at 0xfff9b000 (0x88000000+0xfff9b000)
>> vectors symbol is at 0xfff9b800 (0x88000800+0x77f9b000)
>>
>> scenario #2:
>> CONFIG_SYS_TEXT_BASE 0x88000020
>> vectors: .align 11 /* exception vectors need to be on a 0x800 byte
>> boundary */
>> compiler/linker produces (before relocation):
>> _start symbol is at 0x88000020
>> vectors symbol is at 0x88000800
>> the relocation offset is: 0x77f9afe0
>> therefore, after relocation:
>> _start symbol is at 0xfff9b000 (0x88000020+0x77f9afe0)
>> vectors symbol is at 0xfff9b7e0 (0x88000800+0x77f9afe0)
>>
>> Note that in scenario #2, after relocation, the vectors are not on a
>> 0x800 byte boundary anymore.
>
> Ok, so technically relocation works as it was told to, just was given
> "garbage in", with an image with an unaligned base and _start symbol
> (and an aligned vectors symbol); relocation worked as expected, and
> aligned base and start, thus not aligning vectors.
>
> Now, on to understanding why the CONFIG_SYS_TEXT_BASE is not aligned.
>
> Can you provide details from the case where the actual issue has
> arisen, or even better yet, provide a source tree and build command
> line, that I could reproduce the build here?
>
>> Thanks, Steve
>
> Amicalement,
>

Albert et al.

There could be "many" reasons why the CONFIG_SYS_TEXT_BASE is not
aligned on a 0x1000 byte boundary (Darwin has attempted to document his
particular use-case...)

But we think that the solution to support this is relatively
straightforward:
(1) after determining the "relocation address" (which will be on a
0x1000 byte boundary),
(2) add "CONFIG_SYS_TEXT_BASE % 4096" to that "relocation address"
(which effectively makes the "relocation offset" a multiple of 0x1000
too...)
So, in the scenario #1, (CONFIG_SYS_TEXT_BASE % 4096) = 0, so this
algorithm changes nothing.
And in scenario #2, (CONFIG_SYS_TEXT_BASE % 4096) = 0x20, therefore, we
would now get the following:
the relocation offset is: 0x77f9b000
therefore, after relocation:
_start symbol is at 0xfff9b020 (0x88000020+0x77f9b000)
vectors symbol is at 0xfff9b800 (0x88000800+0x77f9b000)
Which results in everything being aligned properly before AND after
relocation.
(3) HOWEVER, shifting the address UP may cause the end of the relocated
code to run past the end of the available memory... So we could:
(3.1) always relocate DOWN by ((CONFIG_SYS_TEXT_BASE % 4096) - 4096), or
(3.2) add (CONFIG_SYS_TEXT_BASE % 4096) to the calculated "gd->mon_len"
(which is the value used to determine the "relocation address"; this
would guarantee that there is always enough space for the relocated code...)

Note: 3.1 would usually waste up to 4096 bytes; whereas 3.2 would only
adjust when necessary; therefore, we prefer 3.2 ....

I trust that everyone will find this explanation acceptable...
If so, we can publish a [v2] patch.
Thanks, Steve