Originally Published: Wednesday, 6 June 2001 Author: Mike Baker
Published to: develop_articles/Development Articles Page: 1/1 - [Std View]

OSDN Handheld Months: Installing Linux on a Casio E105

Linux.com Senior Developer Mike Baker takes us step-by-step through installing a Linux system on a MIPS-based Windows CE device. If pre-built distributions are not for you, then this article is.

It's no big secret that the iPaq can run Linux, for a while it was all we were hearing in the news, but what is a surprise to many people is the fact that almost any Windows CE device can run Linux to some extent. While mostly still in the infant stages, various communities such as Handhelds.org are proving Linux on PDAs is a technology to keep an eye on.

The Linux-VR project is an attempt to load Linux on devices using the Vr41xx MIPS processors common in various Windows CE devices such as the Vr4121 found in the Casio E105. Recent changes in the Windows API have made booting the Linux kernel impossible (for the time being) on current CE devices. As a result, much of the recent Linux-VR development is aimed at creating a kernel for the Agenda V3 handheld due out next month. Still, if you want to get Linux on your Casio or MIPS-based PDA, for whatever reason, we’ll show you what you can do.

Getting Started

The first thing you'll need to find out is what type of processor your handheld uses and which version of Windows CE it runs. Simply check the system control panel for this information:

start -> controlpanel -> system

The system control panel should look like the image below. This screenshot was taken from my Casio E105. As you can see the system is Windows CE 2.11 running on a MIPS processor. Although the installation procedure outlined in this article is based on installing on the E105 it should still apply to any CE device using a MIPS processor. (If you're not using a MIPS processor check the links at the end of the article for more information.)

system screenshot

In order for you to be able to run Linux on your handheld you must be running a version of Windows CE less than 3.0. Curiously, the changes in Windows CE 3.0 have rendered the boot-loader unusable and many of the API calls used by CyaCE have been removed. This may work to your advantage since many of the older WinCE devices are becoming obsolete in the Windows world, making the hardware an even more attractive candidate for Linux. Even though the new devices have almost the exactly the same hardware, without the ability to update to 2.11 they're not of much use.

Pre-made Distributions

Before we begin building our own lets take a quick look at your choices of pre-built distribution for your handheld.

The QT Palmtop Environment

A good example of a system built around a ramdisk is TrollTech's QT Palmtop Environment. It's also the easiest system to install since it doesn't require any repartitioning of the compact flash. The distribution consists of a three-megabyte kernel and the CyaCE boot-loader. Installation is as simple as copying two files over to the compact flash and running CyaCE.

Upon boot-up QT will automatically go into a calibration mode and then take you to the QT desktop. If the interface looks slightly familiar it's because QT is the same set of widgets used by KDE. The handheld runs an embedded version that draws directly to the framebuffer to avoid the potential overhead X brings. I've been assured that most QT applications can simply be recompiled and run on the handheld with only minor changes to the interface to reflect the small screen size.

QT Screenshot

Three megabytes? How is that possible? Simple -- there isn't much in the distribution. In total there's maybe half a dozen applications, for the most part they're nothing more than "hello worlds"; an application written to prove the system works. For example, the text editor is nothing more than a large text entry box with no easy means of saving files or loading them, for that matter. It takes after the memo application found in the PalmOS and uses the first line of text as an identifier for later retrieval. In short, don't expect to be able to customize startup scripts with this application.

Pocket Linux

Pocket Linux is another pre-made distribution for the handheld, probably more widely known than QT's Palmtop environment since it has been featured in places such as the Embedded Linux Journal.

Pocket Linux is an attempt to recreate the same PIM-style interface you've seen on PalmOS devices only using Linux. In order to be cross-platform and run on as many handheld systems as possible, the Pocket Linux interface is written almost entirely in Java. While the use of Java does make it easier to program for, it also makes it considerably slower when compared with other distributions. Even just booting the interface on my Casio took about a minute, during such time I was subjected to a nice blue screen; when Kaffe initializes the framebuffer you get a blue screen until the interface loads. After the interface loads the response times are decent. I won't go so far as calling them fast however, switching applications still has a considerable delay.

QT Screenshot

Although the use of Java certainly does make the system more extensible, I can't help but wonder why it was done. Sure, Windows CE runs on many different platforms and that requires users to search for versions of applications that will run on their system and some applications aren't even available on all platforms -- but this is Linux. In other words, if you want to run an application on your system you just compile it yourself.

Pocket Linux does use Linux internally and provides access via a serial PPP interface; this means that you can use Linux on the road provided you have a laptop with a serial cable with you.

Rolling your Own

After trying out the pre-made distributions I decided to try my own. What I'd seen so far basically hid the fact that it was Linux, in my opinion, the whole point. I wanted a system that ran X and used standard applications, not just a PIM. It seems this is exactly what the folks from the Familiar distribution had in mind.

So why don't I just run Familiar? You'll notice I didn't review the Familiar distribution, and there's a simple reason for that -- the Familiar distribution is meant to be loaded into the flash Rom of Compaq's iPaq which uses the StrongARM processor. Unfortunately my cheap editors weren't about to buy me an iPaq, and none of the applications from the Familiar distribution will work without recompiling for the MIPS processor: back to putting together my own distribution!

The Basics: Storage

Unlike the iPaq models most WindowsCE devices don't have a flash Rom so the only way to boot Linux is through the use of a compact flash card. You'll need to think carefully about how large a compact flash card you'll need. Remember, the compact flash card will contain the kernel, the bootloader and the entire root filesystem and acts essentially like a hard-drive. In fact, as far as Linux is concerned it's just another IDE hard-drive. While it's entirely possible to build a system in 8Mb it's also all too tempting to fill up a 64Mb card and then some. With the advent of cheap gigabyte drives commonplace in the desktop world most of us don't give much thought to how much space we're actually using. Chances are your /usr/bin is larger than the memory and storage space of the handheld combined.

So, how much space do you need? The answer is really "it depends." If you want an X11 server, a small suite of command-line utilities and a few X applications you're easily looking at 64Mb. If you want a stripped down PDA approach with the standard set of PIM (Personal Information Manager) utilities then you can do that in as little as 5Mb, (just look at QT's Palmtop environment). Personally though, I'd advise you to buy the largest card you can afford since the prices are pretty low right now. This article was written using a 64Mb card.

