Single ZEN Linux Floppy

SUMMARY:

I am going to try an attempt to explain how easy it is to make
Linux on a floppy disk. There are MANY ways to do this, but I found
the following to be the easiest. Once you get the idea, we will
change it around to be specific to a ZENImaging floppy, and use
some bash scripts to ftp the needed files into place. It's a little
complicated, but once you get the idea, you'll see how easy and
customizable it can be. If after this, you still have questions
feel free to contact me.

PREREQUISITES:

**Novell's ZEN Imaging CD (actually, just the initrd.gz file that's on it)

**A firm understanding of Linux, it's commands...etc.

**GRUB or LILO, I will explain using GRUB

**Busybox package. Last time I got this from: http://www.busybox.net/

**You must have an empty directory somewhere on a linux box.
mkdir /usr/storage/bootdisk
**Place the following script in this directory:

#!/bin/sh
# Begin ./build-initrd.sh
#

[ ! -d /mnt/loop1 ] && mkdir -p /mnt/loop1

INITRD=floppy/initrd
RAM=49152
# The above variable uses a ~48MB ram disk...change this to
# bigger or smaller depending on the size of "du -sh ./initrd"
# is, as this is what will fit in the extracted initrd ram
# disk space
DEVLOOP=/dev/loop1
MNTLOOP=/mnt/loop1


dd if=/dev/zero of=$INITRD bs=1k count=$RAM
losetup $DEVLOOP $INITRD
mkfs -t ext2 -m 0 $DEVLOOP
mount $DEVLOOP $MNTLOOP
cd initrd
tar cvf - . | (cd $MNTLOOP ; tar xvf - )
cd ..
umount $MNTLOOP
losetup -d $DEVLOOP
echo "Gzipping the initrd file"
gzip -9 -f $INITRD

#
# End ./build-initrd.sh

NOTE: The above script I got from somewhere I can not remember,
and I altered it a little. Feel free to alter however you like,
just make sure it does what it is supposed to
**Create a folder called initrd. This will be used to hold the
root file system that is extracted to RAM
mkdir /usr/storage/bootdisk/initrd
**Create a folder called floppy. This will be used to hold the
contents that will be placed on the actual floppy disk
mkdir /usr/storage/bootdisk/floppy

PROCEDURE:

FIRST, NON-ZEN related Linux floppy

1. Compiling the kernel that will be placed on the floppy disk
Now hopefully you already know how to do this, as I am not
going to walk you through this part. You just need to know that,
when you configure your kernel, I have found that the following settings
will keep the kernel small enough to fit on to the floppy with
the busybox filesystem we will create later. It gives enough
drivers to make it bootable on a fair amount of systems, but alter
however you need. Keep in mind, that at the end of making the
kernel, if "make bzImage" comes back and says something about the
kernel like

warning: kernel is too big for standalone boot from floppy

...then it probably is, and you need to adjust it.
Here is the kernel .config file I used.
This is for a linux 2.4.x kernel, again alter however you need.

Just load that file into your kernel, and then type the common:
make dep && make bzImage
I've compiled everything commonly needed into the kernel, without
using modules.

Finally, copy the kernel into the current ./floppy directory, renaming
it along the way:
cp arch/i386/boot/bzImage /usr/storage/bootdisk/linux

2. The Busybox root filesystem
After you have downloaded and extracted the busybox package, change
into the directory and run:
make menuconfig
You can either go through this configuration, and select the tools
you want, or download and load my busy box config file and use that.

