Tweaking the Linksys WRT54GL Wifi router

From the outside, the WRT54GL is a wifi router sold by Linksys and which is well-known for, and advertised as, running Linux. Lesser known is the fact that its bootloader is derived from the Broadcom Common Firmware Environment, an open source bootloader distributed under a license similar to BSD (with the advertising clause, for those who like to ask).

There's plenty of open source "firmware" projects for the WRT, meaning projects which provide a Linux kernel and root filesystem, so there's no point in adding to the list. Rather, this project aims at creating and distributing an enriched, open source, WRT-aware, firmware for the WRT.

This book is intended as the documentation and journal of the project.

Copyright Notice

This book is Copyright (c) 2007 by me.

At the moment, this book is not distributed under a well-known license, so plain old Berne Convention holds.

At the moment, consider that:

Trade marks, logos, and other intellectual properties are the property of their respective owners. I have done my best to dutyfully respect others' intellectual property rights; if the owner of some intellectual property wants to exert his rights in relation to this site, they can and should contact me.


I've been using a Linksys WRT54GS for some time now, and while I did choose that model because it ran Linux and could be tweaked, I never actually went beyond putting DD-WRT in it and setting a few options. But I knew I could, and one day I would.

Now I do.

Well, almost. While I like to fiddle with things, I'm unconfortable fiddling with things that I do have a use for. I'd hate it if my home network went down the drain because I'd flashed the wrong code into the router. So I did buy another router, a WRT54GL, just for the sake of fiddling with my mind at rest.

So I get to fiddle with the GL. Of course, I'm not going to simply put a pre-compiled open source alternate firmware. I mean, come on, that's basic stuff. Rolling out my own WRT distribution? No point, those out there are already pretty good and polished, I'd take years to get there. I mean, they've redone everything but the bootloader.

Hey, wait. They haven't redone the bootloader.

What's the point in writing a bootloader for the WRT, you say? Well, obviously, none for the mere mortals who just want their WRT to behave as a WRT. But for those who want to tweak and fiddle with it, then that could come in handy for having the WRT boot from the network as a diskless device, rather than from flash. No more tedious flash/reboot/debug/flash... sequences. No risk of Flash wear-out. A live root filesystem. Wow.

(normal folks please excuse me. I know thinking like that is somehow unnatural, to put things mildly. But then, well... I don't care.)

So, a fresh bootloader, and booting the WRT from the network as a proof-of-concept (well, a proof-of-development). Ok, then. Let's do it.

A word of warning

Hold it, folks.

What I have done has had the effect of voiding the warranty of my WRT54GL.

I knew when I did it, and I did it just the same; but you might not be ok with losing the warranty. So for the record, let's just repeat that loud and clear:

Modifying the WRT54G in any way not described in the Linksys documentation voids the warranty.

I've soldered things to my WRT54GL.

I've flashed it with weird code.

All this could have had a lethal effect on it, and still can, in fact, and if it does, I'm on my own.

Are you ready to risk that too? Fine, then: follow me!


In reality, folks, I did not do the following in the order I'm showing it. Actually I did a lot of focused googling and surfing, experimenting, going back to the Web, pulling out the soldering iron, then back to compiling, until things made sense. But I want to save you the time and hassle to do the same, so I tried and re-organized things to make them faster to grasp.

In the first section, we'll have a good look around to see what we can gather about the WRT54G regarding the hardware, the binaries that runs on it, the source code related to it and any other information.

Then we'll dive deep into the software as it is: the binary CFE, the Linksys GPL code, the Broadcom CFE.

At that point, we'll be ready to get hacking. The WRT54GL might not be, though. So we'll start by hacking it open and adding a JTAG debug connector and an RS232 interface. Remember this voids your warranty--well, that router's warranty at least; then we'll go about trying to put some vanilla software on it and see what happens.

As a conclusion, we'll have a look back at what we had to begin with and what we end up with, just in case it was an improvement.

I'll be fleshing out this book as time goes by.

Cheers, and enjoy the devices you own!

About this book

I am writing this book as I progress on this project, which means the book is unfinished. :)

As a matter of fact, I use the book, especially the "analysis" chapter, as a scratchpad for collecting information on the WRT while I am progressing.

So you'll find sections that are marked "to be filled in", or "to be defined", or TBD most probably. Unless you are convinced that I should have filled them in by now, do assume that they are in this state because at the moment I do not have any information to put in those pages.

For the pages that do contain information, feel free to contact me about it. There's a "Contact" form on the site just for this.

Also, although I gladly accept feedback or contributions (which I'll faithfully attribute), I do not consider collaborative work at the moment, so please refrain from asking for an account on Tweaky unless you are really, really, really sure that you'll be able to convince me to change my mind.

Apart from that, have a look this book's Copyright notice, so that you know what you can do with it and what you can't.

Available material

Ok, so what can we gather from the Web about the WRT54GL?

Well, for starters, Linksys provides an archive in their GPL Code Center for it, as they do for other versions of the WRT54 which are all based on Linux except the (in)famous WRT54G(S)v5, WRT54GSv5.1 and WRT54G(S)v6 which are VxWorks-based (but can nevertheless be brought back from the dark side of the Source).

Then, there are numerous other firmwares for WRTs. This is by no means an exhaustive list, but DD-WRT and OpenWRT come to mind.

However this does not cover it all. For one thing, there's the bootloader, based on Broadcom's CFE. It's not included in either the Linksys or the alternate firmware distribution. Linksys could have distributed it, as per Broadcom's license for it, but they did not. Broadcom does, however, but their releases do not contain explicit support for the WRT hardware.

So we have some sources for learning as much as we can from the WRT hardware and software. Let's dive deep into each of those sources.

The Linksys GPL archive

(to be filled in)

The Broadcom CFE

(to be filled in

In-depth analysis


Dumping dmesg

The first thing I did with the WRT54GL was to flash it with DD-WRT 0.9 White Russian and look for logs. There is no syslog in DD-WRT, but dmesg is there and provides the most important part: the boot log. So let's have a look (the comments in bold point out the salient parts):

# dmesg
CPU revision is: 00029008
Primary instruction cache 16kB, physically tagged, 2-way, linesize 16 bytes.
Primary data cache 8kB, 2-way, linesize 16 bytes.
Linux version 2.4.30 (nbd@ds10) (gcc version 3.4.4 (OpenWrt-1.0)) #1 Sat Feb 3 13:16:08 CET 2007
Setting the PFC value as 0x15
Determined physical RAM map:
memory: 01000000 @ 00000000 (usable) -> That's 16 Megs at physical address 0
On node 0 totalpages: 4096
zone(0): 4096 pages.
zone(1): 0 pages.
zone(2): 0 pages.
Kernel command line: root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd console=ttyS0,115200
CPU: BCM5352 rev 0 at 200 MHz -> So we have a BCM5352, whatever that is
Using 100.000 MHz high precision timer.
Calibrating delay loop... 199.47 BogoMIPS -> Somebody give me my missing .53 BogoMIPS. :)
Memory: 14228k/16384k available (1455k kernel code, 2156k reserved, 104k data, 80k init, 0k highmem)
Dentry cache hash table entries: 2048 (order: 2, 16384 bytes)
Inode cache hash table entries: 1024 (order: 1, 8192 bytes)
Mount cache hash table entries: 512 (order: 0, 4096 bytes)
Buffer cache hash table entries: 1024 (order: 0, 4096 bytes)
Page-cache hash table entries: 4096 (order: 2, 16384 bytes)
Checking for 'wait' instruction... unavailable.
POSIX conformance testing by UNIFIX
PCI: no core -> so there's PCI on this platform?
PCI: Fixing up bus 0
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
Starting kswapd
Registering mini_fo version $Id$
devfs: v1.12c (20020818) Richard Gooch (
devfs: boot_options: 0x1
JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.
Squashfs 2.1-r2 (released 2004/12/15) (C) 2002-2004 Phillip Lougher
pty: 256 Unix98 ptys configured
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled
ttyS00 at 0xb8000300 (irq = 3) is a 16550A ->We've got two 16550A UARTS at b8000{34}00
ttyS01 at 0xb8000400 (irq = 0) is a 16550A
b44.c:v0.93 (Mar, 2004)
PCI: Setting latency timer of device 00:01.0 to 64
eth0: Broadcom 47xx 10/100BaseT Ethernet 00:18:39:c9:a7:01 -> There's one Ethernet I/F
Physically mapped flash: Found an alias at 0x400000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x800000 for the chip at 0x0
Physically mapped flash: Found an alias at 0xc00000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x1000000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x1400000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x1800000 for the chip at 0x0
Physically mapped flash: Found an alias at 0x1c00000 for the chip at 0x0
Amd/Fujitsu Extended Query Table v3.3 at 0x0040
number of CFI chips: 1
cfi_cmdset_0002: Disabling fast programming due to code brokenness.
Flash device: 0x400000 at 0x1c000000 ->The flash is 4 Megs at 0x1c000000
bootloader size: 262144
Physically mapped flash: Filesystem type: squashfs, size=0xfb158
Creating 5 MTD partitions on "Physically mapped flash":
0x00000000-0x00040000 : "cfe"
0x00040000-0x003f0000 : "linux"
0x000be400-0x001c0000 : "rootfs"
mtd: partition "rootfs" doesn't start on an erase block boundary -- force read-only
0x003f0000-0x00400000 : "nvram"
0x001c0000-0x003f0000 : "OpenWrt"
Initializing Cryptographic API
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP, IGMP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 1024 bind 2048)
ip_conntrack version 2.1 (5953 buckets, 5953 max) - 332 bytes per conntrack
ip_tables: (C) 2000-2002 Netfilter core team
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
NET4: Ethernet Bridge 008 for NET4.0
802.1Q VLAN Support v1.8 Ben Greear
All bugs added by David S. Miller
VFS: Mounted root (squashfs filesystem) readonly.
Mounted devfs on /dev
Freeing unused kernel memory: 80k freed
Algorithmics/MIPS FPU Emulator v1.5
diag: Detected 'Linksys WRT54G/GS/GL'
Probing device eth0: found!
b44: eth0: Link is up at 100 Mbps, full duplex. -> the Linux driver for the 47xx is 'b44'
b44: eth0: Flow control is off for TX and off for RX.
mini_fo: using base directory: /
mini_fo: using storage directory: /jffs SIZE compression mode activated.
PCI: Setting latency timer of device 00:05.0 to 64
eth1: Broadcom BCM4320 802.11 Wireless Controller -> BCM4320 is eth1, the wifi I/F
BFL_ENETADM not set in boardflags. Use force=1 to ignore.
device eth0 entered promiscuous mode
b44: eth0: Link is up at 100 Mbps, full duplex.
b44: eth0: Flow control is off for TX and off for RX.
vlan0: add 01:00:5e:00:00:01 mcast address to master interface
vlan0: dev_set_promiscuity(master, 1)
vlan0: dev_set_allmulti(master, 1)
vlan1: add 01:00:5e:00:00:01 mcast address to master interface
vlan1: attempt to add interface with same source address.
vlan1: dev_set_promiscuity(master, 1)
device eth1 entered promiscuous mode
br0: port 3(eth1) entering learning state
br0: port 2(vlan1) entering learning state
br0: port 3(eth1) entering forwarding state
br0: topology change detected, propagating
br0: port 1(vlan0) entering learning state
br0: port 2(vlan1) entering forwarding state
br0: topology change detected, propagating
br0: port 1(vlan0) entering forwarding state
br0: topology change detected, propagating

So let's sum up what we've found:

  • The RAM is 16 Meg at 0 and FLASH is 4 Meg at 0x1c000000;
  • We have two 16550A UARTS, an Ethernet 47xx and a Wifi BCM4730;
  • There is some Broadcom BCM5352 IC involved;
  • There is some PCI involved.

Looking on Broadcom's site for a BCM5352 leads us to the BCM5352EL page which says:

The BCM5352EL integrates a high-performance MIPS32 processor, IEEE 802.11 b/g MAC/PHY, SDRAM controller, and a configurable five-port Fast Ethernet (FE) switch.

We've got the CPU, the Wlan MAC/PHY, the SDRAM, plus an Ethernet and two UARTS. On the other hand, we haven't seen any sign of a switch.

So let's move on and look into the PCI subsystem. Maybe the switch is in there?

Peeking at PCI

The usual command to list all PCI devices in a system is lspci. Does it exist in DD-WRT?

# lspci
-ash: lspci: not found

Sigh. Well, you can't always win...

Wait. Maybe /proc/pci exists?

# cat /proc/pci
PCI devices found:
Bus 0, device 0, function 0:
Class 0501: PCI device 14e4:0800 (rev 0).
IRQ 3.
Non-prefetchable 32 bit memory at 0x18000000 [0x18000fff].
Non-prefetchable 32 bit memory at 0x1fc00000 [0x1fffffff].
Non-prefetchable 32 bit memory at 0x1c000000 [0x1dffffff].
Non-prefetchable 32 bit memory at 0x1a000000 [0x1bffffff].
Bus 0, device 1, function 0:
Class 0200: PCI device 14e4:4713 (rev 0).
IRQ 4.
Master Capable. Latency=64.
Non-prefetchable 32 bit memory at 0x18001000 [0x18001fff].
Bus 0, device 2, function 0:
Class 0b30: PCI device 14e4:0816 (rev 0).
IRQ 5.
Non-prefetchable 32 bit memory at 0x18002000 [0x18002fff].
Bus 0, device 3, function 0:
Class 0c03: PCI device 14e4:4716 (rev 0).
IRQ 6.
Non-prefetchable 32 bit memory at 0x18003000 [0x18003fff].
Bus 0, device 4, function 0:
Class 0500: PCI device 14e4:080f (rev 0).
IRQ 3.
Non-prefetchable 32 bit memory at 0x18004000 [0x18004fff].
Non-prefetchable 32 bit memory at 0x0 [0x7ffffff].
Non-prefetchable 32 bit memory at 0x10000000 [0x17ffffff].
Non-prefetchable 32 bit memory at 0x80000000 [0x9fffffff].
Bus 0, device 5, function 0:
Class 0280: PCI device 14e4:4320 (rev 0).
IRQ 2.
Master Capable. Latency=64.
Non-prefetchable 32 bit memory at 0x18005000 [0x18005fff].
Bus 0, device 6, function 0:
Class 0280: PCI device 14e4:4719 (rev 0).
IRQ 3.
Non-prefetchable 32 bit memory at 0x18006000 [0x18006fff].

... Yes it does, and so do seven devices. They all have a vendor ID of 14e4, and sport the following device IDs: 0800, 4713, 0816, 4716, 080f, 4320, 4719. Time to Google for "PCI 14e4", and the first result is this list, which allows us to identify those seven devices:

  • 0800 is a Sentry5 Chipcommon I/O Controller
  • 4713 is a Sentry5 Ethernet Controller (that's probably our '47xx'
  • 0816 is a BCM3302 Sentry5 MIPS32 CPU
  • 4716 is a BCM47xx Sentry5 USB Host Controller
  • 080f is a Sentry5 DDR/SDR RAM Controller
  • 4320 is a BCM4306 802.11b/g Wireless LAN Controller
  • 4719 is a BCM47xx/53xx RoboSwitch Core

Looking at the addresses allocated to those PCI devices, we can safely conclude that the Chipcommon does include the two 16550A UARTS, and provides access to the Flash area, while the SDRAM controller quite luckily has memory mapped exactly where the RAM seems to be.

What's inside the WRT54GL

Based on the analysis just done, we can now sum up our knowledge of the WRT54GL regarding hardware, memory mapping, interfaces...

Building a new CFE


The plain Broadcom CFE

The following was written based on Broadcom's CFE v1.4.0 as available on their site under a BSD-like license. Broadcom regularly makes new CFE releases available ; I'll try and keep up to date with their releases.

CFE stands for Common Firmware Environment. It is a generic firmware, able to run on several CPUs, chipsets and boards.

Shuffling through CFE

The following was written based on Broadcom's CFE v1.4.0 as available on their site under a BSD-like license. Broadcom regularly makes new CFE releases available ; I'll try and keep up to date with their releases.

CFE stands for Common Firmware Environment. It is a generic firmware, able to run on several CPUs, chipsets and boards.

Our first step with Broadcom's CFE will be to analyze its source code and see how much support it has for the WRT54GL hardware.

Browsing through code is a tedious task, in which one repeatedly looks for some symbol, or some constant, or some piece of text, and try and piece things together. Granted, you can do that with grep and vi. In fact, you can do that with vi alone, and a pen and paper and patience. Mind me, I'm lazy, and I've got little time, so I went straight to the task and installed kscope.

KScope is a basic editing environment which can use cscope to collect symbol information on a full tree of source files, letting you search for definition and/or uses of a given symbol, or grep through the whole tree, open a file, modify it... It's basic, but I don't really need more than that when I study code.

So let's import the whole CFE source tree into a KScope project and look for items we've learned about when tinkering with Linux. To make sure that I got the makefiles and READMEs, I've created a KScope project called CFE, then replaced the original filetypes (*.h, *.c) with a catchall ('*') before adding the whole cfe-1.4.0 tree to the KScope project.

First things first: any sign of a '3302' in the code?

Yep, there is, in cfe/arch/mips/cpu/bcmcore/include/sbmips32, where it basically says the file provides support for the BCM3302 Silicon Backplane.

Hmm... Guess we can safely assume that our future WRT54GL target will use 'bcmcore' as its CPU. Maybe some target already uses the bcmcore cpu? Well, yes: the bcm95836cpci. Let's have a look at that target.

The BCM95836CPCI target

Booting from the Net

To be filled in


References that I should turn into links sometime:

- The Broadcom CFE site

- The Linksys GPL code site

- Bitsum's pages

- The MIPS Linux site

- Others?