#!/bin/sh

# Author   : Benoit PAPILLAULT <benoit.papillault@free.fr>
# Creation : 2003-07-17
# License  : GPL

# This script is used to build the initrd.gz file (ramdisk) use by the
# installer. The resulting file is : $TARGET.gz

. config
. config-auto

TARGET=work/initrd

# function to strip all binaries
strip_binaries() {

  DIR="$1"
  TMP="/tmp/list.$$"

  find "${DIR}" -type f -exec file {} \; \
    | grep " ELF " \
    | grep -v "relocatable" \
    | awk -F ':' '{print $1}' > "${TMP}"

  (while read file;
   do
     strip "${file}"
   done ) < "${TMP}"

  rm "${TMP}"
}

# umount directories under ${TARGET}

if [ -d "${TARGET}" ]; then
  DIR=`cd "${TARGET}" && pwd` &&
  cat /proc/mounts | awk '{print $2}' | grep "^${DIR}" | sort -r |
  while read dir;
  do
    echo "umounting ${dir}..."
    umount "${dir}" || exit 1
  done || exit 1
fi

# erase existing directory if any

echo "deleting existing initrd"
rm -rf "${TARGET}" || exit 1

# creates FHS 2.3 directories

cat data/FHS-2.3 | grep -v "^#" | grep -v "^$" | while read dir mode;
do
  mkdir -p "${TARGET}/${dir}" &&
  if [ -n "${mode}" ]; then
    chmod "${mode}" "${TARGET}/${dir}"
  fi
done &&

# /lib64 -> /lib symlink
if [ "${LIB64_SYMLINK}" = "yes" ]; then
  ln -sf lib "${TARGET}/lib64" &&
  ln -sf lib "${TARGET}/usr/lib64"
fi &&

# /etc files

mkdir -p "${TARGET}/etc" &&
cp -p "${IMAGE}/etc/dialogrc" "${TARGET}/etc" &&

# /etc/fstab
cp src/initrd/fstab "${TARGET}/etc/fstab" &&

# we create an empty /etc/mtab and we will use mount -n switch
#(cd ${TARGET}/etc; ln -sf ../proc/mounts mtab)

mkdir -p "${TARGET}/etc" &&
touch "${TARGET}/etc/mtab" &&

# installer script

mkdir -p "${TARGET}/sbin" &&
cp src/initrd/smgl.init "${TARGET}/sbin" &&
ln -sf sbin/init "${TARGET}/linuxrc" &&
ln -sf smgl.init "${TARGET}/sbin/init" &&

# create devices from a tar.gz
# cat src/initrd/dev.tar.gz | (cd ${TARGET}; tar zxf -)

# termcap entry for linux
mkdir -p "${TARGET}/usr/share/terminfo/l" &&
cp -a "${IMAGE}/usr/share/terminfo/l/linux" "${TARGET}/usr/share/terminfo/l" &&

# copy /etc/pcmcia from image (if it exists)
if [ -d "${IMAGE}/etc/pcmcia" ]; then
  mkdir -p "${TARGET}/etc" &&
  cp -a "${IMAGE}/etc/pcmcia" "${TARGET}/etc"
fi &&

# copy binaries and libraries

mkdir -p "${TARGET}/bin" &&
mkdir -p "${TARGET}/sbin" &&
for exe in basename cardmgr cat chroot cp dialog echo grep \
	insmod ls lsmod mkdir modprobe mount pivot_root rmmod \
	true umount uname sh;
do
  # get absolute path name
  chroot "${IMAGE}" which "${exe}" || exit 1
