NSLU2-Linux
view · edit · print · history

Introduction

As the Linksys WAG354G wireless ADSL router uses the same CPU core, endianess, kernel version and uClibc version as the WL500G it occured to me that it might be possible to run the executables from the WL500G optware feed on it. The minor fly in the ointment was the lack of any form of remote login capability hence the first step had to be creating a modified version of the firmware. I decided I wanted to take a similar approach to Unslung, modifying the original functionality as little as possible while adding the new function I wanted.

How to get Optware on WAG354G

The WAG354G doesn't have any way of adding a local disk so /opt has to be on some form of remote disk (I've chosen NFS, Samba is probably possible but the lack of true unix permissions might cause some problems). If you only want one or two programs you could just copy them to the RAM disk.
You can get Optware on your WAG354G by:

  1. Using an already-built firmware
  2. Building your own firmware from sources.

1. Using an already-built firmware

Neptune354 is a firmware for WAG354G and HG200 routers, that contains all the needed stuff required by Optware.

Installation

Once you have flashed Neptune354 firmware on your router, you can automatically mount a NFS folder at boot, using the web interface (Administration->Utility).
NFS share is mounted on /opt, you can check it using the mount from telnet. Then, simply enter: optware-install
All the needed binaries are downloaded from Internet and installed in /opt folder. Once download and installation is finished, if you've never used ipkg utility, read How To Use ipkg

Known Issues

The command optware-install and the download of packages with ipkg, can be done only with router connected to Internet from the ethernet ports. I really dont know the reason of this. I see that wget breaks the download after some kB of download. I have tried with another version of wget without succes, so the problem is elsewhere.
To access Internet from the ethernet ports, you need another ADSL modem with an ethernet port. Set up the WAG354G as follows:

  1. Enter
    route add default gw ip-of-modem
  2. Add to /etc/resolv.conf a line with a valid dns server (usually the modem ip is ok):
    nameserver ip-of-dns
  3. Enter
    killall -HUP dnsmasq

2.Build your own firmware from sources.

The Toolchain

Linksys included a minimal tool chain in the old UK firmware version (WAG354G-UK-v1_01_03-001.tar.gz) at http://www.linksys.com/gpl. As it explains in the associated Readme, this requires you to add the MontaVista 2.1 preview kit to it and then replace the binutils in that preview kit that are linked against some obsolete dynamic libraries with newer versions. As the only link I could find to that preview kit included some non-GPL MontaVista material and didn't include source to the GPL material I won't provide a link here. That was the route I took to set up a toolchain but I now suspect that it would equally be possible to use the WL500G toolchain at http://dlsvr01.asus.com/pub/ASUS/wireless/WL-500g-03/GPL_1927.zip - I'll update this when I get a chance to try it.

One huge gotcha with the Linksys supplied toolchain is that the copy of linux/atm.h in the toolchain doesn't match the one in the kernel which prevents PPPoA from working. Copy WAG354G-EU-v1_01_05-004/src/linux/linux-2.4.17_mvl21/include/linux/atm.h into include/linux in the toolchain to fix it.

Modifying the firmware

I used the EU 1.01.05 release as the basis for my modified firmware. My firmware changes fall into 6 categories:

  1. Adding NFS support to the kernel
  2. Adding facilities to uClibc that Linksys chose to omit
  3. Adding a remote login capability
  4. Adding an ability to specify a command to run at reboot
  5. Making busybox support mounting NFS shares
  6. Creating a /opt directory (The root file system uses squashfs which is readonly)

Adding NFS support to the kernel

In the kernel directory (WAG354G-EU-v1_01_05-004/src/linux/linux-2.4.17_mvl21) use make menuconfig to add these 3 options to the kernel:

  • CONFIG_NFS_FS=y
  • CONFIG_SUNRPC=y
  • CONFIG_LOCKD=y

TODO: see if there is room to add NBD support as well to allow for a remote host to be used to provide swap space - swapping over NFS requires extensive kernel patching.

Adding facilities to uClibc that Linksys chose to omit

