This is a quick post to share my experience booting uncompressed Linux kernel images, during the benchmarks of kernel compression options, and no compression at all was one of these options.
It is sometimes useful to boot a kernel image with no compression. Though the kernel image is bigger, and takes more time to copy from storage to RAM, the kernel image no longer has to be decompressed to RAM. This is useful for systems with a very slow CPU, or very little RAM to store both the compressed and uncompressed images during the boot phase. The typical case is booting CPUs emulated by FPGA, during processor development, before the final silicon is out. For example, I saw a Cortex A15 chip boot at 11 MHz during Linaro Connect Q2.11 in Budapest. At this clock frequency, booting a kernel image with no compression saves several minutes of boot time, reducing development and test time. Note that with such hardware emulators, copying the kernel image to RAM is cheap, as it is done by the emulator from a file given by the user, before starting to emulate the system.
Building a kernel image with no compression on ARM is easy, but only once you know where the uncompressed image is and what to do! For people who have never done that before, I’m sharing quick instructions here.
To generate your uncompressed kernel image, all you have to do is run the usual
make command. The file that you need is
Depending on the bootloader that you use, this could be sufficient. However, if you use U-boot, you still need to put this image in a
uImage container, to let U-boot know about details such as how big the image is, what its entry point is, whether it is compressed or not… The problem is you can’t run
make uImage any more to produce this container. That’s because Linux on ARM has no configuration option to keep the kernel uncompressed, and the
uImage file would contain a compressed kernel.
Therefore, you have to create the
uImage by invoking the
mkimage command manually. To do this without having to guess the right
mkimage parameters, I recommend to run
make V=1 uImage once:
$ make V=1 uImage ... Kernel: arch/arm/boot/zImage is ready /bin/bash /home/mike/linux/scripts/mkuboot.sh -A arm -O linux -T kernel -C none -a 0x80008000 -e 0x80008000 -n 'Linux-3.3.0-rc6-00164-g4f262ac' -d arch/arm/boot/zImage arch/arm/boot/uImage Image Name: Linux-3.3.0-rc6-00164-g4f262ac Created: Thu Mar 8 13:54:00 2012 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3351272 Bytes = 3272.73 kB = 3.20 MB Load Address: 80008000 Entry Point: 80008000 Image arch/arm/boot/uImage is ready
Don’t be surprised if the above message says that the kernel is uncompressed (corresponding to
-C none). If we told U-boot that the image is already compressed, it would take care of uncompressing it to RAM before starting the kernel image.
Now, you know what
mkimage command you need to run. Just invoke this command on the
Image file instead of
zImage (you can directly replace
$ mkimage -A arm -O linux -T kernel -C none -a 0x80008000 -e 0x80008000 -n 'Linux-3.3.0-rc6-00164-g4f262ac' -d arch/arm/boot/Image arch/arm/boot/uImage Image Name: Linux-3.3.0-rc6-00164-g4f262ac Created: Thu Mar 8 14:02:27 2012 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 6958068 Bytes = 6794.99 kB = 6.64 MB Load Address: 80008000 Entry Point: 80008000
Now, you can use your
uImage file as usual.
15 thoughts on “How to boot an uncompressed Linux kernel on ARM”
I have question regarding decompressed kernel booting. [zImage]
Ignore this if this question is not valid for this forum.
What exactly this load and entry point address, why were they same?
As per my knowledge load address is where once the decompression is done the memory [base+offset] where the kernel loads and this is constant address specified on valid machine Makefile.boot.
and also Can I attach the mkimage header to ramdisk and boot? is this valid scenario?
Does anyone know how this could be done with xipImage?
Hi Michael Opdenacker, I created the uncompressed image(uImage). But I didn’t boot it within existing root file system. Because there are already existing uncompressed kernel in boot directory. How can configure my existing root file system with new uncompressed image? OR How can properly create new root file system for new uncompressed image?
Thanks in advance.
After I had a UImage file. What are the steps to test it?
If you use U-Boot, you already now what to do with uImage files. It’s then like normal kernel compiling for your board. Nothing special 😉
How do you determine the kernel load address and entry point?
The board maker well tell you in the board manual. If the value is hardcoded in the kernel, you can also look at the last lines of the “make uImage” output.
I had similar issue compiling rock chip kernel. Could you please update me if possible.
Kernel: arch/arm/boot/Image is ready
/kernel/mkkrnlimg: /kernel/mkkrnlimg: cannot execute binary file
make: *** [kernel.img] Error 126
Hi, I just tried the make V=1 uImage command on linux 4.4.39 but it seems to no longer call mkuboot.sh and display the desired load address and entry point. Would you have happened to come across another way to determine these important parameters?
I am trying to boot uncompressed kernel, but it is not booting , I followed the same steps as you mentioned above.
I just build my kernel 4.1.15 code for ARM after exporting tool chain, steps as mentioned below:
mkimage -A arm -T multi -C none -O linux -a 0x12000000 -e 0x12000040 -n ‘Multi Image’ -d arch/arm/boot/Image:arch/arm/boot/dts/own-base.dtb uImage
MMC read: dev # 1, block # 129088, count 20480 … 20480 blocks read: OK
## Booting kernel from Legacy Image at 12000000 …
Image Name: Multi Image
Image Type: ARM Linux Multi-File Image (uncompressed)
Data Size: 7881826 Bytes = 7.5 MiB
Load Address: 12000000
Entry Point: 12000040
Image 0: 7841396 Bytes = 7.5 MiB
Image 1: 40418 Bytes = 39.5 KiB
Verifying Checksum … OK
## Loading TEE from multi component Legacy Image at 12000000 …
## Flattened Device Tree from multi component Image at 12000000
Booting using the fdt at 0x1277a6c0
Loading Multi-File Image … OK
Using Device Tree in place at 18000000, end 1800cde1
No PMIC found!
Starting kernel …
SWG –> DTB 0x18000000 images->ft_addr = 0x18000000 images->ft_len= 40418l
SWG –> no secure kernel_entry= 0x12000040 machid= 0xf8c dtb in r2 = 0x18000000
Error: unrecognized/unsupported processor variant (0x2ef5aeb8).
Can anyone let me know what might be the issue.
I would like to add that sometimes (in my case at least), the ‘make uImage’ generates the uncompressed image according to ‘mkimage -l uImage’, so I would highly recommend to check it after each generation
Thanks for interesting article. I am working on a Linux Arm board and the Flash memory chips changed part numbers. The CFI number changed from a 1.2 to a 1.5. The Linux kernal 2.6.36 I am using only checks upto 1.4. Since the commands used are the same, the CFI ID is the only issue. Thus I need to change the ‘4’ to a ‘5’ – one byte – in the uImage file. since I do not have the original linux source code used. Question is, how do I un-compress uImage, change this byte, then recompress.
mkimage -l uImage shows “no compression” but the actual kernal image is compressed. I tried extracting the uImage 64 byte header then using gzip, bzip2 etc but to no avail – always wrong file type. A steer/suggestion would be greatly appreciated 🙂
Thanks for your comment. You will probably have to update the Linux kernel on your platform. Could you contact us at firstname.lastname@example.org so that we can discuss, and see if we can help you with this ?
Is is possible to boot a x86 uncompressed kernel arch/x86/boot/compressed/vmlinux.bin in qemu-system-x86_64 instead of arch/x86/boot/bzImage
Probably. Please try and let us know here 🙂