#!/sbin/sh

################################################################################
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#	Copyright 1992-95 AT&T Global Information Solutions
#
# ident	"@(#)luactivate.sh	5.55	09/07/28 SMI"
#
# luactivate is used to activate an alternative boot environment; that is, prepares the system
# to boot from another boot environment the next time the system is brought down gracefully.
#
# USAGE: luactivate [-l error_log] [-o outfile] [-s] [ [-n] BE-name ]
#
# -l - if specified error messages are logged to this file.
#	-> This overrides the LU_ERROR_LOG_FILE setting read from /etc/default/lu.
# -o - if specified entire session is logged to thie file.
#	-> This overrides the LU_SESSION_LOG_FILE setting read from /etc/default/lu.
# -s - if specified, force a sync on the newly activated be.
# -n n - name of the boot environment to activate.
#
# UNDOCUMENTED PRIVATE USAGE BY LUUPD_BOOT:
#	luactivate -u -n "be-name"
#
# Cause a newly created BE to have its vtoc and bootstrap information updated in real time.
#
# The VTOC is updated to change the partition identification flag of the root slice of the 
# BE to be activated to "V_ROOT", and to change any existing partition marked as the root
# slice to "V_UNASSIGNED".
#
# The bootstrap is updated to be compatible with the version of the OS on the BE to be activated.
#
# OUTPUT  :  For no arguments, the name of BE that will be active on next
#            reboot will be printed.
# DEV     :  Satish
#
# NOTES:
# If the -u option is specified, the behavior of luactivate is modified as follows:
# 
# 1. No check is done to prevent operation if a COPYLOCK is present (a BE is busy).
# 2. No delayed update scripts are created; the following actions are performed in real time:
# 2a. the vtoc on the target BE boot disk is updated using fmthard.
# 2b. the OS bootstrap on the target BE boot disk is updated using installboot.
# 3. No check is done to see if the current PBE is being activated.
# 4. The fallback information is not updated.
# 5. The system boot device parameters are not updated.
# 6. No activate/fallback information is output.
#
# Note: performance testing has proven that "/sbin/sh" provides the best performance over
# /bin/sh and /bin/ksh.
#
################################################################################

LU_PROG_FULL_PATH="$0"
LU_PROG_NAME="`basename ${LU_PROG_FULL_PATH}`"; export LU_PROG_NAME

TMPFILE=/tmp/.luactivate.$$
TMP_RESULT_FILE="/tmp/.luactivate.results.tmp.$$"

PFINSTALL_UPGRADE_FAILED_PKGADDS='/var/sadm/system/data/upgrade_failed_pkgadds'
PFINSTALL_PACKAGES_TO_BE_ADDED='/var/sadm/system/data/packages_to_be_added'

DELAY_UPD_DIR=/etc/lu/DelayUpdate

#
# If changing the name of the DELAY_UPD_SCRIPT
# then change bootadm in ON to also use
# the new filename.
#
DELAY_UPD_SCRIPT=$DELAY_UPD_DIR/activate.sh
DELAY_UPD_SCRIPT_EXEC=$DELAY_UPD_DIR/exec_activate.sh

GRUB_INSTALL=sbin/installgrub
CREATE_RAMDISK='boot/solaris/bin/create_ramdisk'
MBR="mbrfile"
PBE_BOOT_MENU_FILE="menu.pbe"
BOOT_RAW_SLICE=""
BOOT_LOGICAL_SLICE=""
BOOT_LOGICAL_FSTYP=""
BOOT_SLICE_IS_PART=""
LU_IS_PHYS_CONSOLE=no
LU_CONSOLE_ARG=""

################################################################################
# Name:		usage
# Description:	output command line usage information; then call exit to terminate execution.
# Local Prefix:	<none>
# Arguments:	$1 = exit code for script ("" defaults to "1").
# Example:	usage 1
# Returns:	<none> 
################################################################################

usage()
{
  ${LUPRINTF} -p2 "`gettext 'USAGE: %s [ -X ] [ -l error_log ] [ -o outfile ] \
[ -s ] [ [ -n ] BE_name ]'`" "${LU_PROG_NAME}"
  ${LUPRINTF} -Ip2 "`gettext 'Any BE_name should be enclosed in single quotes.'`"
  if [ -z "$1" ] ; then
    exit 1
  fi
  exit "$1"
}

report_error()
{
	# A file has changed on the source and on the target - warn user.

        ${LUPRINTF} -fWelp2 "`gettext 'The following files have changed on \
both the current boot environment <%s> zone <%s> and the boot environment to \
be activated <%s>:'`" "${CURR_BE}" "$1" "${BE_NAME}"
        echo "${ERRMSG}" | while read line ; do
                ${LUPRINTF} -elp2 '   %s' "${line}"
        done

        ${LUPRINTF} -fIelp2 "`gettext 'The files listed above are in \
conflict between the current boot environment <%s> zone <%s> and the boot \
environment to be activated <%s>. These files will not be automatically \
synchronized from the current boot environment <%s> when boot environment \
<%s> is activated.'`" "${CURR_BE}" "$1" "${BE_NAME}" "${CURR_BE}" "${BE_NAME}"
}

################################################################################
# Name:		run_activate_sync
# Description:	Check to see if any synchronization issues will occur when the
#		BE is synchronized on reboot.
# Local Prefix:	csi_
# Arguments:	$1 = mount point for BE to check.
# Returns:	<none>
################################################################################
run_activate_sync()
{
        NEW_BE_MNT_PT=$1
	csi_tmp_sync_file="$NEW_BE_MNT_PT/tmp/.luactivate.sync.$$"

	#If SYNCLIST file is different in Source BE and Target BE, the following
        #code takes the diff of the two files and appends those entries to the
        #new BE that are present in the current BE but not in the BE that is to
        #be activated.

        /bin/diff -w -b  "${LU_SYNCLIST}" "$NEW_BE_MNT_PT${LU_SYNCLIST}"|/bin/egrep -e "^<"| \
           while read line; do
	     xt=`/bin/echo "$line"|/bin/sed -e 's/^<//g'`
             [ -n "$xt" ] && /bin/echo "$xt" >> "${csi_tmp_sync_file}"
           done

        if [ -s "${csi_tmp_sync_file}" ]; then
          /bin/cat "${csi_tmp_sync_file}" >> "$NEW_BE_MNT_PT${LU_SYNCLIST}"
        fi
	#
	# If NEXT_BE and CURR_BE are same
	# simply return.
	#
	if [ "$BE_NAME" = "$CURR_BE" ] ; then
		return
	fi

	ERRMSG=`${LUETCBIN}/lu_activate_sync / "${NEW_BE_MNT_PT}"`
        if [ ! -z "${ERRMSG}" ] ; then
		report_error 'global'
	fi
        #
        # check if current BE supports zones.
	# and has non global zones
	# BE_NAME is the name of the new BE.
        # NEW_BE_MNT_PT is the mount point for the new zone.
	SAVEIFS="$IFS"
	lulib_list_zones -i |
	while IFS=: read zoneid zonename state zonepath uuid extra; do
	    IFS="$SAVEIFS"

	    if [ "$zonename" = global ]; then
		continue
	    fi

	    # Check if the CURR_BE and NEXT_BE have same zones by searching
	    # on zone name and UUID.  If they do, log into the scratch zone
	    # mounted within NEXT_BE.
	    # CURR_BE is mounted on /b in the zone, and we're updating the
	    # zone root at /a.
	    if azname=`zoneadm -R "$NEW_BE_MNT_PT" -z $zonename -u "$uuid" list`
	    then
		# Enter the zone and run the sync process.
		ERRMSG=`zlogin -R "$NEW_BE_MNT_PT" $azname \
		    "$LUETCBIN/lu_activate_sync" /b /a`
		if [ $? -ne 0 -o -n "$ERRMSG" ] ; then
		    report_error "$zonename"
		fi
	    fi
	done

	#Remove the temp file
	/bin/rm -f "${csi_tmp_sync_file}"
}

################################################################################
# Name:		check_os_on_be
# Description:	Check to see if the OS on a boot environment is bootable.
# Local Prefix:	cob_
# Arguments:	$1 = mount point for BE to check.
# Example:      check_os_on_be mntpt
# Returns:	0 = successful (BE can be booted).
#		1 = failure (BE cannot be booted).
################################################################################

check_os_on_be() {
	cob_mntPt="$1"
	cob_returnCode=0

	# Check to see if any packages failed to be added during an upgrade - 
	# this is a warning situation only because a normal upgrade will allow
	# the system to boot with failed packages.
	if [ -f "${cob_mntPt}${PFINSTALL_UPGRADE_FAILED_PKGADDS}" ] ; then
		${LUPRINTF} -Welp2 "`gettext '<%d> packages failed to install \
properly on boot environment <%s>.'`" \
"`/bin/cat ${cob_mntPt}${PFINSTALL_UPGRADE_FAILED_PKGADDS} | /bin/wc -l`" "${BE_NAME}"
		${LUPRINTF} -fIlp1 "`gettext '<%s> on boot environment <%s> \
contains a list of packages that failed to upgrade or install properly. \
Review the file before you reboot the system to determine if any \
additional system maintenance is required.'`" \
"${PFINSTALL_UPGRADE_FAILED_PKGADDS}" "${BE_NAME}"
	fi

	# Check to see if any packages need to be added as a result of a partial
	# upgrade - this is an error condition as the boot environment has an
	# incomplete or failed upgrade.
	if [ -f "${cob_mntPt}${PFINSTALL_PACKAGES_TO_BE_ADDED}" ] ; then
		${LUPRINTF} -Eelp2 "`gettext '<%d> required packages are not \
installed on boot environment <%s>.'`" \
"`/bin/grep -c '^PKG=' ${cob_mntPt}${PFINSTALL_PACKAGES_TO_BE_ADDED}`" "${BE_NAME}"
		${LUPRINTF} -fIlp1 "`gettext '<%s> on boot environment <%s> \
contains a list of required packages that are not installed. The boot \
environment is missing required packages. This might be the result of \
an upgrade operation that failed or that is incomplete. If the boot \
environment was upgraded using a multiple media distribution, for example \
the Solaris CD media, you must continue the upgrade process until it is \
fully completed. Failure to complete the upgrade process with all media of \
the software distribution makes the boot environment unstable.'`" \
"${PFINSTALL_PACKAGES_TO_BE_ADDED}" "${BE_NAME}"
		cob_returnCode=1
	fi

	return "${cob_returnCode}"
}

################################################################################
# Name:		create_delayupdate_script
# Description:	Create the delayed update processing script run by delayed update exec script.
# Local Prefix:	
# Arguments:	$1 = entire command line to luactivate (placed in delayed update script as comment).
#		<none>
# Example:      create_delayupdate_script
# Returns:	0 = successful.
#		1 = failure.
################################################################################

create_delayupdate_script()
{
  dus_commandLineText="$1"

  ${LUPRINTF} -lp2D - "`gettext 'Creating delayed update script <%s>.'`" "${DELAY_UPD_SCRIPT}"

  /bin/rm -f $DELAY_UPD_DIR/boot.* 2>/dev/null
  /bin/rm -f $DELAY_UPD_DIR/vtoc.* 2>/dev/null
  /bin/rm -f $DELAY_UPD_DIR/${MBR} 2>/dev/null
  /bin/rm -f $DELAY_UPD_DIR/${BOOT_MENU_FILE} 2>/dev/null
  /bin/rm -f "${DELAY_UPD_SCRIPT}"
  ERRMSG="`${LUPRINTF} -c \"${DELAY_UPD_SCRIPT}\" 2>&1`"
  if [ $? -ne 0 ] ; then
    [ -n "${ERRMSG}" ] && ${LUPRINTF} -elp2 '%s' "${ERRMSG}"
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to create shutdown script <%s>.'`" "${DELAY_UPD_SCRIPT}"
    return 1
  fi

  # Output the preamble to the delayed update script.
  # Setup LU_PROG_NAME and LUPRINTF.

	/bin/cat <<-EOF >> ${DELAY_UPD_SCRIPT}
		#
		# File: ${DELAY_UPD_SCRIPT}
		# Command: ${dus_commandLineText}
		# OS: `uname -a`
		# Date: `/bin/date`
		# Who: `/bin/who -m`
		# Run-Level: `/bin/who -r`
		#
		# Setup Environment.
		#
		LU_PROG_NAME=\${LU_PROG_NAME:=/etc/init.d/lu}
		if [ -f ${LUBIN}/lulib ] ; then
		    . ${LUBIN}/lulib
		fi
		if [ -x /etc/lib/lu/luprintf ] ; then
		    LUPRINTF=/etc/lib/lu/luprintf
		else
		    LUPRINTF=\${LUPRINTF:=echo}
		fi
	EOF

  chmod 755 $DELAY_UPD_SCRIPT
  return 0
}

################################################################################
# Name:		create_delayupdate_exec_script
# Description:	Create the delayed update execute processing script run by the /etc/init.d/{K,S}#lu scripts
#		on system shutdown.
# Local Prefix:	dup_
# Arguments:	$1 = activated boot environment name (e.g. "be1").
#		$2 = entire command line to luactivate (placed in delayed update script as comment).
# Example:      create_delayupdate_exec_script "be1" "luactivate be1"
# Returns:	0 = successful.
#		1 = failure.
################################################################################

create_delayupdate_exec_script()
{
  dup_beName="$1"
  dup_commandLineText="$2"

  ${LUPRINTF} -lp2D - "`gettext 'Creating delayed update exec script <%s>.'`" "${DELAY_UPD_SCRIPT_EXEC}"

  /bin/rm -f "${DELAY_UPD_SCRIPT_EXEC}"

  ERRMSG="`${LUPRINTF} -c \"${DELAY_UPD_SCRIPT_EXEC}\" 2>&1`"
  if [ $? -ne 0 ] ; then
    [ -n "${ERRMSG}" ] && ${LUPRINTF} -elp2 '%s' "${ERRMSG}"
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to create shutdown execute script <%s>.'`" "${DELAY_UPD_SCRIPT_EXEC}"
    return 1
  fi

  # Output the entire delayed update exec script.
  # 1. Setup LU_PROG_NAME and LUPRINTF.
  # 2. Locate and run the delayed activation script.
  # 3. Output success/fail results.
  # 4. Remove any delayed update files so the procedure is not run on the next reboot again.

	/bin/cat <<-EOF >> ${DELAY_UPD_SCRIPT_EXEC}
		#
		# File: ${DELAY_UPD_SCRIPT_EXEC}
		# Command: "${dup_commandLineText}"
		# OS: `uname -a`
		# Date: `/bin/date`
		# Who: `/bin/who -m`
		# Run-Level: `/bin/who -r`
		#
		# Setup Environment.
		#
		LU_PROG_NAME=\${LU_PROG_NAME:=/etc/init.d/lu}
		if [ -f ${LUBIN}/lulib ] ; then
		    . ${LUBIN}/lulib
		fi
		if [ -x /etc/lib/lu/luprintf ] ; then
		    LUPRINTF="/etc/lib/lu/luprintf"
		else
		    LUPRINTF="echo"
		fi
		#
		# Run activation script and report results.
		#
		if [ -x "${DELAY_UPD_SCRIPT}" ] ; then
		    \${LUPRINTF} +X -fl1 "`gettext 'Live Upgrade: Activating boot environment <%s>.'`" '${dup_beName}'
		    ${DELAY_UPD_SCRIPT}
		    ret="\$?"
		else
		    \${LUPRINTF} +X -fEel1 "`gettext 'Live Upgrade: Unable to locate script <%s> to activate boot environment <%s>.'`" '${DELAY_UPD_SCRIPT}' '${dup_beName}'
		    ret="1"
		fi
		if [ "\$ret" -eq "0" ] ; then
		    \${LUPRINTF} +X -fl1 "`gettext 'Live Upgrade: Activation of boot environment <%s> completed.'`" '${dup_beName}'
		else
		    \${LUPRINTF} +X -fEel1 "`gettext 'Live Upgrade: Activation of boot environment <%s> FAILED.'`" '${dup_beName}'
		fi
		#
		# Remove temporary files and activation script and then exit.
		#
		/bin/rm -f /etc/lu/DelayUpdate/boot.*
		/bin/rm -f /etc/lu/DelayUpdate/vtoc.*
		/bin/rm -f /etc/lu/DelayUpdate/${MBR}
		/bin/rm -f /etc/lu/DelayUpdate/${BOOT_MENU_FILE}
		#
		# For the restore GRUB feature of Live Upgrade to work
		# correctly, it is important that the DELAY_UPD_SCRIPT
		# is deleted after it runs.
		# 
		/bin/rm -f ${DELAY_UPD_SCRIPT}
	EOF

  ret="$?"
  chmod 755 $DELAY_UPD_SCRIPT_EXEC
  if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
    /bin/cp -p /usr/platform/${LU_HARDWARE_IMPLEMENTATION}/lib/fs/${ABE_root_fstyp}/bootblk ${DELAY_UPD_DIR}/bootblk
    ret="$?"
  elif [ "${LU_SYSTEM_ARCH}" = "i386" -o "${LU_SYSTEM_ARCH}" = "ppc" ] ; then
    if [ "$PBE_boot_method" = GRUB ]; then
       /bin/cp -p /${GRUB_INSTALL} ${DELAY_UPD_DIR}/installgrub
       /bin/cp -p /${GRUB_DIR}/stage1 ${DELAY_UPD_DIR}/stage1
       /bin/cp -p /${GRUB_DIR}/stage2 ${DELAY_UPD_DIR}/stage2
    else
       /bin/cp -p /usr/sbin/installboot ${DELAY_UPD_DIR}/installboot
       /bin/cp -p /usr/platform/${LU_HARDWARE_IMPLEMENTATION}/lib/fs/${ABE_root_fstyp}/pboot ${DELAY_UPD_DIR}/pboot
       ret="$?"
       if [ "${ret}" -eq "0" ] ; then
          /bin/cp -p /usr/platform/${LU_HARDWARE_IMPLEMENTATION}/lib/fs/${ABE_root_fstyp}/bootblk ${DELAY_UPD_DIR}/bootblk
          ret="$?${ret}"
       fi
    fi
  fi
  return "${ret}"
}

################################################################################
# Name:		get_curr_bename
# Description:	Determine the current BE name given a BE mount point.
# Local Prefix:	gcb_
# Arguments:	$1 = BE mount point.
# Example:      get_curr_bename ""  <or>  get_curr_bename "/.alt.12321/"
# Returns:	Name of current BE from BE at given mount point.
#		0 - success.
#		1 - fail.
################################################################################

get_curr_bename()
{
  gcb_beMntpt="$1"
  gcb_beName="`${LUBIN}/lucurr -m \"${gcb_beMntpt}\"`"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine root slice for the boot environment mounted at <%s>.'`" "${gcb_beMntpt}"
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'Current BE name from BE at mounted at <%s> is <%s>.'`" "${gcb_beMntpt}" "${gcb_beName}"

  echo "${gcb_beName}"
  return 0
}

################################################################################
# Name:		fsmount
# Description:	Mount an element of a BE, using the appropriate utility
#		based on the fstype.
# Local Prefix:	fsm
# Arguments:	$1 = the filesystem type
#		$2 = the BE device or dataset
#		$3 = The directory mountpoint
# Return codes:
#    0 - Mount success
#    non-0 - Mount failure
################################################################################
fsmount()
{
  if [ "$1" = "zfs" ]; then
    /sbin/zfs set mountpoint="$3" $2
    ret=$?
    if [ "$ret" = "0" ]; then
      /sbin/zfs mount "$2"
      ret=$?
    fi
  else
    /usr/sbin/mount -F $1 $2 $3
    ret=$?
  fi

  return $ret
}

################################################################################
# Name:		chk_mount
# Description:	verify that the ABE's root partition is not currently mounted,
#		and that it can be mounted. 
# Local Prefix:	ckm_
# Arguments:	$1 = the BE root device.
#		$2 = the BE root device file type.
#		$3 = the BE name.
# Return codes:
#    0 - ABE root slice is not mounted and is mountable
#    1 - ABE root slice is already mounted
#    2 - ABE root slice is not mountable
#    3 - ABE root slice was mounted but is now not unmountable 
################################################################################

chk_mount()
{
  ckm_device=$1
  ckm_fstype=$2
  ckm_beName="$3"
  ckm_mntpt="/tmp/.alt.luactivate.$$"
  
  /usr/sbin/mount | /bin/nawk -v dev=$ckm_device '{if ($3 == dev) {printf("%s\n", $1);exit 1;}}'
  if [ $? = 1 ] ; then
    ## The ABE root slice is already mounted - this is an error
    ${LUPRINTF} -Eelp2 "`gettext 'The target boot environment <%s> root device <%s> is already mounted.'`" "${ckm_beName}" "${ckm_device}"
    return 1
  fi
  
  ## the ABE root slice is NOT mounted - attempt to mount to verify it is correct
  if [ ! -d $ckm_mntpt ] ; then
    /bin/mkdir -p $ckm_mntpt
  fi
  
  fsmount $ckm_fstype $ckm_device $ckm_mntpt 2>$TMPFILE
  if [ $? != 0 ] ; then
    /bin/cat $TMPFILE
    /bin/rm -f $TMPFILE
    /bin/rmdir $ckm_mntpt
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to mount target boot environment <%s> root device <%s> to mount point <%s>.'`" "${ckm_beName}" "${ckm_device}" "${ckm_mntpt}"
    return 2
  fi

  # sync data to storage medium before unmounting
  /bin/sync

  # force log to be flushed before unmounting
  if [ -x "/usr/sbin/lockfs" ] ; then
	  /usr/sbin/lockfs -f "${ckm_mntpt}" 1>/dev/null 2>&1
  fi

  # Unmount the temporary mount point
  lulib_unmount_pathname $ckm_device 2>$TMPFILE
  ret=$?
  if [ $ret -ne 0 ] ; then
    lulib_unmount_pathname -f $ckm_device 2>>$TMPFILE
    ret=$?
  fi

  if [ $ret -eq 0 ] ; then
    /bin/rmdir $ckm_mntpt
  else
    /bin/cat $TMPFILE
    /bin/rm -f $TMPFILE
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to unmount target boot environment <%s> root device <%s> mount point <%s>.'`" "${ckm_beName}" "${ckm_device}" "${ckm_mntpt}"
    return 3
  fi
  /bin/rm -f $TMPFILE

  return 0
}

