#!/bin/ksh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# ident	"@(#)bfu.sh	1.432	08/01/28 SMI"
#
# Upgrade a machine from a cpio archive area in about 5 minutes.
# By Roger Faulkner and Jeff Bonwick, April 1993.
# (bfu == Bonwick/Faulkner Upgrade, a.k.a. Blindingly Fast Upgrade)
#
# Usage: bfu    [-f] <archive_dir> [root-dir]	# for normal machines
#        bfu -c [-f] <archive_dir> <exec-dir>	# for diskless clients
#
# The -f flag is to override the built-in safety check which requires
# that the starting-point OS be a least a certain revision.
#
# You have to be super-user.  It's safest to run this from the
# system console, although I've run it under OW and even via
# remote login with no problems.
#
# You will have to reboot the system when the upgrade is complete.
#
# You should add any administrative files you care about to this list.
# Warning: there had better be no leading '/' on any of these filenames.

#
# The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout
# under certain circumstances, which can really screw things up; unset it.
#
unset CDPATH

export LC_ALL="C"

if [ -z "$GATEPATH" ]; then
	GATEPATH=/ws/onnv-gate
	test -d $GATEPATH || GATEPATH=/net/onnv.eng/export/gate
fi
if [ -z "$ARCHIVEPATH" ]; then
	ARCHIVEPATH=/ws/onnv-gate
	test -d $ARCHIVEPATH || ARCHIVEPATH=/net/onnv.eng/export
fi
export GATE=${GATEPATH}
export ARCHIVE=${ARCHIVEPATH}

#
# NOTE:	Entries in *_files must expand to either the exact files required,
#	or to directories that will be scoured for files.  Any directories
#	(and subdirectories) resulting from a wildcard expansion will be
#	fully recursed by BFU's searching for files.  (E.g. /etc/inet/* will
#	include all files in any of its directories, as well as any files in
#	/etc/inet/ itself.
#
#	These lists should really be generated automatically from the
#	pkgmap(4) metadata.
#

#
# First list: files to be saved in global and non-global zones.
#
all_zones_files="
	etc/.login
	etc/acct/holidays
	etc/acctadm.conf
	etc/auto_*
	etc/cron.d/at.deny
	etc/cron.d/cron.deny
	etc/crypto/pkcs11.conf
	etc/default/*
	etc/dev/reserved_devnames
	etc/dfs/dfstab
	etc/dumpdates
	etc/ftpd/*
	etc/ftpusers
	etc/group
	etc/gss/gsscred.conf
	etc/gss/mech
	etc/gss/qop
	etc/inet/*
	etc/init.d/*
	etc/inittab
	etc/ipf/ipf.conf
	etc/iu.ap
	etc/krb5/kadm5.acl
	etc/krb5/kdc.conf
	etc/krb5/kpropd.acl
	etc/krb5/krb5.conf
	etc/krb5/warn.conf
	etc/ksh.kshrc
	etc/logadm.conf
	etc/logindevperm
	etc/lp/Systems
	etc/mail/*.cf
	etc/mail/*.hf
	etc/mail/*.rc
	etc/mail/aliases
	etc/mail/helpfile
	etc/mail/local-host-names
	etc/mail/trusted-users
	etc/named.conf
	etc/net/*/services
	etc/netconfig
	etc/nfs/nfslog.conf
	etc/nfssec.conf
	etc/nscd.conf
	etc/nsswitch.*
	etc/pam.conf
	etc/passwd
	etc/policy.conf
	etc/printers.conf
	etc/profile
	etc/project
	etc/publickey
	etc/remote
	etc/resolv.conf
	etc/rmmount.conf
	etc/rpc
	etc/rpld.conf
	etc/saf/_sactab
	etc/saf/_sysconfig
	etc/saf/zsmon/_pmtab
	etc/security/audit_class
	etc/security/audit_control
	etc/security/audit_event
	etc/security/audit_startup
	etc/security/audit_user
	etc/security/audit_warn
	etc/security/auth_attr
	etc/security/crypt.conf
	etc/security/exec_attr
	etc/security/policy.conf
	etc/security/prof_attr
	etc/sfw/openssl/openssl.cnf
	etc/shadow
	etc/skel/.profile
	etc/skel/local.*
	etc/smartcard/.keys
	etc/smartcard/desktop.properties
	etc/smartcard/ocf.classpath
	etc/smartcard/opencard.properties
	etc/ssh/ssh_config
	etc/ssh/sshd_config
	etc/syslog.conf
	etc/ttydefs
	etc/ttysrch
	etc/user_attr
	etc/uucp/[A-Z]*
	etc/vfstab
	var/smb/*
	var/spool/cron/crontabs/*
	var/yp/Makefile
	var/yp/aliases
	var/yp/nicknames
"

#
# Second list: files to be saved in the global zone only.
#
global_zone_only_files="
	boot/grub/menu.lst
	boot/solaris/bootenv.rc
	boot/solaris/devicedb/master
	boot/solaris/filelist.ramdisk
	etc/aggregation.conf
	etc/dladm/*
	etc/bootrc
	etc/crypto/kcf.conf
	etc/datalink.conf
	etc/devlink.tab
	etc/driver_aliases
	etc/driver_classes
	etc/lvm/devpath
	etc/lvm/lock
	etc/lvm/md.cf
	etc/lvm/md.ctlrmap
	etc/lvm/md.tab
	etc/lvm/mddb.cf
	etc/lvm/runtime.cf
	etc/mach
	etc/minor_perm
	etc/name_to_major
	etc/name_to_sysnum
	etc/nca/nca.if
	etc/nca/ncakmod.conf
	etc/nca/ncalogd.conf
	etc/nca/ncaport.conf
	etc/openwin/server/etc/OWconfig
	etc/path_to_inst
	etc/power.conf
	etc/ppp/chap-secrets
	etc/ppp/options
	etc/ppp/pap-secrets
	etc/security/device_policy
	etc/security/extra_privs
	etc/security/tsol/tnrhdb
	etc/security/tsol/tnrhtp
	etc/security/tsol/tnzonecfg
	etc/security/tsol/label_encodings
	etc/security/tsol/relabel
	etc/security/tsol/devalloc_defaults
	etc/system
	etc/dladm/vnic.conf
	etc/inet/flowadm.conf
	etc/inet/flowprop.conf
	etc/zones/index
	kernel/drv/elxl.conf
	kernel/drv/md.conf
	kernel/drv/options.conf
	kernel/drv/ra.conf
	kernel/drv/scsa2usb.conf
	kernel/drv/scsi_vhci.conf
	kernel/drv/sd.conf
	kernel/drv/mpt.conf
	platform/*/kernel/drv/*ppm.conf
	platform/i86pc/kernel/drv/aha.conf
	platform/i86pc/kernel/drv/asy.conf
	platform/sun4u/boot.conf
"

#
# Third list: files extracted from generic.root but which belong in the global
# zone only: they are superfluous (and some even harmful) in nonglobal zones.
#
# (note: as /etc/init.d scripts are converted to smf(5) "Greenline" services,
# they (and their /etc/rc?.d hardlinks) should be removed from this list when
# they are added to smf_obsolete_rc_files, below)
#
superfluous_nonglobal_zone_files="
	dev/dsk
	dev/fd
	dev/pts
	dev/rdsk
	dev/rmt
	dev/stderr
	dev/stdin
	dev/stdout
	dev/swap
	dev/term
	devices
	etc/dacf.conf
	etc/dat
	etc/default/metassist.xml
	etc/default/power
	etc/flash/postdeployment/svm.cleanup
	etc/flash/predeployment/svm.save
	etc/inet/ipqosconf.1.sample
	etc/inet/ipqosconf.2.sample
	etc/inet/ipqosconf.3.sample
	etc/inet/sock2path
	etc/init.d/devlinks
	etc/init.d/dodatadm.udaplt
	etc/init.d/drvconfig
	etc/init.d/llc2
	etc/init.d/ncakmod
	etc/init.d/ncalogd
	etc/init.d/pcmcia
	etc/init.d/pppd
	etc/init.d/wrsmcfg
	etc/llc2
	etc/lvm
	etc/nca
	etc/openwin
	etc/ppp
	etc/rc0.d/K34ncalogd
	etc/rc0.d/K50pppd
	etc/rc0.d/K52llc2
	etc/rc1.d/K34ncalogd
	etc/rc1.d/K50pppd
	etc/rc1.d/K52llc2
	etc/rc2.d/S40llc2
	etc/rc2.d/S42ncakmod
	etc/rc2.d/S47pppd
	etc/rc2.d/S81dodatadm.udaplt
	etc/rc2.d/S94ncalogd
	etc/rcS.d/K34ncalogd
	etc/rcS.d/K44wrsmcfg
	etc/rcS.d/K50pppd
	etc/rcS.d/K52llc2
	etc/rcS.d/S29wrsmcfg
	etc/rcm
	etc/sock2path
	etc/usb
	etc/wrsm
	etc/zones
	kernel
	lib/libmeta.so
	lib/libmeta.so.1
	lib/svc/method/sf880dr
	lib/svc/method/svc-cvcd
	lib/svc/method/svc-dcs
	lib/svc/method/svc-drd
	lib/svc/method/svc-dscp
	lib/svc/method/svc-dumpadm
	lib/svc/method/svc-intrd
	lib/svc/method/svc-hal
	lib/svc/method/svc-labeld
	lib/svc/method/svc-mdmonitor
	lib/svc/method/svc-metainit
	lib/svc/method/svc-metasync
	lib/svc/method/svc-oplhpd
	lib/svc/method/svc-poold
	lib/svc/method/svc-pools
	lib/svc/method/svc-power
	lib/svc/method/svc-resource-mgmt
	lib/svc/method/svc-rmvolmgr
	lib/svc/method/svc-scheduler
	lib/svc/method/svc-sckmd
	lib/svc/method/svc-syseventd
	lib/svc/method/svc-tnctl
	lib/svc/method/svc-tnd
	lib/svc/method/svc-vntsd
	lib/svc/method/svc-zones
	platform/*/kernel
	platform/SUNW,Sun-Fire-15000/lib/cvcd
	platform/SUNW,Ultra-Enterprise-10000/lib/cvcd
	platform/i86pc/biosint
	platform/i86pc/multiboot
	platform/sun4u/cprboot
	platform/sun4u/lib/libwrsmconf.so
	platform/sun4u/lib/libwrsmconf.so.1
	platform/sun4u/lib/sparcv9/libwrsmconf.so
	platform/sun4u/lib/sparcv9/libwrsmconf.so.1
	platform/sun4u/sbin
	platform/sun4u/wanboot
	platform/sun4v/wanboot
	sbin/metadb
	sbin/metadevadm
	sbin/metainit
	sbin/metarecover
	sbin/metastat
	usr/include/sys/dcam
	usr/lib/devfsadm/linkmod/SUNW_dcam1394_link.so
	usr/lib/ldoms
	usr/platform/SUNW,SPARC-Enterprise/lib/dscp.ppp.options
	usr/platform/SUNW,SPARC-Enterprise/lib/libdscp.so
	usr/platform/SUNW,SPARC-Enterprise/lib/libdscp.so.1
	usr/platform/SUNW,SPARC-Enterprise/lib/llib-ldscp.ln
	usr/platform/SUNW,SPARC-Enterprise/sbin/prtdscp
	var/adm/pool
	var/log/pool
	var/svc/manifest/network/rpc/mdcomm.xml
	var/svc/manifest/network/rpc/meta.xml
	var/svc/manifest/network/rpc/metamed.xml
	var/svc/manifest/network/rpc/metamh.xml
	var/svc/manifest/network/tnctl.xml
	var/svc/manifest/network/tnd.xml
	var/svc/manifest/platform/i86pc/eeprom.xml
	var/svc/manifest/platform/sun4u/dcs.xml
	var/svc/manifest/platform/sun4u/dscp.xml
	var/svc/manifest/platform/sun4u/efdaemon.xml
	var/svc/manifest/platform/sun4u/oplhpd.xml
	var/svc/manifest/platform/sun4u/sckmd.xml
	var/svc/manifest/platform/sun4u/sf880drd.xml
	var/svc/manifest/platform/sun4v
	var/svc/manifest/system/cvc.xml
	var/svc/manifest/system/dumpadm.xml
	var/svc/manifest/system/fmd.xml
	var/svc/manifest/system/hal.xml
	var/svc/manifest/system/intrd.xml
	var/svc/manifest/system/labeld.xml
	var/svc/manifest/system/mdmonitor.xml
	var/svc/manifest/system/metainit.xml
	var/svc/manifest/system/metasync.xml
	var/svc/manifest/system/picl.xml
	var/svc/manifest/system/poold.xml
	var/svc/manifest/system/pools.xml
	var/svc/manifest/system/power.xml
	var/svc/manifest/system/resource-mgmt.xml
	var/svc/manifest/system/scheduler.xml
	var/svc/manifest/system/sysevent.xml
	var/svc/manifest/system/zones.xml
	var/svc/manifest/system/filesystem/rmvolmgr.xml
"

#
# Fourth list: files to be preserved, ie unconditionally restored to
# "child" versions
#
preserve_files="
	kernel/misc/amd64/sysinit
	kernel/misc/amd64/usbs49_fw
	kernel/misc/sparcv9/usbs49_fw
	kernel/misc/sysinit
	kernel/misc/usbs49_fw
	var/adm/aculog
	var/adm/spellhist
	var/adm/utmpx
	var/adm/wtmpx
	var/log/authlog
	var/log/syslog
	var/saf/zsmon/log
"

realmode_files="
	boot/solaris/bootenv.rc
	boot/solaris/devicedb/master
"

fail() {
	print "$*" >& 2
	print "bfu aborting" >& 2
	rm -f "$bfu_zone_list"
	exit 1
}

filelist() {
	files="$all_zones_files $preserve_files"
	if [ $1 = "global" ]; then
		files="$global_zone_only_files $files"
	fi
	find $files -depth -type f ! -name core -print 2>/dev/null | sort -u || {
		#
		# Force cpio to return non-zero by printing an error message
		# to stdout that it won't be able to lstat().
		#
		echo 'filelist: sort failed'
		fail "sort failed"
	}
}

realmode_filelist() {
	find $realmode_files -depth -type f ! -name core -print 2>/dev/null | sort
}

smf_inetd_conversions="
	100134
	100150
	100155
	100229
	100230
	100234
	100242
	100422
	chargen
	comsat
	daytime
	discard
	echo
	eklogin
	exec
	finger
	ftp
	gssd
	klogin
	krb5_prop
	kshell
	ktkt_warnd
	login
	metad
	metamedd
	metamhd
	name
	ocfserv
	printer
	rexd
	rquotad
	rstatd
	rusersd
	shell
	smserverd
	sprayd
	sun-dr
	talk
	telnet
	time
	uucp
	walld
"

enable_next_boot () {
	if [ -x /tmp/bfubin/svccfg ]; then
	    svcadm disable -t $1
	    [ $? = 0 ] || echo "warning: unable to temporarily disable $1"
	    svccfg -s $1 setprop general/enabled = true
	    [ $? = 0 ] || echo "warning: unable to enable $1 for next boot"
	fi
}

smf_inetd_disable() {
	inetconf=$rootprefix/etc/inet/inetd.conf
	inettmp=/tmp/inetd.tmp.$$

	sed "$(for i in $smf_inetd_conversions; do 
		echo "s:^[ 	]*$i[ 	/]:#SMFbfu# &:"
	done)" $inetconf > $inettmp && ! cmp -s $inettmp $inetconf &&
	    cp $inettmp $inetconf

	rm -f -- $inettmp
}

smf_inetd_reenable() {
	inetconf=$rootprefix/etc/inet/inetd.conf
	inettmp=/tmp/inetd.tmp.$$

	sed 's/^#SMFbfu# //' $inetconf > $inettmp && cp $inettmp $inetconf

	rm -f -- $inettmp
}

smf_tftp_reinstall() {
	inetconf=$rootprefix/etc/inet/inetd.conf
	inettmp=/tmp/inetd.tmp.$$

	if grep '^#SMFbfu# tftp' $inetconf >/dev/null ; then
		# BFU previously commented out, put it back in place
	    	sed 's/^#SMFbfu# tftp/tftp/' $inetconf > $inettmp &&
		    cp $inettmp $inetconf
	elif ! grep '^[#	 ]*tftp' $inetconf >/dev/null; then
		# No entry, append to end
		cat >>$inetconf <<EOF
# TFTPD - tftp server (primarily used for booting)
#tftp	dgram	udp6	wait	root	/usr/sbin/in.tftpd	in.tftpd -s /tftpboot
EOF
	fi

	rm -f -- $inettmp
}

inetd_conf_svm_hack() {
	# Since inetd.conf is updated by SUNWmdr's postinstall script,
	# we will update the actual inetd.conf here to reflect the postinstall
	# changes.

	inetconf=$rootprefix/etc/inet/inetd.conf
	inettmp=/tmp/inetd.tmp.$$
	inetnew=/tmp/inetd.new.$$

	#
	# only change inetd.conf if the rpc.metad entry is out of date
	#

	if ! grep "^[# 	]*100229/1-2" $inetconf > /dev/null ; then

		# Grab existing rpc entries for rpc.metad
		# and convert spaces to tabs within the rpc entry, as well as
		# the transport method; 
		# or add a new entry in case there was none.
		if grep "^[# 	]*100229/1" $inetconf > /dev/null ; then
			grep "^# METAD - SLVM metadb" $inetconf > $inettmp
			grep "^[# 	]*100229/1" $inetconf | \
			    sed -e 's/[ 	][ 	]*/	/g' \
				-e 's?100229/1?100229/1-2?' >> $inettmp
		else
			echo '# METAD - SVM metadb Daemon' > $inettmp
			echo "100229/1-2\ttli\trpc/tcp\twait\troot\t/usr/sbin/rpc.metad\trpc.metad" >> $inettmp
		fi

		grep -v '^# METAD - SLVM metadb' $inetconf | \
		    grep -v '^[# 	]*100229/1' > $inetnew
		cat $inettmp >> $inetnew

		if ! diff $inetnew $inetconf > /dev/null ; then
			print "Updating inet.conf metad entry ... \c"
			if cp $inetnew $inetconf ; then
				print "done."
			else
				print "failed."
			fi
		fi
		rm -f $inettmp $inetnew
	fi

	#
	# only change inetd.conf if the rpc.mdcommd entry is out of date
	#

	if ! grep "^[# 	]*100422/1" $inetconf > /dev/null ; then

		# Grab existing rpc entries for rpc.mdcommd
		# and convert spaces to tabs within the rpc entry,
		# or add a new entry in case there was none.
		if grep "^[#    ]*100422/1" $inetconf > /dev/null ; then
			grep "^# MDMN_COMMD - SVM Multi node" $inetconf > $inettmp
			grep "^[#       ]*100422/1" $inetconf | \
				sed -e 's/[         ][      ]*/     /g' >> $inettmp 
		else
			echo '# MDMN_COMMD - SVM Multi node communication daemon' >$inettmp
			echo '100422/1\ttli\trpc/tcp\twait\troot\t/usr/sbin/rpc.mdcommd\trpc.mdcommd' >> $inettmp
		fi

		grep -v '^# MDMN_COMMD - SVM Multi node' $inetconf | \
		grep -v '^[#        ]*100422/1' > $inetnew
		cat $inettmp >> $inetnew

		if ! diff $inetnew $inetconf > /dev/null ; then
			print "Updating inetd.conf rpc.mdcommd entry ... \c"
			if cp $inetnew $inetconf; then
				print "done."
			else
				print "failed."
			fi
		fi

		rm -f $inettmp $inetnew
	fi
}

# update x86 version mpt.conf for property tape
mpttapeprop='[ 	]*tape[ 	]*=[ 	]*"sctp"[ 	]*;'
update_mptconf_i386()
{
	conffile=$rootprefix/kernel/drv/mpt.conf
	test -f $conffile || return
	egrep -s "$mpttapeprop" $conffile
	if [ $? -ne 0 ] ; then
	    echo 'tape="sctp";' >> $conffile
	fi
}

update_policy_conf() {
	# update /etc/security/policy.conf with the default
	# Solaris crypt(3c) policy.
	
	dest=$rootprefix/etc/security/policy.conf

	grep 'CRYPT_' $dest > /dev/null 2>&1
	if [ $? = 1 ] ; then
		print "Updating entries for crypt(3c), see policy.conf(4)"
	cat >> $dest <<EOM

# crypt(3c) Algorithms Configuration
#
# CRYPT_ALGORITHMS_ALLOW specifies the algorithms that are allowed to
# be used for new passwords.  This is enforced only in crypt_gensalt(3c).
#
CRYPT_ALGORITHMS_ALLOW=1,2a,md5

# To deprecate use of the traditional unix algorithm, uncomment below
# and change CRYPT_DEFAULT= to another algorithm.  For example,
# CRYPT_DEFAULT=1 for BSD/Linux MD5.
#
#CRYPT_ALGORITHMS_DEPRECATE=__unix__

# The Solaris default is the traditional UNIX algorithm.  This is not
# listed in crypt.conf(4) since it is internal to libc.  The reserved
# name __unix__ is used to refer to it.
#
CRYPT_DEFAULT=__unix__
EOM
	fi
	grep PRIV_ $dest >/dev/null 2>&1
	if [ $? = 1 ]; then
		echo "Updating entries for privileges(5)," \
		     "see policy.conf(4) for details."
cat >> $dest <<EOM
#
# These settings determine the default privileges users have.  If not set,
# the default privileges are taken from the inherited set.
# There are two different settings; PRIV_DEFAULT determines the default
# set on login; PRIV_LIMIT defines the Limit set on login.
# Individual users can have privileges assigned or taken away through
# user_attr.  Privileges can also be assigned to profiles in which case
# the users with those profiles can use those privileges through pfexec(1m).
# For maximum future compatibility, the specifications should
# always include "basic" or "all"; privileges should then be removed using
# the negation.  E.g., PRIV_LIMIT=all,!sys_linkdir takes away only the
# sys_linkdir privilege, regardless of future additional privileges.
# Similarly, PRIV_DEFAULT=basic,!file_link_any takes away only the
# file_link_any privilege from the basic privilege set; only that notation
# is immune from a future addition of currently unprivileged operations to
# the basic privilege set.
# NOTE: removing privileges from the the Limit set requires EXTREME care
# as any set-uid root program may suddenly fail because it lacks certain
# privilege(s).
#
#PRIV_DEFAULT=basic
#PRIV_LIMIT=all
EOM
	fi

}