unpack the uClibc archive in WAG354G-EU-v1_01_05-004/tools-src and use make menuconfig to enable the following options:

  • UCLIBC_HAS_FLOATS=y
  • HAS_FPU=y
  • LDSO_LDD_SUPPORT=y
  • UCLIBC_HAS_RPC=y

and change the kernel source directory to point at where you have unpacked the kernel source. Build uClibc and copy the resulting libuClibc-0.9.19.so, ld-uClibc-0.9.19.so and libm-0.9.19.so to the lib directory in the toolchain.

Warning: I'm still running a firmware version where I failed to include the floating point support before doing this and I've got the FP capable uClibc in /opt/lib. It is just possible that ther will be space problems doing it properly but you must at least have RPC support in the uClibc in flash otherwise NFS mount won't work.

Adding a remote login capability

Linksys did include most of what you need for remote login but then disabled it. To turn what they did back on you need to edit 2 files in WAG354G-EU-v1_01_05-004/src,

src/cy_conf.h
25,26c25,26
< #define       CLI_SUPPORT     1
< #define       CONFIG_CLI      y
---
> //#define     CLI_SUPPORT     0       <remove the line>
> //#define     CONFIG_CLI      n       <remove the line>

src/cy_conf.mak
26,27c26,27
< CLI_SUPPORT=1
< CONFIG_CLI=y
---
> #CLI_SUPPORT  is not set     <remove the line>
> # CONFIG_CLI is not set       <remove the line>

You then need to comment out the bit around line 211 in WAG354G-EU-v1_01_05-004/src/router/Makefile where it adds parser to the list of objects to build if the CLI is enabled and edit src/router/rc/mketc.c to use a normal shell

15c15
<       fprintf(passwd,"%s:0:0::/tmp:/bin/sh\n",crypt(nvram_safe_get("http_passwd"),"Zi"));
---
>       fprintf(passwd,"%s:0:0::/tmp:/bin/configurator\n",crypt(nvram_safe_get("http_passwd"),"Zi"));
17c17
<       fprintf(passwd,"%s:0:0::/tmp:/bin/sh\n",crypt(nvram_safe_get("http_remote_passwd"),"Zi"));
---
>       fprintf(passwd,"%s:0:0::/tmp:/bin/configurator\n",crypt(nvram_safe_get("http_remote_passwd"),"Zi"));

Adding an ability to specify a command to run at reboot

In order to automate starting up with Optware available you need to be able to specify an action to run at boot. The normal Linux startup script is actually a binary in the read only file system so we need to change this binary to grab a command to run from NVRAM.

--- rc/rc.c     2006-03-02 23:06:03.000000000 +0000
+++ ../../../clean/WAG354G-EU-v1_01_05-004/src/router/rc/rc.c   2005-08-25 10:04:16.000000000 +0100
@@ -85,20 +85,4 @@
 extern unsigned int firstsetlanip;

