TS-4900 Debian 12 Sections

From embeddedTS Manuals

Debian 12 - Bookworm

Debian 12 - Getting Started

This Debian release is available in 3 flavors with various packages. See our Debian releases in the Software Images section for links to the latest images available.

Image Description
X11
  • Linux kernel built with more featured defconfig
  • Base Debian with common utilities
  • Common embedded tools (i2c-tools, can-utils, gpiod, libiio-utils, setserial, picocom, etc.)
  • Includes full hardware support
  • Networking tools (nftables, wireless-tools, wpasupplicant, bridge-utils, bluetoothctl, etc.)
  • Includes Development tools (build-essential, make, cmake, python, libraries, etc.)
  • Includes X11 that launches matchbox and xterm on startup
  • Includes touchscreen support
Headless
  • Linux kernel built with more featured defconfig
  • Base Debian with common utilities
  • Common embedded tools (i2c-tools, can-utils, gpiod, libiio-utils, setserial, picocom, etc.)
  • Includes full hardware support
  • Networking tools (nftables, wireless-tools, wpasupplicant, bridge-utils, bluetoothctl, etc.)
  • Includes Development tools (build-essential, make, cmake, python, libraries, etc.)
Minimal
  • Linux kernel built with the minimal defconfig variation
  • Includes base Debian root filesystem with basic wired networking, minimal hardware support, no development tools, etc.

The default login for all images is root with no password.


We recommend using the Image Replicator tool for writing images to bootable median on the platform itself. However, a bootable microSD card can also easily be prepared from a Linux workstation. To write any of the compatible images to a microSD card, first partition the microSD card to have one large ext3, or ext4 partition. See the guide here for more information. Once, formatted, extract the desired tarball to the microSD card.

The following example assumes a microSD card connected to a workstation as /dev/sdc and already has an MBR partition table set up with a single partition:

mkfs.ext3 /dev/sdc1
mkdir /mnt/sd/
sudo mount /dev/sdc1 /mnt/sd/
sudo tar --numeric-owner -xjf <image file>.tar.bz2 -C /mnt/sd
sudo umount /mnt/sd
sync


The onboard eMMC can also be written via the Image Replicator tool. It is also possible to write the eMMC when booted from microSD by repeating the instructions above to format and extract a tarball to the eMMC. Note that the eMMC cannot be rewritten if the system is currently booted to it or if it is actively mounted and used elsewhere. When booted from microSD, the eMMC can be formatted with the following:

mkfs.ext3 /dev/mmcblk2p1
mkdir /mnt/emmc
mount /dev/mmcblk2p1 /mnt/emmc
wget -qO- <image URL from Software Images> | tar --numeric-owner -xj -C /mnt/emmc/
umount /mnt/emmc
sync


Note: The ext4 filesystem can be used instead of ext3, but it may require additional options. U-Boot does not support the 64-bit addressing added as the default behavior in recent revisions of mkfs.ext4. If using e2fsprogs 1.43 or newer, the options -O ^64bit,^metadata_csum must be used with ext4 for proper compatibility. Older versions of e2fsprogs do not need these options passed for ext4 support nor are they needed for ext3.

Debian 12 - Networking

The network in Debian is configured with /etc/network/interfaces. For complete documentation, see Debian's documentation here

Some common examples are shown below. On this release network interfaces follow the predictible network interface names. Run ip addr show to get a list of the network interfaces.

Most commonly:

  • end0 - Ethernet device 0 (CPU Ethernet)
  • enp1s0 - Ethernet PCIe port 1 slot 0 Ethernet
  • usb<mac> - USB Ethernet
  • wlan0 - Wi-Fi

DHCP on end0. Create the file /etc/network/interfaces.d/end0 with the contents:

allow-hotplug end0
iface end0 inet dhcp

Static IP on end0. Create the file /etc/network/interfaces.d/end0 with the contents:

allow-hotplug end0
iface end0 inet static
    address 192.0.2.7/24
    gateway 192.0.2.254

These will take effect on the next boot, or by restarting the networking service:

service networking restart

Debian 12 - WIFI Client

Wireless interfaces are also managed with configuration files in /etc/network/interfaces.d/. For example, to connect as a client to a WPA network with DHCP. Note some or all of this software may already be installed on the target.

Install wpa_supplicant:

apt-get update && apt-get install wpasupplicant -y

Run:

wpa_passphrase youressid yourpassword

This command will output information similar to:

network={
  	ssid="youressid"
  	#psk="yourpassword"
	psk=151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b
}

Use the hashed PSK in the specific network interfaces file for added security. Create the file /etc/network/interfaces.d/wlan0 with the contents:

allow-hotplug wlan0
iface wlan0 inet dhcp
    wpa-ssid youressid
    wpa-psk 151790fab3bf3a1751a269618491b54984e192aa19319fc667397d45ec8dee5b

To have this take effect immediately:

service networking restart

For more information on configuring Wi-Fi, see Debian's guide here.

Debian 12 - WIFI Access Point

hostapd needs to be installed if it is not already in order to manage the access point on the device:

