#!/bin/ksh -p
#
# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# ident	"@(#)s8_boot.ksh	1.2	08/07/10 SMI"
#
# s8 boot script.
#
# The arguments to this script are the zone name and the zonepath.
#

PATH=/sbin:/usr/bin:/usr/sbin; export PATH

# Make a backup copy.  If we have already done so, backup the backup.
safe_backup()
{
	typeset src="$1"
	dst=$src.pre_p2v

	if [ -h $src -o -h $dst -o -d $dst ] ; then
		return
	fi

	/* Nothing to backup */
	if [ ! -f $src ] ; then
		return
	fi

	if [ -f $dst ] ; then
		tmpnm=$dst.`date +%y%m%d-%H:%M:%S`
		if [ ! -h $tmpnm -a ! -f $tmpnm -a ! -d $tmpnm ]; then
			mv $dst $tmpnm || exit 1
		fi
	fi

	cp -p $src $dst || exit 1
}

# Make a copy even if the destination already exists.
safe_copy()
{
	typeset src="$1"
	typeset dst="$2"

	/* Nothing to copy */
	if [ ! -f $src ] ; then
		return
	fi

	if [ ! -h $src -a ! -h $dst -a ! -d $dst ] ; then
		cp -p $src $dst || exit 1
	fi
}

# Replace targ with a symlink to src.  Incorporates safe_backup logic.
safe_link()
{
	typeset src="$1"
	typeset targ="$2"
	typeset type="$3"

	bkup=$targ.pre_p2v

	if [ -h $targ -o -h $bkup -o -d $bkup ] ; then
		return 0
	fi

	if [ -f $bkup ] ; then
		tmpnm=$bkup.`date +%y%m%d-%H:%M:%S`
		if [ ! -h $tmpnm -a ! -f $tmpnm -a ! -d $tmpnm ]; then
			mv $bkup $tmpnm || exit 1
		fi
	fi

	mv $targ $bkup || exit 1
	if [ "$type" = "s" ] ; then
		ln -s $src $targ || exit 1
	else
		ln $src $targ || exit 1
	fi
}

#
# Replace the file with a wrapper pointing to the native brand code.
# However, we only do the replacement if the file hasn't already been
# replaced with our wrapper.  This function expects the cwd to be the
# location of the file we're replacing.
#
# Some of the files we're replacing are hardlinks to isaexec so we need to 'rm'
# the file before we setup the wrapper while others are hardlinks to rc scripts
# that we need to maintain.
#
safe_replace()
{
	typeset filename="$1"
	typeset runname="$2"
	typeset mode="$3"
	typeset own="$4"
	typeset rem="$5"

	if [ -h $filename -o ! -f $filename ]; then
		return
	fi

	egrep -s "Solaris 8 Brand Replacement" $filename
	if [ $? -eq 0 ]; then
		return
	fi

	safe_backup $filename
	if [ $rem = "remove" ]; then
		rm -f $filename
	fi

	cat <<-END >$filename || exit 1
	#!/bin/sh
	#
	# Solaris 8 Brand Replacement
	#
	# Attention.  This file has been replaced with a new version for
	# use in a virtualized environment.  Modification of this script is not
	# supported and all changes will be lost upon reboot.  The
	# {name}.pre_p2v version of this file is a backup copy of the
	# original and should not be deleted.
	#
	END

	echo ". $runname \"\$@\"" >>$filename || exit 1

	chmod $mode $filename
	chown $own $filename
}

ZONENAME=$1
ZONEPATH=$2
ZONEROOT=$ZONEPATH/root

#
# Before booting, verify the RTU has been installed. 
#
if [ ! -f /usr/lib/brand/solaris8/files/patches/order ]; then
	echo "ERROR: The Solaris 8 Containers right-to-use package" \
	    "has not been installed"
	exit 2
fi

#
# Warn if the SUNWs8brandk pkg is not installed.
#
if [ ! -d /var/sadm/pkg/SUNWs8brandk ]; then
	echo "WARNING: The Solaris 8 Containers product is out of date.\n" \
	    "You should download and re-install the Solaris 8 Containers" \
	    "product,\nversion 1.01 or later, from sun.com/download."
fi

if [ `uname -p` = "i386" ]; then
        ARCH64=amd64
elif [ `uname -p` = "sparc" ]; then
        ARCH64=sparcv9
else
        echo "Unsupported architecture: " `uname -p`
        exit 2
fi

#
# Tell the user to rerun p2v if the zone has been migrated to a new system.
#
if [ ! -h $ZONEROOT/.host.orig ]; then
	if [ -f $ZONEROOT/.host.orig ]; then
		orighostid=`cat $ZONEROOT/.host.orig`
	fi
	myhostid=`/usr/bin/hostid`

	if [ "$myhostid" != "$orighostid" ]; then
		echo "[NOTICE: This zone has been migrated to a new host.]" \
		    >/dev/zcons/$ZONENAME/zoneconsole
		echo "[NOTICE: Run \"/usr/lib/brand/solaris8/s8_p2v" \
		   "$ZONENAME\" before booting.]" \
		    >/dev/zcons/$ZONENAME/zoneconsole
		echo "This zone has been migrated to a new host."
		echo "Run \"/usr/lib/brand/solaris8/s8_p2v" \
		   "$ZONENAME\" before booting."

		exit 1
	fi
