Skip to content
  • About
  • Friends
  • About
  • Friends
The Blog of phausmy personal Site of Things
  • About
  • Friends
Written by Philipp on 2026-04-18

Running gokrazy on a Banana Pi BPI-R1

CLI . Go . Hacking . Testing

I had a BPI-R1 sitting in a drawer. The board is from 2014 — only ancient OpenWrt and outdated Armbian images exist for it. Nobody maintains this platform anymore.

The hardware is fine though: dual-core Allwinner A20, 1GB RAM, SATA, and a BCM53125 5-port Gigabit switch on the board. Not bad for a dedicated network appliance.

I’m a Go fan, and I knew about gokrazy — pure Go userland, squashfs root, no package manager. The BPI-R1 wasn’t supported. So I added it.

The Board

The BPI-R1 (aka “Lamobo R1”) runs an Allwinner A20 SoC — dual Cortex-A7 @ 1GHz, ARMv7, 32-bit. The standout feature is the BCM53125 switch with four LAN ports and one WAN port, managed by Linux’s DSA framework. That switch caused most of the trouble.

Device Tree — The Source of Truth

When porting gokrazy to a new board, the Device Tree Source in the mainline kernel is your primary reference. For the BPI-R1: arch/arm/boot/dts/allwinner/sun7i-a20-lamobo-r1.dts.

This file tells you everything that matters:

  • The model string is "Lamobo R1" — not “Banana Pi R1”, not “BPI-R1”. gokrazy uses this string from /proc/device-tree/model for device identification. Wrong string = nothing works.
  • The Ethernet topology: DWMAC connected to BCM53125 via MDIO, five switch ports with their PHY addresses. This determines which kernel configs to enable.
  • The serial console: UART0 on ttyS0, pins PB22/PB23 on the J13 header.
  • The DTB filename: sun7i-a20-lamobo-r1.dtb — one of the build artifacts for the kernel package.

I had an old Armbian snapshot to cross-reference, but the DTS source is authoritative. Marketing names and wiki pages will mislead you.

Kernel and U-Boot

gokrazy’s kernel packaging is convention-based: put vmlinuz, DTB, boot.scr, and u-boot-*.bin into a Go module, and the packer finds them. I used gokrazy-rock64-kernelas a template.

The build scripts download mainline Linux 6.12.23 and U-Boot 2025.04, cross-compile in Docker, and copy the artifacts out.

Kernel config

Base: sunxi_defconfig. Problem: it doesn’t include CONFIG_SQUASHFS. gokrazy needs squashfs for its root filesystem. Without it:

Kernel panic - VFS: Unable to mount root fs on "PARTUUID=..."

My config addendum adds ~175 options. The critical ones:

  • CONFIG_SQUASHFS=y — cost me an hour of debugging
  • CONFIG_VFAT_FS=y, CONFIG_NLS_* — FAT32 boot partition
  • CONFIG_NET_DSA=y, CONFIG_B53=y — BCM53125 switch
  • CONFIG_RTL8XXXU=m, CONFIG_CFG80211=m, CONFIG_MAC80211=m — WiFi (the old CONFIG_RTL8192CU staging driver was removed in kernel 6.12)

U-Boot

Straightforward: Lamobo_R1_defconfig, output is u-boot-sunxi-with-spl.bin. 32-bit ARM boots with bootz (not booti). SPL goes to sector 16 on the SD card, MBR-only.

Device Config

gokrazy needs to know the U-Boot offset on the SD card. This goes into deviceconfig/config.go:

"Lamobo R1": {
    MBROnlyWithoutGPT: true,
    RootDeviceFiles: []RootFile{
        {"u-boot-sunxi-with-spl.bin", 16 * sectorSize, 2032 * sectorSize},
    },
    BootPartitionStartLBA: 2048,
    Slug:                  "bpi_r1",
},

I forked gokrazy/internal, added the config, and rebuilt gok with a local replacedirective. Works until the PR is merged.

Serial Console

Without serial, this project would not have worked.

gokrazy is headless — no SSH by default, no shell. On a new board port, the network doesn’t work yet. Serial is your only way in.

The BPI-R1 has a UART header (J13). USB-to-serial adapter, 

screen /dev/tty.usbserial-111130 115200,cs8

on macOS.

