Linksys WVC54G Experiments

WARNING: this document may contain errors. The standard disclaimer applies: if you choose to follow any of these instructions, it is your fault if it goes wrong. Having said that, it really takes a lot of incompetence to mess this up, and I tried (I was drunk too)!

Things that you should be aware of: stuff that I wish you to type is in bold face and...

this typeface
...is usually where I am quoting the output of a command, a script or a patch file.

If you just want a WVC54G image and you don't want to read all the blurb below, try the OLSR firmware - however, there was a reason why I didn't continue with this firmware myself: the image is based on an old Linksys firmware, and the camera stuff is buggy. I also didn't need the OLSR ('optimised link-state routing') stuff, although it looks really cool. If you don't have any luck with t hat, I've compiled an image with my desktop computer (Spatula) but I HAVE NOT TESTED IT so beware! Amendments to the standard image: inetd has been enabled so telnet is available; /etc/shadow has been removed; there are no passwords for 'root' and 'user'.

A Bit Of History

At the end of 2004, I decided to buy myself a Linksys WVC54G Internet Video Camera. Having parted with my £179'ish, I was disappointed to find the device quite limited in a lot of areas: it has an ActiveX page for viewing video, and it is buggy. Its video stream is viewable in MPlayer though:
mplayer http://192.168.1.115/img/video.asf
.. and although the video stream had many errors and dropped frames, it was at least viewable on my Linux systems. I have since found out a lot about the device and it is quite a smart little gadget, but it's a shame that Linksys didn't make better firmware when it was first released. They have introduced new models since then - smaller, faster devices that probably have fewer bugs.

Linksys have released source code for lots of their devices under the GPL, and this is very welcome. I downloaded the WVC54G source code from their GPL page. I was not sure which version to choose, and ended up getting the 5.0.1 source code. This file decrunches to three files under a 'WVC54G_Intamac_5.01' directory (clicking the links shows a listing of the files): cadexnux.tgz (Cadenux build tools), readme.txt (instructions) and wvc54g_eu_intamac_GPL_5.01.tgz (kernel and tools source code).

I initially tried building the firmware image on a fairly modern computer, and had a lot of trouble because of usage changes in common tools, and other assumptions by the WVC54G build scripts. I had a lot more luck when I copied everything over to a K6-2/500-based PC, which has Red Hat 7.3 installed. This is the computer that I use whenever I have any really old stuff to compile, and in this case, it was flawless and I didn't need to patch anything (see below).

The main problems that I found were the kernel config - there isn't one. If you do 'make menuconfig' in the kernel source dir, a default config is used, though may I suggest that you check it several times to make sure that it's not using something else - in fact, double-check everything because there's always the chance that something could go wrong.

Of particular note: the instructions assume that you are doing the build process as root. It is possible to use su or sudo by adding 'SU_CMD' to the Make command line - e.g.

# make FW SU_CMD=sudo
I tried this a few times and found that sometimes it would prompt me for a password and sometimes not, depending on when I'd last run sudo. I had a lot less trouble doing the build as root, although naturally, you have to be careful.

Modifications to the firmware

The first thing that I wanted to do was enable the telnet service. The WVC54G has a telnet server and inetd - both are disabled by default. It is possible to extract the cramfs filesystem from the firmware image using this command:
dd if=WVC54G-intamac-v510.bin bs=65536 of=fs.img skip=15
This will extract the firmware right up to the end of the file. This doesn't matter as the cruft after the end of the filesystem is ignored by cramfs. It's probably a good idea to check that you have extracted the right data: doing 'file fs.img' should return something like this:
fs.img: Linux Compressed ROM File System data, little endian size 1716224 version #2 sorted_dirs CRC 0x66f1c54c, edition 0, 933 blocks, 334 files
If you have support for cramfs in the kernel, you can then mount the image like this:
sudo mount -t cramfs fs.img /mnt/tmp -o ro,loop
I got the map of the firmware file from the the Linksys build environment's 'FW' dir. This map is used by the 'combine-image' tool to build the firmware. Here's a listing of it:
size = 00400000
file = WVC54G.bin
f1_name = loader
f1_start = 00000000
f2_name=kernel
f2_start=00010000
f3_name=filesystem
f3_start=000F0000
f4_name=PID
f4_start=003FFFB2
RRLoader is the first section, then the Linux kernel, the filesystem and the 'PID'. I've tried to find out what this is and have not had much luck. I was originally going to rebuild the firmware by using the Linksys firmware file's loader, kernel and PID and putting it together with a filesystem image that I was going to build myself, with mkcramfs (from the cramfs tools). It turned out to be a lot easier to use the standard Cadenux tools to build the whole thing.

