Debian on Soekris

Recently I bought a Soekris net4801 from kd85.com. This article is about my experiences installing Debian sarge onto it.

What is it?
Soekris boards are essentially complete x86 computers on a single board. The net4801 offers the following on its main board:


 * 266MHz Geode CPU
 * Up to 3 100M ethernet ports (NatSemi DP83816)
 * CompactFlash type I/II socket
 * 44 pin IDE interface supporting UDMA 33
 * Up to 256MB RAM soldered onto the board
 * 2 serial (only one has a DB9 connector, the other is just a header)
 * 1 USB 1.1
 * 1 3.3v PCI slot
 * 1 Mini-PCI type III socket

All that on a board measuring just 13.2 x 14.5cm.

Notice there are no VGA, keyboard or mouse connectors. All communication with the net4801 goes over serial, or by normal network means once you've installed an OS on it.

The model I bought had 128MB RAM, 3 ethernet, and came with a case 21.6 x 15 x 3cm, and I made sure to get a PSU with a UK plug! I bought a 512M CompactFlash card from elsewhere.

Why?
The practical goal was to get a pretty much fully-functioning Linux box onto small low-power hardware with no moving parts, to replace my home firewall/DSL router/NAT gateway that I had running on an old PC. With no moving parts it would be silent, energy-efficient and hopefully very reliable.

Note however that for what they are, Soekris products are very expensive! My order, after the 21% tax of Belgium (where kd85.com is) and shipping to UK, came to just over 250 Euro - and that's before the cost of the CF is counted. If you just want a Linux box that can do DSL, routing, firewalling and NAT then you will find it much cheaper to get something like a Linksys WRT54G and install OpenWRT firmware on it. Alternatively if you wanted a full machine to install your chosen operating system on then you could build a mini-ITX-based machine. That would cost more, but you'd get a much faster CPU and more memory.

