| #! /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 "$@" |