#!/bin/bash
################################################################################
# $Id: mkinitrd_gedi 400 2007-10-19 15:42:27Z makia $
################################################################################
#  Copyright (C) 2004 The Regents of the University of California.
#  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
#  Written by Makia Minich <makia@llnl.gov>
#  UCRL-CODE-155916
#  
#  This file is part of GeDI, a diskless image management tool.
#  For details, see <http://www.llnl.gov/linux/gedi/>.
#  
#  GeDI 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.
#  
#  GeDI 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 GeDI; if not, write to the Free Software Foundation, Inc.,
#  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
################################################################################

# Source variables
CONFIG_FILE=/etc/sysconfig/gedi
. ${CONFIG_FILE}

usage () {
   echo "usage: $(basename $0) [OPTION]... <initrd-image> <kernel version>"
   echo ""
   echo "       (ex: $(basename $0) /boot/initrd-2.6.9-34.EL-gedi 2.6.9-34.EL)"
   echo ""
   echo "Options:"
   echo "      -n          Do not build unionfs."
   echo "      -f          Overwrite the current initrd."
   echo "      -d          Set <kernel version> as the default to boot from."
   echo "      -h          Print out this help statement."
   exit 1
}

BUILD_UNION=1
FORCE=0
DEFAULT=0

while getopts hnfd opt ; do
   case "$opt" in
      n) BUILD_UNION=0 ;;
      f) FORCE=1 ;;
      d) DEFAULT=1 ;;
      h) usage ; exit 0 ;;
   esac
done
shift $(($OPTIND-1))

