[U-Boot] Booting uncompressed uImages

Hi all,
I've got an interesting issue with a MIPS board I'm working on. The uncompressed uImage has been created with a Load Address of 0x80500000 and an Entry Point of 0x80504590. This gets TFTP's into RAM at 0x8055b728. When I run a "bootm 0x8055b728" this image fails to run. Tracing through the code, I see that in bootm_load_os() it follows the IH_COMP_NONE path for non XIP images. This should copy the uImage to the load address so it can be executed.
However, the copy command is : memmove_wd ((void *)load, (void *)image_start, image_len, CHUNKSZ);
This actually copies the image 'payload' instead of the whole uImage thereby dropping 64 bytes from the front of the copy and moving the entry point. (I've verified this by breaking into the process and looking at the source and destinations of the copy and comparing to an XIP bootm invocation) I've scratched my head as I'm really surprised that it behaves this way with a zillion boards out there, BUT from digging via google it seems that the world and his/her dog nearly always use the same address for both load address and entry point which subsequently masks this behaviour in that particular case. I've verified that if I change to : memmove_wd ((void *)load, (void *)blob_start, image_len + (blob_end - blob_start), CHUNKSZ); Then the kernel boot works as I'd expect it to.
Can anyone sanity-check my reasoning here and tell me if this is the correct fix or if I'm being mislead by something more insidious that just happens to present itself in this way....?
Cheers!
~Pev

Dear David Peverley,
In message BANLkTikRLXMdZoWUwR0wDnUzGM8mPEcAqQ@mail.gmail.com you wrote:
I've got an interesting issue with a MIPS board I'm working on. The uncompressed uImage has been created with a Load Address of 0x80500000 and an Entry Point of 0x80504590. This gets TFTP's into RAM at 0x8055b728. When I run a "bootm 0x8055b728" this image fails to run.
Why using such an odd address as 0x8055b728?
Please be aware that is just 365 KB above your load address, and I guess your kernel image is way bigger than 365 KB.
This actually copies the image 'payload' instead of the whole uImage thereby dropping 64 bytes from the front of the copy and moving the entry point. (I've verified this by breaking into the process and
It does not "move the entry point". The entry point address is a constant address and does never move.
Can anyone sanity-check my reasoning here and tell me if this is the correct fix or if I'm being mislead by something more insidious that just happens to present itself in this way....?
Just follow the rules and never download the image to an address range that overlaps with the area where the image will be unpacked / loaded to.
Best regards,
Wolfgang Denk

Hi Wolfgang,
Thanks for the reply!
Why using such an odd address as 0x8055b728?
That is a symptom of the system I'm working on...!
Just follow the rules and never download the image to an address range that overlaps with the area where the image will be unpacked / loaded to.
I'd wondered if that was the case originally and tested this by changing the download address to +32MB higher. This behaved with exactly the same failure so I think that while it's a more sensible thing to do it's a red herring with regards to what I'm seeing with the memmove().
Please be aware that is just 365 KB above your load address, and I guess your kernel image is way bigger than 365 KB.
Yep, I'm aware of this but I'm not keen to meddle too much with an existing working system! Despite it being a bit dubious (and most likely a failure if a compressed image) it works due to the way that for uncompressed images memmove_wd() is implemented in that it copies in smallish chunks and hence doesn't overwrite itself.
This actually copies the image 'payload' instead of the whole uImage thereby dropping 64 bytes from the front of the copy and moving the entry point. (I've verified this by breaking into the process and
It does not "move the entry point". The entry point address is a constant address and does never move.
If I add some debugging, I find that in the situation previously mentioned (and equivalently if I download higher too, see above) what happens is that in bootm_load_os() I find that at the point we reach the memmove_wd() to move the uncompressed image : load_start = 0x8055b798 image_len = 0x4c11c0 blob_start = 0x8055b758 blob_end = 0x80a1c958 because the memmove_wd() is called to copy to load_start, as you can see this copies from 64 bytes above the start of the uImage. Because of this the whole image shifts down by 64 bytes relative to the loadaddr compared to if we'd manually downloaded the uImage to the load address (Also, note the value of image len - the actual size of the uImage is 0x4c1200 - i.e. the same as blob_end - blob_start)
This logic looks like : if (load == blob_start) { printf (" XIP %s ... ", type_name); } else { printf (" Loading %s ... ", type_name); memmove_wd ((void *)load, (void *)image_start, image_len, CHUNKSZ); } The logic here checks (load == blob_start) for XIP i.e. that the blob state resides at the load address. Following this logic in isolation, why does the memmove_wd() move the image to image_start instead of blob_start if we want that to be at loadaddr as in the first check for XIP? My understanding is that after this logic the uImage should reside at exactly the same location whether you have followed either the if or the else path...?
Having said that, I just checked one of our non mips boards (ARM1176) and it seems to handle this same situation OK so I'm wondering if it's something peculiar to the port we're working with or perhaps the MIPS code...? My guess is that maybe it's something kernel related rather than in u-boot.
Cheers,
~Pev

On Wednesday, June 15, 2011 13:00:32 David Peverley wrote:
I've got an interesting issue with a MIPS board I'm working on. The uncompressed uImage has been created with a Load Address of 0x80500000 and an Entry Point of 0x80504590. This gets TFTP's into RAM at 0x8055b728.
if it's uncompressed, why not simply load it to the final address in the first place ? then bootm wont have to do any memcpy, it can simply jump to the entry point. -mike

Hi Mike,
Thanks for the reply.
if it's uncompressed, why not simply load it to the final address in the first place ? then bootm wont have to do any memcpy, it can simply jump to the entry point.
In our system we use a software update mechanism where the kernel + initfs images reside in a 'package' in NAND which gets downloaded to ram first by an initial loader so that it can be verified (CRC + a cryptographic hash). This means that the sections containing the kernel are already in RAM somewhere other than the load address...! Admittedly, the mechanism could have been designed so that taking headers into account the uImage was always at a known offset but this wasn't the way it was designed unfortunately.
Cheers,
~Pev
participants (3)
-
David Peverley
-
Mike Frysinger
-
Wolfgang Denk