################################################################################
# Name:		fdisk130
# Description:	Examine the boot/root of every BE in /etc/lutab
#		if it is 0xbf partition id, change it to 0x82
# Local Prefix: fpa_
# Arguments:	$1 = device name
# Returns:	0 = successful.
#		1 = no fdisk partition table
#
# NOTE:		S9 (and before) will not recognize the new fdisk partition id
#		Therefore if luactivate is run on a system with a new
#		partitionid then switch to the old partition id
################################################################################
fdisk130()
{
  sbt_oosFlag="$1"
  #
  # This only applies to x86-32 and x86-64
  [ `uname -m` != 'i86pc' ] && return 0

  cat /etc/lutab \
  | grep '^[0-9].*[12]$' \
  | sed \
      -e 's/[^:]*:[^:]*://' \
      -e 's/:.*//' \
      -e 's/[sp][0-9][0-9]*/p0/' \
      -e 's/\/dsk\//\/rdsk\//' \
  | sort -u \
  | while read fpa_dvn
  do
    #
    # A really messed up MBR will produce a warning and pause for input
    # so if any message occurs, dont change anything
    echo "n" | fdisk -W - $fpa_dvn 2>&1 | grep '^[A-Za-z]' > /dev/null && continue

    #
    # Get block address of Solaris2 partition
    rsect=`fdisk -W - $fpa_dvn \
    | grep '^  191 ' \
    | awk '{print $9}'`

    #
    # Skip if Solaris2 partition doesnt exist
    [ "$rsect" -lt 1 ] && continue

    if [ -z "${sbt_oosFlag}" ] ; then
    echo "
      #
      #change Solaris2 to Solaris
      /sbin/fdisk -W - $fpa_dvn \\
      | /bin/grep '^ *[0-9]' \\
      | /bin/sed 's/^ *191 /  130 /' \\
      > /tmp/.fdisk.\$\$

      #
      # update partition id
      /sbin/fdisk -F /tmp/.fdisk.\$\$ $fpa_dvn

      /bin/rm -f /tmp/.fdisk.\$\$
      " >> ${DELAY_UPD_SCRIPT}
    else
       #change Solaris2 to Solaris
       /sbin/fdisk -W - $fpa_dvn \
       | /bin/grep '^ *[0-9]' \
       | /bin/sed 's/^ *191 /  130 /' \
       > /tmp/.fdisk.$$
       /sbin/fdisk -F /tmp/.fdisk.$$ $fpa_dvn
       /bin/rm -f /tmp/.fdisk.$$
    fi
  done

  return 0
}


 ################################################################################
 # Name:         fb_restore_boot_partition
 # Description:  Restore the boot partition for the fallback BE
 # Special:      Called during OOS and so may not call into lulib.
 #               Also, LUPRINTF may be set to "echo"
 # Local Prefix: rbp_
 # Arguments:    $1 = mount point of fallback BE
 #               $2 = Name of fallback BE
 # Returns:      0 = successful.
 #               1 = failure.
 ################################################################################
 fb_restore_boot_partition()
 {
    rbp_mntpt="$1"
    rbp_beName="$2"
    rbp_temp="/tmp/.luactivate.rbp.$$"

    # See set_boot() for why we do this.
    if [ "${PBE_boot_method}" != DCA ]; then
       ${LUPRINTF} "`gettext 'ERROR: fallback boot environment <%s> is not a DCA boot environment.'`" "${rbp_beName}"
       return 1
    fi

    rbp_boot="`/bin/grep -s -v '^#' ${rbp_mntpt}/etc/vfstab | /bin/grep \"[     ]/boot[         ]*pcfs[         ]\"`"
    if [ "$?" -ne 0 ]; then
      ${LUPRINTF} "`gettext 'Fallback boot environment <%s> doesn't use a boot partition.'`" "${rbp_beName}"
      return 0
    else
      rbp_boot="`echo $rbp_boot | /bin/awk '{print $1}' | /bin/sed -e 's:p0\:boot::g'`"
    fi
    diskid="`/bin/basename $rbp_boot`"

    # Get fdisk table after deleting all blank lines and comments
      /usr/sbin/fdisk -W - /dev/rdsk/${diskid}p0 | /bin/grep -v '^*' | /bin/grep -v '^$' > ${rbp_temp}

      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=`/bin/expr $num + 1`
            continue
      fi

     #
     # Found X86 boot partition - restore current boot partition (if one exists for PBE)
     # It is safe to do this without worrying about GRUB menu, since we are falling back from
     # a failed activation and the last active GRUB menu has been saved in the file
     # .dd_x86_boot_copy.
     #

     bootpart_id="/dev/rdsk/${diskid}p${num}"
    /sbin/umount /dev/dsk/${diskid}p0:boot > /dev/null 2>&1         # May not be mounted. so ignore errors
    ${LUPRINTF} "`gettext 'Restoring boot partition for boot environment <%s>.'`" "${rbp_beName}"
    /bin/dd if="${rbp_mntpt}/etc/lu/.dd_x86_boot_copy" of="${bootpart_id}"
    if [ "$?" -ne 0 ]; then
       ${LUPRINTF} "`gettext 'ERROR: Restore of boot partition failed.'`"
      return 1
    fi
    break;
  done < ${rbp_temp}

  return 0

}

 ################################################################################
 # Name:         fb_restore_bootpath
 # Description:  Restore the boot path for the fallback BE
 # Special:      Called during OOS and so may not call into lulib.
 #               Also, LUPRINTF may be set to "echo"
 # Local Prefix: rbt_
 # Arguments:    $1 = mount point of fallback BE
 #               $2 = Name of fallback BE
 # Returns:      0 = successful.
 #               1 = failure.
 ################################################################################
 fb_restore_bootpath()
 {
     rbt_mntpt="$1"
     rbt_beName="$2"
     rbt_temp="/tmp/.luactivate.rbt.$$"

     # See set_boot() for why we do this.
    if [ "${PBE_boot_method}" != DCA ]; then
       ${LUPRINTF} "`gettext 'ERROR: fallback boot environment <%s> is not a DCA boot environment.'`" "${rbt_beName}"
       return 1
    fi
    ${LUPRINTF} "`gettext 'Updating bootpath for fallback boot environment <%s>.'`" "${rbt_beName}"

    rbt_bpath_log=`${rbt_mntpt}/etc/lib/lu/ludo get_boot_device_from_be_name ${rbt_beName} ${rbt_mntpt}/etc/lutab`
    if [ "$?" -ne 0 -o -z "${rbt_bpath_log}" ]; then
         ${LUPRINTF} "`gettext 'ERROR: Cannot find bootpath for fallback boot environment <%s>.'`" "${rbt_beName}"
         return 1
    fi
    rbt_bpath_phys=`/bin/ls -l "$rbt_bpath_log" | /bin/sed 's:.*/devices/:/:g'`
    if [ "$?" -ne 0 -o -z "${rbt_bpath_phys}" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Cannot determine bootpath for fallback boot environment <%s>.'`" "${rbt_beName}"
       return 1
    fi

    rbt_mnted=""
    /bin/grep -s -v '^#' "${rbt_mntpt}"/etc/vfstab | /bin/grep "[ 	]/boot[ 	]*pcfs[ 	]" >/dev/null
    if [ "$?" -eq 0 ]; then
       rbt_pboot_bdev=`/bin/egrep '/boot' "${rbt_mntpt}"/etc/vfstab | /bin/cut -f 1` 
       if [ "$?" -ne 0 -o -z "$rbt_pboot_bdev" ]; then
          ${LUPRINTF} "`gettext 'ERROR: Cannot determine boot partition device for fallback boot environment <%s>. '`" "${rbt_beName}"
      	  return 1
       fi

       /sbin/mount -F pcfs "${rbt_pboot_bdev}" "${rbt_mntpt}"/boot > /dev/null 2>&1
       if [ $? -ne 0 ]; then
          ${LUPRINTF} "`gettext 'ERROR: Cannot mount boot partition for fallback \
              boot environment <%s>. '`" "${rbt_beName}"
          return 1
       fi
       rbt_mnted=yes
    fi

    /bin/egrep -v '^setprop bootpath ' "${rbt_mntpt}"/boot/solaris/bootenv.rc > "$rbt_temp" 
    echo "setprop bootpath ${rbt_bpath_phys}" >> "$rbt_temp"
    /bin/cp "${rbt_temp}" "${rbt_mntpt}"/boot/solaris/bootenv.rc
    /bin/rm -f "${rbt_temp}" > /dev/null 2>&1

    if [ "$rbt_mnted" = yes ]; then
       lulib_unmount_pathname "${rbt_pboot_bdev}" > /dev/null 2>&1
    fi
    return 0
}

 ################################################################################
 # Name:         fb_update_victim_BEs
 # Description:  Set fallback BE bootpath on DCA victim BEs. For a definition
 #               of a victim BE see set_boot()
 # Special:      Called during OOS and so may not call into lulib.
 #               Also, LUPRINTF may be set to "echo"
 #               Also, assumes that fallback BE has its bootpath set correctly
 # Local Prefix: uvb_
 # Arguments:    $1 = mount point of fallback BE
 #               $2 = Name of fallback BE
 # Returns:      0 = successful.
 #               1 = failure.
 ################################################################################

fb_update_victim_BEs()
 {
    uvb_mntpt="$1"
    uvb_beName="$2"
    uvb_temp="/tmp/.luactivate.uvb.$$"

    # See set_boot() for why we do this.
    if [ "${PBE_boot_method}" != DCA ]; then
      ${LUPRINTF} "`gettext 'ERROR: fallback boot environment <%s> is not a DCA boot environment.'`" "${rbt_beName}"
      return 1
    fi

    if [ ! -f "${uvb_mntpt}"/etc/lutab -o ! -s "${uvb_mntpt}"/etc/lutab ]; then
       ${LUPRINTF} "`gettext 'ERROR: Cannot find lutab in fallback boot environment <%s>.'`" "${uvb_beName}"
       return 1
    fi
    # First get the list of all BE IDs
    uvb_ids=`/bin/egrep -v "^#" "${uvb_mntpt}"/etc/lutab | nawk -F: '{print $1}' | sort -u -n`
    if [ -z "$uvb_ids" ]; then
       ${LUPRINTF} "`gettext 'ERROR: Cannot determine boot environment IDs.'`"
       return 1
    fi
    uvb_names=`for i in $uvb_ids; do "${uvb_mntpt}"/etc/lib/lu/ludo get_be_name "$i" "${uvb_mntpt}"/etc/lutab; done`
    if [ -z "$uvb_names" ]; then
       ${LUPRINTF} "`gettext 'ERROR: Cannot determine boot environment names.'`"
       return 1
    fi

    # uvb_currbeName is the name of the ABE which was activate previously,
    # and failed to boot properly.
    uvb_currbeName=`/usr/bin/cat "$uvb_mntpt/etc/lu/.NEXT_ACTIVE"`

    for i in $uvb_names
    do
      # Fallback BE bootpath should have been set correctly before this
      # function is called.
      if [ "$i" = "${uvb_beName}" ]; then
           continue
      fi
    
      if [ "$i" = "${uvb_currbeName}" ]; then
           continue
      fi

      uvb_status=`"${uvb_mntpt}"/etc/lib/lu/ludo get_be_status_from_be_name "$i" "${uvb_mntpt}"/etc/lutab`
      if [ "$uvb_status" != C ]; then
           continue
      fi

      # Mount the BE. Cannot use lumount directly as it is in /usr

      uvb_temp_mntpt=`"${uvb_mntpt}"/etc/lib/lu/ludo lumount "$i"`
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} "`gettext 'ERROR: Cannot mount boot environment <%s>.'`" "$i"
         continue
      fi

     # Skip if GRUB BE - only DCA BEs can be victim BEs
     if [ -f "${uvb_temp_mntpt}"/platform/i86pc/multiboot ]; then

        # This is not a DCA  BE
        # Do an unmount and continue

        "${uvb_mntpt}"/etc/lib/lu/ludo luumount "$i"
        continue
	
      fi

      # Check if BE uses an x86 boot partition. If it does, we have nothing to
      # do as there is only 1 x86 boot partition that is used for booting and we
      # have already updated bootenv.rc on that boot partition to have the fallback
      # BE's bootpath

      /bin/grep -s -v '^#' "${uvb_temp_mntpt}"/etc/vfstab | /bin/grep "[ 	]/boot[ 	]*pcfs[ 	]" >/dev/null
      if [ "$?" -eq 0 ]; then
         # This DCA BE has a x86 boot partition, so do an unmount and continue
         "${uvb_mntpt}"/etc/lib/lu/ludo luumount "$i"
         continue
      fi

      # This is a DCA BE. This is a victim BE, so set its bootpath to fallback BE
      # The following assumes that bootpath setting for fallback BE is
      # correctly set

      /bin/egrep -v '^setprop bootpath ' "${uvb_temp_mntpt}"/boot/solaris/bootenv.rc > "$uvb_temp"
      /bin/egrep '^setprop bootpath ' "${uvb_mntpt}"/boot/solaris/bootenv.rc >> "$uvb_temp"
      /bin/cp "$uvb_temp" "${uvb_temp_mntpt}"/boot/solaris/bootenv.rc
      /bin/rm -f "${uvb_temp}" > /dev/null 2>&1
      "${uvb_mntpt}"/etc/lib/lu/ludo luumount "$i"
  done

  return 0
}



################################################################################
# Name:		set_boot
# Description:	Change the boot device for a newly activated BE
# Local Prefix:	sbt_
# Arguments:	$1 = the BE root device to boot the system from.
#		$2 = the BE root device mount point (where the $1 slice is currently mounted; "" = /).
#		$3 = the BE name of the newly activated BE.
#		$4 = do not delay flag ("" = delay until shutdown, otherwise do immediately).
#		$5 = doing oos servicing ("" = not doing OOS servicing)
# Returns:	0 = successful.
#		1 = failure.
################################################################################

set_boot()
{
  sbt_bootDisk="$1"
  sbt_beMntpt="$2"
  sbt_beName="$3"
  sbt_doNotDelay="$4"
  sbt_oosFlag="$5"

  # If in single user mode then there is no "current boot environment" as
  # the system may be booted from an install image and be in the
  # mini-root. In this case:
  # - assume the current BE name is "single-user-mode"
  # - if there is a /etc/lu/.BE_CONFIG then set the current BE name from there

  if [ -n "${sbt_oosFlag}" ] ; then
    sbt_currBeName="single-user-mode"
    if [ -f "${sbt_beMntpt}/etc/lu/.BE_CONFIG" ] ; then
      . ${sbt_beMntpt}/etc/lu/.BE_CONFIG
      if [ -n "${LUBECF_BE_NAME}" ] ; then
        sbt_currBeName="${LUBECF_BE_NAME}"
      fi
    fi
  else
    sbt_currBeName="`get_curr_bename ${sbt_beMntpt}`"
    if [ "$?" -ne "0" -o -z "${sbt_currBeName}" ] ; then
      ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine name of the target boot environment mounted at <%s>.'`" "${sbt_beMntpt}"
      exit 2
    fi
  fi
 
  #
  # For the "delayed" and "non-delayed" cases, we have already
  # called get_pbe_config(). We call get_pbe_config() here only
  # for the OOS case. luprintf may not be available and we may
  # have to fallback to echo. 
  #
  if [ -n "${sbt_oosFlag}" ]; then
     get_pbe_config "${sbt_currBeName}" "${sbt_beMntpt}" "${sbt_oosFlag}"
     if [ $? != 0 ] ; then
        ${LUPRINTF} "`gettext 'ERROR: Unable to determine the configuration of the target boot environment mounted at <%s>.'`" "${sbt_beMntpt}"
        exit 2
     fi
  fi

  if [ -z "${sbt_doNotDelay}" ] ; then
    # Delay: add proper boot environment changes to delayed update script.
    if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
        #
        # This is a SPARC architecture system with an Open Boot EEPROM interface.
        #
	sbt_bbootDisk="`echo ${sbt_bootDisk} |sed 's:/rdsk/:/dsk/:g'`"
	sbt_bootDev="`/bin/ls -l ${sbt_bbootDisk} |/bin/sed 's:.*/devices/:/:g'`"

	if [ "$LU_KEEP_ALTERNATIVE_BOOT" = "YES" -o "$LU_KEEP_ALTERNATIVE_BOOT" = "yes" ] ; then
	  sbt_lubootdevsetting="/etc/lib/lu/lubootdev '${sbt_bootDev}'"
	else
	  sbt_lubootdevsetting="/etc/lib/lu/lubootdev '${sbt_bootDev}' '$PBE_root_bdev'"
	fi

	${LUPRINTF} -lp2D - "`gettext 'Adding sparc boot device update from BE <%s> device <%s> to BE <%s> device <%s>.'`" "${sbt_currBeName}" "${PBE_root_bdev}" "${sbt_beName}" "${sbt_bootDev}"

	/bin/cat <<-EOF >> ${DELAY_UPD_SCRIPT}
		#
		# Change sparc boot device to boot environment "${sbt_beName}" device "${sbt_bootDev}"
		#
		\${LUPRINTF} +X -flS ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'Live Upgrade: Changing primary boot device to boot environment <%s>.'`" "${sbt_beName}"
		currBootDevice="\`eeprom boot-device | cut -d= -f2\`"
		\${LUPRINTF} +X -flS ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'Live Upgrade: The current boot environment <%s> boots from device <%s>.'`" "${sbt_currBeName}" "\${currBootDevice}"

		${sbt_lubootdevsetting}

		if [ "\$?" != "0" ] ; then
		    \${LUPRINTF} +X -fEel2S ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'Live Upgrade: Unable to change primary boot device to boot environment <%s>.'`" "${sbt_beName}"
		    \${LUPRINTF} +X -fEel2S ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'You must manually change the system boot prom to boot the system from device <%s>.'`" "${sbt_bootDev}"
		else
		    newBootDevice="\`eeprom boot-device | cut -d= -f2\`"
		    \${LUPRINTF} +X -flS ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'Live Upgrade: The new boot environment <%s> boots from device <%s>.'`" "${sbt_beName}" "\${newBootDevice}"
		fi
	EOF

	${LUPRINTF} -lp2D - "`gettext 'Configured init.d scripts to change primary boot device to BE <%s> device <%s>.'`" "${sbt_beName}" "${sbt_bootDev}"

    elif [ "${LU_SYSTEM_ARCH}" = "i386" ] ; then
        #
        # This is an INTEL architecture system with potentially an X86 Boot Partition.
        #
	${LUPRINTF} -lp2D - "`gettext 'Adding i386 boot partition check from BE <%s> device <%s> to BE <%s> device <%s>.'`" "${sbt_currBeName}" "${PBE_root_bdev}" "${sbt_beName}" "${sbt_bootDev}"


	#
        # The following code switches boot partitions via
	# lux86bootdevicecare (if applicable). It also allows
	# strapping DCA BEs by setting bootpath (necessary if
	# the DCA BE is on a disk which is not the boot disk.)
	# If there is a boot partition it is assumed that it
	# is on the boot disk.
	# 
	# The following matrix indicates how the boot partitions
	# are switched:
	# 
	# Transition		Boot partition change
	# -------------------------------------------
	# DCA  -> DCA		switch boot part
	# DCA  -> GRUB		save boot part 
	# GRUB -> DCA		restore boot part
	# GRUB -> GRUB		nop
	#
	# Note: It is not possible to strap via bootpath
	# from a GRUB BE to a DCA/GRUB BE. Doing so
	# will result in a kernel that is from GRUB BE,
	# but a root file system that is from the other BE.
	# Also GRUB BEs don't need strapping via
	# bootpath (we strap via menu.lst).
	# 
	# The following matrix indicates how each case
	# is handled. In the following, target BE is the BE
	# we are switching to. Victim BE is an inactive BE
	# whose bootpath may potentially be changed to
	# boot the target BE.
	#	
	# Victim-BE	Target-BE 	strap via bootpath ?
	# ---------------------------------------------------
	# DCA  		 DCA			YES
	# DCA   	 GRUB			NO
	# GRUB  	 DCA			NO
	# GRUB           GRUB			NO
	#
	# Note: bootpath has different semantics with GRUB boot.
	# It is actually the root filesystem mounted during boot.
	#
       
	if [ -f ${LUBIN}/lux86bootdevicecare -a -x ${LUBIN}/lux86bootdevicecare ]
	then
		/bin/cat <<-EOF >> ${DELAY_UPD_SCRIPT}

		bemnt_state="/tmp/.luactivate.sbt.state.\$\$"

		/bin/rm -f "\$bemnt_state"

		#
		# Change boot partition information and boot device.
		#
		sbt_abe_mntpt=\`lulib_mount -Z "$sbt_beName" "\$bemnt_state"\`
		if [ "\$?" -ne 0 -o -z "\$sbt_abe_mntpt" ]; then
			\${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to mount boot environment <%s>: the activation is aborted.'`" "$sbt_beName"
	   		/bin/rm -f "\$bemnt_state"
			exit 2
		fi

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

		lulib_umount "$sbt_beName" "\$bemnt_state"
		if [ "\$?" -eq 0 ]; then
		   /bin/rm -f "\$bemnt_state"
		fi

		/bin/grep -s -v '^#' /etc/vfstab | /bin/grep "[ 	]/boot[ 	]*pcfs[ 	]" >/dev/null
		sbt_res2="\$?"

                #
		# Newboot BEs will *not* have a boot partition
	        # For legacy boot BEs - it is all or none.
                #
		if [ "\$sbt_res1" -eq 0 -o "\$sbt_res2" -eq 0 ] ; then
			\${LUPRINTF} +X -fl1S ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'Live Upgrade: Updating boot partition for boot environment <%s>.'`" "${sbt_beName}"
			\${LUBIN}/lux86bootdevicecare "${sbt_beName}"

                elif [ "$ABE_boot_method" = DCA ]; then
		    #
		    # We have two goals in the following code: 
		    #
		    # 1) set bootpath for ABE(if DCA)
		    #    GRUB BEs already have their bootpath set
		    #    in create_script()
		    # 2) set DCA target bootpath in victim DCA BEs
		    #	 see comment above on victim and target BEs
		    #
		    
		    TMP_BOOTENV_RC=/tmp/.delayupdate.\$\$

		    # determine the active BE of the system.
		    curr_be=`lulib_lucurr`

                    #
		    # Determine the bootpath of the boot environment to be activated
                    # For legacy (DCA), the bootpath must be physical (not SVM path)
                    #
		    ABE_SLICE=`/etc/lib/lu/ludo get_boot_device_from_be_name ${sbt_beName}`
		    ABE_BOOT_DEV=\`/bin/ls -l \${ABE_SLICE} | /bin/sed 's:.*/devices/:/:g'\`

		    # Change bootpath's value in eeprom (i.e. PBE victim) only if DCA
		    if [ "$PBE_boot_method" = DCA ]; then 
		       /usr/sbin/eeprom bootpath=\${ABE_BOOT_DEV}
		    fi

		    # modify ABE_BOOT_DEV variable such that it can be used in sed command
		    # ABE_BOOT_DEV has format /pci@0,0/pci8086,341a@7,1/sd@0,0:a
		    # it should be changed to \/pci@0,0\/pci8086,341a@7,1\/sd@0,0:a
		    ABE_BOOT_DEV=\`/bin/echo \${ABE_BOOT_DEV} | /bin/sed "s/\\\\//\\\\\\\\\\\\\\\\\\\\//g"\`

		    # for each valid and complete DCA BE, change the BE's bootpath value in eeprom
		    \$LUBIN/lunames_get |
		    while read be_name
		    do
		        # if the BE is the current, then we have already
			# modified it via eeprom command above
		        [ "\$be_name" = "\$curr_be" ] && continue

		        # determine the status of the target BE.
		        status="\`\${LUETCBIN}/ludo get_be_status_from_be_name \"\$be_name\"\`"
		        # if the status of this BE is not 'C' then we should not modify.
		        [ "\$status" != 'C' ] && continue
			

		        # Mount the BE
			BE_MPT=\`lulib_mount -Z "\$be_name" "\$bemnt_state"\`
			if [ "\$?" -ne 0 -o -z "\${BE_MPT}" ]; then
			    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to mount boot environment <%s>: cannot update bootpath value in <%s>.'`" "\${be_name}" "/boot/solaris/bootenv.rc"
	   		   /bin/rm -f "\$bemnt_state"
			   continue
			fi

			#
		        # Modify the boot/solaris/bootenv.rc file if it is a DCA BE
		        # The format of this file is:
		        # setprop variable_name 'value'
			#
			if [ -f "\${BE_MPT}/$MULTI_BOOT" ]; then
			   # A GRUB BE, so skip.
			   lulib_umount "\$be_name" "\$bemnt_state"
			   if [ "\$?" -eq 0 ]; then
			      /bin/rm -f "\$bemnt_state"
			   fi
			   continue
			fi

		        /bin/cat \${BE_MPT}/boot/solaris/bootenv.rc | /bin/sed "s/\(.*\)bootpath.*$/\1bootpath '\${ABE_BOOT_DEV}'/g" > \${TMP_BOOTENV_RC}
		        /bin/cp \${TMP_BOOTENV_RC} \${BE_MPT}/boot/solaris/bootenv.rc
		        /bin/rm -f \${TMP_BOOTENV_RC} 2>/dev/null

		        # Unmount the BE
		        \${LUBIN}/luumount -f "\${BE_MPT}" 2>/dev/null
		    done
		fi
		EOF
	fi
    fi
 elif [ -n "${sbt_oosFlag}" ] ; then
    # Doing oos servicing - bare minimum to fallback to previous boot environment.
    if [ -d /mnt/usr/lib/lu ] ; then
        LUBIN='/mnt/usr/lib/lu'
        LUETCBIN='/mnt/etc/lib/lu'
        LUPRINTF='/mnt/etc/lib/lu/luprintf'
    else
        LUBIN='/usr/lib/lu'
        LUETCBIN='/etc/lib/lu'
        LUPRINTF='/etc/lib/lu/luprintf'
    fi

    if [ -x $sbt_beMntpt/etc/lib/lu/lubootdev ] ; then
      sbt_bbootDisk=`echo ${sbt_bootDisk} | sed  "s/\/rdsk\//\/dsk\//g"`
      sbt_bootDev="`/bin/ls -l ${sbt_bbootDisk} | /bin/sed 's/.*\/devices\//\//g'`"

      if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
        ${LUPRINTF} -1 "`gettext 'Changing primary boot device to boot environment <%s>.'`" "${sbt_beName}"
        ${LUPRINTF} -1 "`gettext 'The current boot environment <%s> boots from device <%s>.'`" "${sbt_currBeName}" "`/usr/sbin/eeprom boot-device |cut -d= -f2`"

        if [ "$LU_KEEP_ALTERNATIVE_BOOT" = "YES" -o "$LU_KEEP_ALTERNATIVE_BOOT" = "yes" ] ; then
           $sbt_beMntpt/etc/lib/lu/lubootdev ${sbt_bootDev} $PBE_root_bdev
        else
           $sbt_beMntpt/etc/lib/lu/lubootdev ${sbt_bootDev}
        fi
        if [ "$?" -eq "0" ] ; then
           ${LUPRINTF} -1 "`gettext 'The new boot environment <%s> boots from device <%s>.'`" "${sbt_beName}" "`/usr/sbin/eeprom boot-device |cut -d= -f2`"
        else
           ${LUPRINTF} -1 "`gettext 'Unable to change primary boot device to boot environment <%s>.'`" "${sbt_bootDev}"
	   ${LUPRINTF} -1 "`gettext 'You must manually change the system boot prom to boot the system from device <%s>.'`" "${sbt_bootDev}"
        fi
      elif [ "${LU_SYSTEM_ARCH}" = "i386" ] ; then
             #
             # This is an INTEL architecture system with potentially an X86 Boot Partition.
             #

             # We have three goals here
             # 1. switching boot partition
             # 2. Setting bootpath for PBE
             # 3. setting bootpath for "victim" DCA BEs (see comments above)

             #
             # 1. Switch boot partition
             # During fallback the situation is much simpler than the "forward activation" case
             # We assume that the ABE is messed up (which is why are doing a fallback).
             # So we only need to restore the PBE i.e. the fallback BE's boot partition
             #
             # Here is the matrix explaining this situation
             #
             # ABE     Fallback-BE          Boot partition change
             # ---------------------------------------
             # DCA ->  DCA      restore boot partition
             # DCA ->  GRUB     nop
             # GRUB->  DCA      restore boot partition
             # GRUB -> GRUB     nop
             #

             #
             # We did a get_pbe_config() above and so we know
             # what type of boot the fallback BE uses
             #
             ${LUPRINTF} "`gettext 'Checking for a boot partition on fallback boot environment <%s>.'`" "${sbt_currBeName}"
             if [ "${PBE_boot_method}" = DCA ]; then
                fb_restore_boot_partition "${sbt_beMntpt}" "${sbt_beName}"
             fi

             # 2. Update bootpath. Only a DCA BE requires the update, since we never change bootpaths
             #    on GRUB BE to strap another BE
             if [ "${PBE_boot_method}" = DCA ]; then
                fb_restore_bootpath "${sbt_beMntpt}" "${sbt_beName}"
             fi

             #
             # 3. Update victim BEs (if applicable)
             # Here is a matrix explaining the changes
             #
             # Victim-BE                fallback-BE      strap via bootpath ?
             # ------------------------------------------------------------
             # DCA                      DCA             yes
             # DCA                      GRUB            no
             # GRUB                     DCA             no
             # GRUB                     GRUB            no
             #
             # So only DCA BEs will be victim BEs and that too only if
             # the fallback BE is a DCA BE
             #
             if [ "${PBE_boot_method}" = DCA ]; then
                fb_update_victim_BEs "${sbt_beMntpt}" "${sbt_beName}"
             fi

            # This is OOS. Since we already changed all fdisk IDs to 130 while going
            # in the forward direction, there is no need to set that again here.
        fi
       fi
else
    # Neither delayed update nor oos servicing - apply boot environment changes now.
    sbt_bbootDisk=`echo ${sbt_bootDisk} | sed  "s/\/rdsk\//\/dsk\//g"`
    sbt_bootDev="`/bin/ls -l ${sbt_bbootDisk} | /bin/sed 's/.*\/devices\//\//g'`"
    if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
      ${LUPRINTF} -lp1S ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'Changing primary boot device to boot environment <%s>.'`" "${sbt_beName}"
      ${LUPRINTF} -lp1SD - ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'The current boot environment <%s> boots from device <%s>.'`" "${sbt_currBeName}" "`eeprom boot-device |cut -d= -f2`"
      ${LUPRINTF} -lp2SD - ${LU_SYSLOG_FACILITY}.debug -D - "`gettext 'Changing boot environment from BE <%s> device <%s> to BE <%s> device <%s>.'`" "${sbt_currBeName}" "${PBE_root_bdev}" "${sbt_beName}" "${sbt_bootDev}"

	if [ "$LU_KEEP_ALTERNATIVE_BOOT" != "YES" ] ; then
	  /etc/lib/lu/lubootdev ${sbt_bootDev} $PBE_root_bdev
	else
	  /etc/lib/lu/lubootdev ${sbt_bootDev}
	fi

	if [ "$?" -eq "0" ] ; then
	  ${LUPRINTF} -lp1S ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'The new boot environment <%s> boots from device <%s>.'`" "${sbt_beName}" "`eeprom boot-device |cut -d= -f2`"
	  ${LUPRINTF} -lp2D - "`gettext 'Changed primary boot device to BE <%s> device <%s>.'`" "${sbt_beName}" "${sbt_bootDev}"
	else
	  ${LUPRINTF} -Eelp2S ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'Unable to change primary boot device to boot environment <%s>.'`" "${sbt_bootDev}"
	  ${LUPRINTF} -Eelp2 "`gettext 'You must manually change the system boot prom to boot the system from device <%s>.'`" "${sbt_bootDev}"
	fi
    fi
  fi
}

#
# This routine only accepts a char device
#
# Given a name in the c-t-d-p0:boot format, it converts it into
# c-t-d-p<n> where <n> is the real fdisk partition. <n> is number
# between 1 and 4.
#
# Arguments
#	$1 - name in c-t-d-p0:boot format
#	$2 - name of results file
# Returns
#	c-t-d-pN name in result file
#	0 on success
#	1 on failure
#
# It may be called during OOS
#
get_real_boot_partition()
{
   gbp_p0Boot="$1"
   gbp_resFile="$2"

   gbp_tmp1="/tmp/.luact.gbp.1.$$"
   gbp_tmp2="/tmp/.luact.gbp.2.$$"

   /bin/rm -f "$gbp_tmp1" "$gbp_tmp2"

   if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
	${LUPRINTF} "`gettext 'ERROR: get_real_boot_partition(): Invalid arguments'`"
	return 1
   fi

   /bin/echo "$gbp_p0Boot" | /bin/egrep "p0:boot$" > /dev/null 2>&1
   if [ "$?" -ne 0 ]; then
	${LUPRINTF} "`gettext 'ERROR: Not a boot partition name: <%s>'`" "${gbp_p0Boot}"
	return 1
   fi

   #
   # Translate /dev/rdsk/c-t-d-p0:boot to p0
   #
   gbp_p0=`/bin/echo "$gbp_p0Boot" | /bin/sed 's/p0:boot$/p0/g'`
   if [ -z "$gbp_p0" -o ! -c "$gbp_p0" ]; then
	${LUPRINTF} "`gettext 'ERROR: No such partition or not a char device: <%s>'`" "${gbp_p0}"
	return 1
   fi

   /usr/sbin/fdisk -W "$gbp_tmp1" "$gbp_p0" > /dev/null 2>&1
   /usr/bin/grep -v \* "$gbp_tmp1" | /usr/bin/grep -v '^[ 	]*$' > "$gbp_tmp2"
   #
   # Note: while executed in a subshell
   #
   /bin/rm -f "$gbp_tmp1"
   num=1
   while read id act bhead bcycl ehead ecycl rsect numsect
   do
	if [ -z "$id" ]; then
	   continue
	fi

        if [ "$id" -eq 190 ]; then
	   /bin/echo "$num" > "$gbp_tmp1" 
	   break;
	fi
	num=`/bin/expr "$num" + 1`

   done < "$gbp_tmp2"

   if [ -f "$gbp_tmp1" -a -s "$gbp_tmp1" ]; then
      part=`/usr/bin/cat "$gbp_tmp1"`
      if [ "$part" -lt 1 -o "$part" -gt 4 ]; then
         ${LUPRINTF} "`gettext 'ERROR: partition number derived is invalid: <%s>'`" "${part}"
         retval=1
      else
         disk=`/bin/echo "$gbp_p0" | /bin/sed 's/p0$//g'`
         echo "${disk}p${part}" > "$gbp_resFile"
         retval=0
      fi
     
   else
      ${LUPRINTF} "`gettext 'ERROR: No Solaris x86 boot partition on device: <%s>'`" "${gbp_p0}"
      retval=1
   fi

   /bin/rm -f "$gbp_tmp1"
   /bin/rm -f "$gbp_tmp2"

   return "$retval"
}