done |
while read file;
do
  # copy binaries in /bin or /sbin
  #
  # some path are harcoded in the kernel, so check for them
  # /sbin/modprobe, /sbin/hotplug, /sbin/shutdown
  # /sbin/poweroff, /sbin/critical_overtemp, /sbin/loader
  #
  # to avoid harcoded names here too, we follow the path used
  # on $IMAGE
  case "${file}" in
    /sbin/*)
      cp "${IMAGE}/${file}" "${TARGET}/sbin"
      ;;
    *)
      cp "${IMAGE}/${file}" "${TARGET}/bin"
      ;;
  esac &&
# the sed formula works with either ldd on a NPTL enabled system or not
  chroot "${IMAGE}" ldd "${file}" | grep / |
  sed 's|[^/]*\(/[^ ]*\).*|\1|' || exit 1
done | sort -u |
while read lib;
do
  # copy libraries and create symlink if needed
  if [ -h "${IMAGE}/${lib}" ]; then
    real_lib=`chroot "${IMAGE}" readlink -f "${lib}"` &&
    dir=`dirname "${lib}"` &&
    mkdir -p "${TARGET}/${dir}" &&
    ln -sfv "${real_lib}" "${TARGET}/${lib}"
  else
    real_lib="${lib}"
  fi &&
  dir=`dirname "${real_lib}"` &&
  mkdir -p "${TARGET}/${dir}" &&
  cp -av "${IMAGE}/${real_lib}" "${TARGET}/${real_lib}" || exit 1
done || exit 1

# /etc/ld.so.conf
mkdir -p "${TARGET}/etc" &&
for dir in /lib /lib64 /usr/lib /usr/lib64;
do
  if [ -d "${TARGET}/${dir}" ]; then
    echo "${dir}" >> "${TARGET}/etc/ld.so.conf"
  fi
done &&

# creates correct symlinks in directories listed in /etc/ld.so.conf
# and creates /etc/ld.so.cache which will be used at runtime
ldconfig -r "${TARGET}" &&

# get the version of the installed kernel
if [ ! -f "${SPELL_STATUS}" ]; then
  echo "${SPELL_STATUS} missing"
  exit 1
fi

VERSION=`grep "^linux:" "${SPELL_STATUS}"|cut -d: -f4`
if [ -z "${VERSION}" ]; then
  echo "linux is missing on image"
  exit 1
fi

echo "using ${VERSION} linux kernel modules"

# copy kernel modules
mkdir -p "${TARGET}/lib/modules" &&
if [ -d "${IMAGE}/lib/modules/${VERSION}" ]; then
  cp -a "${IMAGE}/lib/modules/${VERSION}" "${TARGET}/lib/modules"
else
  echo "${VERSION} linux kernel modules missing"
  exit 1
fi

# remove some kernel modules (we mostly keep only drivers needed to
# access disk (ide, raid, scsi, usb-storage) and CDROM and filesystem
# (fat, vfat)

(cd "${TARGET}/lib/modules/${VERSION}";
	rm -rf build;
    rm -rf kernel/arch;
	rm -rf kernel/crypto;
    rm -rf kernel/drivers/acpi;
	rm -rf kernel/drivers/atm;
	rm -rf kernel/drivers/base;
	rm -rf kernel/drivers/block/nbd.ko;
	rm -rf kernel/drivers/block/paride;
	rm -rf kernel/drivers/block/ps2esdi.ko;
	rm -rf kernel/drivers/bluetooth;
	rm -rf kernel/drivers/cdrom/aztcd.ko;
	rm -rf kernel/drivers/cdrom/cdu31a.ko;
	rm -rf kernel/drivers/cdrom/cm206.ko;
	rm -rf kernel/drivers/cdrom/gscd.ko;
	rm -rf kernel/drivers/cdrom/isp16.ko;
	rm -rf kernel/drivers/cdrom/mcd.ko;
	rm -rf kernel/drivers/cdrom/mcdx.ko;
	rm -rf kernel/drivers/cdrom/optcd.ko;
	rm -rf kernel/drivers/cdrom/sbpcd.ko;
	rm -rf kernel/drivers/cdrom/sjcd.ko;
	rm -rf kernel/drivers/cdrom/sonycd535.ko;
    rm -rf kernel/drivers/char;
	rm -rf kernel/drivers/cpufreq;
	rm -rf kernel/drivers/firmware;
	rm -rf kernel/drivers/i2c
	rm -rf kernel/drivers/ide/ide-tape.ko;
	rm -rf kernel/drivers/ieee1394;
    rm -rf kernel/drivers/input;
    rm -rf kernel/drivers/isdn;
	rm -rf kernel/drivers/media;
	rm -rf kernel/drivers/message/i2o;
	rm -rf kernel/drivers/message/fusion/mptctl.ko;
	rm -rf kernel/drivers/misc;
	rm -rf kernel/drivers/mtd;
    rm -rf kernel/drivers/net;
	rm -rf kernel/drivers/parport;
	rm -rf kernel/drivers/pci;
	rm -rf kernel/drivers/scsi/pcmcia;
	rm -rf kernel/drivers/scsi/scsi_debug.ko;
	rm -rf kernel/drivers/serial;
	rm -rf kernel/drivers/telephony;
    rm -rf kernel/drivers/usb;
	rm -rf kernel/drivers/video;
	rm -rf kernel/fs/autofs;
	rm -rf kernel/fs/autofs4;
	rm -rf kernel/fs/binfmt_aout.ko;
	rm -rf kernel/fs/binfmt_misc.ko;
	rm -rf kernel/fs/coda;
	rm -rf kernel/fs/nls;
	rm -rf kernel/fs/lockd;
	rm -rf kernel/fs/ncpfs;
	rm -rf kernel/fs/nfs;
	rm -rf kernel/fs/nfsd;
	rm -rf kernel/fs/smbfs
	rm -rf kernel/lib/libcrc32*;
    rm -rf kernel/net;
	rm -rf kernel/security;
	rm -rf kernel/sound;
    rm -rf net;
)

# temporarily copy /sbin/depmod
mkdir -p "${TARGET}/sbin" &&
cp "${IMAGE}/sbin/depmod" "${TARGET}/sbin" &&
chroot "${TARGET}" /sbin/depmod -ae "${VERSION}" &&
rm -f "${TARGET}/sbin/depmod" || exit 1

# we no longer strip binaries because it cannot be done when cross compiling
# since strip and $HOST-strip are not binary compatible

#strip_binaries "${TARGET}"

# create a file initrd that will be mounted on work/mnt/initrd
# and where ${TARGET} will be copied

case "${INITRD_FS}" in
  ext2)
    # create a 40 MB file
	dd if=/dev/zero of=${TARGET}.fs bs=1M count=40 &&

    # create an ext2 filesystem on it
	mke2fs -q -b 1024 -i 1024 -F ${TARGET}.fs &&

    # create a mount point for this ext2 filesystem
	mkdir -p work/mnt/initrd &&

    # mount the ext2 filesystem at the mount point
	if ! mount -o loop -t ext2 ${TARGET}.fs work/mnt/initrd; then
      echo "make sure your running kernel has loopback support (CONFIG_BLK_DEV_LOOP=y)"
      exit 1
    fi &&

    # copy the initrd content to it
	if ! (cd ${TARGET} ; tar cfl - . )|(cd work/mnt/initrd ; tar xfp - ); then
		echo "failed to copy system on a 40MB ramdisk"
		umount work/mnt/initrd
		exit 1
	fi &&

    # umount the ext2 filesystem (this ensure that all its content is copied
    # into the initrd file).

	umount work/mnt/initrd
	;;

  cramfs)
	if ! mkcramfs "${TARGET}" "${TARGET}.fs"; then
      echo "make sure you have installed mkcramfs (cramfs spell)"
      exit 1
    fi
	;;

  *)
	echo "You need to define INITRD_FS in config"
	;;
esac &&

# -c : keep existing file
# -9 : do the best compression method.

rm -f "${TARGET}.gz" &&
gzip -c -9 "${TARGET}.fs" > "${TARGET}.gz" &&

echo "initrd.gz is ready:" &&
ls -lak "${TARGET}.fs" "${TARGET}.gz"
