At Technologic Systems, we've identified and cater to a market that needs the same product shipped every time. This means once a product has reached its "Fully Developed" state, we strive to deliver the same product with the same software to eliminate any "gotchas" in end user code. (See our Product Lifecycle statement for more information: https://www.embeddedTS.com/about/product-lifecycle)
There are times, however, where it is necessary for us or customers to modify and build software that was designed and rolled out many years ago. With the Linux kernel and GNU Project always marching forward, support for older software projects can often go untested and neglected. Given long enough time spans, these older projects may reach a point where modern tools can no longer properly compile them due to deprecated or changed features in the tools.
Our TS-72XX series of products based on the 2.4 Linux kernel (TS-7200, TS-7250, TS-7260, TS-7300, and TS-7400) are our focus in this article. These products still ship with a 2.4.26 kernel, and either Debian Sarge or a Busybox based distribution depending on the product and its booted media. Compiling the original kernel is documented in our product manuals, but is somewhat cumbersome on modern GNU/Linux distributions due to the tools available and even the modern 64-bit architecture of desktop computers. We will be using Docker to create a simple userspace, based on an original i386 Debian Sarge release, that is capable of building the 2.4 kernel using the original and recommended cross compiler and manual instructions.
Docker at its core is an OS-level virtualization platform. Similar to chroots or jails on Unix-like platforms, Docker containers are instances of a userspace that is virtualized and isolated from both the host and other containers. Docker goes beyond a simple chroot by giving every container its own process and network namespace thanks to supporting kernel features. But Docker also offers services such as a free cross platform image distribution system with public and private access, all the way through Enterprise grade management and support. Our use here is completely free and open to end users.
This process is compatible with other products beyond the aforementioned series. Setting up a Docker environment is very similar to a chroot under Unix-like operating systems; the Docker ecosystem makes setting up this environment a lot easier. This process can be expanded to allow for compatibility with newer or older kernels, or for cross-compiling userspace applications so long as Docker container images are readily available for a specific environment.
These instructions are all about setting up the specific environment that can be used to successfully compile an older kernel. They assume familiarity with Linux and that all of the necessary tools (Docker, wget, etc.) are already installed or the reader is comfortable installing them as needed. These commands were used on a modern 64-bit Debian Stretch installation and have also been tested on a Mac OS 10.15 installation with success. Once the container is set up, the kernel compile process outlined in a given manual should be used to then compile the kernel and modules, and install these files to the SBC.
Note that all of these steps otherwise can and should be run as a local system user rather than a superuser account. In general, the Docker workflow discourages running any component of Docker (other than the "dockerd" daemon) as a superuser. Instead, the normal user should be added to the "docker" group. All of the commands below were ran as a standard user from a terminal shell.
1) Set up our build directory, with tools, to persist between Docker instances:
mkdir kernel-build cd kernel-build wget ftp://ftp.embeddedarm.com/ts-arm-sbc/ts-7200-linux/cross-toolchains/crosstool-linux-gcc-3.3.4-glibc-2.3.2-0.28rc39.tar.bz2 tar xvf crosstool-linux-gcc-3.3.4-glibc-2.3.2-0.28rc39.tar.bz2 wget ftp://ftp.embeddedarm.com/ts-arm-sbc/ts-7200-linux/sources/tskernel-2.4.26-ts11-feb232011.tar.gz tar xvf tskernel-2.4.26-ts11-feb232011.tar.gz
2) The compiler is hard-coded in the kernel Makefile via the CROSS_COMPILE variable. Usually, the product manual will briefly touch on how to set it up. Since we have a known compiler and Docker setup, 'sed' can be used for a quick one-line change. (The reason /work/ is used will be discussed further below)
sed -i -e "s_^CROSS\_COMPILE.*_CROSS\_COMPILE = /work/usr/local/opt/crosstool/arm-linux/gcc-3.3.4-glibc-2.3.2/bin/arm-linux-_" linux24/Makefile
3) Set up docker. This uses "debian/eol:sarge" from Docker Hub to create a similar userspace environment that would have been used to build the original kernel. The two 'echo' commands make a quick "Dockerfile" to describe the image and install necessary utilities. Note that additional utilities can be added to the Docker image by appending them to the 'apt-get ...' command in "docker/Dockerfile" The image is then built with a specific tag to identify it.
mkdir docker echo "FROM debian/eol:sarge" > docker/Dockerfile echo "RUN apt-get update && apt-get install -y build-essential libncurses5-dev" >> docker/Dockerfile docker build --tag "technologic-sarge" docker/
4) Enter the Docker container using the above image. There are a couple arguments passed here that are important:
--rm Simply removes the container after it is exited/closed, the image stays in place for the future. In some cases, retaining the container is useful for logging or debugging purposes; this is not necessary in our application
-i Makes the container interactive
-t Allocates a PTY device to the container to allow the current terminal to connect STDIN and STDOUT of the container
--volume $(pwd):/work Maps/mounts the present directory, "kernel-build/" to the "/work/" directory inside of the container. Note that, once in the container, the only persistent changes by default will be to this or other mapped volumes. Any modified files that exist outside of mapped volumes will disappear once the container is exited. This is inherent to the design of a Docker container
-w /work Sets the working directory inside the container to "/work/"
-e HOME=/work Sets the "/work/" directory as the users home directory inside the container
--user $(id -u):$(id -g) Sets the user inside the container to the current user and group ID. Root is not needed inside the container for the kernel compilation process as it can all happen as a normal user
technologic-sarge This is the tag of the image to use
bash Run bash once the container is set up
docker run --rm -it --volume $(pwd):/work -w /work -e HOME=/work --user $(id -u):$(id -g) technologic-sarge bash
5) At this point, the terminal should be inside of the container that is Debian Sarge. The "linux24/" directory contains the previously extracted kernel sources and the cross compiler is already set up. We do recommend, however, that the first time this process is used that the following commands be run to clean up any stale files inside of the kernel archive:
cd linux24 make mrproper && make distclean && make clean
Once in the "linux24/" directory, the commands outlined in the respective manual can then be used to configure and compile the kernel and modules. Note that if 'make modules_install' is run, by default the modules will be installed to "/lib/modules/" which is not a persistent directory inside the Docker container. It is recommended to archive the folder to a location in the "/work/" directory (which is the home directory for the container user and is persistent) for use later. For a 2.4 series kernel, this would roughly look like:
make <platform>_config make oldconfig make dep clean make Image && make modules make modules_install
Simply type 'exit' to close the container and return to the standard workstation terminal. At this point, the kernel binary exists in "linux24/arch/arm/boot/". This as well as the modules can be unpacked to an SD card or transferred to the SBC via any modern means from outside the Docker container.
Notes:
- The "debian/eol:sarge" Docker Hub entry is maintained by the Debian Project
- The "debian/eol:sarge" base image inherently uses "archive.debian.org" for the Debian package repository. Any packages that exists in that repository can be installed. The archive repository is maintained by the Debian Project.