#
# Given a char s2 slice in Solaris, converts it into the GRUB fdisk
# partition number (which begins with 0)
# 
# Argument:
#	$1  A *char* s2 Solaris slice
#	$2  Name of the results file
# Returns
#	GRUB partition number in specified results file
#	0 on success
#	1 on failure
#
grub_part()
{
  if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'grub_part(): invalid arguments.'`"
     return 1
  fi

  grp_disk=$1 
  grp_out=$2

  grp_tmp1="/tmp/.luactivate.grp.1.$$"
  grp_tmp2="/tmp/.luactivate.grp.2.$$"


  grp_p0=`echo "$grp_disk" | /usr/bin/sed 's/s2$/p0/g'`

  /usr/sbin/fdisk -W "$grp_tmp1" "$grp_p0" > /dev/null 2>&1
  /usr/bin/grep -v \* "$grp_tmp1" | /usr/bin/grep -v '^[ 	]*$' > "$grp_tmp2"

  #
  # Note: while loop is executed in a subshell
  #
  /bin/rm -f "$grp_tmp1"
  num=1
  while read id act bhead bcycl ehead ecycl rsect numsect
  do
	if [ -z "$id" ]; then
          continue
        fi

	#
	# Handle both Solaris and Solaris2 IDs
	#
        if [ "$id" -eq 130 -o "$id" -eq 191 ]; then 
           # GRUB uses partition numbering from 0, so adjust
           num=`expr "$num" - 1`
           echo "$num" > "$grp_tmp1"
	   break
        fi
	num=`expr "$num" + 1`

  done < "$grp_tmp2"

  if [ -f "$grp_tmp1" -a -s "$grp_tmp1" ]; then
     /bin/cp "$grp_tmp1" "$grp_out"
     retval=0
  else
     ${LUPRINTF} -Eelp2 "`gettext ' No Solaris partition on device <%s>.'`" "${grp_p0}"
     retval=1
  fi

  /bin/rm -f "$grp_tmp1"
  /bin/rm -f "$grp_tmp2"

  return "$retval"
}

#
# Given a Solaris block slice (/dev/dsk/cNtNdNsN), find
# the corresponding GRUB slice designator (starting from 'a')
#
# Argument: 
#	$1 - A Solaris block slice
#	$2 - The name of a results file
# Returns:
#	Slice name in results file
#	0 on success
#	1 on failure
#
grub_slice()
{
  if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'grub_slice(): invalid arguments.'`"
     return 1
  fi

  grs_bdev="$1"
  grs_out="$2"

  /bin/ls -l "$grs_bdev" | sed 's/.*\(.\)$/\1/g' > "$grs_out"

  return 0
}


get_pbe_config()
{

  gpc_tmp="/tmp/.luactivate.gpc.1.$$"

  gpc_beName="$1"
  gpc_mntpt=""
  if [ -n "$2" ] ; then
    gpc_mntpt="$2"
  fi
  gpc_oosFlag="$3"

  # If in single user mode then there is no "current boot environment"
  # so set the PBE BE ID to "0"
  if [ -n "${gpc_oosFlag}" ] ; then
    PBE_id=0
  else
    # Get the BE ID for the PBE.
    PBE_id="`${LUETCBIN}/ludo get_be_id \"${gpc_beName}\" \"${gpc_mntpt}${LU_LUTAB_FILE}\" 2>&1`"
    if [ "$?" -ne "0" -o -z "${PBE_id}" ] ; then
      [ -n "${PBE_id}" ] && ${LUPRINTF} -elp2 '%s' "${PBE_id}"
      return 1
    fi
  fi
  ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> BE ID is <%s>.'`" "${gpc_beName}" "${PBE_id}"

  # Get the BE block boot device for the PBE.
  PBE_root_bdev="`${LUETCBIN}/lubootdevice -m \"${gpc_mntpt}\"`"
  if [ "$?" -ne "0" -o -z "${PBE_root_bdev}" ] ; then
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> BE physical boot block device is <%s>.'`" "${gpc_beName}" "${PBE_root_bdev}"

  # Get the BE root specification for the PBE (that is, it may contain a meta
  # device name or ZFS root pool).
  PBE_root_logical_bdev="`${LUETCBIN}/lurootspec -m \"${gpc_mntpt}\"`"
  if [ "$?" -ne "0" -o -z "${PBE_root_logical_bdev}" ] ; then
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> BE root specification is <%s>.'`" "${gpc_beName}" "${PBE_root_logical_bdev}"

  # Get the BE character boot device for the PBE.
  PBE_root_cdev=`echo $PBE_root_bdev | sed  "s/\/dsk\//\/rdsk\//g"`
  if [ "$?" -ne "0" -o -z "${PBE_root_cdev}" ] ; then
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> BE boot character device is <%s>.'`" "${gpc_beName}" "${PBE_root_cdev}"

  # Get the BE character boot device file system type for the PBE.
  # If in out of service (single user) mode, may not call lulib functions.
  if [ -z "${gpc_oosFlag}" ] ; then
    PBE_root_fstyp="`lulib_fstyp $PBE_root_cdev 2>/dev/null`"
    if [ "$?" -ne "0" -o -z "${PBE_root_fstyp}" ] ; then
      return 1
    fi
  else
    PBE_root_fstyp="`/usr/sbin/fstyp $PBE_root_cdev 2>/dev/null`"
    if [ "$?" -ne "0" -o -z "${PBE_root_fstyp}" ] ; then
      PBE_root_fstyp="ufs"
    fi
  fi
  ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> BE boot character device fstype is <%s>.'`" "${gpc_beName}" "${PBE_root_fstyp}"

  # Get the BE boot character device entire disk access slice for the PBE.
  PBE_boot_disk="`echo $PBE_root_cdev| sed 's/.$/2/g'`"
  if [ "$?" -ne "0" -o -z "${PBE_boot_disk}" ] ; then
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> BE boot character device entire disk access slice is <%s>.'`" "${gpc_beName}" "${PBE_boot_disk}"
  
  PBE_root_slice="`echo $PBE_root_cdev| sed 's/.*\(.\)/\1/g'`"
  if [ $? != 0 ] ; then
    return 1
  fi
  case $PBE_root_slice in
    a)	PBE_root_slice=10;;
    b)	PBE_root_slice=11;;
    c)	PBE_root_slice=12;;
    d)	PBE_root_slice=13;;
    e)	PBE_root_slice=14;;
    f)	PBE_root_slice=15;;
  esac

  ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> BE root slice is <%s>.'`" "${gpc_beName}" "${PBE_root_slice}"

  #
  # The rest only applies to SPARC and x86 only
  #
  if [ "$LU_SYSTEM_ARCH" != "i386" -a "$LU_SYSTEM_ARCH" != sparc ]; then
     PBE_boot_method=""
     return 0
  fi

  #
  # Check if SPARC boot is ARCHIVE based or non-ARCHIVE based
  #
  if [ "$LU_SYSTEM_ARCH" = sparc ]; then
     if [ -x "${gpc_mntpt}/${CREATE_RAMDISK}" ]; then
        PBE_boot_method=ARCHIVE
     else
	PBE_boot_method=NON_ARCHIVE
     fi
     ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> boot method is <%s>.'`" "${gpc_beName}" "${PBE_boot_method}"
     return 0
  fi

  #
  # The rest applies to x86 only
  #

  #
  # Checking if grub boot or DCA boot
  #
  PBE_boot_method=""
  if [ -f "${gpc_mntpt}/$MULTI_BOOT" -a -s "${gpc_mntpt}/$MULTI_BOOT" ]; then
          PBE_boot_method=GRUB
  else
          PBE_boot_method=DCA
  fi 

  # Check if multiboot GRUB based PBE has findroot
  PBE_has_findroot=""
  if [ -f "${gpc_mntpt}/${GRUB_CAP}" -a -s "${gpc_mntpt}/${GRUB_CAP}" ]; then
	 /bin/egrep "^findroot$" "${gpc_mntpt}/${GRUB_CAP}" > /dev/null 2>&1
         if [ "$?" -eq 0 ]; then
            PBE_has_findroot=yes
         fi
   fi

  ${LUPRINTF} -lp2D - "`gettext 'PBE <%s> boot method is <%s>.'`" "${gpc_beName}" "${PBE_boot_method}"

  if [ "$PBE_boot_method" = "GRUB" ]; then
      ${LUPRINTF} -lp2D - "`gettext 'Checking for GRUB binaries on PBE <%s>'`" "$gpc_beName"
      if [ ! -x "${gpc_mntpt}/${CREATE_RAMDISK}" -o ! -x "${gpc_mntpt}/${GRUB_INSTALL}" ]; then
          ${LUPRINTF} -Eelp2 "`gettext 'Missing GRUB binaries on PBE <%s>'`" "$gpc_beName"
          return 1
      fi
      ${LUPRINTF} -lp2D - "`gettext 'All GRUB binaries present on PBE <%s>'`" "$gpc_beName"
  fi

  #
  # There is no need to determine GRUB sign entry if in OOS.
  # We rely on a saved menu.lst to do fallback.
  # Also note that we cannot determine the GRUB disk during
  # OOS since lulib functions are not available
  #
  if [ -n "$gpc_oosFlag" ]; then
     return 0
  fi

  #
  # Get GRUB partition and slice
  #
  PBE_boot_sign=""
  if [ "$PBE_boot_method" = GRUB ]; then
     ${LUPRINTF} -lp1 "`gettext 'Generating boot-sign, partition and slice information for PBE <%s>'`" "$gpc_beName"
     [ -z "${gpc_mntpt}" ] && gpc_fixed_mntpt="/"
     lulib_set_bootsign "${gpc_beName}" "${gpc_fixed_mntpt}" "${gpc_tmp}"
     if [ "$?" -ne 0 -o ! -s "${gpc_tmp}" ]; then
       	${LUPRINTF} -Eelp2 "`gettext 'Cannot generate boot signature for PBE <%s>'`" "${gpc_beName}"
	/bin/rm -f "$gpc_tmp"
	return 1
     fi
     PBE_boot_sign=`/bin/cat "$gpc_tmp"`
     /bin/rm -f "$gpc_tmp"

     grub_part $PBE_boot_disk "$gpc_tmp"
     if [ "$?" -ne 0 ]; then 
       	${LUPRINTF} -Eelp2 "`gettext 'Cannot determine GRUB partition for PBE disk <%s>'`" "${PBE_root_bdev}"
	/bin/rm -f "$gpc_tmp"
	return 1
     fi
     PBE_part=`/bin/cat "$gpc_tmp"`

     grub_slice $PBE_root_bdev "$gpc_tmp"
     if [ "$?" -ne 0 ]; then 
       	${LUPRINTF} -Eelp2 "`gettext 'Cannot determine GRUB slice name for PBE disk <%s>'`" "${PBE_root_bdev}"
	/bin/rm -f "$gpc_tmp"
	return 1
     fi
     PBE_slice=`/bin/cat "$gpc_tmp"`

     /bin/rm -f "$gpc_tmp"

     ${LUPRINTF} -lp2D 5 "`gettext 'PBE GRUB partition=<%s> and slice=<%s>'`" "$PBE_part" "$PBE_slice"

  fi

  return 0
}

get_abe_config()
{
  gac_beName="$1"
  gac_resFile="/tmp/.luactivate.gac.0.$$"

  # Get the BE ID for the ABE.
  ABE_id=`${LUETCBIN}/ludo get_be_id "${gac_beName}" 2>&1`
  if [ "$?" -ne "0" -o -z "${ABE_id}" ] ; then
    [ -n "${ABE_id}" ] && ${LUPRINTF} -Eelp2 '%s' "${ABE_id}"
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'ABE <%s> BE ID is <%s>.'`" "${gac_beName}" "${ABE_id}"

  # The BE must not currently be mounted.
  lulib_verify_be_unmounted "${gac_beName}"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to activate boot environment <%s>.'`" "${gac_beName}"
    return 1
  fi

  # Get the BE block boot device for the ABE.
  forceFlag=""
  [ -n "${flag_u}" ] && forceFlag="-f"
  gac_beMntpt="`LU_OUTPUT_FORMAT=text ${LUBIN}/lumount ${forceFlag} \"${gac_beName}\" 2>${TMP_RESULT_FILE}`"
  if [ "$?" -ne "0" -o -z "${gac_beMntpt}" ] ; then
    [ -s "${TMP_RESULT_FILE}" ] && ${LUPRINTF} -elp2 '%R' < "${TMP_RESULT_FILE}"
    /bin/rm -f "${TMP_RESULT_FILE}"
    return 1
  fi
  /bin/rm -f "${TMP_RESULT_FILE}"

  ${LUPRINTF} -lp2D - "`gettext 'Mounted ABE <%s> at <%s>.'`" "${gac_beName}" "${gac_beMntpt}"

  #
  # Check if
  #	grub boot or DCA boot (on x86)
  #	ARCHIVE or NON_ARCHIVE (on SPARC)
  #
  ABE_boot_method=""
  ABE_has_findroot=""
  if [ "$LU_SYSTEM_ARCH" = "i386" ]; then
      if [ -f "${gac_beMntpt}/$MULTI_BOOT" -a -s "${gac_beMntpt}/$MULTI_BOOT" ]; then
          ABE_boot_method=GRUB
      else
          ABE_boot_method=DCA
      fi

      # Check if GRUB based ABE has findroot
      if [ -f "${gac_beMntpt}/${GRUB_CAP}" -a -s "${gac_beMntpt}/${GRUB_CAP}" ]; then
	 /bin/egrep "^findroot$" "${gac_beMntpt}/${GRUB_CAP}" > /dev/null 2>&1
         if [ "$?" -eq 0 ]; then
            ABE_has_findroot=yes
         fi
      fi

  elif [ "$LU_SYSTEM_ARCH" = sparc ]; then
     if [ -x "${gac_beMntpt}/${CREATE_RAMDISK}" ]; then
        ABE_boot_method=ARCHIVE
     else
	ABE_boot_method=NON_ARCHIVE
     fi
  fi 

  ${LUPRINTF} -lp2D - "`gettext 'ABE <%s> boot method is <%s>.'`" "${gac_beName}" "${ABE_boot_method}"

  #
  # Checking if we are on physical console. Enabling splash image
  # on serial console messes up the display of the GRUB menu - so be paranoid. 
  #
  LU_IS_PHYS_CONSOLE="no"
  if [ "$LU_SYSTEM_ARCH" = "i386" ]; then
     gac_bootenv="${gac_beMntpt}/boot/solaris/bootenv.rc"
     consprop=""
     # First check for the console property
     gac_console=`/bin/egrep "^[ 	]*setprop[ 	]+console[ 	]+" "$gac_bootenv" | /bin/awk '{print $3}'`
     gac_output=`/bin/egrep "^[ 	]*setprop[ 	]+output-device[ 	]+" "$gac_bootenv" | /bin/awk '{print $3}'`
     if [ -n "$gac_console" ]; then
	if /bin/echo "$gac_console" | /bin/egrep "^['\"]*text['\"]*" > /dev/null  2>&1; then
           LU_IS_PHYS_CONSOLE="yes"
	elif /bin/echo "$gac_console" | /bin/egrep "^['\"]*graphics['\"]*" > /dev/null 2>&1; then
           LU_IS_PHYS_CONSOLE="yes"
	fi
        consprop="$gac_console"
     elif [ -n "$gac_output" ]; then
	if /bin/echo "$gac_output" | /bin/egrep "^['\"]*screen['\"]*" > /dev/null 2>&1; then
           LU_IS_PHYS_CONSOLE="yes"
	fi
        consprop="$gac_output"
     fi

     tmpcon=""
     if [ "$LU_IS_PHYS_CONSOLE" = no -a -n "$consprop" ]; then
	if /bin/echo "$consprop" | /bin/egrep "^'" > /dev/null 2>&1; then
	   tmpcon=`/bin/echo "$consprop" | /bin/sed "s/[']*\([^']*\)[']*$/\1/g"`
	elif /bin/echo "$consprop" | /bin/egrep '^"' > /dev/null 2>&1; then
	   tmpcon=`/bin/echo "$consprop" | /bin/sed 's/["]*\([^"]*\)["]*$/\1/g'`
        elif /bin/echo "$consprop" | /bin/egrep '^[ 	]*t' > /dev/null 2>&1; then
	   tmpcon=`/bin/echo "$consprop"`
	fi
        if [ -n "$tmpcon" ]; then
           LU_CONSOLE_ARG="-B console=$tmpcon"
           export LU_CONSOLE_ARG
           ${LUPRINTF} -lp1 "`gettext 'Setting failsafe console to <%s>.'`" "${tmpcon}"
	else
          ${LUPRINTF} -Eelp2 "`gettext 'Error parsing console property in ABE <%s> /boot/solaris/bootenv.rc'`" "$gac_beName"
        fi
     fi
  fi

  #
  # If ABE_boot_method value is GRUB, implies an x86 system
  #
  if [ "$ABE_boot_method" = "GRUB" ]; then
      ${LUPRINTF} -lp2D - "`gettext 'Checking for GRUB binaries on ABE <%s>'`" "$gac_beName"
      if [ ! -x "${gac_beMntpt}/${CREATE_RAMDISK}" -o ! -x "${gac_beMntpt}/${GRUB_INSTALL}" ]; then
          ${LUPRINTF} -Eelp2 "`gettext 'Missing GRUB binaries on ABE <%s>'`" "$gac_beName"
          ${LUBIN}/luumount -f $gac_beName 2>/dev/null
          return 1
      fi
      ${LUPRINTF} -lp2D - "`gettext 'All GRUB binaries found on ABE.'`"
  fi

  ABE_boot_sign=""
  if [ "$ABE_boot_method" = "GRUB" ]; then
     ${LUPRINTF} -lp1 "`gettext 'Generating boot-sign for ABE <%s>'`" "$gac_beName"
     lulib_set_bootsign "${gac_beName}" "${gac_beMntpt}" "${gac_resFile}"
     if [ "$?" -ne 0 -o ! -s "$gac_resFile" ]; then
       	${LUPRINTF} -Eelp2 "`gettext 'Cannot generate boot signature for ABE <%s>'`" "${gac_beName}"
        ${LUBIN}/luumount -f "$gac_beName" 2>/dev/null
        /bin/rm -f "$gac_resFile"
	return 1
     fi
     ABE_boot_sign=`/bin/cat "$gac_resFile"`
     /bin/rm -f "$gac_resFile"
  fi

  # Get the BE physical block boot device for the ABE, and get the
  # logical BE block boot device for the ABE (that is, it may contain a
  # meta device name).

  ABE_root_bdev="`${LUETCBIN}/lubootdevice -m \"${gac_beMntpt}\"`"
  ret="$?"
  if [ "${ret}" -eq "0" ] ; then
    ABE_root_logical_bdev="`${LUETCBIN}/lurootspec -m \"${gac_beMntpt}\"`"
    ret="$?"
  fi

  # Get the BE character boot device for the ABE.
  ABE_root_cdev="`lulib_get_cdevice $ABE_root_bdev`"
  if [ "$?" -ne "0" -o -z "${ABE_root_cdev}" ] ; then
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'ABE <%s> BE root character device is <%s>.'`" "${gac_beName}" "${ABE_root_cdev}"

  # Get the BE character boot device file system type for the ABE.
  ABE_root_fstyp="`lulib_fstyp $ABE_root_cdev 2>/dev/null`"
  if [ "$?" -ne "0" -o -z "${ABE_root_fstyp}" ] ; then
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'ABE <%s> BE root character device fstype is <%s>.'`" "${gac_beName}" "${ABE_root_fstyp}"

  ${LUBIN}/luumount -f $gac_beName 2>/dev/null
  if [ $? -ne 0 ]; then
      ${LUPRINTF} -Eelp2 "`gettext 'Failed to unmount boot environment <%s>'`" "${gac_beName}"
      return 1
  fi

  # reset the mountpoints (lumount/luumount modifies them)
  if [ "$ABE_root_fstyp" = zfs ]; then
      /sbin/zfs list -t filesystem -Ho name,mountpoint -r $ABE_root_logical_bdev | awk '$2!="legacy" {print $1}'|
          while read ds_name; do
              /sbin/zfs inherit mountpoint "$ds_name"
          done

     /sbin/zfs set mountpoint=/ $ABE_root_logical_bdev
  fi

  if [ "${ret}" -ne "0" -o -z "${ABE_root_bdev}" -o -z "${ABE_root_logical_bdev}" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Cannot determine root device for ABE <%s>'`" "${gac_beName}"
    return 1
  fi
 
  ${LUPRINTF} -lp2D - "`gettext 'ABE <%s> root block device is <%s>.'`" "${gac_beName}" "${ABE_root_bdev}"

  ${LUPRINTF} -lp2D - "`gettext 'ABE <%s> logical root block device is <%s>.'`" "${gac_beName}" "${ABE_root_logical_bdev}"


  # Get the BE boot character device entire disk access slice for the ABE.  
  ABE_boot_disk="`echo $ABE_root_cdev| sed 's/s[^s]*$/s2/g'`"
  if [ "$?" -ne "0" -o -z "${ABE_boot_disk}" ] ; then
    return 1
  fi
  ${LUPRINTF} -lp2D - "`gettext 'ABE <%s> BE root character device entire disk access slice is <%s>.'`" "${gac_beName}" "${ABE_boot_disk}"

  ABE_root_slice="`echo $ABE_root_cdev| sed 's/.*s\([^s]*\)/\1/g'`"
  if [ $? != 0 ] ; then
    return 1
  fi
  
  case $ABE_root_slice in
    a)	ABE_root_slice=10;;
    b)	ABE_root_slice=11;;
    c)	ABE_root_slice=12;;
    d)	ABE_root_slice=13;;
    e)	ABE_root_slice=14;;
    f)	ABE_root_slice=15;;
  esac

  ${LUPRINTF} -lp2D - "`gettext 'ABE <%s> root slice is <%s>.'`" "${gac_beName}" "${ABE_root_slice}"

  # Now check if the ABE-Root slice is not mounted and is mountable.
  
  chk_mount $ABE_root_logical_bdev $ABE_root_fstyp "${gac_beName}"
  if [ $? -ne 0 ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'ABE <%s> root slice <%s> is not available.'`" "${gac_beName}" "${ABE_root_logical_bdev}"
    return 1
  fi

  ${LUPRINTF} -lp2D - "`gettext 'ABE: not mounted and mountable.'`"

  # A GRUB ABE_boot_method implies x86
  if [ "$ABE_boot_method" = GRUB ]; then

     #
     # Get GRUB partition and slice
     #
     ${LUPRINTF} -lp1 "`gettext 'Generating partition and slice information for ABE <%s>'`" "$gac_beName"

     grub_part $ABE_boot_disk "$gac_resFile"
     if [ "$?" -ne 0 ]; then
        ${LUPRINTF} -Eelp2 "`gettext 'Cannot determine GRUB partition number for ABE <%s>'`" "$gac_beName"
        /bin/rm -f "$gac_resFile"
        return 1
     fi
     ABE_part=`/bin/cat "$gac_resFile"`

     grub_slice $ABE_root_bdev "$gac_resFile"
     if [ "$?" -ne 0 ]; then
        ${LUPRINTF} -Eelp2 "`gettext 'Cannot determine GRUB slice name for ABE <%s>'`" "$gac_beName"
        /bin/rm -f "$gac_resFile"
        return 1
     fi
     ABE_slice=`/bin/cat "$gac_resFile"`

     /bin/rm -f "$gac_resFile"

     ${LUPRINTF} -lp2D - "`gettext 'ABE GRUB partition=<%s> and slice=<%s>.'`" "${ABE_part}" "${ABE_slice}"
  fi

  return 0
}

get_be_vtoc()
{
  gbv_beId="$1"
  gbv_beBootDisk="$2"

  ${LUPRINTF} -lp2D - "`gettext 'Getting the vtoc for disk <%s> BE ID <%d>.'`" "${gbv_beBootDisk}" "${gbv_beId}"

  /usr/sbin/prtvtoc -h $gbv_beBootDisk | awk ' { print $1,$2,$3,$4,$5 } ' > /etc/lu/vtoc.$gbv_beId
  if [ $? != 0 ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to obtain vtoc from <%s> for boot environment <%s>.'`" "${gbv_beBootDisk}" "${gbv_beId}"
      exit 2
  fi
}

edit_be_vtoc()
{
  ebv_beId="$1"
  ebv_beRootSlice="$2"
  ebv_tmpVtoc="/tmp/.luactivate.vtoc.$$"
  
  ${LUPRINTF} -lp2D - "`gettext 'Editing the vtoc ROOT tag information for slice <%s> BE ID <%d>.'`" "${ebv_beRootSlice}" "${ebv_beId}"
    
  # Change the existing ROOT tags to 0.
  # ROOT must be read/write so assume 00 in flag field
  awk ' { if ( $2 == "2" ) printf "%s 0 %s %s %s\n",$1,$3,$4,$5
	      else printf "%s %s %s %s %s\n",$1,$2,$3,$4,$5
	      } ' /etc/lu/vtoc.$ebv_beId > $ebv_tmpVtoc 

  # Tag of the slice $ebv_beRootSlice needs to be changed to 0x2
  sed 's/^\([ 	]*'$ebv_beRootSlice'[ 	][ 	]*\)[^ 	]*\(.*\)$/\12\2/g' $ebv_tmpVtoc > /etc/lu/vtoc.$ebv_beId

  /bin/rm -f $ebv_tmpVtoc
}

