A Development environment

To extend the functionality of the inventel box you need more software. This will require a MIPS cross compiler that can be executed on an external Development Linux server.

All linux development was done using Ubuntu 8.10 running inside VMWARE.

Linux cross compiler for MIPS toolchain

This is the toolchain that I have been using to perform all my development, including on the Home Automation Hub. It's based upon the Inventel toolchain with a few additional libraries thrown in for good measure.

Install into a directory called /opt this is important as paths are coded into the binaries.

toolchains.tar.gz 18Mb

Then add the directory /opt/toolchains/uclibc/bin to you path and you're good to go.

Native MIPS development

This is a development toolchain compiled natively for the LIVEBOX that is to say they are ELF 32-bit MSB MIPS-I executables. Yes a GCC that runs on the Livebox itself, along with various other utilities. You need to configure SWAP on the livebox if you want to do any serious compilations.

Includes:

  • GCC 3.2.2 (as,cpp,nm,ranlib,gcc,ld,objdump,size,ar,strip,nm,readelf,abxtest,gcov)
  • Utilities (make,lsof,tset,clear)
  • Python 1.5
  • Python 2.5

These should be mounted on a directory called /opt for the internal paths to resolve correctly.

Inventel Source and Precompiled Toolchain

Lots of software for the 2.6 era kernel is posted here → http://www.livebox-floss.com/

This is the official software release that Inventel made to meet their GPL requirements, as Inventel no longer makes this available you can get it from here.

The source code released by Inventel includes the sources, binaries and configuration files required to build the inventel firmware. This builds if you follow the instructions.

tar xf OPENSOURCE-5G-2006-07-18.tgz
cd OPENSOURCE-5G-2006-07-18
tar xf sources-toolchain-3.2.2.tar.gz
cd gcc-3.2.2
mkdir /opt
mv toolchain /opt

Append to your ~/.bashrc

PATH=$PATH:/opt/toolchain/bin 

Building a Toolchain

Following along with the document from http://buildroot.uclibc.org/buildroot.html you can setup a MIPS toolchain. To summarize:

For Ubuntu you will need to have at least the following installed:

apt-get install subversion
apt-get install gcc
apt-get install g++
apt-get install libc6-dev
apt-get install bison
apt-get install flex
apt-get install gettext
apt-get install libncurses5-dev
apt-get install texinfo
$ svn co svn://uclibc.org/trunk/buildroot
$ cd buildroot
$ make menuconfig
-> Target: mips
-> Variant: mips32
$ make

Now to test out the compiler:

$ cd build_mips/staging_dir/usr/bin
$ PATH=`pwd`:$PATH
$ cd ~
$ cat >hello.c <<EOF
#include <stdio.h>
int main(int argc, char **argv) {
  printf("hello world\n");
}
EOF
$ cat >Makefile <<EOF
XCOMPILE=mips-linux-
CC=${XCOMPILE}gcc
hello:
        ${CC} -o hello hello.c
EOF
$ make

For some reason this cross compiler once built has problems handling the

(int argc, char **argv)

parameters passed to main() until the binary is compiled static.

This section is largely redundant as the ucLib toolchain has an option to build gdb. Guess I didn't notice this when I embarked on this exercise.

First you need to download the source code for the GDB debugger.

apt-get install dpkg-dev
apt-get source gdb

Now configure it for MIPS support. This binary will run natively on i386 but will be able to examine MIPS core dumps and MIPS generated binaries. We do this as the livebox does not have sufficient resources to be able to run a full debugger. That and the fact that we don't have ALL the libraries necessary for a x-compile; things such as termcap (mips) etc..

cd gdb-6.8
./configure --target=mips-linux --host=i386 --build=i386
make

This is the process used to bootstrap from the cross compiler tools on our development i686 linux machine to a native MIPS set of development tools that can be ran from the livebox.

