#!/sbin/sh
#
#        "@(#)rcS.sh 1.130 96/11/11"
#
# Copyright (c) 1992-1996 Sun Microsystems, Inc.  All Rights Reserved.
#

#
# the 2.X install "rcS" file
# run by init(8) to create the environment for doing the installation
# replaces normal rcS
#
#* init starts
# *     mount tmpfs onto /tmp
# *     copy any needed files into /tmp...
# *     device reconfigure
# *     figure out root and /cdrom
# *     mount /cdrom
#

PLATFORM=`/sbin/uname -p`
export PLATFORM

RELEASE=`uname -r`

I386="i386"
SPARC="sparc"
PPC="ppc"

ROOT=/tmp/root
LOGS=${ROOT}/var/sadm/system/logs

Network="no"
FJS_BOOT="no"
DoDrvconfig="yes"
SINGLE_USER=0
#
# Functions
#

#
# use shell to snarf the base device name so we can make slice 0's name
# now we (only) do OBP style names
# INPUT: $1 - the rootfs device name
# OUTPUT: spits out on stdout the short device name of the cdrom device
#
basedevof() {
  D=$1    # Device
  T=$2    # Type

  # if we had expr on root, this is what we would simply do
  # U=`expr $D : '\(.*\):.*'
  # echo "${U}:a"

  # but we don't have expr and would like to live without it
  # so we use set to separate at all ":"
  IFS=":"
  set -- ${D}
  # get everything up till last ":" into U
  U=$1
  shift ;
  while [ $# -gt 1 ] ; do
    U=${U}:$1
    shift ;
  done
  # now we got everything except the stuff after the last ":",
  # which we assume was just a partition letter

  # x86 & ppc use p0 device for hsfs.  sparc uses s0 device.
  # These map to :q and :a respectively under /devices/...

  if [ "${PLATFORM}" = "${SPARC}" ]; then
    echo "${U}:a"
  else
    if [ "${T}" = "ufs" ]; then
      echo "${U}:b"
    else
      echo "${U}:q"
    fi
  fi
}

#
# Find and mount the CD image using DHCP
#
dhcp_find_and_mount_cdrom() {
  /sbin/dhcpagent -a

  #
  # Look for the root boot parameters;
  # For dhcpinfo:	SrootNM  returns the root file system server name
  #		SrootPTH returns the root file system path
  #
  if rs=`/sbin/dhcpinfo SrootNM` && rp=`/sbin/dhcpinfo SrootPTH` ; then
    Rootfs=$rs:$rp
    #echo "/sbin/rcS.dhcp:  Rootfs = $Rootfs"
    echo "${Rootfs} - / ${Roottype} - no ro" >> /etc/vfstab
  else
    echo "ERROR: dhcpagent unable to access network information"
    exec /sbin/sh
  fi

  #
  # Look for the install boot parameter;
  # For dhcpinfo: SinstNM  returns the install file system server name
  #               SinstPTH returns the install file system path
  #
  if is=`/sbin/dhcpinfo SinstNM` && ip=`/sbin/dhcpinfo SinstPTH` ; then
    Installfs=$is:$ip
    echo $Installfs > /tmp/.netmnt
    #echo "/sbin/rcS.dhcp:  Installfs = $Installfs"
  else
    echo "ERROR: dhcpinfo unable to access network install information"
    exec /sbin/sh
  fi

  # Get the server IP address so we can complain about it by name if need be
  DHCPServerAddr=`/sbin/dhcpinfo ServerID`

  # update the hosts file with the proper name to address translation for our
  # install server.
  echo "`/sbin/dhcpinfo SinstIP4` $is" >> /etc/inet/hosts

  /sbin/mount -F ${Installtype} -o ro ${Installfs} /cdrom >/dev/null 2>&1
  if [ $? -ne 0 ]; then
    # Bad information was returned by this DHCP server
    # display what information is available and
    # exit to allow the user to correct the situation
    #
    echo "received from DHCP server at $DHCPServerAddr"
    echo "install info:  server $is, path $ip"
    echo "root info:  server $rs, path $rp"
    echo "ERROR:  Unable to NFS mount ${Installfs}"
    echo "             Exiting to shell."
    exec /sbin/sh
  fi
}

#
# Find and mount the CD image using bootparams
#
bootparams_find_and_mount_cdrom() {
  #
  # net_device_list contains a ":" delimited list
  # of network devices
  # do an auto-revarp on each of them with the
  # exception of the loopback device
  #
  old_ifs=$IFS
  IFS=":"
  set -- $net_device_list
  for i
  do
    #
    # skip the auto-revarp for the loopback device
    #
    if [ "$i" = "lo0" ]; then
      continue
    fi
    /sbin/ifconfig $i auto-revarp -trailers up >/tmp/dev.$$ 2>&1
  done
  IFS=$old_ifs
  /sbin/hostconfig -p bootparams 2> /dev/null

  #
  # if not booting from the net add root entry to
  # /etc/vfstab
  #
  if [ "${Network}" != "yes" ]; then
    echo "${Rootfs} - / ${Roottype} - no ro" >> /etc/vfstab
  else
    #
    # Look for the root boot parameter;
    # bpgetfile returns $1 = server name, $2 = server IP addr, $3 = path
    #
    set -- ""
    set -- `/sbin/bpgetfile`
    SERVER_IPADDR=$2
    if [ $2"x" != "x" ]; then
      Rootfs=$1:$3
      echo "${Rootfs} - / ${Roottype} - no ro" >> /etc/vfstab
      # NOTE: the root filesystem will just *stay* read-only
    else
      echo "ERROR: bpgetfile unable to access network information"
      exec /sbin/sh
    fi

    # get the server's netmask
    if [ -x /sbin/get_netmask ]; then
      netmask=`/sbin/get_netmask $SERVER_IPADDR 2>/dev/null`
      if [ -n "$netmask" ]; then
	/sbin/ifconfig -a netmask 0x${netmask}  >/dev/null 2>&1
      fi
    fi

    #
    # Look for the install boot parameter;
    # bpgetfile returns $1 = server name, $2 server IP addr, $3 = path
    #
    set -- ""
    set -- `/sbin/bpgetfile install`
    if [ $2"x" != "x" ]; then
      Installfs=$2:$3
      echo $Installfs > /tmp/.netmnt
    else
      echo "ERROR: bpgetfile unable to access network install information"
      exec /sbin/sh
    fi
  fi

  /sbin/mount -F ${Installtype} -o ro ${Installfs} /cdrom >/dev/null 2>&1
}



###################################################
###################################################
#           Main
#

#
# Mount tmpfs and procfs and start accumulating mnttab
# entries for when mnttab is writeable
#
if [ ! -f /tmp/.rcSmnt ]; then
  # mount tmpfs, for now it can't swap so we can't fill it too full
  /sbin/mount -F tmpfs swap /tmp
  if [ $? -ne 0 ]; then
    echo "tmpfs mount failed."
    /sbin/sh
  fi

  # mount proc
  /sbin/mount -F proc proc /proc
  if [ $? -ne 0 ]; then
    echo "proc mount failed."
    /sbin/sh
  fi
  cat < /dev/null > /tmp/.rcSmnt

  # Mount the kernel mnttab file
  #
  /usr/lib/fs/mntfs/mount mnttab /etc/mnttab
fi

#
# Check for no reboot flag
#
if [ "${RB_NOBOOTRC}" = "YES" ]; then
  RB_NOBOOTRC="no"
  export RB_NOBOOTRC
  /sbin/sh
fi

if [ -f /tmp/.rcSrun ]; then
  exit 0
fi

DownRevRoss=`echo "downrev_ross_detected/X" | adb /dev/ksyms /dev/kmem | \
 ( read junk ; read junk ; read junk rev; echo $rev )`

if [ "$DownRevRoss" = "1" ]; then
  echo " "
  echo "The ROSS 605 CPU modules installed in this system are not fully"
  echo "compatible with this version of Solaris.  If this version of Solaris"
  echo "software is installed, this system will run only in uni-processor"
  echo "mode, which will affect performance."
  echo " "
  echo "Please upgrade your CPU module(s) in order to run in multi-processor"
  echo "mode."
  echo " "
  echo "    Do you want to continue with the installation?  If you choose"
  echo "    not to continue, previous system software will be left intact."
  echo "    Continue installation (y/n)?"
  read answer
  if [ "$answer" = "n" ]; then
    echo "Installation stopped. Previous system software has been left intact."
    echo "Please reboot."
    sync;sync
    /sbin/uadmin 2 0  # force it down 
  fi
  echo "WARNING: System performance will be affected. Are you sure (y/n)?"
  read answer
  if [ "$answer" = "n" ]; then
    echo "Installation stopped. Previous system software has been left intact."
    echo "Please reboot."
    sync;sync
    /sbin/uadmin 2 0  # force it down 
  fi
fi

#
# Start the twirling dial
#
if [ -x /sbin/dial ]; then
  dial &
  dial_pid=$!
fi

#    
# Unpack writeable initialized files into /tmp.
# NOTE: send output to /tmp (not /dev/null) to avoid nfs bug on remote
#       ro mounted fs
( cd /.tmp_proto; find . -print -depth | cpio -pdm /tmp 2>/tmp/cpio.out )

mkdir -p /tmp/root/var/sadm/system/logs

MEMSIZE=`/sbin/mem`
echo "Memory free after tmpfs initialization: ${MEMSIZE}" >> ${LOGS}/sysidtool.log
if [ ${MEMSIZE} -lt 4000 ]; then 
  echo "ERROR: ${MEMSIZE}KB is not enough free memory to install Solaris 2"
  /sbin/uadmin 2 0  # force it down
fi

########
# Configured "/" writeable files may not be updated.
#
# create /etc/vfstab (/tmp/root/etc/vfstab)
echo "swap - /tmp tmpfs - no -" >> /etc/vfstab

#
# add the procfs mount line
#
echo "/proc - /proc proc - no -" >> /etc/vfstab

# configure devfs in /tmp/dev and /tmp/devices
# using find | cpio to preserve the directory attributes
#echo "Configuring devices..."
find devices dev -depth -print | cpio -pdum /tmp >/dev/null 2>&1

if [ $RELEASE = "5.8" ];then
  #
  # Loopback mount the newly plumbed devices onto the main
  # file systems
  #
  /sbin/mount -F lofs /tmp/devices /devices
  
  /sbin/mount -F lofs /tmp/dev /dev
  
  _INIT_RECONFIG=set; export _INIT_RECONFIG
  mkdir -p /tmp/root/etc
  /usr/lib/devfsadm/devfseventd
  /usr/lib/devfsadm/devfsadmd -r /tmp -p /tmp/root/etc/path_to_inst
else
  # drvconfig requires you be in "/" (/tmp) or the pathnames
  # will be messed up
  cd /tmp
  /usr/sbin/drvconfig -r devices -p /tmp/root/etc/path_to_inst
  
  cd /
  /usr/sbin/devlinks -r /tmp
  /usr/sbin/disks -r /tmp
  
  if [ "${PLATFORM}" = "${SPARC}" ]; then
    /usr/sbin/tapes -r /tmp
  fi
  
  #
  # Loopback mount the newly plumbed devices onto the main
  # file systems
  #
  /sbin/mount -F lofs /tmp/devices /devices
  
  /sbin/mount -F lofs /tmp/dev /dev
fi


#
# PPC/Intel Unbundled Driver support - Sun private interface
# Copy driver scripts and data files onto the system from
# floppy, CD or netinstall image (if they exist). We are
# looking for the rc.d directory in the top level of the floppy
# or in /boot/rc.d on a CD or netinstall image.  Floppy files
# take precedence over CD or net files if the same file exists
# in both places.
#
if [ "${PLATFORM}" = "${I386}" -o "${PLATFORM}" = "${PPC}" ];
then

  /sbin/mount -F pcfs -o ro,foldcase /dev/diskette /mnt >/dev/null 2>&1
  status=$?

  if [ ${status} -ne 0 ]; then
    /sbin/mount -F ufs -o ro /dev/diskette /mnt >/dev/null 2>&1
    status=$?
  fi

  if [ ${status} -eq 0 ]; then
    if [ -d /mnt/rc.d ]; then
      FILES=`/usr/bin/ls /mnt/rc.d`
      if [ ! -z "${FILES}" ]; then
	/usr/bin/mkdir /tmp/diskette_rc.d
	/usr/bin/cp -p -r /mnt/rc.d/* /tmp/diskette_rc.d
      fi
    fi
    if [ -d /mnt/kernel ]; then
      FILES=`/usr/bin/ls /mnt/kernel`
      if [ ! -z "${FILES}" ]; then
	/usr/bin/mkdir -p /tmp/kernel
	/usr/bin/cp -p -r /mnt/kernel/* /tmp/kernel
      fi
    fi
    /sbin/umount /dev/diskette
  fi

  if [ -d /boot/rc.d ]; then
    if [ ! -d /tmp/diskette_rc.d ]; then
      /usr/bin/mkdir /tmp/diskette_rc.d
    fi
    for FILE in `/usr/bin/ls /boot/rc.d`; do
      RCPATH=/boot/rc.d/$FILE
      if [ -f $RCPATH -a ! -f /tmp/diskette_rc.d/$FILE ]; then
	/usr/bin/cp -p $RCPATH /tmp/diskette_rc.d/$FILE
      fi
    done
  fi

  if [ -r /tmp/diskette_rc.d/rcs1.sh ]; then
    /sbin/sh /tmp/diskette_rc.d/rcs1.sh
  fi
fi



#
# read bootargs for the boot device
# if fails - ignore and assume regular install
# if ok - see if preinstall bootargs set
#	and if possible, copy the /devices from the stub

# read prom for default boot dev
# looking for "FD=..."
set -- ""
set -- `/sbin/getbootargs 2>/dev/null`
if [ $# -gt 0 ] ; then
  while [ $# -gt 0 ] ; do
    case $1 in
      FD=*)
	    
	    # at end of script, save root dev in /tmp/.preinstall
	    # this is an unambiguous indication of stub boot
	    FJS_BOOT="yes"
	    From=`(IFS="="; set -- $1; echo "$2 $3 $4 $5" )`
	    break
	    ;;
      browser)
	       shift
	       ;;
      w)
	 cat < /dev/null > /tmp/.nowin
	 shift
	 ;;
      *)
	 shift
	 ;;
    esac
  done
fi


#
# figure out root file system information (ie local or remote)
#
eval `/sbin/get_root -t Roottype -b Rootfs /`

case ${Roottype} in
  ufs|hsfs)            # we are on a ufs or hsfs (local machine)
	    # get the name of the device for the Solaris distribution
	    Network="no"
	    Installfs=`basedevof ${Rootfs} ""`
	    if [ -b ${Installfs} ] ; then
	      echo  $Installfs >> /tmp/.cdroot
	      break
	    else
	      # "this never happens" :-)
	      echo "ERROR: The Solaris Distribution, ${Installfs} does not exist"
	      echo "             Exiting to shell."
	      /sbin/sh
	    fi
	    # the slice 0 is type hsfs
	    Installtype=hsfs
	    ;;
  nfs*)            # we are over the network (nfs, nfs2, nfs3)
	Roottype=nfs
	Network="yes"
	# set Installfs=... from config file from server
	Installtype=nfs
	;;
  *)              # fatal error - unknown "/" filesystem
     # we cannot use it as-is - note all the fs specific changes
     /sbin/dial $dial_pid
     while : ; do
       echo "FATAL ERROR: "/" file system type \"${Roottype}\" is unknown"
       echo "             Exiting to shell."
       /sbin/sh
     done
     ;;
esac

#
# Configure network interfaces:
#	- software loopback interface
#	- hardware interfaces
# Complete the network configuration
#
/sbin/ifconfig lo0 plumb
/sbin/ifconfig lo0 127.0.0.1 up > /dev/null 2>&1

#
# Configure all network interfaces
#
/sbin/ifconfig -a plumb > /dev/null 2>&1

# Export net boot configuration strategy. _INIT_NET_IF is set to the
# interface name of the netbooted interface if this is a net boot.
# _INIT_NET_STRATEGY is set to the network configuration strategy.
set -- `/sbin/netstrategy`
if [ $? -eq 0 ]; then
  if [ "$1" = "nfs" -o "$1" = "cachefs" ]; then
    _INIT_NET_IF="$2"
  fi
  _INIT_NET_STRATEGY="$3"
  export _INIT_NET_IF _INIT_NET_STRATEGY 
fi

#
# Get the complete list of network devices
# so that we can revarp them individually
for i in `ifconfig -a |grep "^[a-z0-9]*:"`
do
  echo $i |grep "^[a-z0-9]*:" >/dev/null 2>&1
  if [ $? -eq 1 ]; then
    continue
  fi
  net_device_list="${i}${net_device_list}"

done

if [ "X${_INIT_NET_STRATEGY}" = "Xdhcp" ] ; then
  echo "Using DHCP for network configuration information."
    dhcp_find_and_mount_cdrom
else
  echo "Using RPC Bootparams for network configuration information."
    bootparams_find_and_mount_cdrom
fi

echo "fd - /dev/fd fd - no -" >> /etc/vfstab
/sbin/mount -F fd /dev/fd

#####
### Intel/PPC private interface for unbundled device drivers
### Execute diskette shell script
if [ ${PLATFORM} = ${PPC} -o ${PLATFORM} = ${I386} ]; then
  if [ -r /tmp/diskette_rc.d/rcs3.sh ]; then
    /sbin/sh /tmp/diskette_rc.d/rcs3.sh
  fi
fi

if [ $RELEASE = "5.8" ];then

  ##########
  # now we have /usr, we can load our keyboard mappings
  # (architecture specific mechanisms)

  # Included from init.d/keymap

  #
  # Systems with no hardware keyboard ID will provide an eeprom value.
  #
  if test -x /usr/lib/set_keyboard_layout
  then
    /usr/lib/set_keyboard_layout
  fi
  
  # Load the keymap for the attached keyboard.
  /usr/bin/loadkeys
  
  # Initialize the keyboard defaults
  
  [ -h /dev/kbd -a -x /usr/bin/kbd ] && /usr/bin/kbd -i >/dev/null 2>&1
  
  # end of init.d/keymap code
  

else
  
  if [ "${PLATFORM}" = "${I386}" ]
  then
    # Load the default fonts. 
    LOADFONT=/usr/bin/loadfont
    ETC_DEFAULTFONT=/etc/defaultfont
    SYS_DEFAULTFONT=/usr/share/lib/fonts/8859.bdf
    
    if [ -x ${LOADFONT} ]
    then
      if [ -f ${ETC_DEFAULTFONT} ]
      then
	${LOADFONT} -f `cat ${ETC_DEFAULTFONT}` < /dev/console
      else
	if [ -f ${SYS_DEFAULTFONT} ]
	then
	  ${LOADFONT} -f ${SYS_DEFAULTFONT} < /dev/console
	else
	  echo "Failed to set the default fonts."
	  echo "Neither ${ETC_DEFAULTFONT} nor ${SYS_DEFAULTFONT} exist."
	fi
      fi
    else
      echo "Failed to set the default font."
      echo "${LOADFONT} does not exist or not executable."
    fi
    
    # Load the default keyboard mappings. 
    PCMAPKEYS=/usr/bin/pcmapkeys
    ETC_DEFAULTKB=/etc/defaultkb
    SYS_DEFAULTKB=/usr/share/lib/keyboards/8859/en_US
    
    if [ -x ${PCMAPKEYS} ]
    then
      if [ -f ${ETC_DEFAULTKB} ]
      then
	${PCMAPKEYS} -f `cat ${ETC_DEFAULTKB}` < /dev/console
      else
	if [ -f ${SYS_DEFAULTKB} ]
	then
	  ${PCMAPKEYS} -f ${SYS_DEFAULTKB} < /dev/console
	else
	  echo "ERROR: Failed to set the default keyboard mappings."
	  echo "       Neither ${ETC_DEFAULTKB} nor ${SYS_DEFAULTKB} exist."
	fi
      fi
    else
      echo "ERROR: Failed to set the default keyboard mappings."
      echo "       ${PCMAPKEYS} does not exist or is not executable."
    fi
  else
    # Load the keymap for the attached keyboard.
    if [ -x /usr/bin/loadkeys ]
    then
      /usr/bin/loadkeys -e
    fi
  fi
fi
# save the name of the root device in /tmp/.preinstall
if [ "${FJS_BOOT}" = "yes" -a "${From}" ]; then
  FromDisk=`echo ${From} | ( read d n junk ; echo $d )`
  if [ -b /devices/${FromDisk} ]; then
    lsline=`ls -l /dev/dsk | grep ${FromDisk}`
    if [ "${lsline}" ]; then
      shortname=`( set -- ${lsline} ;
        while [ $# -gt 3 ]; do
	shift;
        done
        if [ "$2" = "->" ]; then 
	echo "$1"; else echo "" ; fi )`
      if [ -b /dev/dsk/${shortname} ]; then
	echo /dev/dsk/${shortname} > \
	 /tmp/.preinstall
      fi
    fi
  fi
fi

##########
# Intel config cleanup logic
if [ -x /usr/sbin/install.d/atconfig ]; then
  /usr/sbin/install.d/atconfig
fi

#####
### Intel/PPC - Sun private device driver update interface
if [ ${PLATFORM} = ${PPC} -o ${PLATFORM} = ${I386} ]; then
  if [ -r /tmp/diskette_rc.d/rcs9.sh ]; then
    /sbin/sh /tmp/diskette_rc.d/rcs9.sh
  fi
fi

########
# PowerPC Virtual OpenFirmware validation
VOFCHECK=/usr/sbin/install.d/vofcheck
if [ -x ${VOFCHECK} ]; then
  ${VOFCHECK}
  if [ $? != 0 ]; then
    if [ ! -z "${dial_pid}" ]; then
      kill $dial_pid >/dev/null 2>&1
    fi
    echo
    echo "ERROR: The Solaris boot diskette must be inserted in the diskette"
    echo "       drive to continue the Solaris installation program."
    echo
    echo "       > Insert the Solaris diskette and press the Enter key."
    echo "         The system will reboot."
    read a < /dev/console
    uadmin 2 0
  fi
fi

###########################################################################
# now we exit rcS, and the rc files bring the system further
# on up (ie networking comes up...)
###########################################################################

if [ ! -z "${dial_pid}" ]; then
  kill $dial_pid >/dev/null 2>&1
fi

if [ "`uname -m`" = "i86pc" ] && [ -x /usr/sbin/eeprom ];then
      /usr/sbin/eeprom -I
fi

cat < /dev/null > /tmp/.rcSrun

exit 0
