Search:  
Gentoo Wiki

Linksys_NSLU2

This article is part of the Hardware series.
Laptops TV Tuner Cards Wireless Servers Storage Other Hardware Motherboards Related
Merge-arrows.gifIt has been suggested that this article be Merged into one article with Gentoo on NSLU2    (Discuss)

The Linksys NSLU2 (aka 'Slug') is sold as a NAS device (just plug it into your network, add a USB hard disk, and away you go!) but in reality it is much more useful than that. It is a complete, cheap, embedded Linux system. It features an Intel IXP420 (ARM) CPU, 32 MB of RAM, 8 MB of flash, an Intel IXP425 Ethernet PHY, and a dual-port USB controller. Best of all is the fact that the official Linksys firmware uses the Linux kernel, and so Linksys released the source code. This led to some excellent custom firmware projects like Unslung and SlugOS.

This document is a guide to installing and running a Gentoo root filesystem on a hard disk attached to your NSLU2, using parts of SlugOS. It assumes a good working knowledge of Linux in general, and Gentoo in particular. It also assumes you have successfully flashed SlugOS to your NSLU2.

This document is a work in progress! Please expand it with your experiences/knowledge/problems (this is a wiki, after all!). In particular, SlugOS experts (and Gentoo experts) are encouraged to fill in the parts where I had to just guess.


Contents

How?

As mentioned above, SlugOS provides the basis for the Gentoo installation.

The SlugOS firmware installs a 2.6 kernel and a very basic, but fully useable, root filesystem in flash. When you first flash an SlugOS image to your NSLU2 you log into this rootfs.

Included on this rootfs are some boot scripts which will then chainload another rootfs (either on an attached hard disk, NFS, ...), by chrooting and execing init. The turnup script, when run, writes some configuration information to /linuxrc on the flash rootfs which instructs the boot script how and what to actually boot.

With an ordinary SlugOS installation you create a rootfs on your attached hard disk that is very similar to the flash rootfs — just without the space restriction. The flash rootfs then loads the disk rootfs on every boot. We are going to completely replace the disk rootfs with a Gentoo installation (with a few important modifications). We will still be relying on the SlugOS folks to provide a kernel and flash rootfs, which can be updated whenever SlugOS produce a new release.


If things turn ugly ...

If you run into problems that render the Gentoo system unbootable you can resolve them by booting into the standard SlugOS environment again. To do so, reboot your slug with no disk attached. Once booted and connected via ssh, reconnect the hdd and try to resolve the error.


Building a basic working Gentoo root

