blob: 1d3d3fcdcc70eac145f89977d7f9862a111e0a30 [file] [log] [blame]
#! /bin/sh
################################################################################
## ##
## Copyright (c) International Business Machines Corp., 2001 ##
## ##
## This program is free software; you can redistribute it and#or modify ##
## it under the terms of the GNU General Public License as published by ##
## the Free Software Foundation; either version 2 of the License, or ##
## (at your option) any later version. ##
## ##
## This program is distributed in the hope that it will be useful, but ##
## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ##
## for more details. ##
## ##
## You should have received a copy of the GNU General Public License ##
## along with this program; if not, write to the Free Software ##
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ##
## ##
################################################################################
# File: mkrootfs
#
# Description: script to create rootfs that will fit on a floppy. This
# filesystem contains a staticly linked busybox that provides
# basic commands and a shell.
#
# Author: Manoj Iyer - manjo@mail.utexas.edu
#
# History: June 17 2003 - Created.
#
TWDIR=/tmp/mkrootfs.$$ # temporary working directory
clean()
{
echo "INFO: Cleaning and exiting program"
mount | grep "$TWDIR/mnt" 2>&1 >/dev/null && \
{
echo "INFO: unmounting $TWDIR/mnt"
umount $TWDIR/mnt 2>&1 >/dev/null || \
{
echo "WARNING: failed unmounting temporary device."
echo "WARNING: clean up temporary devices manually"
}
}
rm -fr $TWDIR 2>&1 >/dev/null || \
{
echo "WARNING: failed to remove temporary working directory"
echo "WARNING: clean up temporary files and directories manually"
}
[ -a ./busybox-0.60.5.tar.gz ] && \
{
rm ./busybox-0.60.5.tar.gz 2>&1 >/dev/null || \
{
echo "WARNING: unable to remove busybox tarball"
echo "WARNING: clean up temporary files and directories manually"
}
}
}
usage()
{
echo "Usage: `basename $0` [-b] -c -d <HDDTYPE> -f <fSTYPE> -h"
echo " "
echo " "
echo " -b location of the staticly linked busybox binary."
echo " (if you dont provide one, this script will build one)"
echo " -c creates rootfs on floppy."
echo " (if this option is not provided rootfs.gz will be "
echo " created in the current working directory.)"
echo " -d <HDDTYPE> options available are scsi or ide"
echo " -f <FSTYPE> options available are ext2, ext3, reiserfs, xfs"
echo " -h help"
echo " "
echo "Example: `basename $0` -b /tmp/busybox-dir/ -c -d ide -f ext2"
exit 0
}
help()
{
echo "This program will create a root file system with busybox commads."
echo "Follow these steps to boot your machine with this file system"
echo "1. create a boot floppy."
echo " - dd if=<path>/bzImage of=/dev/fd0h1440 bs=1k"
echo "2. create a root floppy "
echo " - using this program eg: $0 -c -d scsi -f ext2 "
echo "3. boot machine with kernel in boot floppy"
echo " - provide boot options root=/dev/fd0h1440 (floppy device)"
echo "4. insert root floppy when prompted by the kernel."
echo " "
echo " "
usage
}
main()
{
local SYS_DIR=" " # names of various system directory
local SYS_DEV=" " # names of various system devices
local RC=0 # return value from commands.
local FORCEREI=" " # force mkfs.reiserfs to be quite
local CREATEFD=0 # flag to create floppy or just image
local FSTYPE=ext2 # file system type default is ext2
local HDDTYPE=ide # HDD type SCSI or IDE default: ide
local BBLOC="NONE" # location of static busybox binary.
# parse input arguments
while getopts b:cd:f:h arg
do case $arg in
b) BBLOC=$OPTARG;;
c) CREATEFD=1;;
d) HDDTYPE=$OPTARG;;
f) FSTYPE=$OPTARG;;
h) help;;
\?) usage;;
esac
done
# on exit clean up all temporary files and directories.
trap "clean" 0
# create temporary working directory
mkdir -p $TWDIR 2>&1 || \
{
echo "FAILED: creating temporary working directory"
exit 1
}
# make block or character special files called ramdisk_fs
mknod $TWDIR/ramdisk_fs b 1 0 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: creating block file $TWDIR/ramdisk_fs"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1;
}
# create a file system of required size, zeroing is important because
# the filesystem will be compressed before its put on a floppy, zeroing
# achives maximum compression. Creating a block file of size 8K.
dd if=/dev/zero of=$TWDIR/ramdisk_fs bs=1k count=8 \
2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: unable create filesystem of 8K size"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
# create the filesystem, EXT2 file system will be default.
if [ $FSTYPE == "ext2" ]; then
mke2fs -v -m 0 -N 2000 $TWDIR/ramdisk_fs 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: unable to create EXT2 filesystem on block file."
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
else
[ "$FSTYPE" == "reiserfs" ] && \
{
FORCEREI="-f -f";
}
mkfs.$FSTYPE $FORCEREI $TWDIR/ramdisk_fs 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: unable to create $FSTYPE filesystem on block file."
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
fi
# mount this filesystem so that it can be populated with system files and
# commands.
# create a temporary mount directory.
mkdir -p $TWDIR/mnt 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: creating temporary mount directory"
exit 1
}
mount -o loop $TWDIR/ramdisk_fs $TWDIR/mnt 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: unable to mount block file TWDIR/ramdisk_fs on $TWDIR/mnt"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
# remove lost+found directory from the rootfs file system, this is not
# required.
rm -fr $TWDIR/mnt/lost+found 2>&1 >$TWDIR/crfs.out || \
{
echo "WARNING: unable to remove lost+found from $TWDIR/mnt/ directory"
echo "WARNING: `cat $TWDIR/crfs.out`"
}
# create system directories.
for SYS_DIR in bin boot dev etc etc/init.d etc/rc.d lib mnt opt proc \
root sbin tmp usr usr/bin usr/sbin usr/lib usr/share \
var var/lock var/log var/run var/lib/rpm
do
mkdir -p $TWDIR/mnt/$SYS_DIR 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: creating $SYS_DIR"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
done
# initialize RPM database, just in case any RPMs will be installed to this
# root filesystem.
rpm --initdb --root=$TWDIR/mnt 2>&1 >$TWDIR/crfs.out || \
{
echo "WARNING: initializing RPM database."
echo "WARNING: cat `$TWDIR/crfs.out`"
}
# setting up the /etc directory, the three main files that will
# be created are fstab, rc.sysinit and inittab.
# create the inittab file.
cat > $TWDIR/mnt/etc/inittab <<-EOF || RC=$?
::sysinit:/etc/rc.d/rc.sysinit
::askfirst:/bin/sh
EOF
[ $RC -ne 0 ] && \
{
echo "FAILED: creating inittab file"
exit 1
}
# changing perissions if inittab file to 644
chmod 644 $TWDIR/mnt/etc/inittab 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: changing permissions of $TWDIR/mnt/etc/inittab"
exit 1
}
# create a /etc/rc.d/rc.sysinit file.
cat > $TWDIR/mnt/etc/rc.d/rc.sysinit <<-EOF || RC=$?
#!/bin/sh
mount -a -n
EOF
[ $RC -ne 0 ] && \
{
echo "FAILED: creating rc.sysinit file"
exit 1
}
# changing perissions of rc.sysinit file to 755
chmod 755 $TWDIR/mnt/etc/rc.d/rc.sysinit 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: changing permissions of $TWDIR/mnt/etc/rc.d/rc.sysinit"
exit 1
}
# creating etc/fstab file.
cat > $TWDIR/mnt/etc/fstab <<-EOF || RC=$?
/dev/ram0 / ext2 defaults 0 0
dev/fd0 / ext2 defaults 0 0
/proc /proc proc defaults 0 0
none /tmp tmpfs defaults 0 0
EOF
[ $RC -ne 0 ] && \
{
echo "FAILED: creating etc/fstab file"
exit 1
}
# changing perissions of rc.sysinit file to 644
chmod 644 $TWDIR/mnt/etc/fstab 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: changing permissions of $TWDIR/mnt/etc/fstab"
exit 1
}
# setting up /dev directory. Assuming that this script is
# executed on a linux system, contents of /dev directory of the
# host system will simply be copied to the rootfs file. Alternatively
# the mknod command may be used to create
# each device file. But the former is quick and easy.
# set up floppy drives. /dev/null and /dev/console
for SYS_DEV in /dev/fd[01]* /dev/null /dev/console /dev/zero
do
cp -dpR $SYS_DEV $TWDIR/mnt/dev 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: creating $SYS_DEV on $TWDIR/mnt/dev"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
done
# set up scsi or ide devices.
if [ "$HDDTYPE" == "scsi" ] || [ "$HDDTYPE" == "SCSI" ]
then
# set up SCSI cdrom drives.
cp -dpR /dev/sr0 $TWDIR/mnt/dev 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: creating SCSI cdrom device on $TWDIR/mnt/dev"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
# set up SCSI hard drives.
cp -dpR /dev/sd* $TWDIR/mnt/dev 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: creating SCSI cdrom device on $TWDIR/mnt/dev"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
elif [ "$HDDTYPE" == "ide" ] || [ "$HDDTYPE" == "IDE" ] ; then
# set up IDE cdrom drive.
cp -dpR /dev/cdrom $TWDIR/mnt/dev 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: creating SCSI cdrom device on $TWDIR/mnt/dev"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
# set up IDE hard drives.
cp -dpR /dev/hd* $TWDIR/mnt/dev 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: creating SCSI cdrom device on $TWDIR/mnt/dev"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
else
echo "FAILED: unknown hardware type:"
usage
fi
# setting up busybox.
if [ "$BBLOC" == "NONE" ]
then
echo "ÏNFO: downloading busybox from www.busybox.net"
wget -q -c http://www.busybox.net/downloads/busybox-0.60.5.tar.gz \
2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: fetching busybox from www.busybox.net"
exit 1
}
tar zxf ./busybox-0.60.5.tar.gz 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: uncompressing busybox tar ball"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
mv ./busybox-0.60.5 $TWDIR/ 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: moving busybox dir to temporary working dir"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
echo "INFO: Compiling static busybox... this will take few minutes"
make -C $TWDIR/busybox-0.60.5 clean 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: compiling static busybox."
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
make -C $TWDIR/busybox-0.60.5 DOSTATIC=true 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: compiling static busybox."
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
cp $TWDIR/busybox-0.60.5/busybox $TWDIR/mnt/bin/ 2>&1 \
>$TWDIR/crfs.out || \
{
echo "FAILED: copying busybox binary to $TWDIR/mnt/bin/"
exit 1
}
elif [ -z $BBLOC ]; then
echo "FAILED: bad path for static busybox"
usage
else
cp $BBLOC/busybox $TWDIR/mnt/bin/ 2>&1 \
>$TWDIR/crfs.out || \
{
echo "FAILED: copying busybox binary to $TWDIR/mnt/bin/"
exit 1
}
fi
echo "INFO: installing busybox"
# set up / directory
ln -f $TWDIR/mnt/bin/busybox $TWDIR/mnt/linuxrc 2>&1 \
>$TWDIR/crfs.out || \
{
echo "FAILED: linking busybox to linuxrc"
exit 1
}
# set up /usr/sbin directory
ln -f $TWDIR/mnt/bin/busybox $TWDIR/mnt/usr/sbin/chroot 2>&1 \
>$TWDIR/crfs.out || \
{
echo "FAILED: linking busybox to chroot"
exit 1
}
# set up /bin directory
for SYS_CMD in ash chmod dd false kill mknod pidof rmdir sync umount \
chown df grep ln more ps sed tar uname cat cp dmesg \
gunzip ls mount pwd sh touch zcat chgrp date echo gzip \
mkdir mv rm sleep true
do
ln -f $TWDIR/mnt/bin/busybox $TWDIR/mnt/bin/$SYS_CMD 2>&1 \
>$TWDIR/crfs.out || \
{
echo "FAILED: linking busybox to $SYS_CMD"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
done
# set up /sbin directory
for SYS_CMD in halt klogd mkswap poweroff swapoff syslogd \
init lsmod modprobe reboot swapon
do
ln -f $TWDIR/mnt/bin/busybox $TWDIR/mnt/sbin/$SYS_CMD 2>&1 \
>$TWDIR/crfs.out || \
{
echo "FAILED: linking busybox to $SYS_CMD"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
done
# set up /usr/bin directory
for SYS_CMD in clear du free killall sort \
tty wc xargs basename cut env head \
logger tail uniq which yes chvt dirname \
find id reset test uptime whoami
do
ln -f $TWDIR/mnt/bin/busybox $TWDIR/mnt/usr/bin/$SYS_CMD 2>&1 \
>$TWDIR/crfs.out || \
{
echo "FAILED: linking busybox to $SYS_CMD"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
done
# sync'ing changes to disk.
sync; sync; sync; sync; sync; sync;
echo "INFO: creating compressed file system"
# creating compressed file system.
dd if=$TWDIR/ramdisk_fs bs=1k | gzip -v9 > $TWDIR/rootfs.gz || \
{
echo "FAILED: creating compressed file system."
exit 1
}
# create a copy of the rootfs.gz on PWD.
cp $TWDIR/rootfs.gz ./ 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: coping rootfs.gz from temp directory to $PWD"
echo "FAILED: `cat $TWDIR/crfs.out`"
exit 1
}
if [ $CREATEFD -ne 0 ]
then
# creating filesystem on floppy
if [ $FSTYPE == "ext2" ]; then
mke2fs -v -m 0 -N 24 /dev/fd0h1440 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: unable to create EXT2 filesystem on floppy"
echo "FAILED: `cat $TWDIR/crfs.out`"
echo "INFO: mke2fs -m 0 -N 24 /dev/fd0h1440"
echo "INFO: and dd rootfs.gz to this floppy"
exit 1
}
else
[ "$FSTYPE" == "reiserfs" ] && \
{
FORCEREI="-f -f";
}
mkfs.$FSTYPE $FORCEREI /dev/fd0h1440 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: unable to create $FSTYPE on floppy"
echo "FAILED: `cat $TWDIR/crfs.out`"
echo "INFO: mke2fs -m 0 -N 24 /dev/fd0h1440"
echo "INFO: and dd rootfs.gz to this floppy"
exit 1
}
fi
sync; sync; sync; sync
# dd the rootfs on to floppy, if the rootfs.gz is greater than
# dd will fail so no pre-check is done on size of rootfs.gz
dd if=$TWDIR/rootfs.gz of=/dev/fd0h1440 bs=1k 2>&1 >$TWDIR/crfs.out || \
{
echo "FAILED: dd'ing the rootfs.gz onto floppy."
echo "FAILED: `cat $TWDIR/crfs.out`"
echo "INFO: please try it manually"
echo "INFO: dd if=./rootfs.gz of=/dev/fd0 bs=1k"
exit 1
}
exit 0
else
echo "INFO: create floppy manually"
echo "INFO: rootfs.gz in in $PWD directory"
echo "INFO: dd if=./rootfs.gz of=/dev/fd0 bs=1k"
exit 0
fi
}
main "$@"