IMPORTANT EDIT: There is now an Alpha release of Froyo hacked onto the Eken M001. This isn't the same as full support, but it's a step in the right direction!

Over the past couple of evenings I've been looking into porting Android 2.x (eclair or froyo) to the Eken M001. These are my notes from unsuccessful binary-only reverse engineering.

Short version

Although Android 2.1, and possibly 2.2, will run against Eken's supplied 2.6.29 kernel, Eken have patched several of the 'base' userspace binaries against the proprietary Wondermedia SDK. Without accessing the SDK, or reverse engineering the SDK's workings, it may not be possible to port Android 2.x to the Eken.

I worked this out trying to install the iPhone Android 2.2 port by munging it into the existing Eken binary firmware. I initially had a lot of success, because the link I followed was completely wrong, and I had the Android 1.6 iPhone build. After I got that booting to the home screen, someone on the slatedroid forums let me know it was the wrong version. Oops! I then found a genuine binary release of Froyo for iPhone and tried the same tricks, without success.

In this post I'll explain what I learned. I hope it's of use to someone.

Differences in firmware format

One of the first things that you'll notice is that Eken firmware looks different to "normal" Android disk images. Instead of a group of disk images, the main Android userspace data is contained in two tarballs - android_fs.tgz and data.tgz. android_fs.tgz contains the parts of the filesystem would normally be mounted from ramdisk.img and system.img, data.tgz contains the parts from userdata.img.

A u-boot script (scriptcmd) in the firmware package performs an initial flash of the bootloader and then directs the Eken to boot from a small ramdisk image on the SD card. Ramdisk init then runs update.sh to reflash the firmware onto the internal flash.

Other than the different firmware image layout, the firmware layout of a running Eken is similar to any other Android system.

Using the Eken kernel

There are no kernel sources, so the Eken-provided 2.6.29 kernel is the only one we have. Slatedroid user bushing has started working on an alternative kernel, here, but it is very early days (doesn't boot, let alone support any of the Eken's WM8505 hardware.)

I don't this is the big problem for Android 2.x, though. 2.1 officially supports kernel 2.6.29, and it looks like the 2.2 userspace components might even run against the 2.6.29 kernel without any serious problems (although probably with reduced performance.)

Getting info

The serial port on the board gives you a linux kernel console, and then a root shell with busybox. Running 'logcat' gives you the Android log as it runs. Run 'logcat -d' if you don't want to lose your root shell forever. Strace is also available.

Munging the firmwares

My dodgy technique for munging the firmwares together was, roughly:

  • Copy the iPhone system.img contents over system/ in android_fs
  • Copy init and init.rc from iPhone ramdisk.img to the root of android_fs
  • Merge differences between the new init.rc and the old Eken one.
  • Flash & Boot!

Dodgy framebuffer driver

This method eventually leaves you with a flashing LCD display, showing 4 distorted copies of the screen you're expecting. That's what I got with 1.6 & 2.2, and I think that's where Slatedroid modder ECOTOX got to as well.

If the Eken kernel provided a properly supported framebuffer device, this wouldn't happen. The framebuffer device looks correct (although unaccelerated):

/ # fbset -s -fb /dev/graphics/fb0

mode "800x480-0"
# D: 0.033 MHz, H: 0.035 kHz, V: 0.066 Hz
geometry 800 480 800 480 32
timings 30000000 40 24 32 11 96 2
accel false
rgba 8/16,8/8,8/0,0/0
endmode
</code>

... but that's not enough. There's some userspace magic required to make the display work properly. Normally this would be implemented in the driver itself, and standard ioctl calls would make the changes. In this case, Android's /system/lib/libui.so has been patched and now links against libwmtapi.so, a proprietary Wondermedia WM8505 SDK library:

:lib gus$ strings libui.so | grep wmt wmt_vpp_init wmt_vpp_set_direct_path wmt_vpp_exit wmt_mb_init wmt_mb_alloc wmt_mb_user2phys libwmtapi.so wmt_setsyspara wmt_getsyspara wmt_getsocinfo wmt_vpp_set_direct_path

... I have no idea what it's doing, but when I copied the patched libui.so (and dependencies) onto my Android 1.6 iPhone system, the display immediately started working.

On Android 2.2, copying the library causes system_server to segfault because the library is no longer ABI compatible. There have been big changes, just look at the 1.6 ui headers compared to the 2.1 ui headers. So there's no way the patched libui will work without the source patches being merged and recompiled, at the minimum.

That's not all either, there are actually quite a few Android libraries linked against WMT libraries, presumably with other patches:
$ grep libwmt * Binary file libcamera.so matches Binary file libmediaplayerservice.so matches Binary file libopencore_player.so matches Binary file libui.so matches

Where to from here?

Speaking for myself, I'm done, unless Eken release their Android & kernel sources. There's no sense in working to improve a product when the company itself is blatantly abusing OSS and refusing to honour its obligations.

On the other hand, even if an Eken source release left out the Wondermedia SDK, it would be a great start.

In the absense of the source, it seems there would be two options for the intrepid coder. The first would be to reverse-engineer the WM8505 hardware and write an OSS version of the platform drivers. This would be a massive job, although there is a datasheet we don't even have JTAG available for debugging.

Alternatively, some judicious use of objdump would probably show what calls are being made to libwmt. With that knowledge, it is possible to reverse engineer function declarations and create patches for the relevant sources in Android 1.6, then port those source patches to Android 2.x. (I posted steps that I would try to follow, here.)

Thoughts on “Notes on porting Android 2.x to Eken M001