Building a Custom Mainline Linux Kernel System on the Orange Pi PC

Markus | Updated Sunday, August 6th 2017, 09:21

Figure 1. The Orange Pi PC single board computer
This post will explain how to build an Arch Linux system with the latest mainline Linux kernel for the Orange Pi PC by Xunlong from scratch. The target system is intended for server use only. Graphical features, while they may work, have not been tested and are not the focus of this post. The tutorial starts with a completely blank SD card, which means the following steps need to be accomplished in order to reach the goal:
  • Build the cross compiler
  • Build U-Boot
  • Partition the SD card and install U-Boot
  • Build the Linux kernel
  • Install it and the Arch Root FS onto the SD Card
  • Fun and profit :)

Notes

Each time make is invoked to actually compile a program, add -j<num-of-proc> to significantly improve compile times.

The following conventions are used to display commands:

$ Execute me as user
$ foobar % After this character, it is just a comment

# Execute me as root

This is the contents of a file or a note

Prerequisites

This tutorial is written to be followed on an Arch Linux host. While the fundamental steps remain the same with other distributions such as Ubuntu, some parts, especially regarding the installation of the cross compiler, may vary. Here's a short list of requirements and recommendations for following this tutorial. You need ...

  • an Orange Pi PC (duh!). The tutorial may also be applicable to other boards, but I can not verify that.
  • a USB to serial (3.3V) converter.
  • an afternoon of time if you already have some experience. Otherwise plan an entire day.
  • to be comfortable with Google. As with everything as freaky as compiling your own kernel from scratch, you will run into problems.
  • to be genuinely interested in the topic. If you just need a running system, get a precompiled image.

The following parts are not necessary, but make this work definitely easier. You should have ...

  • a fast Internet connection. You will be downloading a lot of data.
  • a fast computer. Compiling takes a while, especially building the cross toolchain.

To follow this tutorial, connect to the UART of the Orange Pi PC at a rate of 115200 Baud. The GND/RX/TX pins are located between the power and HDMI jack in that order [1]. Any serial terminal client will work, for example screen:

$ screen /dev/ttyUSBX 115200

Make sure you have the proper udev rule for your USB to serial converter so that access as user is possible. For example:

ATTRS{idVendor}=="067b",ATTRS{idProduct}=="2303",MODE="0666",GROUP="users"

Building the Cross Compiler

In order to compile software for the Orange Pi, or any ARM system for that matter, on your main computer, you will need a so called cross toolchain. This toolchain needs to supply various tools, such as the compiler, linker, assembler and utilities to process binary files beside a few more. Luckily, there is a really great tool called crosstool-ng which does the job of collecting and installing the toolchain for us [2].

In Arch Linux, crosstool-ng can be easily installed using these commands:

$ wget "https://aur.archlinux.org/cgit/aur.git/snapshot/crosstool-ng-git.tar.gz"
$ tar xvf crosstool-ng-git.tar.gz
$ cd crosstool-ng-git
$ makepkg -s
$ sudo pacman -U <file>

Now, you should have the command ct-ng on your computer.

To build the actual toolchain, create a directory to contain the configuration of it. The target for the installation will be a different directory. In this directory, execute the ct-ng menuconfig command.

$ mkdir toolchain
$ cd toolchain
$ ct-ng menuconfig

This opens a graphical interface to configure the toolchain. Make sure you set the following options:

Paths and misc option --> Prefix directory : /opt/x-tools/${CT_TARGET}

Target options --> Target Architecture : arm
Target options --> Use specific FPU : vfp
Target options --> Floating point: hardware (FPU)
Target options --> Use EABI : *
Target options --> append 'hf' to the tuple (EXPERIMENTAL) : *

Toolchain options --> Tuple's vendor string : opi

Operating System --> Target OS : linux
Operating System --> Linux kernel version : [select latest]

C compiler --> C compiler : gcc
C compiler --> gcc version : 5.3.0
C compiler --> C++ : *

As crosstool-ng constantly changes, some of these settings may be deprecated by now. So, for example, you can try to select newer versions of the tools and add more features if desired.

Next, to build the toolchain, enter

$ ct-ng build

. This process takes quite some time, so grab a cup of coffee and return to, hopefully, see a toolchain in the above selected build (prefix) directory. If any errors occur, change the version of gcc and try again. Also make sure that crosstool-ng is current.

Setting Up the Build Environment

After the toolchain has been built, it needs to be "enabled". If the toolchain has been built into a directory outside of the system path, it needs to be added to it first. Then, all compile scripts need to be told to compile for ARM and to use the cross toolchain. This can be accomplished using:

