[U-Boot] [PATCH v2 08/10] bootstage: Correct relocation algorithm
Heinrich Schuchardt
xypron.debian at gmx.de
Sat Jan 25 09:59:21 CET 2020
On 10/22/19 1:26 AM, Simon Glass wrote:
> At present bootstage relocation assumes that it is possible to point back
> to memory available before relocation, so it does not relocate the
> strings. However this is not the case on some platforms, such as x86 which
> uses the cache as RAM and loses access to this when the cache is enabled.
>
> Move the relocation step to before U-Boot relocates, expand the allocated
> region to include space for the strings and relocate the strings at the
> same time as the bootstage records.
>
> This ensures that bootstage data can remain accessible from TPL through
> SPL to U-Boot before/after relocation.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
Hello Simon,
this merged patch seems to be incorrect. I compiled sandbox_defconfig
with clang and ran it with valgrind.
We allocate memory in bootstage_init() for gd->bootstage. But from
bootstage_get_size() we return a size that is larger than what we have
allocated and use that larger memory area in reloc_bootstage(). See
output below.
sudo docker pull trini/u-boot-gitlab-ci-runner:bionic-20200112-17Jan2020
sudo docker run -it 2e501a804876 /bin/bash
cd ~
git clone https://gitlab.denx.de/u-boot/u-boot.git
cd u-boot
sudo apt-get update
sudo apt-get install clang valgrind
make CC=clang HOSTCC=clang sandbox_defconfig
make CC=clang HOSTCC=clang -j8
valgrind ./u-boot -d arch/sandbox/dts/test.dtb
==89423== Memcheck, a memory error detector
==89423== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==89423== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==89423== Command: ./u-boot -d arch/sandbox/dts/test.dtb
==89423==
U-Boot 2020.01-00812-gc98c2b07e5 (Jan 25 2020 - 07:36:12 +0000)
Model: sandbox
DRAM: 128 MiB
==89423== Invalid read of size 8
==89423== at 0x4D4E90: memcpy (string.c:543)
==89423== by 0x424F88: reloc_bootstage (board_f.c:702)
==89423== by 0x424B22: initcall_run_list (initcall.h:40)
==89423== by 0x424B22: board_init_f (board_f.c:1019)
==89423== by 0x402755: main (start.c:386)
==89423== Address 0xa66f4e8 is 0 bytes after a block of size 968 alloc'd
==89423== at 0x4C2FB0F: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==89423== by 0x42E740: bootstage_init (bootstage.c:522)
==89423== by 0x424B84: initf_bootstage (board_f.c:806)
==89423== by 0x424B22: initcall_run_list (initcall.h:40)
==89423== by 0x424B22: board_init_f (board_f.c:1019)
==89423== by 0x402755: main (start.c:386)
==89423==
==89423== Invalid read of size 8
==89423== at 0x4D4EA4: memcpy (string.c:542)
==89423== by 0x424F88: reloc_bootstage (board_f.c:702)
==89423== by 0x424B22: initcall_run_list (initcall.h:40)
==89423== by 0x424B22: board_init_f (board_f.c:1019)
==89423== by 0x402755: main (start.c:386)
==89423== Address 0xa66f4f0 is 8 bytes after a block of size 968 alloc'd
==89423== at 0x4C2FB0F: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==89423== by 0x42E740: bootstage_init (bootstage.c:522)
==89423== by 0x424B84: initf_bootstage (board_f.c:806)
==89423== by 0x424B22: initcall_run_list (initcall.h:40)
==89423== by 0x424B22: board_init_f (board_f.c:1019)
==89423== by 0x402755: main (start.c:386)
==89423==
WDT: Started with servicing (60s timeout)
MMC: mmc2: 2 (SD), mmc1: 1 (SD), mmc0: 0 (SD)
In: serial
Out: vidconsole
Err: vidconsole
Model: sandbox
SCSI:
Net: eth0: eth at 10002000, eth5: eth at 10003000, eth3: sbe5, eth1:
eth at 10004000
Hit any key to stop autoboot: 0
=>
Best regards
Heinrich
> ---
>
> Changes in v2: None
>
> common/board_f.c | 1 +
> common/board_r.c | 1 -
> common/bootstage.c | 25 ++++++++++++++++++++++---
> 3 files changed, 23 insertions(+), 4 deletions(-)
>
> diff --git a/common/board_f.c b/common/board_f.c
> index 4852a3b0d84..e3591cbaebd 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -696,6 +696,7 @@ static int reloc_bootstage(void)
> gd->bootstage, gd->new_bootstage, size);
> memcpy(gd->new_bootstage, gd->bootstage, size);
> gd->bootstage = gd->new_bootstage;
> + bootstage_relocate();
> }
> #endif
>
> diff --git a/common/board_r.c b/common/board_r.c
> index d6fb5047a26..c1ecb06b743 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -670,7 +670,6 @@ static init_fnc_t init_sequence_r[] = {
> #ifdef CONFIG_SYS_NONCACHED_MEMORY
> initr_noncached,
> #endif
> - bootstage_relocate,
> #ifdef CONFIG_OF_LIVE
> initr_of_live,
> #endif
> diff --git a/common/bootstage.c b/common/bootstage.c
> index 4557ed4508c..e8b7bbf81a6 100644
> --- a/common/bootstage.c
> +++ b/common/bootstage.c
> @@ -53,14 +53,23 @@ int bootstage_relocate(void)
> {
> struct bootstage_data *data = gd->bootstage;
> int i;
> + char *ptr;
> +
> + /* Figure out where to relocate the strings to */
> + ptr = (char *)(data + 1);
>
> /*
> * Duplicate all strings. They may point to an old location in the
> * program .text section that can eventually get trashed.
> */
> debug("Relocating %d records\n", data->rec_count);
> - for (i = 0; i < data->rec_count; i++)
> - data->record[i].name = strdup(data->record[i].name);
> + for (i = 0; i < data->rec_count; i++) {
> + const char *from = data->record[i].name;
> +
> + strcpy(ptr, from);
> + data->record[i].name = ptr;
> + ptr += strlen(ptr) + 1;
> + }
>
> return 0;
> }
> @@ -490,7 +499,17 @@ int bootstage_unstash(const void *base, int size)
>
> int bootstage_get_size(void)
> {
> - return sizeof(struct bootstage_data);
> + struct bootstage_data *data = gd->bootstage;
> + struct bootstage_record *rec;
> + int size;
> + int i;
> +
> + size = sizeof(struct bootstage_data);
> + for (rec = data->record, i = 0; i < data->rec_count;
> + i++, rec++)
> + size += strlen(rec->name) + 1;
> +
> + return size;
> }
>
> int bootstage_init(bool first)
>
More information about the U-Boot
mailing list