#!/bin/sh
#
# 	$Source: /cvsroot/bootcd/bootcd/bootcdproberoot,v $
#       $Id: bootcdproberoot,v 1.7 2006-11-27 16:36:34 bs Exp $
#    author: Carsten Dinkelmann <din@foobar-cpa.de>
#            Bernd Schumacher <bernd.schumacher@hp.com>
#     start: 25.01.2005
#     topic: try to detect the root device and set it as new
#            wait for usb, but stop waiting if device is recognized
#

# devices: device:major:minor
devices="hda:3:0 hdb:3:64 hdc:22:0 hdd:22:64 hde:33:0 hdf:33:64 hdg:34:0 hdf:34:64 scd0:11:0 scd1:11:2 scd2:11:3 scd3:11:4 scd4:11:5 scd5:11:6 scd6:11:7 scd7:11:8"

# search for this file on the cd
bootcdfile="/etc.ro/bootcd/bootcd2disk.conf"

################### nothing to configure behind this line #####################

devs=""
rootdev=""
#oldroot=$(cat /proc/sys/kernel/real-root-dev)
#echo "bootcdproberoot: /proc/cmdline=\"$(cat /proc/cmdline)\"" >&2

# next line gets the last "root=*"
cmdlineroot=$(cat /proc/cmdline | sed "s/^.*\<root=\([^ ]*\)\>.*$/\1/")

getdevice()
{
  ret=""
  for i in $*; do
    j=$(echo " $devices " | sed "s/^.* \($i[^ ]*\) .*$/\1/" |
      grep -v "$devices")

   if [ "$j" ]; then
     [ "$ret" ] && ret="$ret $j" || ret="$j"
   else
     echo "bootcdproberoot: Can't find major and minor for device \"$i\" ... please add to /usr/share/bootcd/bootcdproberoot!" >&2
    fi 
  done
  echo "$ret"
}
#echo "cmd=\"getdevice hda\" expect=\"hda:3:0\" result=\"$(getdevice hda)\""
#echo "cmd=\"getdevice scd1\" expect=\"scd1:11:2\" result=\"$(getdevice scd1)\""
#echo "cmd=\"getdevice scd7\" expect=\"scd7:11:8\" result=\"$(getdevice scd7)\""
#echo "cmd=\"getdevice bad\" expect=\"\" result=\"$(getdevice bad)\""
#echo "cmd=\"getdevice scd1 scd2 hda\" expect=\"scd1:11:2 scd2:11:3 hda:3:0\" result =\"$(getdevice scd1 scd2 hda)\""
#exit 0

# gethd - search all hd* which inlude ide-cdrom in driver
gethd()
{
  echo "bootcdproberoot: try to find ide-cdrom: " >&2
  ret=""
  for i in $(cd /proc/ide; ls -d hd*); do
    j=$(cat /proc/ide/$i/driver)
    if [ "$(echo "$j" |grep "ide-cdrom")" ]; then
      echo "bootcdproberoot: - $i ... found cdrom ($j) " >&2
      [ "$ret" ] && ret="$ret $i" || ret="$i"
    else
      echo "bootcdproberoot: - $i ... no cdrom    ($j) " >&2
    fi
  done
  echo "$ret"
}
#gethd
#exit 0

# getscd - simple grep for scsi-cdroms ;-)
getscd()
{
  echo "bootcdproberoot: try to find scsi-cdrom: " >&2
  ret=""
  j=$(cat /proc/scsi/scsi |grep "Type:[[:space:]]*CD-ROM"  |wc -l)
  i=0
  while [ $i -lt $j ]; do
    echo "bootcdproberoot: - scd$i ... found cdrom " >&2
    [ "$ret" ] && ret="$ret scd$i" || ret="scd$i"
    i=$(expr $i + 1)
  done
  echo "$ret"
}

real2device()
{
  i=$(($1>>8))
  j=$(($1-($i<<8)))
  echo "real:$i:$j"
}
#echo "cmd=\"real2device 769\" expect=\"real:3:1\" result=\"$(real2device 769)\""
#exit 0

device2real()
{
  echo $((($(echo $1| cut -d":" -f2) <<8)+ $(echo $1| cut -d":" -f3)))
}
#echo "cmd=\"device2real hda:3:1\" expect=\"769\" result=\"$(device2real hda:3:1)\""
#exit 0

for try in 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1; do 
  if [ "$cmdlineroot" = "auto" ]; then
    if [ $try -eq 20 ]; then 
      echo "bootcdproberoot: cmdlineroot=auto - searching ..." >&2
    fi
    devs=$(getdevice $(gethd))
    devs="$devs $(getdevice $(getscd))"
  elif [ "$(echo "$cmdlineroot" | grep "^[0123456789]*$")" ]; then
    if [ $try -eq 20 ]; then
      echo "bootcdproberoot: cmdlineroot=hex \"0x$cmdlineroot\"" >&2
      devs="$(real2device $((0x$cmdlineroot)))"
    fi
  else
    # cmdlineroot could be /dev/hda3 and we have no info in devices
    [ $try -eq 20 ] && echo "bootcdproberoot: will do usbwait" >&2
  fi
   
  [ "$devs" ] && echo "bootcdproberoot: search on this devices: $devs" >&2
  mkdir -p /mnt /dev2
  for d in $devs; do
    devname=$(echo $d| cut -d":" -f1)
    major=$(echo $d| cut -d":" -f2) 
    minor=$(echo $d| cut -d":" -f3)
    if [ "$cmdlineroot" = "auto" ]; then
      # try to mount the selected devices to /mnt and look for bootcdfile
      # create device
      rm -f /dev2/$devname
      mknod /dev2/$devname b $major $minor
      ret=$(mount -t iso9660 -n /dev2/$devname /mnt >/dev/null 2>&1; echo $?)
      if [ $ret != 0 ]; then
        echo "bootcdproberoot: - not found on $d (not mountable)" >&2
      else
        if [ -e "/mnt/$bootcdfile" ]; then 
          echo "bootcdproberoot: - found bootcd on $d" >&2
	  if [ -e "/scripts/init-premount/runbootcdproberoot" ]; then
	    # initramfs-tools
	    ROOT=/dev2/$devname
	    echo "ROOT=$ROOT" >/conf/param.conf
          else
	    # initrd-tools
            real=$(device2real $d)
            echo "bootcdproberoot: found bootcd on $d; set $real as new root!" >&2
            echo $real >/proc/sys/kernel/real-root-dev
	  fi
          umount /mnt
          break 2
        else
          echo "bootcdproberoot: - not found on $d" >&2
          umount /mnt
        fi
      fi
    else
      # no mount, we know nothing about filesystems; only check /proc/partitions
      if [ "$(cat /proc/partitions | grep "^ *$major *$minor ")" ]; then
        echo "bootcdproberoot: found given device in /proc/partitions" >&2
        break 2
      else
        echo "bootcdproberoot: given device not found" >&2
      fi
    fi
  done

  [ $try -eq 20 ] && echo -n "bootcdproberoot: waiting for usb " >&2
  echo -n "$try " >&2
  sleep 1
done
echo "" >&2

# For DEBUG enable /bin/sh
#/bin/sh