apt-get update && apt-get install hostapd -y
Note: The install process will start an unconfigured hostapd process. This process must be killed and restarted before new hostapd.conf contents will take effect.


Edit /etc/hostapd/hostapd.conf to include the following lines:

interface=wlan0
ssid=YourWiFiName
wpa_passphrase=Somepassphrase
interface=wlan0
channel=7
driver=nl80211
logger_stdout=-1 # Print all module output to standard out
logger_stdout_level=2 # Print informational messages to standard out
wpa=2
wpa_key_mgmt=WPA-PSK
Note: Refer to the kernel's hostapd documentation for more wireless configuration options.


To start the access point launch hostapd:

hostapd /etc/hostapd/hostapd.conf &

This will start up an access point that can be detected by Wi-Fi clients. A DHCP server will likely be desired to assign IP addresses. Refer to Debian's documentation for more details on DHCP configuration.

Debian 12 - Installing New Software

Debian uses the Advanced Package Tool (APT) suite to manage installation of prebuilt applications. The APT tools require a network connection to the internet in order to automatically download and install new software. The update command will download a list of the current versions of available packages:

apt-get update

A common example is installing a simple web server like nginx. Find the package name first with search, and then install it:

root@host:~# apt-cache search nginx
...
nginx - small, powerful, scalable web/proxy server
nginx-common - small, powerful, scalable web/proxy server - common files
nginx-core - nginx web/proxy server (standard version)
nginx-dev - nginx web/proxy server - development headers
nginx-doc - small, powerful, scalable web/proxy server - documentation
nginx-extras - nginx web/proxy server (extended version)
nginx-full - nginx web/proxy server (standard version with 3rd parties)
nginx-light - nginx web/proxy server (basic version)
nginx-confgen - nginx configuration file macro language and preprocessor
...

In this case, the wanted package will likely be the nginx package itself. Names of packages can be found on Debian's wiki pages or the Debian packages site.

With the package name apt-get install can be used to install the prebuilt packages.

apt-get install nginx
# More than one package can be installed at a time.
apt-get install nginx nano vim vbindiff

For more information on using the various APT tools, refer to Debian's APT documentation.

Debian 12 - Setting up SSH

OpenSSH is installed in our Debian images, but by default OpenSSH does not permit logging in as the root user as a security measure. Even if logging in as root is enabled, a password must be set for the root account. Additionally, an SSH host key is required if one hasn't already been created (though this should automatically be created on the first boot).

It is generally discouraged to allow the root user to log in directly. Instead, a user account should be created, with a password set on it. No changes are needed to the OpenSSH configuration file to allow a non-root user to log in.


However, in order to login to a device as root via SSH, the following steps must occur:

sed --in-place 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart ssh.service
passwd root # Set any password

Debian 12 - Starting Automatically

A systemd service can be created to start up various applications. Create the file /etc/systemd/system/yourapp.service with the contents:

[Unit]
Description=Run an application on startup
# Uncomment the following line if networking is a dependency of the application being run
# After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/your_app_or_script

[Install]
WantedBy=multi-user.target


The service can be started immediately and enableed on future boots with the following:

# Start the app on startup, but will not start it now
systemctl enable yourapp.service

# Start the app now, but doesn't change auto startup
systemctl start yourapp.service


See the systemd documentation for more information on how systemd services can be set up and configured.

Debian 12 - Cross Compiling

Debian provides cross toolchains within their distribution for different architectures.

For best portability, we recommend using a containerized environment like Docker to run a Debian 12 environment for toolchain access. This will allow a consistent build environment to run from almost any Linux system that can run Docker. Keep in mind that while docker does run under macOS and Windows, these are run under a case insensitive filesystem which will cause problems with complex builds like the Linux kernel so a Linux host is still recommended.

  • Ubuntu/Debian:
sudo apt-get install docker.io -y
  • Fedora
sudo dnf install docker -y

After installing docker on any distribution make sure your user is in the docker group:

# Add your user to the docker group.  You may need to logout/log back in.
sudo usermod -aG docker $USER

Make sure you can run docker's hello world image as your user to verify it is working:

docker run hello-world

Now create a file Dockerfile:

sudo mkdir -p /opt/docker-toolchain/docker-debian-bookworm-armhf
# Use any preferred editor, vim/emacs/nano/etc
sudo nano /opt/docker-toolchain/docker-debian-bookworm-armhf/Dockerfile
# syntax = docker/dockerfile:1.2

FROM debian:bookworm

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 \
    libyaml-dev \
    locales \
    lz4 \
    lzop \
    make \
    multistrap \
    ncurses-dev \
    pkg-config \
    python3 \
    python3-cbor \
    python3-pexpect \
    python3-pip \
    qemu-user-static \
    rsync \
    runit \
    socat \
    srecord \
    swig \ 
    texinfo \
    u-boot-tools \
    zstd \
    unzip \
    vim \
    wget \
    xz-utils

# Provide a more friendly name
ENV debian_chroot debian_bookworm
RUN echo "PS1='\${debian_chroot}\\[\033[01;32m\\]@\\H\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '" >> /etc/bash.bashrc

