diary @ telent

Ready for action#

Sun 05 Mar 2023 10:27:08 AM UTC

Topics: liminix

Last week I said I was going to spend this week on fixing the 5GHz wireless suport and then put the GL-AR750 away and start working on some other device. Some of that happened ...

Radio

Getting the ath10k driver running was mostly a similar process to the ath9k that provides 2.4GHz wifi: I'd already done the work for building and loading modules from the backports tree, so just had to load more of them. The only extra fillip is that the ath10k driver requires "calibration data" (for the full handwavey explanation see my NixWRT blog on the subject) which lives in a separate partition of the flash.

I don't want to extract this binary blob from my device and check it into the Liminix source repo because (1) it's not source, and (2) probably that ends up with having to do the same for everybody's device. So I wrote a service to extract it at boot time and made the module depend on it.

This and some reflection led to a rearrangement of responsibilities in the module structure. Given that the function, whereabouts and labelling of network ports on a particular hardware device are properties of that device, Liminix device modules are now expected to provide config.hardware.networkInterfaces.{lan,wan,wlan,whatever} services that correspond to whatever actual connections the board offers. For hardware ethernet the name should follow whatever's printed on the case, or whatever the device manufacturer calls that port; for wireless I don't have a good pattern yet so we still need to use judgement.

The other thing that ath10k made apparent is that an insmod call can return before the device is ready for use, so my insmod ath10k_pci && ip link set up dev wlan was failing because the second command ran too soon. To accommodate this I have evolved (and simplified) waitup into ifwait, which doesn't just wait for a device to be running but can also wait for it to exist.

Everything else

Before I put this device down and start work on another, I want it to boot unattended and without a serial connection. This meant:

Sorting these little niggles out took most of the rest of the week. Maybe next week I'll get to Hardware Device Number Two.

MT vessels: make some noise#

Sun 12 Mar 2023 04:21:18 PM UTC

Topics: liminix

tl;dr MT300N-v2 and MT300A are both implemented

Last week:

Sorting these little niggles out took most of the rest of the week. Maybe next week I'll get to Hardware Device Number Two.

This week I have the MT-300A running in what I am pleased to call "production", providing Wifi access in the outbuilding I use as an office, and an MT-300N-V2 almost in production as my backup host, except that for reasons I haven't yet been able to ascertain it won't mount its USB disk at boot time (though it works fine if I ssh in and start that service after boot). It's a big lump of spinning rust and it might just need more time to reach its target angular velocity.

Highlights

What's next

I'm pretty happy with where we've got to: there are only a couple of gaps between where we are now and NixWRT feature parity

That done, I need to turn my attention to the User Manual, which is currently completely silent on how to flash the image onto the device.

Side quest#

Sun 19 Mar 2023 01:59:50 PM UTC

Topics: liminix

This week: I made a video, then I went on a tangent.

The things I said last week that I was going to do this week were fixing a bug in the backup server, and adding NTP - but all the devices I need to do them to are deployed to "in the field" and I would rather not have to unplug them again and reattach the serial console wires to update them.

How can we make this better? After a bit of thought I have a new approach, which works in principle but needs a bit of polish and more testing. We use a combination of kexec and the watchdog timer to allow a new configuration that runs entirely in RAM to be booted from a running system. If the new configuration is doesn't work right, the watchdog will reboot the device - and because the new system hasn't been written to flash, then it'll boot to the previous configuration instead of bootlooping the new one.

The new configuration is built using outputs.kexecboot, which generates a vmlinux, a dtb and a squashfs that can be transferred to the device e.g. via ssh:

$ nix-build --show-trace -I liminix-config=./examples/arhcive.nix \
  --arg device "import ./devices/gl-ar750" -A outputs.kexecboot \
   &&  (tar chf - result | ssh root@192.168.8.185 tar -C /run -xvf -)

and then on the device we do

# kexec --map-file squashfs@104857600 --dtb dtb \
  --command-line "mtdparts=phram0:9945088(rootfs) phram.phram=phram0,104857600,9945088 memmap=9945088$104857600" \
  kernel

(the magic numbers in this command will be generated appropriately by tooling) to map the new root filesystem into a "phram" fake MTD device and then boot the new kernel.

This involved

Other fixes this week:

Next week ... the things we were originally going to do this week? I'd like also to set up a mailing list for the project, but am trying to find something more usable/searchable for the archives than Pipermail.

Self-ghosting email#

Tue 21 Mar 2023 09:13:55 PM UTC

Topics: nix liminix email

[ Reminder: more regular updates on what I'm spending most of my time on lately are at https://www.liminix.org/ ]

I had occasion recently to set up some mailing lists and although the subject matter for those lists is Liminix-relevant, the route to their existence really isn't. So, some notes before I forget:

      local_recipient_maps = [
        "proxy:unix:passwd.byname"
        "$alias_maps"
        "hash:/var/lib/mailman/data/postfix_lmtp"
      ];

Anyway, that's where we are. I'm quite certain I've done something wrong, but I'm yet to discover what.

We've got mail#

Sun 26 Mar 2023 11:19:45 AM UTC

Topics: liminix

As you'll see if you're reading this on www.liminix.org (but not if you're using the RSS feed) we're now on version 0.2 of the web site. I've starting to add a bit more structure beyond the blog entries and would draw your attention particularly to:

In development news - yes, there was also a little bit of development -

At your command

The problem is this: many devices have hacked-up or restricted versions of U-boot installed which hardcode the kernel command-line parameters instead of letting the user configure them. These hardcoded parameters are most likely wrong for Liminix, but luckily we can configure the kernel to ignore the bootloader command line and use a builtin command line or refer to the embedded DTB.

However, this creates another problem: when we are hacking away on an open device with a serial cable, or when we are booting with kexecboot, or when running emulated Liminix with QEMU, we want to change the bootloader kernel command line.

So we needed one kernel with CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER and one with CONFIG_MIPS_CMDLINE_FROM_DTB. Because kernel configuration is a property of the configuration not of the "output", this meant editing the configuration.nix to comment-out or uncomment the kexecboot or flashable module depending on which output was needed - a reliable source of strange behaviour whenever I forgot to.

Our solution is to add an option for "ignore the bootloader command line unless it contains a magic string", and then ensure that the tooling for tftpboot and kexecboot adds that string. The bootloader hardcoded command line doesn't, so we have the desired behaviour in both use cases.

This does require a small kernel patch but hopefully that's not a huge maintenance burden to carry.

(Fixing vendor U-boot on all devices is most certainly not within scope for Liminix.)

Next week

Next week we are moving on to "Task 2":

NixWRT used a self-designed module system (instead of Nixos modules) to allow us to easily express the configuration of multiple instances of the same module – for example when two differently configured copies of the same service are running on different network interfaces. But it had no validity checking or type checking of module options, making it painfully easy to generate and install a bad image. In this phase we revisit this decision, and figure out how to gain the advantages of the Nixos options/type system while still allowing multiple instances of the same module

See you then.