#!/bin/ksh -p
#
# Copyright 2003 by Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#pragma	ident	"@(#)stmsboot.ksh	1.7	03/11/21 SMI"
#

# print usage
function usage {
    echo "Usage: stmsboot [-e | -d | -L | -l controller_number]"
    echo "\n\te - Enable the enumeration of devices connected to the boot"
    echo "\t\tcontroller port under scsi_vhci (the multipathing virtual"
    echo "\t\tcontroller).  Devices on the boot controller port will be"
    echo "\t\tenumerated under the scsi_vhci virtual controller and will"
    echo "\t\tbe controlled by STMS.\n"
    echo "\td - Disable the enumeration of devices connected to the boot"
    echo "\t\tcontroller port under scsi_vhci.  Devices on the boot"
    echo "\t\tcontroller port will be enumerated directly under the"
    echo "\t\tphysical controller and will not be controlled by STMS.\n"
    echo "\tL - Display the device name changes from non-STMS device names"
    echo "\t\tto STMS device names that would occur if STMS were enabled.\n"
    echo "\tl - controller_number"
    echo "\t\tDisplay the device name changes from non-STMS device names"
    echo "\t\tto STMS device names that would occur for the given controller"
    echo "\t\tif STMS were enabled.\n"
}

# commit will copy all the tmp files in /var/tmp into into the /etc
function m_commit {
    cp $TMP_PATH_TO_INST $PATH_TO_INST
    cp $TMP_ETC_SYSTEM $ETC_SYSTEM
    cp $TMP_VFSTAB $VFSTAB    
    cp $TMP_DUMPADM $DUMPADM    
    
    echo "cp $ROOT_TMP_PATH_TO_INST_SAVE $ROOT_PATH_TO_INST" >> $UNDO_SCRIPT
    echo "cp $ROOT_TMP_ETC_SYSTEM_SAVE $ROOT_ETC_SYSTEM" >> $UNDO_SCRIPT
    echo "cp $ROOT_TMP_VFSTAB_SAVE $ROOT_VFSTAB" >> $UNDO_SCRIPT
    echo "cp $ROOT_TMP_DUMPADM_SAVE $ROOT_DUMPADM" >> $UNDO_SCRIPT
}

# saves off the /etc/path_to_inst, /etc/system, /etc/vfstab and
# /etc/dumpadm.conf files into /var/tmp
function m_save {
    cp $PATH_TO_INST $TMP_PATH_TO_INST
    cp $PATH_TO_INST $TMP_PATH_TO_INST_SAVE
    cp $ETC_SYSTEM $TMP_ETC_SYSTEM
    cp $ETC_SYSTEM $TMP_ETC_SYSTEM_SAVE
    cp $VFSTAB $TMP_VFSTAB
    cp $VFSTAB $TMP_VFSTAB_SAVE
    cp $DUMPADM $TMP_DUMPADM
    cp $DUMPADM $TMP_DUMPADM_SAVE
    
    # create the undo script in case we need to restore later
    rm -f $UNDO_SCRIPT
    touch $UNDO_SCRIPT
    chmod 755 $UNDO_SCRIPT
    echo "#!/bin/ksh" >> $UNDO_SCRIPT
    echo "ROOT_MOUNT=\"\"" >> $UNDO_SCRIPT
    echo '[[ $# -eq 1 ]] && ROOT_MOUNT=$1' >> $UNDO_SCRIPT
}

update_path()
{
        ES=`eeprom boot-device`

        NS=`echo $ES |awk -F= '{print $2}'`

        set $NS

        STR=$SELECTED_PATH

        while [ "$1" != "" ]
        do
                if [ "$1" == "$SELECTED_PATH" ]
                then
                        shift
                        continue
                fi

		NEWLEN=`echo "$STR $1" |wc -c`

		if [ $NEWLEN -gt 256 ]
		then
			break
		fi

                STR="$STR $1"
                shift
        done
}