$ export PATH=$PATH:/opt/x-tools/arm-opi-linux-gnueabihf/bin
$ export ARCH=arm
$ export CROSS_COMPILE=arm-opi-linux-gnueabihf-

As this needs to be done for each newly opened terminal, it is useful to write these commands into a script and execute is using

source setupEnv.sh

before working on the project.

To verify that it worked, try to execute the following commands. Each command should print something other than an error message.

$ arm-opi-linux-gnueabihf-gcc -v
[...]
gcc version a.b.c date
$ echo $ARCH|grep arm
arm
$ echo $CROSS_COMPILE|grep arm
arm-opi-linux-gnueabihf-

Building U-Boot

Das U-Boot is the boot loader that we are going to use on the Orange Pi PC. The boot loader is responsible for initializing the hardware of the system (kind of like the BIOS/UEFI in a PC) and starting the actual operating system. U-Boot allows to boot the Orange Pi from either SD card (mmc), USB-Stick or from the network. This chapter explains how to configure, build and install U-Boot onto the SD card.

Before beginning with this chapter, make sure that the environment is configured properly as explained in the previous chapter.

U-Boot is available from the git repository at DENX [3]. As the Orange Pi PC is fully supported in their master branch, its compilation is straightforward.

$ git clone git://git.denx.de/u-boot.git
$ cd u-boot
$ make orangepi_pc_defconfig
$ make

This step produces a u-boot-sunxi-with-spl.bin file, which contains the compiled bootloader. The next step explains how it can be installed onto the SD card so that the Orange Pi PC can boot from it.

SD Card and U-Boot

As the Orange Pi PC directly boots a sector on the SD card, installation is not as simple as copying a file to the card. Instead, a card image needs to be carefully crafted in regard to where partition and raw data are placed. Thankfully, codekipper on the orangepi.org forums provided all required information to create this image [4].

The first step is to create the partitioning of the SD card. To do this, execute the following commands. Replace /dev/sdX with the device name of your SD card. Verify this number very carefully. Failing to do so may result in absolute destruction of your current host installation or even data on currently connected devices! Things after the % do not need to be typed as they are just comments to explain what is going on. All commands need to be executed as root.

# dd if=/dev/zero of=/dev/sdX bs=1 count=128M % Clear any old info
# fdisk /dev/sdX
: n
: p
: 2048 % Clearance for the boot loader code
: +15M % Size of the boot partition
: n
: p
: 2
: 32768
: [enter] % Use rest of card for the root FS
: p
: w

You may decrease the size of the root FS partition to make SD card images smaller. This can, although more complicated, also be changed after the fact.

These steps create the partition table. Next, the partitions need to be configured as file systems. The boot loader uses a vfat file system, the kernel uses ext4. Before executing these steps, unplug and replug your SD card to make sure the kernel uses the latest partition table.

# mkfs.vfat /dev/sdX1
# mkfs.ext4 /dev/sdX2

After the partitions are created, it is time to copy the U-Boot binary into the correct place. As already mentioned, it does not go into one of the file systems, but rather into the blank space at the beginning of the card. This can be done by issuing

# dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8
# sync

from the U-Boot build directory.

At this step, you can take the card and plug it into the Orange Pi PC. After power cycling, the UART console should show the U-Boot console. Press enter to interrupt startup and enter ? to see the version number of the U-Boot release you just compiled. Congratulations!

Building the Linux Kernel

In this step, we will build the Linux kernel itself. It is the most likely step to change over time as the current stable version of the kernel is still missing many of the required features. Information about the status of the so called sunxi drivers in the mainline kernel can be found on their wiki [5]. The stable version of the kernel at the point of writing this post is 4.7.2 (see update below!). This version still lacks support for USB and the Ethernet PHY among some other minor modules. Therefore, the latest development build needs to be obtained. This can be achieved using:

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
$ cd linux
$ git checkout v4.8-rc4

Update August 2017: As of Linux Kernel 4.13, Ethernet is supported out of the box using the stmmac driver. This makes the following patching steps unnecessary. Make sure to use git checkout v4.13 or newer to get the supported version.

As this version still lacks the networking drivers, these need to be patched in manually. To do this, follow these steps:

$ git remote add ethdriver https://github.com/montjoie/linux
$ git pull ethdriver
$ git merge ethdriver/sun8i-emac-wip-v3

If a newer version of the kernel than 4.7.2 is available, try compiling it without any patches first. Directly check out the latest stable release using the following command after cloning the kernel.

