Skip to main content

i. The current situation

There are various articles describing how to install and run Debian GNU/Linux on USB flash memory on an Asus WL-500W. This guide differs in that it will provide a complete end-to-end set of instructions. All you need is an Asus WL-500W, USB flash memory (say, 2 GB in size), a computer to build the firmware and Debian root filesystem, and an Internet connection to get the source code for OpenWRT and packages for Debian.

ii. Summary

There are three main, separate components to this work. Parts 1 and 2 can be run in any sequence. Part 3 requires parts 1 and 2 to be completed first. Part 2 requires root access to the local machine.

  1. Building and installing OpenWRT firmware
  2. Installing Debian MIPS on USB flash
  3. Integrating OpenWRT and Debian

This guide has been tested on various versions of OpenWRT ranging from Kamikaze (trunk) revision 16424 to Backfire (branch) revision 36945. Originally this guide was written for Debian Lenny but it has been tested and updated for Squeeze and Wheezy.

1. Building and installing OpenWRT firmware

This part of the process is performed by a normal, non-root user. It was run on a x64 Debian Lenny machine, but could be executed on a variety of architectures as OpenWRT builds its own cross compiling tool chain.

All commands should be run from a command terminal. Builds were made under /home/ewan/qemu/openwrt-7 but could be built anywhere.

1.1. Check-out latest OpenWRT source code

$ mkdir /home/ewan/qemu
$ mkdir /home/ewan/qemu/openwrt-7
$ cd /home/ewan/qemu/openwrt-7
$ svn checkout svn://svn.openwrt.org/openwrt/branches/backfire
$ mv -i backfire/ backfire-32396

Alternatively, you might need to check-out an older revision of the OpenWRT source code, thus.

$ svn checkout --revision 26314 svn://svn.openwrt.org/openwrt/trunk/ trunk-26314

1.2. Configure OpenWRT and BusyBox

$ cd backfire-32396
$ make menuconfig

Now make the following configuration changes. This will ensure a 2.6 Linux kernel is used and USB is enabled.

  • Enter Change Target System
    • Choose Broadcom BCM947xx/953xx
    • Select
  • Select and enter Advanced configuration options
    • Select and enter Target options
      • De-select Use software floating point by default
      • Exit
    • Exit
  • Enter Base system
    • Ensure the following are selected (*)
      • base-files
      • block-extroot
      • busybox
      • dropbear
      • firewall
      • mtd
      • nvram
      • udevtrigger
    • Ensure the following are selected as modules (M)
      • bridge
    • De-select the following
      • dnsmasq
    • Exit
  • Enter Network
    • Ensure the following are selected (*)
      • ppp
    • Select as a module (M)
      • arptables
      • ebtables
      • ip
    • De-select the following
      • wpad-mini
    • Enter iptables
      • Select everything as a module
      • Exit
    • Exit
  • Enter IPv6
    • Select ip6tables as a module
    • Exit
  • Enter Kernel modules
    • Enter Block Devices
      • Select as a module (M)
        • kmod-loop
        • kmod-scsi-core
      • Exit
    • Enter Filesystems
      • Select kmod-fs-ext3
      • Select kmod-fs-ext4
      • Exit
    • Enter Netfilter Extensions
      • Select as a module (M)
        • kmod-ebtables
        • kmod-ebtables-ipv4
        • kmod-ebtables-ipv6
        • kmod-ipt-nathelper
        • kmod-ipt-nathelper-extra
        • kmod-ipt-queue
        • kmod-nf-conntrack-netlink
        • kmod-nfnetlink
        • kmod-nfnetlink-log
        • kmod-nfnetlink-queue
      • Exit
    • Enter Network Support
      • Select as a module (M)
        • kmod-ip6-tunnel
        • kmod-ipip
        • kmod-tun
      • Exit
    • Enter USB Support
      • Ensure the following are selected (*)
        • kmod-usb-core
        • kmod-usb-ohci
        • kmod-usb-storage
        • kmod-usb-uhci
        • kmod-usb2
      • Select as a module (M)
        • kmod-usb-acm
        • kmod-usb-printer
        • kmod-usb-serial (and all sub-options)
      • Exit
    • Exit
  • Enter Utilities
    • Enter disc
      • Select swap-utils
      • Exit
    • Select losetup, mount-utils and robocfg
    • Exit
  • Exit

When asked Do you wish to save your new OpenWrt configuration? answer Yes.

Now run

$ make -j 8

Press CTRL-C to interrupt the build when the display shows

 make[3] -C target/linux compile

Next, run

