+--------------
| Installation.
+--------------

Apply the patch to the kernel source (if you are not running 1pl3,
you may need to do a little manual patching, although it should
patch anything above pl15b cleanly):

	(cd /usr/src/linux ; patch -s -p0) < diff-1.03

Do a `make config' and specify the minimum necessary for your hardware
setup (eg, no need to include sound support on an emergency boot disk).
Do a `make dep' to set up all the dependencies - if nothing breaks, pop
a floppy into /dev/fd0 and do a `make zdisk'.

+-------------
| Quick Start.
+-------------

For more detailed instruction on what's going on, see the next
section.  If you want a compressed ramdisk right now, read on.

    1.	Build a bootable disk as outlined above.
    2.	Unmount your swap partition (no swap?  See next section):
		swapoff -a
    3.	Create a 4Mb minix filesystem on your swap device:
		mkfs.minix /dev/<whatever> 4096
    4.	Mount the new filesystem:
		mount -t minix /dev/<whatever> /mnt
    5.	Copy the files you want onto the new partition.  At
	a bare minimum, you'll probably want
		/mnt/etc/{init,inittab,getty}
		/mnt/bin/sh
		/mnt/sbin/{mkfs*,fsck*,fdisk,dd,mount,umount}
	Don't forget the shared libs if the programs you copy
	use them.  Don't forget to adjust startup files as
	needed (etc/rc, etc/inittab, etc/fstab).

	Of course, you can fit a lot more than this on the disk.
	I've included a list of the contents of my bootdisk at
	the end of this document.
    6.	Unmount the partition:
		umount /dev/<whatever>
    7.	Write the filesystem to the floppy:
		makefsz /dev/<whatever> - | writefsz -
    8.	Reboot.


+--------------------------------------------------------------
| On the Care and Feeding of the Compressed RAMDISK (CRAMDISK).
+--------------------------------------------------------------

CRAMDISK is a modified ramdisk loader.  The normal ramdisk loads a minix
filesystem from one of two spots on the floppy, setting the root dev to
the ramdisk after a successful load.  In this way, a self contained
Linux system can live on a single floppy.

The major drawback to this scheme is that the useable space on a ramdisk
is limited to the size of the filesystem that can be placed on a floppy.
This is either 1.4Mb or 928k, depending on where the filesystem image is
located on the floppy (assuming 3.5", less for 5.25").  If you have
built an emergency boot disk, you will know how difficult it is to stuff
enough utilities into 1.2Mb to recover from a major crash.  The ramdisk
is also constrained to use the minix filesystem.

CRAMDISK circumvents these problems by allowing the user to create a
filesystem, compress it with gzip, and write it to a floppy disk along
with a pointer to its starting position.  When booted, the kernel
creates a ramdisk in the normal manner, and then decompresses the
filesystem image, writing it to the ramdisk.  This allows any filesystem
type to be used in the ramdisk, and a ramdisk of any size.  Of course,
the decompressed filesystem must match the size of the ramdisk - if the
image is too large, the decompress will fail, too small and precious RAM
will be wasted.

The code uses the word at offset 502 in the boot block to determine
whether or not to attempt to load a compressed file system.  This offset
is better known as SWAPDEV, although for a kernel configured with
CRAMDISK, a non zero value in this field is the starting block of the fs
image.  It doesn't appear to be used in current versions of the kernel,
which is why I reassigned its use.  However, I've been told that it will
be used in upcoming releases.  This shouldn't be a problem, as it would
be unwise for an emergency bootdisk to use a default value for a
resource like swap space.  The upshot is that if you compile the code
with CRAMDISK configured, offset 502 is the starting point of the fs
image; without CRAMDISK configured, it contains SWAPDEV.

CRAMDISK increases the kernel size by about 8K.

Building a compressed file system image
---------------------------------------

The intent here is to build a filesystem that contains as many useful
programs as will fit on a floppy disk.  The final tally will depend on
the compressibility of the programs you put in the filesystem.  My
bootdisk has 3.5Mb of programs in a 4Mb filesystem, which compresses to
about 1.1Mb.  This leaves 557k free on the ramdisk, although I have a
number of shell functions for killing selected portions - for example,
removing the networking stuff leaves about 1.2Mb free on the ramdisk.

The first thing to do is find a place in which to build the filesystem.
If you have a spare partition, you're set.  If not, you can temporarily
reuse the swap partition, or as a last resort, use the loop patches
from Werner Almesberger/Theodore Ts'o to mount a file.  The advantage
of using a partition is that you can boot from it to check that it is
actually bootable.

Decide on the type of filesystem you want to create.  I personally use
minix because it has a low overhead.

Create a filesystem on the device you are using.  This means determining
what size fs you want to build.  I normally use a 4Mb fs because a) I
have only 8Mb and b) the most I can cram onto a floppy is about 3.7Mb.
However, this depends on the compressibility of the programs you use in
the filesystem.  Note that if you have sufficient RAM, there is no
reason you can't create a larger filesystem containing a lot of free
space.  The unsused portion of the fs will occupy very little of the
floppy because of the compression.

Mount the filesystem and copy the files you want onto it.  Since this is
to be a bootable image, you will need /bin/sh, /etc/init and support
files.  Choices after the essentials will differ depending on what the
disk is to be used for.  After copying the disk repair utilities I
needed to the filesystem for my disk, I found I had enough space left to
build a general purpose Linux disk, so as well as fsck*, mkfs*, dd, bpe,
etc, I added text utilities (less, sort, head, wc, etc), general system
stuff (ls, touch, mkdir, ps), communications (rz, sz, minicom, getty),
networking (ftp, telnet, rlogin), compression (gzip) and interpreters
(awk, perl).  This pretty much gives me linux on a disk.  I can use this
as a system recovery tool, to show linux to newbies, or to evaluate how
well linux will run on new hardware.

Some tips: I found it best to use shared libraries.  A program can be
checked for shared lib usage with `ldd progname' - no output means the
file is statically linked (ie, doesn't use shared libraries).  Generally
recompiling (without -g in the link phase) will generate a shared
library version, and is usually worth it - for example, it shaves 77k
off tar.  Try to find versions of the programs you want to use that are
small in size.  pdksh weighs in at 200k less than bash, yet contains
most of the functionality.

If you are building on a partition, don't forget to try actually booting
from this partition.  This will ensure that you have configured the
startup files correctly.

When you're happy with the contents of the filesystem, compress it.  The
included script `makefsz' will do this for you, but here are the steps:

	1.	Mount the filesystem and tar everything off.
	2.	Unmount the filesystem.
	3.	Wipe the partition clean (dd if=/dev/zero).
	4.	Make a file system on the partition.
	5.	Remount the filesystem.
	6.	Untar onto the filesystem.
	7.	Unmount the filesystem.
	8.	Pipe the filesystem image through gzip.

The purpose of scrubbing the partition and then reinstalling the files
with tar is to make sure that all unused space on the filesystem is
zero-filled.  This ensures that compression will be optimum.

makefsz take two parameters, a third being optional.  The first is the
block device on which the filesystem you built lives.  (If you used a
file via the loop fs patches, you will need to do the compression by
hand - refer to the above list of steps.)  The second is the name of the
file in which the compressed file system is to be saved.  Use `-' to
send the output to stdout.  The third parameter is the size of the
filesystem on the block device.  If not supplied, makefsz assumes 4Mb.

Installing a compressed file system image
-----------------------------------------

Once you have a compressed fs, it needs to copied to the floppy disk,
and the kernel informed on where to find it.  The script `writefsz' does
this, and takes one or two parameters.  The first is the filename of the
image, or `-' for stdin.  The optional second argument is the size of
the ramdisk to create on boot.  This must match the size of the
compressed image.  By default, this is 4Mb.  writefsz performs the
following steps:

	1.	Set the size of the ramdisk (4Mb by default).
	2.	Mark the root filesystem as read-only.
	3.	Set the root device to /dev/fd0.
	4.	Set the pointer to the image to the block following
		the kernel.
	5.	Write the fs image to the block following the kernel.

WARNING: writefsz examines /usr/src/linux/zImage to find out where on
the floppy to start writing the image.  If zImage is not that same
kernel as is on the floppy, you will need to write the fs image by
hand.

Upgrading the kernel
--------------------

Provided that a new kernel has the same number of blocks as the previous
one, it can be written over the older kernel without having to rewrite
the compressed file system image.  After the new kernel is written to
the floppy, simply used `cramon' to configure it.  cramon takes one
optional argument, the size of the ramdisk (4Mb by default).  For the
simple case, the kernel upgrade would be done as follows:

	$ make zdisk
	$ cramon

If the new kernel does not have the same number of blocks, you will have
to copy the compressed image off, update the kernel, and then copy the
image back on.  You can use the command `readfsz' to get a copy of the
image, so your kernel upgrade would go something like:

	$ readfsz /tmp/cram
	$ make zdisk
	$ writefsz /tmp/cram

Be aware that there is no information stored anywhere on how long the
image is, so that readfsz will copy from the start of the image to the
end of the disk, even if the image isn't that long.  Consequently, if
your kernel has grown by a few K, writefsz will not be able to write
back all the information that readfsz got.  As long as the kernel hasn't
grown to the point where it really is forcing the end of the image off
the floppy, there is no problem with writefsz not writing everything.
If the kernel size really has blown out, you will have to decompress the
image and delete some files (see the next section).

NOTE: readfsz assumes the existence of the command `hexdump'.

Updating the filesystem
-----------------------

The filesystem is effectively set in stone after you compress it and
write it to the floppy - you cannot mount it and tweak it if necessary.
This is not a bad thing for a boot disk - it makes sure that you get it
configured correctly before committing to it.  Because of this, doing
the initial build on a partition is advantageous as it allows you to
boot from it, revealing any weaknesses.

However, there are times when you wish to update the filesystem - a
change in network configuration, or the size needs to be adjusted, etc.
Extracting the filesystem is fairly straightforward.  As for the initial
build, you will need a partition (or a file and the loop fs patches).
There is no need to run mkfs on the partition, just put the floppy in
the drive and run:

	$ readfsz - | gzip -d > /dev/<whatever>

As noted above, readfsz will read junk from the end of the disk, and
gzip will notice this, but will ignore it.  Now just mount the partition
as normal, and perform whatever maintenance is required.  When done,
unmount the partition and update the floppy with:

	$ makefsz /dev/<whatever> - | writefsz -

+-----------------
| Assigning blame.
+-----------------

Inspired by the kernel compressing code by Hannu Savolainen and Nick
Holloway, which used code from gzip by Jean-loup Gailly and Mark Adler.
Multi page malloc and support code by Richard Lyons (me).  Please
send bugs/suggestions to me at
	rick@razorback.brisnet.org.au
or	pclink@qus102.qld.npb.telecom.com.au.

+------------------
| Sample file list.
+------------------

This is a list of the files on my bootdisk.  Some of them are links (eg
/bin/sh, /bin/ksh), and the /dev directory is not included.  This is
just to give an idea of how complete a filesystem can fit on a floppy.

/bin			   /etc/protocols	/usr/bin/sleep
/bin/ksh		   /home		/usr/bin/minicom
/bin/sh			   /home/rick		/usr/bin/who
/bin/cat		   /home/guest		/usr/bin/hexdump
/bin/chmod		   /lib			/usr/bin/od
/bin/chown		   /lib/libc.so.4.4.1	/usr/bin/setleds
/bin/cp			   /lib/libc.so.4	/usr/bin/setmetamode
/bin/dd			   /lib/libm.so.4.4.1	/usr/tmp
/bin/df			   /lib/libm.so.4	/usr/lib
/bin/du			   /mnt			/usr/lib/terminfo
/bin/bpe		   /proc		/usr/lib/terminfo/c
/bin/gunzip		   /sbin		/usr/lib/terminfo/c/console
/bin/zcat		   /sbin/dirdump	/usr/lib/terminfo/v
/bin/login		   /sbin/e2fsck		/usr/lib/terminfo/v/vt100
/bin/mv			   /sbin/fsck.ext2	/usr/lib/terminfo/v/vt100-am
/bin/free		   /sbin/mke2fs		/usr/lib/terminfo/v/vt100am
/bin/touch		   /sbin/mkfs.ext2	/usr/lib/runscript
/bin/ln			   /sbin/mklost+found	/usr/lib/minirc.dfl
/bin/ls			   /sbin/tune2fs	/usr/log
/bin/mkdir		   /sbin/getty		/usr/net
/bin/mknod		   /sbin/uugetty	/usr/net/bin
/bin/ps			   /sbin/fsck		/usr/net/bin/ftp
/bin/pstree		   /sbin/fsck.minix	/usr/net/bin/ping
/bin/passwd		   /sbin/fsck.msdos	/usr/net/bin/rcp
/bin/top		   /sbin/mkfs		/usr/net/bin/rlogin
/bin/rm			   /sbin/mkfs.minix	/usr/net/bin/telnet
/bin/sed		   /sbin/mkdosfs	/usr/net/bin/arp
/bin/stty		   /sbin/mkfs.msdos	/usr/net/bin/dip
/bin/hostname		   /sbin/dosfsck	/usr/net/bin/finger
/bin/w			   /sbin/shutdown	/usr/net/bin/host
/bin/tar		   /sbin/update		/usr/net/bin/ifconfig
/bin/gzip		   /sbin/bdflush	/usr/net/bin/iflink
/bin/false		   /sbin/mkswap		/usr/net/bin/ifsetup
/bin/true		   /sbin/mount		/usr/net/bin/named
/bin/tload		   /sbin/umount		/usr/net/bin/named-xfer
/bin/uptime		   /sbin/swapoff	/usr/net/bin/named.reload
/bin/su			   /sbin/swapon		/usr/net/bin/named.restart
/bin/head		   /sbin/fdisk		/usr/net/bin/netstat
/bin/tail		   /sbin/sync		/usr/net/bin/route
/bin/uniq		   /sbin/fastboot	/usr/net/bin/rsh
/bin/sort		   /sbin/fasthalt	/usr/net/bin/ruptime
/bin/date		   /sbin/halt		/usr/net/bin/rwho
/etc			   /sbin/telinit	/usr/net/bin/tftp
/etc/init		   /sbin/selection	/usr/net/daemons
/etc/brc		   /sbin/fuser		/usr/net/daemons/fingerd
/etc/rc			   /tmp			/usr/net/daemons/ftpd
/etc/default		   /usr			/usr/net/daemons/inetd
/etc/default/getty.tty1	   /usr/bin		/usr/net/daemons/mountd
/etc/default/uugetty.ttyS1 /usr/bin/elvis	/usr/net/daemons/nfsd
/etc/fstab		   /usr/bin/ex		/usr/net/daemons/pcnfsd
/etc/gettydefs		   /usr/bin/input	/usr/net/daemons/rlogind
/etc/group		   /usr/bin/vi		/usr/net/daemons/routed
/etc/inittab		   /usr/bin/view	/usr/net/daemons/rshd
/etc/issue		   /usr/bin/awk		/usr/net/daemons/rwhod
/etc/passwd		   /usr/bin/grep	/usr/net/daemons/syslogd
/etc/utmp		   /usr/bin/egrep	/usr/net/daemons/tcpd
/etc/reboot		   /usr/bin/fgrep	/usr/net/daemons/telnetd
/etc/termcap		   /usr/bin/rz		/usr/net/daemons/tftpd
/etc/fastboot		   /usr/bin/sz		/usr/net/etc
/etc/services		   /usr/bin/perl	/usr/net/etc/inetd.conf
/etc/hosts		   /usr/bin/less	/usr/net/etc/rc.net
/etc/host.conf		   /usr/bin/strings	/usr/net/etc/rc.net1
/etc/networks		   /usr/bin/wc		/usr/net/etc/hosts
/etc/resolv.conf	   /usr/bin/diff	/usr/net/etc/host.conf
/etc/mtab		   /usr/bin/find	/usr/net/etc/networks
/etc/profile		   /usr/bin/tr		/usr/net/etc/resolv.conf
/usr/net/etc/services	   /usr/spool		/var
/usr/net/etc/protocols	   /usr/spool/uucp	/.profile