$ git checkout <kernel-version>

Follow the tutorial with this version. Should the resulting system lack Ethernet support, try to apply the patch as noted above.

The next step is to configure the kernel. The INSTALL_MOD_PATH is the path where to place run-time loadable kernel modules. These are required when creating the root FS.

$ export INSTALL_MOD_PATH=/some/path/for/mods
$ make sunxi_defconfig % Load default config for the SoC
$ make menuconfig

and change the following settings:

Kernel Features --> Enable seccomp to safely compute untrusted bytecode : *

Device Drivers --> Network device support --> Ethernet driver support --> Allwinner sun8i EMAC support : *

for Kernel 4.13 and above, choose the following driver instead of the Allwinner sun8i EMAC (also enable the sun8i suboption):

Device Drivers --> Network device support --> Ethernet driver support --> STMicroelectronics devices : *

Then, to compile the kernel, enter

$ make LOADADDR=0x40008000 uImage dtbs modules
$ make modules_install

Installing the Kernel and Arch Root File System

First, mount both partitions from the SD card. This tutorial assumes they are mounted to

/dev/sdX1 -> /mnt/sdX1
/dev/sdX2 -> /mnt/sdX2

To install the Kernel onto the SD card, the uImage along with the device tree and the boot script need to be copied onto the previously created VFAT partition. The boot script, written as a U-Boot script, looks as follows [4]:

#COMMON SETTINGS
setenv fdt_high ffffffff
#Settings for booting from the card.
setenv loadkernel fatload mmc 0 \$kernel_addr_r uImage
setenv loaddtb fatload mmc 0 \$fdt_addr_r sun8i-h3-orangepi-pc.dtb
setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait
setenv uenvcmd run loadkernel \&\& run loaddtb \&\& bootm \$kernel_addr_r - \$fdt_addr_r
run uenvcmd

Write these lines to a file called boot.cmd and run the following command. Copy the resulting boot.scr file to the root of the FAT partition.

$ mkimage -C none -A arm -T script -d ./boot.cmd ./boot.scr

Next, copy the previously created <build-root>/linux/arch/arm/boot/uImage file to the same directory on the SD card. To complete the installation of the kernel, the <build-root>/linux/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dtb file needs to be placed next to the kernel as well.

Finally, the last step is to install the Arch Linux root FS [6]. To do this, download the latest version of alarm. Again, make sure that you are in the right directory before issuing the tar command.

$ wget "http://os.archlinuxarm.org/os/ArchLinuxARM-armv7-latest.tar.gz"
# cd /mnt/sdX2
# tar xvf /path/to/ArchLinuxARM-armv7-latest.tar.gz
$ sync

Optionally, if kernel modules were selected to be built, copy the directory structure from the $INSTALL_MOD_PATH to /mnt/sdX2/lib/modules/<kernel-version>/.

That's it! You're done. Now properly unmount the SD card, put it into your Orange Pi PC and power it up. You should see Arch booting after a few seconds. The default login is root:root.

$ [root@alarm /]# uname -a
Linux alarm 4.8.0-rc4-00210-ge81e8f2 #1 SMP Sun Sep 4 18:04:02 CEST 2016 armv7l GNU/Linux

Final Steps

By default, the root file system is read only. To make it writable for a single session, the following command can be used on the Orange Pi PC:

# mount -o remount,rw /

To make the system automatically remount the root file system on startup, create the /etc/fstab file with the following content:

/dev/mmcblk0p2 / ext4 rw,noatime,data=ordered,discard 0 1

Also, ensure that Arch Linux is up to date by issuing pacman -Syu.

Closing Remarks

Hopefully, this article has helped you to get started building your own Linux system from scratch for the Orange Pi PC. With small changes, this tutorial also applies to many other single-board computers.

As already noted above, this tutorial only takes server use into account. For GPU support, additional drivers and packages are required. This may be covered in a future post.

Thanks for reading and have fun with your new Arch Linux on the Orange Pi PC!


Sources:
    [1]: https://linux-sunxi.org/Orange_Pi_PC#Locating_the_UART
    [2]: http://crosstool-ng.org/
    [3]: http://www.denx.de/wiki/U-Boot
    [4]: http://www.orangepi.org/orangepibbsen/forum.php?mod=viewthread&tid=119
    [5]: http://linux-sunxi.org/Linux_mainlining_effort#Status_Matrix
    [6]: https://archlinuxarm.org/


Tags: linux orangepi software