Document Home

Valid HTML 4.01 Transitional

Nokia N810 and 770 Internet Tablets
System Hacking

James F. Carter <>, 2006-03-24, updated 2008-03-15

This page has been updated for Maemo-2.0 Mistral.


Rsync is a lot more functional for making backups than prior software, particularly rdist. I've installed the Gnu extended find command from package findutils-find-xargs (some-gnu-utils in Maemo-1.1), and the rsync package. The find in the provided Busybox knows about -newer, which is mandated by IEEE 1003.1 (POSIX dated 2003), but not -cnewer which is a Gnu extension. The script at this link backs up the ITB to a directory on my server -- the destination is hardwired in the script, as is the list of directories to be backed up.

Trans-net backups are done daily. Weekly, the backups of all my machines get burned on a CD, which is rotated in a modified binary tree, and at longer intervals additional CDs are burned and put in my safe and offsite in my deposit box.

All important and hard-to-replace data is covered by the listed directories, plus a fair amount of data which is much more easily replaced. However, it takes work to restrict the backup to only configuration files that I have modified. The memory card is not backed up because its content is large and can be rebuilt easily, e.g. re-rip a (legally owned) music disc.

The Osso suite includes a backup application, which is configured in /etc/osso-backup/osso-backup.conf. It is a sub-page of the Control Panel. The backup appears as a directory on the memory card; the help doesn't say what its name is. It would appear that only /home/user/MyDocs is backed up, which is important but there's a fair amount beyond that which a system hacker would not want to have to re-do by hand. Applications can add their special files or directories to the backup list but that doesn't seem to have happened for the applications that I installed.

Cryptographic Vault

I describe the Cryptographic Vault in this document. Software such as OpenVPN and Postfix need to use your X.509 certificate to authenticate to a remote server and they don't have any good way to talk to you, the authorized user, to get a passphrase. Therefore the secret key needs to be unencrypted. The basic idea of the vault is that you put your various secrets in a small crypto filesystem. You mount it, giving a passphrase, and the daemons can get at the secrets whenever they need them. When your laptop or ITB gets suspended -- and you make sure this happens when the machine is not in immediate, hands-on use -- the machine clams up by unmounting the vault. The passphrase is required again when the machine wakes, to make the clam re-open.

On Maemo there are a few problems with this approach:

So the less secure substitute will be to use GPG to decrypt a tar file containing the secrets, which will be erased upon clamming up, which will have to be done manually.

Which Version Do I Have?

Comparing the files in Scratchbox with those on the device I found some significant differences, e.g. xterm was pre-installed and had a place on the main menu. Do I have an old version, and specifically, have troublesome bugs been fixed in the latest version?

It's not easy to find a definitive indication of the software version. SuSE has /etc/SuSE-release, for example. The Nokia 770 has /etc/osso_software_version which says SU-18R_3.2005.51-13_PR_MR0 (not too revealing). Perhaps the best clue is /etc/apt/sources.list which in Scratchbox refers unambiguously to Maemo 1.1, but on the device points to a non-resolveable host from which one could obtain sputnik-pe1.

MD5sums of libraries and binaries reveal that about 2000 are identical on the device and in Scratchbox, out of about 5000 on the device and 16500 in Scratchbox. This test was inconclusive.

The most authoritative clue was found in the package inventory list. Almost all packages that are on the device match the 1.1 Scratchbox item in version, and I didn't see any which matched 1.0 (except if 1.1 and 1.0 were equal, which did occur). Thus it's official: the production devices have Maemo 1.1 on them.

Look at Control Panel - Device - About Product. The most recent root filesystem version (as of 2006-04-07) is 3.2005.51-13. This string appears in the filename of the root filesystem image, if you're downloading it in order to re-flash your ITB.

How to Become Root (Part 1)

The first step to improving your Nokia 770, and to wiping out your root filesystem, is to become root.

Out of the box, your loginID is user. su is part of busybox, which of course is not setUID, so you can't become root that way. It turns out that you need to enable RD mode (for Research & Development).