Serial was essential at every stage:

  • First boot: Seeing the exact kernel panic (squashfs not compiled in) instead of just a board that doesn’t come up.
  • DSA debugging: Running ip link show to discover all switch ports were down, then ip link set wan up and udhcpc -i wan to manually test DHCP.
  • Iteration loop: Flash card, boot, read serial, identify problem, fix, repeat. About a dozen cycles, 5 minutes each.

One quirk: gokrazy starts a busybox shell when it detects serial input. The first character triggers the shell and gets swallowed. Type ip link show too fast and you get p link show. Wait for the / # prompt.

DSA Networking

The board booted on the first try. But no network.

gokrazy’s DHCP client defaults to eth0. On the BPI-R1, eth0 is the DSA master interface — the CPU port of the switch. Traffic flows through the individual switch ports instead: lan1–lan4 and wan. All start DOWN.

3: eth0: ... state UP
4: lan2@eth0: ... state DOWN
7: wan@eth0: ... state DOWN
8: lan1@eth0: ... state DOWN

Fix: point DHCP at the port with the cable.

"PackageConfig": {
    "github.com/gokrazy/gokrazy/cmd/dhcp": {
        "CommandLineFlags": ["-interface=wan"]
    }
}

The DHCP client calls LinkSetUp() on the target interface automatically. Port comes up, DHCP lease obtained, web interface reachable.

Result

The BPI-R1 boots gokrazy in ~6 seconds. 5-port switch works via DSA. Persistent storage on ext4. Hardware watchdog active. OTA updates and breakglass SSH both work over the network.

Still missing: WiFi firmware blobs and the upstream device config PR.

Takeaways

  1. Check what defconfig actually includes. sunxi_defconfig is minimal. It doesn’t have squashfs, WiFi, or other things gokrazy needs.
  2. DSA boards need per-port DHCP. The master interface isn’t where traffic flows.
  3. Read the DTS, not the wiki. The model string, peripheral wiring, and driver requirements are all in the Device Tree Source.
  4. Serial is non-negotiable for board bring-up. No serial, no debugging.

Code: consolving/gokrazy-kernel-a20 | consolving/gokrazy-internal (branch add-bpi-r1-device-config)

Share this:

  • Share on X (Opens in new window) X
  • Share on Facebook (Opens in new window) Facebook

Like this:

Like Loading...

Related

Leave a ReplyCancel reply

Archives

  • April 2026
  • March 2026
  • August 2025
  • November 2023
  • February 2023
  • January 2023
  • April 2020
  • January 2018
  • December 2017
  • May 2017
  • February 2016
  • September 2015
  • December 2014
  • August 2014
  • June 2014
  • March 2014
  • February 2014
  • September 2013
  • August 2013
  • July 2013
  • November 2012
  • October 2012
  • September 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • August 2011
  • July 2011
  • June 2011
  • May 2011
  • January 2011
  • August 2010
  • July 2010
  • June 2010
  • May 2010
  • January 2010
  • November 2009
  • October 2009
  • September 2009
  • July 2009
  • June 2009
  • May 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • November 2008
  • October 2008
  • September 2008
  • August 2008
  • July 2008
  • June 2008
  • May 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • March 2007
  • February 2007
  • January 2007
  • December 2006
  • November 2006
  • September 2006
  • June 2006
  • May 2006
  • April 2006
  • March 2006
  • February 2006
  • January 2006

Calendar

April 2026
M T W T F S S
 12345
6789101112
13141516171819
20212223242526
27282930  
« Mar    

Categories

  • Bash
  • Bochum
  • Build
  • CCC
  • CLI
  • Coderwall
  • Coventry
  • DB
  • Edu
  • Freenas
  • Gitlab
  • Go
  • Graphics
  • Hacking
  • iOS
  • Java
  • Javascript
  • Mac
  • NAS
  • Network
  • nexenta
  • Perl
  • Personal
  • PHP
  • Play! Framework
  • Proxmox
  • ruby
  • Ruby on Rails
  • Security
  • SmartOS
  • Snippets
  • Sound
  • Tech
  • Testing
  • Tooling
  • Twitter
  • UI
  • Uncategorized
  • Video
  • Virtualisierung
  • ZFS

Copyright The Blog of phaus 2026 | Theme by ThemeinProgress | Proudly powered by WordPress

 

Loading Comments...
 

    %d