All the hard work of preparing a basic working system has been taken care of by the excellent Gentoo Embedded project. As pointed out by Ned Ludd on the gentoo-embedded list, you can download an appropriate stage from one of the Gentoo mirrors under experimental/arm/embedded/stages (many mirrors don't carry this directory, but at the very least OSU Open Source Lab do).

Although the IXP420 CPU can dynamically switch between big- and little-endian modes, the NSLU2 ships set to run in big-endian mode. Since we will still be using Redboot and the SlugOS kernel installed on the flash, we will need to keep everything big-endian. This means we will need a stage for the armeb host type (not arm). Gentoo Embedded provides only armeb stages that are based on uClibc (as opposed to glibc), but this should be an advantage on the slug because of the smaller memory footprint. Ned Ludd in his post also suggests using softfloat, since the IXP420 lacks a floating-point unit.

The kernel will emulate floating-point operations anyway, but you will have to switch to kernel (trap) for each and every float point operation, and it isn't very fast. On the other side, size of applications with float point operations will be larger, depending on a number of operations even very much larger. You can consider it as a kind of 'inlining'.

So the stage we want is stage3-armeb-uclibc-softfloat-2005.1.tar.bz2 (as of august 2008, there's no more recent stage ...). Unpacking this will give a fully working Gentoo installation, but you will need to make a few changes to it before you can boot it from the SlugOS flash image.


Burn the SlugOS firmware to your NSLU2

First, get the SlugOS (BE) firmware from http://www.slug-firmware.net/s-dls.php. You will also need the upslug2 flash program. As it is in portage, you can simply do

Code: Install upslug2
# emerge -av upslug2

when using a Gentoo box. It's also availibe on nslu2-linux.org.

To be able to flash the slug, make sure you do not have any devices (hard drives etc.) connected to it. Next, get the NSLU into 'upgrade mode'. Hold the reset button in while powering on, for example with a paper clip, until the led turns from amber to red (really more of a dark amber). Then release the reset button. When in upgrade mode the LED will blink between green and red.

Now, we can flash SlugOS to the NSLU2:

Code: Burn SlugOS firmware
# upslug2 --image <your SlugOS image file>

If you are running multiple NSLU2 devices then you will also need to specify the MAC address of the device to upgrade. Either way the output of the program will look similar to this:

Code: Burn SlugOS firmware specific device
# upslug2 --image openslug-3.10-beta.bin --target 00:11:22:33:44:55
Upgrading LKG664039 00:11:22:33:44:55
    . original flash contents  * packet timed out
    ! being erased             - erased
    u being upgraded           U upgraded
    v being verified           V verified

  Display:
    <status> <address completed>+<bytes transmitted but not completed>
  Status:
    * timeout occured          + sequence error detected

  7fffff+000000 ...VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
Rebooting... done 

Once that has finished the NSLU2 will automatically reboot and come up onto your network using a DHCP-assigned address, or 192.168.1.77 if DHCP is not available. Rebooting will take around 2 minutes. The ready/status LED indicates the boot progress, it should stay green when the system is booted. You now should be able to ssh into the SlugOS firmware.


Ssh to your slug and do some basic settings

When no DHCP is availible, the NSLU2 will choose 192.168.1.77 as IP. So, for example, do:

Code: Ssh into SlugOS
# ssh root@192.168.1.77

The pre-set root password is 'opeNSLUg'. Now run the turnup script to prepare the firmware, answering the questions when prompted:

Code: init
# turnup init
Please enter a new password for 'root'.
The password must be non-empty for ssh login to succeed!
Changing password for root
Enter the new password (minimum of 5, maximum of 8 characters)
Please use a combination of upper and lower case letters and numbers.
Enter new password:
Re-enter new password:
Password changed.
Host name [LKG664039]: SLUG1
Domain name [workgroup]: workgroup
Boot protocol (dhcp|static) [dhcp]: static
IP address [192.168.1.77]: 10.50.100.60
IP netmask [255.255.255.0]: 255.255.255.0
IP gateway []: 10.50.100.1
First DNS server []: 10.50.100.1
Second DNS server []:
Third DNS server []:
turnup init: you must reboot for the changes to take effect
 You may want to run 'turnup preserve' to save these settings,
 after making any additional configuration changes which you
 require.
#

Create a filesystem and unpack the stage

Note: This section can either be completed from SlugOS running on your slug, or to speed things up you can attach your USB disk to another Linux system. Then attach the disk to the slug and do the rest there.

Create a new filesystem on a partition of your hard disk. Space required depends on what you will be installing; 1.5 GB is a reasonable minimum. You have to use a filesystem supported by SlugOS (as of 4.8 Beta, these are ext2 and ext3). For example:

Code: Create a filesystem
# mkfs.ext3 /dev/sda1

You can then mount it and unpack the stage:

Code: Mount the filesystem and unpack the stage (assuming you have downloaded the stage to your home dir)
# mkdir /mnt/gentoo
# mount /dev/sda1 /mnt/gentoo
# cd /mnt/gentoo
# tar -xvjpf ~/stage3-armeb-uclibc-softfloat-2005.1.tar.bz2

Now is also a good time to install the Portage tree. You can copy your local portage tree if you are using a Gentoo box. If the disc is attached to this box, simply do

Code: Copying a local portage tree locally:
cp -r /usr/portage /mnt/gentoo/usr/portage

You can also use scp if the disc is attached to the NSLU2:

Code: Copying a local portage tree remotely:
scp -r /usr/portage root@<your IP/hostname for the slug>/mnt/gentoo/usr/portage

Alternatively, you can download a snapshot, just as you would do when setting up a new Gentoo box. See The Handbook.

Another alternative would be, if you are running a gentoo system with NFS installed, to mount portage (including distfiles) from the other machine saving disk space. Also when the time comes to emerge --sync, just syncing the larger gentoo box will update the portage on the slug as well

Code: Mounting Portage using NFS from 192.168.1.2:
# cd /mnt/gentoo/usr/
# mkdir portage
# mount 192.168.1.2:/usr/portage portage


Copy kernel modules

You will need to provide your Gentoo system with the kernel modules for the SlugOS kernel. In particular your Gentoo installation needs to load the ixp4xx module in order to bring up the network. You should copy all the kernel modules from /lib/modules/ in an existing SlugOS installation to the same path on your new Gentoo root:

Code: Copy kernel modules
# cp -r /lib/modules /mnt/gentoo/lib/


chroot into the Gentoo system

You are now ready to chroot into the new filesystem. Note that this should be done on the slug itself (from SlugOS), not on another Linux machine.

Code: chroot into the filesystem
# mount -o bind /dev /mnt/gentoo/dev
# mount -o bind /dev/pts /mnt/gentoo/dev/pts
# mount -t proc none /mnt/gentoo/proc
# cp /etc/resolv.conf /mnt/gentoo/etc/
# chroot /mnt/gentoo /bin/bash

Since there is only 32M RAM on the NSLU2, you will likely need to enable swap space. This is recommended when using emerge or gcc.

Create a swap partition on the USB drive and mount it. (sda2 used in this example).

Code: create and enable swap (optional)
# mkswap /dev/sda2
# swapon /dev/sda2


Basic configuration

Note: This section corresponds to chapters 8 and 9 of part one of the Gentoo Handbook.

Checking the relevant config files

You should have a look in all the important config files to make sure they are set up the way you want:

File: /etc/fstab working example with /dev/sda1 as the root partition
...
/dev/sda1               /               ext3            defaults                0 2
/dev/sda2               swap            swap            defaults                0 0
proc                    /proc           proc            defaults                0 0
usbfs                   /proc/bus/usb   usbfs           defaults                0 0
shm                     /dev/shm        tmpfs           nodev,nosuid,noexec     0 0
...
File: /etc/conf.d/net working example with static IP
...
config_eth0="192.168.1.77/24"
routes_eth0="default via 192.168.1.1"
...

If you want your NSLU2 to run with a different timezone than UTC, you have to set the TZ environment variable (/etc/localtime will not work with uclibc). See this FAQ entry for more details. The value of the TZ variable can be stored in /etc/TZ. An example value for CEST would be:

File: /etc/TZ working example setting the local timezone to CEST
CEST-1CEST-2,M3.5.0,M10.5.0

Don't forget to set the password for root:

Code: Set root password
# passwd


Making the ethernet interface work

Since you certainly want the ethernet interface to be available we add the following two items to /etc/modules.autoload.d/kernel-2.6 in order to load the network driver during bootup:

File: /etc/modules.autoload.d/kernel-2.6
...
ixp4xx_qmgr
ixp4xx_mac
...

If you are using a proxy server to access the internet on your slug, you will need to add the following settings to /etc/profile

File: /etc/profile
export http_proxy="192.168.1.100:1234"
export ftp_proxy="192.168.1.100:1234"
export RSYNC_PROXY="192.168.1.100"

making sure the correct IP addresses and ports are specified. then type

Code: source /etc/profile
# source /etc/profile

the proxy settings should now work.

Make sure the ethernet controller gets started at system boot :

Code: Add net.eth0 to the default runlevel
# rc-update add net.eth0 default


Installing the relevant system tools

Also install any system tools you want; at a bare minimum you should have a syslogger, for example metalog. If you are using DHCP for your network configuration, don't forget to emerge a DHCP client as well.

Code: Emerge metalog & dhcpcd
# emerge -av metalog dhcpcd
Code: If applicable add syslogger and/or DHCP client to the default runlevel
# rc-update add metalog default
# rc-update add dhcpcd default

You will need to install an SSH server to access the Slug, since the SSH server on the flash disk will not be used. Dropbear is really simple and lightweight and openssh is the "industry standard" with lots of options. The compile will take a while, since there's not a lot of CPU to go around.

Code: Emerge SSH Server
# emerge dropbear

or

Code: Emerge SSH Server
# emerge net-misc/openssh

Add the ssh server to the default runlevel:

Code: Add SSH Server to the default runlevel
# rc-update add dropbear default

or

Code: Add SSH Server to the default runlevel
# rc-update add sshd default

You should have a cron daemon (vixie-cron is recommended).

Code: Emerge vixie-cron
# emerge vixie-cron
Code: Add vixie-cron to the default runlevel
# rc-update add vixie-cron default


Create the flash mount point

When the SlugOS flash image boots your Gentoo installation, it "swivels" the root so that Gentoo ends up mounted as root and the flash filesystem is mounted in a subdirectory underneath it. SlugOS will use as the mount point /initrd, if found on the Gentoo filesystem; otherwise it falls back to /mnt (which is pretty much guaranteed to exist).

The Gentoo stage does not include a /initrd directory so you should create it:

Code: Create the flash mount point
# mkdir /initrd

This will keep /mnt free for mounting other filesystems as usual.


Symlink chroot

SLugOS will try to use the chroot image on the Gentoo system when booting. It will search for it in /usr/sbin, but Gentoo has chroot in /bin, so you should add a symlink:

Code: Add symlink to chroot
# ln -s /bin/chroot /usr/sbin/chroot


Ensure /.recovery is removed

One final important step is to add the following line to /etc/conf.d/local.start:

File: /etc/conf.d/local.start
...
rm /.recovery
...

The /.recovery file is touched by the boot scripts on the flash rootfs, with the assumption that once booting is finished it will be removed. If you try to reboot with /.recovery present, the flash boot scripts will assume that the previous boot attempt failed and will fall back to booting from flash.


Rebooting into your new system

Before you are able to use your new Gentoo system you first need to tell SlugOS to boot off of your hard disk rather than the flash rootfs. Luckily this is not as hard as it sounds. First you need to exit from your chrooted environment and un-mount your drive:

Code: Exit from the chrooted environment
# exit
# cd /
# umount /mnt/gentoo/proc
# umount /mnt/gentoo/dev/pts
# umount /mnt/gentoo/dev
# umount /mnt/gentoo

Now all that remains is to tell SlugOS to boot off of your hard disk and reboot (assuming that the device that you want to boot off of is /dev/sda1 and that it is an ext3 partition):

Code: Change the root device and reboot
# turnup disk /dev/sda1 -t ext3
# reboot


Some other random things, in order of importance

Swap

Portage itself (particularly emerge metadata), as well as many of the compiles (Perl, I'm looking at YOU!) are extremely memory-hungry. Make sure you have lots of swap enabled before attempting any of these. I think 128 MB is probably enough, but I am using 512 MB. If you are doing anything serious with your slug you will probably need plenty of swap anyway. In the case that your swap partition isn't big enough and your compiles fail due to lack of memory you can add a swap file on your attached disk. Consulting man mkswap should give enough info already but here's an example for the impatient:

Code: Adding temporary 128MB swap file
# dd if=/dev/zero of=/tmp/swapfile bs=1024 count=131072
# mkswap /tmp/swapfile
# swapon /tmp/swapfile

When you're done using it, just do a

Code: Clearing temporary swap
# swapoff /tmp/swapfile
# rm /tmp/swapfile

to get rid of the swap file again. If you however want to add the swap file permanently, edit your /etc/fstab accordingly.


CFLAGS

The armeb stages are compiled for a generic big-endian ARM target, with the -Os ("optimise for small size") CFLAG set, but perhaps better performance could be had by telling GCC exactly what type of CPU you are using. Apparently SLugOS uses -march=armv5te -mtune=xscale. I would suggest adding this to your CFLAGS in /etc/make.conf. The reason for not using -march=xscale is simply that there are no such valid value according to: http://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/ARM-Options.html.

File: /etc/make.conf
...
CFLAGS="-march=armv5t -mtune=xscale -Os"
CHOST="armeb-softfloat-linux-uclibc"
CXXFLAGS="${CFLAGS}"
...

You could run emerge -e system to recompile everything, if you wanted to make sure every part of your system takes advantage of the new CFLAGS. But be warned — only do this if you don't need your slug for a few days! On mine it took around 36 hours to compile everything, Perl and GCC being the worst culprits. Also see above re swap. I would suggest that you don't bother with this, as pretty much everything will eventually be recompiled when you update it.

Note: The above is certainly needed when you want to use distcc to cross-compile on another host.


Kernel headers

The uclibc embedded stages use the uclibc/arm/2.4 profile by default, which will prevent you from installing newer versions of the kernel headers. This is not harmful, but prevents uclibc from taking advantage of newer features provided by the 2.6 kernels.

If you change your /etc/make.profile symlink to point to the uclibc/arm profile instead (no 2.4 subdir) Portage will let you upgrade to the 2.6 headers. This is recommended. Note that you will also need to re-emerge uclibc after this, to take advantage of the new headers.

Code: Update /etc/make.profile symlink
# rm  /etc/make.profile
# ln -s ../usr/portage/profiles/uclibc/arm /etc/make.profile

Notes from users

This repeatedly caused my system updates to crash with endless uclibc-errors. If you know the cause of this, please post. If not, and you encounter similar problems, it should be safe to omit this part. ---Daniel


I too have had issues with this. so suggest not doing this.


I had the same grief but a potential solution appears to be emerging ('scuse the pun) I am past all my previous failures and currently well into an emerge -e system compile. Will confirm as success if everything completes. uclibc is confirmed to emerge without problem.

Steps:

Code: Ensure package tree current
# emerge --sync; emerge portage
File: Update /etc/make.conf
...
UCLIBC_CPU="ARM_XSCALE"
USE="uclibc <your other use flags>"
...

[>=2.6.19 do not work, 2.6.17.* are suspected to work but hung my nslu2 on emerge]

File: Update /etc/portage/package.mask
... 
>=sys-kernel/linux-headers-2.6.12
...
Code: Update sytem
# emerge linux-headers
# emerge -e system

Tarek---

The /dev tree

The uclibc/arm/2.4 profile, which is selected by default in the stage (see above), includes devfsd (although it is not run by default). I suggest setting Gentoo to use a simple static /dev tree :

File: /etc/conf.d/rc
...
RC_DEVICES="static"
...


inittab

The default Gentoo /etc/inittab runs six instances of agetty on the first six virtual ttys, as well as two instances on ttyS0 and ttyS1. Since we don't have a console on the NSLU2 we can save memory (and error messages in /var/log/messages!) by commenting out the lines for the six virtual ttys. I have also commented the lines for the serial ports, but if you have a serial connection on your slug you will of course want to leave in the line for ttyS0.

File: /etc/inittab
...
# TERMINALS
#c1:2345:respawn:/sbin/agetty 38400 tty1 linux
#c2:2345:respawn:/sbin/agetty 38400 tty2 linux
#c3:2345:respawn:/sbin/agetty 38400 tty3 linux
#c4:2345:respawn:/sbin/agetty 38400 tty4 linux
#c5:2345:respawn:/sbin/agetty 38400 tty5 linux
#c6:2345:respawn:/sbin/agetty 38400 tty6 linux

# SERIAL CONSOLES
#s0:12345:respawn:/sbin/agetty 115200 ttyS0 vt100
#s1:12345:respawn:/sbin/agetty 9600 ttyS1 vt100
...


syslog-ng

The default Gentoo /etc/syslog-ng/syslog-ng.conf instructs syslog-ng to display all messages on /dev/tty12, as well as logging them to /var/log/messages. Ordinarily this is really helpful (just hit Alt+F12 to see the latest log entries) but of course on the headless NSLU2 this is just a waste. Two lines need to be commented out:

File: /etc/syslog-ng/syslog-ng.conf
...
# By default messages are logged to tty12...
#destination console_all { file("/dev/tty12"); };
...
log { source(src); destination(messages); };
#log { source(src); destination(console_all); };


LEDs

SlugOS uses the slug's LEDs to signal the various stages of the boot process. Gentoo will of course do nothing of the sort by default, so you will end up with a flashing amber status LED even once bootup is finished. I would suggest adding a few boot scripts to (roughly) mimic the SlugOS behaviour.


SlugOS 3.10 and above

You can use the file from /initrd/sbin/leds - copy it to the /usr/local/sbin/ directory

Code: Add leds.boot to the boot runlevel
# cp /initrd/sbin/leds /usr/local/sbin

and edit line 10 and 11 to change the path to /initrd/etc/default/rcS and /initrd/etc/defaults/functions.

File: /usr/local/sbin/leds
...
*)      . /initrd/etc/default/rcS
        . /initrd/etc/default/functions;;
...

To get the same effect during booting as with SlugOS, create /etc/init.d/leds.boot as follows

File: /etc/init.d/leds.boot
#!/sbin/runscript

start() {
	/usr/local/sbin/leds system
}

and add it to the boot runlevel as above:

Code: Add leds.boot to the boot runlevel
# chmod +x /etc/init.d/leds.boot
# rc-update add leds.boot boot

Add this line to local.start to set the status LED green once everything has finished booting:

File: /etc/conf.d/local.start
...
/usr/local/sbin/leds user
...

Add this line to local.stop to have a flashing green/amber status LED at system shutdown and reboot:

File: /etc/conf.d/local.stop
...
/usr/local/sbin/leds shutdown
...


OpenSlug 2.7 and below

Firstly, you will need to compile and install the OpenSlug leds program. Just pull out leds.h and leds.c from the OpenSlug source tarball (or from Subversion) and compile them (under your Gentoo system) with

# gcc -Os -march=armv5te -mtune=xscale -o leds leds.c

and copy the resulting output leds to /usr/local/sbin. You will also need to create /dev/leds with

# mknod /dev/leds c 126 0

You can now use this program to set the LEDs. I created an initscript:

File: /etc/init.d/leds.boot
#!/sbin/runscript

start() {
	/usr/local/sbin/leds +gr
}

and added it to the boot runlevel:

Code: Add leds.boot to the boot runlevel
# chmod +x /etc/init.d/leds.boot
# rc-update add leds.boot boot

I also added a line to local.start to set the status LED green once everything has finished booting:

File: /etc/conf.d/local.start
...
/usr/local/sbin/leds -r +g
...

Add this line to local.stop to have a flashing green/amber status LED at system shutdown and reboot:

File: /etc/conf.d/local.stop
...
/usr/local/sbin/leds !r +g
...


Power Button

The default behaviour under SlugOS is to power off when the power button on the front is pressed. The default Gentoo behaviour is to restart when the button is pressed. To get the same behaviour as SlugOS, alter the "ctrlaltdel" entry in /etc/inittab:

File: /etc/inittab
...
# What to do at the "Three Finger Salute".
ca:12345:ctrlaltdel:/sbin/shutdown -hP now
...


Make beep beep again

The standard app-misc/beep does not work on the slug. See http://bugs.gentoo.org/show_bug.cgi?id=235428 for an ebuild patching beep and also symlinking /usr/bin/beep to /bin/beep so that the leds script can also beep again.


MAC address

As of OpenSlug 3.10 and newer versions and with SlugOS-4.8beta at least the MAC address is correctly detected and handled by the kernel. Its unlikely that you will need this work around (and it actually stops udhcpc from working properly), however if you notice that the Slug changed its MAC address that's because their address is not fixed, but stored in flash memory and configured at each boot. To let Gentoo use this address, you might find it useful to add the following to you network configuration:

File: /etc/conf.d/net
preup() {
        /sbin/ifconfig eth0 hw ether "$(/bin/grep '^hw_addr=' /initrd/etc/default/sysconf | /usr/bin/cut -d '=' -f 2)"
        return 0
}

Note that etc/default/sysconf referred to above is stored on the flash filesystem, so its path will depend on where the flash ends up mounted in your Gentoo filesystem (see above).

Attention: Be aware: With that little Workaroud my MAC address changes every bootup. With a kind like this: 42:10:BE:xx:xE:2C. Inssert nothing in there will keep the right one!

See Initialising OpenSlug

Retrieved from "http://www.gentoo-wiki.info/Linksys_NSLU2"

Last modified: Sat, 30 Aug 2008 04:58:00 +0000 Hits: 25,214