[REGRESSION] imx: spl_imx_romapi: boot loops

Rasmus Villemoes rasmus.villemoes at prevas.dk
Tue Oct 24 16:32:27 CEST 2023


On 24/10/2023 15.15, Marcel Ziswiler wrote:

Hi Marcel

tl;dr: can you try

@@ -330,7 +335,7 @@ static int spl_romapi_load_image_stream(struct
spl_image_info *spl_image,

                ss.base = phdr;
                ss.end = p;
-               ss.pagesize = pagesize;
+               ss.pagesize = 1024;

                memset(&load, 0, sizeof(load));
                load.bl_len = 1;

and also put 1024 in the binman node so u-boot.itb is also 1024-byte
aligned?

This will likely break usb boot (where pagesize==1), so if you want the
binary to work with usb you can make the RHS instead "(pagesize > 1 ?
1024 : 1)" or something like that.

I don't think it will work, but OTOH my analysis below doesn't find any
other (fundamental) difference between the old and new code.

> 
> On Tue, 2023-10-24 at 13:17 +0200, Rasmus Villemoes wrote:
> 
>>
>> and this works just fine. But in my case ss->pagesize is 1, whereas you
>> have 512.
>>
>> Just exactly how are you booting? It says "Boot Stage: Primary boot"
>> whereas I'm doing serial download with uuu (i.e. "Boot Stage: USB boot").
> 
> Yes, regular eMMC boot.

[snip]

> 
> At least I am not aware that we would be doing anything special for eMMC boot.

Well, I/we usually do boot from eMMC (except during bootstrap where we
use uuu), more precisely from the eMMC boot partitions, but that doesn't
end up using the spl_romapi_load_image_stream() but instead the expected
spl_romapi_load_image_seekable().

Perhaps some NXP folks can explain the logic behind

static int is_boot_from_stream_device(u32 boot)
{
	u32 interface;

	interface = boot >> 16;
	if (interface >= BT_DEV_TYPE_USB)
		return 1;

	if (interface == BT_DEV_TYPE_MMC && (boot & 1))
		return 1;

	return 0;
}

Apparently that "boot & 1" is an indication that "eMMC fast boot mode"
is enabled (not to be confused with fastboot which is a USB protocol
that only becomes relevant once U-Boot proper is up and running).

As I've complained about previously, the ROM API is almost entirely
undocumented. There's something in imx93rm.pdf (which is where I have
that eMMC fast boot info from), but I have no idea if that applies to
imx8/imx8mp as well.

Are there any alignment requirements on the destination and/or the size
parameter? Is there some timing requirements so that if we read too late
the data is lost? So could e.g. a bunch of printf debugging break boot?

Because I really can't see the fundamental difference between now and
then. Both before and after the commit in question, the code does:

- read 1024 bytes at a time, search each chunk for FDT magic

This then gives the "Find img info 0x4802b000"

- make sure the leftover within that 1024 chunk is a full FDT header
(usually ok, so no output)

- read the FDT size from that header, round up to a multiple of 1024,
fetch that - that's the "Need continue download 1024".

And then the flow deviates.

The old code would do the fake spl_fit_load to figure out the maximum
offset (thus the real total .itb size), then take that remaining size,
round up to ->pagesize (512), and fetch that with one final
rom_api_download_image(p, 0, imagesize);.

My code instead does a number of rom_api_download_image() calls, where
each size argument is rounded up to the ->pagesize from the boot_info
query (i.e. 512). So it's possible that for one of those calls, the
destination is only 512-byte aligned (because a previous call fetched an
odd number of 512 byte blocks), and that doesn't happen in the previous
case where all but the last rom_api_download_image() have fetched 1024
byte aligned chunks.

What am I missing?

Rasmus



More information about the U-Boot mailing list