-static void doScript(void)
-{
-    if (fork() == 0)
-    {
-        char * cmd;
-        sleep(5);
-        cmd=nvram_get("boot_command");
-        if ((cmd != NULL) && (strcmp(cmd,"boot_command") != 0))
-        {
-            system(cmd);
-        }
-        exit(0);
-    }
-
-}
-
 static void restore_all_pvc_defaults(void)
 {
@@ -599,5 +583,4 @@
        cprintf("now insmod tiatm\n");
        eval("insmod", "tiatm");
-        doScript();

        for (;;) {

Making busybox support mounting NFS shares

NFS support is useless if we can't run a mount command so we need to change the busybox command to support mount

src/router/busybox/Config.h
86c86
< #define BB_MOUNT
---
> //#define BB_MOUNT
257c257
< #define BB_FEATURE_NFSMOUNT
---
> //#define BB_FEATURE_NFSMOUNT

Creating a /opt directory (The root file system uses squashfs which is readonly)

Add the line "mkdir -p opt" to the end of src/router/misc/rootprep.sh

Build the firmware

Just follow Linksys's instructions. Note that the symlink to cy_codepattern.h in the kernel includes directory sometimes ends up broken after multiple rebuilds, just create a new one.

Install the firmware

If anything goes wrong with your new firmware you'll need to use the bootloaders upgrade capabilty. It isn't as easy to prove this works for you as it is with unslung but at least make sure you've got the rigth programs installed. To do an upgrade via the bootloader instead of using the web interface do sudo arping -f 192.168.1.1 ; tftp -m binary 192.168.1.1 -c put upgrade_code.bin After doing an upgrade this way, the only way to tell it has completed and that the bottom LED stops blinking - If you switch off before that point you will end up with a router where doing the above command or soldering up a serial interface are the only ways to fix it.

Mount your /opt directory

Log in to your upgraded router and type

nvram set boot_command="mount -t nfs -o nolock,rw,nfsvers=2 host:path /opt;/opt/etc/rc"

nvram save

and then reboot. host needs to be specified in dotted decimal form as DNS may not be usable when this command runs.

Set up ipkg on /opt

You need to build ipkg itself and also a couple of busybox utilities that you are likely to need. The version of wget in busybox 0.60 which is what is in the firmware doesn't support http redirect which is needed by the Optware feeds mirror system so rather than upgrade the stock busybox I chose to put a new busybox in /opt.

In order to make ipkg live in /opt, keep all its data in /opt and use /opt/tmp as its temp directory (necessary otherwise large packages can fill the RAM disk) you need to make some patches to ipkg. I used ipkg V0-99-148 as a base version with the diffs below..

Index: ipkg_cmd.c
===================================================================
RCS file: /cvs/familiar/dist/ipkg/C/ipkg_cmd.c,v
retrieving revision 1.103
diff -r1.103 ipkg_cmd.c
238c238
<             tmp = strdup ("/tmp/ipkg.XXXXXX");
---
>             tmp = strdup ("/opt/tmp/ipkg.XXXXXX");
Index: ipkg_conf.c
===================================================================
RCS file: /cvs/familiar/dist/ipkg/C/ipkg_conf.c,v
retrieving revision 1.78
diff -r1.78 ipkg_conf.c
106c106
<      char *etc_ipkg_conf_pattern = "/etc/ipkg/*.conf";
---
>      char *etc_ipkg_conf_pattern = "/opt/etc/ipkg/*.conf";
Index: ipkg_conf.h
===================================================================
RCS file: /cvs/familiar/dist/ipkg/C/ipkg_conf.h,v
retrieving revision 1.34
diff -r1.34 ipkg_conf.h
32c32
< #define IPKG_CONF_DEFAULT_TMP_DIR_BASE "/tmp"
---
> #define IPKG_CONF_DEFAULT_TMP_DIR_BASE "/opt/tmp"
Index: update-alternatives
===================================================================
RCS file: /cvs/familiar/dist/ipkg/C/update-alternatives,v
retrieving revision 1.4
diff -r1.4 update-alternatives
24c24
< ad="$IPKG_OFFLINE_ROOT/usr/lib/ipkg/alternatives"
---
> ad="$IPKG_OFFLINE_ROOT/opt/lib/ipkg/alternatives"

Then to actually configure and build ipkg type

./configure CC=mipsel-uclibc-gcc --host=mipsel-*-linux --prefix=/opt LD_FLAGS=-Wl,-rpath,/opt/lib@@
make
make install DESTDIR=/tmp/ipkg
cd /tmp/ipkg/opt
tar cf ../ipkg.tar .

and unpack the tar file in /opt (generally it is easier to do this on the NFS host)

To build busybox I used version 1.1.0 which now uses make menuconfig. Edit the configuration to cross compile with a compiler prefix of mipsel-uclibc- and disable all of the commands and shells except wget, sed and umount. Type make to build busybox, copy the executable to /opt/bin (it's best to give it a different name to avoid confusion with the one in /bin) and create links from /opt/bin/{sed,wget,umount} to it.

Finally you need to configure feeds so create /opt/etc/ipkg/wl500g.conf with the contents src/gz wl500g http://ipkg.nslu2-linux.org/feeds/unslung/wl500g

view · edit · print · history · Last edited by fcarolo.
Based on work by fcarolo, cyberstorm, and Adam Baker.
Originally by Adam Baker.
Page last modified on February 05, 2008, at 08:07 PM