Previous Next Contents

3. Components

3.1 File Systems

The Linux kernel now supports two file system types for root disks to be automatically copied to ramdisk. These are minix and ext2, of which ext2 is the preferred file system. The ext2 support was added sometime between 1.1.17 and 1.1.57, I'm not sure exactly which. If you have a kernel within this range then edit /usr/src/linux/drivers/block/ramdisk.c and look for the word "ext2". If it is not found, then you will have to use a minix file system, and therefore the "mkfs" command to create it. If using ext2, then you may find it useful to use the -i option to specify more inodes than the default; -i 2000 is suggested so that you don't run out of inodes. Alternatively, you can save on inodes by removing lots of unnecessary /dev files. Mke2fs will by default create 360 inodes on a 1.44Mb diskette. I find that 120 inodes is ample on my current rescue root diskette, but if you include all the devices in the /dev directory then you will easily exceed 360. Using a compressed root filesystem allows a larger filesystem, and hence more inodes by default, but you may still need to either reduce the number of files or increase the number of inodes.

To create an ext2 file system on a diskette on my system, I issue the following command:

        mke2fs -m 0 /dev/fd0

The mke2fs command will automatically detect the space available and configure itself accordingly. If desired, the diskette size in 1Kb blocks can be specified to speed up mke2fs operation. The -m 0 parameter prevents it from reserving space for root, and hence provides more usable space on the disk.

An easy way to test the result is to create a system using the above command or similar, and then attempt to mount the diskette. If it is an ext2 system, then the command:

        mount -t ext2 /dev/fd0 /<mount point>
should work.

3.2 Kernel

Building a Custom Kernel

In most cases it would be possible to copy your current kernel and boot the diskette from that. However there may be cases where you wish to build a separate one.

One reason is size. The kernel is one of the largest files in a minimum system, so if you want to build a boot/root diskette, then you will have to reduce the size of the kernel as much as possible. The kernel now supports changing the diskette after booting and before mounting root, so it is not necessary any more to squeeze the kernel into the same disk as everything else, therefore these comments apply only if you choose to build a boot/root diskette.

There are two ways of reducing kernel size:

Having worked out a minimum set of facilities to include in a kernel, you then need to work out what to add back in. Probably the most common uses for a boot/root diskette system would be to examine and restore a corrupted root file system, and to do this you may need kernel support.

For example, if your backups are all held on tape using Ftape to access your tape drive, then, if you lose your current root drive and drives containing Ftape, then you will not be able to restore from your backup tapes. You will have to reinstall Linux, download and reinstall Ftape, and then try and read your backups.

It is probably desirable to maintain a copy of the same version of backup utilities used to write the backups, so that you don't waste time trying to install versions that cannot read your backup tapes.

The point here is that, whatever I/O support you have added to your kernel to support backups should also be added into your boot/root kernel.

The procedure for actually building the kernel is described in the documentation that comes with the kernel. It is quite easy to follow, so start by looking in /usr/src/linux. Note that if you have trouble building a kernel, then you should probably not attempt to build boot/root systems anyway.

3.3 Devices

A /dev directory containing a special file for all devices to be used by the system is mandatory for any Linux system. The directory itself is a normal directory, and can be created with the mkdir command in the normal way. The device special files, however, must be created in a special way, using the mknod command.

There is a shortcut, though --- copy your existing /dev directory contents, and delete the ones you don't want. The only requirement is that you copy the device special files using the -R option. Warning: The cp command supplied with the most recent version of fileutils (3.13) is reported not to respect the -R flag. This will copy the directory without attempting to copy the contents of the files. Note that if you use lower caser, as in "-r", there will be a vast difference, because you will probably end up copying the entire contents of all of your hard disks - or at least as much of them as will fit on a diskette! Therefore, take care, and use the command:

        cp -dpR /dev /mnt
assuming that the diskette is mounted at /mnt. The dp switches ensure that symbolic links are copied as links (rather than the target file being copied) and that the original file attributes are preserved, thus preserving ownership information.

You can also use the -p option of cpio, because cpio will handle device special files correctly, and not try and copy the contents. For example:

        cd /dev
        find . -print | cpio -pmd /mnt/dev

will copy all device special files from /dev to /mnt/dev. In fact it will copy all files in the directory tree starting at /dev, and will create any required subdirectories in the target directory tree.

If you want to do it the hard way, use ls -l to display the major and minor device numbers for the devices you want, and create them on the diskette using mknod.

Many distributions include a shell script called MAKEDEV in the /dev directory. This shell script could be used to create the devices, but it is probably easier to just copy your existing ones, especially for rescue disk purposes.

Whichever way the device directory is copied, it is worth checking that any special devices you need have been placed on the rescue diskette. For example, Ftape uses tape devices, so you will need to copy all of these.

