Why Using a Uimage Instead of a Zimage

Image vs zImage vs uImage


What is the difference between them?

Image: the generic Linux kernel binary image file.

zImage: a compressed version of the Linux kernel image that is self-extracting.

uImage: an image file that has a U-Boot wrapper (installed by the mkimage utility) that includes the OS type and loader information.

A very common practice (e.g. the typical Linux kernel Makefile) is to use a zImage file. Since a zImage file is self-extracting (i.e. needs no external decompressors), the wrapper would indicate that this kernel is "not compressed" even though it actually is.


Note that the author/maintainer of U-Boot considers the (widespread) use of using a zImage inside a uImage questionable:

Actually it's pretty stupid to use a zImage inside an uImage. It is
much better to use normal (uncompressed) kernel image, compress it
using just gzip, and use this as poayload for mkimage. This way
U-Boot does the uncompresiong instead of including yet another
uncompressor with each kernel image.

(quoted from https://lists.yoctoproject.org/pipermail/yocto/2013-October/016778.html)


Which type of kernel image do I have to use?

You could choose whatever you want to program for.

For economy of storage, you should probably chose a compressed image over the uncompressed one.

Beware that executing the kernel (presumably the Linux kernel) involves more than just loading the kernel image into memory. Depending on the architecture (e.g. ARM) and the Linux kernel version (e.g. with or without DTB), there are registers and memory buffers that may have to be prepared for the kernel. In one instance there was also hardware initialization that U-Boot performed that had to be replicated.

ADDENDUM

I know that u-boot needs a kernel in uImage format.

That is accurate for all versions of U-Boot which only have the bootm command.

But more recent versions of U-Boot could also have the bootz command that can boot a zImage.

Why using a uImage instead of a zImage


In my understanding uImage is got by running mkimage on the Image

Your understanding is only partly correct.

A uImage can contain any type of file, and is not restricted to the Linux Image file. In fact it not likely to be the (uncompressed) Image file (since that is not a conventional make option).

In the other hand the zImage is the compressed Image, it doesn't contain the load address and entry point(what i think, correct me if i'am [sic] wrong)

You're incorrect, the zImage does contain the kernel's load address and entry point. The load address is needed in order to decompress the kernel Image to the proper RAM address. The kernel's entry point is needed to execute it after it has been decompressed.

When building the Image and zImage for ARM, the Makefiles use

ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)

which should translate to the start of physical memory + 0x8000.

The zImage itself (i.e. the self-extraction program) is PIC, position independent code. The zImage can be loaded anywhere in RAM, and executed at its first address, i.e. its entry point is its load address.

In this case why using a uImage instead of a zImage?

For older versions of U-Boot, there was no choice since the bootz command may not have been available for Linux kernels.

Nowadays it may be a subjective choice.

Note that there has been some resentment in the Linux kernel community towards the support of U-Boot in the kernel. IOW if some people had their way, I get the impression that you would not be able to build a uImage from the mainline source.

I'am [sic] curious to learn what are the formats of a zImage and a uImage could you please suggest some references ?

The layout of the zImage is essentially given by its linker specification.

For ARM see arch/arm/boot/compressed/vmlinux.lds.S.

Note that _magic_start contains a meaningless load address. This is also mentioned in Section 5 of Vincent Sanders' Booting ARM Linux

The zImage has a magic number and some useful information near its beginning.

Table 2. Useful fields in zImage head code
Offset into zImage Value Description
0x24 0x016F2818 Magic number used to identify this is an ARM Linux zImage
0x28 start address The address the zImage starts at
0x2C end address The address the zImage ends at

The start and end offsets can be used to determine the length of the compressed image (size = end - start).
...
The start address is usually 0 as the zImage code is position independent.

Note however that the ARM booting requirements have been superseded by Russel King's Documentation/arm/booting

The layout of a uImage is simply the U-Boot header plus the image file, whatever that may be.

(Hopefully nothing I wrote contradicts what Tom Rini wrote.)

LEDE: The uImage compress type not supported

The message seems to indicate that whatever boot program that you're using to load the Linux kernel does not have any decompression capability.

Therefore instead of expecting the boot program to perform the decompression, you need to build a kernel image that is self-decompressing, i.e. a zImage.

If you insist, you can wrap the zImage in a uImage header, but since the zImage is self-extracting the image needs to be marked as "uncompressed".

Note that the file type uImage is produced by the U-Boot utility mkimage, and this type of image is for the benefit of U-Boot.

Other boot programs may or may not recognize a uImage.

Boot programs for ARM are expected to support zImage.

Your post is sparse in terms of details.

If all you did was select XZ instead of the default gzip for the Kernel compression mode in the kernel's menuconfig, and did build a zImage, then the mkimage was used with incorrect arguments.

A zImage within a uImage must be marked as "uncompressed".

How to build uImage?

Install u-boot-tools. The command depends on your distribution. If you are using Debian/Ubuntu, it should look like

sudo apt-get install u-boot-tools

See U-Boot documentation on tool installation


make uImage

mkimage -A <arch> -O linux -T kernel -C none -a <load-address> -e <entry-point> -n "Linux kernel" -d arch/arm/boot/zImage uImage

or in the kernel source

make uImage

U-Boot error while decompressing gzipped kernel

First U-Boot copies the uImage from NAND to RAM at the specified address 0x80100000. Then it unpacks the kernel to the load address specified in the uImage header, 0x80008000.

Since our kernel is about 8 MB uncompressed, that means the kernel's memory from 0x80008000 to approximately 0x80800000 overlaps where we copied the uImage at 0x80100000.

If the uImage is not compressed, unpacking the kernel can use memmove which handles overlapping address ranges without issue. (If the load address is the address where we copied it in RAM, the kernel gets executed in-place.)

But for compressed uImages, if we overwrite the compressed data while decompressing, decompression will obviously fail.



Related Topics



Leave a reply



Submit