$ make kernel_menuconfig
  • Select Enable FPU emulation
  • Enter Networking support
  • Enter Networking options
  • Select as a module (M)
    • IP: tunneling
  • Select (*)
    • IP: PIM-SM version 1 support
    • IP: PIM-SM version 2 support
  • Exit, Exit
  • Enter File systems
  • Select (*)

    • Inotify support for userspace

    This allows udev in Debian 6.0 (squeeze) to assign network interface names correctly.

  • Exit, Exit
  • when asked Do you wish to save your new kernel configuration? choose Yes.

It's really amazing how something as simple as selecting the FPU emulation, above, can cause problems. It took two days to discover why my base build at revision 16424 worked at the pivot_root and the latest trunk revision did not. Firstly I scanned the change logs to roll back to earlier kernels (revisions 20444, 18635 and 17732, if you are interested). No change, so tested a different version of BusyBox. Still no change. So I performed a binary search through the revisions, loading and testing each one until I found revisions between a small range that did and did not work. From there I found that revision 16605 was responsible for the breakage. Now, if you use a search engine to find MIPS_FPU_EMU, the cause of the failure seems obvious. But not many people have found it. When fixed, the kernel logs show the following once the pivot_root is performed.

Algorithmics/MIPS FPU Emulator v1.5

1.3. Build firmware

Now preserve the config files that we have painstakingly built.

$ cp -pi .config ../config-32396
$ cp -pi build_dir/linux-brcm47xx/linux-2.6.32.27/.config ../kconfig-32396

Build the firmware.

$ make -j 8

The downloads and compilations took about forty minutes on my hardware.

Retain a copy of the kernel modules associated with the OpenWRT kernel.

$ mkdir ../modules-32396
$ cd build_dir/linux-brcm47xx/linux-2.6.32.27/
$ ARCH=mips INSTALL_MOD_PATH=../../../../modules-32396 make modules_install
$ cd ../../../../modules-32396/
$ fakeroot tar cvf ../modules-32396.tar .

Finally, save the precious firmware image.

$ cd ..
$ mkdir build-32396
$ cp -pi backfire-32396/bin/brcm47xx/openwrt-brcm47xx-squashfs.trx build-32396/

1.4. Upload firmware

As root, configure the network so the local machine can 'see' the router on IP address 192.168.1.1, e.g.

# ifconfig eth0:0 192.168.1.2

Now, back as a normal user again, prepare to upload the firmware image. Plug a network cable into LAN port 1 of the router. Hold down the restore button and plug in the power. Wait for the power LED to flash. Release the restore button. Run the following commands.

$ cd build-32396
$ tftp 192.168.1.1
tftp> binary
tftp> trace
tftp> put openwrt-brcm47xx-squashfs.trx
tftp> quit
$ sleep 120

The reason why there is a two minute wait is to ensure that the router has had sufficient time to copy the firmware image from its RAM into its flash RAM. Power off the router.

2. Installing Debian MIPS on USB flash

Much of the process of loading Debian GNU/Linux onto USB requires the root user. Therefore it is assumed that this user will be used throughout this section. Run these commands on a fast computer. Ensure that qemu is installed.

2.1. Download Debian installer

Fetch the kernel and initrd files needed for the MIPS installer.

# wget http://ftp.nl.debian.org/debian/dists/lenny/main/installer-mipsel/current/images/malta/netboot/initrd.gz
# wget http://ftp.nl.debian.org/debian/dists/lenny/main/installer-mipsel/current/images/malta/netboot/vmlinux-2.6.26-2-4kc-malta

2.2. Install base system

Determine the device of the USB flash.

# cat /proc/partitions >/tmp/part1

Insert the USB memory into a spare USB port, then run the following.

# cat /proc/partitions >/tmp/part2
# diff /tmp/part1 /tmp/part2
12a13,14
>    8   112    3928063 sdh
>    8   113    3919841 sdh1

If the USB is automatically mounted by your operating system, dismount it.

# df -k | grep sdh1
# umount /dev/sdh1

Create a little-endian MIPS virtual machine with the USB flash memory available and running the Debian installer.

# qemu-system-mipsel -M malta -m 256 -nographic -no-reboot -hda /dev/sdh -kernel vmlinux-2.6.26-2-4kc-malta -initrd initrd.gz

Now perform the installation of Debian GNU/Linux onto the USB flash. A brief, basic set of configuration options follow for a 4 GB USB flash stick.

2.3. Prepare operating system

The partition table on the USB memory must be re-read and the disk remounted so that some configuration can be applied to the Debian operating system from the host system. Unplug the USB memory. Plug it back into a free USB slot. Dismount the filesystem on the USB, if necessary. Remove filesystem checks (as the WL-500W does not have a battery backed-up clock). Place the OpenWRT kernel modules onto the USB filesystem.

