How to compile Tomato firmware 1.23 in Ubuntu Linux 8.10 – Beefing up your WRT54GL

Its been 2.5 months now since I switched from running Windows XP to Ubuntu Linux 8.10 and I am loving it! As a software developer both professionally and as a hobby I use my computer a lot for many different things including writing my own custom applications.

Having switched to Linux and also looking around me to see what devices I can purchase that run Linux (and therefore can be customized further by me giving me more choices) I have experienced an overwhelming feeling of freedom and empowerment. I have the freedom to choose in a world of communism, Nazism and all these other ism’s where everything wants to force you into their way. Getting to the main point of this article, I’ll touch on how to get your Linux based LinkSys router (in this case the WRT54GL) changed over to the enhanced Tomato firmware. Follow These Steps:

1. Download the original firmware source code from LinkSys here or I have it mirrored on my website here

2. Download the latest Tomato firmware source code from here.

3. Copy the downloaded archives to ~/Code/TomatoSource_1_23

4. Download two scripts from my website here and here.

(the first script may need to be edited depending on the version of Tomato you download, I used v 1.23 which was the latest as of this writing). The first script does it all (extract and compiles the code), while the second script is used to change your default shell (sh) in Ubuntu from dash back to what it used to be which is bash. Many Ubuntu users have numerous problems compiling Tomato firmware due to the fact that dash is not 100% compatible with bash and the build system assumes a bash shell.

5. Open a terminal window and change your default shell to bash by executing the second script (only needs to be done once):


6. Open a terminal window and change to ~/Code/TomatoSource_1_23 and run the first script:


Voila. If you get compile errors you may be missing dependent packages (I had to install bison and flex):

sudo apt-get install bison flex

If you get errors related to tomato_profile.h with a -e at the top of the file and also errors related to {js;jsx} then your Ubuntu is trying to compile the firmware using dash instead of bash and you need to run the script in step #5.

*NOTE: The whole compile process for Tomato is VERY delicate. What this means is that if for any reason you have errors of some kind during an attempt to build the code, you should re-run the whole process from scratch (with a clean set of folders) as doing a: make clean DOES NOT WORK. The build process DOES NOT recover well from error and leaves things in a hideous state.

Now just some quick comments about why free software and Linux are so excellent:

I was able to fix EVERY SINGLE PROBLEM I have encountered over the past 2.5 months for every project that was free, open source software. Why? Because I was able to download the source code, investigate the problem and patch it. These are the following projects I have worked with in the last few months:

ALSA (Advanced Linux Sound Architecture)


Blood Frontier


Tomato Firmware



DatabaseLayer (a subproject of wxWidgets)

GNomad2 – software to connect with my Creative Labs Zen Vision: M

(My next mp3 player will likely be the GP2x Wiz)

As I round out my skills on the Linux platform and learn how to navigate the OS and code for it, I understand why Richard Stallman started this community, it is truly awesome, not only technologically but philosophically and morally. Having the freedom to fix software is like being able to fix my washer and dryer without fear of legal retribution! Reverting to reverse engineering is hardly a meaningful solution and is shady in most circumstances.

Now that I am able to compile the Tomato firmware (which is basically a version of embedded linux based on BusyBox) I plan to add Bandwidth monitioring per IP / MAC Address so that people can track which computers on their private network are bandwidth hogs and deal with them appropriately. I wrote a system using PHP scripts for my local ISP to manage customer bandwidth usage and it has worked vbery well over the past few years. Having searched around for an easy to use option for my WRT54GL Embedded Linux based router I didn’t find one consicse, easy to use solution. Thus I plan to make something that works well and then share it with others.