Note that an inode is required for each device special file, and inodes can at times be a scarce resource, especially on diskette filesystems. It therefore makes sense to remove any device special files that you don't need from the diskette /dev directory. Many devices are obviously unnecessary on specific systems. For example, if you do not have SCSI disks, then you can safely remove all the device files starting with "sd". Similarly, if you don't intend to use your serial port then all the device files starting with "cua" can go.

3.4 Directories

It might be possible to get away with just /dev, /proc and /etc to run a Linux system. I don't know - I've never tested it. However it will certainly be difficult, because without shared libraries all your executables would have to be statically linked. A reasonable minimum set of directories consists of the following:

/dev

Required to perform I/O with devices

/proc

Required by the ps command

/etc

System configuration files

/bin

Utility executables considered part of the system

/lib

Shared libraries to provide run-time support

/mnt

A mount point for maintenance on other disks

/usr

Additional utilities and applications

Note that the directory tree presented here is for root diskette use only. Refer to the Linux File System Standard for much better information on how file systems should be structured in "standard" Linux systems.

Four of these directories can be created very easily:

The remaining 3 directories are described in the following sections.

/etc

This directory must contain a number of configuration files. On most systems, these can be divided into 3 groups:

Files which are not essential can be identified with the command:

        ls -ltru
This lists files in reverse order of date last accessed, so if any files are not being accessed, then they can be omitted from a root diskette.

On my root diskettes, I have the number of config files down to 15. This reduces my work to dealing with three sets of files:

Out of this, I only really have to configure two files, and what they should contain is surprisingly small.

Inittab should be ok as is, unless you want to ensure that users on serial ports cannot login. To prevent this, comment out all the entries for /etc/getty which include a ttys or ttyS device at the end of the line. Leave in the tty ports so that you can login at the console.

Inittab defines what the system will run or rerun in various states including startup, move to multi-user mode, powerfail, and others. A point to be careful of here is to carefully check that the commands entered in inittab refer to programs which are present and to the correct directory. If you place your command files on your rescue disk using the sample directory listing in this HOWTO as a guide, and then copy your inittab to your rescue disk without checking it, then the probability of failure will be quite high, because half of the inittab entries will refer to missing programs or to the wrong directory.

It is worth noting here as well that some programs cannot be moved from one directory to another or they will fail at runtime because they have hardcoded the name of another program which they attempt to run. For example on my system, /etc/shutdown has hardcoded in it /etc/reboot. If I move reboot to /bin/reboot, and then issue a shutdown command, it will fail because it can't find the reboot file.

For the rest, just copy all the text files in your /etc directory, plus all the executables in your /etc directory that you cannot be sure you do not need. As a guide, consult the sample ls listing in "Sample Boot/Root ls-lR Directory Listing" - this is what I have, so probably it will be sufficient for you if you copy only those files - but note that systems differ a great deal, so you cannot be sure that the same set of files on your system is equivalent to the files on mine. The only sure method is to start with inittab and work out what is required.

Most systems now use an /etc/rc.d directory containing shell scripts for different run levels. The absolute minimum is a single rc script, but it will probably be a lot simpler in practice to copy the inittab and /etc/rc.d directory from your existing system, and prune the shell scripts in the rc.d directory to remove processing not relevent to a diskette system environment.

/bin

Here is a convenient point to place the extra utilities you need to perform basic operations, utilities such as ls, mv, cat, dd etc.

See the section titled "Sample Boot/Root ls-lR Directory Listing" for the list of files that I place in my boot/root /bin directory. You may notice that it does not include any of the utilities required to restore from backup, such as cpio, tar, gzip etc. That is because I place these on a separate utility diskette, to save space on the boot/root diskette. Once I have booted my boot/root diskette, it then copies itself to the ramdisk leaving the diskette drive free to mount another diskette, the utility diskette. I usually mount this as /usr.

Creation of a utility diskette is described below in the section titled "Adding Utility Diskettes".

/lib

In /lib you place necessary shared libraries and loaders. If the necessary libraries are not found in your /lib directory then the system will be unable to boot. If you're lucky you may see an error message telling you why.

Nearly every program requires at least the libc library:

        libc.so.X
where X is the current version number. Check your /lib directory. Note that libc.so.4 may be a symlink to a libc library with version number in the filename. If you issue the command:
        ls -l /lib
you will see something like:
        libc.so.4 -> libc.so.4.5.21

In this case, the libc library you want is libc.so.4.5.21. This is an example only - the ELF libc library is currently libc.so.5.xxxx.

To find other libraries you should go through all the binaries you plan to include and check their dependencies. You can do this with ldd command. For example, on my system the command:

        ldd /bin/mount
