#!/bin/bash
#
# prepareroot
#
# --------------------------------------------------------------------------
# Copyright notice
# --------------------------------------------------------------------------
# Copyright: Rene Mayrhofer, 2000 - 2003
#
# 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
# ------------------------------------------------------------

. /usr/lib/gibraltar-bootsupport/common-definitions.sh
. /usr/lib/gibraltar-bootsupport/ide-scsi-probe.sh

umask 077
set -e

VERBOSE=no
if grep "verbose" /proc/cmdline >/dev/null; then
  VERBOSE=yes
fi
export VERBOSE

old_printk=`cat /proc/sys/kernel/printk`
kernelver=`cat /proc/sys/kernel/osrelease`

probemod() {
  if insmod_helper $1; then
    if [ "$VERBOSE" = "yes" ]; then
      echo "Loaded $1 module.";
    fi
  else
    local path=`find /lib/modules/$kernelver/ -name "$1.o"`
    # ignore it if the module does not exist
    if [ -n "$path" ] && [ -r $path ]; then
      # if the module is already loaded, ignore the error
      if ! lsmod | grep "$1" > /dev/null; then
        echo "Error: module $1 is available, but could not be loaded !"
      fi
    fi
  fi
}

# try to load the configuration from the given device $1 with filesystem $2
# returns 0 on success, 1 on failure
try_load() {
  echo "0 0 0 0" > /proc/sys/kernel/printk
  if mount -n -o ro -t $2 $1 $save_mntpoint >/dev/null 2>/dev/null; then
    echo "$old_printk" > /proc/sys/kernel/printk
    if [ -r $save_etcimage ]; then
      # get the config
      echo -en "\n${COLOR_GREEN}Found configuration${COLOR_NORMAL} on ${COLOR_BLUE}$1${COLOR_NORMAL}."
      echo " Loading from it."
      restore-etc $save_etcimage /etc
      # remember the location from where we loaded the configuration
      # and be sure that we can write there....
      if [ ! -d /etc/gibraltar ]; then
        mkdir /etc/gibraltar
      fi
      echo "$1" > /etc/gibraltar/config_source
      # first script hook for config-loaded
      call_script_hook config-loaded $save_mntpoint $save_etcimage /etc
      umount $save_mntpoint
      return 0
    elif [ -r $save_etcimage_old ]; then
      echo -en "\n${COLOR_GREEN}Found configuration${COLOR_NORMAL} on ${COLOR_BLUE}$1${COLOR_NORMAL} in old format."
      echo " Loading and converting it to new format."
      # restore the configuration to a temporary location and then convert it
      convert-config $save_etcimage_old /etc
      # the same here
      if [ ! -d /etc/gibraltar ]; then
        mkdir /etc/gibraltar
      fi
      echo "$1" > /etc/gibraltar/config_source
      # first script hook for config-loaded
      call_script_hook config-loaded $save_mntpoint $save_etcimage /etc
      umount $save_mntpoint
      return 0
    fi
    umount $save_mntpoint
  fi
  echo "$old_printk" > /proc/sys/kernel/printk
  return 1
}

# Try mounting all given partitions and try to load a stored
# configuration from them.
# $1 is a list of partitions that should be checked.
# $2 is a list of partitions that should NOT be checked.
# This routine will check all partitions that are known are contained in $1 AND
# not contained in $2.
check_hd_partitions() {
  for part in $1; do
    if ! echo "$2" | grep "$part" >/dev/null; then
      for fs in $save_filesystems_hdd; do
        if try_load "/dev/$part" $fs; then
          return 0
        fi
      done
    fi
  done
  return 1
}

# Try to load a configuration from a floppy disk. No input parameters.
# Returns 0 on success, 1 when no configuration could be found.
try_load_floppy() {
    # check if we even have a floppy
    if [ ! -e ${save_floppies}0 ]; then
      # we don't have a (supported) floppy disk in the system
      return 1
    fi

    # Try to load from other floppy drives (that might be installed) as well,
    # but only once. This is for people using one floppy drive for the bootdisk
    # and the second floppy drive for the configuration data.
    if [ $tried_floppies -eq 0 ]; then
      tried_floppies=1

      echo -e "    ${COLOR_BLUE}all floppies${COLOR_NORMAL} ... "

      for drive in ${save_floppies}?; do
        for fs in $save_filesystems_floppy; do
          if try_load $drive $fs; then
            return 0
          fi
        done
      done
    else
      echo -e "    ${COLOR_BLUE}first floppy${COLOR_NORMAL} ... "

      for fs in $save_filesystems_floppy; do
        if try_load ${save_floppies}0 $fs; then
          return 0
        fi
      done
    fi

    return 1
}

# Try to load configuration from harddisk partitions.
# $1 is a list of partitions that should NOT be checked (e.g. because they
# have already been checked by try_load_usb).
# Returns 0 on success, 1 when no configuration could be found.
try_load_hdd() {
    echo -e "    ${COLOR_BLUE}all harddisk partitions${COLOR_NORMAL} ... "
    # load IDE and SCSI modules and probe for SCSI adapters (if not done already)
    echo "0 0 0 0" > /proc/sys/kernel/printk
    install_ide_hd_mods
    echo "$old_printk" > /proc/sys/kernel/printk
    if check_hd_partitions "`cat /proc/partitions | egrep \"/part[0-9]*\" | mawk '{print $4;}'`" "$1"; then
      return 0
    else
      # only check scsi adapters if this has not been done before (during
      # locating the CD-ROM drive)
      if lsmod | grep "scsi_mod" | grep -v "grep" > /dev/null; then
        scsi_probed=1
      else
        scsi_probed=0
      fi
      echo "0 0 0 0" > /proc/sys/kernel/printk
      install_scsi_hd_mods
      echo "$old_printk" > /proc/sys/kernel/printk
      if [ $scsi_probed -eq 0 ]; then
        check_scsi
      fi
      if check_hd_partitions "`cat /proc/partitions | egrep \"/part[0-9]*\" | mawk '{print $4;}'`" "$1"; then
        return 0
      else
        #if [ $scsi_probed -eq 0 ]; then
        #  probe_scsi_mods
        #  if check_hd_partitions "`cat /proc/partitions | egrep \"/part[0-9]*\" | mawk '{print $4;}'`" "$1"; then
        #    return 0
        #  else
        #    return 1
        #  fi
        #else
          return 1
        #fi
      fi
    fi
}