# umount /dev/sdh1
# tune2fs -c0 -i0 /dev/sdh1
# mount /dev/sdh1 /mnt
# cd /mnt
# tar xvpf /home/ewan/qemu/openwrt-7/modules-32396.tar

The root filesystem I have set up assumes that OpenWRT's robocfg tool is available in Debian to configure the switch. This way there is no need to remove the USB and reboot into OpenWRT to perform and test switch configuration changes.

You should copy the directory /home/ewan/qemu/openwrt-7/backfire-32396/package/robocfg to a MIPS machine running Debian. You could create a new virtual machine or use the operating system just installed. Next, the executable can be built.

$ cd /usr/local/src/robocfg
$ make

You could download a pre-compiled executable (md5sum 749324a49984fa0d1e5c78d999508200). This was built from OpenWRT revision 16424 on Debian Lenny on 12th June 2009.

Copy the robocfg file to the USB flash at /usr/local/sbin.

# cp -pi /tmp/robocfg usr/local/sbin
# chown root:root usr/local/sbin/robocfg
# chmod 755 usr/local/sbin/robocfg

Create a directory to which we will pivot the old OpenWRT root filesystem to.

# mkdir initrd

To make the task of replacing the init script on the router more straightforward, create a new file root/init on the USB filesystem containing the following.

#!/bin/sh
debug=0
# change this to your boot partition
boot_dev="/dev/sda1"
# this may need to be higher if your disk is slow to initialise
usb_wait="10s"
#root@OpenWrt:/# ls -l /sbin/init
#lrwxrwxrwx    1 root     root           14 Jun 13  2009 /sbin/init -> ../bin/busybox
# install needed modules for usb and the ext3 filesystem
# **NOTE** for usb2.0 replace "uhci" with "ehci-hcd"
# **NOTE** for ohci chipsets replace "uhci" with "usb-ohci"
for module in nls_base usbcore scsi_mod crc-t10dif sd_mod ehci-hcd uhci-hcd ohci-hcd usb-storage jbd ext3 switch-core switch-robo switch-adm cfg80211 mac80211 b43 b43-legacy; do {
   insmod $module
}; done
sleep $usb_wait
if [ $debug -ne 0 ]; then
   mkdir /old_debug
   mv /debug* /old_debug
   dmesg >/debug_dmesg
   cat /proc/partitions >/debug_partitions
   lsmod >/debug_lsmod
fi
# mount the usb stick
mount -o ro,errors=remount-ro,noatime "$boot_dev" /mnt
# prevent 'ps' from abending by setting the btime
date -s 12:00
if [ $debug -ne 0 ]; then
   df >/debug_df1
   ls -l /mnt/sbin/init >/debug_ls1
fi
if [ -x /mnt/sbin/init ]; then
   if [ $debug -ne 0 ]; then ls -l /mnt/sbin/init >/debug_ls2; fi
   killall hotplug2
   cd /mnt
   pivot_root . initrd
   if [ $debug -ne 0 ]; then df >/initrd/debug_df2; fi
   # finally, run the real init (from USB).
   if [ $debug -eq 0 ]; then
      #umount /initrd/rom
      #umount /initrd/tmp
      #umount /initrd/dev
      #umount /initrd/overlay
      #umount /initrd
      exec /sbin/init
   else
      exec /sbin/init >/initrd/debug_init1 2>/initrd/debug_init2
   fi
fi
# finally, run the original init (from flash).
exec /bin/busybox init

Set the correct permissions.

# chmod +x root/init

Now replace the contents of etc/fstab on USB. Note that for Debian 7.0 Wheezy you must comment out the root filesystem in the fstab to prevent e2fsck giving you a maintenance prompt at every boot. I had to build a serial cable to find and fix this!

# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
/dev/sda1       /               ext3    defaults,errors=remount-ro,noatime 0       1
/dev/sda2       none            swap    sw                      0       0
ramdisk         /var/run        tmpfs   defaults,size=163840    0       2
ramdisk         /var/lock       tmpfs   defaults,size=163840    0       2
ramdisk         /etc/network/run tmpfs   defaults,mode=0755,size=16384                0       2
ramdisk         /tmp            tmpfs   defaults                0       2

Pre-configure Debian's network interfaces. Edit etc/network/interfaces Interface eth0 will be the LAN interface and eth1 will be the WAN interface.

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto eth0
iface eth0 inet static
  pre-up ifconfig eth0 up
  address 192.168.1.1
  netmask 255.255.255.0
  up /usr/local/sbin/robocfg switch disable vlans disable reset vlan 0 ports "4 5u" vlan 1 ports "0 1 2 3 4 5u" port 0 state enabled stp none switch enable
