Table of Contents
In the previous chapter it might seem like we did not accomplish very much. A lot of energy was expended redesigning the root disk, but the functionality is basically the same as in the initial prototype phase. The root disk still does not do very much. But we did make significant improvements when it comes to space savings. In this chapter we will put that extra space to good use and start cramming the root disk with as many utilities as it can hold.
The first two root disks we built only had shell built-in commands like echo and pwd. This time it would be nice to have some of the commonly used external commands like cat, ls, mkdir, rm and such on the root disk. Keeping this in mind we can define the goals for this phase as follows:
Retain all of the functionality from the previous root disk.
Add some of the commonly used external commands.
The first question that might come to mind is, "How do we know which commands are needed?" It is possible to just start with cat and ls then install other commands as we discover a need for them. But this is terribly inefficient. We need a plan or a blueprint to work from. For this we can turn to the Filesystem Hierarchy Standard (FHS) available from http://www.pathname.com/fhs/. The FHS dictates which commands should be present on a Linux system and where they should be placed in the directory structure.
The next logical question is, "Now that we know what we need, where do we get the source code?" One way to find the answer to this question is to check the manpages. We can either search the manpages included with one of the popular GNU/Linux distributions or use one of the manpage search engines listed at http://www.tldp.org/docs.html#man. One thing that should tip us off as to where to find the source code for a particular command is the email address listed for reporting bugs. For example the cat manpage lists bug-textutils@gnu.org. From this email address we can deduce that cat is part of the textutils package from GNU.
So let's look at the FHS requirements for the /bin directory. The first few commands in the list are cat, chgrp, chmod, chown and cp. We already know that cat is part of GNU's textutils. Using the next few commands as keywords in a manpage search we discover that we need GNU's fileutils package for chmod, chgrp, chown and cp. In fact quite a few of the commands in /bin come from GNU's fileutils. The date command also comes from a GNU package called sh-utils. So a good way to tackle the problem of finding source code might be to group the commands together by package as shown below.
The BASH shell -- echo, false, pwd, sh, true
GNU textutils -- cat
GNU fileutils -- chgrp, chmod, chown, cp, dd, df, ln, ls, mkdir, mknod, mv, rm, rmdir, sync
GNU sh-utils -- date, hostname, stty, su, uname
These four packages do not contain all of the commands in the /bin directory, but they do represent of over 70% of them. That should be enough to accomplish our goal of adding some of the commonly used external commands. We can worry about the other commands in later phases of the project.
To fetch the source code we simply need to connect to GNU's FTP site and navigate to the appropriate package directory.
When we get to the directory for textutils there are several versions available. There is also a note informing us that the package has been renamed to coreutils. The same message about coreutils appears in the fileutils and sh-utils directories as well. So instead of downloading three separate packages we can get everything in one convenient bundle in the coreutils directory.
Rather than copying files directly to the ramdisk, we can make things easier by setting up a staging area. The staging area will give us room to work without worrying about the space constraints of the ramdisk. It will also provide a way to save our work and make it easier to enhance the rootdisk in later phases of the project.
The staging procedure will work like this:
Create a directory structure as defined in the FHS.
Copy in the files from phase 2's root disk.
Build the new package from source code.
Install files into the correct FHS directories.
Strip the binaries to save space.
Check library dependencies.
Copy to the whole directory structure to the ramdisk.
Compress the ramdisk and write it out to floppy.
bash# mkdir ~/staging bash# cd ~/staging bash# mkdir bin boot dev etc home lib mnt opt proc root sbin tmp usr var bash# mkdir var/log var/run
bash# dd if=~/phase2-image.gz | gunzip -c > /dev/ram7 bash# mount /dev/ram7 /mnt bash# cp -dpR /mnt/* ~/staging bash# umount /dev/ram7 bash# rmdir ~/staging/lost+found
Download a recent version of coreutils from ftp://ftp.gnu.org/gnu/coreutils/
bash# cd /usr/src/coreutils-5.2.1 bash# export CC="gcc -mcpu=i386" bash# ./configure --host=i386-pc-linux-gnu bash# make bash# cd src bash# cp cat chgrp chmod chown cp date dd df ~/staging/bin bash# cp hostname ln ls mkdir mkfifo mknod ~/staging/bin bash# cp mv rm rmdir stty su sync uname ~/staging/bin
Check library requirements by using ldd on some of the new binaries.
bash# ldd ~/staging/bin/cat bash# ldd ~/staging/bin/ls bash# ldd ~/staging/bin/su bash# ls ~/staging/lib
Note the differences in the required libraries, as shown by the ldd command, and the libraries present in the staging area, as shown by the ls command, then copy any missing libraries to the staging area.
bash# cp /lib/librt.so.1 ~/staging/lib bash# cp /lib/libpthread.so.0 ~/staging/lib bash# cp /lib/libcrypt.so.1 ~/staging/lib
bash# strip ~/staging/bin/* bash# strip --strip-unneeded ~/staging/lib/*
bash# cd / bash# dd if=/dev/zero of=/dev/ram7 bs=1k count=4096 bash# mke2fs -m0 /dev/ram7 4096 bash# mount /dev/ram7 /mnt bash# cp -dpR ~/staging/* /mnt bash# umount /dev/ram7 bash# dd if=/dev/ram7 of=~/phase3-image bs=1k count=4096 bash# gzip -9 ~/phase3-image
The process for creating the compressed root disk image will change very little throughout the remaining chapters. Writing a small script to handle this function can be a great time saver.
We will need to have a read-write filesystem in order for some of the commands to work. The kernel's normal behavior is to mount root as read-only, but we can change this using a kernel option. By passing the kernel the rw option before init=/bin/sh we will get a read-write root filesystem.
Follow these steps to get the system running.
Boot the PC from using the GRUB boot disk.
At the grub> prompt, type kernel (fd0)/boot/vmlinuz rw init=/bin/sh root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1.
Verify that you remembered to add the rw parameter and press Enter.
Type boot and press Enter.
Insert the recently created root disk when prompted.
The terminal display should look similar to the example below.
GNU GRUB version 0.95 grub> kernel (fd0)/boot/vmlinuz rw init=/bin/sh root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1 [Linux-bzImage, setup=0xc00, size=0xce29b] grub> boot Linux version 2.4.26 .. .. [various kernel messages] .. VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER RAMDISK: Compressed image found at block 0 VFS: Mounted root (ext2 filesystem) read-write. Freeing unused kernel memory: 178k freed # _
Now that the system is up and running, try using some of the new commands.
bash# uname -a bash# ls /etc bash# echo "PocketLinux" > /etc/hostname bash# hostname $(cat /etc/hostname) bash# uname -n bash# mkdir /home/stuff bash# cd /home/stuff
If everything goes well the commands like cat, ls and hostname should work now. Even mkdir should work since the root filesystem is mounted read-write. Of course since we are using a ramdisk, any changes will be lost once the PC is reset.