After you have configured busybox run:
make && make install
This will create a usable root filesystem inside the _install
directory. All you have to do is copy the contents of this directory,
to the initrd directory you made above:
cp -a ./_install/* /usr/storage/bootdisk/initrd/
After you copy the busybox files in place, you'll need to create a few
other needed files and directories in the initrd dir. Change into the
/usr/storage/bootdisk/initrd/
directory, and make the following directories:
mkdir -p etc/rc.d
And create the following files:
#etc/inittab
#
# inittab
#

::sysinit:/etc/rc.d/rc.S

#::respawn:/bin/sh
tty1::respawn:/bin/sh
tty2::respawn:/bin/sh
tty3::respawn:/bin/sh
tty4::respawn:/bin/sh

::ctrlaltdel:/sbin/reboot
#etc/rc.d/rc.S
#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin;export PATH
mount -t proc none /proc
mount -o remount,rw /
/sbin/ifup
#sbin/ifup
#!/bin/sh

ifconfig eth0 up
ifconfig eth0 >/dev/urandom
udhcpc -q
Finally, just change into the root of the bootdisk directory, and
run the ./build-initrd.sh script from above, and it will
automatically create, compress and place the needed initrd.gz
file into the floppy directory for you....I make things easy :-)
cd /usr/storage/bootdisk
./build.sh
You should see it scroll through the initrd directory, and end with:
Gzipping the initrd file

3. Copy the files and GRUB the floppy
Create a directory in the floppy directory for GRUB:
mkdir -p /usr/storage/bootdisk/floppy/boot/grub
Now, if you are not using grub on your Linux box, then you will
have to download the source from:
http://www.gnu.org/software/grub/#download
...extract it, ./configure and make GRUB. You do
NOT need to do the normal "make install" part, all we need is the
stage1 and stage2 files that are created after make is ran.
Just copy the files to /usr/storage/bootdisk/floppy/boot/grub:
cd /tmp
tar -xvzf grub-0.94.tar.gz
cd grub-0.94
./configure && make
cp stage1/stage1 stage2/stage2 /usr/storage/bootdisk/floppy/boot/grub

OR, if you have grub on your linux box, then all you have to do is copy
them from grub's installed location, something like this:
cp /usr/share/grub/i386-pc/stage1/stage1 /usr/storage/bootdisk/floppy/boot/grub
cp /usr/share/grub/i386-pc/stage2/stage2 /usr/storage/bootdisk/floppy/boot/grub
Next, create GRUB's menu.lst file:
# ./grub.conf

default=0
timeout=1

title Novell ZEN Linux Imaging (2.4.24)
root (fd0)
kernel /linux rw root=/dev/ram0 rw init=/sbin/init
initrd /initrd.gz
....and place it in /usr/storage/bootdisk/floppy/boot/grub
Change into the ./floppy directory and check the size:
cd ./floppy
ls -la
By using the -la option, you should get an output like this:

total 1305
drwxr-xr-x    2 root     root         4096 Jan 24 21:58 .
drwxr-xr-x    8 root     root         4096 Jan 24 18:13 ..
drwxr-xr-x    8 root     root         4096 Jan 24 18:13 boot
-rw-r--r--      1 root     root     442205 Jan 24 21:58 initrd.gz
-rw-r--r--      1 root     root     975351 Jan 21 22:46 linux

Look at the total 1305 part of the output, that is what to
watch out for. Make sure that doesn't get higher than a normal floppy.
Play it safe, and keep it around, or lower than 130x.

Once you are sure things will fit on the floppy, place a floppy in the
drive, format it using ext2, copy all the files in place and then grub it:
mke2fs /dev/fd0
mount /dev/fd0 /mnt/floppy
cp -a /usr/storage/bootdisk/floppy/* /mnt/floppy
umount /mnt/floppy
grub --batch --device-map=/dev/null <<EOGRUB
device (fd0) /dev/fd0
root (fd0)
setup (fd0)
quit
EOGRUB
NOTE: If you do not have GRUB installed, then change the above:
grub --batch --device-map=/dev/null <<EOGRUB
to
/tmp/grub-0.94/grub/grub --batch --device-map=/dev/null <<EOGRUB

Test this floppy in all your standard devices and make sure you can boot to a
bash prompt, and that you get an IP. If you get to this point:

BusyBox v1.00-pre5 (2004.01.28-19:24+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
...then you are ready to make it ZENable :-)

ZEN enabled Linux floppy

Once you get the above part (pretty cool eh?) working, now let's change things
around a bit, to make it specific to ZEN Imaging.

4. Change the kernel to ZEN Imaging kernel
We need to alter the kernel a bit in order for it to work with the ZEN Imaging
"img" utility. Thankfully, cool solutions provided me with this aritlce:
http://www.novell.com/coolsolutions/zenworks/features/a_build_imaging_drivers_zw.html
It provides a link to download the needed build_drivers.zip which contains the
kernel patch: zfd3krnlpatch.tgz. You can follow along Martin Buckley's article:
http://www.novell.com/coolsolutions/zenworks/features/a_zwz_building_linux_kernel_zw.html
which will tell you how to apply the patch....HOWEVER! you need to alter the patch
before it will apply to newer kernels (that's the trick, and the cool solution part :-))
Get the patch extracted and open it in a file editor. There are a couple of lines that
need to be altered. Change:
--- /usr/src/linux/drivers/block/ide.c Tue Jan 4 11:12:14 2000
+++ drivers/block/ide.c Fri Feb 23 17:03:56 2001

to

--- /usr/src/linux/drivers/ide/ide.c Tue Jan 4 11:12:14 2000
+++ drivers/ide/ide.c Fri Feb 23 17:03:56 2001

Now apply the patch to the kernel you used above, recompile the kernel and copy
it in place and to the floppy:
cd /tmp/linux-2.4.24
patch -p0 < /tmp/zfd3krnlpatch/ZENPatch
make dep && make bzImage
cp arch/i386/boot/bzImage /usr/storage/bootdisk/linux
mount /mnt/floppy
cp arch/i386/boot/bzImage /mnt/floppy/linux
umount /mnt/floppy
Again, test it and make sure it works. You will be able to tell if the ZEN components
are in the new kernel, because during the boot process you should see:
"Uncompressing and Loading ZENworks Imaging. Please wait... "
...and no other kernel output will happen, because the patch quiets the boot process.
Now onto the file updates.

5. Change the busybox filesystem (initrd.gz) for ZEN Imaging
Well, the problem is a single floppy only holds 1.4MB of data, which is nowhere near
enough room for us to store all the drivers we will need, plus the ZEN img utility
with all of it's libs, or any extra packages or scripts we want. So, the way we get
around that is the use of an FTP server.

Create a "ws-build" user in eDir,and give it a home space somewhere. I will
use \\zenserver\users\ws-build as an example. This home space is where we will
store some needed updates that our floppy will use.

You might be wondering, how do I get the correct libs that "img" utility needs
from the ZEN cd. Well, thanks to Linux and it's amazing ability to mount loopbacks
have no fear, this is how you do it. Create a zenstuff folder and mount
the ZEN Imaging CD.
mkdir /usr/storage/bootdisk/zenstuff
mount /mnt/cdrom
"ls" the contents of the CD and you should see a file called initrd.gz
That's the file that contains all the ZEN goodies we will need. It's just a compressed
filesystem, the exact same thing we created above. To get the stuff out of it, first
uncompress it and then temporarily mount it somewhere:
cd /usr/storage/bootdisk/zenstuff
cp /mnt/cdrom/initrd.gz ./
gunzip initrd.gz
mkdir /usr/storage/bootdisk/zenstuff/temp
mount -o loop ./initrd ./temp
If everything worked out, you should be able to "ls" the contents of
/usr/storage/bootdisk/zenstuff/temp and see something like this:
bin boot dev etc install lib linuxrc mnt proc sbin tmp update usr var
Now, you don't need everything in there, and I've taken the time to weed out
exactly what you do need in order to get the img utility to work.

I need to mention that I saw a little problem with the version of gzip I used to
package up the files, compared to the busybox version I used to uncompress the
files once they were transffered to the ramdisk. To get around that, make some
temp folders inside the /usr/storage/bootdisk/initrd/tmp directory, and copy the
files there, becuase that is where we will package them up, using busybox's gzip
version. Don't worry it will all make sense once you see it being done.
mkdir -p /usr/storage/bootdisk/initrd/tmp/bin
mkdir -p /usr/storage/bootdisk/initrd/tmp/lib
mkdir -p /usr/storage/bootdisk/initrd/tmp/usr/lib
Once the above directories are created, it's time to copy:
cd /usr/storage/bootdisk/zenstuff/temp
cp ./bin/img /usr/storage/bootdisk/initrd/tmp/bin
cp ./lib/lib* /usr/storage/bootdisk/initrd/tmp/lib
cp ./usr/lib/lib* /usr/storage/bootdisk/initrd/tmp/usr/lib

Ok, we are just going to chroot into the initrd area, and compress:
cd /usr/storage/bootdisk/initrd
chroot .
You should see the familiar:
BusyBox v1.00-pre5 (2004.01.28-19:24+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
...screen, so now just cd into tmp and compress the files, and exit:
cd tmp
tar -cvzf ../updates.tar.gz ./*
exit
When you run the "ls -lah" command from the current directory, you
should see the shiny new updates.tar.gz file, and it should only be
about 2.4MB or so in size....which is nothing to FTP across a LAN. :-)
Move it out of the /usr/storage/bootdisk/initrd directory and copy it to "ws-build" home space:
mv updates.tar.gz /usr/storage/bootdisk/zenstuff/
rm -rf /usr/storage/bootdisk/initrd/tmp/*
cd ..
Now just ftp the updates.tar.gz package up to ws-build's home space.
Or, if you have a NCP mount to the volume, copy it manually. Just make sure
that the updates.tar.gz file is setting in ws-build's home space.

Next, create some new /usr/storage/bootdisk/initrd/ files:
cd /usr/storage/bootdisk/initrd/sbin

#sbin/getupdates.sh
#!/bin/sh

ftpget -v -u ws-build x.x.x.x /tmp/updates.tar.gz \
/zenserver/users/ws-build/updates.tar.gz

tar -xvzf /tmp/updates.tar.gz
...just change x.x.x.x to the IP of your ftp server. You can't
use a dns name just yet, becuase you need the correct libs (libresolv.so.2)
and stuff in order for DNS resolution to work. And that's what we will be
FTPing down shortly.

Now just change /usr/storage/bootdisk/initrd/etc/rc.d/rc.S
#etc/rc.d/rc.S
#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin;export PATH
mount -t proc none /proc
mount -o remount,rw /
/sbin/ifup
/sbin/getupdates.sh
when you extract the contents of the updates.tar.gz file from the
root of the ramdisk area, it will place the proper files in /bin /lib...etc

6. Test out the new Single floppy ZEN Imaging disk
You should be able to run the "./build-initrd.sh" script
to update the initrd.gz file, and copy it back to the floppy:
cd /usr/storage/bootdisk
./build-initrd.sh
mount /mnt/floppy
cp floppy/initrd.gz /mnt/floppy
umount /mnt/floppy

Now boot off this new floppy, and test it out. You should see it boot with
the new kernel, and then it should run the etc/rc.d/rc.S which should run the
sbin/getupdates.sh script. After all that, test it by trying to type just:
img
at the BusyBox prompt, and it should launch. Tada!

7. Extra boot scripts (menu.sh)
I wanted to make it one step easier to manually rebuild workstations, so I
implemented a menu system for our more common workstations and laptops. Since
we try to stay with the same hardware manufacturer (IBM) it made it easier since
they all pretty much use the eepro100 network driver. Here it is:
NOTE: THIS FILE SHOULD BE SETTING IN ws-build's HOME SPACE
call it menu.sh
#!/bin/sh

#######################
##Begin variables section
HDA="/dev/hda1"
LOCALMOUNT="/mnt/harddisk"
HOST="zenserver"
DIR="//$HOST/zenworks"
HDPARM="hdparm -X66 -d1 -u1 -m16 -c3 /dev/hda"
ZENIMG="img restorep $HOST"


#######################
##Begin menu selection section
/usr/bin/clear
echo ""
echo ""
echo "----------------------------------------------------"
echo " Welcome to the Health First Linux Build Environment"
echo "----------------------------------------------------"
echo " Please EJECT the floppy disk or CD."
echo ""
echo ""
echo ""
echo " a.) Build an IBM 8xxx Series Workstation"
echo " b.) Build an IBM 6792 Workstation"
echo " c.) Build an IBM 6578 Workstation"
echo " d.) Build an IBM 6565 Workstation"
echo " e.) Build an IBM 6862 Workstation"
echo " f.) Build an IBM Rxx Series or A3x Series Laptop"
echo " g.) Build an IBM A2x Series Laptop"
echo ""
echo " exit.) To boot to a bash# prompt"
echo ""
echo ""
echo -n -e "\nMake a selection from the list above: " ; read ANSWER


if [ "$ANSWER" = "a" ]; then
echo""
echo "Building an IBM 8xxx Series Workstation"
echo""
$HDPARM
FILE="$DIR/workstations/IBM-8xxx.zmg"
elif [ "$ANSWER" = "b" ]; then
echo""
echo "Building an IBM 6792 Workstation"
echo""
$HDPARM
FILE="$DIR/workstations/IBM-8xxx.zmg"
elif [ "$ANSWER" = "c" ]; then
echo""
echo "Building an IBM 6578 Workstation"
echo""
$HDPARM
FILE="$DIR/workstations/IBM-6578.zmg"
elif [ "$ANSWER" = "d" ]; then
echo""
echo "Building an IBM 6565 Workstation"
echo""
$HDPARM
FILE="$DIR/workstations/IBM-6565.zmg"
elif [ "$ANSWER" = "e" ]; then
echo""
echo "Building an IBM 6862 Workstation"
echo""
$HDPARM
FILE="$DIR/workstations/IBM-6862.zmg"
elif [ "$ANSWER" = "f" ]; then
echo""
echo "Building an IBM Rxx Series or A3x Series Laptop"
echo""
$HDPARM
FILE="$DIR/laptops/IBM-R50.zmg"
elif [ "$ANSWER" = "g" ]; then
echo""
echo "Building an IBM A2x Series Laptop"
echo""
$HDPARM
FILE="$DIR/laptops/IBM-A2x.zmg"
elif [ "$ANSWER" = "exit" ]; then
exit
fi
#######################
##Finally rebuild and reboot
echo ""
echo ""
echo "DON'T FORGET TO EJECT THE CD/FLOPPY!!!"
echo ""
echo ""
sleep 2
$ZENIMG $FILE
reboot
exit

And make the following changes to etc/rc.d/rc.S:
#etc/rc.d/rc.S
#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin;export PATH
mount -t proc none /proc
mount -o remount,rw /
/sbin/ifup
/sbin/getupdates.sh
/sbin/getmenu.sh

Finally add the sbin/getmenu.sh script:
#sbin/getmenu.sh
#!/bin/sh

ftpget -v -u ws-build x.x.x.x /sbin/getmenu.sh \
/zenserver/users/ws-build/getmenu.sh

chmod +x /sbin/getmenu.sh
/sbin/menu.sh
I do this, so that I only have the one file on the network
to update when newer builds come along. I don't have to update
a whole bunch of CDs and floppies, just this one file which is
on the network. Better, huh?

Generate and copy the initrd.gz file once more:
cd /usr/storage/bootdisk
./build-initrd.sh
mount /mnt/floppy
cp floppy/initrd.gz /mnt/floppy
umount /mnt/floppy
Test out the new menu enabled disk.

CONCLUSION

I have succefully been able to use this method on the following devices:
IBM Workstation class devices (ThinkCenter, NetVistas...etc.)
IBM Laptops (Thinkpad)
Fujitsu B Series Laptop (using a USB floppy drive)
Fujitsu Tablet (using a USB floppy drive)
NEC Tablet (using a USB floppy drive)
...so it obvioulsy works. If you find something is not working, then
like I said before, feel free to contact me.


Happy booting!