From DietPC
Revision as of 20:02, 21 January 2015 by Whitpa (Talk | contribs)

Jump to: navigation, search

by Paul Whittaker, Jan 2012



Well, I never thought that I'd have an opportunity to put my 32-bit SPARC port of DIET-PC to actual use, but then this Netgear ReadyNAS Duo hardware fell in my lap! Very popular in its day, but a bit of an underperforming relic nowadays. Let's see if we can put it to slightly better use with more modern software (for the most part, at least - I am limited by the development environments that I use as far as glibc and Xorg baselines are concerned, so in these respects I can at best upgrade the ReadyNAS from a Sarge-like machine (glibc 2.3.2, no udev) to an Etch-like machine (glibc 2.3.6, with udev)). The 2.6.17 kernel is a pretty elderly, but it's good enough for inotify, udev and GPT.

The Hardware


It's a strange little beast, based on a custom Infrant IT3107 ASIC with a 280 MHz SPARC (32-bit) CPU, quite unlike anything else I've seen in the NAS market. It has a PCI bus, but the only thing on it are the Via USB chipsets; everything else is on proprietary platform busses. The platform is named "Padre".

The ergonomic design of this unit is rather nice, although how often you are going to replace hard disks in a two-disk unit? Do we really need hot-swap drive bays? The variable speed 60mm fan is unusual and much appreciated, as it keeps the noise down fairly well.

The basics:

Type Make/Model Properties
CPU Infrant IT3107 (sparcv8) 280 MHz, XOR offload engine, DES crypto engine
RAM Unigen DDR400 SODIMM 256 MiB
NIC Padre GMac (custom) Gigabit ethernet
Storage Hynix NAND MTD 64 GiB
Storage Controller Unknown (custom) 2x SATA (<= 1.5 Gbit/s) presenting as IDE
USB Controller Via VT82xxxxx 1.1 / Via 2.0 2x UHCI (1.1) ports, 1x EHCI (2.0) port
Serial Padre serial (custom) 3.3V @ 9600 8n1, pins only, behind sticker on rear
Cooling Generic 60mm fan

Official Firmware

The ReadyNAS RAIDiator 4.1.x firmware is a 32-bit SPARC Debian derivative mated to a Linux 2.6.17 kernel with numerous proprietary drivers. Netgear have done the right thing by GPL and provided them as external modules; with a couple of minor tweaks, the provided kernel code does compile from the source provided (with some caveats), and the configuration does seems to match their kernel. The userspace appears to be a derivative of Debian 3.1 (Sarge), with GLibC 2.3.4 and an old MAKEDEV-style /dev.

Hard disks are formatted as a software RAID device containing an ext3 filesystem with a non-standard 16k block size (the maximum size for most platforms - including x86 and x86_64 - is 4k; this can make data recovery from a failed ReadyNAS rather difficult). Netgear use a modified version of Linux md RAID called X-RAID, which appears to have some kind of DMA engine offload capability. It's format-compatible with ordinary md RAID, but you have to use Infrant's "mdconfig" tool rather than mdadm.

The kernel, ext2 initrd, and installation tarball for the Debian userspace - all encrypted - reside in /dev/mtd1, which is all of the available NAND flash minus the 1 MiB "iboot" boot loader (unencrypted, in /dev/mtd0). There is a simple container format, (poorly) documented here; I'll talk more about this later. The boot loader decrypts the kernel and initrd into RAM and then executes the kernel; on first run the initrd will initialise a RAID device and ext3 filesystem, and then install the third file (root.tgz) onto it; otherwise it will just pivot_root into the hard disk userspace.

Hacking the ReadyNAS

Fortunately the ReadyNAS Duo has a concealed serial port, as the only other means of boot loader configuration and viewing kernel boot messages is by means of press-and-hold-at-power-on button sequences, which of course leave you completely blind as to what may have gone wrong with your custom kernel and/or initrd.

The serial port consists of four pins behind a sticker, above the reset button pinhole on the rear, and runs at 9600 bps (8 data bits, no parity, 1 stop bit, no flow control). The pinout is { GND, RXD, TXD, VCC 3.3V }, counting from the reset-button-end upwards (see The NAS-Central Wiki for details). Fortunately I already possessed a cable for one of my ThinLinx ARM devices that could be easily rewired for this pinout, and was able to get serial access to iBoot with minimum fuss. Of course, not everybody is going to have such gear lying around, so I've built my alternate ReadyNAS kernel with netconsole support, and will endeavour to explain in detail how to use the button-press-and-hold recovery modes for testing.

The boot loader some custom-made thing called "iboot". For something that occupies an entire megabyte of NAND flash, it's pretty rigid and featureless; inability to pass user-defined Linux kernel command parameters and to repartition the NAND is particularly annoying. It can boot from USB, the network via TFTP, and NAND flash. It has no filesystem support, and only understands the crude container format that Infrant devised. Iboot lives in /dev/mtd0 (1 MiB), and the firmware container is stored in /dev/mtd1 (63 MiB) without any unpacking, decryption or modification whatsoever (exactly as you downloaded it).