write_be_vtoc()
{
  wbv_beId="$1"
  wbv_beBootDisk="$2"
  wbv_beName="$3"
  wbv_currBeName="$4"
  wbv_doNotDelay="$5"

  if [ -z "${wbv_doNotDelay}" ] ; then
    # Delay: add proper boot environment changes to delayed update script.
    ${LUPRINTF} -lp2D - "`gettext 'Storing new vtoc information to device <%s> for BE ID <%d> BE <%s> for activate delay update script.'`" "${wbv_beBootDisk}" "${wbv_beId}" "${wbv_beName}"
    /bin/cp /etc/lu/vtoc.$wbv_beId $DELAY_UPD_DIR/vtoc.$wbv_beId.$$
    # Before writing vtoc, verify that the BE can be mounted

    ${LUPRINTF} -lp2D - "`gettext 'Adding boot device vtoc update from BE <%s> to BE ID <%d> BE <%s>.'`" "${wbv_currBeName}" "${wbv_beId}" "${wbv_beName}"

	/bin/cat <<-EOF >> ${DELAY_UPD_SCRIPT}
		#
		# Update vtoc on the boot environment "${wbv_beName}"
		#
		\${LUPRINTF} +X -fl1D - "`gettext 'Live Upgrade: Updating partition ID tag on boot environment <%s> device <%s> to be root slice.'`" "${wbv_beName}" "${wbv_beBootDisk}"
	EOF

    if [ "${wbv_currBeName}" != "${wbv_beName}" ] ; then
	/bin/cat <<-EOF >> ${DELAY_UPD_SCRIPT}
		#
		# Remove root from "${wbv_currBeName}" set root on "${wbv_beName}"
		#
		if [ ! -s "$DELAY_UPD_DIR/vtoc.$wbv_beId.$$" ] ; then
		    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: New vtoc contents file <%s> missing: the activation is aborted.'`" "$DELAY_UPD_DIR/vtoc.$wbv_beId.$$"
		    exit 1
		fi
		if [ ! -s "/etc/lu/ICF.$wbv_beId" ] ; then
		    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Internal Configuration File <%s> missing: the activation is aborted.'`" "/etc/lu/ICF.$wbv_beId"
		    exit 1
		fi
		BE_MOUNT="\`LU_OUTPUT_FORMAT=text ${LUBIN}/lumount -Zi /etc/lu/ICF.$wbv_beId 2> /dev/null\`"
		if [ "\$?" -ne "0" ] ; then
		    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to mount boot environment <%s>: the activation is aborted.'`" "${wbv_beName}"
		    exit 1
		fi
		${LUBIN}/luumount -f -i /etc/lu/ICF.$wbv_beId
	EOF
    fi

	/bin/cat <<-EOF >> ${DELAY_UPD_SCRIPT}
		#
		# Revise vtoc on "${wbv_beBootDisk}"
		#
		/bin/cp /dev/null /tmp/.lu_fmthard_res.$$
		/usr/sbin/fmthard -s $DELAY_UPD_DIR/vtoc.$wbv_beId.$$ $wbv_beBootDisk 2>>/tmp/.lu_fmthard_res.$$ 1>&2
		if [ "\$?" -ne "0" ] ; then
		    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to write the vtoc for boot environment <%s> to device <%s>.'`" "${wbv_beName}" "${wbv_beBootDisk}"
		    /bin/cat /tmp/.lu_fmthard_res.$$
		    /bin/rm -f /tmp/.lu_fmthard_res.$$
		    exit 1
		fi
		/bin/rm -f $DELAY_UPD_DIR/vtoc.$wbv_beId.$$
		/bin/rm -f /tmp/.lu_fmthard_res.$$
	EOF

  else
    # Neither delayed update nor oos servicing - apply boot environment changes now.
    ${LUPRINTF} -lp2D - "`gettext 'Updating partition ID tag on boot environment <%s> device <%s> to be root slice.'`" "${wbv_beName}" "${wbv_beBootDisk}"
    /bin/cp /dev/null /tmp/.lu_fmthard_res.$$
    /usr/sbin/fmthard -s /etc/lu/vtoc.$wbv_beId $wbv_beBootDisk >/dev/null 2>>/tmp/.lu_fmthard_res.$$ 1>&2
    if [ $? != 0 ] ; then
      ${LUPRINTF} -Eelp2 "`gettext 'Unable to write vtoc to device <%s> boot environment ID <%d> BE <%s>.'`" "${wbv_beBootDisk}" "${wbv_beId}" "${wbv_beName}"
      /bin/cat /tmp/.lu_fmthard_res.$$
      /bin/rm -f /tmp/.lu_fmthard_res.$$
      exit 1
    fi
    /bin/rm -f /tmp/.lu_fmthard_res.$$
  fi
}

write_loader()
{
  wld_bootDisk="$1"
  wld_doNotDelay="$2"
  wld_beName="$3"
  wld_currBeName="$4"

  wld_tmp_file="/tmp/.luactivate.wld.$$"
  wld_mirror_config=""

  ${LUPRINTF} -lp2D - "`gettext 'Storing new loader information to device <%s> BE <%s> for activate delay update script.'`" "${wld_bootDisk}" "${wld_beName}"

  # the zfs bootblk is larger, so if we're using installboot we need a -F
  additional_installboot_option=""
  if [ "$ABE_root_fstyp" = "zfs" ]; then
	additional_installboot_option="-F zfs"
	wld_pname=`echo "$ABE_root_logical_bdev" | /bin/cut -d/ -f1`
	wld_mirror_config=`/usr/bin/env LC_ALL=C /sbin/zpool status $wld_pname | /bin/grep -n mirror | cut -d: -f1`
  fi

  fake_boot="`echo $wld_bootDisk | sed 's/\/dsk\//\/rdsk\//g'`"
  if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
    final_boot="$fake_boot"
  fi
  if [ "${LU_SYSTEM_ARCH}" = "i386" -o "${LU_SYSTEM_ARCH}" = "ppc" ] ; then
    final_boot="`echo $fake_boot | sed 's/s.$/s2/g'`"
  fi
  
  if [ -z "${wld_doNotDelay}" ] ; then
    # Delay: add proper boot environment changes to delayed update script.
    if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
      if [ "$wld_currBeName" != "$wld_beName" ] ; then
	BE_ID="`${LUETCBIN}/ludo get_be_id \"$wld_beName\" 2>&1`"
	if [ $? != 0 ] ; then
	  [ -n "${BE_ID}" ] && ${LUPRINTF} -Eelp2 '%s' "${BE_ID}"
	  ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine boot environment ID for target boot environment <%s>.'`" "${wld_beName}"
	  return 1
	fi

	${LUPRINTF} -lp2D - "`gettext 'Adding sparc boot loader update from BE <%s> to BE <%s> device <%s>.'`" "${wld_currBeName}" "${wld_beName}" "${wld_bootDisk}"

	/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
		#
		# Switching boot environments on sparc platform: write new bootstrap to disk bootblock
		#
		\${LUPRINTF} +X -fl1D - "`gettext 'Live Upgrade: Updating boot loader for <%s> on boot environment <%s> device <%s> to match OS release.'`" "${LU_HARDWARE_IMPLEMENTATION}" "${wld_beName}" "${final_boot}"
		BE_MOUNT="\`LU_OUTPUT_FORMAT=text ${LUBIN}/lumount -Zi /etc/lu/ICF.$BE_ID 2> /dev/null\`"
		if [ "\$?" != "0" ] ; then
		    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to mount boot environment <%s>: the activation is aborted.'`" "${wld_beName}"
		    exit 1
		fi
	EOF

	if [ "$ABE_root_fstyp" = "zfs" -a -n "$wld_mirror_config" ]; then
		wld_mirror_config=`expr $wld_mirror_config + 1`

	/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
		# zfs pool is a mirror; loop over each entry
		# note that 'NF > 1' in the nawk line will allow us to
		# installboot spares as well
		/usr/bin/env LC_ALL=C /sbin/zpool status $wld_pname | /bin/tail +$wld_mirror_config |
		/bin/sed '/^$/q' | 
		/bin/nawk 'NF > 1 {print "/dev/rdsk/" \$1 }' |
		while read diskname; do
		    \$BE_MOUNT/usr/sbin/installboot -F zfs \$BE_MOUNT/usr/platform/${LU_HARDWARE_IMPLEMENTATION}/lib/fs/${ABE_root_fstyp}/bootblk \$diskname
		done
		    
	EOF
	else
	/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
		\$BE_MOUNT/usr/sbin/installboot $additional_installboot_option \$BE_MOUNT/usr/platform/${LU_HARDWARE_IMPLEMENTATION}/lib/fs/${ABE_root_fstyp}/bootblk ${final_boot}
		if [ "\$?" != "0" ] ; then
		    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to update boot loader for boot environment <%s> on device <%s>: the activation is aborted.'`" "${wld_beName}" "${final_boot}"
		    exit 1
		fi
	EOF
	fi

	if [ "$ABE_boot_method" = ARCHIVE ]; then

		#
		# If ARCHIVE based boot, create the boot archive
		#
		/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT


			\${BE_MOUNT}/${CREATE_RAMDISK} -R "\${BE_MOUNT}"
			if [ "\$?" != "0" ] ; then
		    	   \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to create boot_archive for boot environment <%s> on device <%s>: the activation is aborted.'`" "${wld_beName}" "${final_boot}"
		    	    exit 1
			fi
		EOF
	fi

	/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
		${LUBIN}/luumount -f -i /etc/lu/ICF.$BE_ID
	EOF
      fi

	/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
		\${LUPRINTF} +X -fl1 "`gettext 'Live Upgrade: The boot device for boot environment <%s> is <%s>.'`" "${wld_beName}" "$wld_bootDisk"
	EOF

    fi

    if [ "${LU_SYSTEM_ARCH}" = "i386" ] ; then

      ${LUPRINTF} -lp2D - "`gettext 'Adding i386 boot loader update from BE <%s> to BE <%s> device <%s>.'`" "${wld_currBeName}" "${wld_beName}" "${wld_bootDisk}"

      if [ "$wld_beName" != "$wld_currBeName" ] ; then
	BE_ID="`${LUETCBIN}/ludo get_be_id \"$wld_beName\" 2>&1`"
	if [ $? != 0 ] ; then
	    [ -n "${BE_ID}" ] && ${LUPRINTF} -Eelp2 '%s' "${BE_ID}"
	    ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine boot environment ID for target boot environment <%s>.'`" "${wld_beName}"
	    return 1
	fi

	/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
		#
		# Update boot loader for "${wld_beName}" on "${final_boot}"
		#
		\${LUPRINTF} +X -fl1D - "`gettext 'Live Upgrade: Updating boot loader for <%s> on boot environment <%s> device <%s> to match OS release.'`" "${LU_HARDWARE_IMPLEMENTATION}" "${wld_beName}" "${final_boot}"
		BE_MOUNT="\`LU_OUTPUT_FORMAT=text ${LUBIN}/lumount -Zi /etc/lu/ICF.$BE_ID 2> /dev/null\`"
		if [ "\$?" != "0" ] ; then
		    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to mount boot environment <%s>: the activation is aborted.'`" "${wld_beName}"
		    exit 1
		fi
		# on x86 ZFS boot code never comes here
		\$BE_MOUNT/usr/sbin/installboot \$BE_MOUNT/usr/platform/${LU_HARDWARE_IMPLEMENTATION}/lib/fs/${ABE_root_fstyp}/pboot \$BE_MOUNT/usr/platform/${LU_HARDWARE_IMPLEMENTATION}/lib/fs/${ABE_root_fstyp}/bootblk ${final_boot}
		if [ "\$?" != "0" ] ; then
		    \${LUPRINTF} +X -fEel2 "`gettext 'Live Upgrade: Unable to update boot loader for boot environment <%s> on device <%s>: the activation is aborted.'`" "${wld_beName}" "${final_boot}"
		    exit 1
		fi

		${LUBIN}/luumount -f -i /etc/lu/ICF.$BE_ID
	EOF
      fi
	/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
		\${LUPRINTF} +X -fl1 "`gettext 'Live Upgrade: The boot device for boot environment <%s> is <%s>.'`" "${wld_beName}" "$wld_bootDisk"
	EOF
    fi

  else
    # This function is not called in the context of oos servicing. We handled the delay update case above.
    # This case deals with "flag_u" (called in the context of lucreate)
    ${LUPRINTF} -lp2D - "`gettext 'Updating boot loader for <%s> on boot environment <%s> device <%s> to match OS release.'`" "${LU_HARDWARE_IMPLEMENTATION}" "${wld_beName}" "${wld_bootDisk}"
    if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
      final_boot="$fake_boot"
      if [ "$wld_currBeName" != "$wld_beName" ] ; then
	BE_ID=`${LUETCBIN}/ludo get_be_id "$wld_beName" 2>&1`
	if [ $? != 0 ] ; then
	  [ -n "${BE_ID}" ] && ${LUPRINTF} -Eelp2 '%s' "${BE_ID}"
	  ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine boot environment ID for target boot environment <%s>.'`" "${wld_beName}"
          return 1
	fi

	BE_MOUNT="`LU_OUTPUT_FORMAT=text ${LUBIN}/lumount -i /etc/lu/ICF.$BE_ID 2>${TMP_RESULT_FILE}`"
	if [ $? != 0 ] ; then
	  [ -s "${TMP_RESULT_FILE}" ] && ${LUPRINTF} -elp2 '%R' < "${TMP_RESULT_FILE}"
	  ${LUPRINTF} -Eelp2 "`gettext 'Unable to mount boot environment <%s>.'`" "${wld_beName}"
	  /bin/rm -f "${TMP_RESULT_FILE}"
          return 1
	fi
	/bin/rm -f "${TMP_RESULT_FILE}"

	ERRMSG="`$BE_MOUNT/usr/sbin/installboot $additional_installboot_option $BE_MOUNT/usr/platform/${LU_HARDWARE_IMPLEMENTATION}/lib/fs/${ABE_root_fstyp}/bootblk ${final_boot} 2>&1`"
	if [ $? != 0 ] ; then
	  [ -n "${ERRMSG}" ] && ${LUPRINTF} -Eelp2 '%s' "${ERRMSG}"
	  ${LUPRINTF} -Eelp2 "`gettext 'Unable to update boot loader for boot environment <%s> on device <%s>.'`" "${wld_beName}" "${final_boot}"
          return 1
	fi
	if [ "$ABE_boot_method" = ARCHIVE ]; then
	   ${BE_MOUNT}/${CREATE_RAMDISK} -R ${BE_MOUNT} 2>&1
	   if [ $? != 0 ]; then
	      ${LUPRINTF} -Eelp2 "`gettext 'Unable to create boot_archive for boot environment <%s> on device <%s>.'`" "${wld_beName}" "${final_boot}"
              return 1
	   fi
	fi
	${LUBIN}/luumount -f -i /etc/lu/ICF.$BE_ID
      fi
    fi

  fi
  return 0
}