# this function returns information guid and purple mode information for
# a device
function get_deviceInfo {
    [[ $DEBUG -eq 1 ]] && set -x
    # check to make sure device is a valid device
    if [[ ! -a ${devices[$i]} ]]; then
	echo "Error: ${devices[$i]} is an invalid link"
	return 1
    fi

    # retrieve the /devices path 
    physpath=`ls -l ${devices[$i]} | sed 's/.*\(\/devices.*\)/\1/'`
    [[ $VERBOSE -eq 1 ]] && echo "\t\tphysical path= $physpath"
    
    physpath_raw=${physpath},raw
    [[ $VERBOSE -eq 1 ]] && echo "\t\tphysical path raw= $physpath_raw"
    
    # check to make sure this is a valid physical path    
    if [[ ! -a $physpath_raw ]]; then
	echo "Error: $physpath_raw is an invalid physical path"
	return 1
    fi

    # do not list vhci paths.
    echo $physpath | grep "scsi_vhci" > /dev/null 2>&1
    if [[ $? -eq 0 ]]; then
        return 1;
    fi

    # check to make sure this is a ssd device path
    echo $physpath | grep "/ssd" > /dev/null 2>&1
    if [[ $? -eq 1 ]]; then
	# if I am just listing paths, I do not want to print an error message
	[[ $OPTION_l -eq 0 && $LISTALL -eq 0 ]] &&
	    echo "Error: $physpath is not a STMS device path."
	return 1
    fi
   
    ctd=`echo ${devices[$i]} | sed 's/.*\/dev\/dsk\/\(.*\)s.*/\1/'`
    [[ $VERBOSE -eq 1 ]] && echo "\t\tctd: $ctd"
    
    # do the inquiry and retrieve GUID from 0x83
    failure_count=0
    while [[ $failure_count -lt 3 ]]; do
	get_guidOutput=`${lib_dir}/stmsboot_util -g $physpath_raw`
	if [[ $? -eq 0 ]]; then
	    break
	else
	    failure_count=`expr $failure_count + 1`
	fi
    done
    if [[ $failure_count -eq 3 ]]; then
	return 1
    fi
   
    guid=`echo $get_guidOutput | sed 's/.*GUID: //'`
    [[ $VERBOSE -eq 1 ]] && echo "\t\tguid: $guid"
    mode=`echo $get_guidOutput | awk ' "asymmetric_mode:" == $1 { print $2 }'`
    
    # Get the Controller number
    # ls -l on /dev/rdsk looking for a link with scsi_vhci.
    # take one of the links and return X from cXtYdZ....
    if [[ "$new_cnum" == "" ]]; then
	new_cnum=`ls -l /dev/rdsk | grep scsi_vhci  | grep c | tail -1 |
		sed 's/.* c\(.*\)t.*/\1/g'`

	if [[ "$new_cnum" == "" ]]; then
	    new_cnum=`ls /dev/cfg | grep "^c" | sed 's/.*c//' | sort -n |
		    tail -1 | sed 's/\@.*//'`
	    new_cnum=`expr $new_cnum + 1`
	fi
    fi

    # check to make sure new_cnum is a number
    tmp=`expr $new_cnum + 1` > /dev/null 2>&1
    if [[ $? -ne 0 ]]; then
	echo "Error: Invalid controller number: $new_cnum"
	return 1
    fi
    [[ $VERBOSE -eq 1 ]] && echo "\t\tcontroller number: $new_cnum"
  
    # turn all letters into capital letters 
    typeset -u guid_caps=$guid
}