There are two ways you can use the card. First of all you can have the file-system as part of the kernel in a ramdisk configuration. This means when the system boots it loads both the kernel and the file-system into memory. You'll have a longer boot-up time and less free memory with this configuration, but the benefit is that the file-system will be reset upon each boot-up so you will not need to worry about maintaining it. However, you will need to rebuild your kernel each time you wish to change the file-system.

The other choice is to repartition the compact flash card into at least two partitions: a boot partition and a root partition. The boot partition would be a 5Mb DOS file-system containing the CyaCE boot-loader, config and the kernel then the root file-system on the remainder of the card. You can partition for swap space, but it's unlikely to be of much use due to the slow writing speeds of compact flash.

Partitioning the Compact Flash

Partitioning the compact flash card is easy enough, if you use a compact flash to PCMCIA adapter you can just stick the card into any laptop running Linux and it'll show up as a hard-drive. If you don't have access to a laptop running Linux you can purchase either a PCMCIA adapter card or a compact flash USB adapter. If you decide to use a USB adapter you may find this article of some use. It may even be possible to repartition a compact flash card using Windows, however you'll need to be able to mount the ext2 partition so it won't help much.

Partitioning is done with nothing more than Linux's fdisk. It's assumed that the compact flash is /dev/hde.

$ fdisk /dev/hde

Command (m for help): p

Disk /dev/hde: 4 heads, 32 sectors, 978 cylinders
Units = cylinders of 128 * 512 bytes

Device Boot Start End Blocks Id System
/dev/hde1 * 1 978 62576 6 FAT16

Command (m for help): d
Partition number (1-4): 1

Command (m for help): n
Command action
e extended
p primary partition (1-4)
Partition number (1-4): 1
First cylinder (1-978, default 1): <enter>
Last cylinder or +size or +sizeM or +sizeK (1-978, default 978): +5M

Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): 6
Changed system type of partition 1 to 6 (FAT16)

Command (m for help): n
Command action
e extended
p primary partition (1-4)
Partition number (1-4): 2
First cylinder (82-978, default 82): <enter>
Using default value 82
Last cylinder or +size or +sizeM or +sizeK (82-978, default 978): <enter>
Using default value 978

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

$ mkdosfs /dev/hde1
mkdosfs 2.8 (28 Feb 2001)
$ mke2fs /dev/hde2
mke2fs 1.19, 13-Jul-2000 for EXT2 FS 0.5b, 95/08/09
warning: 63 blocks unused.

Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
14392 inodes, 57345 blocks
2870 blocks (5.00%) reserved for the super user
First data block=1
7 block groups
8192 blocks per group, 8192 fragments per group
2056 inodes per group
Superblock backups stored on blocks:

8193, 24577, 40961

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

Building the Kernel