propagate_be_file()
{
  pbf_fileName="$1"

  ${LUPRINTF} -lp2D - "`gettext 'Propagating the file <%s> to all BEs.'`" "${pbf_fileName}"
  # Call luupdall to propagate the file to all BEs.
  ${LUBIN}/luupdall "${pbf_fileName}"
  if [ $? != 0 ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to propagate the file <%s> to all boot environments.'`" "${pbf_fileName}"
    return 1
  fi
  return 0
}

find_be_mntpt()
{
    foundAnswer=""
    /usr/sbin/mount | /bin/awk '{ print $1, $3}' | while read mntpt bdevice ; do
    if [ -z "${foundAnswer}" -a -f "$mntpt/etc/lu/.CURR_VARS" -a -s "$mntpt/etc/lu/.CURR_VARS" ] ; then
    .  "$mntpt/etc/lu/.CURR_VARS"
    if [ "${BEROOT}" = "${bdevice}" ] ; then
    #Parent BE to fallback found
    gpc_mntpt="$mntpt"
    PBE_root_bdev="`${LUETCBIN}/lubootdevice -m \"${gpc_mntpt}\"`"
    ABE_m="`ls -l $bdevice | /bin/sed 's/.*\/devices\//\//g' | sed 's/:.$//g'`"
    PBE_m="`ls -l $PBE_root_bdev | /bin/sed 's/.*\/devices\//\//g' | sed 's/:.$//g'`"
    if [ "$ABE_m" = "$PBE_m" ] ; then
    echo "${mntpt}:$bdevice"
    foundAnswer="yes"
     break
    fi
   fi 
  fi
  done
}

# 
# Mount the GRUB slice (if not already mounted). If the GRUB slice
# has a boot partition mounted off it, unmount the boot partition.
# Note: Don't use the -f flag while umounting boot partition, it
#       will fail (pcfs doesn't support forced unmounts).
#
# Arguments
#	$1 - The *char* logical name for the GRUB slice (may be a /dev/md name)
#	$2 - Name of the results file
#	$3 - A string that indicates if in oos mode (OOS) or not (NOT_OOS)
# Returns
#	1 - on error
#	0 - on success
#	state for unmount_boot_slice() in results file specified in $2
#
mount_boot_slice()
{
      if [ "$#" -ne 3 -o -z "$1" -o -z "$2" -o -z "$3" ]; then
	 ${LUPRINTF} "`gettext 'ERROR: mount_boot_slice(): Invalid arguments.'`"
	 return 1
      fi

      mbs_boot="$1"
      mbs_res="$2"
      mbs_oos="$3"

      mbs_tmp="/tmp/.luactivate.mbs.1.$$"
      mbs_mnted=""
      mbs_mnt=""
      mbs_umnted=""
      mbs_dev=""
      mbs_real=""


      #
      # First mount the boot slice.
      # Boot slice is a /dev path
      #
      mbs_chr="$mbs_boot"
      mbs_boot=`/bin/echo "$mbs_boot" | /bin/sed "s/\/rdsk\//\/dsk\//g"`
      if [ "$?" -ne 0 -o -z "$mbs_boot" ]; then
	 ${LUPRINTF} "`gettext 'ERROR: Cannot determine block device for <%s>.'`" "${mbs_boot}"
	 /usr/bin/rm -f "$mbs_res"
         return 1
      fi

      #
      # mbs_boot could be in the form cXtYdZp0:boot. Change
      # this into the "real" fdisk partition since fstyp doesn't
      # understand the p0:boot name.
      # get_real_boot_partition() only accepts a char device
      # and may be called in OOS mode.
      #
      /bin/echo "$mbs_chr" | /bin/egrep "p0:boot$" > /dev/null 2>&1 
      if [ "$?" -eq 0 ]; then
         get_real_boot_partition "$mbs_chr" "$mbs_tmp"
         if [ "$?" -ne 0 ]; then
	    ${LUPRINTF} "`gettext 'ERROR: Cannot determine real boot partition for <%s>.'`" "${mbs_boot}"
	    /bin/rm -f "$mbs_res" "$mbs_tmp"
	    return 1
         fi
         mbs_real=`/bin/cat "$mbs_tmp"`
      else
         mbs_real="$mbs_chr"
      fi

      /bin/rm -f "$mbs_tmp"

      if [ -z "$mbs_real" ]; then
	 ${LUPRINTF} "`gettext 'ERROR: Cannot determine real boot partition for <%s>.'`" "${mbs_boot}"
	 /usr/bin/rm -f "$mbs_res"
	 return 1
      fi

      #
      # Maybe called during OOS administration, so check if oos
      # If in OOS mode, don't use lulib functions
      #
      if [ "$mbs_oos" = OOS ]; then
         mbs_fs=`/usr/sbin/fstyp $mbs_real`
      else
         mbs_fs=`lulib_fstyp $mbs_real`
      fi
      if [ "$?" -ne 0 -o -z "$mbs_fs" ]; then
	 ${LUPRINTF} "`gettext 'ERROR: Cannot determine fstype for <%s>.'`" "${mbs_boot}"
	 /usr/bin/rm -f "$mbs_res"
         return 1
      fi

      # Strip off duplicate and trailing /
      if [ "$mbs_boot" != / ]; then
         mbs_boot=`/bin/echo "$mbs_boot" | /bin/sed "s://[/]*:/:g" | /bin/sed "s:/$::g"`
      fi

      #
      # Now check if mbs_boot is already mounted.
      # mbs_boot is a /dev path
      #
      if [ "$mbs_fs" = "zfs" ]; then
          mbs_pname=`lulib_get_pool_from_slice "${mbs_boot}"`
	  if [ $? != 0 ]; then
	    ${LUPRINTF} "`gettext 'ERROR: Cannot determine pool name from slice <%s>.'`" "${mbs_boot}"
	    return 1
	  fi
	  lulib_dataset_mounted "${mbs_pname}"
	  if [ $? = 0 ]; then
	      /sbin/zfs mount "${mbs_pname}"
	      if [ $? != 0 ]; then
	        ${LUPRINTF} "`gettext 'ERROR: Cannot mount pool dataset <%s>.'`" "${mbs_boot}"
	        return 1
	      fi
	  fi
	  mbs_mnt=`/sbin/zfs get -Ho value mountpoint "${mbs_pname}"`
      else
          mbs_mnted=""
          mbs_mnt=`/sbin/mount | /bin/nawk -v dev=$mbs_boot ' { if ($3 == dev) {printf("%s\n", $1); exit 6;}}'`
          if [ "$?" -ne 6 ]; then
	     /usr/bin/mkdir -p "$mbs_tmp" 
	     fsmount "$mbs_fs" "$mbs_boot" "$mbs_tmp" > /dev/null 2>&1
             if [ "$?" -ne 0 ]; then
	        /usr/bin/rmdir "$mbs_tmp"
	        ${LUPRINTF} "`gettext 'ERROR: Cannot mount <%s>.'`" "${mbs_boot}"
	        /usr/bin/rm -f "$mbs_res"
	        return 1
	     fi
             mbs_mnted=1
             mbs_mnt="$mbs_tmp"
          else
             # Strip off duplicate and trailing /
             if [ "$mbs_mnt" != / ]; then
	        mbs_mnt=`echo $mbs_mnt | /usr/bin/sed 's://[/]*:/:g' | /usr/bin/sed 's:/$::g'` 
	     fi
             if [ "$mbs_mnt" = / ]; then
	        mbs_dev=`/usr/sbin/mount | /usr/bin/nawk -v mnt=/boot ' { if ($1 == mnt) {printf("%s\n", $3); exit 7;}}'`
             else
	        mbs_dev=`/usr/sbin/mount | /usr/bin/nawk -v mnt=${mbs_mnt}/boot ' { if ($1 == mnt) {printf("%s\n", $3); exit 7;}}'`
             fi
             if [ "$?" -eq 7 ]; then
	        #
	        # pcfs does not support forced unmount. So just do a plain umount
	        #
	        /usr/sbin/umount "${mbs_mnt}/boot" > /dev/null 2>&1
	        if [ "$?" -ne 0 ]; then
	           ${LUPRINTF} "`gettext 'ERROR: Cannot umount <%s>.'`" "${mbs_mnt}/boot"
	           /usr/bin/rm -f "$mbs_res"
	           return 1
                fi
	        mbs_umnted=1
	        if [ "$mbs_oos" != OOS ]; then
                   ${LUPRINTF} -lp2D - "`gettext 'Unmounted boot partition at <%s>'`" "${mbs_mnt}/boot"
	        fi
	     fi
           fi
       fi

       echo "${mbs_mnted}=${mbs_mnt}=${mbs_umnted}=${mbs_dev}" > "$mbs_res"

       return 0
}

#
# Given the output from a prior mount_boot_slice() call
# unmounts the GRUB slice (if it was mounted in mount_boot_slice()
# and mounts the boot partition (if it was unmounted in mount_boot_slice()
#
# Arguments
#	$1  - state from a prior mount_boot_slice()
#	$2  - indicates if invoked during oos (OOS) or not (NOT_OOS)
# Returns
#	Nothing
#
umount_boot_slice()
{

   if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
      ${LUPRINTF} "`gettext 'ERROR: umount_boot_slice: Invalid arguments.'`"
      return
   fi

   ubs_mnted=`echo $1 | cut -d'=' -f 1`
   ubs_mnt=`echo $1 | cut -d'=' -f 2`
   ubs_umnted=`echo $1 | cut -d'=' -f 3`
   ubs_dev=`echo $1 | cut -d'=' -f 4`

   ubs_oos="$2"

  if [ -n "$ubs_mnted" ]; then
     lulib_unmount_pathname "$ubs_mnt" > /dev/null 2>&1
     /usr/bin/rmdir "$ubs_mnt"
     return
  elif [ -n "$ubs_umnted" ]; then
     /usr/sbin/mount -F pcfs "$ubs_dev" "$ubs_mnt"/boot > /dev/null 2>&1
     if [ "$?" -ne 0 ]; then
	${LUPRINTF} "`gettext 'ERROR: Cannot mount boot partition <%s> at <%s>.'`" "$ubs_dev" "${ubs_mnt}/boot"
     elif [ "$ubs_oos" != OOS ]; then
        ${LUPRINTF} -lp2D - "`gettext 'Remounted boot partition at <%s>'`" "${ubs_mnt}/boot"
     fi
  fi

}

#
# This function is called to mount a legacy top dataset in a pool
#
# fb_mount_legacy_top_dataset
# Arguments:
#	$1	pool name
#	$2	State file
#
# Returns:
#	0	Legacy top dataset mounted
#	1	A fatal error occurred
#
# Local Prefix:  fbld
#
fb_mount_legacy_top_dataset()
{
   fbld_tmpmnt="/tmp/.luactivate.fbld.tmp.$$"

   if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Invalid arguments. Usage: fb_mount_legacy_top_dataset <pool-name> <state-file>.'`"
      return 1
   fi

   fbld_pool="$1"
   fbld_state="$2"

   /bin/rm -f "$fbld_state"

   # Is a legacy dataset
   /bin/echo "LEGACY=YES" > "$fbld_state"

   # First check if mounted
   fbld_mounted=`/sbin/zfs get -Ho value mounted "$fbld_pool"`
   if [ "$?" -ne 0 -o -z "$fbld_mounted" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Cannot determine if pool <%s> has legacy top dataset mounted.'`" "$fbld_pool"
      /bin/rm -f "$fbld_state"
      return 1
   fi

   # Mount the dataset if not already mounted
   if [ "$fbld_mounted" = no ]; then
      /bin/mkdir -p "$fbld_tmpmnt"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} "`gettext 'ERROR: Unable to create mountpoint for legacy top dataset in pool <%s>.'`" "$fbld_pool"
         /bin/rm -f "$fbld_state"
	 return 1
      fi
      /sbin/mount -F zfs "$fbld_pool" "$fbld_tmpmnt"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} "`gettext 'ERROR: Unable to mount legacy top dataset in pool <%s>.'`" "$fbld_pool"
         /bin/rm -f "$fbld_state"
	 /bin/rmdir "$fbld_tmpmnt"
	 return 1
      fi
      /bin/echo "MOUNTED=YES" >> "$fbld_state"
      /bin/echo "MOUNTPOINT=$fbld_tmpmnt" >> "$fbld_state"
      return 0
   fi

   /bin/echo "MOUNTED=NO" >> "$fbld_state"

   # Legacy dataset already mounted. Get mountpoint
   fbld_mntpt=`/bin/cat /etc/mnttab | /bin/nawk -v POOL=$fbld_pool '$1 == POOL && $3 == "zfs" {print $2; exit 26}'`
   if [ "$?" -ne 26 -o -z "$fbld_mntpt" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Unable to get mountpoint for legacy top dataset in pool <%s>'`" "$fbld_pool"
      /bin/rm -f "$fbld_state"
      return 1
   fi

   /bin/echo "MOUNTPOINT=$fbld_mntpt" >> "$fbld_state"

   return 0
}

#
# This function is called to mount the top dataset in a pool during fallback
#
# Arguments:
#	$1	pool name
#	$2	State file
#
# Returns:
#	0	Top dataset mounted
#	1	A fatal error occurred
#
# Local Prefix:  fbmd
#
fb_mount_top_dataset()
{
   if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Invalid arguments. Usage: fb_mount_top_dataset <pool> <state-file>.'`"
      return 1
   fi

   fbmd_pool="$1"
   fbmd_state="$2"

   /bin/rm -f "$fbmd_state"

   # first check if this is a legacy dataset
   fbmd_legacy=`/sbin/zfs get -Ho value mountpoint "$fbmd_pool"`
   if [ "$?" -ne 0 -o -z "$fbmd_legacy" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Cannot check if pool <%s> has legacy dataset.'`" "$fbmd_pool"
      return 1
   fi

   if [ "$fbmd_legacy" = legacy ]; then
      fb_mount_legacy_top_dataset "$fbmd_pool" "$fbmd_state"
      return "$?"
   fi

   # Not a legacy dataset
   /bin/echo "LEGACY=NO" > "$fbmd_state"

   # First check if mounted
   fbmd_mounted=`/sbin/zfs get -Ho value mounted "$fbmd_pool"`
   if [ "$?" -ne 0 -o -z "$fbmd_mounted" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Cannot determine if pool <%s> is mounted.'`" "$fbmd_pool"
      /bin/rm -f "$fbmd_state"
      return 1
   fi

   # Mount the dataset if not already mounted
   if [ "$fbmd_mounted" = no ]; then
      /sbin/zfs mount "$fbmd_pool"
      if [ "$?" -ne 0 ]; then
      ${LUPRINTF} "`gettext 'ERROR: Unable to mount top dataset in pool <%s>.'`" "$fbmd_pool"
         /bin/rm -f "$fbmd_state"
	 return 1
      fi
      /bin/echo "MOUNTED=YES" >> "$fbmd_state"
      fbmd_mounted=yes
   else
      /bin/echo "MOUNTED=NO" >> "$fbmd_state"
      fbmd_mounted=no
   fi

    # Now that dataset is mounted, get the mountpoint
    fbmd_mountpoint=`/sbin/zfs get -Ho value mountpoint "$fbmd_pool"`
    if [ "$?" -ne 0 -o -z "$fbmd_mountpoint" ]; then
       ${LUPRINTF} "`gettext 'ERROR: Unable to get mount point for top dataset in pool <%s>.'`" "$fbmd_pool"
       if [ "$fbmd_mounted" = yes ]; then
          /sbin/zfs unmount "$fbmd_pool"
       fi
       /bin/rm -f "$fbmd_state"
       return 1
    fi

    /bin/echo "MOUNTPOINT=$fbmd_mountpoint" >> "$fbmd_state"

    return 0
}

#
# This function is called to unmount the top dataset in a pool
# (if it was mounted by use)
#
# Arguments:
#	$1	pool name
#	$2	State file
#
# Returns:
#	0	Top dataset unmounted
#	1	A fatal error occurred
#
# Local Prefix:  fbtd
#
fb_unmount_top_dataset()
{
   if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
      ${LUPRINTF} "`gettext 'ERROR: fb_unmount_top_dataset <pool-name> <state-file>.'`"
      return 1
   fi

   fbtd_pool="$1"
   fbtd_state="$2"

   if [ ! -f "$fbtd_state" -o ! -s "$fbtd_state" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Cannot unmount dataset for pool <%s>.'`" "$fbtd_pool"
      return 1
   fi

   # Check if the dataset was mounted by someone else. In that case we have nothing to do
   fbtd_mounted=`/bin/awk -F= '$1 == "MOUNTED" {print $2; exit 23}' "$fbtd_state"`
   if [ "$?" -ne 23 -o -z "$fbtd_mounted" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Cannot determine if dataset was mounted. Cannot unmount dataset for pool <%s>.'`" "$fbtd_pool"
      return 1
   fi

   if [ "$fbtd_mounted" = no ]; then
      # Nothing to do
      /bin/rm -f "$fbtd_state"
      return 0
   fi

   # Check if a legacy dataset
   fbtd_legacy=`/bin/awk -F= '$1 == "LEGACY" {print $2; exit 24}' "$fbtd_state"`
   if [ "$?" -ne 24 -o -z "$fbtd_legacy" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Cannot determine if dataset is legacy. Cannot unmount dataset for pool <%s>.'`" "$fbtd_pool"
      return 1
   fi

   if [ "$fbtd_legacy" = no ]; then
      /sbin/zfs unmount "$fbtd_pool"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} "`gettext 'ERROR: Failed to unmount dataset for pool <%s>.'`" "$fbtd_pool"
         return 1
      fi
      /bin/rm -f "$fbtd_state"
      return 0
   fi

   # This is a legacy dataset that we mounted. Use the umount command.
   /sbin/umount "$fbtd_pool"
   if [ "$?" -ne 0 ]; then
      ${LUPRINTF} "`gettext 'ERROR: Failed to unmount legacy dataset for pool <%s>'`" "$fbtd_pool"
      return 1
   fi

   # Remove the mountpoint
   fbtd_mntpt=`/bin/awk -F= '$1 == "MOUNTPOINT" {print $2; exit 25}' "$fbtd_state"`
   if [ "$?" -ne 25 -o -z "$fbtd_mntpt" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Cannot determine mountpoint for legacy dataset in pool <%s>'`" "$fbtd_pool"
      return 1
   fi

   /bin/rmdir "$fbtd_mntpt"
   /bin/rm -f "$fbtd_state"

   return 0
}

#
# This function is called during OOS to mount the x86 boot partition on the system (if one exists)
#
# Arguments:
#	$1	fallback BE mount-point
#	$2	The state file to record mount state
#
# Returns:
#	0	x86 boot partition mounted or does not exist
#	1	A fatal error occurred
#	2	One or more non-fatal errors occurred
#
# Local Prefix:  fmbp
#
fb_mount_boot_part()
{
   fmbp_mntdir="/tmp/.luactivate.fmbp.mntdir.$$"

   if [ "${LU_SYSTEM_ARCH}" != "i386" ]; then
      ${LUPRINTF} "`gettext 'ERROR: fb_mount_boot_part() only supported on x86'`"
      return 1
   fi

   if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Usage: fb_mount_boot_part <fallback-BE-mount-point> <state-file>'`"
      return 1
   fi

   fmbp_be_mntpt="$1"
   fmbp_state="$2"

   /bin/rm -f "$fmbp_state"

   # Now check if x86 boot partition is present
   fmbp_bootpart=`/bin/grep -v '^#' "${fmbp_be_mntpt}/etc/vfstab" | /bin/grep "[ 	]/stubboot[ 	]*pcfs[ 	]" | /bin/awk '{print $1}'`
   ret="$?"
   if [ "$ret" -ne 0 -o -z "$fmbp_bootpart" ]; then
      fmbp_bootpart=`/bin/grep -v '^#' "${fmbp_be_mntpt}/etc/vfstab" | /bin/grep "[ 	]/boot[ 	]*pcfs[ 	]" | /bin/awk '{print $1}'`
      ret="$?"
   fi
   if [ "$ret" -ne 0 -o -z "$fmbp_bootpart" ]; then
      ${LUPRINTF} "`gettext 'No x86 boot partition.'`"
      return 0
   fi
    
   fmbp_mntpt=`/sbin/mount | /bin/nawk -v dev=$fmbp_bootpart '{ if ($3 == dev) {printf("%s\n", $1); exit 10;}}'`
   if [ "$?" -ne 10 ]; then
      /bin/mkdir -p "$fmbp_mntdir"
      /sbin/mount -F pcfs "$fmbp_bootpart" "$fmbp_mntdir"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} "`gettext 'ERROR: Cannot mount x86 boot partition <%s>'`" "$fmbp_bootpart"
         /bin/rmdir "$fmbp_mntdir"
         return 1
      fi
      fmbp_mnted=1
      fmbp_mntpt="$fmbp_mntdir"
  else
      fmbp_mnted=""
  fi

  /bin/echo "${fmbp_mnted}:${fmbp_mntpt}" > "$fmbp_state"

  return 0
}

#
# This function is called to unmount the x86 boot partition mounted by fb_mount_boot_part()
#
# Arguments:
#	$1	The state file containing mount information
#
# Returns:
#	0	x86 boot partition unmounted
#	1	A fatal error occurred
#
# Local Prefix:  fubp
#
fb_unmount_boot_part()
{
   if [ "${LU_SYSTEM_ARCH}" != "i386" ]; then
      ${LUPRINTF} "`gettext 'ERROR: fb_unmount_boot_part() only supported on x86'`"
      return 1
   fi

   if [ "$#" -ne 1 -o -z "$1" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Usage: fb_unmount_boot_part <state-file>'`"
      return 1
   fi

   fubp_state="$1"

   fubp_mnted=`/bin/cat "$fubp_state" | /bin/cut -d ':' -f1`
   fubp_mntpt=`/bin/cat "$fubp_state" | /bin/cut -d ':' -f2`

   if [ -z "$fubp_mnted" ]; then
      return 0
   fi

   /sbin/umount "$fubp_mntpt"
   if [ "$?" -ne 0 ]; then
      ${LUPRINTF} "`gettext 'ERROR: Failed to unmount x86 boot partition mounted at <%s>'`" "$fubp_mntpt"
      return 1
   fi

   /bin/rmdir "$fubp_mntpt"

   return 0
}

#
# This function is called to install GRUB on a GRUB based x86 boot partition (/stubboot) during fallback
#
# Arguments:
#	$1	Mountpoint of fallback BE
#
# Returns:
#	0	GRUB installed or x86 boot partition missing
#	1	A fatal error occurred
#
# Local Prefix:  fibg
#
fb_install_boot_GRUB()
{
   fibg_error="/tmp/.luactivate.fibg.error.$$"

   /bin/rm -f "$fibg_error"

   if [ "${LU_SYSTEM_ARCH}" != "i386" ]; then
      ${LUPRINTF} "`gettext 'ERROR: fb_install_boot_GRUB() only supported on x86'`"
      return 1
   fi

   if [ "$#" -ne 1 -o -z "$1" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Usage: fb_install_boot_GRUB <mount point of fallback BE>'`"
      return 1
   fi

   fibg_be_mntpt="$1"

   # Check if the fallback BE /stubboot (GRUB based x86 boot partition)
   fibg_bootpart=`/bin/grep -v '^#' "${fibg_be_mntpt}/etc/vfstab" | /bin/grep "[ 	]/stubboot[ 	]*pcfs[ 	]" | /bin/awk '{print $1}'`
   if [ "$?" -eq 0 -a -n "$fibg_bootpart" ]; then
      fibg_bootchr=`/bin/echo "$fibg_bootpart" | /bin/sed 's:/dsk/:/rdsk/:g'` 
      ${LUPRINTF} "`gettext 'Installing GRUB bootloader to x86 boot partition <%s>.'`" "$fibg_bootchr"
      oldpwd=`/bin/pwd`
      cd "${fibg_be_mntpt}/${LU_DIR}"
      ./installgrub.findroot ./stage1.findroot ./stage2.findroot "$fibg_bootchr"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} "`gettext 'ERROR: installgrub failed for x86 boot partition <%s>'`" "$fibg_bootchr"
	 /bin/touch $fibg_error
      fi
      cd "$oldpwd"
   fi

   if [ -f "$fibg_error" ]; then
      /bin/rm -f "$fibg_error"
      return 1
   fi

   return 0
}

################################################################################
# Name:		fb_propagate
# Description:	Propagate the GRUB menu and GRUB bootloader to all BEs
# Local Prefix:	<none>
# Arguments:	$1 - mount point of fallback BE
#		$2 - name of fallback BE
#		$3 - path of file to be copied.
#		$4 - copy to top dataset
#		$5 - install GRUB as well
# Returns:	0 = successful.
#		1 = failure.
################################################################################

fb_propagate()
{
   pmb_state="/tmp/.luactivate.pmb.state.$$"
   pmb_tmpmnt="/tmp/.luactivate.pmb.mntpt.$$"

   if [ "$#" -ne 3 -o -z "$1" -o -z "$2" -o -z "$3" ]; then
      ${LUPRINTF} "`gettext 'ERROR: Invalid arguments. Usage: fb_propagate <fb-mntpt> <fb-name> <file>.'`"
      return 1
   fi

   pmb_mntpt="$1"
   pmb_beName="$2"
   pmb_file="$3"
   pmb_top="$4"
   pmb_boot="$5"
   pmb_error=""

   if [ ! -f "${pmb_mntpt}/${pmb_file}" -o ! -s "${pmb_mntpt}/${pmb_file}" ]; then 
      ${LUPRINTF} "`gettext 'ERROR: fb_propagate: file <%s> does not exist in fallback BE <%s>.'`" "$pmb_file" "$pmb_beName"
      return 1
   fi

   if [ ! -f "${pmb_mntpt}/etc/lu/installgrub.findroot" -o ! -s "${pmb_mntpt}/etc/lu/installgrub.findroot" ]; then 
      ${LUPRINTF} "`gettext 'ERROR: fb_propagate: /etc/lu/installgrub.findroot does not exist in fallback BE <%s>.'`" "$pmb_beName"
      return 1
   fi

   if [ ! -f "${pmb_mntpt}/etc/lu/stage1.findroot" -o ! -s "${pmb_mntpt}/etc/lu/stage1.findroot" ]; then 
      ${LUPRINTF} "`gettext 'ERROR: fb_propagate: /etc/lu/stage1.findroot does not exist in fallback BE <%s>.'`" "$pmb_beName"
      return 1
   fi

   if [ ! -f "${pmb_mntpt}/etc/lu/stage2.findroot" -o ! -s "${pmb_mntpt}/etc/lu/stage2.findroot" ]; then 
      ${LUPRINTF} "`gettext 'ERROR: fb_propagate: /etc/lu/stage2.findroot does not exist in fallback BE <%s>.'`" "$pmb_beName"
      return 1
   fi

   # for all the valid and complete BEs mount the root
   $LUBIN/lunames_get | 
   while read be_name
   do

      # if the BE is active, then no need of copying.
      [ "$be_name" = `/sbin/lucurr` ] && continue

      # determine the status of the target BE.
      status=`${pmb_mntpt}/etc/lib/lu/ludo get_be_status_from_be_name "$be_name"`
      if [ "$?" -ne 0 ] ; then
         ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot get status of BE <%s>.'`"  "$be_name"
	 pmb_error=yes
	 continue
      fi

      # if the status of this BE is not 'C' then we should not copy.
      [ "$status" != 'C' ] && continue

      # get the ROOT slice for the BE.
      # if the root slice for the BE cannot be obtained then continue.
      RSLICE=`${pmb_mntpt}/etc/lib/lu/ludo get_root_slice_from_be_name "${be_name}"`
      if [ "$?" -ne 0 -o -z "$RSLICE" ] ; then
         ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot determine root slice of BE <%s>.'`"  "$be_name"
	 pmb_error=yes
	 continue
      fi

      # determine the filesystem type of the root device of BE
      R_FST=`/usr/sbin/fstyp "$RSLICE"`
      if [ "$?" -ne 0 -o -z "$R_FST" ] ; then
         ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot determine root fstype for BE <%s>.'`"  "$be_name"
	 pmb_error=yes
	 continue
      fi

      if [ "$R_FST" = zfs -a "$pmb_top" = yes ]; then
         pmb_pool=`/bin/echo "$RSLICE" | /bin/awk -F/ '{print $1; exit 27}'`
         if [ "$?" -ne 27 -o -z "$pmb_pool" ]; then
            ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot get pool name for rootslice <%s>.'`" "$RSLICE"
	    pmb_error=yes
            continue
         fi
         fb_mount_top_dataset "$pmb_pool" "$pmb_state"
	 if [ "$?" -ne 0 ]; then
            ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot mount pool dataset for pool <%s>.'`" "$pmb_pool"
	    pmb_error=yes
            continue
         fi

	 pmb_rslice_mntpt=`/bin/awk -F= '$1 == "MOUNTPOINT" {print $2; exit 28}' "$pmb_state"`
	 if [ "$?" -ne 28 -o -z "$pmb_rslice_mntpt" ]; then
            ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot get mount point for pool dataset for pool <%s>.'`" "$pmb_pool"
	    fb_umount_top_dataset "$pmb_state"
	    pmb_error=yes
	    continue
	 fi
      else
         # continue if the root device node for BE does not exist.
         if [ ! -b "$RSLICE" ] ; then
            ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot access root device <%s> for BE <%s>.'`"  "$RSLICE" "$be_name"
	    pmb_error=yes
	    continue
         fi
         # Check to see if the file system is already mounted. If it is, we
         # will not mount it.
         MOUNTED=`${pmb_mntpt}/etc/lib/lu/ludo get_mntpt_from_root_slice "${RSLICE}" 2>/dev/null`
         if [ "$?" -eq 0 -a -n "${MOUNTED}" ] ; then
	    pmb_rslice_mntpt=$MOUNTED
	    UMOUNT=NO
         else
	    UMOUNT=YES
	    # If the mountpoint does not exist then create it.
	    [ ! -d "$pmb_tmpmnt" ] && /bin/mkdir -p "$pmb_tmpmnt"
	    /usr/sbin/mount -F $R_FST $RSLICE "$pmb_tmpmnt"
	    if [ "$?" -ne 0 ]; then
               ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot mount UFS root device <%s> for BE <%s>.'`"  "$RSLICE" "$be_name"
	       pmb_error=yes
	       continue
	    fi
	    pmb_rslice_mntpt="$pmb_tmpmnt"
	 fi
      fi


      # Copy the GRUB menu
      pmb_dir=`dirname $pmb_file`

      /bin/mkdir -p "$pmb_rslice_mntpt/$pmb_dir"

      /bin/cp -p $pmb_file "$pmb_rslice_mntpt/$pmb_dir"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot copy file <%s> to BE <%s>.'`" "$pmb_file" "$be_name"
	 pmb_error="yes"
      fi

      # If boot loader needs to be installed, install it now
      if [ "$pmb_boot" = yes ]; then
         pmb_olddir=`pwd`
         cd "${pmb_mntpt}/etc/lu/"

         ./installgrub.findroot ./stage1.findroot ./stage2.findroot $RSLICE
         if [ "$?" -ne 0 ]; then
            ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot install GRUB bootloader to BE <%s>.'`" "$be_name"
	    pmb_error="yes"
         fi
         cd "$pmb_olddir"
     fi

      # Now unmount the root slice
      if [ "$R_FST" = zfs -a "$pmb_top" = yes ]; then
         fb_umount_top_dataset "$pmb_state"
	 if [ "$?" -ne 0 ]; then
            ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot unmount pool dataset for pool <%s>.'`" "$pmb_pool"
	    pmb_error=yes
            continue
         fi
      else
         if [ "$UMOUNT" != NO ]; then
	    # force log to be flushed before unmounting
	    if [ "$R_FST" = ufs -a -x "/usr/sbin/lockfs" ] ; then
		/usr/sbin/lockfs -f "${pmb_rslice_mntpt}" 1>/dev/null 2>&1
	    fi
	    # unmount the root of the BE
	    /usr/sbin/umount "${pmb_rslice_mntpt}"
	    if [ "$?" -ne 0 ] ; then
		/usr/sbin/umount -f "${pmb_rslice_mntpt}"
	    	if [ "$?" -ne 0 ] ; then
            	   ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot unmount root slice <%s> for BE <%s>.'`" "$RSLICE" "$be_name"
	           pmb_error=yes
		   continue
	        fi
	    fi
	    /bin/rmdir "$pmb_tmpmnt"
	fi
      fi
   done


   # Now if there is a GRUB x86 boot partition (/stubboot), install
   # GRUB on it
   fb_install_boot_GRUB "$pmb_mntpt"
   if [ "$?" -ne 0 ]; then
      ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Failed to install GRUB on x86 boot partition during fallback to <%s>.'`" "$be_name"
      pmb_error=yes
   fi

   fb_mount_boot_part "$pmb_mntpt" "$pmb_state"
   ret="$?"
   case "$ret" in
      0) # Successful
         ${LUPRINTF} "`gettext 'mounted x86 boot partition.'`"
         ;;
      1) # Fatal error
         ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Failed to propagate GRUB menu to x86 boot partition during fallback to <%s>.'`" "$be_name"
         return 1
         ;;
      2) # Non-fatal error. Drive on
         /bin/touch "$pmb_error"
         ;;
      *) # Unknown error - fatal
         ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Failed to propagate GRUB menu to x86 boot partition with error code <%s>.'`" "$ret"
         return 1
         ;;
   esac


   if [ "$ret" -eq 0 ]; then
      pmb_bootpart_mntpt=`/bin/cat "$pmb_state" | /bin/cut -d: -f 2`

      if [ -f "${pmb_bootpart_mntpt}/${pmb_file}" -a -s "${pmb_bootpart_mntpt}/${pmb_file}" ]; then
         # There is a preexisting file at the specified location. Propagate the file anyway,
         # but save the previous file.
         /bin/mv "${pmb_bootpart_mntpt}/${pmb_file}" "${pmb_bootpart_mntpt}/${pmb_file}.prev"
      fi

      # Copy the GRUB menu
      pmb_dir=`dirname $pmb_file`

      /bin/mkdir -p "$pmb_bootpart_mntpt/$pmb_dir"

      /bin/cp -p $pmb_file "$pmb_bootpart_mntpt/$pmb_dir"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} "`gettext 'ERROR: fb_propagate: Cannot GRUB menu to x86 boot partition during fallback to BE<%s>.'`" "$be_name"
	 pmb_error="yes"
      fi

      fb_umount_boot_part "$pmb_state"
      if [ "$?" -ne 0 ]; then
         /bin/touch "$pmb_error"
      else
         /bin/rm -f "$pmb_state"
      fi
   fi

   if [ "pmb_error" = yes ]; then
      ${LUPRINTF} "`gettext 'ERROR: fb_propagate: One or more non-fatal errors occurred during fallback propagation for fallback BE<%s>.'`" "$be_name"
   fi

   return 0
}

################################################################################
# Name:		do_fallback
# Description:	Fallback to previous boot environment (call during single user/
#		maintenance mode only).
# Local Prefix:	<none>
# Arguments:	<none>
# Returns:	0 = successful.
#		1 = failure.
# IMPORTANT NOTES:
#
# do_fallback is called when the system is in single user or maintenance mode;
# there are two primary scenarios:
#
# 1) boot to # mini-root (cdrom, net, alternative disk) to fallback to previous
#    boot environment
# 2) boot single user to current boot environment to fallback to previous boot
#    environment.
#
# In case #1 the live upgrade product is NOT contained within the root file
# system of the currently running system - most probably it is at /mnt but that
# is not guaranteed.
#
# In either case, none of the live upgrade libraries (/usr/lib/lu) or defaults
# (/etc/defaults/lu) have been loaded or are available. ALL calls made within
# this function or in functions called by this function MUST be able to this
# condition.
################################################################################

do_fallback()
{
  dfb_luupdall=""
  dfb_tmp="/tmp/.luactivate.dfb.1.$$"

  echo ''
  echo "`gettext 'Welcome to the Live Upgrade out of service administration.'`"
  echo "`gettext 'Activating the previous working boot environment.'`"
  echo ''

  yesAnswer="`gettext \"yes\"`"
  noAnswer="`gettext \"no\"`"
  
  ## Now determine to which mount point the root disk of a BE is mounted.
  ## This is done by searching through all of the mount points until <mntpt>/etc/lu/.CURR_VARS
  ## is found - that should be the root slice of the fallback BE.

  dfb_fbinfo="`find_be_mntpt`"

  # Extract the mount point and boot device for the root disk of the BE found.
  dfb_mntpt="`echo ${dfb_fbinfo} | /bin/cut -f1 -d':'`"
  dfb_bdevice="`echo ${dfb_fbinfo} | /bin/cut -f2 -d':'`"

  if [ -z "${dfb_fbinfo}" -o -z "${dfb_mntpt}" -o -z "${dfb_bdevice}" -o ! -s "$dfb_mntpt/etc/lu/.CURR_VARS" -o ! -s "$dfb_mntpt/etc/default/lu" ] ; then
    echo ''
    echo '**********************************************************************'
    echo "`gettext 'Unable to activate the previous working boot environment. You have not mounted the correct root slice containing the previous working boot environment to be activated. Please mount the proper root slice and re-invoke luactivate.'`" | /bin/fold -s -w 75
    echo '**********************************************************************'
    echo ''
    echo "`gettext 'Fallback activation failed.'`"
    return 1
  fi

  # Source in the defaults from the BE to be activated, and set flag that
  # forces the defaults to not be reloaded by a subsequent lu program.

  . ${dfb_mntpt}/etc/default/lu

  # Now, override all of the defaults to operate in this limited
  # single user maintenance mode environment. Note, we also need
  # to set the LD_LIBRARY_PATH, since ludo is dependent on liblu.so.1
  # and liblu.so.1 lives inside <mnt_pt>/etc/lib/lu, where <mnt_pt>
  # is the mount point for the root filesystem of a BE. In case of
  # a fallback scenario, liblu.so.1 will never be present in the
  # miniroot of the DVD/network image.

  LUBIN="$dfb_mntpt/sbin"

  LU_SYSTEM_ARCH="`/bin/uname -p`"
  LU_HARDWARE_ARCH="`/bin/uname -m`"
  LU_HARDWARE_IMPLEMENTATION="`/bin/uname -i`"

  LU_BE_CONFIG_FILE="$dfb_mntpt/etc/lu/.BE_CONFIG" ; export LU_BE_CONFIG_FILE
  LU_LUTAB_FILE="$dfb_mntpt/etc/lutab" ; export LU_LUTAB_FILE
  COPYLOCK="$dfb_mntpt/etc/lu/COPY_LOCK" ; export COPYLOCK
  CURR_VARS="$dfb_mntpt/etc/lu/.CURR_VARS" ; export CURR_VARS
  ### LU_OPTFS="$dfb_mntpt/etc/lu/optfs" ; export LU_OPTFS
  NEXT_ACTIVE="$dfb_mntpt/etc/lu/.NEXT_ACTIVE" ; export NEXT_ACTIVE
  SYNCKEY="$dfb_mntpt/etc/lu/.SYNCKEY" ; export SYNCKEY

  PATH=${LUBIN}:/etc:/sbin:/usr/bin:/usr/sbin:$PATH ; export PATH
  LD_LIBRARY_PATH="$dfb_mntpt/etc/lib/lu" ; export LD_LIBRARY_PATH
  MULTI_BOOT="platform/i86pc/multiboot" ; export MULTI_BOOT

  # Locate luprintf
  if [ -x "${LUETCBIN}/luprintf" ] ; then
    # If luprintf is found, then the only flags turned on are "fold" and
    # "standard output" because it is assumed that in single user mode the
    # simplest output will be preferred. XML output is disabled.
    LUPRINTF="${LUETCBIN}/luprintf +X -f1"
    LUPRINTFN="${LUETCBIN}/luprintf +X -f1n"
  else
    # luprintf is not found - default to echo.
    LUPRINTF='echo'
    LUPRINTFN='echo'
  fi
  
  ## Source in the information about the last (fallback) boot environment:
  ## BEID - i.d. of the boot environment
  ## BENAME - name of the boot environment
  ## BEROOT - root device for the boot environment
  ## BEROOT_FSTYP - "mount" file system type for the BE root device
 
  .  ${CURR_VARS}
  
  ## Make sure that the device found matches what the last (fallback) 
  ## boot environment should be.
  
  if [ "$BEROOT" != "$dfb_bdevice" ] ; then
    # This slice is the root slice of some other BE.
    ${LUPRINTF} ''
    ${LUPRINTF} '%s' '**********************************************************************'
    ${LUPRINTF} ''
    ${LUPRINTF} "`gettext 'ERROR: You mounted device <%s> which is the root slice of some other boot environment. You need to mount device <%s> to mount point <%s> and run luactivate again.'`" "${dfb_bdevice}" "${BEROOT}" "${dfb_mntpt}"
    ${LUPRINTF} ''
    ${LUPRINTF} '%s' '**********************************************************************'
    ${LUPRINTF} ''

    ${LUPRINTF} "`gettext 'Fallback activation failed with errors.'`"
    return 1
  fi

  ## The boot device for this BE matches the root slice for this BE -
  ## Found the correct mount point for the "last active BE". 
  
  ## Confirm with user that fallback should be done.
  
  ${LUPRINTF} "`gettext 'The previous boot environment name is <%s> root is on device <%s>.'`" "${BENAME}" "${BEROOT}"
  /bin/tty -s
  if [ "$?" -eq "0" ] ; then
    theAnswer=""
    while [ "X${theAnswer}" != "X${yesAnswer}" -a "X${theAnswer}" != "X${noAnswer}" ] ; do
      ${LUPRINTFN} "`gettext 'Do you want to fallback to (activate) boot environment <%s> (%s or %s)? '`" "${BENAME}" "${yesAnswer}" "${noAnswer}"
      read theAnswer < `/bin/tty`
      if [ "X${theAnswer}" != "X${yesAnswer}" -a "X${theAnswer}" != "X${noAnswer}" ] ; then
	${LUPRINTF} "`gettext 'ERROR: <%s> is an invalid Choice - valid choices are: <%s> or <%s>.'`" "${theAnswer}" "${yesAnswer}" "${noAnswer}"
      fi
    done
    if [ "X${theAnswer}" != "X${yesAnswer}" ] ; then
      ${LUPRINTF} "`gettext 'Fallback activation cancelled.'`"
      return 1
    fi
  fi

  ${LUPRINTF} "`gettext 'Activating previous boot environment <%s> root is on device <%s>.'`" "${BENAME}" "${BEROOT}"
  
  # dfb_Error: null if no error on fallback; non-null if there is an error
  dfb_Error=""

  # For SPARC, this changes the boot device in the EEPROM 
  # For i386, this code switches boot partition and updates boot path.
  
  set_boot "$BEROOT" "$dfb_mntpt" "${BENAME}" "yes" "yes"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} "`gettext 'ERROR: Unable to change system boot device to boot from fallback boot environment <%s> device <%s>.'`" "${BENAME}" "${BEROOT}"
    dfb_Error="yes"
  fi
  
  ## Write the old vtoc out to the physical boot disk.
  
  if [ -f "$dfb_mntpt/etc/lu/vtoc.$BEID" -a -s "$dfb_mntpt/etc/lu/vtoc.$BEID" ] ; then
    /bin/cp /dev/null /tmp/.lu_fmthard_res.$$
    ${LUPRINTF} "`gettext 'Updating partition ID tag on fallback boot environment <%s> device <%s> to be root slice.'`" "${BENAME}" "${BEROOT}"
    /usr/sbin/fmthard -s $dfb_mntpt/etc/lu/vtoc.$BEID $BEDISK 2>>/tmp/.lu_fmthard_res.$$ 1>&2
    if [ "$?" -ne "0" ] ; then
      ${LUPRINTF} "`gettext 'ERROR: Unable to write vtoc to device <%s> on fallback boot environment id <%s> BE <%s>.'`" "${BEDISK}" "${BEID}" "${BENAME}"
      /bin/cat /tmp/.lu_fmthard_res.$$
      dfb_Error="yes"
    fi
    /bin/rm -f /tmp/.lu_fmthard_res.$$
  else
    ${LUPRINTF} "`gettext 'WARNING: no vtoc image available to update device <%s> on fallback boot environment id <%s> BE <%s>.'`" "${BEDISK}" "${BEID}" "${BENAME}"
  fi
  
  ## Write out a new boot loader to the physical disk.
  
  if [ "${LU_SYSTEM_ARCH}" = sparc ]; then
     if [ -f "$dfb_mntpt/$DELAY_UPD_DIR/bootblk" -a -s "$dfb_mntpt/$DELAY_UPD_DIR/bootblk" ]; then
        ${LUPRINTF} "`gettext 'Updating boot loader on fallback boot environment <%s> device <%s> to match OS release.'`" "${BENAME}" "${BEDISK}"
	zfs_option=""
	bootblk_size=`ls -s $dfb_mntpt/$DELAY_UPD_DIR/bootblk | awk '{print $1}'`
	if [ "$bootblk_size" -gt 15 ]; then
		zfs_option="-Fzfs"
	fi
        /usr/sbin/installboot $zfs_option $dfb_mntpt/$DELAY_UPD_DIR/bootblk ${BEDISK}
        if [ "$?" -ne "0" ] ; then
           ${LUPRINTF} "`gettext 'ERROR: Unable to update boot loader for fallback boot environment <%s> on device <%s>.'`" "${BENAME}" "${BEDISK}"
           dfb_Error="yes"
        fi
    else
        ${LUPRINTF} "`gettext 'ERROR: No bootblock available. Cannot update boot loader for fallback boot environment <%s> on device <%s>.'`" "${BENAME}" "${BEDISK}"
        dfb_Error="yes"
    fi
    if [ -f "$dfb_mntpt/${CREATE_RAMDISK}" -a -s "$dfb_mntpt/${CREATE_RAMDISK}" ]; then
       $dfb_mntpt/${CREATE_RAMDISK} -R "$dfb_mntpt"
       if [ $? != 0 ]; then
          ${LUPRINTF} "`gettext 'ERROR: Cannot create boot_archive for fallback boot environment <%s> on device <%s>.'`" "${BENAME}" "${BEDISK}"
          dfb_Error="yes"
       fi
    fi
  elif [ "${LU_SYSTEM_ARCH}" = "i386" ] ; then
    if [ -f "$dfb_mntpt/$DELAY_UPD_DIR/bootblk" -a -f "$dfb_mntpt/$DELAY_UPD_DIR/pboot" ] ; then

      ${LUPRINTF} "`gettext 'Updating boot loader on fallback boot environment <%s> device <%s> to match OS release.'`" "${BENAME}" "${BEDISK}"
      # There is no DCA boot based ZFS root. ZFS only present on GRUB BEs
      # Installboot may not be present on GRUB boot BEs, so use a saved copy
      $dfb_mntpt/$DELAY_UPD_DIR/installboot $dfb_mntpt/$DELAY_UPD_DIR/pboot $dfb_mntpt/$DELAY_UPD_DIR/bootblk ${BEDISK}
      if [ "$?" -ne "0" ] ; then
	${LUPRINTF} "`gettext 'ERROR: Unable to update boot loader for fallback boot environment <%s> on device <%s>.'`" "${BENAME}" "${BEDISK}"
	dfb_Error="yes"
      fi
    elif [ -f "$dfb_mntpt/$DELAY_UPD_DIR/installgrub" ]; then
      # The PBE aka fallback BE is a GRUB/DBOOT BE
      # Set the boot menu default to the fallback BE and write GRUB bootloader to all BEs
      if [ -f "${dfb_mntpt}/${DELAY_UPD_DIR}/${PBE_BOOT_MENU_FILE}" ]; then

	 dfb_dir=`dirname ${dfb_mntpt}/${BOOT_MENU}`
	 /bin/mkdir -p "$dfb_dir"
         /bin/cp -p "${dfb_mntpt}/${DELAY_UPD_DIR}/${PBE_BOOT_MENU_FILE}" ${dfb_mntpt}/${BOOT_MENU} 
	 if [ "$?" -ne 0 ]; then
	    ${LUPRINTF} "`gettext 'ERROR: Cannot copy fallback menu'`"
            $dfb_Error=yes
         fi

	 dfb_dir=`dirname ${dfb_mntpt}/${GRUB_backup_menu}`
	 /bin/mkdir -p "$dfb_dir"
         /bin/cp -p "${dfb_mntpt}/${DELAY_UPD_DIR}/${PBE_BOOT_MENU_FILE}" ${dfb_mntpt}/${GRUB_backup_menu}
	 if [ "$?" -ne 0 ]; then
	    ${LUPRINTF} "`gettext 'ERROR: Cannot copy fallback backup menu'`"
            $dfb_Error=yes
         fi

         fb_propagate "$dfb_mntpt" "$BENAME"  "$BOOT_MENU" "yes" "yes"
	 if [ "$?" -ne 0 ]; then
	    ${LUPRINTF} "`gettext 'ERROR: Cannot propagate GRUB bootloader and menu to all BEs.'`"
            $dfb_Error=yes
         fi

         fb_propagate "$dfb_mntpt" "$BENAME"  "$GRUB_backup_menu" "" ""
	 if [ "$?" -ne 0 ]; then
	    ${LUPRINTF} "`gettext 'ERROR: Cannot propagate GRUB backup menu to all BEs - not a fatal error.'`"
         fi

      else
	 if [ "$?" -ne 0 ]; then
	    ${LUPRINTF} "`gettext 'ERROR: Cannot find fallback menu. Cannot propagate fallback menu to all BEs.'`"
            $dfb_Error=yes
         fi
      fi
    fi
  else
    ${LUPRINTF} "`gettext 'WARNING: no boot loader available to update device <%s> boot environment id <%s> BE <%s>.'`" "${BEDISK}" "${BEID}" "${BENAME}"
  fi

  ## If the activation was successful, remove all of the files that setup
  ## the system to activate the new boot environment so that if the admin
  ## uses either 'init' or 'shutdown' the new boot environment will not 
  ## be mistakenly reactivated.

  if [ -z "$dfb_Error" ] ; then
    /bin/rm -f ${NEXT_ACTIVE} ${SYNCKEY} ${CURR_VARS} ${COPYLOCK} 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/$DELAY_UPD_DIR/vtoc.* 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/$DELAY_UPD_SCRIPT 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/$DELAY_UPD_SCRIPT_EXEC 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/${MBR} 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/${BOOT_MENU_FILE} 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/${PBE_BOOT_MENU_FILE} 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/installgrub 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/stage1 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/stage2 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/installboot 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/pboot 2>/dev/null
    /bin/rm -f ${dfb_mntpt}/${DELAY_UPD_DIR}/bootblock 2>/dev/null
  fi

  ## Activation should be done...
  
  if [ -z "$dfb_Error" ] ; then
    ${LUPRINTF} ''
    ${LUPRINTF} '%s' '**********************************************************************'
    ${LUPRINTF} ''
    ${LUPRINTF} "`gettext 'Successfully activated the previous working boot environment <%s>. You can unmount the root device of the previous working boot environment (via <umount %s>) and reboot the system.'`" "${BENAME}" "${dfb_mntpt}"
    ${LUPRINTF} ''
    ${LUPRINTF} '%s' '**********************************************************************'
    ${LUPRINTF} ''
    ${LUPRINTF} "`gettext 'Fallback activation successful.'`"
    return 0
  fi

  # If the following error is displayed to user then it would
  # be better to reinstall the machine, then try out some thing
  # else. We have lost both PBE and ABE.
  ${LUPRINTF} ''
  ${LUPRINTF} '%s' '**********************************************************************'
  ${LUPRINTF} ''
  ${LUPRINTF} "`gettext 'ERROR: Unable to activate the previous working boot environment <%s>. You must repair any problems reported and try activating the boot environment again, or reinstall the system software.'`" "${BENAME}"
  ${LUPRINTF} ''
  ${LUPRINTF} '%s' '**********************************************************************'
  ${LUPRINTF} ''
  ${LUPRINTF} "`gettext 'Fallback activation failed with errors.'`"
  return 1
}