fi

#
# Set the zone_restart_init property to B_FALSE
#
/usr/lib/brand/solaris8/s8_support boot $ZONENAME
if (( $? != 0 )) ; then
	echo "Unable to set zone_restart_init to false"
	exit 1
fi

# Before we boot we validate and fix, if necessary, the required files within
# the zone.  These will need to be fixed up on the first zone boot and these
# could be lost after a patch was applied within the zone.

# First validate that the zone filesystem looks like we expect it to.
if [ -h $ZONEROOT/usr  -o ! -d $ZONEROOT/usr ]; then
        echo "$ZONEROOT/usr must be a directory"
	exit 1
fi

if [ -h $ZONEROOT/usr/lib -o ! -d $ZONEROOT/usr/lib ]; then
	echo "$ZONEROOT/usr/lib must be a directory"
	exit 1
fi

if [ -a $ZONEROOT/usr/4lib ] ; then
	if [ -h $ZONEROOT/usr/4lib -o ! -d $ZONEROOT/usr/4lib ]; then
		echo "$ZONEROOT/usr/4lib must be a directory"
		exit 1
	fi
fi

if [ -h $ZONEROOT/usr/platform -o ! -d $ZONEROOT/usr/platform ]; then
        echo "$ZONEROOT/usr/platform must be a directory"
	exit 1
fi

if [ -h $ZONEROOT/usr/sbin -o ! -d $ZONEROOT/usr/sbin ]; then
        echo "$ZONEROOT/usr/sbin must be a directory"
	exit 1
fi

if [ -h $ZONEROOT/sbin -o ! -d $ZONEROOT/sbin ]; then
        echo "$ZONEROOT/sbin must be a directory"
	exit 1
fi

if [ -h $ZONEROOT/etc -o ! -d $ZONEROOT/etc ]; then
        echo "$ZONEROOT/etc must be a directory"
	exit 1
fi

if [ -h $ZONEROOT/etc/init.d -o ! -d $ZONEROOT/etc/init.d ]; then
        echo "$ZONEROOT/etc/init.d must be a directory"
	exit 1
fi

d=`pwd`

cd $ZONEROOT/usr/lib

#
# We only backup and copy the lwp/libs when we first boot and then whenever
# they are overwritten by a patch.
#

sig1=`sum libthread.so.1 | cut -f1 -d' '`
sig2=`sum lwp/libthread.so.1 | cut -f1 -d' '`
if [ $sig1 -ne $sig2 ]; then
	safe_link lwp/libthread.so.1 libthread.so.1 h
fi

sig1=`sum libthread_db.so.1 | cut -f1 -d' '`
sig2=`sum lwp/libthread_db.so.1 | cut -f1 -d' '`
if [ $sig1 -ne $sig2 ]; then
	safe_link lwp/libthread_db.so.1 libthread_db.so.1 h
fi

#
# S8 systems can be installed 32-bit only.
#
if [ ! -h sparcv9 -a -d sparcv9 ]; then
	cd sparcv9

	sig1=`sum libthread.so.1 | cut -f1 -d' '`
	sig2=`sum ../lwp/sparcv9/libthread.so.1 | cut -f1 -d' '`
	if [ $sig1 -ne $sig2 ]; then
		safe_link ../lwp/sparcv9/libthread.so.1 libthread.so.1 h
	fi

	sig1=`sum libthread_db.so.1 | cut -f1 -d' '`
	sig2=`sum ../lwp/sparcv9/libthread_db.so.1 | cut -f1 -d' '`
	if [ $sig1 -ne $sig2 ]; then
		safe_link ../lwp/sparcv9/libthread_db.so.1 libthread_db.so.1 h
	fi
fi

BRANDDIR=/.SUNWnative/usr/lib/brand/solaris8;
FILEDIR=$BRANDDIR/files;
cd $ZONEROOT/sbin || exit 1

# update rc statup script
for i in rcS rc0 rc2 rc3
do
	safe_replace $i $FILEDIR/$i 0744 root:sys keep
