[PATCH] env: Leave invalid env for nowhere location
Kunihiko Hayashi
hayashi.kunihiko at socionext.com
Thu Jun 10 10:25:26 CEST 2021
Hi Marek,
On 2021/06/10 10:07, Marek Vasut wrote:
> On 6/8/21 9:54 AM, Kunihiko Hayashi wrote:
>
> Hi,
>
> [...]
>
>>>>>>> I would expect that after relocation, if all you have is env_nowhere
>>>>>>> driver, the env_nowhere_init() is called again from the first for() loop
>>>>>>> of env_init() [1], which would set gd->env_valid to ENV_INVALID [1], and
>>>>>>> that for() loop would exit with ret = -ENOENT [2], so then the last part
>>>>>>> of env_init() would check for ret == -ENOENT and update gd->env_addr to
>>>>>>> relocated default_environment [3].
>>>>>>>
>>>>>>> 324 int env_init(void)
>>>>>>> 325 {
>>>>>>> 326 struct env_driver *drv;
>>>>>>> 327 int ret = -ENOENT;
>>>>>>> 328 int prio;
>>>>>>> 329
>>>>>>> 330 for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
>>>>>>> /* Part [1] */
>>>>>>> 331 if (!drv->init || !(ret = drv->init()))
>>>>>>> 332 env_set_inited(drv->location);
>>>>>>> 333 if (ret == -ENOENT)
>>>>>>> 334 env_set_inited(drv->location);
>>>>>>> 335
>>>>>>> 336 debug("%s: Environment %s init done (ret=%d)\n", __func__,
>>>>>>> 337 drv->name, ret);
>>>>>>> 338
>>>>>>> /* Part [2] */
>>>>>>> 339 if (gd->env_valid == ENV_INVALID)
>>>>>>> 340 ret = -ENOENT;
>>>>>>> 341 }
>>>>>>> 342
>>>>>>> 343 if (!prio)
>>>>>>> 344 return -ENODEV;
>>>>>>> 345
>>>>>>> /* Part [3] */
>>>>>>> 346 if (ret == -ENOENT) {
>>>>>>> /* This should be relocated default_environment address */
>>>>>>> 347 gd->env_addr = (ulong)&default_environment[0];
>>>>>>> 348 gd->env_valid = ENV_VALID;
>>>>>>> 349
>>>>>>> 350 return 0;
>>>>>>> 351 }
>>>>>>> 352
>>>>>>> 353 return ret;
>>>>>>> 354 }
>>>>>>>
>>>>>>> Or am I missing something obvious ?
>>>>>>
>>>>>> These are called before relocation, and update gd->env_addr to non-relocated
>>>>>> default_environment by [3].
>>>>>>
>>>>>> After that, gd->env_addr is relocated in initr_reloc_global_data()
>>>>>> if CONFIG_SYS_RELOC_GD_ENV_ADDR is defined.
>>>>>>
>>>>>> | #ifdef CONFIG_SYS_RELOC_GD_ENV_ADDR
>>>>>> | /*
>>>>>> | * Relocate the early env_addr pointer unless we know it is not inside
>>>>>> | * the binary. Some systems need this and for the rest, it doesn't hurt.
>>>>>> | */
>>>>>> | gd->env_addr += gd->reloc_off;
>>>>>> | #endif
>>>>>>
>>>>>
>>>>> Shouldn't the post-relocation env update happen in env_relocate() ?
>>>>
>>>> Usually env_relocate() calls env_load() that uses relocated gd->env_addr.
>>>> It's no problem.
>>>>
>>>> If CONFIG_SYS_TEXT_BASE is zero, gd->reloc_off becomes illegal.
>>>> CONFIG_SYS_RELOC_GD_ENV_ADDR should be disabled in that case.
>>
>> Sorry this isn't wrong.
>>
>>> But then, if CONFIG_SYS_TEXT_BASE is zero, the env shouldn't be relocated or how should it
>>> behave ?
>>
>> I think the env should be relocated if CONFIG_SYS_RELOC_GD_ENV_ADDR=y
>> regardless of CONFIG_SYS_TEXT_BASE.
>>
>> If CONFIG_POSITION_INDEPENDENT=y and CONFIG_SYS_TEXT_BASE is zero,
>> there is something wrong with the calculation of the relocation address about env.
>
> Ah, got it.
>
>> gd->reloc_off is relocated address offset from zero, however,
>> gd->env_addr has still non-relocated address.
>>
>> >>>> | gd->env_addr += gd->reloc_off;
>>
>> I think the env should be relocated if CONFIG_SYS_RELOC_GD_ENV_ADDR=y.
>> But this code sets gd->env_addr incorrectly.
>>
>> In that case, there is a non-relocated <textbase> address instead of
>> CONFIG_SYS_TEXT_BASE.
>>
>> This should be "gd->env_addr = (gd->env_addr - <textbase>) + gd->reloc_off",
>> However, I'm not sure how we get non-relocated <textbase> address.
>
> Maybe what you need to do is store current $pc register when you enter U-Boot very early on, in
> _start function, and then use it here ? Although, I am not entirely sure whether this is still
> possible on arm64.
Exactly. I guess it's reasonable to fix gd->env_addr when POSITION_INDEPENDENT=y
before relocation. I'll try it.
Thank you,
---
Best Regards
Kunihiko Hayashi
More information about the U-Boot
mailing list