Updated 2014-12-29 - I've moved the patch files to github and provided updated build instructions there. Other than those build instruction updates most of this post is still valid.
Inferno is a small operating system that can be built to run on Host operating systems as a user process or natively on bare hardware. Inferno uses ideas from the Plan 9 operating system and has some interesting features. These include the Plan 9 system of representing resources as files using the 9P protocol.
Last year source and binaries were released to run the hosted version of Inferno on an Android phone. A YouTube video of it running is here. The binaries and installation are quite tightly tied to a specific android revision. It involves replacing the init.rc file on the phone to enable dual booting of Android or Inferno. Replacing this file in versions of Android different to that which the replacement was based on won't work. For example the version used is from a Gingerbread device and won't work on an Ice Cream Sandwich device. I set about building from source so I could run Inferno on my Nexus S alongside Boot To Gecko. I used B2G as the base instead of Android as B2G is easier to build and it's interesting to compare the two operating system approaches on the phone.
Warning: These steps flash data to your phone and may result in having to re-flash the original OS. Make backups first! B2G and Inferno are experimental operating systems running on the phone. They may not make for a great Phone experience at this early stage in their development.
This first step is to build the B2G system. This is pretty well covered on the Mozilla Developer Network. Basic steps to build for the Nexus S (with the phone connected to the PC):
$ git clone git://github.com/mozilla-b2g/B2G
$ cd B2G
$ ./config.sh nexus-s
$ ./build.sh
$ export B2G_ROOT=`pwd`
$ cd ..
If you want to flash B2G to your phone you can run the following command with the phone connected (this will delete everything on your phone and is not needed if you want to just try Inferno on your rooted Android phone):
$ cd B2G
$ ./flash.sh && ./flash.sh gaia
$ cd ..
We'll use the B2G tools to build Inferno and 'adb' to copy it to the device and start it.
The most recent port of Inferno that runs on Android is available in a mercurial repository hosted on bitbucket. This should be cloned and the PATH modified to use the Linux version of the Inferno build tools which we also need to build. Unfortunately the repository modifications to get Android builds working has broken Linux builds slightly so the first build attempt will fail and then we manually build the features we need. The location of the build needs to be in /data/inferno
to match the directory it will be in on the device.
To build the Linux tools after cloning, edit the mkconfig
file to have the following settings (change the existing ones set to Android/ARM):
SYSHOST=Linux
OBJTYPE=386
Now we build:
$ cd /data
$ hg clone https://bitbucket.org/floren/inferno
$ cd inferno
$ vim mkconfig # Change SYSHOST and OBJTYPE as above
$ ./makemk.sh
$ export PATH=$PATH:/data/inferno/Linux/386/bin
$ mk nuke
$ mk install # This will error out, ignore the error and continue
$ cd lib9 && mk install && cd ..
$ cd libmath && mk install && cd ..
$ cd utils/iyacc && mk install && cd ../..
$ cd limbo && mk install && cd ..
Now that the Linux tools are built we can build the Android version. This requires an ARM C compiler compatible with Android. I use the one built during the B2G build process which is accessed via a wrapper shell script called agcc. This agcc
script is based on using the Android SDK. A patch to have this work with the B2G toolset is available here. This assumes B2G's gcc
is in your PATH. The example below sets this and you'll need to change it to where you cloned B2G. You should also adjust the instructions to put agcc
somewhere in your path. I use a bin
subdirectory off my home directory.
I was unable to get the prebuilt audio binaries working that are provided with the Inferno for Android port. There were also some changes I needed to do to get it working on ICS. Patches to disable the audio, compile on ICS, and get events working are in inferno.patch which is applied in the commands below.
Edit the mkconfig
file to have the following settings (change the existing ones from Linux/386 that we set earlier):
SYSHOST=Android
OBJTYPE=arm
Install agc
modified to use B2G:
$ cd ~/bin
$ curl http://plausible.org/andy/agcc >agcc
$ chmod +x agcc
$ curl http://www.bluishcoder.co.nz/inferno/agcc.patch | patch -p0
$ export PATH=$PATH:$B2G_ROOT/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin
There is an issue with building using the B2G toolchain regarding stdlib.h
. To prevent a compile error around the use of wchar_t
I modified $B2G_ROOT/bionic/libc/include/stdlib.h
line 167 to change #if 1
to #ifndef INFERNO
to prevent the wchar_t
usage of mblen
and friends from being used.
Build Android Inferno:
$ cd /data/inferno
$ vim mkconfig # Make SYSHOST/OBJTYPE changes for Android
$ curl http://www.bluishcoder.co.nz/inferno/inferno.patch | patch -p1
$ vim $B2G_ROOT/bionic/libc/include/stdlib.h # Change to line 167 described above
$ mk nuke
$ mk install
Inferno for the device is now built. I use a B2G device to test but it will run on a rooted Android phone as well. To install run the parallel-push.sh
script with the device connected. This copies everything to /data/inferno
on the phone:
$ ./parallel-push.sh
Booting the phone will still boot into the main OS (B2G or Android). Inferno can be manually run using adb
:
$ adb shell
# stop b2g # 'stop zygote' on Android
# cd /data/inferno/Android/arm/bin
# ./emu-g
;; wm/wm &
From the running emu-g
shell you can run any Inferno commands. The device interface to access phone functions is documented in README.android. For example, to turn the phone on and enable GSM data on New Zealand's Vodafone network:
;; echo on > /phone/ctl
;; echo net on gsm www.vodafone.net.nz '' '' > /phone/ctl
Photos of the main phone screen and tetris running on the phone are below:
To switch from Inferno back to the main OS, kill the running emu-g
process and start b2g
or zygote
:
# kill 1234 # where 1234 = process id of emu-g
# start b2g # 'start zygote' for Android
There are a bunch of issues with the existing port unfortunately. The 'hardware' capacitive keys don't work. I work around this by tweaking /etc/buttonserver.cfg
to use the down volume key to bring up the keyboard so I can at least type. The touch screen seems to be out by a few pixels. Sound doesn't work due to disabling it in my patch applied above to get things compiling. I did test receiving and making a call though using direct device access and that worked.
Inferno is an interesting operating system and with its distributed features and Limbo programming language there might be some different approaches that could be taken to integrate phones with desktop devices to share computing resources. The existing port has some bitrot and the steps to build, as can be seen above, are quite manual but it can be streamlined. Dual booting B2G (or Android) with Inferno shouldn't be too difficult. It'd be nice to see continued work on Inferno for Android to experiment with distributed applications on mobile devices.