[ $# -ne 2 ] && usage

target=$1
KERNEL=$2

if [ -f ${target} ] && [ $FORCE -eq 0 ] ; then
   echo "$target already exists."
   exit
fi

[ ! -d /lib/modules/${KERNEL} ] && echo "KERNEL" && usage
MODDIR=/lib/modules/${KERNEL}

TMPDIR=""
for t in /tmp /var/tmp /root ; do
   [ ! -d $t ] && continue
   ( (echo > $t/.gedi_test) > /dev/null 2>&1 ) && TMPDIR="$t" && \
                                                  rm -f $t/.gedi_test && \
                                                  break
done

if [ -z "$TMPDIR" ] ; then
   echo "No useable tmp directory"
   exit 1
fi

MNTIMAGE=$(mktemp -d ${TMPDIR}/initrd.XXXXXX)
IMAGEFILE=$(mktemp ${TMPDIR}/initrd.img.XXXXXX)
RCFILE=$MNTIMAGE/init

if [ -z "$MNTIMAGE" -o -z "$IMAGEFILE" ] ; then
   echo "Couldn't create temp files or directories."
   exit 1
fi

mkdir -p $MNTIMAGE

echo "Creating directory structure"
mkdir -p $MNTIMAGE/bin
mkdir -p $MNTIMAGE/dev
mkdir -p $MNTIMAGE/etc
mkdir -p $MNTIMAGE/lib/modules
mkdir -p $MNTIMAGE/proc
mkdir -p $MNTIMAGE/sys
mkdir -p $MNTIMAGE/union
mkdir -p $MNTIMAGE/sysroot
mkdir -p $MNTIMAGE/writeable
mkdir -p $MNTIMAGE/var/run
ln -s bin $MNTIMAGE/sbin
ln -s lib $MNTIMAGE/lib64

echo "Copying binaries and associated libraries"
NEEDED_BIN=( bash mount find modinfo awk lsmod grep insmod lspci ifconfig
             nameif sleep ln chmod mkdir umount chroot hostname ip dhclient
             printenv ls ps rm mount.nfs mount.nfs4 )

for bin in ${NEEDED_BIN[*]} ; do
   r=$(which $bin | tail -1)
   if [ -z "$r" ] ; then
      echo "You need $bin installed in the image to continue."
      exit
   fi

   install $r "$MNTIMAGE/bin/$bin"

   if ( file $r | grep -qv statically ) ; then
      for lib in $(ldd $r | awk -F"=> " '{print $NF}' | sed "s/ (.*//" | sort | uniq) ; do
         install $lib "$MNTIMAGE/lib/"
      done
   fi
done

if [ -f ${MODDIR}/modules.pcimap ] ; then
   install ${MODDIR}/modules.pcimap ${MNTIMAGE}/lib/modules
fi

ln -s /bin/bash $MNTIMAGE/bin/sh

mknod $MNTIMAGE/dev/console c 5 1
mknod $MNTIMAGE/dev/null c 1 3
mknod $MNTIMAGE/dev/ram b 1 1
for i in $(seq 0 4) ; do
   mknod $MNTIMAGE/dev/tty$i c 4 $i
done
ln -s tty0 $MNTIMAGE/dev/systty
mknod $MNTIMAGE/dev/hda b 3 0
mknod $MNTIMAGE/dev/hdb b 3 64
mknod $MNTIMAGE/dev/hdc b 22 0
mknod $MNTIMAGE/dev/hdd b 22 64

echo "Modifying the startup-file"
if [ -f /etc/modprobe.conf ] ; then
   eth0_mod=$(awk '/alias[[:space:]]eth0/ {print $NF}' /etc/modprobe.conf)

   if [ -n "$eth0_mod" ] ; then
      eth0_opts=$(awk "/options[[:space:]]+$eth0_mod/ {print \$NF}" \
                      /etc/modprobe.conf)
      if [ -n "$eth0_opts" ] ; then
         nic_options="$eth0_mod) insmod \$rmod $eth0_opts > /dev/null 2>\&1 ;;"
         echo "Adding options for $eth0_mod ($eth0_opts)"
      fi
   fi
fi
sed -e "s|#MOUNT_OPTIONS#|-o $MOUNT_OPTIONS|" ${LIBDIR}/init > $RCFILE
chmod +x $RCFILE

echo "Finding modules to install"
if [ -z "$eth0_mod" ] ; then
   echo "Installing all network device drivers"
   [ -d ${MODDIR}/kernel/drivers/net ] &&
      find ${MODDIR}/kernel/drivers/net -type f \
         -exec install {} ${MNTIMAGE}/lib/modules \;
else
   echo "Installing ${eth0_mod}"
   for mod in $(find ${MODDIR}/kernel/drivers/net -name "${eth0_mod}.*" ) ; do
      install $mod ${MNTIMAGE}/lib/modules
      for dep in $( modinfo ${mod} | awk '/depends/ {gsub(",", " ");
                                                     sub($1 FS FS "*",""); \
                                                     print}') ; do
         echo "Installing ${dep}"
         find ${MODDIR}/kernel/drivers/net -name "${dep}.*" \
               -exec install {} ${MNTIMAGE}/lib/modules \;
      done
   done
fi
for dir in kernel/fs/lockd kernel/fs/nfs kernel/fs/fscache \
           kernel/net/sunrpc kernel/fs/nfs?common ; do
   [ -d ${MODDIR}/$dir ] &&
      find ${MODDIR}/$dir -type f \
         -exec install {} ${MNTIMAGE}/lib/modules \;
done
for cdfile in cdrom.ko ide-cd.ko ; do
   find ${MODDIR} -name "$cdfile" -type f \
      -exec install {} ${MNTIMAGE}/lib/modules \;
done

if [ $BUILD_UNION -eq 1 ] ; then
   AVAIL_UNION=($(find ${MODDIR} -type f -name "unionfs*ko"))
   if [ -z "$AVAIL_UNION" ] ; then
      echo "Creating and Installing Union RPM"
      ${LIBDIR}/create_union_rpm ${KERNEL}
   else
      if [ ! -d /unionfs ] ; then
         mkdir -p /unionfs/sysroot
         mkdir -p /unionfs/union
         mkdir -p /unionfs/writeable
      fi
   fi
fi

[ -f ${LIBDIR}/gedi_libs.sh ] && install ${LIBDIR}/gedi_libs.sh ${MNTIMAGE}/lib
[ -f ${CONFIG_FILE} ] && install ${CONFIG_FILE} ${MNTIMAGE}/lib
cat <<__END__ > ${MNTIMAGE}/etc/dhclient.conf
interface "eth0" {
   request root-path, subnet-mask, broadcast-address, routers, ip-address;
}
__END__

(cd $MNTIMAGE; find . | cpio --quiet -c -o -B) > $IMAGEFILE || exit 1

echo "Compressing the image (this may take a bit)"
[ -f $target ] && rm -f $target
gzip -c < ${IMAGEFILE} > $target

rm -rf $MNTIMAGE $IMAGEFILE

[ $DEFAULT -eq 1 ] && ln -s vmlinuz-${KERNEL} ${BOOTDIR}/vmlinuz

echo "Done"
