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