#!/bin/sh
# set -x
# wabiload
#  	Driver load script for wabi svr4 driver.
#

#
# Define system BASEDIR
#
SYSBASEDIR=`echo ${BASEDIR} | awk -F// '{ print $2 }'`
if [ "$SYSBASEDIR" = "a" ]
then
     SYSBASEDIR="/a"
else
     SYSBASEDIR=""
fi

#
# Define variables
#
DEVLINKS="/usr/sbin/devlinks"
ADD_DRV="/usr/sbin/add_drv"
REM_DRV="/usr/sbin/rem_drv"
MODLOAD="/usr/sbin/modload"

DEVLINKS_TAB="/etc/devlink.tab"

UNAME="/usr/bin/uname"

AWK="/bin/awk"
GREP="/bin/grep"
ID="/bin/id"
ECHO="/bin/echo"
CP="/bin/cp"
MODINFO="/usr/sbin/modinfo"
ARCH=`${UNAME} -m`

# Find out where this script lives, and determine WABIDRVHOME.
FROM_PATH=`echo "$0" | ${GREP} "/"`
 
if [ -n "$FROM_PATH" ]
then
	#in this case $0 is a directory component.
	FIRSTARG=`echo ${FROM_PATH} | ${AWK} -F/ '{ print $1 }'`
 
	if [ -z "$FIRSTARG" ]
	then
		SOURCE3=`echo ${0} | ${AWK} -F/ '{ for (i = 1; i < NF; i++)  { printf "%s", $i; printf "/" } }'`
	else
		SOURCE3=`echo ${0} | ${AWK} -F/ '{ if ($1 == "") printf "/"; for (i = 1; i < NF; i++)  { printf "%s", $i; printf "/" } }'`
	fi
else
	#in this case $0 is not a directory component.
	SOURCE3="./"
fi
cd "$SOURCE3"

#
# Must be root to run, test that right away.
#
OSREV=`${UNAME} -r`
SPARC_ARCH=`${UNAME} -m | ${AWK} '/sun4/ {print}'`
INTEL_ARCH=`${UNAME} -m | ${AWK} '/i86pc/ {print}'`
if [ ! -z "$SPARC_ARCH" ]
then
	DRIVER_NAME=wabi.sparc.${OSREV}.o
else
	if [ ! -z "$INTEL_ARCH" ]
	then
		DRIVER_NAME=wabi.intel.${OSREV}.o
	else
		${ECHO} "\nNO ARCH"
		DRIVER_NAME=""
	fi
fi

if [ "$OSREV" = "5.1" -o "$OSREV" = "5.2" ]
then
	BASEDIR=/
	export BASEDIR
fi

#
# Must be root to run, test that right away.
#

ISROOT=`${ID} | ${AWK} '/root/ {print}'`
if [ -z "$ISROOT" ]
then
	${ECHO} "\nMust be root to install Wabi driver."
	${ECHO} "\nInstall script is exiting."
	exit 1
fi

if [ ! -f ${DRIVER_NAME} ]
then
	${ECHO} "\nThe wabi locking driver "
	${ECHO} ${DRIVER_NAME}
	${ECHO} "for this system was not found."
	exit 1
