Print
PhoneME, a JavaVM for the Fonera FON Router
OpenWRT is a Linux distribution optimized especially for embedded devices and also builds the starting point for many popular RouterOS distributions, like DD-WRT, FreeWRT, or X-Wrt. Wikipedia has details on all those project, a good starting point would be here.
Since OpenWrt is optimized for embedded systems, it doesn't come as a surprise that features like a read-only Flash memory filesystem (SquashFS) and a read/write Flash memory filesystem (JFFS2), or BusyBox, which combines many common UNIX utilities into a single executable, are readily available to be configured into a custom image. OpenWrt also comes with a lightweight package management system (IPKG or more recently OPKG), meaning that features that have not already been built into the kernel, can be added later, at runtime.
A Java-Runtime Environment would be one of those features that are not built-in but would be nice to have for some of us. So let's take a look at how a JavaVM could be build, packaged, and deployed into an embedded system that has the OpenWrt firmware.
Just like JavaSE gets build and packaged for a particular host OS, a JavaVM for an embedded system needs to be build with a particular hardware platform in mind. A JavaVM calls directly into the Linux kernel, which means, not only do we need all the kernel related resources when building the JavaVM, we also need to choose a hardware platform.
The OpenWrt sources are easily available at https://svn.openwrt.org/openwrt/trunk/ and for the hardware platform, I have picked the Fonera FON, a relatively simple and inexpensive router, built on the AR531x/231x Atheros WiSoC (Wireless System-on-a-Chip), with an integrated 32-bit MIPS R4000-class processor running at 183.5 MHz. It features 8 MBytes of Flash ROM and 16 MBytes of RAM. Check here fore more details.
With the hardware platform selected and the OpenWrt source downloaded, we can start building. To add a little excitement, I decide to try the build process on a Mac, using OS X 10.5.

Fink or MacPorts

The OpenWrt build process requires that several GNU tools are installed on machine that will eventually perform the build process and while some of these tools seem to be available on OS X, they aren't parameter compatible with the GNU version, i.e. either Fink or MacPorts is needed to get the GNU tools working.

To find out what tools are needed, open a Terminal, cd into the OpenWrt trunk folder and run make help.
After installing binutils, patch, bzip2, flex, bison, gettext, ... with the help of Fink Commander, we're ready to configure the build process by running make menuconfig

The result may come as a surprise, but the kernel configuration is done with the help of a character based UI.
The most important thing to get right here is to pick the correct Target System. For the Fonera FON, this would be Atheros 231x/5312 [2.6]. Moreover, to be able to build a JavaVM later, building the OpenWrt SDK needs to be enable here.
After a subsequent default build (entering make without any arguments) has been successfully completed, the sdk can be found here:
Kamikaze/trunk/build_dir/mips/OpenWrt-SDK-atheros-for-Darwin-i386

(If the build process fails, running make V=99 is revealing what went wrong. In my case it was a missing library. After installing it - again with the help of Fink Commander - the error message went away.)

Kernel configuration with the help of a character based UI

Java

A good starting point for Java in embedded world can be found here and one actually does have a choice, when is comes to Java Virtual Machines for OpenWrt Embedded Linux.
  • JamVM
    JamVM is a new Java Virtual Machine which conforms to the JVM specification version 2 (blue book). In comparison to most other VM's, it is extremely small, but requires the building of the GNU Classpath. Clearly the full version of Classpath isn't going to fit onto a small router, contains some native code and need to be cross-compiled.
  • SableVM and SableVM Mini
    SableVM is a Java Bytecode Interpreter implementing Java virtual machine (JVM) specification, second edition. Its goals are to be reasonably small, fast, and efficient, as well as providing a well-designed and robust platform.
  • PhoneME
    The PhoneME project was created after opensourcing Sun implementation of Java ME. It comes in two versions: PhoneME feature software (CLDC), for mobile phones and PhoneME advanced software (CDC), for higherend devices. Reference implementations are available for x86, ARM and MIPS.
