Useful Links

The tclDisk for those who want to quickly make their own linux floppy. It's a simple linux floppy with room to grow.

Overview

This document covers the steps I take when creating a self-contained bootable linux floppy. Beginning with a kernel and a couple programs (uclibc and busybox) it is possible to make a floppy disk which will boot to a linux shell and give you access to a set of basic programs for manipulating data (vi,sed,awk,...), configuring disks (mkfs.minix,...), and creating a network workstation (ifconfig, route, httpd,...). In addition it will be possible to add other programs to the disk like GNUmp3d a streaming mp3 and ogg vorbis daemon, Xkdrive a tiny X server, and any other program that you can compile and fit on the disk.

I will begin with the basics of compiling a suitable linux kernel. Then I will walk-through creating the filesystem structure for the root partition (/) of the floppy disk. After that I will show how to make a disk image from these two parts, how to test the disk image using Bochs, and finally how to put the image on a floppy disk for use in booting a computer.

If this document happens to help you and you're feeling generous consider getting something from my Amazon wishlist

Compile the kernel

Compiling a proper kernel is important in that the options you choose depend greatly on the hardware you have and the software you plan on running. Yet it is important to keep the size of the kernel in mind as it can take up nearly half the space of a floppy disk if too many options are selected. At the end of this section I will include a config file which can be used to configure a basic kernel.

To keep the kernel small, disable everything in the kernel except the options below. The following options are either required or helpful in getting a functioning linux floppy. If you are unsure of any of the options mentioned below it is best to leave it in, get the kernel working properly, and then removing it later to see if anything breaks.

Kernel options

Code maturity level options Loadable module support Processor type and features General setup Plug and Play configuration Block devices Networking options ATA/IDE/MFM/RLL support SCSI support Network device support Input core support Character devices File systems Console drivers USB support

Example kernel config

floppy.config.v1

You can import this by selecting 'Load an Alternate Configuration File' in the kernel's make menuconfig and typing in the full path to this file.

Compile the kernel

Now compile the kernel.
make dep bzImage

Prepare you working directory

Let's start by moving to the directory you planning on working in and we'll save that location so that later instructions can use it as a reference point.
cd /<YOUR-DEVEL-DIR</
export WORKDIR=`pwd`

Create rootfs in dir

To have a useable linux system you must have a filesystem holding programs and other utilities. This will contain everything that will be placed in the root filesystem (/) after the kernel has loaded. In this section we will create required directories, startup scripts and other configurations files.

Directory structure

Start by creating a directory in which to hold the root filesystem.
mkdir rootfs
cd rootfs
Now we populate it with the required directories. The following operations should all occur in the rootfs directory.
mkdir -p etc/init.d dev lib proc var tmp bin sbin usr/bin usr/sbin
Next we create some required files.

fstab

This files lists devices with filesystems to be mounted at bootup. Execute the following within the rootfs directory.
cat > etc/fstab << EOF
none    /proc   proc    defaults        0 0
EOF
  

/etc/init.d/rcS

This file servers as the initial startup script called by the init program.
cat > etc/init.d/rcS << EOF
#!/bin/sh 
echo "Starting init script..."
echo "Mounting /proc..."
mount /proc
echo "Creating links for Busybox apps..."
busybox --install -s
EOF
chmod +x rootfs/etc/init.d/rcS
  

Programs

uClibc

uClibc is a C library similar to the GNU C Library but optimized for systems with limited resources. This makes it a perfect starting place for software on the linux floppy. Download and untar uClibc. I used version 0.9.20 for this tutorial. While the new versions may have new features it seems the compilation process has changed somewhat, so keep that in mind.
cd uClibc-version
make menuconfig
Most defaults should work fine but configure the following requirements

