4.9.y Kernel Compile Guide

From embeddedTS Manuals

This board has a 4.9 LTS kernel, the source for which is on github in embeddedTS/linux-4.9.y. Compiling the kernel requires an armhf toolchain.

Preparing to Build

We recommend building in a Debian environment, whether actual system (or VM) or a Docker container. Here are the instructions for each:

Building under Debian

Builds require several tools to be present your distribution. For Debian:

WARNING: This process may be broken for generic Debian; the commands for Ubuntu should be correct.
su root

apt-get install curl git build-essential lzop u-boot-tools libncursesw5-dev
echo "deb http://emdebian.org/tools/debian buster main" > /etc/apt/sources.list.d/emdebian.list
curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add -
dpkg --add-architecture armhf
apt-get update
apt-get install crossbuild-essential-armhf

For Ubuntu:

sudo apt-get update
sudo apt-get install crossbuild-essential-armhf git build-essential lzop u-boot-tools libncursesw5-dev

Building under Docker

Debian only provides their cross compiler for their distribution. Our examples will set up a Docker for Debian to use for development. If using Debian 10 Buster directly, or through a VM then the docker usage can be skipped.

Create a file called "Dockerfile" with these contents:

FROM debian:buster

RUN dpkg --add-architecture armhf

RUN apt-get update && apt-get install -y \
    autogen \
    automake \
    bash \
    bc \
    bison \
    build-essential \
    bzip2 \
    ca-certificates \
    ccache \
    chrpath \
    cpio \
    curl \
    diffstat \
    fakeroot \
    file \
    flex \
    gawk \
    gcc-arm-linux-gnueabihf \
    git \
    gzip \
    kmod \
    libgpiod-dev:armhf \
    libncursesw5-dev \
    libssl-dev \
    libtool \
    locales \
    lzop \
    make \
    multistrap \
    ncurses-dev \
    pkg-config \
    python \
    python3 \
    python3-pip \
    python3-pexpect \
    qemu-user-static \
    rsync \
    socat \
    runit \
    texinfo \
    u-boot-tools \
    unzip \
    vim \
    wget \
    xz-utils

# To make a more readable PS1 to show we are in the Docker
ENV debian_chroot debian_buster
RUN echo "PS1='\${debian_chroot}\\[\033[01;32m\\]@\\H\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '" >> /etc/bash.bashrc

# Set up locales.  Needed by yocto.
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
        echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
        dpkg-reconfigure --frontend=noninteractive locales && \
        update-locale LANG=en_US.UTF-8

ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US.UTF-8

In the same directory as the file named "Dockerfile" run:

docker build --tag armhf-buster-toolchain .

When this has finished the docker can be used with:

docker run --rm -it --volume $(pwd):/work armhf-buster-toolchain bash

This will map the current directory to /work.

At this point the Debian Docker is ready to compile armhf binaries. For example, create a hello world in your home folder at ~/hello.c

#include <stdio.h>
int main(){
    printf("Hello World\n");
}

To compile this enter the docker with:

docker run -it --volume $(pwd):/work armhf-buster-toolchain bash
# Then from the docker:
cd /work/
arm-linux-gnueabihf-gcc hello.c -o hello

Check "file hello" to verify the binary type:

user@host:~/$ file hello
hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=8a8cee3341d3ef76ef6796f72d5722ae9d77c8ea, not stripped

This can also be used to develop against dynamic libraries from Debian. The armhf packages can be installed in the Docker. For example, to link against curl:

# Enter the Docker:
docker run -it --volume $(pwd):/work armhf-buster-toolchain bash
cd /work/

apt-get install libcurl4-openssl-dev:armhf
# Download curl's simple.c example
wget https://raw.githubusercontent.com/bagder/curl/master/docs/examples/simple.c
arm-linux-gnueabihf-gcc simple.c -o simple -lcurl

The "simple" binary is now built for armhf and links dynamically to curl.

This will only retain the armhf libcurl package until the docker is exited. To make the changes permanent, add the package to the Dockerfile and rerun:

docker build --tag armhf-buster-toolchain .

Compiling the Kernel

Once your build environment is prepared:

git clone https://github.com/embeddedTS/linux-4.9.y
cd linux-4.9.y
git checkout master

## If you are using the 64-bit toolchain:
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm
export LOADADDR=0x80800000

make tsimx6ul_defconfig

## Make any changes in "make menuconfig" or driver modifications, then compile
make && make zImage && make modules

Installing the Kernel, Headers, or Modules

To install the headers and/or objects built above to a board, first create a tarball so you can copy it to removable media or another machine.

The following will install the kernel and modules to a temporary directory, and then pack them up in to a single tarball:

TEMPDIR=$(mktemp -d)
mkdir "${TEMPDIR}/boot/"
cp arch/arm/boot/zImage "${TEMPDIR}"/boot/zImage
cp arch/arm/boot/dts/imx6ul*ts*.dtb  "${TEMPDIR}"/boot/
INSTALL_MOD_PATH="${TEMPDIR}" make modules_install
INSTALL_HDR_PATH="${TEMPDIR}" make headers_install 
tar czf linux-tsimx6ul-"$(cat include/config/kernel.release)"-"$(date +"%Y%m%d")".tar.gz -C "${TEMPDIR}" .
rm -rf "${TEMPDIR}"

This will output a tarball with the kernel version and short git hash, as well as the date the tarball was created. For example: linux-tsimx6ul-v4.9.171-60-g01e2117e-20190823.tar.gz

This tarball can be directly unpacked to the root folder of a bootable media for the device. It is also possible to unpack it directly on a booted system, however we do not recommend doing so on an active deployed system without extensive testing.

# Unpack it to a mounted disk, this assumes the disk is mounted to "/mnt"
tar xf linux-tsimx6ul...tar.gz -C /mnt

# Unpack it to the root directory of a booted system
tar xf linux-tsimx6ul...tar.gz -C /

Troubleshooting

If you experience problems compiling the kernel with the compiler in your distribution, please try whichever of the below toolchains is appropriate for your architecture:

In the case of either toolchain you would run these commands to install them:

chmod a+x poky-*.sh
sudo ./poky-*.sh