1#!/bin/ksh -p 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22# 23# Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26 27export PATH=/usr/bin:/usr/sbin:/usr/ccs/bin 28unset ENV TMPDIR 29umask 022 30cwd=$PWD 31 32isa=$(uname -p) 33if [[ $isa = sparc ]]; then 34 isa64=sparcv9 35elif [[ $isa = i386 ]]; then 36 isa64=amd64 37else 38 isa64=unknown 39fi 40 41if [[ -n "$CODEMGR_WS" ]]; then 42 sysroot=$CODEMGR_WS/proto/root_$isa 43elif [[ -n "$ROOT" ]]; then 44 sysroot=$ROOT 45else 46 sysroot=/ 47fi 48 49quote= 50eol='\' 51files= 52 53simchan=com.sun:fm:fmd$$ 54simroot=/tmp/fmd.$$ 55simscript=run 56simpid= 57 58truss_cmd= 59truss_args= 60dump_args= 61inj_args= 62fmd_args= 63 64opt_h=false 65opt_i=false 66opt_s=false 67opt_w=false 68opt_x=false 69 70function cp_so 71{ 72 nm -ghp $1 2>/dev/null | while read addr type name; do 73 [[ $type != T ]] && continue 74 case $name in 75 _fmd_init) cp $1 $2/usr/lib/fm/fmd/plugins; return ;; 76 fmd_fmri_nvl2str) cp $1 $2/usr/lib/fm/fmd/schemes; return ;; 77 topo_load) cp $1 $2/usr/lib/fm/topo/plugins; return ;; 78 esac 79 done 80 die "\nunknown .so type -- $1" 81} 82 83function cp_topo 84{ 85 mkdir -p $2/usr/lib/fm/topo/maps 86 cp $1 $2/usr/lib/fm/topo/maps; 87 for platdir in $2/usr/platform/*/lib/fm/topo/maps; do 88 rm -f $platdir/* 2>/dev/null 89 done 90} 91 92function list_cmds 93{ 94 for cmd in fmadm fmdump fmstat; do 95 echo usr/sbin/$cmd 96 done 97} 98 99function wait_status 100{ 101 if [[ $1 -gt 128 ]]; then 102 sig=$(kill -l $(($1 - 128))) 103 die "fmd terminated from signal $sig (see $simroot)" 104 elif [[ $1 -ne 0 ]]; then 105 die "fmd terminated with status $1 (see $simroot)" 106 fi 107} 108 109function wait_prompt 110{ 111 echo "fmsim: [ Press return to $* ] \c" 112 mode=$(stty -g) 113 stty -echo -isig min 1 time 0 114 read s; echo 115 stty $mode 116} 117 118function die 119{ 120 echo "fmsim: $*" >& 2 121 $opt_w && wait_prompt exit 122 [[ -n "$simpid" ]] && exit 1 || exit 2 123} 124 125while [[ $# -gt 0 ]]; do 126 OPTIND=1; while getopts ':d:D:ehio:st:vVwx' c; do 127 case "$c" in 128 d) 129 simroot=$OPTARG 130 ;; 131 D) 132 truss_cmd=dtrace 133 truss_args="-s $OPTARG -c" 134 quote="'"; eol="" 135 ;; 136 e|v|V) 137 dump_args="$dump_args -$c" 138 ;; 139 h|i|s|w|x) 140 eval opt_$c'='true 141 ;; 142 o) 143 fmd_args="$fmd_args -o $OPTARG" 144 ;; 145 t) 146 truss_cmd=truss 147 truss_args="$OPTARG" 148 ;; 149 :) 150 die "option requires an argument -- $OPTARG" 151 ;; 152 *) 153 die "illegal option -- $OPTARG" 154 ;; 155 esac 156 done 157 let OPTIND="$OPTIND - 1"; shift $OPTIND 158 159 if [[ $# -gt 0 ]]; then 160 if [[ -d $1 ]]; then 161 files="$files $1/*" 162 else 163 files="$files $1" 164 fi 165 shift 166 fi 167done 168 169for file in $files; do 170 [[ -r $file ]] || die "input file is missing or not readable -- $file" 171done 172 173if $opt_h || [[ -z "$files" && $opt_i = false ]]; then 174 echo "Usage: fmsim [-ehisvVwx] [-d dir] [-D a.d] [-o opt=val]" \ 175 "[-t args] [file ...]" 176 177 echo "\t-d set the simulation root directory to the given location" 178 echo "\t-D start fmd(8) using dtrace(8) and specified D script" 179 echo "\t-e display error log content instead of fault log content" 180 echo "\t-h display usage information for fmsim and exit" 181 echo "\t-i set interactive mode: do not stop after sending events" 182 echo "\t-o set fmd(8) option to specified value during simulation" 183 echo "\t-s set up simulation world but do not actually run simulation" 184 echo "\t-t start fmd(8) using truss(1) and specified arguments" 185 echo "\t-v set verbose mode: display additional event detail" 186 echo "\t-V set very verbose mode: display complete event contents" 187 echo "\t-w wait for a keypress after simulation completes" 188 echo "\t-x delete simulation world if simulation is successful" 189 190 exit 0 191fi 192 193echo "fmsim: creating simulation world $simroot ... \c" 194[[ -d $simroot ]] || mkdir -p $simroot || exit 1 195cd $simroot || exit 1 196echo "done." 197 198echo "fmsim: populating /var ... \c" 199mkdir -p -m 0755 var/fm/fmd 200mkdir -p -m 0700 var/fm/fmd/ckpt 201mkdir -p -m 0700 var/fm/fmd/rsrc 202mkdir -p -m 0700 var/fm/fmd/xprt 203echo "done." 204 205echo "fmsim: populating /usr/lib/fm from $sysroot ... \c" 206(cd $sysroot && find usr/lib/fm -depth -print | cpio -pdmu $simroot) 207 208for platdir in $sysroot/usr/platform/*/lib/fm; do 209 [[ -d $platdir ]] && platdir=${platdir#$sysroot} || continue 210 echo "fmsim: populating $platdir from $sysroot ... \c" 211 (cd $sysroot && find ${platdir#/} -depth -print | cpio -pdmu $simroot) 212done 213 214echo "fmsim: populating /usr/lib/locale/$LANG from $sysroot ... \c" 215(cd $sysroot && find usr/lib/locale/$LANG -depth -print | cpio -pdmu $simroot) 216 217echo "fmsim: populating /usr/sbin from $sysroot ... \c" 218(cd $sysroot && list_cmds | cpio -pdmu $simroot) 219 220echo "fmsim: adding customizations:\c" 221cd $cwd || exit $1 222 223for file in $files; do 224 base=$(basename $file) 225 case $base in 226 *.cmd) die "\neversholt command file not yet supported -- $file" ;; 227 fmd.conf) cp $file $simroot/etc/fm/fmd ;; 228 *.conf) cp $file $simroot/usr/lib/fm/fmd/plugins ;; 229 *.dict) cp $file $simroot/usr/lib/fm/dict ;; 230 *.eft) cp $file $simroot/usr/lib/fm/eft ;; 231 *.esc) die "\neversholt source file not yet supported -- $file" ;; 232 *.inj) inj_args="$inj_args $file" ;; 233 *.log) inj_args="$inj_args $file" ;; 234 *log) inj_args="$inj_args $file" ;; 235 *.mo) cp $file $simroot/usr/lib/locale/$LANG/LC_MESSAGES ;; 236 *.so) cp_so $file $simroot ;; 237 *.topo) die "\n .topo files not supported -- $file" ;; 238 *.xml) cp_topo $file $simroot ;; 239 *) die "\nunknown file type or suffix -- $file" ;; 240 esac 241 echo " $base\c" 242done 243 244cd $simroot || exit 1 245echo " done." 246 247echo "fmsim: generating script ... \c" 248cat >$simscript <<EOS 249#!/bin/ksh -p 250# 251# Copyright 2005 Sun Microsystems, Inc. All rights reserved. 252# Use is subject to license terms. 253# 254#ident "@(#)fmsim.ksh 1.5 06/10/11 SMI" 255 256# 257# fmsim(8) script generated for $simroot $(date) 258# 259 260export LD_LIBRARY_PATH=$simroot/usr/lib:$simroot/usr/lib/fm 261export LD_LIBRARY_PATH_64=$simroot/usr/lib/64:$simroot/usr/lib/fm/$isa64 262 263export _THREAD_ERROR_DETECTION=2 264 265exec $truss_cmd $truss_args $quote./usr/lib/fm/fmd/fmd -R $simroot $eol 266 -o fg=true -o clock=simulated $eol 267 -o rpc.adm.prog=0 -o rpc.adm.path=$simroot/rpc $eol 268 -o sysevent-transport:device=/dev/null $eol 269 -o sysevent-transport:channel=$simchan $fmd_args$quote 270 271EOS 272 273chmod 0555 $simscript 274echo "done." 275 276if $opt_s; then 277 echo "fmsim: simulation is saved in $simroot" 278 exit 0 279fi 280 281export LD_LIBRARY_PATH=$simroot/usr/lib:$simroot/usr/lib/fm 282export LD_LIBRARY_PATH_64=$simroot/usr/lib/64:$simroot/usr/lib/fm/$isa64 283 284echo "fmsim: simulation $$ running fmd(8)\c" 285./usr/lib/fm/fmd/fmd -V | cut -d: -f2 286 287./$simscript & 288simpid=$! 289trap '' INT HUP 290cd $cwd 291i=0 292 293while [[ ! -s $simroot/rpc ]]; do 294 [[ $i -ge 30 ]] && kill -9 $simpid >/dev/null 2>&1 295 kill -0 $simpid >/dev/null 2>&1 || break 296 let i="$i + 1" 297 sleep 1 298done 299 300kill -0 $simpid >/dev/null 2>&1 || { 301 wait $simpid 302 wait_status $? 303} 304 305echo "fmsim: rpc adm requests can rendezvous at" $(<$simroot/rpc) 306echo "fmsim: injectors should use channel $simchan" 307echo "fmsim: debuggers should attach to PID $simpid" 308 309for arg in $inj_args; do 310 echo "fmsim: injecting events from $arg ... \c" 311 $simroot/usr/lib/fm/fmd/fminject -q -c $simchan $arg || { 312 echo "fmsim: fminject failed for $arg: aborting simulation" >& 2 313 kill $simpid >/dev/null 2>&1 314 } 315 echo "done." 316done 317 318if [[ $opt_i = false ]]; then 319 echo "fmsim: injecting event to advance to end-of-time ... \c" 320 echo 'endhrtime;' | $simroot/usr/lib/fm/fmd/fminject -q -c $simchan - 321 echo "done." 322fi 323 324wait $simpid 325status=$? 326 327if [[ -f $simroot/var/fm/fmd/errlog ]]; then 328 echo; $simroot/usr/sbin/fmdump -R $simroot $dump_args; echo 329fi 330 331wait_status $status 332$opt_w && wait_prompt exit 333$opt_x && rm -rf $simroot 334 335exit 0 336