Hint of how to become root: sudo gainroot (password rootme) Then alter this to make it properly secure. Everyone knows that root password, not that it does any good, so change it promptly. /usr/sbin/gainroot checks in /mnt/initfs for RD Mode and gives you a root shell if it is Enabled, which it isn't. What that blog doesn't tell you is that you need to put the ITB into RD mode by following the instructions below. And it turns out that in the current filesystem image, gainroot does not need a password. How to get root on the Nokia 770. Karoliina is one of their developers. She says:

But... Unfortunately there are a few missing details, for which see the following section about the flasher.

How to Become Root (Part 2)

Sergio in Italy pointed out an interesting writeup in the Maemo Wiki. This has a good description of how to run the flasher, in English and Spanish, plus oddities that some users have encountered. There are two additional payloads.

At the end of the article there's a reference to two small programs that can split up a Nokia filesystem image into its parts. You can then mount the JFFS2 root image and hack away, and then recreate a flashable image. This is useful if the flasher cannot be used to turn on RD mode, or if you need to make a custom image with extensive configuration and software installation, e.g. if you're giving a Nokia 770 to everyone in your department for inventory control or customer support.

A major theme in the article is that you can modify /usr/sbin/gainroot, commenting out the test for RD mode, so it gives you a root shell whether or not the ITB is in RD mode.

How to Use the Flasher

Unfortunately the instructions in the previous section for using the flasher are not quite complete. This link is to instructions for using the flasher on MacOS, but the command line method works just as well with Linux. There are a few key steps that were not obvious in other web posts:

In the above procedure the ritual of turning on the ITB after the flasher is running is optional, I believe, being a maneuver to overcome problems recognizing a new USB device on some operating systems. However, I wouldn't try any of this with the operating system running on the ITB; it's important to power it off and then have only enough BIOS activation to do the USB connection.

With RD mode enabled, sudo gainroot will give you a root shell without requiring a password.

What To Do If You Hork Your Root Filesystem

Several of the escapades described in the following sections had a baleful effect on the ability of the ITB to boot. Here is what I did to recover from that problem.

The symptom is that the ITB is in an infinite loop of rebooting. It may or may not show the progress bar, but the user interface fails to start, specifically fails to signal its aliveness to the watchdog timer, and the watchdog reboots the machine. To put it out of its misery, remove the battery, wait ten seconds, then put the battery back in. This link is to a script that will automatically revert hacks after 3 reboots.

It is assumed that you were smart enough to back up your filesystem just before you did whatever stupid stunt that made it unbootable. The procedure herein will replace the entire root filesystem with a new copy, wiping out all evil changes, but also all your user data (memory card excepted).

In my case the backups are on my server and will be restored over wireless. For me, the provided backup application saves only the files in ~user, and most of the work is in the system area, so that's not enough. This procedure certainly can be varied -- you could also copy the backup data via USB onto the memory card, then restore from there. But remember that the memory card has a vfat filesystem, which can't do symlinks or ownership by a specific user, and limited access modes.

Setup Notes

For use after mysterious filesystem horkage, here is a list of setup actions to be taken, in case it was deemed prudent to set it up from scratch rather than to restore system files from backups:

Mysterious Crashes

Maemo-1.1 had some syndromes of mysterious crashes after some of my hacking campaigns. I've condensed the results so they're of more general interest. The major lesson is, make very sure that /etc/profile and ~user/.profile are bug-free. The user interface runs as <user>, and if something in either of these files prevents the user interface from starting, the watchdog timer will reboot the ITB in an infinite loop.

Someone wrote in and said he had changed the shell of <user> to bash. I was scared to do that, although bash is POSIX-compliant and so it should work if you substitute it for the Busybox version of ash. However, the person had an incorrect or missing entry for bash in /etc/shells, and su or sudo didn't like it, preventing the user interface from starting.

Being Myself on the ITB

I move files back and forth between my various machines, and having them owned by <user> on the ITB and by <jimc> everywhere else is rather bothersome. In addition, Pine determines the sender of mail from the numeric UID, and I was embarassed to find that all my mail was sent as <user>. I want to change my loginID and numeric UID and GID to match the values elsewhere.

