diary at Telent Netowrks

Lede by example#

Tue, 20 Mar 2018 21:51:52 +0000

My GL-MT300A arrived just as I was about to go on holiday. This is how far I've got -

Serial console

These things are, if not actually made for DIY purposes, at least very tolerant to such uses. Take it out of its case and you find three standard 0.1" header pins on the PCB labelled "TX", "RX", "GND" - connect each of them to something that speaks TTL serial (I used a Raspberry Pi) and set the baud rate to 115200. Worked first time.

"The U is for Uninitialized"-Boot

I commented previously about the differences one may encounter between two devices both of which run the allegedly "Universal" U-Boot boot loader. This time I couldn't work out why my tftp downloads were loading into memory at offset 0 instead of, say, 0x811f8000. Until I realised that (i) it no longer sufficed to say

setenv rootaddr 11f8000
setenv rootaddr_useg 0x$rootaddr
setenv rootaddr_ks0 0x8$rootaddr

and I must now surround environment variable references with curly braces.

setenv rootaddr 11f8000
setenv rootaddr_useg 0x${rootaddr}
setenv rootaddr_ks0 0x8${rootaddr}

and (ii) on this device, double quotes around the value of a setenv are no longer special, so

  setenv bootn "foo;bar"
will set the value of bootn to "foo and then attempt to run the command bar". Which typically doesn't work all that well.

Hello darkness my old friend

Having made the relevant changes I was able to get the following output:

## Booting image at 81000000 ... Image Name: Linux-4.9.76 Image Type: MIPS Linux Kernel Image (lzma compressed) Data Size: 1705466 Bytes = 1.6 MB Load Address: 80001000 Entry Point: 803fa9c0 Verifying Checksum ... OK Uncompressing Kernel Image ... OK No initrd ## Transferring control to Linux (at address 803fa9c0) ... ## Giving linux memsize in MB, 128

Starting kernel ...

followed by indefinite but emphatic silence, and various bouts of fiddling with CONFIG_EARLY_PRINTK and stuff have not yet persuaded it to loosen up. Currently I am running LEDE in a Docker container to see what it does, and diffing its .config with mine. This has shown up a couple of things that I've now added to my configuration, but I am only going to get one shot at running it before I go home, because at 70 miles distant from the hardware I can't reach across and power cycle it.

Booted out#

Wed, 14 Mar 2018 14:12:58 +0000

This is another week of not much done, but for the record


You can't use kexec to boot into a new kernel unless the kernel you're booting from has support for it. So that cunning plan is out.

Das U-Boot

Das U-Boot is billed as "the Universal Boot Loader", but sometimes I wonder if in practice the U stands for "unique per board" or "unco-ordinated" or even "uninstallable" - simply because the actual version of u-boot that comes installed on your cheap consumer router or IoT device board is a forked and undocumented mess based on an upstream release that's probably about ten years old, and if you want to replace it with mainline U-Boot you have to either (1) be lucky enough to have your new build work perfectly first time, or (2) have access to JTAG or a serial programmer in case it doesn't.


... u-boot_mod looks really rather cool if you have a device it supports - in addition to the basic u-boot it has a web server and a network console

Unfortunately, as it doesn't support my device (it supports some varieties of TL-WR841 and a later revision of WR842 than mine) I'm disinclined to try building it given that if it doesn't work - and that it's sensitive to things like gcc version - there is again no way to resurrect the device without special hardware.

Excuses, excuses. What's the answer?

New hardware

I ordered this yesterday, so when Amazon eventually deign to deliver it, development will/may resume.

Grandmaster, cut faster#

Tue, 06 Mar 2018 22:28:59 +0000

No Nix content at all this week, as all I've done is flash (please refer back to blog post title) my TL-WR842ND back to the factory firmware in preparation for figuring out how to get NixWRT onto it.

There's some discussion of how to do this on the OpenWRT wiki - attach router to wired network, configure a tftp server to answer on and respond to requests for a file called wr842ndv1_tp_recovery.bin which was previously downloaded from the TP-Link site, then turn the router on while holding RESET and wait for stuff to happen.

As always, however, there is a wrinkle. The firmware I downloaded was a ZIP which contained a file called wr842ndv1_en_3_12_25_up_boot(130322).bin, and according to most sources (most sources parrot the OpenWRT wiki)

in case the file name of this firmware file does contain the word “boot” in it, you need to cut off parts of the image file before flashing it:

specifically, remove the first 131584 bytes. Why that number? It doesn't say.

This is what binwalk is for

[dan@carobn:~]$ nix-shell -p python27Packages.binwalk --run "binwalk /tmp/wr842.bin"

DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 TP-Link firmware header, firmware version: 1.-3012.3, image version: "", product ID: 0x0, product version: 138543105, kernel load address: 0x0, kernel entry point: 0x80002000, kernel offset: 8258048, kernel length: 512, rootfs offset: 872767, rootfs length: 1048576, bootloader offset: 7077888, bootloader length: 0 110592 0x1B000 U-Boot version string, "U-Boot 1.1.4 (Mar 22 2013 - 09:09:03)" 110768 0x1B0B0 CRC32 polynomial table, big endian 131584 0x20200 TP-Link firmware header, firmware version: 0.0.3, image version: "", product ID: 0x0, product version: 138543105, kernel load address: 0x0, kernel entry point: 0x80002000, kernel offset: 8126464, kernel length: 512, rootfs offset: 872767, rootfs length: 1048576, bootloader offset: 7077888, bootloader length: 0 132096 0x20400 gzip compressed data, has original file name: "vmlinux.bin", from Unix, last modified: 2013-03-22 01:11:22 1180160 0x120200 Squashfs filesystem, big endian, lzma signature, version 3.1, size: 4675579 bytes, 562 inodes, blocksize: 65536 bytes, created: 2013-03-22 01:24:41

So there you are: the emergency tftp restore expects an image with a TP-Link firmware header followed by a kernel followed by a filesystem - which roughly corresponds with the description of mtd5 in the openwrt flash layout - but the image on the TP-Link site prefaces that with about 128k of something that might be U-boot, which roughly corresponds with the layout of the entire flash chip

Going forward this is relevant insofar as it means we really have two problems not just one

Currently thinking: we can tackle problem 2 first. Let's put OpenWRT on the machine (then at least I have ssh available) and then build a kernel/fs I can start with kexec and iterate on that until I know it works on the hardware. Once we have the right code then we can start figuring out how to put it at the right offset.

Musl memory#

Wed, 28 Feb 2018 00:36:07 +0000

A short post this week, but this is because I need to sleep, not because there is nothing to write about.

First up, NixWRT has moved. It is no longer part of a "lightly forked nixpkgs" repo, it has its own repo containing only NixWRT stuff at https://github.com/telent/nixwrt . Instead of embedding the Nix package collection it now requires that you provide it with one by e..g using the -I flag to nix-build

nix-build -I nixpkgs=../nixpkgs-for-nixwrt/  -A tftproot backuphost.nix

Presently there is still a mildly forked Nix package collection involved, but it is now available separately, and I have started the process of feeding the changes back into upstream so I hope to be able to eliminate that dependency in time.

Second, it builds with musl - which is great news as the image for `backuphost` is too big to fit in 8MB flash when using glibc. The changes required to switch to musl are - apart from a small bug in nixpkgs libiconv derivation - ludicrously trivial.

Third, I was not entirely correct last week when I said that upgrading to nixpkgs master caused nixwrt to break "almost not at all", because after I actually split the repos up I found a couple more patches needed than just the two mentioned. But nothing too serious.

Here's what it looks like:

[dan@loaclhost:~/src/nixwrt]$ ls -l yun/
total 9608
-r--r--r-- 1 root root 1565199 Jan  1  1970 kernel.image
-r--r--r-- 1 root root 2568192 Jan  1  1970 rootfs.image
-r-xr-xr-x 1 root root 5698784 Jan  1  1970 vmlinux

(vmlinux is not actually required on the target, it's a leftover)

Next up will be more patch upstreaming, and making it generate an image I can actually flash onto a TL-WR842. It is claimed that the emergency debricking TFTP client only works when fed with actual TP-Link images and not with OpenWRT, which is going to be bit of a drag if true.

Milestone 0 / Mildly stunned 1#

Tue, 20 Feb 2018 23:46:18 +0000

Since last week I added USB mass storage support and came up with a reasonably effective - I think - way to mount my USB hard drive when the disk appears.

This entailed rebuilding the kernel with usb-storage driver plus support for various kinds of filesystem and partition table I thought I might reasonably encounter, and then an inordinate amount of time poking through /sys and looking at kernel sources to find out why the disk still wasn't showing up. After girding my mental loins - hmm, that might be an image I could have lived without - in preparation for a deeply techy post about whatever subtle trick or obscure option was necessary to make it all work, a sudden flash of enlightenment led to the realisation that I simply hadn't copied the new kernel into the tftp server directory


The only actual problem I found was that USB is hotpluggable, so devices are added to the system asynchronously and generally after the rc script has run mount -a, so just putting the disk in /etc/fstab doesn't work. Instead I am using mdev to get events when devices are added/removed, and causing it to run a monit command to start/stop monit "filesystem" services. This works for my use case (mounting a known filesystem in a known place) but wouldn't be much good for a more dynamic environment - e.g. automounting random USB keys on insertion. I don't think I want to do that anyway though, because security.

So the only thing I really still need to do for M0 is get this onto the original router. If it still works. (And yes, I am alert to the possibility that this may require shrinking the image a bit, somehow, just to get it into the WR-842's flash)

Faced with that tantalising glimpse of success I decided it was time to make matters more complicated: I would upgrade my nixpkgs installation to current master and see how badly it caused nixwrt to break. And the answer, dear reader, which I still find really quite surprising, is "almost not at all". I have a couple of PRs to add mips32 support and to make monit cross-compile, and really that's about all there is.

Current status: waiting for a git filter-branch thing to finish, because I would like to extract nixwrt from the wreckage of the nixpkgs it grew up in and make it point to a package collection somewhere else.