#
# Cleanup nfsmapid configuration before extracting
# root bits.  Remove if they exist:
#	nfsmapid entry in inetd.conf
#	nfsmapid entry in /etc/net/ti*/services
#
# Going forward neither should exist, but no harm if services entry exists
# Going way backwards (pre-04/28/2004), inetd.conf must exist but will
# be a conflict that should be merged in
#
nfsmapid_cfg() {
	inetdconf=$rootprefix/etc/inet/inetd.conf
	tmpinetcf=/tmp/inetd.conf.$$
	cp -pf ${inetdconf} ${tmpinetcf}
	cat /dev/null > ${inetdconf} 2>&1
       	sed -e "/^#[#	 ]*NFSv4/d"		\
	    -e "/^[#	 ]*100166\/1/d"		\
	    ${tmpinetcf} > ${inetdconf} 2>&1
	rm -f ${tmpinetcf}

	tmpservices=/tmp/services.$$

	services=$rootprefix/etc/net/ticotsord/services
	cp -pf ${services} ${tmpservices}
	cat /dev/null > ${services} 2>&1
       	sed -e "/^[#	 ]*nfsmapid/d"		\
	    ${tmpservices} > ${services} 2>&1
	rm -f ${tmpservices}

	services=$rootprefix/etc/net/ticots/services
	cp -pf ${services} ${tmpservices}
	cat /dev/null > ${services} 2>&1
       	sed -e "/^[#	 ]*nfsmapid/d"		\
	    ${tmpservices} > ${services} 2>&1
	rm -f ${tmpservices}

	services=$rootprefix/etc/net/ticlts/services
	cp -pf ${services} ${tmpservices}
	cat /dev/null > ${services} 2>&1
       	sed -e "/^[#	 ]*nfsmapid/d"		\
	    ${tmpservices} > ${services} 2>&1
	rm -f ${tmpservices}
}

#
# Define global variables
#
CALL_DEVID_DESTROY=""
#
# List of SDS commands that must be deleted.
#
SDSCMDLIST="
growfs
metaclear
metadb
metadetach
metahs
metainit
metaoffline
metaonline
metaparam
metarename
metareplace
metaroot
metaset
metastat
metasync
metattach
rpc.metad
rpc.metamhd
"
#
# List of SDS configuration files that must be deleted.
#
SDSCONFIGLIST="
lock
md.cf
mddb.cf
md.tab
devpath
md.ctlrmap
"
#
# List of rc scripts that must be deleted.
#
RCLIST="
etc/init.d/SUNWmd.init
etc/init.d/SUNWmd.sync
etc/init.d/lvm.init
etc/init.d/lvm.sync
etc/rcS.d/S35SUNWmd.init
etc/rcS.d/S35lvm.init
etc/rc2.d/S95SUNWmd.sync
etc/rc2.d/S95lvm.sync
etc/rcS.d/S35slvm.init
etc/rc2.d/S95slvm.sync
etc/init.d/slvm.init
etc/init.d/slvm.sync
etc/init.d/init.mdlogd
etc/rc3.d/S25mdlogd
"
#
# List of flashprom-related files that must be deleted.
#
FLASHPROMLIST="
etc/rc2.d/S75flashprom
etc/init.d/flashprom
usr/platform/SUNW,Ultra-2/lib/flash-update.sh
usr/platform/SUNW,Ultra-4/lib/flash-update.sh
usr/platform/SUNW,Ultra-Enterprise/lib/flash-update.sh
usr/platform/sun4u/doc/flashupdate.txt
usr/platform/sun4u/lib/flash-update.sh
usr/platform/sun4u/lib/prom/SUNW,Ultra-2
usr/platform/sun4u/lib/prom/SUNW,Ultra-4
usr/platform/sun4u/lib/prom/SUNW,Ultra-Enterprise
"

#
# delete the entries associated with bootlist from /etc/system
#

delete_system_bootlist() {
	sed -e /"Begin MDD database info"/,/"End MDD database info"/d \
	    < ${SYSTEM_FILE} > /tmp/system.$$
	cp /tmp/system.$$ ${SYSTEM_FILE} || \
	    echo "copy error: /tmp/system.$$ to ${SYSTEM_FILE}"
}

#
# Add entries in md.conf for bootlist
#

fix_mdconf() {
	cp ${mdconf} /tmp/md.conf.$$
	echo >> /tmp/md.conf.$$
	echo "# Begin MDD database info (do not edit)" >> /tmp/md.conf.$$
	sed -e 's/^set md://' -e 's/$/;/' ${SYSTEM_FILE} | \
	    grep mddb_bootlist >> /tmp/md.conf.$$
	echo "# End MDD database info (do not edit)" >> /tmp/md.conf.$$
	cp /tmp/md.conf.$$ ${mdconf} || \
	    echo "copy error: /tmp/md.conf.$$ to ${mdconf}"
}

#
# add_devid_destroy(filename)
# returns contents in filename
# md_devid_destroy property is required when upgrading
# from pre SVM to SVM releases or when the device ID returned from
# the driver changes.
# It is specifically placed between
# # Begin MDD database info and # End MDD database info because
# on the subsequent reboot, this line will be removed automatically when
# metadevadm is run in rc2.d.
#
add_devid_destroy() {
	cat $1 | awk '{
		if ( $2 == "End" && $4 == "database") {
			print "md_devid_destroy=1;"
		}
		print $0
	}' >> /tmp/t$$
	mv /tmp/t$$ $1
}

#
# Reads existing configuration values in /etc/rcap.conf and puts 
# them in repository upon reboot(via /var/svc/profile/upgrade).
#
migrate_rcap_conf() {
	RCAP_CONF="${rootprefix}/etc/rcap.conf"
	PROFILE_UPGRADE="${rootprefix}/var/svc/profile/upgrade"
	SVCCFG="/usr/sbin/svccfg"
	RCAP_FMRI="svc:/system/rcap:default"
	PG="config"

	pressure=`awk '$1 == "RCAPD_MEMORY_CAP_ENFORCEMENT_PRESSURE" \
	    && NF == 3 {print $3}' $RCAP_CONF`

	reconfig_int=`awk '$1 == "RCAPD_RECONFIGURATION_INTERVAL" \
	    && NF == 3 {print $3}' $RCAP_CONF`

	walk_int=`awk '$1 == "RCAPD_PROC_WALK_INTERVAL" && \
	    NF == 3 {print $3}' $RCAP_CONF`

	report_int=`awk '$1 == "RCAPD_REPORT_INTERVAL" && \
	    NF == 3 {print $3}' $RCAP_CONF`

	rss_sample_int=`awk '$1 == "RCAPD_RSS_SAMPLE_INTERVAL" && \
	    NF == 3 {print $3}' $RCAP_CONF`

	# Blindly update default configuration values with
	# pre-existing values
	#
	echo "# Migrating pre-existing rcap configuration" >> \
	    $PROFILE_UPGRADE

	echo "$SVCCFG -s $RCAP_FMRI setprop ${PG}/pressure = " \
	    "$pressure" >> $PROFILE_UPGRADE

	echo "$SVCCFG -s $RCAP_FMRI " \
	    "setprop ${PG}/reconfig_interval = $reconfig_int" >> \
	    $PROFILE_UPGRADE

	echo "$SVCCFG -s $RCAP_FMRI " \
	    "setprop ${PG}/walk_interval = $walk_int" >> \
	    $PROFILE_UPGRADE

	echo "$SVCCFG -s $RCAP_FMRI " \
	    "setprop ${PG}/report_interval = $report_int" >> \
	    $PROFILE_UPGRADE

	echo "$SVCCFG -s $RCAP_FMRI " \
	    "setprop ${PG}/rss_sample_interval = $rss_sample_int" >> \
	    $PROFILE_UPGRADE

	echo "/usr/sbin/svcadm refresh $RCAP_FMRI" >> \
	    $PROFILE_UPGRADE

	echo "rm /etc/rcap.conf" >> \
	    $PROFILE_UPGRADE
}

#
# smf(5) "Greenline" doesn't install the init.d or rc*.d scripts for
# converted services.  Clean up previous scripts for such services.
#
smf_obsolete_rc_files="
	etc/init.d/ANNOUNCE
	etc/init.d/MOUNTFSYS
	etc/init.d/RMTMPFILES
	etc/init.d/audit
	etc/init.d/autofs
	etc/init.d/coreadm
	etc/init.d/cron
	etc/init.d/cryptosvc
	etc/init.d/cvc
	etc/init.d/devfsadm
	etc/init.d/dhcp
	etc/init.d/dhcpagent
	etc/init.d/domainname
	etc/init.d/efcode
	etc/init.d/inetd
	etc/init.d/inetinit
	etc/init.d/inetsvc
	etc/init.d/initboot
	etc/init.d/ipfboot
	etc/init.d/kdc
	etc/init.d/kdc.master
	etc/init.d/keymap
	etc/init.d/ldap.client
	etc/init.d/libc.mount
	etc/init.d/network
	etc/init.d/nfs.client
	etc/init.d/nodename
	etc/init.d/nscd
	etc/init.d/perf
	etc/init.d/picld
	etc/init.d/power
	etc/init.d/rcapd
	etc/init.d/rootusr
	etc/init.d/rpc
	etc/init.d/savecore
	etc/init.d/sckm
	etc/init.d/sf880dr
	etc/init.d/slpd
	etc/init.d/sshd
	etc/init.d/standardmounts
	etc/init.d/svm.init
	etc/init.d/svm.sync
	etc/init.d/sysid.net
	etc/init.d/sysid.sys
	etc/init.d/syslog
	etc/init.d/utmpd
	etc/init.d/volmgt
	etc/init.d/xntpd
	etc/init.d/zones
	etc/rc0.d/K00ANNOUNCE
	etc/rc0.d/K01zones
	etc/rc0.d/K03sshd
	etc/rc0.d/K05volmgt
	etc/rc0.d/K07snmpdx
	etc/rc0.d/K10rcapd
	etc/rc0.d/K21dhcp
	etc/rc0.d/K28kdc
	etc/rc0.d/K28kdc.master
	etc/rc0.d/K28nfs.server
	etc/rc0.d/K32cryptosvc
	etc/rc0.d/K33audit
	etc/rc0.d/K33efcode
	etc/rc0.d/K34svm.sync
	etc/rc0.d/K36sendmail
	etc/rc0.d/K36utmpd
	etc/rc0.d/K37power
	etc/rc0.d/K40cron
	etc/rc0.d/K40inetd
	etc/rc0.d/K40nscd
	etc/rc0.d/K40sf880dr
	etc/rc0.d/K40slpd
	etc/rc0.d/K40syslog
	etc/rc0.d/K40xntpd
	etc/rc0.d/K41autofs
	etc/rc0.d/K41ldap.client
	etc/rc0.d/K41nfs.client
	etc/rc0.d/K41rpc
	etc/rc0.d/K42sckm
	etc/rc0.d/K43inet
	etc/rc0.d/K68picld
	etc/rc0.d/K83devfsadm
	etc/rc0.d/K90dhcpagent
	etc/rc1.d/K00ANNOUNCE
	etc/rc1.d/K01zones
	etc/rc1.d/K03sshd
	etc/rc1.d/K05volmgt
	etc/rc1.d/K07snmpdx
	etc/rc1.d/K10rcapd
	etc/rc1.d/K21dhcp
	etc/rc1.d/K28kdc
	etc/rc1.d/K28kdc.master
	etc/rc1.d/K28nfs.server
	etc/rc1.d/K33audit
	etc/rc1.d/K33efcode
	etc/rc1.d/K34svm.sync
	etc/rc1.d/K36sendmail
	etc/rc1.d/K36utmpd
	etc/rc1.d/K37power
	etc/rc1.d/K40cron
	etc/rc1.d/K40inetd
	etc/rc1.d/K40nscd
	etc/rc1.d/K40sf880dr
	etc/rc1.d/K40slpd
	etc/rc1.d/K40syslog
	etc/rc1.d/K40xntpd
	etc/rc1.d/K41autofs
	etc/rc1.d/K41ldap.client
	etc/rc1.d/K41rpc
	etc/rc1.d/K42sckm
	etc/rc1.d/K43inet
	etc/rc1.d/K99libc.mount
	etc/rc1.d/S01MOUNTFSYS
	etc/rc2.d/K01zones
	etc/rc2.d/K03sshd
	etc/rc2.d/K05volmgt
	etc/rc2.d/K07snmpdx
	etc/rc2.d/K21dhcp
	etc/rc2.d/K28kdc
	etc/rc2.d/K28kdc.master
	etc/rc2.d/K28nfs.server
	etc/rc2.d/S01MOUNTFSYS
	etc/rc2.d/S05RMTMPFILES
	etc/rc2.d/S21perf
	etc/rc2.d/S30sysid.net
	etc/rc2.d/S65ipfboot
	etc/rc2.d/S69domainname
	etc/rc2.d/S69inet
	etc/rc2.d/S70sckm
	etc/rc2.d/S71ldap.client
	etc/rc2.d/S71rpc
	etc/rc2.d/S71sysid.sys
	etc/rc2.d/S72inetsvc
	etc/rc2.d/S72slpd
	etc/rc2.d/S73nfs.client
	etc/rc2.d/S74autofs
	etc/rc2.d/S74syslog
	etc/rc2.d/S74xntpd
	etc/rc2.d/S75cron
	etc/rc2.d/S75savecore
	etc/rc2.d/S76nscd
	etc/rc2.d/S77inetd
	etc/rc2.d/S77sf880dr
	etc/rc2.d/S85power
	etc/rc2.d/S88sendmail
	etc/rc2.d/S88utmpd
	etc/rc2.d/S95svm.sync
	etc/rc2.d/S98efcode
	etc/rc2.d/S98libc.mount
	etc/rc2.d/S99audit
	etc/rc2.d/S99rcapd
	etc/rc3.d/S13kdc.master
	etc/rc3.d/S14kdc
	etc/rc3.d/S15nfs.server
	etc/rc3.d/S34dhcp
	etc/rc3.d/S76snmpdx
	etc/rc3.d/S81volmgt
	etc/rc3.d/S89sshd
	etc/rc3.d/S99zones
	etc/rcS.d/K01zones
	etc/rcS.d/K03sshd
	etc/rcS.d/K05volmgt
	etc/rcS.d/K07snmpdx
	etc/rcS.d/K10rcapd
	etc/rcS.d/K21dhcp
	etc/rcS.d/K28kdc
	etc/rcS.d/K28kdc.master
	etc/rcS.d/K28nfs.server
	etc/rcS.d/K33audit
	etc/rcS.d/K33efcode
	etc/rcS.d/K34svm.sync
	etc/rcS.d/K36sendmail
	etc/rcS.d/K36utmpd
	etc/rcS.d/K37power
	etc/rcS.d/K40cron
	etc/rcS.d/K40inetd
	etc/rcS.d/K40nscd
	etc/rcS.d/K40sf880dr
	etc/rcS.d/K40slpd
	etc/rcS.d/K40syslog
	etc/rcS.d/K40xntpd
	etc/rcS.d/K41autofs
	etc/rcS.d/K41ldap.client
	etc/rcS.d/K41rpc
	etc/rcS.d/K42sckm
	etc/rcS.d/K43inet
	etc/rcS.d/K99libc.mount
	etc/rcS.d/S10cvc
	etc/rcS.d/S28network.sh
	etc/rcS.d/S29nodename.sh
	etc/rcS.d/S30rootusr.sh
	etc/rcS.d/S33keymap.sh
	etc/rcS.d/S35svm.init
	etc/rcS.d/S40standardmounts.sh
	etc/rcS.d/S42coreadm
	etc/rcS.d/S45initboot
	etc/rcS.d/S50devfsadm
	etc/rcS.d/S72cryptosvc
	etc/rcS.d/S95picld
"

# Obsolete smf manifests
smf_obsolete_manifests="
	var/svc/manifest/application/print/cleanup.xml
	var/svc/manifest/network/tftp.xml
	var/svc/manifest/network/lp.xml
	var/svc/manifest/system/filesystem/volfs.xml
	var/svc/manifest/network/pfil.xml
	var/svc/manifest/platform/sun4u/mpxio-upgrade.xml
	var/svc/manifest/network/tname.xml
"

# smf services whose manifests have been renamed
smf_renamed_manifests="
	var/svc/manifest/milestone/name-service.xml
	var/svc/manifest/system/filesystem/boot-archive.xml
"

# Obsolete smf methods
smf_obsolete_methods="
	lib/svc/method/print-cleanup
	lib/svc/method/print-server
	lib/svc/method/svc-volfs
	lib/svc/method/pfil
"

smf_cleanup () {
	(
		cd $root;
		print "Removing obsolete rc.d scripts ... \c"
		rm -f $smf_obsolete_rc_files
		print "done."
	)
}

smf_new_profiles () {
	[[ "$bfu_isa" = "sparc" ]] || return 0

	[[ -x /tmp/bfubin/svccfg ]] || return 0

	print "Clearing platform profile hash ..."

	# platform_SUNW,Sun-Fire.xml (and other new and
	# corrected platforms) were delivered in Build 68.
	if [ ! -f \
		$rootprefix/var/svc/profile/platform_SUNW,Sun-Fire.xml \
		]; then
		for pfx in " " "v"; do
			for plname in \
			    none \
			    SUNW_Sun_Fire_880 \
			    SUNW_Sun_Fire_V890 \
			    SUNW_Sun_Fire_15000 \
			    SUNW_UltraEnterprise_10000; do
				svccfg -f - <<EOF
select smf/manifest
delpg ${pfx}ar_svc_profile_platform_${plname}_xml
exit
EOF
			done
		done
	fi
}

smf_handle_new_services () {
	#
	# Detect, prior to extraction the arrival of new,
	# default-enabled-in-profile services.  If so, add a command
	# such that they are enabled.
	#
	if [ ! -f $rootprefix/var/svc/profile/system/sac.xml ]; then
		echo /usr/sbin/svcadm enable system/sac >> \
		    $rootprefix/var/svc/profile/upgrade
	fi
	if [[ $zone = global &&
            ! -f $rootprefix/var/svc/manifest/system/intrd.xml ]]; then
		echo /usr/sbin/svcadm enable system/intrd >> \
		    $rootprefix/var/svc/profile/upgrade
	fi
	if [[ $zone = global &&
	    ! -f $rootprefix/var/svc/manifest/system/scheduler.xml ]]; then
		echo /usr/sbin/svcadm enable system/scheduler >> \
		    $rootprefix/var/svc/profile/upgrade
	fi
	if [[ $zone = global &&
	    ! -f $rootprefix/var/svc/manifest/system/hal.xml ]]; then
		echo /usr/sbin/svcadm enable system/hal >> \
		    $rootprefix/var/svc/profile/upgrade
	fi
	if [[ $zone = global &&
	    ! -f $rootprefix/var/svc/manifest/system/filesystem/rmvolmgr.xml ]]; then
		echo /usr/sbin/svcadm enable system/filesystem/rmvolmgr >> \
		    $rootprefix/var/svc/profile/upgrade
	fi
	if [[ $zone = global &&
	    ! -f $rootprefix/var/svc/manifest/network/ipsec/manual-key.xml &&
	    -f $rootprefix/etc/inet/secret/ipseckeys ]]; then
		smf_enable svc:/network/ipsec/manual-key:default
	fi
	if [[ $zone = global &&
	    ! -f $rootprefix/var/svc/manifest/network/ipsec/ike.xml &&
	    -f $rootprefix/etc/inet/ike/config ]]; then
		smf_enable svc:/network/ipsec/ike:default
	fi
	if [[ $zone = global &&
	    ! -f $rootprefix/var/svc/manifest/system/pools.xml &&
	    -f $rootprefix/etc/pooladm.conf ]]; then
		smf_enable svc:/system/pools:default
	fi
}

smf_copy_manifest() {
	mfstbase=`basename $1`
	mymfs=$rootprefix/var/svc/manifest/$2/$mfstbase
	if [[ ! -f $mymfs ]] || ! cmp -s $manifest_src/$1 $mymfs ; then
		cp $manifest_src/$1 $mymfs ||
		    echo "bfu: could not copy $manifest_src/$1"
	fi
}

smf_copy_method() {
	cp $manifest_src/$1 $rootprefix/lib/svc/method ||
	    echo "bfu: could not copy $manifest_src/$1"
}

smf_cleanup_initd() {
	rm -f $rootprefix/etc/rc?.d/[SK]??$1
}

smf_delete_manifest() {
	(
		mfst=$1
		cd $root
		[ -f $mfst ] || return;
		if [ -r /etc/svc/volatile/repository_door ]; then
			ENTITIES=`/tmp/bfubin/svccfg inventory $mfst`
			for fmri in $ENTITIES; do
				/tmp/bfubin/svccfg delete -f $fmri
			done
		fi
		rm $mfst
	)
}

smf_delete_methods() {
	(
		cd $root;
		rm -f $smf_obsolete_methods
	)
}	

smf_delete_renamed_manifests() {
	(
		cd $root;
		rm -f $smf_renamed_manifests
	)
}

smf_gldv3_manifests="
	var/svc/manifest/network/aggregation.xml
	var/svc/manifest/network/datalink.xml
	var/svc/manifest/network/datalink-init.xml
"
smf_gldv3_methods="
	lib/svc/method/aggregation
	lib/svc/method/datalink
	lib/svc/method/datalink-init
"
smf_cleanup_gldv3() {
	(
		for f in $smf_gldv3_manifests; do
			smf_delete_manifest $f
		done
		cd $root;
		rm -f $smf_gldv3_methods
	)
}