disp_fallback_info()
{
  
  # target would be the Config Asst disk number of previous boot disk.
  # Since eeprom must be changed on a failed BE boot, we can't
  # instruct the user to use Config Asst to direct the boot since
  # conf asst will just use the bootdev in eeprom.
  ABEmaj="`ls -l $ABE_root_bdev | /bin/sed 's/.*\/devices\//\//g' | sed 's/:.$//g'`"
  PBEmaj="`ls -l $PBE_root_bdev | /bin/sed 's/.*\/devices\//\//g' | sed 's/:.$//g'`"
  
  ${LUPRINTF} ''
  ${LUPRINTF} '%s' '**********************************************************************'
  ${LUPRINTF} ''

  ${LUPRINTF} -f1 '%s' "`gettext 'In case of a failure while booting to the target BE, the following process needs to be followed to fallback to the currently working boot environment:'`"
  ${LUPRINTF} ''

  if [ "$ABEmaj" = "$PBEmaj" ] ; then
      if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
	# sparc with 2 BEs on same disk

	### -->1. Enter the PROM monitor (ok prompt).
	### -->
	### -->2. Boot the machine to Single User mode using a different boot device (like the Solaris Install CD or Network). Examples:
	### -->
	### -->     At the PROM monitor (ok prompt):
	### -->     For boot to Solaris CD:  boot cdrom -s
	### -->     For boot to network:     boot net -s
	### -->
	### -->3. Mount the Current BE root slice to the mount point /mnt. You
	###	    can use the following command to mount:
	### -->
	### -->     mount -FPBE_root_fstyp PBE_root_bdev /mnt
	### -->
	### -->4. Run <luactivate> utility with out any arguments from the current BE root slice, as shown below:
	### -->
	### -->     /mnt/sbin/luactivate
	### -->
	### -->5. luactivate, activates the previous working boot environment and indicates the result.
	### -->
	### -->6. Exit Single User mode and reboot the machine.

	${LUPRINTF} -f1 "`gettext '1. Enter the PROM monitor (ok prompt).\\n\\n2. Boot the machine to Single User mode using a different boot device (like the Solaris Install CD or Network). Examples:\\n\\n     At the PROM monitor (ok prompt):\\n     For boot to Solaris CD:  boot cdrom -s\\n     For boot to network:     boot net -s\\n\\n3. Mount the Current boot environment root slice to some directory (like /mnt). You can use the following command to mount:\\n\\n     mount -F%s %s /mnt\\n\\n4. Run <luactivate> utility with out any arguments from the current boot environment root slice, as shown below:\\n\\n     /mnt/sbin/luactivate\\n\\n5. luactivate, activates the previous working boot environment and indicates the result.\\n\\n6. Exit Single User mode and reboot the machine.'`" "$PBE_root_fstyp" "$PBE_root_bdev"
      else
	# x86 with 2 BEs on same disk

	### -->1. Boot from Solaris Failsafe or boot in single user mode
	### -->   from Solaris Install CD or Network
	### -->
	### -->2. Mount the Parent BE root slice to the mount point /mnt. You can
	### -->use the following command to mount:
	### -->
	### -->     mount -F$PBE_root_fstyp $PBE_root_bdev /mnt
	### -->
	### -->3. Run <luactivate> utility with out any arguments from the Parent BE 
	### -->root slice, as shown below:
	### -->
	### -->     /mnt/sbin/luactivate
	### -->
	### -->4. luactivate, activates the previous working boot environment and 
	### -->indicates the result.
	### -->
	### -->5. Exit Single User mode and reboot the machine.
	### -->

	${LUPRINTF} -f1 "`gettext '1. Boot from Solaris failsafe or boot in single user mode from the Solaris Install CD or Network.\\n\\n2. Mount the Parent boot environment root slice to some directory (like /mnt). You can use the following command to mount:\\n\\n     mount -F%s %s /mnt\\n\\n3. Run <luactivate> utility with out any arguments from the Parent boot environment root slice, as shown below:\\n\\n     /mnt/sbin/luactivate\\n\\n4. luactivate, activates the previous working boot environment and indicates the result.\\n\\n5. Exit Single User mode and reboot the machine.\\n\\n'`" "$PBE_root_fstyp" "$PBE_root_bdev"
      fi
  else
    if [ "${LU_SYSTEM_ARCH}" = sparc ] ; then
      # sparc with 2 BEs on different disks

      ### -->1. Enter the PROM monitor (ok prompt).
      ### -->
      ### -->2. Change the boot device back to the original BE by typing:
      ### -->
      ### -->     setenv boot-device 
      ### -->
      ### -->3. Boot to the original BE by typing:
      ### -->
      ### -->     boot

	${LUPRINTF} -f1 "`gettext '1. Enter the PROM monitor (ok prompt).\\n\\n2. Change the boot device back to the original boot environment by typing:\\n\\n     setenv boot-device %s\\n\\n3. Boot to the original boot environment by typing:\\n\\n     boot'`" "`/etc/lib/lu/lubootdev -n $PBE_root_bdev`"
    else
      #
      # x86 with 2 BEs on different disks
      # same instructions as the 1 disk case
      #
	${LUPRINTF} -f1 "`gettext '1. Boot from the Solaris failsafe or boot in Single User mode from Solaris Install CD or Network.\\n\\n2. Mount the Parent boot environment root slice to some directory (like /mnt). You can use the following command to mount:\\n\\n     mount -F%s %s /mnt\\n\\n3. Run <luactivate> utility with out any arguments from the Parent boot environment root slice, as shown below:\\n\\n     /mnt/sbin/luactivate\\n\\n4. luactivate, activates the previous working boot environment and indicates the result.\\n\\n5. Exit Single User mode and reboot the machine.\\n\\n'`" "$PBE_root_fstyp" "$PBE_root_bdev"
    fi
  fi

  ${LUPRINTF} ''
  ${LUPRINTF} '%s' '**********************************************************************'
  ${LUPRINTF} ''
}

disp_activate_info()
{
  ${LUPRINTF} ''
  ${LUPRINTF} '%s' '**********************************************************************'
  ${LUPRINTF} ''
  ${LUPRINTF} -f1 "`gettext 'The target boot environment has been activated. It will be used when you reboot. NOTE: You MUST NOT USE the reboot, halt, or uadmin commands. You MUST USE either the init or the shutdown command when you reboot. If you do not use either init or shutdown, the system will not boot using the target BE.'`"
}



#
# This function checks for the presence of an "active" x86 boot
# partition on the disk. If one exists, it is made inactive
# and the Solaris partition is made active instead 
#
# Arguments:
#	$1 - Physical disk slice (may not be a /dev/md name)
#	$2 - when to update (NOW or DELAYED)
#	$3 - Indicates if in oos mode (OOS or NOT_OOS)
# Returns:
#	Nothing 
#
set_boot_inactive()
{

  if [ "$#" -ne 3 -o -z "$1" -o -z "$2" -o -z "$3" ]; then
     ${LUPRINTF} "`gettext 'ERROR: set_boot_inactive(): Invalid arguments.'`"
     return
  fi

  dab_raw_slice="$1"
  dab_when="$2"
  dab_oos="$3"

  dab_tmp1=/tmp/.luactivate.dab.1.$$
  dab_tmp2=/tmp/.luactivate.dab.2.$$

  #
  # dab_raw_slice is a /dev path
  #
  /bin/echo "$dab_raw_slice" | /bin/egrep "p0:boot$" > /dev/null 2>&1
  if [ "$?" -eq 0 ]; then
     dab_p0=`/bin/echo "$dab_raw_slice" | /bin/sed 's/p0:boot$/p0/g'`
  else
     dab_p0=`/bin/echo "$dab_raw_slice" | /bin/sed 's/s.$/p0/g'`
  fi

  /sbin/fdisk -W "$dab_tmp1" "$dab_p0"
  /bin/grep -v \* "$dab_tmp1" | /bin/grep -v '^[	 ]*$' > "$dab_tmp2"
  /bin/rm -f "$dab_tmp1"
  if [ "$dab_oos" != OOS ]; then
     ${LUPRINTF} -lp2D 8 "`gettext 'Read fdisk table for <%s>.'`" "${dab_p0}"
  fi

  #
  # if there is a boot partition on hd? and it is active, make the Solaris
  # partion active.
  #
  /bin/awk ' { if ( $1 == "190" && $2 == "128" ) exit 9; } ' "$dab_tmp2"
  ret1="$?"
  /bin/awk ' { if ( $1 == "130" || $1 == "191" ) exit 10; } ' "$dab_tmp2"
  ret2="$?"
  if [ "$ret1" -eq 9 -a "$ret2" -eq 10 ]; then
    if [ "$dab_oos" != OOS ]; then
       ${LUPRINTF} -lp2D - "`gettext 'Active boot partition found on boot disk <%s>.'`" "${dab_p0}"
    fi
    /bin/awk '{ if ( $1 == "190" ) printf "%s 0 %s %s %s %s %s %s %s %s\n", $1, $3, $4, $5, $6, $7, $8, $9, $10
                else if ( $1 == "130" ) printf "%s 128 %s %s %s %s %s %s %s %s\n", $1, $3, $4, $5, $6, $7, $8, $9, $10
                else if ( $1 == "191" ) printf "%s 128 %s %s %s %s %s %s %s %s\n", $1, $3, $4, $5, $6, $7, $8, $9, $10
                else printf "%s %s %s %s %s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10
              } ' "$dab_tmp2" > "$dab_tmp1"

    if [ "$dab_oos" != OOS ]; then
       ${LUPRINTF} -lp2D - "`gettext 'Generated fdisk table with deactivated boot partition.'`"
    fi
    if [ "$dab_when" = DELAYED ]; then
	/bin/cp "$dab_tmp1" $DELAY_UPD_DIR/$MBR
        if [ "$dab_oos" != OOS ]; then
           ${LUPRINTF} -lp2D - "`gettext ' Created function for delayed update of fdisk table <%s>.'`" "${dab_p0}"
	fi
    elif [ "$dab_when" = NOW ]; then
        /sbin/fdisk -F "$dab_tmp1" "$dab_p0"
        if [ "$dab_oos" != OOS ]; then
           ${LUPRINTF} -lp2D 8 "`gettext 'Updated fdisk table with deactivated boot partition.'`"
	fi
    fi
  fi

  /bin/rm -f "$dab_tmp1"
  /bin/rm -f "$dab_tmp2"
}

#
# NOTE: This function should only use files in /, since it may be
# called during OOS administration
#
# If there is a "active" Solaris fdisk partition and x86 boot partition
# make the boot partition active
#
# Arguments
#	$1  - Physical GRUB slice (i.e. cannot be /dev/md names
#	$2  - When update should occur: NOW or DELAYED
#	$3  - Is this oos mode (OOS or NOT_OOS)
# Returns
#	Nothing
#
set_boot_active()
{

  if [ "$#" -ne 3 -o -z "$1" -o -z "$2" -o -z "$3" ]; then
     ${LUPRINTF} "`gettext 'ERROR: set_boot_active(): Invalid arguments.'`"
     return
  fi

  acb_raw_slice="$1"
  acb_when="$2"
  acb_oos="$3"

  acb_tmp1=/tmp/.luactivate.acb.1.$$
  acb_tmp2=/tmp/.luactivate.acb.2.$$

  #
  # acb_raw_slice is a /dev path
  #
  /bin/echo "$acb_raw_slice" | /bin/grep "p0:boot$" > /dev/null 2>&1
  if [ "$?" -eq 0 ]; then
     acb_p0=`/bin/echo "$acb_raw_slice" | /bin/sed 's/p0:boot$/p0/g'`
  else
     acb_p0=`/bin/echo "$acb_raw_slice" | /bin/sed 's/s.$/p0/g'`
  fi

  /sbin/fdisk -W "$acb_tmp1" "$acb_p0"
  /bin/grep -v \* "$acb_tmp1" | /bin/grep -v '^[ 	]*$' > "$acb_tmp2"
  /bin/rm -f "$acb_tmp1"
  if [ "$acb_oos" != OOS ]; then
     ${LUPRINTF} -lp2D - "`gettext 'Read fdisk table for <%s>.'`" "${acb_p0}"
  fi

  #
  # If there is an instance of Solaris on the disk that is active AND there is a boot partition
  # make the boot partition active
  #
  /bin/awk ' { if ( $1 == "130" && $2 == "128" ) exit 10
               else if ( $1 == "191" && $2 == "128" ) exit 10
             } ' "$acb_tmp2"
  if [ "$?" -eq 10 ]; then
     if [ "$acb_oos" != OOS ]; then
        ${LUPRINTF} -lp2D - "`gettext 'Active Solaris partition.'`"
     fi
     /bin/awk ' { if ( $1 == "190" && $2 == "0" ) exit 11; }  ' "$acb_tmp2"
     if [ "$?" -eq 11 ]; then
        if [ "$acb_oos" != OOS ]; then
           ${LUPRINTF} -lp2D - "`gettext 'Active Solaris partition and inactive Boot partition.'`"
	fi
        /bin/awk ' { if ( $1 == "190" ) printf "%s 128 %s %s %s %s %s %s %s %s\n", $1, $3, $4, $5, $6, $7, $8, $9, $10
		  else if ( $1 == "130" ) printf "%s 0 %s %s %s %s %s %s %s %s\n", $1, $3, $4, $5, $6, $7, $8, $9, $10
		  else if ( $1 == "191" ) printf "%s 0 %s %s %s %s %s %s %s %s\n", $1, $3, $4, $5, $6, $7, $8, $9, $10
		  else printf "%s %s %s %s %s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10
	        } ' "$acb_tmp2" > "$acb_tmp1"
        if [ "$acb_oos" = OOS ]; then
           ${LUPRINTF} "`gettext 'Generated fdisk table with active boot partition.'`"
	else
           ${LUPRINTF} -lp1 "`gettext 'Generated fdisk table with active boot partition.'`"
	fi
        if [ "$acb_when" = DELAYED ]; then 
          /bin/cp "$acb_tmp1" ${DELAY_UPD_DIR}/$MBR
          if [ "$acb_oos" != OOS ]; then
             ${LUPRINTF} -lp2D - "`gettext ' Created MBR for delayed set active for fdisk <%s>.'`" "${acb_p0}"
	  fi
        elif [ "$acb_when" = NOW ]; then
	  /sbin/fdisk -F "$acb_tmp1" "$acb_p0"
          if [ "$acb_oos" != OOS ]; then
             ${LUPRINTF} -lp2D 5 "`gettext 'Updated fdisk table with active boot partition.'`"
	  fi
        fi
      fi
  fi

  /bin/rm -f "$acb_tmp1"
  /bin/rm -f "$acb_tmp2"
}

