HOWTO install a natively compiled Linux kernel

This HOWTO assumes you have just natively compiled a new custom Linux kernel for your "La Frite" or "Le Potato" and now want to install it (and test it). It also assumes you are using Armbian Ubuntu, or possibly Armbian Debian on your SBC. For different distributions the below steps will be similar but a little different, YMMV. Also, the steps for kernel installation differ slightly depending on whether you have compiled and intend to boot an Armbian Amlogic patched kernel (from the balbes150 GitHub repository) or an unpatched mainline kernel (straight from kernel.org).

The Linux kernel pieces you have to collect

You have just finished compiling the Linux kernel by executing the following make command or similar:

make Image modules dtbs
  • "Image" is the newly compiled u-boot loadable kernel image file which you can find in the arch/arm64/boot directory. It is usually between 10MB and 22MB in size.
  • "modules" are the modules you selected in the kernel configuration file, which are available as separate object files.
  • "dtbs" means all the device trees for the selected architecture/SoC have been compiled from Device Tree Source (.dts extension) format to Device Tree Blob (.dtb extension) format. Similar to the Image kernel file, the dtb files are available under arch/arm64/boot/dts/<your selected SoC's family>
modules

Let's put the modules where they belong:

sudo make modules_install

This copies all the modules to /lib/modules/<linux_kernel_version>/ and works out the dependencies between them. Note we need the proper permissions to copy the kernel modules to /lib/modules, hence the sudo. Also please write down <linux_kernel_version> somewhere, we are going to need it in a couple of minutes (ls /lib/modules if in doubt).

Armbian Amlogic patched kernel (from balbes150 github repository)

We now copy Image to /boot, after making a backup of the previous kernel Image file. Note that Image has to be renamed to zImage, a legacy of 32-bit times.

sudo cp /boot/zImage /boot/zImage.bak
sudo cp ./arch/arm64/boot/Image /boot/zImage

Note that this zImage kernel file is loaded into memory and booted using u-boot's booti command. It does not have to be translated into u-boot format.

Mainline kernel (from kernel.org, any version >= 4.19)

We now copy Image to /boot, after making a backup of the previous kernel Image file. Note that the mainline kernel Image file requires a u-boot header (see reference below for why this is so).

sudo cp /boot/uImage /boot/uImage.bak
sudo mkimage -A arm64 -O linux -C none -T kernel -a 0x01080000 -e 0x01080000 -d arch/arm64/boot/Image /boot/uImage

This kernel is booted using u-boot's bootm command. It has to be translated into u-boot format (that's why we rename it to uImage).

IMPORTANT: as far as I know, mainline kernels can only be booted using the bootm command, or they require two small patches (see reference below).

dtb files

Copy whatever newly compiled dtb file(s) you need manually from the arch/arm64/boot/dts/<your selected SoC's> directory to /boot/dtb. Note that dtb files are not versioned (meaning they don't depend on any particular kernel version, in principle), so if they have not changed from the previous kernel, they don't require re-installation.

uInitrd

At this point we have prepared the Kernel image file, the modules directory, the dtb files, we are just missing one piece: the u-boot loadable Initrd (initial ramdisk) file. Creating a working initial ramdisk file manually is exceedingly difficult, but thankfully there is a tool to create a fully functional initrd file with a single command: update-initramfs. Let's use it, but first we backup our previous uInitrd:

sudo cp /boot/uInitrd /boot/uInitrd.bak
sudo update-initramfs -c -k <linux_kernel_version>

This creates a file initrd.img-<linux_kernel_version> in /boot and then converts it to u-boot format and writes the final uInitrd.

At this stage everything is in place for a reboot!

Reboot

sudo shutdown -h now

Power off the SBC/TV box, then power it on. If all goes well u-boot should load the kernel and get the OS booted with your new kernel. Login and run the command:

uname -r

to verify that your new kernel is running. Voilà!

If it doesn't work…

Remove your SD card (you were working on an SD card, right?), restore the original zImage/uImage, dtb's and uInitrd, reboot and try to check what went wrong. A USB-to-serial cable is essential at this stage!

References