# Try to load configuration from USB mass storage devices.
# No input parameters.
# This script figures out the partitions that are stored on an USB mass
# storage device and sets the global variable "usb_storage_partitions".
# Returns 0 on success, 1 when no configuration could be found.
try_load_usb() {
    echo -e "    ${COLOR_BLUE}USB mass storage${COLOR_NORMAL} ... "

    echo "0 0 0 0" > /proc/sys/kernel/printk
    install_usb_storage_mods
    for mod in `/sbin/listpci | egrep "^USB" | cut -d' ' -f2,2`; do
      probemod $mod
    done
    echo "$old_printk" > /proc/sys/kernel/printk

    # this seems to be necessary for the kernel to get a list of devices
    sleep 1s
    usb_storage_partitions=`get_usb_storage_partitions`

    if check_hd_partitions "$usb_storage_partitions" ""; then
      return 0
    else
      return 1
    fi
}



# check if the script should actually run...
if [ ! -e /etc/default/prepareroot ]; then
  echo "/etc/default/prepareroot does not exist, skipping creating of the /etc RAM-disk."
  exit 0
fi

# to mount the image, we may need to load the loop module
#probemod loop
# and possibly the floppy and vfat modules
probemod floppy
probemod fat
probe_mods $save_filesystems_floppy
probe_mods $save_filesystems_hdd

found_disk=0
# if the admin wants to use the default configuration, then just skip this
# step and the default config will be loaded afterwards
if ! `grep "defaultconfig" /proc/cmdline >/dev/null`; then
  # first restore the /etc directory
  # check if this is an unconfigured (default) boot or if there is already a
  # config disk
  echo "Trying to load configuration: "
  try=0
  tried_hdd=0
  tried_floppies=0
  usb_storage_partitions=""
  while true; do
    if ! grep -q "fastboot-usb" /proc/cmdline && try_load_floppy; then
      found_disk=1
      break
    fi

    # The next best thing are USB storage devices...
    if ! grep -q "fastboot-floppy" /proc/cmdline && try_load_usb; then
      found_disk=1
      break
    fi

    # Also try to load from a harddisk partition, but only once. It is unlikely
    # that the harddisk partitions change in between, so there is no need to
    # check twice....
    if [ $tried_hdd -eq 0 ]; then
      tried_hdd=1
      if ! ( grep -q "fastboot-floppy" /proc/cmdline || grep -q "fastboot-usb" /proc/cmdline ) \
           &&  try_load_hdd $usb_storage_partitions; then
        found_disk=1
        break
      fi
    fi

    echo "not found."

    # break if we already tried it MAX_DISK_TRIES times or when the fastboot
    # option has been used - in this case we do not wait at all for the
    # administrator to insert a disk
    if [ $try -ge $MAX_DISK_TRIES ] || grep -q "fastboot" /proc/cmdline; then
      break;
    fi

    echo "No configuration could be found. If you already have one on floppy disk, then"
    echo "please insert it now in your disk drive. If you have one on an USB storage"
    echo "device, then please attach it now. To pause now, press any key."
    echo ""
    beepconsole -f 500 -l 200 -r 2 -d 200
    if read -n 1 -r -s -t 10; then
      # the user wants to pause
      echo "Boot procedure paused. Press enter to continue."
      echo ""
      read -s
    fi

    try=`expr $try + 1`
  done
fi

if [ $found_disk -eq 0 ]; then
  echo "No configuration disk supplied. Loading default values."
  restore-etc $DEFAULT_ETC /etc
fi
# /etc should be there now
beepconsole -f 750 -l 200

# script hook for pre-update
call_script_hook pre-update

# is the version of the currently running system the same as the version that
# the config image has been created with ?
# if not, try to update it
if [ -e /etc/gibraltar/version ]; then
  old_version=`cat /etc/gibraltar/version`
else
  old_version=`cat /etc/gibraltar_version`
fi
new_version=`cat /system/etc-static/gibraltar/version`
if [ "$old_version" != "$new_version" ]; then
  update-config /etc $DEFAULT_ETC /etc/gibraltar/update-${old_version}_to_${new_version}.log || true
fi

# script hook for post-update
call_script_hook post-update /etc/gibraltar/update-${old_version}_to_${new_version}.log

# if the kernel supports devfs, but it is not mounted until now, do it
if grep "devfs" /proc/filesystems >/dev/null; then
  if [ "$VERBOSE" = "yes" ]; then
    echo -n "Good, the kernel supports devfs ... "
  fi
  if ! grep "devfs" /proc/mounts >/dev/null; then
    mount -t devfs none /dev
    if [ "$VERBOSE" = "yes" ]; then
      echo "mounted."
    fi
  else
    if [ "$VERBOSE" = "yes" ]; then
      echo "already mounted."
    fi
  fi
fi

echo

/sbin/patchall-local skip-hooks

exit 0
