Impenetrable Thoughts
Installing and Configuring Slackware 12.1 on an OLPC XO-1

The XO is a pretty nice piece of hardware: nice solid case, solid state everything, low power consumption and a screen that is as readable as a newspaper in the full light of day. Now the OLPC project has the goal of educating children around the world by providing them with a powerful computer and appropriate software. While this software is probably good for children who have never seen a computer before, I find it entirely unsatisfactory.

Part of this stems from Sugar, the default GUI, but that is replaceable. The larger problem is that the entire system is based upon Redhat. Now I'm not much a fan of Redhat based system because I find that they complicate matters and aggravate me. Perhaps they aren't designed for CLI users like myself. Conveniently one of the secondary goals of the OLPC project is to being advanced computer literacy to those children. This means tinkering and hacking is promoted and that's just what I'm going to do. Here is what I've done to replace the original Linux distribution with my favourite Slackware.

1. Overview

Now the XO isn't a run of the mill PC. It has no floppy drive, no CD-ROM drive, no ethernet port and no traditional PC BIOS. Instead of a harddrive it has Flash which is soldered onto the motherboard. This setup presents a couple of problems:

  1. The Slackware Installation disks cannot be run directly (No CD-ROM/DVD drive)

  2. Removing the harddrive to install on another machine isn't an option

  3. Instead of a traditional BIOS the XO has OpenFirmware. In my opinion OpenFirmware is at the same time both more powerful and less flexible (in this case) than a traditional BIOS. This complicates the procedures to get a kernel booting.

  4. The XO is actually a powerful embedded system and this means special hardware. The problems this presents are mostly that the necessary kernel drivers are not yet in the mainline kernel so the OLPC kernel must be used.

  5. Finally though you can install ext3 onto Flash it isn't a terribly good idea and JFFS2 is much preferred. Unfortunately as far as I know the Slackware installers don't support JFFS2.

The plan to get around these problems and install Slackware is as follows:

  1. 'Install' the Slackware packages into a directory

  2. Move these to the appropriate place on the XO to make it bootable

  3. Get the kernel booting

  4. Tweak the Slackware startup scripts to deal with some peculiarities

  5. Handroll the most important configurations the setup programs usually does for us

  6. Delete the original software (Optional)

  7. Tweak the install to perfection

Let us begin.

2. Preliminaries

Before beginning you'll need to get a couple of items. Most notable is the Developer Key for your XO. See for information on how to retrieve that.

The second things you'll require is installation media (not necessarily physical) of Slackware. I used Slackware 12.1 for this particular operation, but any recent version should work.

3. Unpacking Slackware

It is unfortunate that it seems to be exceptionally difficult to get the XO to boot the regular Slackware installation system as that would save some manual work later in configuration things later. It is not to be so instead we will unpack the Slackware packages into a directory such that we can drop this into place as a starting point for the fully configured installation.

I performed all these steps as root, but lesser permissions could possibly be used in some particular cases. I also performed all these operations on my Slackware running desktop due to space constraints and ease. Slackware is most likely unnecessary. With care it is probably completely possible to perform this conversion entirely on the XO.

