#!/bin/ksh -p # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "@(#)install-du.ksh 1.5 08/12/04 SMI" # # This script extracts the contents of ITU media and install them onto the # miniroot. It also stores them in the directory /tmp/ITUs. At the end of # install, it is invoked (with rootdir arg) to install the contents of # /tmp/ITUs onto the target OS. # # # Install ITU on the target disk (at the end of Solaris installation). # function install_to_target # { typeset osroot first=1 i installer icmd typeset tmpdir=/tmp/tmpitu.$$ trap '/bin/rm -rf $tmpdir' EXIT if (( $# != 1 )) then print "install_target is missing argument." exit 1 fi osroot=$1 # Install ITUs saved in $ITUDIR and on the Solaris media, if any. for i in $SOLMEDIA_ITUDIR/* $ITUDIR/* do installer=DU/sol_$VERS/$MACH/Tools/install.sh icmd=$i/$installer [[ -f "${icmd}" ]] || continue if (( first )) # do only once then print "Installing Driver Updates" first=0 fi if [[ ! -x "$icmd" ]] then # Be lenient, in case user forgot to chmod +x # install.sh. We need to copy the DU directory to /tmp # since it could be on a readonly media. /bin/rm -rf "$tmpdir" /bin/mkdir -p "$tmpdir" /bin/cp -Rp "$i"/* "$tmpdir" icmd=$tmpdir/$installer /bin/chmod a+x "$icmd" fi # We can't use pipes here such as # # yes | "$icmd" -R "$osroot" # # to feed in y's to interactive pkgadd in $icmd since pfinstall # sets SIGPIPE to be ignored. And sh/ksh doesn't let a # signal's disposition to be changed when it's ignored or set # to a function when the shell starts. So use a here-document. "$icmd" -R "$osroot" << eof y y y eof done } # # Install ITU onto the running miniroot. # function install_to_miniroot { typeset icmd status statusfile logfile typeset -l ans trap '/bin/rm -f $statusfile' EXIT if [[ ! -d $ITUDIR/$MEDIA_COUNT ]] then print "Can't find directory $ITUDIR/$MEDIA_COUNT." return 1 fi icmd=$ITUDIR/$MEDIA_COUNT/DU/sol_$VERS/$MACH/Tools/install.sh logfile=$ITUDIR/$MEDIA_COUNT/install_to_miniroot.log statusfile=$ITUDIR/$MEDIA_COUNT/.status if [[ ! -f "$icmd" ]] then print "Can't find install script $icmd." return 1 fi [[ ! -x "$icmd" ]] && /bin/chmod a+x "$icmd" # Run install script. Save all output to a logfile, but also # display lines from pkgadd which say "Installing ... as ". # If the install script exited with nonzero value, give user chance # to drop into shell (e.g. to manually fix the problem). print "Installing Driver Updates onto miniroot." status=1 { "$icmd" 2>&1 << eof y y y eof echo $? > $statusfile /bin/touch $statusfile # make sure file is created } | /bin/sed -n -e "w $logfile" -e '/^Installing/p' \ -e '/^Installation.*successful/p' [[ -s $statusfile ]] && status=$(<$statusfile) if [[ $status = 0 ]] then # Run devfsadm to make sure any new disks are enumerated /usr/sbin/devfsadm return 0 fi print "\nInstall script $icmd exited with" print "nonzero value $status. A possible failure might have occurred." print "Output from the script was saved in $logfile." until [[ $ans = [yn]* ]] do read ans?"Would you like to run a single user shell? (y/n) " done if [[ $ans = y* ]] then print "(Exit from shell to continue.)" /sbin/sulogin return 0 # assume everything is ok now fi return $status } # # Get a device's product and vendor info. # function device_info # { if (( $# != 1 )) then print "device_info is missing argument." exit 1 fi /usr/sbin/prtconf -v "$1" | /bin/nawk -v dev="$1" -F\' ' /name='"'"'inquiry-(vendor-id|product-id|revision-id)/ { name = $2 getline # get value on next line value = $0 if (value ~ /value='"'"'/) { sub(/.*value='"'"'/, "", value) sub(/'"'"'[ \t]*$/, "", value) } else { sub(/.*value=/, "", value) } prop[name] = value } END { if (length(prop["inquiry-vendor-id"])) printf(prop["inquiry-vendor-id"]) if (length(prop["inquiry-product-id"])) printf(" " prop["inquiry-product-id"]) if (length(prop["inquiry-revision-id"])) printf(" " prop["inquiry-revision-id"]) }' } # # Check specified device for the given filesystem type. If it matches then # check if DU directory exists on the device. # function do_find # { typeset dev fs cmd index i if (( $# != 2 )) then print "do_find is missing arguments." exit 1 fi dev=$1 fs=$2 # For faster execution, use the filesystem-specific fstyp # command directly instead of the generic /usr/sbin/fstyp. cmd=/usr/lib/fs/$fs/fstyp [[ -x $cmd ]] || return $cmd $dev >/dev/null 2>&1 || return /sbin/mount -o ro -F $fs $dev "$MNTDIR" 2>/dev/null || return if [[ -d "$MNTDIR/DU/sol_$VERS/$MACH" ]] then # Record the found device, fs type and device information. index=${#DEV_PATH[*]} DEV_PATH[index]=$dev DEV_FSTYPE[index]=$fs DEV_INFO[index]=$(device_info $dev) # Special name for floppy drive (if there's no name). if [[ $dev = /dev/*diskette* ]] then : ${DEV_INFO[index]:="Legacy, non-USB diskette"} fi fi # Collect CD/DVD devices. We'll use these before exiting this script # to see if user needs to reinsert the Solaris CD/DVD. if [[ $INSTALL_MEDIA = cdrom && $fs = hsfs ]] then index=${#DEV_HSFS[*]} i=0 while (( i < index )) do # If already stored. [[ ${DEV_HSFS[i]} = $dev ]] && break (( i += 1 )) done # If not stored yet. (( i == index )) && DEV_HSFS[i]=$dev fi /sbin/umount $dev 2>/dev/null return 0 } # # Look for DU on ISA floppy. Assume it's formatted either PCFS or UFS. # function find_floppy { typeset dev fs for dev in /dev/diskette?* do for fs in pcfs ufs do do_find $dev $fs && break done done } # # Look for DU on removable media. Assume it's on either p0 or p1, and # it can be formatted either PCFS or UFS. # function find_rmmedia { typeset dev fs for dev in /dev/dsk/*p[01] do for fs in pcfs ufs do do_find $dev $fs && break done done } # # Look for DU on CD/DVD. # function find_cd { typeset dev for dev in /dev/dsk/*p0 do do_find $dev hsfs done } # # Extract Driver Updates from a device # function do_extract # [device_info...] { typeset dev fs devinfo retval if (( $# < 2 )) then print "do_extract is missing arguments." exit 1 fi dev=$1 fs=$2 shift 2 (( $# )) && devinfo=" ($*)" print "\nExtracting Driver Updates from ${dev}${devinfo}." /sbin/mount -o ro -F $fs $dev "$MNTDIR" 2>/dev/null || return /bin/mkdir -p $ITUDIR/$MEDIA_COUNT || return /bin/cp -p -r "$MNTDIR"/DU $ITUDIR/$MEDIA_COUNT || return install_to_miniroot retval=$? /sbin/umount $dev 2>/dev/null (( MEDIA_COUNT += 1 )) return $retval } # # Extra DU from one or more media. # function extract_du { typeset ndevs=${#DEV_PATH[*]} # number of media found with DU typeset i dev fs devinfo inst typeset -l ans yn if (( ndevs == 0 )) then print "No Driver Updates found." return 0 elif (( ndevs == 1 )) then do_extract "${DEV_PATH[0]}" "${DEV_FSTYPE[0]}" "${DEV_INFO[0]}" return fi # Multiple media with DU found. Offer user choices. while true do print "\nMultiple media with Driver Updates were found." print "Enter one the following and press Return:" i=0 while (( i < ndevs )) do dev=${DEV_PATH[i]} fs=${DEV_FSTYPE[i]} devinfo=${DEV_INFO[i]:+" (${DEV_INFO[i]})"} inst=${DEV_INSTALLED[i]:+" "} print " [$((i+1))] ${inst}${dev}${devinfo}" (( i += 1 )) done print " [a] All of the above" print " [e] End" read ans?'Enter choice and press Return: ' case $ans in +([0-9])) yn=y if (( ans < 1 || ans > ndevs )) then print "Invalid selection." yn=n elif [[ -n "${DEV_INSTALLED[ans-1]}" ]] then print "Driver Updates from" \ "${DEV_PATH[ans-1]} have been installed." while true do read yn?"Continue to install? (y/n) " [[ $yn = [yn]* ]] && break done fi if [[ $yn = y* ]] then if do_extract "${DEV_PATH[ans-1]}" \ "${DEV_FSTYPE[ans-1]}" "${DEV_INFO[ans-1]}" then DEV_INSTALLED[ans-1]=y fi fi ;; a*) yn=y if (( ${#DEV_INSTALLED[*]} > 0 )) then print "Driver Updates from one or more" \ "media above have been installed." while true do read yn?"Continue to install? (y/n) " [[ $yn = [yn]* ]] && break done fi if [[ $yn = y* ]] then i=0 while (( i < ndevs )) do if do_extract "${DEV_PATH[i]}" \ "${DEV_FSTYPE[i]}" "${DEV_INFO[i]}" then DEV_INSTALLED[i]=y fi (( i += 1 )) done break # we're done fi ;; e*) break ;; *) print "Invalid selection." ;; esac done } # # If Solaris is being installed from CD/DVD, check if there is any Solaris # CD/DVD currently. If not, ask user to reinsert it. # function reinsert_solaris_cd { typeset dev cmd try # If Solaris isn't being installed from cdrom, we're done. [[ $INSTALL_MEDIA != cdrom ]] && return # If we didn't look at any CD/DVD, we're done. (( ${#DEV_HSFS[*]} == 0 )) && return cmd=/usr/lib/fs/hsfs/fstyp [[ -x $cmd ]] || return try=0 while true do for dev in "${DEV_HSFS[@]}" do $cmd $dev >/dev/null 2>&1 || continue /sbin/mount -o ro -F hsfs $dev "$MNTDIR" 2>/dev/null || continue if [[ -d $(echo "$MNTDIR"/Solaris_*) ]] then /sbin/umount $dev 2>/dev/null break 2 fi /sbin/umount $dev 2>/dev/null done (( try > 0 )) && print "No Solaris media found." print -n "Reinsert Solaris media now and press Return." read (( try += 1 )) done } # # Grab a character without a newline requirement useful to match and keep # menu prompts consistent # function getcharacter { typeset character stty raw character=`/usr/bin/dd bs=1 count=1 2> /dev/null` stty -raw print -r -- "${character}" } # # Clean up at exit # function cleanup { /sbin/umount "$MNTDIR" 2>/dev/null /bin/rm -rf "$MNTDIR" } # # MAIN # readonly ITUDIR=/tmp/ITUs readonly SOLMEDIA_ITUDIR=/cdrom/ITUs # Use a unique mount directory in case /mnt is already used. readonly MNTDIR=/tmp/${0##*/}.mnt.$$ readonly VERS=$(/bin/uname -r | /bin/sed -e 's/5\./2/') readonly MACH=$(/bin/uname -m) typeset -Z3 MEDIA_COUNT=0 while getopts at: c ; do case $c in a) itu_device=`/usr/sbin/eeprom itu-device | \ grep -v "data not available" | cut -f 2 -d =` [ "$itu_device" ] || exit 0 DEV_PATH[0]=$itu_device DEV_FSTYPE[0]=ufs DEV_INFO[0]=$(device_info $dev) extract_du exit 0 ;; t) # we are invoked to install ITU media to target OS install_to_target "$OPTARG" exit 0 ;; \?) printf "usage: $0 [-a] [-t ]\n" exit 1 ;; esac done trap cleanup EXIT # We are at the beginning of install. # remount root rw so install.sh will succeed /sbin/mount -o remount,rw / || exit 1 # make add_drv -b / load and attach driver touch /ADD_DRV_IGNORE_ROOT_BASEDIR /bin/mkdir -p "$ITUDIR" "$MNTDIR" unset DEV_HSFS # reset array typeset -l ans # ignore case # Find out where Solaris is being installed from. INSTALL_MEDIA=$(/usr/sbin/prtconf -v /devices | /bin/nawk -F\' '/install_media/{getline; print $2}') while true do print "\nInsert Driver Update media and press Return, or" print "enter one of the following and press Return:" print " [1] CD/DVD devices" print " [2] Legacy, non-USB diskettes" print " [3] All other removable mass-storage devices" print " [a] Search all of the above" print " [e] End" print -n "Enter choice: " ans=`getcharacter` print "" unset DEV_PATH DEV_FSTYPE DEV_INFO DEV_INSTALLED # reset arrays case $ans in ''|a*) # Unspecified media or search all. print "Searching for Driver Updates." find_floppy find_rmmedia find_cd ;; 1*) # CD/DVD: look for DU on CD/DVD print "Searching for Driver Updates on CD/DVD devices." find_cd ;; 2*) # Floppy: look for DU on ISA floppy. print "Searching for Driver Updates on" \ "legacy, non-USB diskettes." find_floppy ;; 3*) # Removable Media: look for DU on removable media print "Searching for Driver Updates on" \ "other removable mass-storage devices." find_rmmedia ;; e*) # End: ask user to reinsert Solaris CD/DVD if necessary. reinsert_solaris_cd break # we're done ;; *) continue ;; esac extract_du done