Installing Gentoo Linux on the Orange Pi PC2

If you have questions or remarks, please contact me at the URL of this page, replacing the first dot with an at-sign. This page dates from February 2021.

After numerous attempts, I managed to boot the Orange Pi PC2 with Gentoo. Unfortunately a kernel problem prevented it from running as a stable system. Whenever I started compiling things, it crashed with the message:
rcu_sched detected stalls on CPUs/tasks
So I decided to stop hacking here, because it is no longer worth the effort.

Introduction

At the various places I've been, both personally and for work, I've found that sometimes, the place would benefit from a flexible router with firewall. This router should have gigabit NIC and be able to run my custom Linux installation. Why? Because many off-the-shelf routers are costly and do not always facilitate what I want.

These routers are perfectly fine for most people, but I have been running Linux for over 25 years and am reasonably skilled in manually configuring firewalls, VLANs, networks and (dynamic) routing. So for me, anything off-the-shelf routers can do, I can configure myself. The only thing I need for that, is a small, cheap, Linux-capable system with a decent network interface.

I've first looked at the Raspberry Pi. At that time, it only had a 100MBit network interface. It was also accessed via USB drivers, making it the not-very-ideal solution for my custom router. Other embedded solutions exist that have one or more Gigabit network interfaces, such as the Soekris line, Intel Atom and other Mini-ITX boards. However, all of them are more expensive than an Orange Pi and have more resources than I need.

True, true, there are other SoC boards (Beaglebone, Olimex, probably more) that would also suit my needs. But in the end I bought an Orange Pi PC2, had it in my tech drawers for a long time and now the need has arisen once again to have a cheap but reasonably fast custom Linux router at my disposal. So here's how I did it.

Specifications

Procedure

Execute commands as root. Again, this procedure assumes that your SD-card is accessible as /dev/mmcblk0. Change where appropriate.

Install Gentoo packages

  1. Install Git: emerge -uva dev-vcs/git
  2. Install U-boot tools: emerge -uva dev-embedded/u-boot-tools
  3. Install f2fs tools: emerge -uva sys-fs/f2fs-tools

Setup a cross development environment

Put this on an amd64 Gentoo system. These commands were taken from the Crossdev section on the Gentoo Wiki Crossdev build environment . If you name the overlay crossdev, the crossdev commands below will automatically install packages in this overlay.

  1. mkdir -p /var/db/repos/crossdev/{profiles,metadata}
  2. echo 'crossdev' > /var/db/repos/crossdev/profiles/repo_name
  3. echo 'masters = gentoo' > /var/db/repos/crossdev/metadata/layout.conf
  4. chown -R portage:portage /var/db/repos/crossdev
  5. cat <<EOF >/etc/portage/repos.conf/crossdev.conf
    [crossdev]
    location = /var/db/repos/crossdev
    priority = 10
    masters = gentoo
    auto-sync = no
    EOF
  6. Your crossdev build environment also needs a static version of the glibc libraries, otherwise the kernel will fail to compile. The error message I got during kernel compilation was: ld: cannot find -lc
    So to setup your crossdev build environment with static glibc libraries, run:
    crossdev --stable --lenv 'USE=static-libs' --target aarch64

Download and build ARM Trusted Firmware (ATF)

  1. Go to sources dir: cd /usr/src
  2. Shallow clone the ATF repo at https://github.com/ARM-software/arm-trusted-firmware.git :
    git clone --depth 1 https://github.com/ARM-software/arm-trusted-firmware.git atf
  3. Set target arch and cross compilation environment variables:
    export ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu-
  4. Make the ATF for the Orange Pi PC2:
    make -C atf PLAT=sun50i_a64 DEBUG=1 bl31
  5. Tell U-Boot where to find the bl31.bin file:
    export BL31=/usr/src/atf/build/sun50i_a64/debug/bl31.bin

Download and build U-Boot

  1. Go to sources dir: cd /usr/src
  2. Shallow clone the opi-v2019.10 branch from the U-Boot repo at https://megous.com/git/u-boot:
    git clone --depth 1 --branch opi-v2019.10 https://megous.com/git/u-boot uboot
  3. Set target arch and cross compilation environment variables:
    export ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu-
  4. Make config: make -C uboot orangepi_pc2_defconfig
  5. Symlink /usr/bin/python3 to python2, because U-Boot needs Python 2 but is compatible with Python 3:
    ln -s /usr/bin/python3 /usr/bin/python2
  6. Make U-Boot: make -C uboot
  7. Remove symlink again:
    rm -f /usr/bin/python2

Get the firmware and build the kernel

  1. Go to sources dir: cd /usr/src
  2. Shallow clone the Orange Pi Firmware from https://megous.com/git/linux-firmware:
    git clone --depth 1 https://megous.com/git/linux-firmware linux-firmware
  3. I found a relatively random asus.bin firmware from here, please download it, rename it to asus.bin and put it in the edid (still to be created) directory under /usr/src/linux-firmware
  4. Shallow clone the Xunlong Orange Pi Kernel on your amd64 Gentoo system:
    cd /usr/src
    git clone --depth 1 https://github.com/orangepi-xunlong/linux-orangepi.git orangepi
  5. Go into the checkout dir: cd orangepi
  6. Set target arch and cross compilation environment variables:
    export ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu-
  7. Configure the kernel for default Orange Pi PC2 options:
    make orangepi_defconfig
  8. Configure the correct firmware directory:
    sed -rie 's/CONFIG_EXTRA_FIRMWARE_DIR="[^"]+"/CONFIG_EXTRA_FIRMWARE_DIR="\/usr\/src\/linux-firmware"/g' /usr/src/orangepi/.config
  9. Configure the following kernel options, otherwise the kernel will not compile:
  10. Build kernel and device tree: make -j$(nproc) Image dtbs

