BTW I use AArch(64)
Been a while since I did one of these, but I found some time during the Christmas holidays to advance the state of Liminix a bit by finishing off the port to Belkin RT3200. It turned out to be a lot closer to finished already than I remember it, which was gratifying.
ECCe hoc
The wrinkle with this device is that as shipped from the factory it has ECC errors in the flash chip image, which the “new SPI-NAND driver” fails on, which means that putting an up-to-date distro on it doesn’t work at all well.
Happily the OpenWrt people have a solution for this already, in the shape of the owrt-ubi-installer which munges the flash layout to upgrade U-Boot and move almost all the important from-factory stuff (WiFi config data, U-boot environment etc) from fixed-offset MTD partitions into UBI volumes.
However :-) there’s a complication. The device tree is coupled to the partition layout. Newer versions of the installer are able to move more of the factory data to UBI than the old ones did, which means that you have to use the correct DTS for the version of the installer you used. And this is not just a matter of copying it from the newer OpenWrt because there are other changes in the DTS made at the same time to make it compatible with newer versions of the kernel.
So, tl;dr you need to make sure to get the right version of the installer for the kernel of the OS distribution that you plan to use it with, and this is why the Release notes for the installer 1.1.3 say “Do not use this installer if you just want to run release 23.05.x or ealier. Use the v1.0.2 release instead for now.”. To which I’d respond: do use this 1.1.3 installer if you want to run a Liminix version from about January 2025 with git sha 9fd9b8b or better. Because it uses kernel 6.6.67 just like the prerelease OpenWrt does.
If the boot fits
Like the Turris Omnia, the U-Boot on this device understands the filesystem and can load a kernel from it. This is ideal for Liminix because it means we can handle the kernel as (very nearly) “just another package” and so switch to some new/different kernel as part of running the updater script.
It doesn’t use extlinux-compatible, which is a bit of a shame, but I
added a second “bootloader” module such that if you set
config.boot.loader.fit.enable = true
the upshot is that you get a
kernel+dtb+initramfs in /boot/fit
. Then in U-Boot you redefine the
boot_production
variable to find it and boot from it:
uboot> fw_setenv boot_production 'led $bootled_pwr on ; ubifsmount ubi0:liminix && ubifsload ${loadaddr} boot/fit && bootm ${loadaddr}'
Updater updated
Previously unreported except in the NEWS file, liminix-rebuild
is
deprecated and possibly even defunct. The way we now do an in-place
upgrade on a device that supports them is by building the
outputs.updater
target and then running result/bin/update.sh
. This
is mostly because it was 93% impossible (for me, anyway) to remember
how to invoke liminix-rebuild with its gnarly nix-shell wrapper and
this means I have more consistency between my updatable devices and my
needs-reflashing-every-time devices.
Yule log
This is mostly unrelated, but also happened. By default, logs in
Liminix are written to /run/log/current
(and then rotated to
datestamped files in /run/log
), which is an ephemeral filesystem.
This is good, because who wants to wear out their flash cycles on storing a million copies of
@40000000677a7bdb326105f4 rotuer klogd <4>DENIED CHAIN=input-ip4 IN=ppp0 OUT= MAC= SRC=203.0.113.123 DST=192.0.2.10 LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=0 DF PROTO=TCP SPT=29405 DPT=2s WINDOW=65535 RES=0x00 SYN URGP=0
However: this is not good, because if the device crashes you don’t know
what went wrong. So. On devices that support it or that can be made
to support it, we now have log persistence. You can set logging.persistent.enable = true
and
the last ~ kB of logs that were written before rebooting will be
available after rebooting in /run/log/previous-boot
. This works by the magic of CONFIG_PSTORE_PMSG.
This is device-specific in that there needs to be something in the device tree that says where the messages get stored. Typically this would be something like
reserved-memory {
ramoops@03f00000 {
compatible = "ramoops";
reg = <0x03f00000 0x10000>;
pmsg-size = <0x10000>; # <- this line is important
};
};
};
(your memory map may vary)
and no device I’ve looked at yet has this enabled by default. So I’ve also made it a little easier to “patch” the device tree at build time so that you can add a suitable config to any device you so choose.
Is that all?
Yes, or at least that’s it as far as I can still remember. Anyway, I am dogfooding this router at home, and granted it’s only been running since lunchtime but so far it works just fine.
With the aid of my notes-to-self file I have the following things on my radar for attention next. Please note the HTML markup is semantic: this is an unordered list :-)
-
revamp firewall based on advice from security audit (for clarity: they described this as a “non-finding” but nevertheless it could be improved) and lessen the noise it makes in logs
-
all devices to set credible default output, rootfsType, etc
-
expunge remaining references to kexecboot
-
dynamic uid assigment for users
-
update.sh –fast sends wlan services for a spin
-
now that I’ve freed up the Turris Omnia from providing internet service to my family, see whether (a) we can add support for the SFP cage; (b) we can put both eth0 and eth1 into the LAN bridge.
In other “forthcoming” news, open PR for Openwrt One device support