allow-hotplug eth1
iface eth1 inet dhcp

Create a cron job that will turn the power LED on when the router has completed booting Debian. Place the following in etc/cron.d/local.

# Power LED
@reboot root echo 1 >/proc/diag/led/power

Dismount the USB filesystem.

# cd -
# umount /mnt

Install ssh onto the MIPS Debian system. Start the virtual machine again.

# qemu-system-mipsel -M malta -m 256 -nographic -no-reboot -hda /dev/sdh -kernel vmlinux-2.6.26-2-4kc-malta -append root=/dev/hda1 -net nic,vlan=0 -net user,vlan=0 -net nic,vlan=1 -net user,vlan=1

Login as root using the password you set during installation. Run these commands.

# aptitude install --without-recommends openssh-server
# shutdown -h now

Flush the changes to USB.

# sync
# sync

Remove the USB memory.

3. Integrating OpenWRT and Debian

3.1. Prepare router firmware

Power on the router with the USB flash memory disconnected. Wait patiently. The power LED will eventually go off and eventually come back on again. Check that no SCSI devices are present.

$ telnet 192.168.1.1
root@OpenWrt:/# ls -ltr /dev/sd*

Nothing should be listed. Plug in the USB memory and re-check for SCSI devices.

root@OpenWrt:/# ls -ltr /dev/sd*
brw-r--r--    1 root     root        8,   0 Jan  1 00:02 /dev/sda
brw-r--r--    1 root     root        8,   2 Jan  1 00:02 /dev/sda2
brw-r--r--    1 root     root        8,   1 Jan  1 00:02 /dev/sda1

Mount the USB flash on the router and copy the init script prepared earlier onto the router's flash.

root@OpenWrt:/# mount -o ro /dev/sda1 /mnt
root@OpenWrt:/# ls -l /sbin/init
lrwxrwxrwx    1 root     root            14 Apr  9  2010 /sbin/init -> ../bin/busybox
root@OpenWrt:/# rm /sbin/init
root@OpenWrt:/# cp -pi /mnt/root/init /sbin
root@OpenWrt:/# ls -l /sbin/init
-rwxr-xr-x    1 root     root          1479 Apr  8  2010 /sbin/init
root@OpenWrt:/# umount /mnt
root@OpenWrt:/# sync
root@OpenWrt:/# sync
root@OpenWrt:/# reboot

The telnet session will now hang, so terminate it by pressing CTRL+] and then typing q and pressing return.

3.2. Configure hardware in Debian

Debian will now be booting, but there will no network connectivity. Boot-up will take a couple of minutes, by which time the power LED will alight. Wait for USB flash activity to stop. Remove the USB key and plug it into another computer. View /mnt/var/log/kern.log and search for eth0.

Jan  1 01:01:18 debian kernel: Algorithmics/MIPS FPU Emulator v1.5
Jan  1 01:01:18 debian kernel: udev: renamed network interface eth0 to eth2
Jan  1 01:01:18 debian kernel: udev: renamed network interface eth1 to eth3
Jan  1 01:01:18 debian kernel: Adding 996020k swap on /dev/sda2.  Priority:-1 extents:1 across:996020k

Edit /mnt/etc/udev/rules.d/70-persistent-net.rules. Change eth2 to eth0 and eth3 to eth1. This will undo the changes that udev made to the kernel device names assigned to the network interfaces. Save your changes and dismount the USB flash memory.

# umount /mnt
# sync
# sync

Remove the USB key. Power off the router.

3.3. Test and use

Plug the USB key into the router. Power on router and wait for the boot-up to complete (the LED will alight). Now you can log in to the router.

$ ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no root@192.168.1.1
Warning: Permanently added '192.168.1.1' (RSA) to the list of known hosts.
root@192.168.1.1's password: 
Linux debian 2.6.32.27 #2 Sun Jun 17 09:51:55 BST 2012 mips GNU/Linux
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Jan  1 01:02:17 1970 from xxx.example.com
root@debian:~#

If the above fails you might be able to debug the system by setting debug=1 in /sbin/init on the router or examining the contents of /var/log on the USB flash stick.

If you are unable to load kernel modules then refresh the module dependencies with

# depmod -a

Your system is now up and running! You may wish to research the use of OpenWRT's block-extroot to mount the Debian root file system instead of the custom init script. You may also wish to explore kexec-tools as a means of rebooting into Debian.

Since the system is so slow at performing certain operations, such as running aptitude, you may wish to shutdown the router, plug the USB into a faster machine, and use qemu to perform the resource-intensive task. This way you can increase available RAM from 32 MiB to 256 MiB and the processor speed from 266 MHz to approximately one third of the virtual machine's host processor speed.

See also

Classifications