Building a Minimal Linux System

Introduction

The application the Netwinders are to be used in specifies no hard drive and no network connection. So, since we have to boot our system out of flash, we need to determine the minimum amount of Linux required to actually do something useful. This is broken up in to several stages which can be added or ignored depending on your needs.

This system is based on RedHat version 5.2 as the .rpm files are readily available on ftp.netwinder.org. I'm sure that other distributions will work just as well but I am more familiar with RedHat. I've found that I've learnt a bit about how Linux works by doing this and I hope other people can derive something useful out of it.

Thanks to Mike Montour for his NFS Rescue Package for lots of tips on getting started and having a working system to play with.

Table of Contents

Using RPM to locate and extract files

The best tool for setting up a system like this is the rpm program. Using the -qf options we can determine which package files belong to (this requires a running system unfortunately. Once we have the name of the RPM package, use rpm2cpio rpmfile.rpm | cpio -vid to extract all the files. Copy out the ones required. Note there may be a problem with any post-install scripts that are normally run when you install the RPM file. Not sure how to handle this at the moment.

Creating devices

Extract the MAKEDEV script from the MAKEDEV rpm into the /dev/ directory of your new installation. Note that since MAKEDEV creates new device nodes using mknod, this script is required to be run as root. Use MAKEDEV in turn with the arguments below to create the appropriate device files.

stdCreates "standard" devices including core, full, mem, null, port, ram, tty, and zero
ptyCreates master and slave pty devices
consoleCreates virtual console devices
fdSymbolic links for fd and stdio devices (not to be confused with floppy disk device files)

Other devices which may be of use, but not in my particular application are as follows.

ttyS0, ttyS1Serial port devices
hdaFirst IDE hard disk device files
audioSound driver devices

Note that due to the way MAKEDEV calculates the major numbers for devices, the kernel running the script needs to have those options compiled in to it. For example, you can't create the device files for the loopback or audio devices without having loopback or audio support compiled in to the currently running kernel, respectively.

A Bourne shell

Extract a version of your favourite shell into the /bin directory. If you're feeling lucky (punk) then extract a dynamically linked version. If you just want to muck around before getting the dynamic linker working then use a statically linked version. I recommend /bin/ash.static from the ash rpm package.

Writing /sbin/init

Now, the very last thing the Linux kernel does is try and execute /sbin/init which is the very first process run in user-land. From init/main.c from the kernel source code:
        /*
         * We try each of these until one succeeds.
         *
         * The Bourne shell can be used instead of init if we are 
         * trying to recover a really broken machine.
         */

        if (execute_command)
                execve(execute_command,argv_init,envp_init);
        execve("/sbin/init",argv_init,envp_init);
        execve("/etc/init",argv_init,envp_init);
        execve("/bin/init",argv_init,envp_init);
        execve("/bin/sh",argv_init,envp_init);
        panic("No init found.  Try passing init= option to kernel.");
Normally the version of init installed on a Linux system, in the case of the RedHat distribution, is the SysVinit package. This is a fairly complicated series of shell scripts in /etc/init.d involving runlevels and such. For a minimal Linux system I consider this overkill and the whole arrangement can consist of a simple shell script.

An simple example of an init script is below.

#!/bin/ash
echo Welcome to nano-linux
/bin/ash
This will present you with a (single) console shell logged in as root. Note that if you log out of it your system basically hangs. I think the kernel is still runing and scheduling processes but you may have no way of logging in. What is needed is to run ash as a login shell. According to the manual page for ash,
       If the first character of argument zero to  the  shell  is
       ``-'',  the  shell is assumed to be a login shell, and the
       files /etc/profile and .profile are read  if  they  exist.
I'm not sure how you do this from a shell script. A C program may be able to do this by fiddling with the arguments to execv().

Running dynamically linked executables

Through trial and error, I've discovered the minimum number of files required to run dynamically linked executables. The following files are required. Make the following symbolic links.
    # ln -s /lib/ld-2.0.*.so /lib/ld-linux.so.2
    # ln -s /lib/libc-2.0.*.so /lib/libc.so.6
    # ln -s /lib/ld-linux.so.2 /usr/lib/ld.so.1
The glibc RPM also contains the math library, /libm and many others which may be needed by other applications.

The /proc filesystem

Copy mount and umount from their RPM. Add the following lines to your /sbin/init script to mount the proc filesystem.
    echo >/etc/mtab
    mount /proc /proc -t proc

File and text utilities

I consider the following programs to be fairly essential in being able to get something useful done.

Networking

Presently, running ping on the minimal linux system produces the error "no such protocol: icmp" which would imply some problem in the getprotobyname() library call. I've copied across the following files but it still doesn't work. I suspect there may be some other configuration files needed (perhaps some entries in /etc/resolv.conf or /etc/nsswitch.conf plus associated libraries out of the glibc rpm to get protocol resolution working correctly. Going over the source for the getprotobyname() function will probably be instructive.

To get some more useful network things happening, the following binaries may be needed. This information can probably be retrieved or set from the /proc directory.

Virtual consoles

How to get virtual consoles working. Dunno.

Other useful packages

Other programs considered to be standard UNIX functions which you may want to add to your minimal linux system are:

Scripts

Need to write some scripts to extract files from RPMs as it would be nice to be able to copy across updated versions of RPMs and use make to rebuild the image. Doing it by hand is a bit annoying.

Other resources

Some other resources on building a minimal linux distribution include:

Notes/Ideas/TODO


Tim Potter <tpot@acsys.anu.edu.au>
Last modified: Fri Feb 26 14:04:00 EST 1999