But the geek in me wanted to play with installing Debian over PXE, having a familiar Linux distribution installed how I wanted, with a serial console to provide some administrative comforts (if you're the type of person that finds administering things over serial better than using some web interface that is...).

There are a variety of Soekris boards and add-ons, so you can add a wifi card to make a wlan access point, or a crypto card to make a VPN concentrator, or just add an extra 4-port ethernet to make a bigger router/firewall. The basic net4801 on its own was enough for my purposes.

Installation
Most of the installation instructions I gleaned from the following excellent sites:


 * http://roland.entierement.nu/index.php/archives/2005/02/16/debian-on-soekris-howto/
 * http://www.davidcourtney.org/soekris/debian/

Things needed:


 * A server that can run DHCP and TFTP on the same network that the net4801 would be plugged into
 * Somewhere to get Debian from (in my case an Internet mirror, but no doubt you could set up a local mirror).
 * A null modem cable
 * Somewhere to plug the null modem cable into that has a terminal emulator (minicom works).
 * A toothpick or something of similar size is useful to trigger the reset button

Preparing the net4801
I plugged an ethernet cable into the net4801's eth0, the null modem cable into the net4801's serial port, the other end into my laptop, and started a terminal emulator. The default settings for the net4801's serial console are 19200 8N1. After setting my terminal emulator to that, I then plugged the power into the net4801. I saw something like this:

POST: 0123456789bcefghipajklnopq,,,tvwxy comBIOS ver. 1.28 20050529  Copyright (C) 2000-2005 Soekris Engineering.

net4801

CPU Geode 266 Mhz 0128 Mbyte Memory

Pri Mas TOSHIBA THNCF512MPG             LBA 993-16-63  500 Mbyte

Slot  Vend Dev  ClassRev Cmd  Stat CL LT HT  Base1    Base2   Int --- 0:00:0 1078 0001 06000000 0107 0280 00 00 00 00000000 00000000 0:06:0 100B 0020 02000000 0107 0290 00 3F 00 0000E101 A0000000 10 0:07:0 100B 0020 02000000 0107 0290 00 3F 00 0000E201 A0001000 10 0:08:0 100B 0020 02000000 0107 0290 00 3F 00 0000E301 A0002000 10 0:18:2 100B 0502 01018001 0005 0280 00 00 00 00000000 00000000 0:19:0 0E11 A0F8 0C031008 0117 0280 08 38 00 A0003000 00000000 11

5 Seconds to automatic boot. Press Ctrl-P for entering Monitor.

I hit Ctrl-P to get into the comBIOS.

The first comBIOS setting to change is the serial speed; the easiest way to make every piece of software involved in booting happy is to have it all set to 9600 8N1:

> set ConSpeed 9600 > reboot

At this point I had to alter my terminal emulator to 9600 as well of course.

DHCP
I was planning to install over DHCP/PXE so for that I needed to know the MAC address of the ethernet card. An easy way to do that is to tell it to boot over the network. Ctrl-P again then:

> boot f0

The net4801 printed its MAC address to the console and started looking for a DHCP server.

Over on my DHCP server, since I'm using ISC dhcpd, the following went into dhcpd.conf:

host pride { hardware ethernet 00:00:24:C4:36:DC; fixed-address 192.168.0.7; filename "soekpxe.0"; }

At this point I rebooted the Soekris again and did boot f0 to be sure that it was able to get an IP address from DHCP.

TFTP
Back on my DHCP server, I installed a TFTP server. My DHCP server is actually Fedora Core where the correct package is tftp-server, but on Debian I would use tftpd-hpa.

/tftpboot is the default path for files to get served out of via TFTP. As I was installing Debian I needed to get the netboot installer image, netboot.tar.gz from a Debian download site, and unpacked it in /tftpboot:

drwxr-xr-x  4 root root    4096 Jun 10 00:35. drwxr-xr-x 26 root root    4096 Jun  9 23:49 .. drwxr-xr-x  3 root root    4096 Mar  5 19:00 debian-installer/ lrwxrwxrwx  1 root root      32 Jun 10 00:00 pxelinux.0 -> debian-installer/i386/pxelinux.0 drwxr-xr-x  2 root root    4096 Jun 17 20:47 pxelinux.cfg -> debian-installer/i386/pxelinux.cfg

The pxelinux.0 that comes with netboot does not work very well with the Soekris boards. A working image can be found as pxelinux.0.gz</tt> at http://centerclick.org/net4801/pxelinux/ which is also mirrored at http://strugglers.net/~andy/soekris/net4801/pxelinux/. I downloaded that, uncompressed it and renamed it to soekpxe.0</tt>.

By default after unpacking netboot.tar.gz</tt>, pxelinux.cfg</tt> is symlinked to debian-installer/i386/pxelinux.cfg</tt>. I found that this would not work for me, halting just before I would expect the boot:</tt> prompt to appear. I had to change the symlink instead to debian-installer/i386/pxelinux.cfg.serial-9600</tt>.

Installing Debian
With everything now in place, I was finally ready to do the install:

POST: 0123456789bcefghipajklnopq,,,tvwxy comBIOS ver. 1.28 20050529  Copyright (C) 2000-2005 Soekris Engineering.

net4801

CPU Geode 266 Mhz 0128 Mbyte Memory

Pri Mas TOSHIBA THNCF512MPG             LBA 993-16-63  500 Mbyte

Slot  Vend Dev  ClassRev Cmd  Stat CL LT HT  Base1    Base2   Int --- 0:00:0 1078 0001 06000000 0107 0280 00 00 00 00000000 00000000 0:06:0 100B 0020 02000000 0107 0290 00 3F 00 0000E101 A0000000 10 0:07:0 100B 0020 02000000 0107 0290 00 3F 00 0000E201 A0001000 10 0:08:0 100B 0020 02000000 0107 0290 00 3F 00 0000E301 A0002000 10 0:18:2 100B 0502 01018001 0005 0280 00 00 00 00000000 00000000 0:19:0 0E11 A0F8 0C031008 0117 0280 08 38 00 A0003000 00000000 11

5 Seconds to automatic boot. Press Ctrl-P for entering Monitor.

> boot f0

NSC DP83815/DP83816 Fast Ethernet UNDI, v1.03 Copyright (C) 2002, 2003 National Semiconductor Corporation All rights reserved.

Pre-boot eXecution Environment PXE-2.0 (build 082) Copyright (C) 1997-2000 Intel Corporation

CLIENT MAC ADDR: 00 00 24 C4 36 DC CLIENT IP: 192.168.0.7 MASK: 255.255.255.0  DHCP IP: 192.168.0.4

PXELINUX 2.06 0x3fb30aea Copyright (C) 1994-2003 H. Peter Anvin

Press control and F then 1 for help, or ENTER to boot:

At this point I typed "expert26" to get the "expert" Debian Installer with 2.6 kernel.

The install proceeded just the same as for any minimal server install. Only select the minimum needed! That means just openssh really. One thing I completely forgot about before rebooting was to set the serial side of things up.

/boot/grub/menu.lst</tt>:

[...]

serial --unit=0 --speed=9600 terminal serial

[...]


 * 1) kopt=root=/dev/hda1 ro console=ttyS0,9600n81