The first thing you'll need is a cross compiler and its supporting applications and libraries. Some distributions already contain a complete mipsel toolchain although my experience has been that these are generally not up to date with the latest patches, so instead I download from:


The minimal set of RPMs you'll need for compiling the kernel is listed below.  You may want to grab the C++ RPMs too since they'll be used later to compile Blackbox.


binutils (ar,as,ld,nm,ranlib,strip) compiled to support little endian MIPS (mipsel)


mipsel version of egcs (compiler)


mipsel version glibc (GNU C library)

Now for the kernel sources, you'll find these in Linux-vr's cvs.

$ cvs -d:pserver:anonymous@cvs.linux-vr.sourceforge.net:/cvsroot/linux-vr login
(Logging in to anonymous@cvs.linux-vr.sourceforge.net)
CVS password: <enter>
$ cvs -d:pserver:anonymous@cvs.linux-vr.sourceforge.net:/cvsroot/linux-vr co linux
$ cd linux

At this point we need to make a minor change so that the compact flash is detected. Edit arch/mips/vr41xx/ide-vr41xx.c and find the function vr41xx_ide_default_io_base(); and change case 2 to return 0xc170 like shown here:

static ide_ioreg_t vr41xx_ide_default_io_base(int index) {

switch (index) {

case 0: return 0x1f0;

case 1: return 0x170;

case 2: return 0xc170;

case 3: return 0;

case 4: return 0;

case 5: return 0;


return 0;



Next, copy the config shown below to .config and run make menuconfig. You may need to change options If you're not using the same device.




Start the kernel compile by running make. While you're waiting visit ftp://ftp.ltc.com/pub/linux/mips/boot and grab the CyaCE boot-loader. In order to get the system to automatically run the boot-loader upon card insertion it needs to be named AutoRun.exe and placed in CE/R4100/on the card. You'll need to create a configuration file to go with it: The CyaCE config is named cyacecfg.txt and is also placed in the CE/R4100/ directory. The cyacecfg.txt is nothing more than the following:

append=root=/dev/hde2 console=ttyS0

By now the kernel compilation should be finished and you should have a vmlinux file in your kernel directory. Copy the vmlinux file to CE/R4100/on the compact flash. At this point you can verify that the kernel is compiled correctly and actually boots, you can accomplish this by hooking up a serial cable and running minicom. Set minicom to 9600 baud and insert the compact flash card. You should get the output shown below.

(If your CE device has an error message on screen with "unable to allocate heap" you'll need to perform a memory reset (hold down the power button and hit reset) and try inserting the card again.)

CyaCE ELF Program Loader
Detected 32MB of memory. Will use 32MB of it.
Loading R4000 MMU routines.
CPU revision is: 00000c60
Primary instruction cache 16kb, linesize 16 bytes.
Primary data cache 8kb, linesize 16 bytes.
Linux version 2.4.0-test9 (root@paranoia)
(gcc version egcs-2.90.29 980515 (egcs-1.0.3 release))
#8 Mon Mar 19 14:10:28 EST 2001
On node 0 totalpages: 8192
zone(0): 8192 pages.
zone(1): 0 pages.
zone(2): 0 pages.
Kernel command line: root=/dev/hde2 init=/bin/sh console=ttyS0
Console: colour dummy device 80x25
Calibrating delay loop... 87.24 BogoMIPS
Memory: 30372k/32768k available (1534k kernel code, 2396k reserved, 78k data, 56k init)
Dentry-cache hash table entries: 4096 (order: 3, 32768 bytes)
Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes)
Page-cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 2048 (order: 2, 16384 bytes)
Checking for 'wait' instruction...  unavailable.
POSIX conformance testing by UNIFIX
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 2048 bind 2048)
Starting kswapd v1.8
Console: switching to colour frame buffer device 60x53
fb0: HPC Simple frame buffer device, using 160K of video memory
No keyboard driver installed
VR41xx touch panel initialized, using IRQ 13.
loop: enabling 8 loop devices
Uniform Multi-Platform E-IDE driver Revision: 6.31
ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
hde: Hitachi CVM1.1.1, ATA DISK drive
ide2 at 0xc170-0xc177,0xc376 on irq 40
hde: 125184 sectors (64 MB) w/1KiB Cache, CHS=978/4/32
Partition check:
hde: hde1 hde2
VR41xx Serial driver version 0.4 (22-Oct-2000)
ttyS00 at 0xac000000 (irq = 17) is a 16550A
ttyS01 at 0xac000000 (irq = 17) is a 16550A
VR41xx Real Time Clock Driver v1.0
PPP generic driver version 2.4.1
PPP Deflate Compression module registered
PPP BSD Compression module registered
DMA sound driver installed, using 64 buffers of 2k.
IP-Config: No network devices available.
kmem_create: Forcing size word alignment - nfs_fh
hde: hde1 hde2
hde: hde1 hde2
VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 56k freed
Warning: unable to open an initial console.
Kernel panic: No init found.  Try passing init= option to kernel.

At this point there's nothing on the ext2 partition for the kernel to run so you'll get a kernel panic message complaining about init. Don’t worry about it. The reason for booting the kernel here is simply to verify that it loads properly. If, for some reason your kernel doesn't get this far you might try recompiling it with a different binutils.


Now that we have a booting kernel the next thing to do is commence with loading the rest of the system. The first thing we need is a shell environment to work from and this is where busybox comes in. Busybox is a small set of the most common Linux/Unix tools, perfect for this sort of application.

After grabbing the source from the above URL make any changes to Config.h that you need (you can disable many of the applications to save space). Compiling and installing Busybox is simply a matter of the following:

$ make CROSS=mipsel-linux-
$ mount /dev/hde2 /mnt
(/dev/hde2 is assumed to be the ext2 partition of the compact flash)

$ ./install.sh /mnt
$ mkdir /mnt/etc
$ cp scripts/inittab /mnt/etc
(At this point we've almost got a working system, we just need to copy over glibc and create a few devices.)

$ cd /mnt
$ mkdir {dev,etc,lib,proc,tmp,var}
$ echo "/dev/hde2 / ext2 remount,rw 0 0" > etc/fstab
(hde2 in this case is how the handheld sees the compact flash device)

$ echo "proc /proc defaults 0 0" >> etc/fstab
$ echo "root::0:0:root:/:/bin/sh" > etc passwd
$ mkdir etc/init.d
$ echo -e "#!bin/sh\nmount -a" > etc/init.d/rcS
$ chmod 755 etc/init.d/rcS
$ cp /usr/mipsel-linux/lib/{*o,*\.so*} lib -a
$ cd dev
$ cp /dev/MAKEDEV .
$ ./MAKEDEV generic

Congratulations, at this point you now have a minimal but functional system on your handheld. You can connect up the serial cable and play around.

X Server

What fun would a handheld with no keyboard be at the command line? We need X on this thing.

The X server in this case is a stripped down version referred to as kdrive. kdrive is supported as a standard part of the XFree86 source, so if you already have a copy there's no need to download another. If not, grab a copy from CVS with the following:

$ cvs -d:pserver:anoncvs@anoncvs.xfree86.org:/cvs login
(Logging in to anoncvs@anoncvs.xfree86.org)
CVS password: anoncvs
$ cvs -d:pserver:anoncvs@anoncvs.xfree86.org:/cvs co xc

Before the touch panel will work we need to swap a few files. Make a quick visit to ftp://ftp.ltc.com/pub/linux/mips/ and grab tp.c, tptrans.h and tpcal. All but the last file go in xc/programs/Xserver/hw/kdrive/Linux/ of your XFree86 sources. The last one, tpcal is the calibration program and goes on the compact flash card.

The next step is to adjust xc/config/cf/host.def to compile for the MIPS platform.

#define CrossCompiling YES
#define KDriveXServer YES
#define KdriveServerExtraDefines -DMAXSCREENS=2
#define TinyXServer YES
#define KDriveXServer YES
#define TouchScreen YES
#define BuildXinerama YES
#define ProjectRoot /usr/mipsel-linux/X11R6

#undef i386Architecture
#define MipsArchitecture

#undef TermcapLibrary

#undef OptimizedCDebugFlags
#define OptimizedCDebugFlags -O3
#define ServerCDebugFlags -O3
#undef StandardDefines
#define StandardDefines -DLinux -D__mips__ -D_POSIX_SOURCE \


-mcpu=r4600 -mips2 -Wa,-m4100,--trap
#undef CcCmd
#undef LdCmd
#undef AsCmd

#define CcCmd mipsel-linux-gcc
#define LdCmd mipsel-linux-ld
#define AsCmd mipsel-linux-as

#define StdIncDir /usr/mipsel-linux/include
#define PreIncDir /usr/lib/gcc-lib/mipsel-linux/egcs-2.90.29/include
#define DoRanlibCmd YES
#define RanlibCmd mipsel-linux-ranlib
#undef ExtraLoadFlags
#define ExtraLoadFlags
#define FbNoPixelAddrCode

#undef LdPostLib
#define LdPostLib -L/usr/mipsel-linux/lib -L../../lib/zlib

#undef XfbdevServer
#define XfbdevServer YES
#undef BuildXprint
#define BuildXKB YES
#define BuildLBX NO
#define BuildFonts NO
#define BuildAppgroup NO
#define BuildRECORD NO
#define BuildDBE NO
#define BuildXCSecurity NO
#define ItsyCompilerBug YES
#define FontServerAccess NO
#define ServerXdmcpDefines /**/

#undef ExtensionOSDefines
#define ExtensionOSDefines
#define GzipFontCompression YES

#include <cross.rules>

After changing the host.def it's a simple matter of running make World install -iks from the xc directory to compile the XFree86 sources. After the compile you'll find the binaries in /usr/mipsel-linux/X11R6. You'll still have to copy them over to the compact flash card. When X loads on the CE device it'll be looking for /usr/mipsel-linux/X11R6 -- it's one of the downsides to cross compiling; symlink mipsel-linux to usr to keep your sanity.

Don't worry too much about copying things to the compact flash yet. We've still got a few more things to compile. For instance, unless you're particularly thrilled with twm I'd strongly suggest building Blackbox.


Handhelds.org maintains a slightly customized version of Blackbox optimized for the one button interface that the touch screen provides, it's also patched for XFree86's new RENDER extension. In other words, it supports anti-aliased fonts.

QT Screenshot

Unfortunately the configure script for this hacked up version of Blackbox isn't the smartest script in the class, so if the instructions look like a kludge it's because they are.

$ cvs -d:pserver:anoncvs@cvs.handhelds.org:/cvs login
(Logging in to anoncvs@cvs.handhelds.org)
CVS password: anoncvs
$ cvs -d:pserver:anoncvs@cvs.handhelds.org:/cvs cp apps/blackbox
$ cd apps/blackbox
$ export CC=mipsel-linux-gcc
$ export CFLAGS="-L/usr/mipsel-linux/X11R6/lib"
$ export CXX=mipsel-linux-g++
$ ./configure --prefix=/usr/mipsel-linux/
$ make LDFLAGS="-L/usr/mipsel-linux/X11R6/lib -lXft -lXrender -lfreetype"
$ make install

Again, we'll hold off on copying the files to the compact flash at this point.


It's somewhat unfortunate that most CE devices don't have any decent means of input, specifically a keyboard. To get around the lack of input devices fscrib turns the entire screen into a Graffiti pad. It takes a bit of getting used to, the character recognition sometimes leaves you wondering exactly what it was thinking, but as an input method it works a lot better than onscreen keyboards.

$ cvs -d:pserver:anoncvs@cvs.handhelds.org:/cvs login
(Logging in to anoncvs@cvs.handhelds.org)
CVS password: anoncvs
$ cvs -d:pserver:anoncvs@cvs.handhelds.org:/cvs cp apps/blackbox
$ /usr/mipsel-linux/X11R6/bin/xkmf -a
$ make
$ make install
$ mkdir -p /usr/mipsel-linux/root/.classifiers
$ cp classifiers/* skin.xpm /usr/mipsel-linux/.classifiers -a

Putting it All Together

So now we have everything in /usr/mipsel-linux. I'm not going to bore you with the details of how to copy that over to the compact flash card, you can pretty much copy it over directly. You might want to clean up things before you do though: The static libraries and include directories are no longer needed and may be deleted to save space.

Before running the X server you'll have to calibrate the touch screen. The calibration is done simply with by running the command tpcal > /etc/tpcal with the serial console. You only need to do this once since the calibration of an individual unit won't change from one bootup to the next.


So, was it worth the trouble? That all depends, it's certainly not practical by any means. To fill the majority of a compact flash card with the base operating system doesn't leave much room for extra applications or storage. The other downside is that with CE in ROM it'll always boot to CE on power-up. If you're serious about running Linux on the handheld you can purchase an iPaq, load Linux into flash ROM and still have the compact flash left over for an IBM micro-drive. You can even use the PCMCIA sleeve with an 802.11b network card and NFS mount storage as needed. The Casio E105 only has a single compact flash slot for expansion so after booting Linux there's not much potential for expansion.

Still, all things considered, it's still rather impressive and fun to see Linux running on the handheld.



Links to various resources and home to many iPaq related projects.


Linux on the MIPS, homepage is somewhat dated.


Home of the Agenda VR3 (MIPS based linux handheld)


NetBSD on the MIPS.


Linux on the Hitachi SuperH.


Development on QT's Palmtop Environment