Building the firmware

Extract the GPL code (decrunches to /opt/Cadenux).
sudo tar -xzf toolchain.tgz -C /
cd <build dir>
tar -xzf wvc54g-EU.src.tgz
cd wvc54g-EU/SOURCE

# Su to root.  BE VERY CAREFUL! (Sorry if I've said this too much)

sudo su
PS1="\u@\h:\W# "
. ./setenv EN
make clean
cd linux
make menuconfig

# In the System Type menu, check that 'ARM system type' is 'TMS320' and
# 'TMS320 architecture' is 'DM270'.  If so, you're probably using the right
# config.
# Exit menuconfig, saving the configuration.

make dep
cd ..
make
# The kernel will be built, hopefully.
Errors that you may get: "sed: -e expression #1, char 85: unterminated address regex": This is due to changes in Sed. Fix: edit linux/arch/armnommu/Makefile: find the line starting
ifeq ($(CONFIG_ARCH_DM270),y)
and replace the single-quotes in the following sed command with double-quotes. Here's a patch if you don't want to do that manually:
root@spatula:SOURCE# diff -u linux/arch/armnommu/Makefile.orig linux/arch/armnommu/Makefile
--- linux/arch/armnommu/Makefile.orig   2004-04-16 08:33:25.000000000 +0100
+++ linux/arch/armnommu/Makefile        2008-03-31 09:56:41.000000000 +0100
@@ -340,9 +340,9 @@
              s/IRAMBASE/$(BSPCONF_IRAM_BASE)/' <$< >$@
 else
 ifeq ($(CONFIG_ARCH_DM270),y)
-       @sed 's/TEXTADDR/$(TEXTADDR)/;\
+       @sed "s/TEXTADDR/$(TEXTADDR)/;\
              s/DATAADDR/$(DATAADDR)/;\
-             s/IRAMBASE/$(BSPCONF_IRAM_BASE)/' <$< >$@
+             s/IRAMBASE/$(BSPCONF_IRAM_BASE)/" <$< >$@
 else
 ifeq ($(CONFIG_ARCH_C5471),y)
        @sed 's/TEXTADDR/$(TEXTADDR)/;\
The next error you'll probably get is a 'cannot stat' from cp, after 'Syncing the header files from KERNEL to TOOL-CHAIN......' Fix: edit kmods/cmos/Makefile and expand the filenames in the line with '@cp -f ../../linux/include/linux/{sys_buffer.h...'
A patch:
root@spatula:SOURCE# diff -u kmods/cmos/Makefile.orig kmods/cmos/Makefile       --- kmods/cmos/Makefile.orig    2005-10-14 07:48:04.000000000 +0100
+++ kmods/cmos/Makefile 2008-03-31 10:00:28.000000000 +0100
@@ -24,7 +24,9 @@
        @echo "--->>> --->>> --->>> --->>> --->>> --->>> --->>> --->>>"
        @cp -f ../../linux/include/asm/unistd.h             $(BSPCONF_BIN)/../arm-uclinux/include/asm/
        @cp -f ../../linux/include/asm/arch/hardware.h      $(BSPCONF_BIN)/../arm-uclinux/include/asm/arch/