[...]


 * 1) update-grub

Make sure that ttyS0</tt> is in /etc/securetty</tt> so you can log in as root from there.

And make sure you have something like:

T0:23:respawn:/sbin/getty -L ttyS0 9600 vt102

in /etc/inittab</tt> so there is a getty on the serial port at all.

And after all that you should have a working Debian install, probably in about 250MB of space. You could make it much smaller if you really wanted.

Custom kernel
The next thing I wanted to do was build a custom kernel. This would be much smaller, stripped down, and would take advantage of some features specific to the net4801's CPU. I found it advisable to run at least a 2.6.12 kernel because a number of bug fixes and Geode-specific enhancements had been added in that release.

I found useful information about a suitable kernel config at http://dev.gentoo.org/~brix/papers/net4801/net4801.html

Here follows the important parts of the kernel configuration.

CPU and architecture
The Geode SC1100 is a 586-class CPU.


 * Subarchitecture Type (PC-compatible) (CONFIG_X86_PC</tt>)
 * Processor family (GeodeGX1) (CONFIG_MGEODEGX1</tt>)
 * PCI support (CONFIG_PCI</tt>)
 * PCI device name database (CONFIG_PCI_NAMES</tt>)
 * ISA support (CONFIG_ISA</tt>)
 * NatSemi SCx200 support (<tt>CONFIG_SCx200</tt>)

Suspend modulation
Suspend modulation allows the CPU to run slower and consume less power when it is not busy.


 * CPU Frequency scaling (<tt>CONFIG_CPU_FREQ</tt>)
 * Cyrix MediaGX/NatSemi Geode Suspend Modulation (<tt>CONFIG_X86_GX_SUSPMOD</tt>)

IDE chipset
I needed the following options to use CompactFlash. Note that the CF is not hot pluggable. It also doesn't support DMA, although a hard drive should.


 * ATA/ATAPI/MFM/RLL support (<tt>CONFIG_IDE</tt>)
 * Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support (<tt>CONFIG_BLK_DEV_IDE</tt>)
 * Include IDE/ATA-2 DISK support (<tt>CONFIG_BLK_DEV_IDEDISK</tt>)
 * PCI IDE chipset support (<tt>CONFIG_BLK_DEV_IDEPCI</tt>)
 * Sharing PCI IDE interrupts support (<tt>CONFIG_IDEPCI_SHARE_IRQ</tt>)
 * National SCx200 chipset support (<tt>CONFIG_BLK_DEV_SC1200</tt>)

Ethernet

 * Ethernet (10 or 100Mbit) (<tt>CONFIG_NET_ETHERNET</tt>)
 * Generic Media Independent Interface device support (<tt>CONFIG_MII</tt>)
 * EISA, VLB, PCI and on board controllers (<tt>CONFIG_NET_PCI</tt>)
 * National Semiconductor DP8381x series PCI Ethernet support (<tt>CONFIG_NATSEMI</tt>)

USB
I had no intention of using the USB support so I didn't bother putting support in my kernel. If I had wanted to though, I would have needed the following:


 * Support for Host-side USB (<tt>CONFIG_USB</tt>)
 * OHCI HCD support (<tt>CONFIG_USB_OHCI_HCD</tt>)

