#!/bin/bash
#
# --------------------------------------------------------------------------
# Copyright notice
# --------------------------------------------------------------------------
# Copyright: Rene Mayrhofer, Mar. 2000
#
# 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, 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; see the file COPYING.  If not, write to
# the Free Software Foundation, 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# On Debian GNU/Linux systems, the complete text of the GNU General
# Public License can be found in `/usr/share/common-licenses/GPL'.
# --------------------------------------------------------------------------
#

# do not edit below this line
# =================================================

# get config options from our config file
. /etc/mkinitrd-cd/mkinitrd-cd.conf

# where do we find our needed files?
copy_files_from_indep=/usr/share/mkinitrd-cd
copy_files_from_arch=/usr/lib/mkinitrd-cd

bytes_per_inode=8096
reserve_kbytes=100

if [ $# -lt 3 ] || ( [ "$3" != "min" ] && [ "$3" != "full" ] ) ; then
  echo "Usage: $0 <path to modules> <created initrd image> <size> [<version>]"
  echo
  echo "Where <size> can be either 'min' or 'full'. 'min' copies only the "
  echo "modules needed for booting from CD-ROM drives, 'full' additionally "
  echo "copies all modules needed to boot from harddisk partitions."
  echo
  echo "If <version> is specified, it will replace any occurance of the string"
  echo "'$VERSION_TEMPLATE' in the used id.txt file for checking if the correct"
  echo "CD-ROM is inserted (template taken from"
  echo "/etc/mkinitrd-cd/id.txt)."
  exit 1
fi

if [ `id -u` -ne 0 ]; then
  echo "This script must be run as root."
  exit 2
fi

if [ ! -d $1 ]; then
  echo "$1 is not a directory."
  exit 3
fi

umask 077
set -e

olddir=`pwd`

image=$2
# create temporary name for the image
tmpimage=`mktemp`
modulepath=$1
imagesize=$3
# temporary image names can not created with tempfile
mntpoint=`mktemp -d`
tmpstructure=`mktemp -d`

# detect which version of the directory layout we have (2.2.x or 2.4.x)
if [ -d $modulepath/kernel/drivers ]; then
  # 2.4.x layout
  moduledirs="kernel/drivers/scsi kernel/drivers/ide kernel/drivers/cdrom kernel/drivers/block kernel/fs kernel/drivers/usb"
else
  # 2.2.x layout
  moduledirs="scsi cdrom block fs"
fi

# first create the structure that the initrd image should contain
echo -n "Creating file structure ... "
mkdir $tmpstructure/bin
mkdir $tmpstructure/dev
mkdir $tmpstructure/etc
mkdir $tmpstructure/lib
mkdir $tmpstructure/lib/discover
mkdir $tmpstructure/mnt
mkdir $tmpstructure/mnt/media
mkdir $tmpstructure/mnt/root
mkdir $tmpstructure/modules
mkdir $tmpstructure/sbin
mkdir $tmpstructure/tmp
mkdir $tmpstructure/proc
mkdir $tmpstructure/usr
mkdir $tmpstructure/usr/i386-uclibc-linux
mkdir $tmpstructure/usr/i386-uclibc-linux/lib
echo "done"

# devices
echo -n "Creating device files ... "
cd $tmpstructure/dev
#for n in console null ram ram[01] tty[012345] ttyS[0123] fd stdout stderr \
#  hd[abcd] scd[0123456789] log; do
##  cp -a /dev/$n $tmpstructure/dev
#  echo $n
#  /sbin/MAKEDEV $n
#done
tar -C $tmpstructure/dev --preserve --same-owner --atime-preserve \
    -xzf $copy_files_from_indep/initrd-dev.tar.gz
echo "done"

cd $olddir
echo "Copying modules ... "
# copy the modules listed in scsiprobe.dat as well as common modules
# (in $additional_modules)
for n in $moduledirs; do
  if [ -d $modulepath/$n ] ; then
    for f in `find $modulepath/$n/ -name '*.o' -o -name '*.ko'`; do
      # copy only those that are also listed in scsiprobe.dat
      mod=`expr $(basename $f) : '\(.*\).[k]*o'`
      echo -ne "    $mod\t"
      # cosmetics (another tab for short file names)
      if [ `expr "$mod" : '.*'` -lt 4 ]; then
        echo -ne "\t"
      fi
      echo -n "... "
      # I don't know why this doesn't work - it should....
      #if ( ( echo "$cdboot_required_modules" | grep $mod >/dev/null ) ||
      #     ( [ "$imagesize" = "min" ] &&
      #       ( cat $copy_files_from/scsiprobe-min.dat | grep $mod >/dev/null ) ) ||
      #     ( [ "$imagesize" = "full" ] &&
      #       ( echo "$hdboot_additional_modules" | grep $mod >/dev/null ) ||
      #       ( cat $copy_files_from/scsiprobe.dat | grep $mod >/dev/null ) ) )
      #then
      # so try this instead - it is more complicated, slower and just plain 
      # ugly but it works
      copyit=0
      if echo "$cdboot_required_modules" | grep $mod >/dev/null; then
        copyit=1
      elif [ "$imagesize" = "min" ]; then
        if cat $copy_files_from_indep/scsiprobe-min.dat | grep $mod >/dev/null; then
          copyit=1
        fi
      else
        # $imagesize = "full" here
        if echo "$hdboot_additional_modules" | grep $mod >/dev/null ||
           echo "$usbboot_additional_modules" | grep $mod >/dev/null ||
           cat $copy_files_from_indep/scsiprobe.dat | grep $mod >/dev/null; then
          copyit=1
        fi
      fi
      if [ "$copyit" -eq 1 ]; then
        cp -a $f $tmpstructure/modules/
        echo "copied"
      else
        echo "skipped"
      fi
    done
  fi
done
# determine the biggest of the modules. this will have to fit on the initrd
# disk for loading - therefore this much free space has to be left on the image
maxsize=0
for f in $tmpstructure/modules/*; do
  modsize=`ls -l $f | awk '{print $5}'`
  if [ $modsize -gt $maxsize ]; then
    maxsize=$modsize
  fi
done
gzip -9 $tmpstructure/modules/*
echo "done"
echo "The largest module will need $maxsize bytes to be unzipped."
reserve_kbytes=`expr $maxsize / 1024 + $reserve_kbytes`

echo "Creating / copying binaries and libraries ... "
echo -n "    Installing binaries in temporary file structure ... "
install $copy_files_from_arch/busybox $tmpstructure/bin
cd $tmpstructure/bin
ln -s ash sh
ln -s test \[
install $copy_files_from_indep/chown-wrapper $tmpstructure/bin/chown
# now make the links for busybox
cd $tmpstructure/bin
for f in $busybox_bin; do
  ln -s busybox $f
done

# now /sbin
install /sbin/MAKEDEV $tmpstructure/sbin
cd $tmpstructure/sbin
for f in $busybox_sbin; do
  ln -s ../bin/busybox $f
done
install $copy_files_from_arch/discover $tmpstructure/sbin
install $copy_files_from_arch/paste $tmpstructure/sbin
#########install $copy_files_from/insmod $tmpstructure/sbin
echo "done"

echo -n "    Creating config files in temporary file structure ... "
# now /etc
touch $tmpstructure/etc/fstab
echo -e "root:x:0:0:root:/:/bin/sh" > $tmpstructure/etc/passwd
echo -e "root:x:0:\ndisk:x:6:" > $tmpstructure/etc/group
# the identifier for checking if the CD is correct
if [ -z "$4" ]; then
  install /etc/mkinitrd-cd/id.txt $tmpstructure/etc
else
  sed "s/${VERSION_TEMPLATE}/$4/" < /etc/mkinitrd-cd/id.txt > $tmpstructure/etc/id.txt
fi
# the modules autoprobing database and utilities
cp $copy_files_from_indep/scsiprobe.dat $tmpstructure/etc
cp $copy_files_from_indep/discover.conf $tmpstructure/etc
# pci device names and modules
#cp /lib/discover/list.xml $tmpstructure/lib/discover
#cp /lib/discover/pci*.xml $tmpstructure/lib/discover
# hmm, only the above two don't seem to work - need to figure out why
cp /lib/discover/*.xml $tmpstructure/lib/discover
echo "done"

# now /lib - with uClibc it is now wonderfully simple because we don't need to
# strip it in any way. Just copy it as it is, it's small enough (half the size
# of a stripped, minimized glibc with only the needed functions).
echo -n "    Copying uClibc ... "
cp -a /usr/i386-uclibc-linux/lib/ld-uClibc*.so* \
	/usr/i386-uclibc-linux/lib/libc.so* \
	/usr/i386-uclibc-linux/lib/libdl.so* \
	/usr/i386-uclibc-linux/lib/libdl-*.so \
        /usr/i386-uclibc-linux/lib/libuClibc*.so \
        $tmpstructure/usr/i386-uclibc-linux/lib
ln -s /usr/i386-uclibc-linux/lib/ld-uClibc*.so* \
	/usr/i386-uclibc-linux/lib/libc.so* \
	/usr/i386-uclibc-linux/lib/libdl.so* \
	/usr/i386-uclibc-linux/lib/libdl-*.so \
        /usr/i386-uclibc-linux/lib/libuClibc*.so \
	$tmpstructure/lib
echo "done"

echo -n "Copying bootup files ... "
# finally the linuxrc file
install $copy_files_from_indep/linuxrc $tmpstructure/
cp $copy_files_from_indep/initrd-common-definitions.sh $tmpstructure/
cp $copy_files_from_indep/probe-devs.sh $tmpstructure/
echo "done"

cd $olddir
# determine the size of the filesystem
size=`du -s $tmpstructure | awk '{print $1}'`
size=`expr $size + $reserve_kbytes`
echo "The image will take ${size} kb (including ${reserve_kbytes} kb of free"\
	"space for temp files)."

# now create the image
echo -n "Creating image file ... "
/bin/dd if=/dev/zero of=$tmpimage bs=1024 count=$size 2> /dev/null || {
  echo "failed during creation with dd !"
  exit 2
}
echo y | /sbin/mke2fs -i $bytes_per_inode -m 0 -q $tmpimage \
	> /dev/null 2> /dev/null || {
  echo "failed during creation with mke2fs !"
  exit 2
}
echo "done"
echo -n "Copying structure to image file ... "
mount -o loop -t ext2 $tmpimage $mntpoint

# copy the structure onto it
cp -a $tmpstructure/* $mntpoint
rm -rf $mntpoint/lost+found

# save and compress the image
umount $mntpoint
cd $olddir
echo "done"
echo -n "Compressing image file ... "
gzip -9 < $tmpimage > $image
echo "done"

# clean up
echo -n "Cleaning up ... "
rm -rf $tmpimage $mntpoint $tmpstructure
echo "done"

exit 0