Target Architecture Features and Options

  • Linux kernel header location (Set this to the location of the source used to create your floppy kernel)
  • General Library Settings Networking Support Library Installation Options After exiting the configure menu and saving those options go ahead and compile
    make
    make install
    
    Copy some important uClibc libraries to the root filesystem location.
    cp <YOUR-DEVEL-DIR>/i386-linux-uclibc/lib/ld-uClibc.so.0 rootfs/lib/
    cp <YOUR-DEVEL-DIR>/i386-linux-uclibc/lib/libc.so.0 rootfs/lib/
    

    uClibc Notes

    If you compile a program using i386-linux-uclibc/usr/bin/cc or gcc and want to make sure the program is actually linked to the uClibc libraries you can do the following. Execute /usr/bin/ldd on the newly created binary. If it returns an error such as
    % /usr/bin/ldd ./iptables
    /usr/bin/ldd: line 1: ./iptables: No such file or directory' 
    
    but i386-linux-uclibc/usr/bin/ldd ./iptables gives you the list of uClibc libraries e.g.
            libdl.so.0 => /var/tmp/floppy/i386-linux/lib/libdl.so.0 (0x00000000)
            libnsl.so.0 => /var/tmp/floppy/i386-linux/lib/libnsl.so.0 (0x00000000)
            libc.so.0 => /var/tmp/floppy/i386-linux/lib/libc.so.0 (0x00000000)
            /lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)
    
    then you can be fairly confident that it is compiled correctly with uClibc.

    Busybox

    Busybox is program which includes a number of minimal versions of standard system programs (e.g. ls, ifconfig, sed, mount, init, etc...). You can get it from here

    After unpacking the source enter the busybox source directory and begin the configuration

    cd busybox-ver
    make menuconfig
    
    Configure busybox with the following suggested options and any others you would like.

    General Configuration

    Build Options
  • Do you want to build BusyBox with a Cross Compiler?
  • /<YOUR-WORK-DIR>/i386-linux-uclibc/bin/i386-uclibc-
  • Archival Utilities
  • bunzip2
  • gunzip
  • gzip
  • tar
  • Enable -z option
  • Enable support for some GNU tar extensions
  • Coreutils
  • cat
  • chmod
  • chroot
  • cp
  • dd
  • df
  • echo
  • ln
  • lsi
  • Enable symlinks dereferencing (-L)
  • Sort the file names
  • mkdir
  • mv
  • rm
  • tail
  • Utilities
  • vi (good to have a text editor but may I can imagine this taking up a bit of space)
  • Init Utilities
  • init
  • halt
  • poweroff
  • reboot
  • Linux Module Utilities (if you plan on using modules enable these)
  • insmod
  • lsmod
  • modprobe
  • rmmod
  • Networking Utilities
  • hostname
  • httpd (if you want a mini web server, can serve device files also e.g. /dev/disks/)
  • ifconfig
  • nc
  • ping
  • route
  • udhcp Server/Client (Useful for some)
  • Process Utilities
  • kill
  • ps
  • uptime
  • Another Bourne-like Shell
  • ash
  • Optimize for size instead of speed
  • command line editing (comes in handy on interactive shells)
  • System Logging Utilities
  • syslog
  • Remote Log support (this can come in handy on firewall or networked machine)
  • klogd
  • logger
  • Linux System Utilities
  • hwclock
  • more
  • mount
  • umount
  • support for loop devices
  • Exit and save the configuration program. Then compile busybox

    make
    

    Busybox example config

    Busybox-ver
    Here is an example config script to be used with busybox

    Now copy the busybox binary to your floppy root filesystem.

    cp busybox $WORKDIR/rootfs/bin
    
    Create useful links on the floppy filesystem.
    cd $WORKDIR/rootfs/bin
    ln -s busybox mount
    ln -s busybox sh
    ln -s busybox echo
    cd $WORKDIR/rootfs/sbin
    ln -s ../bin/busybox init
    
    A quick way to test this is to execute the following and watch for errors
    cp -r rootfs rootfs.test
    mount --bind /proc rootfs.test/proc/
    chroot rootfs.test /bin/sh
    busybox --install -s
    ls /bin
    exit
    
    If all goes well you should see something like this
    root@peter:/var/tmp/floppy# chroot rootfs.test/ /bin/sh
    
    
    BusyBox v1.00-pre1 (2003.08.02-06:13+0000) Built-in shell (ash)
    Enter 'help' for a list of built-in commands.
    
    # busybox --install -s
    # ls /bin
    ash       cp        echo      kill      more      ps        sh        zcat
    busybox   dd        gunzip    ln        mount     pwd       tar
    cat       df        gzip      ls        mv        rm        umount
    chmod     dmesg     hostname  mkdir     ping      rmdir     vi
    # exit   
    root@peter:/var/tmp/floppy# 
    

    Iptables

    Obtain iptables from www.netfilter.org. Compile iptables with the following command
    make CC=/<YOUR-WORK-DIR>/i386-linux-uclibc/usr/bin/cc DO_IPV6=0 KERNEL_DIR=<your_kernel_source_location> PREFIX=/usr
    <YOUR-WORK-DIR>/i386-linux/usr/bin/strip extensions/*.so
    mkdir <YOUR-WORK-DIR>/rootfs/usr/lib/iptables
    cp iptables <YOUR-WORK-DIR>/rootfs/usr/sbin
    
    Check to see what shared libraries are needed
    <YOUR-WORK-DIR>/i386-linux-uclibc/usr/bin/ldd iptables
            libdl.so.0 => /var/tmp/floppy/i386-linux/lib/libdl.so.0 (0x00000000)
            libnsl.so.0 => /var/tmp/floppy/i386-linux/lib/libnsl.so.0 (0x00000000)
            libc.so.0 => /var/tmp/floppy/i386-linux/lib/libc.so.0 (0x00000000)
            /lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)
    
    Copy over any libraries that aren't already in the root fs directory.
    cp <YOUR-WORK-DIR>/i386-linux-uclibc/lib/libdl.so.0 <YOUR-WORK-DIR>/rootfs/lib/
    cp <YOUR-WORK-DIR>/i386-linux-uclibc/lib/libnsl.so.0 <YOUR-WORK-DIR>/rootfs/lib/
    
    Now either copy all the iptables extensions
    cp extensions/libipt_*.so <YOUR-WORK-DIR>/rootfs/usr/sbin
    
    or copy just the ones you need by using the command following this list of useful modules

    cp extensions/libipt_<module>.so <YOUR-WORK-DIR>/rootfs/usr/sbin
    

    You must also copy over some linux modules or have them included in the kernel ??? which ones ??

    Others

    djbdns qmail dhcp

    pppd

    Compiling pppd with uclibc I will use this as an example of how to take an arbitrary program and try to get it working with uClibc. So instead of just giving you the straight instructions I will try to also explain some of the rational behind what I do here.

    First download and uncompress the pppd First I ran the configure with --help to see if it gave options for CC or cross compilers.

    ~$ ./configure --help
    Creating links to Makefiles.
      Makefile -> linux/Makefile.top
      pppd/Makefile -> Makefile.linux
      pppstats/Makefile -> Makefile.linux
      chat/Makefile -> Makefile.linux
      pppdump/Makefile -> Makefile.linux
    ~$
    
    No good it seems to only detect my OS and copy appropriate Makefiles, no help given in response to my argument.

    All I need is pppd so took a look at the Makefile it created in the pppd directory.

    Noticed this important section in the Makefile and set the variable for my uClibc location.

      
    # CC = gcc
    #
    CC=<YOUR-DEVEL-DIR>/i386-linux-uclibc/usr/bin/cc
    
    Hoping that is all I need to do I try to compile
    make
    
    Luckily that completed without error so I check to make sure the pppd executable is actually linked to the uClibc libraries.
    ldd: ./ppd: No such file or directory
    
    That is a good error, that is what happens when a uClibc linked executable has the non uClibc ldd run on it.

    Tried the uClibc ldd next to make sure

    ~$ <YOUR-DEVEL-DIR>/i386-linux-uclibc/usr/bin/ldd pppd
            libcrypt.so.0 => <YOUR-DEVEL-DIR>/i386-linux-uclibc/lib/libcrypt.so.0 (0x00000000)
            libdl.so.0 => <YOUR-DEVEL-DIR>/i386-linux-uclibc/lib/libdl.so.0 (0x00000000)
            libc.so.0 => <YOUR-DEVEL-DIR>/i386-linux-uclibc/lib/libc.so.0 (0x00000000)
            /lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)
    ~$
    
    That looks good, no errors and it shows me the libraries I will need to copy to my floppy root image.

    libc.so and ld-uClibc.so should already be copied but I will need to add libcrypt.so and libdl.so.

    Now we strip the executable to save space

    ~$ ls -l  pppd
    -rwxr-xr-x    1 root     root       501949 Sep 30 10:28 rootfs.v3/usr/sbin/pppd
    ~$ <YOUR-DEVEL-DIR>/i386-linux-uclibc/usr/bin/strip pppd
    ~$ ls -l  pppd
    -rwxr-xr-x    1 root     root       164752 Sep 30 10:29 rootfs.v3/usr/sbin/pppd
    

    Place the directory on a filesystem image

    Create a minix fs (4 megs in this example)
     dd if=/dev/zero of=root.img.minix bs=1k count=4096
    /sbin/mkfs.minix root.img.minix
    
    Mount the image so that you can copy the root filesystem to it
    mount root.img.minix /mnt/floppy/ -o loop
    cp -rv rootfs/* /mnt/floppy/
    umount /mnt/floppy/
    
    Compress the root image
    gzip -9 root.img.minix
    
    Create a floppy sized image
    dd if=/dev/zero of=disk.img bs=1k count=1440
    

    Method 1 - Kernel boot loader

    Place the kernel on the disk image
    dd if=bzImage of=disk.img conv=notrunc
    
    Place the root filesystem onto the disk image
    dd if=root.img.minix.gz of=disk.img bs=1k seek=`du -k bzImage|awk '{print $1}'` conv=notrunc
    
    Tell the kernel on the disk image what device holds the root filesystem
    rdev disk.img /dev/fd0
    
    Tell the kernel where on the disk image the root image begins.
    SKIP=`du -k bzImage|awk '{print $1}'`;rdev -r disk.img `expr 16384 + $SKIP`
    
    Tell the kernel to mount the root disk read-write.
    rdev -R disk.img 0
    

    Method 2 - Syslinux

    Syslinux provides a little more expandability over the first method. It is easier to add files to a syslinux floppy since it is a dos formatted disk.
    /sbin/mkfs.msdos disk.img
    syslinux disk.img
    mount disk.img /mnt/floppy -o loop
    cp bzImage /mnt/floppy/linux
    
    Add the following line to /mnt/floppy/syslinux.cfg
    APPEND load_ramdisk=1 initrd=root.img root=/dev/ram0 rw
    
    Copy a root image to the floppy
    cp root.fs.gz /mnt/floppy/root.img
    
    Unmount the floppy
    umount /mnt/floppy
    

    Placing the image on an actual floppy

    dd if=disk.img of=/dev/fd0
    

    Placing image on CD

    If you have followed the syslinux image method then placing you linux system on a cdrom should be fairly easy. I am not positive of the kernel requirements but I would make sure you have built in support for an IDE or SCSI controller and for IDE of SCSI CD-Rom drives. Also it would probably be a good idea to include Filesystems->ISO9660 support. (With this you could mount a disk full of larger programs for example)

    The basic steps are as follows (assuming you have used the syslinux method above)

    1. Create a working directory for the CD image
              mkdir linux-cd
              
    2. Place all your files from the syslinux floppy in that directory (assuming you have mounted your syslinux floppy to /mnt/floppy)
              cp /mnt/floppy/linux linux-cd/linux
              cp /mnt/floppy/root.img linux-cd/root.img
              cp /mnt/floppy/syslinux.cfg linux-cd/isolinux.cfg
              
    3. Copy the isolinux.bin file from your system to the CD image dir (this file is included with the syslinux package but it's location may vary so your best bet is to search for it. e.g. 'locate isolinux.bin')
               cp /usr/lib/syslinux/isolinux.bin linux-cd/isolinux.bin
              
    4. Use mkisofs (part of cdrtools)to create the CD image
               mkisofs -o yourdisk.iso -b isolinux.bin \
                       -no-emul-boot -boot-load-size 4 \
                       -boot-info-table linux-cd/
              
    5. Burn the yourdisk.iso image to CD and boot