Serial
The net4801 has two 8250 serial ports.


 * 8250/16550 and compatible serial support (<tt>CONFIG_SERIAL_8250</tt>)
 * Maximum number of non-legacy 8250/16550 serial ports (2) (<tt>CONFIG_SERIAL_8250_NR_UARTS</tt>)

And for serial console:


 * Console on 8250/16550 and compatible serial port (<tt>CONFIG_SERIAL_8250_CONSOLE</tt>)

Miscellaneous
The net4801 has a red error LED which is controllable from the GPIO on the SC1100.


 * NatSemi SCx200 GPIO Support (<tt>CONFIG_SCx200_GPIO</tt>)

Using a kernel with the aove support and having a device created as follows:


 * 1) mknod -m 600 /dev/error_led c 254 20

It is possible to turn the error LED on by writing 1 to the device and turn it off by writing 0. e.g.:


 * 1) echo 1 > /dev/error_led
 * 2) echo 0 > /dev/error_led

There is also a hardware watchdog feature which can be used with a user-space watchdog program to reboot the board if problems are detected.


 * Watchdog Timer Support (<tt>CONFIG_WATCHDOG</tt>)
 * National Semiconductor SCx200 Watchdog (<tt>CONFIG_SCx200_WDT</tt>)

Finally, there is also a realtime clock:


 * Enhanced Real Time Clock Support (<tt>CONFIG_RTC</tt>)

TSC autohalt bug
I only found the following out much later on but for those using this article as a guide I better point this out now.

There is a hardware bug with the SC1100 and similar CPUs where the TSC (timestamp counter) does not increment when the CPU enters autohalt state. Autohalt state is what happens when the CPU is idle, and it serves to reduce power consumption of the board. The effect is that the system clock appears to run very slow, often losing hours in a day. Even when using NTP, it will continually lose sync.

A workaround would be to disable CPU frequency scaling, which would result in the CPU running at full speed at all times and the maximum amount of power being used.

Fortunately for those that do not wish to do that there is a patch available which applies cleanly to 2.6.12, and may even be already present in later kernels. It can be found at http://www.gnusto.com/scx200-hr-timer.html

bunzip2 -c | patch -p1 patching file arch/i386/Kconfig patching file arch/i386/kernel/scx200.c patching file arch/i386/kernel/timers/Makefile patching file arch/i386/kernel/timers/timer.c patching file arch/i386/kernel/timers/timer_scx200hr.c patching file include/asm-i386/timer.h patching file include/linux/scx200.h
 * 1) cd /usr/src
 * 2) cp -a linux-2.6.12 linux-2.6.12-scx200-hr-timer
 * 3) cd linux-2.6.12-scx200-hr-timer
 * 4) wget -qO - http://www.gnusto.com/src/scx200-hr-timer-2.6.12-rc6-6.diff.bz2 | \

This provides a new kernel config option.


 * NatSemi SCx200 27MHz High-Resolution Timer Support (<tt>CONFIG_SCx200HR_TIMER</tt>)

When booting you will see something like:

scx200hr: timer not yet accessible; will probe later. Detected 266.647 MHz processor. Using tsc for high-res timesource

scx200: NatSemi SCx200 Driver scx200: GPIO base 0x6100 scx200: Configuration Block base 0x6000 switching to scx200 high-resolution timer (255961 cpt)

Your net4801 should now keep perfect time.

Compilation
So after all that I had some kernel source, patched and ready to configure and compile. I recommend you do this on a normal machine, as it will be much faster than the net4801's 266MHz Geode (probably about equivalent to a Pentium 133MHz)!

$ cd /usr/src/linux-2.6.12-scx200-hr-timer $ sudo make-kpkg --config=menuconfig --revision=1 \ --append-to-version=-scx200-hr-timer-pride kernel_image

That left me with <tt>kernel-image-2.6.12-scx200-hr-timer-pride_1_i386.deb</tt> in <tt>/usr/src/</tt>. I transferred that to my net4801 and installed it:

$ sudo dpkg -i kernel-image-2.6.12-scx200-hr-timer-pride_1_i386.deb

That updates <tt>/boot/grub/menu.lst</tt>, too.

Still to come!
How I set up a read-only root filesystem.