Michiel Toneman sent me this URL that he found, which details two ways to configure Pine to send mail as a user other than <user>, like myself. This is a good hack, but I still need to deal with the file copying issue.

Anyway, here's a summary. First, since Pine 4.1.x you can create a role, which you can induce Pine to (almost) always use. Second, since version 4.0 Pine has a hidden feature (accessible only by editing .pinerc) by which you can alter the default From header. Append allow-changing-from to the feature-list (comma separated, put a comma after the formerly last item). Then append From to the customized-hdrs list (comma separated, create it if not formerly existing); the author gives this example (the second line is indented with a blank):

customized-hdrs=From: AnyPersonalName <AnyUserID@AnyDomain>,
  Organization: Your Company Name and URL

Even though the Pine hack would have solved one of my problems, I continued working on the original plan. Here are where the loginID of <user> appears, as far as I can see:

So I can't just rename <user> to <jimc>. Instead I'll try to create a parallel user identity, placing <jimc> ahead of <user> in /etc/passwd. Oops, that wasn't such a good idea. See the previous section for recovery procedures.

I went back and carefully analysed the startup scripts. These are the changes that I made. Links are to paragraphs in the scripts page from which the hacked files can be viewed or downloaded. See that page for the DISCLAIMER OF WARRANTY and additional warnings.

FIASCO: How to Get At the Root Image

After detecting a second memory error I wanted to check my root image for concealed damage. Here is the procedure I used.

Helpful Dpkg Information

In a RPM-based system you can use rpm to get a list of files provided by a package. There's an equivalent on Debian systems: look in /var/lib/dpkg/info . This is a big flat directory with various files for each package, as follows:

Filesystem on Memory Card

The manual (page 9, Insert the Memory Card) says, make sure that the memory card is formatted with a FAT16/32 filesystem; other filesystem types will not work. Just what part of will not work do I not understand; just what part can I slither around?

A major issue with flash memory is that each block can only be written about 100,000 times, so upon repeated writing the same block needs to migrate to many places on the memory chip. In general, filesystems on flash work on top of a translation layer which makes the block device imitate a rotating magnetic disc, while dealing with the migration issue.

Here are the filesystem types which the provided kernel can do, and a discussion of their use on flash memory. Nonphysical filesystems such as procfs are omitted.


This is what the Maemo distro wants to see, warts and all: it requires a translation layer, it has a max of 2^16 allocation units and hence requires big clusters, 16 kb on a 1 Gb filesystem. It can't do UNIX-style symbolic links, FIFOs, devices or sockets. Both FATs have to be rewritten for every allocation of space. Vfat is just about pessimal as a filesystem on Flash, and I'd really like to get away from it.


This is vfat's little brother, with the same disadvantages.


While it's an excellent filesystem for a real disc, on flash there's no advantage to ext2 and there's the disadvantage that it needs to rewrite metadata frequently (the free block map).


Since journalled filesystems like ext3 and Reiser write metadata into both the journal and the real location, they just wear out the flash memory faster and they ensure frequent CPU-intensive migrations. Never put ext3 on flash memory.


This filesystem was specifically designed to be used on flash memory, and should not work through a translation layer. It is quasi-journalled, in that metadata (and payload data) is written in an order which is failsafe if the process is killed at any point, and a half-written block can be recognized and recycled. Blocks are compressed (with zlib) intrinsically, a big advantage trading CPU time for file space (and the time needed to read from the flash memory). The filesystem intrinsically uses flash blocks in a non-repetitive order including on rewrites. Rewritten metadata is minimized.

This filesystem is superior on flash memory to all others, and should be used if feasible. But, will it bypass the translation layer in the block device? No, the kernel source suggests that jffs2 is closely integrated with the MTD block driver, and empirically jffs2 can only be mounted on a MTD device, not a MMC device.

Here are some speed tests and comparisons. All times are elapsed seconds. Generally the system plus user time does not add up to the elapsed time.

