Username/Email:  Password: 
TwitterFacebookFlickrRSS

BOEL, Part 2: Kernel Configuration and Booting

Every byte counts when building a small custom kernel for network booting. Save the bytes!

Brian's Own Embedded Linux, or BOEL as it is affectionately known, was created as part of the SystemImager Project. SystemImager is a tool used for, well, imaging systems and distributing live updates. Part of the imaging process involves booting a client machine in such a way that its hard disks are not in use and are therefore available for manipulation. The SystemImager autoinstall client does this by using a root filesystem that exists entirely in memory or an initrd (initial RAM disk). This initrd and the kernel that goes with it are the embedded Linux system we call BOEL.

This is the second article of a two-part series. In the first article, in the March/April 2002 issue of ELJ, we went through the process of creating our initrd and discussed issues such as libraries, shells, filesystems and inodes. Much of our focus is on creating a system as small as possible--the complete BOEL system has to fit on a single 1.44MB floppy. In this article we go through the process of tying a kernel to our initrd and making the system bootable from a variety of media.

Figure 1. Uncompressed RAM Disk Components (in Kilobytes)

Compiling the Kernel

One nice thing about compiling a kernel for an embedded system is that you typically have a very limited set of hardware to support. In the case of BOEL, the only types of hardware we have to support are NICs (Network Interface Cards), disk drives and disk drive controllers. This makes it much easier to pare down the drivers needed for our kernel. It also allows us to use a non-modular kernel, which in addition to simplifying the boot process, also simplifies the development process. Even as such, it can still take a lot of time to whittle down a kernel to exactly what is needed and nothing more. But it's worth making that effort. Every additional driver takes up valuable space on our system, so we only want to include the drivers that we need.

This means we can leave out things like USB, sound, Ham radio support, etc. However, we do have to be sure to include support for things like an initrd (we have to be able to mount the thing for our root filesystem), loopback devices (the initrd gets put on a loopback device before the kernel mounts it), NICs, TCP/IP, IDE, SCSI and the filesystems that we support. If you want to have a look at exactly what we include in our standard kernel, you can take a look at the kernel .config file at http://systemimager.org/pub/boot/2.0.1/systemimager-boot-i386-standard-2.0.1.config.

Once you've made your driver selections, you must compile your kernel. Funny thing is, each time you compile it, your resultant kernel may have a slightly different size. I usually will do several compiles until I'm convinced I've gotten the smallest one possible.

Figure 2. Kernel Sizes

Now that we have our kernel ready and our initrd as prepared in the first article, we need to configure the system for booting. In the case of BOEL, we need to be able to boot from floppy, CD-ROM, a hard drive or the network. I'll describe how we make each of these happen using the same kernel and initrd.

Booting the System

First, a bit about booting in general. When booting a system that uses an initrd, the actual steps the computer goes through are not necessarily intuitive. On a Linux system that has its root filesystem on a hard disk partition (with no initrd), the boot loader simply loads the kernel and tells it where to find its root filesystem. When the kernel finishes initializing the hardware, it happily mounts the root filesystem, and you're off and running.

With an initial RAM disk, the initrd must be decompressed and placed into memory before the kernel is loaded. Otherwise, there would be no root filesystem available for the kernel to mount when it finishes its initialization. Here's a summary of the steps taken by a boot loader when using an initrd:

  1. Decompress the initial RAM disk (usually stored as initrd.gz).

  2. As it is being decompressed, toss it up into memory.

  3. Toss the kernel up into memory (without overwriting the RAM disk), telling it the memory address where the RAM disk starts, the device it's supposed to use to mount the RAM disk (/dev/ram0), and kick the kernel to start it spinning through the processor.

  4. Once the kernel finishes initializing, it mounts the RAM disk as its root filesystem as if nothing special happened, using the device location that it was told by the boot loader.

H. Peter Anvin has created a package, called SYSLINUX, that contains some utilities that make it really quite easy to get a system with an initrd to boot from a floppy, a CD-ROM or from the network. In recent releases, there are three separate tools for the three different boot methods mentioned above: SYSLINUX, ISOLINUX and PXELINUX. These tools can use a configuration file (syslinux.cfg, isolinux.cfg or pxelinux.cfg) to specify boot options and a messages file (messages.txt) to give the person booting the system important messages, like ``This is the SystemImager autoinstall system. If you do not want your disks repartitioned and freshly formatted, power off now!''

______________________