One of my recurring, probably never-to-be-achieved, dreams, is to own a small, completely noiseless PC that I could leave running 24/7/365 for use as a router, Wifi access point, and server for some basic services (such as NTP and DNS), so as to turn off—or at least, suspend—my main desktop PC at night. The current fad in this area is currently the Raspberry Pi, which is undoubtedly a wonderful gadget, and I'll probably get one eventually, but it doesn't quite match my criteria. (As a matter of fact, there are zillions of similar embedded devices which come quite close to what I want, but never actually there. One of my more outrageous demands is that I want two gigabit Ethernet connectors plus Wifi, and that's where mostly everything fails, except for a few things which are build for use as switches but then they don't satisfy me for other reasons.)
My last attempt at substantiating this dream came in the form of the GuruPlug by GlobalScale Technologies. But I was pretty pissed off when it turned out that the gadget, while it matched my more difficult criteria (dual gigabit Ethernet plus Wifi, eSATA, yada yada) utterly failed in the simple but crucial condition of being silent. Seems it was a design error: they had hoped to make it fanless, but it was found to overheat, and they added the fan ex post facto, making the dang thing pretty much pointless. So, I have two of these GuruPlugs Server ExtraNoisy Deluxe on my hands and I still haven't found any use for them.
Well, later GlobalScale came to realize the evil of its ways and amended them by releasing a new product, the DreamPlug. It differs from its older sibling in two important respects: (1) this time it is truly fanless, hence noiseless, and (2) the internal NAND memory used for permanent storage has been replaced by a removable µSD card, making the device easier to unbrick[#] in case something goes wrong. I resisted buying this DreamPlug for some time, because I was really annoyed by the fiasco of my previous purchase at GlobalScale, but in the end resistance was futile and I bought myself a pair of DreamPlugs. They were delivered to me on Monday.
⁂
Well, I have no gripes with the hardware, now: the DreamPlug is, indeed, completely silent, and from what I have seen so far, it seems to work well. No gripes apart from the general fact that the ARM architecture is a chaotic mess: there seem to be a zillion kinds of ARMs, each with a zillion subtypes and sub-subtypes. And as a consequence of this fragmentation, I ran into a number of software problems which I may or may not be able to solve (but which will probably solve themselves on their own: that's the nice thing about software problems as opposed to hardware ones).
The DreamPlug comes with a Linux distro which is essentially Debian with a custom kernel, including a number of custom drivers (essentially for Wifi), and a custom bootloader. And a number of hastily bundled scripts which were installed by raping the Debian package manager with gravel. Anyway. It works. But I hate badly customized distros and customized kernels, so I'd like to reinstall a fresh Debian (or Ubuntu) on the box. But it's not that simple.
The bootloader (also serving some kind of BIOS
functions) used to boot Linux on the ARM
architecture is something known
as U-Boot. Now Marvell
provides a specifically patched U-Boot for this device, which has some
annoying limitations, such as not being able to load files from ext2
filesystems: so I thought I'd try
a more
recent U-Boot provided by Debian
(u-boot_2011.12-2_armel.deb
), and which is said to
support the DreamPlug. Reflashing U-Boot
is ridiculously
complicated (one takes control of the machine
through JTAG using
the OpenOCD
program, but unfortunately OpenOCD cannot directly flash
the particular kind of nonvolatile memory used on the DreamPlug — as
opposed to the GuruPlug — so one must go through a strange process of
loading the new U-Boot to RAM, booting it there,
and using U-Boot itself to reflash itself); but I managed it.
However, (1) the U-Boot taken from Debian is incapable of booting the
kernel provided by Marvell (it just gets stuck
after Uncompressing Linux... done, booting the kernel.
),
and (2) the Debian kernels for Kirkwood apparently do not support the
DreamPlug (as such, they refuse to boot, complaining that they don't
know the machine identifier 0xdde
; and if I try to trick
them in using identifier 0xa63
which is that of the
GuruPlug, they fail a bit later on).
So Marvell must have patched both their U-Boot bootloader and
kernel in a way that each is compatible only with the other. The
details escape me, though it is obviously must have something to do
with the annoying mechanism
of machine
identifiers used by the ARM architecture. And
whatever the excuse of ARM being fucked up in the
first place, Marvell must have fucked it up some more for their Linux
kernel to be unbootable by a standard U-Boot (conversely, their
patched U-Boot
is said
to be able to boot standard kernels, but only with a special
option mainlineLinux
option and by fiddling with the
machine identifier): what a mess! And the enormity of having to use a
specific bootloader to load a specific kernel is such that it defeats
the whole purpose of a bootloader, namely: to boot more than one
kernel.
I thought I'd step out of the mess by avoiding any Marvell patches
altogether and using a recent mainline kernel to boot with the
standard U-Boot. And when I say recent, I mean
essentially today's
snapshot of the ARM SoC tree (merged with the 3.3.0-rc7
fixes
from the Linux tree). It is supposed to support the
DreamPlug, according
to this
commit (and a couple of later ones): I really don't know why
support for a device that has been commercialized for well over a
year has only begun finding its way in the kernel a few weeks
ago; but unfortunately another problem is that said support is taking
the form not of recognizing the infamous machine ID
(0xdde
) but using something known as a flattened
device tree
which is a kind
of machine
description file: only this requires an even newer U-Boot, and it
seems I have entered a world of pain.
So in the end, I wasted more than five hours first creating
an ARM
cross-compiler[#2] and then
tediously configuring the kernel (the number of choices to be made is
frightening; and even by merging several known configurations it was
still a pain in the ass) to get a kernel that simply does not boot and
I have no idea why (the most useful message I elicited from it
was: Kernel panic - not syncing: ERROR: Failed to allocate
0x1000 bytes below 0x0.
— and that's with Marvell's U-Boot
because with the standard one it didn't even get that far).
The moral of this is that I probably should have stuck with the working system provided by Marvell, but I still hate it and hate the idea that the system needs specific patches to function. And judging by the patch needed to provide master mode support on the Wifi chipset (which is so obviously a badly fangled port of a Windows driver), I'd like to stay clear of any code of this sort.
The dust will settle eventually, I guess, and maybe someday Linux will run correctly on a device that was, after all, specifically made to run Linux. But in the mean time, I can't say its performance has been brilliant.
⁂
[#] Remind me to rant someday about the fact that it ought never to be possible to brick an electronic device of any kind by purely software means.
[#2] In case it's of value to anyone, here's more or less what I did:
mkdir /opt/arm-linux-gnueabi mkdir /opt/arm-linux-gnueabi-tools dpkg-deb -x libc6_2.13-27_armel.deb /opt/arm-linux-gnueabi dpkg-deb -x libc6-dev_2.13-27_armel.deb /opt/arm-linux-gnueabi dpkg-deb -x linux-libc-dev_3.2.6-1_armel.deb /opt/arm-linux-gnueabi (cd /opt/arm-linux-gnueabi/usr ; tar cf - *) | (cd /opt/arm-linux-gnueabi ; tar xf -) rm -rf /opt/arm-linux-gnueabi/usr ln -s . /opt/arm-linux-gnueabi/usr cd /tmp ; apt-get source binutils cd binutils-2.22 ./debian/rules patch mkdir /tmp/binutils-build cd /tmp/binutils-build /tmp/binutils-2.22/configure --target=arm-linux-gnueabi --prefix=/opt/arm-linux-gnueabi-tools --enable-shared --enable-plugins --with-sysroot=/opt/arm-linux-gnueabi make -j4 && make install cd /tmp ; apt-get source gcc-4.6 cd gcc-4.6-4.6.3 DEB_CROSS_NO_BIARCH=yes ./debian/rules patch mkdir /tmp/gcc-build cd /tmp/gcc-build /tmp/gcc-4.6-4.6.3/src/configure --target=arm-linux-gnueabi --prefix=/opt/arm-linux-gnueabi-tools --with-sysroot=/opt/arm-linux-gnueabi --enable-languages=c make -j4 && make install