Piero V.

OpenWrt on the Orange Pi Zero

A couple of months ago, Debian bookworm became stable and I decided to upgrade my Orange Pi Zero. I wanted to re-install the system with the smallest amount of physical access and that made the whole process tiresome and longer.

The new system did not work well. It often crashed, and I continuously had to reset the system by power cycling it. As stated in my previous article, physical access to that system is not easy, which made the problem even less bearable.

After one of the crashes, I managed to get some logs, and I saw they mentioned a “kernel bug”. However, I believe high temperatures were to blame, as July was very hot here. Anyway, I had a little hope that installing a more recent kernel could solve my problem, so I tried to run apt upgrade, which gave me this output:

Preparing to unpack .../base-files_12.4+deb12u1_armhf.deb ...
Unpacking base-files (12.4+deb12u1) over (12.4) ...
dpkg: error processing archive /var/cache/apt/archives/base-files_12.4+deb12u1_armhf.deb (--unpack):
 unable to stat '.' (which was about to be installed): Value too large for defined data type
Errors were encountered while processing:
 /var/cache/apt/archives/base-files_12.4+deb12u1_armhf.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

I do not have a minimal clue about what this means. It might be related to the Orange Pi being 32-bit and me having created its system from a 64-bit system. But the error is so generic that I struggled to find its cause.

If you have an idea, we could start a conversation 😄️. I made an image of the system and I can replicate the same error in a chroot in my machine with qemu-armhf-static.

Anyway, I understood I could not do much more with this system: I had to reinstall it. But, at this point, I also took the occasion to try other distributions.

I started with OpenWrt. I like it, and I have used it in my routers forever as well as in my GoflexNet. If a device is supported, it will work out of the box, without requiring much maintenance. Usually, after configuring an OpenWrt device, I forget it exists because it just works️™️.

The only initial difficulty I encountered was that I wanted to use a USB drive instead of a microSD for the system storage, but OpenWrt’s U-Boot script is hardcoded to load the kernel from the MMC.

If you also want to run from USB, you can flash one of the official images onto it (I chose the ext4 one, but the squashfs image also works) and then replace the boot.scr in the FAT partition. Starting from OpenWrt’s script and from the one shipped with my previous Debian system, I wrote this script:

setenv fdt_high ffffffff
fatload ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} uImage
fatload ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} dtb
setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/sda2 rootwait
bootm ${kernel_addr_r} - ${fdt_addr_r}

It can be converted to the U-Boot format with this command:

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

The package containing mkimage is called u-boot-tools in many distributions. You can also run it from an x86 PC because one of the arguments is the target architecture, even though my hypothesis is that it does not influence the boot script in any way.

Please notice that I explicitly specified /dev/sda2 as my root. This is not optimal because it is not a unique or persistent identifier, but even though the partition has the rootfs label, root=LABEL=rootfs did not boot. The reason could be that OpenWrt does not use an initial ramdisk (unless they embed it in the kernel image).

I love that the green LED of the Orange Pi turns on once the kernel is loaded and booted successfully. It tells you the boot troubles have ended.

While preparing your boot medium, you might want to add a network configuration to /etc/config/network since the image does not include a default one. My guess is that without it, you only get serial access, but I have not tried.

So, I used this:

config interface 'lan'
	option proto 'static' # Or you can use 'dhcp'
	option ipaddr 'your-ip-address'
	option netmask '255.255.255.0' # Or change with your actual netmask
	option gateway 'your-gateway-address'
	list dns 'your-dns-address'
	option device 'eth0'

It is the base to get started, but after the first boot, you should complete the configuration with the web interface (yes, you will also get LuCI 🤩️!). OpenWrt is aimed towards routers, so it includes some features you will likely want to disable, such as the DHCP server (both for IPv4 and IPv6, as they are separate) or the built-in DNS server that automatically adds itself to /etc/resolv.conf.

Apart from some quirks, you should be able to do a lot with OpenWrt. It has many packages, and I could run my Node.js-based Telegram bot without trouble.

However, I could not use the GPIO as I wanted because /dev/mem is disabled for security reasons. The only way to get it back is to recompile the kernel, which turned OpenWrt into a no-go for me.

My next choice was Alpine Linux, which allowed me to use GPIO but was also much more difficult to bootstrap. So, I will talk about that in another article, stay tuned 😄️!