Keywords: Linux kernel | image format | embedded systems
Abstract: This paper provides an in-depth technical analysis of three primary Linux kernel image formats: Image, zImage, and uImage. Image represents the uncompressed kernel binary, zImage is a self-extracting compressed version, while uImage is specifically formatted for U-Boot bootloaders. The article examines the structural characteristics, compression mechanisms, and practical selection strategies for embedded systems, with particular focus on direct booting scenarios versus U-Boot environments.
Overview of Linux Kernel Image Formats
In embedded Linux system development, the choice of kernel image format significantly impacts boot processes, storage efficiency, and compatibility. This article systematically analyzes three common Linux kernel image formats: Image, zImage, and uImage, exploring their technical differences, application scenarios, and best practices.
Image Format: Raw Kernel Binary
The Image format is the raw binary file generated after Linux kernel compilation, without any compression. This kernel image directly contains executable machine code and is suitable for scenarios with ample storage space or strict boot speed requirements. Being uncompressed, Image files are typically larger but avoid decompression overhead during boot.
// Typical Makefile rule for generating Image
vmlinux: $(vmlinux-deps)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=init
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=usr
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh
zImage Format: Self-Extracting Compressed Image
zImage is a compressed Linux kernel image that uses gzip compression and embeds a self-extracting program in the image header. This design allows zImage to automatically decompress into memory during boot, significantly reducing storage requirements. The self-extracting mechanism means bootloaders don't need additional decompression support, simplifying the boot process.
// zImage self-extracting header structure
struct zImage_header {
uint32_t magic; // Magic number identifier
uint32_t start; // Decompressed code start address
uint32_t end; // Decompressed code end address
uint32_t compressed_len; // Compressed data length
uint8_t compressed[]; // Compressed kernel data
};
uImage Format: U-Boot Specific Wrapper
uImage is a kernel image format specifically designed for U-Boot bootloaders, created by adding a 64-byte header to raw kernel images (such as Image or zImage) using the mkimage utility. This header contains metadata including operating system type, load address, entry point, and timestamp, enabling U-Boot to properly identify and load the kernel.
// Example command to create uImage using mkimage
mkimage -A arm -O linux -T kernel -C none -a 0x80008000 -e 0x80008000 \
-n "Linux Kernel" -d zImage uImage
Format Comparison and Technical Selection
From a technical architecture perspective, the three formats differ primarily in compression methods and encapsulation levels. Image serves as the base format with maximum compatibility; zImage achieves space optimization through built-in decompression; uImage is specifically adapted for the U-Boot ecosystem.
In practice, a common but controversial approach is wrapping zImage within uImage. While widely used, U-Boot maintainers have criticized this redundancy: "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 payload for mkimage. This way U-Boot does the uncompressing instead of including yet another uncompressor with each kernel image."
Bootloader Compatibility Analysis
Traditional U-Boot versions primarily load uImage-formatted kernels via the bootm command. Modern U-Boot versions have added the bootz command, which can directly boot zImage format, reducing dependence on uImage wrapping. For systems seeking to bypass U-Boot for direct booting, image format selection depends on the first-stage bootloader's capabilities: if the bootloader supports decompression, zImage is appropriate; otherwise, uncompressed Image is required.
Embedded System Implementation Guidelines
When selecting kernel image formats, developers should consider the following factors:
- Storage Constraints: zImage's compression advantages are significant in storage-limited systems
- Boot Time: Image format avoids decompression overhead, offering fastest boot speed
- Boot Environment: U-Boot environments prioritize uImage, while direct booting requires bootloader capability assessment
- Hardware Initialization: Certain architectures (like ARM) require specific register setup and hardware initialization, typically handled by U-Boot, which must be managed separately in direct boot scenarios
For the scenario mentioned in the question—bypassing U-Boot for direct booting—technical choice depends on first-stage bootloader capabilities. If this bootloader supports compressed image decompression, zImage is optimal; otherwise, uncompressed Image format is necessary. Regardless of format choice, proper device tree (DTB) setup and necessary hardware initialization parameters must be ensured.