Hacking the Netgear wgt634u

From
Revision as of 20:39, 4 May 2005 by 82.82.95.51 (talk) (some text added)
Jump to navigation Jump to search

Abstract

OpenWRT is a Linux port (2.4 kernel) for embedded plattforms including the Netgear wgt634u wireless router.

Click is a modular software for implementing advanced router functionality on Linux systems.

Madwifi is a WLAN driver (802.11 wireless network) that runs on OpenWRT and can be integrated with the click system.

This tutorial describes the steps of downloading the source code for each of these 3 components, for compiling them, and for getting them to run (together) on a wgt634 Netgear wireless router platform.

This work has been done for the Berlin Roof Net project ( http://sarwiki.informatik.hu-berlin.de/wiki/BerlinRoofNet ), with substantial support from the MIT Roof Net project team ( http://pdos.csail.mit.edu/click/ )


Introduction

The Netgear wgt634u Wireless Router has a Broadcom?? CPU, running at 200??MHz. This CPU is not compatible with the Pentium (or similar) on your desktop computer, i.e. you can not simply take a binary program file from your desktop and execute it on the Netgear router - the Broadcom CPU encodes instructions and data in a completely different way and would therefore not "understand" your Pentium-based program at all.

The operating system on the Router router is Linux - again, not the same Linux that you might run on your desktop, but a Linux that was specifically compiled for the Broadcom CPU. The operating system along with all other programs is stored in a regular Linux file system which physically resides on the Netgear router's 8??MB of flash memory. Flash memory is nonvolatile RAM which does not lose its data when the device is powered-off. But it is RAM, i.e. it can be modified in much the same way as regular RAM - just at a slower speed. In addition to the 8??MB of non-volatile flash memory for the file system, the Netgear router has 16??MB of regular volatile RAM.

The content of the flash memory (i.e. the file system with all its data, including the operating system, programs and configuration data) is also called firmware. When we say that we replace the firmware of the Netgear router, we mean that we erase the content of the flash memory, i.e. it the entire file system that was stored in it - and replace it with an entirely new file system, which contains a completely new operating system, and a new set of programs and data files. Nothing from the old system will survive when the firmware is replaced.

For the initial setup of the Netgear router we will download the source code for the OpenWRT firmware and cross-compile it for the Broadcom CPU. Cross-compilation is a process where the compiler produces binary program files that are not meant to be executed on the local system, but rather on another platform (here the Netgear router with its Broadcom CPU). Then, using tricky configuration script, we will tinker with the original bootloader configuration and finally replace the Netgear firmware with our OpenWRT firmware.

Before you begin, one word of caution: Once you overwrite the original Netgear firmware, it is gone forever. No pressing of the reset button or power cycling will bring it back. If the new firmware does not work, then you have transformed your Netgear router into a nice paperweight. But fortunately, this does not happen often.

Getting Started

You need a Linux system with approximately 1GB free disk space to download and compile the OpenWRT source code and the toolchain.


OpenWRT Toolchain

What is a toolchain?

To build a Linux system for the Broadcom CPU, you need several tools that are not part of your normal Linux distribution. To obtain those tools, you have to download their source code and compile them on your Linux system. All these tools together make up the toolchain. Note, that the toolchain programs run on your local (Pentium-based) computer; they are only needed to build the OpenWRT firmware, but they will not be included in the firmware itself!

Downloading the OpenWRT toolchain sources

First of all you need to install the openwrt toolchain ( [1] ) on your build computer.

 cvs -d:pserver:anonymous@openwrt.org:/openwrt login
 cvs -d:pserver:anonymous@openwrt.org:/openwrt co buildroot

The following tools/libs are required:

  • wget, tftp
  • cvs, subversion
  • gcc, gcc-c++, bison, flex
  • patch, gettext
  • autoconf, automake
  • zlib-devel

Compiling the OpenWRT toolchain

We need a C++-compiler, so you’ll need to patch $OPENWRT/buildroot/Makefile.

 INSTALL_LIBSTDCPP:=true

That's all: run make

Compiling click

To build click you have to copy the following Makefile (click.mk) to the $OPENWRT/buildroot/make directory:

 #############################################################
 #
 # click
 #
 #############################################################
 CLICK_DIR:=$(BUILD_DIR)/click
 
 click-source: $(CLICK_DIR)/.unpacked
 
 
 $(CLICK_DIR)/.unpacked: $(DL_DIR)/$(CLICK_SOURCE)
       (cd $(BUILD_DIR); \
       svn co svn://merkur.sardmn.informatik.hu-berlin.de/click)
       touch $(CLICK_DIR)/.unpacked
 
 
 $(CLICK_DIR)/.configured: $(CLICK_DIR)/.unpacked
       (cd $(CLICK_DIR); rm -rf config.cache; \
               $(TARGET_CONFIGURE_OPTS) \
               CFLAGS="$(TARGET_CFLAGS)" \
               AR_CREATEFLAGS="cru" \
               CLFLAGS=-static \
               CXXFLAGS=-static \
               ./configure \
               --build=i686-pc-linux-gnu \
               --host=mipsel-linux \
               --disable-linuxmodule \
               --enable-brn \
               --disable-ip \
               --enable-wifi \
               --disable-ip \
               --enable-tools=mixed \
       );
       touch  $(CLICK_DIR)/.configured
 
 $(CLICK_DIR)/click: $(CLICK_DIR)/.configured
       $(MAKE) CC=$(TARGET_CC) -C $(CLICK_DIR)
 
 $(TARGET_DIR)/usr/bin/click: $(CLICK_DIR)/click
       install -c $(CLICK_DIR)/userlevel/click $(TARGET_DIR)/usr/bin/click
       $(STRIP) $(TARGET_DIR)/usr/bin/click > /dev/null 2>&1
 
 click: uclibc $(TARGET_DIR)/usr/bin/click 
 
 click-clean: 
       $(MAKE) -C $(CLICK_DIR) clean
       rm -rf $(TARGET_DIR)/usr/bin/click
 
 click-dirclean: 
       rm -rf $(CLICK_DIR)

That's all: run make click to build click. Currently, I only tested the userlevel click binary.

Compiling Madwifi.stripped

The madwifi.stripped driver lets Click directly read and write raw frames from the wireless card, and strips out the usual driver logic. To build the madwifi.stripped driver you have to copy the following Makefile (madwifi.mk) to the $OPENWRT/buildroot/make directory:

 #############################################################
 #
 # madwifi.stripped
 #
 #############################################################
 MADWIFI_DIR:=$(BUILD_DIR)/madwifi
 
 
 $(DL_DIR)/$(MADWIFI_SOURCE):
       $(WGET) -P $(DL_DIR) $(MADWIFI_SITE)/$(MADWIFI_SOURCE)
 
 madwifi-source: $(DL_DIR)/$(MADWIFI_SOURCE)
 
 $(MADWIFI_DIR)/.unpacked: $(DL_DIR)/$(MADWIFI_SOURCE)
       (cd $(BUILD_DIR); \
       cvs -d :pserver:anoncvs@cvs.pdos.lcs.mit.edu:/cvs login)
       (cd $(BUILD_DIR); \
       cvs -z5 -d :pserver:anoncvs@cvs.pdos.lcs.mit.edu:/cvs co -d madwifi roofnet/release/stripped)
       touch $(MADWIFI_DIR)/.unpacked
 
 $(MADWIFI_DIR)/madwifi: $(MADWIFI_DIR)/.unpacked
       $(MAKE) CC=$(TARGET_CC) TARGET=mips-le-elf KERNELPATH=$(BUILD_DIR)/WRT54GS/release/src/linux/linux/ -C $(MADWIFI_DIR)
 
 $(TARGET_DIR)/usr/bin/madwifi: $(MADWIFI_DIR)/madwifi
       mkdir $(TARGET_DIR)/usr/bin/madwifi/
       cp $(MADWIFI_DIR)/madwifi/driver/ath_pci.o $(TARGET_DIR)/usr/bin/madwifi/
       cp $(MADWIFI_DIR)/madwifi/ath_hal/ath_hal.o $(TARGET_DIR)/usr/bin/madwifi/
       $(STRIP) $(TARGET_DIR)/usr/bin/madwifi/ath_pci.o > /dev/null 2>&1
       $(STRIP) $(TARGET_DIR)/usr/bin/madwifi/ath_hal.o > /dev/null 2>&1
 
 madwifi: uclibc $(TARGET_DIR)/usr/bin/madwifi/
 
 madwifi-clean: 
       $(MAKE) -C $(MADWIFI_DIR) clean
       rm -rf $(TARGET_DIR)/usr/bin/madwifi/
 
 madwifi-dirclean: 
       rm -rf $(MADWIFI_DIR)

That's all: run make madwifi to build the driver.

Compiling New Kernel

To build the linux kernel for the wgt634u-box you have to copy the following Makefile (wgtkernel.mk) to the $OPENWRT/buildroot/make directory:

 #############################################################
 #
 # linux kernel for wgt634
 #
 #############################################################
 WGTKERNEL_DIR:=$(BUILD_DIR)/wgt634u-1.4.1.8-gpl-src
 WGTKERNEL_SOURCE=wgt634u-1.4.1.8-gpl-src.tar.bz2
 WGTKERNEL_SITE=ftp://downloads.netgear.com/files/GPL
 WGTKERNEL_KERNEL=wgt634u-1.4.1.8-gpl-src/linux-2.4.x
 WGTKERNEL_BROADCOM_SRC=wgt634u-1.4.1.8-gpl-src/broadcom-src
 LINUX_DIR:=$(WGTKERNEL_DIR)/linux-2.4.x
 UCLIBC_DIR:=$(BUILD_DIR)/staging_dir/mipsel-linux-uclibc/
 STAGING_DIR:=$(BUILD_DIR)/staging_dir/
 
 all: wgtkernel
 
 $(DL_DIR)/$(WGTKERNEL_SOURCE):
       $(WGET) -P $(DL_DIR) $(WGTKERNEL_SITE)/$(WGTKERNEL_SOURCE)
 
 $(WGTKERNEL_DIR)/.source: $(DL_DIR)/$(WGTKERNEL_SOURCE)
       bzcat $(DL_DIR)/$(WGTKERNEL_SOURCE) | tar -C $(BUILD_DIR) -xvf - $(WGTKERNEL_KERNEL) $(WGTKERNEL_BROADCOM_SRC)
       touch $(WGTKERNEL_DIR)/.source
 
 wgtkernel: dep zImage
 
 dep: $(WGTKERNEL_DIR)/.source
       $(MAKE) CC=$(TARGET_CC) -C $(WGTKERNEL_DIR)/linux-2.4.x oldconfig include/linux/version.h
       $(MAKE) CC=$(TARGET_CC) -C $(WGTKERNEL_DIR)/linux-2.4.x SRCBASE=$(WGTKERNEL_DIR)/broadcom-src dep
 
 zImage:
       $(MAKE) CC=$(TARGET_CC) -C $(WGTKERNEL_DIR)/linux-2.4.x SRCBASE=$(WGTKERNEL_DIR)/broadcom-src zImage
 
 
 wgtkernel-clean: 
       $(MAKE) -C $(LINUX_DIR) clean
       rm $(WGTKERNEL_DIR)/.unpacked
 
 wgtkernel-dirclean: 
       rm -rf $(WGTKERNEL_DIR)


First, the stock kernel doesn’t link with gcc 3.3.3, so you’ll need to patch linux-2.4.x/arch/mips/brcm-boards/bcm947xx/cfe_flash_nvram.c.

 @@ -927,6 +927,12 @@
       struct page *page, *end;
       unsigned int i;
 
 +       /* Register char device */
 +       if ((nvram_major = devfs_register_chrdev(252, "nvram", &nvram_fops)) < 0) {
 +               ret = nvram_major;
 +               return ret;
 +       }
 +
         /* Allocate and reserve memory to mmap() */
         while ((PAGE_SIZE << order) < NVRAM_SPACE)
                 order++;
 @@ -955,21 +961,11 @@
         /* Initialize hash table */
         nvram_rehash();
 
 -       /* Register char device */
 -       if ((nvram_major = devfs_register_chrdev(252, "nvram", &nvram_fops)) < 0) {
 -               ret = nvram_major;
 -               goto err;
 -       }
 -
         /* Create /dev/nvram handle */
         nvram_handle = devfs_register(NULL, "nvram", DEVFS_FL_NONE, nvram_major, 0,
                                       S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, &nvram_fops, NULL);
         return 0;
 -
 - err:
 -       nvram_exit();
 -       return ret;
  }
 
  module_init(nvram_init);


Third, you’ll need to patch linux-2.4.x/Makefile.

 27a28,29
 > MIPS_BASE     	= $(TOPDIR)/../../staging_dir/bin/
 > 
 29c31
 < LD		= $(CROSS_COMPILE)ld
 ---
 > LD		= $(MIPS_BASE)/$(CROSS_COMPILE)ld
 32,36c34,38
 < AR		= $(CROSS_COMPILE)ar
 < NM		= $(CROSS_COMPILE)nm
 < STRIP		= $(CROSS_COMPILE)strip
 < OBJCOPY		= $(CROSS_COMPILE)objcopy
 < OBJDUMP		= $(CROSS_COMPILE)objdump
 ---
 > AR		= $(MIPS_BASE)/$(CROSS_COMPILE)ar
 > NM		= $(MIPS_BASE)/$(CROSS_COMPILE)nm
 > STRIP		= $(MIPS_BASE)/$(CROSS_COMPILE)strip
 > OBJCOPY		= $(MIPS_BASE)/$(CROSS_COMPILE)objcopy
 > OBJDUMP		= $(MIPS_BASE)/$(CROSS_COMPILE)objdump


Fourth, you’ll need to patch linux-2.4.x/arch/mips/Makefile.

 69c69
 < GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 ---
 > GCCFLAGS	+= -mips2 -Wa,--trap
 72c72
 < GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 ---
 > GCCFLAGS	+= -mips2 -Wa,--trap
 75c75
 < GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 ---
 > GCCFLAGS	+= -mips2 -Wa,--trap
 78c78
 < GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 ---
 > GCCFLAGS	+= -mips2 -Wa,--trap
 81c81
 < GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 ---
 > GCCFLAGS	+= -mips2 -Wa,--trap

Fifth, you’ll need to patch linux-2.4.x/arch/mips/brcm-boards/bcm947xx/compressed/Makefile.

 21d20
 < STRIP := $(CROSS_COMPILE)strip
 23c22,25
 < OBJCOPY		:= $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
 ---
 > MIPS_BASE	:= $(TOPDIR)/../../staging_dir/bin/
 > STRIP 		:= $(MIPS_BASE)/$(CROSS_COMPILE)strip
 > 
 > OBJCOPY		:= $(MIPS_BASE)/$(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
 28c30
 < ASFLAGS		+= -G 0  -mno-abicalls -fno-pic -pipe -mcpu=r4600 -mips2 -Wa --trap -m4710a0kern
 ---
 > ASFLAGS		+= -G 0  -mno-abicalls -fno-pic -pipe -mips2


Last, if you’re planning to run userlevel click, edit the linux-2.4.x/.config file and change the CONFIG_ETHERTAP and CONFIG_TUN lines to y.

That's all: run make wgtkernel to build the kernel.

References