NWR04B: Digging through firmware

Over the last few weeks, I've been slowly picking away at the original firmware for the NWR04B. This is the stuff that lets me upload Linux to the router, and then run it (as opposed to the various firmwares from different companies that do useful stuff like firewalling, web control panels and so on). This is the second time I've taken on this beast, and like the first time it's because I can't get the damned thing to write to flash from Linux.

Writing to flash should be simple. I've got a datasheet for the chip that's on the router, and it lays out pretty explicitly exactly what you need to do to erase a sector, program a random location, find out what model chip you have, and so on. I keep watching what the kernel does by throwing printfs everywhere, but I still get no response from the flash. So I decided to see how the firmware does it.

The first time I looked at it I was just confused. There were at least half a dozen places in the firmware where I could find the magic numbers used to send the flash into command mode, where you could query or program it. The two numbers were right next to each other, and it was obviously no coincidence. But trying to read what the damned thing was doing just made my head hurt. All these registers, changing all the time, and no hint of what they were when you got here....

I tried, once, following from the very beginning, and keeping track of what register held what value. That didn't last very long. Then I thought of whipping up a quick Perl script to do the same...you know, writing an ARM simulator. That didn't last very long either (though for the sort of very basic functionality I was after, it might not have been that hard).

After that, I gave up and upgraded the kernel. At the very least, I figured the new MTD framework would probably make the problem pretty generic; if I was very lucky, it might even have drivers already in place. Instead, though, I kept having the same problem: the numbers looked good, but it just didn't respond the way I thought it should. The framework was there to query the thing in three different ways, but none of them did what I wanted.

So...back to the firmware, and this time I'm beginning to understand it a little better. For example: there's a big series of tables at the end of the program. I only noticed 'em this time, but they're pretty fundamental to what I'm after. There's a list of sectors you can erase, and then addresses for routines to erase a sector, fill a region with bytes, program it, and check some details on the chip itself.

And the half-dozen places where you can find the command numbers are there because there are half a dozen erase-a-sector routines -- which, in turn, is because this firmware supports six chips from four manufacturers: SST, AMD, Atmel and Hynix. It's the Hynix chip that I've got, so that means I can focus on that.

Since I can see the addresses of all these routines, I'm confident now that I can pick out where a subroutine starts and ends, and how to pick out the registers used to carry arguments. With that down, I can pick out other routines and see what calls them, and I can pay less attention to keeping track of all the registers at all times.

Now I need to look at the driver in the kernel, and compare it to what I can see in the original firmware. The firmware's check for the chip I've got seems to match what the kernel does, so at least that part's good.

Part of the problem is having to recompile and reload the kernel each time I want to check the driver, and the fact that the probing is not under my control; I'm still trying to wrap my head around the driver initialization sequence in the kernel. I'm thinking of writing a toy kernel module to do the writes I want, since it looks like the MTD drivers can't be compiled as modules on my own. This would save me having to reboot with a new image all the time.

Ah, well...at least this is all fun. I'm still having the time of my life here. :-)