The first thing we need to do is extract all the setup scripts so we can use them.

  1. Locate the initrd.img file from the media (it's isolinux/initrd.img on the 12.1 DVD ISO).

  2. Create a temporary directory to place the extraction in: `mkdir initrd`

  3. Extract the initrd: `cd initrd; cat initrd.img | gunzip | cpio -i`

  4. Note where the script slackinstall is located within the extraction. On 12.1 this was in usr/lib/setup, I'll denote this by $SLACKINSTALL_PATH.

  5. This directory needs to be _prepended_ to the path. Try export PATH=${SLACKINSTALL_PATH}:${PATH}

We now have the setup scripts located and are ready to install the packages into the directory which will become the basis of our installation.

  1. Create a directory to place the installed tree into 'mkdir slackware'

  2. Install the packages.

    • $SRC is where the disk pack directories are, on the DVD this is slackware

    • $DST is the directory where you are going to install, slackware in this example

    • $MODE is one of {newbie, expert, full, custom}. This is the level of prompting to be done. newbie installs anything that is required and prompts verbosely for the rest. expert shows a list from which you select the packages to install. Full installs everything and custom uses customized tag files to determine what to install.

      I don't recommend full because that installation option will install far more than will fit on the internal Flash. If you have an additional SD card to install onto I would recommend getting a basic installation working, move /usr to the SD card and then install the rest of the software.

      Space is low on this device as it only has 1GB. However, by not reformatting the Flash we get to use JFFS2 which is transparently compressing and will provide an average compression ratio of 2:1. When selecting packages keep this in mind. You needn't worry about not installing all the packages you want right away. It is possible to install additional packages later. Instead focus on getting a basic system installed. Whatever you do ensure you install a CLI text editor. When I have finished the major fiddling with my installation I will post what I consider a minimal set of necessary packages.

      To do the installation simply run the following command and select packages as appropriate when prompted. `slackinstall --device noremount --promptmode $MODE --srcpath $SRC --mountpoint $DST\ --target $DST --series 'a ap d e f k kde kdi l n t tcl x xap y`

4. Moving onto the XO

Most of this information is an adaptation of the information found at

The next step is to move this newly installed Slackware installation over to the XO and put it into the correct place. The XO uses a unique boot system so that updates can occur seamlessly and always leave a path to revert to the previous version while keeping the home directories untouched. It further efficiently enables any changes in the current OS to be reverted with ease and the original configuration made accessable. This is accomplished through the use of hardlinking, root swizzling and perhaps multiple mounting of devices.

In any case we'll be using the kernel and initrd image from the original XO distribution. Later, once we have the system mostly configured we'll come back to compiling a custom kernel.

These first steps only needs to be done if you unpacked Slackware on a separate machine. The exact tranfer mechanism doesn't matter to much, I merely show this method for those who are otherwise stuck. The one thing which is important is that you probably have insufficient free disk space (See the new anachronism forming right before your eyes!) to first copy an archive and then unarchive it, yet at the same time whatever method is used must preserve all permissions.

  1. # tar -cf slackware.tar slackware (performed as root on the machine with the installed Slackware)

Now on the XO

  1. cd /versions/pristine

  2. ssh username@desktop 'cat /path/to/slackware.tar' | tar -x

Now as long as you have followed my suggested names above you should have the directory /versions/pristine/slackware. This is good. Now we'll copy a few configuration files over, most importantly fstab so that the root is mounted correctly.

  1. cp /etc/{hosts, fstab} /versions/pristine/slackware/etc

Now we copy the kernel, initrd image, kernel modules, wireless firmware and the boot loader configuration.

  1. cp -r /lib/modules/* /versions/pristine/slackware/lib/modules

  2. cp -r /lib/firmware/* /versions/pristine/slackware/firmware

  3. cp /boot/* /versions/pristine/slackware/boot

There are a few nonstandard directories which are referenced by the default fstab, the initrd and firmware which must exist for several things to happen. Create those now.

  1. mkdir /versions/pristine/slackware/{ofw, versions, security}

Now it is important that you have the developer key available to the firmware at all times, so I highly recommend placing it there now.

  1. cp /security/develop.sig /versions/pristine/slackware/security

The XO has many useful power saving devices installed. In fact the majority of the system architecture is designed around being able to turn just about everything off to maximize battery life. One of these useful devices in the DCON, which basically is able to refresh the screen while the CPU is off. On bootup it appears that the DCON is set to refresh the screen, thus ignoring whatever the GPU (which is built into the CPU) is sending to be displayed. We need to add one small command to the Slackware init scripts to enable displaying from the GPU.

  1. Add the line "echo 0 > /sys/devices/platform/dcon/freeze" to /versions/pristine/slackware/etc/rc.d/rc.S right after sysfs is mounted and before udev is started. This is near the top of the file.

We have finally finished contructing the pristine copy of the Slackware install. Now though this copy isn't fully configured it is bootable. Before we do so we need to quickly make a running copy which we will configure so our liking. Once we've done that (which will take a long while) we'll move the configured copy to be the pristine copy and then we'll consider our work temporarily finished.

  1. cd /versions/boot

  2. rm alt

  3. ln -s /versions/pristine/slackware alt

That covers setting Slackware as the alternate OS. Now we configure the Copy on Write (that's how it's efficient) running copy of the pristine installation.

  1. cp -rl /versions/pristine/slackware /versions/run/slackware

  2. /usr/sbin/setattr -R --iunlink /versions/run/slackware

5. Booting

Useful tips on the various special bootup modes is found at

Booting into Slackware is now fairly simple. The short of it is to hold the O button (on the right of the screen) during power on (but only until directed to release it). You only do this the first time.

The slightly longer explanation is that the firmware is designed to allow multiple versions to be installed at any one time. The previous steps installed Slackware as the alternate OS. Holding the O button swaps the default and the alternate OS. This means that you only need to hold the button once, but can of course load the other OS at any time.

Doing this should bring you to the wonderful darkstar prompt. You'll notice that you are only able to see the kernel message roll off the top of the screen. This is because the DCON wasn't put into pass through mode until the init scripts started to run.

The first time you boot you'll be presented with an error because the JFFS2 root can't be checked. You can just proceed past it and we'll fix it later.

6. Base Installation Configuration

The setup program walks us through seveveral important configuration steps. We didn't run setup so we need to do these steps manually.

The first configuration to do is to name the machine. This involves changing /etc/HOSTNAME and /etc/hosts. /etc/HOSTNAME just contains the fully qualified domain name of the machine. /etc/hosts contains a static mapping of IPs to hostnames. You'll need to add a line like odysseus odysseus.lan

where odysseus.lan is the line in /etc/HOSTNAME. This appears to be all that is required for IPv4 naming of the machine. IPv6 is coming into the mainstream so we should also add the loopback names for that (TODO).

The second piece of configuration has to do with timezones. Conviently there exists a Slackware configuration utility timeconfig. Run this and configure as appropriate. I recommend storing the time in UTC because we don't have a legacy OS to deal with. As a laptop this machine may also change timezones; with UTC is merely takes a timeconfig to change. The clock will still be accurate.

7. X11 is the original source of much of the following information.

The first step to getting X working is to ensure that you have it installed. The XO makes use of the geode Xorg driver, make sure you have it installed. The next step is to get the mouse device working. The XO default kernel has the module mousedev which drives the touchpad. You must have this module loaded before starting X. This could be done by adding a line similar to the one below to /etc/rc.d/rc.modules.

/sbin/modprobe mousedev tap_time=0

The parameter tap_time determines what the driver considers a tap. If you, like me, dislike tap-clicking set this to zero to disable it.

The second thing we need to do is to add the XO keymap. I copied this from the end of the original /usr/share/X11/xkb/symbols/us file. Place them at the end of that same file under Slackware. I have repeated that text here for reference.

partial alphanumeric_keys

xkb_symbols "olpc" {

include "us(basic)"

name[Group1]= "USA";

// OLPC international US English keyboard layout.

// It's a little different from the usual international layout.

// See:

key { [ grave, asciitilde, dead_grave, dead_tilde ] };

key { [ 1, exclam, exclamdown, exclamdown ] };

key { [ 2, at, notsign, notsign ] };

key { [ 3, numbersign, 0x1000300, 0x1000300 ] }; // combining grave

key { [ 4, dollar, 0x1000301, 0x1000301 ] }; // combining acute

key { [ 5, percent, 0x1000306, 0x1000306 ] }; // combining breve above

key { [ 6,asciicircum, 0x100030A, 0x100030A ] }; // combining ring above

key { [ 7, ampersand, 0x1000302, 0x1000302 ] }; // combining circumflex above

key { [ 8, asterisk, 0x1000324, 0x1000324 ] }; // combining caron above

key { [ 9, parenleft, 0x1000307, 0x1000307 ] }; // combining dot above

key { [ 0, parenright, 0x1000308, 0x1000308 ] }; // combining diaeresis above

key { [ minus, underscore, 0x1000304, 0x1000304 ] }; // combining macron above

key { [ equal, plus, 0x1000303, 0x1000303 ] }; // combining tilde above

key { [ q, Q, Greek_omega, Greek_OMEGA ] };

key { [ w, W, oslash, Oslash ] };

key { [ e, E, oe, OE ] };

key { [ r, R, 0x1000327, 0x1000327 ] }; // combining cedilla

key { [ t, T, 0x100032E, 0x100032E ] }; // combining breve below

key { [ y, Y, 0x1000325, 0x1000325 ] }; // combining ring below

key { [ u, U, 0x100032D, 0x100032D ] }; // combining circumflex below

key { [ i, I, 0x100032C, 0x100032C ] }; // combining caron below

key { [ o, O, 0x1000323, 0x1000323 ] }; // combining dot below

key { [ p, P, 0x1000304, 0x1000304 ] }; // combining diaeresis below

key { [ bracketleft, braceleft, 0x1000331, 0x1000331 ] }; // combining macron below

key { [bracketright, braceright, 0x1000330, 0x1000330 ] }; // combining tilde below

key { [ a, A, ae, AE ] };

key { [ s, S, ssharp, ssharp ] };

key { [ d, D, eth, ETH ] };

key { [ f, F, thorn, THORN ] };

key { [ h, H, sterling, sterling ] };

key { [ j, J, EuroSign, EuroSign ] };

key { [ semicolon, colon, masculine, ordfeminine ] };

key { [ apostrophe, quotedbl, currency, currency ] };

key { [ backslash, bar, section, section ] };

key { [ c, C, ccedilla, Ccedilla ] };

key { [ n, N, ntilde, Ntilde ] };

key { [ m, M, mu, mu ] };

key { [ comma, less, guillemotleft, guillemotleft ] };

key { [ period, greater, guillemotright, guillemotright ] };

key { [ slash, question, questiondown, questiondown ] };

key { [ multiply, division, ISO_Next_Group, ISO_Prev_Group ] };

include "level3(ralt_switch)"


partial alphanumeric_keys

xkb_symbols "olpc2" {

include "us(olpc)"

name[Group1]= "USA - Group toggle on multiply/divide key";

key { [ ISO_Next_Group, ISO_Prev_Group ] };


Adding this keymap isn't quite sufficient as it leaves the directional pad, rotate button and two buttons on the keyboard unusable. To solve this there are a few commands I recommend adding to rc.local to map these keys. Add the following to some file run at startup.


#rockerpad up

setkeycodes 65 120

#rockerpad right

setkeycodes 68 121

#rockerpad down

setkeycodes 66 122

#rockerpad left

setkeycodes 67 123

#rotate button

setkeycodes 69 124

#magnifying glass

setkeycodes e079 125

#overlapping rectangles

setkeycodes e06e 126

There is one final thing which needs to be done to make these keys work and that is give them names. You can do this using xmodmap. I have a .Xmodmap file which contains the information you need. This needs to be run on every login, or perhaps loaded from xinitrc if you desire to change it there.

Now all that is required is to put into place xorg.conf. I have posted my working xorg.conf as a good starting point. Copy that into place (/etc/X11/xorg.conf), tweak it to taste and try firing up X from the command line. If it comes up you'll want to make sure that you move the mouse around. If all seems well you can move onto window managers.

If it doesn't come up take a look at the error output. I had X complaining that it couldn't find the 'fixed' default font. I believe this is related to another step that setup would normally perform for us. To work around this run the following commands:

  1. cd /usr/share/fonts

  2. for i in ls; do mkfontdir $i; done

This rebuilds some font location information and should fix that problem. Try X again.

8. Making Window Managers Work

Window managers should be a relatively easy thing to get going. The first thing to do is to point to the default window manager This is only necessary if you don't want to use KDE which is the default default. I personally use XFCE because it requires less memory and disk space than KDE.

  1. cd /etc/X11/xinit

  2. rm xinitrc

  3. ln -s xinitrc.xfce xinitrc

You are free to modify the last command to point to your preference. Some of the installed options are listed in that directory.

You should now start X via whatever means you would normally to ensure that all permissions and necessary packages are installed. Doing this as a regular user is recommended. Any window manager errors will be found in ~/.xsession-errors. I expected this to work without a hitch, but needed to run the following command to reset the permissions on /tmp/.ICE-unix. chmod 177 /tmp/.ICE-unix This was the only step I reguired beyond ensuring all the appropriate packages were installed to get xdm (my preferred X starting method) to allow me to log in as myself and get a working XFCE desktop.

Should you decide to use xdm I made one small configuration change to decrease the size of the login box to a usable size. Edit /etc/X11/xdm/Xresources and change the line "#if WIDTH > 800" to "#if WIDTH < 800".

Changing the screen brightness is on of the important operations on a laptop. Especially if you want to enjoy great battery life in the sun. Brightness is controlled by writing a value between 0 and 15 to the file /sys/class/backlight/dcon-bl/brightness. The first thing that needs to be done to let regular users change the brightness is to change the permissions on that file to allow writing by the appropriate users. This needs to be done on every bootup. I accomplish this with the following two lines added to rc.local.

chown root.plugdev /sys/class/backlight/dcon-bl/brightness chmod g+w /sys/class/backlight/dcon-bl/brightness

Now whats needed is a script to increase the brightness and a script to decrease the brightness. These scripts are and . Bind these to a couple of keys and you'll be done. I recommend Shift-F9 and Shift-F10.

I have written a small script which rotates the screen using XRandR. It can be found . I recommend you tie this to the rotate button using your favourite window manager. It's a simple script so you could rewrite in something else if you wished.

9. Sound

Note that this may not be a problem you'll run into. This problem is caused by device files with incorrect minor number. I fixed this by checking in /sys/class/sound/*/dev. Anything with a major number of 116 I needed to recreate. Here is the output of ls -l in the /dev/snd directory where I recreated them.

crw-rw-rw- 1 root audio 116, 5 2008-05-08 14:41 controlC0

crw--w--w- 1 root audio 116, 4 2008-05-08 14:42 pcmC0D0c

crw-rw-rw- 1 root audio 116, 3 2008-05-08 14:42 pcmC0D0p

crw-rw-rw- 1 root audio 116, 6 2008-05-08 14:43 seq

crw-rw-rw- 1 root audio 116, 2 2008-05-08 14:43 timer

Changing the volume using the volume keys is as simple as attaching shortcuts to those keys (with or without the fn key held) to run `aumix -v+10` and `aumix -v-10`. Easy as can be.

10. Power Management

The XO hardware is designed to be very power efficient. Not only does it have low power components (embedded processor, no fans, flash instead of a spinning harddrive), but it is also possible to put some components to sleep to save power while others continue operating.

There are five broad things that can be turned off:

  1. The processor (done by the kernel)

  2. The GPU (controlled by /sys/devices/platform/dcon/freeze)

  3. The display (controlled by /sys/devices/platform/dcon/sleep)

  4. The motherboard (ie. suspend to memory)

  5. The wifi chip (off if the module isn't loaded

Now these can be put to sleep in a variety of configurations to suit the needs of a user. Most useful is turning everything off when the lid is closed. Second most useful is turning off the motherboard and GPU. This is an ebook or reading mode that can recover in a small amount of time.

Putting parts to sleep while maintaining interactive usability is currently beyond this document and probably requires kernel help.

Suspending the entire laptop with minimal power usage is accomplished by unloading the wifi module, sleeping the display and suspending to memory. The script does this. Now some people like the laptop to suspend when the lid closes and wake up when it is opened. The XO does have a few switches which mark when the lid is opened or closed and then the laptop enters/leaves ebook mode. These are accessable via /dev/input/event1 and event2 respectively.

Though there most likely exist other power management daemons which could take these triggers as input I decided to write my own because my needs are minimal. This I called xo_pm and I suggest starting it up in rc.local to have the laptop suspend when the lid is closed and wakeup (without wireless enabled) upon opening. It will also eventually work well with the X screen saver I am going to write which will suspend the laptop but leave the display on after a short period to save power. Interaction with xo_pm will let it know when it is in ebook mode to reduce the timeout before sleep.

put to sleep echo "mem" > /sys/power/state doesn't turn backlight off

The power/wakeup files seem to determine whether that device will wakeup the machine or not.

turn display off echo 1 > /sys/device/platform/dcon/sleep echo 0 to turn back on

11. Software

Most software from the Slackware discs seems to work just fine, though I haven't tried it all. At the very least all the programs I use regularly. There are a couple of things that need be to watched out for when compiling software though. Specifically it appears that GCC 4.2 thinks the Geode in the XO is a K8 and optimizes as such. This causes GCC to emit the freep instruction. Though this instruction exists on all other 32 bit x86 processors it doesn't exist on the Geode. To prevent GCC from emitting this instruction you'll need to modify the build configuration to change any '-mtune native' to be '-mtune k6-3'. That should fix it. GCC 4.3 is supposed to have Geode specific optimizations which should prevent these problems and make things run faster.

12. Slimming Down

Even though Slackware is by no means a fat distribution there are still things which can be cut to save space. Precisely what can be cut is a function of the individualized user.