Partition and format the SD-card

  1. Partition your SD-card with a bootable primary 128M W95 FAT32 (fdisk type b) partition. Add a swap partition (this guide assumes you did and that the root FS is on partition 3) and lastly a Linux partition to contain your root filesystem. I recommend using f2fs for your root filesystem. My layout after partitioning looks like:
    Disk /dev/mmcblk0: 14.44 GiB, 15489564672 bytes, 30253056 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0x00000000
    
    Device         Boot   Start      End  Sectors  Size Id Type
    /dev/mmcblk0p1 *       2048   264191   262144  128M  b W95 FAT32
    /dev/mmcblk0p2       264192  4458495  4194304    2G 82 Linux swap / Solaris
    /dev/mmcblk0p3      4458496 30253055 25794560 12.3G 83 Linux
    
  2. Format the boot partition: mkfs.vfat /dev/mmcblk0p1
  3. If you made a swap partition, format it: mkswap /dev/mmcblk0p2
  4. Format the root partition: mkfs.f2fs -l <hostname-of-orange-pi> /dev/mmcblk0p3

Install stage 3 and configure

  1. Create a temporary mountpoint: mkdir -p /mnt/tmp
  2. Mount the root partition on the temporary mountpoint: mount /dev/mmcblk0p3 /mnt/tmp.
  3. Go to regular tempdir (not the mountpoint): cd /var/tmp
  4. Download the latest arm64 stage3 with systemd from a Gentoo Mirror to /var/tmp
  5. Extract stage3: tar -C /mnt/tmp -JxSvpf /var/tmp/stage3-arm64-systemd-*.tar.xz
  6. Remove the * for the root password in /mnt/tmp/etc/shadow, otherwise you can't login.

Set up the /boot partition and booting on the SD-card

  1. Mount the boot partition on the boot subdir: mount /dev/mmcblk0p3 /mnt/tmp/boot
  2. Copy used U-Boot config for reference:
    cp /usr/src/uboot/.config /mnt/tmp/boot/uboot.config
  3. Compose the U-Boot binary for the boot sector:
    cat /usr/src/uboot/{spl/sunxi-spl.bin,u-boot.itb} > /mnt/tmp/boot/uboot.bin
  4. Write the U-Boot binary to the bootsector:
    dd if=/mnt/tmp/boot/uboot.bin of=/dev/mmcblk0 bs=1024 seek=8
  5. Copy kernel config for reference:
    cp /usr/src/orangepi/.config /mnt/tmp/boot/linux.config
  6. Copy actual kernel:
    cp /usr/src/orangepi/arch/arm64/boot/Image /mnt/tmp/boot
  7. Copy Orange Pi PC2 device tree binary:
    cp /usr/src/orangepi/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dtb /mnt/tmp/boot/board.dtb
  8. Write the image tree configuration to board.its: cat > /mnt/tmp/boot/board.its << EOF
    /dts-v1/;
    / {
            description = "Orange Pi PC 2";
            #address-cells = <1>;
            images {
                    kernel-1 {
                            description = "Xunlong Linux Kernel 5.4";
                            type = "kernel";
                            os = "linux";
                            arch = "arm64";
                            data = /incbin/("Image");
                            compression = "none";
                            load = <0x40080000>;
                            entry = <0x40080000>;
                    };
                    fdt-1 {
                            description = "DTB for Orange Pi PC 2";
                            type = "flat_dt";
                            os = "linux";
                            arch = "arm64";
                            data = /incbin/("board.dtb");
                            compression = "none";
                            load = <0x4fa00000>;
                    };
            };
            configurations {
                    default = "conf-1";
                    conf-1 {
                            description = "Default Configuration";
                            kernel = "kernel-1";
                            fdt = "fdt-1";
                    };
            };
    };
    EOF
    
  9. Go to boot subdir: cd /mnt/tmp/boot
  10. Optionally install a Makefile that will execute the mkimage commands:
    cat >/mnt/tmp/boot/Makefile <<EOF
    all: boot.scr board.itb
    
    boot.scr: boot.cmd
    	mkimage -A arm64 -T script -C none -d boot.cmd boot.scr
    
    board.itb: board.its Image board.dtb
    	mkimage -f board.its board.itb
    
  11. Build the flat image tree (FIT) binary:
    mkimage -f board.its board.itb
  12. Write /mnt/tmp/boot/boot.cmd with the following contents:
    # Kernel parameters
    setenv bootargs console=tty1 rootfstype=f2fs root=/dev/mmcblk0p3 rw rootwait panic=10 init=/lib/systemd/systemd
    
    # Load the FIT binary
    load mmc 0:1 0x44000000 board.itb
    
    # Boot it
    bootm 0x44000000
    
  13. Make the boot.scr code:
    mkimage -A arm64 -T script -C none -d boot.cmd boot.scr

Finalize Orange Pi PC2

  1. Go back to /var/tmp: cd /var/tmp
  2. Unmount SD-card boot partition: umount /mnt/tmp/boot
  3. Unmount SD-card root partition: umount /mnt/tmp
  4. Put the card in the Orange Pi PC2, connect keyboard and monitor and power.
  5. Login as root with empty password.
  6. Set your root password: passwd root
  7. Follow the Gentoo Quick Install Checklist

Failed attempts

Here are the things I've tried that did not work:

References

I used these pages to compose this procedure: