[U-Boot] zImage on ARM

Nicolas Pitre nicolas.pitre at linaro.org
Mon Sep 13 06:20:08 CEST 2010


On Sun, 12 Sep 2010, Wolfgang Denk wrote:

> In message <20100912150749.GB23760 at bee.dooz.org> you wrote:
> > > I don't see why uImages differ across boards - if the same kernel
> > > image can be used (i. e. the same zImage file use to generate the
> > > uImages) on these boards?
> > 
> >  Well, it was my understanding that different boards need different load
> >  addresses and/or different entry points; currently, for the same ARM
> >  SoC, it's mostly the same address.  But when you start building a
> >  single zImage targetting multiple SoCs, it might not be the case
> >  anymore.  (https://wiki.ubuntu.com/Specs/ARMSingleKernel)
> 
> Maybe this should/could be addressed on the Linux side then? We don't
> have such problems on PwerPC, for example.

On the Linux side, we currently have a fully position independent 
zImage.  So you already can load it anywhere in RAM and branch to it 
with an offset of 0 from where it is loaded.

> > > If you can come up with position independent payload, you still need
> > > the entry point (then probably in terms of offset relative to the
> > > current image address).

The entry point for an ARM kernel image is always at an offset of 0.

> >  Yes; but even with a position independent kernel, we need to know where
> >  in memory it should preferably be loaded (even if almost anywhere would
> >  work, there's a limited range or physical memory).
> 
> So you agree that in addition to the kexpnrel image we need information
> about the entry point and the load address. Um, well, that's exactly
> what uImage requires.  If this information is indeed needed, then
> what's the problem of creating an uImage?

We are working on the ability for a single kernel binary image to work 
on different SOCs.  However, on one SOC, the RAM is physically located 
at 0xc0000000, on another that might be 0x02000000, on another it is 
0x00000000, etc.  While zImage could be loaded at any of those addresses 
and executed there, in the uImage case the load address has to be 
provided at mkimage time.  That makes the distribution of a single 
uImage impossible for varied targets while distributing the 
corresponding zImage would just work.

> > > Patches to implement this (in the context of FIT images) are welcome.
> > 
> >  To make sure I got that right: you propose extending the uImage.FIT
> >  format to allow for a relative entry address instead of absolute load
> >  address + absolute entry point, correct?  That sounds like something
> >  useful indeed.
> 
> Well, I would not oppose such an extension if it's indeed usefult -
> which I doubt. If you give an absolute load address anyway, then there
> is basicly no difference between a relative or an absolute entry point
> address.

We need to be able to provide the load address at _load_ time instead of 
at _mkimage_ time.  In all cases, the entry point for the ARM kernel is 
always at offset 0 from the load address as mentioned above.

> >  My understanding of the ARM zImage uncompress code is that the entry
> >  point would basically be at offset zero once loaded in memory, for all
> >  targets/boards.
> 
> Can we not omit that code, and use the one we already have in U-Boot?
> Why increasing the Linux kernel image size (and thus flash footprint,
> load time, etc.) without need?

Sorry, I'm not following you here.

> >  I don't know enough about the ARM kernel's ramdisk code to comment on
> >  whether or not it could be uncompressed directly from flash into RAM;
> 
> It can. We've been doing this for many years. Just never managed to
> get the patches accepted for mainline.

And even better: rather than decompressing a ramdisk from flash, this is 
even more efficient to set an MTD partition for it and use the ramdisk 
content directly from flash as needed through the mtdblock device and 
not pin down memory for it needlessly.

Yet, the point of a ramdisk is to let the kernel decide at run time what 
driver it really needs to mount its root fs, and load the appropriate 
module just like desktop Linux is doing.  And that's what we're looking 
for here: equivalent of a desktop Linux on ARM.

> >  the way these are usually handled in Debian/Ubuntu so far is that the
> >  bootloader has a load command for the ramdisk from persistent storage
> >  to RAM (either NAND or MMC), then a load command for the kernel from
> >  persistent storage to RAM (either NAND or MMC), then calls the kernel
> >  entry point with the ramdisk address as an ATAG.  You could argue that
> >  we could also run zImage directly from flash, and let it unpack itself
> >  into RAM.  I suspect the reason it's not commonly done is because it's
> >  very specialized to flash and doesn't apply to e.g. MMC, but I don't
> >  really know for sure.

That's correct.  Decompressing a zImage directly from flash is good for 
specific embedded applications where boot time is critical.

> The reason we don't do that is that we use a bare Linux image, using
> U-Boot and it's uncompression code to load it from persistent storage
> to RAM and uncompress it on the fly.  This avoids a copy operation and
> should be faster in almost all cases.

... except in those specific cases for which the zImage in ROM was 
created.  But that's not a case that's interesting for us here anyway.

> >  Hmm ok; do you have some pointers/rationale?  It's interesting to
> >  gather past ideas and counter-arguments to try to improve the ARM boot
> >  architecture.
> 
> The most recent attempt can be seen here:
> http://thread.gmane.org/gmane.linux.ports.arm.kernel/53969
> 
> As before, RMK smashed this with his "I don't see any reason for this."

And I agree with him.  You don't need it because you may achieve better 
system resource usage by mapping an MTD block device onto a squashfs 
image instead.  And that would work for either NOR or NAND flash which 
is not the case for the patch referenced above.

> > > You may be aware that the implementation of the "bootm" command has
> > > been split into small building blocks some time ago. The idea was to
> > > allow for easy customizing, eventually even on command line level.
> > > You should be able to craft a custom boot command this way, which
> > > omits the header check.
> > 
> >  Ok; I wonder if we could just have an IMAGE_FORMAT_ZIMAGE and
> >  CONFIG_ZIMAGE instead?
> 
> You need a command to boot his image. "bootm" cannot be used as it
> tries to verify integrity of the images you pass to it, and extracts
> information about load address and entry point from it, too.
> 
> You need a command that does not do this, but eventually receives
> these parameters from somewhere else (command line?), but still passes
> all required information like ATAGs and/or device tree, kernel command
> line etc. to the image.

Exact!

> You might consider extending the bootelf
> command and relying on information passed in the ELF header (if you
> don't care to waste another 64 kB flash memory footprint for the
> image, IIRC).

We don't have an ELF image.  We want to have the option of booting a 
zImage.

> > > But I don't think that this solves your problem - you still need
> > > information at least about the entry point address, which then has to
> > > be stored separate from the image file, which just shifts the problem
> > > to another area.
> > 
> >  Isn't it always at offset 0 for an ARM zImage payload?
> 
> I don't know. 

Yes it is.

> >  The main thing I'd like the bootloader to keep track of is the physical
> >  load address at which to load the kernel; usually this is 0x8000 when
> >  possible.  I am not sure it needs to track anything else.
> 
> On most ARM systems 0x8000 is in the ROM address space; I wonder if
> you talk about an address offset relative to the begin of system RAM
> rather than an absolute physical address?

On many ARM systems the ROM is not at 0.  In those cases the hardware 
makes a part of the ROM visible at 0xffff0000 where the high reset 
vector is.

But regardless of that detail, it would be a good thing to have if we 
could script something like:

	load zImage 0x00008000
	bootz 0x00008000

The first command would load a zImage from wherever and put it at 
0x00008000 in RAM.  I think this can already be achieved with the 
standard U-Boot load command.

The second command would prepare the ATAGs as usual and boot the kernel 
known to be at 0x00008000.


Nicolas


More information about the U-Boot mailing list