The container format consists of a two-part 512-byte header containing 80 bytes of encrypted (using key 0) zero-padded plain text (LF, not CR-LF) index followed by 432 bytes of unencrypted zero-padded plain text (LF) descriptor, followed by the encrypted files specified in the index (zero padded to a 512-byte block boundary). Each line of the index has the form "name::start-block::size-in-bytes". start-block includes the header in the count, so the start block of the first file is always 1. The boot loader expects two files, which must be "vmlinux.bin" (encrypted using key 0) and "initrd.img" (encrypted using key 3) specifically; any additional files present in the container will be ignored by iboot. The official firmware has a third file (the root filesystem archive) encrypted using key 0.

FWIW, the clear-text descriptor part of the header has the format "\ninfo::name=fw-name,version=fw-version,time=secs-since-epoch,size=size-in-bytes,md5sum=md5-checksum,descr=fw-description,release_notes=URL\n\n", zero padded up to 432 bytes. I'm not sure what this is read by, but it almost certainly isn't anything we care about for DIET-PC.

Except for the second part of the header, everything in the firmware is encrypted. The official firmware contains a (hardware-accelerated) decryption utility for one of the two ciphers used, but nothing for encryption. Fortunately Henrik Nordstrom has written a utility called readynas_crypto that can both encrypt and decrypt both the DES (-k0) and XOR (-k3) ciphers. He also wrote a kernel module and utility for hardware accelerated DES encryption/decryption, but I couldn't get this to work. Please note that statements in his READMEs that "-k1" is the default encryption mode are wrong; it's actually "-k0". The alternate cipher (-k3) is used only on the initrd file, and apparently also on TFTP downloads (not yet tested).

Button press sequences are documented in the NAS-Central wiki. Most of these alternate boot modes just pass alternate kernel command line parameters (hardcoded into iBoot) and are will thus be meaningless to my alternate firmware. The ones of particular interest are the TFTP and USB boot modes. I haven't yet figured out exactly how the TFTP boot is supposed to work, but USB boot is pretty straightfoward; you just write your firmware container straight to a USB stick (no partition tables, no filesystem, just dd the raw data to the raw device).

Building your own firmware is complicated and prone to human error so I have written a shell script to do it. A 32-bit SPARC build of the readynas_crypto binary that it needs is here.

Own Code Compilation

I encountered a great many problems getting my own kernel and glibc builds to work on this box.

Why do any ReadyNAS-specific code compilation when I already have a working OEM kernel and 32-bit SPARC DIET-PC port, you ask? Because:

  • My DIET-PC build of GlibC 2.3.6 didn't work on ReadyNAS, for some I reasons I found out later, and the 2.3.2 GlibC provided with the official kernel is too old for the rest of my userspace binaries, which have symbol dependencies on at least GLibC 2.3.4 and possibly later.
  • The official firmware's kernel has a hard-coded command line that I needed to change. In particular, "init=/linuxrc" and "rw" are a problem - for DIET-PC, I need "init=/sbin/init" (the default) and "ro").
  • The official firmware's kernel has a default maximum initrd size of 16k, which is too small for the ambitious userspace I wanted. You can override this default on the command line, but see above regarding compiled-in command line!
  • The official firmware's kernel lacks compiled in support for NAND flash and SquashFS or JFFS2, which would be very handy for creating a "real" (non-initrd) root filesystem with integral compression.
  • The NAND partitioning is hard-coded into the NAND driver, and I'd need to change this to add a /dev/mtd2 to put SquashFS or (preferably) JFFS2 on. Root-on-JFFS2 also needs a special command line parameter (rootfstype=jffs2).


Long story short, these are the things you need to watch out for:

  • The ReadyNAS' CPU uses an unusual instruction set (apparently a sparcv8 variant, although glibc must be compiled with -mcpu=v7) that requires a special glibc patch. If you don't apply this, then will die with an "Illegal Instruction" and you will get nowhere. The patch is provided in the GPL tarball, under glibc-2.3.2.ds1/debian/patches/infrant.dpatch. I've updated the patch for glibc 2.3.6 and made it available here. I am trying to forward-port the patch to a later version of glibc, but this is very difficult due to widespread abandonment of any 32-bit SPARC ABI other than sparcv8plus, which requires a sparcv9 CPU.
  • The kernel must be compiled with gcc 3.3, and if you use anything other than gcc 3.3.5 as provided for Debian Sarge (you can find the debs on and install them as a downgrade on Etch) you will encounter additional problems with kernel modules containing ".eh_frame" sections with R_SPARC_UA32 symbols that are not understood by the loader and cause "Unknown relocation: 17" errors.
  • If you do encounter "Unknown relocation: 17" errors, you can run "strip --strip-unneeded -R .eh_frame" on the *.ko files to make the problem go away.


Coming soon to a theatre near you!

Personal tools