The Gig of Ham

One geek's contributions to the series of tubes

Feb 12, 2016 - 5 minute read - Comments - ARM Blog

Mainline Linux 4.4 kernel on a Jetson TK1

I was really hoping this would be easier than it was. Most (all?) of the pieces needed are upstream, with a minor patch for das U-boot needed to make it all work with L4T. I’m going to provide links to my u-boot images and kernel packages, but first I wanted to go over what I’ve done and why.

My Jetson TK1 still has L4T installed on the internal eMMC device. I used that to debug and build a few minor tools. My target was Debian 8 on an SSD attached to the SATA port. In order to make life easier, I just copy the boot files (kernel, initramfs, dtb) to the eMMC:/boot directory and then add an entry to the extlinux.conf to boot them.

Known issues:

  • It takes about 30s for the kernel, SATA interface, and my SSD to get their act together on boot. I had the same problem when trying to mount the SSD from L4T. I had hoped a new kernel would help this, it did not. Everything works, and it’s stable but you get a LOT of SATA error messages on boot once it tries to mount the filesystem from the SATA SSD.
  • I didn’t bother to try and bring the binary nvidia drivers over, I’m just using the open source stuff (this is a compile box for me and runs headless anyway)
  • No network boot support in das U-boot (this is a mystery to me as to how to fix this, if anyone knows please reach out)

Why the heck did I even build my own kernel? An excellent question, it was mostly to satisfy these requirements:

  • XFS filesystem support
  • systemd support (the L4T kernel will fail to boot Debian 8 properly)
  • LXC support (running build and test targets in containers, and many of the required features were not in 3.10)
  • LVM support
  • More advanced networking options (nftables, etc)

Getting a kernel build was interesting, and learning what features were required for LXC was also more involved than I would have liked. I also learned from the #tegra channel on freenode that I was also going to need to update das U-boot as well. So, let’s get started.

Das U-Boot

I built against the 2016.01 release. Pretty much everything is built in, and you can generate a mostly working build with the following command from the official source tree:

make defconfig_jetson-tk1

However, this build will fail to boot L4T or any of the default nvidia 3.10 kernels because the command line length is too short (512B allowed, the default command line is 518B). So, this is the change I made (this patch will not apply with a cut and paste due to formatting issues, I’ve linked it below in the files section):

diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h
index ba819c4..b448b4b 100644
--- a/include/configs/tegra-common.h
+++ b/include/configs/tegra-common.h
@@ -76,7 +76,7 @@
 * Increasing the size of the IO buffer as default nfsargs size is more
 * than 256 and so it is not possible to edit it
-#define CONFIG_SYS_CBSIZE (256 * 2) /* Console I/O Buffer Size */
+#define CONFIG_SYS_CBSIZE (256 * 4) /* Console I/O Buffer Size */
 /* Print Buffer Size */
 sizeof(CONFIG_SYS_PROMPT) + 16

At that point, everything started to work. I was able to generate and flash the image to the Jetson TK1 board using the tegra-uboot-flasher-scripts provided by nvidia on a separate host. Follow the directions there, and know that you will need the Das U-Boot source, and the cboot-image-configs from nvidia, a device-tree-compiler, and a cross-compiler toolchain if the other host is also not an ARM. On a Debain 8 amd64 host, I installed these packages and used these commands:

sudo apt-get install gcc-arm-none-eabi binutils-arm-none-eabi device-tree-compiler
export CROSS_COMPILE="arm-none-eabi-"
git clone git://
git clone
git clone
git clone
cd u-boot
git checkout tag/v2016.01
patch -p1 < ~/u-boot-tegra-commandline.patch
cd ../tegra-uboot-flasher-scripts
./build --socs tegra124 --boards jetson-tk1 build
sudo ./tegra-uboot-flasher flash jetson-tk1

The resulting image is linked below if you want to skip all that crap and just flash it directly.

Linux Kernel 4.4

At the time I built it, the 4.4 kernel was the latest stable. Getting started was similar to Das U-Boot:

make defconfig_tegra

Gets you to a state where most of the options you need to just get the darned thing to boot are turned on. I also used the LXC Kernel Requirements list and the lxc-checkconfig tool to ensure all the options I needed for LXC were turned on. There were many more than I expected. It also turns out you need to pass a command line argument of “cgroup_enable=memory” in order for everything to work correctly. Along with a few other tweaks, this was my final kernel config, which generated the following DEB using make-kpkg. You also need to “make dtb” in the kernel directory to get the required dtb for booting out. Then I copied the kernel, generated initramfs, and dtb to the eMMC partition and added the following kernel config to eMMC:/boot/extlinux/extlinux.conf

LABEL debian
 MENU LABEL debian 8 on sda1 with 4.4 kernel and ramdisk
 LINUX /boot/vmlinuz-4.4.0
 FDT /boot/dtb/tegra124-jetson-tk1.dtb
 APPEND initrd=/boot/initrd.img-4.4.0 console=ttyS0,115200n8 console=tty1 ignore_loglevel earlyprintk cgroup_enable=memory root=/dev/sda1

The files

Here are all the files needed and their SHA256 checksums:

f7ffbfe4f3a10b6c91f41963957360190c0102daafc731f1d805950c5fdd9cda tegra124-jetson-tk1.dtb
a96b9a0e779f0f1abe4e5f85e146ef9a71c409ebfbb937a00eb8a2c303d0ab16 linux-image-4.4.0_5_armhf.deb
843ae0cce792966395083fbd7590993410d94f8bd34e07953ce236239a0e5323 config-4.4.0
e29210c3fef917f8c89a83fb00b43f80a9c8b9ede46284a3b5c8421805f9a57a jetson-tk1-emmc.img
75bfde768022e83e5995000291ff97217d11cd6e59673a4124d881992d2edd47 u-boot-tegra-commandline.patch

Hope this helps others trying to build a mainline kernel for the Jetson TK1. Please feel free to contact me if you have questions!

comments powered by Disqus