Early last week, I ordered a Raspberry Pi 3 Model B+ off of Amazon. At a first glance, this new model released in March 2018 comes with a slightly higher clock speed, as well as upgraded Ethernet, Wi-Fi, and Bluetooth capabilities over its immediate predecessor.
(RPi kit: https://www.amazon.ca/gp/product/B06XXSZVLM)
I decided I wanted to install Debian on my Pi and use it as a potential ARM build box. Although it’s not as supported as the official Raspbian release, this custom build did offer the ability to track the rolling release Debian testing (useful for development) and run a 64-bit system.
- ARM64 support like all the latest smartphones (Raspbian uses 32 bit mode exclusively)
- Tracking the latest code in Debian testing (currently buster)
- A very lean base (a < 2GB disk image!) to start with
- No support – every guide and support form assumes you’re using Raspbian and not Debian
- No support – every support answer for firmware-related issues asks you to run rpi-update (what’s that?)
- A very lean base to start with (where are my drivers?!)
Part 1 – Making the boot image
I based my setup off of the unofficial Debian image for the Raspberry Pi 3 over at https://wiki.debian.org/RaspberryPi3. Because this image targets the original Pi 3 and not the Model B+, some additional tweaks are needed to get the system working. After extracting the image to my SD card and expanding the root partition via GParted, here’s roughly the preparations I made:
Copying in new firmware
The first problem was an outdated firmware version – this can be fixed by copying newer versions (start*.elf fixup*.dat bootcode.bin bcm2710-rpi-3-b-plus.dtb) from the Raspberry Pi firmware repository into the boot partition of the SD card. Then, set
device-tree in config.txt to use that .dtb: i.e.
Building a custom kernel
The 4.14 kernel shipped in the Debian image unfortunately lacks support for Ethernet – complete support for the LAN7515 chip used by the Model 3 B+ only landed in kernel 4.18, which is currently in RC.
This essentially leaves two kernel options for the RPi: a mainline 4.18 kernel or the official Raspberry Pi kernel built for arm64. In my case, I actually started out with a 4.18 kernel before switching to the RPi fork, since there are a few components (e.g. a cpufreq driver) that haven’t been upstreamed yet. Both of these options involve a bit of kernel compiling, since Linux 4.18 was not in Debian as of writing.
To cross compile an ARM64 kernel from my AMD64 Debian machine, you will need to install gcc-aarch64-linux-gnu and build-essential (though this is not a complete list as other build-deps may have already been on my machine).
Option 1: Mainline kernel (4.18+)
After extracting or checking out the mainline kernel, use the arm64 default config:
cp arch/arm64/configs/defconfig .config
Unlike with 32 bit ARM, there is only one generic default config for ARM64 encompassing a variety of devices.
Note: if you use a mainline kernel, make sure to use the device tree blob shipped in mainline Linux (arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dtb) instead of the one in the raspberrypi/firmware repo (bcm2710-rpi-3-b-plus.dtb). Otherwise, you may get stuck at the rainbow boot screen!
The compile+install process is similar to that of the RPi kernel (see below).
Option 2: Raspberry Pi kernel (4.14 LTS)
Although Raspbian does not use it, the Raspberry Pi kernel itself has supported 64-bit mode for quite some time. After checking out the sources:
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig
will configure a kernel build for the RPi 3.
Compilation and installation
First, mount the two SD card partitions on your machine; in this example, I used /mnt/boot for the first (boot) partition and /mnt/ext4 for the second (root) partition.
# Build make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- # Install sudo make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=/mnt/ext4 modules_install # You can replace kernel.img with a more descriptive name: # e.g. I used something like raspberrypi-kernel_1.20180417-1_arm64.img # for the RPi kernel sudo cp arch/arm64/boot/Image /mnt/boot/kernel.img sudo cp arch/arm64/boot/dts/broadcom/*.dtb /mnt/boot/ # For the RPi kernel, also install the following: sudo cp arch/arm64/boot/dts/overlays/*.dtb* /mnt/boot/overlays/ sudo cp arch/arm64/boot/dts/overlays/README /mnt/boot/overlays/
Now, edit your config.txt to point to your new kernel (and keep a backup of it in case it gets overwritten!)
Part 2: Making things work
At this point, I could boot into what might be one of the world’s largest terminals. USB, HDMI video, and Ethernet just about worked out of the box, though I had a minor issue with the default firewall provided in the Debian image (the -m comment module for iptables didn’t autoload with my custom kernel).
Because I was running a custom kernel at this point, I had to purge Debian’s raspi3-firmware since it automatically updates / overwrites config.txt to point to the Debian kernel on updates. Once Linux 4.18+ makes its way into Debian, this should no longer be necessary. (I also elected to remove the Debian kernel image since it wasn’t being used)
What didn’t work out of the box, but could be easily fixed
- HDMI audio: required adding
- Wi-Fi: need to copy brcmfmac43455-sdio.txt (an NVRAM config file) from the RPi-Distro/firmware-nonfree repository into /lib/firmware/brcm/, since Debian does not ship it in its firmware-brcm80211 package. (Raspbian’s fork of the package does though!)
- Xorg: I had issues with Xorg only showing a cursor on startx and crashing a few seconds later. dmesg showed me errors like “vc4: Failed to allocate from CMA”, which I fixed by adding
Now I have a Pi running Debian in working condition! 🍥🎉
Anything not mentioned in this article (Bluetooth, GPIO, etc.) has not been tested yet.