fi
#
# check if have an alternate vmunix file to load against
#
if [ $# -eq 2 ]
then
    if [ $1 = "-A" ]
    then
	VMUNIX_FILE=$2
    else
	if [ $1 = "" ]
	then
		${ECHO} "\nusage: wabiload -A vmunix_file"
		exit 1
	fi
	VMUNIX_FILE=/kernel/unix
    fi
else
	if [ $# -eq 0 ]
	then
		VMUNIX_FILE=/kernel/unix
	else
		echo "\nusage: wabiload -A vmunix_file"
		exit 1
	fi
fi


#echo VMUNIX_FILE=${VMUNIX_FILE}

#
# Check if driver is already installed.
#
${MODINFO} > $SYSBASEDIR/tmp/modinfo.txt
WABIDRV_INSTALLED=`${GREP} wabi $SYSBASEDIR/tmp/modinfo.txt`
if [ -n "$WABIDRV_INSTALLED" ]
then
${REM_DRV} wabi
fi

#
# Driver might not show up with modinfo if it has not been opened yet,
# so check out the /etc/driver_aliases file for the wabi alias.
#
WABIDRV_INSTALLED=`${GREP} wabi $SYSBASEDIR/etc/driver_aliases`
if [ -n "$WABIDRV_INSTALLED" ]
then
${REM_DRV} wabi
fi

#
# Copy driver files into kernel driver area.
#
${CP} ${DRIVER_NAME} $SYSBASEDIR/usr/kernel/drv/wabi
${CP} wabi_drv.conf $SYSBASEDIR/usr/kernel/drv/wabi.conf

if [ "$SYSBASEDIR" != "/a" ]
then
    #
    # Check if devlink.tab file already has a wabi entry.
    # (if not, add the wabi entry.)
    #
    DEVLINK_MODIFIED=`${GREP} wabi ${DEVLINKS_TAB}`
    if [ -z "$DEVLINK_MODIFIED" ]
    then
    	${CP} ${DEVLINKS_TAB} ${DEVLINKS_TAB}.wabi
    	echo "#The following lines added for the Wabi kernel driver" >> ${DEVLINKS_TAB} 
    	echo "type=ddi_pseudo;name=wabi	\M0" >> ${DEVLINKS_TAB}
    fi

    ${ADD_DRV} -m '* 0666 root sys' -i 'wabi Wabi' wabi
    fail=$?
    test $fail -eq 0 && sync && exit 0
fi


#
# If add_drv failed, we update name_to_major, minor_perm, devlink.tab and
# driver_aliases by following subroutines.
#
NAMEMAJOR="$SYSBASEDIR/etc/name_to_major"
MINORPERM="$SYSBASEDIR/etc/minor_perm"
DEVLINKTB="$SYSBASEDIR/etc/devlink.tab"
DRIVERALS="$SYSBASEDIR/etc/driver_aliases"

if test ! -f ${NAMEMAJOR} -o ! -w ${NAMEMAJOR}; then
	echo "add_major: data file ${NAMEMAJOR} is missing/inacessible." >&2
	exit 1
fi

if test ! -f ${MINORPERM} -o ! -w ${MINORPERM}; then
	echo "add_minor: data file ${MINORPERM} is missing/inacessible." >&2
	exit 1
fi

if test ! -f ${DEVLINKTB} -o ! -w ${DEVLINKTB}; then
	echo "add_devlink: data file ${DEVLINKTB} is missing/inacessible." >&2
	exit 1
fi

if test ! -f ${DRIVERALS} -o ! -w ${DRIVERALS}; then
	echo "add_drv_alias: data file ${DRIVERALS} is missing/inacessible." >&2
	exit 1
fi

trap "rm -f /tmp/$$.*;exit" 0 1 2 3 13 15
TMP=/tmp/$$

# adds new major numbers to system for device drivers
# Usage:
#	add_major name1 name2 name3 name4 ....

add_major()
{
sort +1 -2n ${NAMEMAJOR} | nawk '#
BEGIN	{oldmajor = -1}
NR == 1	{n=split(namelist,x)
	 if (n < 1)
	    exit(1)
	 for (i=1; i<=n; i++)
	    chklist[x[i]]++
	}
	{for (name in chklist)
	 {
	    if ($1 == name)
		delete chklist[name]
	 }
	 if (($2 - oldmajor) > 1)
	 {
	    gap++
	    gaplist[gap] = oldmajor " " $2;
	 }
	 oldmajor = $2;
	}
END	{addsize=1
	 for (name in chklist)
	    addlist[addsize++] = name
	
	 addidx = 1
	 for (i=1; i<=gap && addidx < addsize; i++)
	 {
	    split(gaplist[i],x)
	    begmajor = x[1]
	    endmajor = x[2]
	    for (begmajor++;begmajor < endmajor && addidx < addsize;)
	    {
		printf "%s %d\n",addlist[addidx],begmajor
		addidx++
		begmajor++
	    }
	 }
	 for (; addidx < addsize; addidx++)
	 {
	    oldmajor++
	    printf "%s %d\n",addlist[addidx],oldmajor
	 }
	}
' namelist="$*" - > $TMP.new

if [ -s $TMP.new ]
then
#    echo "Adding following devices to ${NAMEMAJOR}"
#    cat $TMP.new
    sort +1 -2n ${NAMEMAJOR} $TMP.new -o ${NAMEMAJOR}
fi
}

# adds new minor permissions to system for device drivers
# Usage:
#	add_minor perm1 perm2 perm3 perm4 ....
#    i.e.
#	add_minor 'sd:* 0666 bin bin' 'sd:a 0644 root sys'

add_minor()
{
for p in "$@"
do echo "$p"
done | nawk '#
FILENAME != "-"	{permtab[$1] = $0;next}
FILENAME == "-"	{
		 if ($4 == "") {
			 printf("Missing token: (%s), skipping.\n", $0)
			 next
		 }
		 if ($5 != "") {
			 printf("Too many arguments: (%s), skipping.\n", $0)
			 next
		 }
		 if ($1 !~ /:/) {
			 printf("Bad name:minor pair: %s, skipping.\n", $1)
			 next
		 }
		 if ($2 < "0000" || $2 > "4777") {
			 printf("Bad mode: %s, skipping %s.\n", $2, $1)
			 next
		 }
		 if (!($1 in permtab))
		     print >> permtmp
		 next
		}
' permtmp=$TMP.perm ${MINORPERM} - >&2

if [ -s $TMP.perm ]
then
#	echo "Adding following permissions to ${MINORPERM}"
#	cat $TMP.perm
	sort +0 -1 ${MINORPERM} $TMP.perm -o ${MINORPERM}
fi
}

# adds new entries to devlink.tab file
# Usage:
#	add_devlink spec1 spec2 spec3 spec4 ...
#
#	where each <spec> is:
#	    <devfs-spec> <dev-name> <dev-link>
#
#    i.e.
#	add_devlink 'type=ddi_display;name=SUNW,leo' 'fbs/\\M0' 'leo\\N0'	
#

add_devlink()
{
while test $# -ge 3
do
echo "$1	$2	$3"
shift 3
done | nawk '-F	' '#
FILENAME == "-"		{devlinktab[$1] = $0;next}
FILENAME != "-"		{if ($1 in devlinktab)
			     delete devlinktab[$1]
			}
END			{for (d in devlinktab)
			    print devlinktab[d] >> devlinktmp
			}
' devlinktmp=$TMP.devlink - ${DEVLINKTB} >&2

if [ -s $TMP.devlink ]
then
#	echo "Adding following entries to ${DEVLINKTB}"
#	cat $TMP.devlink
	cat $TMP.devlink >> ${DEVLINKTB}
fi
}

# adds new entries to driver_aliases file
# Usage:
#	add_drv_alias spec1 spec2 spec3
#
#	where spec is:
#		<driver> <alias>
#    i.e.
#	add_drv_alias 'leo' 'SUNW,leo'
#

add_drv_alias()
{
while test $# -ge 2
do
	echo "$1 $2"
	shift 2
done | nawk '#
FILENAME == "-"		{newaliases[$2] = $1;next}
FILENAME != "-"		{if ($2 in newaliases) {
			     if ($1 == newaliases[$2])
				 delete newaliases[$2]
			 }
			}
END			{for (d in newaliases)
			    print newaliases[d],d > drvalias
			}
' drvalias=$TMP.drvalias - ${DRIVERALS} >&2
 
if [ -s $TMP.drvalias ]
then
#   echo "Adding following entries to ${DRIVERALS}"
#   cat $TMP.drvalias
    cat $TMP.drvalias >> ${DRIVERALS}
fi
}

#
# We're modifying a mounted kernel
#

add_major wabi
add_minor 'wabi:* 0666 root sys' 
add_devlink 'type=ddi_pseudo;name=wabi' '\M0' ' '
add_drv_alias 'wabi' 'wabi' 'wabi' 'Wabi'
touch ${SYSBASEDIR}/reconfigure

exit 0
