larwe.com logo Home Contact Resume Writing Technical projects Scout restoration Vintage computing

Book 3

My third book is released! Learn what you'll need to know in order to become an embedded engineer.


Book 2

Check out my second book; learn practical stuff about building robots and control systems around Linux PCs and the Atmel AVR.


Book 1

My first book gives you all the intro you need on developing 32-bit embedded systems on a hobbyist budget.

Creating bootable system restore CD-ROMs with Linux


IMPORTANT: This is an "escaped" document. It is not complete. I inadvertently uploaded it during a site update, and people started asking me about it. This document is actually an excerpt from my second book.


This essay describes how I created a simple framework for building a bootable CD-ROM that will noninteractively install a system image onto a target's hard drive. There are two major reasons why this document might be of interest to you:

  • You are shipping Linux-based desktop computers, special-purpose workstations (such as POS terminals), or other embedded devices built around a standard Intel CPU running Linux, and you need to supply your users with a simple, idiot-proof means to restore corrupted installations or recover from hard disk replacement, or
  • You want to be able to back up your entire system's boot configuration on a single CD-ROM so you can restore it in cases of emergency.

There are several HOWTOs on the Internet describing how to create bootable CD-ROMs under Linux, but none of them cover exactly what I needed to do. There is in fact at least one project (a collection of scripts, basically) that will build your entire running root filesystem into a bootable CD, but this is not what embedded developers need, because we need to create an image of a running system that probably doesn't have all the necessary utilities installed on it, and we need it to be self-installing onto a hard drive in the target system.

My specific need was to provide an emergency recovery CD-ROM for a Linux-based appliance. The appliance runs a highly pruned version of Red Hat Linux 8.0 (basically because I was too lazy to build the system from scratch; there's really very little of the Red Hat-specific materials left). Initially we were using Norton Ghost to do the restore operation, but this is (a) payware [hence unsuitable for in-box inclusion with our product], and (b) doesn't appear to work properly on ext3 drives. More importantly than either of these, however, the version of Ghost we have requires the user to enter a serial number using the keyboard. Since our appliance doesn't ship with a keyboard, we have to tell the user to borrow one from another computer around the place.

The ElTorito specification for bootable CD-ROMs essentially specifies that the CD contains a disk image of a 1.44Mb or 2.88Mb floppy disk (or a hard disk of arbitrary size). At boot time, the system BIOS looks for an ElTorito signature on the disk, and if it is found, goes into a special mode where either BIOS int 13h device 00H (A: drive) or 80H (C: drive) read requests are directed to the image file residing on the CD. So the basic process for creating a bootable Linux CD is to create a bootable floppy disk containing the kernel and enough goodies to mount the CD-ROM filesystem and do something useful with it. You then create the rest of the CD's filesystem containing whatever else you want to put on the disk, and you bring the whole thing together onto the target media.

Most of the CD-Boot-HOWTOs on the Internet begin with instructions on how to create a bootable floppy disk containing the kernel and a gzip-compressed initial RAM disk (initrd). Unfortunately there's more to it than this. The only way of getting to the emulated disk image is through BIOS calls, and as soon as the kernel has loaded, the BIOS is out of the picture. So you can't do the usual bootdisk process of putting the kernel at the start of the disk, putting the compressed initrd filesystem immediately after it, and using rdev(8) to let the kernel know where to find the initrd image. What you need is an external bootloader program that will use BIOS services to load both the kernel and initrd image, and only then pass control to the kernel. Almost all of the HOWTOs I've read talk about installing LILO on the floppy disk as the bootloader.

Now, it's very challenging to cram a useful kernel and runtime environment onto a single 1.44Mb floppy disk. It's much easier to get up and running if you can use a 2.88Mb disk image. However, unless you have a 2.88Mb floppy drive (and I've never even seen one except on Japanese-market machines), you have to work entirely with a disk image file. The problem with this is that the current version of LILO doesn't seem to want to work on loopback devices, and I spent the better part of a workday fiddling with it trying to get it to play nice. Eventually I decided that it isn't possible, and I gave up.

The first thing you should do, then is download SYSLINUX from syslinux.zytor.com. SYSLINUX is a much simpler bootloader to work with than LILO, and it even comes precompiled so you can get straight to work. (Note that many Linux distributions will include SYSLINUX already; find / |grep syslinux to see if you already have it).

Now, let's create an empty 2.88Mb disk image to be our CD-ROM boot disk. Working on our development computer, first we create an appropriately-sized empty file:

dd if=/dev/zero of=/288mboot.img bs=1k count=2880

Since SYSLINUX only works with FAT-formatted media, we need to format this image file using mkfs:

mkfs -t msdos /288mboot.img

Now we're ready to install SYSLINUX onto the target image. Assuming that the SYSLINUX binaries are in the current directory, we can achieve this as follows:

./syslinux /288mboot.img

We now need to mount that disk image to a convenient point so that we can copy files to it:

mkdir /mnt/bootdisk
mount -t msdos -o loop /288mboot.img /mnt/bootdisk

(If you get an error trying to mount the image file, you might not have loopback support compiled into your kernel. Recompile your development system's kernel including loopback support - you'll find it in the Block devices section).

At this point, if you ls /mnt/bootdisk you will see that SYSLINUX has placed a file called ldlinux.sys in the root directory of your disk image. This is the actual bootloader. SYSLINUX also modified the boot sector of the disk to load and execute the ldlinux.sys file. The default behavior of the bootloader is to load the Linux kernel from a file named LINUX. We can override this behavior (and specify more complex behaviors) by creating a text file called SYSLINUX.CFG in the root directory of the disk image. For my system, I use the following single-line configuration file:

DEFAULT LINUX initrd=INITRD.IMG root=/dev/ram console=/dev/ttyS0

This tells SYSLINUX to load the kernel from /LINUX and the initial RAM disk from /INITRD.IMG. The reason I tell the kernel to use /dev/ttyS0 as the default console is because it's the easiest way to suppress a lot of messages that I don't want the user to see.

At this time you should configure the kernel for your target hardware, and make bzImage to build it. Once the build is finished (assuming the current directory is your kernel build directory):

cp arch/i386/boot/bzImage /mnt/bootdisk/LINUX

Now, we need to build the root filesystem for the initial RAM disk. To save you time, I've built a fairly complete root filesystem for you (Note - this downloadable file is NOT a bootable initrd image!). When you extract this tarball, you'll get a directory called rootfs and a shell script called mkroot.sh. The contents of this shell script are as follows:

#!/bin/bash
umount /mnt
dd if=/dev/zero of=initrd.img.expanded bs=1k count=4096
echo y | mke2fs -m 0 -N 2000 initrd.img.expanded
mount -t ext2 -o loop initrd.img.expanded /mnt
cp -a --reply=yes rootfs/* /mnt
umount /mnt
dd if=initrd.img.expanded bs=1k | gzip -v9 > initrd.img
rm initrd.img.expanded

What this script does is create a temporary disk image file in ext2 format, and copy the contents of the rootfs directory into it. It then compresses the disk image to a file called initrd.img and deletes the uncompressed copy.


larwe.com and all original content herein is © Copyright 2003 by Lewin A.R.W. Edwards. "larwe.com" is a trademark protected under U.S. and international law. Infringement or attempted dilution of the intellectual property rights held by Lewin A.R.W. Edwards will be prosecuted to the fullest possible extent.