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
- Prompt for development and/or incomplete code/drivers
Loadable module support
- Enable loadable module support (Required if you know what modules are and how to use them otherwise disable it)
- Set version information on all module symbols (A good idea if the previous option is selected)
- Kernel module loader (Also a good idea if module support is enabled)
Processor type and features
- Processor family (Option: select the lowest processor module you think you will use this linux disk for, a Pentium-Classic kernel probably won't run on a 386)
- Math emulation (Required for computers without math coprocessors, e.g. 386,486SX)
General setup
- Networking support (Required if you plan on placing the compute on a network of any sort use this)
- PCI support (Required: A number of network cards and disk controllers are on PCI so best to use this)
- ISA support (Required only if you will be using ISA cards)
- PCI device name database (Disable unless you really need to see PCI device names, it uses up 80kb)
- Sysctl support (Required: some applets in busybox need this)
- Kernel support for ELF binaries
Plug and Play configuration
- Plug and Play support (Possibly Required on certain PCI or ISA cards)
- ISA Plug and Play support (Possibly Required for PnP ISA cards)
Block devices
- Normal floppy disk support
- RAM disk support
- Default RAM disk size (4096 is good)
- Initial RAM disk (initrd)
Networking options
- Packet socket (Useful if you want to run tcpdump or other packet sniffer, not required otherwise)
- Unix domain sockets
- TCP/IP networking (Required if you want to be on a network)
- IP: multicasting (Probably not needed but could be useful for creating a workstation which can receive multicasted audio or video)
ATA/IDE/MFM/RLL support
- ATA/IDE/MFM/RLL support (Required if you want to access Hard Drives and other IDE drives)
- IDE, ATA and ATAPI Block devices
- Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support (Required for IDE drives)
- Include IDE/ATA-2 DISK support (Required for IDE Hard drive)
- Include IDE/ATAPI CDROM support (Required for IDE CDrom drive)
- Generic PCI IDE chipset support (Required for PCI IDE controller)
SCSI support
- SCSI support (Required for SCSI drives and some USB drives using SCSI generic support)
- SCSI disk support (Required for SCSI disks)
- SCSI generic support (Required for some USB drives)
- SCSI low-level drivers (Select your SCSI controller from here if you need supports)
Network device support
- Ethernet (10 or 100Mbit) (Select your network card from the drivers here)
- Ethernet (10 or 100Mbit) (Required for network card support)
Input core support
- Input core support (Required for USB keyboard or USB mouse)
- Keyboard support (Required for USB keyboard)
- Mouse support (Required for USB mouse)
Character devices
- Virtual terminal (Required)
- Support for console on virtual terminal (Required for error messages to be displayed on screen)
- Unix98 PTY support (Required)
- Mice (Required for non USB/Serial mice)
- Mouse Support (For PS/2 and other odd mice interfaces)
File systems
- Reiserfs support (Required to access reiserfs journalling filesystems)
- Ext3 journalling file system support (Required for ext3 journalling filesystems)
- DOS FAT fs support (Required to access DOS filesystems)
- MSDOS fs support (Required for old DOS filesystems)
- VFAT (Windows-95) fs support (Required for long filename support Windows filesystems)
- ISO 9660 CDROM file system support (Required to mount CDs)
- Microsoft Joliet CDROM extensions (Required for CD with long filenames)
- Minix fs support (Required: this is what we will use for our root filesystem)
- NTFS file system support (read only) (Required to read Windows NT/2000 filesystems)
- /proc file system support (Required)
- /dev file system support (EXPERIMENTAL) (Required: this is only available for 2.4 kernel you must manually make the devices with a 2.2 kernel)
- Automatically mount at boot (Required)
Console drivers
- VGA text console (Required)
USB support
- Support for USB
- UHCI (Intel PIIX4, VIA, ...) support (Required for USB keyboard)
- OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support (Required for USB keyboard)
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
- Enable floating point number support
- Enable full C99 math library support ( I'm using this for tinycc compiler)
Linux kernel header location (Set this to the location of the source used to create your floppy kernel)
General Library Settings
- Generate Position Independent Code
- Enable support for shared libraries (This will let us dynamically link our programs to this library)
- Compile native shared library loader
- Native shared library loader 'ldd' support
- POSIX Threading Support (Required for pthreads support)
- Assume that /dev/pts is a devpts or devfs file system
Networking Support
- Remote Procedure Call (RPC) support (If NFS is required)
Library Installation Options
- Shared library loader path (/lib)
- uClibc development environment (/<YOUR-DEVEL-DIR>/$(TARGET_ARCH)-linux-uclibc)
(Where <YOUR-DEVEL-DIR> is a location that you can run the uclibc compiler from later.)
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
- Support --install [-s] to install applet links at runtime
- Support for devfs
- Use the devpts filesystem for Unix98 PTYs
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
- DNAT destination network address translation (useful for redirecting external addresses to internal services)
- SNAT source network address translation (for masquerading a single internal ip address as an external address
- MASQUERADE (for masquerading internal addresses as an external, possibly dynamic, address
- LOG (to log iptables stats)
- REJECT (for denying packets and sending a rejection response)
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)
- Create a working directory for the CD image
mkdir linux-cd
- 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
- 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
- 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/
- Burn the yourdisk.iso image to CD and boot