done
cd $ZONEROOT/etc/init.d
for i in /usr/lib/brand/solaris8/files/init.d/*
do
        name=`basename $i`
	safe_replace $name $FILEDIR/init.d/$name 0744 root:sys keep
done

#
# Update sbcp to be a link to the native sbcp.  In Solaris 10 the kernel
# passes the return pc to sbcp using %g6.  In Solaris 8, %g7 was used.
#
# sbcp is a very simple program.  It does not need to be run as a native
# process.  It can link with the solaris 8 linker and libraries.
#
if [ -f $ZONEROOT/usr/4lib/sbcp -a -f /usr/4lib/sbcp ] ; then
	safe_link /.SUNWnative/usr/4lib/sbcp $ZONEROOT/usr/4lib/sbcp s \
	    || exit 1
fi

#
# Update prtconf to point to use the native prtconf, as the s8 prtconf
# fails due to zones do not having /devices.
#
# Since the zone may only have sparcv7 binaries, and the global zone only
# has a sparcv9 prtconf replace isaexec with a link to the native
# sparcv9 prtconf wrapper.  Also Replace sparcv9 prtconf with link to
# wrapper, just in case it is invoked directly instead of via isaexec
#
cd $ZONEROOT/usr/sbin || exit 1
safe_replace prtconf $BRANDDIR/s8_prtconf 0555 root:bin remove
if [ ! -h sparcv9 -a -d sparcv9 ]; then
	cd sparcv9 || exit 1
	safe_replace prtconf $BRANDDIR/s8_prtconf 0555 root:sys remove
fi

#
# Update prtdiag to print an error instead of dumping core, since prtdiag
# doesn't run inside a zone.  The various platform specific prtdiags are
# symlinked to the sun4u one.  There is no sun4v in S8.
#
cd $ZONEROOT/usr/platform || exit 1
if [ ! -h sun4u -a -d sun4u -a ! -h sun4u/sbin -a -d sun4u/sbin ]; then
	cd sun4u/sbin || exit 1
	safe_replace prtdiag $BRANDDIR/s8_prtdiag 0555 root:sys remove
fi
cd $ZONEROOT/usr/platform || exit 1
if [ ! -h sun4d -a -d sun4d -a ! -h sun4d/sbin -a -d sun4d/sbin ]; then
	cd sun4d/sbin || exit 1
	safe_replace prtdiag $BRANDDIR/s8_prtdiag 0555 root:sys remove
fi
cd $ZONEROOT/usr/platform || exit 1
if [ ! -h sun4us -a -d sun4us -a ! -h sun4us/sbin -a -d sun4us/sbin ]; then
	cd sun4us/sbin || exit 1
	safe_replace prtdiag $BRANDDIR/s8_prtdiag 0555 root:sys remove
fi

#
# Update psrinfo to use the native psrinfo, as the s8 psrinfo fails on OPL
# and emulating the kstat differences for OPL is complex.  The original
# OPL bug is:
#     6363544 psrinfo(1M) -p dumps core on OPL
#
cd $ZONEROOT/usr/sbin || exit 1
safe_replace psrinfo $BRANDDIR/s8_psrinfo 0555 root:sys remove

# Update ipsecconf and ipseckey to use the native versions.  The private
# ioctl interfaces to the kernel have changed.
cd $ZONEROOT/usr/sbin || exit 1
safe_replace ipsecconf $BRANDDIR/s8_ipsecconf 0555 root:sys remove
safe_replace ipseckey $BRANDDIR/s8_ipseckey 0555 root:sys remove

#
# Update netstat to use the native netstat, as the s8 psrinfo fails on -i.
#
cd $ZONEROOT/usr/bin || exit 1
safe_replace netstat $BRANDDIR/s8_netstat 0555 root:sys remove

# update lockd and statd so that they run the native binaries
cd $ZONEROOT/usr/lib
if [ ! -h nfs -a -d nfs ]; then
	cd nfs || exit 1
	safe_replace lockd $BRANDDIR/s8_lockd 0555 root:bin remove
	safe_replace statd $BRANDDIR/s8_statd 0555 root:bin remove
fi
cd $d

#
# Now lofs mount our /dev/ksyms substitute
# This is a workaround for 4319403 and 4343253.
#
mount -F lofs -o ro /usr/lib/brand/solaris8/s8_ksyms \
	$ZONEROOT/dev/ksyms || exit 1

#
# If this is not an exclusive stack zone, create a dummy
# /dev/ip to make mibiisa happy
#
if [ ! -c $ZONEROOT/dev/ip ]; then
	ln -s /dev/null $ZONEPATH/dev/ip || exit 1
fi

#
# Make of a copy of /etc/system during boot.  This copy is used by
# the emulated init(1m) and settaskid(2) for setting rctls based on
# /etc/system tunables.

if [ ! -h $ZONEROOT/etc -a -d $ZONEROOT/etc ]; then
	safe_copy $ZONEROOT/etc/system $ZONEROOT/.etc_system.boot
fi

#
# For exclusive stack zones, install ipsecalgs.
#
if [ -c $ZONEPATH/dev/rawip -a ! -h $ZONEROOT/etc -a \
    ! -h $ZONEROOT/etc/inet -a -d $ZONEROOT/etc/inet ] ; then
	safe_copy /etc/inet/ipsecalgs $ZONEROOT/etc/inet/ipsecalgs
fi

exit 0
