Ubuntunizing i.MX6 kernels
Published on February 24, 2015
Yes, we're verbifying a noun here, but hope that the term is meaningful. We've been shipping binary images of Ubuntu for a while now, but haven't really discussed the differences in the boot layout and will remedy that in this post.
Our standard kernels for this platform follow some Ubuntu conventions, which makes packaging straightforward and enables apt-get dist-upgrade for kernel upgrades.
The three primary differences from other platforms are:
- A symlink (/vmlinuz points at the kernel,
- Symlinks in /boot point at the device tree files,
- A symlink /initrd.img points at the initial RAM disk loaded at boot time.
This makes things more complicated if you want to drop in a custom kernel though so we recently pushed a patch adding ubuntunize/Makefile help to our kernel trees to make that easier.
Basic usage
The simplest way to use this is similar to our Cross Compiling Kernels post:
~/$ git clone git://github.com/boundarydevices/linux-imx6.git
~/$ cd linux-imx6
~/linux-imx6$ export ARCH=arm
~/linux-imx6$ export CROSS_COMPILE=arm-linux-gnueabihf-
~/linux-imx6$ export LOADADDR=10008000
~/linux-imx6$ git checkout boundary-imx_3.10.17_1.0.2_ga
~/linux-imx6$ make nitrogen6x_defconfig
... make code or configuration changes here
~/linux-imx6$ make zImage modules dtbs -j4
~/linux-imx6$ make -C ubuntunize tarball
This differs from the device tree section of the other post only at the last two steps. Instead of building the uImage target, you can use zImage and instead of using modules_install by hand, you use ubuntunize/Makefile to create a tar-ball of everything you need to copy to your image.
The tar-ball is placed into the ubuntunize/ directory, and is named with the kernel version:
~/linux-imx6$ ls -l ubuntunize/
total 6156
-rw-rw-r-- 1 ericn ericn 6291763 Feb 19 13:28 linux-3.10.53-04943-g4cc8b53.tar.gz
drwxrwxr-x 4 ericn ericn 4096 Feb 19 13:28 linux-staging
Also note that there's a staging/ directory which contains the content of the tar-ball.
If you're iterating on versions of the kernel, it may be useful to use scp or rsync to copy these files onto your board.
Installation
To install this kernel, you need to extract the content of the tar-ball to your bootable image.
If you have an SD card connected to your development PC and mounted as /media/trusty, you can just extract it using tar:
~/linux-imx6$ sudo tar zxvf ubuntunize/linux-*.tar.gz -C /media/trusty
~/linux-imx6$ sync
If you copy the tar-ball to a running system, you can extract it into the root directory:
ubuntu@nitrogen6x:~$ sudo tar zxvf linux-*.tar.gz -C /
Note the use of the -C directive in each of these to extract into a particular directory. Also note that root privilege is needed to write to the / and /boot/ directories.
Post-installation fixup
One more piece is required before you have a fully functional system: you need to create or update the RAM disk to match the kernel.
This step must be done on the board, using the update-initramfs utility. The utility takes two primary arguments: -c to tell it to create the initramfs image, and -k to specify a kernel version.
If you've already booted the kernel, you can use uname -r to produce the kernel version.
root@nitrogen:~# update-initramfs -c -k`uname -r`
update-initramfs: Generating /boot/initrd.img-3.10.17-37-boundary-4j3
root@nitrogen:~# ls -l /initrd.img
lrwxrwxrwx 1 root root 40 Feb 23 15:26 /initrd.img -> /boot/initrd.img-3.10.17-37-boundary-4j3
If you haven't yet booted the new kernel, you can extract the kernel version from the tar-ball name. The portion of the name from linux- to .tar.gz is what you're after, so for the file linux-3.10.53-04943-g4cc8b53.tar.gz above, you'd use this:
root@nitrogen:~# update-initramfs -c -k3.10.53-04943-g4cc8b53
update-initramfs: Generating /boot/initrd.img-3.10.53-04943-g4cc8b53
root@nitrogen:~# ls -l /initrd.img
lrwxrwxrwx 1 debian debian 38 Feb 19 13:28 /initrd.img -> boot/initrd.img-3.10.53-04943-g4cc8b53
Preventing overwrites
The tools above are sufficient to get you up and booting a custom kernel on one of our Ubuntu (or upcoming Debian) images, but it leaves you a little vulnerable.
Specifically, your local modifications will be overwritten by apt-get dist-upgrade may pull in a new, standard kernel and over-write your local changes.
Thankfully, removing that concern is simple: remove the linux-boundary package:
root@nitrogen:~# apt-get remove linux-boundary* linux-headers-* linux-image-*
Reading package lists... Done
Building dependency tree
Reading state information... Done
...
The following packages will be REMOVED:
linux-boundary-4t3 linux-boundary-4t3-headers-3.10.17-29
linux-headers-3.10.17-29-boundary-4t3 linux-headers-boundary-4t3
linux-image-3.10.17-29-boundary-4t3 linux-image-boundary-4t3
0 upgraded, 0 newly installed, 6 to remove and 55 not upgraded.
After this operation, 77.8 MB disk space will be freed.
Do you want to continue? [Y/n] Y
Removing linux-boundary-4t3 (3.10.17.29.29) ...
Removing linux-headers-boundary-4t3 (3.10.17.29.29) ...
Removing linux-headers-3.10.17-29-boundary-4t3 (3.10.17-29.29) ...
Removing linux-boundary-4t3-headers-3.10.17-29 (3.10.17-29.29) ...
Removing linux-image-boundary-4t3 (3.10.17.29.29) ...
Removing linux-image-3.10.17-29-boundary-4t3 (3.10.17-29.29) ...
Examining /etc/kernel/postrm.d .
run-parts: executing /etc/kernel/postrm.d/initramfs-tools 3.10.17-29-boundary-4t3 /boot/vmlinuz-3.10.17-29-boundary-4t3
update-initramfs: Deleting /boot/initrd.img-3.10.17-29-boundary-4t3
Final notes
We hope these tools make it easier for you to customize your environment to match a particular board or application use case, but they're certainly not a panacea.
You still need to be careful to match the needs of the image you're tweaking, and need to align your kernel version and configuration with the O/S image used. This is especially true if you need graphics or video acceleration provided by our GPU and VPU packages.
As always, let us know how/if this works for you. We've found this Makefile to be useful internally and hope the same is true for you.