old_mfst_dir="var/svc/manifest.orig"
new_mfst_dir="var/svc/manifest"

smf_enable() {
	echo "svcadm enable $*" >> $rootprefix/var/svc/profile/upgrade
}

smf_check_repository() {
	repository=etc/svc/repository.db
	[[ -f $rootprefix/$repository ]] || return

	print -n "$rootprefix/$repository: " >&2

	sqlite="${SQLITEBIN-$GATE/public/bin/$bfu_isa/sqlite}"
	[[ -x $sqlite ]] || sqlite=/lib/svc/bin/sqlite
	if [[ ! -x $sqlite ]]; then
		echo "no sqlite binary: skipped integrity check" >&2
		return
	fi

	rm -f /tmp/bfurepo.db;
	cp $rootprefix/$repository /tmp/bfurepo.db
	bad_errors=`echo "PRAGMA integrity_check;" |
	    $sqlite /tmp/bfurepo.db 2>&1 | grep -v '^ok$'`
	if [[ $? -eq 0 ]]; then
		echo "integrity check failed:" >&2
		echo "$bad_errors" >&2
		echo >&2
		if [[ $force_override = no ]]; then
			cat >&2 <<EOF
Reseed the repository (see http://greenline.eng/quickstart.shtml#newrep)
before BFUing (or use the -f flag to force BFU to continue).  Re-seeding
will lose all smf(5) customizations.
EOF
			echo >&2
			exit 2;
		else
			echo "driving on anyway" >&2
		fi
	else
		echo "passed integrity check" >&2;
	fi
}

smf_bkbfu_warning() {
	print ""
	print "*************************************************************"
	print " WARNING: BFU'ing $1 backwards across 5090532."
	print " Fixes have been made but the services cannot be refreshed"
	print " on the $1's inactive repository. Next boot for the"
	print " $1 will probably result in maintenance mode due to"
	print " dependency cycles. If so, at the $1's console, run:"
	print ""
	print " /usr/sbin/svcadm refresh system/sysidtool:system"
	print " /usr/sbin/svcadm refresh system/sysidtool:net"
	print " /usr/sbin/svcadm clear milestone/single-user"
	print " /usr/sbin/svcadm clear system/sysidtool:system"
	print " /usr/sbin/svcadm clear system/sysidtool:net"
	print ""
	print " to resolve."
	print " To avoid these problems, reseed the zone's repository."
	print " See http://greenline.eng/quickstart.shtml#newrep ."
	print " Note: Re-seeding will lose all smf(5) customization."
	print "*************************************************************"
	print ""
}

smf_is_sysconfig() {
	#
	# Return success if going to post-5090532, i.e. post-sysconfig bits
	#
	# By now, we're going to post-smf bits - so multi-user.xml must
	# exist (since it was introduced by first SMF putback).
	# 
	# Function return status is return status of last command executed.
	# So, no need to check return status from grep below.

	grep sysconfig $rootprefix/var/svc/manifest/milestone/multi-user.xml \
		>/dev/null 2>&1
}

smf_bkbfu_past_sysconfig() {
	#
	# Check if bfu'ing back from post-5090532 to pre-5090532 bits.
	#
	if [[ -f $rootprefix/var/svc/manifest/milestone/sysconfig.xml ]] &&
	    ! smf_is_sysconfig ; then
		return 0
	fi
	return 1
}

smf_bkbfu_repair_sysconfig() {
	#
	# Perform the necessary corrections when bfu'ing backwards
	# from post-5090532 to pre-5090532 bits.
	#
	# Get the pre-5090532 non-ON manifests, and issue minimal fixes
	# to the repository, to enable re-boot.
	#
	smf_copy_manifest pre-5090532/sysidtool.xml system
	if [[ $zone = global && $karch = i86pc ]]; then
		smf_copy_manifest pre-5090532/kdmconfig.xml platform/i86pc
	fi
	#
	# Now, remove sysidtool:{system, net}'s dependency on
	# single-user and filesystem-local.
	#
	# If $rootprefix is not empty, this could be the global zone,
	# with an alternate root BFU, or a non-global zone. For either
	# case, the repository to be updated is not the live one: use
	# SVCCFG_REPOSITORY to point to the repository to be updated.
	#
	# Note that in the alternate-root case, doing this seems better
	# than forcing the user to re-seed, or to dis-allow it. The
	# issue of svccfg and the repository not matching seems remote,
	# given that from initial SMF integration (on10_64) to on10_74,
	# there was no mismatch. In the remote possibility that there is a
	# mis-match (in the future) causing these calls to be suspect,
	# the user is already being advised, via the warning message, to
	# reseed the repository in case of trouble. If a mis-match is ever
	# introduced, code such as this would have to be fixed, so this
	# aspect of the warning is useful only during the interim period.
	#
	# NOTE that this is not an issue for non-global zones'
	# repositories - they couldn't be out-of-sync with
	# /tmp/bfubin/svccfg.
	#
	if [[ -n $rootprefix ]]; then
		export SVCCFG_REPOSITORY=$rootprefix/etc/svc/repository.db
		if [[ $zone = global ]]; then
			smf_bkbfu_warning "alternate root"
		else
			smf_bkbfu_warning "zone"
		fi
	fi
	#
	# Using the newer "-s" option to svccfg in the following is OK
	# since its introduction preceded 5090532 (and this routine wouldn't
	# be called unless the machine is running post-5090532 bits).
	#
	/tmp/bfubin/svccfg -s system/sysidtool:net delpg single-user
	/tmp/bfubin/svccfg -s system/sysidtool:system delpg single-user
	/tmp/bfubin/svccfg -s system/sysidtool:net delpg filesystem_local
	/tmp/bfubin/svccfg -s system/sysidtool:system delpg filesystem_local

	#
	# On a live system, issue the refresh; For alternate root or non-global
	# zone, the user was asked to issue the refreshes and "clear"s in the
	# message above after a post-bfu reboot.
	#
	if [[ -z $rootprefix ]]; then
		/tmp/bfubin/svcadm refresh system/sysidtool:system \
		    system/sysidtool:net
	fi

	#
	# Now, reset SVCCFG_REPOSITORY, if it was set
	#
	[[ -n $rootprefix ]] && unset SVCCFG_REPOSITORY

	#
	# Remove the sysconfig.xml manifest when going back.  So backward
	# bfu check continues to work, and all manifests are correct.
	#
	cat >> $rootprefix/var/svc/profile/upgrade <<-EOF
	rm -f /var/svc/manifest/milestone/sysconfig.xml
	EOF
}

#
# Return true if $file exists in $archive.  $file may also be a pattern.
#
archive_file_exists()
{
	archive=$1
	file=$2

	$ZCAT $cpiodir/${archive}${ZFIX} | cpio -it 2>/dev/null | \
	    egrep -s "$file"
}

#
# If we're no longer delivering the eeprom service, remove it from the system,
# as eeprom -I is removed as well.
#
smf_fix_i86pc_profile () {
	mfst="var/svc/manifest/platform/i86pc/eeprom.xml"
	profile="var/svc/profile/platform_i86pc.xml"

	if [ ! "$karch" = "i86pc" ]; then
		return
	fi

	if ! archive_file_exists generic.root "^$profile"; then
		rm -f $rootprefix/$profile
		rm -f $rootprefix/var/svc/profile/platform.xml
	fi

	if [ ! -f $rootprefix/$mfst ]; then
		return
	fi

	if archive_file_exists generic.root "^$mfst"; then
		return
	fi

	rm -f $rootprefix/$mfst

	#
	# we must disable via svccfg directly, as manifest-import runs after
	# this service tries to run
	#
	[[ -n "$rootprefix" ]] &&
	    export SVCCFG_REPOSITORY=$rootprefix/etc/svc/repository.db
	/tmp/bfubin/svccfg delete -f platform/i86pc/eeprom
	[[ -n "$rootprefix" ]] && unset SVCCFG_REPOSITORY
}

smf_apply_conf () {
	#
	# Go thru the original manifests and move any that were unchanged
	# (or are not system-provided) back to their proper location.  This
	# will avoid superfluous re-import on reboot, as the inode and mtime
	# are both part of the hash.
	#
	if [ -d $rootprefix/$old_mfst_dir ]; then
		for f in `cd $rootprefix/$old_mfst_dir ; find . -type f`
		do
			old=$rootprefix/$old_mfst_dir/$f
			new=$rootprefix/$new_mfst_dir/$f
			if [ ! -f $new ]; then
				mkdir -m 0755 -p `dirname $new`
				mv $old $new
				continue
			fi
			cmp -s $old $new && mv $old $new
		done
		rm -rf $rootprefix/$old_mfst_dir
	fi

	if [ -f $rootprefix/etc/init.d/inetd ]; then
		#
		# BFUing to non-SMF system -- undo our previous changes,
		# run an old hack, and skip the remainder of this function.
		#
		smf_inetd_reenable
		smf_tftp_reinstall

		# Update inetd.conf only if we find rpc.metad file.
		[ -f $usr/sbin/rpc.metad ] &&
		    inetd_conf_svm_hack

		return
	fi

	#
	# At this point, the archive in question is a SMF version.  If
	# the smf(5) repository does not yet exist, create it by copying
	# the appropriate seed repository.  Since updating of non-global
	# zones only occurs when the live system is bfu'ed, the
	# appropriate seed is guaranteed to exist under the /lib
	# directory.
	#
	repository=$rootprefix/etc/svc/repository.db
	if [ ! -f $repository ]; then
		print "Initializing service configuration repository ..."
		if [ $zone = global ]; then
			cp $rootprefix/lib/svc/seed/global.db $repository
		else
			cp /lib/svc/seed/nonglobal.db $repository
		fi
		chmod 0600 $repository
		chown root:sys $repository
	fi

	print "Removing obsolete smf services ..."
	for f in $smf_obsolete_manifests; do
		smf_delete_manifest $f
	done
	smf_delete_methods
	smf_delete_renamed_manifests
	if [ $need_datalink = no ]; then
		smf_cleanup_gldv3
	fi

	print "Disabling unneeded inetd.conf entries ..."
	smf_inetd_disable
	smf_tftp_reinstall

	print "Connecting platform and name service profiles ..."

	rm -f $rootprefix/var/svc/profile/name_service.xml

	grep ldap $rootprefix/etc/nsswitch.conf >/dev/null 2>&1
	is_ldap=$?
	grep nisplus $rootprefix/etc/nsswitch.conf >/dev/null 2>&1
	is_nisplus=$?
	grep nis $rootprefix/etc/nsswitch.conf >/dev/null 2>&1
	is_nis=$?

	if [ $is_ldap  = 0 ]; then
		ns_profile=ns_ldap.xml
	elif [ $is_nisplus = 0  ]; then
		ns_profile=ns_nisplus.xml
	elif [ $is_nis = 0 ]; then
		ns_profile=ns_nis.xml
	else
		ns_profile=ns_files.xml
	fi

	ln -s $ns_profile $rootprefix/var/svc/profile/name_service.xml

	rm -f $rootprefix/var/svc/profile/inetd_services.xml
	ln -s inetd_upgrade.xml $rootprefix/var/svc/profile/inetd_services.xml

	print "Marking converted services as enabled ..."

	[ -f $rootprefix/etc/resolv.conf ] && smf_enable network/dns/client
	[ -f $rootprefix/etc/inet/dhcpsvc.conf ] && \
	    smf_enable network/dhcp-server
  
	# Not concerned about enabling/disabling rcap but will migrate
	# configuration parameters if rcap.conf exists
	#
	if [ -f $rootprefix/etc/rcap.conf ]; then
		migrate_rcap_conf
	fi

	if [ $zone = global ]; then
		if [ -f $rootprefix/etc/dfs/dfstab ] &&
		    grep '^[ 	]*[^# 	]' $rootprefix/etc/dfs/dfstab \
		    > /dev/null; then
		    	smf_enable network/nfs/server
		fi
	else
		echo "/usr/sbin/svcadm disable network/nfs/server" >> \
		    $rootprefix/var/svc/profile/upgrade
	fi

	[ -f $rootprefix/etc/inet/ntp.conf ] && smf_enable network/ntp


	domainname=`cat $rootprefix/etc/defaultdomain 2>/dev/null`
        if [ ! -z "$domainname" -a -d $rootprefix/var/yp/$domainname ]; then
		smf_enable network/nis/server

		# Determining whether we're a NIS master requires
		# looking through the maps.
		cat >>$rootprefix/var/svc/profile/upgrade <<\_EOF
# Determine whether we are a YP master.
domain=`/usr/bin/domainname`
hostname=`uname -n | cut -d. -f1 | tr '[A-Z]' '[a-z]'`

if [ -x /usr/sbin/makedbm ]; then
	if [ -f /var/yp/NISLDAPmapping ]; then
		master=`/usr/sbin/makedbm -u /var/yp/\$domain/LDAP_passwd.byname | grep YP_MASTER_NAME | nawk '{ print $2 }'`
	else
		master=`/usr/sbin/makedbm -u /var/yp/\$domain/passwd.byname | grep YP_MASTER_NAME | nawk '{ print $2 }'`
	fi
fi

# If we are the master server, enable appropriate services.
if [ "$master" = "$hostname" -a "$YP_SERVER" = "TRUE" ]; then
	/usr/sbin/svcadm enable network/nis/xfr
	/usr/sbin/svcadm enable network/nis/passwd

	if [ ! -f /var/yp/NISLDAPmapping ]; then
		[ -f /var/yp/updaters ] && \
		    /usr/svc/svcadm enable network/nis/update
	fi
fi
_EOF
	fi

	# Check if mddbs don't exist on the image.  If so, disable SVM services.
	MDDB_STATUS=1
	if [ -f $rootprefix/kernel/drv/md.conf ]; then
		sed -e 's/#.*$//' $rootprefix/kernel/drv/md.conf | \
		    egrep '^[        ]*mddb_bootlist' >/dev/null 2>&1
		MDDB_STATUS=$?
	fi

	if [ $MDDB_STATUS -ne 0 ]; then
		for svc in metainit mdmonitor; do
		    echo "/usr/sbin/svcadm disable system/$svc:default" >> \
			$rootprefix/var/svc/profile/upgrade
		done

		for svc in meta mdcomm metamed metamh; do
		    echo "/usr/sbin/svcadm disable network/rpc/$svc:default" \
			>> $rootprefix/var/svc/profile/upgrade
		done
	fi

	# Workaround inetd's handling of "tcp6/udp6" when no IPv6 interfaces
	# are configured.
	for svc in meta mdcomm metamed metamh; do
	    echo "/usr/sbin/inetadm -m network/rpc/$svc:default proto=tcp" \
		">/dev/null 2>&1" >> $rootprefix/var/svc/profile/upgrade
	done

	manifest_src=${MANIFEST_SRC-$GATE/public/smf}
	[[ -d $manifest_src ]] ||
	    manifest_src=/net/onnv.eng/export/gate/public/smf
	[[ -d $manifest_src ]] || manifest_src=/net/greenline.eng/meta0/smf

	if smf_bkbfu_past_sysconfig ; then
		echo "BFU'ing backwards across 5090532! Now repairing..."
		smf_bkbfu_repair_sysconfig
	fi

	#
	# If bfu'ing milestone/sysconfig bits or onwards, update the
	# corresponding non-ON manifests - sysidtool and kdmconfig.
	#
	sysidmfst=$rootprefix/var/svc/manifest/system/sysidtool.xml
	kdmmfst=$rootprefix/var/svc/manifest/platform/i86pc/kdmconfig.xml
	if smf_is_sysconfig ; then
		if [[ ! -f $sysidmfst ]]; then
			#
			# if WOS build on machine is pre-greenline, and
			# we're bfu'ing to the sysconfig bits.
			#
			smf_copy_manifest post-5090532/sysidtool.xml system
			if [[ $zone = global ]]; then
				smf_copy_method sysidtool-net
				smf_copy_method sysidtool-system
			fi
			echo "Converted system/sysidtool (post-5090532)"
		else
			#
			# If sysidtool.xml already exists, update it
			# if necessary. Future updates of sysidtool.xml
			# must occur in the dir: $manifest_src/post-5090532
			#
			smf_copy_manifest post-5090532/sysidtool.xml system
		fi
		if [[ $zone = global && $karch = i86pc ]]; then
			if [[ ! -f $kdmmfst ]]; then
				#
				# if WOS build on machine is pre-greenline, and
				# we're bfu'ing to the sysconfig bits.
				#
				smf_copy_manifest post-5090532/kdmconfig.xml \
				    platform/i86pc
				smf_copy_method   svc-kdmconfig
				smf_cleanup_initd kdmconfig
				echo "Converted platform/i86pc/kdmconfig"
				echo "(post-5090532)"
			else
				#
				# If kdmconfig.xml already exists, update
				# it if necessary. Future updates of
				# kdmconfig.xml must occur in the dir:
				# $manifest_src/post-5090532
				#
				smf_copy_manifest post-5090532/kdmconfig.xml \
				    platform/i86pc
			fi
		fi
	else
		if [[ ! -f $sysidmfst ]]; then
			smf_copy_manifest pre-5090532/sysidtool.xml system
			if [[ $zone = global ]]; then
				smf_copy_method sysidtool-net
				smf_copy_method sysidtool-system
			fi
			echo "Converted system/sysidtool"
		fi
		if [[ $zone = global && $karch = i86pc && ! -f $kdmmfst ]];
		then
			smf_copy_manifest pre-5090532/kdmconfig.xml \
			    platform/i86pc
			smf_copy_method   svc-kdmconfig
			smf_cleanup_initd kdmconfig
			echo "Converted platform/i86pc/kdmconfig"
		fi
	fi

	# If we've still got the old dtlogin manifest delivered by earlier
	# versions of bfu, delete it, as it was broken and should have
	# never been delivered.  A new version delivered by the CDE
	# consolidation should be left alone.
	if [[ -f $rootprefix/var/svc/manifest/application/dtlogin.xml &&
	    `grep -c GLXXX \
	    $rootprefix/var/svc/manifest/application/dtlogin.xml` -gt 0 &&
	    -x /tmp/bfubin/svccfg ]]; then

		# Delete the obsolete manifest.
		rm -f $rootprefix/var/svc/manifest/application/dtlogin.xml

		# Delete the service from repository, then use dtconfig -e to
		# revert to whatever the WOS bits are using if dtlogin was
		# enabled.
		cat >> $rootprefix/var/svc/profile/upgrade <<-EOFA
if /usr/bin/svcprop -q application/cde-login; then
	if [ \`/usr/bin/svcprop -p general/enabled \
		application/cde-login:default\` = "true" ]; then
		do_dtconfig=1;
	else
		do_dtconfig=0;
	fi

	/usr/sbin/svccfg delete -f application/cde-login
	type instance_refresh 2>&1 > /dev/null
	if [ \$? = 0 ]; then
		instance_refresh system/console-login
	else
		/usr/sbin/svcadm refresh system/console-login
	fi

	if [ \$do_dtconfig -eq 1 -a -x /usr/dt/bin/dtconfig ]; then
		/usr/dt/bin/dtconfig -e
	fi
fi
EOFA
	fi


	# Enable the inetd-upgrade service to convert any changes to inetd.conf
	smf_enable network/inetd-upgrade

	# If global zone, and bfu'ing from smf, and the inetd-upgrade
	# service has an obsolete dependency, then add a clear of inetd
	# and inetd-upgrade to the upgrade file as either may drop into
	# maintenance due to a dependency loop resulting from the new
	# inetd manifest
	if [[ $zone = global && -x /tmp/bfubin/svccfg ]]; then
		/tmp/bfubin/svcprop -q -p network/entities network/inetd-upgrade
		if [[ $? = 0 ]]; then
		    	echo "/usr/sbin/svcadm clear network/inetd" >> \
			    $rootprefix/var/svc/profile/upgrade
			echo "/usr/sbin/svcadm clear network/inetd-upgrade" >> \
			    $rootprefix/var/svc/profile/upgrade
		fi
	fi

	# If we're in the global zone, and using an alternate root, see if
	# we are in an smf root.  If so, import name-service-cache. If we're
	# not bfu'ing an alternate root, and we're post-smf, import
	# name-service-cache.  This is to get name-service-cache(with correct
	# dependencies) in the repository before reboot.  If we're bfu'ing
	# from pre-smf, this isn't an issue, as name-service-cache will be
	# installed with correct dependencies.
	if [[ $zone = global &&
	    -f $rootprefix/var/svc/manifest/system/name-service-cache.xml ]];
	    then
		if [[ -n $rootprefix ]]; then
			if [ -x /usr/sbin/svccfg ]; then
			SVCCFG_REPOSITORY=$rootprefix/etc/svc/repository.db
			/usr/sbin/svccfg import \
		    $rootprefix/var/svc/manifest/system/name-service-cache.xml
			else
			echo "Warning: This system does not have SMF, so I "
			echo "cannot ensure the pre-import of "
			echo "name-service-cache.  If name-service-cache does "
			echo "not work, reboot your alternate root to fix it."
			fi
		elif [ -x /tmp/bfubin/svccfg ]; then
			/tmp/bfubin/svccfg import \
			    /var/svc/manifest/system/name-service-cache.xml
		fi
	fi

	# If we're in the global zone, and using an alternate root, see if
	# we are in an smf root.  If so, import datalink and aggregation svcs.
	# If we're not bfu'ing an alternate root, and we're post-smf,
	# import datalink and aggregation.  This is to get them 
	# in the repository before reboot.  If we're bfu'ing from pre-smf,
	# this isn't an issue, as they are in the seed repository.
	if [[ $zone = global &&
	    -f $rootprefix/var/svc/manifest/network/datalink.xml ]]; then
		if [[ -n $rootprefix ]]; then
			if [ -x /usr/sbin/svccfg ]; then
			SVCCFG_REPOSITORY=$rootprefix/etc/svc/repository.db
			sed -e "s/enabled='true'/enabled='false'/" \
			 $rootprefix/var/svc/manifest/network/aggregation.xml \
			    | svccfg import -
			sed -e "s/enabled='true'/enabled='false'/" \
			    $rootprefix/var/svc/manifest/network/datalink.xml \
			    | svccfg import -
			sed -e "s/enabled='true'/enabled='false'/" \
		       $rootprefix/var/svc/manifest/network/datalink-init.xml \
			    | svccfg import -
			else
			echo "Warning: This system does not have SMF, so I"
			echo "cannot ensure the pre-import of datalink and"
			echo "network aggregation.  If they do not work"
			echo "reboot your alternate root to fix it."
			fi
		elif [ -x /tmp/bfubin/svccfg ]; then
			sed -e "s/enabled='true'/enabled='false'/" \
			    /var/svc/manifest/network/aggregation.xml | \
			    svccfg import -
			sed -e "s/enabled='true'/enabled='false'/" \
			    /var/svc/manifest/network/datalink.xml | \
			    svccfg import -
			sed -e "s/enabled='true'/enabled='false'/" \
			    /var/svc/manifest/network/datalink-init.xml | \
			    svccfg import -
		fi

		#
		# Make sure the services are enabled after reboot.
		#
		enable_next_boot svc:/network/aggregation:default
		enable_next_boot svc:/network/datalink:default
		enable_next_boot svc:/network/datalink-init:default
	fi

	# Enable new NFS status and nlockmgr services if client is enabled
	cat >> $rootprefix/var/svc/profile/upgrade <<-EOF
	    cl="svc:/network/nfs/client:default"
	    if [ \`/usr/bin/svcprop -p general/enabled \$cl\` = "true" ]; then
		/usr/sbin/svcadm enable svc:/network/nfs/status:default
		/usr/sbin/svcadm enable svc:/network/nfs/nlockmgr:default
	    fi

EOF

	kpmani="$rootprefix/var/svc/manifest/network/security/krb5_prop.xml"
	if grep svc-kdc.slave $kpmani > /dev/null 2>&1; then
		cat >> $rootprefix/var/svc/profile/upgrade <<EOF
		# We are deleting and reimporting kpropd's manifest, because we
		# need to change the restarter.
		kpfmri="svc:/network/security/krb5_prop"
		kkfmri="svc:/network/security/krb5kdc:default"
		lkpmani="/var/svc/manifest/network/security/krb5_prop.xml"
		restarter=\`svcprop -c -p general/restarter \$kpfmri 2>&1\`
		case \$restarter in
			*network/inetd:default)
				kken=\`svcprop -c -p general/enabled \$kkfmri\`
				svccfg delete -f \$kpfmri
				svccfg import \$lkpmani 
				# Enable kpropd if krb5kdc is enabled, since
				# krb5kdc would have run kpropd
				if [ \$kken = "true" ]; then
					svcadm enable \$kpfmri
				fi
				;;
		esac
EOF
	fi

	# Enable print server if there are local queues
	queues=`echo $rootprefix/etc/lp/printers/*/configuration`
	if [ "$queues" != "$rootprefix/etc/lp/printers/*/configuration" ]; then
		smf_enable application/print/server
	fi

	# Enable rarpd and bootparamd if they would have been running pre-SMF
	if [ -d $rootprefix/tftpboot ] || [ -d $rootprefix/rplboot ]; then
		smf_enable network/rarp
		smf_enable network/rpc/bootparams
	fi

	# To handle the transition from pre-smf ipfilter to smf-aware ipfilter,
	# check if ipfilter had been enabled with at least one rule, and if so
	# enable the smf instance.
	if grep '^[ \t]*[^# \t]' $rootprefix/etc/ipf/ipf.conf >/dev/null 2>&1 &&
	    [[ $zone = global ]]; then
		smf_enable network/ipfilter
	fi

	touch $rootprefix/var/svc/profile/.upgrade_prophist

	cat >> $rootprefix/var/svc/profile/upgrade <<EOF
	# We are deleting and reimporting dcs's manifest, because we
	# need to change the restarter.
	dcsfmri="svc:/platform/sun4u/dcs:default"
	dcsmani="/var/svc/manifest/platform/sun4u/dcs.xml"
	restarter=\`svcprop -c -p general/restarter \$dcsfmri 2>&1\`
	case \$restarter in
		*network/inetd:default)
			en=\`svcprop -c -p general/enabled \$dcsfmri\`
			svccfg delete -f \$dcsfmri
			svccfg import \$dcsmani
			if [ \$en = "true" ]; then
				svcadm enable \$dcsfmri
			fi
			;;
	esac
EOF

	smf_fix_i86pc_profile
}

#
# The directboot putback moved the console property from
# /boot/solaris/bootenv.rc to /boot/grub/menu.lst.  It should be kept in both.
#
cleanup_eeprom_console()
{
	bootenvrc="$root/boot/solaris/bootenv.rc"
	menu_console=`eeprom console 2>/dev/null | \
	    grep -v 'data not available' | cut -d= -f2-`
	bootenv_console=`grep '^setprop[	 ]\{1,\}console\>' $bootenvrc`
	if [ -n "$menu_console" ] && [ -z "$bootenv_console" ]; then
		echo "setprop console '$menu_console'" >> $bootenvrc
	fi
}

EXTRACT_LOG=/tmp/bfu-extract-log.$$

rm -f $EXTRACT_LOG

extraction_error() {
	echo error $* >> $EXTRACT_LOG
}

#
# Make a local copy of bfu in /tmp and execute that instead.
# This makes us immune to loss of networking and/or changes
# to the original copy that might occur during execution.
#
cd .
abspath=`[[ $0 = /* ]] && print $0 || print $PWD/$0`
if [[ $abspath != /tmp/* ]]; then
	localpath=/tmp/bfu.$$
	print "Copying $abspath to $localpath"
	cp $abspath $localpath
	chmod +x $localpath
	print "Executing $localpath $*\n"
	exec $localpath $*
fi

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

usage() {
	echo "Usage:"
	echo "    bfu    [-fh] <archive_dir> [root-dir]"
	echo "\tUpdate a single machine by loading archives on root-dir."
	echo "\troot-dir defaults to / (a live bfu).\n"
	echo "    bfu -c [-fh] <archive_dir> <exec-dir>"
	echo "\tUpdate all diskless clients by loading archives on each client"
	echo "\tthat mounts exec-dir as /usr.  <exec-dir> must start with"
	echo "\t/export/exec and each client's root must be in /export/root.\n"
	echo "\t-f        force bfu to continue even if it doesn't seem safe"
	fail "\t-h|-help  print this usage message and exit\n"
}

diskless=no
force_override=no
while [ $# -gt 0 ]; do
	case $1 in
		-c)		diskless=yes;;
		-f)		force_override=yes;;
		-h|-help)	usage;;
		*)      	break;;
	esac
	shift
done

# Variables for x86 platforms
boot_is_pcfs=no
have_realmode=no
is_pcfs_boot=no
need_datalink=no
new_dladm=no

# Set when moving to either directboot or multiboot
multi_or_direct=no

#
# Shows which type of archives we have, which type of system we are
# running on (before the bfu), and what the failsafe archives are
# (again, before the bfu).  failsafe_type is only needed on diskful
# bfu's, so it's not set in the diskless case.
# Possible values: unknown, dca, multiboot, directboot, xpv
#
archive_type=unknown
system_type=unknown
failsafe_type=unknown

test $# -ge 1 || usage

if [ -x /usr/bin/ppriv ]; then
	# We prefer to use ppriv, as it is a more accurate test, and also
	# has the benefit of preventing use from within a nonglobal zone.
	ppriv $$ | grep -w "E: all" > /dev/null 2>&1 || \
	    fail "bfu requires all privileges"
else
	# Fall back to old id check if system does not yet have ppriv.
	uid=`id | nawk '{print $1}'`
	[ "$uid" = "uid=0(root)" ] || \
	    fail "You must be super-user to run this script."
fi

bfu_isa=`uname -p`
target_isa=$bfu_isa
karch=`uname -m`
plat=`uname -i`

cpiodir=$1

if [ "$cpiodir" = again ]; then
	cpiodir=`nawk '/^bfu.ed from / { print $3; exit }' /etc/motd`
fi

[[ "$cpiodir" = */* ]] || cpiodir=$ARCHIVE/archives/$target_isa/$1

[[ "$cpiodir" = /* ]] || fail "archive-dir must be an absolute path"

cd $cpiodir
case `echo generic.root*` in
	generic.root)		ZFIX="";	ZCAT="cat";;
	generic.root.gz)	ZFIX=".gz";	ZCAT="gzip -d -c";;
	generic.root.Z)		ZFIX=".Z";	ZCAT="zcat";;
	*) fail "generic.root missing or in unknown compression format";;
esac

#
# Determine what kind of archives we're installing, using the following rules:
#
# 1. If i86xpv archives exist, the archives are xpv
# 2. If strap.com is present, the archives are pre-multiboot
# 3. If symdef is present, the archives are directboot
# 4. Otherwise, the archives are multiboot
#
if [ $target_isa = i386 ]; then
	if [ -f $cpiodir/i86xpv.root$ZFIX ]; then
		archive_type=xpv
		multi_or_direct=yes
	elif [ -f $cpiodir/i86pc.boot$ZFIX ] && \
	    archive_file_exists i86pc.boot "strap.com"; then
		archive_type=dca
	elif [ -f $cpiodir/i86pc.root$ZFIX ] && \
	    archive_file_exists i86pc.boot symdef; then
		archive_type=directboot
		multi_or_direct=yes
	else
		archive_type=multiboot
		multi_or_direct=yes
	fi
fi

if [ $diskless = no ]; then
	root=${2:-/}
	[[ "$root" = /* ]] || fail "root-dir must be an absolute path"
	usrroot=$root
	usr=${usrroot%/}/usr
	rootlist=$root

	[[ -f $root/etc/system ]] || \
	    fail "$root/etc/system not found; nonglobal zone target not allowed"

	# Make sure we extract the sun4u-us3 libc_psr.so.1
	if [ -d $root/platform/sun4u -a \
	   ! -d $root/platform/sun4u-us3 ]
	then
		mkdir $root/platform/sun4u-us3
		chmod 755 $root/platform/sun4u-us3
		chown root $root/platform/sun4u-us3
		chgrp sys $root/platform/sun4u-us3
	fi

	if [ $target_isa = i386 ]; then
		if [ $archive_type = xpv ]; then
			#
			# On i386, we want to apply the archives for both
			# platforms (i86pc and i86xpv) if they exist.  We
			# force the platform to i86xpv so that both will be
			# applied.
			#
			karch=i86pc
			plat=i86xpv
		fi
		if [ ! -d $root/platform/i86hvm ]; then
			mkdir $root/platform/i86hvm
		fi
	fi

	if [ $karch != $plat -a -f ${cpiodir}/${plat}.usr$ZFIX ]; then
		usrarchs="$karch $plat"
	else
		usrarchs="$karch"
	fi
	if [ $karch != $plat -a -f ${cpiodir}/${plat}.root$ZFIX ]; then
		rootarchs="$karch $plat"
	else
		rootarchs="$karch"
	fi

	if [ -h ${root}/platform/${plat} ]; then
		rm -f ${root}/platform/${plat}
	fi
	if [ -h ${usr}/platform/${plat} ]; then
		rm -f ${usr}/platform/${plat}
	fi

	if [ $plat != $karch -a -f ${cpiodir}/${plat}.root$ZFIX \
	    -a -f ${cpiodir}/${plat}.usr$ZFIX ]
	then
		cd $cpiodir
		#
		#  Look through all the archives we build and match
		#  the names of built archives with the names of
		#  directories installed on this machine.  We assume
		#  here that we can get the names of all architectures
		#  by pattern matching the names of .root archives - so
		#  if we ever had a case where we had only a .usr archive
		#  we wouldn't find that archive.
		#
		for i in *.root*
		do
			platname=${i%.root*}
			if [ -z "${platname}" -o ${platname} = $karch -o \
			    $platname = generic -o ${platname} = $plat ]; then
				continue;
			fi
			if [ -d ${root}/platform/${platname} -o \
			    -h ${root}/platform/${platname} ]; then
				rootarchs="${rootarchs} ${platname}"
			fi
			if [ -d ${usr}/platform/${platname} -o \
			    -h ${usr}/platform/${platname} ]; then
				usrarchs="${usrarchs} ${platname}"
			fi
			if [ -h ${root}/platform/${platname} ]; then
				rm -f ${root}/platform/${platname}
			fi
			if [ -h ${usr}/platform/${platname} ]; then
				rm -f ${usr}/platform/${platname}
			fi
		done
	fi
	rootslice=`df -k $root | nawk 'NR > 1 { print $1 }' | sed s/dsk/rdsk/`
	print "Loading $cpiodir on $root"
else
	usrroot=$2
	usr=$2/usr
	[[ "$usr" = /export/exec/* ]] || fail "exec-dir $usrroot sounds bogus"
	case $2 in
	    *sparc*)
		target_isa=sparc ;;
	    *i386*)
		target_isa=i386 ;;
	esac
	cd $cpiodir
	test -f generic.root$ZFIX || fail "$cpiodir/generic.root$ZFIX missing"
	allarchs=$(echo $(ls *.root$ZFIX | grep -v generic.root$ZFIX | \
		sed -e 's/.root.*//'))

	if [ $target_isa = i386 -a $archive_type = xpv ]; then
		#
		# On i386, we want to apply the archives for both platforms
		# (i86pc and i86xpv) if they exist.  We force the platform
		# to i86xpv so that both will be applied.
		#
		karch=i86pc
		plat=i86xpv
	else
		# XXX Pick karch as last available root arch
		karch=${allarchs##* }
		# XXX Pick plat as first available root arch
		plat=${allarchs%% *}
	fi

	rootlist=""
	for root in /export/root/*
	do
		test -f $root/etc/vfstab &&
			egrep -s $usrroot $root/etc/vfstab &&
			rootlist="$rootlist $root"
	done
	test -n "$rootlist" || fail "no clients to upgrade"
	print "Loading $cpiodir usr archives on:\n\t$usr\n"
	print "Loading $cpiodir root archives on:"
	for root in $rootlist
	do
		print "\t$root"
	done
fi

if grep '^[ 	]*zfsroot:' $root/etc/system >/dev/null && \
	    archive_file_exists i86pc.boot boot/grub/zfs_stage1_5; then
	echo "Cannot BFU a system with the mountroot version"\
		"of zfs boot support."
	echo "For information on how to transition this system to the new"
	echo "zfs boot support, see:"
	echo "http://www.opensolaris.org/os/community/zfs/boot/zfsboot-manual/mntroot-transition/"
	fail ""
fi

nss_lib="$usr/lib/mps/libnss3.so"
nss_lib64="$usr/lib/mps/64/libnss3.so"
valid_rpath="\$ORIGIN:/usr/lib/mps/secv1:/usr/lib/mps"
rpath_msg="R(UN)?PATH from file ${nss_lib}\)"
if [ ! -x /usr/bin/ldd ]; then
	if [ "$force_override" = yes ]; then
		echo "/usr/bin/ldd is missing but -f is set; continuing."
	else
		echo "/usr/bin/ldd is missing."
		fail "Install the SUNWtoo package."
	fi
fi
nss_rpath=`ldd -s $nss_lib | egrep "$rpath_msg" | head -1 | cut -d'=' -f2 | \
		awk '{print $1}'`
update_script="/ws/onnv-gate/public/bin/update_nsspkgs"
if [ $valid_rpath != "$nss_rpath" ]; then
	if [ "$force_override" = yes ]; then
		echo "$nss_lib is not valid but -f is set; continuing."
	else
		echo "$nss_lib is not valid."
		fail "Run $update_script to update the SUNWtls package."
	fi
fi
if [ $target_isa = i386 -a ! -f $nss_lib64 ]; then
	echo "$nss_lib64 does not exist."
	fail "Run $update_script to update the NSS packages."
fi

update_script="/ws/onnv-gate/public/bin/migrate_bind9"
if [[ ! -f $usr/lib/dns/libdns.so ]] && ! $ZCAT $cpiodir/generic.usr$ZFIX | \
	    cpio -it 2>/dev/null |  egrep -s '^usr/sbin/ndc' ; then
	if [ "$force_override" = yes ]; then
		echo "BIND 9 has not been installed, but -f is set; continuing."
	else
		echo "BIND 8 has been removed from ON; BIND 9 is available from SFW."
		fail "Run $update_script to migrate to BIND 9."
	fi
fi

update_script="/ws/onnv-gate/public/bin/update_ce"
if ifconfig -a | egrep '^ce' >/dev/null 2>/dev/null; then
	# CE version 1.148 or later is required
	cever=`modinfo | grep 'CE Ethernet' | sed 's/.*v1\.//' | tr -d ')' | \
	    nawk '{ if ($1 < 148) print "BAD"; else print $1 }'`
	if [ "$cever" = "BAD" ]; then
		fail "You must run $update_script to upgrade your ce driver."
	fi
fi

update_script="/ws/onnv-gate/public/bin/update_dbus"
if [ ! -x $usr/lib/dbus-daemon ]; then
	fail "Run $update_script to update D-Bus."
fi

#
# We need biosdev if we're moving from pre-multiboot to multiboot or directboot
# kernels.  If we already have an i86xpv kernel, then we must already be a
# directboot kernel, and can therefore skip the check.
#
if [ $target_isa = i386 ] && [ $multi_or_direct = yes ] && \
    [ $diskless = no ] && [ ! -d /platform/i86xpv/ ]; then
	prtconf -v | grep biosdev >/dev/null 2>&1
	if [ $? -ne 0 ] && [ ! -f $rootprefix/platform/i86pc/multiboot ]; then
		echo "biosdev cannot be run on this machine."
		echo "Transitioning from classic to multiboot requires a"
		echo "bootconf which is compatible with biosdev."
		echo "bfu to onnv_12 first, then to a build with multiboot."
		fail ""
	fi
fi

if $ZCAT $cpiodir/generic.root$ZFIX | cpio -it 2>/dev/null | \
    grep datalink.conf > /dev/null 2>&1 ; then
	need_datalink=yes
fi

#
# Check whether the archives have an etc/dladm directory; this is
# later used to determine if aggregation.conf needs to be moved.
#
if $ZCAT $cpiodir/generic.root$ZFIX | cpio -it 2>/dev/null | \
    grep etc/dladm > /dev/null 2>&1 ; then
	new_dladm=yes
fi

#
# Check whether the build is boot-archive or ufsboot sparc
# boot based on the existence of a generic.boot archive
#
newboot_sparc=no
if [ $target_isa = sparc -a -f $cpiodir/generic.boot$ZFIX ]; then
	newboot_sparc=yes
fi

time_ref=/tmp/bfu.time_ref.$$
rm -f $time_ref
touch $time_ref || fail "$time_ref: Unable to create time reference."
time_ref_seconds=$SECONDS

print "\nCreating bfu execution environment ..."

#
# Save off a few critical libraries and commands, so that bfu will
# continue to function properly even in the face of major
# kernel/library/command incompatibilities during a live upgrade.
#
bfucmd="
	/usr/bin/awk
	/usr/bin/cat
	/usr/bin/chgrp
	/usr/bin/chmod
	/usr/bin/chown
	/usr/bin/cmp
	/usr/bin/cp
	/usr/bin/cpio
	/usr/bin/csh
	/usr/bin/cut
	/usr/bin/date
	/usr/bin/dd
	/usr/bin/df
	/usr/bin/diff
	/usr/bin/du
	/usr/bin/echo
	/usr/bin/ed
	/usr/bin/egrep
	/usr/bin/env
	/usr/bin/ex
	/usr/bin/expr
	/usr/bin/false
	/usr/bin/fgrep
	/usr/bin/file
	/usr/bin/find
	/usr/bin/gettext
	/usr/bin/grep
	/usr/bin/head
	/usr/bin/id
	/usr/bin/ksh
	/usr/bin/line
	/usr/bin/ln
	/usr/bin/ls
	/usr/bin/mkdir
	/usr/bin/mktemp
	/usr/bin/more
	/usr/bin/mv
	/usr/bin/nawk
	/usr/bin/pgrep
	/usr/bin/pkginfo
	/usr/bin/pkill
	/usr/bin/printf
	/usr/bin/ps
	/usr/bin/ptree
	/usr/bin/rm
	/usr/bin/rmdir
	/usr/bin/sed
	/usr/bin/sh
	/usr/bin/sleep
	/usr/bin/sort
	/usr/bin/strings
	/usr/bin/stty
	/usr/bin/su
	/usr/bin/sum
	/usr/bin/tail
	/usr/bin/tee
	/usr/bin/touch
	/usr/bin/tr
	/usr/bin/true
	/usr/bin/truss
	/usr/bin/tty
	/usr/bin/uname
	/usr/bin/uniq
	/usr/bin/uptime
	/usr/bin/vi
	/usr/bin/w
	/usr/bin/wc
	/usr/bin/xargs
	/usr/bin/zcat
	/usr/sbin/add_drv
	/usr/sbin/chroot
	/usr/sbin/halt
	/usr/sbin/lockfs
	/usr/sbin/lofiadm
	/usr/sbin/mkfile
	/usr/sbin/mkfs
	/usr/sbin/mknod
	/usr/sbin/mount
	/usr/sbin/newfs
	/usr/sbin/pkgrm
	/usr/sbin/prtconf
	/usr/sbin/reboot
	/usr/sbin/sync
	/usr/sbin/tar
	/usr/sbin/uadmin
	/usr/sbin/umount
	/usr/sbin/wall
	/usr/sbin/zonecfg
	${FASTFS-$GATE/public/bin/$bfu_isa/fastfs}
	${GZIPBIN-$GATE/public/bin/$bfu_isa/gzip}
"

#
# Scripts needed by BFU. These must be modified to use the interpreters in
# /tmp/bfubin. The interpreters in /usr/bin may not be compatible with the
# libraries in the archives being extracted.
#
bfuscr="
	${ACR-${GATE}/public/bin/acr}
"

#
# basename and dirname may be ELF executables, not shell scripts;
# make sure they go into the right list.
#
if `file /usr/bin/basename | grep ELF >/dev/null`
then	bfucmd="$bfucmd /usr/bin/basename"
else	bfuscr="$bfuscr /usr/bin/basename"
fi

if `file /usr/bin/dirname | grep ELF >/dev/null`
then	bfucmd="$bfucmd /usr/bin/dirname"
else	bfuscr="$bfuscr /usr/bin/dirname"
fi

rm -rf /tmp/bfubin
mkdir /tmp/bfubin
set $bfucmd
isalist=`isalist`
while [ $# -gt 0 ]
do
	dir=${1%/*}
	cmd=${1##*/}
	cd $dir
	isacmd=`(find $isalist -name $cmd 2>/dev/null; echo $cmd) | head -1`
	cp $dir/$isacmd /tmp/bfubin || fail "cannot copy $dir/$isacmd"
	shift
done

#
# Optional commands.  We warn, but do not abort, if we are crossing a
# feature boundary (where a command is not present in the parent).
# Clauses requiring these commands must explicitly test for their
# presence in /tmp/bfubin.
#
bfuoptcmd="
	/sbin/biosdev
	/sbin/bootadm
	/sbin/installgrub
	/usr/sbin/fdisk
	/usr/sbin/metastat
	/usr/bin/mkisofs
	/usr/sbin/svcadm
	/usr/sbin/svccfg
	/usr/bin/svcprop
"

set $bfuoptcmd
isalist=`isalist`
while [ $# -gt 0 ]
do
	dir=${1%/*}
	cmd=${1##*/}
	cd $dir
	isacmd=`(find $isalist -name $cmd 2>/dev/null; echo $cmd) | head -1`
	cp $dir/$isacmd /tmp/bfubin 2>/dev/null
	shift
done

#
# set up installgrub and friends if transitioning to multiboot or directboot
# do this now so ldd can determine library dependencies
#
# We split the binaries into two groups: the type where we want to make any
# effort to get the newest version (like symdef and bootadm), and the type
# where any old version will do (like installgrub and biosdev).
#
# If we're bfu'ing across the directboot/multiboot boundary, we need the new
# bootadm and symdef to properly handle menu.lst changes.  If the system is
# directboot, we can use the local copies.  If the system is multiboot but
# the archives are directboot, we extract the binaries early.  Otherwise,
# we're not crossing the boundary, and which one we use doesn't matter.
#
# NB - if bootadm or symdef is ever changed to require a new library, the
# early extraction will blow up horribly.
#
# For testing purposes, a user can set DIRECTBOOT_BIN_DIR in the environment,
# and we'll use that instead.
#
MULTIBOOT_BIN_DIR=${MULTIBOOT_BIN_DIR:=${GATE}/public/multiboot}
have_new_bootadm=unknown

if [ -f "$root/platform/i86xpv/kernel/unix" ]; then
	root_is_xpv=yes
	root_is_directboot=yes
elif [ -x "$root/boot/solaris/bin/symdef" ] && \
    "$root"/boot/solaris/bin/symdef "$root/platform/i86pc/kernel/unix" \
    dboot_image; then
	root_is_xpv=no
	root_is_directboot=yes
else
	root_is_xpv=no
	root_is_directboot=no
fi

#
# A comma-separated list of the command and the archive it's in
#
multiboot_new_cmds="
	sbin/bootadm,generic.sbin
	boot/solaris/bin/symdef,i86pc.boot
"

if [ $multi_or_direct = yes ]; then
	for line in $multiboot_new_cmds
	do
		cmd=${line%,*}
		file=${cmd##*/}
		archive=${line#*,}
		if [ -n "$DIRECTBOOT_BIN_DIR" ] && \
		    [ -f $DIRECTBOOT_BIN_DIR/$file ]; then
			cp $DIRECTBOOT_BIN_DIR/$file /tmp/bfubin/
		else
			if [[ $root_is_xpv = yes ||
			    $root_is_directboot = yes &&
			    $archive_type = multiboot ]]; then
				cp $root/$cmd /tmp/bfubin/
				have_new_bootadm=yes
			elif [ $archive_type = directboot ] || \
			    [ $archive_type = xpv ]; then
				DBOOT_TMPDIR=/tmp/dboot.$$
				trap "rm -rf $DBOOT_TMPDIR" EXIT
				OLD_PWD=$(pwd)
				rm -rf $DBOOT_TMPDIR
				mkdir $DBOOT_TMPDIR
				cd $DBOOT_TMPDIR
				$ZCAT $cpiodir/${archive}$ZFIX | \
				    cpio -id "$cmd" 2>/dev/null
				if [ -x $cmd ]; then
					cp $cmd /tmp/bfubin/
					have_new_bootadm=yes
				fi
				cd $OLD_PWD
				rm -rf $DBOOT_TMPDIR
				trap - EXIT
			fi
		fi

		#
		# If all else fails, grab the local version
		#
		if [ ! -x /tmp/bfubin/$file ]; then
			[ -x /$cmd ] && cp /$cmd /tmp/bfubin
		fi
	done
	if [ $archive_type = directboot ] && [ $root_is_directboot = yes ]; then
		cleanup_eeprom_console
	fi
fi

multiboot_cmds="
	/sbin/biosdev
	/sbin/installgrub
"
copying_mboot_cmds=no
if [ $multi_or_direct = yes ]; then
	for cmd in $multiboot_cmds
	do
		file=`basename $cmd`
		if [ -f $cmd ]; then
			cp $cmd /tmp/bfubin
		elif [ -n "$DIRECTBOOT_BIN_DIR" ] &&
		    [ -d $DIRECTBOOT_BIN_DIR ] &&
		    [ -x $DIRECTBOOT_BIN_DIR/$file ]; then
			cp $DIRECTBOOT_BIN_DIR/$file /tmp/bfubin/
		else
			if [ ! -d $MULTIBOOT_BIN_DIR ]; then
				echo "$MULTIBOOT_BIN_DIR: not found"
			elif [ ! -f $MULTIBOOT_BIN_DIR/$file ]; then
				echo "$MULTIBOOT_BIN_DIR/$file: not found"
			fi
			if [ $copying_mboot_cmds = no ]; then
				echo "installing files from $MULTIBOOT_BIN_DIR"
				copying_mboot_cmds=yes
			fi
			cp $MULTIBOOT_BIN_DIR/$file /tmp/bfubin
		fi

	done
fi

#
# If available, use ldd to determine which libraries bfu depends on.
# Otherwise, just make an educated guess.
#
if [ -x /usr/bin/ldd ]; then
	bfulib="`ldd /tmp/bfubin/* | nawk '$3 ~ /lib/ { print $3 }' | sort -u`"
else
	bfulib="
		/lib/libc.so.1
		/lib/libm.so.2
		/lib/libdoor.so.1
		/lib/libm.so.2
		/lib/libmd.so.1
		/lib/libmd5.so.1
		/lib/libnvpair.so.1
		/lib/libscf.so.1
		/lib/libuutil.so.1
		/usr/lib/libbsm.so.1
		/usr/lib/libc2.so
		/usr/lib/libdl.so.1
		/usr/lib/libelf.so.1
		/usr/lib/libkstat.so.1
		/usr/lib/libmapmalloc.so.1
		/usr/lib/libmp.so.1
		/usr/lib/libnsl.so.1
		/usr/lib/libpam.so.1
		/usr/lib/libsec.so.1
		/usr/lib/libsocket.so.1
		/usr/lib/libtecla.so.1
	"
fi

# add dlopen()'ed stuff
bfulib="
	$bfulib
	/lib/ld.so.1
	/usr/lib/nss_*
"

# add libc_psr.so.1, if available and not empty
if [ -s /platform/`uname -i`/lib/libc_psr.so.1 ]; then
	bfulib="
		$bfulib
		/platform/`uname -i`/lib/libc_psr.so.1
	"
fi

rm -rf /tmp/bfulib /tmp/bl
mkdir /tmp/bfulib /tmp/bl

#
# Create 64 bit directory structure and determine 64 bit arch name.
#
if [ -h /usr/lib/64 ]
then
	link=`ls -dl /usr/lib/64  | awk '{print $NF}'`
	ln -s $link /tmp/bfulib/64
	ln -s $link /tmp/bl/64
	mkdir /tmp/bfulib/$link /tmp/bl/$link
	bfulib="$bfulib /usr/lib/64/nss_*"
	#
	# Copy libraries to proper directories
	#
	for lib in $bfulib
	do
		case $lib in
		*/64/* | */$link/*)
			cp $lib /tmp/bfulib/64;;
		*)
			cp $lib /tmp/bfulib;;
		esac
	done
	#
	# Private 64 bit runtime linker.
	#
	cp /lib/64/ld.so.1 /tmp/bfulib/64/bf.1
	cp /lib/64/ld.so.1 /tmp/bl/64/bf.1
else
	cp $bfulib /tmp/bfulib
fi
cp /lib/ld.so.1 /tmp/bfulib/bf.1	# bfu's private runtime linker
cp /lib/ld.so.1 /tmp/bl/bf.1

${BFULD-$GATE/public/bin/$bfu_isa/bfuld} /tmp/bfubin/* || fail "bfuld failed"

for x in $bfuscr
do
	sed -e 's/\/usr\/bin\//\/tmp\/bfubin\//g' \
	    -e 's/\/bin\//\/tmp\/bfubin\//g' < $x > /tmp/bfubin/`basename $x`
	chmod +x /tmp/bfubin/`basename $x`
done

#
# scripts used together with multiboot
#
multiboot_scr="
	/boot/solaris/bin/create_ramdisk
	/boot/solaris/bin/create_diskmap
	/boot/solaris/bin/root_archive
"

if [ $multi_or_direct = yes ]; then
	for cmd in $multiboot_scr
	do
		file=`basename $cmd`
		if [ -f $cmd ]; then
			cp $cmd /tmp/bfubin
		else
			if [ ! -d $MULTIBOOT_BIN_DIR ]; then
				echo "$MULTIBOOT_BIN_DIR: not found"
				fail ""
			fi

			if [ ! -f $MULTIBOOT_BIN_DIR/$file ]; then
				echo "$MULTIBOOT_BIN_DIR/$file: not found"
				fail ""
			fi
			echo "copying $file from $MULTIBOOT_BIN_DIR"
			cp $MULTIBOOT_BIN_DIR/$file /tmp/bfubin
		fi

		#
		# We do two substitutions here to replace references to
		# both /usr/bin/ and /bin/ with /tmp/bfubin/
		#
		mv /tmp/bfubin/${file} /tmp/bfubin/${file}-
		sed -e 's/\/usr\/bin\//\/tmp\/bfubin\//g' \
		    -e 's/\/bin\//\/tmp\/bfubin\//g' \
		    < /tmp/bfubin/${file}- > /tmp/bfubin/${file}
		chmod +x /tmp/bfubin/${file}
	done
fi

#
# For directboot archives, /boot/platform/i86pc/kernel/unix will be
# overwritten, which could cause a mis-match with the failsafe
# miniroot.  Extract unix from the miniroot and save it off for now.
#
if [ $archive_type = directboot ] && [ $diskless = no ]; then
	if gunzip -c "$root/boot/x86.miniroot-safe" \
	    >/tmp/bfubin/miniroot-unzipped; then
		lofifile=/tmp/bfubin/miniroot-unzipped
	else
		# Shouldn't happen?  See if someone already unzipped it.
		lofifile="$root/boot/x86.miniroot-safe"
	fi
	lofidev=`lofiadm -a $lofifile 2>/dev/null`
	if [ -n "$lofidev" ]; then
		mkdir /tmp/bfubin/mnt
		mount -r $lofidev /tmp/bfubin/mnt

		unix=/tmp/bfubin/mnt/boot/platform/i86pc/kernel/unix
		if [ -f $unix ]; then
			cp $unix /tmp/bfubin/unix
			failsafe_type=directboot
		elif [ -f /tmp/bfubin/mnt/platform/i86pc/multiboot ]
		then
			failsafe_type=multiboot
		fi

		umount /tmp/bfubin/mnt
		rmdir /tmp/bfubin/mnt
		lofiadm -d $lofidev
	fi
	rm -f /tmp/bfubin/miniroot-unzipped
fi

create_datalink_conf()
{
	# /etc/datalink.conf needs to be populated.
	drivers="bge rge xge"
	conf=$rootprefix/etc/datalink.conf

	if [ ! -f $conf ]; then
		# nothing to do if we bfu'ed from an archive that doesn't
		# provide /etc/datalink.conf
		return
	fi

	ls -1 $rootprefix/etc | egrep -e '^hostname.|^hostname6.|^dhcp.' | \
	    cut -d . -f2 | sort -u > /tmp/ifnames.$$

	for driver in $drivers
	do
		grep $driver /tmp/ifnames.$$ | \
		while read ifname
		do
			devnum=`echo $ifname | sed "s/$driver//g"`
			if [ "$driver$devnum" != $ifname -o \
			    -n "`echo $devnum | tr -d '[0-9]'`" ]; then
				echo "skipping invalid interface $ifname"
				continue
			fi

			vid=`expr $devnum / 1000`
			inst=`expr $devnum % 1000`

			awk '{ print $1 }' $conf | grep $ifname > /dev/null
			if [ $? -ne 0 ]; then 
				# An entry for that interface does not exist
				printf \
				    "$ifname\t$driver$inst\t0\t$vid\n" \
				    >> $conf
			fi
		done
	done

	rm -f /tmp/ifnames.$$
}

revert_aggregation_conf()
{
	aggrconf=$rootprefix/etc/aggregation.conf
	nawk '
		/^[ \t]*#/ || /^[ \t]*$/ || $4 ~ "/0" {
			print;
			next;
		}

		{
			OFS="\t";
			gsub(/[^,]*/, "&/0", $4);
			print;
		}' $aggrconf > $aggrconf.bfutmp
	mv -f $aggrconf.bfutmp $aggrconf
}

remove_initd_links()
{
	# If we're delivering a new version of an existing /etc/init.d script,
	# remove all hard links to the existing file in /etc/rc?.d whose
	# names begin with [SK][0-9][0-9].  Additionally, in case an S or K
	# file was previously delivered as a symbolic link or the hard link
	# was broken, remove any file in /etc/rc?.d whose name is
	# [SK][0-9][0-9] followed by the basename of the file we're going
	# to update in /etc/init.d.

	print "Removing init.d links ... \c"
	scripts=`$ZCAT $cpiodir/generic.root$ZFIX |
		cpio -it 2>/dev/null | grep '^etc/init\.d/'`
	if [ -n "$scripts" ]; then
		inodes=`ls -li $scripts 2>/dev/null | \
			nawk '{ print "-inum " $1 " -o " }'`
		names=`ls -1 $scripts 2>/dev/null | \
			nawk -F/ '{ print "-name [SK][0-9][0-9]" $NF }'`
		find etc/rc?.d \( $inodes $names \) -print | xargs rm -f
	fi
	print "done."
}

#
# Remove the old 5.005_03 version of perl.
#
remove_perl_500503()
{
	# Packages to remove.
	typeset -r perl_pkgs='SUNWopl5m SUNWopl5p SUNWopl5u'
	typeset pkg

	#
	# First, attempt to remove the packages cleanly if possible.
	#
	printf 'Removing perl 5.005_03 packages'
	for pkg in $perl_pkgs
	do
		if pkginfo $pkgroot -q $pkg; then
			printf ' %s' $pkg
			pkgrm $pkgroot -n $pkg >/dev/null 2>&1
		fi
	done
	printf '\n'

	#
	# In case that didn't work, do it manually.
	#
	printf 'Removing perl 5.005_03 from %s/var/sadm/install/contents' \
	    $rootprefix
	for pkg in $PKGS
	do
		printf ' %s' $pkg
		if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
			rm -rf $rootprefix/var/sadm/pkg/$pkg
			grep -vw $pkg $rootprefix/var/sadm/install/contents > \
			    /tmp/contents.$$
			cp /tmp/contents.$$ /var/sadm/install/contents.$$
			rm /tmp/contents.$$
		fi
	done
	printf '\n'

	#
	# Remove any remaining 5.005_03 files,
	#
	printf 'Removing perl 5.005_03 from %s/perl5\n' $usr

	# Directories.
	rm -rf $usr/perl5/5.00503
	rm -rf $usr/perl5/site_perl/5.005
}

#
# Remove Wildcat (aka Sun Fire Link)
#
remove_eof_wildcat()
{
	# Packages to remove
	typeset -r wildcat_pkgs='SUNWwrsa SUNWwrsd SUNWwrsu SUNWwrsm'
	typeset pkg

	#
	# First, attempt to remove the packages cleanly if possible.
	# Use a custom "admin" file to specify that removal scripts
	# in the packages being removed should be run even if they
	# will run as root.
	#
	typeset -r admfile='/tmp/wcat_eof.$$'
	echo "action=nocheck" > $admfile

	printf 'Removing Wildcat packages...'
	for pkg in $wildcat_pkgs
	do
		if pkginfo $pkgroot -q $pkg; then
			printf ' %s' $pkg
			pkgrm $pkgroot -n -a $admfile $pkg >/dev/null 2>&1
		fi
	done
	printf '\n'

	#
	# In case that didn't work, do it manually.
	#
	printf 'Removing Wildcat from %s/var/sadm/install/contents...' \
	    $rootprefix
	for pkg in $wildcat_pkgs
	do
		printf ' %s' $pkg
		if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
			rm -rf $rootprefix/var/sadm/pkg/$pkg
			grep -vw $pkg $rootprefix/var/sadm/install/contents > \
			    /tmp/contents.$$
			cp /tmp/contents.$$ \
			    $rootprefix/var/sadm/install/contents
			rm /tmp/contents.$$
		fi
	done
	printf '\n'

	#
	# Cleanup any remaining Wildcat files, symlinks, and directories.
	#
	rm -f $usr/platform/sun4u/include/sys/wci_common.h
	rm -f $usr/platform/sun4u/include/sys/wci_regs.h
	rm -f $usr/platform/sun4u/include/sys/wci_offsets.h
	rm -f $usr/platform/sun4u/include/sys/wci_cmmu.h
	rm -f $usr/platform/sun4u/include/sys/wrsm.h
	rm -f $usr/platform/sun4u/include/sys/wrsm_common.h
	rm -f $usr/platform/sun4u/include/sys/wrsm_config.h
	rm -f $usr/platform/sun4u/include/sys/wrsm_types.h
	rm -f $usr/platform/sun4u/include/sys/wrsm_plat.h
	rm -f $usr/platform/sun4u/include/sys/wrsm_plugin.h
	rm -f $usr/platform/sun4u/include/sys/wrsmconf.h

	rm -f $usr/platform/sun4u/lib/mdb/kvm/sparcv9/wrsm.so
	rm -f $usr/platform/sun4u/lib/mdb/kvm/sparcv9/wrsmd.so

	rm -f $rootprefix/platform/SUNW,Sun-Fire-15000/kernel/misc/sparcv9/gptwo_wci

	rm -f $rootprefix/platform/sun4u/kernel/kmdb/sparcv9/wrsm
	rm -f $rootprefix/platform/sun4u/kernel/kmdb/sparcv9/wrsmd

	rm -f $admfile
}

#
# Remove ASET
#
remove_eof_aset()
{
	# Packages to remove
	typeset -r aset_pkgs='SUNWast'
	typeset pkg

	printf 'Removing ASET... '

	#
	# First, attempt to remove the packages cleanly if possible.
	#
	for pkg in $aset_pkgs
	do
		if pkginfo $pkgroot -q $pkg; then
			printf ' %s' $pkg
			pkgrm $pkgroot -n $pkg >/dev/null 2>&1
		fi
	done
	printf '\n'

	#
	# In case that didn't work, do it manually.
	# Remove ASET from $rootprefix/var/sadm/install/contents
	#
	for pkg in $aset_pkgs
	do
		if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
			rm -rf $rootprefix/var/sadm/pkg/$pkg
			grep -vw $pkg $rootprefix/var/sadm/install/contents > \
			    /tmp/contents.$$
			cp /tmp/contents.$$ $rootprefix/var/sadm/install/contents.$$
			rm /tmp/contents.$$
		fi
	done

	#
	# Cleanup any remaining ASET files, symlinks, and directories.
	#
	rm -rf $usr/aset
}

#
# Remove BIND 8 named server/tools packages
#
remove_eof_bind8()
{
	# Packages to remove
	typeset -r bind8_pkg='SUNWinamd'
	typeset pkg

	printf 'Removing BIND 8 named server/tools... '

	#
	# We cann't pkgrm SUNWinamd at this time as the BIND 9 binaries are
	# already in /usr/sbin.
	# Remove BIND 8 packages from $rootprefix/var/sadm/install/contents
	#
	for pkg in $bind8_pkgs
	do
		if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
			rm -rf $rootprefix/var/sadm/pkg/$pkg
			grep -vw $pkg $rootprefix/var/sadm/install/contents > \
			    /tmp/contents.$$
			cp /tmp/contents.$$ /var/sadm/install/contents.$$
			rm /tmp/contents.$$
		fi
	done

	#
	# Cleanup any BIND 8 specific files, symlinks.
	#

	# files and symlinks.
	rm -f $usr/sbin/named-xfer
	rm -f $usr/lib/nslookup.help
	rm -f $usr/sbin/dnskeygen
	rm -f $usr/sbin/named-bootconf
	rm -f $usr/sbin/nstest
	rm -rf $rootprefix/var/run/ndc.d
	printf 'done.\n'
}

#
# Remove the 5.8.3 version of perl.
#
remove_perl_583()
{
	#
	# Copy perl 5.8.3 into the new 5.8.4 locations.  This will preserve
	# any add-on modules that might have been installed, and any 5.8.3
	# core files that get copied over will be replaced by the new 5.8.4
	# versions when the cpio archives are subsequently extracted.
	#
	printf 'Preserving user-installed perl modules...\n'
	mkdir -p $usr/perl5/5.8.4
	cp -rp $usr/perl5/5.8.3/* \
	    $usr/perl5/5.8.4
	mkdir -p $usr/perl5/site_perl/5.8.4
	cp -rp $usr/perl5/site_perl/5.8.3/* \
	    $usr/perl5/site_perl/5.8.4
	mkdir -p $usr/perl5/vendor_perl/5.8.4
	cp -rp $usr/perl5/vendor_perl/5.8.3/* \
	    $usr/perl5/vendor_perl/5.8.4

	#
	# Update the #! lines in any scripts in /usr/perl5/5.8.4/bin to refer
	# to 5.8.4 instead of 5.8.3.  Take care to edit only scripts.
	#
	typeset bindir="$usr/perl5/5.8.4/bin"
	typeset script
	for script in $(ls $bindir); do
		script="$bindir/$script"
		if [[ $script = "$usr/perl5/5.8.4/bin/perl5.8.3" ]]; then
			rm -f $script
		elif file $script | \
		    egrep -s 'executable .*perl .*script'; then
			sed -e \
			    's!/usr/perl5/5.8.3/bin/perl!/usr/perl5/5.8.4/bin/perl!g' \
			    < $script > $script.tmp
			mv -f $script.tmp $script
		fi
	done

	#
	# Packages to remove.
	#
	typeset -r perl_pkgs='SUNWperl583man SUNWperl583usr SUNWperl583root'

	#
	# First, attempt to remove the packages cleanly if possible.
	#
	typeset pkg
	printf 'Removing perl 5.8.3 packages'
	for pkg in $perl_pkgs
	do
		if pkginfo $pkgroot -q $pkg; then
			printf ' %s' $pkg
			pkgrm $pkgroot -n $pkg >/dev/null 2>&1
		fi
	done
	printf '\n'

	#
	# In case that didn't work, do it manually.
	#
	printf 'Removing perl 5.8.3 from %s/var/sadm/install/contents' \
	    $rootprefix
	for pkg in $PKGS
	do
		printf ' %s' $pkg
		if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
			rm -rf $rootprefix/var/sadm/pkg/$pkg
			grep -vw $pkg $rootprefix/var/sadm/install/contents > \
			    /tmp/contents.$$
			cp /tmp/contents.$$ /var/sadm/install/contents.$$
			rm /tmp/contents.$$
		fi
	done
	printf '\n'

	#
	# Remove any remaining 5.8.3 files,
	# and fix up the symlinks if necessary.
	#
	printf 'Removing perl 5.8.3 from %s/perl5\n' $usr

	# Directories.
	rm -rf $usr/perl5/5.8.3
	rm -rf $usr/perl5/site_perl/5.8.3
	rm -rf $usr/perl5/vendor_perl/5.8.3

	# bin symlink.
	rm -f $usr/perl5/bin
	ln -s ./5.8.4/bin $usr/perl5/bin

	# pod symlink.
	rm -f $usr/perl5/pod
	ln -s ./5.8.4/lib/pod $usr/perl5/pod

	#
	# man symlink.  In earlier S10 builds the man symlink mistakenly points
	# to the 5.6.1 manpages, instead of 5.8.3.  Fix to point to 5.8.4.
	#
	rm -f $usr/perl5/man
	ln -s ./5.8.4/man $usr/perl5/man

	# Symlink /bin/perl to 5.8.4.
	rm -f $usr/bin/perl
	ln -s ../perl5/5.8.4/bin/perl $usr/bin/perl
}

#
# Remove FNS/XFN packages
#
remove_eof_fns()
{
	# Packages to remove
	typeset -r fns_pkgs='SUNWfnx5x SUNWfnsx5 SUNWfnsx SUNWfns'
	typeset pkg

	printf 'Removing FNS/XFN ... '

	#
	# First, attempt to remove the packages cleanly if possible.
	#
	for pkg in $fns_pkgs
	do
		if pkginfo $pkgroot -q $pkg; then
			printf ' %s' $pkg
			pkgrm $pkgroot -n $pkg >/dev/null 2>&1
		fi
	done
	printf '\n'

	#
	# In case that didn't work, do it manually.
	# Remove FNS/XFN from $rootprefix/var/sadm/install/contents
	#
	for pkg in $fns_pkgs
	do
		if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
			rm -rf $rootprefix/var/sadm/pkg/$pkg
			grep -vw $pkg $rootprefix/var/sadm/install/contents > \
			    /tmp/contents.$$
			cp /tmp/contents.$$ $rootprefix/var/sadm/install/contents.$$
			rm /tmp/contents.$$
		fi
	done

	#
	# Cleanup if any remaining FNS/XFN files, symlinks, and directories.
	#

	# directories.
	rm -rf $rootprefix/etc/fn
	rm -rf $usr/include/xfn
	rm -rf $usr/lib/fn
	rm -rf $rootprefix/var/fn

	# files and symlinks.
	rm -f $rootprefix/etc/fn.conf
	rm -f $usr/bin/fnattr
	rm -f $usr/bin/fnbind
	rm -f $usr/bin/fncreate_printer
	rm -f $usr/bin/fnlist
	rm -f $usr/bin/fnlookup
	rm -f $usr/bin/fnrename
	rm -f $usr/bin/fnsearch
	rm -f $usr/bin/fnunbind
	rm -f $usr/sbin/fncheck
	rm -f $usr/sbin/fncopy
	rm -f $usr/sbin/fncreate
	rm -f $usr/sbin/fncreate_fs
	rm -f $usr/sbin/fndestroy
	rm -f $usr/sbin/fnselect
	rm -f $usr/sbin/fnsypd
	rm -f $usr/lib/libfn_p.so
	rm -f $usr/lib/libfn_p.so.1
	rm -f $usr/lib/libfn_spf.so
	rm -f $usr/lib/libfn_spf.so.1
	rm -f $usr/lib/libxfn.so
	rm -f $usr/lib/libxfn.so.1
	rm -f $usr/lib/libxfn.so.2
	rm -f $usr/lib/sparcv9/libfn_p.so
	rm -f $usr/lib/sparcv9/libfn_p.so.1
	rm -f $usr/lib/sparcv9/libfn_spf.so
	rm -f $usr/lib/sparcv9/libfn_spf.so.1
	rm -f $usr/lib/sparcv9/libxfn.so
	rm -f $usr/lib/sparcv9/libxfn.so.1
	rm -f $usr/lib/sparcv9/libxfn.so.2
}

remove_eof_face() {
	# Packages to remove
	typeset -r face_pkgs='SUNWfac'
	typeset pkg

	printf 'Removing AT&T FACE... '

	#
	# First, attempt to remove the packages cleanly if possible.
	#
	for pkg in $face_pkgs
	do
		if pkginfo $pkgroot -q $pkg; then
			printf ' %s' $pkg
			pkgrm $pkgroot -n $pkg >/dev/null 2>&1
		fi
	done
	printf '\n'

	#
	# In case that didn't work, do it manually.
	# Remove FACE from $rootprefix/var/sadm/install/contents
	#
	for pkg in $face_pkgs
	do
		if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
			rm -rf $rootprefix/var/sadm/pkg/$pkg
			grep -vw $pkg $rootprefix/var/sadm/install/contents > \
			    /tmp/contents.$$
			cp /tmp/contents.$$ $rootprefix/var/sadm/install/contents.$$
			rm /tmp/contents.$$
		fi
	done

	#
	# Cleanup any remaining FACE files, symlinks, and directories.
	#
	rm -rf $usr/oasys
	rm -rf $usr/vmsys
}

remove_eof_dmi() {
	# Packages to remove
	typeset -r dmi_pkgs='SUNWsadmi'
	typeset pkg

	printf 'Removing DMI... '

	#
	# First, attempt to remove the packages cleanly if possible.
	#
	for pkg in $dmi_pkgs
	do
		if pkginfo $pkgroot -q $pkg; then
			printf ' %s' $pkg
			pkgrm $pkgroot -n $pkg >/dev/null 2>&1
		fi
	done
	printf '\n'

	#
	# In case that didn't work, do it manually.
	# Remove DMI from $rootprefix/var/sadm/install/contents
	#
	for pkg in $dmi_pkgs
	do
		if [ -d $rootprefix/var/sadm/pkg/$pkg ]; then
			rm -rf $rootprefix/var/sadm/pkg/$pkg
			grep -vw $pkg $rootprefix/var/sadm/install/contents > \
			    /tmp/contents.$$
			cp /tmp/contents.$$ $rootprefix/var/sadm/install/contents.$$
			rm /tmp/contents.$$
		fi
	done

	#
	# Cleanup any remaining DMI files, symlinks, and directories.
	#
	rm -rf $usr/lib/dmi
	rm -rf $rootprefix/var/dmi
	rm -rf $rootprefix/etc/dmi
	rm -f $usr/lib/libdmi.so
	rm -f $usr/lib/libdmici.so
	rm -f $usr/lib/libdmimi.so
	rm -f $usr/lib/libdmi.so.1
	rm -f $usr/lib/libdmici.so.1
	rm -f $usr/lib/libdmimi.so.1
	rm -f $usr/lib/sparcv9/libdmi.so
	rm -f $usr/lib/sparcv9/libdmici.so
	rm -f $usr/lib/sparcv9/libdmimi.so
	rm -f $usr/lib/sparcv9/libdmi.so.1
	rm -f $usr/lib/sparcv9/libdmici.so.1
	rm -f $usr/lib/sparcv9/libdmimi.so.1
	rm -f $usr/lib/amd64/libdmi.so
	rm -f $usr/lib/amd64/libdmici.so
	rm -f $usr/lib/amd64/libdmimi.so
	rm -f $usr/lib/amd64/libdmi.so.1
	rm -f $usr/lib/amd64/libdmici.so.1
	rm -f $usr/lib/amd64/libdmimi.so.1
	rm -f $usr/sbin/dmi_cmd
	rm -f $usr/sbin/dmiget
	rm -f $rootprefix/etc/init.d/init.dmi
	rm -f $rootprefix/etc/rc0.d/K07dmi
	rm -f $rootprefix/etc/rc1.d/K07dmi
	rm -f $rootprefix/etc/rc2.d/K07dmi
	rm -f $rootprefix/etc/rcS.d/K07dmi
	rm -f $rootprefix/etc/rc3.d/S77dmi
}

#
# Remove vold
#
remove_eof_vold()
{
	printf 'Removing vold... '

	rm -rf $usr/lib/vold
	rm -rf $usr/lib/rmmount
	rm -f $usr/lib/fs/hsfs/ident_hsfs.so.1
	rm -f $usr/lib/fs/pcfs/ident_pcfs.so.1
	rm -f $usr/lib/fs/udfs/ident_udfs.so.1
	rm -f $usr/lib/fs/ufs/ident_ufs.so.1
	rm -f $usr/sbin/vold
	rm -f $usr/kernel/drv/vol
	rm -f $usr/kernel/drv/amd64/vol
	rm -f $usr/kernel/drv/sparcv9/vol
	rm -f $usr/include/rmmount.h
	rm -f $usr/include/vol.h
	rm -f $rootprefix/etc/vold.conf
	rm -f $rootprefix/etc/rmmount.conf

	printf '\n'
}

#
# Remove the obsolete Mobile IP packages
#
remove_eof_mobileip() {
	typeset -r mip_pkgs='SUNWmipr SUNWmipu'
	typeset pkg

	printf 'Removing Mobile IP... '

	for pkg in $mip_pkgs
	do
		if pkginfo $pkgroot -q $pkg; then
			printf ' %s' $pkg
			pkgrm $pkgroot -n $pkg >/dev/null 2>&1
		fi
	done

	# In case that did not work, do it manually.
	if [[ -d $rootprefix/var/sadm/pkg/SUNWmipr ]]; then
		rm -f "$rootprefix/etc/inet/mipagent.conf-sample"
		rm -f "$rootprefix/etc/inet/mipagent.conf.fa-sample"
		rm -f "$rootprefix/etc/inet/mipagent.conf.ha-sample"
		rm -f "$rootprefix/etc/init.d/mipagent"
		rm -f "$rootprefix/etc/rc0.d/K06mipagent"
		rm -f "$rootprefix/etc/rc1.d/K06mipagent"
		rm -f "$rootprefix/etc/rc2.d/K06mipagent"
		rm -f "$rootprefix/etc/rc3.d/S80mipagent"
		rm -f "$rootprefix/etc/rcS.d/K06mipagent"
		rm -f "$rootprefix/etc/snmp/conf/mipagent.acl"
		rm -f "$rootprefix/etc/snmp/conf/mipagent.reg"
	fi
	if [[ -d $rootprefix/var/sadm/pkg/SUNWmipu ]]; then
		rm -f "$rootprefix/usr/lib/inet/mipagent"
		rm -f "$rootprefix/usr/sbin/mipagentconfig"
		rm -f "$rootprefix/usr/sbin/mipagentstat"
	fi
	printf '\n'
}

remove_properties() {

	#
	# Remove obsolete smartii setprop from bootenv.rc
	#
	srcbootenvrc=$root/boot/solaris/bootenv.rc
	tmpbootenvrc=/tmp/tmp.bootenvrc.$$

	# Don't touch bootenv.rc unless it contains obsolete property
	egrep -s 'target-driver-for-smartii' $srcbootenvrc 2>/dev/null
	res=$?
	if [ -f $srcbootenvrc -a $res -eq 0 ]; then
		egrep -v "target-driver-for-smartii"\
			$srcbootenvrc > $tmpbootenvrc 2>/dev/null
		cp $tmpbootenvrc $srcbootenvrc
	fi
	rm -f $tmpbootenvrc
}

rbac_cleanup()
{
# This is a copy of the RBAC portions of the SUNWcsr postinstall
# We need to ensure that the RBAC profiles are self-consistent
# as refinements are made that add granularity to the profiles

	print "Cleaning up old RBAC profiles... \c"
	auth_attr=$rootprefix/etc/security/auth_attr
	exec_attr=$rootprefix/etc/security/exec_attr

	if [ -f $auth_attr ]; then
		sed '/^solaris\.\*/d' $auth_attr > /tmp/a.$$
		cp /tmp/a.$$ $auth_attr
		rm -f /tmp/a.$$
	fi

	if [ -f $exec_attr ]; then
		sed -e '/^Network Security.*sbin\/ipsec.*/ D' \
		-e '/^Network Security.*sbin\/ike.*/ D' \
		-e '/^Network Security.*inet\/in\.iked.*/ D' \
		-e '/^Network Security.*inet\/cert.*/ D' $exec_attr > /tmp/e.$$
		cp /tmp/e.$$ $exec_attr
		rm -f /tmp/e.$$
	fi
	print "\n"
}

enable_crypto_unlimited()
{
# This is a "copy" of the SUNWcry* postinstall scripts.
# We enable the encryption kit aes256, arcfour2048, and blowfish448 modules.
# This is needed to ensure bfu users continue to have the full strength of
# cryptographic algorithms they use.

	print "Simulating SUNWcry* installation...\c"
	kcfconf=$rootprefix/etc/crypto/kcf.conf
	ipsecalgs=$rootprefix/etc/inet/ipsecalgs

	cp $kcfconf ${kcfconf}.tmp

	sed -e 's/^aes:/aes256:/' -e 's/^blowfish:/blowfish448:/' -e \
	    's/^arcfour:/arcfour2048:/'\
        	$kcfconf > ${kcfconf}.tmp

	mv -f ${kcfconf}.tmp $kcfconf

	cp $ipsecalgs ${ipsecalgs}.tmp

	sed -e 's/_CBC|128\/32-128,8/_CBC|128\/32-448,8/' \
	    -e 's/AES_CBC|128|/AES_CBC|128\/128-256,64|/' \
	    $ipsecalgs > ${ipsecalgs}.tmp

	mv -f ${ipsecalgs}.tmp $ipsecalgs

	# Since we do that for the kernel we do it for userland as well.

	# "Clone" the policy for pkcs11_softtoken to the encryption kit version
	# and "disable" pkcs11_softoken.

	pkcs11conf=$rootprefix/etc/crypto/pkcs11.conf

	cp $pkcs11conf ${pkcs11conf}.tmp

	sed 's/pkcs11_softtoken\.so/pkcs11_softtoken_extra.so/' \
        	$pkcs11conf > ${pkcs11conf}.tmp

	mv -f ${pkcs11conf}.tmp $pkcs11conf
	print "\n"

}

#
# Add metaslot configuration to pkcs11.conf if it doesn't already exist
#
enable_crypto_metaslot()
{
	pkcs11conf=$rootprefix/etc/crypto/pkcs11.conf
	egrep '^metaslot' ${pkcs11conf} > /dev/null 2>& 1
	if [ $? != 0 ] ; then
		print "Adding cryptographic framework's meta slot feature"
		cp $pkcs11conf ${pkcs11conf}.tmp
		export metaslot_config=\
"metaslot:metaslot_status=enabled;metaslot_auto_key_migrate=enabled;"\
"metaslot_token=Sun Software PKCS#11 softtoken;"\
"metaslot_slot=Sun Crypto Softtoken"
		nawk '/^# End SUNWcsr/ \
			{ print ENVIRON["metaslot_config"] } \
			{ print } \
		' ${pkcs11conf}	> ${pkcs11conf}.tmp
		mv -f ${pkcs11conf}.tmp $pkcs11conf
		print "\n"
	fi
}

cleanup_kerberos_mechanisms()
{
#
# This checks to see if the old 'gl' and 'do' directories
# for the Kerberos GSS-API mechanisms can be deleted.
# If the mechanism exists in /usr/lib/gss, then the old
# subdirs may be deleted.
#
	print "Cleaning up old Kerberos GSS-API mechanisms...\c"

	kerneldir=kernel/misc/kgss
	kerneldir_sparc=kernel/misc/kgss/sparcv9

	newmech=no;
	if [ -f $usr/lib/gss/mech_krb5.so.1 ]; then
		#
		# There is a mech  in the "new" location, so
		# the old stuff can be deleted.
		#
		if [ -d $usr/lib/gss/gl ]; then
			rm -rf $usr/lib/gss/gl
		fi
		if [ -d $usr/lib/gss/do ]; then
			rm -rf $usr/lib/gss/do
		fi
		newmech=yes;
	fi
	if [ -f $usr/lib/sparcv9/gss/mech_krb5.so.1 ]; then
		if [ -d $usr/lib/sparcv9/gss/gl ]; then
			rm -rf $usr/lib/sparcv9/gss/gl
		fi
		if [ -d $usr/lib/sparcv9/gss/do ]; then
			rm -rf $usr/lib/sparcv9/gss/do
		fi
	fi
	#
	# Cleanup kernel mechanisms from default location
	#
	if [ -f $rootprefix/$kerneldir/kmech_krb5 ]; then
		if [ -f $rootprefix/$kerneldir/gl_kmech_krb5 ]; then
			rm -f $rootprefix/$kerneldir/gl_kmech_krb5
		fi
		if [ -f $rootprefix/$kerneldir/do_kmech_krb5 ]; then
			rm -f $rootprefix/$kerneldir/do_kmech_krb5
		fi
	fi
	#
	# For SPARC, cleanup from 2 locations.
	#
	# 1.  /kernel/misc/kgss/sparcv9
	#
	if [ -f $rootprefix/$kerneldir_sparc/kmech_krb5 ]; then
		if [ -f $rootprefix/$kerneldir_sparc/gl_kmech_krb5 ]; then
			rm -f $rootprefix/$kerneldir_sparc/gl_kmech_krb5
		fi
		if [ -f $rootprefix/$kerneldir_sparc/do_kmech_krb5 ]; then
			rm -f $rootprefix/$kerneldir_sparc/do_kmech_krb5
		fi
	fi
	#
	# 2.  /platform/sun4u/kernel/misc/kgss/sparcv9
	#
	kerneldir_sparc=platform/$karch/$kerneldir_sparc
	if [ -f $rootprefix/$kerneldir_sparc/kmech_krb5 ]; then
		if [ -f $rootprefix/$kerneldir_sparc/gl_kmech_krb5 ]; then
			rm -f $rootprefix/$kerneldir_sparc/gl_kmech_krb5
		fi
		if [ -f $rootprefix/$kerneldir_sparc/do_kmech_krb5 ]; then
			rm -f $rootprefix/$kerneldir_sparc/do_kmech_krb5
		fi
	fi
	#
	# Make sure the GSS mechanism configuration file is correct
	#
	if [ "$newmech" = "yes" ]; then
		gssmechconf=$rootprefix/etc/gss/mech

		sed -e 's/gl\/mech_krb5\.so/mech_krb5\.so/' \
		-e 's/do\/mech_krb5\.so/mech_krb5\.so/' \
		-e 's/gl_kmech_krb5/kmech_krb5/' \
		-e 's/do_kmech_krb5/kmech_krb5/'\
		$gssmechconf > ${gssmechconf}.tmp

		if [ $? -eq 0 ]; then
			mv -f ${gssmechconf}.tmp $gssmechconf
		else
			echo  "WARNING: update of $gssmechconf failed."
			return 1
		fi
	fi
	print "\n"
}

mpxiodisableno='^[ 	]*mpxio-disable[ 	]*=[ 	]*"no"[ 	]*;'
mpxiodisableyes='^[ 	]*mpxio-disable[ 	]*=[ 	]*"yes"[ 	]*;'

#
# fix up audit permissions
#
fix_up_audit()
{
	chmod 644 $root/etc/security/audit_control
	chmod 644 $root/etc/security/audit_user
}

#
# disable mpxio on fp(7D) ports using fp.conf
#
disable_mpxio_using_fpconf()
{
	conffile=$rootprefix/kernel/drv/fp.conf
	test -f $conffile || return
	egrep -s "$mpxiodisableyes" $conffile && return

	print "To preserve device names, disabled mpxio on fp(7D) ports by"

	if egrep -s "$mpxiodisableno" $conffile; then
		tmpfile=/tmp/fp.conf.$$
		sed "s/$mpxiodisableno/mpxio-disable=\"yes\";/" $conffile \
		    > $tmpfile
		cp $tmpfile $conffile
		rm -f $tmpfile
		print "changing the value of mpxio-disable to \"yes\" in" \
		  "$conffile"
	else
		echo 'mpxio-disable="yes";' >> $conffile
		print "adding mpxio-disable=\"yes\" entry to $conffile"
	fi
}

#
# enable mpxio in scsi_vhci
#
enable_mpxio_using_scsivhciconf()
{
	#
	# depending on whether the bfu restored the child's or parent's version
	# of scsi_vhci.conf file, we may already have the file with the change
	# we need in place. So make the change only if necessary.
	#

	conffile=$rootprefix/kernel/drv/scsi_vhci.conf
	egrep -s "$mpxiodisableno" $conffile && return

	print "To preserve device names, restored your current mpxio" \
	    "configuration by"

	if egrep -s "$mpxiodisableyes" $conffile; then
		tmpfile=/tmp/scsi_vhci.conf.$$
		sed "s/$mpxiodisableyes/mpxio-disable=\"no\";/" $conffile \
		    > $tmpfile
		cp $tmpfile $conffile
		rm -f $tmpfile
		print "changing the value of mpxio-disable to \"no\" in" \
		  "$conffile"
	else
		echo 'mpxio-disable="no";' >> $conffile
		print "adding mpxio-disable=\"no\" entry to $conffile"
	fi
}

#
# restore the pre-bfu MPxIO on/off setting to the post-bfued configuration
#
fixup_mpxio()
{
	conffile=$rootprefix/kernel/drv/scsi_vhci.conf
	parentconffile=$rootprefix/bfu.parent/kernel/drv/scsi_vhci.conf
	childconffile=$rootprefix/bfu.child/kernel/drv/scsi_vhci.conf
	ancestorconffile=$rootprefix/bfu.ancestor/kernel/drv/scsi_vhci.conf

	# if scsi_vhci.conf doesn't exist return
	test -f $conffile || return

	#
	# Determine the mpxio setting in the child. If the system was bfued
	# before and running with mpxio on by deafult bits, can't rely on the
	# mpxio-disable entry in the child's scsi_vhci.conf file as it may
	# contain stale left over entries.
	#
	mpxio_child=1
	if [ -f $ancestorconffile ]; then
		if egrep -s "$mpxiodisableyes" $ancestorconffile; then
			#
			# prior to the bfu the system was running with
			# mpxio off by default bits.
			#
			mpxio_child=0
			egrep -s "$mpxiodisableno" $childconffile && \
			    mpxio_child=1
		fi
	else
		egrep -s "$mpxiodisableyes" $childconffile && mpxio_child=0
	fi

	if egrep -s "$mpxiodisableyes" $parentconffile; then
		# these bits require explicit enabling of mpxio at in scsi_vhci
		if [ $mpxio_child -eq 1 ]; then
			egrep -s "$mpxiodisableyes" \
			    $rootprefix/kernel/drv/fp.conf || \
			    enable_mpxio_using_scsivhciconf
		fi
	else
		#
		# these bits have mpxio enabled by default in scsi_vhci.
		# if mpxio is disabled in the child, disable mpxio on all
		# fp(7D) ports using fp.conf.
		#
		[ $mpxio_child -eq 0 ] && disable_mpxio_using_fpconf
	fi
}


#
# Check to see if root in $1 has a mounted boot, and that
# it's mounted at the right place for bfu to handle it.
#
# Returns 0 (true) if bfu can handle the upgrade; fails if not
#

boot_is_upgradeable()
{
	ROOT=$1
	if [ "$ROOT" = "/" ] ; then ROOT=""; fi

        BOOTPARTDEV="$(grep -s -v '^#' ${ROOT}/etc/vfstab | \
	    grep "[ 	]/boot[ 	]*pcfs[ 	]" | \
	    awk '{print $1}')"

	# find out if, and where, boot is mounted

	if [ -n "$BOOTPARTDEV" ] ; then 
		if [ -n "$ROOT" ] ; then
		
			BOOTMNT=$(mount | grep "$BOOTPARTDEV" | \
			    awk '{print $1}')
		else
			BOOTMNT="/boot"
		fi
		if [ "$BOOTMNT" != ${ROOT}/boot ] ; then
			cat << BOOTMOUNTERR

${ROOT} refers to an x86 boot partition, but it's not mounted 
at ${ROOT}/boot.

BOOTMOUNTERR
			fail "Mount ${ROOT}s bootpart at ${ROOT}/boot.\n\n"
		fi
	fi

	return 0
}

# update the realmode boot programs at $1 (root) 
# from classic boot psm/stand/bootblks/ufs/i386/installboot.sh

install_boot_i386()
{
	PBOOT=$1
	BOOTBLK=$2
	DEVICE=$3
	if [ ! -f $PBOOT ]; then
		echo "$PBOOT: File not found"
		return 1
	fi
	if [ ! -f $BOOTBLK ]; then
		echo "$BOOTBLK: File not found"
		return 1
	fi
	if [ ! -c $DEVICE ]; then
		echo "$DEVICE: Not a character device"
		return 1
	fi
	if [ ! -w $DEVICE ]; then
		echo "$DEVICE: Not writeable"
		return 1
	fi

	# pboot at block 0, label at blocks 1 and 2, bootblk from block 3 on
	dd if=$PBOOT of=$DEVICE bs=1b count=1 conv=sync >/dev/null 2>&1

	dd if=$BOOTBLK of=$DEVICE bs=1b oseek=3 conv=sync >/dev/null 2>&1

	return 0
}

update_realmode_booters()
{
	ROOT=$1
	
	TMPDIR=/tmp/rmupdate.$$
	trap "rm -rf $TMPDIR" EXIT

	# go get new versions of boot files into TMPDIR

	OLD_PWD=$(pwd)
	mkdir $TMPDIR
	cd $TMPDIR

	# i86pc.boot archive
	REQFILES="boot/mdboot boot/strap.com"
	$ZCAT $cpiodir/i86pc.boot$ZFIX |  cpio -id $REQFILES 2>/dev/null 
	mv $REQFILES $TMPDIR

	# i86pc.usr archive
	REQFILES="usr/platform/i86pc/lib/fs/ufs/pboot"
	REQFILES="$REQFILES usr/platform/i86pc/lib/fs/ufs/bootblk"
	$ZCAT $cpiodir/i86pc.usr$ZFIX | cpio -id $REQFILES 2>/dev/null
	mv $REQFILES $TMPDIR

	cd $OLD_PWD

	grep -s -v '^#' ${ROOT}/etc/vfstab | \
	    grep "[ 	]/boot[ 	]*pcfs[ 	]" >/dev/null

	if [ $? -eq 0 ] ; then
		echo 'Updating /boot on x86 boot partition.'

		REQFILES="mdboot strap.com"
		for f in ${REQFILES}; do
			if [ ! -f ${TMPDIR}/$f ]; then
				fail "Missing $f, aborting."
			fi
		done

		MDBOOT=${TMPDIR}/mdboot
		STRAP=${TMPDIR}/strap.com

		LUBIN=/usr/lib/lu
		TMP_FDFILE1=${TMPDIR}/fdfile1.$$
		LOGFILE=${TMPDIR}/mkfs.log.$$
		DDCOPY=${TMPDIR}/.dd_x86_boot_copy

		DISKID="$(grep -s -v '^#' ${ROOT}/etc/vfstab | \
		    grep "[ 	]/boot[ 	]*pcfs[ 	]" |\
		    awk '{print $1}' | sed -e 's:p0\:boot::g')"

		DISKID="$(basename ${DISKID})"

		# Obtain the disk table; it will look something like the following:
		#
# * Id    Act  Bhead  Bsect  Bcyl    Ehead  Esect  Ecyl    Rsect    Numsect
#   130   128  27     28     0       242    9      553     1728     8897472
		# 
		# Delete all blank lines, and all lines that begin with *,
		# leaving only actual fdisk entries that we can scan
		# looking for the X86BOOT partition

		fdisk -W - /dev/rdsk/${DISKID}p0 | \
		    grep -v '^*' | grep -v '^$' > ${TMP_FDFILE1}

		num=1

		while read id act bhead bcyl ehead ecyl rsect numsect
		do
			# Ignore entry if not X86 /boot partition
			# ID '190' is the X86BOOT partition (see man fdisk(1M))

			if [ $id -ne "190" ] ; then
				num=$(expr $num + 1)
				continue
			fi

			# Found X86 boot partition - save contents to $DDCOPY
			BOOTPART=/dev/rdsk/${DISKID}p${num}
			echo "Boot device is <${BOOTPART}>"

			ERRMSG="$(dd if=${BOOTPART} of=${DDCOPY} 2>&1)"
			if [ $? -ne 0 ] ; then
				[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
				fail "Unable to save copy of <${BOOTPART}>."
			fi

			# mount copy of old /boot partition 
			LOBOOTDEV=$(lofiadm -a ${DDCOPY} 2>&1)
			if [ $? -ne 0 ] ; then
				[ -n "${LOBOOTDEV}" ] && echo "${LOBOOTDEV}"
				fail "Unable to make lo-device <${DDCOPY}>"
			fi
			SOURCE_BOOT_DEV="${TMPDIR}/tmpbootdev.$$"
			mkdir ${SOURCE_BOOT_DEV}
			ERRMSG=$(mount -F pcfs ${LOBOOTDEV} \
			    ${SOURCE_BOOT_DEV})
			if [ $? -ne 0 ] ; then
				[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
				fail "Unable to mount lo-device <${LOBOOTDEV}>."
			fi

			# recreate existing boot partition with updated 
			# boot files

			# umount ${ROOT}'s /boot if mounted

			BOOTMOUNTPT=$(mount | grep ${DISKID}p0:boot 2>&1 | \
			    awk '{print $1;}')

			if [ -n "${BOOTMOUNTPT}" ] ; then
				echo "unmounting /dev/dsk/${DISKID}p0:boot"
				ERRMSG=$(umount \
				    /dev/dsk/${DISKID}p0:boot 2>&1)
				if [ $? -ne 0 ] ; then
					[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
					fail "Unable to umount X86 boot device."
				fi
			fi

			echo "Making new pcfs file system on ${DISKID}"

			echo y | /usr/lib/fs/pcfs/mkfs -F pcfs \
			    -o S,s,B=$MDBOOT,b=BOOT,i=$STRAP \
			    /dev/rdsk/${DISKID}p0:boot >> ${LOGFILE} 2>&1
			if [ $? -ne 0 ] ; then
				echo "Unable to make pcfs:"
				cat ${LOGFILE}
				fail ""
			fi

			echo "Copying x86 boot partition contents back\c"
			echo " to new /boot fs."

			OLD_PWD=$(pwd)

			echo "Remounting freshened /boot partition"

			if [ -z "${BOOTMOUNTPT}" ] ; then 
				# boot ptn wasn't mounted
				BOOTMOUNT="/tmp/bootpart"
				mkdir ${BOOTMOUNT}
			else
				BOOTMOUNT=${BOOTMOUNTPT}
			fi

			ERRMSG=$(mount -F pcfs \
			    /dev/dsk/${DISKID}p0:boot ${BOOTMOUNT} 2>&1)

			if [ $? -ne 0 ] ; then
				[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
				fail "Unable to mount X86 boot device."
			fi

			# copy old /boot contents
			cd ${SOURCE_BOOT_DEV}
			find . -mount \! -type s -print | \
			    cpio -pcdum ${BOOTMOUNT} 2>&1 | \
			    ${LUBIN}/lustripcpioerr

			if [ $? -ne 0 ] ; then
				fail "Unable to copy boot partition contents."
			fi

			cd ${OLD_PWD}

			# unmount and rm our boot mount, if we created it
			if [ -z "${BOOTMOUNTPT}" ] ; then
				ERRMSG=$(umount ${BOOTMOUNT} 2>&1)
				if [ $? -ne 0 ] ; then
					[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
					fail "Unable to umount <$BOOTMOUNT>." 
				fi
				rm -rf ${BOOTMOUNT}
			fi

			# unmount, un-lofi, and rm SOURCE_BOOT_DEV

			ERRMSG=$(umount ${SOURCE_BOOT_DEV} 2>&1)
			if [ $? -ne 0 ] ; then
				[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
				fail "Cannot umount lo-device <${LOBOOTDEV}>." 
			fi

			ERRMSG=$(lofiadm -d ${DDCOPY} 2>&1)
			if [ $? -ne 0 ] ; then
				[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
				fail "Cannot remove lo-device <${LOBOOTDEV}>." 
			fi
		
			rm -rf ${SOURCE_BOOT_DEV}

		done < ${TMP_FDFILE1}
		rm ${TMP_FDFILE1} ${LOGFILE} ${DDCOPY}

	else

		# non boot-partition: use installboot to get pboot and bootblk
		echo "Updating /boot on Solaris partition."

		if [ -z "${ROOT}" ] ; then SEARCH="/"; else SEARCH="${ROOT}"; fi

		ROOTRAWDEV=$(mount | grep "^${SEARCH} on " | \
		    awk '{print $3}' | sed 's;/dsk;/rdsk;')

		if [ -z "${ROOTRAWDEV}" ] ; then
			[ -n "${ROOTRAWDEV}" && echo "${ROOTRAWDEV}" ] 
			fail "${SEARCH} must be a mounted filesystem"
		fi

		echo "Updating Solaris partition ${ROOTRAWDEV} with installboot"
		REQFILES="pboot bootblk"
		for f in ${REQFILES}; do
			if [ ! -f ${TMPDIR}/$f ]; then
				fail "Missing $f, aborting."
			fi
		done
		PBOOT=${TMPDIR}/pboot
		BOOTBLK=${TMPDIR}/bootblk
		install_boot_i386 $PBOOT $BOOTBLK ${ROOTRAWDEV}
		if [ $? -ne 0 ] ; then
			fail "Unable to installboot to <${ROOTRAWDEV}>." 
		fi
	fi
}

print "Verifying archives ..."

for a in generic $allarchs $rootarchs
do
	test -r $cpiodir/$a.root$ZFIX ||
		fail "bfu archive $cpiodir/$a.root$ZFIX missing"
done

if [ ! -r $cpiodir/generic.lib$ZFIX -o ! -r $cpiodir/generic.kernel$ZFIX -o \
    ! -r $cpiodir/generic.sbin$ZFIX ]; then
	old_style_archives="true"
	$ZCAT $cpiodir/generic.root$ZFIX | cpio -it 2>/dev/null | \
	    egrep -s '^etc/zones' && \
		fail "bfu archive $cpiodir/generic.{kernel,lib,sbin}$ZFIX" \
		     "missing;\npossible mkbfu version mismatch: pre-zones" \
		     "style archives with zones files."
fi

for a in generic $allarchs $usrarchs
do
	test -r $cpiodir/$a.usr$ZFIX ||
		fail "bfu archive $cpiodir/$a.usr$ZFIX missing"
done

for root in $rootlist
do
	cd $root || fail "Cannot cd $root"
	prologue=${root%/}/bfu.prologue
	if [ -f $prologue ]; then
		print "Executing $prologue"
		$prologue || fail "$prologue failed with code $?"
	fi
done

print "Performing basic sanity checks ..."

for dir in $usr $rootlist
do
	test -d $dir || fail "$dir does not exist"
	test -w $dir || fail "$dir is not writable"
	cd $dir || fail "Cannot cd $dir"
done

RM_32BIT_KERNEL=0;
if [ "$karch" = "sun4u" ] &&
   ($ZCAT $cpiodir/sun4u.root$ZFIX | cpio -itv 2>&1 |
    grep "^l.*platform/sun4u/kernel/unix -> sparcv9/unix$" > /dev/null);
    then
	RM_32BIT_KERNEL=1;
	if [ "$force_override" = "no" ] && 
	   (prtconf -F 2>&1 | egrep '(cgthree|bwtwo)' > /dev/null);
	    then
		print "\n\nERROR: You are upgrading to a 64-bit-only OS. " \
		      "Your frame buffer does not have a 64-bit driver and " \
		      "will not work after reboot.  To proceed you must run " \
		      "bfu with the -f flag.";
		exit;
	fi;
fi;

if [ $plat = "SUNW,Ultra-1" ] && [ ! -f $cpiodir/SUNW,Ultra-1.root$ZFIX ] &&
   [ "$force_override" = "no" ];
   then
	print "\nERROR: These archives do not have Ultra-1 platform support." \
	      "\nProceeding with this BFU may render this machine unbootable." \
	      "\nTo proceed anyway, you must run bfu with the -f flag.\n";
	exit;
fi;

for root in $rootlist
do
	rootprefix=${root%/}
	smf_check_repository
done

MINIMUM_OS_REV=10

#
# Perform additional sanity checks if we are upgrading the live system.
#
if [ "$rootlist" = "/" ]
then
	#
	# Disallow from older releases
	#
	os_rev=`uname -r | sed -e s/5.//`
	if [ $os_rev -lt $MINIMUM_OS_REV -a "$force_override" = "no" ]; then
		fail "Cannot bfu from pre-Solaris $MINIMUM_OS_REV"
	fi
	if [ ! -x /usr/sbin/svcadm ]; then
		fail "This version of bfu cannot run on pre-Greenline " \
		    "(s10_64) systems"
	fi

	#
	# Filesystem space checks
	#
	set $root 4 $usr 6
	while [ $# -gt 0 ]
	do
		test "`df -b $1 | tail -1 | nawk '{ print $2 }'`" -ge ${2}000 ||
			fail "Less than $2 MB free on $1 -- bfu not safe."
		shift 2
	done
	#
	# Disable kernel module unloading
	#
	print "Disabling kernel module unloading ... \c"
	test -x /usr/bin/adb || fail "/usr/bin/adb not found: bfu not safe."
	echo "moddebug/W20000" | adb -kw /dev/ksyms /dev/mem | grep moddebug
	#
	# Load modules and drivers here not to reload them when you access
	# /devices or its subdirectories later.
	#
	nawk '$1 !~ /^#|^$/ {print $1}' /etc/name_to_major | \
	sed -e 's/#.*$//' | while read driver
	do
		modload -p drv/${driver} >/dev/null 2>&1
	done
	ls $cpiodir >>/dev/null		# loads elfexec and networking

	# exec/intpexec and sys/kaio are needed by lofi
	modload -p exec/intpexec >/dev/null 2>&1
	modload -p sys/kaio >/dev/null 2>&1

	# umount /lib/libc.so.1 if necessary
	if [ -n "`mount | grep '^/lib/libc.so.1'`" ]
	then
		print "Unmounting /lib/libc.so.1 ..."
		umount /lib/libc.so.1
	fi

	PLAT=`/usr/bin/uname -i`
	ARCH=`/usr/bin/uname -m`
	# umount /platform/$PLAT/lib/libc_psr.so.1 if necessary
	if [ -n "`mount | grep "^/platform/$PLAT/lib/libc_psr.so.1"`" ]
	then
		print "Unmounting /platform/$PLAT/lib/libc_psr.so.1 ..."
		umount /platform/$PLAT/lib/libc_psr.so.1
	else
		# umount /platform/$ARCH/lib/libc_psr.so.1 if necessary
		if [ -n "`mount | grep "^/platform/$ARCH/lib/libc_psr.so.1"`" ]
		then
			print "Unmounting /platform/$ARCH/lib/libc_psr.so.1 ..."
			umount /platform/$ARCH/lib/libc_psr.so.1
		fi
	fi

	# umount /platform/$PLAT/lib/sparcv9/libc_psr.so.1 if necessary
	if [ -n "`mount | grep "^/platform/$PLAT/lib/sparcv9/libc_psr.so.1"`" ]
	then
		print "Unmounting /platform/$PLAT/lib/sparcv9/libc_psr.so.1 ..."
		umount /platform/$PLAT/lib/sparcv9/libc_psr.so.1
	else
		# umount /platform/$ARCH/lib/sparcv9/libc_psr.so.1 if necessary
		if [ -n "`mount | grep \
		    "^/platform/$ARCH/lib/sparcv9/libc_psr.so.1"`" ]
		then
			print "Unmounting \c"
			print "/platform/$ARCH/lib/sparcv9/libc_psr.so.1 ..."
			umount /platform/$ARCH/lib/sparcv9/libc_psr.so.1
		fi
	fi

	# umount /platform/sun4u-us3/lib/libc_psr.so.1 if necessary
	if [ -n "`mount | grep '^/platform/sun4u-us3/lib/libc_psr.so.1'`" ]
	then
		print "Unmounting /platform/sun4u-us3/lib/libc_psr.so.1 ..."
		umount /platform/sun4u-us3/lib/libc_psr.so.1
	fi

	# umount /platform/sun4u-us3/lib/sparcv9/libc_psr.so.1 if necessary
	if [ -n "`mount | grep '^/platform/sun4u-us3/lib/sparcv9/libc_psr.so.1'`" ]
	then
		print "Unmounting /platform/sun4u-us3/lib/sparcv9/libc_psr.so.1 ..."
		umount /platform/sun4u-us3/lib/sparcv9/libc_psr.so.1
	fi

	if [ -x /usr/sbin/zoneadm ]; then
		#
		# Stop any running zones: the init script will print a
		# message if needed.
		#
		if [ -x /etc/init.d/zones ]; then
			/etc/init.d/zones stop
		elif [ -x /lib/svc/method/svc-zones ]; then
			#
			# We need all zones to be down before proceeding.
			# We can't accomplish this by just disabling the
			# zones service, since it might already be disabled.
			# So we pretend to be SMF, and invoke the stop method.
			#
			# When zones are someday independently managed as
			# service instances, this will need to be revised.
			#
			export SMF_FMRI="svc:/system/zones:default"
			/lib/svc/method/svc-zones stop
			unset SMF_FMRI
		fi

		[ -z `zoneadm list | grep -v global` ] || \
		    fail "zone(s) failed to halt"
		#
		# Determine the installed zones, which we will want to do
		# after we're done with the global zone.  This is done now
		# rather than later in case bfu'ing the global zone causes
		# the zone configuration to become unreadable (e.g., via a
		# DTD flag day).
		#
		bfu_zone_list=$root/.bfu_zone_list
		rm -f $bfu_zone_list

		zoneadm list -pi | nawk -F: '{
			if ($3 == "installed" &&
			    ($6 == "native" || $6 == "" || $6 == "sn1")) {
				printf "%s %s\n", $2, $4
			}
		}' > $bfu_zone_list
	fi

	#
	# Stop sendmail so that mail doesn't bounce during the interval
	# where /etc/mail/aliases is (effectively) empty.
	#
	# (note that unlike other services here, /etc/init.d/sendmail
	# remains post-smf(5) because it is a public interface.)
	#
	if [ -r /etc/svc/volatile/repository_door ]; then
		print "Disabling sendmail temporarily ..."
		svcadm disable -t network/smtp
	else
		print "Killing sendmail ..."
		/etc/init.d/sendmail stop
	fi

	print "Disabling remote logins ..."
	echo "bfu in progress -- remote logins disabled" >/etc/nologin

	#
	# Stop syslogd so it doesn't interfere with saving preserved files.
	#
	if [ -f /etc/init.d/syslog ]; then
		print "Killing syslogd ..."
		/etc/init.d/syslog stop
	elif [ -r /etc/svc/volatile/repository_door ]; then
		print "Disabling syslog temporarily ..."
		svcadm disable -t system/system-log
	fi

	#
	# Stop apache so it doesn't get upset when the entire world changes
	# out from underneath it.
	#
	if [ -f /etc/init.d/apache ]; then
		print "Killing httpd ..."
		/etc/init.d/apache stop
	elif [ -r /etc/svc/volatile/repository_door ]; then
		print "Disabling httpd temporarily ..."
		svcadm disable -t network/http
	fi

	#
	# Kill off fmd so it doesn't get upset when the entire world changes
	# out from underneath it.
	#
	if [ -f /etc/init.d/savecore ]; then
		print "Killing fmd ..."
		pkill -x fmd
	elif [ -r /etc/svc/volatile/repository_door ]; then
		print "Disabling fmd temporarily ..."
		svcadm disable -t system/fmd
	fi

	#
	# Stop nscd so it doesn't interfere with stuff.
	#
	if [ -x /etc/init.d/nscd ]; then
		print "Killing nscd ..."
		/etc/init.d/nscd stop
	elif [ -r /etc/svc/volatile/repository_door ]; then
		print "Disabling nscd temporarily ..."
		svcadm disable -t system/name-service-cache:default
	fi

	if grep -v "^#" $rootprefix/etc/vfstab | grep boot | \
		grep "[ 	]pcfs[ 	]" >/dev/null 2>&1
	then
		boot_is_pcfs=yes
	fi

	smf_new_profiles

else
	#
	# Check ${root}/etc/motd for SunOS value to get `uname -r`
	#
	os_rev=`head -1 ${root}/etc/motd | sed -e 's/^.*SunOS //' | \
		awk '{print $1}' | sed -e s/5.//`
	if [ $os_rev -lt $MINIMUM_OS_REV -a "$force_override" = "no" ]; then
		fail "Cannot bfu from pre-Solaris $MINIMUM_OS_REV"
	fi
	if [ ! -x /usr/sbin/svcadm ]; then
		fail "This version of bfu cannot run on pre-Greenline " \
		    "(s10_64) systems"
	fi
fi

export PATH=/tmp/bfubin:$PATH
export LD_LIBRARY_PATH=/tmp/bfulib

if [ -h /tmp/bfulib/64 ]
then
	ldlib64="LD_LIBRARY_PATH_64=/tmp/bfulib/64"
	export LD_LIBRARY_PATH_64=/tmp/bfulib/64
fi

# turn off auxiliary filters, since they can cause objects to be loaded
# from outside of the protected environment.
export LD_NOAUXFLTR=1

#
# Since we've turned off auxiliary filters, libc_psr will normally not
# be loaded at all.  But libc_psr was overriding broken code in libc
# for over a week before the fix for 6324631, so we need to explicitly
# LD_PRELOAD it to allow users to bfu from the broken libc.  This can be
# removed once there are no sun4u machines bfued to Nevada bits between
# 9/7/2005 and 9/15/2005.
#
if [ -f /tmp/bfulib/libc_psr.so.1 ]; then
	export LD_PRELOAD_32=/tmp/bfulib/libc_psr.so.1
fi

print "Turning on delayed i/o ..."
fastfs -f $rootlist $usr
fastfs $rootlist $usr

#
# The "| tee -a $EXTRACT_LOG" following do_extraction() is not pulled into the
# function itself because it interferes with the cpio exit status detection.
# pcfs boot is an exception, since its cpio exit status is expected to be bad,
# so a heuristic must be employed to infer whether or not any errors occurred.
#
do_extraction() {
	compressed_archive=$1
	shift
	$ZCAT $compressed_archive | cpio -idmucB $* 2>&1 \
		|| extraction_error "extracting archive $1"
}

do_pcfs_boot_extraction() {
	PCFS_BOOT_LOG=/tmp/bfu-pcfs-boot-log.$$
	$ZCAT $1 | cpio -idmucB 2>&1 | grep -v "error.s" | \
		grep -v "cpio: Cannot chown()" | \
		grep -v "cpio: Error during chown()" | tee $PCFS_BOOT_LOG
	cat $PCFS_BOOT_LOG >> $EXTRACT_LOG
	egrep -s -v blocks $PCFS_BOOT_LOG
	if [ $? -eq 0 ]; then
		extraction_error "extracting archive $1 ... see $PCFS_BOOT_LOG"
	else
		rm -f $PCFS_BOOT_LOG
	fi
}

#
# Usage: extract_archives (root|usr|lib|sbin|kernel) arch-list
#
extract_archives() {
	base=$1
	shift
	test $base = usr && cd $usrroot || cd $root
	for archive in $*
	do
		print "Extracting $archive.$base$ZFIX ... \c" \
			| tee -a $EXTRACT_LOG
		test -h platform/$archive && rm platform/$archive
		if [ $base = root ]; then
			exclude="-f dev/fd home proc etc/mnttab"

			#
			# We don't want to overwrite the sharetab if
			# it is a mount-point. We assume it is a
			# mount-point if it is not writable.
			#
			if [ -f etc/dfs/sharetab ]; then
				if [ ! -w etc/dfs/sharetab ]; then
					exclude="$exclude etc/dfs/sharetab"
				fi
			fi

			[ -d system/contract ] &&
				exclude="$exclude system/contract"
			[ -d system/object ] &&
				exclude="$exclude system/object"
			[ -f etc/svc/repository.db ] &&
				exclude="$exclude etc/svc/repository.db"
			[ -e etc/repository_door ] &&
				exclude="$exclude etc/repository_door"
			[ -f etc/svc/volatile ] &&
				exclude="$exclude etc/svc/volatile"
			do_extraction $cpiodir/$archive.$base$ZFIX $exclude |
				tee -a $EXTRACT_LOG
		elif [ $base = usr ]; then
			do_extraction $cpiodir/$archive.$base$ZFIX \
				-f "usr/openwin" | tee -a $EXTRACT_LOG
		else
			do_extraction $cpiodir/$archive.$base$ZFIX \
				| tee -a $EXTRACT_LOG
		fi
	done
	cd $root
}

extract_boot_archives() {
	base=$1
	shift
	cd $root
	for archive in $*
	do
		if [ ! -f $cpiodir/$archive.$base$ZFIX ]; then
			continue
		fi
		print "Extracting $archive.$base$ZFIX ... \c" \
			| tee -a $EXTRACT_LOG
		if [ $boot_is_pcfs = yes ]; then
			do_pcfs_boot_extraction $cpiodir/$archive.$base$ZFIX
		else
			do_extraction $cpiodir/$archive.$base$ZFIX | \
				tee -a $EXTRACT_LOG
		fi
		$ZCAT $cpiodir/$archive.$base$ZFIX | cpio -it 2>&1 | \
		    grep  "boot/solaris/devicedb/master" >/dev/null 2>&1
		if [ "$?" = "0" ]; then
			have_realmode=yes
		fi
	done
	cd $root
}

#
# Classic boot pboot and bootblk compatibility with old archives
#
setup_pboot()
{
	NEWPBOOTDIR=$GATE/public/pboot
	NEWPBOOT=${NEWPBOOTDIR}/pboot
	NEWBOOTBLK=${NEWPBOOTDIR}/bootblk
	PBOOTDIR=$usr/platform/$karch/lib/fs/ufs
	PBOOT=${PBOOTDIR}/pboot
	BOOTBLK=${PBOOTDIR}/bootblk

	# they should already be there, but...
	if [ -f $NEWPBOOT -a ! -f $PBOOT ]; then
		print "Installing pboot from $NEWPBOOTDIR"
		cp $NEWPBOOT $PBOOT
	fi
	if [ -f $NEWBOOTBLK -a ! -f $BOOTBLK ]; then
		print "Installing bootblk from $NEWPBOOTDIR"
		cp $NEWBOOTBLK $BOOTBLK
	fi

	if [ -f $NEWPBOOT -a -f $PBOOT ]; then
		LATEST=`ls -Lt $PBOOT $NEWPBOOT | head -1`
		if [ "$LATEST" = "$NEWPBOOT" ]; then
			print "Updating pboot from $NEWPBOOT"
			cp $NEWPBOOT $PBOOT
		fi
	fi
	if [ -f $NEWBOOTBLK -a -f $BOOTBLK ]; then
		LATEST=`ls -Lt $BOOTBLK $NEWBOOTBLK | head -1`
		if [ "$LATEST" = "$NEWBOOTBLK" ]; then
			print "Updating bootblk from $NEWBOOTBLK"
			cp $NEWBOOTBLK $BOOTBLK
		fi
	fi
	if [[ "$rootslice" = /dev/rdsk/* ]]; then
		print "Installing boot block."
		( cd $PBOOTDIR ;
		    install_boot_i386 ./pboot ./bootblk ${rootslice%??}s2 )
	fi
	#
	# Since /platform/i86pc/boot/solaris/boot.bin is moved
	# to /boot/solaris, remove the old one if it really
	# exists.
	#
	OLDBOOTDIR=${root}/platform/i86pc/boot/solaris
	OLDBOOTBIN=${OLDBOOTDIR}/boot.bin
	if [ ! -h ${OLDBOOTDIR} -a -f ${OLDBOOTBIN} ] ;
	then
		print "Removing old boot.bin."
		rm -rf ${OLDBOOTBIN}
	fi
}

#
# Multiboot support
#

saved_boot_files="
	solaris/bootenv.rc
	solaris/devicedb/master
"

#
# transition from multiboot to dca
#
check_multi_to_dca_boot()
{
	bootdev=`grep p0:boot $rootprefix/etc/vfstab | \
		grep pcfs | nawk '{print $1}'`
	if [ "$bootdev" != "" ]; then
		is_pcfs_boot=yes
	fi

	if [ $is_pcfs_boot = yes ]; then
		df -h | grep stubboot >/dev/null 2>&1
		if [ $? -eq 0 ]; then

			# save configurable files from /boot
			# before remounting /stubboot.
			# files are relative to /boot.
			for file in $saved_boot_files
			do
				dir="`dirname $rootprefix/stubboot/$file`"
				mkdir -p $dir
				cp $rootprefix/boot/$file $dir
			done

			echo "unmount $bootdev at $rootprefix/stubboot"
			ERRMSG=$(umount $bootdev 2>&1)
			if [ $? -ne 0 ] ; then
				[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
				fail "Unable to umount $bootdev on $rootprefix/stubboot."
			fi

			# adjust vfstab
			sed -e "s/[ 	]\/stubboot[ 	]/	\/boot	/" \
			    <$rootprefix/etc/vfstab >$rootprefix/etc/vfstab+
			mv $rootprefix/etc/vfstab $rootprefix/etc/vfstab-
			mv $rootprefix/etc/vfstab+ $rootprefix/etc/vfstab

			ERRMSG=$(mount -F pcfs $bootdev $rootprefix/boot 2>&1)
			if [ $? -ne 0 ] ; then
				[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
				fail "Unable to mount $bootdev on $rootprefix/boot."
			fi
		fi
	fi
}

check_dca_to_multiboot()
{
	bootdev=`grep p0:boot $rootprefix/etc/vfstab | \
	    grep pcfs | nawk '{print $1}'`
	if [ "$bootdev" != "" ]; then
		is_pcfs_boot=yes
	fi
	if [ $system_type != dca ]; then
		return
	fi

	# ensure bootpath is in $rootprefix/boot/solaris/bootenv.rc
	# It's ok to put a meta device path in there
	bootenvrc=$rootprefix/boot/solaris/bootenv.rc
	grep "^setprop[	 ]*bootpath[	 ]" $bootenvrc > /dev/null
	if [ $? != 0 ]; then
		rootdev=`grep -v "^#" $rootprefix/etc/vfstab | \
		    grep "[	 ]/[	 ]" | nawk '{print $1}'`
		bootpath=`ls -l $rootdev | nawk '{ print $NF }' |\
		    sed "s#../../devices##"`
		echo "setprop bootpath '$bootpath'" >> $bootenvrc
	fi

	rm -f $rootprefix/boot/mdboot
}

#
# Figure out the boot architecture of the current system:
# 1. If an i86xpv kernel exists, it's a xpv system
# 2. If dboot_image is in unix, it's a dboot system
# 3. Otherwise, if multiboot is present, it's a multiboot system
# 4. Otherwise, it's a pre-multiboot system
#
# This is called before we lay down the new archives.
#
check_system_type()
{
	if [ -f $root/platform/i86xpv/kernel/unix ]; then
		system_type=xpv
	elif [ -x $root/boot/solaris/bin/symdef ] && \
	    $root/boot/solaris/bin/symdef $root/platform/i86pc/kernel/unix \
	    dboot_image; then
		system_type=directboot
	elif [ -x $root/platform/i86pc/multiboot ]; then
		system_type=multiboot
	else
		system_type=dca
	fi
}

#
# Detect SVM root and return the list of raw devices under the mirror
#
get_rootdev_list()
{
	if [ -f $rootprefix/etc/lu/GRUB_slice ]; then
		grep '^PHYS_SLICE' $rootprefix/etc/lu/GRUB_slice | cut -d= -f2
	else
		metadev=`grep -v "^#" $rootprefix/etc/vfstab | \
			grep "[	 ]/[ 	]" | nawk '{print $2}'`
		if [[ $metadev = /dev/rdsk/* ]]; then
       		 	rootdevlist=`echo "$metadev" | sed -e "s#/dev/rdsk/##"`
		elif [[ $metadev = /dev/md/rdsk/* ]]; then
       		 	metavol=`echo "$metadev" | sed -e "s#/dev/md/rdsk/##"`
			rootdevlist=`metastat -p $metavol |\
			    grep -v "^$metavol[ 	]" |\
			    nawk '{print $4}' | sed -e "s#/dev/rdsk/##"`
		fi
		for rootdev in $rootdevlist
		do
			echo /dev/rdsk/$rootdev
		done
	fi
}

#
# Done once per transition from classic (dca) to multi boot
#
setup_stubboot()
{
	bootdev=`grep -v "^#" $rootprefix/etc/vfstab | grep pcfs | \
		grep "[ 	]/boot[ 	]"`
	if [[ -n $bootdev ]] ; then

		bootdev=`echo "$bootdev" | nawk '{print $1}'`
		rbootdev=`echo "$bootdev" | sed -e "s/dev\/dsk/dev\/rdsk/"`

		# Remount boot partition as /stubboot, set up new /boot
		mkdir -p $rootprefix/stubboot

		ERRMSG=$(umount $bootdev 2>&1)
		if [ $? -ne 0 ] ; then
			[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
			fail "Unable to umount $bootdev."
		fi
		ERRMSG=$(mount -F pcfs $bootdev $rootprefix/stubboot 2>&1)
		if [ $? -ne 0 ] ; then
			[ -n "${ERRMSG}" ] && echo "${ERRMSG}"
			fail "Unable to mount $bootdev on $rootprefix/stubboot."
		fi

		mkdir -p $rootprefix/boot
		cp -r $rootprefix/stubboot/* $rootprefix/boot
	
		# adjust /etc/vfstab
		sed <$rootprefix/etc/vfstab \
		    -e "s/[ 	]\/boot[ 	]/	\/stubboot	/" | \
			sed -n >$rootprefix/etc/vfstab+ '
			/p0:boot/ {
				s/[ 	]no/	yes/
				}
				p
			'

		mv $rootprefix/etc/vfstab $rootprefix/etc/vfstab-
		mv $rootprefix/etc/vfstab+ $rootprefix/etc/vfstab
	fi
}

#
# multiboot: install grub on the boot slice
#
install_grub()
{
	STAGE1=$rootprefix/boot/grub/stage1
	STAGE2=$rootprefix/boot/grub/stage2

	if [ -x $rootprefix/boot/solaris/bin/update_grub ]; then
		/tmp/bfubin/ksh $rootprefix/boot/solaris/bin/update_grub \
		    -R $root
	elif [ $is_pcfs_boot = no ]; then
		get_rootdev_list | while read rootdev
		do 
			print "Install grub on $rootdev"
			PATH=/tmp/bfubin /tmp/bfubin/installgrub \
				$STAGE1 $STAGE2 $rootdev
		done
	else
		# copy /boot grub & solaris to /stubboot
		cp -r $rootprefix/boot/grub $rootprefix/stubboot/grub
		cp -r $rootprefix/boot/solaris $rootprefix/stubboot/solaris

		# Adjust grub paths relative to pcfs filesystem
		rm -rf $rootprefix/stubboot/boot
		mkdir -p $rootprefix/stubboot/boot
		mv $rootprefix/stubboot/grub $rootprefix/stubboot/boot
		mv $rootprefix/stubboot/solaris $rootprefix/stubboot/boot

		#
		# Run installgrub after copying stubboot to avoid overwriting
		# /stubboot/boot/grub/stage2, which must stay untouched.
		#
		bootdev=`grep -v "^#" $rootprefix/etc/vfstab | grep pcfs | \
			grep "[ 	]/stubboot[ 	]" | nawk '{print $1}'`
		rbootdev=`echo "$bootdev" | sed -e "s/dev\/dsk/dev\/rdsk/"`
		if [ "$rbootdev" != "" ]; then
			print "Install grub on $rbootdev"
			PATH=/tmp/bfubin /tmp/bfubin/installgrub $STAGE1 $STAGE2 $rbootdev
		fi
	fi
}

#
# We check for several possibilites of a bootenv.rc line:
#
# 1. setprop name 'value'
# 2. setprop name "value"
# 3. setprop name value
#
parse_bootenv_line()
{
	line=$1
	value=`echo $line | grep "'" | cut -d\' -f2`
	if [ -z "$value" ]; then
		value=`echo $line | grep "\"" | cut -d\" -f2`
		if [ -z "$value" ]; then
			value=`echo $line | cut -d' ' -f3-`
		fi
	fi
	echo $value
}

update_bootenv()
{
	bootenvrc=$rootprefix/boot/solaris/bootenv.rc
	bootenvrc_updated=0

	# Note: the big space below is actually a space and tab
	boot_file=`grep '^setprop[ 	]\{1,\}boot-file\>' $bootenvrc`
	if [ -n "$boot_file" ]; then
		file=`parse_bootenv_line "$boot_file"`
		if [ -n "$file" ]; then
			PATH=/tmp/bfubin /tmp/bfubin/bootadm set-menu kernel="$file"
			bootenvrc_updated=1
		fi
	fi

	console=`grep '^setprop[ 	]\{1,\}console\>' $bootenvrc`
	if [ -z "$console" ]; then
		console=`grep '^setprop[ 	]\{1,\}input-device\>' \
		    $bootenvrc`
	fi
	if [ -n "$console" ]; then
		cons=`parse_bootenv_line "$console"`
	fi
	boot_args=`grep '^setprop[ 	]\{1,\}boot-args\>' $bootenvrc`
	if [ -n "boot_args" ]; then
		args=`parse_bootenv_line "$boot_args"`
	fi
	if [ -n "$cons" ] && [ -n "$args" ]; then
		# If args starts with a -B, remove it and add a comma instead
		if echo $args | grep '^-B ' >/dev/null; then
			new_args=`echo $args | sed 's/^-B //'`
			args_line="-B console=$cons,$new_args"
		else
			args_line="-B console=$cons $args"
		fi
	elif [ -n "$cons" ]; then
		args_line="-B console=$cons"
	elif [ -n "$args" ]; then
		args_line="$args"
	else
		args_line=""
	fi
	if [ -n "$args_line" ]; then
		PATH=/tmp/bfubin /tmp/bfubin/bootadm set-menu args="$args_line"
		bootenvrc_updated=1
	fi

	if [ $bootenvrc_updated = 1 ]; then
		egrep -v '^setprop[ 	]+(boot-file|boot-args)[ 	]' $bootenvrc > ${bootenvrc}.new
		[ -s ${bootenvrc}.new ] && mv ${bootenvrc}.new $bootenvrc
	fi
}

get_biosdisk()
{
	rootdev=$1
	rootphys=`ls -l $rootdev | nawk '{ print $NF }' | \
	    sed -e "s/\.\.\/\.\.\/devices//" -e "s/:[abcdefgh],raw//"`
	rbootdev=`echo "$rootdev" | sed -e "s/s[0-7]/p0/"`

	#
	# Use biosdev to get the bios disk number
	#
	biosdisk=`biosdev | grep $rootphys | \
		nawk '{print $1}' | sed -e "s/0x8//"`
}

#
# multiboot: set up initial grub menu
#
update_grub_menu()
{
	MENU=$rootprefix/boot/grub/menu.lst

	grubhd=$1

	if [ $archive_type = multiboot ]; then
		BOOT_PROG="kernel /platform/i86pc/multiboot"
		BOOT_ARCHIVE="module /platform/i86pc/boot_archive"
	else
		#
		# directboot archives
		#
		BOOT_PRO