Wednesday, March 16, 2011

Taking a peek at the firmware

TRENDnet offer a download for the GPL source at their website; a quick download later allowed me to take a peek at what they had used to pull it together. Annoyingly, they had only included the bare esentials with no buildchain or any other tools to build a custom firmware.

A bit more research showed that they have used a relatively common platform to build the camera (using the PL1209 chipset) which a very capable and self contained device (more on this later).

It seems that other companies also make use of this platform for these type of devices (indeed some look identical to the 312W I have here) and so I had a look around to see if anyone else has had any joy in getting into the firmware.

A company snappily called Airlink 101 Network Solutions offer a similar looking device; the AICN500W which has a very similar case and the same functionality. A quick look around their website and a download later and I have a much more complete firmware source tree and crucially the tools necessary to build a complete firmware image.

I have republished their toolchain here under the terms of the GPL.

The instructions provided with the image indicate that fedora 3 is needed to use the buildchain; not having the desire to have yet another image on my Mac I took the chance that it would work with Ubuntu; a couple of hours later (and a couple of fixes to the make files provided) and I can get the entire toolchain to compile providing the compiler, headers and source files for all the opensource components.

Not wanting to risk installing the firmware from another manufacturer - and bricking the camera - I looked around for a description of the firmware format to see if the 312W resembled that used in the Airlink devices.

I stumbled across a chap who has already done this for the AICN747W which looks similar enough - and interestingly he has used it to enable telnet on the camera. A quick peek at his instructions and a little tinkering later, using the fwpacker source provided in the tool chain to reverse engineer the process and I wrote a script to extract the components in order to modify the firmware provided with the 312W.

You can download the source here

#!/usr/bin/perl
# TrendNet firmware unpacker
# Matt Brain (matt.brain@gmail.com)
#
# Usage: fwunpack.pl
#
# Extracts: prostub.bin
# vmlinuz
# minix.gz
# autoboot.bat
# footer.bin
#
# Writes log to fwunpack.log

use strict;

my $scriptversion=1; #Version of this script

my $headerPointer=0x04; #Header reference in firmware
my $versionLocation=0x08; #Version location in firmware
my $md5Location=0x0c; #md5 location in firmware
my $md5Size=16; #md5 length
my $crcLocation=$md5Location+$md5Size; #crc location
my $crcSize=4; #crc length
my $pkgSizeLocation=$crcLocation+$crcSize; #package size location
my $headerSize=4096; #size of header found at $headerPointer

my $model="Unknown";
my $headerLocation=0x00;
my $tVersion=0x00;
my @version=(0,0,0,0);

my @chunkStart=(0);
my @chunkLength=(0);
my @chunkName=("vmlinuz", "minix.gz", "autoboot.bat");
my @chunk;

my $footer="";
my $prostub="";
my $numArgs=$#ARGV+1;




sub Usage {
print "Usage: fwunpack \n\n";
exit;
}



if ($numArgs<1) {
&Usage;
}

print "** fwunpack version $scriptversion **\n\n";
print "Opening $ARGV[0]\n";
open(FIRMWARE,"<$ARGV[0]");
binmode(FIRMWARE);

#read the header location
seek(FIRMWARE,$headerPointer,0);

read(FIRMWARE,$headerLocation,4) or die "FATAL: Couldn't read the header location\n";

#firmware location is stored in little endian format so need to fiddle the bits
$headerLocation = unpack('L<',$headerLocation);
printf "Header location at 0x%x\n",$headerLocation;

seek(FIRMWARE,$versionLocation,0);
read(FIRMWARE,$tVersion,4) or die "FATAL: Couldn't read the version\n";
@version=unpack('cccc',$tVersion);
printf "Firmware version $version[3].$version[2].$version[1].$version[0]\n";
#read the model name
seek(FIRMWARE,$headerLocation+4088,0);
read(FIRMWARE,$model,8);
print "Model $model\n";

my $chunkCursor=$headerLocation+4096;
#load the header
for (my $counter=0;$counter < 511;$counter++) {
seek(FIRMWARE,$headerLocation+($counter*8),0);
read(FIRMWARE,$chunkStart[$counter],4);
read(FIRMWARE,$chunkLength[$counter],4);
$chunkStart[$counter] = unpack('L<',$chunkStart[$counter]);
$chunkLength[$counter] = unpack('L<',$chunkLength[$counter]);
if ($chunkStart[$counter]>0) {
printf "%s found, deploy at:0x%x length:%d\n",$chunkName[$counter],$chunkStart[$counter],$chunkLength[$counter];
seek(FIRMWARE,$chunkCursor,0);
read(FIRMWARE,$chunk[$counter],$chunkLength[$counter]);
$chunkCursor = tell(FIRMWARE);
open(CHUNK,">$chunkName[$counter]") or die $!;
binmode CHUNK;
print CHUNK $chunk[$counter];
close CHUNK;
}
}

seek(FIRMWARE,$chunkCursor,0);
print "writing footer.bin\n";