JamVM and SableVM both require the building of the GNU Classpath. Clearly the full version of Classpath isn't going to fit onto a small router, contains some native code, and need to be cross-compiled. Taking the many posts in the OpenWrt related forums seriously, porting GNU Classpath to MIPS seemed to be a very daunting project and even if I'd be successfull, the full version of this project may be to be too to be deployed on the Fonera and still leave some room for an Java application. Considering Bug Labs performance benchmarks for Java on embedded Linux, the PhoneME JavaVM needs to be the 1st choice for a resonably small and fast JavaVM for the embedded target platform, like the Fonera FON. BugLabs.com, JavaVM Benchmark

PhoneME

Next step is to checkout the phoneme sources form: https://phoneme.dev.java.net/svn/phoneme/components (you may have to create an user account at the java.net site before being able to access the source repository). We need cdc's trunk and tools' trunk on the same level and then edit the cdc/trunk/build/linux-mips-openwrt/GNUmakefile, setting the CVM_TARGET_TOOLS_PREFIX to point to the toolchain location in the OpenWrt-SDK, like so:

CVM_TARGET_TOOLS_PREFIX ?= /Users/wolf/Work/Embedded/Kamikaze/trunk/build_dir/mips/OpenWrt-SDK-atheros-for-Darwin-i386/staging_dir/toolchain-mips_gcc4.1.2/bin/mips-linux-uclibc-

Running make in the linux-mips-openwrt folder will produce theses files:
  • linux-mips-openwrt/btclasses.zip
  • linux-mips-openwrt/testclasses.zip
  • linux-mips-openwrt/democlasses.jar
  • linux-mips-openwrt/bin/cvm
  • linux-mips-openwrt/lib/cdc.jar (or linux-mips-openwrt/lib/foundation.jar)

The J2ME_CLASSLIB argument provided to Make, defines what class library will eventually be created:
  • cdc - (default) will create a limited class library (cdc.jar 884 KBytes) that is meant for testing purposes only.
  • foundation - creates the full Foundation Profile class library (foundation.jar 1.475 KBytes).
Just like you would expect,compared to the Foundation Profile, the cdc.jar is missing some of the networking and security related classes.

Creating the ipkg Package

These files now have to be distributed into a manually created folder that needs to look exactly like this: Start by creating a cdc folder in the OpenWrt-SDK package location like here:

/Users/wolf/Work/Embedded/Kamikaze/trunk/build_dir/mips/OpenWrt-SDK-atheros-for-Darwin-i386/package/cdc

Insert this makefile into the cdc folder and also create a files folder.



Eventually, the content layout needs to look like this:
Content Layout
Running make in the SDK folder here:
/Users/wolf/Work/Embedded/Kamikaze/trunk/build_dir/mips/OpenWrt-SDK-atheros-for-Darwin-i386
creates the deployable package, containing the JavaVM and a set of test classes, here:
/Users/wolf/Work/Embedded/Kamikaze/trunk/build_dir/mips/OpenWrt-SDK-atheros-for-Darwin-i386/bin/packages/mips/pmea-wp_1_1-2_mips.ipk

Like declared in the makefile that was responsible for creating the ipk package, the only non-standard OpenWrt package required by PhoneME Advanced is libpthread. Running OpenWrt's make menuconfig again, now shows Java in the Languages menu and if Java gets selected, libpthread (to be found in Base System) is automatically added.
make menuconfig

Deployment and Test

With the package built, all what's left to do is deploying it and running the test suite. Deploying the ipkg file is as easy is putting it into the target's tmp folder (running sftp on the FON and Fugu on the development host, makes this easy and fast).
After ssh- into the FON, running ipkg install /tmp/pmea-wp_1_1-2_mips.ipk or opkg install /tmp/pmea-wp_1_1-2_mips.ipk will install the JavaVM as well as the test classes.
Now executing the test is as simple as /usr/java/bin/cvm -cp /usr/java/testclasses.zip Test

PhoneME Java VM on the LaFonera FON Router


QR code, to put this blog on your mobile