Assuming the SOURCE code has been downloaded and unpacked and our current working directory is here. These versions can be found in http://www.dbzoo.com/public/OPENSOURCE-5G-2006-07-18.tgz (300Mb)

root@gumby:/opt/mips-build# ls -l
drwxr-xr-x 14 root root  4096 2008-10-06 18:14 binutils-2.13.2.1
drwxr-xr-x 17  500 users 4096 2003-02-05 03:54 gcc-3.2.2
root@gumby:/opt/mips-build#

Why are we using GCC 3.2.2 ? Because our cross compiler toolchain as supplied by INVENTEL used this version, which means we can use the already compiled LIBRARIES from our PC cross compiler environment and know for certain there will be no incompatibilities.

Binutils

# mkdir binutils-build; cd binutils-build
# PATH=/opt/toolchains/mips-linux/bin:$PATH ../binutils-2.13.2.1/configure \
--prefix=/opt/usr --disable-largefiles --target=mips-linux --host=mips-linux
# PATH=/opt/toolchains/mips-linux/bin:$PATH make
# make install prefix=/opt/tools/usr

GCC

# mkdir gcc-build; cd gcc-build
# CC=mips-linux-gcc ../gcc-3.2.2/configure \
--build=i486-cross-linux-gnu --host=mips-linux --target=mips-linux  \
--prefix=/opt/usr --enable-languages=c
# make
# make install prefix=/opt/tools/usr

Install additional linkage objects from our cross compiler toolchain: crt0.o crt1.o crti.o crtn.o