43 Responses to How to compile Tomato firmware 1.23 in Ubuntu Linux 8.10 – Beefing up your WRT54GL

  1. Where to get toolchain compiler for this ?
    And install method ?
    mipsel-uclibc-gcc: Command not found ?

  2. This code is vanilla C code and compiles under most any linux or windows C compiler. I compiled ipt-parse (as packaged in the .7z file) using the tool chain from the original tomato download using tomato 1.23 so it should be fully compatible with any tomato firmware. I have posted another blog entry here somewhere about how to build the original tomato firmware on Ubuntu linux, but the information should realistically help with any linux distro.


  3. Sorry I got confused (i recently wrote about bandwidth monitoring with tomato but I see this question was about how to compile the tomato firmware).

    The toolchain is part of the original LinkSys download that I mentioned in step #1:

    1. Download the original firmware source code from LinkSys here.

    The uclibc I beleive is packaged as part of the tomato mods. IF you follow the instructions in the README file in the tomato archive you will see which files need to be delete and which need to be replaced to compile tomato.


  4. Dear Sir:

    I am newbie of tomato and Ubuntu.
    Still can not compile the code.
    If you could kindly help me how to compile this code correctly, that would be appreciated .
    My e-mail :
    Please give me you mail ,I will give u my ubuntu account, If you could connect to my Ubuntu machine and help me.

    Thanks you

  5. Ok, I am also new to Tomato and Ubuntu, so I am no expert. Did you follow all instructions in this posting exactly? Including changing your default Shell from DASH to BASH?


  6. it seems some problem of toolchain setup,
    Can you show me the .bashrc file export path ?
    And what’s the toolchain used , where can i find it , the file name and size of toolchain file you used ?!
    thank you

  7. Did you run the script mentioned in this blog: ./

    That will change you default script frash the default ‘dash’ to what all other linux distros use ‘bash’. Ubuntu’s dash (while claiming to be faster than bash) isn’t 100% comptabile with bash and DOES NOT work with the tomato compile script. If you did follow this step please post what errors you get when compiling.


  8. 1. i have followed the link , to build a tomato success ok

    2. using the same step as in 1, I aslo compile the WRT54GL_v4.30.11_11_US.tgz with success
    (extract file, rename dir to tomaro, and cd tomato/release/src, and make as in Step 1)

    3. But when I extract tomamato.tar to patch tomato dir as in step 2, the compile is not ok, I suspect tomato.tar has some wrong file ? (this is extract from your post)
    error message is here ;make[3]: Leaving directory `/home/gbox/tomato/release/src/router/iproute2/tc’
    make[2]: Leaving directory `/home/gbox/tomato/release/src/router/iproute2′
    make[2]: Entering directory `/home/gbox/tomato/release/src/router/rom’
    make[2]: Leaving directory `/home/gbox/tomato/release/src/router/rom’
    make[2]: Entering directory `/home/gbox/tomato/release/src/router/others’
    make[2]: Nothing to be done for `all’.
    make[2]: Leaving directory `/home/gbox/tomato/release/src/router/others’
    make -C busybox CFLAGS=”-Os”
    make[2]: Entering directory `/home/gbox/tomato/release/src/router/busybox’
    CC libbb/ask_confirmation.o
    libbb/ask_confirmation.c:16: parse error before “bb_ask_confirmation”
    libbb/ask_confirmation.c:17: warning: return type defaults to `int’
    libbb/ask_confirmation.c: In function `bb_ask_confirmation’:
    libbb/ask_confirmation.c:25: `isspace’ undeclared (first use in this function)
    libbb/ask_confirmation.c:25: (Each undeclared identifier is reported only once
    libbb/ask_confirmation.c:25: for each function it appears in.)
    make[3]: *** [libbb/ask_confirmation.o] Error 1
    make[2]: *** [libbb] Error 2
    make[2]: Leaving directory `/home/gbox/tomato/release/src/router/busybox’
    make[1]: *** [busybox] Error 2
    make[1]: Leaving directory `/home/gbox/tomato/release/src/router’
    make: *** [all] Error 2

    I dont know why the WRT54GL_v4.30.11_11_US.tgz compile ok , and with tomato_1_23 patch fail

    (ps. this time i use a clean debian system, no ubuntu dash problem)

  9. How do you update the Openvpn TLS-Ciphers? They are old an insecure. The VPN version of DD-WRT has updated ciphers, and a newer version of openssl..

  10. Sorry but I don’t have the direct answer. One thing I can tell you is that there are limitations using Tomato because of the fact that the device drivers to run the router are binary only (no source code). This limits the linux kernel to 2.4 and thus limits what can be done to update it. There are other projects like openwrt that have a whole new infrastructure and new linux kernel and drivers which may be something to look at.

  11. Is it normal for it to take more than 8 hours to compile? I started the compilation process around 1 AM last night and it’s 9 AM now…

  12. No it should only take about 2 – 5 minutes to fully compile from scratch. Sounds like an infinite loop is happening, perhaps check to make sure your bash interpreter is not really using dash behind the scenes.

  13. Thank you very much for replying, Mark. I know you don’t have to provide support for my mistakes. I wondered if it was an infinite loop (because the make[xx] numbers keep increasing) and have tried to figure out what’s causing it, but I haven’t figured it out yet. I did follow your instructions, so I’ve got:

    $ ls -la /bin/sh*
    lrwxrwxrwx 1 root root 9 2009-09-10 00:04 /bin/sh -> /bin/bash

    Out of curiosity, I tried compiling the Linksys source (WRT54GL_v4.30.11_11_US.tgz), and the Tomato source (TomatoSource_1_25.tar.bz2) without my changes. The Linksys source compiled without errors (I didn’t try installing it though), and the unchanged Tomato source appeared to have the same infinite loop problem. So I’m guessing you’re right–somehow Gnome Terminal or the make commands aren’t running bash. The output of ps says I’m running bash. Do you have any idea how I can further avoid the infinite loop? I don’t see an sh binary or link anywhere in my path other than /bin/sh.

    I’m a web developer, not a C programmer, so I don’t really know what I’m doing, but my end goal here is I’m trying to make my WRT54G let me backup to a CIFS drive via SFTP by modifying the current version of Tomato. So I put my (Ubuntu) OpenSSH sftp-server binary in tomato/release/src/router/prebuilt/, and made the following changes:

    $ diff -r tomato_mod/ tomato_orig/
    diff -r tomato_mod/release/src/router/dropbear/options.h tomato_orig/release/src/router/dropbear/options.h
    #define SFTPSERVER_PATH “/usr/libexec/sftp-server”
    diff -r tomato_mod/release/src/router/prebuilt/Makefile tomato_orig/release/src/router/prebuilt/Makefile
    < install -m 0755 sftp-server $(INSTALLDIR)/usr/lib/sftp-server
    < $(STRIP) $(INSTALLDIR)/usr/lib/sftp-server
    Only in tomato_mod/release/src/router/prebuilt: sftp-server

  14. Whoops…make that:

    diff -r tomato_mod/release/src/router/dropbear/options.h tomato_orig/release/src/router/dropbear/options.h
     #define SFTPSERVER_PATH "/usr/libexec/sftp-server"

  15. Last time…make that:

    diff -r tomato_mod/release/src/router/dropbear/options.h tomato_orig/release/src/router/dropbear/options.h
    [tomato_mod] #define SFTPSERVER_PATH "/usr/lib/sftp-server"
    [tomato_orig] #define SFTPSERVER_PATH "/usr/libexec/sftp-server"

  16. I worked around the compile loop by following these instructions:

    …and will continue seeking support there.

  17. Mark,

    I tried your batch files on Ubuntu 9.10 and I didn’t get very far. I was wondering if you knew what my mistake might be. The only thing I changed in the file was the version number from 1_23 to 1_25.

    dennis@ubuntu:~/Code/TomatoSource_1_25$ ./
    [sudo] password for dennis:
    mv: cannot stat `/bin/sh’: No such file or directory

    dennis@ubuntu:~/Code/TomatoSource_1_25$ ls -la /bin/sh*
    lrwxrwxrwx 1 root root 9 2009-10-16 14:57 /bin/sh? -> /bin/bash
    lrwxrwxrwx 1 root root 9 2009-10-16 15:25 /bin/sh? -> /bin/bash
    lrwxrwxrwx 1 root root 9 2009-10-16 14:55 /bin/sh.dash? -> /bin/bash
    lrwxrwxrwx 1 root root 4 2009-10-16 07:10 /bin/sh.distrib -> bash

    dennis@ubuntu:~/Code/TomatoSource_1_25$ ./
    -bash: ./ /bin/bash^M: bad interpreter: No such file or d

    Also, after running the dash to bash script, whenever I start a terminal, I get this error:
    -bash: /usr/bin/lesspipe: /bin/sh: bad interpreter: No such file or directory

    Any Ideas?

  18. OK, now I’m MAD.

    I shut down the Ubuntu machine and then rebooted it to be stopped with a screen that says: “init: Unable to execute “/bin/sh” for rcS: No Such File or directory. …” and nothing works at that point.

    Whatever anyone does, DO NOT RUN THAT DASH TO BASH script. Now I’m having to reformat and reinstall everything.

  19. Dennis,

    No need to reformat/reinstall, it’s not windows, after all. Just boot up the ubuntu live cd (or any other live cd) and restore /bin/sh from /bin/sh.dash on your installed system.


  20. Upon further analysis, I think I see what went wrong with Dennis’s installation. This line
    -bash: ./ /bin/bash^M: bad interpreter:
    indicates that that there is a carriage return (^M) on the #! line, and since that character is not present in the original file, I’d guess that it is the result of editing the file on a windows system, which tends to use cr/lf to denote the end of a line, whereas unix uses just lf to denote end of line. So it could be that the ChangeDefaultShell script was also damaged in the same way, and when it was run, instead of making a symbolic link for /bin/sh, it made one called “/bin/sh^M”, thereby leaving no legitimate /bin/sh in the filesystem. This is why the output of “ls -la /bin/sh*” shows a symbolic link for “/bin/sh?”

    All the other bad behavior was a result of this, and Dennis did not realize the gravity of the situation before rebooting.


  21. Can this process work under PPC64 or 32?

  22. This process uses a cross compiler. It means the compiler compiles output to the platform used by the router (which I believe is MIPS).


  23. Did you finally succeed in building a tomato firmware with sftp functionality?

  24. No but

    a) with ssh build in you can easily use scp (secure copy) to accomplish a similar encrypted way of doing the same and
    b) if you check you’ll likely find a Tomato mod with sftp already.


  25. Hi Mark,

    I would love to have especially sftp, because that is what bzr (versioning system) supports. I does not work with scp.

    I tried to find one, but none (recent) mod does support sftp, only ftps (secure ftp). Did you found one?

    Thanks, Ernst

  26. Yes the Teddy Bear mod mentioned here has sftp and can be downloaded here

  27. Avatar Ernst Blaauw
    Ernst Blaauw says:

    I believe Teddy Bear’s mod only supports ftps (using vsftpd) and not sftp; For the differences, see
    I read somewehere sftp support can be added to Teddy Bear by installing Optware’s openssh-sftp-server package, but I have no idea how to do this.

  28. Can you add ebtables and openvpn support?


  29. hi Mark
    thanks for your itp-parse !!
    how would one use ipt-parse to heep track of the band width from 6 am to 8 pm , so one can exclude the free downloads that some isp’s let use hgave at night ?

  30. I have created new forums to support the software I have worked on. To see the answer to this check out:


  31. Hi Mark,

    The openvpn mod is based on version 1.25 which does not have ebtables support. Since from your post I understood that you were running tomato on a regular pc linux box I was wondering if the inclusion of ebtables could be possible from the kernel.


  32. I’m VERY surprised if iptables (not ebtables) is not in any Tomato distro since it is build into busybox by default. Without iptables there is not much use in a router firmware! Please make sure that the version you are using does not have iptables built in.

  33. Avatar Karim Gillani
    Karim Gillani says:

    I am new to using/compiling in linux, so bear with my terminology…

    I want to add usb webcam support specifically linux-uvc to Tomato Firmware. I figure I need to make a loadable kernel module.

    So, first newby question…how can you compile a firmware o/s on a i386 Ubuntu? Won’t they conflict? Can you use the firmware (for testing) on ubuntu?

  34. The links mentioned in this blog contain a “cross compiler”. This compiles programs on your normal Linux installation but produces binaries for the router hardware that will run on tomato.

  35. Hey Mark,

    I may be quite stupid for asking this but I am trying to get a tomato firmware running based on 1.28 including SD (maybe SDHC) support and so started the whole progress as mentioned here.

    The first part of the compilation runs without any problems after applying a patch to ldd.c for x86_64. I found myself having to chose the settings of the new kernel which I am not familiar with. I don’t know which support to build in and which should be disabled. Is there any hint or is it set to the defaults needed for tomato, so basically I can just get through with hitting return all the time?
    I tried getting by this configuration doing so. After all I ended up with an error:

    make[2]: Entering directory `/home/baernado/private/wrt/tomato/release/src/linux/linux’
    make[2]: *** No rule to make target `zImage’. Stop.

    I am confused what to do to fix this and like I mentioned earlier I do not really know how to handle the configuration part.

    Thanks for any help =)

  36. Did you follow the directions exactly as they were given?

  37. Hi,

    I did for the main parts. I’ve cut your scripts (using Gentoo I do not need the dash-fix) in half as I decided to create a backup of an untouched tomato-source. So the script unpacked the WRT source, deleted all unneeded directories and unpacked the source of tomato afterwards. Afterwards I created the symlink /opt/brcm and crosscompiling starts. The error you can see there is the result of two tries.

    Best regards

  38. Works flawlessly for me (after applying the ldd.c patch from here)

    I am using Ubuntu 10.10 64 bit by the way. I had to do a few extra things in my script for 64bit namely the following just before the call to make at the end:

    if [ ! -d /opt/brcm ] ; then
    sudo ln -s ~/Code/TomatoSource_1_28/tomato/tools/brcm /opt/brcm

    export PATH=$PATH:/opt/brcm/hndtools-mipsel-uclibc/bin;export PATH=$PATH:/opt/brcm/hndtools-mipsel-linux/bin


  39. Avatar Claudio Consolmagno
    Claudio Consolmagno says:

    Hi everyone. I am getting starting today on developing tomato for a university project. Thank you for your great post Mark, it helped me figure out what was going wrong during my set up.


    I had that same problem with setting options for the kernel. I think what you need to do is go to tomato/release/src/router and do “make menuconfig”. It should bring up an interactive blue screen on the terminal window. Go to the option at the bottom to load existing configuration. It should automatically be set to .config. Just press ok and don’t change anything. Press ESC twice to leave and save. A different interactive screen may show up but do the same thing.

    I also had that problem with “bzImage”. It disappeared after I cleaned up my whole project and started from scratch again. Also, you should really use a simbolic link to brcm from the /opt folder (see sudo ln -s from Mark’s previous reply). If you just moved the whole brcm folder to /opt it could cause problems since you probably have to do “sudo make” instead of just “make” (for tomato/release/src) and changing the $PATH for sudo is a pain.


  40. Hey Mark,

    I have tried it once again. After deleting all the unnecessary directories and unpacking tomatosrc into the same folder I created the symlinks as root. As user I added the two directories to the PATH checking by using echo $PATH. The compiling starts, otherwise the compiling wouldn’t be able to start since the needed compilers are only found in /opt/brcm/…
    There are different things which bug me.
    First of all compiling the source will result in many questions about tweaking which I do not know which options to chose.
    Additionally it seems there is a problem in tomato/release/src/linux/linux mentioning there is no rule to make target “zImage” so basically this means a make-Script tells the interpreter to make zImage and make can not find any information about zImage in the Makefile used.
    I am using the wrt-sources from your server and tomato source 1.28 on Gentoo x64 arch. I have applied the ldd.c patch.
    Can’t find out what’s wrong.
    Do I have a chance to contact in any other way than this comments so we could try to figure things out?

    Best regards

  41. Yes, I am on IRC at on the channel softhaus


  42. Thanks for your attendance Mark and much appreciation to Claudio. Running make menuconfig in release/src/router actually did the trick.