-       @cp -f ../../linux/include/linux/{sys_buffer.h,buffer.h,vdsp.h}   $(BSPCONF_BIN)/../arm-uclinux/include/linux/
+       @cp -f ../../linux/include/linux/sys_buffer.h   $(BSPCONF_BIN)/../arm-uclinux/include/linux/
+        @cp -f ../../linux/include/linux/buffer.h   $(BSPCONF_BIN)/../arm-uclinux/include/linux/
+        @cp -f ../../linux/include/linux/vdsp.h   $(BSPCONF_BIN)/../arm-uclinux/include/linux/

 all: h-files $(objs)
If you edit the Makefile, make sure you use TABs to separate the fields, as 'make' is very picky about this.

My guess is that before, cp would be have been run in a shell and the filenames would have been expanded, but now cp is either not run in a shell, or it's not a bash shell <shrug>.

The next minor buggette:

/bin/sh: @#: not found
/bin/sh: @#done: not found
This is in SOURCE/fs/Makefile.dm270: GNU make doesn't like the line continuation characters in the RPM installation loop. Either delete these lines or apply a the following patch, which does the same thing:
root@spatula:SOURCE# diff -u fs/Makefile.dm270.orig fs/Makefile.dm270
--- fs/Makefile.dm270.orig      2004-12-13 09:17:07.000000000 +0000
+++ fs/Makefile.dm270   2008-03-31 10:12:37.000000000 +0100
@@ -160,9 +160,7 @@
        #${FSROOT_DIR}/usr/bin/gdbreplay

        @## Installing RPMs...
-       @#for i in ${RPMS}; do \
-       @#      rpm --root ${FSROOT_DIR} -iv ${RPM_OPTS} rpm/$${i}.${RPM_ARCH}.rpm; \
-       @#done
+       @#for i in ${RPMS}; do rpm --root ${FSROOT_DIR} -iv ${RPM_OPTS} rpm/$${i}.${RPM_ARCH}.rpm; done
        @#rm -rf $(FSROOT_DIR)/usr/{doc,man,sbin/itox,share} ${FSROOT_DIR}/var/lib

        @# Setting ownership and permissions...
The next: "/bin/sh: arm-uclinux-holes: not found". This is something to do with paths and I didn't figure out why it was happening. Fix this temporarily by telling make where the HOLES app is:
root@spatula:SOURCE# make HOLES="/opt/Cadenux/dm270/uclinux-2.4/crossdev/bin/arm-uclinux-holes"
The next bit is as listed in the Linksys README, except that they've made a mistake with the RRLoader, which is called 'rrload'.
root@spatula:SOURCE# cp linux/linux.stripped.binary FW/kernel
root@spatula:SOURCE# cp fs/fs.img FW/filesystem
root@spatula:SOURCE# cp ../loader/rrload/rrload.stripped.binary FW/loader
Next, build the firmware. This is the last bit, and if this fails, it all does (great, what an optimist I am..):
root@spatula:SOURCE# cd FW
root@spatula:FW# ./combine-image
The result of all this jiggery-pokery: you should have an approx. 4M file called 'WVC54G.bin' in your 'FW' directory. Upload this to the camera, wait a bit, and it'll reboot into the new firmware environment. There are three stages: the sending of the firmware to the camera, the writing of the firmware image to the MTD, and the reboot process. You may find that the camera goes back to its default IP address of 192.168.1.115.

One last thing: this caused me a LOT of annoyance (but then, I was a bit drunk by that time) - whenever I edited the filesystem files (SOURCE/fs/fs is the root dir), the build process overwrote the passwd, inittab and rc files, meaning that all attempts to add my own users - and to enable inetd - failed. The initial root filesystem is copied from SOURCE/fs/userland/scripts, and it overwrites the stuff in fs/fs - so edit the files in fs/userland/scripts first. To rebuild the filesystem, do

make fs
and don't forget to
cp fs/fs.img FW/filesystem && cd FW && ./combine-image

If you have any questions, please email brooknet at imap dot cc, changing the 'at' to an at symbol and the 'dot' to a dot - or see my contact page on the main site.

Good luck!