Replacing TX2 Kernel

Hi, I’m trying to replace the TX2 kernel with a custom-built one (still Linux, but nothing in common with the L4T kernel source). The online documentation says to put the new Image in /boot (and modify /boot/extlinux/extlinux.conf to get u-boot to switch to the new kernel).

My question is: what is the expected format for /boot/Image? ‘file /boot/Image’ tells me that it’s “data”, which is unhelpful. I have my kernel in both arm ELF and u-boot legacy image formats, but am unsure which one to use (if either will work).

If it’s relevant, my kernel is only available in 32-bit (armv7) format.


There are a number of kernel file types used, but all of them are variations only in compression. The file “/boot/Image” is a result of “make Image”, and is uncompressed. Depending on bootloader and architecture, you will find examples of “zImage”, “uImage”, “vmlinuz”, so on. Every one of those types, if hit with the right decompression, results in an exact match to “Image”. Use Image.

FYI, in the older days fastboot was the bootloader. This was using zImage. Then U-Boot was used, and this too was zImage. This was all in 32-bit days. Then we transitioned to 64-bit Linux and Linux kernels, but the bootloader was still the original 32-bit boot chain.

It is worth noting that 32-bit software is unable to address the range of required addresses of a full 64-bit system. Sure, 32-bit can address the first half of the 64-bit space, but how do you guarantee that random data will stay in that range? The decompression of zImage format within the bootloader was not guaranteed to work in a 64-bit world. This is when we transitioned from using zImage to Image.

You will be best with the uncompressed Image format. Maybe after everything works you can experiment with compression, but don’t do it while working on your kernel…do any such experiment after you know it works (which won’t be easy).

Incidentally, when you “make Image” you only get Image. When you “make zImage”, you get Image, and then a copy as file name zImage. The same is true for any other compressed format.

Thanks for the help (and great background on u-boot!). The OS I’m working with is completely custom, so I don’t have access to the traditional “make Image” build path. What I do have is a kernel ELF, which I flatten with objcopy then use mkimage to create the image for u-boot. Does that sound correct?

file gives me: /boot/Image: u-boot legacy uImage, myos, Linux/ARM, OS Kernel Image (Not compressed), 568464 bytes, Fri Oct 2 14:27:40 2020, Load Address: 0x3E000000, Entry Point: 0x3E000000, Header CRC: 0x1CFCFB52, Data CRC: 0xBBAB2FDF

However, when replacing /boot/Image with my image, I get the error:
`Enter choice: 1: primary kernel
Retrieving file: /boot/initrd
5565023 bytes read in 206 ms (25.8 MiB/s)
Retrieving file: /boot/Image
568528 bytes read in 62 ms (8.7 MiB/s)
append: root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 video=tegrafb no_ct

Booting kernel from Legacy Image at 80280000 …

Image Name: myos
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 568464 Bytes = 555.1 KiB
Load Address: 3e000000
Entry Point: 3e000000
Verifying Checksum … OK
Unsupported Architecture 0x2
ERROR: can’t get kernel image!
2: backup kernel

And from there it falls back to the original Kernel image. Is this because my kernel is 32-bit ARM, and the TX2 u-boot expects AARCH64, or because my mkimage (which is on a separate, x86_64 host) is incompatible with the u-boot on the TX2, or something else?

The commands I use for objcopy and mkimage as follows ($OBJROOT/kern/kernel is a ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped):

objcopy $OBJROOT/kern/kernel -I elf32-littlearm -O binary --gap-fill=0xff $OBJROOT/kern/kernel.bin


mkimage -A arm -n myos -C none -a 0x3e000000 -e 0x3e000000 -d $OBJROOT/kern/kernel.bin $OBJROOT/Image

Many thanks,

If you are building a Linux kernel, then Image is always built prior to creating other formats. Regardless, the point to consider is that the default bootloader environment works with an uncompressed format. Some 32-bit code works with a zImage.

Normally an exact kernel used for debugging would be vmlinux, but this is more likely seen in a system using a JTAG debugger or gdboc.

A “uImage” seems to be used a lot in other ARM Linux, but should also have a way to extract the uncompressed image. This was interesting:

Perhaps you could dump an uncompressed kernel if the uImage decompression fails. Otherwise you will probably have to go into the U-Boot code and change parameters to tell it to use uImage compression and to decompress while loading.