To put a jffs2 filesystem on a card you need the source code for mkfs.jffs2.

According to the kernel sources, the JFFS2 code is closely integrated with the MTD driver. Empirically if you try to mount a MMC device with JFFS2 you get a kernel message about attempt to mount non-MTD device /dev/mmcblk0p1 as JFFS2. I posted a message to asking if the situation was likely to change. (No answer seems to be appearing.)

To search for additional sleeping dragons I did a trial run, putting a ext2 filesystem on the card using another machine. It was possible to mount the card manually. However, something in there is fixated on the idea that the card will have a VFAT filesystem; when it's hotplugged, VFAT is the only filesystem tried. (It's not an issue with fstab; I edited that.) So I'm going to put everything back the way it was, and just live with the Gatesoid filesystem. At least for a while. Update, I think I found it. Look in /usr/sbin/mmc-mount -- it hardcodes the vfat filesystem, and it's in /etc/sudoers.

Another idea: see this HOWTO. <Wolfram> suggests to split the memory card into a VFAT partition and a ext2 partition. That way Maemo gets what it wants (even if small) and I get some of what I want. He also suggests what to do with your expanded space: move your downloaded software and /home/user over there, so if you hork the root filesystem, reflashing is not so catastrophic. He also discusses swap files. (Maemo-2.0 has a feature to put a swap file on the VFAT filesystem of the MMC card.

Yet another idea: /etc/sudoers has a line for execing /usr/sbin/mmc-mount. This is a one-line shell script that mounts the MMC card using specifically vfat, ignoring what's in fstab. Hacks here could be productive (of horkage?)

Hotfix for Memory Corruption in Network Driver

Maemo-2.1 (and probably a lot earlier), referred to as OS2006, has a memory corruption bug in the wlan driver. My experiences with the bug are detailed here. Another annoying behavior also appears to be related. Recently the bug has been tracked down and fixed.

Since my ITB is supposed to be in production mode, I wimped out and applied the hotfix, not the hacker's edition. Here is the procedure.

  1. Download the hotfix from the above URL.
  2. Back up Selen.
  3. Run Tripwire -- checksums of all files are OK.
  4. Copy hotfix onto Selen. Park in /media/mmc1/bkup so it can be applied easily when re-flashing.
  5. Install hotfix. dpkg -i [--dry-run] cx3110x...deb (Note the dialog box warning that a reboot is needed.)
  6. Reboot.
  7. Run tripwire again -- Nothing altered, 2 new files: (This is the only file in the /lib/modules directory. I would guess that modules here override the original ones in /mnt/initfs/lib/modules/ .)
  8. Accept tripwire changes.
  9. Now we'll see if anything behaves differently (better). The dead SSH session bug seems to have been cured.

I've found that WLAN operation has been much more reliable. However, unfortunately there is a bad interaction with the clock: formerly the alarm clock feature was 99.9% reliable, but coincident with installing the WLAN hotfix, when it's time for the alarm the operating system freezes solid. (Remove and replace the battery to recover.) Hiss, boo! On three alarm actions, it died three times. This has been reported as comment #59 in the bug report.

Index of Init Scripts

List of init scripts in /etc/init.d: The default runlevel is 2. Runlevel directories are directly under /etc like with Solaris, e.g. /etc/rc2.d. [Updated for Maemo-2.0 Mistral.]

/mnt/initfs/sbin/dsme, the Device State Management Entity, gets started at some time, probably during initrd execution. Source is not available. This looks important.
In rcS.d (in order)
Mounts proc /sys /proc/bus/usb
Clears and initializes /etc/mtab but does not actually run fsck.
Restores /etc/resolv.conf if the system crashed with PPP active.
Sets the hostname from /etc/hostname.
General init (spoof protection, no syncookies, no IP forwarding, duh). Brings up all known interfaces.
Inits utmp, saves boot messages in /var/log/dmesg.
Saves entropy pool (looks like this doesn't happen).
It looks like in reality /etc/init.d/minircS is run, instead of the rcS.d runlevel scripts. This script does:
In rc2.d (in order)
Removes everything in /var/tmp.
Shows boot logo and progress bar.
Starts ppp at boot time.
DNS proxy caching server.
Starts the dbus daemon. You can kill all the daemons that follow dbus and the system will sit there with a blank screen, but if dbus dies the watchdog will reboot the machine. It is possible to wait 60 secs before starting dbus and the watchdog will not go off.
Starts the rsync daemon, if enabled in /etc/default/rsync, but the default is to disable it.
Starts the ssh daemon for incoming connections.
Mode Controller Entity. Maintainer is a Nokia person. It uses dbus, either session or system. No useful info on Google. To find out more about what it does I guess I'll have to read the source.
Starts the X-Windows server.
Su to user, run a script, stop the progress bar. The script does the following:
  • Start the temp reaper.
  • Start gconf daemon (if not started by dbus).
  • Start the dbus for the session.
  • Start sapwood (image server).
  • Start matchbox (window manager).
  • Start osso-media-server, only if we're supposed to ACT DEAD (whatever that means).
Loads initial program for DSP.
Starts Bluetooth subsystem
Starts the BME DBUS proxy server, whatever that is.
Starts the Osso HSS daemon, whatever that is.
Starts Enlightenment Sound Daemon. This multiplexes sounds from all applications onto one audio device.
Starts the system user interface. Not sure exactly what part of the system this is.
Starts Bluetooth Connection Daemon.
Kernel UEvents to D-Bus system daemon proxy.
Starts Wireless LAN Connection Daemon.
Starts Bluetooth PIN Handler.
Starts Osso Internet Connectivity Daemon.
Starts Maemo launcher, changing UID to user. I wouldn't be surprised if this listened on the system dbus for requests to launch a program.
Stops the progress bar, then (executing as user) does these steps:
  • Starts maemo-launcher on the session dbus
  • Displays the startup greeting
  • Only upon first boot:
    • Automatically runs backup to restore stuff after reflashing
    • Starts the Osso connectivity daemon (?)
    • Runs the startup wizard
    • Runs the connectivity initalization
Sets the hostname used in Bluetooth connections.
Running as user, starts these items:
  • maemo-af-desktop
  • Connectivity daemon (2 of them)
  • Keyboard input method
  • Osso media server
  • Clipboard
Starts the Interaction Server, whatever that is.
Starts the system UI if osso-systemui-early did not get it started.
This has something to do with games.
This handles the alarm clock.
Uncomments or re-comments the line in /etc/inittab for a getty on /dev/ttyUSB0 depending on whether it exists, and does telinint Q to inform init. This is how a serial console is done, according to comments. But I haven't figured out what the USB host needs to do to make ttyUSB0 appear. Nor what to do about the watchdog timer. This should be handled through hotplug/udev, not init! And the same for all the gettys.
Other Runlevels

Hacked scripts likely need runlevel links in /etc/rc5.d as well. On one occasion the ITB did this nasty behavior: It was powered off. I plugged in the charger. It booted partially and the hacked /etc/init.d/rc logged that it was going into runlevel 5. There was no link for /etc/init.d/pickuser in rc5.d, and this spoiled the boot process leading to an infinite booting loop. (Recovery: unplug the charger, boot normally, provide links in rc5.d.)

Other Startup Scripts
System pre-initialization wrapper.
  • Mounts /proc /sys /proc/bus/usb.
  • Prepares and mounts /dev/pts.
  • Mounts a tmpfs for /var/run.
  • Starts udev, with tmpfs for /dev.
  • Executes /usr/sbin/retutime -i (whatever that is).
  • Sets the hostname (from /etc/hostname).
  • Brings up lo: (loopback net interface), and other network pre-initialization.
  • Doesn't initialize utmp.
  • Clears and initializes /etc/mtab.
Executor for runlevel 6 (reboot)
Executor for runlevel 0 (shutdown)
Standard runlevel manager script for level 1 - 5. Looks in /etc/rc[1-5].d

Document Home