# Set up locales
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

Next make a shell script to enter into this docker container. Create /usr/local/bin/docker-debian-bookworm:

# Use any preferred editor, vim/emacs/nano/etc
sudo nano /usr/local/bin/docker-debian-bookworm
#!/bin/bash -e

# Enters a docker running Debian 12 Bookworm
# Any arguments are run in the docker, or if no arguments it runs a shell

export TAG=debian-bookworm-armdev
SCRIPTPATH=$(readlink -f "$0")
DOCKERPATH=/opt/docker-toolchain/docker-debian-bookworm-armhf/

DOCKER_BUILDKIT=1 docker build --tag "$TAG" "$DOCKERPATH" --quiet

exec docker run --rm \
        -it \
        --volume "$(pwd)":/work \
        --user $(id -u):$(id -g) \
        -w /work \
        -e HOME=/tmp \
        "$TAG" \
        $@;

Make this executable, and call it:

sudo chmod a+x /usr/local/bin/docker-debian-bookworm

# dont run as root
docker-debian-bookworm

The first time this runs it will download a base Debian image, and run the above apt-get commands which may take around 10 or so minutes depending on your internet connection and disk speed. After it has run once, it will stay cached and adds almost no overhead to run.

This docker can be thought of as a very low overhead virtual machine that only has access to the directory where it is run.

For example, to build a simple c project, create a ~/Desktop/hello-world directory:

mkdir -p ~/Desktop/hello-world/

In ~/Desktop/hello-world/hello.c:

#include <stdio.h>

int main() {
    printf("Hello world!\n");
    return 0;
}

We can now use the docker in that directory to use Debian's cross compiler to create a binary that targets armhf:

user@hostname:~$ cd ~/Desktop/hello-world/
user@hostname:~/Desktop/hello-world$ docker-debian-bookworm
sha256:a92e70c3d7346654b34c0442da20ae634901fd25d1a89dd26517e7d1c1d00c47
debian_bookworm@a8ddfa54989f:/work$ ls
hello.c
debian_bookworm@a8ddfa54989f:/work$ arm-linux-gnueabihf-gcc hello.c -o hello
debian_bookworm@a8ddfa54989f:/work$ arm-linux-gnueabihf-strip hello
debian_bookworm@a8ddfa54989f:/work$ file hello
hello: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=ffda981721a1531418ed1da27238707851ae0126, for GNU/Linux 3.2.0, stripped

Debian 12 - Kernel Recompile

To compile the kernel you should use the Debian cross compile docker from a linux workstation.

We can use a shell script to enter the docker, and compile the kernel into a tar that can be distributed to the board. For example:

mkdir ~/Projects/kernel-5.10/
cd ~/Projects/kernel-5.10/
git clone https://github.com/embeddedTS/linux-lts.git -b linux-5.10.y linux

Make a ~/Projects/kernel-5.10/build.sh with:

#!/bin/bash -e

if [ ! -e "/.dockerenv" ]; then
	exec docker-debian-bookworm "$0 $@";
fi

export ARCH=arm
export CROSS_COMPILE="arm-linux-gnueabihf-"
export LOADADDR=0x10008000

cd linux

if [ "$#" != "0" ]; then
        "$@"
        exit 0;
fi

## Make any changes in "make menuconfig" or driver modifications, then compile
make -j"$(nproc --all)" all uImage

# Install to a temporary directory
TEMPDIR=$(mktemp -d)
export TEMPDIR
mkdir "$TEMPDIR"/boot/
cp arch/arm/boot/uImage  "$TEMPDIR"/boot/uImage
cp arch/arm/boot/zImage  "$TEMPDIR"/boot/zImage
cp arch/arm/boot/dts/imx6*-ts*.dtb "$TEMPDIR"/boot/
INSTALL_MOD_PATH="${TEMPDIR}/usr/" make modules_install
cd ../

fakeroot sh -c "chmod 755 $TEMPDIR;
	chown -R root:root $TEMPDIR;
	tar cjf kernel.tar.bz2 -C $TEMPDIR .;
	rm -rf $TEMPDIR";

Make this executable:

chmod a+x ~/Projects/kernel-5.10/build.sh

The kernel can be compiled by running these two commands:

./build.sh make ts_defconfig
./build.sh # No arguments runs the build and packages the kernel

# This will output the build in the current directory as kernel.tar.bz2

Any arguments to this script will be executed in the linux path. For example:

./build.sh make ts_defconfig
# Customize the kernel config
./build.sh make menuconfig
# Test a compile (does not package the install)
./build.sh make
# Get a shell prompt in the kernel sources to run commands manually:
./build.sh bash

The kernel.tar.bz2 from this build script can be extracted from a board, or over an image to install this kernel. For example, copy this to the SBC and run:

tar -xhf kernel.tar.bz2 -C /

From a workstation this can similarly be used to install over a mounted SD image:

sudo mount /dev/sdc1 /mnt/sd/
sudo tar -xhf kernel.tar.bz2 -C /mnt/sd/
sudo umount /mnt/sd/