produces the output:
        /bin/mount:
                libc.so.5 => /lib/libc.so.5.2.18
indicating that /bin/mount needs the library libc.so.5, which is a symbolic link to libc.so.5.2.18.

In /lib you must also include one or more loaders to load the libraries. The loader file is either ld.so (for a.out libraries) or ld-linux.so (for ELF libraries). If you're not sure which you need, run the "file" command on the library. For example, on my system:

        file /lib/libc.so.5.2.18
tells me:
        /lib/libc.so.5.2.18: ELF 32-bit LSB shared object ...
so it needs an ELF loader. If you have an a.out library you'll instead see something like:
        /lib/libc.so.4.7.2: Linux/i386 demand-paged executable (QMAGIC) ...

Copy the specific loader(s) you need.

Libraries and loaders should be checked carefully against the included binaries. If the kernel cannot load a necessary library, the kernel will usually hang with no error message.

3.5 LILO

Overview

For the boot/root to be any use, it must be bootable. To achieve this, the easiest way is to install a boot loader, which is a piece of executable code stored at sector 0, cylinder 0 of the diskette. See the section above titled "BOOT DISKETTE" for an overview of the boot process.

LILO is a tried and trusted boot loader available from any Linux mirror site. It allows you to configure the boot loader, including:

Sample LILO Configuration

This provides a very convenient place to specify to the kernel how it should boot. My root/boot LILO configuration file, used with LILO 0.15, is:


boot = /dev/fd0
install = ./mnt/boot.b
map = ./mnt/lilo.map
delay = 50
message = ./mnt/lilo.msg
timeout = 150
compact
image = ./mnt/zImage 
        ramdisk = 1440
        root = /dev/fd0

Note that I have not tested this recently, because I no longer use LILO-based boot/root diskettes. There is no reason to suppose that it does not still work, but if you try it and it fails, you must read the LILO documentation to find out why.

Note also that boot/root systems no longer rely on LILO, because since 1.3.48, the kernel supports loading a compressed root filesystem from the same diskette as the kernel. See section Advanced Bootdisk Creation for details.

If you have a kernel later than 1.3.48, the "ramdisk = 1440" line is unnecessary and should be removed.

Note that boot.b, lilo.msg and the kernel must first have been copied to the diskette using a command similar to:


cp /boot/boot.b ./mnt

If this is not done, then LILO will not run correctly at boot time if the hard disk is not available, and there is little point setting up a rescue disk which requires a hard disk in order to boot.

I run lilo using the command:

        /sbin/lilo -C <configfile>

I run it from the directory containing the mnt directory where I have mounted the diskette. This means that I am telling LILO to install a boot loader on the boot device (/dev/fd0 in this case), to boot a kernel in the root directory of the diskette.

I have also specified that I want the root device to be the diskette, and I want a ramdisk created of 1440 1K blocks, the same size as the diskette. Since I have created an ext2 file system on the diskette, this completes all the conditions required for Linux to automatically switch the root device to the ramdisk, and copy the diskette contents there as well.

The ramdisk features of Linux are described further in the section above titled "RAM DISKS AND BOOT/ROOT SYSTEMS".

It is also worth considering using the "single" parameter to cause Linux to boot in single-user mode. This could be useful to prevent users logging in on serial ports.

I also use the "DELAY" "MESSAGE" and "TIMEOUT" statements so that when I boot the disk, LILO will give me the opportunity to enter command line options if I wish. I don't need them at present, but I never know when I might want to set a different root device or mount a filesystem read-only.

The message file I use contains the message:

Linux Boot/Root Diskette
========================
 
Enter a command line of the form:

      zImage [ command-line options]

If nothing is entered, linux will be loaded with
defaults after 15 seconds.

This is simply a reminder to myself what my choices are.

Readers are urged to read the LILO documentation carefully before atttempting to install anything. It is relatively easy to destroy partitions if you use the wrong "boot = " parameter. If you are inexperienced, do NOT run LILO until you are sure you understand it and you have triple-checked your parameters.

Note that you must re-run LILO every time you change the kernel, so that LILO can set up its map file to correctly describe the new kernel file. It is in fact possible to replace the kernel file with one which is almost identical without rerunning LILO, but it is far better not to gamble - if you change the kernel, re-run LILO.

Removing LILO

One other thing I might as well add here while I'm on the LILO topic: if you mess up lilo on a drive containing DOS, you can always replace the boot sector with the DOS boot loader by issuing the DOS command:

        FDISK /MBR

where MBR stands for "Master Boot Record". Note that some purists disagree with this, and they may have grounds, but it works.

Useful LILO Options

LILO has several useful options which are worth keeping in mind when building boot disks:


Previous Next Contents