cp /opt/toolchains/lib/*.o /opt/tools/usr/lib/gcc-lib/mips-linux/3.2.2

The /opt/tools directory where we have been installed the native MIPS binaries must be mounted on the livebox as /opt. So we will end up with /opt/usr/bin/gcc etc…

This is important as the path /opt/usr has been coded into the binaries and the tools will use this search path.

From the host using NFS:

# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
/opt/tools      *(rw,sync,no_subtree_check,no_root_squash)

On the livebox:

mount -t nfs -o nolock 192.168.1.12:/opt/tools /opt

Building new kernel modules

The kernel used in the livebox is 2.4.17 the source code for this kernel can be found in the OPENSOURCE bundle.

So to compile it up we do the following:

# tar jxf OPENSOURCE-5G-2006-07-18/linux-2.4.17-inventel.tar.bz2
# cd linux
# cp Config .config
# make
# make modules

The kernel .config can be adjusted using the configuration screen

# make menuconfig

You can add external storage to your Livebox via NFS

Install the additional kernel modules: nfs-modules.tar.gz

insmod sunrpc
insmod lockd
insmod nfs

To mount an NFS filesystem use the following syntax. Without the -o option NFS will attempt to contact the portmap process, which we don't have, this causes the mount to lock up until it eventually time's out and defaults to 'nolock' anyway.

mount -t nfs -o nolock 192.168.1.12:/opt /mnt/nfsa

Now we have external storage.

# df
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/root                11492     11492         0 100% /
tmpfs                      256        16       240   6% /var
/dev/mtdblock2             640       376       264  59% /mnt/jffs2/jffs2_3
192.168.1.12:/opt      7913216   2820896   4693504  38% /mnt/nfsa

Much for the work to perform this task has been documented. http://www.andyp.uwclub.net/livebox_filesystem_usb_drives.html usb-filesystem.zip

Given the limited amount of storage available in the flash RAM using USB storage is the way to go.

Each of the KERNEL modules needs to be cross compiled and installed into /tmp, once this has been done the following series of commands can be executed to mount an external USB filesystem.

These modules are now already compiled into the kernel USB storage drivers. All that you need to do now to mount a USB drive is issue the necessary insmod and mount commands depending on the USB filesystem type, an example script can be found on your livebox in /etc_ro_fs/mount-usb.

# FOR FAT32/VFAT filesystem
insmod /lib/modules/2.4.17/kernel/fat.o
insmod /lib/modules/2.4.17/kernel/vfat.o
mount -t vfat /dev/sda1 /mnt/usb

To format a PEN drive with a FAT32 (vfat) filesystem you will need to use the command line version of the tool.

c:/> format /FS:FAT32 e:

The ext2 filesystem will use less memory and should be considered if a permanent solution for storage is required

insmod /lib/modules/2.4.17/kernel/ext2.o
mount /dev/sda1 /mnt/usb

It is important to setup the correct sort of ext2 filesystem on any USB data pen that you intend to use with the livebox. Using the ubuntu defaults for mke2fs produces an FS that won't mount on the livebox.

The following worked …

sudo mke2fs -I 128 -r 0  -b 1024 /dev/sdc1

A linux USB serial is not supplied on the inventel box, however this can be compiled up externally and loaded in the kernel to allow RS232 USB devices to be utilized.

We need to perform this operation in two step so that we can find out the product/vendor device codes for the USB/RS232 device being used.

modprobe usb-ohci
insmod usbserial.o

Now we find out the vendor and product code from the output.

# dmesg | tail -4
usbserial.c: USB Serial support registered for Generic
usbserial.c: USB Serial Driver core v1.4
hub.c: USB new device connect on bus1/1, assigned device number 3
usb.c: USB device 3 (vend/prod 0x67b/0x2303) is not claimed by any active driver.
#

Now install the usbserial driver with these codes.

rmmod usbserial
insmod usbserial.o vendor=0x67b product=0x2303

Now if we check the kernel message we see that our device has a driver

# dmesg | tail -4
usbserial.c: USB Serial support registered for Generic
usbserial.c: Generic converter detected
usbserial.c: Generic converter now attached to ttyUSB0 (or usb/tts/0 for devfs)
usbserial.c: USB Serial Driver core v1.4
#

UPDATE: There is a specific driver for this chipset. (PL-2303). So you don't need to do the whole vendor/product thing and this driver is specifically for this USB device.

usb-serial.zip

# insmod usbserial.o
# insmod pl2303.o
# dmesg | tail -7
usb.c: registered new driver serial
usbserial.c: USB Serial support registered for Generic
usbserial.c: USB Serial Driver core v1.4
usbserial.c: USB Serial support registered for PL-2303
usbserial.c: PL-2303 converter detected
usbserial.c: PL-2303 converter now attached to ttyUSB0 (or usb/tts/0 for devfs)
pl2303.c: Prolific PL2303 USB to serial adaptor driver v0.9
#

However to be able to use the device you need to create a character handle.

cd /tmp
mknod ttyUSB0 c 188 0
mknod ttyUSB1 c 188 1    <-- for next serial port etc..

There you go, a shiny USB serial device and a driver handle.

Cross compiling a new BusyBox

A patch needs to be applied to the 1.11.2 busybox source code so that it will compile with the MIPS toolchain. The source is written for GCC 4 which uses syntax that GCC 3 toolchain cannot understand.

Obtain the source code and patch.

# tar jxf busybox-1.11.2.tar.bz2
# cd busybox-1.11.2
# zcat busybox-1.11.2-mips.patch.gz | patch -p1

If you wish to change anything about the configuration

# make menuconfig
Make sure that /opt/toolchains/uclibc/bin is in your PATH before compiling otherwise the mips cross compiling toolchain will not be found.

Building is as simply as:

# make

I use the device /dev/sdb for the USB stick this may vary depending upon what other drives you have connected to your system. Be careful you don't format your HDD

Now that we can access the USB pendrive as a external drive and the compilation of a new busybox with the mkswap, swapon and swapoff commands….

Create a USB pen drive with 2 partitions, 1st is 32Mb of swap, 2nd is EXT2 filesystem. We are using a 128Mb pendrive so your numbers may vary. If using UBUNTU see USB Filesystem support.

# fdisk /dev/sdb
Command (m for help): n
   e extended
   p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-411, default 1): 1
Last cylinder or +size or +sizeM or +sizeK (1-411, default 411): +32M

Command (m for help): t
Hex code (type L to list codes): 82
Change system type of partition 1 to 82 (Linux swap / Solaris)
Command (m for help): n
   e extended
   p primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (102-411, default 102): 102
Last cylinder or +size or +sizeM or +sizeK (102-411, default 411): 
Using default value 411
Command (m for help): p

Disk /dev/sdb: 132 MB, 132120576 bytes
33 heads, 19 sectors/track, 411 cylinders
Units = cylinders of 627 * 512 = 321024 bytes
Disk identifier: 0xc35ef8b8

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1         101       31654   82  Linux swap / Solaris
/dev/sdb2             102         411       97185   83  Linux

Command (m for help): q

# mke2fs /dev/sdb2
mke2fs 1.40.8 (13-Mar-2008)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
24384 inodes, 97184 blocks
4859 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
12 block groups
8192 blocks per group, 8192 fragments per group
2032 inodes per group
Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729

Writing inode tables: done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 24 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
#

Now insert the PEN drive into the USB box and load all the appropriate drivers to get this device recognized. usb-fs-ext.tar

modprobe usb-ohci
insmod scsi_mod.o
insmod sd_mod.o
insmod usb-storage.o
insmod ext2.o

mount /dev/sda2 /opt

Once the device is active

# mkswap /dev/sda1
# swapon /dev/sda1
# free
              total         used         free       shared      buffers
  Mem:        13872         8584         5288            0          576
 Swap:        32696          524        32172
Total:        46568         9108        37460
#

32Mb of shiny swap space.

/etc/rc1.d/S99USB with this additional file you can bring up the SWAP and your additional development tools every time the livebox is rebooted.

# Mount USB pen and add SWAP
insmod scsi_mod.o
insmod sd_mod.o
insmod usb-storage.o
insmod ext2.o
swapon /dev/sda1
mount /dev/sda2 /opt
PATH=$PATH:/opt/usr/bin
export PATH

Sample program cross compiles

As the BOA webserver does not support basic authentication an alternative needs to be found if this feature is required. According to this comparison chart this server will do the trick.

wget http://www.acme.com/software/thttpd/thttpd-2.25b.tar.gz
tar zxf thttpd-2.25b.tar.gz
cd thttpd-2.25b
CC=/opt/toolchain/bin/mips-uclibc-gcc LDFLAGS=-static ./configure --prefix=$HOME/mips/thttpd
make
make -i install

Now strip the binaries.

cd $HOME/mips/thttpd/sbin
mips-linux-strip htpasswd makeweb thttpd

Basic Authentication works well. Simply prepare the usernames/password file with the htpasswd utiity and place this '.htpasswd' file in the appropriate directory where pages that will be subject to authentication reside.

LUA ( http://www.lua.org/ ) is a small portable scripting language. Its footprint makes its ideal for low memory embedded devices where additional scripting capabilities need to be implemented.

wget http://www.lua.org/ftp/lua-5.1.4.tar.gz
tar zxf lua-5.1.4.tar.gz
cd lua-5.1.4
PATH=/opt/toolchain/mips-linux/bin:$PATH make posix MYLDFLAGS=-static
I'm not sure if the MYLDFLAGS=-static directive is strictly necessary. If not it can be removed and that binary can be linked dynamically making it smaller

With luac(1) your able to compile up your source code into a binary that can be executed and shipped into production.

Adjust the default default path
lua_conf.h

#define LUA_ROOT        "/mnt/usb/usr/"
# PATH=/opt/toolchain/mips-linux/bin:$PATH make generic MYLDFLAGS=-static
LDFLAGS=-static CC=mips-uclibc-gcc  ./configure --host=mips --enable-bash-extensions
make

An SMTP client application.

LDFLAGS=-static CC=mips-uclibc-gcc ./configure --host mips --prefix=/usr
make
mips-uclibc-strip src/msmtp