# this will list out the new mpxio paths for the specified controller
function m_listNewPaths_oneController {
    [[ $DEBUG -eq 1 ]] && set -x
    orig_cnum=$CNUM

    # sanity check to make sure orig_cnum is a number
    tmp=`expr $orig_cnum + 1` > /dev/null 2>&1
    if [[ $? -ne 0 ]]; then
	echo "Error: Invalid entry: $orig_cnum"
	return 1
    fi

    devices_found=0
    ls /dev/dsk/c${orig_cnum}t*s0 > /dev/null 2>&1
    if [[ $? -eq 0 ]] then
	devices=`ls /dev/dsk/c${orig_cnum}t*s0`
    else
	return 1
    fi
    
    set -A devices `echo $devices` 
    i=0
    while [[ $i -lt ${#devices[*]} ]]; do
	[[ $VERBOSE -eq 1 ]] && echo "\tWorking on Device: ${devices[$i]}"

	get_deviceInfo
	if [[ $? -ne 0 ]]; then
	    i=`expr $i + 1`
	    continue
	fi
	devices_found=`expr $devices_found + 1`
	typeset -u guid_caps=$guid
        if [[ "$guid" == "" ]]; then
	    i=`expr $i + 1`
        else 
	    echo "/dev/rdsk/${ctd}\t\t/dev/rdsk/c${new_cnum}t${guid_caps}d0"

	    if [[ $LISTALL -eq 0 ]]; then
	        # Check if the device is under the control of VxVM.
	        if [[ $slvm_metastat -eq 1 ]]; then
	            grep $ctd $METASTAT_OUTPUT_FILE > /dev/null 2>&1
	            if [[ $? -eq 0 ]]; then
		        echo "\tWarning: $ctd is being used by a Volume Manager.\n"
	            fi
	        fi
	        # Check if the device is under the control of SVM.
	        if [[ $vxvm_vxdisk -eq 1 ]]; then
	            grep $ctd $VXDISK_OUTPUT_FILE | grep -v "error"> /dev/null 2>&1
	            if [[ $? -eq 0 ]]; then
		        echo "\tWarning: $ctd is being used by a Volume Manager.\n"
	            fi
	        fi
	    fi

	    i=`expr $i + 1`
        fi
    done
}

# this function will list out mpxio paths for all the devices
# on the system
function m_listNewPaths_allController {
    typeset curpwd

    [[ $DEBUG -eq 1 ]] && set -x
    curpwd=$PWD
    cd /dev/cfg
    controllers=`ls c[0-9]* | sed 's/c//' | sort -n`
    cd $curpwd
    set -A controllers `echo $controllers`
    controller_num=0
    while [[ $controller_num -lt ${#controllers[*]} ]]; do
	[[ $VERBOSE -eq 1 ]] &&
		echo "\tWorking on Device: ${controllers[$controller_num]}"
	CNUM=${controllers[$controller_num]}
	m_listNewPaths_oneController
	controller_num=`expr $controller_num + 1`
    done
}

# mpxio enumerate function
function m_enable {
    [[ $DEBUG -eq 1 ]] && set -x
    [[ $VERBOSE -eq 1 ]] && echo "Starting Enumeration"

    # Obtain the boot device path for mpxio enumeration
    # It is assumed that "df /" gives the /dev/dsk/cxtydz format.
    # Devices connected to boot controller port should not be
    # in use by any volume manager.

    bootdev=`df / | sed 's/.*(\(.*\)).*/\1/g'`

    # get rid of any extra spaces that may be in the bootdev
    bootdev=`echo $bootdev`
    [[ $VERBOSE -eq 1 ]] && echo "\tboot device= $bootdev."

    # sanity check to make sure the /dev/dsk /link actually exists   
    if [[ "$bootdev" == "" || ! -L "$bootdev" ]]; then
	echo "Error: Unable to find root device"
	exit 1 
    fi

    ls -l $bootdev | grep "/ssd" > /dev/null 2>&1
    if [[ $? -eq 1 ]]; then
        echo "Error: $bootdev is not a STMS device"
	exit 1
    fi

    ls -l $bootdev | grep "scsi_vhci" > /dev/null 2>&1
    if [[ $? -eq 0 ]]; then
        echo "Error: Invalid attempt to enable STMS Boot."
	echo "STMS Boot was already enabled on the"
	echo "boot device $bootdev"
	exit 1
    fi
    
    # find path to boot controller and save it off in /var/tmp
    # this will be used as the default path during de-enumeration
    ls -l $bootdev | sed 's/.*\(\/devices.*\)\/ssd.*/\1/' > $UNENUMERATED_ROOT_CONTROLLER

    # get the controller number from /dev/dsk/cXtYdZ.
    orig_cnum=`echo $bootdev | sed 's/\/dev\/dsk\/c\(.*\)t.*/\1/'`
    [[ $VERBOSE -eq 1 ]] && echo "\tbootloop cnum= $orig_cnum"
    if [[ "$orig_cnum" == "" ]]; then
	echo "Error: Unable to retrieve controller number from $bootdev"
	exit 1
    fi

    # sanity check to make sure orig_cnum is a number
    tmp=`expr $orig_cnum + 1` > /dev/null 2>&1
    if [[ $? -ne 0 ]]; then
	echo "Error: Unable to retrieve controller number for the boot controller port"
	exit 1
    fi
  
    # get all the targets connected to this controller 
    devices=`ls /dev/dsk/c${orig_cnum}t*s0`
    if [[ "$devices" == "" ]]; then
	echo "Error: Unable to retrieve devices connected to boot controller port"
	exit 1
    fi
    set -A devices `echo $devices` 

    # save off files in case we need to restore later
    m_save

    # kill the devfsadm deamon
    echo "\nWARNING!!!"
    echo "\tImportant system files will be modified."
    echo "\tThe devfsadmd daemon will be killed."
    echo "\tNew STMS links for devices connected to the boot controller port"
    echo "\twill be created.\n"
    echo "Please make sure that there are no processes running devfsadm,"
    echo "devlinks, or disks from now until the system is rebooted."
    echo "This includes, but is not limited to, initiating DR events.\n"

    while :; do
        print -n "Do you want to continue ? [y/n] (default: n) "
        read FOO
        if [[ "$FOO" == "y" ]]; then
		break;
	else
            if [[ "$FOO" == "n" || "$FOO" == "" ]]; then
                exit 1
            fi
        fi
        echo "Invalid entry: $FOO"
    done

	# Killing devfsadm etc., does not guarantee that controller number
	# or target id etc., will not change.
	# Attempting to kill these processes anyways.
	# Ideal is not to add any new hardware or software during
	# stmsboot operations as documented.

    pkill -9 devlinks
    pkill -9 devfsadm
    pkill -9 disks
    pkill -9 devfsadmd

    echo "Boot controller is c$orig_cnum\n"
    echo "Listed below are the non-STMS device names and their corresponding"
    echo "new STMS device names.\n\n"
    echo "non-STMS device name\t\t\tSTMS device name"
    echo "------------------------------------------------------------------"
    i=0
    
    # bootdevice: flag that will be either 1 or 0.
    #	1 meaning the device is the boot device
    #	0 meaning the device is not the boot device
    bootdevice=0
    # asymmetric_change_mode: flag that will be either 1 or 0
    #	1 meaning device is a t3 and is currently in rw mode
    #	0 meaning either device is not a t3 or is already in mpxio mode
    asymmetric_change_mode=0
    while [[ $i -lt ${#devices[*]} ]]; do
	[[ $VERBOSE -eq 1 ]] && echo "\tWorking on Device: ${devices[$i]}"

	get_deviceInfo
	if [[ $? -ne 0 || "$guid" == "" ]]; then

	    # Check if the device exists.
	    # if it does, then get guid failed. Exit
	    dd if=${devices[$i]} of=/dev/null count=1 >/dev/null 2>&1
	    if [[ $? -eq 0 ]]; then
	        echo "Error: Unable to get device id for ${devices[$i]}"
	        exit 1 
	    fi

	    i=`expr $i + 1`
            continue
	fi
	# if mode is rw, then we need to set the asymmetric_change_mode flag
	if [[ "$mode" == "rw" ]]; then
	    asymmetric_change_mode=1
	fi
	    
	if [[ ! -a ${devices[$i]} ]]; then
	    echo "Error: ${devices[$i]} is an invalid link"
	    i=`expr $i + 1`
	    continue
	fi
   
	# check if this is the bootdevice. 
	[[ "$bootdev" == "${devices[$i]}" ]] && bootdevice=1

	# check to see if device entry already exists in path_to_inst
	# if it doesn't, create a new entry for the boot device in
	# /var/tmp/path_to_inst 
	grep "$guid" $TMP_PATH_TO_INST > /dev/null 2>&1
	if [[ $? -eq 0 ]]; then
	    instance=`grep "$guid" $TMP_PATH_TO_INST | awk ' { print $2 }'` 
	else
	    instance=`grep ssd $TMP_PATH_TO_INST | cut -f2 -d ' ' |
		sort -n | tail -1`
	    instance=`expr $instance + 1` > /dev/null 2>&1
	    if [[ $? -ne 0 ]]; then
		echo "Error: Unable to assign an instance number for $guid"
		exit 1
	    fi
	    echo "\"/scsi_vhci/ssd@g${guid}\" ${instance} \"ssd\"" >> $TMP_PATH_TO_INST
	fi
	if [[ "$instance" == "" ]]; then
	    echo "Error: Unable to retrieve instance number for $guid"
	    exit 1
	fi
	[[ $VERBOSE -eq 1 ]] && echo "\t\tinstance: $instance"
   

	# if /devices/scsi_vhci does not exist, create it 
	[[ ! -d /devices/scsi_vhci ]] && mkdir /devices/scsi_vhci

	minor_num=`expr $instance \* 8` > /dev/null 2>&1
	[[ $VERBOSE -eq 1 ]] && echo "\t\tminor number: $minor_num"

	typeset -u guid_caps=$guid
	echo "/dev/rdsk/${ctd}\t\t/dev/rdsk/c${new_cnum}t${guid_caps}d0"

	# Check if the device is being used by a SVM
	if [[ $slvm_metastat -eq 1 ]]; then
	    grep $ctd $METASTAT_OUTPUT_FILE > /dev/null 2>&1
	    if [[ $? -eq 0 ]]; then
		echo "Error: $ctd is being used by a Volume Manager.\n"
		exit 1
	    fi
	fi
	# Check if the device is being used by VxVM or SEVM
	if [[ $vxvm_vxdisk -eq 1 ]]; then
	    grep $ctd $VXDISK_OUTPUT_FILE | grep -v "error" >/dev/null 2>&1
	    if [[ $? -eq 0 ]]; then
		echo "Error: $ctd is being used by a Volume Manager.\n"
		exit 1
	    fi
	fi

	j=0
	set -A ch a b c d e f g h
	while [[ $j -lt 8 ]]; do
	    buf=`expr $minor_num + $j` > /dev/null 2>&1
	    mknod /devices/scsi_vhci/ssd@g${guid}:${ch[${j}]} b 118 ${buf} > /dev/null 2>&1
	    mknod /devices/scsi_vhci/ssd@g${guid}:${ch[${j}]},raw c 118 ${buf} > /dev/null 2>&1
   
	    cd /dev/dsk
	    # create new /dev/dsk/ link
	    ln -s ../../devices/scsi_vhci/ssd@g${guid}:${ch[${j}]} c${new_cnum}t${guid_caps}d0s${j} > /dev/null 2>&1
	    # add this step into the undo script
	    echo "rm -f \${ROOT_MOUNT}/dev/dsk/c${new_cnum}t${guid_caps}d0s${j}" >> $UNDO_SCRIPT

	    cd /dev/rdsk
	    # create new /dev/rdsk/ link
	    ln -s ../../devices/scsi_vhci/ssd@g${guid}:${ch[${j}]},raw c${new_cnum}t${guid_caps}d0s${j} > /dev/null 2>&1
	    echo "rm -f \${ROOT_MOUNT}/dev/rdsk/c${new_cnum}t${guid_caps}d0s${j}" >> $UNDO_SCRIPT

	    j=`expr $j + 1`
	done
	[[ $VERBOSE -eq 1 ]] && echo "\tDone with mknod"
    
	# now need to modify vfstab and dumpadm.conf
	sed "s/${ctd}/c${new_cnum}t${guid_caps}d0/g" $TMP_VFSTAB > $TMP_VFSTAB_TMP
	mv $TMP_VFSTAB_TMP $TMP_VFSTAB
	sed "s/${ctd}/c${new_cnum}t${guid_caps}d0/g" $TMP_DUMPADM > $TMP_DUMPADM_TMP
	mv $TMP_DUMPADM_TMP $TMP_DUMPADM

	# now modify /etc/system only for the bootdevice
	[[ $bootdevice -eq 1 ]] &&
		echo "rootdev:/scsi_vhci/ssd@g${guid}:a" >> $TMP_ETC_SYSTEM
	bootdevice=0

	i=`expr $i + 1`
    done

    #add fp.conf entry to enable mpxio-boot for the root controller.
    hbaInfo=`ls -l $bootdev | sed 's%.*/devices\(.*\)/fp@.*%\1%'`
    echo $hbaInfo | grep "/fp" > /dev/null 2>&1
    if [[ $? -eq 1 ]]; then
	grep "$hbaInfo" /kernel/drv/fp.conf > /dev/null 2>&1
	if [[ $? -ne 0 ]]; then
	   echo "name=\"fp\" parent=\"$hbaInfo\" port=0 mpxio-disable=\"no\";" \
	    >> /kernel/drv/fp.conf
        fi
    fi

    m_commit
   
    # if purple mp_support is rw mode, print a message telling the user
    # they must set mp_support to be mpxio before rebooting
    if [[ $asymmetric_change_mode -eq 1 ]]; then
	echo "\nWARNING!!!"
	echo "There is at least one Sun StorEdge T3/T3B, or 6x20,"
	echo "that is not in \"mpxio\" mode."
	echo "For the system to function properly, please set"
	echo "mp_support to \"mpxio\" mode on the device(s) now and"
	print -n "press any key to continue."
	read FOO
    fi
    [[ $VERBOSE -eq 1 ]] && echo "Done with Enumeration"
}

# mpxio de-enumerate function
function m_disable {
    [[ $DEBUG -eq 1 ]] && set -x
    [[ $VERBOSE -eq 1 ]] && echo "Starting Deenumerate"

    cxtGUIDd=`df / | sed 's/.*(\/dev\/dsk\/\(.*\)).*/\1/g' | sed 's/s.*//'`
    [[ $VERBOSE -eq 1 ]] && echo "\tcxtGUIDd boot device= $cxtGUIDd"

    if [[ "$cxtGUIDd" == "" ]]; then
	echo "Error: Unable to get the root device"
	exit 1
    fi

    ls -l /dev/rdsk/${cxtGUIDd}s2 | grep "scsi_vhci" > /dev/null 2>&1
    if [[ $? -eq 1 ]]; then
        echo "Error: Invalid attempt to disable STMS Boot."
	echo "STMS Boot was not already enabled on the"
	echo "boot device ${cxtGUIDd}"
        exit 1
    fi

    # get guid from cxtGUIDd and turn into lower case
    guid=`echo $cxtGUIDd | sed 's/.*t\(.*\)d.*/\1/'`        
    if [[ "$guid" == "" ]]; then
	echo "Error: Unable to get the device id from $cxtGUIDd"
	exit 1
    fi
    typeset -l guid=$guid

    # make sure the /dev/rdsk path exists.
    if [[ ! -a /dev/rdsk/${cxtGUIDd}s2 ]]; then
	echo "\tError: Unable to find root device"
	exit 1
    fi 

    vhci=`luxadm display /dev/rdsk/${cxtGUIDd}s2 | grep /scsi_vhci |
	    sed 's/:c.*//'`
    [[ $VERBOSE -eq 1 ]] && echo "\tvhci: $vhci"
    if [[ "$vhci" == "" ]]; then
	echo "Error: Unable to get virtual controller for ${cxtGUIDd}s2"
	exit 1
    fi

    controller_number=0   
    controller_number=`luxadm display /dev/rdsk/${cxtGUIDd}s2 |
	    grep Controller | wc -l`
    #eliminate leading spaces    
    controller_number=`echo $controller_number`
    
    if [[ $controller_number -eq -0 ]]; then
	echo "Error: Unable to retrieve paths for /dev/rdsk/${cxtGUIDd}s2"
	exit 1
    fi

    choice_num=0 
    while :; do
        echo "\nWARNING!!!"
        echo "\tImportant system files will be modified."
        echo "\tThe devfsadmd daemon will be killed.\n"
        echo "Please make sure that there are no processes running devfsadm,"
        echo "devlinks, or disks from now on until the system is rebooted."
	echo "This includes but, is not limited to initiating DR events.\n"

	while :; do
	    print -n "Do you want to continue ? [y/n] (default: n) "
	    read FOO
	    if [[ "$FOO" == "y" ]]; then
		break;
	    else
	        if [[ "$FOO" == "n" || "$FOO" == "" ]]; then
		    exit 1
	        fi
	    fi
	    echo "Invalid entry: $FOO"
	done

	echo "Please choose a device path [1 - ${controller_number}]"
	echo "\nWARNING: Devices connected to the selected device path"
        echo "\twill be enumerated under the physical controller\n"
	luxadm display /dev/rdsk/${cxtGUIDd}s2 |
	    grep Controller | awk ' { print NR ") " $2 }'
	if [[ -a $UNENUMERATED_ROOT_CONTROLLER ]]; then
	    old_controller_port=`cat $UNENUMERATED_ROOT_CONTROLLER` > /dev/null 2>&1
	fi
	if [[ "$old_controller_port" == "" ]]; then
	    default=1
	else
	    default=`luxadm display /dev/rdsk/${cxtGUIDd}s2 | grep Controller |
		awk ' "'$old_controller_port'" == $2 { print NR }'`
	    if [[ "$default" == "" ]]; then
		default=1
	    fi
	fi
	print -n "Choice [default: $default]: "
	read choice_num
	
	if [[ "$choice_num" == "" ]]; then
	    choice_num=$default
	fi
    
	# check to make sure user has inputed a number
	tmp=`expr $choice_num + 1` > /dev/null 2>&1
	if [[ $? -eq 0 && $choice_num -ge 1 && $choice_num -le $controller_number ]]; then
	    break
	else
	    echo "$choice_num is an invalid choice."
	    echo "Please choose a number between 1 and $controller_number"
	fi
    done

    pHCI=`luxadm display /dev/rdsk/${cxtGUIDd}s2 | grep Controller |
	awk ' NR == '"$choice_num"' { print $2 }'`
    if [[ "$pHCI" == "" ]]; then
	echo "Error: Unable to get physical controller for ${cxtGUIDd}s2"
	exit 1
    fi
    [[ $VERBOSE -eq 1 ]] && echo "\tpHCI: $pHCI" 
    
    cnum=`ls -l /dev/cfg | grep "$pHCI" | awk ' { print $9 }'`
    if [[ "$cnum" == "" ]]; then
	echo "Error: Unable to find controller number for $pHCI"
	exit 1
    fi
    [[ $VERBOSE -eq 1 ]] && echo "\tcnum: $cnum" 

    phcidevctl=${pHCI}:devctl
  
    # fields in dump_map are different depending on whether this is a
    # fabric or loop.  In a fabric, Node WWN is column 5.  In a loop,
    # Node WWN is column 6 
    luxadm -e dump_map $phcidevctl | grep AL_PA > /dev/null 2>&1
    if [[ $? -eq 0 ]]; then
	# get all the port-wwns for the devices on this controller
	devices=`luxadm -e dump_map $phcidevctl | grep 'Disk device' |
	    awk ' { print $5 }'`
    else
	# get all the port-wwns for the devices on this controller
	devices=`luxadm -e dump_map $phcidevctl | grep 'Disk device' |
	    awk ' { print $4 }'`
    fi
    if [[ "$devices" == "" ]]; then
	echo "Error: Unable to retrieve devices connected to path $phcidevctl"
	exit 1
    fi
    
    # turn devices into an array
    set -A devices `echo $devices`

    #calling get topology
    topo=`${lib_dir}/stmsboot_util -p $phcidevctl`
    if [[ $? -ne 0 ]]; then
	echo "Error: Unable to get the link topology for $phcidevctl"
	exit 1
    fi
    [[ $VERBOSE -eq 1 ]] && echo "\ttopology: $topo" 

    m_save

    # loop through all devices.
    # need to create cXtYdZ for all devices
    i=0
    while [[ $i -lt ${#devices[*]} ]]; do
	[[ $VERBOSE -eq 1 ]] && echo "\tWorking on device: ${devices[$i]}"

	physpath=${pHCI}/ssd@w${devices[$i]}:a,raw
	[[ $VERBOSE -eq 1 ]] && echo "\t\tphyspath: $physpath"
	if [[ "$topo" == "FC_TOP_PUBLIC_LOOP" || "$topo" == "FC_TOP_FABRIC" ]]; then
	    # for fabric loop, the target is the port-wwn
	    tgt=${devices[$i]}
	elif [[ "$topo" == "FC_TOP_PRIVATE_LOOP" ]]; then

	    #calling get_target
	    tgt=`${lib_dir}/stmsboot_util -t $physpath`
	    if [[ $? -ne 0 ]]; then
		echo "Error: Unable to retrieve non-STMS device link for ${devices[$i]}"
		i=`expr $i + 1`
		continue
	    fi
	    [[ $VERBOSE -eq 1 ]] && echo "\t\ttarget number: $tgt"
	else
	    echo "Error: Unexpected topology: $topo for $phcidevctl"
	    exit 1
	fi
	if [[ "$tgt" == "" ]]; then
	    echo "Error: Unable to retrieve target number for $physpath"
	    exit 1
	fi
    
	# need to get all device address for this WWN.
	display_tmp=/var/tmp/display_tmp.$$
	luxadm display ${devices[$i]} > $display_tmp
	if [[ $? -ne 0 ]]; then

	    # The device may be connected but may not be a valid device.
	    # If it can be opened, fail the operation.
	    # Otherwise, ignore this device. 

	    dd if=$physpath of=/dev/null count=1 >/dev/null 2>&1
	    if [[ $? -eq 0 ]]; then
	        echo "Error: Unable to retrieve paths for ${devices[$i]}"
	        exit 1
	    fi
	    i=`expr $i + 1`
	    continue
	fi 
	paths=`cat $display_tmp | grep "/dev/rdsk" |
	    sed 's/s2//'`
	if [[ "$paths" == "" ]]; then
	    echo "Error: Unable to get device information for ${devices[$i]}"
	    exit 1
	fi
	[[ $VERBOSE -eq 1 ]] && echo "\t\tpaths: $paths" 
	rm $display_tmp
    
	set -A paths `echo $paths`

	j=0
	asymmetric_change_mode=0
	while [[ $j -lt ${#paths[*]} ]]; do 

	    [[ $VERBOSE -eq 1 ]] && echo "\t\tWorking on path: ${paths[${j}]}"
	    if [[ -z ${paths[${j}]} ]]; then
		j=`expr $j + 1`
		continue;
	    fi
	    # need to retrieve the lun information
            pHCI_bs=`echo $pHCI| sed 's%/%\\\/%g'`
            lun_hex=`luxadm display ${paths[${j}]}s2 | sed -n '/'"$pHCI_bs"'/{
                n;p
            }' | awk ' { print $3 }' | sed 's/.*,//g'`
            typeset -i10 lun=16#$lun_hex
            [[ $VERBOSE -eq 1 ]] && echo "lun $lun"
	    if [[ "$lun_hex" == "" ]]; then
		echo "Error: Unable to retrieve LUN for ${paths[${j}]}s2"
		exit 1
	    fi
    
	    # if this is a purple, check to make sure it is in the right mode
	    mode=`${lib_dir}/stmsboot_util -g ${paths[${j}]}s0 |
		grep 'asymmetric_mode:' | sed 's/asymmetric_mode: //'`
	    if [[ "$mode" == "mpxio" ]]; then
		asymmetric_change_mode=1
	    fi

    	    typeset -u tgt_caps=$tgt
	    cxtydz=${cnum}t${tgt_caps}d$lun
	    [[ $VERBOSE -eq 1 ]] && echo "\t\tcxtydz: $cxtydz"
    
	    paths_cxtydz=`echo ${paths[${j}]} | sed 's/\/dev\/rdsk\///'` 
	    [[ $VERBOSE -eq 1 ]] && echo "\t\tpaths_cxtydz: $paths_cxtydz"
	    if [[ "$paths_cxtydz" == "" ]]; then
		echo "Error: Invalid path ${paths[${j}]}"
		exit 1
	    fi

	    # modify /etc/vfstab and /etc/dumpadm.conf
	    sed "s%${paths_cxtydz}%${cxtydz}%g" $TMP_VFSTAB > $TMP_VFSTAB_TMP
	    mv $TMP_VFSTAB_TMP $TMP_VFSTAB
	    sed "s%${paths_cxtydz}%${cxtydz}%g" $TMP_DUMPADM > $TMP_DUMPADM_TMP
	    mv $TMP_DUMPADM_TMP $TMP_DUMPADM

	    # add to undo script.  first remove the new links created
	    # and then re-create old links
	    cd /dev/dsk
	    echo "cd \${ROOT_MOUNT}/dev/dsk" >> $UNDO_SCRIPT
	    echo "rm -f ${cxtydz}*" >> $UNDO_SCRIPT
	    for f in ${cxtydz}*; do
		echo "ln -s `ls -l $f | awk ' { print $11 }'` $f" >> $UNDO_SCRIPT
	    done
	    for f in `echo ${paths[${j}]} | sed 's/rdsk/dsk/'`*; do
		echo "ln -s `ls -l $f | awk ' { print $11 }'` $f" >> $UNDO_SCRIPT
	    done

	    # add to undo script.  first remove the new links created
	    # and then re-create old links
	    cd /dev/rdsk
	    echo "cd \${ROOT_MOUNT}/dev/rdsk" >> $UNDO_SCRIPT
	    echo "rm -f ${cxtydz}*" >> $UNDO_SCRIPT
	    for f in ${cxtydz}*; do
		echo "ln -s `ls -l $f |
		    awk ' { print $11 }'` $f" >> $UNDO_SCRIPT
	    done
	    for f in ${paths[${j}]}s*; do
		echo "ln -s `ls -l $f |
		    awk ' { print $11 }'` $f" >> $UNDO_SCRIPT
	    done
	    j=`expr $j + 1`
	done
	i=`expr $i + 1`
    done
    
    # modify /etc/system
    sed "s/rootdev:\/scsi_vhci\/ssd@g${guid}:a//g" $TMP_ETC_SYSTEM > $TMP_ETC_SYSTEM_TMP
    mv $TMP_ETC_SYSTEM_TMP $TMP_ETC_SYSTEM
   
    # remove the entry to disable mpxio from /kernel/drv/fp.conf
    if [[ $old_controller_port != "" ]]; then
        hbaInfo=`ls -l $old_controller_port:devctl | sed 's%.*/devices\(.*\)/fp@.*%\1%'`
        tmp_fpConf=/tmp/fp.conf.$$
        # need to backslash all forward slashes in the parent path so
        # it'll work within the sed on the next line
        bsl_hbaInfo=`echo $hbaInfo | sed 's%/%\\\/%g'`
        sed "/parent=\"$bsl_hbaInfo\"/d" /kernel/drv/fp.conf > $tmp_fpConf
        cp $tmp_fpConf /kernel/drv/fp.conf
    fi

    # commit
    m_commit

    # Always prepend the chosen boot path as the first parameter for
    # the eeprom boot-device CLI.

    eep=`eeprom boot-device | sed 's/boot-device=//'`
    tgtlun=`luxadm display /dev/rdsk/${cxtGUIDd}s2 | sed -n '/'"$pHCI_bs"'/{
            n;p
    }' | awk ' { print $3 }'`
    pHCI_construct=`echo $pHCI | sed 's/\/devices//'`
    SELECTED_PATH=$pHCI_construct/disk@w$tgtlun
    STR=""
    update_path
    eeprom boot-device="$STR"
    echo "\nUpdated eeprom boot-device to boot through the "
    echo "selected path $SELECTED_PATH"


    if [[ $asymmetric_change_mode -eq 1 ]]; then
	echo "\nWARNING!!!"
	echo "There is at least one Sun StorEdge T3/T3B, or 6x20,"
	echo "in \"mpxio\" mode."
	echo "For the sane operation of the system, please set"
	echo "mp_support to \"rw\" (or any appropriate mode other"
	echo "than \"mpxio\") on the device(s) now and"
	print -n "press any key to continue."
	read FOO
 
    fi
}    

# variables used to hold argument values
ENUMERATE=0
DEENUMERATE=0
DEBUG=1
LISTALL=0
CNUM=0
OPTION_l=0
VERBOSE=0

# files used by the script
PATH_TO_INST="/etc/path_to_inst";
TMP_PATH_TO_INST="/var/tmp/path_to_inst";
TMP_PATH_TO_INST_SAVE="/var/tmp/path_to_inst.sav";
TMP_PATH_TO_INST_TMP="/var/tmp/path_to_inst.tmp";

ETC_SYSTEM="/etc/system";
TMP_ETC_SYSTEM="/var/tmp/system";
TMP_ETC_SYSTEM_SAVE="/var/tmp/system.sav";
TMP_ETC_SYSTEM_TMP="/var/tmp/system.tmp";

VFSTAB="/etc/vfstab";
TMP_VFSTAB="/var/tmp/vfstab";
TMP_VFSTAB_SAVE="/var/tmp/vfstab.sav";
TMP_VFSTAB_TMP="/var/tmp/vfstab.tmp";

DUMPADM="/etc/dumpadm.conf";
TMP_DUMPADM="/var/tmp/dumpadm";
TMP_DUMPADM_SAVE="/var/tmp/dumpadm.sav";
TMP_DUMPADM_TMP="/var/tmp/dumpadm.tmp";

UNDO_SCRIPT="/var/tmp/undo.ksh";
# variables used by the undo script.
# will include a ROOT_MOUNT variable that allows the user to specifiy where
# the root paritition is mounted.
ROOT_PATH_TO_INST="\${ROOT_MOUNT}/etc/path_to_inst";
ROOT_TMP_PATH_TO_INST_SAVE="\${ROOT_MOUNT}/var/tmp/path_to_inst.sav";
ROOT_ETC_SYSTEM="\${ROOT_MOUNT}/etc/system";
ROOT_TMP_ETC_SYSTEM_SAVE="\${ROOT_MOUNT}/var/tmp/system.sav";
ROOT_VFSTAB="\${ROOT_MOUNT}/etc/vfstab";
ROOT_TMP_VFSTAB_SAVE="\${ROOT_MOUNT}/var/tmp/vfstab.sav";
ROOT_TMP_DUMPADM_SAVE="\${ROOT_MOUNT}/var/tmp/dumpadm.sav";

UNENUMERATED_ROOT_CONTROLLER=/var/tmp/unencapsulated_root_contoller

DEBUG_ENABLE_FILE=/var/tmp/output_stms-enable
DEBUG_DISABLE_FILE=/var/tmp/output_stms-disable
DEBUG_LIST_FILE=/var/tmp/debug.list.output
METASTAT_OUTPUT_FILE=/var/tmp/output_metastat-p
VXDISK_OUTPUT_FILE=/var/tmp/output_vxdisk-list

echo "Version: 1.7"

# process options
while getopts vedDLl: OPT 2> /dev/null; do
    case $OPT in
	e ) ENUMERATE=1 ;;
	d ) DEENUMERATE=1 ;;
	D ) DEBUG=1 ;;
	v ) VERBOSE=1 ;;
	L ) LISTALL=1 ;;
	l ) OPTION_l=1
	    CNUM=$OPTARG ;;
	* ) echo "$0	$*  bad argument(s)"
	     usage
	     exit 1;;
    esac
done

if [[ $ENUMERATE -eq 1 ]]; then
	LOGFILE=$DEBUG_ENABLE_FILE
elif [[ $DEENUMERATE -eq 1 ]]; then
	LOGFILE=$DEBUG_DISABLE_FILE
else
	LOGFILE=$DEBUG_LIST_FILE
fi

exec 2>$LOGFILE
[[ $DEBUG -eq 1 ]] && set -x

# check to make sure valid arguments were passed in.
# Only one of the following options should be set to one. any more or any
# less means the user passed in incorrect arguments
let argValueCount=`expr $ENUMERATE + $DEENUMERATE + $LISTALL + $OPTION_l`
if [[ $argValueCount -ne 1 ]]; then
    usage
    exit 1
fi

# check to make sure mpxio is not disabled
grep "^mpxio-disable=\"no\"" /kernel/drv/scsi_vhci.conf > /dev/null 2>&1
if [[ $? -eq 1 ]]; then
    echo "set mpxio-disable=\"no\" in /kernel/drv/scsi_vhci.conf to proceed further"
    exit 1
fi

# the stmsboot_util binary included with this script shall be installed
# under /usr/lib.  

lib_dir=/usr/lib

if [[ ! -a ${lib_dir}/stmsboot_util ]]; then
    echo "Error: Unable to find ${lib_dir}/stmsboot_util"
    exit 1
fi    

slvm_metastat=1
if [[ ! -a /usr/sbin/metastat ]]; then
	slvm_metastat=0
fi    
if [[ $slvm_metastat -eq 1 ]]; then
	/usr/sbin/metastat -p > $METASTAT_OUTPUT_FILE
fi

vxvm_vxdisk=1
if [[ ! -a /usr/sbin/vxdisk ]]; then
        vxvm_vxdisk=0
fi

if [[ $vxvm_vxdisk -eq 1 ]]; then
        vxdisk list > $VXDISK_OUTPUT_FILE
fi

if [[ $ENUMERATE -eq 1 ]]; then
    m_enable
    echo "\nA reconfiguration reboot is mandatory for system sanity."
    echo " While you may choose to complete other tasks prior to initiating"
    echo " the reboot, doing so is not recommended."
    print -n "Reboot the system now ? [y/n] (default:y)"
    choice_reboot=""
    read choice_reboot
    if [[ "$choice_reboot" == "" || "$choice_reboot" == "y" ]]; then
	touch /reconfigure
	shutdown -g0 -y -i6
	exit 0
    fi
    
elif [[ $DEENUMERATE -eq 1 ]]; then
    m_disable
    echo "\nA reconfiguration reboot is mandatory for system sanity."
    echo " While you may choose to complete other tasks prior to initiating"
    echo " the reboot, doing so is not recommended."
    choice_reboot=""
    print -n "Reboot the system now ? [y/n] (default:y)"
    read choice_reboot
    if [[ "$choice_reboot" == "" || "$choice_reboot" == "y" ]]; then
	touch /reconfigure
	shutdown -g0 -y -i6
	exit 0
    fi
elif [[ $OPTION_l -ne 0 ]]; then
    echo "non-STMS device name\t\t\tSTMS device name"
    echo "------------------------------------------------------------------"
    m_listNewPaths_oneController
elif [[ $LISTALL -eq 1 ]]; then
    echo "non-STMS device name\t\t\tSTMS device name"
    echo "------------------------------------------------------------------"
    m_listNewPaths_allController
fi
exit 0