read(FIRMWARE,$footer,64);
open(FOOTER,'>footer.bin');
binmode FOOTER;
print FOOTER $footer;
close FOOTER;

print "writing prostub.bin\n";

seek(FIRMWARE,0,0);
read(FIRMWARE,$prostub,$headerLocation);
open(PROSTUB,'>prostub.bin');
binmode PROSTUB;
print PROSTUB $prostub;
close PROSTUB;

close FIRMWARE;


Using the instructions provided with the AICN500W firmware I was then able to rebuild the firmware and do a comparison between the 2 - this was critical to show that i was pulling all the bits out as expected and was able to reconstruct the bits into an identical firmware file. I had to create an ipcam.dsc file to describe the components in the firmware for the fwpacker tool as below and append the footer.bin to the output of fwpacker.

# ipcam.dsc

# describe the firmware version
@version 1.0.0.3

# describe the model which maxium 8 characters
@model IPCAM001

# describe nor flash type and size
@norinit 1 "8x8,64x63"

# describe deployment location and input file
@deployment
vmlinuz 0x20000 777008
minix.gz 0xe0000 2836160
autoboot.bat 0x2000 8192
@end

I then referred back to the instructions found earlier and
enabled telnet access by uncommenting 2 lines in etc/rc.d/init.d/daemon.sh:

# echo "Starting telnetd ..."
# telnetd -p 15566

gzipping the disk image back up produced a smaller image which concerned me - but rebuilding the firmware and uploading proved it worked (bit of a gamble I know) - I had telnet access on 15566.
You may download a bundle which contains the source for the fwunpacker along with the fwpacker and associated files from

It seems all the download links are broken - here is a bundle of all the files used in this project Google Drive ZIP archive

10 comments:

  1. How did you compile the firmware?
    I followed the instructions too, but I am getting a lot of errors.
    I have Win7 x64. Installed Ubuntu 11.04 x64 on VMware Workstation 7.1 x64.

    It fails here:

    arm-linux-strip pppoe/rp-pppoe-3.8/src/pppoe
    arm-linux-strip: Unable to recognise the format of the input file pppoe/rp-pppoe-3.8/src/pppoe
    make*** [opensources Error 1
    make[1]: Leaving directory `/home/user/AICN500W/source/open'
    make: *** [all] Error 2

    I really would like this going.
    Your help is greatly appreciated.

    Thx, Ivan

    ReplyDelete
  2. Thanks for your comment - I see there was an error when I pasted the code in, I have updated it so it should work now,

    Cheers

    Matt

    ReplyDelete
  3. hi, i also have one of these cameras, i want use it as nas & pyload serve. can you upload a copy of the airlink sourcecode and chaintool for crosscompile? airlink has remove the link.

    thanx.

    ReplyDelete
  4. I have added a link to download their toolchain above - hope you have fun ;)

    ReplyDelete
  5. dont forget - you will also want the source for the TV-IP312W as well which I will also post a link to. If you are just cross compiling code, use the Airlink toolchain to compile and then just split open your firmware and add it to the disk image or pop it on a share / usb stick and use my telnet image to get into the camera - However, if you want to recompile the kernel you will need to use the TV-IP312W source and do some splicing to get a kernel suitable for the specific TV-IP312W implementation....

    ReplyDelete
  6. Thanks for all info, it worked also for trendnet IP410W model,
    i managed to re-pack firmware with telnet enabled :)

    ReplyDelete
  7. Can you explain how to recover the tv-ip312w from a failed firmware update to 1.1.0.67? I think the power was interrupted. Power light and ir's turn on, but cannot access device by browser at old or at default ip addresses.

    ReplyDelete
  8. Hello, I am stuck with fwpacker. Here is the error:
    ===================================================
    ./fwpacker ipcam.dsc -o firmware
    fwpacker v1.0.0
    2006 (C) Copyright reserved
    Prolific Technology Inc.

    package description file is ipcam.dsc
    output package file is firmware

    line 15: location (0xe0000, 3630336) of file description is invalid (nor size 0x400000) i 71 lloc 400000 lsize 353536
    ===================================================

    Could you explain what are :

    0x20000
    0xe0000
    0x2000

    in the @deployment section?

    ReplyDelete
    Replies
    1. OK I have managed to pack a new firmware using this ipcam.dsc

      =========================
      # ipcam.dsc

      # describe the firmware version
      @version TV-IP422WN_v1_1.1.1-28-telnet

      # describe the model which maxium is 8 characters
      @model IPCAM001

      # describe nor flash type and size
      #@norinit 1 "8x8,64x63"
      @norinit 1 "8x8,64x127"

      # describe deployment location and input file
      @deployment
      vmlinuz 0x20000 777008
      #minix.gz 0xe0000 2429536
      minix.gz 0xe0000 4000000
      autoboot.bat 0x2000 8192
      #@erase 0x4000 16384
      #@erase 0x8000 24576
      @end
      ====================================

      Delete
    2. BTW, this is for a Trendnet 422WN !

      Delete