On Tue, Feb 24, 2026 at 04:57:10PM +0100, Ludwig Nussel wrote: > FIT images don't work without having to explicitly specify physical > load addresses. Digging into that it looks like a flaw in > bootm_load_os(). > It duplicates images->os for convenience. However, the code handling > "kernel_noload" images then updates the load address in the copy with > the value lmb_alloc_mem() returned. Later there's another call to > lmb_alloc_mem() that uses the old value. This leads to havoc due > to subsequent calls of lmb_alloc_mem() picking too low addresses. > > The "fix" is to mark the local variable const to avoid accidental > assignments. This works but IMO the logic is still flawed somehow as > this leads to overlapping lmb reservations. I guess the fixed > reservation should only be done when the noload path wasn't hit. > > Without the change: > + bootm 0x40200000#qemu-arm 0x40200000#qemu-arm 0x40000000 > Using 'qemu-arm' configuration > Verifying Hash Integrity ... OK > Trying 'kernel' kernel subimage > Description: Linux kernel > Created: 2026-02-24 14:10:09 UTC > Type: Kernel Image (no loading done) > Compression: gzip compressed > Data Start: 0x402000b8 > Data Size: 12227440 Bytes = 11.7 MiB > Hash algo: sha256 > Hash value: 7ea661fdecdd1127edd419cfbf8bff52e2d5ac55c... > Verifying Hash Integrity ... sha256+ OK > Using 'qemu-arm' configuration > Verifying Hash Integrity ... OK > Trying 'ramdisk' ramdisk subimage > Description: Initial ramdisk > Created: 2026-02-24 14:10:09 UTC > Type: RAMDisk Image > Compression: uncompressed > Data Start: 0x40da9528 > Data Size: 1067114 Bytes = 1 MiB > Architecture: AArch64 > OS: Linux > Load Address: unavailable > Entry Point: unavailable > Hash algo: sha256 > Hash value: 2a711dcb5f58615187645ccec615c67eddcfbb3138... > Verifying Hash Integrity ... sha256+ OK > Booting using the fdt blob at 0x40000000 > Working FDT set to 40000000 > Uncompressing Kernel Image (no loading done) to 13a400000 > Loading Ramdisk to 400fb000, end 401ff86a ... OK > device tree - allocation error > FDT creation failed! > resetting ... > Bloblist at 0 not found (err=-2) > alloc space exhausted ptr 400 limit 0 > Bloblist at 0 not found (err=-2) > [reset] > > After: > + bootm 0x40200000#qemu-arm 0x40200000#qemu-arm 0x40000000 > Using 'qemu-arm' configuration > Verifying Hash Integrity ... OK > Trying 'kernel' kernel subimage > Description: Linux kernel > Created: 2026-02-24 14:10:09 UTC > Type: Kernel Image (no loading done) > Compression: gzip compressed > Data Start: 0x402000b8 > Data Size: 12227440 Bytes = 11.7 MiB > Hash algo: sha256 > Hash value: 7ea661fdecdd1127edd419cfbf8bff52e2d5ac55ce... > Verifying Hash Integrity ... sha256+ OK > Using 'qemu-arm' configuration > Verifying Hash Integrity ... OK > Trying 'ramdisk' ramdisk subimage > Description: Initial ramdisk > Created: 2026-02-24 14:10:09 UTC > Type: RAMDisk Image > Compression: uncompressed > Data Start: 0x40da9528 > Data Size: 1067114 Bytes = 1 MiB > Architecture: AArch64 > OS: Linux > Load Address: unavailable > Entry Point: unavailable > Hash algo: sha256 > Hash value: 2a711dcb5f58615187645ccec615c67eddcfbb3138... > Verifying Hash Integrity ... sha256+ OK > Booting using the fdt blob at 0x40000000 > Working FDT set to 40000000 > Uncompressing Kernel Image (no loading done) to 13a400000 > Loading Ramdisk to 13a2fb000, end 13a3ff86a ... OK > Loading Device Tree to 000000013a1f8000, end 000000013a2fafff ... OK > Working FDT set to 13a1f8000 > > Starting kernel ... > > Signed-off-by: Ludwig Nussel <[email protected]>
Interesting. This works fine today on for example Pi 4 (with a few
additional options enabled):
U-Boot> tftpboot 200000 v6.13/image.fit.arm64
Using ethernet@7d580000 device
TFTP from server 192.168.1.10; our IP address is 192.168.1.119
Filename 'v6.13/image.fit.arm64'.
Load address: 0x200000
Loading: ################################################## 27.3 MiB
8.3 MiB/s
done
Bytes transferred = 28574720 (1b40400 hex)
U-Boot> U-Boot> crc32 200000 $filesize
crc32 for 00200000 ... 01d403ff ==> 8513595c
U-Boot> U-Boot> bootm 200000
## Loading kernel (any) from FIT Image at 00200000 ...
Using 'conf-243' configuration
Verifying Hash Integrity ... OK
Trying 'kernel' kernel subimage
Description: Linux-6.13.0-dirty
Type: Kernel Image (no loading done)
Compression: gzip compressed
Data Start: 0x00200138
Data Size: 14546728 Bytes = 13.9 MiB
Verifying Hash Integrity ... OK
## Loading fdt (any) from FIT Image at 00200000 ...
Using 'conf-243' configuration
Verifying Hash Integrity ... OK
Trying 'fdt-243' fdt subimage
Description: bcm2711-rpi-4-b.dtb
Type: Flat Device Tree
Compression: gzip compressed
Data Start: 0x01136f5c
Data Size: 9334 Bytes = 9.1 KiB
Architecture: AArch64
Verifying Hash Integrity ... OK
Uncompressing Flat Device Tree to 3afbfc00
Booting using the fdt blob at 0x3afbfc00
Working FDT set to 3afbfc00
Uncompressing Kernel Image (no loading done) to 36400000
Loading Device Tree to 00000000001f3000, end 00000000001ffb11 ... OK
Working FDT set to 1f3000
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
...
So one thing I'd like to know is what makes your case different, so that
we can catch it in testing in the future.
> ---
> boot/bootm.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/boot/bootm.c b/boot/bootm.c
> index 4bdca22ea8c..280efb26e90 100644
> --- a/boot/bootm.c
> +++ b/boot/bootm.c
> @@ -602,7 +602,7 @@ static int handle_decomp_error(int comp_type, size_t
> uncomp_size,
> #ifndef USE_HOSTCC
> static int bootm_load_os(struct bootm_headers *images, int boot_progress)
> {
> - struct image_info os = images->os;
> + const struct image_info os = images->os;
> ulong load = os.load;
> ulong load_end;
> ulong blob_start = os.start;
> @@ -631,7 +631,7 @@ static int bootm_load_os(struct bootm_headers *images,
> int boot_progress)
> return 1;
>
> load = (ulong)addr;
> - os.load = (ulong)addr;
> + images->os.load = (ulong)addr;
> images->ep = (ulong)addr;
> debug("Allocated %lx bytes at %lx for kernel (size %lx)
> decompression\n",
> req_size, load, image_len);
With a bit more context, the first thing we do after declaring variables
is check for the noload case and set all of "load", "os.load" and
"images->ep" to the location lmb_alloc_mem allocated for us which is the
code here in the second hunk.
This part at the end of bootm_load_os:
if (CONFIG_IS_ENABLED(LMB)) {
phys_addr_t load;
load = (phys_addr_t)images->os.load;
err = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &load,
(load_end - images->os.load), LMB_NONE);
if (err) {
log_err("Unable to allocate memory %#lx for loading
OS\n",
images->os.load);
return 1;
}
}
Is indeed a little odd looking, starting with I would have expected the
compiler to complain about re-declaring "load". But yes, this part here
should not be re-reading images->os.load.
I'm guessing in your failure case we're doing some huge allocation this
second time here and that's why there's not space later on for the
device tree? But it's also a little odd that in your ramdisk is now
being moved around, but perhaps that's because we detected an overlap
now? Can you share how exactly you're making this failure happen please?
Thanks.
--
Tom
signature.asc
Description: PGP signature