#
# This function gets the failsafe type for the BE name that is passed
# in as a parameter.  This is done by mounting the BE and finding out the
# name of the failsafe archve that it contains.  If it is 64 bit the name
# will be x86.miniroot64-safe.
#
get_failsafe_type()
{
  if [ "$#" -ne 1 -o -z "$1" ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'get_failsafe_type(): Invalid arguments.'`"
     ${LUPRINTF} -fWelp2 "`gettext 'get_failsafe_type: Unable to determine the failsafe archive type - reverting to 32 bit'`"
     failsafe_type="32BIT"
     return
  fi

  BE_NAME=$1
  curr_be=`lulib_lucurr`
  BE_DIR=
  if [ "${BE_NAME}" != "${curr_be}" ]; then
      BE_DIR=`LU_OUTPUT_FORMAT=text $LUBIN/lumount -Z "${BE_NAME}" 2>${TMP_RESULT_FILE}`
      if [ "$?" -ne "0" -o -z "${BE_DIR}" ] ; then
	[ -s "${TMP_RESULT_FILE}" ] && \
	  ${LUPRINTF} -elp2 '%R' < "${TMP_RESULT_FILE}"
	${LUPRINTF} -Eelp2 \
	    "`gettext 'Unable to mount boot environment <%s>.'`" "${PBE_NAME}"
	${LUPRINTF} -fWelp2 \
	    "`gettext 'get_failsafe_type: Unable to determine the failsafe archive type - reverting to 32 bit'`"
        failsafe_type="32BIT"
	return
      fi
  fi
  
  if [ -f "${BE_DIR}/${LU_FAILSAFE64_ARCHIVE}" ]; then
	echo "64BIT"
  else
	echo "32BIT"
  fi

  if [ "${BE_NAME}" != "${curr_be}" ]; then
      $LUBIN/luumount -f "${BE_NAME}"
  fi
}

#
# This function sets up the menu.lst for GRUB
#
# NOTE: Rolling the log
# =====================
# Since GRUB cannot roll the UFS log, we must ensure
# that any UFS filesystem entity read by GRUB has its log
# entries rolled before GRUB gets to look at it.
# There are currently 4 such entities:
#
# 1. menu.lst
# 2. multiboot binary
# 3. boot archive
# 4. failsafe archive
# 
# Of these, the boot archive case is already handled by the script
# that creates the boot archive. The multiboot binaries (normal
# and failsafe) are installed by either lucreate or luupgrade.
# Since these scripts have to be followed by an luactivate
# (which invokes the boot archive creation script which rolls
# log for the same filesystem) multiboot is not an issue
# The same applies to the failsafe archive.
# Thus the only entity that needs its log entry rolled is
# menu.lst. We handle this case here and in other functions in
# luactivate by using lockfs
#
#
# Arguments:
#	$1 - The ABE name
#	$2 - The PBE name
#
# Returns:
#	Nothing
#
setup_menu()
{
  if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'setup_menu(): Invalid arguments.'`"
     return 1
  fi

  setm_ABEname="$1"
  setm_PBEname="$2"

  setm_boot_menu="/${BOOT_MENU}"
  setm_tmp_menu="/tmp/.luactivate.setm.1.$$"
  setm_tmp_menu2="/tmp/.luactivate.setm.2.$$"
  setm_tmp_menu3="/tmp/.luactivate.setm.3.$$"

  lulib_copy_from_top_dataset "$setm_PBEname" "$setm_tmp_menu" "/${BOOT_MENU}"
  ret="$?"
  if [ "$ret" -eq 1 ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'Failed to copy file <%s> from top level dataset for BE <%s>'`" "/${BOOT_MENU}" "$setm_PBEname"
     return 1
  elif [ "$ret" -eq 0 ]; then
     # ZFS BE
     ${LUPRINTF} -lp1 "`gettext 'Copied boot menu from top level dataset.'`"
  else
     # UFS.
     if [ -f "$setm_boot_menu" -a -s "$setm_boot_menu" ]; then
  	/bin/cp -p "$setm_boot_menu" "$setm_tmp_menu"
        ${LUPRINTF} -lp1 "`gettext 'Boot menu exists.'`"
     else
	/bin/touch "$setm_tmp_menu"
        ${LUPRINTF} -lp1 "`gettext 'No boot menu exists. Creating new menu file '`"
     fi
  fi

   ${LUPRINTF} -lp2D - "`gettext 'Created tmp menu file at <%s>'`" "${setm_tmp_menu}"

   #
   # If the PBE is a Newboot BE, save the menu.lst. We need it for fallback activation
   #
   if [ "$PBE_boot_method" = GRUB ]; then
      if [ -f "$setm_tmp_menu" -a -s "$setm_tmp_menu" ]; then
         /bin/cp -p "$setm_tmp_menu" "${DELAY_UPD_DIR}/${PBE_BOOT_MENU_FILE}"
      fi
   fi

  #
  # Now install the PBE entries. If the entry already exists, we remove
  # it and recreate it. This is so that future changes in the entry
  # added by Live Upgrade can be accomodated.
  #
  entry_exists=""
  setm_PBEfixedname=`lulib_fix_name $setm_PBEname`

  fixed_menu_hdr="${BOOT_MENU_PREFIX}${setm_PBEfixedname}${BOOT_MENU_HDR_SUFFIX}"
  fixed_menu_ftr="${BOOT_MENU_PREFIX}${setm_PBEfixedname}${BOOT_MENU_FTR_SUFFIX}"
  if [ "$PBE_boot_method" = GRUB ]; then
       /bin/grep "$fixed_menu_hdr" "$setm_tmp_menu" > /dev/null 2>&1
       if [ "$?" -eq 0 ]; then
	  entry_exists=1
	  start=`/usr/bin/awk "/^$fixed_menu_hdr\$/ { print NR }" "$setm_tmp_menu"`
	  stop=`/usr/bin/awk "/^$fixed_menu_ftr\$/ { print NR }" "$setm_tmp_menu"`
	  /bin/nawk -v "hdr=$start" "NR < hdr {print}" "$setm_tmp_menu" > "$setm_tmp_menu2"
	  /bin/nawk -v "ftr=$stop" "NR > ftr {print}" "$setm_tmp_menu" > "$setm_tmp_menu3"
	  /bin/cp -p "$setm_tmp_menu2" "$setm_tmp_menu"
       else
	  entry_exists=""
       fi

       # Write the header
       echo "${BOOT_MENU_PREFIX}${setm_PBEname}${BOOT_MENU_HDR_SUFFIX}" >> "$setm_tmp_menu"
       echo "$LU_GRUB_ITEM_SEP"  >> "$setm_tmp_menu"

       # Write the entries
       echo title "$setm_PBEname" >> "$setm_tmp_menu"
       echo findroot "(${PBE_boot_sign},${PBE_part},${PBE_slice})" >> "$setm_tmp_menu" 

       if [ "$PBE_root_fstyp" = "zfs" ]; then
          PBE_kernel="kernel\$ /${MULTI_BOOT} -B \$ZFS-BOOTFS"
	  echo bootfs "${PBE_root_logical_bdev}" >> "$setm_tmp_menu"
       elif [ "$PBE_root_fstyp" = "ufs" ]; then
          PBE_kernel="kernel /${MULTI_BOOT}"
       else
	  ${LUPRINTF} -Eelp2 "`gettext 'setup_menu: Unsupported PBE root filesystem type <%s>.'`" "$PBE_root_fstyp"
       fi

       if [ "$PBE_boot_method" = GRUB ]; then
          ${LUPRINTF} -lp1 "`gettext 'Generating multiboot menu entries for PBE.'`"
          echo "$PBE_kernel" >> "$setm_tmp_menu"
          echo module "/${BOOT_ARCHIVE}"  >> "$setm_tmp_menu"
       else
	  ${LUPRINTF} -Eelp2 "`gettext 'setup_menu: Unsupported PBE boot method <%s>.'`" "$PBE_boot_method"
       fi
       echo "$LU_GRUB_ITEM_SEP"  >> "$setm_tmp_menu"

       #
       # Install the failsafe archives . This is the install miniroot.
       # If PBE contains the 64 bit miniroot as the failsafe then use it
       # otherwise use the 32 bit miniroot.
       # The kernel/unix arg to multiboot should precede other options
       #
       echo title "$setm_PBEname" "failsafe" >> "$setm_tmp_menu"
       echo findroot "(${PBE_boot_sign},${PBE_part},${PBE_slice})" >> "$setm_tmp_menu" 
       if [ "$PBE_root_fstyp" = "zfs" ]; then
          echo bootfs "${PBE_root_logical_bdev}" >> "$setm_tmp_menu"
       fi
       if [ "$PBE_boot_method" = GRUB ]; then
          echo kernel "/${FAILSAFE_MULTI_BOOT} -s $LU_CONSOLE_ARG"  >> "$setm_tmp_menu"
       else
          ${LUPRINTF} -Eelp2 "`gettext 'setup_menu: Unsupported PBE boot method <%s>.'`" "$PBE_boot_method"  
       fi
       failsafe_type=`get_failsafe_type $setm_PBEname`
       if [ "$failsafe_type" = "64BIT" ]; then
	echo module "/${LU_FAILSAFE64_ARCHIVE}"  >> "$setm_tmp_menu"
       else
	echo module "/${LU_FAILSAFE_ARCHIVE}"  >> "$setm_tmp_menu"
       fi
       echo "$LU_GRUB_ITEM_SEP"  >> "$setm_tmp_menu"
       echo "${BOOT_MENU_PREFIX}${setm_PBEname}${BOOT_MENU_FTR_SUFFIX}" >> "$setm_tmp_menu"

       if [ -n "$entry_exists" ]; then
          /bin/cat "$setm_tmp_menu3" >> "$setm_tmp_menu"
       fi
  fi

  # Install the ABE entries. If the entry already exists, we remove
  # it and recreate it. This is so that future changes in the entry
  # added by Live Upgrade can be accomodated.
  #
  # Escape any special characters in ABE name written to the menu so that egrep and awk don't choke
  #
  setm_ABEfixedname=`lulib_fix_name $setm_ABEname`

  fixed_menu_hdr="${BOOT_MENU_PREFIX}${setm_ABEfixedname}${BOOT_MENU_HDR_SUFFIX}"
  fixed_menu_ftr="${BOOT_MENU_PREFIX}${setm_ABEfixedname}${BOOT_MENU_FTR_SUFFIX}"
  if [ "$ABE_boot_method" = GRUB ]; then
       /bin/grep "$fixed_menu_hdr" "$setm_tmp_menu" > /dev/null 2>&1
       if [ "$?" -eq 0 ]; then
	  entry_exists=1
	  start=`/usr/bin/awk "/^$fixed_menu_hdr\$/ { print NR }" "$setm_tmp_menu"`
	  stop=`/usr/bin/awk "/^$fixed_menu_ftr\$/ { print NR }" "$setm_tmp_menu"`
	  /bin/nawk -v "hdr=$start" "NR < hdr {print}" "$setm_tmp_menu" > "$setm_tmp_menu2"
	  /bin/nawk -v "ftr=$stop" "NR > ftr {print}" "$setm_tmp_menu" > "$setm_tmp_menu3"
	  /bin/cp -p "$setm_tmp_menu2" "$setm_tmp_menu"
       else
	  entry_exists=""
       fi

       # Write the header
       echo "${BOOT_MENU_PREFIX}${setm_ABEname}${BOOT_MENU_HDR_SUFFIX}" >> "$setm_tmp_menu"
       echo "$LU_GRUB_ITEM_SEP"  >> "$setm_tmp_menu"

       # Write the entries
       echo title "$setm_ABEname" >> "$setm_tmp_menu"
       echo findroot "(${ABE_boot_sign},${ABE_part},${ABE_slice})" >> "$setm_tmp_menu" 
 
       if [ "$ABE_root_fstyp" = "zfs" ]; then
          ABE_kernel="kernel\$ /${MULTI_BOOT} -B \$ZFS-BOOTFS"
	  echo bootfs "${ABE_root_logical_bdev}" >> "$setm_tmp_menu"
       elif [ "$ABE_root_fstyp" = "ufs" ]; then
          ABE_kernel="kernel /${MULTI_BOOT}"
       else
          ${LUPRINTF} -Eelp2 "`gettext 'setup_menu: Unsupported ABE root fstype <%s>.'`" "$ABE_root_fstyp"
       fi
       if [ "$ABE_boot_method" = GRUB ]; then
          ${LUPRINTF} -lp1 "`gettext 'Generating multiboot menu entries for ABE.'`"
          echo "$ABE_kernel" >> "$setm_tmp_menu"
          echo module "/${BOOT_ARCHIVE}"  >> "$setm_tmp_menu"
       else
	   ${LUPRINTF} -Eelp2 "`gettext 'setup_menu: Unsupported ABE boot method <%s>.'`" "$ABE_boot_method"
       fi
       echo "$LU_GRUB_ITEM_SEP"  >> "$setm_tmp_menu"

       #
       # Install the failsafe archives . This is the install miniroot.
       # If PBE contains the 64 bit miniroot as the failsafe then use it
       # otherwise use the 32 bit miniroot.
       # The kernel/unix arg to multiboot should precede other options
       #
       echo title "$setm_ABEname" "failsafe" >> "$setm_tmp_menu"
       echo findroot "(${ABE_boot_sign},${ABE_part},${ABE_slice})" >> "$setm_tmp_menu" 
       if [ "$ABE_root_fstyp" = "zfs" ]; then
          echo bootfs "${ABE_root_logical_bdev}" >> "$setm_tmp_menu"
       fi
       if [ "$ABE_boot_method" = GRUB ]; then
          echo kernel "/${FAILSAFE_MULTI_BOOT} -s $LU_CONSOLE_ARG"  >> "$setm_tmp_menu"
       else
          ${LUPRINTF} -Eelp2 "`gettext 'setup_menu: Unsupported ABE boot method <%s>.'`" "$ABE_boot_method"
       fi
       failsafe_type=`get_failsafe_type $setm_ABEname`
       if [ "$failsafe_type" = "64BIT" ]; then
	echo module "/${LU_FAILSAFE64_ARCHIVE}"  >> "$setm_tmp_menu"
       else
	echo module "/${LU_FAILSAFE_ARCHIVE}"  >> "$setm_tmp_menu"
       fi
       echo "$LU_GRUB_ITEM_SEP"  >> "$setm_tmp_menu"

       echo "${BOOT_MENU_PREFIX}${setm_ABEname}${BOOT_MENU_FTR_SUFFIX}" >> "$setm_tmp_menu"

       if [ -n "$entry_exists" ]; then
          /bin/cat "$setm_tmp_menu3" >> "$setm_tmp_menu"
       fi
   fi

   # We can only be in this function if ABE_boot_method is GRUB

   #
   # If not a serial console, enable splash image.
   # If a splash image is already set, disable it if not a physical console
   # NOTE: the splash image command must precede actual entries
   #
   ${LUPRINTF} -lp1 "`gettext 'Disabling splashimage'`"
   /bin/rm -f "$setm_tmp_menu2"
   /bin/rm -f "$setm_tmp_menu3"
   /bin/egrep -v "^[ 	]*${LU_GRUB_SPLASH_CMD}[ 	=]+.+[ 	]*" "$setm_tmp_menu" > "$setm_tmp_menu3"
   if [ "$LU_IS_PHYS_CONSOLE" = yes ]; then
      ${LUPRINTF} -lp1 "`gettext 'Re-enabling splashimage'`"
      echo "$LU_GRUB_SPLASH_CMD" "$LU_GRUB_SPLASH_PATH" > "$setm_tmp_menu2"
   fi
   /bin/cat "$setm_tmp_menu3" >> "$setm_tmp_menu2"
   /bin/cp "$setm_tmp_menu2" "$setm_tmp_menu"  

   # Don't check for errors, best effort
   ${LUPRINTF} -lp2D - "`gettext 'Eliding bootadm entries in <%s>'`" "${setm_tmp_menu}" 
   lulib_elide_bootadm_entries "${setm_tmp_menu}"

   #
   # Check if a timeout value is already set. If it has been, leave it alone
   # NOTE: the timeout command must precede actual entries
   # NOTE: The syntax "timeout=value" (instead of "timeout value") also works
   #       (but is not documented in GRUB). We handle that form as well
   #
   /bin/egrep "^[ 	]*${LU_GRUB_TIMEOUT_CMD}[ 	=]+[0-9]+[ 	]*" "$setm_tmp_menu" > /dev/null 2>&1
   if [ "$?" -ne 0 ]; then
      echo "$LU_GRUB_TIMEOUT_CMD" "$LU_GRUB_TIMEOUT_VALUE" > "$setm_tmp_menu2"
      /bin/cat "$setm_tmp_menu" >> "$setm_tmp_menu2"
      /bin/cp "$setm_tmp_menu2" "$setm_tmp_menu"  
   fi

   # Set the default only *after* we have finished messing with the GRUB menu, else our calculations
   # may be invalidated.

   /bin/egrep "^[ 	]*${LU_GRUB_TITLE_CMD}[ 	]+" "$setm_tmp_menu" > "$setm_tmp_menu2"
   ABEentry=`/usr/bin/awk "/^${LU_GRUB_TITLE_CMD} $setm_ABEfixedname\$/ { print NR }" "$setm_tmp_menu2"`

   # Grub starts its menu entry count at zero, so correct for that
   ABEentry=`expr $ABEentry - 1`

   #
   # Set the current ABE as the default entry
   # NOTE: the default command must precede actual entries
   #
   /bin/egrep -v "^[ 	]*${LU_GRUB_DEFAULT_CMD}[ 	=]+[0-9]+[ 	]*" "$setm_tmp_menu" > "$setm_tmp_menu2"
   echo "$LU_GRUB_DEFAULT_CMD" "$ABEentry" > "$setm_tmp_menu"
   /bin/cat "$setm_tmp_menu2" >> "$setm_tmp_menu"

   ${LUPRINTF} -lp2D - "`gettext 'Updated tmp copy at <%s>'`" "${setm_tmp_menu}" 

   # Delayed update
   /bin/cp "$setm_tmp_menu" "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}"
   /usr/bin/chmod "$LU_GRUB_MENU_PERM" "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}"
   ${LUPRINTF} -lp2D - "`gettext 'Created menu file for delayed update at <%s>'`" "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}"

   /bin/rm -f "$setm_tmp_menu"
   /bin/rm -f "$setm_tmp_menu2"
   /bin/rm -f "$setm_tmp_menu3"

   return 0
}

#
# Setup things (like menu and fdisk active flag) during luactivate
# This will be used later as the system goes down
#
# Arguments:
#	$1 - The ABE name
#	$2 - The PBE name
# Returns:
#	0 - On success
#	1 - On failure
#
setup()
{

  if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'setup(): Invalid arguments.'`"
     return 1
  fi

  stp_ABEname="$1"
  stp_PBEname="$2"

  setup_menu "$stp_ABEname" "$stp_PBEname"

  return "$?"
}

#
# Ensure that the current BE and the associated ZFS dataset are listed
# in the pool's menu.lst
#
# $1 = BE name
# $2 = dataset to boot from
#
update_sparc_menu()
{
	lupool=`echo "$ABE_root_logical_bdev" | cut -d/ -f1`
	src="/$lupool/boot/$BOOT_MENU_FILE"
	dest="$DELAY_UPD_DIR/$BOOT_MENU_FILE"

	if [ -f "$src" ]; then
		nawk -v DS="$2" '/^bootfs / && $2 == DS { exit 1; }' "$src"
		if [ $? = 1 ]; then
			# entry already exists
			return 0
		fi
		cp "$src" "$dest"
	else
		touch "$dest"
	fi

	echo "title $1" >> "$dest"
	echo "bootfs $2" >> "$dest"
	return 0
}

#
# Adds commands to the delayed activation script which runs as the
# system is going down following a luactivate. This does the following
#	- Installs GRUB to GRUB slice
#	- Creates the archive on ABE
#	- Installs the menu on GRUB slice
#	- Sets active flag on approriate fdisk partition
#
# Arguments:
#	$1 - ABE name
#
# Returns:
#	0 - on succes
#	1 - on failure
#
create_script()
{
   if [ "$#" -ne 1 -o -z "$1" ]; then
      ${LUPRINTF} -Eelp2 "`gettext 'create_script(): Invalid arguments.'`"
      return 1
   fi

   scr_ABEname="$1"

   scr_tmp1="/tmp/.luactivate.scr.1.$$"
   scr_tmp2="/tmp/.luactivate.scr.2.$$"

   /bin/cat <<-EOF >> $DELAY_UPD_SCRIPT

        if [ ! -f "${LU_DIR}/installgrub.findroot" -o ! -x "${LU_DIR}/installgrub.findroot" ]; then
	   \${LUPRINTF} -fEel2 "`gettext 'Cannot find GRUB that supports the findroot command.'`"
   	   exit 2
        fi
	/bin/rm -f "\${scr_ABEmntpt}/dev/.devlink_db"
	EOF

   /bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
	# Install GRUB that supports the findroot command on all BEs

	lulib_install_GRUB "no" "yes"
	if [ "\$?" -ne 0 ]; then
	   \${LUPRINTF} -fEel2 "`gettext 'Could not install GRUB that supports the findroot command.'`"
   	   exit 2
	fi
	EOF

   /bin/cat <<-EOF >> $DELAY_UPD_SCRIPT

        # Mount the ABE
        scr_ABEmntpt=\`LU_OUTPUT_FORMAT=text ${LUBIN}/lumount -Zi /etc/lu/ICF.$ABE_id 2>$scr_tmp1\`
        if [ "\$?" -ne 0 ]; then
           \${LUPRINTF} -fEel2 "`gettext 'Unable to mount ABE <%s>.'`" "$scr_ABEname"
           /bin/cat "$scr_tmp1"
           /bin/rm -f "$scr_tmp1"
           exit 2
        fi
        /bin/rm -f "$scr_tmp1"
	EOF


   /bin/cat <<-EOF >> $DELAY_UPD_SCRIPT

   	# Create archive
	[ -x /sbin/zfs ] && /sbin/zfs list "$ABE_root_logical_bdev" > /dev/null 2>&1
	if [ \$? != 0 ]; then
	   # UFS needs the bootpath set in bootenv.rc
   	   scr_rootPhys=\`/bin/ls -l "\${scr_ABEmntpt}/$ABE_root_logical_bdev" | /bin/awk ' { print \$11 } ' | /bin/sed 's/.*\/devices\//\//g'\`
	   if [ "\$?" -ne 0 -o -z \${scr_rootPhys} ]; then
	      \${LUPRINTF} -fEel2 "`gettext 'Cannot set bootpath to <%s>.'`" "\${scr_rootPhys}"
	      ${LUBIN}/luumount -f -i /etc/lu/ICF.$ABE_id
	      exit 2
	   fi

	   scr_bootEnv="\${scr_ABEmntpt}/${LU_GRUB_BOOT_ENV}"

	   # Preserve permissions
	   /bin/rm -f "$scr_tmp1"
	   /bin/cp -p "\${scr_bootEnv}" "$scr_tmp1"
	   /bin/egrep -v "^[ 	]*setprop[ 	]+bootpath[ 	]+" "$scr_tmp1" > "\$scr_bootEnv"
	   /bin/echo "setprop bootpath \${scr_rootPhys}" >> "\$scr_bootEnv"
	fi
	\${scr_ABEmntpt}/${CREATE_RAMDISK} -R "\$scr_ABEmntpt"
	EOF

   /bin/cat <<-EOF >> $DELAY_UPD_SCRIPT

	# Unmount ABE
	${LUBIN}/luumount -f -i /etc/lu/ICF.$ABE_id
	EOF

   /bin/cat <<-EOF >> $DELAY_UPD_SCRIPT

	# Install menu. First try ZFS
	lulib_copy_to_top_dataset `/usr/sbin/lucurr` "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}" "/${BOOT_MENU}"
        ret="\$?" 
	if [ "\$ret" -eq 2 ]; then
	   # UFS
	   /bin/mkdir -p `dirname "/${BOOT_MENU}"`
	   /bin/cp "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}" "/${BOOT_MENU}"
	   if [ "\$?" -ne 0 ]; then
              \${LUPRINTF} +X -fEel2 "`gettext 'Failed to copy <%s> to current UFS BE<%s>.'`" "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}" "`/usr/sbin/lucurr`"
	      exit 2
	   fi
	elif [ "\$ret" -ne 0 ]; then
             \${LUPRINTF} +X -fEel2 "`gettext 'Failed to copy <%s> to current ZFS BE<%s>.'`" "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}" "`/usr/sbin/lucurr`"
	     exit 2
	fi

	lulib_propagate_file "/${BOOT_MENU}" "yes"
	if [ "\$?" -ne 0 ]; then
           \${LUPRINTF} +X -fEel2 "`gettext 'Failed to propagate GRUB menu to all BEs.'`"
	   exit 2
	fi

	/bin/cp -p "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}" "$GRUB_backup_menu"
	lulib_propagate_file "$GRUB_backup_menu" ""
	if [ "\$?" -ne 0 ]; then
              \${LUPRINTF} +X -fEel2 "`gettext 'Unable to propagate backup menu <%s> to all boot environments.'`" "$GRUB_backup_menu"
	fi

	lulib_propagate_file "$LU_GRUB_SPLASH_PATH" ""
	if [ "\$?" -ne 0 ]; then
              \${LUPRINTF} +X -fEel2 "`gettext 'Unable to propagate splashimage file <%s> to all boot environments.'`" "$LU_GRUB_SPLASH_PATH"
	fi
	/bin/rm -f "${DELAY_UPD_DIR}/${BOOT_MENU_FILE}"
	EOF

    if [ "$ABE_root_fstyp" = "zfs" ]; then
	lupool=`echo "$ABE_root_logical_bdev" | cut -d/ -f1`
	/bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
	if [ -f "$DELAY_UPD_DIR/$BOOT_MENU_FILE" ]; then
		[ -d "/$lupool/boot" ] || mkdir -m 755 "/$lupool/boot"
		if [ $? != 0 ]; then
			\${LUPRINTF} +X -fEel2 "`gettext 'Unable to create <%s/%s>'`" "/$lupool/boot" "$BOOT_MENU_FILE"
			exit 2
		fi
		mv "$DELAY_UPD_DIR/$BOOT_MENU_FILE" "/$lupool/boot"
	fi
	# set the bootfs property on the pool
	/sbin/zpool set bootfs="$ABE_root_logical_bdev" "$lupool"
	/sbin/zpool set failmode=continue "$lupool"
	# reset the mountpoints (lumount/luumount modifies them)
        /sbin/zfs list -t filesystem -Ho name,mountpoint -r $ABE_root_logical_bdev | awk '\$2!="legacy" {print \$1}'|
	    while read ds_name; do 
                /sbin/zfs inherit mountpoint "\$ds_name"
	    done
	/sbin/zfs set mountpoint=/ $ABE_root_logical_bdev
	EOF
    fi

   return 0
}

#
# At luactivate time, sets up GRUB so that the next
# active BE is activated as the system goes down. 
#
# Arguments:
#	$1 - ABE name
#	$2 - PBE name
# Returns
#	0 - on success
#	1 - on error
#
update_grub_delayed()
{
   if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
      ${LUPRINTF} -Eelp2 "`gettext 'update_grub_delayed(): Invalid arguments.'`"
      return 1
   fi

   ugd_ABEname="$1"
   ugd_PBEname="$2"

   setup "$ugd_ABEname" "$ugd_PBEname"
   if [ "$?" -ne 0 ]; then
      return 1
   fi

   create_script "$ugd_ABEname"
   if [ "$?" -ne 0 ]; then
      return 1
   fi

   return 0
}

#
# This function vectors things approriately depending on
# whether we are invoked as "luactivate -u" or not.
# It sets up (or in -u case does immediately) installation
# of the GRUB boot loader.
#
# Arguments:
#	$1 - PBE name
#	$2 - ABE name
#
# Returns
#	0 on success
#	1 on failure
#
update_grub_loader()
{
  if [ "$#" -ne 2 -o -z "$1" -o -z "$2" ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'update_grub_loader(): Invalid arguments.'`"
     return 1
  fi

  ugl_PBEname="$1"
  ugl_ABEname="$2"

  if [ "${LU_SYSTEM_ARCH}" != i386 -o "$ABE_boot_method" = DCA ]; then
      ${LUPRINTF} -Eelp2 "`gettext 'update_grub_loader: Internal error: Not a GRUB activation.'`"
      return 1
  fi

  #
  # If PBE == ABE, then we shouldn't be here. Emit an error message and return
  #
  if [ "$ugl_PBEname" = "$ugl_ABEname" ]; then 
      ${LUPRINTF} -Eelp2 "`gettext 'ABE <%s> == PBE <%s>. Cannot install GRUB loader'`" "${ugl_ABEname}" "${ugl_PBEname}"
      return 1
  fi

  if [ -n "$flag_u" ]; then
      ${LUPRINTF} -Eelp2 "`gettext 'Internal error: <%s> option not supported for x86'`" "${flag_u}"
      return 1
  fi

  update_grub_delayed "$ugl_ABEname" "$ugl_PBEname"

  return "$?"
}

#
# On the first boot after luactivate, the boot archive
# verification service complains about a large
# number of files being "new". This is because
# Live upgrade doesn't create the stat data used by
# bootadm. This is harmless to the system. To avoid
# alarming users, we disable the boot archive
# verification service (on first boot only) after
# luactivate
#
disable_boot_verif_svc()
{
  dbs_state="/tmp/.luactivate.dbs.state.$$"

  /bin/rm -f "$dbs_state"

  dbs_abeName="$1"
  dbs_svc="/lib/svc/method/boot-archive"

  if [ "$LU_SYSTEM_ARCH" != i386 -a "$LU_SYSTEM_ARCH" != sparc ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'disable_boot_verif_svc: Unsupported architecture <%s>.'`" "${LU_SYSTEM_ARCH}"
     return
  fi

  #
  # Mount the ABE
  #
  dbs_mntpt=`lulib_mount -Z "$dbs_abeName" "$dbs_state"`
  if [ "$?" -ne 0 -o -z "$dbs_mntpt" ]; then
      ${LUPRINTF} -Eelp2 "`gettext 'Cannot mount ABE: <%s>. Cannot disable boot verification svc.'`" "$dbs_abeName"
      /bin/rm -f "$dbs_state"
      return
  fi

  #
  # Disable only if luactivating to a BE with SMF
  #
  dbs_no_smf=""
  if [ ! -f "${dbs_mntpt}/${dbs_svc}" -o ! -s "${dbs_mntpt}/${dbs_svc}" ]; then 
     dbs_no_smf=yes
  fi

  lulib_umount "$dbs_abeName" "$dbs_state"
  if [ "$?" -ne 0 ]; then
     ${LUPRINTF} -Eelp2 "`gettext 'Cannot reset zfs mountpoint for ABE: <%s>. Cannot disable boot verification svc.'`" "$dbs_abeName"
     return
  else
     /bin/rm -f "$dbs_state"
  fi

  if [ "$dbs_no_smf" = yes ]; then
     return
  fi

  ${LUPRINTF} -lp1 "`gettext 'Modifying boot archive service'`"

  /bin/rm -f "${DELAY_UPD_DIR}/boot-svc" 
  /bin/rm -f "${DELAY_UPD_DIR}/S99lufirstboot" 

   #
   # Step 1: Create boot-svc and start script
   #	     and save them in DELAY_UPD_DIR
   #
  /bin/cat <<-EOF >> ${DELAY_UPD_DIR}/boot-svc
	#!/sbin/sh
	exit 0
	EOF
  /bin/chmod u+x "${DELAY_UPD_DIR}/boot-svc"

  /bin/cat <<-EOF >> ${DELAY_UPD_DIR}/S99lufirstboot
	#!/sbin/sh
	#
	case "\$1" in
	'start')
	         /bin/mv /lu-boot-svc ${dbs_svc}
	         /bin/chmod u+x ${dbs_svc} 
	         /bin/rm -f /etc/rc2.d/S99lufirstboot
	         ;;
	 *)
	         /bin/echo "usage: \$0 start"
	         exit 1
	         ;;
	esac
	exit 0
	EOF
  /bin/chmod u+x "${DELAY_UPD_DIR}/S99lufirstboot"


   #
   # Step 2: Switch boot-archive method with "dummy" script and
   #	     install start script
   /bin/cat <<-EOF  >> $DELAY_UPD_SCRIPT

	# mount the ABE (sans zones)
	dba_mntpt=\`${LUBIN}/lumount -Z $dbs_abeName\`
        if [ "\$?" -ne 0 -o -z "\$dba_mntpt" ]; then
	   \${LUPRINTF} -fEel2 "`gettext 'Unable to mount ABE <%s>.'`" "$dbs_abeName"
	   exit 2
	fi

	/bin/mv "\${dba_mntpt}/${dbs_svc}" "\${dba_mntpt}/lu-boot-svc"
	/bin/mv "${DELAY_UPD_DIR}/boot-svc" "\${dba_mntpt}/${dbs_svc}"
	/bin/mv "${DELAY_UPD_DIR}/S99lufirstboot" "\${dba_mntpt}/etc/rc2.d"
	${LUBIN}/luumount -f \${dba_mntpt}
	EOF

    if [ "$ABE_root_fstyp" = "zfs" ]; then
	lupool=`echo "$ABE_root_logical_bdev" | cut -d/ -f1`
        /bin/cat <<-EOF >> $DELAY_UPD_SCRIPT
	if [ -f "$DELAY_UPD_DIR/$BOOT_MENU_FILE" ]; then
		[ -d "/$lupool/boot" ] || mkdir -m 755 "/$lupool/boot"
		if [ $? != 0 ]; then
			\${LUPRINTF} +X -fEel2 "`gettext 'Unable to create <%s/%s>'`" "/$lupool/boot" "$BOOT_MENU_FILE"
			exit 2
		fi
		mv "$DELAY_UPD_DIR/$BOOT_MENU_FILE" "/$lupool/boot"
	fi
	# set the bootfs property on the pool
	/sbin/zpool set bootfs="$ABE_root_logical_bdev" "$lupool"
	/sbin/zpool set failmode=continue "$lupool"
        zfs list -t filesystem -Ho name,mountpoint -r $ABE_root_logical_bdev | awk '\$2!="legacy" {print \$1}'|
	    while read ds_name; do
                /sbin/zfs inherit mountpoint "\$ds_name"
	    done
	/sbin/zfs set mountpoint=/ $ABE_root_logical_bdev
	EOF
    fi
}

################################################################################
# Name:		<main>
# Description:	Main code (outside of any function definitions) - executed at script startup.
# Local Prefix:	<none>
# Arguments:	$0...$n = All arguments specified by user on command line that invoked this script.
################################################################################

# Ignore all the signals.
# 1- SIGHUP (hangup)
# 2- SIGINT (user interrupt)
# 3- SIGQUIT (user quit)
# 9- SIGKILL (kill process - can not be caught or ignored :)
# 15- SIGTERM (software termination request)
trap "" 1 2 3 9 15

##########
# If luactivate is invoked in maintenance mode, then it needs to perform
# the out of service administration. We do this by executing '/bin/who -r',
# (Indicates the current run-level of the init process) and see if the
# run-level is "s" or "S" (single user mode) or "1" (system administrator 
# mode) - if so then we are in single user / maintenance mode. If 'who -r'
# does not return any value, then use 'who -a' and attempt to extract
# the run-level. This is for 2.6 systems where 'who -r' in single user mode
# does not return any value...
#
# Output looks like this in single user mode:
#   --> # who -r
#   -->   .       run-level S  Mar 27 19:48     S      0  ?
# Output looks like this in system maintenance mode:
#   --> # who -r
#   -->   .       run-level 1  Mar 28 09:50     1      0  S
# Output looks like this in non-single user mode:
#   --> # who -q
#   -->   .       run-level 3  Mar 24 11:06     3      0  S
##########

initRunLevel="`LANG=C LC_ALL=C /bin/who -r | /bin/awk '{print $3; exit 0}'`"
if [ -z "${initRunLevel}" ] ; then
  initRunlevel="`LANG=C LC_ALL=C /bin/who -a | /bin/awk '{if ($2 == \"run-level\") {print $3; exit 0}}'`"
fi

# if called from luupd_boot with the "-u" option then act as the
# system is not in single user mode - the -u option is used by luupd_boot
# to make immediate changes to a boot environment following a lucreate/lumake
if [ "$1" = "-u" -o "$2" = "-u" ] ; then
  # -u specified - set initRunLevel such that it does not appear to
  # indicate the system is in single user mode
  initRunLevel="xxx"
fi

# Check if we are booted off the failsafe. If we are, we are in
# maintenance mode irrespective of what the run level is.
# This applies to both SPARC and x86
oosmode=""
/bin/df -k / | /bin/grep /ramdisk > /dev/null 2>&1
if [ "$?" -eq 0 ]; then
   oosmode=yes
fi

if [ "${initRunLevel}" = "S" -o "${initRunLevel}" = "s" -o "${initRunLevel}" = "1" -o "$oosmode" = yes ] ; then
  # We are in maintenance mode: prepare for minimal operations.
  # Manually setup environment sufficient to perform the operations required.

  TEXTDOMAIN="SUNW_INSTALL_LU_SCRIPTS" ; export TEXTDOMAIN

  # in single user fallback mode - there is no guarantee that /usr contains
  # live upgrade, so set live upgrade's path variables to /mnt if live
  # upgrade is installed there otherwise set them to /usr

  LUPRINTF='echo'

  if [ -d /mnt/usr/lib/lu ] ; then
    LUBIN='/mnt/usr/lib/lu'
    LUETCBIN='/mnt/etc/lib/lu'
    LUPRINTF='/mnt/etc/lib/lu/luprintf'
  else
    LUBIN='/usr/lib/lu'
    LUETCBIN='/etc/lib/lu'
    LUPRINTF='/etc/lib/lu/luprintf'
  fi

  # Verify that no arguments have been entered and alert user that system is in maintenance mode.

  if [ "${initRunLevel}" = "1" ] ; then
    echo "${LU_PROG_NAME}: ""`gettext 'The system is in system administrator maintenance mode.'`" >&2
  else
    echo "${LU_PROG_NAME}: ""`gettext 'The system is in single user maintenance mode.'`" >&2
  fi

  if [ "$#" -ne "0" ] ; then
    echo "${LU_PROG_NAME}: ""`gettext 'Command line arguments not allowed in maintenance mode: '`""<$*>" >&2
    echo "${LU_PROG_NAME}: ""`gettext 'ERROR: The system is in maintenance mode - luactivate can only be used with no command line options or arguments to fallback to the previously working boot environment.'`" >&2
    echo "${LU_PROG_NAME}: ""`gettext 'USAGE in system maintenance mode: '`${LU_PROG_NAME}" >&2
    exit 2
  fi

  # We are in maintenance mode so do the OOS administration tasks.
  # (This means the system is in single user mode and luactivate is used
  # to "fallback" to the previously activated boot environment).
  do_fallback
  exit "$?"
fi

# Dot the defaults file.

if [ ! -s /etc/default/lu ] ; then
  echo "${LU_PROG_NAME}: ""`gettext 'ERROR: Live Upgrade not installed properly (/etc/default/lu not found).'`"
  exit 1
fi
. /etc/default/lu

# Default global variables we expect to be set from /etc/default/lu.

LUBIN=${LUBIN:=/usr/lib/lu}

# Dot the Live Upgrade library functions.

if [ ! -s ${LUBIN}/lulib ] ; then
  echo "${LU_PROG_NAME}: ""`gettext 'ERROR: The Live Upgrade product is not installed properly (${LUBIN}/lulib not found).'`"
  exit 1
fi

. ${LUBIN}/lulib

  ######################################################################################
  ##################### Command line option and argument processing ####################
  ######################################################################################

# Reset all command line parse flags to default values.
flag_l="" # -l f - log file path.
flag_n="" # -n "n" - be name.
flag_o="" # -o f - output file path.
flag_s="" # -s - sync flag.
flag_u="" # -u - update now (do not delay).
flag_x="" # -x n - set debug level to n (PRIVATE).

# Validate the command line arguments.

while [ $# -ne 0 ] ; do
  while getopts l:n:o:usx:X c ; do
    case $c in
      l) # -l f - error log file path.
	 # This overrides the LU_ERROR_LOG_FILE setting read from /etc/default/lu
	 lulib_cannot_duplicate_option "${flag_l}" "${OPTARG}" "-l"
	 ${LUPRINTF} -lp2D - "`gettext 'Verifying that the error log file <%s> specified can be created and appended to.'`" "${OPTARG}"
	 ERRMSG="`${LUPRINTF} -c \"${OPTARG}\" 2>&1`"
	 if [ $? -ne 0 ] ; then
	   [ -n "${ERRMSG}" ] && ${LUPRINTF} -elp2 '%s' "${ERRMSG}"
	   ${LUPRINTF} -Eelp2 "`gettext 'Argument <%s> to -l option may not be created or appended to.'`" "${OPTARG}"
	   exit 3
	 fi
	 flag_l="${OPTARG}"
	 lulib_set_error_log_file "${flag_l}"
	 ;;
      n) # -n "n" - be name.
	 lulib_cannot_duplicate_option "${flag_n}" "${OPTARG}" "-n"
	 flag_n="${OPTARG}"
	 ;;
      o) # -o f - output file path.
	 # This overrides the LU_SESSION_LOG_FILE setting read from /etc/default/lu
	 lulib_cannot_duplicate_option "${flag_o}" "${OPTARG}" "-o"
	 ${LUPRINTF} -lp2D -  "`gettext 'Verifying that the session log file <%s> can be created and appended to.'`" "${OPTARG}"
	 ERRMSG="`${LUPRINTF} -c \"${OPTARG}\" 2>&1`"
	 if [ $? -ne 0 ] ; then
	   [ -n "${ERRMSG}" ] && ${LUPRINTF} -elp2 '%s' "${ERRMSG}"
	   ${LUPRINTF} -Eelp2 "`gettext 'Argument <%s> to -o option may not be created or appended to.'`" "${OPTARG}"
	   exit 3
	 fi
	 flag_o="${OPTARG}"
	 lulib_set_session_log_file "${flag_o}"
	 ;;
      s) # -s - sync flag.
	 flag_s="yes"
	 ;;
      u) # -u - update now (do not delay). (PRIVATE)
	 flag_u="yes"
	 ;;
      x) # -x n - set debug level to n (PRIVATE).
	 # This overrides the default setting read from /etc/default/lu
	 lulib_cannot_duplicate_option "${flag_x}" "${OPTARG}" "-x"
	 /bin/test "${OPTARG}" -ge 0 2>/dev/null
	 if [ $? -gt 1 ] ; then
	   ${LUPRINTF} -Eelp2 "`gettext 'Argument <%s> to -x option is not a number.'`" "${OPTARG}"
	   usage 3
	 fi
	 flag_x="${OPTARG}"
	 lulib_set_debug "${flag_x}"
	 ;;
      X) # -X - set XML output mode.
	  lulib_set_output_format 'xml'
	  ;;
      \?) # unknown - option.
	  usage 3
    esac
  done

  # Found either end of arguments, +option, or non-option argument; shift out
  # what has been processed so far; if a non-option argument is present
  # capture it and continue processing the command line arguments.
  shift `/bin/expr $OPTIND - 1`
  OPTIND=1
  if [ $# -ne 0 -a "$1" = '+X' ] ; then
      # +X - set TEXT output mode.
      lulib_set_output_format 'text'
      shift
  else
    break
  fi
done

# Fixup debug, session log, and error log settings
lulib_fixup_startup_settings

  ######################################################################################
  ############ Validate all command line arguments and options as possible #############
  ######################################################################################

FULL_COMMAND_LINE="${LU_PROG_NAME} $*"

# Validate the number of arguments.
if [ $# -gt 1 ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'The boot environment name should be enclosed in single quotes, like %c%s%c.'`" "'" "$*" "'"
  usage 3
fi

# Check for existence and non-zero size of lutab file.

if [ ! -f ${LU_LUTAB_FILE} -o ! -s ${LU_LUTAB_FILE} ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'No boot environments are configured on this system.'`"
  exit 1
fi

# If -u not specified (do not update now) then delayed update
# requested - check to see if a BE is currently active - if so cannot
# activate a BE yet.
if [ -z "${flag_u}" ] ; then
  lulib_check_any_be_busy
  if [ $? -ne 0 ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'A boot environment is busy with another operation: unable to activate.'`"
    exit 1
  fi
fi


# Name of target BE (ABE).
if [ -n "${flag_n}" -a -z "$1" ] ; then
  BE_NAME="${flag_n}"
elif [ -z "${flag_n}" -a -n "$1" ] ; then
  BE_NAME="$1"
elif [ -z "${flag_n}" -a -z "$1" ] ; then
  BE_NAME=""
else
  ${LUPRINTF} -Eelp2 "`gettext 'You must specify the boot environment to activate either with the <-n> option or by providing the boot environment name on the command line, but not both.'`"
  usage 3
fi

# Determine the name of current BE (PBE).
CURR_BE="`lulib_lucurr`"
if [ $? != 0 ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine the name of the current active boot environment.'`"
  exit 1
fi

  ######################################################################################
  ############## If no BE name, then show name of BE that will boot next ###############
  ######################################################################################

if [ -z "${BE_NAME}" ] ; then
  # Display the name of BE that will be active upon next reboot.
  # echo "Following BE will be active upon next reboot of the machine:"
  if [ -f $NEXT_ACTIVE ] ; then
    ${LUPRINTF} -lp2D - "`gettext 'Requested name of active BE on next reboot: returning next BE activated <%s>.'`" "`/bin/head -1 ${NEXT_ACTIVE}`"
    /bin/cat "${NEXT_ACTIVE}"
  else
    ${LUPRINTF} -lp2D - "`gettext 'Requested name of active BE on next reboot: returning current BE <%s>.'`" "${CURR_BE}"
    echo "$CURR_BE"
  fi
  exit 0
fi

  ###################################################################################
  ############ If ABE is a GRUB BE, convert and propagate the GRUB menu #############
  ###################################################################################
if [ "$LU_SYSTEM_ARCH" = i386 ]; then
   lulib_ask_for_menu_propagate
   if [ "$?" -eq 1 ]; then
      exit 2
   fi
fi

  ######################################################################################
  ############### Get the configuration of the current boot environment ################
  ######################################################################################

get_pbe_config "${CURR_BE}" "" ""
if [ $? != 0 ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine the configuration of the current boot environment <%s>.'`" "${CURR_BE}"
  exit 2
fi

  ######################################################################################
  ########## If -u is not specified (do not update now), handle special cases. #########
  ######################################################################################

if [ -z "${flag_u}" ] ; then
  # No -u specified - delayed update.

  # Validate the given BE name. 
  lulib_validate_be "${BE_NAME}"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to activate boot environment <%s>.'`" "${BE_NAME}"
    exit 1
  fi

  # If the BE to be activated is not the current BE, mount the BE and
  # perform appropriate synchronization and validity checks.

  if [ "$BE_NAME" != "$CURR_BE" ] ; then
    # Unset failed flag - set on any failure to unmount BE and exit with failure.
    failed=''

    # Mount the BE to be activated.
    SYNCBE_ID=`${LUETCBIN}/ludo get_be_id "$BE_NAME" 2>&1`
    if [ $? != 0 ] ; then
      [ -n "${SYNCBE_ID}" ] && ${LUPRINTF} -Eelp2 '%s' "${SYNCBE_ID}"
      ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine boot environment ID of target boot environment <%s>.'`" "${BE_NAME}"
      exit 1
    fi
    SYNCMTPT="`LU_OUTPUT_FORMAT=text ${LUBIN}/lumount -i /etc/lu/ICF.${SYNCBE_ID} 2>${TMP_RESULT_FILE}`"
    if [ "$?" -ne "0" ] ; then
      [ -s "${TMP_RESULT_FILE}" ] && ${LUPRINTF} -elp2 '%R' < "${TMP_RESULT_FILE}"
      ${LUPRINTF} -Eelp2 "`gettext 'Unable to mount the boot environment <%s>.'`" "${BE_NAME}"
      /bin/rm -f "${TMP_RESULT_FILE}"
      exit 1
    fi
    /bin/rm -f "${TMP_RESULT_FILE}"

    ${LUPRINTF} -lp2D - "`gettext 'Mounted ABE<%s> at <%s>.'`" "${BE_NAME}" "${SYNCMTPT}"

    # If synchronization is requested, set the synchronization key file.
    if [ -n "${flag_s}" -o -f $SYNCKEY ] ; then
      ${LUPRINTF} -lp1S ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'A Live Upgrade Sync operation will be performed on startup of boot environment <%s>.'`" "${BE_NAME}"
      echo "${CURR_BE}" >$SYNCMTPT/${SYNCKEY}
    fi

    # Check to see if the BE is partially upgraded.
    check_os_on_be "${SYNCMTPT}"
    [ "$?" -ne '0' ] && failed='yes'

    # Check for any file synchronization problems.
    if [ -n "${flag_s}" -o -f $SYNCKEY ] ; then
        run_activate_sync "${SYNCMTPT}"
    fi
    [ -f $SYNCKEY ] && /bin/rm -f $SYNCKEY

    # Unmount the BE to be activated.
    ${LUBIN}/luumount -f -i /etc/lu/ICF.${SYNCBE_ID}

    # If checks failed, exit.
    if [ -n "${failed}" ] ; then
      ${LUPRINTF} -Eelp2 "`gettext 'Unable to activate boot environment <%s>.'`" "${BE_NAME}"
      exit 1
    fi
  fi

  if [ -f $NEXT_ACTIVE ] ; then
    grep "^${BE_NAME}$" $NEXT_ACTIVE >/dev/null
    if [ $? -eq 0 ] ; then 
      ${LUPRINTF} -Wlp1 "`gettext 'Boot environment <%s> is already activated.'`" "${BE_NAME}"
      exit 0
    fi
    # See if we are reverting to the CURR_BE. If we are, then just
    # remove any older activation data. We need not do anything
    # to make the CURR_BE active other than removing OTHER_BE's
    # activation data.
    if [ "$BE_NAME" = "$CURR_BE" ] ; then
      ${LUPRINTF} -lp1 "`gettext 'Activating the current boot environment <%s> for next reboot.'`" "${CURR_BE}"
      # We don't need delay and fallback data
      /bin/rm -f /etc/lu/DelayUpdate/vtoc.*
      /bin/rm -f /etc/lu/DelayUpdate/boot.*
      /bin/rm -f /etc/lu/DelayUpdate/${MBR}
      /bin/rm -f /etc/lu/DelayUpdate/${BOOT_MENU_FILE}
      /bin/rm -f /etc/lu/DelayUpdate/${PBE_BOOT_MENU_FILE}
      /bin/rm -f /etc/lu/DelayUpdate/installgrub
      /bin/rm -f /etc/lu/DelayUpdate/stage1
      /bin/rm -f /etc/lu/DelayUpdate/stage2
      /bin/rm -f /etc/lu/DelayUpdate/installboot
      /bin/rm -f /etc/lu/DelayUpdate/pboot
      /bin/rm -f /etc/lu/DelayUpdate/bootblock
      /bin/rm -f /etc/lu/DelayUpdate/activate.sh /etc/lu/DelayUpdate/exec_activate.sh
      
      # Store name of the BE to be activated upon reboot in the file .NEXT_ACTIVE
      echo "$CURR_BE" > $NEXT_ACTIVE

      ${LUPRINTF} -lp1S ${LU_SYSLOG_FACILITY}.${LU_SYSLOG_PRIORITY} "`gettext 'The current boot environment <%s> has been activated for the next reboot.'`" "${CURR_BE}"
      exit 0
    fi
  else
    # Since the last boot, no-one has done an active. In this case,
    # if lucurr is BE_NAME then we must be trying to
    # re-activate the current BE. 
    if [ "$BE_NAME" = "$CURR_BE" ] ; then
      ${LUPRINTF} -Wlp1 "`gettext 'Boot environment <%s> is already activated.'`" "${BE_NAME}"
      exit 0
    fi
  fi

  # No -u specified - delayed update: destroy any previous delayed
  # update luactivate and create new delayed update script

  # Create/truncate the script file and set "LU_PROG_NAME"
  create_delayupdate_script "${FULL_COMMAND_LINE}"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} "`gettext 'Unable to create the delayed update script: cannot activate boot environment <%s>.'`" "${CURR_BE}"
    exit 1
  fi
fi


  ######################################################################################
  ################# Get the configuration of the next boot environment #################
  ######################################################################################

get_abe_config "${BE_NAME}"
if [ $? != 0 ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine the configuration of the target boot environment <%s>.'`" "${BE_NAME}"
  exit 2
fi

  ######################################################################################
  ################ Update vtoc and OS loader on target boot environment ################
  ######################################################################################

# No need to update the VTOC if it is a veritas encapsulated boot
# disk; this is because Veritas does strange things with the vtoc and
# we dont want to destroy the encapsulation. So it is assumed that if
# the target root of a BE is a Veritas encapsulated drive, 1) it has
# only one root parititon on it, and 2) it is already marked as the
# boot partition. To change this we need to work with Veritas to figure
# out how to handle the situation where a physical drive has more than
# one encapsulated boot partition in it...
dont_write_vtoc=""
echo "${ABE_root_logical_bdev}" | grep "^/dev/vx/dsk/" > /dev/null 2>&1
if [ "$?" -eq "0" ] ; then
  dont_write_vtoc="yes"
fi

${LUPRINTF} -lp2D - "`gettext 'Veritas root ? <%s>.'`" "${dont_write_vtoc}"

# Check if the system uses a x86 boot partition
/bin/grep -v '^#' /etc/vfstab | /bin/grep "[ 	]/boot[ 	]*pcfs[ 	]" >/dev/null
ret1="$?"
/bin/grep -v '^#' /etc/vfstab | /bin/grep "[ 	]/stubboot[ 	]*pcfs[ 	]" >/dev/null
ret2="$?"

SYS_has_bootpart=""
if [ "$ret1" -eq 0 -o "$ret2" -eq 0 ]; then
   SYS_has_bootpart=yes
fi

#
# NOTE: GRUB boot doesn't need the ROOT tag in VTOC. This allows us to
#       switch GRUB boot BEs without modifying VTOC. We still go through
#	all the steps however a) for compatibility b) to simplify the code
#

if [ "$BE_NAME" = "$CURR_BE" ] ; then
  ${LUPRINTF} -lp1 "`gettext 'Activating the current boot environment <%s> for next reboot.'`" "${CURR_BE}"

  if [ -z "${dont_write_vtoc}" ] ; then
    # Obtain the vtoc of PBE boot disk
    get_be_vtoc $PBE_id $PBE_boot_disk

    # Edit vtoc of the PBE boot disk, so that PBE ROOT and STAND are active
    edit_be_vtoc $PBE_id $PBE_root_slice

    # Write the vtoc to PBE boot disk.
    write_be_vtoc $PBE_id $PBE_boot_disk "${CURR_BE}" "${CURR_BE}" "${flag_u}"
  else
    ${LUPRINTF} -Welp2 "`gettext 'Assuming vtoc on logical device <%s> already has slice <%s> tagged as BOOT slice.'`" "${ABE_root_logical_bdev}" "${ABE_root_bdev}"
  fi
else
  if [ -z "${dont_write_vtoc}" ] ; then
    # Obtain the vtoc of PBE boot disk
    get_be_vtoc $PBE_id $PBE_boot_disk

    # Obtain the vtoc of ABE boot disk
    get_be_vtoc $ABE_id $ABE_boot_disk

    # Edit vtoc of the ABE boot disk, so that ABE ROOT and STAND are active
    edit_be_vtoc $ABE_id $ABE_root_slice

    # Write the vtoc to ABE boot disk.
    write_be_vtoc $ABE_id $ABE_boot_disk "${BE_NAME}" "${CURR_BE}" "${flag_u}"
  else
    ${LUPRINTF} -Welp2 "`gettext 'Assuming vtoc on logical device <%s> already has slice <%s> tagged as BOOT slice.'`" "${ABE_root_logical_bdev}" "${ABE_root_bdev}"
  fi

  # Now check if the ABE-Root slice is not mounted and is mountable.
  chk_mount $ABE_root_logical_bdev $ABE_root_fstyp "${BE_NAME}"
  if [ $? -ne 0 ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'The root slice <%s> of the target boot environment <%s> is not available.'`" "${ABE_ROOT_DEV}" "${BE_NAME}"
    exit 1
  fi
  
  # Write appropriate loader on to the disk.
  # If the system has an x86 boot partition, wait until the boot partition is switched in set_boot() before writing the loader
  if [ "$ABE_boot_method" = GRUB -o "$ABE_boot_method" = DBOOT ]; then
      if [ -z "$SYS_has_bootpart" ]; then
         update_grub_loader "${CURR_BE}" "${BE_NAME}"
  	 if [ "$?" -ne 0 ] ; then
     	    ${LUPRINTF} -Eelp2 "`gettext 'Unable to write bootstrap information to root slice <%s> of target boot environment <%s>.'`" "${ABE_root_bdev}" "${BE_NAME}"
            exit 1
         fi
      fi
  else
      if [ -z "$SYS_has_bootpart" ]; then
         write_loader $ABE_root_bdev "${flag_u}" "${BE_NAME}" "${CURR_BE}"
  	 if [ "$?" -ne 0 ] ; then
     	    ${LUPRINTF} -Eelp2 "`gettext 'Unable to write bootstrap information to root slice <%s> of target boot environment <%s>.'`" "${ABE_root_bdev}" "${BE_NAME}"
            exit 1
         fi
      fi
  fi

fi


  ######################################################################################
  ##################### Create and propagate fallback information ######################
  ######################################################################################

if [ -z "${flag_u}" ] ; then
  # Store the required PBE variables in the file /etc/lu/.CURR_VARS
  echo "BEID=$PBE_id" >$CURR_VARS
  echo "BEDISK=$PBE_boot_disk" >>$CURR_VARS
  echo "BENAME=$CURR_BE" >>$CURR_VARS
  echo "BEROOT=$PBE_root_bdev" >>$CURR_VARS
  echo "BEROOT_FSTYP=$PBE_root_fstyp" >>$CURR_VARS

  # Propagate the BE variables file to all BEs.
  propagate_be_file "${CURR_VARS}"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to propagate fallback information to all boot environments.'`"
    exit 1
  fi
fi

  ######################################################################################
  ########################## Delayed update final processing ###########################
  ######################################################################################

if [ -z "${flag_u}" ] ; then
  # -u is not specified (delayed update):
  # 1. Change the system boot parameters.
  # 2. Display activate/fallback information.
  # 3. Create the delayed update execution script.
  if [ "$BE_NAME" = "$CURR_BE" ] ; then
    set_boot "$PBE_root_bdev" "" "${BE_NAME}" "" ""
  else
    set_boot "$ABE_root_bdev" "" "${BE_NAME}" "" ""
  fi

  if [ "$LU_SYSTEM_ARCH" = sparc -a "$ABE_root_fstyp" = "zfs" ]; then
    update_sparc_menu "${BE_NAME}" "$ABE_root_logical_bdev"
  fi
fi

#
# For x86, Boot partition (if any) has been saved. Safe to install GRUB on it now
#
if [ "$ABE_boot_method" = GRUB ]; then
   if [ -n "$SYS_has_bootpart" ]; then
      update_grub_loader "${CURR_BE}" "${BE_NAME}"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} -Eelp2 "`gettext 'Failed to update GRUB loader.'`"
         exit 1
      fi
   fi

elif [ -n "$SYS_has_bootpart" ]; then
     write_loader $ABE_root_bdev "${flag_u}" "${BE_NAME}" "${CURR_BE}"
     if [ "$?" -ne 0 ] ; then
        ${LUPRINTF} -Eelp2 "`gettext 'Unable to write bootstrap information to root slice <%s> of target boot environment <%s>.'`" "${ABE_root_bdev}" "${BE_NAME}"
        exit 1
     fi
fi

#
# After everyone has finished mucking with the fdisk table, change the fdisk
# partition id of any device in /etc/lutab from Solaris2 to Solaris
#
if [ "$LU_SYSTEM_ARCH" = i386 -a -z "${flag_u}" ]; then
   fdisk130 ""
fi

if [ -z "${flag_u}" ]; then
  # Store name of the BE to be activated upon reboot in the file .NEXT_ACTIVE
  echo "$BE_NAME" > $NEXT_ACTIVE

  # Display activate and fallback information.
  if [ "$BE_NAME" != "$CURR_BE" ] ; then
    disp_activate_info
    disp_fallback_info 
  fi

  if [ "$LU_SYSTEM_ARCH" = i386 -o "$LU_SYSTEM_ARCH" = sparc ]; then
     disable_boot_verif_svc "$BE_NAME"
  fi

  # Create the delayed update execution processing script
  create_delayupdate_exec_script "${BE_NAME}" "${FULL_COMMAND_LINE}"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to create shutdown execute script; unable to activate boot environment <%s>.'`" "${BE_NAME}"
    /bin/rm -f "${DELAY_UPD_SCRIPT}" "${DELAY_UPD_SCRIPT_EXEC}"  
    exit 1
  fi

  # see if dataset is a clone and promote it
  if [ "$ABE_root_fstyp" = "zfs" ]; then
     dstype=`lulib_get_dataset_type $ABE_root_logical_bdev`
     if [ "$dstype" = "clone" ]; then
         lulib_promote_BE_to_top $ABE_root_logical_bdev
     fi
  fi

  if [ "$LU_SYSTEM_ARCH" = i386 ]; then
     lulib_propagate_findroot_GRUB
     if [ "$?" -ne 0 ]; then
        ${LUPRINTF} -Eelp2 "`gettext 'Could not propagate GRUB that supports the findroot command.'`"
     fi
  fi

  ${LUPRINTF} -lp1 "`gettext 'Activation of boot environment <%s> successful.'`" "${BE_NAME}"
fi

exit 0
