I did some rearranging of the network infrastructure in my house recently. The main aim was to move anything that made noise 24/7 into a cupboard out of the way. The downside is that it left the printer and a bunch of USB serial ports without anything to plug into.
The solution? A Linksys NSLU2 running NetBSD.
There’s a significant user community running Linux on the NSLU2, and there are some nicely polished Linux distributions ready to flash in. While Steve Woodford has done the work porting the kernel, the installation isn’t nearly as polished on NetBSD as it is on Linux.
The first thing is that at present you really do need the serial console for NetBSD. This involves soldering a 4-pin header onto the NSLU2 board, and constructing a level converter. Soldering the header onto the board caused me a few headaches, as I managed to remove one of the pads. While the holes are standard 0.1″ pitch, the tracks are tiny, and any such damage is very difficult to repair. Nevertheless I eventually managed to repair the damage I had done. The level converter is much easier to construct – a MAX3232 chip, some capacitors and appropriate connectors on a piece of stripboard. Much easier. I found an oscilloscope particularly useful for testing the connections and the level converter.
Once you have a working serial console, you need a suitable kernel. This is fairly straightforward to build with build.sh, although the network interface requires a binay image from Intel. There is a README stashed in the xscale directory which explains where to find it and how to compile it in. I had a few problems, because the image had been updated, and the NetBSD code which used it is currently rather picky about the image version. Another BSD is less picky about this version number, so NetBSD could probably take a similar approach.
Booting from tftp is relatively straightforward, but somewhat tedious as the fconfig command in RedBoot has been disabled, making impossible to change the default boot command from RedBoot.
There is a 2 second window in which you can interrupt the default boot, after which you can issue RedBoot commands to load and execute the kernel.
Once the kernel is loaded, a DHCP server and an NFS server are required. The kernel knows enough to query a DHCP server to obtain its IP address, and to find its root directory on NFS. NetBSD is extracted onto the NFS server, and configured there.
What NetBSD is currently missing is some way to boot the kernel directly out of flash. The obvious way would be to add gzboot support, but the default flash layout doesn’t leave enough size for a full NetBSD kernel in the segment where RedBoot expects to find a Linux kernel. So to get this to work, gzboot would have to learn how to find its compressed data at an alternative location. I don’t think this would be particularly difficult, and I suspect that this would be the easiest way to get the device booting without interaction.
This is what booting my NSLU2 currently looks like:
+Ethernet eth0: MAC address 00:18:39:36:c9:d0
IP: 192.168.0.1/255.255.255.0, Gateway: 192.168.0.1
Default server: 0.0.0.0, DNS server IP: 0.0.0.0
RedBoot(tm) bootstrap and debug environment [ROMRAM]
Red Hat certified release, version 1.92 – built 15:16:07, Feb 3 2004
Platform: IXDP425 Development Platform (XScale)
Copyright (C) 2000, 2001, 2002, Red Hat, Inc.
RAM: 0×00000000-0×02000000, 0x000723a0-0x01ff3000 available
FLASH: 0×50000000 – 0×50800000, 64 blocks of 0×00020000 bytes each.
== Executing boot script in 2.000 seconds – enter ^C to abort
RedBoot> ip_address -l 192.168.xxx.xxx -h 192.168.yyy.yyy
IP: 192.168.xxx.xxx/255.255.255.0, Gateway: 192.168.0.1
Default server: 192.168.yyy.yyy, DNS server IP: 0.0.0.0
RedBoot> load -r -b 0×200000 nslu2
Using default protocol (TFTP)
Raw file loaded 0×00200000-0x00497d03, assumed entry at 0×00200000
Loaded initial symtab at 0xc042a800, strtab at 0xc044dfd0, # entries 8481
pmap_postinit: Allocated 9 static L1 descriptor tables
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
NetBSD 4.99.23 (NSLU2) #6: Tue Jul 24 09:23:02 BST 2007
total memory = 32768 KB
avail memory = 27152 KB
cpu0 at mainbus0: IXP425 266MHz rev 1 (XScale core)
cpu0: DC enabled IC enabled WB enabled LABT branch prediction enabled
cpu0: 32KB/32B 32-way Instruction cache
cpu0: 32KB/32B 32-way write-back-locking Data cache
ixpsip0 at mainbus0
com0 at ixpsip0 addr 0xc8000000-0xc8000fff: ns16550a, working fifo
ixp425_intr_establish(irq=15, ipl=13, func=c0282838, arg=c10b9200)
ixpclk0 at ixpsip0 addr 0xc8005000-0xc800502f
ixpclk0: IXP425 Interval Timer
ixpdog0 at ixpsip0: Watchdog Timer
slugiic0 at ixpsip0: I2C bus
slugbutt0 at ixpsip0: Power and Reset buttons
slugled0 at ixpsip0: LED support
ixpio0 at mainbus0
ixpio0: configuring PCI bus
pci0 at ixpio0 bus 0
pci0: i/o space, memory space enabled, rd/line, rd/mult, wr/inv ok
ohci0 at pci0 dev 1 function 0: vendor 0x1033 product 0x0035 (rev. 0x43)
ixp425_intr_establish(irq=28, ipl=4, func=c0285408, arg=c1113000)
ohci0: interrupting at INTA
ohci0: OHCI version 1.0
usb0 at ohci0: USB revision 1.0
uhub0 at usb0
uhub0: vendor 0x1033 OHCI root hub, class 9/0, rev 1.00/1.00, addr 1
uhub0: 3 ports with 3 removable, self powered
ohci1 at pci0 dev 1 function 1: vendor 0x1033 product 0x0035 (rev. 0x43)
ixp425_intr_establish(irq=27, ipl=4, func=c0285408, arg=c1115000)
ohci1: interrupting at INTB
ohci1: OHCI version 1.0
usb1 at ohci1: USB revision 1.0
uhub1 at usb1
uhub1: vendor 0x1033 OHCI root hub, class 9/0, rev 1.00/1.00, addr 1
uhub1: 2 ports with 2 removable, self powered
ehci0 at pci0 dev 1 function 2: vendor 0x1033 product 0x00e0 (rev. 0x04)
ixp425_intr_establish(irq=26, ipl=4, func=c028b7a8, arg=c1118000)
ehci0: interrupting at INTC
ehci0: companion controllers, 3 ports each: ohci0 ohci1
usb2 at ehci0: USB revision 2.0
uhub2 at usb2
uhub2: vendor 0x1033 EHCI root hub, class 9/0, rev 2.00/1.00, addr 1
uhub2: 5 ports with 5 removable, self powered
ixme0 at mainbus0: IXP4xx MicroEngine Support
ixp425_intr_establish(irq=3, ipl=5, func=c03cf188, arg=c1111000)
ixp425_intr_establish(irq=4, ipl=5, func=c03cf188, arg=c1111000)
ixpnpe0 at ixme0 NPE-B
ixp425_intr_establish(irq=1, ipl=5, func=c03d0ef4, arg=c10fe380)
npe0 at ixpnpe0: Ethernet co-processor
npe0: remember to fix rx q setup
npe0: Ethernet address 00:18:39:36:c9:d0
rlphy0 at npe0 phy 1: RTL8201L 10/100 media interface, rev. 1
rlphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
clock: hz=100 stathz=0 profhz=0
ixp425_intr_establish(irq=5, ipl=10, func=c03ce290, arg=00000000)
iic0 at slugiic0: I2C bus
xrtc0 at iic0 addr 0x6f: Xicor X1226 Real-time Clock/NVRAM
ixp425_intr_establish(irq=22, ipl=7, func=c03d44d4, arg=c10fec80)
ixp425_intr_establish(irq=29, ipl=7, func=c03d4468, arg=c10fec80)
ixp425_intr_establish(irq=28, ipl=4, func=c03d487c, arg=c10e4200)
ixp425_intr_establish(irq=27, ipl=4, func=c03d47d0, arg=c10e4200)
ixp425_intr_establish(irq=26, ipl=4, func=c03d4724, arg=c10e4200)
ixp425_intr_establish(irq=5, ipl=10, func=c03d4638, arg=00000000)
ehci0: handing over full speed device on port 1 to ohci0
uhub2: port 1, device disappeared after reset
root device: npe0
file system (default generic):
root on npe0
mountroot: trying ffs...
mountroot: trying nfs...
nfs_boot: trying DHCP/BOOTP
ulpt0 at uhub0 port 1 configuration 1 interface 0
ulpt0: Hewlett-Packard hp LaserJet 1010, rev 1.10/1.00, addr 2, iclass 7/1
ulpt0: using bi-directional mode
nfs_boot: DHCP next-server: 192.168.yyy.yyy
root on 192.168.yyy.yyy:/home/nslu2
root time: 0x46ac89d3
root file system type: nfs
init path (default /sbin/init): [enter]
init: copying out path `/sbin/init' 11
Sun Jul 29 13:36:42 BST 2007
Starting file system checks:
Setting tty flags.
Setting sysctl variables:
IPv6 mode: host
Configuring network interfaces:.
add net default: gateway 192.168.yyy.yyy
Adding interface aliases:
Building databases: dev, utmp, utmpx done
Checking for core dump...
savecore: can't find device 2330/1033033
Jul 29 13:36:48 nslu2 savecore: can't find device 2330/1033033
Setting date via ntp.
Mounting all filesystems...
Clearing temporary files.
Checking quotas: done.
Setting securelevel: kern.securelevel: 0 -> 1
swapctl: adding /swap as swap device at priority 0
Starting local daemons:.
Sun Jul 29 13:49:45 BST 2007
NetBSD/evbarm (nslu2.home.coolfactor.org) (console)