powerpc-utils-1.2.26/0000775000175000017510000000000012542271540011425 500000000000000powerpc-utils-1.2.26/config/0000775000175000017510000000000012542271540012672 500000000000000powerpc-utils-1.2.26/config/depcomp0000755000175000017510000005601612527201604014172 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: powerpc-utils-1.2.26/config/compile0000755000175000017510000001624512527201603014172 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: powerpc-utils-1.2.26/config/install-sh0000755000175000017510000003325512527201604014621 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: powerpc-utils-1.2.26/config/missing0000755000175000017510000001533112527201604014207 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2012-06-26.16; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'automa4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: powerpc-utils-1.2.26/doc/0000775000175000017510000000000012542271540012172 500000000000000powerpc-utils-1.2.26/doc/activate_firmware.doxycfg0000664000175000017510000013430712527176005017206 00000000000000# Doxyfile 1.3.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = activate_firmware # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../../cmds/activate_fw.c # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO powerpc-utils-1.2.26/doc/nvram.doxycfg0000664000175000017510000013431012527176005014627 00000000000000# Doxyfile 1.3.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = nvram # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../../cmds/nvram.c ../../cmds/nvram.h # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO powerpc-utils-1.2.26/doc/rtas_ibm_get_vpd.doxycfg0000664000175000017510000013431312527176005017017 00000000000000# Doxyfile 1.3.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = rtas_ibm_get_vpd # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../../cmds/rtas_ibm_get_vpd.c # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO powerpc-utils-1.2.26/doc/serv_config.doxycfg0000664000175000017510000013433412527176005016016 00000000000000# Doxyfile 1.3.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = serv_config # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../../cmds/serv_config.c ../../cmds/librtas_error.c # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO powerpc-utils-1.2.26/doc/set_poweron_time.doxycfg0000664000175000017510000013431312527176005017071 00000000000000# Doxyfile 1.3.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = set_poweron_time # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../../cmds/set_poweron_time.c # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO powerpc-utils-1.2.26/doc/uesensor.doxycfg0000664000175000017510000013432612527176005015356 00000000000000# Doxyfile 1.3.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = uesensor # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of source # files, where putting all generated files in the same directory would otherwise # cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is used # as the annotated text. Otherwise, the brief description is used as-is. If left # blank, the following values are used ("$name" is automatically replaced with the # name of the entity): "The $name class" "The $name widget" "The $name file" # "is" "provides" "specifies" "contains" "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited # members of a class in the documentation of that class as if those members were # ordinary class members. Constructors, destructors and assignment operators of # the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources # only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../../cmds/uesensor.c ../../cmds/librtas_error.c # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_PREDEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse the # parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or # super classes. Setting the tag to NO turns the diagrams off. Note that this # option is superseded by the HAVE_DOT option below. This is only a fallback. It is # recommended to install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes that # lay further from the root node will be omitted. Note that setting this option to # 1 or 2 may greatly reduce the computation time needed for large code bases. Also # note that a graph may be further truncated if the graph's image dimensions are # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO powerpc-utils-1.2.26/m4/0000775000175000017510000000000012542271540011745 500000000000000powerpc-utils-1.2.26/m4/ax_append_compile_flags.m40000664000175000017510000000553112527176005016761 00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html # =========================================================================== # # SYNOPSIS # # AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS]) # # DESCRIPTION # # For every FLAG1, FLAG2 it is checked whether the compiler works with the # flag. If it does, the flag is added FLAGS-VARIABLE # # If FLAGS-VARIABLE is not specified, the current language's flags (e.g. # CFLAGS) is used. During the check the flag is always added to the # current language's flags. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # NOTE: This macro depends on the AX_APPEND_FLAG and # AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with # AX_APPEND_LINK_FLAGS. # # LICENSE # # Copyright (c) 2011 Maarten Bosmans # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 4 AC_DEFUN([AX_APPEND_COMPILE_FLAGS], [AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) for flag in $1; do AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3]) done ])dnl AX_APPEND_COMPILE_FLAGS powerpc-utils-1.2.26/m4/ax_append_flag.m40000664000175000017510000000530412527176005015064 00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_append_flag.html # =========================================================================== # # SYNOPSIS # # AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) # # DESCRIPTION # # FLAG is appended to the FLAGS-VARIABLE shell variable, with a space # added in between. # # If FLAGS-VARIABLE is not specified, the current language's flags (e.g. # CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains # FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly # FLAG. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 2 AC_DEFUN([AX_APPEND_FLAG], [AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl AS_VAR_SET_IF(FLAGS, [case " AS_VAR_GET(FLAGS) " in *" $1 "*) AC_RUN_LOG([: FLAGS already contains $1]) ;; *) AC_RUN_LOG([: FLAGS="$FLAGS $1"]) AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) ;; esac], [AS_VAR_SET(FLAGS,["$1"])]) AS_VAR_POPDEF([FLAGS])dnl ])dnl AX_APPEND_FLAG powerpc-utils-1.2.26/m4/ax_check_compile_flag.m40000664000175000017510000000641112527176005016402 00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 3 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS powerpc-utils-1.2.26/m4/ax_check_link_flag.m40000664000175000017510000000611512527176005015710 00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the linker or gives an error. # (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the linker's default flags # when the check is done. The check is thus made with the flags: "LDFLAGS # EXTRA-FLAGS FLAG". This can for example be used to force the linker to # issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_LINK_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 3 AC_DEFUN([AX_CHECK_LINK_FLAG], [AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ ax_check_save_flags=$LDFLAGS LDFLAGS="$LDFLAGS $4 $1" AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) LDFLAGS=$ax_check_save_flags]) AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_LINK_FLAGS powerpc-utils-1.2.26/m4/ax_require_defined.m40000664000175000017510000000230112527176005015750 00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_require_defined.html # =========================================================================== # # SYNOPSIS # # AX_REQUIRE_DEFINED(MACRO) # # DESCRIPTION # # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have # been defined and thus are available for use. This avoids random issues # where a macro isn't expanded. Instead the configure script emits a # non-fatal: # # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found # # It's like AC_REQUIRE except it doesn't expand the required macro. # # Here's an example: # # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) # # LICENSE # # Copyright (c) 2014 Mike Frysinger # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 1 AC_DEFUN([AX_REQUIRE_DEFINED], [dnl m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) ])dnl AX_REQUIRE_DEFINED powerpc-utils-1.2.26/man/0000775000175000017510000000000012542271540012200 500000000000000powerpc-utils-1.2.26/man/activate_firmware.80000664000175000017510000000150312527176005015707 00000000000000.\" .\" Copyright (C) 2004 International Business Machines .\" .TH ACTIVATE_FIRMWARE 8 "May 2004" Linux "Power Service Tools" .SH NAME activate_firmware - activate a firmware image that has been updated concurrently .SH SYNOPSIS \fB/usr/sbin/activate_firmware .SH DESCRIPTION The activate_firmware utility will cause a firmware image that has already been flashed to be activated concurrently. This utility will be invoked automatically when necessary, and as such should not be manually invoked at the command line. .SH "EXIT STATUS" .TP .B 0 Success. .TP .B 1 This platform does not support concurrent activation of firmware. .TP .B 2 There is no new firmware ready to activate. .TP .B 3 You must have root authority to run this command. .TP .B 4 Hardware failure. .TP .B 5 Memory/resource allocation error. .TP .B 6 General error. powerpc-utils-1.2.26/man/rtas_ibm_get_vpd.80000664000175000017510000000246112527176005015527 00000000000000.\" .\" Copyright (C) 2004 International Business Machines .\" Michael Strosaker .\" .TH RTAS_IBM_GET_VPD 8 "May 2004" Linux "Power Service Tools" .SH NAME rtas_ibm_get_vpd \- retrieve dynamically changing Vital Product Data .SH SYNOPSIS .nf \fB/usr/sbin/rtas_ibm_get_vpd \-h \fB/usr/sbin/rtas_ibm_get_vpd \fR[\fB\-l \fIlocation_code\fR] .fi .SH DESCRIPTION .P The .I rtas_ibm_get_vpd utility is a utility to assist inventory retrieval applications by gathering dynamically changing vital product data on IBM ppc64 systems. The output of this utility is formatted to be parsed by other applications; as such, it is not intended for general command-line usage, though there is no reason that it should not be used in that manner. .SH OPTIONS .TP .B \-l \fIlocation_code Specify the location code of the device from which dynamic VPD should be gathered. If this option is not specified, dynamic VPD for all appropriate devices will be gathered. .TP .B \-h Print a usage message. .SH EXIT STATUS .TP .B 0 Success. .TP .B 1 Usage or parameter error. .TP .B 2 Hardware error. .TP .B 3 The library used to invoke firmware routines, librtas, has experienced an error. .TP .B 4 The necessary firmware routine is not available on this system. .TP .B 5 Out of memory. .SH "SEE ALSO" .BR lsvpd (8), .BR lscfg (8) powerpc-utils-1.2.26/man/uesensor.80000664000175000017510000000455512527176005014070 00000000000000.\" .\" Copyright (C) 2004 International Business Machines .\" Michael Strosaker .\" .TH UESENSOR 8 "May 2004" Linux "Linux on Power Service Tools" .SH NAME uesensor \- view the state of system environmental sensors .SH SYNOPSIS .nf \fB/usr/sbin/uesensor -l \fR| \fB -a \fB/usr/sbin/uesensor -t \fItoken \fB-i \fIindex \fR[\fB-v\fR] .fi .SH DESCRIPTION .P The \fIuesensor\fR utility is used to view the state of environmental sensors on PowerPC-64 machines. .P There are 4 types of system sensors that can be retrieved with \fIuesensor\fR; each sensor has an identifying token: .TP .B 3 Thermal sensor .TP .B 9001 Fan speed sensor .TP .B 9002 Voltage sensor .TP .B 9004 Power supply sensor .P Each sensor is uniquely identified by a combination of token and index number; index numbers start at 0 and are contiguous. For example, the second fan on the system would be identified by token number 9001 and index 1. .P The state of each sensor consists of a status and a measured value. The status value is one of the following: .TP .B 9 Critical low .TP .B 10 Warning low .TP .B 11 Normal .TP .B 12 Warning high .TP .B 13 Critical high .P The measured value depends on the type of sensor. Thermal sensors are measured in degrees Celcius; fan speed is measured in revolutions per minute; voltage is measured in millivolts; power supply measurements are defined as follows: .TP .B 0 Not present .TP .B 1 Present and not operational .TP .B 2 Status unknown .TP .B 3 Present and operational .P Each sensor is also associated with a location code; this location code may not be unique (for example, there may be multiple voltage sensors on a planar). .SH OPTIONS .TP .B \-l List all the sensors in human-readable format. .TP .B \-a List all the sensors in a tabular, numerical format. One line will be printed for each sensor in the following format: .nf .I .fi .TP \fB\-t \fItoken Specify the token of a specific sensor to query. Also requires the \fB\-i\fR option to be specified. .TP \fB\-i \fIindex Specify the index of a specific sensor to query. Also requires the \fB\-t\fR option to be specified. .TP .B \-v Print the measured value rather than the sensor status, which is the default value printed. Requires both the \fB\-t\fR and \fB-i\fR options to be specified. .SH "SEE ALSO" .BR usysident (8), .BR usysattn (8) powerpc-utils-1.2.26/man/amsstat.10000664000175000017510000002735112527176005013671 00000000000000.\" Copyright (C) 2009 International Business Machines. .\" Common Public License Version 1.0 (see COPYRIGHT) .\" .\" Author(s) .\" Robert Jennings .\" .TH AMSSTAT 1 "March 2009" Linux "Linux on Power Service Tools" .SH NAME amsstat \- display a list of Active Memory Sharing (AMS) statistics. .SH SYNOPSIS .B /usr/bin/amsstat [\fISECONDS\fP] .SH DESCRIPTION This program captures memory statistics relevant in an Active Memory Sharing (AMS) environment. This tool can run once or be set to run repeatedly with a specified timeout, in seconds, between instances of data collection. Several sections are displayed for the partition, they are as follows: .SS System Memory Statistics In an AMS environment, the amount of memory available will change as memory is loaned to other partitions by the Cooperative Memory Manager (CMM) module. This section will show how the total amount of memory provided to the partition is being utilized. .P The fields here are taken from \fI/proc/meminfo\fP. .TP MemTotal This value, expressed in kilobytes, is the maximum amount of memory available to the operating system. .TP MemFree This value, displayed in kilobytes, is the amount of memory which is unused. .TP Buffers The amount of memory, in kilobytes, used for file buffers. .TP Cached The amount of memory, in kilobytes, used as cache memory. .TP Inactive The total amount of buffer or page cache memory, in kilobytes, that are free and available. This is memory that has not been recently used and can be reclaimed for other purposes. .TP SwapTotal The total amount of swap available, in kilobytes. .TP SwapFree The total amount of swap free, in kilobytes. .TP DesMem The desired memory field shows the amount of memory that firmware would like to to have currently assigned to the partition. This relates to the amount of assigned memory specified in the HMC or IVM however this value can be out-of-sync withe current amount of memory assigned to the operating system if dynamic memory add or remove operations have failed. .SS Entitlement Information This information is specific to an AMS environment, the fields are taken from \fI/proc/ppc64/lparcfg\fP. .TP entitled_memory The \fIentitled_memory\fP is a specific amount of memory given to the operating system that will be available to be mapped for IO operations; this guarantee is maintained by the platform firmware and can be tuned through the HMC or IVM depending on the particular environment. This value is displayed in kilobytes. The amount of \fIentitled memory\fP is changed by the HMC or IVM in response to hot-plug events or explicit tuning. .TP mapped_entitled_memory The number of bytes of \fIentitled_memory\fP currently mapped for IO operations according to firmware. .TP entitled_memory_group_number This value is assigned to the partition by firmware and can be used by support to help correlate operating system data with firmware data. It is not of use to the end user but is displayed for debug support. .TP entitled_memory_pool_number This is the identification number of the shared memory pool to which this partition belongs. .TP entitled_memory_weight This is the weighting that is used by firmware to help prioritize partitions for memory loaning. .TP entitled_memory_pool_size This is the total size of the physical memory in the memory pool to which this partition belongs and includes memory that may not presently be accessible to the operating system. .TP entitled_memory_loan_request The number of bytes which firmware would like the partition to give or take via the Cooperative Memory Manager (CMM). Positive values denote a request of how much memory, in bytes, it would like the operating system to loan to firmware. Negative values denote that the operating system may take back that number of bytes of memory for its own use. .TP backing_memory This is the amount of physical memory, in bytes, that is currently reserved for access by this partition. This value does change over time based on load of all of the partitions in the shared memory pool. Use of memory in excess of this amount incurs performance penalties as loaning and paging will need to occur. .TP coalesced_bytes The number of bytes of memory assigned to the logical partition which have been coalesced with identical pages either within the logical partition, or with another logical partition. .TP pool_coalesced_bytes The number of bytes of memory in the shared memory pool which have been coalesced with identical pages. .TP cmo_enabled When this value is \fI1\fP the partition is running in shared memory mode. A \fI0\fP in this field indicates that dedicated memory mode is enabled and the AMS kernel code will not be active. .TP cmo_faults A fault occurs when an attempt to access memory is made where the platform firmware must suspend the partition and request data from disk. This value is a sum of the number of faults since the operating system was booted. Increases in this value indicate contention for memory between partitions in the AMS environment. .TP cmo_fault_time_usec This value is a running sum of the amount of time, since boot time, that the operating system has been suspended by platform firmware to process \fIcmo_faults\fP. This value is given is microseconds (10^-6 or 0.0000001 seconds). .TP cmo_primary_psp This is the identification number of the primary paging storage pool (psp). .TP cmo_secondary_psp This is the identification number of the secondary paging storage pool (psp). .SS CMM Statistics The Cooperative Memory Manager (CMM) module loans unused memory to firmware to be used by other partitions within the shared memory pool. The fields here are taken from \fI/sys/module/cmm/parameters\fP and \fI/sys/devices/system/cmm/cmm0\fP. .TP disable The CMM code is disabled when this is set to 1 and is enabled when this value is 0. If CMM is disabled no loaning will occur. .TP debug Set to 1, CMM will print debug information regarding the number of pages loaned, the loan request from firmware, etc to the console or system log. .TP min_mem_mb This the amount of partition memory, in megabytes, which will be reserved from loaning. .TP oom_kb The number of kilobytes of memory taken back from firmware by the CMM module for the operating system when an out of memory signal from the kernel is caught by CMM. .TP delay This is the number of seconds that CMM waits between requests to firmware for the number of pages that firmware would like the operating system to loan. .TP loaned_kb This is the amount of memory, in kilobytes, that the operating system has given back to the platform firmware to be used by other partitions. This value fluctuates to meet the demands of all of the partitions in the shared memory pool of an AMS environment. .TP loaned_target_kb This is the amount of memory, in kilobytes, that the firmware would like the operating system to loan for use by other partitions. This value may be greater than \fIloaned_kb\fP if firmware would like additional pages to be loaned or it may be less than \fIloaned_kb\fP if firmware is providing additional pages to the operating system. .TP oom_freed_kb The amount of memory, in kilobytes, that is no longer being loaned by CMM as a result of out-or-memory kernel signals. .SS VIO Bus Statistics The VIO Bus manages the operating system's \fIentitled memory\fP for devices which may perform DMA operations. The data here is found in the \fI/sys/bus/vio/\fP directory. The use of \fIcmo\fP is a historical reference to the \fIAMS\fP feature and is used interchangeably. .TP cmo_entitled The \fIentitled\fP memory is a specific amount of memory given to the operating system that will be available to be mapped for IO operations; this guarantee is maintained by the platform firmware and can be tuned through the HMC or IVM depending on the particular environment. This value is displayed in kilobytes. The amount of \fIentitled\fP memory is changed by the HMC or IVM in response to hot-plug events or explicit tuning. .TP cmo_reserve_size The \fIentitled\fP memory is split into two pools, the first of which is the \fIreserve pool\fP. This value, expressed in kilobytes, represents the amount of memory guaranteed to individual devices on the bus. .TP cmo_excess_size This pool contains any amount of \fIentitled\fP memory not placed in the \fIreserve pool\fP; the value is displayed in kilobytes. Any device can map memory from this pool for IO operations, after having used up its own allocation from the \fIreserve pool\fP, until the \fIexcess pool\fP is exhausted. .TP cmo_excess_free This value represents the amount of memory, in kilobytes, currently available for devices to use from the \fIexcess pool\fP. .TP cmo_spare This value represents the amount of memory, in kilobytes, kept unused to handle hot-plug events, entitlement rebalancing between devices, and module loading. .TP cmo_min This value represents the current minimum amount of entitlement that the operating system could function with based on the ideal size of the \fIspare\fP allocation plus a small allocation for each device present in the system. Requests to change system entitlement below this value will fail. Setting entitlement to this value may impact performance, but should allow the system to make forward progress, the ideal value is displayed in \fIcmo_desired\fP below. .TP cmo_desired Each device in the system that requires memory for mapping IO operations will specify an amount of memory which is desired for optimal performance. This value is the sum of the requests made by individual devices on the bus and is measured in kilobytes. .TP cmo_curr This value represents the amount of memory, in kilobytes, that is currently mapped by device drivers for IO operations. .TP cmo_high This value, measured in kilobytes, represents the largest amount of memory mapped at any one point in time since the system was booted or the field was last reset. This value can be reset by writing a '0' to the file \fI/sys/bus/vio/cmo_high\fP. .SS VIO Device Statistics Each device that is configured and performs DMA operations will appear listed beneath this heading. The devices are displayed by their location on the VIO bus nd the data is pulled from \fI/sys/bus/vio/devices/\fP\fB\fP\fI/*\fP. For each device the following are shown: .TP cmo_desired The amount of memory, in kilobytes, that the device has requested from the bus to provide optimal performance. The amount of \fIcmo_entitled\fP memory will not exceed this amount. The device may receive a memory entitlement less than its desired level in cases where resources are limited. .TP cmo_entitled The amount of memory, in kilobytes, that the device is guaranteed that it may map for IO operations. The allocation of this entitled memory is made to the device from the bus' \fIcmo_reserve_pool\fP. .TP cmo_allocated The amount of memory, in kilobytes, that the device has currently mapped for IO operations. .TP cmo_allocs_failed When the amount of memory allocated (\fIcmo_allocated\fP) has exhausted both the entitled memory (\fIcmo_entitled\fP) and the bus' excess pool, memory mapping failures will occur. For each failed attempt, the value displayed here will increase by 1. Large changes in this value would indicate resource contention that may require system tuning. The device drivers are written such that these failures, while impacting performance, do not impede functionality. To reset this counter, the value '0' can be written to the file \fI/sys/bus/vio/devices/\fP\fI/cmo_allocs_failed\fP. .SH EXAMPLES .TP .B amsstat Display the AMS data for the local system, providing an update every 10 seconds. .P .TP .BI amsstat " 10" Display a list of AMS statistics and repeat every 10 seconds thereafter. .SH FILES .I /proc/sys/meminfo .br .I /proc/ppc64/lparcfg .br .I /sys/module/cmm/parameters/* .br .I /sys/devices/system/cmm/cmm0/ .br .I /sys/bus/vio/cmo_* .br .I /sys/bus/vio/devices/*/cmo_* powerpc-utils-1.2.26/man/serv_config.80000664000175000017510000001171412527176005014524 00000000000000.\" .\" Copyright (C) 2004 International Business Machines .\" Michael Strosaker .\" .TH SERV_CONFIG 8 "May 2004" Linux "Linux on Power Service Tools" .SH NAME serv_config \- view and configure system service policies and settings on IBM ppc64 platforms .SH SYNOPSIS .nf \fB/usr/sbin/serv_config \fR[\fB-b\fR] [\fB-s\fR] [\fB-r\fR] [\fB-m\fR] \fB/usr/sbin/serv_config -l \fB/usr/sbin/serv_config -z \fIfilename \fB/usr/sbin/serv_config -e \fIvar\fR[\fB=\fIvalue\fR] \fB/usr/sbin/serv_config \fR[\fB--surveillance\fR[\fB=\fIsettings\fR]] \fR[\fB--reboot-policy\fR[\fB=\fIsettings\fR]] \fR[\fB--ring-indicate\fR[\fB=\fIsettings\fR]] \fR[\fB--remote-maint\fR[\fB=\fIsettings\fR]] \fR[\fB--force\fR] .fi .SH DESCRIPTION .P The .I serv_config utility is used to view and manipulate various system service policies and settings on PAPR-compliant PowerPC-64 machines, such as IBM pSeries, iSeries, System p or System i machines. .P .I serv_config can be run in one of two modes; interactive mode, in which the user will be prompted for the value of each variable in the specified category, or macro mode, in which the string provided on the command line will be parsed for the values of the variables in the category. Macro mode is for expert use only; most users should be utilizing the interactive options (\fB\-s\fR, \fB\-b\fR, \fB\-r\fR, and \fB\-m\fR). .P .B NOTE: It is recommended that the current service settings are backed up with the \fB\-l\fR option before the settings are manipulated with this utility. Should a value be mistakenly updated to an incorrect value, all the settings can be restored to the backed up values with the \fB\-z\fR option. .SH OPTIONS .TP .B \-l List all of the current service settings. If this output is stored to a file, these settings can be later restored with the \fB\-z\fR option. .TP \fB\-e \fIvar\fR[\fB=\fIvalue\fR] If only \fIvar\fR is specified, the value of the specified service setting is displayed; if a \fIvalue\fR is also specified, the value of the specified service setting is updated to the specified value. .TP .B \-s Interactively update the Surveillance settings. .TP .B \-b Interactively update the Reboot policies. .TP .B \-r Interactively update the Remote Power-On settings (either Ring Indicate Power-On or Wake On LAN). .TP .B \-m Interactively update the Remote Maintenance settings. .TP .B \-z \fIfilename Restore the service settings that were previously stored to \fIfilename\fR (using the \fB\-a\fR option). .SH ADVANCED OPTIONS .P The following options are for expert users only. They are intended to be used by scripts and utilities which have been designed to automate the retrieval/manipulation of service settings. .TP \fB\-\-surveillance\fR[\fB=\fIsettings\fR] View or update the Surveillance settings in macro mode. If the \fIsettings\fR argument is not specified, all of the Surveillance variables are printed along with their corresponding values. If the \fIsettings\fR argument is specified, the Surveillance settings are updated to the specified values. The \fIsettings\fR argument should be in the following format: .nf \fIsp-sen\fB,\fIsp-sti\fB,\fIsp-del\fB,\fIimmediate .fi .TP \fB\-\-reboot\-policy\fR[\fB=\fIsettings\fR] View or update the Reboot policies in macro mode. If the \fIsettings\fR argument is not specified, all of the Reboot policy variables are printed along with their corresponding values. If the \fIsettings\fR argument is specified, the Reboot policies are updated to the specified values. The \fIsettings\fR argument should be in the following format on legacy systems: .nf \fIsp-bootrt-limit\fB,\fIsp-os-plt-reboot\fB,\fIsp-plt-reboot\fB, \fIsp-dookc\fB,\fIsp-ac-reboot\fR On recent systems, the following format is used: \fIpartition_auto_restart\fB,\fIplatform_auto_power_restart .fi .TP \fB\-\-remote\-pon\fR[\fB=\fIsettings\fR] View or update the Remote Power-On settings in macro mode. If the \fIsettings\fR argument is not specified, all of the Remote Power-On variables are printed along with their corresponding values. If the \fIsettings\fR argument is specified, the Remote Power-On settings are updated to the specified values. The \fIsettings\fR argument should be in the following format for systems with support for Ring Indicate Power-On: .nf \fIsp-ri-pon\fB,\fIsp-rb4-pon\fR On systems with support for Wake On LAN, the format is as follows: \fIsp-remote-pon .fi .TP \fB\-\-remote\-maint\fR[\fB=\fIsettings\fR] View or update the Remote Maintenance settings in macro mode. If the \fIsettings\fR argument is not specified, all of the Remote Maintenance variables are printed along with their corresponding values. If the \fIsettings\fR argument is specified, the Remote Maintenance settings are updated to the specified values. .TP .B \-\-force Do not prompt for confirmation before modifying system settings; only valid in macro mode (ignored in interactive mode). .SH "SEE ALSO" .BR bootlist (8), .BR lscfg (8), .BR nvram (8) powerpc-utils-1.2.26/man/update_flash.80000664000175000017510000001446212527176005014662 00000000000000.\" .\" Copyright (C) 2002 - 2013 International Business Machines .\" Todd Inglett .\" Michael Strosaker .\" Vasant Hegde .\" .TH UPDATE_FLASH 8 "8 May 2013" Linux "PowerLinux Service Tools" .SH NAME update_flash \- manage system and service processor firmware .SH SYNOPSIS .nf \fB/usr/sbin/update_flash \fR[\fB-v|-n\fR] \fB-f \fIfirmware.img .B /usr/sbin/update_flash -h .B /usr/sbin/update_flash -c .B /usr/sbin/update_flash -r .B /usr/sbin/update_flash -s .fi .SH DESCRIPTION .P The .I update_flash script is used to validate, update and manage firmware on an IBM Power Systems servers. .TP .nf .B VALIDATION .fi When used with the .B -v option, the script will ONLY perform validation of the image file. Regardless of the outcome of the validation, no actual flash will occur. This option is only useful on machines that support validation of firmware images. .TP .nf .B UPDATE .fi When used with only the .B -f option and an image file name, the script will attempt to update the system firmware with the given image. If the machine has the ability to pre-validate the image, this will be done automatically before the flash. If the machine is not capable of pre-validation, or if validation passes, this script will upload the firmware image into the kernel and will perform a .B shutdown -r now which will reboot the system. The flash will occur at the end of the reboot process. .B WARNING: The system WILL be rebooted! Wait until the flash process has completed. This can be anywhere from 2 minutes to 20 minutes (or more) depending on the system. The control panel display will show that the system is flashing. Failure to wait may render a system inoperable. .B NOTE: If machine supports two firmware image areas, update is always applied to the temporary image area. The .B -c option is the normal means by which a temporary image is committed to the permanent side (see MANAGEMENT). However, if a platform is running from a temporary image when an update is to be applied, then the platform may automatically commit the current temporary image to the permanent side to allow the new image to be updated to the temporary image area. The .B -v option can be used to determine what would result from an attempt to update a flash image. The .B -n option will prevent the automatic overwrite of the permanent image area and abandon the update entirely. To apply an update to the temporary image area without overwriting the permanent image area, the system must first be running with the permanent image. The temporary image can then be rejected (see MANAGEMENT). Subsequently, the update can be applied. .TP .nf .B MANAGEMENT .fi When used with the .B -c option, the script will commit the temporary image to the permanent side. In order to use this, the machine must be running on the temporary image. This option is only useful on machines supporting two firmware image areas. When used with the .B -r option, the script will reject the temporary image. In order to use this, the machine must be running on the permanent image. To switch from the temporary image to the permanent image, you must reboot from the permanent image -- for example, using the ASMI or HMC. This option is only useful on machines supporting two firmware image areas. .SH OPTIONS .TP .B \-h Print the usage message and exit. .TP \fB\-f \fIfilename Supply the filename to flash (required). .TP .B \-v Validate ONLY with specified image file. .TP .B \-n Do not overwrite permanent side image automatically. .TP .B \-c Commit temporary image to permanent side. .TP .B \-r Reject temporary image. .TP .B \-s Determine if partition has access to perform flash image management. .SH EXAMPLES .P To determine if partition has authority to flash image: # update_flash -s .P For a typical firmware update (this may commit temporary to permanent): # update_flash -f 01AL740_100_042.img .P To update only if permanent side will not be overwritten: # update_flash -n -f 01AL740_100_042.img .P To validate an image: # update_flash -v -f 01AL740_100_042.img .P To commit temporary image to permanent (note that the system must be running on temporary image): # update_flash -c .P To reject temporary image, and copy to permanent to temporary (note that the system must be running on permanent image): # update_flash -r .SH EXIT STATUS .TP .nf All cases: 3 - Usage error 4 - Permission error 6 - Unexpected problem with /proc filesystem access 7 - Error loading module 8 - RTAS(pSeries)/OPAL(PowerNV) call failed 9 - User aborted operation .fi .TP .nf Determine if partition has authority to manage image (-s): 0 - Flash image management is supported 1 - Flash image management is not supported on this system .fi .TP .nf Validation (-v): 0 - Validation successful .fi .TP .nf Update ([-n] -f): 5 - Image file error 10 - Auto overwrite permanent side image 15 - Update Access Key Expired .fi .TP .nf Manage (-c|-r): 0 - Temporary image commit/reject successful .fi .SH FILES .TP .nf pSeries rtas_flash kernel module /proc/ppc64/rtas/firmware_flash (provided by kernel module) .fi .TP .nf PowerNV /sys/firmware/opal/image /sys/firmware/opal/{validate/manage/update}_flash .fi .SH NOTES Firmware may be downloaded from the IBM website. Instructions for downloading and installing the firmware image are also there, and information there will be more up-to-date than this page. .P Various conditions can lead to a firmware update failure. If you receive an authentication-related error, such as: .P .nf update_flash: RTAS: validate() Partition does not have authority -or- update_flash: System does not have authority to perform firmware update. .fi .P This can reflect either 1) That the permission is not set (correctable through the ASM interface, System -> Firmware Update Policy, or through an HMC if attached. .P -or- .P 2) Firmware still believes an HMC is attached. This can be corrected by following the steps outlined here: .P http://publib.boulder.ibm.com/infocenter/powersys/v3r1m5/index.jsp?topic=/p7hatl/iphblresetserverp6.htm .P For older "AIX format" images, the file will have a .BIN extension. This zip file happens to be an AIX binary, but it can be extracted with the unzip command (with password from the web page): unzip 70286C4F.BIN This should produce a file with a .img extension. This image file is what should be flashed. powerpc-utils-1.2.26/man/nvram.80000664000175000017510000000430312527176005013337 00000000000000.\" .\" Copyright (C) 2002 - 2004 International Business Machines .\" .TH NVRAM 8 "May 2004" Linux "Linux on Power Service Tools" .SH NAME nvram \- format data stored in non-volatile RAM .SH SYNOPSIS .B /usr/sbin/nvram [ options ] .SH DESCRIPTION .I Nvram is used to print and modify data stored in the non-volatile RAM (NVRAM) on a PowerPC-64 system. NVRAM on these systems is partitioned into data sections that each have their own format. The print options to this command selects what to print and how to format it. .P The .I nvram utility can also be used to update the data in certain NVRAM partitions of PowerPC-64 systems. .I Nvram can update the value of a name/value pair for NVRAM partitions formatted as a set of name=value pairs. On many systems, the following NVRAM partitions contain data formatted as name=value pairs: common, of-config, and ibm,setupcfg. .SH OPTIONS .TP \fB\--print-config\fR[=\fIvar\fR] print value of a config variable, or print all variables in the specified (or all) partitions. .TP \fB\--update-config \fIname\fR=\fIvalue update the config variable in the specified partition; the -p option must also be specified.. .TP \fB\-p \fIpartition specify a partition; required with the --update-config option, optional with the --print-config option. .TP \fB\--print-vpd print vital product data (VPD) collected by the system in NVRAM. This data may also be viewed with the lscfg(1) command directly from the devices. .TP \fB\--print-all-vpd print viral product data (VPD) collected by the system in NVRAM including vendor specific data. .TP \fB\--print-err-log print the checkstop error log generated by the service processor whenever the system checkstops. .TP \fB\--print-event-scan print the event scan log stored in NVRAM. .TP \fB\--partitions print the contents of all the NVRAM partition headers. .TP \fB\--nvram-file \fIpath read nvram data from a given file rather than /dev/nvram. To capture NVRAM for later use, simply copy /dev/nvram into a file. .TP \fB\--verbose \fR(\fB-v\fR) be more verbose. .TP \fB\--help print usage information including other low level options useful for debugging nvram. .SH FILES /dev/nvram .SH AUTHOR Writtem by Todd Inglett, Nathan Fontenot, and Michael Strosaker powerpc-utils-1.2.26/man/set_poweron_time.80000664000175000017510000000547412527176005015610 00000000000000.\" .\" Copyright (C) 2004 International Business Machines .\" Michael Strosaker .\" .TH SET_POWERON_TIME 8 "May 2004" Linux "Power Service Tools" .SH NAME set_poweron_time \- set a time in the future for the system to be powered on .SH SYNOPSIS .nf \fB/usr/sbin/set_poweron_time \fR[\fB-s\fR] \fB-t \fIabsolute_time \fB/usr/sbin/set_poweron_time \fR[\fB-s\fR] \fB-d \fIdelta_time .B /usr/sbin/set_poweron_time -m .B /usr/sbin/set_poweron_time -h .fi .SH DESCRIPTION .P The .I set_poweron_time utility is used to set a time in the future to power on the system. The utility uses firmware interfaces provided by IBM ppc64 systems to provide this functionality. .P When used with the .B -t option, the utility will configure the system to power-on at the specified date and time. This is usefule for specifying that the sysetm should be restarted at 6 AM on Monday morning, for example. When used with the .B -d option, the utility will treat the specified time as a delta from the present. This is useful for specifying that the system should be restarted in 2 days, for example. Times for the .B -t and .B -d options should be specified in the following format: .P \fBY\fR\fBM\fR\fBD\fR\fBh\fR\fBm\fR\fBs\fR .P The month, if specified, should be in the range of 1-12. The day, if specified, should be in the range of 1-31. The hour, if specified, should be in the range of 0-23. The minute and second, if specified, should be in the range of 0-59. .TP For the -t option: Year, month, and day default to the current date if not specified. Hour, minute, and second default to 0 if not specified. .TP For the -d option: Year, month, day, hour, minute, and second default to 0 if not specified. .P When used with the .B -m option, the utility will print the maximum amount of time in the future that the power-on time can be set (in days). This option cannot be used with any others. When used with the .B -s option, the utility will shut down the system with .B shutdown -h now after the power-on time has been set. If the utility is unable to set the power-on time for any reason, the system will not be shut down. .SH OPTIONS .TP \fB\-t \fIabsolute_time specify the power-on time .TP \fB\-d \fIdelta_time specify the power-on time as a delta from the current time .TP .B \-m print the maximum amount of time in the future that the power-on time can be set (in days) .TP .B \-s shut down the system after setting the power-on time. The system will not be shut down if the power-on time cannot be set for any reason. .TP .B \-h print a usage message with examples .SH EXAMPLES .nf Shut down the system and schedule it to restart in 12 hours and 10 minutes: set_poweron_time -d h12m10 -s Schedule the system to restart at noon on June 15th of this year: set_poweron_time -t M6D15h12 .fi powerpc-utils-1.2.26/man/bootlist.80000664000175000017510000000414212527176005014054 00000000000000.\" .\" Copyright (C) 2004 International Business Machines .\" Nathan Fontenot .\" .TH BOOTLIST 8 "May 2013" Linux "Linux on Power Service Tools" .SH NAME bootlist - update and view the bootlist .SH SYNOPSIS .nf \fB/usr/sbin/bootlist \-m \fR{\fBnormal\fR|\fBservice\fR|\fBboth\fR}\fB -o\fR|\fB-r\fR \fB/usr/sbin/bootlist \-m \fR{\fBnormal\fR|\fBservice\fR|\fBboth\fR} [\fB-o\fR|\fB-r\fR] \fB-f \fIfile \fB/usr/sbin/bootlist \-m \fR{\fBnormal\fR|\fBservice\fR|\fBboth\fR} [\fB-o\fR|\fB-r\fR] <\fIdev_list\fR> .fi .SH DESCRIPTION The bootlist command allows users to view and update the system bootlist stored in NVRAM for PowerPC-64 machines. To update the list of boot devices one or more boot devices can be specified directly or read from a file. This list of devices may be specified as either logical device names or the full Open Firmware device path. The bootlist command uses the \fIofpathanme\fR script to convert between logical device names and Open Firmware device paths, and the \fInvram\fR command to update the stored boot list. If a list of devices is not specified, or the -o or -r options are specified, the current boot list stored in nvram is displayed. .SH OPTIONS .TP \fB\-m normal\fR|\fBservice\fR|\fBboth Required; specify whether the normal or service mode boot list should be viewed/updated. Specifying "both" will update the normal and service mode boot lists. .TP \fB\-o Display the current boot list entries as logical device names. .TP \fB\-r Display the current boot list entries as Open Firmware device path names (default). .TP \fB\-f \fIfile Read the bootlist device names from \fIfile\fR, one entry per line. .TP \fIdev_list A space-separated list of devices, specified as logical device names or OF device path names, depending on whether the \fB-o\fR or \fB-r\fR option is specified. .SH EXAMPLES .nf View the normal mode boot list as logical device names: /usr/sbin/bootlist -o -m normal Update the service mode boot list: /usr/sbin/bootlist -o -m service /dev/sda3 /dev/cdrom .fi .SH AUTHOR Written by Nathan Fontenot .SH "SEE ALSO" .BR ofpathname (8), .BR nvram (8) powerpc-utils-1.2.26/man/ofpathname.80000664000175000017510000000176612527176005014350 00000000000000.\" .\" Copyright (C) 2004 International Business Machines .\" Nathan Fontenot .\" .TH OFPATHNAME 8 "April 2004" Linux "Linux on Power Service Tools" .SH NAME ofpathname \- translate between Open Firmware and logical device names .SH SYNOPSIS \fB/usr/sbin/ofpathname \fR[\fB-laqVh\fR] \fIname .SH DESCRIPTION .I Ofpathname provides the ability to translate logical device names to their Open Firmware device path names for PowerPC-64 systems. It can also translate an Open Firmware device path to its logical device name using the -l option. .SH OPTIONS .TP \fB\-l Translate the \fIname \fRparameter to the corresponding logical device name. .TP \fB\-a Find a matching Open Firmware device alias[es]. .TP \fB\--quiet \fR(\fB\-q\fR) Do not report any failures, exit quietly. .TP \fB\--version \fR(\fB\-V\fR) Display version information and exit. .TP \fB\--help \fR(\fB\-h\fR) print usage information. .SH AUTHOR Written by Nathan Fontenot .SH "SEE ALSO" .BR bootlist (8), .BR nvram (8) powerpc-utils-1.2.26/man/snap.80000664000175000017510000000235412527176005013161 00000000000000.\" .\" Copyright (C) 2002 - 2012 International Business Machines .\" Todd Inglett .\" Michael Strosaker .\" Vasant Hegde .\" .TH SNAP 8 "30 May 2012" Linux "Linux on Power Service Tools" .SH NAME snap \- generate a configuration snapshot for service .SH SYNOPSIS \fB/usr/sbin/snap \fR[\fB-athv\fR] [\fB-d \fIdir\fR] [\fB-o \fIfile\fR] .SH DESCRIPTION The .I snap script copies several system status and config files and the output of several commands from the system into snap.tar.gz in the current directory. System servicers may ask that this be run in order collect data to diagnose a problem. .SH OPTIONS .TP .B \-a All data; collect detailed information (more files and output). .TP \fB\-d \fIdir Specify the directory where files and ouput will be collected (default: /tmp/ibmsupt). .TP .B \-h Print a help message. .TP \fB\-o \fIfile Specify the output path and filename (.tar required, .tar.gz optional) (default: snap.tar.gz). .TP \fB\-t Add hostname and timestamp to output filename. .TP .B \-v verbose output .SH FILES These are some of the files that are archived: .P /var/log/messages .br /var/log/scanoutlog.* .br /proc (select files) .br /dev/nvram .br /etc/yaboot.conf powerpc-utils-1.2.26/man/hvcsadmin.80000664000175000017510000000724312527176005014176 00000000000000.\" Copyright (c) 2005 International Business Machines. .\" Common Public License Version 1.0 (see COPYRIGHT) .\" .\" Author(s) .\" Ryan S. Arnold .\" Original version: January 14, 2005. .\" .Dd January 18, 2005 .Os LINUX .Dt HVCSADMIN 8 .Sh NAME .Nm hvcsadmin .Nd hypervisor virtual console server administration utility .Sh SYNOPSIS .Nm Fl all Op Fl noisy .Op Fl noisy .Pp .Nm Fl close Ar hvcs Op Fl noisy .Op Fl noisy .Pp .Nm Fl console Ar partition Op Fl noisy .Op Fl noisy .Pp .Nm Fl help .Pp .Nm Fl node Ar hvcs Op Fl noisy .Op Fl noisy .Pp .Nm Fl rescan Op Fl noisy .Op Fl noisy .Pp .Nm Fl status Op Fl noisy .Op Fl noisy .Pp .Nm Fl version .Pp .Sh DESCRIPTION This is the IBM hypervisor virtual console server .Pq \fBhvcs\fR administration utility. .Sh OPTIONS .Bl -tag -width -indent .It Fl all Close all open vty-server adapter connections. .Pp Inclusion of a single .Sq Fl noisy flag will direct the utility to output a list of all the adapters that were closed. .It Fl close Ar hvcs Close the vty-server adapter connection that maps to the hvcs device node specified in the option. .Pp By default this operation only exhibits output on error. It is silent on success and silent if the adapter is already closed. When accompanied by a .Sq Fl noisy flag this option will output the device to adapter mapping and a message indicating that the adapter has been closed. .It Fl console Ar partition Which /dev/hvcs node provides the console for the option specified partition? This option takes a partition number and returns a status string which contains the device node that maps to the target partition's slot zero vty-server adapter [A console adapter is always in slot zero]. .Pp Inclusion of a single .Sq Fl noisy flag does not change the default output of this option. .It Fl help Output the utility help text. .It Fl node Ar hvcs Which vty-server adapter is mapped to the option specified /dev/hvcs node? This option takes a device node and returns a status string which contains the vty-server adapter mapped to that node. .Pp Inclusion of a single .Sq Fl noisy flag does not change the default output of this option. .It Fl noisy This directive is optional. Without a .Sq Fl noisy directive the hvcsadmin utility is in \fBsilent\fR mode by default (except in the case of errors and output requests). The output verbosity of the utility is managed by stacking .Sq Fl noisy directives. A single instance of .Sq Fl noisy indicates that the utility should output in \fBstatus\fR mode. A second instance of .Sq Fl noisy indicates that the utility should output in \fBverbose\fR mode. Verbose mode is generally used for script tracing and won't be used by a casual user unless problems arise. .It Fl rescan Direct the hvcs driver to rescan partner information for all vty-server adapters it manages. This may expose additional adapters and partners. .It Fl status Outputs a table with each row containing a vty-server, adapter, its /dev/hvcs device node mapping, and the adapter connection status. "vterm_state:0" means it is free/disconnected and "vterm_state:0" means the vty-server is connected to its vty partner adapter. .Pp An example of \fBhvcsadmin -status\fR output follows: .Pp .Bd -literal \fBvty-server@30000003 partition:1 slot:2 /dev/hvcs0 vterm-state:0 vty-server@30000004 partition:15 slot:0 /dev/hvcs1 vterm-state:0\fR .Ed .Pp When this option is accompanied by a .Sq Fl noisy flag it will output a line for each hvcs device node which doesn't have a current vty-server adapter mapping as well as the status demonstrated above. .It Fl version Out the hvcsadmin script's version number. .El .Sh AUTHOR(S) .An Ryan S. Arnold Aq rsa@us.ibm.com powerpc-utils-1.2.26/man/rtas_dump.80000664000175000017510000000243012527176005014211 00000000000000.\" Copyright (C) 2005 International Business Machines. .\" Common Public License Version 1.0 (see COPYRIGHT) .\" .\" Author(s) .\" Nathan Fontenot .\" .TH RTAS_DUMP 8 "May 2005" Linux "Linux on Power Service Tools" .SH NAME rtas_dump \- dump the contents of an RTAS event. .SH SYNOPSIS .B /usr/sbin/rtas_dump [ options ] .SH DESCRIPTION The \fIrtas_dump\fR icommand is used to dump the contents of an RTAS event into a human readable form. The tool is able to parse the contents of /var/log/messages, /var/log/platform and /var/log/boot.msg to extract dump the contents of RTAS events. RTAS events can also be read in from a specified file or stdin. The real work of de-coding RTAS events is handled by \fI/usr/sbin/rtas_event_decode\fR, the rtas_dump command simply parses the input and files and passes on the data to \fIrtas_event_decode\fR. .SH OPTIONS .TP \fB\-d\fR debug flag, passed through to rtas_event_decode .TP \fB\-f\fI file\fR dump the RTAS event(s) from \fIfile\fR .TP \fB\-h\fI print the usage message and exit .TP \fB\-n\fI num\fR Only dump RTAS event number \fInum\fR .TP \fB\-v\fR dump the entire contents of the RTAS event(s), not just the header .TP \fB\-w\fR set the output character width .SH AUTHOR Nathan Fontenot powerpc-utils-1.2.26/man/sys_ident.80000664000175000017510000000200412527176005014211 00000000000000.\" .\" Copyright (C) 2006 International Business Machines .\" Michael Strosaker .\" .TH SYS_IDENT 8 "Jan 2006" Linux "Linux on Power Service Tools" .SH NAME sys_ident \- generate unique identification numbers .SH SYNOPSIS .nf \fB/usr/sbin/sys_ident -s\fR \fB/usr/sbin/sys_ident -p\fR .fi .SH DESCRIPTION .P The \fIsys_ident\fR utility implements algorithms for generating identification numbers that are uniqe to each system. These numbers are generated with the same algorithm as the numbers generated by \fIuname -f\fR on AIX. .P When invoked with the \fB-s\fR option, a 64-bit identification number will be printed (as a 16-character hexadecimal number). The number will also be unique for each partition on a partitioned system. .P When invoked with the \fB-p\fR option, a 32-bit processor serial number will be printed (as an 8-character hexadecimal number). .SH OPTIONS .TP .B \-s Generate a unique system/partition identification 64-bit number .TP .B \-p Generate the processor serial number powerpc-utils-1.2.26/man/lparcfg.50000664000175000017510000005326612527176005013643 00000000000000.TH LPARCFG 5 "August 2010" .SH NAME /proc/ppc64/lparcfg - IBM Power LPAR Configuration Data .SH SYNOPSIS .BI "/proc/ppc64/lparcfg" .sp .BI "cat /proc/ppc64/lparcfg" .SH DESCRIPTION The .B lparcfg file is a virtual file which contains information related to an IBM Power Logical Partition. .SH OPTIONS The fields displayed in the .B lparcfg file are sorted below according to the version of the .B lparcfg file. Generally, fields are only added and not removed (unless otherwise noted), so the latest version of .B lparcfg contains all fields in all previous versions of the file as well. .PP .B lparcfg 1.6 based values .br (Values added in lparcfg 1.7, 1.8, 1.9 are listed below) .PP .B serial_number .br The serial number of the physical system in which the partition resides .PP .B system_type .br The machine,type-model of the physical system in which the partition resides .PP .B partition_id .br The numeric partition ID. .PP .B R4 .br The hexadecimal representation of partition_entitled_capacity. This field is deprecated and not displayed on more recent versions of the Linux kernel ( .B lparcfg 1.8 or greater). The definition is only provided for historical purposes. .PP .B R5 .br The hexadecimal representation of unallocated_capacity. Not displayed on more recent versions of the Linux kernel. This field is deprecated and not displayed on more recent versions of the Linux kernel ( .B lparcfg 1.8 or greater). The definition is only provided for historical purposes. .PP .B R6 .br This is a hexadecimal value representing both the group and pool. This field is deprecated and not displayed on more recent versions of the Linux kernel ( .B lparcfg 1.8 or greater). The definition is only provided for historical purposes. .PP .B R7 .br This is a hexadecimal value representing capped, capacity_weight, unallocated_capacity_weight, pool_capacity, and system_active_processors. This field is deprecated and not displayed on more recent versions of the Linux kernel ( .B lparcfg 1.8 or greater). The definition is only provided for historical purposes. .PP .B BoundThrds .br For virtual processor dispatches, if the hypervisor always dispatches a set of virtual threads together on a physical processor, the threads are said to be bound. This allows an operating system to make scheduling decisions based on cache affinity and work load. Set to 1 if threads are bound, 0 otherwise. This value is informational and is not a tunable value. .\" A change in this characteristic takes effect on the next reboot of the partition. .PP .B CapInc .br This defines the delta by which the entitled capacity of a partition can be incremented or decremented by DLPAR/WLM. The capacity increment is expressed as a percentage of a physical processor. This value is informational and is not a tunable value. .\" A change in the capacity increment takes effect on the next reboot of the partition. This does not affect the number of virtual processors defined for the partition. .PP .B DisWheRotPer .br The duration of the hypervisor's scheduling window. The time over which the entitled capacity of a virtual processor has to be utilized by the partition. At the start of a dispatch wheel rotation period, each virtual processor is eligible for CPU time corresponding to its entitled capacity. If the entire entitled capacity of a virtual processor is not utilized during a dispatch wheel rotation period, the unused entitled capacity is lost. The dispatch wheel rotation period is expressed as N number of time base ticks. The dispatch wheel duration of a partition with a capacity increment of 100 is 0. This value is informational and is not a tunable value. .PP .B MinEntCap .br The minimum entitled capacity that is needed to boot the partition. The capacity is expressed as a percentage of a physical processor. The minimum entitled capacity is set by the system administrator in the partition definition. DLPAR cannot take the entitled capacity below the minimum entitled capacity. A change in the minimum entitled capacity takes effect on the next reboot of the partition. Linux running in a partition can give up its entitled capacity to be below the minimum entitled capacity, but this is generally not recommended. .PP .B MinEntCapPerVP .br The minimum entitled capacity that the platform requires for a virtual processor of any partition on the platform. The minimum capacity per virtual processor is enforced by the HMC in the partition definition and by the hypervisor. A change in the minimum entitled capacity per virtual processor takes effect on the next reboot of the partition. This is a physical system setting and is not considered a Linux partition tunable. .PP .B MinMem .br The minimum amount of main store that is needed to boot the partition. Minimum memory is expressed in MB of storage. The minimum memory is set by the system administrator in the partition definition. DLPAR cannot take the partition memory below the minimum memory. A change in the minimum memory takes effect on the next reboot of the partition. Linux running in a partition can always give up its memory to go below the minimum memory. .PP .B MinProcs .br The minimum number of virtual processors that are needed to boot the partition. The minimum number of virtual processors is set by the system administrator in the partition definition. DLPAR cannot take the number of virtual processors below the minimum number of processors. A change in the minimum number of processors takes effect on the next reboot of the partition. A partition can always give up its virtual processors to go below the minimum number of processors. The number of virtual processors is a simulated physical core view. Additional logical CPUs are defined in the Linux partition to account for the possible hardware threads. .PP .B partition_max_entitled_capacity .br The maximum entitled capacity currently that can be assigned to the partition through DLPAR/WLM. The capacity is expressed as a percentage of a physical processor. The Maximum entitled capacity is set up by the system administrator in the partition definition. A change in the maximum entitled capacity maximum takes effect on the next reboot of the partition. .PP .B system_potential_processors .br The maximum number of physical processors that can be active on the platform. A change in the maximum platform processors takes effect on the next reboot of the partition. .PP .B DesEntCap .br The desired entitled capacity is the number of processing units, expressed as a percentage of a physical processor, which is desired for a logical partition. The desired entitled capacity is the same as the desired processing units on the HMC. If the system has at least the desired number of processing units available when you activate the partition, then the system commits the desired number of processing units to the logical partition. If the desired number of processing units is not available, but at least the minimum number of processing units is available, then the system activates the logical partition with the processing units it has. .PP .B DesMem .br The desired memory set by the system administrator in the partition definition. The desired memory is expressed in MB of storage. The desired memory can change without a reboot of the partition. The desired memory that the partition is currently using may differ from the desired memory because of WLM actions or because of failed system memory. .PP .B DesProcs .br The desired number of virtual processors set by the system administrator in the partition definition. The desired number of processors can change without a reboot of the partition. The number of processors that the partition is currently using may differ from the desired number of processors because of WLM actions or because of failed system processors. .PP .B DesVarCapWt .br The desired variable capacity weight set by the system administrator in the partition definition. The desired variable capacity weight is a number between 0 and 255. The desired variable capacity weight can change without a reboot of the partition. The variable capacity weight that the partition is currently using may differ from the desired variable capacity because of WLM actions. .PP .B DedDonMode .br For a partition with a capacity increment of 100, the platform uses a dedicated CPU to actualize a virtual processor of the partition. For such a partition, the platform can increase the capacity of the shared processor pool by utilizing the unused processor capacity of the partition. If the platform supports the dedicated donate function, it can be enabled by the system administrator in the partition definition. The value of this characteristic can change without a reboot of the partition. The values for this field are 0 and 1. .PP .B partition_entitled_capacity .br Entitled Processor Capacity Percentage. The percentage of a physical processor that the hypervisor guarantees to be available to the partition's virtual processors (distributed in a uniform manner among the partition's virtual processors -- thus the number of virtual processors affects the time slice size) each dispatch cycle. Capacity ceded or conferred from one partition virtual processor extends the time slices offered to other partition processors. Capacity ceded or conferred after all of the partition's virtual processors have been dispatched is added to the variable capacity kitty. The initial, minimum and maximum constraint values of this parameter are determined by the partition configuration definition. The OS can set this parameter within the constraints imposed by the partition configuration definition minimum and maximums plus constraints imposed by partition aggregation. To change this value, echo the new partition_entitled_capacity into .B /proc/ppc64/lparcfg like this: .br .IP "" 7 .B echo """partition_entitled_capacity=40"" > /proc/ppc64/lparcfg .PP .B group .br LPAR group number of the partition .PP .B system_active_processors .br The number of processors active on the underlying physical system. .PP .B pool .br The pool number of the shared processor pool for the partition. This field is not displayed in the case of a dedicated processor partition. .PP .B pool_capacity .br The number of physical processors active in the partition's processor pool. This field is not displayed in the case of a dedicated processor partition. This value is expressed as a percentage so is 100* the number of active physical processors. .PP .B pool_idle_time .br If no virtual processor is ready to run, the pool_idle_count is incremented the total number of idle processor cycles in the physical processor pool. This field contains the total number of idle processor cycles up to the current point in time. If unsupported or if performance information collection is not enabled for the partition on the HMC, this will report 0. This field is not displayed in the case of a dedicated processor partition. For more information, see the NOTES section below on PURR/PIC. .PP .B pool_num_procs .br The number of physical processors in the partition's processing pool. This field is not displayed in the case of a dedicated processor partition. .PP .B unallocated_capacity_weight .br Unallocated Variable Processor Capacity Weight. The amount of variable processor capacity weight that is currently available within the constraints of the partition's current environment for allocation to the partition's variable processor capacity weight. .PP .B capacity_weight .br Variable Processor Capacity Weight. The unitless factor that the hypervisor uses to assign processor capacity in addition to the Entitled Processor Capacity Percentage. This factor may take the values 0 to 255. In the case of a dedicated processor partition this value is 0. A virtual processor's time slice may be extended to allow it to use capacity unused by other partitions, or not needed to meet the Entitled Processor Capacity Percentage of the active partitions. A partition is offered a portion of this variable capacity kitty equal to: (Variable Processor Capacity Weight for the partition) / (summation of Variable Processor Capacity Weights for all competing partitions). The initial value of this parameter is determined by the partition configuration definition. The OS can set this parameter within the constraints imposed by the partition configuration definition maximum. Certain partition definitions may not allow any variable processor capacity allocation. To change this value, echo the new capacity_weight into .B /proc/ppc64/lparcfg like this: .br .IP "" 7 .B echo """capacity_weight=128"" > /proc/ppc64/lparcfg .PP .B capped .br The partition's virtual processor(s) are capped at their entitled processor capacity percentage if this is 1. If capped=0, the partition is uncapped, and can use processor capacity from the uncapped pool, if available and according to the weighted values. In the case of dedicated processors this bit is set. .PP .B unallocated_capacity .br Unallocated Processor Capacity Percentage. The amount of processor capacity that is currently available within the constraints of the partition's current environment for allocation to Entitled Processor Capacity Percentage. .PP .B purr .br The Processor Utilization of Resources Register. Summation of the PURR value for all of the partition's virtual processors. See the NOTES section below for more information on PURR and PIC. This value is typically not a metric used. .PP .B partition_active_processors .br The total number of virtual processors assigned to the partition. This does not include the potential SMT threads. For dedicated processor partitions, this is the number of physical processors assigned to the partition. Linux will define virtual CPUs for the possible SMT threads across all of the virtual processors defined here. .PP .B partition_potential_processors .br The maximum number of virtual processors that can be assigned to the partition. This does not include SMT threads. For dedicated processor partitions, this is the maximum number of physical processors that can be assigned to the partition. .PP .B shared_processor_mode .br This is set to 1 if the partition is running with shared processors. This is set to 0 for dedicated processor partitions. .PP .B lparcfg 1.7 additional fields .PP .B slb_size .br The total number of entries in the Segment Lookaside Buffer (SLB). This is an attribute of the underlying processor architecture and is provided for informational purposes. The Linux OS uses this when determining the ability to perform Live Partition Migration with differing processor families. .PP .B lparcfg 1.8 .PP .B entitled_memory .br The number of bytes of main storage that the partition is entitled to DMA map for virtual I/O devices. In the case of a dedicated memory partition this is the size of the partition's logical address space. To change this value, echo the new entitled_memory value into .B /proc/ppc64/lparcfg like this: .br .IP "" 7 .B echo """entitled_memory=80740352"" > /proc/ppc64/lparcfg .PP .B mapped_entitled_memory .br The number of bytes of main storage that the partition has DMA mapped. In the case of a dedicated memory partition this is not displayed. .PP .B entitled_memory_group_number .br Entitled Memory Group Number .PP .B entitled_memory_pool_number .br Entitled memory pool number. In the case of a dedicated memory partition, this is 65535. .PP .B entitled_memory_weight .br The partition's shared memory weight. In the case of a dedicated memory partition this is 0. To change this value, echo the new entitled_memory_weight value into .B /proc/ppc64/lparcfg like this: .br .IP "" 7 .B echo """entitled_memory_weight=128"" > /proc/ppc64/lparcfg .PP .B unallocated_entitled_memory_weight .br The unallocated shared memory weight for the calling partition's aggregation. In the case of a dedicated memory partition this is 0. .PP .B unallocated_io_mapping_entitlement .br The unallocated I/O mapping entitlement for the calling partition's aggregation divided by 4096. In the case of a dedicated memory partition this is 0. .PP .B entitled_memory_loan_request .br The signed difference between the number of bytes of logical storage that are currently on loan from the calling partition and the partition's overage allotment (a positive number indicates a request to the partition to loan the indicated number of bytes else they will be expropriated as needed). In the case of a dedicated memory partition this is 0. In the case of a shared memory partition, when running the Collaborative Memory Manager (cmm module), this will typically be 0, as the CMM will monitor and fulfill the hypervisor's loan requests. .PP .B backing_memory .br The number of bytes of main storage that is backing the partition logical address space. In the case of a dedicated memory partition this is the size of the partition's logical address space. .PP .B cmo_enabled .br If Active Memory Sharing is enabled for the partition, this is set to 1. For dedicated memory partitions, this is 0. .PP .B cmo_faults .br Displayed only for shared memory partitions. Indicates the total number of times the partition has accessed a page in memory which was paged out to disk by firmware, requiring it to be paged back in. If the Collaborative Memory Manager is disabled, this value may be large. If it is enabled (default setting for most Linux distributions), this number is typically small. If this value is large and is increasing, it may be an indication that the partition's shared memory pool has too high of an overcommit ratio, in which case you may need to assign additional physical memory to the shared memory pool. .PP .B cmo_fault_time_usec .br Displayed only for shared memory partitions. Indicates the total amount of time in microseconds the partition has had a virtual processor blocked in order for firmware to page in data. Directly related to cmo_faults. .PP .B cmo_primary_psp .br Displayed only for shared memory partitions. Partition ID of the primary paging VIOS. .PP .B cmo_secondary_psp .br Displayed only for shared memory partitions. Partition ID of the secondary paging VIOS. If there is no secondary paging VIOS, this will be set to 65535. .PP .B cmo_page_size .br Displayed only for shared memory partitions. Physical page size in bytes. .PP .B lparcfg 1.9 additional fields .PP .B physical_procs_allocated_to_virtualization .br The number of physical platform processors allocated to processor virtualization. This is a physical system attribute and has no bearing on the Linux partition. .PP .B max_proc_capacity_available .br The maximum processor capacity percentage that is available to the partition's shared processor pool. .PP .B entitled_proc_capacity_available .br The entitled processor capacity percentage available to the partition's pool. .PP .B dispatches .br Virtual Processor Dispatch Counter. Counter that is incremented each time a virtual processor is dispatched/preempted. .PP .B dispatch_dispersions .br Virtual Processor Dispatch Dispersion Accumulator. Incremented on each virtual processor dispatch if the physical processor differs from that of the last dispatch. .PP .B coalesced_bytes .br The number of bytes of memory assigned to the logical partition which have been coalesced with identical pages either within the logical partition, or with another logical partition. .PP .B pool_coalesced_bytes .br The number of bytes of memory in the shared memory pool which have been coalesced with identical pages. .PP .B coalesce_pool_purr .br The number of PURR cycles which have been consumed to coalesce pages of data. .PP .B coalesce_pool_spurr .br The number of SPURR cycles which have been consumed to coalesce pages of data. .SH NOTES .PP .B PURR/PIC .br These two statistics are counts in the same units as counted by the processor time base. Like the time base, the PUR and PIC are 64 bit values that are set to a numerically low value during system initialization. The difference between their values at the end and beginning of monitored operations provides data on virtual processor performance. The value of the PUR is a count of processor cycles used by the calling virtual processor. The PUR count is intended to provide an indication to the partition software of the computation load supported by the virtual processor. Shared processor virtual processors are created by dispatching the virtual processor's architectural state on one of the physical processors from a pool of physical processors. The value of the PIC is the summation of the physical processor pool idle cycles, that is the number of time base counts when the pool could not dispatch a virtual processor. The PIC count is intended to provide an indication to platform management software of the pool capacity to perform more work. .PP .B Processors vs. SMT threads .br The Power processors support Simultaneous Multi-Threading (SMT). SMT is generally enabled by default on most Linux distributions that support Power. When enabled, a single Power 5 or Power 6 CPU will be seen as up to two logical CPUs in the Linux operating system. A single Power 7 CPU will be seen as four logical CPUs. SMT can be disabled with the .B ppc64_cpu utility, which is packaged in powerpc-utils. When SMT is disabled, the logical CPUs seen by Linux will not be contiguous. For example, a four core Power 7 partition with SMT disabled will show CPUs 0, 4, 8, and 12 in /proc/cpuinfo. A Power7 CPU/processor/core can also be set to SMT=2 mode. .SH VERSIONS .PP .B Linux Distribution Version Mapping The following is a brief list of the mapping of some enterprise versions of Linux for Power to the version of the .B lparcfg file. .br SLES 9: lparcfg 1.6 .br SLES 10: lparcfg 1.7 .br SLES 11: lparcfg 1.8 .br SLES 11 SP1: lparcfg 1.9 .br RHEL 4: lparcfg 1.6 .br RHEL 5: lparcfg 1.7 .br RHEL 6: lparcfg 1.9 .SH FILES .TP .B /proc/ppc64/lparcfg .SH AUTHOR Written by Brian King . .br Comments and questions on this document should be posted on the .B Linux for Power Architecture forum: .br .B http://www.ibm.com/developerworks/forums/forum.jspa?forumID=375&start=0. powerpc-utils-1.2.26/man/lparstat.80000664000175000017510000002126612527176005014055 00000000000000.\" Copyright (C) 2011 International Business Machines. .\" .\" Author(s) .\" Santiago Leon .\" Text extracted from AIX 6.1 Information Document. .\" Copyright International Business Machines Corporation 1997, 2010. .\" .TH LPARSTAT 8 "May 2011" Linux "Linux on Power Service Tools" .SH NAME lparstat \- Reports logical partition ( LPAR ) related information and statistics. .SH SYNOPSIS .B /usr/sbin/lparstat [ -i ] [ interval [ count ] ] .SH DESCRIPTION The \fIlparstat\fR command provides a report of LPAR related information and utilization statistics. This command provides a display of current LPAR related parameters and Hypervisor information, as well as utilization statistics for the LPAR. The \fIlparstat\fR command with no options will generate a single report containing utilization statistics related to the LPAR since boot time. The following information is displayed in the system configuration row: .TP type Partition Type. Can be either dedicated or shared. .TP mode Indicates whether the partition processor capacity is capped or uncapped allowing it to consume idle cycles from the shared pool. Dedicated LPAR is capped or donating. .TP smt Indicates whether simultaneous multi-threading is enabled or disabled in the partition. If SMT is enabled, the number of SMT threads is displayed. .TP lcpu Number of online logical processors. .TP mem Online Memory Capacity. .TP cpus Number of online physical processors in the pool. .TP ent Entitled processing capacity in processor units. This information is displayed only if the partition type is shared. .P The following information is displayed in the utilization row: .TP %user Shows the percentage of the entitled processing capacity used while executing at the user level (application). For dedicated partitions, the entitled processing capacity is the number of physical processors. For uncapped partitions with a current physical processor consumption above their entitled capacity, the percentage becomes relative to the number of physical processor consumed (physc). .TP %sys Shows the percentage of the entitled processing capacity used while executing at the system level (kernel). For dedicated partitions, the entitled processing capacity is the number of physical processors. For uncapped partitions with a current physical processor consumption above their entitled capacity, the percentage becomes relative to the number of physical processor consumed (physc). .TP %wait Shows the percentage of the entitled processing capacity unused while the partition was idle and had outstanding disk I/O requests. For dedicated partitions, the entitled processing capacity is the number of physical processors. For uncapped partitions with a current physical processor consumption above their entitled capacity, the percentage becomes relative to the number of physical processor consumed (physc). .TP %idle Shows the percentage of the entitled processing capacity unused while the partition was idle and did not have any outstanding disk I/O request. For dedicated partitions, the entitled processing capacity is the number of physical processors. For uncapped partitions with a current physical processor consumption above their entitled capacity, the percentage becomes relative to the number of physical processor consumed (physc). .P The following statistics are displayed when the partition type is shared or dedicated-donating: .TP physc Shows the number of physical processors consumed. .TP vcsw Shows the number of virtual context switches that are virtual processor hardware preemptions. .P The following statistics are displayed only when the partition type is shared: .TP %entc Shows the percentage of the entitled capacity consumed. Because the time base over which this data is computed can vary, the entitled capacity percentage can sometimes exceed 100%. This excess is noticeable only with small sampling intervals. .TP lbusy Shows the percentage of logical processor(s) utilization that occurred while executing at the user and system level. .TP phint Shows the number of phantom (targeted to another shared partition in this pool) interruptions received. .SH OPTIONS .TP \fB\-i\fR Lists details on the LPAR configuration. The various details displayed by the -i option are listed below: .RS .TP Node Name Description .TP Partition Name Logical partition name as assigned at the HMC. .TP Partition Number Number of this Logical Partition. .TP Type Indicates whether the LPAR is using dedicated or shared CPU resource and if the SMT is turned ON. The Type is displayed in the format [Shared | Dedicated] [ -SMT ] [ -# ] The following list explains the different Type formats: .RS .TP Shared - Indicates that the LPAR is running in the Shared processor mode. .TP Dedicated - Indicates that the LPAR is running in the dedicated processor mode. .TP SMT[-#] - Indicates that the LPAR has SMT mode turned ON and the number of SMT threads is 2. If the number of threads is greater than 2, then the number of threads is also displayed. .RE .TP Mode Indicates whether the LPAR processor capacity is capped, or if it is uncapped and allowed to consume idle cycles from the shared pool. Dedicated LPAR is capped or donating. .TP Entitled Capacity The number of processing units this LPAR is entitled to receive. .TP Partition Group-ID LPAR group that this LPAR is a member of. .TP Shared Pool ID Identifier of Shared Pool of Physical processors that this LPAR is a member. .TP Online Virtual CPUs Number of CPUs (virtual engines) currently online. .TP Maximum Virtual CPUs Maximum possible number of CPUs (virtual engines). .TP Minimum Virtual CPUs Minimum number of virtual CPUs this LPAR was defined to ever have. .TP Online Memory Amount of memory currently online. .TP Minimum Memory Minimum memory this LPAR was defined to ever have. .TP Variable Capacity Weight The priority weight assigned to this LPAR which controls how extra (idle) capacity is allocated to it. A weight of -1 indicates a soft cap is in place. .TP Minimum Capacity The minimum number of processing units this LPAR was defined to ever have. Entitled capacity can be reduced down to this value. .TP Maximum Capacity The maximum number of processing units this LPAR was defined to ever have. Entitled capacity can be increased up to this value. .TP Capacity Increment The granule at which changes to Entitled Capacity can be made. A value in whole multiples indicates a Dedicated LPAR. .TP Active Physical CPUs in System The current number of active physical CPUs in the system containing this LPAR. .TP Active CPUs in Pool The maximum number of CPUs available to this LPAR's shared processor pool. .TP Maximum Capacity of Pool The maximum number of processing units available to this LPAR's shared processor pool. .TP Entitled Capacity of Pool The number of processing units that this LPAR's shared processor pool is entitled to receive. .TP Unallocated Capacity The sum of the number of processor units unallocated from shared LPARs in an LPAR group. This sum does not include the processor units unallocated from a dedicated LPAR, which can also belong to the group. The unallocated processor units can be allocated to any dedicated LPAR (if it is greater than or equal to 1.0 ) or shared LPAR of the group. .TP Physical CPU Percentage Fractional representation relative to whole physical CPUs that these LPARs virtual CPUs equate to. This is a function of Entitled Capacity / Online CPUs. Dedicated LPARs would have 100% Physical CPU Percentage. A 4-way virtual with Entitled Capacity of 2 processor units would have a 50% physical CPU Percentage. .TP Unallocated Weight Number of variable processor capacity weight units currently unallocated within the LPAR group. .TP Memory Mode Indicates whether the memory mode is shared or dedicated. If Active Memory Expansion is enabled, the memory mode also includes a new mode called Expanded. .TP Total I/O Memory Entitlement The I/O memory entitlement of the LPAR. .TP Variable Memory Capacity Weight .TP Memory Pool ID The memory pool ID of the pool that the LPAR belongs to. .TP Physical Memory in the Pool The physical memory present in the pool that the LPAR belongs to. .TP Unallocated Variable Memory Capacity Weight he unallocated variable memory-capacity weight of the LPAR. .TP Unallocated I/O Memory Entitlement The unallocated I/O memory entitlement of the LPAR. .TP Memory Group ID of LPAR The memory group ID of the Workload Manager group that the LPAR belongs to. .TP Desired Variable Capacity Weight The variable memory capacity weight of the LPAR. .TP .SH interval The .B interval parameter specifies the amount of time between each report. .TP .SH count The .B count parameter specifies how many reports will be displayed. .TP powerpc-utils-1.2.26/man/lsslot.80000664000175000017510000000330012542271360013525 00000000000000.\" .\" Copyright (C) 2011 International Business Machines .\" Brian King .\" .TH LSSLOT 8 "December 2011" Linux "Linux on Power Service Tools" .SH NAME lsslot \- display hot plug capable slots and resources .SH SYNOPSIS .BI "lsslot [-c | -a | -b | -p | -o | -s | -F | -d | -w]" .SH DESCRIPTION The .B lsslot command can be used to display hot plug capable I/O slots, CPUs and caches. Please note that this command does not display all I/O slots, only slots which are physically capable of hot plug. Slots which are capable of DLPAR but not hot plug capable will not be listed. .SH OPTIONS .TP .B \-c Display the slots of the specified connector type. The valid connector types are "pci" for hotplug PCI slots, "slot" for logical slots, "phb" for PHB's, "port" for LHEA ports, "mem" for memory, and "cpu" for cpu's. The default is "slot" if no -c option is specified. .TP .B \-a Display available slots, valid for "pci" slots only. .TP .B \-b Display cpu's and caches, valid for "cpu" only. .TP .B \-o Display occupied slots, valid for "pci" slots only. .TP .B \-p Display caches, valid for "cpu" slots only. .TP .B \-s [ | ] Display characteristics of the specified slot or the LMB with the specified drc index. .TP .B \-F Specified a single character to delimit the output. The heading is not displayed and the columns are delimited by the specified character. .TP .B \-d Enable debugging output. When displaying memory information this flag will also enable printing information about LMBs not currently owned by the system. .TP .B \-w Specify a timeout when attempting to acquire locks. .SH AUTHOR Brian King powerpc-utils-1.2.26/man/ppc64_cpu.80000664000175000017510000000544212527176005014024 00000000000000.\" .\" Copyright (C) 2015 International Business Machines .\" .TH PPC64_CPU 8 "January 2015" Linux "Linux on Power Service Tools" .SH NAME ppc64_cpu \- Display cpu characteristics of PowerPC systems .SH SYNOPSIS .B /usr/sbin/ppc64_cpu [ command ] [ options ] .SH DESCRIPTION The .I ppc64_cpu command is used to display and set cpu characteristics on PowerPC platforms. .SH OPTIONS .TP \fB\-\-smt\fR Display the current smt setting for the system. The output will state whether smt is off indicating there is only one thread per core online, smt is on indicating that all threads of every core is online, the smt is in a mixed state indicating that the number of threads online varies per core, or 'SMT=X' indicating a specific smt state. .TP \fB\-\-smt\fR={\fIon\fR|\fIoff\fR} Set the current smt state for the system to either \fIon\fR, which will online every thread in every core on the system, or \fIoff\fR which will leave each core on the system with only one thread online. .TP \fB\-\-smt\fR=\fIvalue\fR Set the smt state for each core to the specified \fIvalue\fR. .TP \fB\-\-cores\-present\fR Display the number of cores present. .TP \fB\-\-cores\-on\fR Display the number of cores online. .TP \fB\-\-cores\-on\fR=\fIvalue\fR Put exactly \fIvalue\fR number of cores online. Note that this will either online or offline cores to achieve the desired result. .TP \fB\-\-dscr\fR Display the current Data Stream Control Register (DSCR) setting for the system. .TP \fB\-\-dscr\fR=\fIvalue\fR Set the DSCR setting for the system to \fIvalue\fr. .TP \fB\-\-dscr\fR [\fIpid\fR] Display the DSCR setting for process \fIpid\fR. .TP \fB\-\-dscr\fR=\fIvalue\fR [\fIpid\fR] Set the DSCR to the specified \fIvalue\fR for process \fIpid\fR. .TP \fB\-\-smt\-snooze\-delay\fR Display the current smt\-snooze\-delay setting. .TP \fB\-\-smt\-snooze\-delay\fR=\fIvalue\fR Set the smt\-snooze\-delay to the specified \fIvalue\fR. .TP \fB\-\-run-mode\fR Display the current diagnostics run mode. .TP \fB\-\-run\-mode\fR=\fIvalue\fR Set the current diagnostics run mode to \fIvalue\fR. .TP \fB\-\-frequency\fR [\-t \fItime\fR] Determine the cpu frequency. The default sampling period is one second unless a time is specified with the \fB\-t \fItime\fR option. .TP \fB\-\-subcores\-per\-core\fR Display the number of subcores per core. .TP \fB\-\-subcores\-per\-core\fR=\fIvalue\fR Set the number of subcores per core to \fIvalue\fR. .TP \fB\-\-threads\-per\-core\fR Display the number of threads per core. .TP \fB\-\-info\fR Display system state information. The output will print a line for each core and possible sub\-core along with the thread numbers for each thread in the core with an asterick next to it if the thread is online. .TP \fB\-\-version\fR Print the version number. .SH AUTHOR Written by Anton Blanchard and Nathan Fontenot powerpc-utils-1.2.26/scripts/0000775000175000017510000000000012542271540013114 500000000000000powerpc-utils-1.2.26/scripts/amsstat0000775000175000017510000001341312527176005014443 00000000000000#!/bin/bash # IBM "amsstat": Active Memory Sharing statistics gathering tool # # Copyright (c) 2009 International Business Machines. # Common Public License Version 1.0 (see COPYRIGHT) # # Authors: # Andrew Theurer # Robert Jennings # # This script will gather AMS related information on supported Linux systems # usage: # amstat # # If you do not provide an interval, amsstat will display stats only once # # For further details on this tool and the fields it displays please # reference man page amsstat.1 sleep_interval=$1 indent=-4 devstat_data_spacing=-30 lparcfg_data_spacing=-30 lparcfg_file=/proc/ppc64/lparcfg # Hardcoding pseries_platform path as amstat will be placed in bin PSERIES_PLATFORM=/usr/sbin/pseries_platform function print_meminfo_stats { echo "System Memory Statistics:" OLD_IFS=${IFS} IFS=" " for stat in `cat /proc/meminfo`; do IFS=${OLD_IFS} if echo $stat | grep "^MemTotal\|^MemFree\|^Buffers\|^Cached\|^Inactive\|SwapTotal\|SwapFree" >/dev/null; then this_stat=`echo $stat | awk -F: '{print $1}'` this_value=`echo $stat | awk -F: '{print $2}'` printf "%${indent}s %${lparcfg_data_spacing}s %${lparcfg_data_spacing}s\n" " " "$this_stat:" "${this_value##\ }" fi done # Include Desired Memory value from /proc/ppc64/lparcfg stat=`grep "^DesMem" $lparcfg_file` if [ ! -z "${stat}" ]; then this_stat=`echo $stat | awk -F= '{print $1}'` this_value=`echo $stat | awk -F= '{print $2}'` printf "%${indent}s %${lparcfg_data_spacing}s %${lparcfg_data_spacing}s\n" " " "$this_stat:" "$this_value MB" fi } function print_entitlement_data { echo "Entitlement Information:" for stat in `cat $lparcfg_file`; do if echo $stat | grep "^entitled_memory\|^mapped_entitled_memory\|^entitled_memory_weight\|entitled_memory_pool_size\|^backing_memory\|^cmo_enabled\|^cmo_faults\|^cmo_fault_time_usec\|cmo_primary_psp\|^cmo_secondary_psp\|^coalesced_bytes\|^pool_coalesced_bytes" >/dev/null; then this_stat=`echo $stat | awk -F= '{print $1}'` this_value=`echo $stat | awk -F= '{print $2}'` printf "%${indent}s %${lparcfg_data_spacing}s %${lparcfg_data_spacing}s\n" " " "$this_stat:" "$this_value" fi done } function print_cmm_stats { # CMM kernel parameters echo "CMM Statistics:" local path=/sys/module/cmm/parameters pushd $path >/dev/null 2>&1 if [ $? -ne 0 ] ; then printf "%${indent}s Could not get CMM Statistics.\n" " " return fi for stat in `find . -mindepth 1 -maxdepth 1 -print`; do printf "%${indent}s %${devstat_data_spacing}s %${devstat_data_spacing}s\n" " " "${stat#\.\/}:" "`cat $stat`" done popd >/dev/null # CMM statistics local path=/sys/devices/system/cmm/cmm0 pushd $path >/dev/null 2>&1 if [ $? -ne 0 ] ; then return fi for stat in `find . -mindepth 1 -maxdepth 1 -print`; do printf "%${indent}s %${devstat_data_spacing}s %${devstat_data_spacing}s\n" " " "${stat#\.\/}:" "`cat $stat`" done popd >/dev/null } function print_vio_bus_stats { echo "VIO Bus Statistics:" local found=0 local path=/sys/bus/vio pushd $path >/dev/null 2>&1 if [ $? -ne 0 ] ; then printf "%${indent}s Could not get VIO Bus Statistics.\n" " " return fi for stat in `find . -mindepth 1 -maxdepth 1 -name "cmo*" -print`; do found=1 printf "%${indent}s %${devstat_data_spacing}s %${devstat_data_spacing}s\n" " " "${stat#\.\/}:" "`cat $stat`" done popd >/dev/null if [ "$found" -eq "0" ]; then printf "%${indent}s No AMS Busses found.\n" " " fi } function print_vio_dev_stats { echo "VIO Device Statistics:" local found=0 local path=/sys/bus/vio/devices pushd $path >/dev/null 2>&1 if [ $? -ne 0 ] ; then printf "%${indent}s Could not get VIO Device Statistics.\n" " " return fi for dir in `find . -mindepth 1 -print`; do pushd $dir >/dev/null 2>&1 if [ $? -ne 0 ] ; then break fi # Skip printing devices that are not using entitlement if [ ! -e "cmo_entitled" ]; then popd >/dev/null continue fi value=`cat cmo_entitled` if [ ${value} -eq "0" ]; then popd >/dev/null continue fi NAME=$(cat devspec) echo " ${NAME##/*/}:" for stat in `find . -mindepth 1 -maxdepth 1 -name "cmo*" -print`; do found=1 printf "%${indent}s %${devstat_data_spacing}s %${devstat_data_spacing}s\n" " " "${stat#\.\/}:" "`cat $stat`" done popd >/dev/null done popd >/dev/null if [ "$found" -eq "0" ]; then printf "%${indent}s No AMS devices found.\n" " " fi } if [ ! -f $PSERIES_PLATFORM ]; then echo "$PSERIES_PLATFORM does not exist" echo "amstat: is not supported on the Unknown platform" exit 1; fi . $PSERIES_PLATFORM if [[ $platform != $PLATFORM_PSERIES_LPAR ]]; then echo "amstat: is not supported on the $platform_name platform" exit 1 fi # Verify CMO is present and enabled enabled=`cat $lparcfg_file | grep "^cmo_enabled" | awk -F= '{print $2}'` if [ -z $enabled ]; then echo "This system is not capable of Active Memory Sharing." exit -1 elif [ "$enabled" -eq "0" ]; then echo "Active Memory Sharing is not enabled on this system." exit -1 fi if [ -z $sleep_interval ]; then date print_meminfo_stats print_entitlement_data print_cmm_stats print_vio_bus_stats print_vio_dev_stats else while [ 1 ]; do date print_meminfo_stats print_entitlement_data print_cmm_stats print_vio_bus_stats print_vio_dev_stats sleep $sleep_interval echo done fi powerpc-utils-1.2.26/scripts/update_flash0000775000175000017510000003250512542271360015426 00000000000000#!/bin/sh # Copyright (c) 2003, 2004, 2008 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Authors: John Rose # Mike Strosaker # Simple script to update flash. The kernel module rtas_flash does # the real work at reboot time. # This script has minimal dependencies so it can operate in a rescue # environment. This is probably overkill since it is easy enough to # flash without this script. #set -x # For now firmware can only handle 4k pages. At some point in the # future they will be able to handle large pages. When that (hopefully) # happens we will need to use getconf to retrieve the systems page size. PAGE_SIZE=4096 # Error Codes E_SUCCESS=0 # Success E_UNSUPPORTED=1 # Flash update is not supported on this system E_USAGE=3 # Usage error E_PERM=4 # Permission error E_IMAGE=5 # Image file error E_PROC_FS=6 # Proc file either doesn't exist, or behaves unexpectedly E_MODULE=7 # Error loading module E_RTAS=8 # RTAS call failed E_USER=9 # User aborted operation E_OVERWRITE=10 # Auto overwrite permanent side image E_WRNTY=15 # Update Access Key Expired # Script Constants PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH PROCFLASH=/proc/ppc64/rtas/firmware_update PROCMANAGE=/proc/ppc64/rtas/manage_flash PROCVALIDATE=/proc/ppc64/rtas/validate_flash OLDPROCFLASH=/proc/ppc64/rtas/firmware_flash PSERIES_PLATFORM=$(dirname $0)/pseries_platform # firmware_update Status Values FLASH_AUTH=-9002 # RTAS Not Service Authority Partition FLASH_NO_OP=-1099 # No operation initiated by user FLASH_IMG_SHORT=-1005 # Flash image shorter than expected FLASH_IMG_BAD_LEN=-1004 # Bad length value in flash list block FLASH_IMG_NULL_DATA=-1003 # Bad data value in flash list block FLASH_IMG_READY=0 # Firmware img ready for flash on reboot # manage_flash Status Values MANAGE_AUTH=-9002 # RTAS Not Service Authority Partition MANAGE_ACTIVE_ERR=-9001 # RTAS Cannot Overwrite Active Img MANAGE_NO_OP=-1099 # No operation initiated by user MANAGE_PARAM_ERR=-3 # RTAS Parameter Error MANAGE_HW_ERR=-1 # RTAS Hardware Error MANAGE_SUCCESS=0 # Operation Successful # validate_flash Status Values VALIDATE_AUTH=-9002 # RTAS Not Service Authority Partition VALIDATE_INCOMPLETE=-1002 # User copied < VALIDATE_BUF_SIZE VALIDATE_READY=-1001 # Firmware image ready for validation VALIDATE_PARAM_ERR=-3 # RTAS Parameter Error VALIDATE_HW_ERR=-1 # RTAS Hardware Error VALIDATE_TMP_UPDATE=0 # RPA Section 7.3, Table 63 VALIDATE_FLASH_AUTH=1 # RPA Section 7.3, Table 63 VALIDATE_INVALID_IMG=2 # RPA Section 7.3, Table 63 VALIDATE_CUR_UNKNOWN=3 # RPA Section 7.3, Table 63 VALIDATE_TMP_COMMIT_DL=4 # RPA Section 7.3, Table 63 VALIDATE_TMP_COMMIT=5 # RPA Section 7.3, Table 63 VALIDATE_TMP_UPDATE_DL=6 # RPA Section 7.3, Table 63 VALIDATE_OUT_OF_WRNTY=7 # RPA Section 7.3, Table 63 error() { local exit_code=$1 if [ $# -lt 1 ]; then echo "error(): usage" >&2 return $E_USAGE fi shift; echo update_flash: $* >&2 exit $exit_code } usage() { local exit_code; if [ "$1" = $E_SUCCESS ]; then exit_code=$E_SUCCESS else exit_code=$E_USAGE fi echo "USAGE: update_flash {-h | -s | -r | -c | [-v|-n] -f }" >&2 echo " -h Print this message." >&2 echo " -s Determine if partition has access to" >&2 echo " perform flash image management." >&2 echo " -r Reject temporary image." >&2 echo " -c Commit temporary image." >&2 echo " -v Validate ONLY with given image file." >&2 echo " -n Do not overwrite Permanent side" >&2 echo " image automatically." >&2 echo " -f Update with given image file. If possible," >&2 echo " the image is automatically validated prior" >&2 echo " to update." >&2 echo "" >&2 exit $exit_code } query_support() { local exit_status=$E_UNSUPPORTED if [ ! -r "$PROCVALIDATE" ]; then modprobe rtas_flash || error $E_MODULE "could not load rtas_flash kernel module" fi if [ -e "/proc/device-tree/rtas/ibm,manage-flash-image" ]; then grep \\"$VALIDATE_AUTH" "$PROCVALIDATE" > /dev/null if [ $? -ne 0 ]; then # validate-flash did not return "not authorized" head --bytes=4k /dev/zero > $PROCVALIDATE 2>/dev/null grep 1 "$PROCVALIDATE" > /dev/null if [ $? -ne 0 ]; then # validate-flash did not return "not authorized" exit_status=0 fi fi else if [ -e "/proc/device-tree/rtas/ibm,update-flash-64-and-reboot" ] || [ -e "/proc/device-tree/rtas/udpate-flash-and-reboot" ]; then exit_status=0 fi fi if [ $exit_status -ne 0 ]; then echo update_flash: flash image cannot be managed from this partition else echo update_flash: flash image management is supported fi exit $exit_status; } echo_validate_rtas_buf() { local output="$1" local cur_t_name=$(echo "$output" | grep "^MI" | head -n 1 | awk ' { print $2 } ') local cur_p_name=$(echo "$output" | grep "^MI" | head -n 1 | awk ' { print $3 } ') local new_t_name=$(echo "$output" | grep "^MI" | tail -n 1 | awk ' { print $2 } ') local new_p_name=$(echo "$output" | grep "^MI" | tail -n 1 | awk ' { print $3 } ') echo "Projected Flash Update Results:" echo "Current T Image: $cur_t_name" echo "Current P Image: $cur_p_name" echo "New T Image: $new_t_name" echo "New P Image: $new_p_name" } echo_entitlement_expiry_date() { local build_date=`cat $PROCVALIDATE | grep "^MG" | tail -n 1 | cut -d " " -f2` local entl_date=`cat $PROCVALIDATE | grep "^ME" | cut -d " " -f2` echo "The selected firmware image cannot be applied." echo "" echo -n "The Build Date of the firmware image selected is " if [ "$build_date" != "" ]; then echo "$(date --date=$build_date +"%B %d, %Y")." else echo "UNKNOWN." fi echo -n "The System's Update Access Key Expiration Date is " if [ "$entl_date" != "" ]; then echo "$(date --date=$entl_date +"%B %d, %Y")." else echo "UNKNOWN." fi echo "" echo "Please go to http://www.ibm.com/servers/eserver/ess to obtain " echo "a replacement update access key." } echo_validate_return_status() { local output="$1" local rc=$(echo "$output" | head -n 1) local rtas_buf=$(echo "$output" | tail -n +2) [ $# -eq 1 ] || error $E_USAGE "echo_validate_return_status(): usage" case "$rc" in $VALIDATE_PARAM_ERR) error $E_RTAS "RTAS: validate() Parameter Error";; $VALIDATE_HW_ERR) error $E_RTAS "RTAS: validate() Hardware Error";; $VALIDATE_FLASH_AUTH) error $E_RTAS "RTAS: validate() Partition does not have authority";; $VALIDATE_AUTH) error $E_RTAS "RTAS: validate() Partition does not have authority";; $VALIDATE_INVALID_IMG) error $E_RTAS "RTAS: validate() Invalid candidate image for this platform";; $VALIDATE_TMP_UPDATE) echo "info: Temporary side will be updated with a newer or" echo "identical image";; $VALIDATE_CUR_UNKNOWN) echo "info: Current fixpack level is unknown";; $VALIDATE_TMP_COMMIT_DL) echo "info: Current Temporary image will be committed to" echo "Permanent side before being replaced with new image, and" echo "the new image is downlevel from current image";; $VALIDATE_TMP_COMMIT) echo "info: Current Temporary side will be committed to" echo "Permanent side before being replaced with the new image";; $VALIDATE_TMP_UPDATE_DL) echo "info: Temporary side will be updated with a downlevel" echo "image";; $VALIDATE_OUT_OF_WRNTY) echo_entitlement_expiry_date error $E_WRNTY "Please contact your service support structure.";; *) error $E_RTAS "RTAS: Unknown validate-flash-image Return Status" esac echo echo_validate_rtas_buf "$rtas_buf" # Do not commit T side image to P side if [ $no_overwrite_opt -eq 1 ]; then if [ $rc -eq $VALIDATE_TMP_COMMIT_DL ] || [ $rc -eq $VALIDATE_TMP_COMMIT ]; then echo "" echo "update_flash: Run without -n option to flash new image" exit $E_OVERWRITE fi fi } validate_flash() { local img_file=$1 local output="" [ $# -eq 1 ] || error $E_USAGE "validate_flash(): usage" [ -r $PROCVALIDATE ] || return $E_PROC_FS grep \\"$VALIDATE_AUTH" "$PROCVALIDATE" > /dev/null if [ $? -eq 0 ]; then # validate-flash returned "not authorized" return $E_RTAS fi # Copy image file to proc file cp "$img_file" "$PROCVALIDATE" || error $E_PROC_FS "error copying flash image to rtas_flash validate module" # Display appropriate message, exiting if necessary output="$(cat $PROCVALIDATE)" echo_validate_return_status "$output" return 0 } validate_flash_from_file() { local img_file=$1 [ $# -eq 1 ] || error $E_USAGE "validate_flash_from_file(): usage" if [ ! -r "$PROCVALIDATE" ]; then modprobe rtas_flash || error $E_MODULE "could not load rtas_flash kernel module" [ -r "$PROCVALIDATE" ] || error $E_PROC_FS "rtas_flash kernel module did not create $PROCVALIDATE" fi if validate_flash $img_file; then return 0; else case "$?" in $E_PROC_FS) error $E_PROC_FS "validate: $PROCVALIDATE does not exist";; $E_RTAS) error $E_RTAS "validate: firmware validation not supported on this system";; esac fi } echo_update_status() { local rc="$1" [ $# -eq 1 ] || error $E_USAGE "echo_update_status(): usage" case "$rc" in $FLASH_AUTH) error $E_RTAS "RTAS: Partition does not have authority";; $FLASH_IMG_SHORT) error $E_IMAGE "Flash image shorter than expected";; $FLASH_IMG_BAD_LEN) error $E_PROC_FS "Bad length value in flash list block";; $FLASH_IMG_NULL_DATA) error $E_PROC_FS "Bad data value in flash list block";; $FLASH_IMG_READY) echo "Flash image ready...rebooting the system...";; *) error $E_PROC_FS "RTAS: Unknown update flash status" esac } update_flash_from_file() { local img_file=$1 local output="" local oldkernel=0 [ $# -eq 1 ] || error $E_USAGE "update_flash_from_file(): usage" [ -r "$img_file" ] || error $E_IMAGE "cannot read $img_file" flashfile=$PROCFLASH if [ ! -r "$PROCFLASH" ]; then modprobe rtas_flash if [ ! -r "$PROCFLASH" ]; then if [ -r "$OLDPROCFLASH" ]; then oldkernel=1 else error $E_PROC_FS "rtas_flash kernel module did not create $PROCFLASH" fi fi fi if [ -r "$PROCVALIDATE" ]; then validate_flash "$img_file" fi if [ $oldkernel -eq 0 ]; then dd if="$img_file" of="$PROCFLASH" bs=$PAGE_SIZE 2>/dev/null || error $E_PROC_FS "error copying flash image to rtas_flash kernel module" output="$(cat $PROCFLASH)" echo_update_status "$output" else dd if="$img_file" of="$OLDPROCFLASH" bs=PAGE_SIZE 2>/dev/null || error $E_PROC_FS "error copying flash image to rtas_flash kernel module" cat "$OLDPROCFLASH" fi #XXX reboot return 0; } echo_manage_return_status() { local is_commit=$1 local output=$2 local rc=$(echo $output) [ $# -eq 2 ] || error $E_USAGE "echo_manage_return_status(): usage" case "$rc" in $MANAGE_AUTH) error $E_RTAS "RTAS: manage() Partition does not have authority";; $MANAGE_ACTIVE_ERR) error $E_RTAS "RTAS: manage() Cannot Overwrite the Active Firmware Image";; $MANAGE_PARAM_ERR) error $E_RTAS "RTAS: manage() Parameter Error";; $MANAGE_HW_ERR) error $E_RTAS "RTAS: manage() Hardware Error";; $MANAGE_SUCCESS) if [ $is_commit -eq 0 ]; then echo "success: Rejected temporary firmware image" else echo "success: Committed temporary firmware image" fi ;; *) error $E_RTAS "Unknown manage-flash-image Return Status" esac } manage_flash() { local is_commit=$1 local commit_str="1" local reject_str="0" local output="" [ $# -eq 1 ] || error $E_USAGE "manage_flash(): usage" if [ ! -r "$PROCMANAGE" ]; then modprobe rtas_flash || error $E_MODULE "could not load rtas_flash kernel module" [ -r "$PROCMANAGE" ] || error $E_PROC_FS "rtas_flash kernel module did not create $PROCMANAGE" fi if [ $is_commit -eq 1 ]; then echo $commit_str > $PROCMANAGE else echo $reject_str > $PROCMANAGE fi output=$(cat $PROCMANAGE) echo_manage_return_status $is_commit "$output" if echo $output | grep "^success" > /dev/null; then return 0 else return $E_RTAS fi } file="" check_opt=0 commit_opt=0 reject_opt=0 validate_opt=0 no_overwrite_opt=0 file_opt=0 [ -d /proc/device-tree ] || error $E_PROC_FS "iSeries or /proc not mounted" #XXX #[ "`whoami`" = "root" ] || error $E_PERM "must be root to execute this command" # Check for platform and if PowerNV call update_flash_nv # PowerNV update_flash tool UPDATE_FLASH_NV=$(dirname $0)/update_flash_nv . $PSERIES_PLATFORM case "$platform" in $PLATFORM_UNKNOWN | $PLATFORM_POWERKVM_GUEST) echo "update_flash: is not supported on the $platform_name platform" exit 1;; $PLATFORM_POWERNV) if [ ! -r "$UPDATE_FLASH_NV" ]; then error $E_PERM "Couldn't find $UPDATE_FLASH_NV file." fi /bin/sh $UPDATE_FLASH_NV $@ exit $? esac while [ -n "$1" ]; do arg="$1" shift case "$arg" in -q|-l|-D|-S) error $E_USAGE "the $arg option is not implemented";; -h) usage $E_SUCCESS;; -s) check_opt=1;; -c) commit_opt=1;; -r) reject_opt=1;; -v) validate_opt=1;; -n) no_overwrite_opt=1;; -f) file_opt=1; file="$1"; shift;; *) error $E_USAGE "unknown option $arg" esac done if [ -n "$file" ]; then if [ $commit_opt -eq 1 ] || [ $reject_opt -eq 1 ] || [ $check_opt -eq 1 ]; then usage elif [ $validate_opt -eq 1 ] && [ $no_overwrite_opt -eq 1 ]; then usage elif [ $validate_opt -eq 1 ]; then validate_flash_from_file $file else update_flash_from_file $file fi else [ $check_opt -eq 1 ] && query_support [ $commit_opt -eq 0 ] && [ $reject_opt -eq 0 ] && usage [ $commit_opt -eq 1 ] && [ $reject_opt -eq 1 ] && usage manage_flash $commit_opt fi powerpc-utils-1.2.26/scripts/update_flash_nv0000775000175000017510000002762112527176005016137 00000000000000#!/bin/sh # Copyright (c) 2013 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Authors: Vasant Hegde # # Simple script for code update on "KVM on Power" machines. This # is a simple wrapper script to pass the image. The Linux kernel # and FW does the real work during system reboot. # # This script has minimal dependencies so it can operate in a # rescue environment. #set -x # Error codes E_SUCCESS=0 # Success E_UNSUPPORTED=1 # Firmware update is not supported E_USAGE=3 # Usage error E_PERM=4 # Permission error E_IMAGE=5 # Image file error E_SYS_FS=6 # Firmware update related sysfs file doesn't exist E_MODULE=7 # Error loading module E_OPAL=8 # OPAL call failed E_USER=9 # User aborted operation E_OVERWRITE=10 # Auto overwrite permanent side image E_WRNTY=15 # Update Access Key Expired # Firmware update related files SYS_IMAGE_FILE=/sys/firmware/opal/image SYS_VALIDATE_FLASH=/sys/firmware/opal/validate_flash SYS_MANAGE_FLASH=/sys/firmware/opal/manage_flash SYS_UPDATE_FLASH=/sys/firmware/opal/update_flash # Current firmware version files DT_FW_MI_FILE=/proc/device-tree/ibm,opal/firmware/mi-version DT_FW_ML_FILE=/proc/device-tree/ibm,opal/firmware/ml-version # Code update status values FLASH_SUCCESS=0 # Success FLASH_PARAM_ERR=-1 # Parameter error FLASH_BUSY=-2 # OPAL busy FLASH_HW_ERR=-6 # Hardware error FLASH_INTERNAL_ERR=-11 # Internal error FLASH_NO_OP=-1099 # No operation initiated by user FLASH_NO_AUTH=-9002 # Inband firmware update is not allowed # Validate image status values FLASH_IMG_READY=-1001 # Image ready for validation FLASH_IMG_INCOMPLETE=-1002 # User copied < VALIDATE_BUF_SIZE # Manage image status values FLASH_ACTIVE_ERR=-9001 # Cannot overwrite active img # Flash image status values FLASH_IMG_READY=0 # Image ready for flash on reboot FLASH_INVALID_IMG=-1003 # Flash image shorter than expected FLASH_IMG_NULL_DATA=-1004 # Bad data FLASH_IMG_BAD_LEN=-1005 # Bad length # Validate image update result tokens # # T side will be updated VALIDATE_TMP_UPDATE=0 # # Partition does not have authority VALIDATE_FLASH_AUTH=1 # # Candidate image is not valid for this platform VALIDATE_INVALID_IMG=2 # # Current fixpack level is unknown VALIDATE_CUR_UNKNOWN=3 # # Current T side will be committed to P side before being replace # with new image, and the new image is downlevel from current image VALIDATE_TMP_COMMIT_DL=4 # # Current T side will be committed to P side before being replaced # with new image VALIDATE_TMP_COMMIT=5 # # T side will be updated with a downlevel image VALIDATE_TMP_UPDATE_DL=6 # # The candidate image's release date is later than the system's Update # Access Key Expiration date - service warranty period has expired VALIDATE_OUT_OF_WRNTY=7 error() { local exit_code=$1 if [ $# -lt 1 ]; then echo "error(): usage." >&2 return $E_USAGE fi shift; echo update_flash: $* >&2 exit $exit_code } usage() { local exit_code; if [ "$1" = $E_SUCCESS ]; then exit_code=$E_SUCCESS else exit_code=$E_USAGE fi echo "USAGE: update_flash {-h | -s | -r | -c | -d | [-v|-n] -f }" >&2 echo " -h Print this message." >&2 echo " -s Determine if partition has access to" >&2 echo " perform flash image management." >&2 echo " -r Reject temporary image." >&2 echo " -c Commit temporary image." >&2 echo " -d Display current firmware version." >&2 echo " -v Validate the given image file." >&2 echo " -n Do not overwrite Permanent side" >&2 echo " image automatically." >&2 echo " -f Update with given image file. If possible," >&2 echo " the image is automatically validated prior" >&2 echo " to update." >&2 echo "" >&2 exit $exit_code } # Validate sysfs interface validate_sysfs_file() { local file="$1" if [ -r "$file" ]; then return $E_SUCCESS fi error $E_SYS_FS "sysfs interface for firmware update does not exists." } # Copy image to sysfs file copy_candidate_image() { local img_file=$1 [ $# -eq 1 ] || error $E_USAGE "copy_candidate_image(): usage." [ -r "$img_file" ] || error $E_IMAGE "Cannot read ${img_file}." # Copy candidate image dd if=$img_file of=$SYS_IMAGE_FILE 2>/dev/null if [ $? -ne 0 ]; then echo "update_flash: Error copying firmware image." error $E_IMAGE "Please retry with valid firmware image." fi } echo_opal_return_status() { case "$1" in $FLASH_PARAM_ERR) error $E_OPAL "Parameter Error.";; $FLASH_BUSY) error $E_OPAL "OPAL Busy.";; $FLASH_HW_ERR) error $E_OPAL "Hardware error.";; $FLASH_INTERNAL_ERR) error $E_OPAL "OPAL internal error.";; $FLASH_NO_AUTH) error $E_PERM "System does not have authority to perform firmware update.";; $FLASH_IMG_INCOMPLETE) error $E_IMAGE "Invalid candidate image.";; $FLASH_ACTIVE_ERR) error $E_OVERWRITE "Cannot Overwrite the Active Firmware Image.";; $FLASH_INVALID_IMG) error $E_IMAGE "Invalid candidate image.";; $FLASH_IMG_NULL_DATA) error $E_IMAGE "Bad data value in flash list block.";; $FLASH_IMG_BAD_LEN) error $E_IMAGE "Bad length value in flash list block.";; *) error $E_OPAL "Unknown return status.";; esac } # Determine if partition has access to perform flash image management query_flash_support() { # Validate sysfs interface validate_sysfs_file $SYS_IMAGE_FILE # By default KVM on Power host is allowed to do firmware management echo "update_flash: Firmware image management is supported." exit $E_SUCCESS } echo_validate_buf() { local output="$1" local cur_t=$(echo "$output" | grep "^MI" | head -n 1 | awk ' { print $2 } ') local cur_p=$(echo "$output" | grep "^MI" | head -n 1 | awk ' { print $3 } ') local new_t=$(echo "$output" | grep "^MI" | tail -n 1 | awk ' { print $2 } ') local new_p=$(echo "$output" | grep "^MI" | tail -n 1 | awk ' { print $3 } ') echo "Projected Flash Update Results:" echo "Current T Image: $cur_t" echo "Current P Image: $cur_p" echo "New T Image: $new_t" echo "New P Image: $new_p" } echo_validate_return_status() { local output="$1" local rc="$(echo "$output" | head -n 1)" local opal_buf="$(echo "$output" | tail -n +2)" [ $# -eq 1 ] || error $E_USAGE "echo_validate_return_status(): usage." if [ $rc -lt 0 ]; then echo_opal_return_status $rc fi # Validation result case "$rc" in $VALIDATE_TMP_UPDATE) echo -n "info: Temporary side will be updated with a newer or" echo " identical image.";; $VALIDATE_FLASH_AUTH) error $E_OPAL "System does not have authority.";; $VALIDATE_INVALID_IMG) error $E_OPAL "Invalid candidate image for this platform.";; $VALIDATE_CUR_UNKNOWN) echo "info: Current fixpack level is unknown.";; $VALIDATE_TMP_COMMIT_DL) echo "info: Current Temporary image will be committed to" echo "Permanent side before being replaced with new image," echo "and the new image is downlevel from current image.";; $VALIDATE_TMP_COMMIT) echo "info: Current Temporary side will be committed to" echo "Permanent side before being replaced with the new" echo "image.";; $VALIDATE_TMP_UPDATE_DL) echo "info: Temporary side will be updated with a downlevel image.";; *) error $E_OPAL "Unknown return status." esac echo echo_validate_buf "$opal_buf" # Do not commit T side image to P side if [ $no_overwrite_opt -eq 1 ]; then if [ $rc -eq $VALIDATE_TMP_COMMIT_DL ] || [ $rc -eq $VALIDATE_TMP_COMMIT ]; then echo "" echo "update_flash: Run without -n option to flash new image." exit $E_OVERWRITE fi fi } validate_flash() { local output="" # Validate candidate image echo 1 > $SYS_VALIDATE_FLASH 2>/dev/null # Display appropriate message, exiting if necessary output="$(cat $SYS_VALIDATE_FLASH)" echo_validate_return_status "$output" } validate_flash_from_file() { local img_file=$1 [ $# -eq 1 ] || error $E_USAGE "validate_flash_from_file(): usage." # Validate sysfs interface validate_sysfs_file $SYS_VALIDATE_FLASH # Copy candiadate image copy_candidate_image $img_file # Validate candidate image validate_flash exit $E_SUCCESS } echo_update_return_status() { local rc="$1" [ $# -eq 1 ] || error $E_USAGE "echo_update_return_status(): usage." if [ $rc -lt 0 ]; then echo_opal_return_status $rc elif [ $rc -eq $FLASH_IMG_READY ]; then echo echo "FLASH: Image ready...rebooting the system..." echo "FLASH: This will take several minutes." echo "FLASH: Do not power off!" else error $E_SYS_FS "Unknown return status." fi } update_flash_from_file() { local img_file=$1 local output="" [ $# -eq 1 ] || error $E_USAGE "update_flash_from_file(): usage." # Validate sysfs interface validate_sysfs_file $SYS_UPDATE_FLASH # Copy candidate image copy_candidate_image $img_file # Validate candidate image validate_flash # Update image echo 1 > $SYS_UPDATE_FLASH 2>/dev/null output="$(cat $SYS_UPDATE_FLASH)" echo_update_return_status "$output" # Reboot system, so that we can flash new image reboot exit $E_SUCCESS } echo_manage_return_status() { local is_commit=$1 local output=$2 local rc=$(echo $output) [ $# -eq 2 ] || error $E_USAGE "echo_manage_return_status(): usage." if [ $rc -lt 0 ]; then echo_opal_return_status $rc elif [ $rc -eq $FLASH_SUCCESS ]; then if [ $is_commit -eq 0 ]; then echo "Success: Rejected temporary firmware image." else echo "Success: Committed temporary firmware image." fi else error $E_OPAL "Unknown return status." fi } manage_flash() { local is_commit=$1 local commit_str="1" local reject_str="0" local output="" [ $# -eq 1 ] || error $E_USAGE "manage_flash(): usage." # Validate sysfs interface validate_sysfs_file $SYS_MANAGE_FLASH # Commit operation if [ $is_commit -eq 1 ]; then echo $commit_str > $SYS_MANAGE_FLASH else echo $reject_str > $SYS_MANAGE_FLASH fi # Result output=$(cat $SYS_MANAGE_FLASH) echo_manage_return_status $is_commit "$output" exit $E_SUCCESS } display_current_fw_version() { if [ ! -r "$DT_FW_MI_FILE" ] || [ ! -r "$DT_FW_ML_FILE" ]; then error $E_SYS_FS "Firmware version information is not available" fi echo "Current firwmare version :" # P side local ml_ver=`cat $DT_FW_ML_FILE | head -n 1 | awk ' { print $3 }'` local mi_ver=`cat $DT_FW_MI_FILE | head -n 1 | awk ' { print $3 }'` echo " P side : $ml_ver ($mi_ver)" # T side local ml_ver=`cat $DT_FW_ML_FILE | head -n 1 | awk ' { print $2 }'` local mi_ver=`cat $DT_FW_MI_FILE | head -n 1 | awk ' { print $2 }'` echo " T side : $ml_ver ($mi_ver)" # Boot side local ml_ver=`cat $DT_FW_ML_FILE | head -n 1 | awk ' { print $4 }'` local mi_ver=`cat $DT_FW_MI_FILE | head -n 1 | awk ' { print $4 }'` echo " Boot side : $ml_ver ($mi_ver)" exit $E_SUCCESS } file="" check_opt=0 display_opt=0 commit_opt=0 reject_opt=0 validate_opt=0 no_overwrite_opt=0 file_opt=0 # Only root user can perform firmware update [ "`whoami`" = "root" ] || error $E_PERM "Must be root to execute this command." # Parse command line options while [ -n "$1" ]; do arg="$1" shift case "$arg" in -q|-l|-D|-S) error $E_USAGE "The $arg option is not implemented.";; -h) usage $E_SUCCESS;; -s) check_opt=1;; -d) display_opt=1;; -c) commit_opt=1;; -r) reject_opt=1;; -v) validate_opt=1;; -n) no_overwrite_opt=1;; -f) file_opt=1; file="$1"; shift;; *) error $E_USAGE "Unknown option ${arg}." esac done if [ -n "$file" ]; then if [ $commit_opt -eq 1 ] || [ $reject_opt -eq 1 ] || [ $display_opt -eq 1 ] || [ $check_opt -eq 1 ]; then usage elif [ $validate_opt -eq 1 ] && [ $no_overwrite_opt -eq 1 ]; then usage elif [ $validate_opt -eq 1 ]; then validate_flash_from_file $file else update_flash_from_file $file fi else if [ $check_opt -eq 1 ]; then if [ $commit_opt -eq 1 ] || [ $reject_opt -eq 1 ] || [ $display_opt -eq 1 ]; then usage else query_flash_support fi fi # Display current firmware version if [ $display_opt -eq 1 ]; then if [ $commit_opt -eq 1 ] || [ $reject_opt -eq 1 ]; then usage else display_current_fw_version fi fi [ $commit_opt -eq 0 ] && [ $reject_opt -eq 0 ] && usage [ $commit_opt -eq 1 ] && [ $reject_opt -eq 1 ] && usage manage_flash $commit_opt fi powerpc-utils-1.2.26/scripts/hvcsadmin0000775000175000017510000005241312527176005014746 00000000000000#!/usr/bin/perl -w # IBM "hvcsadmin": HVCS driver 'helper' application # # Copyright (c) 2004, 2005 International Business Machines. # Common Public License Version 1.0 (see COPYRIGHT) # # Author(s): Ryan S. Arnold # # This application provides a simple command line interface for simplifying # the management of hvcs. # # For further details please reference man page hvcsadmin.8 use strict; use File::Basename; use vars '$app_name'; $app_name = "hvcsadmin"; use vars '$app_version'; $app_version = "1.0.0"; use vars '$driver'; $driver = "hvcs"; use vars '$global_node_name'; $global_node_name = "hvcs"; use vars '$noisy'; $noisy = 0; use Getopt::Long; sub verboseprint( $ ) { my $output = shift; if($noisy > 1) { print "$output"; } } sub statusprint( $ ) { my $output = shift; if($noisy > 0 ) { print "$output"; } } sub errorprint( $ ) { my $output = shift; print "$output"; } # Simply output the version information about this helper application. sub versioninfo { print "IBM ", $app_name, " version ",$app_version,"\n"; print "Copyright (C) 2004, IBM Corporation.\n"; print "Author(s) Ryan S. Arnold\n"; } # Help information text displayed to the user when they invoke the script with # the -h tag. sub helpinfo { print "Usage: ", $app_name, " [options]\n"; print "Options:\n"; print " -all"; print "\t\t\tClose all open vty-server adapter connections.\n"; print "\n"; print " -close "; print "\tClose the vty-server adapter connection for the\n"; print "\t\t\t$driver device node specified in the option.\n"; print "\n"; print " -console "; print "\tWhich /dev/$driver\* node provides the console for\n"; print "\t\t\tthe option specified partition?\n"; print "\n"; print " -help"; print "\t\t\tOutput this help text.\n"; print "\n"; print " -node "; print "\tWhich vty-server adapter is mapped to the option\n"; print "\t\t\tspecified /dev/$driver\* node?\n"; print "\n"; print " -noisy"; print "\t\t\tThis is a stackable directive denoting the verbosity\n"; print "\t\t\tof the $app_name script. The default noise level of\n"; print "\t\t\t'0' makes $app_name silent on success but verbose on\n"; print "\t\t\terror. A noise level of '1' will output additional\n"; print "\t\t\tsuccess information. A noisy level of '2' will\n"; print "\t\t\toutput $app_name script trace information.\n"; print "\n"; print "\t\t\tNOTE: options for which $app_name queries data are\n"; print "\t\t\tnot squelched with the default noise level.\n"; print "\n"; print " -rescan"; print "\t\tDirect the hvcs driver to rescan partner info\n"; print "\t\t\tfor all vty-server adapters.\n"; print "\n"; print " -status"; print "\t\tOutput a table with each row containing a vty-server,\n"; print "\t\t\tadapter, its /dev/$driver\* device node mapping, and\n"; print "\t\t\tits connection status. \"vterm_state:0\" means it is\n"; print "\t\t\tfree and \"vterm_state:1\" means the vty-server is\n"; print "\t\t\tconnected to its vty partner adapter.\n"; print "\n"; print " -version\t\tOutput the ", $app_name, " script's version number.\n"; print "\n"; } sub rescan { # Determine the sysfs path and driver name programatically because these can # change. my $val; my $local_driver; my $driver_path; verboseprint("$app_name: initiating rescan of all vty-server adapter partners.\n"); #use systool to find the vio devices which we want to close local *SYSTOOL; open SYSTOOL, "systool -b vio -D -p |" or die "systool: $!"; while (my $line = ) { ($val) = ($line =~ /^\s*Driver = "(.*)"\s*$/); if(defined $val) { $local_driver = $1; $driver_path = ""; next; } ($val) = ($line =~ /^\s*Driver path = "(.*)"\s*$/); if(defined $val) { $driver_path = $1; if ($local_driver eq $driver) { `echo 1 > $driver_path/rescan`; statusprint("$app_name: $driver driver rescan executed.\n"); close SYSTOOL; exit; } next; } } errorprint("$app_name: $driver sysfs entry or $driver rescan attribute not found.\n"); close SYSTOOL; } sub closeall { # Programatically locate all the vty-server adapters and close their # connections (or at least attempt to). One or more closures may fail if # there is an application using the device node that is mapped to the # vty-server adapter that is being closed. my $val; my $local_driver; my $local_device; my $vterm_state; my $device_path; local *SYSTOOL; #use systool to find the vio devices which we want to close open SYSTOOL, "systool -b vio -D -A vterm_state -p |" or die "systool: $!"; while (my $line = ) { ($val) = ($line =~ /^\s*Driver = "(.*)"\s*$/); if(defined $val) { $local_driver = $1; $local_device = ""; $device_path = ""; next; } ($val) = ($line =~ /^\s*Device path = "(.*)"\s*$/); if(defined $val) { $device_path = $1; next; } ($val) = ($line =~ /^\s*Device = "(.*)"\s*$/); if(defined $val) { $local_device = $1; next; } ($val) = ($line =~ /^\s*vterm_state\s*= "(.*)"\s*$/); if(defined $val) { $vterm_state = $1; if (($local_driver eq $driver) and ($vterm_state eq "1")) { `echo 0 > $device_path/vterm_state`; statusprint("$app_name: closed vty-server\@$local_device partner adapter connection.\n"); } next; } } close SYSTOOL; } # This is a input validation routine which checks a user entered device path # to determine if the device index is in the proper range. sub validindex( $ ) { my $dev_index = shift; verboseprint("$app_name: is $dev_index a valid device node number? ...\n"); # We didn't find an invalid number that starts with 0 and has more digits if ($dev_index =~ /(^0.+$)/) { errorprint("$app_name: \"$dev_index\" is an invalid device node number.\n"); return -1; } verboseprint("$app_name: $dev_index is a valid device node index.\n"); return 0; } # Checks to see if the user entered device node exists in the /dev directory. # If this unexpectedly indicates that there is no device it may be because # udev is managing the /dev directory and the hvcs driver has not yet been # inserted. sub finddeventry( $ $ ) { my $node_name = shift; my $dev_number = shift; my $device_path = "/dev/$node_name$dev_number"; verboseprint("$app_name: is $device_path in /dev? ...\n"); if(! -e "$device_path") { errorprint("$app_name: $device_path not found in /dev.\n"); return -1; } verboseprint("$app_name: found $device_path in /dev.\n"); return 0; } sub is_driver_installed() { my $val = ""; my $local_driver = ""; my $driver_path = ""; verboseprint("$app_name: is $driver loaded.\n"); local *SYSTOOL; open SYSTOOL, "systool -b vio -D -p|" or die "systool: $!"; while (my $line = ) { ($val) = ($line =~ /^\s*Driver = "(.*)"\s*$/); if(defined $val) { $local_driver = $1; $driver_path = ""; next; } ($val) = ($line =~ /^\s*Driver path = "(.*)"\s*$/); if(defined $val) { $driver_path = $1; # grab only the Driver,Driver path pair for $driver if ($local_driver eq $driver) { verboseprint("$app_name: verified that $driver is loaded at $driver_path\.\n"); close SYSTOOL; return $driver_path; } next; } } errorprint("$app_name: $driver is not loaded.\n"); close SYSTOOL; return ""; } # Verify that the systools package is installed. This package is required for # using this scripts because this script uses systools to make sysfs queries. # It then strips relevant data from the systool queries for use in additional # features. sub findsystools() { #--------------- Look for the systool application ----------------------- local *WHICH; open WHICH, "which systool|"; my @whicharray = ; my $whichline = join("\n", @whicharray); chomp($whichline); close WHICH; verboseprint("$app_name: looking for \"systool\" application.\n"); if ($whichline eq "") { errorprint("$app_name: systool is not installed or not in the path?\n"); errorprint("$app_name: systool is required by the $app_name script.\n"); return -1; } verboseprint("$app_name: found \"systool\" at $whichline\.\n"); return 0; } # This function is a helper function that is used to return a sysfs hvcs # device path based upon a partition number. This function always looks for # the zeroeth indexed partner adapter, meaning it will always return the path # to the console device for the selected target partition. sub get_device_path_by_partition ( $ ) { my $target_partition = shift; my $local_driver; my $found_partition; my $found_slot; my $device_path; my $val; verboseprint("$app_name: fetching device path for partition $target_partition\.\n"); local *SYSTOOL; open SYSTOOL, "systool -b vio -D -A current_vty -p|" or die "systool: $!"; while (my $line = ) { ($val) = ($line =~ /^\s*Driver = "(.*)"\s*$/); if(defined $val) { $local_driver = $1; $device_path = ""; $found_partition = ""; $found_slot = ""; next; } ($val) = ($line =~ /^\s*Device path = "(.*)"\s*$/); if(defined $val) { $device_path = $1; next; } # Grab the partition number out of clc, e.g. the numeric index # following the V, and grab the slot number, e.g. the numeric index # following the C: "U9406.520.100048A-V15-C0" ($val) = ($line =~ /^\s*current_vty\s*= "\w+\.\w+\.\w+-V(\d+)-C(\d+)"\s*$/); if(defined $val) { $found_partition = $1; $found_slot = $2; if (($local_driver eq $driver) and ($target_partition eq $found_partition) and ($found_slot eq "0")) { verboseprint("$app_name: found console device for partition $target_partition at $device_path\.\n"); return $device_path; } } } statusprint("$app_name: could not find device path for partition $target_partition\.\n"); return ""; } # This function is a helper function that is used to return a sysfs path based # upon an index number. The "index" is the number that is part of the hvcs # device path name. For instance, in "/dev/hvcs2", the number '2' is refered # to as the "index". Additionally, the sysfs entry keeps track of the index # number for the hvcs entries in sysfs so there is a correlation between the # data kept in the sysfs entry and the actual /dev/hvcs* entry. sub get_device_path_by_index ( $ ) { my $target_index = shift; my $device_path; my $index; my $local_driver; my $val; verboseprint("$app_name: fetching device path for index $target_index\.\n"); local *SYSTOOL; open SYSTOOL, "systool -b vio -D -A index -p|" or die "systool: $!"; while (my $line = ) { ($val) = ($line =~ /^\s*Driver = "(.*)"\s*$/); if(defined $val) { $local_driver = $1; $device_path = ""; $index = ""; next; } ($val) = ($line =~ /^\s*Device path = "(.*)"\s*$/); if(defined $val) { $device_path = $1; next; } ($val) = ($line =~ /^\s*index\s*= "(.*)"\s*$/); if(defined $val) { $index = $1; if (($local_driver eq $driver) and ($index eq $target_index)) { verboseprint("$app_name: found device path for device index $target_index at $device_path\.\n"); close SYSTOOL; return $device_path; } next; } } statusprint("$app_name: /dev/$global_node_name$target_index does not map to a vty-server adapter\.\n"); close SYSTOOL; return ""; } # This function takes a sysfs path to an hvcs adapter and displays it in a # formatted manner. This path is gathered using one of the previous path # retrieval functions. Generally devices are displayed in a sequence and a # table is created out of these details though they can be displayed # individually as well. sub displaybypath( $ ) { my $path = shift; verboseprint("$app_name: displaying status information for $path\.\n"); if ($path eq "") { errorprint("$app_name: displaybypath( \$ ) path parameter is empty.\n"); return -1; } if(! -e "$path/current_vty") { errorprint("$app_name: $path/current_vty attribute does not exist.\n"); exit; } verboseprint("$app_name: $path/current_vty attribute exists.\n"); if(! -e "$path/index") { errorprint("$app_name: $path/index attribute does not exist.\n"); exit; } verboseprint("$app_name: $path/index attribute exists.\n"); if(! -e "$path/vterm_state") { errorprint("$app_name: $path/vterm_state attribute does not exist.\n"); exit; } verboseprint("$app_name: verified that $path/vterm_state attribute exists.\n"); local *CURRENT_VTY; open CURRENT_VTY, "$path/current_vty"; chomp (my $current_vty = ); close CURRENT_VTY; # parse the CLC, nasty as it may be my ($machine, $partition, $slot) = $current_vty =~ /(\w+\.\w+\.\w+)-V(\d+)-C(\d+)$/; local *VTERM_STATE; open VTERM_STATE, "$path/vterm_state"; chomp (my $vterm_state = ); close VTERM_STATE; local *INDEX; open INDEX, "$path/index"; chomp (my $device_index = ); close INDEX; #/sys/devices/vio/30000005 my ($vty_server) = $path =~ /.+(3\d+)$/; print "vty-server\@$vty_server partition:$partition slot:$slot /dev/$driver$device_index vterm-state:$vterm_state\n"; } # This function simply takes a /dev/hvcs* entry and displays the relevant # sysfs entry data about that device node. sub querynode( $ ) { my $dev_node = shift; my $dev_index = getindex( $dev_node ); my $dev_name = getnodename( $dev_node ); verboseprint("$app_name: querying status information for node $dev_node\.\n"); if ($dev_name ne $global_node_name) { errorprint("$app_name: $dev_node is an invalid device node name.\n"); exit; } if (validindex($dev_index)) { exit; } if (finddeventry($dev_name, $dev_index)) { exit; } #check modinfo version of the hvcs module? my $path = get_device_path_by_index( $dev_index ); if ($path eq "") { return; } displaybypath( $path ); } # This function displays the sysfs information about a console to a specific # partition. This function should only display output if a device is found # that maps to a zero slotted vty-server adapter, since only slot 0 adapters # are console adapters. sub queryconsole( $ ) { my $partition = shift; my $path = get_device_path_by_partition( $partition ); if ($path eq "") { return; } displaybypath( $path ); } sub status { local *DIRHANDLE; opendir(DIRHANDLE, "/dev"); my @allentries = sort readdir DIRHANDLE; closedir DIRHANDLE; my $path = ""; my $count = 0; verboseprint("$app_name: gathering status for all vty-server adapters.\n"); verboseprint("$app_name: some device nodes won't be mapped to vty-server adapters.\n"); foreach my $entry (@allentries) { if( $entry =~ /$global_node_name(\d)$/) { $path = get_device_path_by_index( $1 ); if ($path ne "") { displaybypath( $path ); $count++; } } $path = ""; } if ($count eq 0) { print("$app_name: no hvcs adapters found\.\n"); } } sub getindex ( $ ) { $_ = shift; /$global_node_name([0-9]+$)/; if(defined $1) { return $1; } else { return -1; } } sub getnodename ( $ ) { $_ = shift; /($global_node_name)[0-9]+$/; if(defined $1) { return $1; } else { return ""; } } sub closedevice ( $ ){ my $parameter = shift; my $node_name = getnodename( $parameter ); my $node_index = getindex( $parameter ); #--------------- Is the specified device name valid? -------------------- if ($node_name ne "$global_node_name") { errorprint("$app_name: $parameter is an invalid device node name.\n"); exit; } #--------------- Is the specified device index reasonable? -------------- if (validindex($node_index)) { exit; } #--------------- Does the /dev/ entry exist ----------------------------- if (finddeventry($node_name, $node_index)) { exit; } #check modinfo version of the hvcs module #--------------- Gather sysfs info from systool ------------------------- my $device_path = get_device_path_by_index($node_index); if ($device_path eq "") { exit; } verboseprint("$app_name: vty-server adapter $device_path maps to /dev/$node_name$node_index\.\n"); if(! -e "$device_path/vterm_state"){ errorprint("$app_name: vterm_state attribute does not exist.\n"); exit; } verboseprint("$app_name: verified that $device_path/vterm_state attribute exists.\n"); local *CAT_VTERM_STATE; open CAT_VTERM_STATE, "cat $device_path/vterm_state|"; my $catval = ; close CAT_VTERM_STATE; if ($catval =~ /^0$/) { statusprint("$app_name: vty-server adapter $device_path is already disconnected.\n"); exit; } verboseprint("$app_name: preparing to terminate vty-server connection at $device_path\.\n"); system("echo 0 > $device_path/vterm_state"); local *CAT_STATE; open CAT_STATE, "cat $device_path/vterm_state|"; my $cat = ; close CAT_STATE; if ($cat !~ /^0$/) { errorprint("$app_name: vty-server adapter $device_path disconnection failed.\n"); errorprint("$app_name: please check dmesg for further information.\n"); exit; } my ($vty_server) = $device_path =~ /.+(3\d+)$/; statusprint("$app_name: /dev/node/$node_name$node_index is mapped to vty-server\@$vty_server\.\n"); statusprint("$app_name: closed vty-server\@$vty_server partner adapter connection.\n"); } my $PSERIES_PLATFORM = dirname(__FILE__) . "/pseries_platform"; my $perldumpenv='perl -MData::Dumper -e '."'". '\$Data::Dumper::Terse=1;print Dumper(\%ENV);'."'"; eval '%ENV=('.$1.')' if `bash -c " . $PSERIES_PLATFORM; $perldumpenv"` =~ /^\s*\{(.*)\}\s*$/mxs; if ($ENV{'platform'} != $ENV{'PLATFORM_PSERIES_LPAR'}) { print "$app_name: is not supported on the $ENV{'platform_name'} platform\n"; exit 1; } my $help = ''; my $version = ''; my $close_device = ''; my $all = ''; my $query_node = ''; my $query_console = ''; my $status = ''; my $rescan = ''; my $num_options = @ARGV; # -noisy is the only option that stacks GetOptions ( 'all' => \$all, 'help|?' => \$help, 'noisy+' => \$noisy,# noisy is incremental, # 0 : silent (except on error) [default] # 1 : status (successes) # 2 : verbose operation trace 'status' => \$status, 'rescan' => \$rescan, 'version' => \$version, 'node=s' => \$query_node, 'close=s' => \$close_device, 'console=s' => \$query_console, ); # An empty invocation of this script will result in the help text being # output. If help text has been specified then this script will terminate # after outputing the help text without completing further operations. if ($num_options == 0 || $help) { helpinfo(); exit; } if ($version) { versioninfo(); exit; } verboseprint("$app_name: executing in verbose mode.\n"); # DON'T rely on the module existence to determine whether $driver is # supported since it could have been built into the kernel. #--------------- Look for the $driver module in lsmod ------------------- if (!is_driver_installed()) { exit; } #--------------- Look for the systool application ----------------------- # The systool application is required for invoking most/many of these # operations so we'll express it as a standard requirement. if (findsystools()) { exit; } if ($status) { status(); exit; } if ($rescan) { rescan(); } if ($all) { closeall(); exit; } if ($close_device) { closedevice($close_device); exit; } if ($query_node) { querynode($query_node); exit; } if ($query_console) { queryconsole($query_console); exit; } exit; powerpc-utils-1.2.26/scripts/rtas_dump0000775000175000017510000000672312542271360014770 00000000000000#! /usr/bin/perl # # This updated version of the rtas_dump script will # do everything the original rtas_dump script does except # it does it cleaner and without as many cmdline options. # # Copyright (C) 2004 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Author: Nathan Fontenot # use vars qw/ %opt /; use Getopt::Long; use File::Basename; $re_decode = $ENV{RTAS_EVENT_DECODE} || "/usr/sbin/rtas_event_decode"; # # usage statement # sub usage() { print "Usage: rtas_dump [OPTIONS]\n"; print "Dump the contents of an RTAS event, by default RTAS events\n"; print "are read from stdin unless the -f flag is used.\n\n"; print " -d debug flag, passed through to rtas_event_decode\n"; print " -f dump the RTAS events from \n"; print " -h print this message and exit\n"; print " -n only dump RTAS event number \n"; print " -v dump the entire RTAS event, not just the header\n"; print " -w set the output character width\n"; exit 1; } # # Read in the contents of an RTAS event and invoke rtas_event_decode on it. # sub handle_rtas_event() { my ($event_no) = @_; $re_decode_args = "$re_decode_args -n $event_no"; # create the pipe to rtas_event_decode open EVENT_DECODE, "| $re_decode $re_decode_args"; while(<$fh>) { ($crud, $data) = split (/RTAS/); $rtas_str = $rtas_str . "RTAS" . $data; if (/RTAS event end/) { print EVENT_DECODE $rtas_str; $rtas_str = ""; last; } } close EVENT_DECODE; } # # Main # my $PSERIES_PLATFORM = dirname(__FILE__) . "/pseries_platform"; my $perldumpenv='perl -MData::Dumper -e '."'". '\$Data::Dumper::Terse=1;print Dumper(\%ENV);'."'"; eval '%ENV=('.$1.')' if `bash -c " . $PSERIES_PLATFORM; $perldumpenv"` =~ /^\s*\{(.*)\}\s*$/mxs; if ($ENV{'platform'} == $ENV{'PLATFORM_UNKNOWN'} || $ENV{'platform'} == $ENV{'PLATFORM_POWERNV'}) { print "rtas_dump: is not supported on the $ENV{'platform_name'} platform\n"; exit 1; } # process cmdline args Getopt::Long::Configure("bundling"); GetOptions("help|h" => \$help_flag, "dump_raw|d" => \$debug_flag, "file|f=s" => \$filename, "n=i" => \$event_no, "w=i" => \$width, "verbose|v+" => \$verbose) or usage(); usage() if $help_flag; # make sure the rtas_event_decode application is available -e $re_decode or die "File $re_decode does not exist and is needed by rtas_dump.\n"; -x $re_decode or die "File $re_decode is not executable.\n"; # get a reference to our input filehandle if ($filename) { if (-e $filename) { open INPUT_FILE, $filename; $fh = \*INPUT_FILE; $close_input_file = 1; } else { print "File $filename does not exist\n" ; return -1; } } else { $fh = \*STDIN; } # create the arg list to rtas_event_decode $re_decode_args = "$re_decode_args -d" if $debug_flag; $re_decode_args = "$re_decode_args -v" if $verbose; $re_decode_args = "$re_decode_args -w $width" if $width; while (<$fh>) { if (/RTAS event begin/) { # found the beginning of an RTAS event, process it. ($crud, $data) = split (/RTAS:/); ($this_event_no, $d) = split (' ', $data); if ($event_no) { if ($event_no == $this_event_no) { $rtas_str = $rtas_str . "RTAS:" . $data; &handle_rtas_event($this_event_no); } } else { $rtas_str = $rtas_str . "RTAS:" . $data; &handle_rtas_event($this_event_no); } next; } } if ($close_input_file) { close INPUT_FILE; } powerpc-utils-1.2.26/scripts/snap0000775000175000017510000002562312542271360013733 00000000000000#!/usr/bin/perl -w # Copyright (c) 2003, 2004, 2012 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Author Todd Inglett # updates by Michael Strosaker # updates by Vasant Hegde # Snapshot system config # Command-line parameters: # a: all data; collect detailed information (more files and output) # d dir: specify the directory where files and output will be collected # (default: /tmp/ibmsupt) # h: print this help message # o file: specify the output file (.tar required, .tar.gz optional) # (default: snap.tar.gz) # v: verbose output # # Exit codes (view with "echo $?" immediately after running): # 0: snap data was successfully captured # 1: invalid command line # 2: other fatal error use strict; use Getopt::Std; use POSIX qw(strftime); use Sys::Hostname; use FileHandle; use File::Basename; my $PSERIES_PLATFORM = dirname(__FILE__) . "/pseries_platform"; my $outdir = "/tmp/ibmsupt"; # note NO trailing / my $outfile = "snap.tar.gz"; # in the working dir. my $cmddir = "snap_commands"; # cmd output dir. my $cmdoutdir = "$outdir/$cmddir"; # in outdir dir. my $rsxx_exists = 0; # Does an IBM Flash Adapter exist? my $distro_file = "/etc/issue"; my $redhat_release_file = "/etc/redhat-release"; if (-e $redhat_release_file) { open(RELEASE, "< $redhat_release_file") or die "open: $!\n"; $_ = ; my $redhat_version = (split / /, $_)[6]; if ($redhat_version >= 7.0) { print "snap is not supported on the RHEL 7 onwards..!\n"; print "Please use sosreport to collect log data..!! \n"; exit 1; } } our($opt_a, $opt_d, $opt_h, $opt_o, $opt_t, $opt_v); # Files to include in all snaps my @snap_paths_general = ( "/var/log/messages", "/var/log/platform", "/var/log/scanoutlog.*", # "/proc/bus/pci", ?? binary file "/proc/cmdline", "/proc/cpuinfo", "/proc/devices", "/proc/dma", "/proc/filesystems", "/proc/fs", "/proc/ide", "/proc/interrupts", "/proc/iomem", "/proc/ioports", "/proc/loadavg", "/proc/locks", "/proc/mdstat", "/proc/meminfo", "/proc/misc", "/proc/modules", "/proc/mounts", "/proc/net", "/proc/partitions", "/proc/pci", "/proc/ppc64/lparcfg", "/proc/ppc64/eeh", "/proc/ppc64/pci", "/proc/ppc64/systemcfg", "/proc/scsi", "/proc/slabinfo", "/proc/stat", "/proc/swaps", "/proc/sys", "/proc/sysvipc", "/proc/uptime", "/proc/version", "/dev/nvram", "/etc/fstab", "/etc/raidtab", "/etc/yaboot.conf", ); # Files to include in all snaps on SuSE systems my @snap_paths_general_SuSE = ( "/etc/SuSE-release", "/var/log/boot.msg", ); # Files to include in all snaps on Red Hat systems my @snap_paths_general_RedHat = ( "/etc/redhat-release", "/var/log/dmesg", ); # Files to include only in detailed snaps (-a option) my @snap_paths_detailed = ( "/proc/tty", "/etc/inittab", "/proc/ppc64/", "/proc/device-tree/", ); # Command output to include in all snaps my @snap_commands_general = ( "lscfg -vp", "ifconfig -a", "lspci -vvv" ); # Command output to include only in detailed snaps (-a option) my @snap_commands_detailed = ( "rpm -qa", "servicelog --dump", "servicelog_notify --list", "usysattn", "usysident", "serv_config -l", "bootlist -m both -r", "lparstat -i", "lsmcode -A", "lsvpd --debug", "lsvio -des", "ppc64_cpu --smt --cores-present --cores-on --run-mode --frequency --dscr", ); # Command output to include for IBM Flash Adapter(s) my @snap_command_rsxx = ( "rs_cardreport -d 'all'", ); # Files, which are to be ignored as they are deprecated my @snap_deprecated_files = ( "retrans_time", "base_reachable_time", ); sub recurse_dir($); # function prototype sub error { my ($fatal, $message) = @_; if ($fatal) { print "$0: $message\n"; exit 2; } else { if ($opt_v) { print "$0: $message\n"; } } } sub print_usage { print "Usage: $0 [-athv] [-d dir] [-o file]\n\n"; print " Command-line parameters:\n"; print " a: all data; collect detailed information (more files and output)\n"; print " d dir: specify the directory where files and output will be collected\n"; print " (default: /tmp/ibmsupt)\n"; print " o file: specify the output file (.tar required, .tar.gz optional)\n"; print " (default: snap.tar.gz)\n"; print " t: add hostname and timestamp to output filename\n"; print " v: verbose output\n\n"; print " h: print this help message\n"; print " Exit codes (view with \"echo \$?\" immediately after running):\n"; print " 0: snap data was successfully captured\n"; print " 1: invalid command line\n"; print " 2: other fatal error\n\n"; } sub copy { my ($source, $destination) = @_; my ($dir, @path, $d, $blocksize, $buffer, $length, $offset, $written); #print "Copying $source..."; # Create directories, if necessary $dir = substr $destination, 0, rindex($destination, "/"); if (!(-d $dir)) { @path = split /\//, $dir; if (substr($dir, 0, 1) eq "/") { # remove leading / shift @path; } $dir = ""; foreach $d (@path) { $dir .= "/" . $d; if (!(-d $dir)) { if (!mkdir($dir, 0644)) { error(0, "Cannot create directory: $dir"); return; } } } } # Copy file if (!sysopen(SRC, "$source", O_NONBLOCK|O_RDONLY)) { error(0, "Cannot open file for reading: $source"); return; } binmode SRC; if (!open(DST, ">$destination")) { error(0, "Cannot open file for writing: $destination"); goto copy_out; } binmode DST; $blocksize = (stat SRC)[11] || 16384; while ($length = sysread SRC, $buffer, $blocksize) { if (!defined $length) { next if $! =~ /^Interrupted/; # ^Z and fg error(0, "System read error while reading $source: $!"); goto copy_out; } $offset = 0; while ($length) { if (!defined($written = syswrite DST, $buffer, $length, $offset)) { error(0, "System write error while writing $destination: $!"); goto copy_out; } $length -= $written; $offset += $written; } } copy_out: #print "done.\n"; close SRC; close DST; } sub recurse_dir ($) { my ($dir) = @_; my ($file) = ""; my (@contents) = (); if (!opendir(DIR, $dir)) { error(0, "Could not open directory $dir"); return; } @contents = readdir DIR; closedir DIR; foreach $file (@contents) { if ($file eq "." or $file eq ".." or (-l "$dir/$file")) { next; } if (-d "$dir/$file") { recurse_dir "$dir/$file"; } else { next if (grep { /$file/ } @snap_deprecated_files); copy "$dir/$file", $outdir."$dir/$file"; } } } sub snap_paths { my ($file, $dir, $search, @contents); foreach $file (@_) { # For now do not collect proc ppc64 files for guest. next if ($file =~ "/proc/ppc64/" && $ENV{'platform'} == $ENV{'PLATFORM_POWERKVM_GUEST'}); if (-d $file) { recurse_dir $file; } else { # Check for wildcard (* in last character only) if (substr($file, -1) eq "*") { $dir = substr $file, 0, rindex($file, "/"); $search = substr $file, rindex($file, "/")+1, -1; if (!opendir(DIR, $dir)) { error(0, "Could not open directory $dir"); return; } @contents = readdir DIR; closedir DIR; foreach $file (@contents) { if (substr($file, 0, length($search)) eq $search) { copy "$dir/$file", $outdir."$dir/$file"; } } } else { copy $file, $outdir.$file; } } } } sub snap_commands { my ($path, @junk, @path, $filename, $command, $exit_value); if (!(-d $cmdoutdir)) { if (!mkdir($cmdoutdir, 0644)) { error(0, "Cannot create directory: $cmdoutdir"); return; } } foreach $command (@_) { # Retrieve the name of the binary to run (for output file name) ($path, @junk) = split / /, $command; @path = reverse(split /\//, $path); $filename = shift @path; system("$command > $cmdoutdir/$filename.out 2>&1"); if ($exit_value = $? >> 8) { error(0, "\"$command\" returned $exit_value"); } } } $< == 0 or error(1, "Must be executed as root"); my $perldumpenv='perl -MData::Dumper -e '."'". '\$Data::Dumper::Terse=1;print Dumper(\%ENV);'."'"; eval '%ENV=('.$1.')' if `bash -c " . $PSERIES_PLATFORM; $perldumpenv"` =~ /^\s*\{(.*)\}\s*$/mxs; open(my $input, "<", $distro_file); if (<$input> =~ /Ubuntu/) { print "snap: is not supported on the Ubuntu platform\n"; exit 1; } if ($ENV{'platform'} == $ENV{'PLATFORM_UNKNOWN'} || $ENV{'platform'} == $ENV{'PLATFORM_POWERNV_HOST'}) { print "snap: is not supported on the $ENV{'platform_name'} platform\n"; exit 1; } if (!getopts('atd:ho:v')) { print_usage; exit 1; } if ($opt_h) { print_usage; exit 0; } if ($opt_d) { $outdir = $opt_d; $cmdoutdir = "$opt_d/$cmddir"; } if (-e $outdir) { print "$0: cannot run; $outdir already exists.\n"; exit 2; } if (substr($outdir, -1) eq "/") { $outdir = substr $outdir, 0, -1; } if ($opt_o) { if ($opt_o !~ /.tar/) { print "$0: The filename provided, $opt_o, does not contain .tar;"; print " Using default filename $outfile\n"; } else { $outfile = $opt_o; } } if ($opt_t) { my $host = `hostname`; chomp($host); my @halias = split(/\./, $host); my $time = strftime('%Y%m%d%H%M%S',localtime); my $temp = substr $outfile, 0, rindex($outfile, ".tar"); my $temp1 = substr $outfile, rindex($outfile, ".tar") + 1; $outfile = "$temp-$halias[0]-$time.$temp1"; } if (-e $outfile) { print "$0: cannot run; $outfile already exits.\n"; exit 2; } # Check to see if we need to gather information on IBM Flash Adapter(s). if (glob("/dev/rsxx*")) { $rsxx_exists = 1; } snap_paths(@snap_paths_general); # Check distro if (-e "/etc/SuSE-release") { snap_paths(@snap_paths_general_SuSE); } elsif (-e "/etc/redhat-release") { snap_paths(@snap_paths_general_RedHat); } # Run commands and capture output snap_commands(@snap_commands_general); # Gather detail files if requested (-a option) if ($opt_a) { snap_paths(@snap_paths_detailed); snap_commands(@snap_commands_detailed); } # Gather information regarding IBM Flash Adapter(s) if ($rsxx_exists) { # Verify the rsxx utils are installed. system("rpm -qa | grep rsxx-utils > /dev/null"); if ($? == 0) { snap_commands(@snap_command_rsxx); } else { print "Warning: The rsxx-utils RPM are not installed, ". "unable to gather IBM Flash Adapter information.\n". "\t Run 'yum install rsxx-utils' to install.\n"; } } my ($basefile, $extension) = split /\.tar/, $outfile; my $basedir = substr $outdir, 0, rindex($outdir, "/"); my $compressdir = substr $outdir, rindex($outdir, "/") + 1; system ("tar -cf $basefile.tar --directory=$basedir $compressdir 2>/dev/null"); if ($extension eq ".gz") { system ("gzip -f $basefile.tar"); } elsif ($extension eq "") { } else { $outfile = "$basefile.tar"; print "$0: Unrecognized extension $extension\n"; } # Delete temporary directory system("rm -rf $outdir"); print "output written to $outfile\n"; print "WARNING: archive may contain confidential data and/or cleartext passwords!\n"; exit 0; powerpc-utils-1.2.26/scripts/bootlist0000775000175000017510000003312512527176005014630 00000000000000#! /bin/bash # Copyright (c) 2004 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # bootlist - command to display and/or update the bootlist in nvram. # # author Nathan Fontenot # OFPATHNAME=/usr/sbin/ofpathname NVRAM=/usr/sbin/nvram PSERIES_PLATFORM=$(dirname $0)/pseries_platform # # usage # usage() { echo "Usage: $0 -m {normal|service|both} -o | -r" echo " $0 -m {normal|service|both} [-o | -r] -f " echo " $0 -m {normal|service|both} [-o | -r] " echo "View and update the system boot lists" echo "" echo " -m {normal|service|both}" echo " Specify the boot mode for boolist manipulation" echo " -o Display bootlist entries as logical device names" echo " -r Display bootlist entries as Open Firmware device" echo " path names" echo " -f file Read the boolist device names from file" echo " -?, --help display this help information and exit" echo " a space-separated list of devices, specified as" echo " logical device names or OF device path names," echo " depending on whether the -o or -r option is specified" echo "" echo "Additional optional arguments for ethernet devices:" echo " bserver=" echo " gateway=" echo " client=" echo " speed=, default=auto" echo " duplex=, default=auto" echo "" } # # update_eth_dev # When specifying an ethernet device for the bootlist we need to also get # the additional parameters for ethernet devices (i.e gateway, speed, ...) # # Please NOTE: this routine does depend on global variables # update_eth_dev() { local speed=auto local duplex=auto local bserver=0.0.0.0 local gateway=0.0.0.0 local client=0.0.0.0 local eth_index=$[$ctr] local index=$[$ctr + 1] local found=1 while [[ $found -eq 1 ]]; do found=0 case ${LOGICAL_NAMES[$index]} in speed*) speed=${LOGICAL_NAMES[$index]##*=} found=1 ;; duplex*) duplex=${LOGICAL_NAMES[$index]##*=} found=1 ;; bserver*) bserver=${LOGICAL_NAMES[$index]##*=} found=1 ;; gateway*) gateway=${LOGICAL_NAMES[$index]##*=} found=1 ;; client*) client=${LOGICAL_NAMES[$index]##*=} found=1 ;; esac if [[ $found -eq 1 ]]; then index=$[$index + 1] ctr=$[$ctr + 1] fi done # update the ethernet device OF_DEVPATH[$eth_index]=${OF_DEVPATH[$eth_index]}:speed=$speed,duplex=$duplex,$bserver,,$client,$gateway } # # parse_eth_info # Ethernet read from nvram (possibly) have additional data appended to # them specifying the gateway, speed, ... # # $1 ethernet device name # $2 ethernet device data # parse_eth_info() { local eth_name=$1 local eth_info=${2##*:} echo $eth_name # first the speed local item=${eth_info%%,*} if [[ -n $item ]]; then echo " speed = ${item##*=}" fi # then the duplex eth_info=${eth_info#*,} item=${eth_info%%,*} if [[ -n $item ]]; then echo " duplex = ${item##*=}" fi # then the BOOTP server eth_info=${eth_info#*,} item=${eth_info%%,*} if [[ -n $item ]]; then echo " BOOTP Server: $item" fi # then the Mask eth_info=${eth_info#*,} item=${eth_info%%,*} if [[ -n $item ]]; then echo " Mask: $item" fi # then the client eth_info=${eth_info#*,} item=${eth_info%%,*} if [[ -n $item ]]; then echo " Client: $item" fi # then the Gateway eth_info=${eth_info#*,} item=${eth_info%%,*} if [[ -n $item ]]; then echo " Gateway: $item" fi } # # get_logical_device_name # Translate the provided boot device to its logical device name # # $1 device name to convert # get_logical_device_name() { local devname=$1 local logical_name logical_name=`$OFPATHNAME -l $devname 2>/dev/null` if [[ $? -ne 0 ]]; then echo "" else echo $logical_name fi } # # get_of_device_name # Translate the provided boot device to its OF device name # # $1 device name to convert # get_of_device_name() { local devname=$1 local of_name of_name=`$OFPATHNAME $devname 2>/dev/null` if [[ $? -ne 0 ]]; then echo "" else echo $of_name fi } # # show_bootlist # Retrieve a bootlist from nvram and print its contents # # $1 bootlist to print # show_bootlist() { local devlist=$1 local i for i in `$NVRAM --print-config=${devlist} | sed 's/ /\n/g'`; do if [[ $TRANSLATE_NAMES = "yes" ]]; then name=`get_logical_device_name $i` if [[ -z $name ]]; then echo "Could not translate $i to logical device name" else case $name in eth*) parse_eth_info $name $i ;; *) echo $name ;; esac fi else echo $i fi done } # # Main # . $PSERIES_PLATFORM if [[ $platform != $PLATFORM_PSERIES_LPAR ]]; then echo "bootlist: is not supported on the $platform_name platform" exit 1 fi # make sure we can parse names if [[ ! -a $OFPATHNAME ]]; then echo "no $OFPATHNAME!!!" fi # make sure we can update nvram if [[ ! -a $NVRAM ]]; then echo "no $NVRAM!!!" fi BOOTLIST_MODE=unknown dm_to_part() { local dmp=$1 local dmdev=$2 local sddev=$3 local dmmapper partname=$(cat "/sys/block/$dmp/dm/name" 2>/dev/null | sed 's/[0-9]*$//g') diskname=$(cat "/sys/block/$dmdev/dm/name" 2>/dev/null) delim=${partname##$diskname} dmpmajmin=$(cat "/sys/block/$dmp/dev" 2>/dev/null) dmdevmajmin=$(cat "/sys/block/$dmdev/dev" 2>/dev/null) for dmapper in /dev/mapper/* ; do dmajor=$(stat -L --format="%t" $dmapper 2>/dev/null) dminor=$(stat -L --format="%T" $dmapper 2>/dev/null) dmajmin=$(printf "%d:%d" 0x$dmajor 0x$dminor) if [[ "$dmajmin" = "$dmdevmajmin" ]]; then dmmapper=$dmapper; break; fi done kpartx -p $delim -l $dmmapper | while read kp ; do kpname=${kp%% *} tmajor=$(stat -L --format="%t" /dev/mapper/$kpname 2>/dev/null) tminor=$(stat -L --format="%T" /dev/mapper/$kpname 2>/dev/null) tmajmin=$(printf "%d:%d" 0x$tmajor 0x$tminor) if [[ "$tmajmin" = "$dmpmajmin" ]]; then partstart=${kp##* } for part in `ls -1d /sys/block/$sddev/$sddev*`; do pstart=$(cat $part/start 2>/dev/null) if [[ "$pstart" -eq "$partstart" ]] ; then echo "${part##*/}" return fi done fi done } add_logical() { local DEVNAME=$1 local major minor majmin devno local startctr=$ctr if [[ ! -e $DEVNAME ]]; then DEVNAME=/dev/$DEVNAME fi if [[ ! -e $DEVNAME ]]; then LOGICAL_NAMES[$ctr]=$1 ctr=$[$ctr + 1] return fi major=$(stat -L --format="%t" $DEVNAME 2>/dev/null) minor=$(stat -L --format="%T" $DEVNAME 2>/dev/null) majmin=$(printf "%d:%d" 0x$major 0x$minor) # Look for a matching multipath device for dm in /sys/block/dm*; do dmdev=${dm##*/} devno=$(cat $dm/dev 2>/dev/null) devmaj=${devno%:*} devmin=${devno#*:} if [[ ! -d $dm/slaves ]] ; then # Old kernel for which there is no good way to reliably map # a kpartx device with its parent break; fi if [[ ! -d $dm/dm ]] ; then # Old kernel for which there is no good way to reliably map # a kpartx device with its parent break; fi if [[ "$devno" = "$majmin" ]]; then for slave in $dm/slaves/*; do slavedev=${slave##*/} if [[ "$slavedev" == dm-* ]] ; then for slave2 in $slave/slaves/*; do slavedev2=${slave2##*/} if [[ "$slavedev2" == dm-* ]] ; then # dmdev is an LV on physical multipath partition for slave3 in $slave2/slaves/*; do slavedev3=${slave3##*/} partdev=$(dm_to_part $slavedev $slavedev2 $slavedev3) if [[ ! -z "$partdev" ]] ; then LOGICAL_NAMES[$ctr]=$partdev ctr=$[$ctr + 1] fi done else # /sys/block/dm-2/slave/dm-0/slaves/sdb kp=$(kpartx -l /dev/$slavedev) if [[ -z "$kp" ]] ; then # dmdev is an LV on physical multipath # disk LV->DMDEV->DEV LOGICAL_NAMES[$ctr]=$slavedev2 ctr=$[$ctr + 1] else # dmdev is multipath partition of slave # DMP->DMDEV->DEV partdev=$(dm_to_part $dmdev $slavedev $slavedev2) if [[ ! -z "$partdev" ]] ; then LOGICAL_NAMES[$ctr]=$partdev ctr=$[$ctr + 1] fi fi fi done else # DMDEV is a multipath device on a physical device or # a LV on a disk partition LOGICAL_NAMES[$ctr]=$slavedev ctr=$[$ctr + 1] fi done fi done if [[ "$startctr" = "$ctr" ]] ; then LOGICAL_NAMES[$ctr]=$1 ctr=$[$ctr + 1] fi } # # Parse the command line arguements and put them into two parallel # arrays, one to hold the logical device name and one to hold the # corresponding open firmware device path. # typeset -i ctr=0 while [[ -n $1 ]]; do if [[ $1 = "-o" ]]; then DISPLAY_BOOTLIST=yes TRANSLATE_NAMES=yes elif [[ $1 = "-r" ]]; then DISPLAY_BOOTLIST=yes elif [[ $1 = "-m" ]]; then shift if [[ ! -n $1 ]]; then echo "did not specify \"normal\" or \"service\" mode with -m" >&2 usage exit -1 fi if [[ $1 = "normal" ]]; then BOOTLIST_MODE=boot-device elif [[ $1 = "service" ]]; then BOOTLIST_MODE=diag-device elif [[ $1 = "both" ]]; then BOOTLIST_MODE=$1 else echo "invalid mode specified with -m; must be \"normal\", \"service\" or \"both\"" >&2 usage exit -1 fi elif [[ $1 = "-f" ]]; then # get bootlist names from specified file if [[ ! -a $2 ]]; then echo "file $2 does not exist" >&2 fi for i in `cat $2 2>/dev/null`; do add_logical $i done shift elif [[ $1 = -* ]]; then # catch any illegal flags here usage exit -1 else # add this element to the array add_logical $1 fi shift done if [[ ${BOOTLIST_MODE} = "unknown" ]]; then echo "The boot mode must be specified with the -m option" >&2 usage exit -1 fi # Now we need to convert all of the logical device names to # open firmware device paths. if [[ ${#LOGICAL_NAMES[*]} -ne 0 ]]; then ctr=0 while [[ $ctr -lt ${#LOGICAL_NAMES[*]} ]]; do OF_DEVPATH[$ctr]=`get_logical_device_name ${LOGICAL_NAMES[$ctr]}` if [[ -z ${OF_DEVPATH[$ctr]} ]]; then # See if this is an OF pathname OF_DEVPATH[$ctr]=`get_of_device_name ${LOGICAL_NAMES[$ctr]}` fi if [[ -z ${OF_DEVPATH[$ctr]} ]]; then echo "Device ${LOGICAL_NAMES[$ctr]} does not appear to be valid." >&2 else # See if this is an ethernet adapter. If so, the next entries # may be parameters for the bootlist entry. ethdev=`get_logical_device_name ${OF_DEVPATH[$ctr]}` ethdev=${ethdev%%[0-9]*} if [[ $ethdev = "eth" ]]; then update_eth_dev fi # bootlist entries cannot exceed more than 255 chars if [[ ${#OF_DEVPATH[$ctr]} -gt 255 ]]; then echo "Bootlist entries cannot exceed 255 characters" >&2 echo "${OF_DEVPATH[$ctr]}" >&2 exit -1 fi fi ctr=$[$ctr + 1] done # We cannot have a bootlist with more than five entries if [[ ${#OF_DEVPATH[*]} -gt 5 ]]; then echo "More than five entries cannot be specified in the bootlist" >&2 exit -1 fi # update the bootlist in nvram if [[ $BOOTLIST_MODE = "both" ]]; then $NVRAM --update-config "boot-device=${OF_DEVPATH[*]}" -pcommon if [[ $? -ne 0 ]]; then echo "Could not update service-mode bootlist" >&2 fi $NVRAM --update-config "diag-device=${OF_DEVPATH[*]}" -pcommon if [[ $? -ne 0 ]]; then echo "Could not update normal-mode bootlist" >&2 fi else $NVRAM --update-config "${BOOTLIST_MODE}=${OF_DEVPATH[*]}" -pcommon if [[ $? -ne 0 ]]; then echo "Could not update bootlist!" >&2 fi fi fi # Display the bootlist if desired if [[ $DISPLAY_BOOTLIST = "yes" ]]; then if [[ $BOOTLIST_MODE = "both" ]]; then show_bootlist "boot-device" show_bootlist "diag-device" else show_bootlist $BOOTLIST_MODE fi fi powerpc-utils-1.2.26/scripts/ofpathname0000775000175000017510000010640512542271360015112 00000000000000#! /bin/bash # Copyright (c) 2004 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Author Nathan Fontenot # # ofpathname - This utility provides a mechanism for converting a logical # device name to an open firmware device path, and vice versa. # # TODO: This script doesn't handle floppy drives and token ring devices, # perhaps they should be added in at some point. # OFPATHNAME="ofpathname" VERSION="0.5" FIND=/usr/bin/find CAT=/bin/cat PSERIES_PLATFORM=$(dirname $0)/pseries_platform # Find out what platfrom we are running on. Hopefully this # list will get expanded with time. PLATFORM=$(sed /proc/cpuinfo -ne "s/^machine\t*: \(.*\)/\1/p") case $PLATFORM in EFIKA5K2\ *) PLATFORM=efika ;; esac # Usage statemnet usage() { echo "Usage: $OFPATHNAME [OPTION] DEVICE" echo "Provide logical device names <==> Open Firmware Device Path Conversion" echo "" echo "Optional arguments." echo " -l Convert Open Firmware device pathname to" echo " logical device name." echo " -a Find matching Open Firmware device alias[es]." echo " -q, --quiet Do not report failures, exit quietly" echo " -V, --version Display version information and exit" echo " -h, --help Display this help information and exit" echo "" } show_version() { echo "$OFPATHNAME: Version $VERSION" echo "Written by: Nathan Fontenot " } # # err # Common routine to print error messages for ofpathname. Since most of the # error messages can be generated in multiple places, we put all the text # here to avoid errors in duplicating the messages. # # The first and only parameteris the error message number, all of which # are defined below as ERR_*. # ERR_NO_OFPATH=1 ERR_NO_SYSFS=2 ERR_NO_SYSFS_DEVINFO=3 ERR_NOT_CONFIG=4 ERR_NO_LOGDEV=5 err() { local emsg=$1 if [[ -n $be_quiet ]]; then exit 1 fi case $emsg in 1) echo "$OFPATHNAME: Could not retrieve Open Firmware device path" echo " for logical device \"$DEVNAME_ARG\"." ;; 2) echo "$OFPATHNAME: sysfs (/sys) is needed and does not appear" echo " to be mounted on this system." ;; 3) echo "$OFPATHNAME: Could not find sysfs information for logical" echo " device \"$DEVNAME_ARG\"." ;; 4) echo "$OFPATHANME: Logical device \"$DEVNAME_ARG\" does not appear" echo " to be configured." ;; 5) echo "$OFPATHNAME: Could not retrieve logical device name for" echo " Open Firmware path \"$DEVNAME_ARG\"." esac exit 1 } # is_hbtl # return true if the link is in HBTL (Host:Bus:Target ID:LUN) format is_hbtl() { local ln_name=$1; local tmp="${ln_name//[^:]}" if [[ ${#tmp} = 3 ]]; then echo 1 else echo 0 fi } # # get_link # return the directory path that a link points to. # The only parameter is the link name. # get_link() { local ln_name=$1; echo `ls -l $ln_name 2>/dev/null | awk -F"->" '{print $2}'` } # # get_hbtl # Given a path that ends in an HBTL (Host:Bus:Target ID:LUN), break it apart # into its constituent parts in the global vars HOST, BUS, TARGET and LUN # # #1 path ending in HBTL # get_hbtl() { local hbtl HBTL=${1##*/} hbtl=$HBTL HOST=${hbtl%%:*} hbtl=${hbtl#*:} BUS=${hbtl%%:*} BUS=`echo "ibase=10;obase=16; $BUS" | bc | tr "[:upper:]" "[:lower:]"` hbtl=${hbtl#*:} ID=${hbtl%%:*} ID=`echo "ibase=10;obase=16; $ID" | bc | tr "[:upper:]" "[:lower:]"` LUN=${hbtl#*:} LUN=`echo "ibase=10;obase=16; $LUN" | bc | tr "[:upper:]" "[:lower:]"` } # # get_scsi_disk_no # Given a path that ends in an HBTL, convert the HBTL values into a # virtual disk number (not sure what the real terminology is for it). # To do the conversion, the HBTL (A:B:C:D) is split apart and # calculated as; # no = (0x1000000 | C << 16 | D) # # $1 path ending in HBTL get_scsi_disk_no() { get_hbtl $1 local C D C=$((0x$ID << 16)) D=$((0x$LUN)) local vdiskno vdisk typeset -i vdiskno vdiskno=$((0x1000000 | $C | $D )) vdisk=${vdiskno##-} vdisk=`echo \`bc << END ibase=10 obase=16 $vdisk END\`` local extrazeroes="00000000" echo $vdisk$extrazeroes } # # get_vdisk_no # Given a path that ends in an HBTL, convert the HBTL values into a # virtual disk number (not sure what the real terminology is for it). # To do the conversion, the HBTL (A:B:C:D) is split apart and # calculated as; # no = (0x8000 | B << 8 | C << 5 | D) * 1000000000000 # # $1 path ending in HBTL # get_vdisk_no() { get_hbtl $1 local B C D typeset -i B C D B=$((0x$ID << 8)) C=$((0x$BUS << 5)) D=$((0x$LUN)) local vdiskno vdisk typeset -i vdiskno vdiskno=$((0x8000 | $B | $C | $D )) vdisk=${vdiskno##-} vdisk=`echo \`bc << END ibase=10 obase=16 $vdisk END\`` local extrazeroes="000000000000" echo $vdisk$extrazeroes } # # get_usb_vdisk_no # Given a path that ends in an HBTL, convert the HBTL values into a # virtual disk number (not sure what the real terminology is for it). # To do the conversion, the HBTL (A:B:C:D) is split apart and # calculated as; # no = (0x1000000 | (usb_port << 16) | D); # # $1 path ending in HBTL # get_usb_vdisk_no() { get_hbtl $1 local usb_port=$2 local B B=$((0x$usb_port << 16)) local vdiskno vdisk vdiskno=$((0x1000000 | $B | $LUN )) vdisk=${vdiskno##-} vdisk=$(bc << END ibase=10 obase=16 $vdisk END ) local extrazeroes="00000000" echo $vdisk$extrazeroes } # # get_usb_storage_no # Get usb device storage (port) number which is captured in # devpath file # # $1 starting directory to look for devpath file get_usb_storage_no() { for dir in `$FIND /sys -name $1`; do # Move up until we find one with a devpath link goto_dir $dir "devpath" 0 if [ $? -eq 0 ]; then break; fi done; if [ -f $PWD/devpath ]; then echo `$CAT $PWD/devpath` else err $ERR_NOT_CONFIG fi } # # goto_dir # This looks for a given file in a given directory or any parents of the # given directory. # # $1 starting directory # $2 file to search for # $3 on_exit behavior on error goto_dir() { local start_dir=$1 local fname=$2 local found=0 local on_exit=1 if [[ $# -eq 3 ]]; then on_exit=$3 fi cd $start_dir while [[ $PWD != "/" ]]; do ls $fname >/dev/null 2>&1 if [[ $? -eq 0 ]]; then found=1 break fi cd .. done if [[ $found -eq 0 ]]; then if [[ $on_exit -eq 1 ]]; then err $ERR_NO_SYSFS_DEVINFO else return 1 fi fi } # # find_dir # This looks for a given file in a given directory or any parents of the # given directory. This differs from goto_dir in that we don't actually try # to cd to the directories, we just return the directory name if found. # # $1 starting directory # $2 file to search for # $3 on_exit behavior on error find_dir() { local dir=$1 local fname=$2 while [[ -n $dir ]]; do /bin/ls $dir/$fname >/dev/null 2>&1 if [[ $? -eq 0 ]]; then echo $dir return fi dir=${dir%/*} done } # # is_pata_dev # Check to see if this is a PATA device # is_pata_dev() { local this_dir=$PWD local sysfs_dir local udev_path local udevinfo="/usr/bin/udevinfo" local udevadm="/sbin/udevadm" if [[ -a $udevadm ]]; then udev_path=`$udevadm info --query=path --name=$DEVNAME` elif [[ -a $udevinfo ]]; then udev_path=`$udevinfo -q path -n $DEVNAME` else echo "no" return fi if [[ -z $udev_path ]]; then echo "no" else sysfs_dir=`get_link -f /sys/$udev_path/device` if [[ ! -d $sysfs_dir ]]; then echo "no" else goto_dir $sysfs_dir devspec DEVTYPE=$(cat /proc/device-tree/$(cat $PWD/devspec)/device_type) if [[ $DEVTYPE = "ata" ]]; then echo "yes" else echo "no" fi fi fi cd $this_dir } # # print_aliases # Print the aliases from /proc/device-tree/aliases for the specified device # print_aliases() { dev=$1 local found=0 shopt -s nullglob for i in /proc/device-tree/aliases/*; do if sed -e "s/\x00$//g" $i | grep -qx "$dev" ; then echo ${i##*/} found=1 fi done if [[ $found = "0" ]]; then echo "No aliases found." exit 1 else exit 0 fi } get_slave() { cd /sys/class/*/$1 while [[ -n "`ls slaves 2> /dev/null`" ]]; do cd slaves/*; done $FIND /dev -name "`basename $PWD`" } # # is_net_interface # Check to see if this is a network interface # is_net_interface() { local res res=`$FIND /sys/class/net -name $1` if [[ ${#res} = 0 ]]; then echo "no" else echo "yes" fi } # # logical_to_ofpathname # Conversion for logical device name to an Open Firmware device path # logical_to_ofpathname() { local is_cdrom # follow any links to the real device name while [[ -L $DEVNAME ]]; do DEVNAME=`get_link $DEVNAME` done while [[ -L /dev/$DEVNAME ]]; do DEVNAME=`get_link /dev/$DEVNAME` done DEVICE=${DEVNAME##*/} DEVNODE=${DEVICE%%[0-9]*} # try to determine if this is a cdrom device if [[ ${DEVNAME_ARG##*/} = cdrom ]]; then is_cdrom=yes elif [[ `get_link /dev/cdrom` = /dev/$DEVICE ]]; then is_cdrom=yes else is_cdrom=no fi case $DEVICE in eth*) l2of_ethernet ;; hf*) l2of_hfi ;; sd* | sr*) # PATA devices appear as sd*, but should be converted # using the ide logic is_pata=$(is_pata_dev $DEVNAME) if [[ $is_pata = "yes" ]]; then l2of_ide else l2of_scsi fi ;; hd*) l2of_ide ;; vd*) l2of_vd ;; fd*) echo "no fd support yet" ;; dm-*) DEVNAME=`get_slave $DEVICE` logical_to_ofpathname exit ;; *) # check if the device is a network interface is_net=$(is_net_interface $DEVICE) if [[ $is_net = "yes" ]]; then l2of_ethernet fi ;; esac if [[ -z $OF_PATH ]]; then err $ERR_NO_OFPATH fi if [[ $is_cdrom = yes ]]; then OF_PATH=$OFPATH:1\\ppc\\bootinfo.txt fi if [[ $do_alias = "1" ]]; then print_aliases $OF_PATH else echo $OF_PATH fi } # # l2of_ide # Conversion routine for logical => OF path of ide devices # l2of_ide() { cd /sys/block/$DEVICE local link=`get_link "device"` if [[ -z $link ]]; then err $ERR_NO_SYSFS_DEVINFO fi cd $link # get the device number local devdir=${PWD##/*/} local channelno=${devdir%%\.*} local devno=${devdir##*\.} goto_dir $PWD "devspec" OF_PATH=`$CAT $PWD/devspec` if [[ -z $OF_PATH ]]; then err $ERR_NO_OFPATH fi # PCI ATA controller nodes (found on some Macs) have one child per IDE # channel. case `$CAT "/proc/device-tree/$OF_PATH/device_type"` in pci-ata | pci-ide) OF_PATH=$OF_PATH/@$channelno ;; esac # On Efika, obtained devno "0:0:0:0" doesn't match actual device. # Note: according to vendor, "0,0" means primary master. Secondary # channel is not present, and primary slave is rare enough that we # can reasonably ignore it. if [ "$PLATFORM" = "efika" ] ; then devno=0,0 fi OF_PATH=$OF_PATH/disk@$devno } # # l2of_vd # Conversion routine for logical => OF path of virtio block devices # l2of_vd() { local found=0 # There may be many instances of DEVICE under /sys for dir in `$FIND /sys -name $DEVICE`; do # Move up until we find one with a device link goto_dir $dir "device" 0 if [ $? -eq 0 ]; then found=1; break; fi done; if [ $found -eq 0 ]; then err $ERR_NOT_CONFIG fi local link=`get_link "device"` if [[ -z $link ]]; then err $ERR_NO_SYSFS_DEVINFO fi cd $link goto_dir $PWD "devspec" OF_PATH=`$CAT $PWD/devspec` if [[ -z $OF_PATH ]]; then err $ERR_NO_OFPATH fi } # # l2of_ethernet # Conversion routine for logical => OF path of ethernet devices # l2of_ethernet() { for syspath in `$FIND /sys -name $DEVICE 2> /dev/null`; do if [[ -e $syspath/device/devspec ]]; then OF_PATH=`$CAT $syspath/device/devspec` break fi done if [[ -z $OF_PATH ]]; then err $ERR_NO_OFPATH fi } # # l2of_hfi # Conversion routine for logical => OF path of HFI devices # l2of_hfi() { local hfnum=${DEVICE##hf} local hfpath if [[ $hfnum = "0" || $hfnum = "2" ]]; then hfpath=`$FIND /proc/device-tree -name hfi-ethernet* | sort | head -n 1` elif [[ $hfnum = "1" || $hfnum = "3" ]]; then hfpath=`$FIND /proc/device-tree -name hfi-ethernet* | sort | tail -n 1` else err $ERR_NO_OFPATH fi OF_PATH=${hfpath##/proc/device-tree} } # # int_to_scsilun # Conversion routine for SCSI HBTL LUN => SCSI LUN name # int_to_scsilun() { local lunint=$1 local A B C D A=$(( ($lunint >> 8) & 0xff )) B=$(($lunint & 0xff)) C=$(( ($lunint >> 24) & 0xff )) D=$(( ($lunint >> 16) & 0xff )) local lunstr=$(printf "%02x%02x%02x%02x00000000" $A $B $C $D) lunstr=`echo $lunstr | sed 's/^[0]*//'` echo "$lunstr" } # # scsilun_to_int # Conversion routine for SCSI LUN name => SCSI HBTL LUN # scsilun_to_int() { local lunstr=$1 local A B C D L L=${lunstr/00000000} L=`echo $L | tr "[a-z]" "[A-Z]"` L=`echo "ibase=16;obase=A; $L" | bc` A=$(( ($L >> 8) & 0xff )) B=$(($L & 0xff)) C=$(( ($L >> 24) & 0xff )) D=$(( ($L >> 16) & 0xff )) L=$(( (($A << 24) | ($B << 16) | ($C << 8) | $D) )) echo "$L" } get_fc_scsilun() { local lun=$1 local L L=`echo $lun | tr "[a-z]" "[A-Z]"` L=`echo "ibase=16;obase=A; $L" | bc` local fc_lun=`int_to_scsilun $L` echo "$fc_lun" } get_fc_wwpn() { local start_dir=$1 for f in `$FIND -H $start_dir -maxdepth 2 -name port_name`; do local wwpn=`$CAT $f` break done # strip the leading 0x wwpn=${wwpn:2} echo "$wwpn" } # # l2of_scsi # Converion routine for logical => OF path of scsi devices # l2of_scsi() { local found=0 local devtype # There may be many instances of DEVICE under /sys for dir in `$FIND /sys -name $DEVICE`; do # Move up until we find one with a device link goto_dir $dir "device" 0 if [ $? -eq 0 ]; then found=1; break; fi done; if [ $found -eq 0 ]; then err $ERR_NOT_CONFIG fi # follow the 'device' link local link=`get_link "device"` if [[ -z $link ]]; then # device may not be a link link=device fi get_hbtl $link cd $link # save the name of the current directory, we may need it later... local device_dir=${PWD##/*/} local device_path=$PWD # move up directories until we find one with devspec information goto_dir $PWD "devspec" OF_PATH=`$CAT $PWD/devspec` if [[ -z $OF_PATH ]]; then err $ERR_NO_OFPATH fi local vdev=${OF_PATH%/*} local fc=${OF_PATH%@*} fc=${fc##/*/} if [[ -e /proc/device-tree$OF_PATH/device_type ]]; then devtype=`$CAT /proc/device-tree$OF_PATH/device_type`; if [[ $devtype = "fcp" || $devtype = "scsi-fcp" ]]; then fc="fibre-channel"; fi fi if [[ $fc = "usb" ]]; then local hub_no storage_no disk_no storage_no=`get_usb_storage_no $DEVICE` if [[ $storage_no = *.* ]]; then hub_no=${storage_no%%.*} storage_no=${storage_no##*.} fi disk_no=`get_usb_vdisk_no $device_dir $storage_no` if [[ -z $hub_no ]]; then OF_PATH=$OF_PATH/storage\@$storage_no/disk\@$disk_no else OF_PATH=$OF_PATH/hub\@$hub_no/storage\@$storage_no/disk\@$disk_no fi elif [[ $fc = "fibre-channel" ]]; then local wwpn=`get_fc_wwpn "$device_path/../../fc_remote_ports*"` if [[ ! -e /proc/device-tree$OF_PATH/disk ]]; then for dir in `$FIND /proc/device-tree$OF_PATH -type d`; do if [[ -e $dir/disk ]]; then OF_PATH=${dir##/proc/device-tree} break; fi done fi OF_PATH=$(printf "%s/disk@%s" $OF_PATH $wwpn) if [[ $LUN != "0" ]]; then local fc_lun=`get_fc_scsilun $LUN` OF_PATH=$(printf "%s,%s" $OF_PATH $fc_lun) fi elif [[ $vdev = "/vdevice" ]]; then # get the v-device data local tmp=${OF_PATH//\/vdevice/} local vdevtype=${tmp%@*} if [[ $vdevtype = "/vfc-client" ]]; then local vfc_lun=`get_fc_scsilun $LUN` local wwpn=`get_fc_wwpn "$device_path/../../fc_remote_ports*"` OF_PATH=$(printf "%s/disk@%s,%s" $OF_PATH $wwpn $vfc_lun) else local i vdiskno cd host* cd target* vdiskno=`get_vdisk_no $device_dir` OF_PATH=$OF_PATH/disk\@$vdiskno fi elif [[ -d /proc/device-tree$OF_PATH/sas ]]; then local vendor_id sas_id vendor_id=`od -tx /proc/device-tree/$OF_PATH/vendor-id` vendor_id=`echo $vendor_id | cut -d " " -f 2` if [[ $vendor_id = "00001000" ]]; then local dev_id goto_dir $device_path "sas_end_device*" dev_id=${PWD##*-} sas_id=`cat /sys/class/sas_device/end_device-$dev_id/sas_address` sas_id=${sas_id##0x} OF_PATH=$(printf "%s/sas/disk@%s" $OF_PATH $sas_id) if [[ $LUN != "0" ]]; then local LUNSTR=`int_to_scsilun $LUN` OF_PATH=$(printf "%s,%s" $OF_PATH $LUNSTR) fi else local B T L local fwtype="0" if [[ -e /sys/class/scsi_host/host$HOST/fw_type ]]; then fwtype=`$CAT /sys/class/scsi_host/host$HOST/fw_type` fi if [[ $fwtype = "1" ]]; then goto_dir $device_path "device_id" sas_id=`$CAT $PWD/device_id` sas_id=${sas_id##0x} OF_PATH=$(printf "%s/sas/disk@%s" $OF_PATH $sas_id) if [[ $LUN != "0" ]]; then local LUNSTR=`int_to_scsilun $LUN` OF_PATH=$(printf "%s,%s" $OF_PATH $LUNSTR) fi else B=`echo $BUS | tr "[a-z]" "[A-Z]"` B=`echo "ibase=16;obase=A; $B" | bc` T=`echo $ID | tr "[a-z]" "[A-Z]"` T=`echo "ibase=16;obase=A; $T" | bc` L=`echo $LUN | tr "[a-z]" "[A-Z]"` L=`echo "ibase=16;obase=A; $L" | bc` sas_id=$(( ($B << 16) | ($T << 8) | $L )) OF_PATH=$(printf "%s/sas/disk@%x" $OF_PATH $sas_id) if [[ $LUN != "0" ]]; then OF_PATH=$(printf "%s,%x" $OF_PATH $LUN) fi fi fi else # make sure the "scsi" information is on the end of the path local scsi_name=${OF_PATH##/*/} scsi_name=${scsi_name%%@*} if [[ $scsi_name != "scsi" ]]; then scsi_name="scsi@$BUS" OF_PATH=$OF_PATH/$scsi_name fi local modalias="" goto_dir $device_path "device" if [ $? -eq 0 ]; then modalias=`$CAT $PWD/modalias` fi if [[ $modalias =~ "virtio" ]]; then local diskno diskno=`get_scsi_disk_no $device_dir` OF_PATH=$OF_PATH/disk\@$diskno else OF_PATH=$OF_PATH/sd@$ID,$LUN fi fi } # # ofpathname_to_logical # Conversion for Open Firmware device paths to logical device names # ofpathname_to_logical() { DEVPATH=${DEVNAME%/*} DEVICE=${DEVNAME##/*/} DEVTYPE=${DEVICE%\@*} SAS=${DEVPATH##/*/} FC=${SAS%%\@*} if [[ $do_alias = "1" ]]; then print_aliases $OF_PATH fi if [[ $DEVTYPE = "disk" && $DEVICE != ${DEVICE%:*} ]]; then DEVTYPE=${DEVICE%:*} fi if [[ $DEVTYPE = "disk" && $FC = "v-scsi" ]]; then DEVTYPE="v-scsi" fi if [[ $DEVTYPE = "disk" && $FC = "scsi" ]]; then DEVTYPE="scsi" fi if [[ $DEVTYPE = "disk" && $SAS = "sas" ]]; then DEVTYPE="sas" fi if [[ $DEVTYPE = "disk" && $FC = "vfc-client" ]]; then DEVTYPE="vfc" fi if [[ $DEVTYPE = "disk" && $FC = "fibre-channel" ]]; then DEVTYPE="fc" fi if [[ $DEVTYPE = "disk" && $FC = "QLGC,qlc" ]]; then DEVTYPE="fc" fi if [[ $DEVTYPE = "disk" && $FC = "fp" ]]; then DEVTYPE="fc" fi if [[ $DEVTYPE = "disk" && $FC = "storage" ]]; then local devpath=$DEVPATH DEVPATH=${devpath%/*} DEVTYPE="usb" if [[ $DEVNAME = *hub* ]]; then devpath=$DEVPATH DEVPATH=${devpath%/*} fi fi # Remove any possible cdrom data from DEVICE if [[ ${DEVICE##*,} = "\ppc\bootinfo.txt" || ${DEVICE##*,} = \ppc\bootinfo.txt ]]; then DEVICE=${DEVICE%,*} fi # Remove any possible yaboot suffix from DEVICE if [[ ${DEVICE##*,} = "yaboot" ]]; then DEVICE=${DEVICE%,*} fi case $DEVTYPE in sd* | scsi* ) of2l_scsi ;; sas ) of2l_sas ;; vfc ) of2l_vfc ;; fc ) of2l_fc ;; v-scsi | disk ) of2l_vscsi if [[ -z $LOGICAL_DEVNAME && $DEVTYPE = disk ]]; then of2l_ide fi ;; eth* | l-lan ) of2l_ethernet ;; hfi-ethernet* ) of2l_hfi ;; disk* ) of2l_ide ;; usb ) of2l_usb ;; esac if [[ -z $LOGICAL_DEVNAME ]]; then err $ERR_NO_LOGDEV fi # See if this device is the cdrom if [[ `get_link "/dev/cdrom"` = $LOGICAL_DEVNAME ]]; then LOGICAL_DEVNAME="cdrom" fi echo $LOGICAL_DEVNAME } # # of2l_ide # Conversion routine for OF path => logical name for ide devices # of2l_ide() { local dir for dir in `$FIND /sys/block -name 'hd*'`; do # get devno local devno=${DEVICE##*@} devno=${devno%%:*} cd $dir local link=`get_link "device"` if [[ -n $link ]]; then cd $link # see if this is the correct device local this_devno=${PWD##*\.} if [[ $devno -eq $this_devno ]]; then goto_dir $PWD "devspec" local devspec=`$CAT ./devspec 2>/dev/null` if [[ $devspec = $DEVPATH ]]; then LOGICAL_DEVNAME="${dir##*/}" break fi fi fi done } # # of2l_ethernet # Conversion routine for OF path => logical names of ethernet devices # of2l_ethernet() { local dir # strip off ip info if present local devname=${DEVNAME%%:*} local netdir="/sys/class/net" for dir in `ls $netdir`; do local devdir=`find_dir $netdir/$dir device` if [[ -z $devdir ]]; then continue fi cd $devdir local link=`get_link "device"` if [[ -z $link ]]; then err $ERR_NO_SYSFS_DEVINFO fi cd $link local devspec=`$CAT ./devspec 2>/dev/null` if [[ $devspec = $devname ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi done } # # of2l_hfi # Conversion routine for OF path => logical names of HFI devices # of2l_hfi() { # strip off ip info if present local devname=${DEVNAME%%:*} local hfpath hfpath=`$FIND /proc/device-tree -name hfi-ethernet* | sort | head -n 1` hfpath=${hfpath##/proc/device-tree} if [[ $hfpath = $devname ]] ; then LOGICAL_DEVNAME="hf0" else hfpath=`$FIND /proc/device-tree -name hfi-ethernet* | sort | tail -n 1` hfpath=${hfpath##/proc/device-tree} if [[ $hfpath = $devname ]] ; then LOGICAL_DEVNAME="hf1" else err $ERR_NO_LOGDEV fi fi } # # of2l_usb # Conversion routine for OF path => logical names of usb devices # of2l_usb() { DEV_HBTL_NO=${DEVICE##*\@} local dir for dir in `$FIND /sys/block -name 's[dr]*'`; do # go up to find directory with 'device' link local devdir=`find_dir $dir device` if [[ -z $devdir ]]; then continue fi cd $devdir local link=`get_link "device"` local vdisk_no if [[ -n $link ]]; then local port_no storage_no target target=${link##*/} port_no=`get_usb_storage_no $target` storage_no=${port_no##*.} vdisk_no=`get_usb_vdisk_no $target $storage_no` cd $link if [[ $vdisk_no = $DEV_HBTL_NO ]]; then goto_dir $PWD "devspec" local devspec=`$CAT ./devspec 2>/dev/null` if [[ $devspec = $DEVPATH ]]; then LOGICAL_DEVNAME=${dir##/*/} return fi fi fi done } # # of2l_vscsi # Conversion routine for OF path => logical names of virtual scsi devices # of2l_vscsi() { DEV_HBTL_NO=${DEVICE##*\@} local dir for dir in `$FIND /sys/block -name 's[dr]*'`; do # go up to find directory with 'device' link local devdir=`find_dir $dir device` if [[ -z $devdir ]]; then continue fi cd $devdir local link=`get_link "device"` if [[ -n $link ]]; then local vdiskno=`get_vdisk_no $link` cd $link if [[ $vdiskno = $DEV_HBTL_NO ]]; then goto_dir $PWD "devspec" local devspec=`$CAT ./devspec 2>/dev/null` if [[ $devspec = $DEVPATH ]]; then LOGICAL_DEVNAME=${dir##/*/} return fi fi fi done } # # of2l_scsi # Conversion routine for OF path => logical names of scsi devices # of2l_scsi() { DEV_HBTL_NO=${DEVICE##*\@} DEV_TARGET=${DEVICE##*\@} DEV_TARGET=${DEV_TARGET%%,*} DEV_LUN=${DEVICE##*,} # At this point DEV_LUN may be in the form X:Y, we're only interested # in the X component. DEV_LUN=${DEV_LUN%%:*} local dir for dir in `$FIND /sys/block -name '[sv][dr]*'`; do # go up to find directory with 'device' link local devdir=`find_dir $dir device` if [[ -z $devdir ]]; then continue fi cd $devdir local link=`get_link "device"` if [[ -z $link ]]; then err $ERR_NO_SYSFS_DEVINFO fi local hbtl=`is_hbtl $link` local diskno # Do not call get_hbtl for virtio block devices if [[ $hbtl = 1 ]]; then get_hbtl $link diskno=`get_scsi_disk_no $link` fi cd $link # save the name of the current directory, we may need it later... local device_dir=${PWD##/*/} if [[ $hbtl = 0 || $diskno = $DEV_HBTL_NO || ($ID = $DEV_TARGET && $LUN = $DEV_LUN) ]]; then goto_dir $PWD "devspec" local devspec=`$CAT ./devspec 2>/dev/null` # Handle virtio block devices if [[ $hbtl = 0 && $devspec = $DEVNAME ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi if [[ $devspec = $DEVPATH ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi local scsi_name=${devspec##/*/} scsi_name=${scsi_name%%@*} if [[ $scsi_name != "scsi" ]]; then scsi_name="scsi@$BUS" devspec=$devspec/$scsi_name if [[ $devspec = $DEVPATH ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi fi fi done } # # of2l_sas # Conversion routine for OF path => logical names of sas devices # of2l_sas() { local matchtype dir DEV_NAME=${DEVICE##*\@} DEV_ID=${DEV_NAME%%,*} LUN=${DEV_NAME/$DEV_ID} LUN=${LUN/,/} if [[ ${#LUN} = 0 ]]; then LUN="0" fi lunint=`scsilun_to_int $LUN` PCI_ID=${DEVPATH%%/sas*} vendor_id=`od -tx /proc/device-tree/$PCI_ID/vendor-id` vendor_id=`echo $vendor_id | cut -d " " -f 2` if [[ $vendor_id = "00001000" ]]; then matchtype="libsas" else matchtype="ipr32" fi for dir in `$FIND /sys/class/scsi_host -maxdepth 1 -name 'host*'`; do cd $dir local link=`get_link "device"` cd $link cd .. local devspec=`$CAT ./devspec 2>/dev/null` if [[ $devspec = $PCI_ID ]]; then # check for ipr64 if [[ -e $dir/fw_type ]]; then local fwtype=`$CAT $dir/fw_type` if [[ $fwtype = "1" ]]; then matchtype="ipr64" break fi fi break fi done for dir in `$FIND /sys/block -name 's[dr]*'`; do # go up to find directory with 'device' link local devdir=`find_dir $dir device` if [[ -z $devdir ]]; then continue fi cd $devdir local link=`get_link "device"` if [[ -z $link ]]; then err $ERR_NO_SYSFS_DEVINFO fi get_hbtl $link cd $link # save the name of the current directory, we may need it later... local device_dir=$PWD local B T L B=`echo $BUS | tr "[a-z]" "[A-Z]"` B=`echo "ibase=16;obase=A; $B" | bc` T=`echo $ID | tr "[a-z]" "[A-Z]"` T=`echo "ibase=16;obase=A; $T" | bc` L=`echo $LUN | tr "[a-z]" "[A-Z]"` L=`echo "ibase=16;obase=A; $L" | bc` if [[ $matchtype = "ipr32" ]]; then local sas_id=$((($B << 16) | ($T << 8) | $L)) sas_id=`echo "ibase=A;obase=16; $sas_id" | bc` sas_id=`echo $sas_id | tr "[A-Z]" "[a-z]"` if [[ $sas_id = $DEV_ID ]]; then goto_dir $PWD "devspec" local devspec=`$CAT ./devspec 2>/dev/null` if [[ $devspec/sas = $DEVPATH ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi fi elif [[ $matchtype = "ipr64" ]]; then if [[ -e $devdir/device/device_id ]]; then local deviceid=`$CAT $devdir/device/device_id` deviceid=${deviceid##0x} if [[ $deviceid != $DEV_ID ]]; then continue fi if [[ $L = $lunint ]]; then goto_dir $PWD "devspec" local devspec=`$CAT ./devspec 2>/dev/null` if [[ $devspec/sas = $DEVPATH ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi fi fi elif [[ $matchtype = "libsas" ]]; then local dev_id goto_dir $device_dir "sas_end_device*" 0 dev_id=${PWD##*-} if [[ ! -e /sys/class/sas_device/end_device-$dev_id/sas_address ]]; then continue fi sas_id=`cat /sys/class/sas_device/end_device-$dev_id/sas_address` sas_id=${sas_id##0x} if [[ $sas_id != $DEV_ID ]]; then continue fi if [[ $L = $lunint ]]; then goto_dir $PWD "devspec" local devspec=`$CAT ./devspec 2>/dev/null` if [[ $devspec/sas = $DEVPATH ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi fi else err $ERR_NO_LOGDEV fi done } # # of2l_vfc # Conversion routine for OF path => logical names of vFC devices # of2l_vfc() { DEV_ID=${DEVICE##*\@} OF_WWPN=${DEV_ID%%,*} OF_LUN=${DEV_ID##$OF_WWPN} OF_LUN=${OF_LUN#,} OF_LUN=`echo $OF_LUN | sed 's/^[0]*//'` local dir for dir in `$FIND /sys/block -name 's[dr]*'`; do # go up to find directory with 'device' link local devdir=`find_dir $dir device` if [[ -z $devdir ]]; then continue fi cd $devdir local link=`get_link "device"` if [[ -z $link ]]; then continue fi get_hbtl $link cd $link link=$PWD local device_dir=${PWD##/*/} goto_dir $PWD "devspec" OF_PATH=`$CAT $PWD/devspec` if [[ -z $OF_PATH ]]; then err $ERR_NO_LOGDEV fi local vdev=${OF_PATH%/*} local tmp=${OF_PATH//\/vdevice/} local vdevtype=${tmp%@*} if [[ $vdevtype != "/vfc-client" ]]; then continue fi local vfc_lun=`get_fc_scsilun $LUN` local wwpn=`get_fc_wwpn "$link/../../fc_remote_ports*"` if [[ $vfc_lun = $OF_LUN && $wwpn = $OF_WWPN ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi done } # # of2l_fc # Conversion routine for OF path => logical names of FC devices # of2l_fc() { DEV_ID=${DEVICE##*\@} OF_WWPN=${DEV_ID%%,*} OF_LUN=${DEV_ID/$OF_WWPN} OF_LUN=${OF_LUN/,/} if [[ ${#OF_LUN} = 0 ]]; then OF_LUN="0" fi lunint=`scsilun_to_int $OF_LUN` local dir for dir in `$FIND /sys/block -name 's[dr]*'`; do # go up to find directory with 'device' link local devdir=`find_dir $dir device` if [[ -z $devdir ]]; then continue fi cd $devdir local link=`get_link "device"` if [[ -z $link ]]; then continue fi get_hbtl $link cd $link link=$PWD # find device_path, not all dirs will have a fc_remote_ports goto_dir $PWD "fc_remote_ports*" 0 if [[ $? -eq 1 ]]; then continue fi device_path=$PWD cd $link local device_dir=${PWD##/*/} goto_dir $PWD "devspec" OF_PATH=`$CAT devspec` if [[ -z $OF_PATH ]]; then err $ERR_NO_LOGDEV fi local wwpn=`get_fc_wwpn "$device_path/fc_remote_ports*"` if [[ $wwpn = $OF_WWPN ]]; then local L L=`echo $LUN | tr "[a-z]" "[A-Z]"` L=`echo "ibase=16;obase=A; $L" | bc` if [[ $L = $lunint ]]; then LOGICAL_DEVNAME="${dir##*/}" return fi fi done } # # Main # . $PSERIES_PLATFORM if [[ $platform = $PLATFORM_POWERNV ]]; then echo "$OFPATHNAME: is not supported on the $platform_name platform" exit 1 fi if [[ "$#" -eq 0 ]]; then usage exit 0 fi # default: convert logical => OFpath do_of2l=0 # default: do not do alias lookups do_alias=0 getopt -o "l:Vqh" -l "help,version,quiet" $@ > /dev/null 2>&1 while [[ -n $1 ]]; do case "$1" in -a) do_alias=1 ;; -l) do_of2l=1 DEVNAME_ARG=$2 shift ;; -V | --version) show_version exit 0 ;; -q | --quiet) be_quiet=1 ;; -h | --help) usage exit 0 ;; *) DEVNAME_ARG=$1 ;; esac shift done DEVNAME=$DEVNAME_ARG # double check device name if [[ -z $DEVNAME ]]; then usage exit 1 fi # We need sysfs if [[ ! -d "/sys" ]]; then err $ERR_NO_SYSFS exit 1 fi if [[ $do_of2l = "0" ]]; then # logical devname => OF pathname logical_to_ofpathname else # OF pathnmae => logical devname ofpathname_to_logical fi exit 0 powerpc-utils-1.2.26/scripts/lsdevinfo0000775000175000017510000003644712527176005014774 00000000000000#! /bin/bash # Copyright (c) 2004 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Author Santiago Leon # # lsdevinfo - This utility provides the HMC or IVM with name information for # virtual devices so they can be matched against the VIOS names. # # TODO: Show more device info # (currently only the essential information is displayed) # Show MPIO devices # LSDEVINFO="lsdevinfo" VERSION="0.1" OFPATHNAME="/usr/sbin/ofpathname" CAT="/bin/cat" LS="/bin/ls" GREP="/bin/grep" SED="/bin/sed" TR="/usr/bin/tr" OD="/usr/bin/od" CUT="/usr/bin/cut" PSERIES_PLATFORM=$(dirname $0)/pseries_platform # Usage statemnet usage() { echo "Usage: $LSDEVINFO [-q criteria] [-F format] [-R] [-c] [-h]" echo "Provide information on Virtual devices" echo "" echo "Optional arguments." echo " -q criteria Specifies a criteria to select which devices are" echo " to be displayed." echo " -F format Specifies the set of attributes to be displayed." echo " -R Recursively display children of selected devices" echo " -c Display output as a comma separated list for" echo " each device." echo " -V Display version information and exit" echo " -h Display this help information and exit" echo "" } show_version() { echo "$LSDEVINFO: Version $VERSION" echo "Written by: Santiago Leon " } # check_criteria # Modifies $show if the the attribute in the first parameter matches the # criteria from the command line. # The operands (=, !=, and LIKE) are defined the the lsdevinfo spec. # check_criteria() { attr=$1 attr_val=${!attr} if [[ $criteria =~ "!=" ]] ; then # Pull out the operands from the criteria (everything to the left of # the operand, and everything on the right of the operand) crit_opd1=$(echo $criteria | $SED -e "s/[ ]*!=.*//") crit_opd2=$(echo $criteria | $SED -e "s/.*!=[ ]*//") # Perfom the comparison of the attribute and its value if [[ $crit_opd1 == $attr && $crit_opd2 != $attr_val ]]; then show=1 fi elif [[ $criteria =~ "=" ]]; then crit_opd1=$(echo $criteria | $SED -e "s/[ ]*=.*//") crit_opd2=$(echo $criteria | $SED -e "s/.*=[ ]*//") if [[ $crit_opd1 == $attr && $crit_opd2 == $attr_val ]]; then show=1 fi elif [[ $criteria =~ " LIKE " ]]; then crit_opd1=$(echo $criteria | $SED -e "s/[ ]*LIKE.*//") crit_opd2=$(echo $criteria | $SED -e "s/.*LIKE[ ]*//") if [[ $crit_opd1 == $attr && $attr_val =~ $crit_opd2 ]]; then show=1 fi else echo "Criteria must have =, !=, or LIKE operand. Exiting." exit 1 fi } # print_attr # Prints the attribute in the first parameter if the name of the attribute is # in the argument of the -F command line parameter. # print_attr () { attr=$1 attr_val=${!attr} if [[ $format == "" || $format =~ $attr ]]; then echo -ne $separator$begin$attr=\"$attr_val\" fi } # # Main # # default: CR separated list comma_sep=0 # default: non recursive recursive=0 # default: display all devices criteria="" # default: display all attributes format="" . $PSERIES_PLATFORM if [[ $platform != $PLATFORM_PSERIES_LPAR ]]; then echo "$LSDEVINFO: is not supported on the $platform_name platform" exit 1 fi while getopts "cRq:F:Vh" flag ; do case "$flag" in c) comma_sep=1;; R) recursive=1;; q) criteria=$OPTARG;; F) format=$OPTARG;; V) show_version exit 0 ;; h) usage exit 0 ;; \?) usage exit 1 ;; :) echo "Option -$OPTARG requires an argument." exit 1 ;; esac done # Criteria can't have conjunctions (by the spec) if [[ $criteria =~ " AND " ]] ; then echo "AND conjunction not supported. Exiting" exit 1 fi # Fill variables for the two display formats (regular and comma-separated) so # we can print the output in a single place. if [[ $comma_sep -eq 0 ]]; then dev_begin="device:\n" separator="\n" begin="\t" dev_end="\n\n" path_begin="\n\npath:\n\tparent=" path_end="" else dev_begin="" separator="," dev_end="\n" path_begin=",path=(parent=" path_end=")" fi show_eth () { # if there is a criteria in the command line, check if this device matches if [[ $criteria != "" ]] ; then show=0 check_criteria "name" check_criteria "physloc" check_criteria "uniquetype" check_criteria "class" check_criteria "subclass" check_criteria "type" check_criteria "prefix" check_criteria "driver" check_criteria "status" fi # print the info only if the device matches the criteria if [[ $show -ne 0 ]]; then # the name attribute is always printed echo -ne $dev_begin$begin"name="\"$name\" print_attr "uniquetype" print_attr "class" print_attr "subclass" print_attr "type" print_attr "prefix" print_attr "driver" print_attr "status" # if there is no format in the command line or it contains "path", then # print the path. Doesn't use print_attr because all of the fields in # the path attribute should be printed. if [[ $format == "" || $format =~ "path" ]]; then echo -ne $path_begin\"$parent\" echo -ne $separator$begin"physloc="\"$physloc\" echo -ne $separator$begin"connection="\"$connection\" echo -ne $path_end fi # done with this device echo -ne $dev_end fi } # Look at every ibmveth (Virtual Ethernet) device for dev in $($LS -d /proc/device-tree/vdevice/l-lan* 2> /dev/null); do # use ofpathname to get the device name (i.e. eth0) name=$($OFPATHNAME -l $(echo $dev | $SED -e "s/\/proc\/device-tree//")) connection=$(echo $dev | $SED -e "s/\/proc\/device-tree\/vdevice\/l-lan@//") parent="vio" # get the physical location physloc=$($CAT $dev/ibm,loc-code) uniquetype="adapter/vdevice/IBM,l-lan" class="adapter" subclass="vdevice" type="IBM,l-lan" prefix="eth" driver="ibmveth" status=1 show=1 show_eth done # Look for PCI ethernet devices for pci_dev in $($LS -d /proc/device-tree/pci* 2> /dev/null); do for dev in $($LS -d $pci_dev/ethernet* 2> /dev/null); do # use ofpathname to get the device name (i.e. eth0) name=$($OFPATHNAME -l $(echo $dev | $SED -e "s/\/proc\/device-tree//")) connection=$(echo $pci_dev | $SED -e "s/\/proc\/device-tree\/pci@//") parent="pci" # get the physical location physloc=$($CAT $dev/ibm,loc-code) type="$($OD -t x2 $dev/vendor-id $dev/device-id | $CUT -f3,5 -d ' ' -s --output-delimiter='')" uniquetype="adapter/pci/$type" class="adapter" subclass="pci" prefix="eth" driver=$($LS -l /sys/class/net/$name/device/driver | $SED -e "s/^.*\///") status=1 show=1 show_eth done done # Look at every ibmvscsi (Virtual SCSI) device for dev in $($LS -d /proc/device-tree/vdevice/v-scsi* 2> /dev/null) ; do # pull the physical location physloc=$(cat $dev/ibm,loc-code) hostphysloc=$physloc connection=$(echo $dev | $SED -e "s/\/proc\/device-tree\/vdevice\/v-scsi@//") # find the slot so it can be used in sysfs slot=$(echo $dev | $SED -e "s/\/proc\/device-tree\/vdevice\/v-scsi@//") # there is only one host per device, assign it to the path's name for host in $($LS -d /sys/devices/vio/$slot/host*) ; do parent=$(echo $host | $SED -e "s/.*\///") name=$parent uniquetype="adapter/vdevice/IBM,v-scsi" class="adapter" subclass="vdevice" type="IBM,v-scsi" prefix="host" driver="ibmvscsic" host=$($LS -d /sys/devices/vio/$slot/host*/) if [[ -d $host/scsi_host ]]; then scsihost=$($LS -d $host/scsi_host/host*/) else scsihost=$($LS -d $host/scsi_host*/) fi if [[ $(cat $scsihost/state) == "running" ]] ; then status=1 else status=0 fi show=1 # if there is a criteria in the command line, check if this # device matches if [[ $criteria != "" ]] ; then show=0 check_criteria "name" check_criteria "physloc" check_criteria "status" check_criteria "uniquetype" check_criteria "class" check_criteria "subclass" check_criteria "type" check_criteria "prefix" check_criteria "driver" fi if [[ $show -ne 0 ]]; then # the name attribute is always printed echo -ne $dev_begin$begin"name="\"$name\" print_attr "uniquetype" print_attr "class" print_attr "subclass" print_attr "type" print_attr "prefix" print_attr "driver" print_attr "status" # print the path, see note for ibmveth above if [[ $format == "" || $format =~ "path" ]]; then echo -ne $path_begin"\"vio\"" echo -ne $separator$begin"connection="\"$connection\" echo -ne $separator$begin"physloc="\"$physloc\" echo -ne $path_end fi # done with this target echo -ne $dev_end fi # loop through the targets for this host. for t in $($LS -d $host/target*); do target=$(echo $($LS -d $t/$($LS $t | $GREP -v uevent | $GREP -v power | $GREP -v subsystem))) if [[ ! -d $target/block ]]; then name=$(echo $($LS -d $target/block*) | $SED -e "s/.*://") else name=$($LS $target/block) fi conn=$($OFPATHNAME /dev/$name 2> /dev/null | $SED -e "s/.*disk@//") connection=${conn:0:12} uniquetype="disk/vscsi/vdisk" class="disk" subclass="vscsi" type="vdisk" physloc=$hostphysloc"-L"$conn if [[ $(cat $target/state) == "running" ]] ; then status=1 else status=0 fi # if there is a criteria in the command line, we are recursive and # the parent passed criteria, show the device if [[ $criteria != "" && $show -eq 1 && $recursive -eq 1 ]]; then show=1 elif [[ $criteria != "" ]] ; then # if there is a criteria in the command line, check if this # device matches show=0 check_criteria "name" check_criteria "status" check_criteria "physloc" check_criteria "parent" check_criteria "uniquetype" check_criteria "class" check_criteria "subclass" check_criteria "type" else show=1 fi # print the info only if the device matches the criteria if [[ $show -ne 0 ]]; then # the name attribute is always printed echo -ne $dev_begin$begin"name="\"$name\" print_attr "uniquetype" print_attr "class" print_attr "subclass" print_attr "type" print_attr "status" # print the path, see note for ibmveth above if [[ $format == "" || $format =~ "path" ]]; then echo -ne $path_begin\"$parent\" echo -ne $separator$begin"connection="\"$connection\" echo -ne $separator$begin"physloc="\"$physloc\" echo -ne $separator$begin"path_id="\""0"\" echo -ne $separator$begin"path_status="\"$status\" echo -ne $path_end fi # done with this target echo -ne $dev_end fi done done done # Look at every ibmvfc (Virtual FibreChannel) device for dev in $($LS -d /proc/device-tree/vdevice/vfc-client* 2> /dev/null) ; do # pull the physical location physloc=$(cat $dev/ibm,loc-code) connection=$(echo $dev | $SED -e "s/\/proc\/device-tree\/vdevice\/vfc-client@//") hostphysloc=$physloc # find the slot so it can be used in sysfs slot=$(echo $dev | $SED -e "s/\/proc\/device-tree\/vdevice\/vfc-client@//") # there is only one host per device, assign it to the path's name for host in $($LS -d /sys/devices/vio/$slot/host*) ; do parent=$(echo $host | $SED -e "s/.*\///") name=$parent uniquetype="adapter/vdevice/IBM,vfc-client" class="adapter" subclass="vdevice" type="IBM,vfc-client" prefix="host" driver="ibmvfc" host=$($LS -d /sys/devices/vio/$slot/host*/) if [[ -d $host/scsi_host ]]; then scsihost=$($LS -d $host/scsi_host/host*/) else scsihost=$($LS -d $host/scsi_host*/) fi if [[ $(cat $scsihost/state) == "running" ]] ; then status=1 else status=0 fi show=1 # if there is a criteria in the command line, check if this # device matches if [[ $criteria != "" ]] ; then show=0 check_criteria "name" check_criteria "physloc" check_criteria "status" check_criteria "uniquetype" check_criteria "class" check_criteria "subclass" check_criteria "type" check_criteria "prefix" check_criteria "driver" fi if [[ $show -ne 0 ]]; then # the name attribute is always printed echo -ne $dev_begin$begin"name="\"$name\" print_attr "uniquetype" print_attr "class" print_attr "subclass" print_attr "type" print_attr "prefix" print_attr "driver" print_attr "status" # print the path, see note for ibmveth above if [[ $format == "" || $format =~ "path" ]]; then echo -ne $path_begin"\"vio\"" echo -ne $separator$begin"connection="\"$connection\" echo -ne $separator$begin"physloc="\"$physloc\" echo -ne $path_end fi # done with this target echo -ne $dev_end fi # As opposed to ibmvscsi, there are multiple rports in each host for rport in $($LS -d $host/rport*); do # in ibmvfc there are two layers of directories before getting to # the targets for t in $($LS -d $rport/target*); do for target in $($LS $t | $GREP "[0-9]*:[0-9]*:[0-9]*:[0-9]*"); do if [[ ! -d $t/$target/block ]]; then name=$(echo $($LS -d $t/$target/block*) | $SED -e "s/.*://") else name=$($LS $t/$target/block) fi connection=$($OFPATHNAME /dev/$name 2> /dev/null | $SED -e "s/.*disk@//") physloc=$hostphysloc"-W"$(echo $connection | $TR "[:lower:]" "[:upper:]" | $SED -e "s/,/-L/") uniquetype="disk/fcp/disk" class="disk" subclass="fcp" type="disk" if [[ $(cat $t/$target/state) == "running" ]] ; then status=1 else status=0 fi # if there is a criteria in the command line, we are recursive and # the parent passed criteria, show the device if [[ $criteria != "" && $show -eq 1 && $recursive -eq 1 ]]; then show=1 elif [[ $criteria != "" ]] ; then # if there is a criteria in the command line, check if this # device matches show=0 check_criteria "name" check_criteria "physloc" check_criteria "status" check_criteria "parent" check_criteria "uniquetype" check_criteria "class" check_criteria "subclass" check_criteria "type" else show=1 fi # print the info only if the device matches the criteria if [[ $show -ne 0 ]]; then # the name attribute is always printed echo -ne $dev_begin$begin"name="\"$name\" print_attr "uniquetype" print_attr "class" print_attr "subclass" print_attr "type" print_attr "status" # print the path, see note for ibmveth above if [[ $format == "" || $format =~ "path" ]]; then echo -ne $path_begin\"$parent\" echo -ne $separator$begin"connection="\"$connection\" echo -ne $separator$begin"physloc="\"$physloc\" echo -ne $separator$begin"path_id="\""0"\" echo -ne $separator$begin"path_status="\"$status\" echo -ne $path_end fi # done with this device echo -ne $dev_end fi done done done done done exit 0 # end powerpc-utils-1.2.26/scripts/ls-veth0000664000175000017510000000310012527176005014336 00000000000000#! /bin/bash # Copyright (c) 2010 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Author Brian King # # ls-veth - This utility provides the HMC or IVM with name information for # virtual ethernet devices # LSVETH="ls-veth" VERSION="0.1" OFPATHNAME="/usr/sbin/ofpathname" CAT="/bin/cat" LS="/bin/ls" SED="/bin/sed" PSERIES_PLATFORM=$(dirname $0)/pseries_platform usage() { echo "Usage: $LSVETH " echo "Provide information on Virtual Ethernet devices" echo "" echo "Optional arguments." echo " -V Display version information and exit" echo " -h Display this help information and exit" echo "" } show_version() { echo "$LSVETH: Version $VERSION" echo "Written by: Brian King " } . $PSERIES_PLATFORM if [[ $platform != $PLATFORM_PSERIES_LPAR ]]; then echo "$LSVETH: is not supported on the $platform_name platform" exit 1 fi while getopts ":Vh" flag ; do case "$flag" in V) show_version exit 0 ;; h) usage exit 0 ;; \?) usage exit 1 ;; esac done # Look at every ibmveth (Virtual Ethernet) device for dev in $($LS -d /proc/device-tree/vdevice/l-lan* 2> /dev/null); do # use ofpathname to get the device name (i.e. eth0) name=$($OFPATHNAME -l $(echo $dev | $SED -e "s/\/proc\/device-tree//")) # get the physical location physloc=$($CAT $dev/ibm,loc-code) echo "$name $physloc" done exit 0 # end powerpc-utils-1.2.26/scripts/ls-vscsi0000664000175000017510000000326212527176005014530 00000000000000#! /bin/bash # Copyright (c) 2010 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Author Brian King # # ls-vscsi - This utility provides the HMC or IVM with name information for # virtual scsi devices # LSVSCSI="ls-vscsi" VERSION="0.1" CAT="/bin/cat" LS="/bin/ls" SED="/bin/sed" PSERIES_PLATFORM=$(dirname $0)/pseries_platform usage() { echo "Usage: $LSVSCSI" echo "Provide information on Virtual devices" echo "" echo "Optional arguments." echo " -V Display version information and exit" echo " -h Display this help information and exit" echo "" } show_version() { echo "$LSVSCSI: Version $VERSION" echo "Written by: Brian King " } . $PSERIES_PLATFORM if [[ $platform != $PLATFORM_PSERIES_LPAR ]]; then echo "$LSVSCSI: is not supported on the $platform_name platform" exit 1 fi while getopts ":Vh" flag ; do case "$flag" in V) show_version exit 0 ;; h) usage exit 0 ;; \?) usage exit 1 ;; esac done # Look at every ibmvscsi (Virtual SCSI) device for dev in $($LS -d /proc/device-tree/vdevice/v-scsi* 2> /dev/null) ; do # pull the physical location physloc=$($CAT $dev/ibm,loc-code) # find the slot so it can be used in sysfs slot=$(echo $dev | $SED -e "s/\/proc\/device-tree\/vdevice\/v-scsi@//") # there is only one host per device, assign it to the path's name for host in $($LS -d /sys/devices/vio/$slot/host*) ; do name=$(echo $host | $SED -e "s/.*\///") echo "$name $physloc" done done exit 0 # end powerpc-utils-1.2.26/scripts/ls-vdev0000664000175000017510000000407712527176005014352 00000000000000#! /bin/bash # Copyright (c) 2010 International Business Machines # Common Public License Version 1.0 (see COPYRIGHT) # # Author Brian King # # ls-vdev - This utility provides the HMC or IVM with name information for # virtual scsi adapters and devices # LSVDEV="ls-vdev" VERSION="0.1" LS="/bin/ls" GREP="/bin/grep" SED="/bin/sed" PSERIES_PLATFORM=$(dirname $0)/pseries_platform usage() { echo "Usage: $LSVDEV" echo "Provide information on Virtual SCSI adapters and devices" echo "" echo "Optional arguments." echo " -V Display version information and exit" echo " -h Display this help information and exit" echo "" } show_version() { echo "$LSVDEV: Version $VERSION" echo "Written by: Brian King " } . $PSERIES_PLATFORM if [[ $platform != $PLATFORM_PSERIES_LPAR ]]; then echo "$LSVDEV: is not supported on the $platform_name platform" exit 1 fi while getopts ":Vh" flag ; do case "$flag" in V) show_version exit 0 ;; h) usage exit 0 ;; \?) usage exit 1 ;; esac done # Look at every ibmvscsi (Virtual SCSI) device for dev in $($LS -d /proc/device-tree/vdevice/v-scsi* 2> /dev/null) ; do # find the slot so it can be used in sysfs slot=$(echo $dev | $SED -e "s/\/proc\/device-tree\/vdevice\/v-scsi@//") # there is only one host per device, assign it to the path's name for host in $($LS -d /sys/devices/vio/$slot/host* 2> /dev/null) ; do parent=$(echo $host | $SED -e "s/.*\///") host=$($LS -d /sys/devices/vio/$slot/host*/) # loop through the targets for this host. for t in $($LS -d $host/target* 2> /dev/null); do target=$(echo $($LS -d $t/$($LS $t | $GREP -v uevent | $GREP -v power | $GREP -v subsystem))) if [[ ! -d $target/block ]]; then name=$(echo $($LS -d $target/block*) | $SED -e "s/.*://") else name=$($LS $target/block) fi echo "$parent $name" done done done exit 0 # end powerpc-utils-1.2.26/scripts/pseries_platform0000664000175000017510000000125212542271360016335 00000000000000#!/bin/sh SOURCE_FILE="pseries_platform" PLATFORM_FILE=/proc/cpuinfo export PLATFORM_UNKNOWN=0 export PLATFORM_POWERNV=1 export PLATFORM_POWERKVM_GUEST=2 export PLATFORM_PSERIES_LPAR=3 export platform_name="Unknown" export platform=$PLATFORM_UNKNOWN if grep -q "PowerNV" $PLATFORM_FILE; then platform_name="PowerNV Host" platform=$PLATFORM_POWERNV elif grep -q "IBM pSeries (emulated by qemu)" $PLATFORM_FILE; then platform_name="Power KVM pSeries Guest" platform=$PLATFORM_POWERKVM_GUEST elif grep -q "pSeries" $PLATFORM_FILE; then platform_name="PowerVM pSeries LPAR" platform=$PLATFORM_PSERIES_LPAR fi if [ $SOURCE_FILE = `basename $0` ]; then echo $platform_name fi powerpc-utils-1.2.26/src/0000775000175000017510000000000012542271540012214 500000000000000powerpc-utils-1.2.26/src/common/0000775000175000017510000000000012542271540013504 500000000000000powerpc-utils-1.2.26/src/common/pseries_platform.c0000664000175000017510000000203412542271360017145 00000000000000/** * @file platform.c * * Copyright (C) 2014 IBM Corporation * See 'COPYRIGHT' for License of this code * * @author Aruna Balakrishnaiah */ #include #include #include "pseries_platform.h" #define LENGTH 512 const char *power_platform_name[] = { "Unknown", "PowerNV", "Power KVM pSeries Guest", "PowerVM pSeries LPAR", /* Add new platforms name here */ }; const char *platform_name; int get_platform(void) { int rc = PLATFORM_UNKNOWN; FILE *fp; char line[LENGTH]; if((fp = fopen(PLATFORM_FILE, "r")) == NULL) return rc; while (fgets(line, LENGTH, fp)) { if (strstr(line, "PowerNV")) { rc = PLATFORM_POWERNV; break; } else if (strstr(line, "IBM pSeries (emulated by qemu)")) { rc = PLATFORM_POWERKVM_GUEST; break; } else if (strstr(line, "pSeries")) { rc = PLATFORM_PSERIES_LPAR; /* catch model for PowerNV guest */ continue; } } platform_name = power_platform_name[rc]; fclose(fp); return rc; } powerpc-utils-1.2.26/src/common/pseries_platform.h0000664000175000017510000000061012542271360017150 00000000000000/** * Copyright (C) 2014 IBM Corporation * See 'COPYRIGHT' for License of this code. */ #ifndef PLATFORM_H #define PLARFORM_H #define PLATFORM_FILE "/proc/cpuinfo" enum { PLATFORM_UNKNOWN = 0, PLATFORM_POWERNV, PLATFORM_POWERKVM_GUEST, PLATFORM_PSERIES_LPAR, /* Add new platforms here */ PLATFORM_MAX, }; extern const char *platform_name; extern int get_platform(void); #endif powerpc-utils-1.2.26/src/common/librtas_error.c0000664000175000017510000000362512527176005016452 00000000000000/** * @file librtas_error.c * @brief Common librtas_error routine for powerpc-utils-papr commands * * Copyright (c) 2004 International Business Machines * Common Public License Version 1.0 (see COPYRIGHT) * * @author Nathan Fontenot */ #include #include /** * librtas_error * @brief check for librtas specific return codes * * This will check the erro value for a librtas specific return code * and fill in the buffer with the appropraite error message * * @param error return code from librtas * @param buf buffer to fill with error string * @param size size of "buffer" */ void librtas_error(int error, char *buf, size_t size) { switch (error) { case RTAS_KERNEL_INT: snprintf(buf, size, "No kernel interface to firmware"); break; case RTAS_KERNEL_IMP: snprintf(buf, size, "No kernel implementation of function"); break; case RTAS_PERM: snprintf(buf, size, "Non-root caller"); break; case RTAS_NO_MEM: snprintf(buf, size, "Out of heap memory"); break; case RTAS_NO_LOWMEM: snprintf(buf, size, "Kernel out of low memory"); break; case RTAS_FREE_ERR: snprintf(buf, size, "Attempt to free nonexistant RMO buffer"); break; case RTAS_TIMEOUT: snprintf(buf, size, "RTAS delay exceeded specified timeout"); break; case RTAS_IO_ASSERT: snprintf(buf, size, "Unexpected librtas I/O error"); break; case RTAS_UNKNOWN_OP: snprintf(buf, size, "No firmware implementation of function"); break; default: snprintf(buf, size, "Unknown librtas error %d", error); } return; } int is_librtas_error(int error) { int rc = 0; switch (error) { case RTAS_KERNEL_INT: case RTAS_KERNEL_IMP: case RTAS_PERM: case RTAS_NO_MEM: case RTAS_NO_LOWMEM: case RTAS_FREE_ERR: case RTAS_TIMEOUT: case RTAS_IO_ASSERT: case RTAS_UNKNOWN_OP: rc = 1; } return rc; } powerpc-utils-1.2.26/src/common/librtas_error.h0000664000175000017510000000061712527176005016455 00000000000000/** * @file librtas_error.h * @brief Common librtas_error routine for powerpc-utils-papr commands * * Copyright (c) 2004 International Business Machines * Common Public License Version 1.0 (see COPYRIGHT) * * @author Nathan Fontenot */ #ifndef _LIBRTAS_ERROR_H #define _LIBRTAS_ERROR_H void librtas_error(int, char *, size_t); int is_librtas_error(int); #endif powerpc-utils-1.2.26/src/drmgr/0000775000175000017510000000000012542271540013327 500000000000000powerpc-utils-1.2.26/src/drmgr/drcpu.h0000664000175000017510000000263212527176005014543 00000000000000/** * @file drcpu.h * * Copyright (C) IBM Corporation 2006 */ #ifndef _H_DRCPU #define _H_DRCPU #include "dr.h" #define CPU_PROBE_FILE "/sys/devices/system/cpu/probe" #define CPU_RELEASE_FILE "/sys/devices/system/cpu/release" struct cache_info { char name[DR_BUF_SZ]; /* node name */ char path[DR_BUF_SZ]; /* node path */ uint32_t phandle; uint32_t l2cache; uint32_t removed; struct cache_info *next; /* global list */ }; struct dr_info { struct dr_node *all_cpus; struct cache_info *all_caches; struct thread *all_threads; }; int init_cpu_drc_info(struct dr_info *); void free_cpu_drc_info(struct dr_info *); int get_thread_state(struct thread *); int set_thread_state(struct thread *, int); int get_cpu_state(struct dr_node *); int offline_cpu(struct dr_node *); int online_cpu(struct dr_node *, struct dr_info *); int cpu_enable_smt(struct dr_node *, struct dr_info *); int cpu_disable_smt(struct dr_node *); int smt_enabled(struct dr_info *); int system_enable_smt(struct dr_info *); int system_disable_smt(struct dr_info *); struct cache_info * cpu_get_dependent_cache(struct dr_node *, struct dr_info *); struct cache_info * cache_get_dependent_cache(struct cache_info *, struct dr_info *); int release_cpu(struct dr_node *, struct dr_info *); int probe_cpu(struct dr_node *, struct dr_info *); struct dr_node *get_available_cpu(struct options *, struct dr_info *); #endif /* _H_DRCPU */ powerpc-utils-1.2.26/src/drmgr/dr.h0000664000175000017510000000753112542254225014034 00000000000000/** * @file dr.h * * Copyright (C) IBM Corporation 2006 */ #ifndef _H_DR #define _H_DR #include #include #include #include #include #include "rtas_calls.h" #include "drpci.h" extern int output_level; extern int log_fd; /* Error Exit Codes */ #define RC_IN_USE 1 #define RC_NONEXISTENT 3 #define RC_DONT_OWN 4 #define RC_ALREADY_OWN 5 #define RC_LINUX_SLOT 6 /* Special case for ConcMaint */ /* Online/Offline */ #define OFFLINE 0 #define ONLINE 1 static inline int is_dot_dir(char * _p) { return (_p[0] == '.'); } void * __zalloc(size_t, const char *, int); #define zalloc(x) __zalloc((x), __func__, __LINE__); #define DR_LOCK_FILE "/var/lock/dr_config_lock" #define PLATFORMPATH "/proc/device-tree/device_type" #define OFDTPATH "/proc/ppc64/ofdt" #define DR_COMMAND "drslot_chrp_%s" #define DRMIG_COMMAND "drmig_chrp_%s" struct options { int action; /* remove, add, REPLACE, IDENTIFY ... */ #define NONE 0 #define ADD 1 #define REMOVE 2 #define QUERY 3 #define REPLACE 4 #define IDENTIFY 5 #define MIGRATE 6 #define HIBERNATE 7 int no_ident; /* used in drslot_chrp_pci */ int timeout; /* time (in seconds) to try operation */ char *usr_drc_name; /* pointer to user-specified drc-name * of resource */ uint32_t usr_drc_index; int noprompt; /* 1 = do not prompt user for input, assume yes */ unsigned int quantity; /* number of resources */ char *ctype; char *p_option; int pci_virtio; /* qemu virtio device (legacy guest workaround) */ }; enum say_level { ERROR = 1, WARN, INFO, DEBUG}; /* The follwing are defined in common.c */ int say(enum say_level, char *, ...); void report_unknown_error(char *, int); int dr_init(void); void dr_fini(void); void set_timeout(int); int drmgr_timed_out(void); int dr_lock(void); int dr_unlock(void); int valid_platform(const char *); void free_of_node(struct of_node *); int add_device_tree_nodes(char *, struct of_node *); int remove_device_tree_nodes(char *); int update_property(const char *, size_t); int get_property(const char *, const char *, void *, size_t); int get_int_attribute(const char *, const char *, void *, size_t); int get_str_attribute(const char *, const char *, void *, size_t); int get_ofdt_uint_property(const char *, const char *, uint *); int get_property_size(const char *, const char *); int signal_handler(int, int, struct sigcontext *); int sig_setup(void); char *node_type(struct dr_node *); struct dr_node *alloc_dr_node(struct dr_connector *, int, const char *); int update_sysparm(struct options *); int cpu_dlpar_capable(void); int mem_dlpar_capable(void); int slot_dlpar_capable(void); int phb_dlpar_capable(void); int pmig_capable(void); int phib_capable(void); int hea_dlpar_capable(void); int cpu_entitlement_capable(void); int mem_entitlement_capable(void); void print_dlpar_capabilities(void); void set_output_level(int); #define DR_BUF_SZ 256 int drslot_chrp_slot(struct options *); int valid_slot_options(struct options *); void slot_usage(char **); int drslot_chrp_cpu(struct options *); int valid_cpu_options(struct options *); void cpu_usage(char **); int drslot_chrp_pci(struct options *); int valid_pci_options(struct options *); void pci_usage(char **); int drslot_chrp_phb(struct options *); int valid_phb_options(struct options *); void phb_usage(char **); int drslot_chrp_mem(struct options *); int valid_mem_options(struct options *); void mem_usage(char **); int drslot_chrp_hea(struct options *); int valid_hea_options(struct options *); void hea_usage(char **); int drmig_chrp_pmig(struct options *); int valid_pmig_options(struct options *); void pmig_usage(char **); void phib_usage(char **); int ams_balloon_active(void); #endif powerpc-utils-1.2.26/src/drmgr/drmem.h0000664000175000017510000000131412527176005014526 00000000000000#include "drpci.h" struct lmb_list_head { struct dr_node *lmbs; char *drconf_buf; int drconf_buf_sz; int lmbs_modified; }; struct drconf_mem { uint64_t address; uint32_t drc_index; uint32_t reserved; uint32_t assoc_index; uint32_t flags; }; #define DRMEM_ASSIGNED 0x00000008 #define DRMEM_DRC_INVALID 0x00000020 #define MEM_PROBE_FILE "/sys/devices/system/memory/probe" #define MEM_BLOCK_SIZE_BYTES "/sys/devices/system/memory/block_size_bytes" #define DYNAMIC_RECONFIG_MEM "/proc/device-tree/ibm,dynamic-reconfiguration-memory" #define LMB_NORMAL_SORT 0 #define LMB_REVERSE_SORT 1 #define LMB_RANDOM_SORT 2 struct lmb_list_head *get_lmbs(unsigned int); void free_lmbs(struct lmb_list_head *); powerpc-utils-1.2.26/src/drmgr/drpci.h0000664000175000017510000000433312542271360014524 00000000000000/** * @file drpci.h * * * Copyright (C) IBM Corporation */ #ifndef _DRPCI_H_ #define _DRPCI_H_ #include "rtas_calls.h" #include "ofdt.h" /* PCI Hot Plug defs */ #define PHP_SYSFS_ADAPTER_PATH "/sys/bus/pci/slots/%s/adapter" #define PHP_SYSFS_POWER_PATH "/sys/bus/pci/slots/%s/power" #define PHP_CONFIG_ADAPTER 1 #define PHP_UNCONFIG_ADAPTER 0 #define PCI_RESCAN_PATH "/sys/bus/pci/rescan" /* The following defines are used for adapter status */ #define EMPTY 0 #define CONFIG 1 #define NOT_CONFIG 2 /* Device type definitions */ #define PCI_HP_DEV 1 #define PCI_DLPAR_DEV 2 #define VIO_DEV 3 #define HEA_DEV 4 #define HEA_PORT_DEV 5 #define PHB_DEV 7 #define CPU_DEV 8 #define MEM_DEV 9 #define ADD_SLOT_FNAME "/sys/bus/pci/slots/control/add_slot" #define ADD_SLOT_FNAME2 "/sys/bus/pci/slots/control/\"add_slot\"" #define REMOVE_SLOT_FNAME "/sys/bus/pci/slots/control/remove_slot" #define REMOVE_SLOT_FNAME2 "/sys/bus/pci/slots/control/\"remove_slot\"" #define IGNORE_HP_PO_PROP "/proc/device-tree/ibm,ignore-hp-po-fails-for-dlpar" extern char *add_slot_fname; extern char *remove_slot_fname; #define HEA_ADD_SLOT "/sys/bus/ibmebus/probe" #define HEA_REMOVE_SLOT "/sys/bus/ibmebus/remove" /* %s is the loc-code of the HEA adapter for *_PORT defines */ #define HEA_ADD_PORT "/sys/bus/ibmebus/devices/%s/probe_port" #define HEA_REMOVE_PORT "/sys/bus/ibmebus/devices/%s/remove_port" #define PCI_NODES 0x00000001 #define VIO_NODES 0x00000002 #define HEA_NODES 0x00000004 #define PHB_NODES 0x00000010 struct dr_node *get_hp_nodes(void); struct dr_node *get_dlpar_nodes(uint32_t); struct dr_node *get_node_by_name(const char *, uint32_t); void free_node(struct dr_node *); /* Function prototypes for subroutines */ int get_hp_adapter_status(char *); int set_hp_adapter_status(uint, char *); int pci_rescan_bus(); int pci_remove_device(struct dr_node *); int release_hp_children_from_node(struct dr_node *); int release_hp_children(char *); int dlpar_remove_slot(const char *); int dlpar_add_slot(const char *); int cmp_drcname(char *, char *); int acquire_hp_children(char *, int *); int enable_hp_children(char *); int disable_hp_children(char *); void print_node_list(struct dr_node *); #endif /* _DRPCI_H_ */ powerpc-utils-1.2.26/src/drmgr/rtas_calls.h0000664000175000017510000000621112527176005015552 00000000000000/** * @file rtas_calls.h * * * Copyright (C) IBM Corporation */ #ifndef _RTAS_CALLS_H_ #define _RTAS_CALLS_H_ #include #include "drpci.h" /* The following definitions are used in the interfaces to various * subroutines. */ /* Indicators for rtas_set_indicator */ #define ISOLATION_STATE 9001 /* value for isolation-state */ #define DR_INDICATOR 9002 /* value for dr-indicator */ #define ALLOCATION_STATE 9003 /* value for allocation-state */ /* Error status from rtas_set_indicator */ #define HARDWARE_ERROR -1 #define HARDWARE_BUSY -2 #define NO_INDICATOR -3 #define MULTI_LEVEL_ISO_ERROR -9000 #define VALID_TRANSLATION -9001 /* Error status from dr-entity-sense(get-sensor-state) */ #define NEED_POWER -9000 /* Need to turn on power to slot */ #define PWR_ONLY -9001 /* Power on slot, leave isolated */ /* Sensor values from dr-entity-sense(get-sensor-state) */ #define EMPTY 0 /* No card in slot */ #define PRESENT 1 /* Card in slot */ #define STATE_UNUSABLE 2 /* No DR operation will succeed */ #define EXCHANGE 3 /* resource unlicensed, for sparing only */ #define RECOVERY 4 /* can be recovered by platform */ /* Return status from configure-connector */ #define NOT_THIS_SYSTEM -9001 /* DR entity not supported on this system */ #define NOT_THIS_SLOT -9002 /* DR entity not supported in this slot */ #define DR_UNUSABLE -9003 /* Logical DR connector unusable */ /* Return status from ibm,suspend_me */ #define NOT_SUSPENDABLE -9004 #define MULTIPLE_THREADS -9005 /* State values for set-indicator dr-indicator */ #define LED_OFF 0 #define LED_ON 1 #define LED_ID 2 #define LED_ACTION 3 /* State values for isolation-state */ #define ISOLATE 0 #define UNISOLATE 1 /* Level values for set-power-level */ #define POWER_OFF 0 #define POWER_ON 100 /* State values for allocation-state */ #define ALLOC_UNUSABLE 0 /* Release Unusable Resource to FW */ #define ALLOC_USABLE 1 /* Assign Usable Resource from FW */ /* Tokens for RTAS calls */ #define DR_ENTITY_SENSE 9003 /* token value for dr-entity-sense */ /* Return status from configure-connector */ #define NEXT_SIB 1 /* Next sibling */ #define NEXT_CHILD 2 /* Next child */ #define NEXT_PROPERTY 3 /* Next property */ #define PREV_PARENT 4 /* Previous parent */ #define MORE_MEMORY 5 /* Need more memory */ #define ERR_CFG_USE -9003 /* DR connector unusable */ struct of_property { struct of_property *next; /* Ptr to next property for node */ char *name; /* OF property name */ int length; /* Length of property value in bytes */ char *value; /* Pointer to property value */ }; struct of_node { char *name; /* Node name including unit address */ struct of_property *properties; /* Pointer to OF properties */ struct of_node *parent; /* Pointer to parent node */ struct of_node *sibling; /* Pointer to next sibling node */ struct of_node *child; /* Pointer to first child node */ int added; }; extern char *hw_error; int dr_entity_sense(int index); struct of_node *configure_connector(int index); int set_power(int domain, int level); int acquire_drc(uint32_t); int release_drc(int, uint32_t); struct of_node *configure_connector(int); #endif /* _RTAS_CALLS_H_ */ powerpc-utils-1.2.26/src/drmgr/ofdt.h0000664000175000017510000000747612542271360014372 00000000000000/** * @file ofdt.h * * * Copyright (C) IBM Corporation 2006 * */ #ifndef _OFDT_H_ #define _OFDT_H_ #define DRC_STR_MAX 48 #define OFDT_BASE "/proc/device-tree" #define CPU_OFDT_BASE "/proc/device-tree/cpus" #define DR_PATH_MAX 1024 #define DR_STR_MAX 128 #define MAX_CPU_INTSERV_NUMS 8 struct dr_connector { char name[DRC_STR_MAX]; char type[DRC_STR_MAX]; char ofdt_path[DR_PATH_MAX]; unsigned int index; unsigned int powerdomain; struct dr_connector *next; struct dr_connector *all_next; }; struct mem_scn { struct mem_scn *next; int removable; uint64_t phys_addr; char sysfs_path[DR_PATH_MAX]; }; struct thread { int id; /* linux "logical" cpu id */ uint32_t phys_id; char path[DR_PATH_MAX]; /* node path */ struct thread *next; struct thread *sibling; struct dr_node *cpu; }; /* This structure represents a DR-capable node. Data from * the Open Firmware tree is gathered here. There is a pointer * to a linked list of the OF nodes representing the device(s) * connected to this slot (if they exist) */ struct dr_node { struct dr_node *next; struct dr_node *children; uint32_t drc_index; char drc_type[DR_STR_MAX]; char drc_name[DR_STR_MAX]; uint32_t drc_power; char loc_code[DR_STR_MAX]; char ofdt_path[DR_PATH_MAX]; char *name; /* This will just point to the name part of * the ofdt_path buffer, no need to free */ char ofdt_dname[DR_STR_MAX]; char sysfs_dev_path[DR_PATH_MAX]; uint32_t dev_type; uint32_t is_owned:1; uint32_t skip:1; uint32_t unusable:1; uint32_t is_removable:1; uint32_t post_replace_processing:1; uint32_t reserved:27; union { struct mem_info { uint64_t _address; uint32_t _lmb_size; uint32_t _lmb_aa_index; struct mem_scn *_mem_scns; struct of_node *_of_node; } _smem; #define lmb_address _node_u._smem._address #define lmb_size _node_u._smem._lmb_size #define lmb_aa_index _node_u._smem._lmb_aa_index #define lmb_mem_scns _node_u._smem._mem_scns #define lmb_of_node _node_u._smem._of_node struct hea_info { uint _port_no; uint _port_tenure; }_shea; #define hea_port_no _node_u._shea._port_no #define hea_port_tenure _node_u._shea._port_tenure struct pci_info { uint _vendor_id; /* vendor ID */ uint _device_id; /* device ID */ uint _class_code; /* class code */ }_spci; #define pci_vendor_id _node_u._spci._vendor_id #define pci_device_id _node_u._spci._device_id #define pci_class_code _node_u._spci._class_code struct phb_info { char _ic_ofdt_path[DR_PATH_MAX]; }_sphb; #define phb_ic_ofdt_path _node_u._sphb._ic_ofdt_path struct cpu_info { uint32_t _intserv_nums[MAX_CPU_INTSERV_NUMS]; int _nthreads; uint32_t _reg; uint32_t _l2cache; struct thread *_threads; }_scpu; #define cpu_intserv_nums _node_u._scpu._intserv_nums #define cpu_nthreads _node_u._scpu._nthreads #define cpu_reg _node_u._scpu._reg #define cpu_l2cache _node_u._scpu._l2cache #define cpu_threads _node_u._scpu._threads } _node_u; }; static inline void set_drc_info(struct dr_node *node, struct dr_connector *drc) { node->drc_index = drc->index; node->drc_power = drc->powerdomain; snprintf(node->drc_name, DR_STR_MAX, "%s", drc->name); snprintf(node->drc_type, DR_STR_MAX, "%s", drc->type); } struct dr_connector *get_drc_info(const char *); void free_drc_info(void); char *of_to_full_path(const char *); /* Search types for search_drc_list() */ #define DRC_NAME 0 #define DRC_TYPE 1 #define DRC_INDEX 2 #define DRC_POWERDOMAIN 3 struct dr_connector *search_drc_list(struct dr_connector *, struct dr_connector *, int, void *); int get_my_drc_index(char *, uint32_t *); int drc_name_to_index(const char *, struct dr_connector *); char * drc_index_to_name(uint32_t, struct dr_connector *); int get_drc_by_name(char *, struct dr_connector *, char *, char *); #endif /* _OFDT_H_ */ powerpc-utils-1.2.26/src/drmgr/lsslot.h0000664000175000017510000000124312527176005014743 00000000000000/** * @file lsslot.h * @brief Common data for lsslot* commands * * Copyright (C) IBM Corporation 2006 * * @author Nathan Fontenot */ #ifndef _H_LSSLOT #define _H_LSSLOT /* command options */ struct cmd_opts { int slot_type; #define PCI 0 #define SLOT 1 #define PHB 2 #define CPU 3 #define MEM 4 #define PORT 5 int a_flag; int o_flag; int b_flag; int p_flag; int timeout; char *delim; char *s_name; }; #define MAX(x,y) (((x) > (y)) ? (x) : (y)) /* lsslot.c */ int lsslot(struct cmd_opts *); /* lsslot_chrp_phb.c */ int lsslot_chrp_phb(struct cmd_opts *); /* lsslot_chrp_cpu.c */ int lsslot_chrp_cpu(struct cmd_opts *); #endif powerpc-utils-1.2.26/src/drmgr/common.c0000664000175000017510000007040312542254225014710 00000000000000/** * @file common.c * * Copyright (C) IBM Corporation 2006 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dr.h" #include "ofdt.h" char *add_slot_fname = ADD_SLOT_FNAME; char *remove_slot_fname = REMOVE_SLOT_FNAME; #define DR_LOG_PATH "/var/log/drmgr" #define DR_LOG_PATH0 "/var/log/drmgr.0" #define LPARCFG_PATH "/proc/ppc64/lparcfg" static int dr_lock_fd = 0; static long dr_timeout; /** * set_output level * @brief Common routine to set the output level * * @param level level to set the output level to */ inline void set_output_level(int level) { output_level = level; if (output_level >= 14) { say(DEBUG, "Enabling RTAS debug\n"); rtas_set_debug(output_level); } } int say(enum say_level lvl, char *fmt, ...) { va_list ap; char buf[256]; int len, rc; va_start(ap, fmt); memset(buf, 0, 256); len = vsnprintf(buf, 256, fmt, ap); va_end(ap); if (len >= 256) { strcpy(&buf[243], "\n"); len = 255; } if (log_fd) rc = write(log_fd, buf, len); if (lvl <= output_level) fprintf(stderr, "%s", buf); return len; } void report_unknown_error(char *file, int line) { say(ERROR, "Unexpected error (%s:%d). Contact support and provide " "debug log from %s.\n", file, line, DR_LOG_PATH); } void * __zalloc(size_t size, const char *func, int line) { void *data; data = malloc(size); if (data) memset(data, 0, size); else say(ERROR, "Allocation failure (%lx) at %s:%d\n", size, func, line); return data; } /** * dr_init * @brief Initialization routine for drmgr and lsslot * */ inline int dr_init(void) { int rc; rc = dr_lock(); if (rc) { say(ERROR, "Unable to obtain Dynamic Reconfiguration lock. " "Please try command again later.\n"); return -1; } log_fd = open(DR_LOG_PATH, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (log_fd == -1) { log_fd = 0; say(ERROR, "Could not open log file %s\n\t%s\n", DR_LOG_PATH, strerror(errno)); } else { time_t t; char tbuf[128]; /* Insert seperator at beginning of drmgr invocation */ time(&t); strftime(tbuf, 128, "%b %d %T %G", localtime(&t)); say(DEBUG, "\n########## %s ##########\n", tbuf); } /* Mask signals so we do not get interrupted */ if (sig_setup()) { say(ERROR, "Could not mask signals to avoid interrupts\n"); return -1; } return 0; } /** * dr_fini * @brief Cleanup routine for drmgr and lsslot * */ inline void dr_fini(void) { struct stat sbuf; int max_dr_log_sz = 25000; int rc; time_t t; char tbuf[128]; free_drc_info(); if (! log_fd) return; /* Insert seperator at end of drmgr invocation */ time(&t); strftime(tbuf, 128, "%b %d %T %G", localtime(&t)); say(DEBUG, "########## %s ##########\n", tbuf); close(log_fd); /* Check for log rotation */ rc = stat(DR_LOG_PATH, &sbuf); if (rc) { fprintf(stderr, "Cannot determine log size to check for " "rotation:\n\t%s\n", strerror(errno)); return; } if (sbuf.st_size >= max_dr_log_sz) { fprintf(stderr, "Rotating logs...\n"); rc = unlink(DR_LOG_PATH0); if (rc && (errno != ENOENT)) { fprintf(stderr, "Could not remove %s\n\t%s\n", DR_LOG_PATH0, strerror(errno)); return; } rc = rename(DR_LOG_PATH, DR_LOG_PATH0); if (rc) { fprintf(stderr, "Could not rename %s to %s\n\t%s\n", DR_LOG_PATH, DR_LOG_PATH0, strerror(errno)); return; } } dr_unlock(); } /** * set_timeout * */ void set_timeout(int timeout) { if (!timeout) { dr_timeout = -1; return; } dr_timeout = time((time_t *)0); if (dr_timeout == -1) return; dr_timeout += timeout; } /** * */ int drmgr_timed_out(void) { if (dr_timeout == -1) return 0; /* No timeout specified */ if (dr_timeout > time((time_t *)0)) return 0; say(WARN, "Drmgr has exceeded its specified wait time and will not " "continue\n"); return 1; } /** * dr_lock * @brief Attempt to lock a token * * This will attempt to lock a token (either file or directory) and wait * a specified amount of time if the lock cannot be granted. * * @returns lock id if successful, -1 otherwise */ int dr_lock(void) { struct flock dr_lock_info; int dr_lock_fd; int rc; mode_t old_mode; int first_try = 1; old_mode = umask(0); dr_lock_fd = open(DR_LOCK_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); if (dr_lock_fd < 0) return -1; umask(old_mode); dr_lock_info.l_type = F_WRLCK; dr_lock_info.l_whence = SEEK_SET; dr_lock_info.l_start = 0; dr_lock_info.l_len = 0; do { if (!first_try) { sleep(1); first_try = 0; } rc = fcntl(dr_lock_fd, F_SETLK, &dr_lock_info); if (rc != -1) return 0; if (drmgr_timed_out()) break; if (rc == -1 && errno == EACCES) continue; } while (1); close(dr_lock_fd); dr_lock_fd = 0; perror(DR_LOCK_FILE); return -1; } /** * dr_unlock * @brief unlock a lock granted via dr_lock() * * @param lock_id * @returns 0 on success, -1 otherwise */ int dr_unlock(void) { struct flock dr_lock_info; dr_lock_info.l_whence = SEEK_SET; dr_lock_info.l_start = 0; dr_lock_info.l_len = 0; dr_lock_info.l_type = F_UNLCK; if (fcntl(dr_lock_fd, F_SETLK, &dr_lock_info) < 0) return -1; close(dr_lock_fd); dr_lock_fd = 0; return 0; } /** * add_node * @brief Add the specified node(s) to the device tree * * This will add the specified node(s) to the /proc Open Firmware * tree and the kernel Open Firmware tree. * * @param add_path * @param new_nodes * @returns 0 on success */ static int add_node(char *path, struct of_node *new_nodes) { int rc = 0; int nprops = 0; int fd; struct of_property *prop; char *buf, *pos; char *add_path; size_t bufsize = 0; struct stat sbuf; /* If the device node already exists, no work to be done. This is * usually the case for adding a dedicated cpu that shares a * l2-cache with another apu and that cache already exists in the * device tree. */ if (!stat(path, &sbuf)) { say(DEBUG, "Device-tree node %s already exists, skipping\n", path); return 0; } say(DEBUG, "Adding device-tree node %s\n", path); /* The path passed in is a full ofdt path, remove the preceeding * /proc/device-tree for the write to the kernel. */ add_path = path + strlen(OFDT_BASE); /* determine the total size of the buffer we need to allocate */ bufsize += strlen("add_node "); bufsize += strlen(add_path) + 1; for (prop = new_nodes->properties; prop; prop = prop->next) { char tmp[16] = { '\0' }; /* for length */ nprops++; bufsize += strlen(prop->name) + 1; /* name + space */ sprintf(tmp, "%d", prop->length); bufsize += strlen(tmp) + 1; /* length + space*/ bufsize += prop->length + 1; /* value + space */ } if (! nprops) { say(ERROR, "new_nodes have no properties\n"); return -1; } buf = zalloc(bufsize); if (buf == NULL) { say(ERROR, "Failed to allocate buffer to write to kernel\n"); return errno; } strcpy(buf, "add_node "); strcat(buf, add_path); strcat(buf, " "); pos = buf + strlen(buf); /* this is less than optimal, iterating over the entire buffer * for every strcat... */ for (prop = new_nodes->properties; prop; prop = prop->next) { char tmp[16] = { '\0' }; /* for length */ memcpy(pos, prop->name, strlen(prop->name)); pos += strlen(prop->name); *pos++ = ' '; sprintf(tmp, "%d", prop->length); memcpy(pos, tmp, strlen(tmp)); pos += strlen(tmp); *pos++ = ' '; memcpy(pos, prop->value, prop->length); pos += prop->length; *pos++ = ' '; } *pos = '\0'; /* dump the buffer for debugging */ say(DEBUG, "ofdt update: %s\n", buf); fd = open(OFDTPATH, O_WRONLY); if (fd <= 0) { say(ERROR, "Failed to open %s: %s\n", OFDTPATH, strerror(errno)); return errno; } rc = write(fd, buf, bufsize); if (rc <= 0) say(ERROR, "Write to %s failed: %s\n", OFDTPATH, strerror(errno)); else rc = 0; close(fd); return rc; } /** * remove_node * @brief Remove the specified node to the device tree * * This will remove the specified node to the /proc Open Firmware * tree and the kernel Open Firmware tree. * * @param cmd * @returns 0 on success */ static int remove_node(char *path) { int rc = 0; int fd; int cmdlen; char buf[DR_PATH_MAX]; say(DEBUG, "Removing device-tree node %s\n", path); memset(buf, 0, DR_PATH_MAX); /* The path passed in is a full device path, remove the preceeding * /proc/device-tree part for the write to the kernel. */ sprintf(buf, "remove_node %s", path + strlen(OFDT_BASE)); cmdlen = strlen(buf); fd = open(OFDTPATH, O_WRONLY); if (fd <= 0) { say(ERROR, "Failed to open %s: %s\n", OFDTPATH, strerror(errno)); return errno; } rc = write(fd, buf, cmdlen); if (rc != cmdlen) say(ERROR, "Write to %s failed: %s\n", OFDTPATH, strerror(errno)); else rc = 0; close(fd); return rc; } /** * add_device_tree_nodes * * Process new_nodes from configure_connector and call add_node to * add new nodes to /proc device-tree and the kernel's device tree. * * @param root_path * @param new_nodes * @returns 0 on success, !0 otherwise */ static int _add_device_tree_nodes(char *path, struct of_node *new_nodes) { struct of_node *node; char add_path[DR_PATH_MAX]; int rc = 0; for (node = new_nodes; node; node = node->sibling) { sprintf(add_path, "%s/%s", path, node->name); rc = add_node(add_path, node); if (rc) break; node->added = 1; if (node->child) { rc = _add_device_tree_nodes(add_path, node->child); if (rc) break; } } return rc; } int add_device_tree_nodes(char *path, struct of_node *new_nodes) { struct of_node *node; char rm_path[DR_PATH_MAX]; int rc; rc = _add_device_tree_nodes(path, new_nodes); if (rc) { for (node = new_nodes; node; node = node->sibling) { if (!node->added) continue; sprintf(rm_path, "%s/%s", path, node->name); remove_node(rm_path); } } return rc; } /** * remove_device_tree_nodes * * Remove all device nodes and children device nodes from Open Firmware * device tree * * @param root_path * @returns 0 on success, !0 otherwise */ int remove_device_tree_nodes(char *path) { DIR *d; struct dirent *de; struct stat sb; int found = 1; int rc; rc = lstat(path, &sb); if (rc || (!S_ISDIR(sb.st_mode)) || (S_ISLNK(sb.st_mode))) return rc; d = opendir(path); if (d == NULL) { say(ERROR, "Could not open %s: %s\n", path, strerror(errno)); return -1; } while (found) { char subdir_name[DR_PATH_MAX]; found = 0; /* Remove any subdirectories */ while ((de = readdir(d)) != NULL) { if (is_dot_dir(de->d_name)) continue; sprintf(subdir_name, "%s/%s", path, de->d_name); rc = lstat(subdir_name, &sb); if (!rc && (S_ISDIR(sb.st_mode)) && (!S_ISLNK(sb.st_mode))) { found = 1; break; } } if (found) { rc = remove_device_tree_nodes(subdir_name); rewinddir(d); } if (rc) break; } closedir(d); if (!rc) rc = remove_node(path); return rc; } /** * update_property * * */ int update_property(const char *buf, size_t len) { int fd, rc; say(DEBUG, "Updating OF property\n"); fd = open(OFDTPATH, O_WRONLY); if (fd <= 0) { say(ERROR, "Failed to open %s: %s\n", OFDTPATH, strerror(errno)); return errno; } rc = write(fd, buf, len); if ((size_t)rc != len) say(ERROR, "Write to %s failed: %s\n", OFDTPATH, strerror(errno)); else rc = 0; close(fd); return rc; } /** * get_att_prop * @brief find the value for a given property/attribute. * * @param path path to the property/attribute to retrieve * @param name name of the property/attribute to retrieve * @param buf buffer to write property/attribute to * @param buf_sz size of the buffer * @returns 0 on success, -1 otherwise */ static int get_att_prop(const char *path, const char *name, char *buf, size_t buf_sz, const char *attr_type) { FILE *fp; int rc; char dir[DR_PATH_MAX]; if (buf == NULL) return -1; if (name != NULL) sprintf(dir, "%s/%s", path, name); else sprintf(dir, "%s", path); fp = fopen(dir, "r"); if (fp == NULL) return -1; memset(buf, 0, buf_sz); /* Yes, this is sort of a hack but we only read properties from * either /proc or sysfs so it works and is cheaper than a strcmp() */ switch (dir[1]) { case 'p': /* /proc */ rc = fread(buf, buf_sz, 1, fp); break; case 's': /* sysfs */ rc = fscanf(fp, attr_type, (int *)buf); break; } fclose(fp); return 0; } /** * get_property * @brief retrieve a device-tree property from /proc * * @param path path to the property to retrieve * @param name name of the property to retrieve * @param buf buffer to write property to * @param buf_sz size of the buffer * @returns 0 on success, !0 otherwise */ int get_property(const char *path, const char *property, void *buf, size_t buf_sz) { return get_att_prop(path, property, buf, buf_sz, NULL); } /** * get_int_attribute * @brief retrieve an integer device attribute from sysfs * * @param path path to the attribute to retrieve * @param name name of the attribute to retrieve * @param buf buffer to write attribute to * @param buf_sz size of the buffer * @returns 0 on success, -1 otherwise */ int get_int_attribute(const char *path, const char *attribute, void *buf, size_t buf_sz) { return get_att_prop(path, attribute, buf, buf_sz, "%i"); } /** * get_str_attribute * @brief retrieve a string device attribute from sysfs * * @param path path to the attribute to retrieve * @param name name of the attribute to retrieve * @param buf buffer to write attribute to * @param buf_sz size of the buffer * @returns 0 on success, -1 otherwise */ int get_str_attribute(const char *path, const char *attribute, void *buf, size_t buf_sz) { return get_att_prop(path, attribute, buf, buf_sz, "%s"); } /** * get_ofdt_uint_property * @brief retrieve an unsigned integer property from the device tree and * byteswap if needed (device tree is big endian). * * @param path path to the property to retrieve * @param name name of the property to retrieve * @param data unsigned integer pointer to write property to * @returns 0 on success, -1 otherwise */ int get_ofdt_uint_property(const char *path, const char *attribute, uint *data) { uint tmp; int rc; rc = get_property(path, attribute, &tmp, sizeof(tmp)); if (!rc) *data = be32toh(tmp); return rc; } /** * get_property_size * @brief retrieve the size of a property * * @param path path to the property to retrieve * @param name name of the property to retrieve * @returns size of the property */ int get_property_size(const char *path, const char *property) { char dir[DR_PATH_MAX]; struct stat sb; if (property != NULL) sprintf(dir, "%s/%s", path, property); else sprintf(dir, "%s", path); stat(dir, &sb); return sb.st_size; } /** * sighandler * @brief Simple signal handler to print signal/stack info, cleanup and exit. * * @param signo signal number we caught. */ void sighandler(int signo) { say(ERROR, "Received signal %d, attempting to cleanup and exit\n", signo); if (log_fd) { void *callstack[128]; int sz; sz = backtrace(callstack, 128); backtrace_symbols_fd(callstack, sz, log_fd); } dr_fini(); exit(-1); } /** * sig_setup * @brief Mask signals so that dynamic reconfig operations won't be * interrupted and catch others. * * @returns 0 on success, !0 otherwise */ int sig_setup(void) { sigset_t sigset; struct sigaction sigact; void *callstack[128]; int rc; /* Now set up a mask with all signals masked */ sigfillset(&sigset); /* Clear mask bits for signals we don't want to mask */ sigdelset(&sigset, SIGBUS); sigdelset(&sigset, SIGXFSZ); sigdelset(&sigset, SIGSEGV); sigdelset(&sigset, SIGTRAP); sigdelset(&sigset, SIGILL); sigdelset(&sigset, SIGFPE); sigdelset(&sigset, SIGSYS); sigdelset(&sigset, SIGPIPE); sigdelset(&sigset, SIGVTALRM); sigdelset(&sigset, SIGALRM); sigdelset(&sigset, SIGQUIT); sigdelset(&sigset, SIGABRT); /* Now block all remaining signals */ rc = sigprocmask(SIG_BLOCK, &sigset, NULL); if (rc) return -1; /* Now set up a signal handler for the signals we want to catch */ memset(&sigact, 0, sizeof(sigact)); sigemptyset(&sigact.sa_mask); sigact.sa_handler = sighandler; if (sigaction(SIGQUIT, &sigact, NULL)) return -1; if (sigaction(SIGILL, &sigact, NULL)) return -1; if (sigaction(SIGABRT, &sigact, NULL)) return -1; if (sigaction(SIGFPE, &sigact, NULL)) return -1; if (sigaction(SIGSEGV, &sigact, NULL)) return -1; if (sigaction(SIGBUS, &sigact, NULL)) return -1; /* dummy call to backtrace to get symbol loaded */ backtrace(callstack, 128); return 0; } char *php_slot_type_msg[]={ "", "PCI 32 bit, 33MHz, 5 volt slot", "PCI 32 bit, 50MHz, 5 volt slot", "PCI 32 bit, 33MHz, 3.3 volt slot", "PCI 64 bit, 33MHz, 5 volt slot", "PCI 64 bit, 50MHz, 5 volt slot", /* 5 */ "PCI 64 bit, 33MHz, 3.3 volt slot", "PCI 32 bit, 66MHz, 3.3 volt slot", "PCI 64 bit, 66MHz, 3.3 volt slot", "", /* we don't have connector types for */ "", /* 9 or 10, so skip these indices. */ "PCI-X capable, 32 bit, 66MHz slot", "PCI-X capable, 32 bit, 100MHz slot", "PCI-X capable, 32 bit, 133MHz slot", "PCI-X capable, 64 bit, 66MHz slot", "PCI-X capable, 64 bit, 100MHz slot", /* 15 */ "PCI-X capable, 64 bit, 133MHz slot", "PCI-X capable, 64 bit, 266MHz slot", "PCI-X capable, 64 bit, 533MHz slot", "PCI-E capable, Rev 1, 1x lanes", "PCI-E capable, Rev 1, 2x lanes", /* 20 */ "PCI-E capable, Rev 1, 4x lanes", "PCI-E capable, Rev 1, 8x lanes", "PCI-E capable, Rev 1, 16x lanes", "PCI-E capable, Rev 1, 32x lanes", "PCI-E capable, Rev 2, 1x lanes", /* 25 */ "PCI-E capable, Rev 2, 2x lanes", "PCI-E capable, Rev 2, 4x lanes", "PCI-E capable, Rev 2, 8x lanes", "PCI-E capable, Rev 2, 16x lanes", "PCI-E capable, Rev 2, 32x lanes", /* 30 */ "PCI-E capable, Rev 3, 8x lanes with 1 lane connected", "PCI-E capable, Rev 3, 8x lanes with 4x lanes connected", "PCI-E capable, Rev 3, 8x lanes with 8x lanes connected", "PCI-E capable, Rev 3, 16x lanes with 1 lane connected", "PCI-E capable, Rev 3, 16x lanes with 8x lanes connected", /* 35 */ "PCI-E capable, Rev 3, 16x lanes with 16x lanes connected", "PCI-E capable, Rev 4, 8x lanes with 1 lane connected", "PCI-E capable, Rev 4, 8x lanes with 4x lanes connected", "PCI-E capable, Rev 4, 8x lanes with 8x lanes connected", "PCI-E capable, Rev 4, 16x lanes with 1 lane connected", /* 40 */ "PCI-E capable, Rev 4, 16x lanes with 8x lanes connected", "PCI-E capable, Rev 4, 16x lanes with 16x lanes connected", }; char * node_type(struct dr_node *node) { int desc_msg_num; char *desc = "Unknown"; desc_msg_num = atoi(node->drc_type); if ((desc_msg_num >= 1 && desc_msg_num <= 8) || (desc_msg_num >= 11 && desc_msg_num <= 42)) desc = php_slot_type_msg[desc_msg_num]; else { switch (node->dev_type) { case PCI_DLPAR_DEV: desc = "Logical I/O Slot"; break; case VIO_DEV: desc = "Virtual I/O Slot"; break; case HEA_DEV: desc = "HEA I/O Slot"; break; case HEA_PORT_DEV: desc = "HEA Port I/O Slot"; break; default: desc = "Unknown slot type"; break; } } return desc; } /** * valid_platform * @brief Validate that the platfomr we are on matches the one specified * * @param platform Name of platform to validate * @return 1 if valid, 0 otherwise */ int valid_platform(const char *platform) { char buf[128]; int rc; rc = get_property(OFDT_BASE, "device_type", buf, 128); if (rc) { say(ERROR, "Cannot open %s: %s\n", PLATFORMPATH, strerror(errno)); return 0; } if (strcmp(buf, platform)) { say(ERROR, "This command is not supported for %s platforms.\n", platform); return 0; } return 1; } /** * get_sysparm * * @param parm * @returns 0 on success, !0 otherwise */ static int get_sysparm(const char *parm, unsigned long *value) { int rc = -1; char s[DR_BUF_SZ]; FILE *f; f = fopen(LPARCFG_PATH, "r"); if (f == NULL) { say(ERROR, "Could not open \"%s\"\n%s\n", LPARCFG_PATH, strerror(errno)); return -1; } while (fgets(s, sizeof(s), f)) { if (! strncmp(s, parm, strlen(parm))) { char *tmp = strchr(s, '='); if (tmp == NULL) break; tmp++; rc = 0; *value = strtoul(tmp, NULL, 0); break; } } fclose(f); if (rc) say(ERROR, "Error finding %s in %s\n", parm, LPARCFG_PATH); return rc; } /** * set_sysparm * * @param parm * @param val * @returns 0 on success, !0 otherwise */ static int set_sysparm(const char *parm, int val) { int rc = -1; FILE *f; f = fopen(LPARCFG_PATH, "w"); if (f == NULL) { say(ERROR, "Could not open \"%s\"\n%s\n", LPARCFG_PATH, strerror(errno)); return -1; } say(DEBUG, "Updating sysparm %s to %d...", parm, val); rc = fprintf(f, "%s=%d\n", parm, val); fclose(f); say(DEBUG, "%s.\n", (rc == -1) ? "fail" : "success"); return (rc == -1) ? -1 : 0; } struct sysparm_mapping { char *drmgr_name; char *linux_name; }; static struct sysparm_mapping cpu_sysparm_table[] = { { .drmgr_name = "variable_weight", .linux_name = "capacity_weight" }, { .drmgr_name = "ent_capacity", .linux_name = "partition_entitled_capacity" }, { .drmgr_name = NULL, .linux_name = NULL } }; static struct sysparm_mapping mem_sysparm_table[] = { { .drmgr_name = "variable_weight", .linux_name = "entitled_memory_weight" }, { .drmgr_name = "ent_capacity", .linux_name = "entitled_memory" }, { .drmgr_name = NULL, .linux_name = NULL } }; /** * update_sysparm * * Update the indicated system parameter by the amount specified. * This requires us to establish the current value of the parameter, * since the kernel interface accepts only absolute values. * * @param parm * @param quantity * @returns 0 on success, !0 otherwise */ int update_sysparm(struct options *opts) { struct sysparm_mapping *sysparm_table; unsigned long curval; int i; char *linux_parm = NULL; /* Validate capability */ if (! strcmp(opts->ctype, "cpu")) { if (! cpu_entitlement_capable()) { say(ERROR, "CPU entitlement capability is not enabled " "on this platform.\n"); return -1; } sysparm_table = cpu_sysparm_table; } else if (! strcmp(opts->ctype, "mem")) { if (! mem_entitlement_capable()) { say(ERROR, "Memory entitlement capability is not " "enabled on this platform.\n"); return -1; } sysparm_table = mem_sysparm_table; } else { say(ERROR, "Invalid entitlement update type \"%s\" " "specified.\n", opts->ctype); return -1; } /* Convert the system parameter presented to drmgr into what is * expected by the kernel. */ i = 0; while (sysparm_table[i].drmgr_name) { if (! strcmp(sysparm_table[i].drmgr_name, opts->p_option)) { linux_parm = sysparm_table[i].linux_name; break; } i++; } if (linux_parm == NULL) { say(ERROR, "The entitlement parameter \"%s\" is not " "recognized\n", opts->p_option); return -1; } if ((get_sysparm(linux_parm, &curval)) < 0) { say(ERROR, "Could not get current system parameter value of " "%s (%s)\n", linux_parm, opts->p_option); return -1; } if (opts->action == REMOVE) { if (opts->quantity > curval) { say(ERROR, "Cannot reduce system parameter value %s by " "more than is currently available.\nCurrent " "value: %lx, asking to remove: %x\n", opts->p_option, curval, opts->quantity); return 1; } opts->quantity = -opts->quantity; } return set_sysparm(linux_parm, curval + opts->quantity); } int cpu_dlpar_capable(void) { DIR *d; struct dirent *de; struct stat sbuf; char fname[DR_PATH_MAX]; char *cpu_dir = "/sys/devices/system/cpu"; int capable = 1; say(ERROR, "Validating CPU DLPAR capability..."); d = opendir(cpu_dir); if (d == NULL) { say(ERROR, "no.\n opendir(\"%s\"): %s\n", cpu_dir, strerror(errno)); return 0; } while ((de = readdir(d)) != NULL) { if (strncmp(de->d_name, "cpu", 3)) continue; /* Ensure this is a cpu directory, i.e. cpu0, and not a * non-cpu directory, i.e. cpufreq */ if (!isdigit(de->d_name[3])) continue; sprintf(fname, "%s/%s/online", cpu_dir, de->d_name); if (stat(fname, &sbuf)) { say(ERROR, "no.\n stat(\"%s\"): %s\n", fname, strerror(errno)); capable = 0; } say(ERROR, "yes.\n"); break; } closedir(d); return capable; } static inline int dlpar_capable(const char *type, const char *fname) { struct stat sbuf; int capable = 1; say(ERROR, "Validating %s capability...", type); if (stat(fname, &sbuf)) { say(ERROR, "no.\n stat(\"%s\"): %s\n", fname, strerror(errno)); capable = 0; } else { say(ERROR, "yes.\n"); } return capable; } int mem_dlpar_capable(void) { return dlpar_capable("Memory DLPAR", "/sys/devices/system/memory/block_size_bytes"); } static int check_slot_phb_dlpar(const char *type) { struct stat sbuf; int rc; /* Before checking for dlpar capability, we need to ensure that * rpadlpar_io module is loaded or built into the kernel. This * does make the checking a bit redundant though. */ if ((stat(add_slot_fname, &sbuf)) || (stat(ADD_SLOT_FNAME2, &sbuf))) { rc = system("/sbin/modprobe rpadlpar_io"); if (WIFEXITED(rc) && WEXITSTATUS(rc)) say(ERROR, "rpadlpar_io module was not loaded\n"); } /* For unknown reasons the add_slot and remove_slot sysfs files * used for dlpar operations started appearing with quotes around * the filename. So, this little hack exists to ensure nothing * breaks on the kernels where this exists. * * The default value is without the quotes. This is what was and * what shall be again. */ rc = dlpar_capable(type, add_slot_fname); if (! rc) { add_slot_fname = ADD_SLOT_FNAME2; remove_slot_fname = REMOVE_SLOT_FNAME2; rc = dlpar_capable(type, add_slot_fname); } return rc; } int slot_dlpar_capable(void) { return check_slot_phb_dlpar("I/O DLPAR"); } int phb_dlpar_capable(void) { return check_slot_phb_dlpar("PHB DLPAR"); } int pmig_capable(void) { return dlpar_capable("partition migration", "/proc/device-tree/ibm,migratable-partition"); } int phib_capable(void) { return dlpar_capable("partition hibernation", "/sys/devices/system/power/hibernate"); } int slb_resize_capable(void) { unsigned long value; int rc; rc = get_sysparm("slb_size", &value); if (rc == -1) return 0; return 1; } int hea_dlpar_capable(void) { return dlpar_capable("HEA DLPAR", HEA_ADD_SLOT); } int cpu_entitlement_capable(void) { unsigned long value; int rc; rc = get_sysparm("partition_entitled_capacity", &value); if (rc == -1) return 0; return 1; } int mem_entitlement_capable(void) { unsigned long value; int rc; rc = get_sysparm("entitled_memory", &value); if (rc == -1) return 0; return 1; } void print_dlpar_capabilities(void) { int cpu_dlpar, mem_dlpar, slot_dlpar, phb_dlpar, hea_dlpar; int pmig, phib, slb_resize; int cpu_entitled, mem_entitled; cpu_dlpar = cpu_dlpar_capable(); mem_dlpar = mem_dlpar_capable(); slot_dlpar = slot_dlpar_capable(); phb_dlpar = phb_dlpar_capable(); hea_dlpar = hea_dlpar_capable(); pmig = pmig_capable(); phib = phib_capable(); slb_resize = slb_resize_capable(); cpu_entitled = cpu_entitlement_capable(); mem_entitled = mem_entitlement_capable(); printf("cpu_dlpar=%s,mem_dlpar=%s,slot_dlpar=%s,phb_dlpar=%s," "hea_dlpar=%s,pmig=%s,cpu_entitlement=%s,mem_entitlement=%s," "slb_resize=%s,phib=%s\n", (cpu_dlpar ? "yes" : "no"), (mem_dlpar ? "yes" : "no"), (slot_dlpar ? "yes" : "no"), (phb_dlpar ? "yes" : "no"), (hea_dlpar ? "yes" : "no"), (pmig ? "yes" : "no"), (cpu_entitled ? "yes" : "no"), (mem_entitled ? "yes" : "no"), (slb_resize ? "yes" : "no"), (phib ? "yes" : "no")); } /** * ams_balloon_active * @brief Determines if AMS and memory ballooning is enabled * * @returns 1 if ballooning is active, 0 if AMS or ballooning is inactive */ int ams_balloon_active(void) { /* CMM's loaned_kb file only appears when AMS is enabled */ char *ams_enabled = "/sys/devices/system/cmm/cmm0/loaned_kb"; char *cmm_param_path = "/sys/module/cmm/parameters"; struct stat sbuf; static int is_inactive = 1; static int ams_checked = 0; if (!ams_checked) { if (!stat(ams_enabled, &sbuf) && !stat(cmm_param_path, &sbuf)) get_int_attribute(cmm_param_path, "disable", &is_inactive, sizeof(is_inactive)); say(DEBUG, "AMS ballooning %s active\n", is_inactive?"is not":"is"); ams_checked = 1; } return !is_inactive; } powerpc-utils-1.2.26/src/drmgr/common_cpu.c0000664000175000017510000006027712527176005015571 00000000000000/** * @file common_cpu.c * @brief Common routines for cpu data * * Copyright (C) IBM Corporation 2006 * */ #include #include #include #include #include #include #include #include #include #include "dr.h" #include "drcpu.h" #include "ofdt.h" /* format strings for easy access */ #define DR_THREAD_DIR_PATH "/sys/devices/system/cpu/cpu%d" #define DR_THREAD_ONLINE_PATH "/sys/devices/system/cpu/cpu%d/online" #define DR_THREAD_PHYSID_PATH "/sys/devices/system/cpu/cpu%d/physical_id" #define DR_CPU_INTSERVERS_PATH \ "/proc/device-tree/cpus/%s/ibm,ppc-interrupt-server#s" /** * free_thread_info * @brief free the thread list and any associated allocated memory * * @param thread_list list of threads to free */ static inline void free_thread_info(struct thread *thread_list) { struct thread *thread; while (thread_list) { thread = thread_list; thread_list = thread->next; free(thread); } } /** * get_cpu_threads * Associate a thread to the cpu it belongs to. * * @param all_cpus list of all cpus * @param thread thread to associate. */ static void get_cpu_threads(struct dr_node *cpu, struct thread *all_threads) { struct thread *thread; struct thread *last = NULL; int i; for (thread = all_threads; thread; thread = thread->next) { for (i = 0; i < cpu->cpu_nthreads; i++) { if (cpu->cpu_intserv_nums[i] != thread->phys_id) continue; /* Special case for older kernels where the default * physical id of a thread was 0, which is also a * valid physical id. */ if (thread->phys_id == 0) { char *cpuid = strrchr(thread->path, 'c'); if (cpuid[3] != '0') continue; } if (last) last->sibling = thread; else cpu->cpu_threads = thread; last = thread; thread->cpu = cpu; } } } /** * init_thread_info * @brief Initialize thread data * * Initialize global thread or "logical cpu" data. The physical cpu data * initialization must have been completed before this is called. * * @returns pointer to thread_info on success, NULL otherwise */ static int init_thread_info(struct dr_info *dr_info) { struct thread *thread = NULL; struct thread *thread_list = NULL; struct thread *last = NULL; int rc, i = 0; struct stat s; char path[DR_PATH_MAX]; int nr_threads, thread_cnt = 0; if (stat("/sys/devices/system/cpu", &s)) { say(ERROR, "Cannot gather CPU thread information,\n" "stat(\"/sys/devices/system/cpu\"): %s\n", strerror(errno)); return -1; } nr_threads = s.st_nlink - 2; say(DEBUG, "Expecting %d threads...", nr_threads); sprintf(path, DR_THREAD_DIR_PATH, i); for (i = 0; 0 == stat(path, &s); i++) { thread = zalloc(sizeof(*thread)); thread->id = i; snprintf(thread->path, DR_PATH_MAX, "%s", path); rc = get_int_attribute(thread->path, "physical_id", &thread->phys_id, sizeof(thread->phys_id)); if (rc) { say(ERROR, "Could not get \"physical_id\" of thread " "%s\n", thread->path); free(thread); return -1; } if (thread_list) last->next = thread; else thread_list = thread; last = thread; sprintf(path, DR_THREAD_DIR_PATH, i + 1); thread_cnt++; } say(DEBUG, "found %d.\n", thread_cnt); dr_info->all_threads = thread_list; return 0; } static int cpu_index_to_path(struct dr_node *cpu) { DIR *d; struct dirent *de; int found = 0; int rc; char path[DR_PATH_MAX]; d = opendir(CPU_OFDT_BASE); if (d == NULL) { say(ERROR, "Could not open %s: %s\n", CPU_OFDT_BASE, strerror(errno)); return -1; } while ((de = readdir(d)) != NULL) { uint32_t my_drc_index; if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name)) continue; if (strncmp(de->d_name, "PowerPC", 7)) continue; sprintf(path, "%s/%s", CPU_OFDT_BASE, de->d_name); rc = get_my_drc_index(path, &my_drc_index); if (rc) { /* This is an error, but continue searching since * this may not be the drc index we are looking for */ say(DEBUG, "Could not retrieve drc_index for %s\n", path); continue; } if (my_drc_index == cpu->drc_index) { found = 1; break; } } closedir(d); if (found) snprintf(cpu->ofdt_path, DR_PATH_MAX, "%s", path); return rc; } static int update_cpu_node(struct dr_node *cpu, const char *path, struct dr_info *dr_info) { struct stat sb; char intserv_path[DR_PATH_MAX]; int rc, i; if (path) { snprintf(cpu->ofdt_path, DR_PATH_MAX, "%s", path); } else { rc = cpu_index_to_path(cpu); if (rc) { say(ERROR, "Could not find ofdt path for drc index " "%s\n", cpu->drc_index); return rc; } } /* Skip past CPU_OFDT_BASE plus the '/' */ cpu->name = cpu->ofdt_path + strlen(CPU_OFDT_BASE) + 1; memset(&cpu->cpu_intserv_nums, -1, sizeof(cpu->cpu_intserv_nums)); rc = get_property(cpu->ofdt_path, "ibm,ppc-interrupt-server#s", &cpu->cpu_intserv_nums, sizeof(cpu->cpu_intserv_nums)); /* Making sure the intserv_nums are in correct endian format */ for (i = 0; i < MAX_CPU_INTSERV_NUMS; i++) cpu->cpu_intserv_nums[i] = be32toh(cpu->cpu_intserv_nums[i]); if (rc) { say(ERROR, "Could not retrieve ibm,ppc-interrupt-server#s " "property for %s\n", cpu->name); return -1; } /* The number of threads is the number of 32-bit ints in the * cpu's ibm,ppc-interrupt-server#s property. */ sprintf(intserv_path, "/proc/device-tree/cpus/%s/ibm,ppc-interrupt-server#s", strstr(cpu->name, "PowerPC")); if (stat(intserv_path, &sb)) /* Assume no SMT */ cpu->cpu_nthreads = 1; else cpu->cpu_nthreads = sb.st_size / 4; rc = get_ofdt_uint_property(cpu->ofdt_path, "reg", &cpu->cpu_reg); if (rc) { say(ERROR, "Could not retrieve reg property for %s\n", cpu->name); return -1; } /* l2-cache may not exist */ cpu->cpu_l2cache = 0xffffffff; get_ofdt_uint_property(cpu->ofdt_path, "l2-cache", &cpu->cpu_l2cache); get_cpu_threads(cpu, dr_info->all_threads); cpu->is_owned = 1; return 0; } /** * init_cpu_info * @brief Initialize cpu information * * @returns pointer to cpu_info on success, NULL otherwise */ static int init_cpu_info(struct dr_info *dr_info) { struct dr_connector *drc_list, *drc; struct dr_node *cpu, *cpu_list = NULL; DIR *d; struct dirent *de; int rc = 0; drc_list = get_drc_info(CPU_OFDT_BASE); if (drc_list == NULL) { say(ERROR, "Could not get drc information for %s\n", CPU_OFDT_BASE); return -1; } /* For cpu dlpar, we need a list of all possible cpus on the system */ for (drc = drc_list; drc; drc = drc->next) { cpu = alloc_dr_node(drc, CPU_DEV, NULL); if (cpu == NULL) { say(ERROR, "Could not allocate CPU node structure: " "%s\n", strerror(errno)); free_node(cpu_list); return -1; } cpu->next = cpu_list; cpu_list = cpu; } d = opendir(CPU_OFDT_BASE); if (d == NULL) { say(ERROR, "Could not open %s: %s\n", CPU_OFDT_BASE, strerror(errno)); free_node(cpu_list); return -1; } while ((de = readdir(d)) != NULL) { char path[DR_PATH_MAX]; if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name)) continue; if (! strncmp(de->d_name, "PowerPC", 7)) { uint32_t my_drc_index; memset(path, 0, 1024); sprintf(path, "%s/%s", CPU_OFDT_BASE, de->d_name); rc = get_my_drc_index(path, &my_drc_index); if (rc) { say(ERROR, "Could not retrieve drc index for " "%s\n", path); break; } for (cpu = cpu_list; cpu; cpu = cpu->next) { if (cpu->drc_index == my_drc_index) break; } if (cpu == NULL) { say(ERROR, "Could not find cpu with drc index " "%x\n", my_drc_index); rc = -1; break; } rc = update_cpu_node(cpu, path, dr_info); if (rc) break; say(DEBUG, "Found cpu %s\n", cpu->name); } } closedir(d); if (rc) free_node(cpu_list); else dr_info->all_cpus = cpu_list; return rc; } /** * cpu_get_dependent_cache * @brief Return the cache whose ibm,phandle matches the given cpu's * l2-cache property. * * @param cpu * @returns pointer to cache_info on success, NULL otherwise */ struct cache_info * cpu_get_dependent_cache(struct dr_node *cpu, struct dr_info *dr_info) { struct cache_info * cache; for (cache = dr_info->all_caches; cache != NULL; cache = cache->next) { if (cache->removed) continue; if (cache->phandle == cpu->cpu_l2cache) { say(DEBUG, "found cache %s for cpu %s\n", cache->name, cpu->name); return cache; } } return NULL; } /** * cache_get_dependent_cache * @brief Return the cache whose ibm,phandle matches the given cache's * l2-cache property. * * @param cache * @returns pointer to cache_info on success, NULL otherwise */ struct cache_info * cache_get_dependent_cache(struct cache_info *cache, struct dr_info *dr_info) { struct cache_info *c; for (c = dr_info->all_caches; c != NULL; c = c->next) { if (cache->removed) continue; if (cache->phandle == cache->l2cache) { say(DEBUG, "found cache %s for cache %s\n", c->name, cache->name); return c; } } return NULL; } /** * cache_remove_devnode * @brief Remove the given cache device node from the kernel's device tree. * Also remove the cache from the global cache list. * * @param cache * @returns */ static int cache_remove_devnode(struct cache_info *cache) { int rc; rc = remove_device_tree_nodes(cache->path); if (!rc) cache->removed = 1; return rc; } /** * cache_get_use_count * @brief Calculate a cache's use count * * @param cache * @returns */ static int cache_get_use_count(struct cache_info *cache, struct dr_info *dr_info) { int count = 0; struct dr_node *cpu; struct cache_info *c; if (cache == NULL || cache->removed) return -1; /* Any cpu or cache node whose 'l2-cache' property matches * the ibm,phandle is using our cache */ for (cpu = dr_info->all_cpus; cpu != NULL; cpu = cpu->next) { if (!cpu->is_owned) continue; if (cache == cpu_get_dependent_cache(cpu, dr_info)) { say(DEBUG, "Cache %s is a dependent of cpu %s\n", cache->name, cpu->name); count++; } } for (c = dr_info->all_caches; c != NULL; c = c->next) { if (cache == cache_get_dependent_cache(c, dr_info)) { say(DEBUG, "Cache %s is a dependent of cache %s\n", cache->name, c->name); count++; } } say(DEBUG, "Cache %s dependency count: %d\n", cache->name, count); return count; } /** * free_cache_info * @brief free the cache list and any associated allocated memory * * @param cache_list list of cache structs to free */ void free_cache_info(struct cache_info *cache_list) { struct cache_info *tmp = cache_list; while (tmp != NULL) { cache_list = cache_list->next; free(tmp); tmp = cache_list; } } /** * init_cache_info * * @returns pointer to cache_info on success, NULL otherwise */ static int init_cache_info(struct dr_info *dr_info) { struct cache_info *cache_list = NULL; DIR *d; struct dirent *ent; int rc; d = opendir(CPU_OFDT_BASE); if (d == NULL) { say(ERROR, "Could not open %s: %s\n", CPU_OFDT_BASE, strerror(errno)); return -1; } while ((ent = readdir(d))) { char path[DR_PATH_MAX]; struct stat sb; /* skip everything but directories */ sprintf(path, "/proc/device-tree/cpus/%s", ent->d_name); if (lstat(path, &sb)) { say(ERROR, "Could not access %s,\nstat(): %s\n", path, strerror(errno)); break; } if (!S_ISDIR(sb.st_mode)) continue; if (strstr(ent->d_name, "-cache@")) { struct cache_info *cache; cache = zalloc(sizeof(*cache)); if (cache == NULL) { say(ERROR, "Could not allocate cache info." "\n%s\n", strerror(errno)); free_cache_info(cache_list); return -1; } snprintf(cache->name, DR_BUF_SZ, "%s", ent->d_name); snprintf(cache->path, DR_BUF_SZ, "%s", path); cache->removed = 0; cache->next = cache_list; cache_list = cache; rc = get_ofdt_uint_property(cache->path, "ibm,phandle", &cache->phandle); if (rc) { say(ERROR, "Could not retreive ibm,phandle " "property for %s\n", cache->path); free_cache_info(cache_list); return -1; } /* l3-caches do not have a l2-cache property */ cache->l2cache = 0xffffffff; get_ofdt_uint_property(cache->path, "l2-cache", &cache->l2cache); say(DEBUG, "Found cache %s\n", cache->name); } } closedir(d); dr_info->all_caches = cache_list; return 0; } /** * refresh_cache_info * * @returns 0 on success, !0 otherwise */ static int refresh_cache_info(struct dr_info *dr_info) { int rc; /* Some systems do not have cache device nodes. Assume * that if we did not find any cache nodes during initialization, * we won't find any during a refresh. */ if (dr_info->all_caches == NULL) return 0; free_cache_info(dr_info->all_caches); rc = init_cache_info(dr_info); if (rc) { say(ERROR, "failed to refresh cache information\n"); return rc; } return 0; } /** * acquire_cpu * * Acquire a new cpu for this partition from the hypervisor. * If drc_index is zero, look up an available index to use. * * @param drc_index * @returns pointer to cpu_info on success, NULL otherwise */ static int acquire_cpu(struct dr_node *cpu, struct dr_info *dr_info) { struct of_node *of_nodes; int rc; rc = acquire_drc(cpu->drc_index); if (rc) { say(DEBUG, "Could not acquire drc resources for %s\n", cpu->name); return rc; } of_nodes = configure_connector(cpu->drc_index); if (of_nodes == NULL) { say(ERROR, "Call to configure_connector failed for %s\n", cpu->name); release_drc(cpu->drc_index, CPU_DEV); return -1; } rc = add_device_tree_nodes(CPU_OFDT_BASE, of_nodes); free_of_node(of_nodes); if (rc) { say(ERROR, "Failure to add device tree nodes for %s\n", cpu->name); release_drc(cpu->drc_index, CPU_DEV); return rc; } update_cpu_node(cpu, NULL, dr_info); refresh_cache_info(dr_info); return 0; } int probe_cpu(struct dr_node *cpu, struct dr_info *dr_info) { char drc_index[DR_STR_MAX]; int probe_file; int write_len; int rc = 0; probe_file = open(CPU_PROBE_FILE, O_WRONLY); if (probe_file <= 0) { /* Attempt to add cpu from user-space, this may be an older * kernel without the infrastructure to handle dlpar. */ rc = acquire_cpu(cpu, dr_info); if (rc) return rc; rc = online_cpu(cpu, dr_info); if (rc) { /* Roll back the operation. Is this the correct * behavior? */ say(ERROR, "Unable to online %s\n", cpu->drc_name); offline_cpu(cpu); release_cpu(cpu, dr_info); cpu->unusable = 1; } } else { memset(drc_index, 0, DR_STR_MAX); write_len = sprintf(drc_index, "0x%x", cpu->drc_index); say(DEBUG, "Probing cpu 0x%x\n", cpu->drc_index); rc = write(probe_file, drc_index, write_len); if (rc != write_len) say(ERROR, "Probe failed! rc = %x\n", rc); else /* reset rc to success */ rc = 0; close(probe_file); } if (!rc) { update_cpu_node(cpu, NULL, dr_info); refresh_cache_info(dr_info); } return rc; } /** * release_caches * Remove any unused cache info. Failure to remove the cache, while not * good, should not affect the removal of the cpu. Additionally, the only * way to add the cache info back to the device tree is via a * configure-connector call which could then put multiple copies of any * cache that wasn't fully removed into the device tree. For these reasons * we ignore cache removal failures and do not try to recover. * * @param cpu * @param dr_info */ static void release_caches(struct dr_node *cpu, struct dr_info *dr_info) { struct cache_info *L2_cache, *L3_cache; int usecount, rc; L2_cache = cpu_get_dependent_cache(cpu, dr_info); usecount = cache_get_use_count(L2_cache, dr_info); if (usecount == 0) { L3_cache = cache_get_dependent_cache(L2_cache, dr_info); rc = cache_remove_devnode(L2_cache); if (rc) return; usecount = cache_get_use_count(L3_cache, dr_info); if (usecount == 0) cache_remove_devnode(L3_cache); } return; } /** * release_cpu * * Release a cpu back to the hypervisor, using the cpu's drc-index. * The cpu must have already been offlined. We remove the cpu from the * device tree only when the isolate and set_indicator have succeeded. * The caller must not use the value given for the cpu parameter after * this function has returned. * * @param cpu * @returns 0 on success, !0 otherwise */ int release_cpu(struct dr_node *cpu, struct dr_info *dr_info) { int release_file; int rc; release_file = open(CPU_RELEASE_FILE, O_WRONLY); if (release_file > 0) { /* DLPAR can be done in kernel */ char *path = cpu->ofdt_path + strlen(OFDT_BASE); int write_len = strlen(path); say(DEBUG, "Releasing cpu \"%s\"\n", path); rc = write(release_file, path, write_len); if (rc != write_len) say(ERROR, "Release failed! rc = %d\n", rc); else /* set rc to success */ rc = 0; close(release_file); } else { /* Must do DLPAR from user-space */ rc = offline_cpu(cpu); if (rc) { say(ERROR, "Could not offline cpu %s\n", cpu->drc_name); return rc; } rc = release_drc(cpu->drc_index, CPU_DEV); if (rc) { say(ERROR, "Could not release drc resources for %s\n", cpu->name); return rc; } rc = remove_device_tree_nodes(cpu->ofdt_path); if (rc) { struct of_node *of_nodes; say(ERROR, "Could not remove device tree nodes %s\n", cpu->name); of_nodes = configure_connector(cpu->drc_index); if (of_nodes == NULL) { say(ERROR, "Call to configure_connector failed " "for %s. The device tree\nmay contain " "invalid data for this cpu and a " "re-activation of the partition is " "needed to correct it.\n", cpu->name); } else { rc = add_device_tree_nodes(CPU_OFDT_BASE, of_nodes); free_of_node(of_nodes); } acquire_drc(cpu->drc_index); return rc; } release_caches(cpu, dr_info); } return rc; } /** * init_cpu_drc_info * * @returns pointer to drc_info on success, NULL otherwise */ int init_cpu_drc_info(struct dr_info *dr_info) { struct dr_node *cpu; struct thread *t; int rc; memset(dr_info, 0, sizeof(*dr_info)); rc = init_thread_info(dr_info); if (rc) { return -1; } rc = init_cpu_info(dr_info); if (rc) { free_cpu_drc_info(dr_info); return -1; } rc = init_cache_info(dr_info); if (rc) { free_cpu_drc_info(dr_info); return -1; } say(DEBUG, "Start CPU List.\n"); for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) { say(DEBUG, "%x : %s\n", cpu->drc_index, cpu->drc_name); for (t = cpu->cpu_threads; t; t = t->sibling) say(DEBUG, "\tthread: %d: %s\n", t->phys_id, t->path); } say(DEBUG, "Done.\n"); return 0; } /** * free_cpu_drc_info * @brief free the allocated lists hanging off of the drc_info struct * * @param dr_info dr_info struct to free memory from */ void free_cpu_drc_info(struct dr_info *dr_info) { free_cache_info(dr_info->all_caches); free_thread_info(dr_info->all_threads); free_node(dr_info->all_cpus); memset(dr_info, 0, sizeof(*dr_info)); } /** * set thread_state * @brief Set the thread state * * Set the given thread to the desired state. This just writes "1" or "0" * to /sys/devices/system/cpu/cpu[id]/online. * * @param thread * @param state * @returns 0 on success, !0 otherwise */ int set_thread_state(struct thread *thread, int state) { char path[DR_PATH_MAX]; FILE *file; int rc = 0; say(DEBUG, "%slining thread id %d\n", ((state == ONLINE) ? "On" : "Off"), thread->id); sprintf(path, DR_THREAD_ONLINE_PATH, thread->id); file = fopen(path, "w"); if (file == NULL) { say(ERROR, "Could not open %s, unable to set thread state " "to %d\n", path); return -1; } fprintf(file, "%d", state); fclose(file); /* fprintf apparently does not return negative number * if the write() gets an -EBUSY, so explicitly check the * thread state. */ if (state != get_thread_state(thread)) { say(ERROR, "Failure setting thread state for %s\n", path); rc = -1; } return rc; } /** * get_thread_state * @brief Get the "online" status of the given thread. * * @param thread * @returns 0 = offline, 1 = online, -1 on error */ int get_thread_state(struct thread *thread) { char path[DR_PATH_MAX]; int rc, status = -1; sprintf(path, DR_THREAD_ONLINE_PATH, thread->id); rc = get_int_attribute(path, NULL, &status, sizeof(status)); return rc ? rc : status; } /** * cpu_enable_smt * * For the given physical cpu, online all of its threads. * Just call online_spu for now. * * @param cpu cpu to enable smt on * @returns 0 on success, !0 otherwise */ int cpu_enable_smt(struct dr_node *cpu, struct dr_info *dr_info) { return online_cpu(cpu, dr_info); } /** * cpu_diable_smt * @brief Disable all but one of a cpu's threads * * @param cpu cpu to disable smt on * @returns 0 on success, !0 otherwise */ int cpu_disable_smt(struct dr_node *cpu) { int rc = 0; struct thread *t; int survivor_found = 0; /* Ensure that the first thread of the processor is the thread that is left online * when disabling SMT. */ t = cpu->cpu_threads; if (get_thread_state(t) == OFFLINE) rc |= set_thread_state(t, ONLINE); for (t = cpu->cpu_threads; t != NULL; t = t->sibling) { if (ONLINE == get_thread_state(t)) { if (survivor_found) rc |= set_thread_state(t, OFFLINE); survivor_found = 1; } } return rc; } /** * online_first_dead_cpu * @brief Find the first cpu with attributes online and physical_id both * set to 0 and online it. * * @param nthreads * @returns 0 on success, !0 otherwise */ int online_first_dead_cpu(int nthreads, struct dr_info *dr_info) { struct thread *thread; int rc = 1; for (thread = dr_info->all_threads; thread; thread = thread->next) { if (OFFLINE == get_thread_state(thread) && ((thread->phys_id == 0xffffffff) || (thread->phys_id == 0))) { /* just assume that there will be nthreads to online. */ while (nthreads--) { set_thread_state(thread, ONLINE); thread = thread->next; } rc = 0; break; } } if (rc) say(ERROR, "Could not find any threads to online\n"); return rc; } /** * offline_cpu * @brief Mark the specified cpu as offline * * @param cpu * @param dr_info * @returns 0 on success, !0 otherwise */ int offline_cpu(struct dr_node *cpu) { int rc = 0; struct thread *thread; say(DEBUG, "Offlining cpu %s (%d threads)\n", cpu->name, cpu->cpu_nthreads); for (thread = cpu->cpu_threads; thread; thread = thread->sibling) { if (get_thread_state(thread) != OFFLINE) rc |= set_thread_state(thread, OFFLINE); } return rc; } /** * online cpu * * @param cpu * @param dr_info * @returns 0 on success, !0 otherwise */ int online_cpu(struct dr_node *cpu, struct dr_info *dr_info) { int rc = 0; struct thread *thread = NULL; int found = 0; say(DEBUG, "Onlining cpu %s (%d threads)\n", cpu->name, cpu->cpu_nthreads); /* Hack to work around kernel brain damage (LTC 7692) */ for (thread = dr_info->all_threads; thread; thread = thread->next) { if (thread->cpu == cpu) { found = 1; break; } } if (!found) { /* There are no threads which match this cpu because * the physical_id attribute is not updated until the * cpu is onlined -- this case is for cpus which are * not present at boot but are added afterwards. */ return online_first_dead_cpu(cpu->cpu_nthreads, dr_info); } for (thread = cpu->cpu_threads; thread; thread = thread->sibling) { if (get_thread_state(thread) != ONLINE) rc |= set_thread_state(thread, ONLINE); } return rc; } /** * smt_enabled * @brief Is smt enabled? * * @returns 1 if smt enabled, 0 if not */ int smt_enabled(struct dr_info *dr_info) { struct dr_node *cpu; /* Just return true if the number of threads in the * first owned cpu is more than one. */ for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) { if (cpu->is_owned) break; } if (cpu && (cpu->cpu_nthreads > 1)) return 1; return 0; } /** * system_enable_smt * @brief Activate all threads of each cpu * * @returns 0 on success, !0 otherwise */ int system_enable_smt(struct dr_info *dr_info) { struct dr_node *cpu; int rc = 0; for (cpu = dr_info->all_cpus; cpu != NULL; cpu = cpu->next) { if (cpu->is_owned) rc |= cpu_enable_smt(cpu, dr_info); } return rc; } /** * system_disable_smt * @brief Offline all but one thread of each cpu * * @returns 0 on success, !0 otherwise */ int system_disable_smt(struct dr_info *dr_info) { struct dr_node *cpu; int rc = 0; for (cpu = dr_info->all_cpus; cpu != NULL; cpu = cpu->next) { if (cpu->is_owned) rc |= cpu_disable_smt(cpu); } return rc; } powerpc-utils-1.2.26/src/drmgr/common_ofdt.c0000664000175000017510000002225512527176005015730 00000000000000/** * @file common_ofdt.c * @brief Common routines for Open Firmware Device Tree access * * Copyright (C) IBM Corporation 2006 */ #include #include #include #include #include #include #include "dr.h" #include "ofdt.h" struct of_list_prop { char *_data; char *val; int n_entries; }; struct drc_prop_grp { struct of_list_prop drc_names; struct of_list_prop drc_types; struct of_list_prop drc_indexes; struct of_list_prop drc_domains; }; struct dr_connector *all_drc_lists = NULL; /** * get_of_list_prop * @breif retrieve the specified open firmware property list * * @param full_path * @param prop_name * @param prop * @returns 0 on success, !0 otherwise */ static int get_of_list_prop(char *full_path, char *prop_name, struct of_list_prop *prop) { int size, rc; size = get_property_size(full_path, prop_name); prop->_data = zalloc(size); if (prop->_data == NULL) return -1; rc = get_property(full_path, prop_name, prop->_data, size); if (rc) { free(prop->_data); return -1; } prop->n_entries = be32toh(*(uint *)prop->_data); prop->val = prop->_data + sizeof(uint); return 0; } /** * get_drc_prop_grp * * @param full_path * @param group * @returns 0 on success, !0 otherwise */ static int get_drc_prop_grp(char *full_path, struct drc_prop_grp *group) { struct stat sbuf; char fname[DR_PATH_MAX]; int rc; memset(group, 0, sizeof(*group)); sprintf(fname, "%s/%s", full_path, "ibm,drc-names"); rc = stat(fname, &sbuf); if (rc) return rc; rc = get_of_list_prop(full_path, "ibm,drc-names", &group->drc_names); if (rc) return rc; rc = get_of_list_prop(full_path, "ibm,drc-types", &group->drc_types); if (rc) return rc; rc = get_of_list_prop(full_path, "ibm,drc-indexes", &group->drc_indexes); if (rc) return rc; rc = get_of_list_prop(full_path, "ibm,drc-power-domains", &group->drc_domains); if (rc) return rc; return 0; } /** * free_drc_props * @brief free the properties associated with a drc group * * @param group */ static void free_drc_props(struct drc_prop_grp *group) { if (group->drc_names.val) free(group->drc_names._data); if (group->drc_types.val) free(group->drc_types._data); if (group->drc_indexes.val) free(group->drc_indexes._data); if (group->drc_domains.val) free(group->drc_domains._data); } /** * build_connectors_group * * @param group * @param n_entries * @param list * @returns 0 on success, !0 otherwise */ static int build_connectors_list(struct drc_prop_grp *group, int n_entries, struct dr_connector *list) { struct dr_connector *entry; unsigned int *index_ptr; unsigned int *domain_ptr; char *name_ptr; char *type_ptr; int i; index_ptr = (unsigned int *) group->drc_indexes.val; domain_ptr = (unsigned int *) group->drc_domains.val; name_ptr = group->drc_names.val; type_ptr = group->drc_types.val; for (i = 0; i < n_entries; i++) { entry = &list[i]; entry->index = be32toh(*(index_ptr++)); entry->powerdomain = be32toh(*(domain_ptr++)); strncpy(entry->name, name_ptr, DRC_STR_MAX); name_ptr += strlen(name_ptr) + 1; strncpy(entry->type, type_ptr, DRC_STR_MAX); type_ptr += strlen(type_ptr) + 1; if (i == (n_entries - 1)) entry->next = NULL; else entry->next = &list[i+1]; } return 0; } /** * of_to_full_path * * NOTE: Callers of this function are expected to free full_path themselves * * @param of_path * @returns full path on success, NULL otherwise */ char * of_to_full_path(const char *of_path) { char *full_path = NULL; int full_path_len; if (!strncmp(of_path, OFDT_BASE, strlen(OFDT_BASE))) { full_path = strdup(of_path); if (full_path == NULL) return NULL; } else { full_path_len = strlen(OFDT_BASE) + strlen(of_path) + 2; full_path = zalloc(full_path_len); if (full_path == NULL) return NULL; if (*of_path == '/') sprintf(full_path, "%s%s", OFDT_BASE, of_path); else sprintf(full_path, "%s/%s", OFDT_BASE, of_path); } return full_path; } /** * get_dr_connectors * * NOTE:Callers of this function are expected to free drc_list themselves * * @param of_path * @param drc_list * @param n_drcs * @returns 0 on success, !0 otherwise */ struct dr_connector * get_drc_info(const char *of_path) { struct dr_connector *list = NULL; struct of_list_prop *drc_names; struct drc_prop_grp prop_grp; char *full_path = NULL; int rc, n_drcs; full_path = of_to_full_path(of_path); if (full_path == NULL) goto done; for (list = all_drc_lists; list; list = list->all_next) { if (! strcmp(list->ofdt_path, of_path)) return list; } rc = get_drc_prop_grp(full_path, &prop_grp); if (rc) { say(DEBUG, "Could not find DRC property group in path: %s.\n", full_path); goto done; } drc_names = &prop_grp.drc_names; n_drcs = drc_names->n_entries; list = zalloc(n_drcs * sizeof(struct dr_connector)); if (list == NULL) goto done; /* XXX Unchecked rc */ rc = build_connectors_list(&prop_grp, n_drcs, list); snprintf(list->ofdt_path, DR_PATH_MAX, "%s", of_path); list->all_next = all_drc_lists; all_drc_lists = list; done: free_drc_props(&prop_grp); if (full_path) free(full_path); return list; } /** * free_drc_info * * @param drc_list */ void free_drc_info(void) { struct dr_connector *list; while (all_drc_lists) { list = all_drc_lists; all_drc_lists = list->all_next; free(list); } } /** * search_drc_list * * @param drc_list * @param n_entries * @param start * @param search_type * @param key * @param found_idx * @returns pointer to dr_connector on success, NULL otherwise */ struct dr_connector * search_drc_list(struct dr_connector *drc_list, struct dr_connector *start, int search_type, void *key) { struct dr_connector *drc; if (start) drc = start; else drc = drc_list; for ( ; drc != NULL; drc = drc->next) { switch (search_type) { case DRC_NAME: if (! strcmp(drc->name, (char *)key)) return drc; break; case DRC_TYPE: if (! strcmp(drc->type, (char *)key)) return drc; break; case DRC_INDEX: if (drc->index == *(uint32_t *)key) return drc; break; case DRC_POWERDOMAIN: if (drc->powerdomain == *(uint32_t *)key) return drc; }; } return NULL; } /** * get_my_drc_index * * @param of_path * @param index * @returns 0 on success, !0 otherwise */ int get_my_drc_index(char *of_path, uint32_t *index) { char *full_path = NULL; int rc; full_path = of_to_full_path(of_path); if (full_path == NULL) return -1; rc = get_ofdt_uint_property(full_path, "ibm,my-drc-index", index); free(full_path); return rc; } /** * drc_name_to_index * @brief Find the drc index for the given name * * @param name name to find * @returns drc index corresponding to name on success, 0 otherwise */ int drc_name_to_index(const char *name, struct dr_connector *drc_list) { struct dr_connector *drc; for (drc = drc_list; drc != NULL; drc = drc->next) { if (!strcmp(name, drc->name)) return drc->index; } return 0; /* hopefully 0 isn't a valid index... */ } /** * drc_index_to_name * @brief find the drc name for the specified drc index * * @param index * @returns drc name on success, NULL otherwise */ char * drc_index_to_name(uint32_t index, struct dr_connector *drc_list) { struct dr_connector *drc; for (drc = drc_list; drc != NULL; drc = drc->next) { if (index == drc->index) return drc->name; } return NULL; } /** * get_drc_by_name * @brief Retrieve a dr_connector with the specified drc_name * * This routine searches the drc lists for a dr_connector with the * specified name starting at the specified directory. If a dr_connector * is found the root_dir that the dr_connector was found in is also * filled out. * * @param drc_name name of the dr_connector to search for * @param drc pointer to a drc to point to the found dr_connector * @param root_dir pointer to buf to fill in with root directory * @param start_dir, directory to start searching * @returns 0 on success (drc and root_dir filled in), !0 on failure */ int get_drc_by_name(char *drc_name, struct dr_connector *drc, char *root_dir, char *start_dir) { struct dr_connector *drc_list = NULL; struct dr_connector *drc_entry; struct dirent *de; DIR *d; int rc = -1; memset(drc, 0, sizeof(*drc)); /* Try to get the drc in this directory */ drc_list = get_drc_info(start_dir); if (drc_list == NULL) return -1; drc_entry = search_drc_list(drc_list, NULL, DRC_NAME, drc_name); if (drc_entry != NULL) { memcpy(drc, drc_entry, sizeof(*drc)); sprintf(root_dir, "%s", start_dir); return 0; } /* If we didn't find it here, check the subdirs */ d = opendir(start_dir); if (d == NULL) return -1; while ((de = readdir(d)) != NULL) { char dir_path[DR_PATH_MAX]; if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name)) continue; sprintf(dir_path, "%s/%s", start_dir, de->d_name); rc = get_drc_by_name(drc_name, drc, root_dir, dir_path); if (rc == 0) break; } closedir(d); return rc; } struct dr_connector * get_drc_by_index(uint32_t drc_index, struct dr_connector *drc_list) { struct dr_connector *drc; for (drc = drc_list; drc; drc = drc->next) { if (drc->index == drc_index) return drc; } return NULL; } powerpc-utils-1.2.26/src/drmgr/common_pci.c0000664000175000017510000007612212542271360015546 00000000000000/** * @file common_pci.c * @brief Common routines for pci data * * Copyright (C) IBM Corporation 2006 * */ #include #include #include #include #include #include #include #include #include #include #include "dr.h" #include "drpci.h" #include "ofdt.h" /** * alloc_node * * XXX: This doesn't do any cleanup on error conditions. could be bad. * * @param drc * @param dev_type * @param of_path * @returns pointer to node on success, NULL otherwise */ struct dr_node * alloc_dr_node(struct dr_connector *drc, int dev_type, const char *of_path) { struct dr_node *node; node = zalloc(sizeof(*node)); if (node == NULL) return NULL; node->dev_type = dev_type; set_drc_info(node, drc); if (of_path) { get_property(of_path, "ibm,loc-code", node->loc_code, sizeof(node->loc_code)); snprintf(node->ofdt_path, DR_PATH_MAX, "%s", of_path); } return node; } /** * find_ofdt_dname * * Find "name" of the device_node that is a child * of given node and its "ibm,loc-code" is the same * as node->name. * * @param node * @param path * @param ofdt_dname */ static int find_ofdt_dname(struct dr_node *node, char *path) { DIR *d = NULL; struct dirent *de; struct stat sb; char new_path[DR_PATH_MAX]; char loc_code[DR_BUF_SZ]; char *q; int found = 0; int rc; rc = get_property(path, "ibm,loc-code", &loc_code, DR_BUF_SZ); if ((rc == 0) && (strstr(loc_code, node->drc_name))) { rc = get_property(path, "name", node->ofdt_dname, sizeof(node->ofdt_dname)); if (rc == 0) return 1; } /* First look for a ofdt node that has ibm,loc-code property * with a value that matches node->name. * * Set node->node->ofdt_dname to "name" of the ofdt node. */ d = opendir(path); if (d == NULL) { say(ERROR, "Could not open dir %s\n%s\n", path, strerror(errno)); return 0; } strcpy(new_path, path); q = new_path + strlen(new_path); *q++ = '/'; while(((de = readdir(d)) != NULL) && (! found)) { /* skip all dot files */ if (de->d_name[0] == '.') continue; strcpy(q, de->d_name); if (lstat(new_path, &sb) < 0) continue; if (S_ISLNK(sb.st_mode)) continue; if (S_ISDIR(sb.st_mode)) { rc = get_property(path, "ibm,loc-code", &loc_code, DR_BUF_SZ); if ((rc != 0) || (! strstr(loc_code, node->drc_name))) { found = find_ofdt_dname(node, new_path); continue; } rc = get_property(path, "name", node->ofdt_dname, sizeof(node->ofdt_dname)); if (rc == 0) { found = 1; break; } } } if (d != NULL) closedir(d); return found; } /** * add_child_node * * Create information about the Open Firmware node and * add that information to the appropriate per-node list of * Open Firmware nodes. Also create the corresponding information * for any PCI device. * * NOTES: * 1) does not need to be concerned about one or more Open * Firmware nodes having the used-by-rtas property present. * One of the RTAS services used during removing a PCI adapter * must take the appropriate action (most likely eliminate RTAS * usage) in this case. * 2) Open Firmware node RPA physical location code: * * [Un.m-]Pn[-Pm]-In[[/Zn]-An] * * where * Un.m is for the enclosure for multi-enclosue systems * Pn is for the planar * In is for the slot * /Zn is for the connector on the adapter card * An is for the device connected to the adapter * * note * There may be multiple levels of planars [Pm]. * * RECOVERY OPERATION: * 1) This function does not add the Open Firmware node if the user * mode process has exceeded all available malloc space. This * should not happen based on the rather small total amount of * memory allocation required. The node is marked as skip. * 2) This function does not add the device information if there * is a problem initializing device. The node is marked as skip. * * @param parent * @param child_path */ static void add_child_node(struct dr_node *parent, char *child_path) { struct dr_connector *drc_list, *drc; char loc_code[DR_BUF_SZ]; char *slash; struct dr_node *child; uint my_drc_index; int rc; assert(parent != NULL); assert(strlen(child_path) != 0); /* Make sure that the Open Firmware node is not added twice * in case the ibm,my-drc-index property is put in all nodes * for the adapter instead of just the ones at the connector. */ if (parent->children != NULL) { struct dr_node *tmp; for (tmp = parent->children; tmp; tmp = tmp->next) { if (! strcmp(tmp->ofdt_path, child_path)) return; } } /* Create the Open Firmware node's information and insert that * information into the node's list based on the node's RPA * physical location code. Ignore the OF node if the node * does not have an RPA physical location code because that is * a firmware error. */ rc = get_property(child_path, "ibm,loc-code", &loc_code, DR_BUF_SZ); if (rc) return; /* Skip the Open Firmware node if it is a device node. Determine that * the node is for a device by looking for a hyphen after the last * slash (...-In/Z1-An). */ slash = strrchr(loc_code, '/'); if (slash != NULL) { char *hyphen; hyphen = strchr(slash, '-'); if (hyphen != NULL) return; *slash = '\0'; } if (parent->dev_type == PCI_HP_DEV) { /* hotplug */ /* Squadrons don't have "/" in devices' (scsi, * ethernet, tokenring ...) loc-code strings. * * Skip the Open Firmware node if the node's RPA * physical location code does not match the node's * location code. Ignore the connector information, * i.e. information after last slash if no hyphen * follows. */ if ((strcmp(parent->drc_name, loc_code) != 0) && (slash != NULL)) { parent->skip = 1; return; } } /* Restore the slash because the full RPA location code * is saved for each OF node so that the connector * information can be used to sort the OF node list for * each node. */ if (slash != NULL) *slash = '/'; if (get_my_drc_index(child_path, &my_drc_index)) return; /* need the drc-info in the dir above */ slash = strrchr(child_path, '/'); *slash = '\0'; drc_list = get_drc_info(child_path); *slash = '/'; for (drc = drc_list; drc != NULL; drc = drc->next) { if (drc->index == my_drc_index) break; } /* Allocate space for the Open Firmware node information. */ child = alloc_dr_node(drc, parent->dev_type, child_path); if (child == NULL) { parent->skip = 1; return; } if ((! strcmp(parent->drc_type, "SLOT")) && (parent->dev_type == PCI_DLPAR_DEV)) snprintf(child->ofdt_dname, DR_STR_MAX, "%s", parent->ofdt_dname); else get_property(child_path, "name", child->ofdt_dname, sizeof(child->ofdt_dname)); switch (parent->dev_type) { case PCI_HP_DEV: case PCI_DLPAR_DEV: { get_ofdt_uint_property(child_path, "vendor-id", &child->pci_vendor_id); get_ofdt_uint_property(child_path, "device-id", &child->pci_device_id); get_ofdt_uint_property(child_path, "class_code", &child->pci_class_code); break; } case HEA_DEV: { child->dev_type = HEA_PORT_DEV; get_ofdt_uint_property(child_path, "ibm,hea-port-no", &child->hea_port_no); get_ofdt_uint_property(child_path, "ibm,hea-port-tenure", &child->hea_port_tenure); break; } } child->next = parent->children; parent->children = child; } /* This forward declaration is needed because init_node and examine_child * call each other. */ static int examine_child(struct dr_node *, char *); /** * init_node * * @param node * @returns 0 on success, !0 otherwise */ static int init_node(struct dr_node *node) { struct dirent **de_list, *de; char *newpath; int count; int rc, i; if (node->is_owned) find_ofdt_dname(node, node->ofdt_path); count = scandir(node->ofdt_path, &de_list, 0, alphasort); for (i = 0; i < count; i++) { de = de_list[i]; if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name)) continue; newpath = zalloc(strlen(node->ofdt_path) + strlen(de->d_name) + 2); if (newpath == NULL) { say(ERROR, "Could not allocate path for node at " "%s/%s\n", node->ofdt_path, de->d_name); return 1; } sprintf(newpath, "%s/%s", node->ofdt_path, de->d_name); rc = examine_child(node, newpath); if (rc) return rc; } return 0; } /** * examine_children * * @param node * @param child_path * @returns 0 on success, !0 otherwise */ static int examine_child(struct dr_node *node, char *child_path) { uint32_t my_drc_index; int used = 0; int rc = 0; if (get_my_drc_index(child_path, &my_drc_index)) goto done; if (node->dev_type == PCI_HP_DEV) { if (node->drc_index == my_drc_index) { /* Add hotplug children */ add_child_node(node, child_path); used = 1; } } else { if (! node->is_owned) { if (node->drc_index == my_drc_index) { /* Update node path */ snprintf(node->ofdt_path, DR_PATH_MAX, "%s", child_path); node->is_owned = 1; used = 1; /* Populate w/ children */ rc = init_node(node); } } else { /* Add all DR-capable children */ add_child_node(node, child_path); used = 1; } } done: if (! used) free(child_path); return rc; } static inline int is_hp_type(char *type) { return (strtoul(type, NULL, 10) > 0); } static inline int is_logical_type(char *type) { return (!strcmp(type, "SLOT")); } /** * free_node * @brief free a list of node struct and any allocated memory they reference * * @param node_list list of nodes to free */ void free_node(struct dr_node *node_list) { struct dr_node *node; if (node_list == NULL) return; while (node_list) { node = node_list; node_list = node->next; if (node->children) free_node(node->children); if (node->dev_type == MEM_DEV) { struct mem_scn *mem_scn; while (node->lmb_mem_scns != NULL) { mem_scn = node->lmb_mem_scns; node->lmb_mem_scns = mem_scn->next; free(mem_scn); } if (node->lmb_of_node) free(node->lmb_of_node); } free(node); } } /** * devspec_check_node * * @param node * @param sysfs_path * @param full_of_path * @param found * @returns 0 on success, !0 otherwise */ static int devspec_check_node(struct dr_node *node, char *sysfs_path, char *full_of_path, int *found) { struct dr_node *child; *found = 0; if (node->ofdt_path == NULL) return 0; if (! strcmp(full_of_path, node->ofdt_path)) { snprintf(node->sysfs_dev_path, DR_PATH_MAX, "%s", sysfs_path); *found = 1; return 0; } for (child = node->children; child; child = child->next) { if (! strcmp(full_of_path, child->ofdt_path)) { snprintf(child->sysfs_dev_path, DR_PATH_MAX, "%s", sysfs_path); *found = 1; return 0; } } return 0; } /** * correlate_devspec * * @param sysfs_path * @param ofdt_path */ static int correlate_devspec(char *sysfs_path, char *ofdt_path, struct dr_node *node_list) { struct dr_node *node; char *full_of_path; int found; int rc; full_of_path = of_to_full_path(ofdt_path); for (node = node_list; node != NULL; node = node->next) { rc = devspec_check_node(node, sysfs_path, full_of_path, &found); if (rc) return rc; if (found) break; } free(full_of_path); return 0; } /** * add_linux_devices * */ static void add_linux_devices(char *start_dir, struct dr_node *node_list) { struct dirent *de; DIR *d; char *dir; int rc; if (start_dir == NULL) dir = "/sys/devices"; else dir = start_dir; d = opendir(dir); if (d == NULL) { say(ERROR, "failed to open %s\n%s\n", dir, strerror(errno)); return; } while ((de = readdir(d)) != NULL) { char buf[1024]; if (is_dot_dir(de->d_name)) continue; if (de->d_type == DT_DIR) { sprintf(buf, "%s/%s", dir, de->d_name); add_linux_devices(buf, node_list); } else if (! strcmp(de->d_name, "devspec")) { char devspec[DR_PATH_MAX]; sprintf(buf, "%s/%s", dir, de->d_name); rc = get_str_attribute(buf, NULL, devspec, DR_PATH_MAX); if (rc == 0) rc = correlate_devspec(dir, devspec, node_list); } } closedir(d); } /** * add_hea_node * @brief Add a node for an HEA adapter * * @param path ofdt_path to this node * @param drc_list list of drc's at OFDT_BASE * @param pointer to the node list to add new nodes to * @return 0 on success, !0 otherwise */ static int add_hea_node(char *path, struct dr_connector *drc_list, struct dr_node **node_list) { struct dr_connector *drc; struct dr_node *hea_node; uint my_drc_index; int rc; if (drc_list == NULL) return -1; if (get_my_drc_index(path, &my_drc_index)) return -1; for (drc = drc_list; drc != NULL; drc = drc->next) { if (drc->index == my_drc_index) break; } if (drc == NULL) { say(ERROR, "Could not find drc index 0x%x to add to hea list\n", my_drc_index); return -1; } hea_node = alloc_dr_node(drc, HEA_DEV, path); if (hea_node == NULL) { say(ERROR, "Could not allocate hea node for drc index 0x%x\n", my_drc_index); return -1; } hea_node->is_owned = 1; rc = init_node(hea_node); if (rc) { free(hea_node); return -1; } hea_node->next = *node_list; *node_list = hea_node; return 0; } /** * add_pci_vio_node * @bried Add a PCI or virtual device node * * @param path ofdt path to this node * @param dev_type type of device * @param node_list pointer to list to add node to * @returns 0 on success, !0 otherwise */ static int add_pci_vio_node(const char *path, int dev_type, struct dr_node **node_list) { struct dr_connector *drc_list; struct dr_connector *drc; struct dr_node *node; int child_dev_type = 0; int rc = -1; drc_list = get_drc_info(path); if (drc_list == NULL) return -1; for (drc = drc_list; drc != NULL; drc = drc->next) { switch (dev_type) { case PCI_HP_DEV: if (! is_hp_type(drc->type)) continue; child_dev_type = dev_type; break; case PCI_DLPAR_DEV: case VIO_DEV: if (! is_logical_type(drc->type)) continue; child_dev_type = dev_type; break; case PHB_DEV: if (is_logical_type(drc->type)) child_dev_type = PCI_DLPAR_DEV; else child_dev_type = PCI_HP_DEV; break; } node = alloc_dr_node(drc, child_dev_type, path); if (node == NULL) { say(ERROR, "Could not allocate pci/vio node\n"); return -1; } if (child_dev_type == PCI_HP_DEV) node->is_owned = 1; rc = init_node(node); if (rc) { free(node); return rc; } node->next = *node_list; *node_list = node; } return rc; } /** * add_phb_node * @brief Add a PHB node to the node list * * @param ofdt_poath, ofdt path to this node * @param drc_list list of drc's at OFDT_BASE * @param node_list list of nodes to add node to * @returns 0 on success, !0 otherwise */ static int add_phb_node(char *ofdt_path, struct dr_connector *drc_list, struct dr_node **node_list) { struct dr_node *phb_node; struct dr_connector *drc; uint my_drc_index; if (get_my_drc_index(ofdt_path, &my_drc_index)) return -1; for (drc = drc_list; drc; drc = drc->next) { if (drc->index == my_drc_index) break; } if (drc == NULL) { say(ERROR, "Could not find drc index 0x%x to add to phb list\n", my_drc_index); return -1; } phb_node = alloc_dr_node(drc, PHB_DEV, ofdt_path); if (phb_node == NULL) { say(ERROR, "Could not allocate PHB node for drc index 0x%x\n", my_drc_index); return -1; } phb_node->is_owned = 1; add_pci_vio_node(ofdt_path, PHB_DEV, &phb_node->children); phb_node->next = *node_list; *node_list = phb_node; return 0; } /** * update_phb_ic_info * @brief Add interrupt controller information to PHB nodes * * We need to have the interrupt-controller ofdt paths for all PHB * nodes to do DLPAR. This routine adds that information for PHB nodes * that we found. * * @param node_list list of PHB nodes * @returns 0 on success, !0 otherwise */ static int update_phb_ic_info(struct dr_node *node_list) { char *ic_dir = "interrupt-controller"; struct dr_node *node; struct dirent *de; DIR *d; int rc = 0; d = opendir(OFDT_BASE); if (d == NULL) { say(ERROR, "failed to open %s\n%s\n", OFDT_BASE, strerror(errno)); return -1; } while ((de = readdir(d)) != NULL) { uint my_drc_index; char ofdt_path[DR_PATH_MAX]; if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name)) continue; if (strncmp(de->d_name, ic_dir, strlen(ic_dir))) continue; sprintf(ofdt_path, "%s/%s", OFDT_BASE, de->d_name); rc = get_my_drc_index(ofdt_path, &my_drc_index); if (rc) /* This is expected to fail sometimes, as there can be * more ICs than PHBs on a system. In this case, some * ICs won't have my-drc-index. */ continue; for (node = node_list; node; node = node->next) { if ((node->dev_type == PHB_DEV) && (node->drc_index == my_drc_index)) { snprintf(node->phb_ic_ofdt_path, DR_PATH_MAX, "%s", ofdt_path); break; } } } closedir(d); return 0; } /** * get_dlpar_nodes * * @param list_type * @returns pointer to node list on success, NULL otherwise */ struct dr_node * get_dlpar_nodes(uint32_t node_types) { struct dr_connector *drc_list = NULL; struct dr_node *node_list = NULL; struct dirent *de; DIR *d; char path[1024]; say(DEBUG, "Getting node types 0x%08x\n", node_types); d = opendir(OFDT_BASE); if (d == NULL) { say(ERROR, "failed to open %s\n%s\n", OFDT_BASE, strerror(errno)); return NULL; } while ((de = readdir(d)) != NULL) { if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name)) continue; memset(path, 0, 1024); sprintf(path, "%s/%s", OFDT_BASE, de->d_name); if ((! strcmp(de->d_name, "vdevice")) && (node_types & VIO_NODES)) add_pci_vio_node(path, VIO_DEV, &node_list); else if (! strncmp(de->d_name, "pci@", 4)) { if (node_types & PCI_NODES) add_pci_vio_node(path, PCI_DLPAR_DEV, &node_list); else if (node_types & PHB_NODES) { if (drc_list == NULL) drc_list = get_drc_info(OFDT_BASE); add_phb_node(path, drc_list, &node_list); } } else if ((! strncmp(de->d_name, "lhea@", 5)) && (node_types & HEA_NODES)) { if (drc_list == NULL) drc_list = get_drc_info(OFDT_BASE); add_hea_node(path, drc_list, &node_list); } } closedir(d); if (node_list != NULL) { add_linux_devices(NULL, node_list); if (node_types & PHB_NODES) update_phb_ic_info(node_list); } return node_list; } /** * _get_hp_nodes * @brief The workhorse routine for finding hotplug nodes * * @param dir start directory for searching * @param pointer to list of nodes to return * @return 0 on success, !0 otherwise */ static int _get_hp_nodes(char *dir, struct dr_node **list) { struct dirent *de; DIR *d; char path[1024]; d = opendir(dir); if (d == NULL) { say(ERROR, "failed to open %s\n%s\n", dir, strerror(errno)); return -1; } while ((de = readdir(d)) != NULL) { if ((de->d_type != DT_DIR) || is_dot_dir(de->d_name)) continue; if (strncmp(de->d_name, "pci@", 4)) continue; memset(path, 0, 1024); sprintf(path, "%s/%s", dir, de->d_name); add_pci_vio_node(path, PCI_HP_DEV, list); _get_hp_nodes(path, list); } closedir(d); return 0; } /** * get_hp_nodes * @brief retrieve a list of hotplug nodes on the partition * * @return pointer to node list on success, NULL on failure */ struct dr_node * get_hp_nodes() { struct dr_node *node_list = NULL; say(DEBUG, "Retrieving hotplug nodes\n"); _get_hp_nodes(OFDT_BASE, &node_list); if (node_list != NULL) add_linux_devices(NULL, node_list); return node_list; } struct dr_node * get_node_by_name(const char *drc_name, uint32_t node_type) { struct dr_node *node, *all_nodes; struct dr_node *prev_node = NULL; int child_found = 0; all_nodes = get_dlpar_nodes(node_type); if (all_nodes == NULL) { say(ERROR, "There are no DR capable slots on this system\n"); return NULL; } print_node_list(all_nodes); for (node = all_nodes; node; node = node->next) { struct dr_node *child; uint32_t drc_index; if (strcmp(node->drc_name, drc_name) == 0) break; /* See if the drc index was specified */ drc_index = strtoul(drc_name, NULL, 0); if (node->drc_index == drc_index) continue; for (child = node->children; child; child = child->next) { if (strcmp(drc_name, child->drc_name) == 0) child_found = 1; if (child->drc_index == drc_index) child_found = 1; } if (child_found) break; prev_node = node; } if (node) { if (prev_node) prev_node->next = node->next; else /* First in list */ all_nodes = all_nodes->next; node->next = NULL; } free_node(all_nodes); return node; } /** * cmp_drcname * * Compare the drcname's opf two nodes * * @param name1 * @param name2 * @returns 1 if the drcnames match, 0 otherwise */ int cmp_drcname(char *name1, char *name2) { char *ptr; if (name2 == NULL) return 0; /* The string pointed to by name2 may in fact be a location code * for a device in a PCI node. Hence, its hardware location * code will not match exactly. However, if this is the case, * the substring in the device location code up to the first '/' * character should match the node's location exactly. * * If there's a '/' in name2, then shorten string to the * LAST '/' character. * Note: this affects name2 globally! */ ptr = strrchr(name2, '/'); if (ptr != NULL) /* End the string at the '/' * compiler doesn't like NULL --Linda */ *ptr = '\0'; /* Now compare */ return (! strcmp(name1, name2)); } /** * get_bus_id * * @param loc_code * @returns */ static char * get_bus_id(char *loc_code) { DIR *d; struct dirent *ent; char *dir = "/sys/bus/pci/slots"; int inlen; char *ptr; /* Strip any newline from the input location */ if ((ptr = strchr(loc_code, '\n')) != NULL) inlen = ptr - loc_code; else inlen = strlen(loc_code); d = opendir(dir); if (d == NULL) { say(ERROR, "failed to open %s: %s\n", dir, strerror(errno)); return NULL; } while ((ent = readdir(d))) { char path[DR_PATH_MAX], location[DR_BUF_SZ]; FILE *f; if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; sprintf(path, "/sys/bus/pci/slots/%s/phy_location", ent->d_name); f = fopen(path, "r"); if (f == NULL) continue; fread(location, sizeof(location), 1, f); fclose(f); /* Strip any newline from the location to compare */ if ((ptr = strchr(location, '\n')) != NULL) *ptr = '\0'; if ((strlen(location) == inlen && !strncmp(loc_code, location, inlen))) { char *bus_id; bus_id = strdup(ent->d_name); if (bus_id) return bus_id; else { say(ERROR, "Failed to allocate bus id\n"); break; } } } closedir(d); return NULL; } /** * get_hp_adapter_status * @brief check adapter status * * @param drc_name * @returns 0 if slot is empty * @returns 1 if adapter is configured * @returns 2 if adapter is not configured * @returns <0 on error */ int get_hp_adapter_status(char *drc_name) { int value, rc = 0; char path[DR_PATH_MAX], *bus_id; bus_id = get_bus_id(drc_name); if (bus_id) sprintf(path, PHP_SYSFS_ADAPTER_PATH, bus_id); else sprintf(path, PHP_SYSFS_ADAPTER_PATH, drc_name); rc = get_int_attribute(path, NULL, &value, sizeof(value)); if (rc) return -1; say(DEBUG, "hp adapter status for %s is %d\n", drc_name, value); rc = value; if (rc != CONFIG && rc != NOT_CONFIG && rc != EMPTY) rc = -1; return rc; } /** * set_hp_adapter_status * * @param operation 1=> config 0=> unconfig * @param slot_name * @returns 0 on success, !0 otherwise */ int set_hp_adapter_status(uint operation, char *slot_name) { int rc = 0; FILE *file; char *bus_id; char path[DR_PATH_MAX]; bus_id = get_bus_id(slot_name); if (bus_id) sprintf(path, PHP_SYSFS_POWER_PATH, bus_id); else sprintf(path, PHP_SYSFS_POWER_PATH, slot_name); say(DEBUG, "setting hp adapter status to %s for %s\n", ((operation+1 - 1) ? "CONFIG adapter" : "UNCONFIG adapter"), slot_name); file = fopen(path, "w"); if (file == NULL) { say(ERROR, "failed to open %s: %s\n", path, strerror(errno)); return -ENODEV; } rc = fwrite((operation+1 - 1) ? "1" : "0", 1, 1, file); if (rc != 1) rc = -EACCES; else rc = 0; fclose(file); return rc; } /** * pci_rescan_bus * * @returns 0 on success, !0 otherwise */ int pci_rescan_bus() { int rc = 0; FILE *file; file = fopen(PCI_RESCAN_PATH, "w"); if (file == NULL) { say(ERROR, "failed ot open %s: %s\n", PCI_RESCAN_PATH, strerror(errno)); return -ENODEV; } rc = fwrite("1", 1, 1, file); if (rc != 1) rc = -EACCES; fclose(file); return rc; } /** * pci_remove_device * * @returns 0 on success, !0 otherwise */ int pci_remove_device(struct dr_node *node) { int rc = 0; FILE *file; char path[DR_PATH_MAX]; sprintf(path, "%s/%s", node->sysfs_dev_path, "remove"); file = fopen(path, "w"); if (file == NULL) { say(ERROR, "failed to open %s: %s\n", path, strerror(errno)); return -ENODEV; } rc = fwrite("1", 1, 1, file); if (rc != 1) rc = -EACCES; fclose(file); return rc; } /** * dlpar_io_kernel_op * @brief access kernel interface files * * @param interface_file * @param drc_name * @returns 0 on success, !0 otherwise */ static int dlpar_io_kernel_op(const char *interface_file, const char *drc_name) { int rc = 0, len; FILE *file; len = strlen(drc_name); say(DEBUG, "performing kernel op for %s, file is %s\n", drc_name, interface_file); do { errno = 0; file = fopen(interface_file, "r+"); if (file == NULL) { say(ERROR, "failed to open %s: %s\n", interface_file, strerror(errno)); return -ENODEV; } rc = fwrite(drc_name, 1, len, file); fclose(file); sleep(1); if (drmgr_timed_out()) return -1; } while (errno == EBUSY); if (errno || (rc != len)) { say(ERROR, "kernel I/O op failed, rc = %d len = %d.\n%s\n", rc, len, strerror(errno)); return errno ? errno : rc; } return 0; } int dlpar_remove_slot(const char *drc_name) { return dlpar_io_kernel_op(remove_slot_fname, drc_name); } int dlpar_add_slot(const char *drc_name) { return dlpar_io_kernel_op(add_slot_fname, drc_name); } void print_node_list(struct dr_node *first_node) { struct dr_node *parent; struct dr_node *child; parent = first_node; say(DEBUG, "\nDR nodes list\n==============\n"); while (parent) { say(DEBUG, "%s: %s\n" "\tdrc index: 0x%x description: %s\n" "\tdrc name: %s\n\tloc code: %s\n", parent->ofdt_path, (parent->skip ? "(SKIP)" : ""), parent->drc_index, node_type(parent), parent->drc_name, parent->loc_code); child = parent->children; while (child) { say(DEBUG, "%s: %s\n" "\tdrc index: 0x%x description: %s\n" "\tdrc name: %s\n\tloc code: %s\n", child->ofdt_path, (child->skip ? "(SKIP)" : ""), child->drc_index, node_type(child), child->drc_name, child->loc_code); child = child->next; } parent = parent->next; } say(DEBUG, "\n"); } #define ACQUIRE_HP_START 2 #define ACQUIRE_HP_SPL 3 #define ACQUIRE_HP_UNISO 4 #define ACQUIRE_HP_CFGCONN 5 #define ACQUIRE_HP_ADDNODES 6 /** * acquire_hp_resource * * @param drc * @param of_path * @returns 0 on success, !0 otherwise */ static int acquire_hp_resource(struct dr_connector *drc, char *of_path) { struct of_node *new_nodes; int progress = ACQUIRE_HP_START; int state; int rc; state = dr_entity_sense(drc->index); if (state == PRESENT || state == NEED_POWER || state == PWR_ONLY) { rc = set_power(drc->powerdomain, POWER_ON); if (rc) { say(ERROR, "set power failed for 0x%x\n", drc->powerdomain); return progress; } progress = ACQUIRE_HP_SPL; if (state == PWR_ONLY) state = dr_entity_sense(drc->index); } if (state == PRESENT || state == NEED_POWER) { rc = rtas_set_indicator(ISOLATION_STATE, drc->index, UNISOLATE); if (rc) { say(ERROR, "set ind failed for 0x%x\n", drc->index); return progress; } progress = ACQUIRE_HP_UNISO; if (state == NEED_POWER) state = dr_entity_sense(drc->index); } if (state < 0) { say(ERROR, "invalid state %d\n", state); return progress; } if (state == PRESENT) { new_nodes = configure_connector(drc->index); if (new_nodes == NULL) return progress; progress = ACQUIRE_HP_CFGCONN; rc = add_device_tree_nodes(of_path, new_nodes); if (rc) { say(ERROR, "add nodes failed for 0x%x\n", drc->index); return progress; } } return 0; } /** * acquire_hp_children * * @param slot_of_path * @param n_acquired * @returns 0 on success, !0 otherwise */ int acquire_hp_children(char *slot_of_path, int *n_acquired) { struct dr_connector *drc_list, *drc; int rc; int failure = 0, count = 0; drc_list = get_drc_info(slot_of_path); if (drc_list == NULL) { /* No hotplug-capable children */ return 0; } for (drc = drc_list; drc != NULL; drc = drc->next) { if (is_hp_type(drc->type)) { rc = acquire_hp_resource(drc, slot_of_path); if (rc) { say(ERROR, "failed to acquire %s\n", drc->name); failure = 1; } count++; } } *n_acquired = count; return failure; } /** * release_hp_resource * * @param drc_index * @param power_domain * @returns 0 on success, !0 otherwise */ static int release_hp_resource(struct dr_node *node) { int rc; rc = remove_device_tree_nodes(node->ofdt_path); if (rc) { say(ERROR, "failed to remove kernel nodes for index 0x%x\n", node->drc_index); return -EIO; } rc = rtas_set_indicator(DR_INDICATOR, node->drc_index, LED_OFF); if (rc) { say(ERROR, "failed to set led off for index 0x%x\n", node->drc_index); return -EIO; } rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); if (rc) { say(ERROR, "failed to isolate for index 0x%x\n", node->drc_index); return -EIO; } rc = set_power(node->drc_power, POWER_OFF); if (rc) { struct stat sb; say(ERROR, "failed to power off for index 0x%x\n", node->drc_index); if (!stat(IGNORE_HP_PO_PROP, &sb)) say(ERROR, "Ignoring hot-plug power off failure.\n"); else return -EIO; } return 0; } /** * release_hp_children_from_node * * @param parent_slot dr_node of slot to release children from * @returns 0 on success, !0 otherwise */ int release_hp_children_from_node(struct dr_node *slot) { struct dr_node *child; int rc; for (child = slot->children; child; child = child->next) { rc = release_hp_resource(child); if (rc) return rc; } return 0; } /** * release_hp_children * * @param parent_drc_name * @returns 0 on success, !0 otherwise */ int release_hp_children(char *parent_drc_name) { struct dr_node *hp_list, *slot; int rc; hp_list = get_hp_nodes(); for (slot = hp_list; slot; slot = slot->next) if (!strcmp(parent_drc_name, slot->drc_name)) break; if (slot == NULL) { rc = -EINVAL; goto out; } rc = release_hp_children_from_node(slot); out: free_node(hp_list); return (rc < 0) ? rc : 0; } /** * enable_hp_children * * @param drc_name * @returns 0 on success, !0 otherwise */ int enable_hp_children(char *drc_name) { if (get_hp_adapter_status(drc_name) == NOT_CONFIG) { set_hp_adapter_status(PHP_CONFIG_ADAPTER, drc_name); if (get_hp_adapter_status(drc_name) != CONFIG) return 1; } return 0; } /** * disable_hp_children * * @param drc_name * @returns 0 on success, !0 otherwise */ int disable_hp_children(char *drc_name) { if (get_hp_adapter_status(drc_name) != NOT_CONFIG) { int status; set_hp_adapter_status(PHP_UNCONFIG_ADAPTER, drc_name); status = get_hp_adapter_status(drc_name); if (status != NOT_CONFIG && status != EMPTY) return 1; } return 0; } powerpc-utils-1.2.26/src/drmgr/drmgr.c0000664000175000017510000001726312542271360014537 00000000000000/** * @file drmgr.c * * * Copyright (C) IBM Corporation 2006 */ #include #include #include #include #include #define _GNU_SOURCE #include #include "dr.h" #include "pseries_platform.h" #define DRMGR_ARGS "ac:d:Iimnp:Qq:Rrs:w:t:hCV" int output_level = 1; /* default to lowest output level */ int log_fd = 0; int action_cnt = 0; static int display_capabilities = 0; static int display_usage = 0; typedef int (cmd_func_t)(struct options *); typedef int (cmd_args_t)(struct options *); typedef void (cmd_usage_t)(char **); int drmgr(struct options *); void drmgr_usage(char **); int valid_drmgr_options(struct options *); struct command { cmd_func_t *func; cmd_args_t *validate_options; cmd_usage_t *usage; }; #define DRMGR 0 #define DRSLOT_CHRP_SLOT 1 #define DRSLOT_CHRP_PHB 2 #define DRSLOT_CHRP_PCI 3 #define DRSLOT_CHRP_MEM 4 #define DRSLOT_CHRP_HEA 5 #define DRSLOT_CHRP_CPU 6 #define DRMIG_CHRP_PMIG 7 #define DRSLOT_CHRP_PHIB 8 static struct command commands[] = { { .func = drmgr, .validate_options = valid_drmgr_options, .usage = drmgr_usage, }, { .func = drslot_chrp_slot, .validate_options = valid_slot_options, .usage = slot_usage, }, { .func = drslot_chrp_phb, .validate_options = valid_phb_options, .usage = phb_usage, }, { .func = drslot_chrp_pci, .validate_options = valid_pci_options, .usage = pci_usage, }, { .func = drslot_chrp_mem, .validate_options = valid_mem_options, .usage = mem_usage, }, { .func = drslot_chrp_hea, .validate_options = valid_hea_options, .usage = hea_usage, }, { .func = drslot_chrp_cpu, .validate_options = valid_cpu_options, .usage = cpu_usage, }, { .func = drmig_chrp_pmig, .validate_options = valid_pmig_options, .usage = pmig_usage, }, { .func = drmig_chrp_pmig, .validate_options = valid_pmig_options, .usage = phib_usage, }, }; static struct option long_options[] = { {"capabilities", no_argument, NULL, 'C'}, {"help", no_argument, NULL, 'h'}, {0,0,0,0} }; #define MAX_USAGE_LENGTH 512 void command_usage(struct command *command) { /* * Display the common usage options */ fprintf(stderr, "Usage: drmgr %s", "[-w minutes] [-d detail_level] [-C | --capabilities] [-h | --help]\n"); /* * Now retrieve the command specific usage text */ char *buffer = zalloc(MAX_USAGE_LENGTH); char *pusage=buffer; /* pusage may be over written */ command->usage(&pusage); fprintf(stderr, "%s\n", pusage); free(buffer); } static char *usagestr = "{-c {port | slot | phb | pci | mem | cpu} | -m}\n" "For more information on the specific options for the various\n" "connector types, run drmgr -c -h"; void drmgr_usage(char **pusage) { *pusage = usagestr; } int valid_drmgr_options(struct options *opts) { if (opts->ctype == NULL) { say(ERROR, "A connector type (-c) must be specified\n"); return -1; } if (action_cnt == 0) { say(ERROR, "At least one action must be specified\n"); return -1; } if (action_cnt > 1) { say(ERROR, "Only one action may be specified\n"); return -1; } if ((opts->quantity > 1) && (opts->usr_drc_name)) { say(ERROR, "The -q and -s flags are mutually exclusive\n"); return -1; } if (opts->timeout < 0) { say(ERROR, "Invalid timeout specified: %s\n", optarg); return -1; } return 0; } int parse_options(int argc, char *argv[], struct options *opts) { int c; int option_indx; int option_found = 0; memset(opts, 0, sizeof(*opts)); /* disable getopt error messages */ opterr = 0; while ((c = getopt_long(argc, argv, DRMGR_ARGS, long_options, &option_indx)) != -1) { option_found = 1; switch (c) { case 'a': opts->action = ADD; action_cnt++; break; case 'c': opts->ctype = optarg; break; case 'C': display_capabilities = 1; break; case 'd': set_output_level(atoi(optarg)); break; case 'I': opts->no_ident = 1; break; case 'i': opts->action = IDENTIFY; action_cnt++; break; case 'n': /* The -n option is also used to specify a number of * seconds to attempt a self-arp. Linux ignores this * for hibernation. */ opts->noprompt = 1; break; case 'p': opts->p_option = optarg; break; case 'q': opts->quantity = strtoul(optarg, NULL, 0); break; case 'R': opts->action = REPLACE; action_cnt++; break; case 'r': opts->action = REMOVE; action_cnt++; break; case 's': opts->usr_drc_name = optarg; break; case 'Q': opts->action = QUERY; action_cnt++; break; case 'm': opts->action = MIGRATE; action_cnt++; break; case 'w': opts->timeout = strtol(optarg, NULL, 10) * 60; break; case 'h': display_usage = 1; return 0; break; case 't': /* target lpid (pmig, not used) */ break; case 'V': /* qemu virtio pci device (workaround) */ opts->pci_virtio = 1; break; default: say(ERROR, "Invalid option specified '%c'\n", optopt); return -1; break; } } if (!option_found) display_usage = 1; return 0; } struct command * get_command(struct options *opts) { /* Unfortunately, the connector type specified doesn't always result * in a 1-to-1 relationship with the resulting command to run so we * have to do some extra checking to build the correct command. */ if (opts->action == MIGRATE) return &commands[DRMIG_CHRP_PMIG]; if (!opts->ctype) return &commands[DRMGR]; if ((! strncmp(opts->ctype, "port", 4)) || ((opts->usr_drc_name) && (! strncmp(opts->usr_drc_name, "HEA", 3)))) return &commands[DRSLOT_CHRP_HEA]; if (! strcmp(opts->ctype, "slot")) return &commands[DRSLOT_CHRP_SLOT]; if (! strcmp(opts->ctype, "phb")) return &commands[DRSLOT_CHRP_PHB]; if (! strcmp(opts->ctype, "pci")) return &commands[DRSLOT_CHRP_PCI]; if (! strcmp(opts->ctype, "mem")) return &commands[DRSLOT_CHRP_MEM]; if (! strcmp(opts->ctype, "cpu")) return &commands[DRSLOT_CHRP_CPU]; if (! strcmp(opts->ctype, "phib")) { opts->action = HIBERNATE; return &commands[DRSLOT_CHRP_PHIB]; } /* If we make it this far, the user specified an invalid * connector type. */ say(ERROR, "Dynamic reconfiguration is not supported for connector\n" "type \"%s\" on this system\n", opts->ctype); return &commands[DRMGR]; } int drmgr(struct options *opts) { say(ERROR, "Invalid command: %d\n", opts->action); return -1; } int main(int argc, char *argv[]) { struct options opts; char log_msg[DR_PATH_MAX]; struct command *command; int i, rc, offset; switch (get_platform()) { case PLATFORM_UNKNOWN: case PLATFORM_POWERNV: fprintf(stderr, "%s: is not supported on the %s platform\n", argv[0], platform_name); exit(1); } rc = dr_init(); if (rc) return rc; parse_options(argc, argv, &opts); if (display_capabilities) { print_dlpar_capabilities(); dr_fini(); return 0; } command = get_command(&opts); if (display_usage) { command_usage(command); dr_fini(); return 0; } /* Validate the options for the action we want to perform */ rc = command->validate_options(&opts); if (rc) { dr_fini(); return -1; } /* Validate this platform */ if (!valid_platform("chrp")) { dr_fini(); return -1; } set_timeout(opts.timeout); /* Log this invocation to /var/log/messages and /var/log/drmgr */ offset = sprintf(log_msg, "drmgr: "); for (i = 1; i < argc; i++) offset += sprintf(log_msg + offset, "%s ", argv[i]); log_msg[offset] = '\0'; syslog(LOG_LOCAL0 | LOG_INFO, "%s", log_msg); say(DEBUG, "%s\n", log_msg); /* Now, using the actual command, call out to the proper handler */ rc = command->func(&opts); dr_fini(); return rc; } powerpc-utils-1.2.26/src/drmgr/drmig_chrp_pmig.c0000664000175000017510000003605112527176005016555 00000000000000/** * @file drmig_chrp_pmig.c * * Copyright (C) IBM Corporation * */ #include #include #include #include #include #include #include #include #include #include #include #include "dr.h" #include "ofdt.h" #include "drpci.h" struct pmap_struct { struct pmap_struct *next; unsigned int phandle; int ibmphandle; char *name; }; #define SYSFS_HIBERNATION_FILE "/sys/devices/system/power/hibernate" #define SYSFS_MIGRATION_FILE "/sys/kernel/mobility/migration" #define SYSFS_MIGRATION_API_FILE "/sys/kernel/mobility/api_version" /* drmgr must call ibm,suspend-me and is responsible for postmobility fixups */ #define MIGRATION_API_V0 0 /* drmgr must write to sysfs migration store and allow kernel to do postmobility fixups */ #define MIGRATION_API_V1 1 static struct pmap_struct *plist; static int action = 0; static char *pmig_usagestr = "-m -p {check | pre} -s "; static char *phib_usagestr = "-m -p {check | pre} -s -n "; /** * pmig_usage * */ void pmig_usage(char **pusage) { *pusage = pmig_usagestr; } /** * phib_usage * */ void phib_usage(char **pusage) { *pusage = phib_usagestr; } /** * add_phandle * * @param name * @param phandle * @param ibmphandle */ static void add_phandle(char *name, unsigned int phandle, int ibmphandle) { struct pmap_struct *pm = zalloc(sizeof(struct pmap_struct)); if (strlen(name) == 0) name = "/"; pm->name = zalloc(strlen(name)+strlen(OFDT_BASE)+1); sprintf(pm->name, "%s%s", OFDT_BASE, name); pm->phandle = phandle; pm->ibmphandle = ibmphandle; pm->next = plist; plist = pm; } /** * find_phandle * * @param ph * @returns */ static char * find_phandle(unsigned int ph) { struct pmap_struct *pms = plist; while (pms && pms->phandle != ph) pms = pms->next; return pms ? pms->name : NULL; } /** * add_phandles * * @param parent * @param p * @returns */ static int add_phandles(char *parent, char *p) { DIR *d; struct dirent *de; char path[PATH_MAX]; unsigned int phandle; char *pend; FILE *fd; strcpy(path,parent); if (strlen(p)) { strcat(path,"/"); strcat(path,p); } pend = path + strlen(path); d = opendir(path); if (d == NULL) { perror(path); return 1; } while ((de = readdir(d))) { if ((de->d_type == DT_DIR) && (strcmp(de->d_name,".")) && (strcmp(de->d_name,".."))) add_phandles(path,de->d_name); } strcpy(pend,"/linux,phandle"); fd = fopen(path,"r"); if (fd != NULL) { if (fread(&phandle,sizeof(phandle),1,fd) != 1) { perror(path); say(DEBUG, "Error reading phandle data!\n"); return 1; } *pend = '\0'; add_phandle(path + strlen("/proc/device-tree"),phandle, 0); fclose(fd); } strcpy(pend,"/ibm,phandle"); fd = fopen(path,"r"); if (fd != NULL) { if (fread(&phandle,sizeof(phandle),1,fd) != 1) { perror(path); say(DEBUG, "Error reading phandle data!\n"); return 1; } *pend = '\0'; add_phandle(path + strlen("/proc/device-tree"), phandle, 1); fclose(fd); } closedir(d); return 0; } /** * do_update * * @param cmd * @param len * @returns 0 on success, !0 otherwise */ static int do_update(char *cmd, int len) { int rc; int i, fd; fd = open(OFDTPATH, O_WRONLY); if (fd <= 0) { say(ERROR, "Failed to open %s: %s\n", OFDTPATH, strerror(errno)); rc = errno; return rc; } say(DEBUG, "len %d\n", len); if ((rc = write(fd, cmd, len)) != len) say(ERROR, "Error writing to ofdt file! rc %d errno %d\n", rc, errno); for (i = 0; i < len; i++) { if (! isprint(cmd[i])) cmd[i] = '.'; if (isspace(cmd[i])) cmd[i] = ' '; } cmd[len-1] = 0x00; say(DEBUG, "<%s>\n", cmd); close(fd); return rc; } /** * del_node * * @param phandle */ static void del_node(unsigned int phandle) { char *name = find_phandle(phandle); char delcmd[128] = "remove_node "; if (name == NULL) say(DEBUG, "Delete node error: Invalid phandle %8.8x", phandle); else { strcat(delcmd,name); do_update(delcmd, strlen(delcmd)); } } /** * update_properties * * @param phandle * @returns 0 on success, !0 otherwise */ static int update_properties(unsigned int phandle) { int rc; char cmd[DR_PATH_MAX]; char *longcmd = NULL; char *newcmd; int cmdlen = 0; int proplen = 0; unsigned int wa[1024]; unsigned int *op; unsigned int nprop; unsigned int vd; int lenpos = 0; char *pname; unsigned int i; int more = 0; char *name = find_phandle(phandle); int initial = 1; memset(wa, 0x00, 16); wa[0] = phandle; do { say(DEBUG, "about to call rtas_update_properties. work area:\n" "phandle %8.8x, node %s\n" " %8.8x %8.8x %8.8x %8.8x\n", phandle, name ? name : "NULL", wa[0], wa[1], wa[2], wa[3]); rc = rtas_update_properties((char *)wa, 1); if (rc && rc != 1) { say(DEBUG, "Error %d from rtas_update_properties()\n", rc); return 1; } say(DEBUG, "successful rtas_update_properties (more %d)\n", rc); op = wa+4; nprop = *op++; /* After the initial call to rtas_update_properties the first * property value descriptor in the buffer is the path of the * node being updated. Format is as follows: * * property name - 1 byte set to NULL 0x00 * value descriptor - 4 bytes containing length of value string * value string - fully qualified path name of updated node * */ if (initial) { say(DEBUG, "Null byte = %2.2x, ", *((char *)op)); op = (unsigned int *)(((char *)op) + 1); vd = *op++; say(DEBUG, "string length = %u, path = %s\n", vd, ((char *)op)); op = (unsigned int *)(((char *)op) + vd); initial = 0; /* The path we are skipping is inclusive in the * property count. */ nprop--; } for (i = 0; i < nprop; i++) { pname = (char *)op; op = (unsigned int *)(pname + strlen(pname) + 1); vd = *op++; switch (vd) { case 0x00000000: say(DEBUG, "%s - name only property %s\n", name, pname); break; case 0x80000000: say(DEBUG, "%s - delete property %s\n", name, pname); sprintf(cmd,"remove_property %u %s", phandle, pname); do_update(cmd, strlen(cmd) + 1); break; default: if (vd & 0x80000000) { say(DEBUG, "partial property!\n"); /* twos compliment of length */ vd = ~vd + 1; more = 1; } else { more = 0; } say(DEBUG, "%s - updating property %s length " "%d\n", name, pname, vd); /* See if we have a partially completed * command */ if (longcmd) { newcmd = zalloc(cmdlen + vd); memcpy(newcmd, longcmd, cmdlen); free(longcmd); longcmd = newcmd; } else { longcmd = zalloc(vd+128); /* Build the command with a length * of six zeros */ lenpos = sprintf(longcmd, "update_property %u " "%s ", phandle, pname); strcat(longcmd, "000000 "); cmdlen = strlen(longcmd); } memcpy(longcmd + cmdlen, op, vd); cmdlen += vd; proplen += vd; if (! more) { /* Now update the length to its actual * value and do a hideous fixup of * the new trailing null */ sprintf(longcmd+lenpos,"%06d",proplen); longcmd[lenpos+6] = ' '; do_update(longcmd, cmdlen); free(longcmd); longcmd = NULL; cmdlen = 0; proplen = 0; } op = (unsigned int *)(((char *)op) + vd); } } } while (rc == 1); return 0; } /** * add_new_node * * @param phandle * @param drcindex */ static void add_new_node(unsigned int phandle, unsigned int drcindex) { char *path; int rtas_rc; struct of_node *new_nodes;/* nodes returned from configure_connector */ new_nodes = configure_connector(drcindex); path = find_phandle(phandle); if (path == NULL) { say(DEBUG, "Cannot find pnahdle %x\n", phandle); return; } rtas_rc = add_device_tree_nodes(path, new_nodes); if (rtas_rc) say(DEBUG, "add_device_tree_nodes failed at %s\n", path); } /** * del_nodes * * @param op * @param n */ static void del_nodes(unsigned int *op, unsigned int n) { unsigned int i, phandle; for (i = 0; i < n; i++) { phandle = *op++; say(DEBUG, "Delete node with phandle %8.8x\n", phandle); del_node(phandle); } } /** * update_nodes * * @param op * @param n */ static void update_nodes(unsigned int *op, unsigned int n) { unsigned int i, phandle; for (i = 0; i < n; i++) { phandle = *op++; say(DEBUG, "Update node with phandle %8.8x\n", phandle); update_properties(phandle); } } /** * add_nodes * * @param op * @param n */ static void add_nodes(unsigned int *op, unsigned int n) { unsigned int i, pphandle, drcindex; for (i = 0; i < n; i++) { pphandle = *op++; drcindex = *op++; say(DEBUG, "Add node with parent phandle %8.8x and drc index " "%8.8x\n", pphandle, drcindex); add_new_node(pphandle, drcindex); } } /** * devtree_update * */ static void devtree_update(void) { int rc; unsigned int wa[1024]; unsigned int *op; say(DEBUG, "Updating device_tree\n"); if (add_phandles("/proc/device-tree","")) return; /* First 16 bytes of work area must be initialized to zero */ memset(wa, 0x00, 16); do { rc = rtas_update_nodes((char *)wa, 1); if (rc && rc != 1) { say(DEBUG, "Error %d from rtas_update_nodes()\n", rc); return; } say(DEBUG, "successful rtas_update_nodes (more %d)\n", rc); op = wa+4; while (*op & 0xFF000000) { unsigned int i; say(DEBUG, "op %p, *op %8.8x\n", op, *op); for (i = 0; i < (*op & 0x00FFFFFF); i++) say(DEBUG, " %8.8x\n",op[i+1]); switch (*op & 0xFF000000) { case 0x01000000: del_nodes(op+1, *op & 0x00FFFFFF); break; case 0x02000000: update_nodes(op+1, *op & 0x00FFFFFF); break; case 0x03000000: add_nodes(op+1, *op & 0x00FFFFFF); break; case 0x00000000: /* End */ break; default: say(DEBUG, "Unknown update_nodes op %8.8x\n", *op); } op += 1 + (*op & 0x00FFFFFF); } } while (rc == 1); say(DEBUG, "leaving\n"); } int valid_pmig_options(struct options *opts) { if (opts->p_option == NULL) { say(ERROR, "A command must be specified\n"); return -1; } /* Determine if this is a migration or a hibernation request */ if (!strcmp(opts->ctype, "pmig")) { if (opts->action != MIGRATE) { /* The -m option must be specified with migrations */ say(ERROR, "The -m must be specified for migrations\n"); return -1; } if (!pmig_capable()) { say(ERROR, "Partition Mobility is not supported.\n"); return -1; } action = MIGRATE; } else if (!strcmp(opts->ctype, "phib")) { if (!phib_capable()) { say(ERROR, "Partition Hibernation is not supported.\n"); return -1; } action = HIBERNATE; } else { say(ERROR, "The value \"%s\" for the -c option is not valid\n", opts->ctype); return -1; } return 0; } int do_migration(uint64_t stream_val) { int rc, fd; int api_level = 0; char buf[64]; /* If the kernel can also do the device tree update we should let the kernel do all the work. Check if sysfs migration api_version is readable and use api level to determine how to perform migration and post-mobility updates. */ rc = get_int_attribute(SYSFS_MIGRATION_API_FILE, NULL, &api_level, sizeof(&api_level)); if (rc) say(DEBUG,"get_int_attribute returned %d for path %s\n", rc, SYSFS_MIGRATION_API_FILE); if (api_level == MIGRATION_API_V0) { say(DEBUG, "about to issue ibm,suspend-me(%llx)\n", stream_val); rc = rtas_suspend_me(stream_val); say(DEBUG, "ibm,suspend-me() returned %d\n", rc); } else if (api_level == MIGRATION_API_V1) { sprintf(buf, "0x%llx\n", stream_val); fd = open(SYSFS_MIGRATION_FILE, O_WRONLY); if (fd == -1) { say(ERROR, "Could not open \"%s\" to initiate migration, " "%m\n", SYSFS_MIGRATION_FILE); return -1; } say(DEBUG, "Initiating migration via %s with %s\n", SYSFS_MIGRATION_FILE, buf); rc = write(fd, buf, strlen(buf)); if (rc < 0) { say(DEBUG, "Write to migration file failed with rc: %d\n", rc); rc = errno; } else if (rc > 0) rc = 0; close(fd); say(DEBUG, "Kernel migration returned %d\n", rc); } else { say(ERROR, "Unknown kernel migration api version %d\n", api_level); rc = -1; } return rc; } int do_hibernation(uint64_t stream_val) { int rc, fd; char buf[64]; sprintf(buf, "0x%llx\n", stream_val); fd = open(SYSFS_HIBERNATION_FILE, O_WRONLY); if (fd == -1) { say(ERROR, "Could not open \"%s\" to initiate hibernation, " "%m\n", SYSFS_HIBERNATION_FILE); return -1; } say(DEBUG, "Initiating hibernation via %s with %s\n", SYSFS_HIBERNATION_FILE, buf); rc = write(fd, buf, strlen(buf)); if (rc < 0) { say(DEBUG, "Write to hibernation file failed with rc: %d\n", rc); rc = errno; } else if (rc > 0) rc = 0; close(fd); say(DEBUG, "Kernel hibernation returned %d\n", rc); return rc; } void post_mobility_update(int action) { int rc; int do_update = 0; char *path; if (action == HIBERNATE) path = SYSFS_HIBERNATION_FILE; else path = SYSFS_MIGRATION_API_FILE; /* kernel will return 0 or sysfs attribute will be unreadable if drmgr needs to perform a device tree update */ rc = get_int_attribute(path, NULL, &do_update, sizeof(do_update)); if (rc) say(DEBUG, "get_int_attribute returned %d for path %s\n", rc, path); if (!do_update) { rc = rtas_activate_firmware(); if (rc) say(DEBUG, "rtas_activate_firmware() returned %d\n", rc); devtree_update(); } } int drmig_chrp_pmig(struct options *opts) { int rc; char *cmd = opts->p_option; char sys_src[20]; uint64_t stream_val; /* Ensure that this partition is migratable/mobile */ if (! pmig_capable()) { fprintf(stderr, "drmig_chrp_pmig: Partition Mobility is not " "supported on this kernel.\n"); return -1; } /* Today we do no pre-checks for migratability. The only check * we could do is whether the "ibm,suspend-me" RTAS call exists. * But if it doesn't, the firmware level doesn't support migration, * in which case why the heck are we being invoked anyways. */ if (strcmp(cmd, "check") == 0) { say(DEBUG, "check: Nothing to do...\n"); return 0; } /* The only other command is pre, any other command is invalid */ if (strcmp(cmd, "pre")) { say(DEBUG, "Invalid command \"%s\" specified\n", cmd); return 1; } if (opts->usr_drc_name == NULL) { say(ERROR, "No streamid specified\n"); return -1; } errno = 0; stream_val = strtoull(opts->usr_drc_name, NULL, 16); if (errno != 0) { say(ERROR, "Invalid streamid specified: %s\n", strerror(errno)); return -1; } /* Get the ID of the original system, for later logging */ get_str_attribute(OFDT_BASE, "system-id", sys_src, 20); sleep(5); /* Now do the actual migration */ do { if (action == MIGRATE) rc = do_migration(stream_val); else if (action == HIBERNATE) rc = do_hibernation(stream_val); else rc = -EINVAL; if (rc == NOT_SUSPENDABLE) sleep(1); } while (rc == NOT_SUSPENDABLE); syslog(LOG_LOCAL0 | LOG_INFO, "drmgr: %s rc %d\n", (action == MIGRATE ? "migration" : "hibernation"), rc); if (rc) return rc; post_mobility_update(action); say(DEBUG, "Refreshing RMC via refrsrc\n"); rc = system("/usr/sbin/rsct/bin/refrsrc IBM.ManagementServer"); return 0; } powerpc-utils-1.2.26/src/drmgr/drslot_chrp_cpu.c0000664000175000017510000002100412527176005016605 00000000000000/** * @file drslot_chrp_cpu.c * * * Copyright (C) IBM Corporation 2006 * */ #include #include #include #include #include #include #include #include #include #include "dr.h" #include "drcpu.h" #include "drpci.h" #include "ofdt.h" struct cpu_operation; typedef int (cpu_op_func_t) (struct options *); struct parm_to_func { char *parmname; cpu_op_func_t *func; }; static char *usagestr = "-c cpu {-a | -r} {-q -p {variable_weight | ent_capacity} [-s drc_name | drc_index]"; /** * cpu_usage * */ void cpu_usage(char **pusage) { *pusage = usagestr; } static struct dr_node * get_cpu_by_name(struct dr_info *drinfo, const char *name) { struct dr_node *cpu; for (cpu = drinfo->all_cpus; cpu; cpu = cpu->next) { if (strcmp(cpu->drc_name, name) == 0) { break; } } return cpu; } static struct dr_node * get_cpu_by_index(struct dr_info *drinfo, uint32_t index) { struct dr_node *cpu; for (cpu = drinfo->all_cpus; cpu; cpu = cpu->next) { if (cpu->drc_index == index) { break; } } return cpu; } /** * cpu_count * * Count the number of CPUs currently on the system * * @param dr_info cpu drc information * @return number of cpus */ static int cpu_count(struct dr_info *dr_info) { struct dr_node *cpu; int cpu_count = 0; for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) { if (cpu->is_owned) cpu_count++; } say(DEBUG, "Number of CPUs = %d\n", cpu_count); return cpu_count; } /** * get_available_cpu * * Find an available cpu to that we can add or remove, depending * on the request. * * @param opts options passed in to drmgr * @param dr_info cpu drc information * @returns pointer to cpu on success, NULL on failure */ struct dr_node * get_available_cpu(struct options *opts, struct dr_info *dr_info) { struct dr_node *cpu = NULL; struct dr_node *survivor = NULL; struct thread *t; if (opts->usr_drc_name) { cpu = get_cpu_by_name(dr_info, opts->usr_drc_name); if (!cpu) say(ERROR, "Could not locate cpu %s\n", opts->usr_drc_name); return cpu; } else if (opts->usr_drc_index) { cpu = get_cpu_by_index(dr_info, opts->usr_drc_index); if (!cpu) say(ERROR, "Could not locate cpu %x\n", opts->usr_drc_index); return cpu; } switch (opts->action) { case ADD: for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) { if (cpu->unusable) continue; if (!cpu->is_owned) survivor = cpu; } cpu = survivor; break; case REMOVE: /* Find the first cpu with an online thread */ for (cpu = dr_info->all_cpus; cpu; cpu = cpu->next) { if (cpu->unusable) continue; for (t = cpu->cpu_threads; t; t = t->next) { if (get_thread_state(t) == ONLINE) return cpu; } } break; } if (!cpu) say(ERROR, "Could not find avaiable cpu.\n"); return cpu; } /** * add_cpus * * Attempt to acquire and online the given number of cpus. * This function calls itself recursively to simplify recovery * actions in case of an error. This is intended only for the case * where the user does not specify a drc-name. * * The final steps are to display the drc-names value to stdout and * return with 0. * * @param nr_cpus * @returns 0 on success, !0 otherwise */ static int add_cpus(struct options *opts, struct dr_info *dr_info) { int rc = -1; uint count; struct dr_node *cpu = NULL; count = 0; while (count < opts->quantity) { if (drmgr_timed_out()) break; cpu = get_available_cpu(opts, dr_info); if (!cpu) break; rc = probe_cpu(cpu, dr_info); if (rc) { say(DEBUG, "Unable to acquire CPU with drc index %x\n", cpu->drc_index); cpu->unusable = 1; continue; } fprintf(stdout, "%s\n", cpu->drc_name); count++; } say(DEBUG, "Acquired %d of %d requested cpu(s).\n", count, opts->quantity); return rc ? 1 : 0; } /** * remove_cpus * * Attempt to offline and release to the hypervisor the given number of * cpus. This functions calls itself recursively to simplify recovery * actions in the case of an error. This is intended only for the case * where the user does not specify a drc-name. * * From "Design Specification for AIX Configuration Support of * Dynamic Reconfiguration including the drmgr command and drslot for * memory, processors, and PCI slots" Version 1.2: * * Section V. Part B. Item 2. "drslot_chrp_cpu -r -c cpu" * "Once the resource has been released by the kernel, all the following * steps are taken. Errors are ignored. The code continues releasing the * resource by using RTAS services. ..." * "If successful, the code displays the drc-names value to stdout and * returns with 0, else displays an error message to stderr and returns with * non-zero." * * @param nr_cpus * @returns 0 on success, !0 otherwise */ static int remove_cpus(struct options *opts, struct dr_info *dr_info) { int rc = 0; uint count = 0; struct dr_node *cpu; while (count < opts->quantity) { if (drmgr_timed_out()) break; if (cpu_count(dr_info) == 1) { say(WARN, "Cannot remove the last CPU\n"); rc = -1; break; } cpu = get_available_cpu(opts, dr_info); if (!cpu) break; /* cpu is invalid after release_cpu, so no recovery * steps seem feasible. We could copy the cpu name * and look it up again if the operation fails. */ rc = release_cpu(cpu, dr_info); if (rc) { online_cpu(cpu, dr_info); cpu->unusable = 1; continue; } fprintf(stdout, "%s\n", cpu->drc_name); count++; } say(DEBUG, "Removed %d of %d requested cpu(s)\n", count, opts->quantity); return rc; } /** * smt_thread_func * @brief Act upon logical cpus/threads * * @param opts * @returns 0 on success, !0 otherwise */ static int smt_threads_func(struct options *opts, struct dr_info *dr_info) { int rc; struct dr_node *cpu; if (opts->quantity != 1) { say(ERROR, "Quantity option '-q' may not be specified with " "the '-p smt_threads' option\n"); return -1; } if (! smt_enabled(dr_info)) { say(ERROR, "SMT functions not available on this system.\n"); return -1; } if (opts->usr_drc_name) { cpu = get_cpu_by_name(dr_info, opts->usr_drc_name); if (cpu == NULL) { say(ERROR, "Could not find cpu %s\n", opts->usr_drc_name); return -1; } if (opts->action == ADD) rc = cpu_enable_smt(cpu, dr_info); else if (opts->action == REMOVE) rc = cpu_disable_smt(cpu); } else if (opts->usr_drc_index) { cpu = get_cpu_by_index(dr_info, opts->usr_drc_index); if (cpu == NULL) { say(ERROR, "Could not find cpu %x\n", opts->usr_drc_index); return -1; } if (opts->action == ADD) rc = cpu_enable_smt(cpu, dr_info); else if (opts->action == REMOVE) rc = cpu_disable_smt(cpu); } else { /* no drc name given, action is system-wide */ if (opts->action == ADD) rc = system_enable_smt(dr_info); if (opts->action == REMOVE) rc = system_disable_smt(dr_info); } return rc; } int valid_cpu_options(struct options *opts) { /* default to a quantity of 1 */ if ((opts->quantity == 0)) opts->quantity = 1; if ((opts->action != ADD) && (opts->action != REMOVE)) { say(ERROR, "The '-r' or '-a' option must be specified for " "CPU operations.\n"); return -1; } /* The -s option can specify a drc name or drc index */ if (opts->usr_drc_name && !strncmp(opts->usr_drc_name, "0x", 2)) { opts->usr_drc_index = strtoul(opts->usr_drc_name, NULL, 16); opts->usr_drc_name = NULL; } return 0; } int drslot_chrp_cpu(struct options *opts) { struct dr_info dr_info; int rc = -1; if (! cpu_dlpar_capable()) { say(ERROR, "CPU DLPAR capability is not enabled on this " "platform.\n"); return -1; } if (opts->p_option) { if ((strcmp(opts->p_option, "ent_capacity") == 0) || (strcmp(opts->p_option, "variable_weight") == 0)) { rc = update_sysparm(opts); if (rc) say(ERROR, "Could not update system parmaeter " "%s\n", opts->p_option); return rc; } } if (init_cpu_drc_info(&dr_info)) { say(ERROR, "Could not intialize Dynamic Reconfiguration " "information.\n"); return -1; } /* If a user specifies a drc name, the quantity to add/remove is * one. Enforce that here so the loops in add/remove code behave * accordingly. */ if (opts->usr_drc_name) opts->quantity = 1; if (opts->p_option && (strcmp(opts->p_option, "smt_threads") == 0)) { rc = smt_threads_func(opts, &dr_info); } else { switch (opts->action) { case ADD: rc = add_cpus(opts, &dr_info); break; case REMOVE: rc = remove_cpus(opts, &dr_info); break; } } free_cpu_drc_info(&dr_info); return rc; } powerpc-utils-1.2.26/src/drmgr/drslot_chrp_hea.c0000664000175000017510000001742512527176005016567 00000000000000/** * @file drslot_chrp_hea.c * * Copyright (C) IBM Corporation 2006 * */ #include #include #include #include #include #include #include #include #include #include "dr.h" #include "drpci.h" #include "ofdt.h" static char *usagestr = "-c port {-a | -r | -Q} -s drc_name"; /** * hea_uasge */ void hea_usage(char **pusage) { *pusage = usagestr; } /** * sysfs_hea_op * @brief Write to the sysfs file to hotplug add/remove a HEA adapter or port * * @param fname sysfs file to write to * @param name information to write to the sysfs file * @returns 0 on success, !0 otherwise */ static int sysfs_write(char *fname, char *name) { int rc, len; FILE *file; file = fopen(fname, "w"); if (file == NULL) { say(ERROR, "Could not open %s:\n%s\n", fname, strerror(errno)); return -ENODEV; } len = strlen(name); rc = fwrite(name, 1, len, file); fclose(file); rc = (rc >= 0) ? 0 : rc; if (rc) say(ERROR, "Write to %s failed:\n%s\n", fname, strerror(errno)); return rc; } /** * hotplug_hea * @brief Hotplug add/remove a HEA adapter from the system. * * @param action add or remove the adapter * @param name name of the HEA adapter to add/remove * @returns 0 on success, !0 otherwise */ static int hotplug_hea(int action, char *name) { int rc; char *action_str = (action == ADD) ? "add" : "remove"; char *action_path = (action == ADD) ? HEA_ADD_SLOT : HEA_REMOVE_SLOT; say(DEBUG, "Attempting to hotplug %s %s\n", action_str, name); rc = sysfs_write(action_path, name); if (rc) say(ERROR, "Could not hotplug %s %s\n", action_str, name); return rc; } /** * hotplug_port * @brief Hotplug add/remove a HEA port to the system. * * @param action add/remove of the port * @parm hea HEA adpater of the port to be added * @param port port to be added/removed * @return 0 on success, !0 otherwise */ static int hotplug_port(int action, struct dr_node *hea, struct dr_node *port) { char fname[128]; char port_str[4]; char *action_str = (action == ADD) ? "add" : "remove"; uint port_no; int rc; say(DEBUG, "Attempting to hotplug %s Port.\n", action_str); if (! hea->sysfs_dev_path) { say(DEBUG, "Non-existant sysfs dev path for Port, hotplug " "failed.\n"); return -EINVAL; } rc = get_property(port->ofdt_path, "ibm,hea-port-no", &port_no, sizeof(port_no)); if (rc) return -EINVAL; sprintf(port_str, "%d", port_no); sprintf(fname, "%s/%s", hea->sysfs_dev_path, (action == ADD) ? "probe_port" : "remove_port"); rc = sysfs_write(fname, port_str); if (rc) say(ERROR, "Hotplug %s of Port %d failed\n", action_str, port_no); return rc; } /** * remove_port * @brief Remove the HEA adapater or port specified by the options * * @param opts command options * @returns 0 on success, !0 otherwise */ static int remove_port(struct options *opts) { struct dr_node *hea; struct dr_node *port, *tmp; int rc; int no_ports = 0; int hea_hp_removed = 0; hea = get_node_by_name(opts->usr_drc_name, HEA_NODES); if (hea == NULL) return RC_NONEXISTENT; for (port = hea->children; port; port = port->next) { if (! strcmp(port->drc_name, opts->usr_drc_name)) break; } if (!port) { say(ERROR, "Could not find HEA Port \"%s\" to remove\n", opts->usr_drc_name); free_node(hea); return -1; } rc = hotplug_port(REMOVE, hea, port); if (rc) { free_node(hea); return -1; } /* if this is the last port to be removed, we need to remove the * hea adapter from the OS also. do not actually remove the * HEA adapter from the device tree or unallocate it, we will get * a request to do that later. */ for (tmp = hea->children; tmp; tmp = tmp->next) no_ports++; if (no_ports == 1) { rc = hotplug_hea(REMOVE, strstr(hea->ofdt_path, "/lhea")); if (rc) { hotplug_port(ADD, hea, port); free_node(hea); return -1; } hea_hp_removed = 1; } rc = release_drc(port->drc_index, port->dev_type); if (rc) { if (hea_hp_removed) hotplug_hea(ADD, strstr(hea->ofdt_path, "/lhea")); hotplug_port(ADD, hea, port); free_node(hea); return rc; } rc = remove_device_tree_nodes(port->ofdt_path); if (rc) { if (hea_hp_removed) hotplug_hea(ADD, strstr(hea->ofdt_path, "/lhea")); hotplug_port(ADD, hea, port); free_node(hea); return rc; } say(DEBUG, "device node(s) for %s removed\n", port->drc_name); free_node(hea); return 0; } /** * remove_hea * @brief Remove the HEA adapater or port specified by the options * * @param opts command options * @returns 0 on success, !0 otherwise */ static int remove_hea(struct options *opts) { struct dr_node *hea; int rc; hea = get_node_by_name(opts->usr_drc_name, HEA_NODES); if (hea == NULL) return RC_NONEXISTENT; rc = release_drc(hea->drc_index, hea->dev_type); if (rc) { free_node(hea); return rc; } rc = remove_device_tree_nodes(hea->ofdt_path); if (rc) say(ERROR, "Error removing HEA adapter from the device tree\n"); free_node(hea); return rc; } /** * add_slot * @bried Add the HEA adapter or port specified by the options * * @param opts command options * @returns 0 on success, !0 otherwise */ static int add_slot(struct options *opts) { struct dr_connector drc; struct of_node *of_nodes; struct dr_node *hea; struct dr_node *port; char ofdt_path[DR_PATH_MAX]; char *slot_type = (opts->usr_drc_name[0] == 'H') ? "HEA" : "Port"; int rc = 0; rc = get_drc_by_name(opts->usr_drc_name, &drc, ofdt_path, OFDT_BASE); if (rc) return rc; rc = acquire_drc(drc.index); if (rc) return rc; of_nodes = configure_connector(drc.index); if (of_nodes == NULL) { release_drc(drc.index, HEA_DEV); return -1; } rc = add_device_tree_nodes(ofdt_path, of_nodes); free_of_node(of_nodes); if (rc) { say(ERROR, "Error adding % to the device tree\n", slot_type); release_drc(drc.index, HEA_DEV); return rc; } hea = get_node_by_name(opts->usr_drc_name, HEA_NODES); if (hea == NULL) { say(ERROR, "Could not get find \"%s\" in the updated device " "tree,\nAddition of %s failed.\n", opts->usr_drc_name, slot_type); remove_device_tree_nodes(ofdt_path); release_drc(drc.index, HEA_DEV); return -1; } switch (opts->usr_drc_name[0]) { case 'H': rc = hotplug_hea(ADD, strstr(hea->ofdt_path, "/lhea")); break; case 'P': for (port = hea->children; port; port = port->next) { if (! strcmp(opts->usr_drc_name, port->drc_name)) break; } rc = hotplug_port(ADD, hea, port); break; } if (rc) { remove_device_tree_nodes(ofdt_path); release_drc(drc.index, HEA_DEV); } free_node(hea); return rc; } int valid_hea_options(struct options *opts) { if (opts->usr_drc_name == NULL) { say(ERROR, "A drc name must be specified\n"); return -1; } if ((opts->action != ADD) && (opts->action != REMOVE) && (opts->action != QUERY)) { say(ERROR, "The '-r', '-a', or '-Q' option must be specified " "for HEA operations.\n"); return -1; } return 0; } int drslot_chrp_hea(struct options *opts) { int rc; if (! hea_dlpar_capable()) { say(ERROR, "DLPAR HEA operations are not supported on" "this kernel"); return -1; } switch (opts->action) { case ADD: rc = add_slot(opts); break; case REMOVE: if (! strcmp(opts->ctype, "port")) rc = remove_port(opts); else if (! strcmp(opts->ctype, "slot")) rc = remove_hea(opts); else { say(ERROR, "The connector type %s is not supported.\n", opts->ctype); rc = -1; } break; case QUERY: { struct dr_node *node; node = get_node_by_name(opts->usr_drc_name, HEA_NODES); if (node == NULL) { say(ERROR, "%s not owned by partition\n", opts->usr_drc_name); rc = RC_DONT_OWN; } else { /* Special case for HMC */ rc = RC_LINUX_SLOT; } free_node(node); break; } default: rc = -1; } return rc; } powerpc-utils-1.2.26/src/drmgr/drslot_chrp_mem.c0000664000175000017510000007264412542271360016611 00000000000000/** * @file drslot_chrp_mem * * * Copyright (C) IBM Corporation 2006 */ #include #include #include #include #include #include #include #include #include #include #include "dr.h" #include "ofdt.h" #include "drmem.h" static int block_sz_bytes = 0; static char *state_strs[] = {"offline", "online"}; static char *usagestr = "-c mem {-a | -r} {-q -p {variable_weight | ent_capacity} | {-q | -s [ | ]}}"; /** * mem_usage * @brief return usage string * * @param char ** pointer to usage string */ void mem_usage(char **pusage) { *pusage = usagestr; } /** * get_phandle * * @param char * device tree node path * @param int * pointer to phandle */ int get_phandle(char *path, uint *phandle) { int rc1,rc2; /* get "linux,phandle" property */ rc1 = get_ofdt_uint_property(path, "linux,phandle", phandle); /* overwrite with "ibm,handle" if it exists */ rc2 = get_ofdt_uint_property(path, "ibm,phandle", phandle); /* return bad if both gets failed */ if (rc1 && rc2) return rc1; else return 0; } /** * free_lmbs * @brief Free any allocated memory referenced from the list head * * @param lmb_list list head to free */ void free_lmbs(struct lmb_list_head *lmb_list) { free_node(lmb_list->lmbs); if (lmb_list->drconf_buf) free(lmb_list->drconf_buf); } /** * get_mem_scns * @brief Find the memory sections associated with the specified lmb * * @param lmb lmb to find memory sections of * @return 0 on success, !0 otherwise */ static int get_mem_scns(struct dr_node *lmb) { uint32_t lmb_sz = lmb->lmb_size; uint64_t phys_addr = lmb->lmb_address; uint32_t mem_scn; int rc = 0; mem_scn = phys_addr / block_sz_bytes; /* Assume the lmb is removable. If we find a non-removable memory * section then we flip the lmb back to not removable. */ lmb->is_removable = 1; lmb_sz = lmb->lmb_size; while (lmb_sz > 0) { char *sysfs_path = "/sys/devices/system/memory/memory%d"; struct mem_scn *scn; struct stat sbuf; scn = zalloc(sizeof(*scn)); if (scn == NULL) return -1; sprintf(scn->sysfs_path, sysfs_path, mem_scn); scn->phys_addr = phys_addr; if (!stat(scn->sysfs_path, &sbuf)) { get_int_attribute(scn->sysfs_path, "removable", &scn->removable, sizeof(scn->removable)); if (!scn->removable) lmb->is_removable = 0; } scn->next = lmb->lmb_mem_scns; lmb->lmb_mem_scns = scn; lmb_sz -= block_sz_bytes; phys_addr += block_sz_bytes; mem_scn = phys_addr / block_sz_bytes; } /* If we do not find any associated memory sections, mark this * as not removable. */ if ((lmb->lmb_mem_scns == NULL) || lmb->unusable) lmb->is_removable = 0; return rc; } /** * get_lmb_size * @brief Retrieve the size of the lmb * * @param lmb lmb to get size for, or NULL for drconf lmb size * @param lmb_list list of lmbs, used to determine drconf usage * @returns size of lmb on succes, 0 on failure */ static int get_lmb_size(struct dr_node *lmb) { uint32_t regs[4]; int rc; rc = get_property(lmb->ofdt_path, "reg", ®s, sizeof(regs)); if (rc) { say(DEBUG, "Could not determine LMB size for %s\n", lmb->ofdt_path); return rc; } lmb->lmb_size = be32toh(regs[3]); return 0; } /** * get_mem_node_lmbs * @brief Retrieve lmbs from the OF device tree represented as memory@XXX nodes * * @param lmb_list pointer to lmb list head to populate * @returns 0 on success, !0 on failure */ int get_mem_node_lmbs(struct lmb_list_head *lmb_list) { struct dr_node *lmb; struct dirent *de; DIR *d; int rc = 0; d = opendir(OFDT_BASE); if (d == NULL) { report_unknown_error(__FILE__, __LINE__); say(DEBUG, "Could not open %s\n", OFDT_BASE); return -1; } while ((de = readdir(d)) != NULL) { char path[1024]; uint32_t my_drc_index; char *tmp; if (de->d_type != DT_DIR) continue; if (strncmp(de->d_name, "memory@", 7)) continue; memset(path, 0, 1024); sprintf(path, "%s/%s", OFDT_BASE, de->d_name); if (get_my_drc_index(path, &my_drc_index)) continue; for (lmb = lmb_list->lmbs; lmb; lmb = lmb->next) { if (lmb->drc_index == my_drc_index) break; } if (lmb == NULL) { say(DEBUG, "Could not find LMB with drc-index of %x\n", my_drc_index); rc = -1; break; } snprintf(lmb->ofdt_path, DR_PATH_MAX, "%s", path); lmb->is_owned = 1; /* Find the lmb size for this lmb */ /* XXX Do nothing with size and break if it can't be found * but don't change rc to indicate failure? * Why not continue? If we break, set rc=-1? */ if (get_lmb_size(lmb)) break; /* Find the physical address for this lmb */ tmp = strrchr(lmb->ofdt_path, '@'); if (tmp == NULL) { say(DEBUG, "Could not determine physical address for " "%s\n", lmb->ofdt_path); /* XXX No rc change? */ break; } lmb->lmb_address = strtoull(tmp + 1, NULL, 16); /* find the associated sysfs memory blocks */ rc = get_mem_scns(lmb); if (rc) break; } closedir(d); return rc; } /** * get_dynamic_reconfig_lmbs * @brief Retrieve lmbs from OF device tree located in the ibm,dynamic-memory * property. * * @param lmb_list pointer to lmb list head to populate * @returns 0 on success, !0 on failure */ int get_dynamic_reconfig_lmbs(struct lmb_list_head *lmb_list) { struct drconf_mem *drmem; uint64_t lmb_sz; int i, num_entries; int rc = 0; int found = 0; rc = get_property(DYNAMIC_RECONFIG_MEM, "ibm,lmb-size", &lmb_sz, sizeof(lmb_sz)); /* convert for LE systems */ lmb_sz = be64toh(lmb_sz); if (rc) { say(DEBUG, "Could not retrieve drconf LMB size\n"); return rc; } lmb_list->drconf_buf_sz = get_property_size(DYNAMIC_RECONFIG_MEM, "ibm,dynamic-memory"); lmb_list->drconf_buf = zalloc(lmb_list->drconf_buf_sz); if (lmb_list->drconf_buf == NULL) { say(DEBUG, "Could not allocate buffer to get dynamic " "reconfigurable memory\n"); return -1; } rc = get_property(DYNAMIC_RECONFIG_MEM, "ibm,dynamic-memory", lmb_list->drconf_buf, lmb_list->drconf_buf_sz); if (rc) { say(DEBUG, "Could not retrieve dynamic reconfigurable memory " "property\n"); return -1; } /* The first integer of the buffer is the number of entries */ num_entries = *(int *)lmb_list->drconf_buf; /* convert for LE systems */ num_entries = be32toh(num_entries); /* Followed by the actual entries */ drmem = (struct drconf_mem *) (lmb_list->drconf_buf + sizeof(num_entries)); for (i = 0; i < num_entries; i++) { struct dr_node *lmb; for (lmb = lmb_list->lmbs; lmb; lmb = lmb->next) { if (lmb->drc_index == be32toh(drmem->drc_index)) break; } if (lmb == NULL) { say(DEBUG, "Could not find LMB with drc-index of %x\n", drmem->drc_index); rc = -1; break; } sprintf(lmb->ofdt_path, DYNAMIC_RECONFIG_MEM); lmb->lmb_size = lmb_sz; lmb->lmb_address = be64toh(drmem->address); lmb->lmb_aa_index = be32toh(drmem->assoc_index); if (be32toh(drmem->flags) & DRMEM_ASSIGNED) { found++; lmb->is_owned = 1; /* find the associated sysfs memory blocks */ rc = get_mem_scns(lmb); if (rc) break; } drmem++; /* trust your compiler */ } say(INFO, "Found %d LMBs currently allocated\n", found); return rc; } /** * shuffle_lmbs * @brief Randomly shuffle list of lmbs * * @param list pointer to lmb list to be randomly shuffled * @param length number of lmbs in the list * * @return list of shuffled lmbs */ struct dr_node * shuffle_lmbs(struct dr_node *lmb_list, int length) { struct dr_node **shuffled_lmbs, *lmb; int i, j; srand(time(NULL)); shuffled_lmbs = zalloc(sizeof(*shuffled_lmbs) * length); for (i = 0, lmb = lmb_list; lmb; i++, lmb = lmb->next) { j = rand() % (i + 1); if (j == i) { shuffled_lmbs[i] = lmb; } else { shuffled_lmbs[i] = shuffled_lmbs[j]; shuffled_lmbs[j] = lmb; } } for (i = 0; i < (length - 1); i++) shuffled_lmbs[i]->next = shuffled_lmbs[i + 1]; shuffled_lmbs[length - 1]->next = NULL; lmb = shuffled_lmbs[0]; free(shuffled_lmbs); return lmb; } /** * get_lmbs * @brief Build a list of all possible lmbs for the system * * @param sort LMB_NORMAL_SORT or LMB_REVERSE_SORT to control sort order * * @return list of lmbs, NULL on failure */ struct lmb_list_head * get_lmbs(unsigned int sort) { struct dr_connector *drc_list, *drc; struct lmb_list_head *lmb_list = NULL; struct dr_node *lmb, *last = NULL; struct stat sbuf; char buf[DR_STR_MAX]; int rc = 0; int found = 0; drc_list = get_drc_info(OFDT_BASE); if (drc_list == NULL) { report_unknown_error(__FILE__, __LINE__); return NULL; } lmb_list = zalloc(sizeof(*lmb_list)); if (lmb_list == NULL) { say(DEBUG, "Could not allocate LMB list head\n"); return NULL; } /* For memory dlpar, we need a list of all posiible memory nodes * for the system, initalize those here. */ for (drc = drc_list; drc; drc = drc->next) { if (strncmp(drc->name, "LMB", 3)) continue; lmb = alloc_dr_node(drc, MEM_DEV, NULL); if (lmb == NULL) { free_lmbs(lmb_list); return NULL; } if (sort == LMB_REVERSE_SORT) { if (last) lmb->next = last; lmb_list->lmbs = lmb; last = lmb; } else { if (last) last->next = lmb; else lmb_list->lmbs = lmb; last = lmb; } found++; } if (sort == LMB_RANDOM_SORT) lmb_list->lmbs = shuffle_lmbs(lmb_list->lmbs, found); say(INFO, "Maximum of %d LMBs\n", found); rc = get_str_attribute("/sys/devices/system/memory", "/block_size_bytes", &buf, DR_STR_MAX); if (rc) { say(DEBUG, "Could not determine block size bytes for memory.\n"); free_lmbs(lmb_list); return NULL; } block_sz_bytes = strtoul(buf, NULL, 16); /* We also need to know which lmbs are already allocated to * the system and their corresponding memory sections as defined * by sysfs. Walk the device tree and update the appropriate * lmb entries (and their memory sections) as we find their device * tree entries. */ if (stat(DYNAMIC_RECONFIG_MEM, &sbuf)) rc = get_mem_node_lmbs(lmb_list); else { /* A small hack to here to allow memory add to work in * certain kernels. Due to a bug in the kernel (see comment * in acquire_lmb()) we need to get lmb info from both places. * For a good kernel, the get_mem_node_lmbs routine will not * update the lmb_list. */ rc = get_dynamic_reconfig_lmbs(lmb_list); if (! rc) rc = get_mem_node_lmbs(lmb_list); } if (rc) { free_lmbs(lmb_list); lmb_list = NULL; } return lmb_list; } /** * get_available_lmb * * Find the first lmb which does not correspond to a lmb * already owned by the partition and is available, or the lmb * matching the one specified by the user. * * @param start_lmb first lmbs to be searched for an available lmb * @returns pointer to avaiable lmb on success, NULL otherwise */ static struct dr_node * get_available_lmb(struct options *opts, struct dr_node *start_lmb) { uint32_t drc_index; struct dr_node *lmb; struct dr_node *usable_lmb = NULL; int balloon_active = ams_balloon_active(); for (lmb = start_lmb; lmb; lmb = lmb->next) { int rc; if (opts->usr_drc_name) { drc_index = strtoul(opts->usr_drc_name, NULL, 0); if ((strcmp(lmb->drc_name, opts->usr_drc_name)) && (lmb->drc_index != drc_index)) continue; } else if (opts->usr_drc_index) { if (lmb->drc_index != opts->usr_drc_index) continue; } if (lmb->unusable) continue; switch (opts->action) { case ADD: if (lmb->is_owned) continue; rc = dr_entity_sense(lmb->drc_index); if (rc != STATE_UNUSABLE) continue; usable_lmb = lmb; break; case REMOVE: /* removable is ignored if AMS ballooning is active. */ if ((!balloon_active && !lmb->is_removable) || (!lmb->is_owned)) continue; usable_lmb = lmb; break; } /* Found an available lmb */ break; } if (usable_lmb) say(DEBUG, "Found available LMB, %s, drc index 0x%x\n", usable_lmb->drc_name, usable_lmb->drc_index); return usable_lmb; } static void update_drconf_affinity(struct dr_node *lmb, struct drconf_mem *drmem) { struct of_node *node; struct of_property *prop; uint32_t assoc_prop_sz; uint32_t *assoc_prop; uint32_t assoc_entries; uint32_t assoc_entry_sz; uint32_t *prop_val; int i; /* find the ibm,associativity property */ node = lmb->lmb_of_node; for (prop = node->properties; prop; prop = prop->next) { if (!strcmp(prop->name, "ibm,associativity")) break; } if (!prop) return; /* find the associtivity index atrrays */ assoc_prop_sz = get_property_size(DYNAMIC_RECONFIG_MEM, "ibm,associativity-lookup-arrays"); assoc_prop = zalloc(assoc_prop_sz); if (!assoc_prop) return; get_property(DYNAMIC_RECONFIG_MEM, "ibm,associativity-lookup-arrays", assoc_prop, assoc_prop_sz); assoc_entries = be32toh(assoc_prop[0]); assoc_entry_sz = be32toh(assoc_prop[1]); prop_val = (uint32_t *)prop->value; for (i = 0; i < assoc_entries; i++) { if (memcmp(&assoc_prop[(i * assoc_entry_sz) + 2], &prop_val[1], assoc_entry_sz * sizeof(uint32_t))) continue; /* found it */ drmem->assoc_index = htobe32(i); break; } free(assoc_prop); return; } /** * update_drconf_node * @brief update the ibm,dynamic-memory property for added/removed memory * * @param lmb pointer to updated lmb * @param lmb_list pointer to all lmbs * @param action ADD or REMOVE * @returns 0 on success, !0 on failure */ static int update_drconf_node(struct dr_node *lmb, struct lmb_list_head *lmb_list, int action) { char *prop_buf; size_t prop_buf_sz; char *tmp; struct drconf_mem *drmem; uint phandle; int i, entries; int rc; /* The first int of the buffer is the number of entries */ entries = *(int *)lmb_list->drconf_buf; /* convert for LE systems */ entries = be32toh(entries); drmem = (struct drconf_mem *)(lmb_list->drconf_buf + sizeof(entries)); for (i = 0; i < entries; i++) { if (be32toh(drmem->drc_index) != lmb->drc_index) { drmem++; continue; } if (action == ADD) { drmem->flags |= be32toh(DRMEM_ASSIGNED); update_drconf_affinity(lmb, drmem); } else { drmem->flags &= be32toh(~DRMEM_ASSIGNED); } break; } /* Now create the buffer we pass to the kernel to have this * property updated. This buffer has the format * "update_property ibm,dynamic-memory \ * [strlen("remove") | strlen("add")] " * * The simple collapsing of all strings, spaces, and ints makes this * a length of 61 + the size of the drconf property, round the * calculation to 128 + to ensure the buffer is * always big enough. */ prop_buf_sz = 128 + lmb_list->drconf_buf_sz; prop_buf = zalloc(prop_buf_sz); if (prop_buf == NULL) return -1; rc = get_phandle(lmb->ofdt_path, &phandle); if (rc) { say(DEBUG, "Failed to get phandle for %s under %s. (rc=%d)\n", lmb->drc_name, lmb->ofdt_path, rc); return rc; } memset(prop_buf, 0, prop_buf_sz); tmp = prop_buf; tmp += sprintf(tmp, "update_property 0x%x ibm,dynamic-memory %d ", phandle, lmb_list->drconf_buf_sz); memcpy(tmp, lmb_list->drconf_buf, lmb_list->drconf_buf_sz); tmp += lmb_list->drconf_buf_sz; tmp += sprintf(tmp, " %s %d ", (action == ADD ? "add" : "remove"), sizeof(lmb->lmb_address)); memcpy(tmp, &lmb->lmb_address, sizeof(lmb->lmb_address)); tmp += sizeof(lmb->lmb_address); rc = update_property(prop_buf, (tmp - prop_buf)); free(prop_buf); return rc; } /** * remove_device_tree_lmb * @brief Update the device tree for the lmb being removed. * * @param lmb memory block to be removed from the device tree * @param lmb_list list of all lmbs * @returns 0 on success, !o otherwise */ static int remove_device_tree_lmb(struct dr_node *lmb, struct lmb_list_head *lmb_list) { if (lmb_list->drconf_buf) return update_drconf_node(lmb, lmb_list, REMOVE); return remove_device_tree_nodes(lmb->ofdt_path); } /** * add_device_tree_lmb * @brief Update the device tree for the lmb being added.. * * @param lmb lmb to acquire * @param lmb_list list of all lmbs * @returns 0 on success, !0 otherwise */ static int add_device_tree_lmb(struct dr_node *lmb, struct lmb_list_head *lmb_list) { int rc; lmb->lmb_of_node = configure_connector(lmb->drc_index); if (lmb->lmb_of_node == NULL) { release_drc(lmb->drc_index, MEM_DEV); return -1; } if (lmb_list->drconf_buf) { errno = 0; rc = update_drconf_node(lmb, lmb_list, ADD); if (errno == ENODEV) { /* Due to bug in pre 2.6.27 kernels, updating the * property in the device tree fails when the phandle * is processed as a signed int instead of unsigned * In this case we provide this little hack to allow * memory add to work on these kernels. */ say(DEBUG, "Assuming older kernel, trying to add " "node\n"); sprintf(lmb->ofdt_path, "%s/%s", OFDT_BASE, lmb->lmb_of_node->name); rc = add_device_tree_nodes(OFDT_BASE, lmb->lmb_of_node); } else { sprintf(lmb->ofdt_path, "%s/%s", OFDT_BASE, "/ibm,dynamic-reconfiguration-memory"); } } else { /* Add the new nodes to the device tree */ sprintf(lmb->ofdt_path, "%s/%s", OFDT_BASE, lmb->lmb_of_node->name); rc = add_device_tree_nodes(OFDT_BASE, lmb->lmb_of_node); } if (rc) return rc; if (! lmb_list->drconf_buf) { /* Find the physical address for this lmb. This is only * needed for non-drconf memory. The address for drconf * lmbs is correctly initialized when building the lmb list */ char *tmp = strrchr(lmb->ofdt_path, '@'); if (tmp == NULL) { say(DEBUG, "Could not determine physical address for " "%s\n", lmb->ofdt_path); remove_device_tree_nodes(lmb->ofdt_path); return -1; } lmb->lmb_address = strtoull(tmp + 1, NULL, 16); rc = get_lmb_size(lmb); if (rc) { remove_device_tree_nodes(lmb->ofdt_path); return rc; } } rc = get_mem_scns(lmb); if (rc) remove_device_tree_lmb(lmb, lmb_list); return rc; } /** * get_mem_scn_state * @brief Find the state of the specified memory section * * @param mem_scn memory section to validate * @return OFFLINE, ONLINE, or -1 for failures */ static int get_mem_scn_state(struct mem_scn *mem_scn) { char path[DR_PATH_MAX]; char state[8]; int file; int rc; memset(path, 0, DR_PATH_MAX); sprintf(path, "%s/state", mem_scn->sysfs_path); file = open(path, O_RDONLY); if (file <= 0) { say(DEBUG, "Could not open %s to validate its state.\n%s\n", path, strerror(errno)); return -1; } memset(state, 0, 8); rc = read(file, state, 8); close(file); if (!strncmp(state, "online", 6)) return ONLINE; if (! strncmp(state, "offline", 7)) return OFFLINE; return rc; } /** * set_mem_scn_state * @brief Marks a memory section as online or offline * * @param mem_scn memory section to update * @param state state to mark memory section * @return 0 on success, !0 otherwise */ static int set_mem_scn_state(struct mem_scn *mem_scn, int state) { int file; char path[DR_PATH_MAX]; int rc = 0; int unused; time_t t; char tbuf[128]; time(&t); strftime(tbuf, 128, "%T", localtime(&t)); memset(path, 0, DR_PATH_MAX); sprintf(path, "%s/state", mem_scn->sysfs_path); say(DEBUG, "%s Marking %s %s\n", tbuf, mem_scn->sysfs_path, state_strs[state]); file = open(path, O_WRONLY); if (file <= 0) { say(DEBUG, "Could not open %s to %s memory.\n\t%s\n", path, state_strs[state], strerror(errno)); close(file); return -1; } unused = write(file, state_strs[state], strlen(state_strs[state])); close(file); if (get_mem_scn_state(mem_scn) != state) { time(&t); strftime(tbuf, 128, "%T", localtime(&t)); say(DEBUG, "%s Could not %s %s.\n", tbuf, state_strs[state], mem_scn->sysfs_path); rc = EAGAIN; } else { time(&t); strftime(tbuf, 128, "%T", localtime(&t)); say(DEBUG, "%s Completed marking %s %s.\n", tbuf, mem_scn->sysfs_path, state_strs[state]); } return rc; } /** * probe_lmb * @brief Probe all of the memory sections of the lmb * * @param lmb pointer to lmb to probe * @returns 0 on success,!0 otherwise */ static int probe_lmb(struct dr_node *lmb) { struct mem_scn *scn; int probe_file; int rc = 0; probe_file = open(MEM_PROBE_FILE, O_WRONLY); if (probe_file <= 0) { say(DEBUG, "Could not open %s to probe memory\n", MEM_PROBE_FILE); return errno; } for (scn = lmb->lmb_mem_scns; scn; scn = scn->next) { char addr[DR_STR_MAX]; memset(addr, 0, DR_STR_MAX); sprintf(addr, "0x%"PRIx64, scn->phys_addr); say(DEBUG, "Probing memory address 0x%llx\n", scn->phys_addr); rc = write(probe_file, addr, strlen(addr)); if (rc == -1) { say(DEBUG, "Probe failed:\n%s\n", strerror(errno)); return rc; } } close(probe_file); return 0; } /** * set_lmb_state * * @param lmb lmb to set the state for * @param state 1 = online, 0 = offline * @returns 0 on success, !0 otherwise */ static int set_lmb_state(struct dr_node *lmb, int state) { struct mem_scn *scn; int rc = 0; struct stat sbuf; say(INFO, "Attempting to %s %s.\n", state_strs[state], lmb->drc_name); if (state == ONLINE) { rc = probe_lmb(lmb); if (rc) return rc; } for (scn = lmb->lmb_mem_scns; scn; scn = scn->next) { if (stat(scn->sysfs_path, &sbuf)) continue; rc = set_mem_scn_state(scn, state); if (rc) break; } if (rc) { /* Revert state of any memory sections of this lmb to their * original state */ int new_state = (state == OFFLINE) ? ONLINE : OFFLINE; for (scn = lmb->lmb_mem_scns; scn; scn = scn->next) { if (stat(scn->sysfs_path, &sbuf)) continue; if (get_mem_scn_state(scn) == state) set_mem_scn_state(scn, new_state); } } if (rc) { if (rc == EAGAIN) say(INFO, "Could not %s %s at this time.\n", state_strs[state], lmb->drc_name); else report_unknown_error(__FILE__, __LINE__); } else say(INFO, "%s is %s.\n", lmb->drc_name, state_strs[state]); return rc; } /** * add_lmbs * * Attempt to acquire and online the given number of LMBs. * This function calls itself recursively to simplify recovery * actions in case of an error. This is intended only for the case * where the user does not specify a drc-name. * * @param nr_lmbs number of lmbs to add * @param lmb_list list of lmbs on the partition * @returns 0 on success, !0 otherwise */ static int add_lmbs(struct options *opts, struct lmb_list_head *lmb_list) { int rc = 0; struct dr_node *lmb_head = lmb_list->lmbs; struct dr_node *lmb; lmb_list->lmbs_modified = 0; while (lmb_list->lmbs_modified < (int)opts->quantity) { if (drmgr_timed_out()) break; lmb = get_available_lmb(opts, lmb_head); if (lmb == NULL) return -1; /* Iterate only over the remaining LMBs */ lmb_head = lmb->next; rc = acquire_drc(lmb->drc_index); if (rc) { report_unknown_error(__FILE__, __LINE__); lmb->unusable = 1; continue; } rc = add_device_tree_lmb(lmb, lmb_list); if (rc) { report_unknown_error(__FILE__, __LINE__); release_drc(lmb->drc_index, MEM_DEV); lmb->unusable = 1; continue; } rc = set_lmb_state(lmb, ONLINE); if (rc) { report_unknown_error(__FILE__, __LINE__); remove_device_tree_lmb(lmb, lmb_list); release_drc(lmb->drc_index, MEM_DEV); lmb->unusable = 1; continue; } lmb_list->lmbs_modified++; } return rc; } /** * mem_add * @brief Add memory to the partition * * @param opts user options * @returns 0 on success, !0 otherwise */ static int mem_add(struct options *opts) { struct lmb_list_head *lmb_list; int rc; lmb_list = get_lmbs(LMB_NORMAL_SORT); if (lmb_list == NULL) { say(ERROR, "Could not gather LMB (logical memory block " "information.\n"); return -1; } say(DEBUG, "Attempting to add %d LMBs\n", opts->quantity); rc = add_lmbs(opts, lmb_list); say(DEBUG, "Added %d of %d requested LMB(s)\n", lmb_list->lmbs_modified, opts->quantity); printf("DR_TOTAL_RESOURCES=%d\n", lmb_list->lmbs_modified); free_lmbs(lmb_list); return rc; } /** * remove_lmbs * * @param nr_lmbs * @param opts * @param lmb_list * @return 0 on success, !0 otherwise */ static int remove_lmbs(struct options *opts, struct lmb_list_head *lmb_list) { struct dr_node *lmb_head = lmb_list->lmbs; struct dr_node *lmb; int rc; while (lmb_list->lmbs_modified < (int)opts->quantity) { if (drmgr_timed_out()) break; lmb = get_available_lmb(opts, lmb_head); if (!lmb) return -1; /* Iterate only over the remaining LMBs */ lmb_head = lmb->next; rc = set_lmb_state(lmb, OFFLINE); if (rc) { lmb->unusable = 1; continue; } rc = remove_device_tree_lmb(lmb, lmb_list); if (rc) { report_unknown_error(__FILE__, __LINE__); set_lmb_state(lmb, ONLINE); lmb->unusable = 1; continue; } while (lmb->lmb_mem_scns) { struct mem_scn *scn = lmb->lmb_mem_scns; lmb->lmb_mem_scns = scn->next; free(scn); } rc = release_drc(lmb->drc_index, 0); if (rc) { report_unknown_error(__FILE__, __LINE__); add_device_tree_lmb(lmb, lmb_list); set_lmb_state(lmb, ONLINE); lmb->unusable = 1; continue; } lmb->is_removable = 0; lmb_list->lmbs_modified++; } return 0; } /** * mem_remove * * @param opts * @return 0 on success, !0 otherwise */ static int mem_remove(struct options *opts) { struct lmb_list_head *lmb_list; struct dr_node *lmb; unsigned int removable = 0; unsigned int requested = opts->quantity; int rc = 0; lmb_list = get_lmbs(LMB_RANDOM_SORT); if (lmb_list == NULL) { say(ERROR, "Could not gather LMB (logical memory block " "information.\n"); return -1; } /* Can not know which lmbs are removable by the is_removable field * if AMS ballooning is active. */ if (!ams_balloon_active()) { /* Make sure we have enough removable memory to fulfill * this request */ for (lmb = lmb_list->lmbs; lmb; lmb = lmb->next) { if (lmb->is_removable) removable++; } if (removable == 0) { say(ERROR, "There is not enough removable memory " "available to fulfill the request.\n"); rc = -1; } if (removable < opts->quantity) { say(INFO, "Only %u LMBs are currently candidates " "for removal.\n", removable); opts->quantity = removable; } } if (!rc) { say(DEBUG, "Attempting removal of %d LMBs\n", opts->quantity); rc = remove_lmbs(opts, lmb_list); } say(ERROR, "Removed %d of %d requested LMB(s)\n", lmb_list->lmbs_modified, requested); if (lmb_list->lmbs_modified < requested) say(ERROR, "Unable to hotplug remove the remaining %d LMB(s)\n", requested - lmb_list->lmbs_modified); printf("DR_TOTAL_RESOURCES=%d\n", lmb_list->lmbs_modified); free_lmbs(lmb_list); return rc; } /* These two defines are taken from drivers/net/ehea/ehea.h in the kernel. * Unfortunately they do not appear in any header we can include so we * have to define the values here so we can check ehea capabilities. */ #define MEM_ADD_ATTR 0x0000000000000002 #define MEM_RM_ATTR 0x0000000000000004 /** * ehea_compatable * @brief Determine if ehea is loaded and if it can handle memory dlpar * * In order to properly support memory DLPAR on systems with HEAdevices, * we have to ensure that the ehea module is either not loaded or we are * using a version that can handle memory dlpar operations. Otherwise bad * stuff happens. * * This uses system() to run lsmod and grep to check for the presence * of the ehea module. If it is present we check its capabilities file * to determine if it can handle memory dlpar. * * @param action memory add/remove action that is to be checked for * @return 1 if we are ehea compatable, 0 otherwise */ static int ehea_compatable(int action) { FILE *fp; uint64_t flags = 0; int rc; rc = system("/sbin/lsmod | grep ehea >/dev/null 2>&1"); if (WEXITSTATUS(rc) != 0) { /* The ehea module is not loaded, everything is good */ return 1; } /* The module is loaded, now we need to see if it * can handle memory dlpar operations. */ fp = fopen("/sys/bus/ibmebus/drivers/ehea/capabilities", "r"); if (fp == NULL) { /* File doesn't exist, memory dlpar operations are not * supported by this version of the ehea driver. */ say(INFO, "The eHEA module for this system does not support " "memory DLPAR operations.\n"); return 0; } rc = fscanf(fp, "%"PRIu64, &flags); fclose(fp); /* Assume memory dlpar is not supported */ rc = 0; if ((action == ADD) && (flags & MEM_ADD_ATTR)) rc = 1; if ((action == REMOVE) && (flags & MEM_RM_ATTR)) rc = 1; if (!rc) say(INFO, "The eHEA modules loaded on this system does not " "support memory DLPAR %s operations.\n", (action == ADD) ? "add" : "remove"); return rc; } int valid_mem_options(struct options *opts) { /* default to a quantity of 1 */ if (opts->quantity == 0) opts->quantity = 1; if ((opts->action != ADD) && (opts->action != REMOVE)) { say(ERROR, "The '-r' or '-a' option must be specified for " "memory operations\n"); return -1; } /* The -s option can specify a drc name or drc index */ if (opts->usr_drc_name && !strncmp(opts->usr_drc_name, "0x", 2)) { opts->usr_drc_index = strtoul(opts->usr_drc_name, NULL, 16); opts->usr_drc_name = NULL; } return 0; } int drslot_chrp_mem(struct options *opts) { int rc = -1; if (opts->p_option) { /* This is a entitlement or weight change */ return update_sysparm(opts); } if (! mem_dlpar_capable() || ! ehea_compatable(opts->action)) { say(ERROR, "DLPAR memory operations are not supported on" "this kernel."); return -1; } /* The recursive nature of the routines that add/remove lmbs * require that the quantity be non-zero. */ if (opts->usr_drc_name) opts->quantity = 1; switch (opts->action) { case ADD: rc = mem_add(opts); break; case REMOVE: rc = mem_remove(opts); break; } return rc; } powerpc-utils-1.2.26/src/drmgr/drslot_chrp_pci.c0000664000175000017510000005571412527176005016610 00000000000000/** * @file drslot_chrp_pci.c * * Copyright (C) IBM Corporation 2006 * */ #include #include #include #include #include #include #include #include #include "rtas_calls.h" #include "dr.h" #include "drpci.h" static char *sw_error = "Internal software error. Contact your service " "representative.\n"; static char *speed_error = "Add operation failed. The 33MHz PCI card may\n" "not be added to the PCI bus with another adapter\n" "running at 66 MHz.\n"; #define HW_ERROR -1 /* RTAS hardware error */ /* Error status from set-power */ #define SPEED_ERROR -9000 /* 33MHz card on bus running at 66MHz */ #define USER_QUIT 0 /* user wants to bail out of operation */ #define USER_CONT 1 /* user wants to continue with operation */ static char *usagestr = "-c pci -s {-i | -a [-I] | -r [-I] | -R [-I]}"; /** * pci_usage * */ void pci_usage(char **pusage) { *pusage = usagestr; } /** * process_led * * sets the given slot's led to the specified state. If the * return from set_led is bad, call the error_exit function to clean up * and exit the command. * * @param lslot pointer to slot we're setting * @param led setting for led */ static int process_led(struct dr_node *node, int led) { int rtas_rc; rtas_rc = rtas_set_indicator(DR_INDICATOR, node->drc_index, led); if (rtas_rc) { if (rtas_rc == HW_ERROR) say(ERROR, "%s", hw_error); else say(ERROR, "%s", sw_error); return -1; } return 0; } /** * identify_slot * * Given a slot structure, set the led of the slot to the identify * state and print a message to the user. Read the user input and return it. * * @param islot pointer to slot to be set * @returns USER_CONT if user pushes enter key, USER_QUIT otherwise */ static int identify_slot(struct dr_node *node) { if (process_led(node, LED_ID)) return USER_QUIT; printf("The visual indicator for the specified PCI slot has\n" "been set to the identify state. Press Enter to continue\n" "or enter x to exit.\n"); if (getchar() == '\n') return (USER_CONT); else return (USER_QUIT); } static char * find_drc_name(uint32_t drc_index, struct dr_node *all_nodes) { struct dr_node *node; node = all_nodes; while (node != NULL) { say(DEBUG, "%#x =? %#x\n", drc_index, node->drc_index); if (node->drc_index == drc_index) { say(DEBUG, "Found drc_name %s\n", node->drc_name); return node->drc_name; } else node = node->next; } if ((node == NULL)) say(ERROR, "Could not find drc_name for index %#x\n", drc_index); return NULL; } /** * find_slot * * Searches through all slots and returns a pointer to the slot * whose location code matches the user input. If no slot is found, * an error message is displayed and the entire command is exited. * * This routine uses a common function "cmp_drcname" so that all routines * validating a slot name will compare on the same basis. A slot could be * found, but if the "skip" field of the slot structure is set, we * shouldn't use it. * * @returns pointer to slot on success, NULL otherwise */ static struct dr_node * find_slot(char *drc_name, struct dr_node *all_nodes) { struct dr_node *node; /* working pointer */ /* Search through all_nodes to see if the * user-specified location exists. */ node = all_nodes; while (node != NULL) { if (cmp_drcname(node->drc_name, drc_name)) break; else node = node->next; } if ((node == NULL) || (node->skip)) say(ERROR, "The specified PCI slot is either invalid\n" "or does not support hot plug operations.\n"); return node; } static int check_card_presence(struct options *opts, struct dr_node *node) { int state = EMPTY; int i, keep_working; say(DEBUG, "Waiting for the card to appear...\n"); do { keep_working = 0; for (i = 0; i < 30; i++) { state = dr_entity_sense(node->drc_index); if (state != EMPTY) return state; sleep(1); } if (0 == opts->noprompt) { printf("The card still does not appear to be present" "\npress Enter to continue to wait or enter " "'x' to exit.\n"); if ((getchar() == '\n')) keep_working = 1; } } while (keep_working); return state; } /** * card_present * @brief Determines if there is a card present in the specified slot * * Attempt to check if a card is present. If we get a definite answer, * return that and indicate that we did not turn the power on. Depending * on the adapter, we may have to power on and we may have to unisolate * to determine if a card is present. If that's the case, power on * maybe isolate and try sensing again. If we hit fatal errors, call * error_exit to clean up and exit the command. * * @param opts * @param slot pointer to slot we're checking * @param power_state state of power when we leave this routine * @param isolate_state state of isolation when we leave this routine * @returns EMPTY or PRESENT */ static int card_present(struct options *opts, struct dr_node *node, int *power_state, int *isolate_state) { int state, rc; *power_state = POWER_OFF; /* initialize */ *isolate_state = ISOLATE; state = check_card_presence(opts, node); if ((state == EMPTY) || (state == PRESENT)) return state; else if (state == HW_ERROR) { say(ERROR, "%s", hw_error); return -1; } else if ((state == NEED_POWER) || (state == PWR_ONLY)) { /* set power on, and if needed, unisolate too */ rc = set_power(node->drc_power, POWER_ON); if (rc) { if (rc == HW_ERROR) { say(ERROR, "%s", hw_error); return -1; } else if (rc == SPEED_ERROR) { say(ERROR, "%s", speed_error); set_power(node->drc_power, POWER_OFF); return -1; } /* Catch any other errors. */ else { say(ERROR, "%s", sw_error); set_power(node->drc_power, POWER_OFF); return -1; } } *power_state = POWER_ON; if (state == NEED_POWER) { /* If we get here, we have power on now * but we still need to unisolate */ rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, UNISOLATE); if (rc) { if (rc == HW_ERROR) say(ERROR, "%s", hw_error); else say(ERROR, "%s", sw_error); rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); set_power(node->drc_power, POWER_OFF); return -1; } *isolate_state = UNISOLATE; } /* Now we have power on, and the unisolate is done * if it was needed. check for card again. */ state = check_card_presence(opts, node); if ((state == EMPTY) || (state == PRESENT)) return state; if (state) { if (rc == HW_ERROR) say(ERROR, "%s", hw_error); else say(ERROR, "%s", sw_error); rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); set_power(node->drc_power, POWER_OFF); return -1; } } else { /* catch any other errors from first dr_entity_sense */ say(ERROR, "%s", sw_error); } return state; } /** * do_identify * @brief Main processor for the drslot_chrp_pci -i command * * Validate the user input, a slot name. Call the routine which actually * does the call to set the LED. When we're done identifying, reset the * LED based on whether or not there's an OF node representing an adapter * connected to the slot. If an adapter node exists, turn the LED on, * else turn if off. */ static int do_identify(struct options *opts, struct dr_node *all_nodes) { struct dr_node *node; int usr_key; int led_state; node = find_slot(opts->usr_drc_name, all_nodes); if (node == NULL) return -1; usr_key = identify_slot(node); /* when we're done with identify, put the LED back * where we think it ought to be. ON if an adapter is * connected, OFF if not */ if (node->children == NULL) led_state = LED_OFF; else led_state = LED_ON; if (process_led(node, led_state)) return -1; if (usr_key == USER_QUIT) return -1; return 0; /* don't return anything on identify */ } /** * add_work * * Prepares a PCI hot plug slot for adding an adapter, then * configures the adapter and any PCI adapters below into the * kernel's and /proc's Open Firmware device tree. * * If there are any errors from the RTAS routines, * the slot is powered off, isolated, and the LED is turned off. No * configuration is completed. * If the OF tree cannot be updated, the slot is powered * off, isolated, and the LED is turned off. * * @param opts * @param slot * @returns 0 on success, !0 on failure */ static int add_work(struct options *opts, struct dr_node *node) { int pow_state; /* Tells us if power was turned on when */ int iso_state; /* Tells us isolation state after */ int rc; struct of_node *new_nodes;/* nodes returned from configure_connector */ /* if we're continuing, set LED_ON and see if a card is really there. */ if (process_led(node, LED_ON)) return -1; say(DEBUG, "is calling card_present\n"); rc = card_present(opts, node, &pow_state, &iso_state); if (!rc) { say(ERROR, "No PCI card was detected in the specified " "PCI slot.\n"); rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); set_power(node->drc_power, POWER_OFF); return -1; } if (!pow_state) { say(DEBUG, "is calling set_power(POWER_ON index 0x%x, " "power_domain 0x%x\n", node->drc_index, node->drc_power); rc = set_power(node->drc_power, POWER_ON); if (rc) { if (rc == HW_ERROR) say(ERROR, "%s", hw_error); else if (rc == SPEED_ERROR) say(ERROR, "%s", speed_error); else say(ERROR, "%s", sw_error); rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); set_power(node->drc_power, POWER_OFF); return -1; } } if (!iso_state) { say(DEBUG, "calling rtas_set_indicator(UNISOLATE index 0x%x)\n", node->drc_index); rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, UNISOLATE); if (rc) { if (rc == HW_ERROR) say(ERROR, "%s", hw_error); else say(ERROR, "%s", sw_error); rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); set_power(node->drc_power, POWER_OFF); return -1; } } /* Now go get all the new nodes for this adapter. If * the return status requires a message, print it out * and exit, otherwise, add the nodes to the OF tree. */ new_nodes = configure_connector(node->drc_index); if (new_nodes == NULL) { rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); set_power(node->drc_power, POWER_OFF); return -1; } say(DEBUG, "Adding %s to %s\n", new_nodes->name, node->ofdt_path); rc = add_device_tree_nodes(node->ofdt_path, new_nodes); if (rc) { say(DEBUG, "add_device_tree_nodes failed at %s\n", node->ofdt_path); say(ERROR, "%s", sw_error); rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); set_power(node->drc_power, POWER_OFF); return -1; } return 0; } /** * do_add * * Prepares a PCI hot plug slot for adding an adapter, then * configures the adapter and any PCI adapters below into * the Open Firmware device tree. * * Verifies that a given hot plug PCI slot does not have an adapter * already connected, identifies the slot to the user unless requested not * to with the -i flag, prompts the user to connect the adapter, powers * the slot on, and calls configure connector. When configure connector * completes and returns the new node(s) for the new PCI adapter and any * attached devices then the Open Firmware device tree is * updated to reflect the new devices. */ static int do_add(struct options *opts, struct dr_node *all_nodes) { struct dr_node *node; int usr_key = USER_CONT; int rc; node = find_slot(opts->usr_drc_name, all_nodes); if (node == NULL) return -1; /* Prompt user only if in interactive mode. */ if (0 == opts->noprompt) { if (!opts->no_ident) usr_key = identify_slot(node); if (usr_key == USER_QUIT) { if (node->children == NULL) process_led(node, LED_OFF); else process_led(node, LED_ON); return 0; } } if (node->children != NULL) { /* If there's already something here, turn the * LED on and exit with user error. */ process_led(node, LED_ON); say(ERROR, "The specified PCI slot is already occupied.\n"); return -1; } /* Now it's time to isolate, power off, set the * action LED, and prompt the user to put the * card in. */ say(DEBUG, "is calling rtas_set_indicator(ISOLATE index 0x%x)\n", node->drc_index); rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); if (rc) { if (rc == HW_ERROR) say(ERROR, "%s", hw_error); else say(ERROR, "%s", sw_error); set_power(node->drc_power, POWER_OFF); return -1; } say(DEBUG, "is calling set_power(POWER_OFF index 0x%x, " "power_domain 0x%x) \n", node->drc_index, node->drc_power); rc = set_power(node->drc_power, POWER_OFF); if (rc) { if (rc == HW_ERROR) say(ERROR, "%s", hw_error); else say(ERROR, "%s", sw_error); return -1; } if (0 == opts->noprompt) { /* Prompt user to put in card and to press * Enter to continue or other key to exit. */ if (process_led(node, LED_ACTION)) return -1; printf("The visual indicator for the specified PCI slot has\n" "been set to the action state. Insert the PCI card\n" "into the identified slot, connect any devices to be\n" "configured and press Enter to continue. Enter x to " "exit.\n"); if (!(getchar() == '\n')) { process_led(node, LED_OFF); return 0; } } /* Call the routine which determines * what the user wants and does it. */ rc = add_work(opts, node); if (rc) return rc; say(DEBUG, "is calling enable_slot to config adapter\n"); /* Try to config the adapter. The rpaphp module doesn't play well with * qemu pci slots so we let the generic kernel pci code probe the device * by rescanning the bus in the qemu virtio case. */ if (!opts->pci_virtio) set_hp_adapter_status(PHP_CONFIG_ADAPTER, node->drc_name); else pci_rescan_bus(); return 0; } /** * remove_work * * Removes nodes associated a PCI slot from the * Open Firmware device tree and isolates and powers off the PCI slot. * * A remove may be specified by the location code of the PCI slot. * Unless the user specifies the -I flag, the slot is identified to * the user. * Nodes representing the device(s) are removed from the * Open Firmware device tree. The slot is isolated and powered off, * and the LED is turned off. * * @returns pointer slot on success, NULL on failure */ static struct dr_node * remove_work(struct options *opts, struct dr_node *all_nodes) { struct dr_node *node; struct dr_node *child; int rc; int usr_key = USER_CONT; node = find_slot(opts->usr_drc_name, all_nodes); if (node == NULL) return NULL; say(DEBUG, "found node: drc name=%s, index=0x%x, path=%s\n", node->drc_name, node->drc_index, node->ofdt_path); /* Prompt user only if not in noprompt mode */ if (0 == opts->noprompt) { if (!opts->no_ident) usr_key = identify_slot(node); if (usr_key == USER_QUIT) { if (node->children == NULL) process_led(node, LED_OFF); else process_led(node, LED_ON); return NULL; } } /* Turn on the LED while we go do some work. */ if (process_led(node, LED_ON)) return NULL; /* Make sure there's something there to remove. */ if (node->children == NULL) { process_led(node, LED_OFF); say(ERROR, "There is no configured card to remove from the " "specified PCI slot.\n"); return NULL; } if (!opts->pci_virtio) { /* Make sure all the devices are * not configured before proceeding */ if (get_hp_adapter_status(node->drc_name) == CONFIG) { say(DEBUG, "unconfiguring adapter in slot[%s]\n", node->drc_name); set_hp_adapter_status(PHP_UNCONFIG_ADAPTER, node->drc_name); int rc = get_hp_adapter_status(node->drc_name); if (rc != NOT_CONFIG) { say(ERROR, "Unconfig adapter failed.\n"); return NULL; } } else { /* In certain cases such as a complete failure of the * adapter there may not have been the possibility to clean * up everything. Mark these adapaters for additional * processing later. */ node->post_replace_processing = 1; } } else { /* The rpaphp module fails to work with qemu pci slots so * so we rely on the devices remove attribute in sysfs to * inform the generic kernel pci code to remove the qemu virtio * device */ for (child = node->children; child; child = child->next) pci_remove_device(child); /* The kernel adds the pci device removal to a work queue which * makes the previous pci_remove_device call asynchronous. Need * to let kernel finish cleanup before informing qemu to isolate * and power down virtio pci device. */ sleep(3); } /* Call subroutine to remove node(s) from * the device tree. */ for (child = node->children; child; child = child->next) { rc = remove_device_tree_nodes(child->ofdt_path); if (rc) { say(ERROR, "%s", sw_error); rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); set_power(node->drc_power, POWER_OFF); return NULL; } } /* We have to isolate and power off before * allowing the user to physically remove * the card. */ say(DEBUG, "is calling rtas_set_indicator(ISOLATE index 0x%x)\n", node->drc_index); rc = rtas_set_indicator(ISOLATION_STATE, node->drc_index, ISOLATE); if (rc) { if (rc == HW_ERROR) say(ERROR, "%s", hw_error); else say(ERROR, "%s", sw_error); set_power(node->drc_power, POWER_OFF); return NULL; } say(DEBUG, "is calling set_power(POWER_OFF index 0x%x, power_domain " "0x%x)\n", node->drc_index, node->drc_power); rc = set_power(node->drc_power, POWER_OFF); if (rc) { if (rc == HW_ERROR) say(ERROR, "%s", hw_error); else say(ERROR, "%s", sw_error); set_power(node->drc_power, POWER_OFF); return NULL; } return node; } /** * do_remove * * Removes nodes associated a PCI slot from the Open Firmware * device tree and isolates and powers off the PCI slot. * * A remove may be specified by the location code of the PCI slot. * Unless the user specifies the -I flag, the slot is identified * the user. Nodes representing the device(s) are removed from the * Open Firmware device tree. The slot is isolated and powered off, * and the LED is turned off. * * If there are any errors from the RTAS routines, * the slot is powered off, isolated, and the LED is turned off. No * unconfiguration is completed. * If the OF tree cannot be updated, the slot is powered * off, isolated, and the LED is turned off. */ static int do_remove(struct options *opts, struct dr_node *all_nodes) { struct dr_node *node; /* Remove the specified slot and update the device-tree */ node = remove_work(opts, all_nodes); if (node == NULL) return -1; /* Prompt user to remove card and to press * Enter to continue. Can't exit out of here. */ if (0 == opts->noprompt) { if (process_led(node, LED_ACTION)) return -1; printf("The visual indicator for the specified PCI slot " "has\nbeen set to the action state. Remove the PCI " "card\nfrom the identified slot and press Enter to " "continue.\n"); getchar(); if (process_led(node, LED_OFF)) return -1; } return 0; } /** * do_replace * @brief Allows the replacement of an adapter connected to a * PCI hot plug slot * * A replace may be specified by the location code of the PCI slot. * Unless the user specifies the -I flag, the slot is identified to * the user. * Nodes representing the old device(s) are removed from the * Open Firmware device tree. The slot is isolated and powered off, * and the LED is set to the ACTION state. The user is prompted to replace * the adpater. The slot is powered on and unisolated and configure * connector is executed. * * If there are any errors from the RTAS routines, * the slot is powered off, isolated, and the LED is turned off. If the * original adapter has been removed, it is left in that state. * If the OF tree cannot be updated, the slot is powered * off, isolated, and the LED is turned off. */ static int do_replace(struct options *opts, struct dr_node *all_nodes) { struct dr_node *repl_node; int rc; /* Call the routine which does the work of getting the node info, * then removing it from the OF device tree. */ repl_node = remove_work(opts, all_nodes); if (repl_node == NULL) return -1; if (!repl_node->children) { say(ERROR, "Bad node struct.\n"); return -1; } say(DEBUG, "repl_node:path=%s node:path=%s\n", repl_node->ofdt_path, repl_node->children->ofdt_path); /* Prompt user to replace card and to press * Enter to continue or x to exit. Exiting here * means the original card has been removed. */ if (0 == opts->noprompt) { if (process_led(repl_node, LED_ACTION)) return -1; printf("The visual indicator for the specified PCI slot " "has\nbeen set to the action state. Replace the PCI " "card\nin the identified slot and press Enter to " "continue.\nEnter x to exit. Exiting now leaves the " "PCI slot\nin the removed state.\n"); if (!(getchar() == '\n')) { process_led(repl_node, LED_OFF); return 0; } } rc = add_work(opts, repl_node); if (rc) return rc; say(DEBUG, "CONFIGURING the card in node[name=%s, path=%s]\n", repl_node->drc_name, repl_node->ofdt_path); set_hp_adapter_status(PHP_CONFIG_ADAPTER, repl_node->drc_name); if (repl_node->post_replace_processing) { int prompt_save = opts->noprompt; say(DEBUG, "Doing post replacement processing...\n"); /* disable prompting for post-processing */ opts->noprompt = 1; repl_node = remove_work(opts, repl_node); rc = add_work(opts, repl_node); if (!rc) set_hp_adapter_status(PHP_CONFIG_ADAPTER, repl_node->drc_name); opts->noprompt = prompt_save; } return rc; } int valid_pci_options(struct options *opts) { if ((opts->action == IDENTIFY) && (opts->no_ident)) { say(ERROR, "Cannot specify the -i and -I option together\n"); return -1; } /* The -s option can specify a drc name or drc index */ if (opts->usr_drc_name && !strncmp(opts->usr_drc_name, "0x", 2)) { opts->usr_drc_index = strtoul(opts->usr_drc_name, NULL, 16); opts->usr_drc_name = NULL; } if (opts->usr_drc_name == NULL && !opts->usr_drc_index) { say(ERROR, "A drc name or index must be specified\n"); return -1; } if ((opts->action != ADD) && (opts->action != REMOVE) && (opts->action != IDENTIFY) && (opts->action != REPLACE)) { say(ERROR, "The '-r', '-a', '-R' or '-i' option must be spcified " "for PCI operations\n"); return -1; } return 0; } int drslot_chrp_pci(struct options *opts) { int rc; struct dr_node *all_nodes; all_nodes = get_hp_nodes(); if (all_nodes == NULL) { say(ERROR, "There are no PCI hot plug slots on this system.\n"); return -1; } #ifdef DBG_HOT_PLUG print_slots_list(all_nodes); #endif if (!opts->usr_drc_name) opts->usr_drc_name = find_drc_name(opts->usr_drc_index, all_nodes); switch (opts->action) { case ADD: rc = do_add(opts, all_nodes); break; case REMOVE: rc = do_remove(opts, all_nodes); break; case REPLACE: rc = do_replace(opts, all_nodes); break; case IDENTIFY: rc = do_identify(opts, all_nodes); break; default: say(ERROR, "Invalid operation specified!\n"); rc = -1; break; } free_node(all_nodes); return rc; } powerpc-utils-1.2.26/src/drmgr/drslot_chrp_phb.c0000664000175000017510000002452212542271360016574 00000000000000/** * @file drslot_chrp_phb.c * * * Copyright (C) IBM Corporation 2006 */ #include #include #include #include #include #include #include "dr.h" #include "drpci.h" #include "ofdt.h" static char *usagestr = "-c phb [-Q | -r | -a] -s "; static int release_phb(struct dr_node *); static int acquire_phb(char *, struct dr_node **); /** * phb_usage * @brief return the usage message * * @returns 1, always */ void phb_usage(char **pusage) { *pusage = usagestr; } /** * query_phb * * @param op * @returns 0 if a remove would succeed, or if it's alreday been removed * @returns 1 if a remove would not succeed */ static int query_phb(struct options *opts) { struct dr_node *phb; struct dr_node *child; phb = get_node_by_name(opts->usr_drc_name, PHB_NODES); if (phb == NULL) return RC_NONEXISTENT; /* If this PHB still owns children that are not hotplug, fail. */ for (child = phb->children; child; child = child->next) { if ((child->is_owned) && (child->dev_type != PCI_HP_DEV)) { free_node(phb); return RC_IN_USE; } } free_node(phb); return RC_LINUX_SLOT; } /** * release_phb * */ static int release_phb(struct dr_node *phb) { int rc; rc = remove_device_tree_nodes(phb->ofdt_path); if (rc) return rc; if (phb->phb_ic_ofdt_path[0] != '\0') { rc = remove_device_tree_nodes(phb->phb_ic_ofdt_path); if (rc) return rc; } rc = release_drc(phb->drc_index, PHB_DEV); return rc; } struct hpdev { struct hpdev *next; char path[256]; char devspec[256]; }; #define SYSFS_PCI_DEV_PATH "/sys/bus/pci/devices" static void free_hpdev_list(struct hpdev *hpdev_list) { struct hpdev *hpdev; while (hpdev_list) { hpdev = hpdev_list; hpdev_list = hpdev_list->next; free(hpdev); } } static int get_os_hp_devices(struct hpdev **hpdev_list) { struct hpdev *hp_list = NULL; struct hpdev *hpdev; DIR *d; struct dirent *de; int rc = 0; d = opendir(SYSFS_PCI_DEV_PATH); if (!d) { say(ERROR, "Failed to open %s\n", SYSFS_PCI_DEV_PATH); return -1; } while ((de = readdir(d)) != NULL) { if (is_dot_dir(de->d_name)) continue; hpdev = zalloc(sizeof(*hpdev)); if (!hpdev) { rc = -1; break; } rc = sprintf(hpdev->path, "%s/%s", SYSFS_PCI_DEV_PATH, de->d_name); if (rc < 0) break; rc = get_str_attribute(hpdev->path, "devspec", hpdev->devspec, 256); if (rc) break; say(DEBUG, "HPDEV: %s\n %s\n", hpdev->path, hpdev->devspec); hpdev->next = hp_list; hp_list = hpdev; } closedir(d); if (rc) { free_hpdev_list(hp_list); hp_list = NULL; } *hpdev_list = hp_list; return rc; } static int hp_remove_os_device(struct hpdev *hpdev) { FILE *file; char path[256]; int rc; sprintf(path, "%s/%s", hpdev->path, "remove"); file = fopen(path, "w"); if (!file) return -1; say(DEBUG, "Removing %s\n", hpdev->path); rc = fwrite("1", 1, 1, file); if (rc == 1) rc = 0; fclose(file); sleep(5); return rc; } static int disable_os_hp_children_recurse(struct dr_node *phb, struct hpdev *hpdev_list, char *ofpath) { struct hpdev *hpdev; DIR *d; struct dirent *de; int rc = 0; d = opendir(ofpath); if (!d) return -1; while ((de = readdir(d)) != NULL) { char devspec[256]; if (is_dot_dir(de->d_name)) continue; if (de->d_type == DT_DIR) { char lpath[4096]; sprintf(lpath, "%s/%s", ofpath, de->d_name); rc = disable_os_hp_children_recurse(phb, hpdev_list, lpath); } memset(devspec, 0, 256); sprintf(devspec, "%s/%s", ofpath + strlen(OFDT_BASE), de->d_name); for (hpdev = hpdev_list; hpdev; hpdev = hpdev->next) { if (!strcmp(hpdev->devspec, devspec)) { rc = hp_remove_os_device(hpdev); break; } } if (rc) { say(ERROR, "Failed to hotplug remove %s\n", hpdev->path); break; } } closedir(d); return rc; } static int disable_os_hp_children(struct dr_node *phb) { struct hpdev *hpdev_list; int rc = 0; rc = get_os_hp_devices(&hpdev_list); if (rc) return -1; rc = disable_os_hp_children_recurse(phb, hpdev_list, phb->ofdt_path); free_hpdev_list(hpdev_list); return rc; } /** * remove_phb * * @param op * @returns 0 on success, !0 otherwise */ static int remove_phb(struct options *opts) { struct dr_node *phb; struct dr_node *child; struct dr_node *hp_list; int rc = 0; phb = get_node_by_name(opts->usr_drc_name, PHB_NODES); if (phb == NULL) return RC_NONEXISTENT; /* If this PHB still owns children that are not hotplug, fail. */ for (child = phb->children; child; child = child->next) { if ((child->is_owned) && (child->dev_type != PCI_HP_DEV)) { rc = -1; goto phb_remove_error; } } /* Now, disable any hotplug children */ hp_list = get_hp_nodes(); for (child = phb->children; child; child = child->next) { struct dr_node *slot; if (child->dev_type == PCI_HP_DEV) { rc = disable_hp_children(child->drc_name); if (rc) say(ERROR, "failed to disable hotplug children\n"); /* find dr_node corresponding to child slot's drc_name */ for (slot = hp_list; slot; slot = slot->next) if (!strcmp(child->drc_name, slot->drc_name)) break; /* release any hp children from the slot */ rc = release_hp_children_from_node(slot); if (rc && rc != -EINVAL) { say(ERROR, "failed to release hotplug children\n"); goto phb_remove_error; } } } /* If there are any directories under the phb left at this point, * they are OS hotplug devies. Note: this is different from DR * hotplug devices. This really occurs on systems that do not * support DR hotplug devices. The device tree does not get populated * with drc information for these devices and such they do not appear * on the list generated by the calls to get_node_* * * For these devices we simply hotplug remove them from the OS. */ rc = disable_os_hp_children(phb); if (rc) goto phb_remove_error; rc = dlpar_remove_slot(phb->drc_name); if (rc) { say(ERROR, "kernel remove failed for %s, rc = %d\n", phb->drc_name, rc); goto phb_remove_error; } rc = release_phb(phb); phb_remove_error: if (phb) free_node(phb); return rc; } /** * acquire_phb * */ static int acquire_phb(char *drc_name, struct dr_node **phb) { struct dr_connector drc; struct of_node *of_nodes; char path[DR_PATH_MAX]; int rc; rc = get_drc_by_name(drc_name, &drc, path, OFDT_BASE); if (rc) { say(ERROR, "Could not find drc index for %s, unable to add the" "PHB.\n", drc_name); return rc; } rc = acquire_drc(drc.index); if (rc) return rc; of_nodes = configure_connector(drc.index); if (of_nodes == NULL) { release_drc(drc.index, PHB_DEV); return -1; } rc = add_device_tree_nodes(path, of_nodes); free_of_node(of_nodes); if (rc) { say(ERROR, "add_device_tree_nodes failed at %s\n", path); release_drc(drc.index, PHB_DEV); return -1; } /* Now that the node has been added to the device-tree, retrieve it. * This also acts as a sanity check that everything up to this * point has succeeded. */ *phb = get_node_by_name(drc_name, PHB_NODES); if (*phb == NULL) { say(ERROR, "Could not get find \"%s\"\n", drc_name); /* or should we call release_drc? but need device type */ release_drc(drc.index, PHB_DEV); return -1; } return 0; } /** * add_phb * * @param op * @returns 0 on success, !0 otherwise */ static int add_phb(struct options *opts) { struct dr_node *phb = NULL; int rc, n_children = 0; phb = get_node_by_name(opts->usr_drc_name, PHB_NODES); if (phb) { say(ERROR, "PHB is already owned by this partition\n"); rc = RC_ALREADY_OWN; goto phb_add_error; } rc = acquire_phb(opts->usr_drc_name, &phb); if (rc) return rc; rc = acquire_hp_children(phb->ofdt_path, &n_children); if (rc) { if (release_phb(phb)) { say(ERROR, "Unknown failure. Data may be out of sync " "and\nthe system may require a reboot.\n"); } goto phb_add_error; } rc = dlpar_add_slot(phb->drc_name); if (rc) { if (n_children) { if (release_hp_children(phb->drc_name)) { say(ERROR, "Unknown failure. Data may be out " "of sync and\nthe system may require " "a reboot.\n"); } } if (release_phb(phb)) { say(ERROR, "Unknown failure. Data may be out of sync " "and\nthe system may require a reboot.\n"); } goto phb_add_error; } if (n_children) { rc = enable_hp_children(phb->drc_name); if (rc) { say(ERROR, "Adapter configuration failed.\n"); if (release_hp_children(phb->drc_name)) { say(ERROR, "Unknown failure. Data may be out " "of sync and \nthe system may require " "a reboot.\n"); } if (dlpar_remove_slot(phb->drc_name)) { say(DEBUG, "remove %s from hotplug subsystem " "failed\n", phb->drc_name); say(ERROR, "Unknown failure. Data may be out " "of sync and \nthe system may require " "a reboot.\n"); } if (release_phb(phb)) { say(ERROR, "Unknown failure. Data may be out " "of sync and \nthe system may require " "a reboot.\n"); } } } phb_add_error: if (phb) free_node(phb); return rc; } int valid_phb_options(struct options *opts) { /* The -s option can specify a drc name or drc index */ if (opts->usr_drc_name && !strncmp(opts->usr_drc_name, "0x", 2)) { opts->usr_drc_index = strtoul(opts->usr_drc_name, NULL, 16); opts->usr_drc_name = NULL; } if (opts->usr_drc_name == NULL && !opts->usr_drc_index) { say(ERROR, "A drc name or index must be specified\n"); return -1; } if ((opts->action != ADD) && (opts->action != REMOVE) && (opts->action != QUERY)) { say(ERROR, "The '-r', '-a', or '-Q' option must be specified " "for PHB operations.\n"); return -1; } return 0; } int drslot_chrp_phb(struct options *opts) { int rc = -1; if (! phb_dlpar_capable()) { say(ERROR, "DLPAR PHB operations are not supported on" "this kernel."); return rc; } if (!opts->usr_drc_name) { struct dr_connector *drc_list = get_drc_info(OFDT_BASE); opts->usr_drc_name = drc_index_to_name(opts->usr_drc_index, drc_list); if (!opts->usr_drc_name) { say(ERROR, "Could not locate DRC name for DRC index: 0x%x", opts->usr_drc_index); return -1; } } switch(opts->action) { case ADD: rc = add_phb(opts); break; case REMOVE: rc = remove_phb(opts); break; case QUERY: rc = query_phb(opts); break; } return rc; } powerpc-utils-1.2.26/src/drmgr/drslot_chrp_slot.c0000664000175000017510000001545312527176005017012 00000000000000/** * @file drslot_chrp_slot.c * * Copyright (C) IBM Corporation 2006 * */ #include #include #include #include #include #include #include #include #include "dr.h" #include "drpci.h" #include "ofdt.h" static char *usagestr = "-c slot {-a | -r | -Q} -s "; void slot_usage(char **pusage) { *pusage = usagestr; } static int query_slot(struct dr_node *node, struct options *opts) { if (node == NULL) return RC_NONEXISTENT; if (! node->is_owned) { say(ERROR, "%s not owned by partition\n", opts->usr_drc_name); return RC_DONT_OWN; } /* Special case for HMC */ return RC_LINUX_SLOT; } /** * release_slot * */ static int release_slot(struct dr_node *slot) { int rc; rc = release_drc(slot->drc_index, slot->dev_type); if (rc) return rc; rc = remove_device_tree_nodes(slot->ofdt_path); if (rc) { acquire_drc(slot->drc_index); return rc; } return rc; } /** * remove_slot * */ static int remove_slot(struct dr_node *node) { int rc,rc2; rc = disable_hp_children(node->drc_name); if (rc) say(ERROR, "failed to disable hotplug children\n"); rc = release_hp_children(node->drc_name); if (rc && rc != -EINVAL) { say(ERROR, "failed to release hotplug children\n"); return rc; } say(DEBUG, "The sensor-state of drc_index 0x%x is %d\n", node->drc_index, dr_entity_sense(node->drc_index)); /* need to remove slot from sysfs which will * "Hot unplug" the slot from pci world. unmap_bus_range will be * done here also. */ rc = dlpar_remove_slot(node->drc_name); if (rc) { say(DEBUG, "remove %s from hotplug subsystem failed\n", node->drc_name); say(ERROR, "Unknown failure. Data may be out of sync and \n" "the system may require a reboot.\n"); return rc; } rc = release_slot(node); if (rc) { int num_acquired = 0; // try to restore to previous state rc2 = acquire_hp_children(node->ofdt_path, &num_acquired); if (rc2 && rc2 != -EINVAL) { say(ERROR, "Unknown failure %d. Data may be out of " "sync and\nthe system may require a reboot.\n", rc2); return rc; } rc2 = dlpar_add_slot(node->drc_name); if (rc2) { say(ERROR, "Unknown failure %d. Data may be out of " "sync and\nthe system may require a reboot.\n", rc2); return rc; } if (num_acquired) { rc2 = enable_hp_children(node->drc_name); if (rc2) { say(ERROR, "failed to re-enable hotplug " "children. %d\n", rc2); return rc; } } } return rc; } /** * acquire_slot * */ static int acquire_slot(char *drc_name, struct dr_node **slot) { struct dr_connector drc; struct of_node *of_nodes; char path[DR_PATH_MAX]; int rc; rc = get_drc_by_name(drc_name, &drc, path, OFDT_BASE); if (rc) { say(ERROR, "Could not find drc index for %s, unable to add the" "slot.\n", drc_name); return rc; } rc = acquire_drc(drc.index); if (rc) return rc; of_nodes = configure_connector(drc.index); if (of_nodes == NULL) { release_drc(drc.index, PCI_DLPAR_DEV); return -1; } rc = add_device_tree_nodes(path, of_nodes); free_of_node(of_nodes); if (rc) { say(ERROR, "add_device_tree_nodes failed at %s\n", path); release_drc(drc.index, PCI_DLPAR_DEV); return -1; } /* Now that the node has been added to the device-tree, retrieve it. * This also acts as a sanity check that everything up to this * point has succeeded. */ *slot = get_node_by_name(drc_name, PCI_NODES | VIO_NODES); if (*slot == NULL) { say(ERROR, "Could not get find \"%s\"\n", drc_name); /* or should we call release_drc? but need device type */ release_drc(drc.index, PHB_DEV); return -1; } return 0; } /** * add_slot * */ static int add_slot(struct options *opts) { struct dr_node *node = NULL; int rc, n_children = 0; rc = acquire_slot(opts->usr_drc_name, &node); if (rc) return rc; /* For PCI nodes */ if (node->dev_type == PCI_DLPAR_DEV) { rc = acquire_hp_children(node->ofdt_path, &n_children); if (rc) { if (release_slot(node)) { say(ERROR, "Unknown failure. Data may be out " "of sync and\nthe system may require " "a reboot.\n"); } goto slot_add_exit; } } /* Need to add node into sysfs which will "Hot plug" the node into * pci world. */ rc = dlpar_add_slot(node->drc_name); if (rc) { if (n_children) { if (release_hp_children(node->drc_name)) { say(ERROR, "Unknown failure. Data may be out " "of sync and\nthe system may require " "a reboot.\n"); } } if (release_slot(node)) { say(ERROR, "Unknown failure. Data may be out of sync " "and\nthe system may require a reboot.\n"); } } if (n_children) { rc = enable_hp_children(node->drc_name); if (rc) { say(ERROR, "Configure adapter failed.\n"); if (release_hp_children(node->drc_name)) { say(ERROR, "Unknown failure. Data may be out " "of sync and\nthe system may require " "a reboot.\n"); } if (dlpar_remove_slot(node->drc_name)) { say(DEBUG, "remove %s from hotplug subsystem " "failed\n", node->drc_name); say(ERROR, "Unknown failure. Data may be out " "of sync and\nthe system may require " "a reboot.\n"); } if (release_slot(node)) { say(ERROR, "Unknown failure. Data may be out " "of sync and\nthe system may require " "a reboot.\n"); } goto slot_add_exit; } say(DEBUG, "adapter in node[%s] has been configured.\n", node->drc_name); } slot_add_exit: if (node) free_node(node); return rc; } int valid_slot_options(struct options *opts) { if (opts->usr_drc_name == NULL) { say(ERROR, "A drc name must be specified\n"); return -1; } if ((opts->action != ADD) && (opts->action != REMOVE) && (opts->action != QUERY)) { say(ERROR, "The '-r', '-a', or '-Q' option must be specified " "for slot operations.\n"); return -1; } return 0; } int drslot_chrp_slot(struct options *opts) { struct dr_node *node; int rc; if (! slot_dlpar_capable()) { say(ERROR, "DLPAR slot operations are not supported on" "this kernel."); return -1; } node = get_node_by_name(opts->usr_drc_name, PCI_NODES | VIO_NODES); switch (opts->action) { case ADD: if (node && node->is_owned) { say(ERROR, "partition already owns %s\n", opts->usr_drc_name); rc = RC_ALREADY_OWN; } else { rc = add_slot(opts); } break; case REMOVE: if (node == NULL) { say(ERROR, "%s does not exist\n", opts->usr_drc_name); rc = RC_NONEXISTENT; } else { if (! node->is_owned) { say(ERROR, "%s not owned by partition\n", opts->usr_drc_name); rc = RC_DONT_OWN; } else rc = remove_slot(node); } break; case QUERY: rc = query_slot(node, opts); break; default: rc = -1; } free_node(node); return rc; } powerpc-utils-1.2.26/src/drmgr/rtas_calls.c0000664000175000017510000003173512527176005015556 00000000000000/** * @file rtas_calls.c * * * Copyright (C) IBM Corporation 2006 */ #include #include #include #include #include #include #include "rtas_calls.h" #include "dr.h" #include "ofdt.h" char *hw_error = "Hardware error. You must correct this error before\n" "attempting any further dynamic reconfiguration " "operations.\nCheck the system error log for more " "information.\n"; /** * get_node * @brief Allocates and initializes a node structure. * * @param workarea work area returned by "ibm,configure-connector" RTAS call. * @returns pointer to allocated node on success, NULL otherwise */ static struct of_node * get_node(char *workarea) { struct of_node *node; /* Pointer to new node structure */ int *work_int; /* Pointer to workarea */ char *node_name; /* Pointer to memory for node name */ /* Allocate new node structure */ node = zalloc(sizeof(*node)); if (node == NULL) return NULL; work_int = (int *)workarea; node_name = workarea + be32toh(work_int[2]); node->name = (char *)zalloc(strlen(node_name)+1); if (node->name == NULL) { /* Malloc error */ free(node); return NULL; } strcpy(node->name, node_name); return node; } /** * free_of_node * @brief Free all memory allocated by the configure_connector() * * @param node node returnd by configure_connector() * @returns 0 on success, !0 otherwise */ void free_of_node(struct of_node *node) { struct of_property *prop; /* Used in freeing property memory */ struct of_property *next_prop; /* Used in freeing property memory */ /* If node has a child, make recursive call to free child memory */ if (node->child) free_of_node(node->child); /* If node has a sibling, make recursive call to free its memory */ if (node->sibling) free_of_node(node->sibling); /* Now loop through and free all property related memory */ prop = node->properties; while (prop) { next_prop = prop->next; free(prop->name); free(prop->value); free(prop); prop = next_prop; } /* Finally free the memory for the name and the node itself */ if (node->name) free(node->name); free(node); } /** * get_rtas_property * @brief Allocates and initializes a property structure. * * @param Pointer to work area returned by "ibm,configure-connector" RTAS call. * @returns pointer to of_property_t on success, NULL otherwise */ static struct of_property * get_rtas_property(char *workarea) { struct of_property *prop; /* Pointer to new property strucutre */ int *work_int; /* Pointer to workarea */ char *name; /* Pointer to memory for property name */ char *value; /* Pointer to memory for property value */ /* Allocate a new property structure */ prop = zalloc(sizeof(*prop)); if (prop != NULL) { /* Initialize the new property structure */ work_int = (int *)workarea; prop->next = NULL; name = workarea + be32toh(work_int[2]); prop->name = (char *)zalloc(strlen(name)+1); if (prop->name == NULL) { /* Malloc error */ free(prop); return NULL; } strcpy(prop->name, name); prop->length = be32toh(work_int[3]); value = workarea + be32toh(work_int[4]); prop->value = (char *)zalloc(prop->length); if (prop->value == NULL) { /* Malloc error */ free(prop->name); free(prop); return NULL; } memcpy(prop->value, value, prop->length); } return prop; } /** * dr_entity_sense * @brief Determine if a PCI card is present in a hot plug slot. * * @param index slot index to check * @returns EMPTY if no card detected in slotor not a valid state for logical * resources * @returns PRESENT if a card was detected in the slot or logical connector * is owned by the partition. * @returns EXCHANGE Logical resource is unlicensed and is available for * sparing operations. * @returns NEED_POWER Must power on slot before checking for card presence. * @returns PWR_ONLY Power on slot, but leave isolated. * @returns STATE_UNUSABLE No DR operation will succeed * @returns HW_ERROR Hardware error * @returns SW_ERROR Other errors. */ int dr_entity_sense(int index) { int state; int rc; rc = rtas_get_sensor(DR_ENTITY_SENSE, index, &state); say(DEBUG, "get-sensor for %x: %d, %d\n", index, rc, state); return (rc >= 0) ? state : rc; } /* * entity_sense_error * @brief provide a detailed error message for dr_entity_sense() errors * * @param error error returned from dr_entity_sense() * @return pointer to message string, empty string if error is invalid */ char * entity_sense_error(int error) { char *empty = "Unable to allocate the resource to the partition."; char *present = "Resource is already assigned to the partition."; char *unusable = "Resource is not available to the partition."; char *exchange = "Resource is available for exchange."; char *recovery = "Resource is available for recovery by partition."; char *rc = ""; switch (error) { case EMPTY: rc = empty; break; case PRESENT: rc = present; break; case STATE_UNUSABLE: rc = unusable; break; case EXCHANGE: rc = exchange; break; case RECOVERY: rc = recovery; break; } return rc; } /* * set_indicator_error * @brief provide a detailed error message for rtas_set_indicator() errors * * @param error error returned from rtas_set_indicator() * @return pointer to message string, empty string if error is invalid */ char * set_indicator_error(int error) { char *hw_error = "Hardware error."; char *hw_busy = "Hardware busy, try again later."; char *no_ind = "No such indicator implemented."; char *iso_error = "Multi-level isolation error."; char *vot = "Valid outstanding translations exist."; char *rc = ""; switch (error) { case HARDWARE_ERROR: rc = hw_error; break; case HARDWARE_BUSY: rc = hw_busy; break; case NO_INDICATOR: rc = no_ind; break; case MULTI_LEVEL_ISO_ERROR: rc = iso_error; break; case VALID_TRANSLATION: rc = vot; break; } return rc; } #define WORK_SIZE 4096 /* RTAS work area is 4K page size */ /** * configure_connector * * Obtain all of the Open Firmware properties for nodes associated * with the hot plug entitiy. * * @param index slot index from "ibm,drc-indexes" property * @returns pointer to node on success, NULL on failure. */ struct of_node * configure_connector(int index) { char workarea[WORK_SIZE]; struct of_node *node; struct of_node *first_node = NULL; struct of_node *last_node = NULL; /* Last node processed */ struct of_property *property; struct of_property *last_property = NULL; /* Last property processed */ int *work_int; int rc; say(DEBUG, "Configuring connector for drc index %x\n", index); /* initialize work area and args structure */ work_int = (int *) &workarea[0]; work_int[0] = htobe32(index); work_int[1] = 0; while (1) { rc = rtas_cfg_connector(workarea); if (rc == 0) break; /* Success */ if (rc == NEXT_SIB) { if (last_node == NULL) { say(ERROR, "unexpected sibling returned from " "configure_connector\n"); break; } /* Allocate and initialize the node */ node = get_node(workarea); if (node == NULL) { say(ERROR, "failed to allocate sibling node " "for drc index %x\n", index); break; } /* Set parent node to same as that of last node */ node->parent = last_node->parent; /* Chain to last node */ last_node->sibling = node; /* This node becomes the last node */ last_node = node; } else if (rc == NEXT_CHILD) { /* Allocate and initialize the node */ node = get_node(workarea); if (node == NULL) { say(ERROR, "Failed to allocate child node for " "drc index %x\n", index); break; } if (first_node == NULL) { first_node = node; } else { node->parent = last_node; if (last_node) last_node->child = node; } /* This node becomes the last node */ last_node = node; } else if (rc == NEXT_PROPERTY){ if (last_node == NULL) { say(ERROR, "Configure_connector returned a " "property before returning a node\n"); break; } /* Allocate and initialize the property structure */ property = get_rtas_property(workarea); if (property == NULL) break; if (last_node->properties == NULL) last_node->properties = property; else last_property->next = property; /* This property becomes last property for node */ last_property = property; } else if (rc == PREV_PARENT) { /* Need to back up to parent device */ last_node = last_node->parent; } else if (rc == MORE_MEMORY) { say(ERROR, "Configure_connector called with " "insufficient memory.\n"); break; } else if (rc == NOT_THIS_SYSTEM) { /* this card is not supported in this system */ say(ERROR, "This adapter cannot be attached to this " "system at this\ntime. You may have to remove " "other adapters before this\nadapter can be " "successfully attached. Consult the hardware" "\ndocumentation for your system to find an " "explanation of\nthe supported combinations " "of adapters that may be attached\nat one " "time.\n"); break; } else if (rc == NOT_THIS_SLOT) { /* this card is not supported in this slot */ say(ERROR, "This adapter is not supported in the " "specified slot,\nbut there may be other " "slots where it is supported. Consult\nthe " "hardware documentation for your system to " "find the\nappropriate slots for this " "adapter.\n"); break; } else if (rc == ERR_CFG_USE) { /* This entity is not usable */ say(ERROR, "This adapter is currently unusable, available " "for exchange or available for recovery\n"); break; } else if (rc == HARDWARE_ERROR) { say(ERROR, "%s\n", hw_error); break; } else { say(ERROR, "Unexpected error (%d) returned from " "configure_connector\n", rc); break; } } /* end while */ if (rc) { say(ERROR, "Configure_connector failed for drc index %x\n" "Data may be out of sync and the system may require " "a reboot.\n", index); if (first_node) { free_of_node(first_node); first_node = NULL; /* Indicates error condition */ } } return first_node; } /** * set_power * @brief Sets the power level for the specified slot. * * @param domain power domain for the slot from "ibm,drc-power-domains" * @param level POWER_ON or POWER_OFF * @returns 0 Successful completion * @returns SPEED_ERROR Inserted a PCI 33 MHz IOA into a PCIbus which is * operating at 66 MHz. * @returns HW_ERROR Hardware error. * @returns SW_ERROR Other errors. */ int set_power(int domain, int level) { int ret_level; return rtas_set_power_level(domain, level, &ret_level); } /** * acquire_drc * */ int acquire_drc(uint32_t drc_index) { int rc; say(DEBUG, "Acquiring drc index 0x%x\n", drc_index); rc = dr_entity_sense(drc_index); if (rc != STATE_UNUSABLE) { say(ERROR, "Entity sense failed for drc %x with %d\n%s\n", drc_index, rc, entity_sense_error(rc)); return -1; } say(DEBUG, "Setting allocation state to 'alloc usable'\n"); rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_USABLE); if (rc) { say(ERROR, "Allocation failed for drc %x with %d\n%s\n", drc_index, rc, set_indicator_error(rc)); return -1; } say(DEBUG, "Setting indicator state to 'unisolate'\n"); rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE); if (rc) { int ret; rc = -1; say(ERROR, "Unisolate failed for drc %x with %d\n%s\n", drc_index, rc, set_indicator_error(rc)); ret = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE); if (ret) { say(ERROR, "Failed recovery to unusable state after " "unisolate failure for drc %x with %d\n%s\n", drc_index, ret, set_indicator_error(ret)); } } return rc; } int release_drc(int drc_index, uint32_t dev_type) { int rc; say(DEBUG, "Releasing drc index 0x%x\n", drc_index); rc = dr_entity_sense(drc_index); if (rc != PRESENT) say(DEBUG, "drc_index %x sensor-state: %d\n%s\n", drc_index, rc, entity_sense_error(rc)); say(DEBUG, "Setting isolation state to 'isolate'\n"); rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE); if (rc) { if (dev_type == PHB_DEV) { /* Workaround for CMVC 508114, where success returns * too quickly */ int i = 0; while ((rc != 0) && (i < 20)) { rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE); sleep(1); i++; } } if (rc) { say(ERROR, "Isolation failed for %x with %d\n%s\n", drc_index, rc, set_indicator_error(rc)); return -1; } } say(DEBUG, "Setting allocation state to 'alloc unusable'\n"); rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE); if (rc) { say(ERROR, "Unable to un-allocate drc %x from the partition " "(%d)\n%s\n", drc_index, rc, set_indicator_error(rc)); rc = rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE); say(DEBUG, "UNISOLATE for drc %x, rc = %d\n", drc_index, rc); return -1; } rc = dr_entity_sense(drc_index); say(DEBUG, "drc_index %x sensor-state: %d\n%s\n", drc_index, rc, entity_sense_error(rc)); return 0; } powerpc-utils-1.2.26/src/drmgr/lsslot.c0000664000175000017510000005605212542271360014743 00000000000000/** * @file lsslot.c * * Copyriht (C) 2005 IBM Corporatio */ #include #include #include #include #include #include "rtas_calls.h" #include "drpci.h" #include "dr.h" #include "lsslot.h" #include "drmem.h" #include "pseries_platform.h" int output_level = 0; int log_fd = 0; /** * struct print_node * @ brief struct to track list of nodes to be printed. */ struct print_node { struct dr_node *node; /**< node information */ char *desc; /**< message description from catalog*/ struct print_node *next; }; struct print_node *print_list = NULL; /* These are used to determine column widths for output */ uint32_t max_sname = 0; /* Max size of node location codes */ uint32_t max_desc = 0; /* Max size of node descriptions */ #define LNAME_SIZE 12 /* xxxx:xx:xx.x */ /** * usage * @brief Print the usage message and exit */ static void usage(void) { fprintf(stderr, "Usage: lsslot [-c | -a | -b | -p | -o | -s ]" "[-F | -d | -w]\n"); fprintf(stderr, " -c \n"); fprintf(stderr, " Display the slots of the specified " "connector type. The valid\n"); fprintf(stderr, " connector types are \"pci\" for " "hotplug PCI slots, \"slot\" for\n"); fprintf(stderr, " logical slots, \"phb\" for PHB's, " "\"port\" for LHEA ports, \"mem\"\n"); fprintf(stderr, " for memory, and \"cpu\" " "for cpu's. The default\n"); fprintf(stderr, " is \"slot\" if no -c option is " "specified.\n"); fprintf(stderr, " -a Display available slots, valid for " "\"pci\" slots only.\n"); fprintf(stderr, " -b Display cpu's and caches, valid for " "\"cpu\" only.\n"); fprintf(stderr, " -o Display occupied slots, valid for " "\"pci\" slots only.\n"); fprintf(stderr, " -p Display caches, valid for \"cpu\" " "slots only.\n"); fprintf(stderr, " -s [ | ]\n"); fprintf(stderr, " Display characteristics of the " "specified slot or the LMB\n"); fprintf(stderr, " associated with drc index.\n"); fprintf(stderr, " -F \n"); fprintf(stderr, " Specified a single character to " "delimit the output. The \n"); fprintf(stderr, " heading is not displayed and the " "columns are delimited by the\n"); fprintf(stderr, " specified character.\n"); fprintf(stderr, " -d Enable debugging output. When " "displaying LMB information\n"); fprintf(stderr, " this will enable printing of LMBs " "not owned by the system.\n"); fprintf(stderr, " -w \n"); fprintf(stderr, " Specify a timeout when attempting to " "acquire locks.\n"); exit (1); } /** * free_print_nodes * @brief Free all of the items on the print_list * * NOTE: We do not free the node pointed to by the print_node, these * nodes exist on other lists and should be free when those lists are * cleaned up. */ static void free_print_list(void) { struct print_node *pnode; while (print_list != NULL) { pnode = print_list; print_list = print_list->next; free(pnode); } } /** * loc_code_cmp * * loc_code_cmp is used to sort a list of nodes based on their location code. * location codes take the form of * * pn[.n][- or /]pn[.n][- or /] ... * * where p is an alpha location type prefix and n is an instance * number (see RS/6000 Processor Architecture, Location Code Format). * The location code has to be parsed by hyphens, if any. * * @param node1 * @param node2 * @returns 0 if (node1 = node2), -1 if (node1 < node2), 1 if (node1 > node2) */ static int loc_code_cmp(char *node1, char *node2) { char save_n1[64],save_n2[64]; /* for holding node1 and node2 */ char *n1, *n2; ulong nbr1,nbr2; /* hex numbers representing location */ size_t dash_cnt; n1 = save_n1; n2 = save_n2; while (strlen(node1) && strlen(node2)) { dash_cnt = strcspn(node1, "-"); strncpy(n1, node1, dash_cnt); *(n1 + dash_cnt) = '\0'; node1 += dash_cnt; dash_cnt = strcspn(node2, "-"); strncpy(n2, node2, dash_cnt); *(n2 + dash_cnt) = '\0'; node2 += dash_cnt; /* First look at the location type */ if (*n1 < *n2) return -1; else if (*n1 > *n2) return 1; n1++; n2++; /* get the hex value of the instance number */ nbr1 = strtoul(n1, &n1, 16); nbr2 = strtoul(n2, &n2, 16); if (nbr1 < nbr2) return -1; else if (nbr1 > nbr2) return 1; if (strlen(n1) && strlen(n2)) { /* If both strings have more characters, first * determine if they are the same. */ if (*n1 == *n2) { /* If they're the same, compare whatever * follows the delimiter. The slash will have * an alpha and hex following it, while the dot * will have just a hex following it. */ if (*n1 == '/') { n1++; n2++; /* First look at the location type, * which is a single character. */ if (*n1 < *n2) return -1; else if (*n1 > *n2) return 1; } n1++; n2++; /* get the hex value of the instance number */ nbr1 = strtoul(n1, &n1, 16); nbr2 = strtoul(n2, &n2, 16); if (nbr1 < nbr2) return -1; else if (nbr1 > nbr2) return 1; } /* The delimiters are not the same, so check * what they are and return results based on * order of precedence : slash, then dot. */ else if (*n1 == '/') return -1; else if (*n2 == '/') return 1; } /* If we've reached here, either the strings are * the same or one of the strings has run out. * If only one has run out, we can return. */ if (strlen(n1) < strlen(n2)) return -1; else if (strlen(n1) > strlen(n2)) return 1; /* If we get here, we've determined everything * in the n1 and n2 strings are the same. Now * increment past the dash, if any, in the * original strings. */ if (*node1 == '-') node1++; if (*node2 == '-') node2++; } if (strlen(node1)) return 1; else if (strlen(node2)) return -1; return 0; } /** * insert_print_node * * Insert the node into the list of nodes. The list is * sorted by location codes. * * @param node dlpar node to add */ void insert_print_node(struct dr_node *node) { struct print_node *pnode; pnode = zalloc(sizeof(*pnode)); if (pnode == NULL) { fprintf(stderr, "Could not allocate print node for drc %x\n", node->drc_index); return; } pnode->node = node; pnode->desc = node_type(node); pnode->next = NULL; max_sname = MAX(max_sname, strlen(node->drc_name)); max_desc = MAX(max_desc, strlen(pnode->desc)); /* Insert the new print_node into the sorted list of print nodes */ if (print_list == NULL) { print_list = pnode; return; } if (loc_code_cmp(print_list->node->drc_name, pnode->node->drc_name) > 0) { /* The location code for the new node is less than that * of the first node so insert the new node at the front. */ pnode->next = print_list; print_list = pnode; } else { /* Find the first node in the list where the new node's * location code is less than the existing node's location * code and insert the new node before that node. */ struct print_node *last; last = print_list; while (last->next != NULL) { if (loc_code_cmp(last->next->node->drc_name, pnode->node->drc_name) > 0) { pnode->next = last->next; last->next = pnode; break; } last = last->next; } /* Put the new node at the end of the list if itslocation * code is not less than any other node's location code. */ if (last->next == NULL) last->next = pnode; } } /** * print_drslot_line * @brief print a SLOT entry * * @param pnode print_node to print * @param fmt output format string */ static void print_drslot_line(struct print_node *pnode, char *fmt) { struct dr_node *node = pnode->node; char *linux_dname; /* Print node name, description, and linux name */ if (node->sysfs_dev_path[0]) linux_dname = strrchr(node->sysfs_dev_path, '/') + 1; else linux_dname = "?"; printf(fmt, node->drc_name, pnode->desc, linux_dname); /* If no node info, then it is an empty node */ if (node->dev_type == HEA_DEV) { struct dr_node *port = node->children; if (!port) { printf("Empty\n"); } else { int first = 1; for (port = node->children; port; port = port->next) { printf("%s%s ", first ? "" : ",", port->drc_name); first = 0; } printf("\n"); } } else { if (node->ofdt_dname[0] == '\0') printf("Empty\n"); else printf("%s\n", node->ofdt_dname); } } /** * print_phpslot_line * @brief print a hotplug slot entry * * @param pnode print_node to print * @param fmt output format string */ static void print_phpslot_line(struct print_node *pnode, char *fmt) { struct dr_node *child; struct dr_node *node = pnode->node; /* Print node name and description */ printf(fmt, node->drc_name, pnode->desc); /* If no node info, then it is an empty node */ if (! node->children) printf("Empty\n"); else { /* Else we want to print the device names */ for (child = node->children; child; child = child->next) { if (child != node->children) printf(fmt, "", ""); if (child->sysfs_dev_path[0]) printf("%s\n", strrchr(child->sysfs_dev_path, '/') + 1); else if (child->ofdt_dname[0]) printf("%s\n", child->ofdt_dname); else printf("?\n"); } } } /** * parse_options * @brief parse the command line options and fillin the cmd_opts struct * * @param argc * @param argv * @param opts */ static void parse_options(int argc, char *argv[], struct cmd_opts *opts) { int c; while ((c = getopt(argc, argv, "abc:d:F:ops:w:")) != EOF) { switch (c) { case 'a': opts->a_flag = 1; break; case 'b': opts->b_flag = 1; break; case 'c': if (! strcmp(optarg, "phb")) opts->slot_type = PHB; else if (! strcmp(optarg, "slot")) opts->slot_type = SLOT; else if (! strcmp(optarg, "pci")) opts->slot_type = PCI; else if (! strcmp(optarg, "cpu")) opts->slot_type = CPU; else if (! strcmp(optarg, "mem")) opts->slot_type = MEM; else if (! strcmp(optarg, "port")) opts->slot_type = PORT; else { printf("\nThe specified connector type " "is invalid.\n\n"); usage(); } break; case 'd': set_output_level(atoi(optarg)); break; case 'F': opts->delim = optarg; /* make sure the arg specified is only one character * long and is not the '%' character which would * confuse the formatting. */ if ((opts->delim[1] != '\0') || (opts->delim[0] == '%')) { say(ERROR, "You may specify only one character " "for the -F option,\nand it must not " "be the %% character.\n"); exit(1); } break; case 'o': opts->o_flag = 1; break; case 'p': opts->p_flag = 1; break; case 's': opts->s_name = optarg; break; case 'w': opts->timeout = strtoul(optarg, NULL, 10) * 60; if (opts->timeout < 0) usage(); break; default: usage(); break; } } /* Validate the options */ switch (opts->slot_type) { case SLOT: case PORT: /* The a,b,o,p flags are not valid for slot */ if (opts->a_flag || opts->b_flag || opts->o_flag || opts->p_flag) usage(); /* Now, to make the code work right (which is wrong) we * need to set the a and o flags if the s flag wasn't * specified. */ if (opts->s_name == NULL) { opts->a_flag = 1; opts->o_flag = 1; } break; case PHB: /* The a,b,F,o,p options are not valid for phb */ if (opts->a_flag || opts->b_flag || opts->delim || opts->o_flag || opts->p_flag) usage(); break; case PCI: /* The b,p flags are valid for pci */ if (opts->b_flag || opts->p_flag) usage(); /* If no flags specified, then set a_flag and o_flag * so that all slots will be formatted in the output */ if ((! opts->a_flag) && (! opts->o_flag) && (opts->s_name == NULL)) { opts->a_flag = 1; opts->o_flag = 1; } break; case CPU: /* The a,F,o,s options are not valid for cpu */ if (opts->a_flag || opts->delim || opts->o_flag || opts->s_name) usage(); if (opts->b_flag && opts->p_flag) { say(ERROR, "You cannot specify both the -b and -p " "options.\n"); usage(); } break; } } /** * lsslot_chrp_pci * @brief main entry point for lsslot command * * @param opts * @returns 0 on success, !0 otherwise */ int lsslot_chrp_pci(struct cmd_opts *opts) { struct dr_node *all_nodes; /* Pointer to list of all node info */ struct dr_node *node; /* Used to traverse list of node info */ char fmt[128]; struct print_node *p; char *sheading = "# Slot"; /* Used in printing headers */ char *dheading = "Description"; /* Used in printing headers */ char *lheading = "Device(s)"; /* Used in printing headers */ char *lname_header = "Linux Name"; int rc = 0; /* Set initial column sizes */ max_sname = MAX(max_sname, strlen(sheading)); max_desc = MAX(max_desc, strlen(dheading)); /* Get all of node(logical DR or PCI) node information */ if (opts->slot_type == PCI) all_nodes = get_hp_nodes(); else all_nodes = get_dlpar_nodes(PCI_NODES | VIO_NODES | HEA_NODES); /* If nothing returned, then no hot plug node */ if (all_nodes == NULL) { if (opts->slot_type == PCI) say(ERROR, "There are no PCI hot plug slots on " "this system.\n"); else say(ERROR, "There are no DR slots on this system.\n"); return 0; } print_node_list(all_nodes); /* Otherwise, run through the node list looking for the nodes * we want to print */ for (node = all_nodes; node; node = node->next) { if (! node->is_owned || node->skip) continue; if (opts->s_name != NULL) { if (cmp_drcname(node->drc_name, opts->s_name)) insert_print_node(node); } /* If aflag and slot is empty, then format the slot */ else if (opts->a_flag && (node->children == NULL)) insert_print_node(node); /* If oflag and slot occupied, then format the slot */ else if (opts->o_flag && (node->children != NULL)) insert_print_node(node); } if (print_list == NULL) { /* If nothing to print, display message based on if * user specified a slot or a device name. */ if (opts->s_name != NULL) { say(ERROR, "The specified PCI slot is either invalid\n" "or does not support hot plug operations.\n"); rc = 1; } goto lsslot_pci_exit; } /* This creates a format string so that slot name and description * prints out in the required field width. When the -F flag is * specified, the format string contains the delimiting character * which the user specified at the command line. */ if (opts->slot_type == SLOT) { if (opts->delim != NULL) sprintf(fmt, "%s%s%s%s%s%s", "%s", opts->delim, "%s", opts->delim, "%s", opts->delim); else { sprintf(fmt, "%%-%ds%%-%ds%%-%ds", max_sname + 2, max_desc + 2, LNAME_SIZE + 2); /* Print out the header. */ printf(fmt, sheading, dheading, lname_header); printf("%s\n", lheading); } } else { if (opts->delim != NULL) sprintf(fmt, "%s%s%s%s", "%s", opts->delim, "%s", opts->delim); else { sprintf(fmt, "%%-%ds%%-%ds", max_sname + 2, max_desc + 2); /* Print out the header. */ printf(fmt, sheading, dheading); printf("%s\n", lheading); } } /* Now run through the list of slots we actually want to print */ for (p = print_list; p != NULL; p = p->next) { if (! p->node->is_owned) { /* skip it, because the partition doesn't own it */ continue; } if (opts->slot_type == SLOT) print_drslot_line(p, fmt); else print_phpslot_line(p, fmt); } lsslot_pci_exit: free_print_list(); free_node(all_nodes); return rc; } /** * lsslot_chrp_phb * @brief Main entry point for handling lsslot_chrp_phb command * * @param opts pointer to cmd_opts struct * @returns 0 on success, !0 otherwise */ int lsslot_chrp_phb(struct cmd_opts *opts) { struct dr_node *phb_list; struct dr_node *phb; phb_list = get_dlpar_nodes(PHB_NODES); if (phb_list == NULL) return -1; /* display header */ printf("%-10s%-20s %s\n", "PHB name", "OFDT Name", "Slot(s) Connected"); for (phb = phb_list; phb; phb = phb->next) { struct dr_node *child; char *name; int printed_count = 0; if ((opts->s_name != NULL) && (strcmp(opts->s_name, phb->drc_name))) continue; name = strstr(phb->ofdt_path, "/pci"); printf("%-10s%-20s ", phb->drc_name, name); for (child = phb->children; child; child = child->next) { if (! child->is_owned) continue; if (printed_count == 0) printf("%s\n", child->drc_name); else printf("%-30s %s\n", "", child->drc_name); printed_count++; } if (printed_count) printf("\n"); else printf("\n\n"); } return 0; } int print_drconf_mem(struct cmd_opts *opts, struct lmb_list_head *lmb_list) { struct dr_node *lmb; struct mem_scn *scn; int scn_offset = strlen("/sys/devices/system/memory/memory"); char *aa_buf; __be32 *aa; int aa_size, aa_list_sz; int i, rc; uint32_t drc_index = 0; aa_size = get_property_size(DYNAMIC_RECONFIG_MEM, "ibm,associativity-lookup-arrays"); aa_buf = zalloc(aa_size); rc = get_property(DYNAMIC_RECONFIG_MEM, "ibm,associativity-lookup-arrays", aa_buf, aa_size); if (rc) { say(ERROR, "Could not get associativity information.\n"); return -1; } aa = (__be32 *)aa_buf; /* skip past the number of associativity lists */ aa++; aa_list_sz = be32toh(*aa++); if (opts->s_name) drc_index = strtol(opts->s_name, NULL, 0); printf("Dynamic Reconfiguration Memory (LMB size 0x%x)\n", lmb_list->lmbs->lmb_size); for (lmb = lmb_list->lmbs; lmb; lmb = lmb->next) { int first = 1; int aa_start, aa_end; if (drc_index && drc_index != lmb->drc_index) continue; else if ((output_level < 4) && !lmb->is_owned) continue; printf("%s: %s\n", lmb->drc_name, lmb->is_owned ? "" : "Not Owned"); printf(" DRC Index: %x Address: %lx\n", lmb->drc_index, lmb->lmb_address); printf(" Removable: %s Associativity: ", lmb->is_removable ? "Yes" : "No "); if (lmb->lmb_aa_index == 0xffffffff) { printf("Not Set\n"); } else { printf("(index: %d) ", lmb->lmb_aa_index); aa_start = lmb->lmb_aa_index * aa_list_sz; aa_end = aa_start + aa_list_sz; for (i = aa_start; i < aa_end; i++) printf("%d ", be32toh(aa[i])); printf("\n"); } if (lmb->is_owned) { printf(" Section(s):"); for (scn = lmb->lmb_mem_scns; scn; scn = scn->next) { if (first) { printf(" %s", &scn->sysfs_path[scn_offset]); first = 0; } else printf(", %s", &scn->sysfs_path[scn_offset]); } printf("\n"); } } free(aa_buf); return 0; } int lsslot_chrp_mem(struct cmd_opts *opts) { struct lmb_list_head *lmb_list; struct dr_node *lmb; struct mem_scn *scn; int scn_offset = strlen("/sys/devices/system/memory/memory"); int lmb_offset = strlen(OFDT_BASE); lmb_list = get_lmbs(LMB_NORMAL_SORT); if (lmb_list == NULL || lmb_list->lmbs == NULL) return -1; if (lmb_list->drconf_buf) { print_drconf_mem(opts, lmb_list); } else { printf("lmb size: 0x%x\n", lmb_list->lmbs->lmb_size); printf("%-20s %-5s %c %s\n", "Memory Node", "Name", 'R', "Sections"); printf("%-20s %-5s %c %s\n", "-----------", "----", '-', "--------"); for (lmb = lmb_list->lmbs; lmb; lmb = lmb->next) { int first = 1; if (!lmb->is_owned) continue; if (!lmb_list->drconf_buf) printf("%-20s ", &lmb->ofdt_path[lmb_offset]); printf("%-5s %c ", lmb->drc_name, lmb->is_removable ? 'Y' : 'N'); for (scn = lmb->lmb_mem_scns; scn; scn = scn->next) { if (first) { printf(" %s", &scn->sysfs_path[scn_offset]); first = 0; } else printf(", %s", &scn->sysfs_path[scn_offset]); } printf("\n"); } } free_lmbs(lmb_list); return 0; } /** * lsslot_chrp_port * @brief Print LHEA ports based on command line options * * @param opts * @returns 0 on success, !0 otherwise */ int lsslot_chrp_port(struct cmd_opts *opts) { struct dr_node *all_nodes; /* Pointer to list of all node info */ struct dr_node *node; /* Used to traverse list of node info */ struct dr_node *child; /* Used to traverse list of children */ char fmt[128]; struct print_node *p; char *sheading = "LHEA port name"; /* Used in printing headers */ char *dheading = "Description"; /* Used in printing headers */ int rc = 0; /* Set initial column sizes */ max_sname = MAX(max_sname, strlen(sheading)); max_desc = MAX(max_desc, strlen(dheading)); all_nodes = get_dlpar_nodes(HEA_NODES); /* If nothing returned, then no hot plug node */ if (all_nodes == NULL) { say(ERROR, "There are no LHEA ports on this system.\n"); return 1; } print_node_list(all_nodes); /* Otherwise, run through the node list looking for the nodes * we want to print */ for (node = all_nodes; node; node = node->next) { if (node->skip) continue; for (child = node->children; child; child = child->next) { if (child->skip) continue; /* If there is a search parameter, add matching ports. * If there is no search, add all the ports. */ if (opts->s_name != NULL) { if (cmp_drcname(child->drc_name, opts->s_name)) insert_print_node(child); } else insert_print_node(child); } } if (print_list == NULL) { /* If nothing to print, display message based on if * user specified a slot or a device name. */ if (opts->s_name != NULL) { say(ERROR, "The specified port was not found.\n"); rc = 1; } goto lsslot_port_exit; } /* This creates a format string so that port name and description * prints out in the required field width. When the -F flag is * specified, the format string contains the delimiting character * which the user specified at the command line. */ if (opts->delim != NULL) sprintf(fmt, "%s%s%s\n", "%s", opts->delim, "%s"); else { sprintf(fmt, "%%-%ds%%-%ds\n", max_sname + 2, max_desc + 2); /* Print out the header. */ printf(fmt, sheading, dheading); } /* Now run through the list of ports we actually want to print */ for (p = print_list; p != NULL; p = p->next) { printf(fmt, p->node->drc_name, p->desc); } lsslot_port_exit: free_print_list(); free_node(all_nodes); return rc; } int main(int argc, char *argv[]) { struct cmd_opts opts; int rc; switch (get_platform()) { case PLATFORM_UNKNOWN: case PLATFORM_POWERNV: fprintf(stderr, "%s: is not supported on the %s platform\n", argv[0], platform_name); exit(1); } /* make sure that we're running on the proper platform. */ if (! valid_platform("chrp")) exit(1); memset(&opts, 0, sizeof(opts)); /* default to DRSLOT type */ opts.slot_type = SLOT; parse_options(argc, argv, &opts); rc = dr_lock(); if (rc) { say(ERROR, "Unable to obtain Dynamic Reconfiguration lock. " "Please try command again later.\n"); exit(1); } switch (opts.slot_type) { case SLOT: case PCI: rc = lsslot_chrp_pci(&opts); break; case PHB: rc = lsslot_chrp_phb(&opts); break; case CPU: rc = lsslot_chrp_cpu(&opts); break; case MEM: rc = lsslot_chrp_mem(&opts); break; case PORT: rc = lsslot_chrp_port(&opts); break; } dr_unlock(); exit(rc); } powerpc-utils-1.2.26/src/drmgr/lsslot_chrp_cpu.c0000664000175000017510000000602712527176005016626 00000000000000/** * @file lsslot_chrp_cpu.c * @brief routines for lsslot_chrp_cpu command * * Copyright (C) IBM Corporation 2006 */ #include #include #include #include #include #include #include "dr.h" #include "drcpu.h" #include "lsslot.h" /** * list_cpus * @brief list all cpus * */ void list_cpus(struct dr_info *dr_info) { struct dr_node *cpu; struct thread *t; char *fmt_s = "%-11s%-20s%-13s%-13s\n"; char *fmt = "%-11s%-20s%-12x"; printf(fmt_s, "drc-name", "OFDT-node", "drc_index", "thread id(s)"); for (cpu = dr_info->all_cpus; cpu != NULL; cpu = cpu->next) { if (cpu->is_owned) { printf(fmt, cpu->drc_name, cpu->name, cpu->drc_index); for (t = cpu->cpu_threads; t; t = t->sibling) printf(" %x", t->id); printf("\n"); } } return; } /** * list_caches * @brief list all caches * */ void list_caches(struct dr_info *dr_info) { struct cache_info *cache = NULL; printf("cache-name phandle\n"); for (cache = dr_info->all_caches; cache != NULL; cache = cache->next) printf("%-21s%-8x\n", cache->name, cache->phandle); return; } /** * list_all_cpus_and_caches * @bried list all of the cpus and caches * */ void list_cpus_and_caches(struct dr_info *dr_info) { struct dr_node *cpu = NULL; struct thread *t; int thread_id_field_sz = 14; char *fmt_s = "%-11s%-20s%-13s%-13s%-11s%-11s\n"; char *fmt = "%-11s%-20s%-12x%"; char *fmt_caches = "%-11s%-11s\n"; printf(fmt_s, "drc-name", "OFDT-node", "drc_index", "thread id(s)", "l2-cache", "l3-cache"); for (cpu = dr_info->all_cpus; cpu != NULL; cpu = cpu->next) { int i, count = 0; struct cache_info *l2_cache = NULL; struct cache_info *l3_cache = NULL; printf(fmt, cpu->drc_name, cpu->name, cpu->drc_index); for (t = cpu->cpu_threads; t; t = t->sibling) { printf(" %x", t->id); count += 2; } /* pad out the thread ids field */ for (i = count; i < thread_id_field_sz; i++) printf(" "); l2_cache = cpu_get_dependent_cache(cpu, dr_info); if (l2_cache) l3_cache = cache_get_dependent_cache(l2_cache, dr_info); printf(fmt_caches, (l2_cache ? l2_cache->name : "N/A"), (l3_cache ? l3_cache->name : "N/A")); } return; } /** * lsslot_chrp_cpu * @brief main entry point for lsslot_chrp_cpu command * * @param opts * @returns 0 on success, !0 otherwise */ int lsslot_chrp_cpu(struct cmd_opts *opts) { struct stat sb; struct dr_info dr_info; /* Mask signals so the command doesn't get interrupted */ if (sig_setup()) { fprintf(stderr, "\nUnknown failure. Rerun the command.\n\n"); return 1; } /* Check if this is an LPAR System. */ if (stat("/proc/device-tree/ibm,lpar-capable", &sb)) { fprintf(stderr, "\nThe system is not LPAR.\n\n"); return 1; } if (init_cpu_drc_info(&dr_info)) { fprintf(stderr, "\nThere are no dynamically reconfigurable " "CPUs on this system.\n\n"); return 1; } if (opts->b_flag) list_cpus_and_caches(&dr_info); else if (opts->p_flag) list_caches(&dr_info); else list_cpus(&dr_info); return 0; } powerpc-utils-1.2.26/src/activate_fw.c0000664000175000017510000000624112527176005014602 00000000000000/** * @file activate_fw.c * @brief Activate Firmware command */ /** * @mainpage activate_firmware documentation * @section Copyright * Copyright (c) 2004 International Business Machines * Common Public License Version 1.0 (see COPYRIGHT) * * @section Overview * Simple command to call the "ibm,activate-firmware" rtas call via librtas.so * * The return codes for this command are as follows:
* 0 - Success!!
* 1 - This platform doesn't support concurrent activation of firmware.
* 2 - There's no new firmware ready to activate (RTAS returned -9001).
* 3 - You must have root authority to run this command.
* 4 - Hardware failure (RTAS returned -1).
* 5 - Memory/resource allocation error.
* 6 - General error.
* * For the specific mappings of librtas and rtas_call return codes (librtas * return codes are in all caps) to the return codes listed above see the * switch statement in the code. There are two values that can be returned * by the rtas call but are not explicitly handled below and are handled by * the default case statement. These are -2 (busy, try again) and 990x * (extended delay). The librtas module intercepts these return codes and * handles them itself, they should never be returned from librtas. * * @author Nathan Fontenot */ #include #include "librtas.h" #include "pseries_platform.h" /** * @def say(_f, _a...) * @brief DEBUG definition of printf */ #ifdef DEBUG #define say(_f, _a...) printf(_f, ##_a); #else #define say(_f, _a...) #endif int main(void) { int rc; if (get_platform() != PLATFORM_PSERIES_LPAR) { fprintf(stderr, "activate_firmware: is not supported on the %s " "platform\n", platform_name); return 1; } rc = rtas_activate_firmware(); /* Map 'rc' to valid return code listed above */ switch (rc) { /* 0 - Success!! */ case 0: say("activate_firmware: rtas call succeeded\n"); break; /* 1 - activate-firmware not supported */ case RTAS_KERNEL_INT: /* No kernel interface to firmware */ case RTAS_KERNEL_IMP: /* No kernel implementation of function */ case RTAS_UNKNOWN_OP: /* No firmware implementation of function */ say("activate_fw: rtas call returned %d, converting to %d\n", rc, 1); rc = 1; break; /* 2 - no new firmware to activate */ case -9001: /* No valid firmware to activate */ say("activate_fw: rtas call returned %d, converting to %d\n", rc, 2); rc = 2; break; /* 3 - no root authority */ case RTAS_PERM: /* No root authority */ say("activate_fw: rtas call returned %d, converting to %d\n", rc, 3); rc = 3; break; /* 4 - hardware error */ case -1: /* Hardware error */ say("activate_fw: rtas call returned %d, converting to %d\n", rc, 4); rc = 4; break; /* 5 - Memory/resource allocation error */ case RTAS_NO_MEM: case RTAS_NO_LOWMEM: say("activate_fw: rtas call returned %d, converting to %d\n", rc, 5); rc = 5; break; /* 6 - catch all other return codes here */ default: say("activate_fw: rtas call returned %d, converting to %d\n", rc, 4); rc = 4; break; } return rc; } powerpc-utils-1.2.26/src/lparstat.c0000664000175000017510000002451212527176005014141 00000000000000/** * @file lparstat.c * @brief lparstat command * * Copyright (c) 2011 International Business Machines * Common Public License Version 1.0 (see COPYRIGHT) * * @author Nathan Fontenot */ #include #include #include #include #include #include #include #include "lparstat.h" #include "pseries_platform.h" #define LPARCFG_FILE "/proc/ppc64/lparcfg" #define SE_NOT_FOUND "???" #define SE_NOT_VALID "-" struct sysentry *get_sysentry(char *name) { struct sysentry *se = &system_data[0]; while (se->name[0] != '\0') { if (!strcmp(se->name, name)) return se; se++; } return NULL; } void get_sysdata(char *name, char **descr, char *value) { struct sysentry *se; se = get_sysentry(name); if (!se) { *descr = name; sprintf(value, SE_NOT_FOUND); return; } if (se->get) { se->get(se, value); } else if (se->value[0] == '\0') { sprintf(value, SE_NOT_VALID); } else { sprintf(value, "%s", se->value); } *descr = se->descr; } void get_time() { struct timeval t; struct sysentry *se; gettimeofday(&t, 0); se = get_sysentry("time"); sprintf(se->value, "%ld", t.tv_sec + t.tv_usec); } long long elapsed_time() { long long newtime, oldtime = 0; struct sysentry *se; se = get_sysentry("time"); newtime = strtoll(se->value, NULL, 0); oldtime = strtoll(se->old_value, NULL, 0); return newtime - oldtime; } int get_time_base() { FILE *f; char buf[80]; char *tb = NULL; struct sysentry *se; f = fopen("/proc/cpuinfo", "r"); while ((fgets(buf, 80, f)) != NULL) { if (!strncmp(buf, "timebase", 8)) { tb = strchr(buf, ':') + 2; break; } } fclose(f); if (!tb) return -1; se = get_sysentry("timebase"); sprintf(se->value, "%s", tb); return 0; } void get_cpu_physc(struct sysentry *unused_se, char *buf) { struct sysentry *se; float elapsed; float new_purr, old_purr; float timebase, physc; elapsed = elapsed_time(); se = get_sysentry("timebase"); timebase = atoi(se->value); se = get_sysentry("purr"); new_purr = strtoll(se->value, NULL, 0); old_purr = strtoll(se->old_value, NULL, 0); physc = (new_purr - old_purr)/timebase/elapsed; sprintf(buf, "%.2f", physc); } void get_per_entc(struct sysentry *unused_se, char *buf) { char *descr; char physc[32]; char entc[32]; get_sysdata("DesEntCap", &descr, entc); get_sysdata("physc", &descr, physc); sprintf(buf, "%.2f", atof(physc) / atof(entc)); } int parse_lparcfg() { FILE *f; char line[128]; char *unused; f = fopen(LPARCFG_FILE, "r"); if (!f) { fprintf(stderr, "Could not open %s\n", LPARCFG_FILE); return -1; } /* parse the file skipping the first line */ unused = fgets(line, 128, f); while (fgets(line, 128, f) != NULL) { char *name, *value, *nl; struct sysentry *se; if (line[0] == '\n') continue; name = &line[0]; value = strchr(line, '='); *value = '\0'; value++; nl = strchr(value, '\n'); *nl = '\0'; se = get_sysentry(name); if (se) strncpy(se->value, value, SYSDATA_VALUE_SZ); } fclose(f); return 0; } int parse_proc_ints() { FILE *f; char line[512]; char *value; struct sysentry *se; long long int phint = 0; f = fopen("/proc/interrupts", "r"); while (fgets(line, 512, f) != NULL) { /* we just need the SPU line */ if (line[0] != 'S' || line[1] != 'P' || line[2] != 'U') continue; for (value = &line[5]; value[2] != 'S'; value += 11) { int v; v = atoi(value); phint += v; } } fclose(f); se = get_sysentry("phint"); sprintf(se->value, "%lld", phint); return 0; } int parse_proc_stat() { FILE *f; char line[128]; char *value; int i, entries = 6; long long statvals[entries]; struct sysentry *se; char *unused; char *names[] = {"cpu_total", "cpu_user", "cpu_nice", "cpu_sys", "cpu_idle", "cpu_iowait"}; /* we just need the first line */ f = fopen("/proc/stat", "r"); unused = fgets(line, 128, f); fclose(f); statvals[0] = 0; value = line; for (i = 1; i <= (entries - 1); i++) { int v; value = strchr(value, ' ') + 1; if (i == 1) value++; v = atoi(value); statvals[i] = v; statvals[0] += v; } for (i = 0; i < entries; i++) { se = get_sysentry(names[i]); sprintf(se->value, "%lld", statvals[i]); } se = get_sysentry("cpu_lbusy"); sprintf(se->value, "%lld", statvals[1] + statvals[3]); return 0; } void get_smt_state(struct sysentry *se, char *buf) { char *value = "?"; if (se->value[0] == '1') value = "Shared"; else value = "Dedicated"; sprintf(buf, "%s", value); } void get_capped_mode(struct sysentry *se, char *buf) { char *value = "?"; if (se->value[0] == '1') value = "Capped"; else value = "Uncapped"; sprintf(buf, "%s", value); } void get_percent_entry(struct sysentry *se, char *buf) { float value; value = atoi(se->value); sprintf(buf, "%.2f", (value /100)); } void get_phys_cpu_percentage(struct sysentry *se, char *buf) { struct sysentry *tmp_se; int entcap, active; tmp_se = get_sysentry("DesEntCap"); entcap = atoi(tmp_se->value); tmp_se = get_sysentry("partition_active_processors"); active = atoi(tmp_se->value); sprintf(buf, "%d", entcap/active); } void get_active_cpus_in_pool(struct sysentry *se, char *buf) { struct sysentry *tmp; tmp = get_sysentry("pool_capacity"); sprintf(buf, "%d", atoi(tmp->value)/100); } void get_memory_mode(struct sysentry *se, char *buf) { struct sysentry *tmp; tmp = get_sysentry("entitled_memory"); if (tmp->value[0] == '\0') sprintf(buf, "Dedicated"); else sprintf(buf, "Shared"); } void get_name(const char *file, char *buf) { FILE *f; char tmpbuf[64]; int rc; f = fopen(file, "r"); if(!f) { sprintf(buf, "%c", '\0'); return; } rc = fread(tmpbuf, 64, 1, f); fclose(f); sprintf(buf, "%s", tmpbuf); } void get_node_name(struct sysentry *se, char *buf) { char *nl; get_name("/proc/sys/kernel/hostname", buf); /* For some reason this doesn't get null-terminated and makes * for ugly output. */ nl = strchr(buf, '\n'); *nl = '\0'; } void get_partition_name(struct sysentry *se, char *buf) { return get_name("/proc/device-tree/ibm,partition-name", buf); } void get_mem_total(struct sysentry *se, char *buf) { FILE *f; char line[128]; char *mem, *nl, *unused; f = fopen("/proc/meminfo", "r"); unused = fgets(line, 128, f); fclose(f); mem = strchr(line, ':'); do { mem++; } while (*mem == ' '); nl = strchr(mem, '\n'); *nl = '\0'; sprintf(buf, "%s", mem); } void get_smt_mode(struct sysentry *se, char *buf) { FILE *f; char line[128]; char *cmd = "/usr/sbin/ppc64_cpu --smt"; char *unused; f = popen(cmd, "r"); unused = fgets(line, 128, f); pclose(f); /* The output is either "SMT=x" or "SMT is off", we can cheat * by looking at line[8] for an 'f'. */ if (line[8] == 'f') sprintf(buf, "Off"); else sprintf(buf, "%c", line[4]); } long long get_cpu_time_diff() { long long old_total = 0, new_total = 0; struct sysentry *se; se = get_sysentry("cpu_total"); new_total = strtoll(se->value, NULL, 0); old_total = strtoll(se->old_value, NULL, 0); return new_total - old_total; } void get_cpu_stat(struct sysentry *se, char *buf) { float total, percent; float old_val, new_val; total = get_cpu_time_diff(); new_val = atoi(se->value); old_val = atoi(se->old_value); percent = (float)((new_val - old_val)/total) * 100; sprintf(buf, "%.2f", percent); } void init_sysdata(void) { get_time(); parse_lparcfg(); parse_proc_stat(); parse_proc_ints(); get_time_base(); } void update_sysdata(void) { struct sysentry *se = &system_data[0]; while (se->name[0] != '\0') { memcpy(se->old_value, se->value, SYSDATA_VALUE_SZ); se++; } init_sysdata(); } int print_iflag_data() { char *fmt = "%-45s: %s\n"; char value[64]; char *descr; int i = 0; while (iflag_entries[i] != NULL) { get_sysdata(iflag_entries[i], &descr, value); #ifndef DEBUG if (strcmp(value, SE_NOT_VALID) && strcmp(value, SE_NOT_FOUND)) #endif fprintf(stdout, fmt, descr, value); i++; } return 0; } void print_default_output(int interval, int count) { char *fmt = "%5s %5s %5s %5s %5s %5s %5s %5s %5s\n"; char *descr; char buf[128]; int offset; char value[32]; char user[32], sys[32], wait[32], idle[32], physc[32], entc[32]; char lbusy[32], vcsw[32], phint[32]; memset(buf, 0, 128); get_sysdata("shared_processor_mode", &descr, value); offset = sprintf(buf, "type=%s ", value); get_sysdata("capped", &descr, value); offset += sprintf(buf + offset, "mode=%s ", value); get_sysdata("smt_state", &descr, value); offset += sprintf(buf + offset, "smt=%s ", value); get_sysdata("partition_active_processors", &descr, value); offset += sprintf(buf + offset, "lcpu=%s ", value); get_sysdata("MemTotal", &descr, value); offset += sprintf(buf + offset, "mem=%s ", value); get_sysdata("active_cpus_in_pool", &descr, value); offset += sprintf(buf + offset, "cpus=%s ", value); get_sysdata("DesEntCap", &descr, value); offset += sprintf(buf + offset, "ent=%s ", value); fprintf(stdout, "\nSystem Configuration\n%s\n\n", buf); fprintf(stdout, fmt, "\%user", "\%sys", "\%wait", "\%idle", "physc", "\%entc", "lbusy", "vcsw", "phint"); fprintf(stdout, fmt, "-----", "-----", "-----", "-----", "-----", "-----", "-----", "-----", "-----"); do { if (interval) { sleep(interval); update_sysdata(); } get_sysdata("cpu_user", &descr, user); get_sysdata("cpu_sys", &descr, sys); get_sysdata("cpu_iowait", &descr, wait); get_sysdata("cpu_idle", &descr, idle); get_sysdata("cpu_lbusy", &descr, lbusy); get_sysdata("dispatches", &descr, vcsw); get_sysdata("physc", &descr, physc); get_sysdata("per_entc", &descr, entc); get_sysdata("phint", &descr, phint); fprintf(stdout, fmt, user, sys, wait, idle, physc, entc, lbusy, vcsw, phint); } while (--count > 0); } int main(int argc, char *argv[]) { int interval = 0, count = 0; int c; int i_option = 0; if (get_platform() != PLATFORM_PSERIES_LPAR) { fprintf(stderr, "%s: is not supported on the %s platform\n", argv[0], platform_name); exit(1); } while ((c = getopt(argc, argv, "i")) != -1) { switch(c) { case 'i': i_option = 1; break; case '?': default: break; } } /* see if there is an interval specified */ if (optind < argc) interval = atoi(argv[optind++]); /* check for count specified */ if (optind < argc) count = atoi(argv[optind++]); init_sysdata(); if (i_option) print_iflag_data(); else print_default_output(interval, count); return 0; } powerpc-utils-1.2.26/src/lparstat.h0000664000175000017510000001751712527176005014155 00000000000000/** * @file lparstat.h * @brief lparstat command header * * Copyright (c) 2011 International Business Machines * Common Public License Version 1.0 (see COPYRIGHT) * * @author Nathan Fontenot */ #define SYSDATA_VALUE_SZ 64 #define SYSDATA_NAME_SZ 64 #define SYSDATA_DESCR_SZ 128 struct sysentry { char value[SYSDATA_VALUE_SZ]; /* value from file */ char old_value[SYSDATA_VALUE_SZ]; /* previous value from file */ char name[SYSDATA_NAME_SZ]; /* internal name */ char descr[SYSDATA_DESCR_SZ]; /* description of data */ void (*get)(struct sysentry *, char *); }; extern void get_smt_state(struct sysentry *, char *); extern void get_capped_mode(struct sysentry *, char *); extern void get_memory_mode(struct sysentry *, char *); extern void get_percent_entry(struct sysentry *, char *); extern void get_phys_cpu_percentage(struct sysentry *, char *); extern void get_active_cpus_in_pool(struct sysentry *, char *); extern void get_partition_name(struct sysentry *, char *); extern void get_node_name(struct sysentry *, char *); extern void get_mem_total(struct sysentry *, char *); extern void get_smt_mode(struct sysentry *, char *); extern void get_cpu_stat(struct sysentry *, char *); extern void get_cpu_physc(struct sysentry *, char *); extern void get_per_entc(struct sysentry *, char *); struct sysentry system_data[] = { /* System Names */ {.name = "node_name", .descr = "Node Name", .get = &get_node_name}, {.name = "partition_name", .descr = "Partition Name", .get = &get_partition_name}, /* lparcfg data */ {.name = "serial_number", .descr = "Serial Number"}, {.name = "system_type", .descr = "System Model"}, {.name = "partition_id", .descr = "Partition Number"}, {.name = "group", .descr = "Partition Group-ID"}, {.name = "BoundThrds", .descr = "Bound Threads"}, {.name = "CapInc", .descr = "Capacity Increment", .get = &get_percent_entry}, {.name = "DisWheRotPer", .descr = "Dispatch Wheel Rotation Period"}, {.name = "MinEntCap", .descr = "Minimum Capacity", .get = &get_percent_entry}, {.name = "MinEntCapPerVP", .descr = "Minimum Entitled Capacity per Virtual Processor"}, {.name = "MinProcs", .descr = "Minimum Virtual CPUs"}, {.name = "partition_max_entitled_capacity", .descr = "Maximum Capacity", .get = &get_percent_entry}, {.name = "system_potential_processors", .descr = "Maximum System Processors"}, {.name = "DesEntCap", .descr = "Entitled Capacity", .get = &get_percent_entry}, {.name = "DesProcs", .descr = "Desired Processors"}, {.name = "DesVarCapWt", .descr = "Desired Variable Capacity Weight"}, {.name = "DedDonMode", .descr = "Dedicated Donation Mode"}, {.name = "partition_entitled_capacity", .descr = "Partition Entitled Capacity"}, {.name = "system_active_processors", .descr = "Active Physical CPUs in system"}, {.name = "pool", .descr = "Shared Pool ID"}, {.name = "pool_capacity", .descr = "Maximum Capacity of Pool", .get = &get_percent_entry}, {.name = "pool_idle_time", .descr = "Shared Processor Pool Idle Time"}, {.name = "pool_num_procs", .descr = "Shared Processor Pool Processors"}, {.name = "unallocated_capacity_weight", .descr = "Unallocated Weight"}, {.name = "capacity_weight", .descr = "Entitled Capacity of Pool"}, {.name = "capped", .descr = "Mode", .get = &get_capped_mode}, {.name = "unallocated_capacity", .descr = "Unallocated Processor Capacity"}, {.name = "physical_procs_allocated_to_virtualization", .descr = "Physical Processor Allocated to Virtualization"}, {.name = "max_proc_entitled_capacity", .descr = "Maximum Processor Capacity Available to Pool"}, {.name = "entitled_proc_capacity_available", .descr = "Entitled Capacity of Pool"}, {.name = "dispatches", .descr = "Virtual Processor Dispatch Counter"}, {.name = "dispatch_dispersions", .descr = "Virtual Processor Dispersions"}, {.name = "purr", .descr = "Processor Utilization Resource Register"}, {.name = "partition_active_processors", .descr = "Online Virtual CPUs"}, {.name = "partition_potential_processors", .descr = "Maximum Virtual CPUs"}, {.name = "shared_processor_mode", .descr = "Type", .get = &get_smt_state}, {.name = "slb_size", .descr = "SLB Entries"}, {.name = "MinMem", .descr = "Minimum Memory"}, {.name = "DesMem", .descr = "Desired Memory"}, {.name = "entitled_memory", .descr = "Total I/O Memory Entitlement"}, {.name = "mapped_entitled_memory", .descr = "Total I/O Mapped Entitled Memory"}, {.name = "entitled_memory_group_number", .descr = "Memory Group ID of LPAR"}, {.name = "entitled_memory_pool_number", .descr = "Memory Pool ID"}, {.name = "entitled_memory_pool_size", .descr = "Physical Memory in the Pool"}, {.name = "entitled_memory_weight", .descr = "Variable Memory Capacity Weight"}, {.name = "unallocated_entitled_memory_weight", .descr = "Unallocated Variable Memory Capacity Weight"}, {.name = "unallocated_io_mapping_entitlement", .descr = "Unallocated I/O Memory Entitlement"}, {.name = "entitled_memory_loan_request", .descr = "Entitled Memory Loan Request"}, {.name = "backing_memory", .descr = "Backing Memory"}, {.name = "cmo_enabled", .descr = "Active Memory Sharing Enabled"}, {.name = "cmo_faults", .descr = "Active Memory Sharing Page Faults"}, {.name = "cmo_fault_time_usec", .descr = "Active Memory Sharing Fault Time"}, {.name = "cmo_primary_psp", .descr = "Primary VIOS Partition ID"}, {.name = "cmo_secondary_psp", .descr = "Secondary VIOS Partition ID"}, {.name = "cmo_page_size", .descr = "Physical Page Size"}, /* /proc/meminfo */ {.name = "MemTotal", .descr = "Online Memory", .get = &get_mem_total}, /* ppc64_cpu --smt */ {.name = "smt_state", .descr = "SMT", .get = &get_smt_mode}, /* /proc/stat */ {.name = "cpu_total", .descr = "CPU Total Time"}, {.name = "cpu_user", .descr = "CPU User Time", .get = &get_cpu_stat}, {.name = "cpu_nice", .descr = "CPU Nice Time", .get = &get_cpu_stat}, {.name = "cpu_sys", .descr = "CPU System Time", .get = &get_cpu_stat}, {.name = "cpu_idle", .descr = "CPU Idle Time", .get = &get_cpu_stat}, {.name = "cpu_iowait", .descr = "CPU I/O Wait Time", .get = &get_cpu_stat}, {.name = "cpu_lbusy", .descr = "Logical CPU Utilization", .get = &get_cpu_stat}, /* placeholders for derived values */ {.name = "active_cpus_in_pool", .descr = "Active CPUs in Pool", .get = &get_active_cpus_in_pool}, {.name = "phys_cpu_percentage", .descr = "Physical CPU Percentage", .get = &get_phys_cpu_percentage}, {.name = "memory_mode", .descr = "Memory Mode", .get = &get_memory_mode}, {.name = "physc", .descr = "Physical CPU Consumed", .get = &get_cpu_physc}, {.name = "per_entc", .descr = "Entitled CPU Consumed", .get = &get_per_entc}, /* Time */ {.name = "time", .descr = "Time"}, /* /proc/cpuinfo */ {.name = "timebase", .descr = "Timebase"}, /* /proc/interrupts */ {.name = "phint", .descr = "Phantom Interrupts"}, {.name[0] = '\0'}, }; char *iflag_entries[] = { "node_name", "partition_name", "partition_id", "shared_processor_mode", "capped", "DesEntCap", "group", "pool", "partition_active_processors", "partition_potential_processors", "MinProcs", "MemTotal", "MinMem", "MaxMem", "MinEntCap", "partition_max_entitled_capacity", "CapInc", "max_system_cpus", "system_active_processors", "active_cpus_in_pool", "shared_cpus_in_system", "pool_capacity", "entitled_proc_capacity_available", "unallocated_capacity", "phys_cpu_percentage", "unallocated_capacity_weight", "memory_mode", "entitled_memory", "entitled_memory_weight", "entitled_memory_pool_number", "entitled_memory_pool_size", "hypervisor_page_size", "unallocated_entitled_memory_weight", "unallocated_io_mapping_entitlement", "entitled_memory_group_number", "desired_virt_cpus", "desired_memory", "DesVarCapWt", "desired_capacity", "target_mem_factor", "target_mem_size", NULL }; powerpc-utils-1.2.26/src/lsprop.c0000664000175000017510000001106512527176005013625 00000000000000/* * Copyright (C) 1998 Paul Mackerras. * * This program is free software; it may be used and redistributed * under the terms of the GNU Public Licence, either version 2, or * (at your option) any later version, or under the Common Public License * Version 1. */ #include #include #include #include #include #include #include #include int recurse; int maxbytes = 128; int words_per_line = 0; unsigned char *buf; void lsprop(FILE *f, char *name); void lsdir(char *name); int main(int ac, char **av) { FILE *f; int i; struct stat sb; char *endp; while ((i = getopt(ac, av, "Rm:w:")) != EOF) { switch (i) { case 'R': recurse = 1; break; case 'm': maxbytes = strtol(optarg, &endp, 0); if (endp == optarg) { fprintf(stderr, "%s: bad argument (%s) to -m option\n", av[0], optarg); exit(1); } maxbytes = (maxbytes + 15) & -16; break; case 'w': words_per_line = strtol(optarg, &endp, 0); if (endp == optarg) { fprintf(stderr, "%s: bad argument (%s) to -w option\n", av[0], optarg); exit(1); } break; } } buf = malloc(maxbytes); if (buf == 0) { fprintf(stderr, "%s: virtual memory exhausted\n", av[0]); exit(1); } if (optind == ac) lsdir("."); else for (i = optind; i < ac; ++i) { if (stat(av[i], &sb) < 0) { perror(av[i]); continue; } if (S_ISREG(sb.st_mode)) { f = fopen(av[i], "r"); if (f == NULL) { perror(av[i]); continue; } lsprop(f, av[i]); fclose(f); } else if (S_ISDIR(sb.st_mode)) { lsdir(av[i]); } } exit(0); } void lsdir(char *name) { DIR *d; struct dirent *de; char *p, *q; struct stat sb; FILE *f; int np = 0; d = opendir(name); if (d == NULL) { perror(name); return; } p = malloc(strlen(name) + 520); if (p == 0) { fprintf(stderr, "%s: virtual memory exhausted\n", name); closedir(d); return; } strcpy(p, name); q = p + strlen(p); while (q > p && q[-1] == '/') --q; if (q == p + 1 && p[0] == '.') q = p; else *q++ = '/'; while ((de = readdir(d)) != NULL) { if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; strcpy(q, de->d_name); if (stat(p, &sb) < 0) { perror(p); continue; } if (S_ISREG(sb.st_mode)) { f = fopen(p, "r"); if (f == NULL) { perror(p); } else { lsprop(f, de->d_name); fclose(f); ++np; } } } rewinddir(d); while ((de = readdir(d)) != NULL) { if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; strcpy(q, de->d_name); if (lstat(p, &sb) < 0) { perror(p); continue; } if (S_ISDIR(sb.st_mode)) { if (np) printf("\n"); printf("%s:\n", p); lsdir(p); ++np; } } free(p); closedir(d); } void lsprop(FILE *f, char *name) { int n, nw, npl, i, j; n = fread(buf, 1, maxbytes, f); if (n < 0) { printf("%s: read error\n", name); return; } printf("%-16s", name); if (strlen(name) > 16) printf("\n\t\t"); for (i = 0; i < n; ++i) if (buf[i] >= 0x7f || (buf[i] < 0x20 && buf[i] != '\r' && buf[i] != '\n' && buf[i] != '\t' && buf[i] != 0)) break; if (i == n && n != 0 && (n == 1 || buf[0] != 0) && buf[n-1] == 0) { printf(" \""); for (i = 0; i < n - 1; ++i) if (buf[i] == 0) printf("\"\n\t\t \""); else if (buf[i] == '\r' || buf[i] == '\n') printf("\n\t\t "); else putchar(buf[i]); putchar('"'); } else if ((n & 3) == 0) { nw = n >> 2; if (nw == 1) { i = be32toh(*(int *)buf); printf(" %.8x", i); if (i > -0x10000 && !(i >= 0 && i <= 9)) printf(" (%d)", i); } else { npl = words_per_line; if (npl <= 0) { if ((nw % 6) == 0) npl = 6; else if ((nw % 5) == 0) npl = 5; else npl = 4; } for (i = 0; i < nw; i += npl) { if (i != 0) printf("\n\t\t"); for (j = 0; j < npl && i + j < nw; ++j) printf(" %.8x", be32toh(((unsigned int *)buf)[i+j])); } } } else { for (i = 0; i < n; i += 16) { if (i != 0) printf("\n\t\t"); for (j = 0; j < 16 && i + j < n; ++j) printf(" %.2x", buf[i+j]); for (; j < 16; ++j) printf(" "); for (j = 0; j < 16 && i + j < n; ++j) if (buf[i+j] > 0x20 && buf[i+j] <= 0x7e) putchar(buf[i+j]); else putchar('.'); } } printf("\n"); if (n == maxbytes) { while ((i = fread(buf, 1, maxbytes, f)) > 0) n += i; if (n > maxbytes) printf("\t\t [%d bytes total]\n", n); } } powerpc-utils-1.2.26/src/nvram.c0000664000175000017510000012314012527176005013427 00000000000000/** * @file nvram.c * @brief nvram access utility for powerpc platforms. */ /** * @mainpage nvram documentation * @section Copyright * Copyright (c) 2003, 2004, 2005 International Business Machines * Common Public License Version 1.0 (see COPYRIGHT) * * @section Overview * The nvram command is used to print and modify data stored in the * non-volatile RAM (NVRAM) on powerpc systems. NVRAM on powerpc systems * is split into several partitions, each with their own format. * * The print options allow you to view the available partitions in NVRAM * and print their contents. * * The update options allow you to update certain partitions of NVRAM, * namely those containing name=value pairs. On many systems, the * following NVRAM partitions contain data formatted as name=value pairs: * common, of-config, and ibm,setupcfg. * * @author Nathan Fontenot * @author Michael Strosaker * @author Todd Inglett */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for ntohs */ #include #include #include #include #include #include "nvram.h" /** * @var nvram_cmdname * @brief name used to invoke thre nvram command (argv[0]) */ char *nvram_cmdname; static int verbose; static struct option long_options[] = { {"verbose", optional_argument, NULL, 'v'}, {"print-config", optional_argument, NULL, 'o'}, {"zero", optional_argument, NULL, '0'}, {"print-vpd", optional_argument, NULL, 'V'}, {"print-all-vpd", optional_argument, NULL, 'W'}, {"print-err-log", no_argument, NULL, 'e'}, {"print-event-scan", no_argument, NULL, 'E'}, {"partitions", no_argument, NULL, 'P'}, {"dump", required_argument, NULL, 'd'}, {"ascii", required_argument, NULL, 'a'}, {"unzip", required_argument, NULL, 'z'}, {"nvram-file", required_argument, NULL, 'n'}, {"nvram-size", required_argument, NULL, 's'}, {"update-config", required_argument, NULL, 'u'}, {"help", no_argument, NULL, 'h'}, {"partition", required_argument, NULL, 'p'}, {0,0,0,0} }; /** * help * @brief print the help/usage message for nvram */ static void help(void) { printf("nvram options:\n" " --print-config[=var]\n" " print value of a config variable, or print all variables in\n" " the specified (or all) partitions\n" " --zero | -0\n" " terminate config pairs with a NUL character\n" " --update-config =\n" " update the config variable in the specified partition; the -p\n" " option must also be specified\n" " -p \n" " specify a partition; required with --update-config option,\n" " optional with --print-config option\n" " --print-vpd\n" " print VPD\n" " --print-all-vpd\n" " print VPD, including vendor specific data\n" " --print-err-log\n" " print checkstop error log\n" " --print-event-scan\n" " print event scan log\n" " --partitions\n" " print NVRAM paritition header info\n" " --dump \n" " raw dump of partition (use --partitions to see names)\n" " --ascii \n" " print partition contents as ASCII text\n" " --unzip \n" " decompress and print compressed data from partition\n" " --nvram-file \n" " specify alternate nvram data file (default is /dev/nvram)\n" " --nvram-size\n" " specify size of nvram data, must in multiples of 16 Bytes\n" " (for repair operations)\n" " --verbose (-v)\n" " be (more) verbose\n" " --help\n" " print what you are reading right now.\n" ); } /** * @def ERR_MSG * @brief define to denote error messages */ #define ERR_MSG 0 /** * @def WARN_MSG * @brief define to denote warning messages */ #define WARN_MSG 1 /** * @def MAXLINE * @brief maximum line length */ #define MAXLINE 4096 /** * _msg * @brief print a message to stderr with the specified prefix * * @param msg_type either ERR_MSG or WARN_MSG * @param fmt formatted string a la printf() * @param ap initialized varaiable arg list */ void _msg(int msg_type, const char *fmt, va_list ap) { int n; char buf[MAXLINE]; n = sprintf(buf, "%s: %s", nvram_cmdname, (msg_type == WARN_MSG ? "WARNING: " : "ERROR: ")); vsprintf(buf + n, fmt, ap); fflush(stderr); fputs(buf, stderr); fflush(NULL); } /** * err_msg * @brief print an error message to stderr * * @param fmt formatted string a la printf() */ void err_msg(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void err_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); _msg(ERR_MSG, fmt, ap); va_end(ap); } /** * warn_msg * @brief print a warning message to stderr * * @param fmt formatted string a la printf() */ void warn_msg(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void warn_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); _msg(WARN_MSG, fmt, ap); va_end(ap); } /** * nvram_read * @brief read in the contents of nvram * * @param nvram nvram struct to read data into * @return 0 on success, !0 on failure */ int nvram_read(struct nvram *nvram) { int len, remaining, chunk; char *p; /* read in small chunks */ p = nvram->data; remaining = nvram->nbytes; chunk = (NVRAM_READ_SIZE < remaining) ? NVRAM_READ_SIZE : remaining; while ((len = read(nvram->fd, p, chunk)) > 0) { p+=len; remaining -= len; chunk = (NVRAM_READ_SIZE < remaining) ? NVRAM_READ_SIZE : remaining; } if (len == -1) { err_msg("cannot read \"%s\": %s\n", nvram->filename, strerror(errno)); return -1; } /* If we are using the DEFAULT_NVRAM_SZ value we to do a small bit of * fixup here. All of the remaining code assumes that nbytes contains * the actual size of nvram, not a guess-timated amount and bad things * ensue if it is not correct. */ if (nvram->nbytes == DEFAULT_NVRAM_SZ) { nvram->nbytes = nvram->nbytes - remaining; remaining = DEFAULT_NVRAM_SZ - (remaining + nvram->nbytes); } if (remaining) { warn_msg("expected %d bytes, but only read %d!\n", nvram->nbytes, nvram->nbytes - remaining); /* preserve the given nbytes, but zero the rest in case someone cares */ memset(p, 0, remaining); } if (verbose) printf("NVRAM size %d bytes\n", nvram->nbytes); return 0; } /** * checksum * @brief calculate the checksum for a partition header * * @param p pointer to partition header * @return calculated checksum */ static unsigned char checksum(struct partition_header *p) { unsigned int c_sum, c_sum2; unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5]; /* The sum probably may have spilled into the 3rd byte. Fold it back. */ c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff; /* The sum cannot exceed 2 bytes. Fold it into a checksum */ c_sum2 = (c_sum >> 8) + (c_sum << 8); c_sum = ((c_sum + c_sum2) >> 8) & 0xff; return c_sum; } /** * dump_raw_data * @brief raw data dump of a partition. * * Note that data_len must be a multiple of 16 bytes which makes * for a cheap implementation. * * @param data pointer to data to be dumped * @param data_len length of data buffer to be dumped */ void dump_raw_data(char *data, int data_len) { int i, j; int offset = 0; char *h, *a; char *end = data + data_len; h = a = data; while (h < end) { printf("0x%08x ", offset); offset += 16; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (h <= end) printf("%02x", *h++); else printf(" "); } printf(" "); } printf("|"); for (i = 0; i < 16; i++) { if (a <= end) { if ((*a >= ' ') && (*a <= '~')) printf("%c", *a); else printf("."); a++; } else printf(" "); } printf("|\n"); } } /** * parse_of_common * @brief parse a config definition * * Parse an Open Firmware common config definition which * is of the form name=value and return its length. * * Note that the name will always be < 32 chars. OF does * not specify the max value length, but the value is binary * and must be unquoted. We assume 4k is enough. * * @param data pointer to start of raw data (NULL terminated) * @param data_len length of remaining raw data * @param outname buffer to write parsed name * @param outval buffer to write parsed output value * @return number of bytes parsed */ int parse_of_common(char *data, int data_len, char *outname, char *outval) { char *p, *np; char *p_end = data + data_len; for (p = data, np = outname; *p && *p != '='; p++) { *np++ = *p; if (np - outname > 32) break; /* don't overrun */ if (p >= p_end) { err_msg("partition corrupt: ran off end parsing name\n"); return 0; } } *np = '\0'; if (*p != '=') { err_msg("corrupt data: no = sign found or name > 31 chars\n"); return 0; } p++; /* Value needs to be unquoted */ for (np = outval; *p; p++) { if (*p == (char)0xff) { char ch, num; p++; if (p >= p_end) { err_msg("partition corrupt: ran off end parsing " "quoted value\n"); return 0; } num = *p & 0x7f; ch = (*p & 0x80) ? 0xff : 0; /* hi bit chooses ff or 00. */ if (np + num - outval > 4096) break; /* don't overrun */ /* repeat char */ while (num > 0) { *np++ = ch; num--; } } else { *np++ = *p; if (np - outval > 4096) break; /* don't overrun */ } if (p >= p_end) { err_msg("partition corrupt: ran off end parsing value\n"); return 0; } } *np = '\0'; if (*p) { err_msg("data value too long for this utility (>4k)\n"); return 0; /* ToDo: recover */ } return p - data; } /** * nvram_parse_partitions * @brief fill in the nvram structure with data from nvram * * Fill in the partition parts of the struct nvram. * This makes handling partitions easier for the rest of the code. * * The spec says that partitions are made up of 16 byte blocks and * the partition header must be 16 bytes. We verify that here. * * @param nvram pointer to nvram struct to fill out * @return 0 on success, !0 otherwise */ static int nvram_parse_partitions(struct nvram *nvram) { char *nvram_end = nvram->data + nvram->nbytes; char *p_start = nvram->data; struct partition_header *phead; unsigned char c_sum; if (sizeof(struct partition_header) != 16) { err_msg("partition_header struct is not 16 bytes\n"); return -1; } while (p_start < nvram_end) { phead = (struct partition_header *)p_start; nvram->parts[nvram->nparts++] = phead; c_sum = checksum(phead); if (c_sum != phead->checksum) warn_msg("this partition checksum should be %02x!\n", c_sum); phead->length = be16toh(phead->length); p_start += phead->length * NVRAM_BLOCK_SIZE; } if (verbose) printf("NVRAM contains %d partitions\n", nvram->nparts); return 0; } /** * nvram_find_fd_partition * @brief Find a particular nvram partition using a file descriptor * * @param name name of the partition to find * @param nvram pointer to nvram struct to search * @return 0 on success, !0 otherwise */ static int nvram_find_fd_partition(struct nvram *nvram, char *name) { struct partition_header phead; int len; int found = 0; if (lseek(nvram->fd, SEEK_SET, 0) == -1) { err_msg("could not seek to beginning of file %s\n", nvram->filename); return -1; } while (! found) { len = read(nvram->fd, &phead, sizeof(phead)); if (len == 0) { /* EOF */ err_msg("could not find %s partition in %s\n", name, nvram->filename); return -1; } else if (len != sizeof(phead)) { err_msg("Invalid read from %s: %s\n", nvram->filename, strerror(errno)); return -1; } if (! strncmp(phead.name, name, sizeof(phead.name))) found = 1; else { int offset = be16toh(phead.length) * NVRAM_BLOCK_SIZE - len; if (lseek(nvram->fd, offset, SEEK_CUR) == -1) { err_msg("seek error in file %s: %s\n", nvram->filename, strerror(errno)); return -1; } } } if (! found) { err_msg("could not find %s partition in %s\n", name, nvram->filename); return -1; } /* we found the correct partition seek back to the beginning of it */ if (lseek(nvram->fd, -len, SEEK_CUR) == -1) { err_msg("could not seek to %s partition\n", name); return -1; } return 0; } /** * nvram_find_partition * @brief Find a partition given a signature and name. * * If signature is zero (invalid) it is not used for matching. * If name is NULL it is ignored. * start is the partition in which to resume a search (NULL starts at the first * partition). * * @param signature partition signature to find * @param name partition name to find * @param start partition header to start search at * @param nvram nvram struct to search * @return pointer to partition header on success, NULL otherwise */ static struct partition_header * nvram_find_partition(struct nvram *nvram, unsigned char signature, char *name, struct partition_header *start) { struct partition_header *phead; int i; /* Get starting partition. This is not terribly efficient... */ if (start == NULL) { i = 0; if (verbose > 1) printf("find partition starts with zero\n"); } else { for (i = 0; i < nvram->nparts; i++) if (nvram->parts[i] == start) break; i++; /* start at next partition */ if (verbose > 1) printf("find partition starts with %d\n", i); } /* Search starting with partition i... */ while (i < nvram->nparts) { phead = nvram->parts[i]; if (signature == '\0' || signature == phead->signature) { if (name == NULL || strncmp(name, phead->name, sizeof(phead->name)) == 0) { return phead; } } i++; } return NULL; } /** * print_partition_table * @brief print a table of available partitions * * @param nvram nvram struct of partitions */ static void print_partition_table(struct nvram *nvram) { struct partition_header *phead; int i = 0; printf(" # Sig Chk Len Name\n"); for (i = 0; i < nvram->nparts; i++) { phead = nvram->parts[i]; printf("%2d %02x %02x %04x %.12s\n", i, phead->signature, phead->checksum, phead->length, phead->name); } } /** * getvalue * @brief Copy a value into a buf. * The first two bytes of the value is a length. * Return pointer to byte after the value. * * @param p pointer to value to copy * @param buf buffer to copy value into * @return pointer past the copied value in p */ static char * getvalue(char *p, char *buf) { int len = *p++; len |= ((*p++) << 8); memcpy(buf, p, len); buf[len] = '\0'; return p+len; } /** * getsmallvlaue * @brief Copy a value into a buf. * The first one bytes of the value is a length. * * @param p pointer to value to copy * @param buf buffer to copy value into * @return pointer past the copied value in p */ static char * getsmallvalue(char *p, char *buf) { int len = *p++; memcpy(buf, p, len); buf[len] = '\0'; return p+len; } /** * lookupfield * @brief translate a VPD field to human readable string * * Lookup a VPD field name (always 2 chars) and return a human * readable string. * * @param p VPD field name * @return pointer to human readable string on success, NULL otherwise */ static char * lookupfield(char *p) { int i; for (i = 0; (i < sizeof(descs) / sizeof(descs[0])); i++) { if (strcmp(p, descs[i].name) == 0) return descs[i].desc; } return NULL; } /** * printVPDfield * @brief Format and print a VPD field and return a ptr to the next field. * * @param p pointer to VPD field * @param show_all verbosity level * @return pointer to next VPD field */ static char * printVPDfield(char *p, int show_all) { char field[3]; char value[256]; char *fname; field[0] = p[0]; field[1] = p[1]; field[2] = 0; p+=2; p = getsmallvalue(p, value); if ((fname = lookupfield(field)) != NULL) printf(" %-20s %s\n", fname, value); else if (show_all) printf(" %-20s %s\n", field, value); return p; } /** * dump_vpd * @brief Dump Vital Product Data * * See Chapter 18: Expansion ROMs of the PCI spec. * * @param nvram nvram struct to retrieve VPD data from * @param show_all verbosity level */ int dump_vpd(struct nvram *nvram, int show_all) { struct partition_header *phead; char *p, *p_end; char value[4096]; phead = nvram_find_partition(nvram, NVRAM_SIG_HW, "ibm,vpd", NULL); if (!phead) { err_msg("there is no ibm,vpd partition!\n"); return -1; } p = (char *)(phead + 1); p_end = (char *)(phead + phead->length); while (*p && p < p_end) { if (*p == (char)0x82) { /* Identification string descriptor. */ p++; p = getvalue(p, value); printf("%s\n", value); /* print id string */ while (*p != 0x79) { /* loop until VPD end tag */ int vpdlen; char *vpd_endp; p++; vpdlen = *p++; vpdlen |= ((*p++) << 8); vpd_endp = p + vpdlen; while (p < vpd_endp) p = printVPDfield(p, show_all); } p++; /* printf("checksum byte=0x%x\n", *p); */ p++; } else if (*p == 0) { /* end tag */ break; } } if (*p && p < p_end) { warn_msg("found unknown descriptor byte 0x%x\n", *p); } return 0; } /** * dump_errlog * @brief Dump ibm,err-log partition which contains checkstop info. * * ToDo: this code needs more work. * See IBM RPA (IBM internal use only -- sorry). * * @param nvram nvram struct to dump errlog from * @return 0 on success, !0 otherwise */ int dump_errlog(struct nvram *nvram) { struct partition_header *phead; uint16_t *p, *p_end; /* Note: data is organized into 16bit big * endian (network byte order) */ int p_max; /* max index to go out of bounds of the partition */ int i, cpu; char checkstop_count; int offset; int num_cpus; int num_memctrls; int num_ioctrls; uint16_t *sys_regs; /* System specific registers * (e.g. bus arbitration chips, etc */ uint16_t *cpu_regs[MAX_CPUS+1]; uint16_t *memctrl_data; uint16_t *ioctrl_data; phead = nvram_find_partition(nvram, NVRAM_SIG_SP, "ibm,err-log", NULL); if (!phead) { err_msg("there is no ibm,err-log partition!\n"); return -1; } p = (uint16_t *)(phead + 1); p_end = (uint16_t *)(phead + phead->length); p_max = p_end - p; /* max in 16bit values */ if (p_max < 4) { err_msg("Corrupt ibm,err-log partition in nvram\n"); return -1; } /* index 0 is checkstop count (high byte), semaphores (low byte) */ i = 0; /* index through short words */ checkstop_count = p[i] >> 8; if (checkstop_count) printf("Checkstops detected: %d\n", checkstop_count); else printf("No checkstops have been detected.\n"); /* index 1 is system specific register offset */ i++; offset = ntohs(p[i])/2+1; sys_regs = offset + i < p_max ? p + offset + i : 0; /* index 2 is number of cpus */ i++; num_cpus = ntohs(p[i]); printf("CPUS: %d\n", num_cpus); /* Next indexes are offsets to cpu specific regs */ for (cpu = 0; cpu < num_cpus; cpu++) { i++; if (cpu < MAX_CPUS) { offset = ntohs(p[i])/2+1; cpu_regs[cpu] = offset + i < p_max ? p + offset + i : 0; } } if (num_cpus > MAX_CPUS) num_cpus = MAX_CPUS; /* just in case... */ /* next index is number of memory controllers */ i++; num_memctrls = ntohs(p[i]); printf("Memory Controllers: %d\n", num_memctrls); /* next index is offset of memory controller data */ i++; /* ToDo: this may be a list of offsets...manual doesn't show that but only 1 seems odd */ offset = ntohs(p[i])/2+1; memctrl_data = offset + i < p_max ? p + offset + i : 0; /* next index is number of I/O Subsystem controllers */ i++; num_ioctrls = ntohs(p[i]); printf("I/O Controllers: %d\n", num_ioctrls); /* next index is offset of I/O Subsystem controller data */ i++; /* ToDo: this may be a list of offsets...manual doesn't show that but only 1 seems odd */ offset = ntohs(p[i])/2+1; ioctrl_data = offset + i < p_max ? p + offset + i : 0; /*** End of header ***/ /* Now dump sections collected by the header. */ if (sys_regs && num_cpus > 0) { /* ToDo: what is the length of the data? We dump until the first cpu data. */ printf("System Specific Registers\n"); dump_raw_data((char *)sys_regs, cpu_regs[0] - sys_regs); } /* artificial "next cpu" data for length */ cpu_regs[num_cpus] = ioctrl_data; for (cpu = 0; cpu < num_cpus; cpu++) { /*char buf[64];*/ int len; /* ToDo: what is the length of the data? We dump until the next cpu data. */ len = cpu_regs[cpu+1] - cpu_regs[cpu]; printf("CPU %d Register Data (len=%x, offset=%"PRIx64")\n", cpu, len, cpu_regs[cpu]-p); if (len < 4096) /* reasonable bound */ dump_raw_data((char *)cpu_regs[cpu], len); } return 0; } /** * dump_rtas_event_entry * @brief Dump event-scan data. * * Note: This is really only valid for PAPR machines. To ensure * the nvram command can run on all powerpc machines we dlopen the * the librtasevent library to dump the rtas event. * * @param data pointer to rtas error to dump * @param len length of data buffer * @return 0 on success, !0 otherwise */ int dump_rtas_event_entry(char *data, int len) { void *rtas_event; void *handle; void *(*parse_rtas_event)(); void (*rtas_print_event)(); void (*cleanup_rtas_event)(); handle = dlopen("/usr/lib/librtasevent.so", RTLD_LAZY); if (handle == NULL) return 1; parse_rtas_event = dlsym(handle, "parse_rtas_event"); if (parse_rtas_event == NULL) { dlclose(handle); return 1; } rtas_print_event = dlsym(handle, "rtas_print_event"); if (rtas_print_event == NULL) { dlclose(handle); return 1; } cleanup_rtas_event = dlsym(handle, "cleanup_rtas_event"); if (cleanup_rtas_event == NULL) { dlclose(handle); return 1; } rtas_event = parse_rtas_event(data, len); if (rtas_event == NULL) { dlclose(handle); return 1; } rtas_print_event(stdout, rtas_event, 0); cleanup_rtas_event(rtas_event); dlclose(handle); return 0; } /** * dump_eventscanlog * @brief Dump ibm,es-logs partition, which contains a service processor log * * See IBM RPA (IBM internal use only -- sorry). * * @param nvram nvram struct to get eventscan log from * @return 0 on success, !0 otherwise */ int dump_eventscanlog(struct nvram *nvram) { struct partition_header *phead; uint32_t *p, *p_end; /* Note: data is organized into 32bit big * endian (network byte order) */ int p_max; /* max index to go out of bounds of the partition */ int lognum; int num_logs; int rc; #define MAX_EVENTLOGS 100 uint32_t loghdr[MAX_EVENTLOGS+1]; phead = nvram_find_partition(nvram, NVRAM_SIG_SP, "ibm,es-logs", NULL); if (!phead) { err_msg("there is no ibm,es-logs partition!\n"); return -1; } p = (uint32_t *)(phead + 1); p_end = (uint32_t *)(phead + phead->length); p_max = p_end - p; /* max in 32bit values */ if (p_max < 1) { err_msg("Corrupt ibm,es-logs partition in nvram\n"); return -1; } num_logs = ntohl(*p); printf("Number of Logs: %d\n", num_logs); if (num_logs > MAX_EVENTLOGS) { num_logs = MAX_EVENTLOGS; warn_msg("limiting to %d log entries (program limit)\n", num_logs); } if (num_logs > p_max-1) { /* of course this leaves no room for log data (i.e. corrupt partition) */ num_logs = p_max-1; warn_msg("limiting to %d log entries (partition limit)\n", num_logs); } for (lognum = 0; lognum < num_logs; lognum++) { loghdr[lognum] = ntohl(p[lognum+1]); } /* artificial log entry (offset) to put a limit on the last log */ loghdr[num_logs] = p_max * sizeof(uint32_t); for (lognum = 0; lognum < num_logs; lognum++) { uint32_t hdr = loghdr[lognum]; int flags = (hdr >> 24) & 0xff; int logtype = (hdr >> 16) & 0xff; int start = hdr & 0xffff; int end = loghdr[lognum+1] & 0xffff; printf("Log Entry %d: flags: 0x%02x type: 0x%02x\n", lognum, flags, logtype); rc = dump_rtas_event_entry(((char *)p) + start, end - start); if (rc) { printf("==== Log %d ====\n", lognum); dump_raw_data(((char *)p) + start, end - start); } } return 0; } /** * dump_raw_partition * @brief Dump raw data of a partition. Mainly for debugging. * * @param nvram nvram struct containing partition * @param name name of partition to dump * @return 0 on success, !0 otherwise */ int dump_raw_partition(struct nvram *nvram, char *name) { struct partition_header *phead; phead = nvram_find_partition(nvram, 0, name, NULL); if (!phead) { err_msg("there is no %s partition!\n", name); return -1; } dump_raw_data((char *)phead, phead->length * NVRAM_BLOCK_SIZE); return 0; } /** * dump_ascii_partition * @brief ASCII data dump of a partition, excluding header * * @param nvram nvram struct containing partition * @param name name of partition to dump * @return 0 on success, !0 otherwise * * Partition subheaders, if any, are dumped along with the rest of the data. * We substitute periods for unprintable characters. */ int dump_ascii_partition(struct nvram *nvram, char *name) { struct partition_header *phead; char *start, *end, *c; phead = nvram_find_partition(nvram, 0, name, NULL); if (!phead) { err_msg("there is no %s partition!\n", name); return -1; } start = (char*) phead; end = start + phead->length * NVRAM_BLOCK_SIZE; start += sizeof(*phead); /* Skip partition header. */ for (c = start; c < end; c++) { if (isprint(*c) || isspace(*c)) putchar(*c); else putchar('.'); } /* Always end with a newline.*/ putchar('\n'); return 0; } int dump_zipped_text(char *zipped_text, unsigned int zipped_length) { z_stream strm; int result; char unzipped_text[4096]; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = zipped_length; strm.next_in = (Bytef*) zipped_text; result = inflateInit(&strm); if (result != Z_OK) { err_msg("can't decompress text: inflateInit() returned %d\n", result); return -1; } do { strm.avail_out = 4096; strm.next_out = (Bytef*) unzipped_text; result = inflate(&strm, Z_NO_FLUSH); switch (result) { case Z_STREAM_ERROR: case Z_NEED_DICT: case Z_DATA_ERROR: case Z_MEM_ERROR: err_msg("can't decompress text: inflate() returned %d\n", result); (void) inflateEnd(&strm); return -1; } if (fwrite(unzipped_text, 4096 - strm.avail_out, 1, stdout) != 1) { err_msg("can't decompress text: fwrite() failed\n"); (void) inflateEnd(&strm); return -1; } } while (strm.avail_out == 0); (void) inflateEnd(&strm); return 0; } /** * unzip_partition * @brief Uncompress and print compressed data from a partition. * * @param nvram nvram struct containing partition * @param name name of partition to dump * @return 0 on success, !0 otherwise */ int unzip_partition(struct nvram *nvram, char *name) { struct partition_header *phead; char *start, *next; unsigned short zipped_length; phead = nvram_find_partition(nvram, 0, name, NULL); if (!phead) { err_msg("there is no %s partition!\n", name); return -1; } start = (char*) phead; next = start + sizeof(*phead); /* Skip partition header. */ next += sizeof(struct err_log_info); /* Skip sub-header. */ zipped_length = be16toh(*((unsigned short*) next)); next += sizeof(unsigned short); /* New format oops header, zipped_length > OOPS_PARTITION_SZ * signifies the version of new header. Find out new zipped length * and from where the compressed data starts. */ if (zipped_length > OOPS_PARTITION_SZ) { zipped_length = be16toh(*((unsigned short*) next)); next += sizeof(struct oops_log_info) - sizeof(unsigned short); } if ((next-start) + zipped_length > phead->length * NVRAM_BLOCK_SIZE) { err_msg("bogus size for compressed data in partition %s: %u\n", name, zipped_length); return -1; } return dump_zipped_text(next, zipped_length); } /** * print_of_config_part * @brief Print the name/value pairs of a partition * * @param pname partition name containing name/value pairs * @param nvram nvram struct containing partition to dump * @return 0 on success, !0 otherwise */ static int print_of_config_part(struct nvram *nvram, char *pname) { struct partition_header *phead; char *data; int i; phead = nvram_find_partition(nvram, 0, pname, NULL); if (phead == NULL) return -1; data = (char *)phead + sizeof(*phead); printf("\"%s\" Partition\n", pname); for (i = 0; i <= (strlen(pname) + 14); i++) printf("-"); printf("\n"); while (*data != '\0') { printf("%s\n", data); data += strlen(data) + 1; } printf("\n"); return 0; } /* Print a single OF var...or all if "" is used */ /** * @var name_value_parts * @brief List of partition names that contain name/value pairs */ /** * @var num_name_value_parts * @brief number of names in the name_vlaue_parts array */ static char *name_value_parts[] = { "common", "ibm,setupcfg", "of-config" }; static int num_name_value_parts = 3; /** * print_of_config * @brief Print the contents of an Open Firmware config partition * * This will print the name/value pair for a specified Open * Firmware config variable or print all of the name/value pairs * in the partition if the name is NULL. * * @param config_var config variable to print * @param pname partition name containing config_var * @param nvram nvram struct containing pname * @return 0 on success, !0 otherwise */ static int print_of_config(struct nvram *nvram, char *config_var, char *pname, int zero_terminator) { struct partition_header *phead; char *data, terminator; int i, varlen; int rc = -1; terminator = '\n'; if (zero_terminator) terminator = '\0'; /* if config_var is NULL , print the data from the * partition specified by pname or all of the * name/value pair partitions if pname is NULL. */ if (config_var == NULL) { if (pname == NULL) { for (i = 0; i < num_name_value_parts; i++) (void)print_of_config_part(nvram, name_value_parts[i]); } else { for (i = 0; i < num_name_value_parts; i++) { if (strcmp(pname, name_value_parts[i]) == 0) { (void)print_of_config_part(nvram, name_value_parts[i]); rc = 0; } } if (rc) err_msg("There is no Open Firmware \"%s\" partition!\n", pname); } return rc; } /* the config_var is a variable name */ varlen = strlen(config_var); if (pname == NULL) { for (i = 0; i < num_name_value_parts; i++) { phead = nvram_find_partition(nvram, 0, name_value_parts[i], NULL); if (phead == NULL) continue; data = (char *)phead + sizeof(*phead); while (*data != '\0') { if ((data[varlen] == '=') && strncmp(config_var, data, varlen) == 0) { printf("%s%c", data + varlen + 1, terminator); rc = 0; } data += strlen(data) + 1; } } } else { phead = nvram_find_partition(nvram, 0, pname, NULL); if (phead == NULL) { err_msg("There is no Open Firmware \"%s\" partition.\n", pname); return -1; } data = (char *)phead + sizeof(*phead); while (*data != '\0') { if ((data[varlen] == '=') && strncmp(config_var, data, varlen) == 0) { printf("%s%c", data + varlen + 1, terminator); rc = 0; } data += strlen(data) + 1; } } return rc; } /** * update_config_var * @brief Update an Open Firmware config variable in nvram * * This will attempt to update the value half of a name/value * pair in the nvram config partition. If the name/value pair * is not found in the partition then the specified name/value pair * is added to the end of the data in the partition. * * @param config_var OF config variable to update * @param pname partition containing config_var * @param nvram nvram struct containing pname * @return 0 on success, !0 otherwise */ int update_of_config_var(struct nvram *nvram, char *config_var, char *pname) { struct partition_header *phead, *new_phead; char *new_config_value; char *data_offset; char *new_part; char *new_part_offset, *new_part_end; char *tmp_offset; int config_name_len; int len, rc, part_size; new_config_value = strchr(config_var, '='); if (!new_config_value) { err_msg("config variables must be in the format \"name=value\""); return -1; } new_config_value++; phead = nvram_find_partition(nvram, 0, pname, NULL); if (phead == NULL) { err_msg("there is no \"%s\" partition!\n", pname); return -1; } part_size = phead->length * NVRAM_BLOCK_SIZE; data_offset = (char *)((unsigned long)phead + sizeof(*phead)); new_part = malloc(part_size); if (new_part == NULL) { err_msg("cannot allocate space to update \"%s\" partition\n", pname); return -1; } memset(new_part, 0, part_size); /* get the length of then name of the config variable we are updating */ config_name_len = strstr(config_var, "=") - config_var; config_name_len++; /* now find this config variable in the partition */ while (*data_offset != '\0') { if (strncmp(data_offset, config_var, config_name_len) == 0) break; data_offset += strlen(data_offset) + 1; } /* Copy everything up to the config name we are modifying * to the new partition */ memcpy(new_part, phead, data_offset - (char *)phead); /* make sure the new config var will fit into the partition and add it */ new_phead = (struct partition_header *)new_part; new_phead->length = be16toh(new_phead->length); new_part_offset = new_part + (data_offset - (char *)phead); new_part_end = new_part + part_size; if ((new_part_offset + strlen(config_var) + 1) >= new_part_end) { err_msg("cannot update config var to\"%s\".\n" "\tThere is not enough room in the \"%s\" partition\n", config_var, pname); free(new_part); return -1; } if (strlen(new_config_value)) { strncpy(new_part_offset, config_var, strlen(config_var)); new_part_offset += strlen(config_var); *new_part_offset++ = '\0'; } /* Find the end of the name/value pairs in the partition so we * can copy them over to the new partition. */ data_offset += strlen(data_offset) + 1; tmp_offset = data_offset; while (*data_offset != '\0') { data_offset += strlen(data_offset) + 1; } /* we should now be pointing to a double NULL, verify this */ if ((data_offset[-1] != '\0') && (data_offset[0] != '\0')) { err_msg("the \"%s\" partition appears to be corrupt\n", pname); free(new_part); return -1; } /* go past double NULL */ data_offset++; /* verify that this will fit into the new partition */ if ((new_part_offset + (data_offset - tmp_offset)) > new_part_end) { err_msg("cannot update open firmware config var to \"%s\".\n" "\tThere is not enough room in the \"%s\" partition\n", config_var, pname); free(new_part); return -1; } memcpy(new_part_offset, tmp_offset, data_offset - tmp_offset); /* recalculate the checksum */ new_phead->checksum = checksum(new_phead); /* seek the position in the /dev/nvram for the common partition */ if (nvram_find_fd_partition(nvram, new_phead->name) != 0) { free(new_part); return -1; } /* write the partition out to nvram */ for (rc = 0, len = 0; len < part_size; len += rc) { rc = write(nvram->fd, new_part + len, part_size - len); if (rc <= 0) break; } if (len != part_size) { err_msg("only wrote %d bytes of the \"%s\" partition back\n" "\tto %s, expected to write %d bytes\n", len, pname, nvram->filename, part_size); } free(new_part); return 0; } int main (int argc, char *argv[]) { struct nvram nvram; struct stat sbuf; int ret = 0; int option_index; char *endp; char *of_config_var = NULL; int print_partitions = 0; int print_vpd = 0; int print_errlog = 0; int print_event_scan = 0; int print_config_var = 0; int zero_terminator = 0; char *dump_name = NULL; char *ascii_name = NULL; char *zip_name = NULL; char *update_config_var = NULL; char *config_pname = "common"; nvram_cmdname = argv[0]; if (argc == 1) { help(); exit(1); } /* initialize nvram struct */ memset(&nvram, 0, sizeof(struct nvram)); nvram.fd = -1; for (;;) { option_index = 0; ret = getopt_long(argc, argv, "+p:Vv::0", long_options, &option_index); if (ret == -1) break; switch (ret) { case 'h': help(); exit(0); case 'v': verbose += (optarg ? atoi(optarg) : 1); break; case 'd': /* dump */ dump_name = optarg; break; case 'a': /* ASCII dump */ ascii_name = optarg; break; case 'z': /* dump compressed data */ zip_name = optarg; break; case 'n': /* nvram-file */ nvram.filename = optarg; break; case 'o': /*print-config */ print_config_var = 1; of_config_var = optarg; break; case '0': zero_terminator = 1; break; case 'P': /* partitions */ print_partitions = 1; break; case 's': /* nvram-size */ nvram.nbytes = strtoul(optarg, &endp, 10); if (!*optarg || *endp) { err_msg("specify nvram-size as an integer\n"); exit(1); } if (nvram.nbytes % NVRAM_BLOCK_SIZE) { err_msg("nvram-size must be a multiple of 16 Bytes\n"); exit(1); } break; case 'V': /* print-vpd */ print_vpd = 1; break; case 'W': /* print-all-vpd */ print_vpd = 2; break; case 'e': /* print-err-log */ print_errlog = 1; break; case 'E': /* print-event-scan */ print_event_scan = 1; break; case 'u': /* update-config */ update_config_var = optarg; break; case 'p': /* update-config partition name */ config_pname = optarg; break; case '?': exit(1); break; default: printf("huh?\n"); break; } } if (optind < argc) { err_msg("Could not parse the option %s correctly.\n", argv[optind]); help(); exit(-1); } ret = 0; if (nvram.filename) { nvram.fd = open(nvram.filename, O_RDWR); if (nvram.fd == -1) { err_msg("cannot open \"%s\": %s\n", nvram.filename, strerror(errno)); ret = -1; goto err_exit; } } else { nvram.filename = NVRAM_FILENAME1; nvram.fd = open(nvram.filename, O_RDWR); if (nvram.fd == -1) { int errno1 = errno; nvram.filename = NVRAM_FILENAME2; nvram.fd = open(nvram.filename, O_RDWR); if (nvram.fd == -1) { err_msg("cannot open \"%s\": %s\n", NVRAM_FILENAME1, strerror(errno1)); err_msg("cannot open \"%s\": %s\n", NVRAM_FILENAME2, strerror(errno)); ret = -1; goto err_exit; } } } if (fstat(nvram.fd, &sbuf) < 0) { err_msg("cannot stat %s: %s\n", nvram.filename, strerror(errno)); ret = -1; goto err_exit; } if (!nvram.nbytes) { ret = lseek(nvram.fd, 0, SEEK_END); if (ret < 0) { err_msg("cannot seek(END) %s: %s\n", nvram.filename, strerror(errno)); goto err_exit; } nvram.nbytes = ret; ret = lseek(nvram.fd, 0, SEEK_SET); if (ret < 0) { err_msg("cannot seek(SET) %s: %s\n", nvram.filename, strerror(errno)); goto err_exit; } } nvram.data = malloc(nvram.nbytes); if (nvram.data == NULL) { err_msg("cannot allocate space for nvram of %d bytes\n", nvram.nbytes); ret = -1; goto err_exit; } if (nvram_read(&nvram) != 0) { ret = -1; goto err_exit; } if (nvram_parse_partitions(&nvram) != 0) { ret = -1; goto err_exit; } if (print_partitions) print_partition_table(&nvram); if (update_config_var) { if (config_pname == NULL) { err_msg("you must specify the partition name with the -p option\n" "\twhen using the --update-config option\n"); goto err_exit; } if (update_of_config_var(&nvram, update_config_var, config_pname) != 0) ret = -1; } if (print_config_var) if (print_of_config(&nvram, of_config_var, config_pname, zero_terminator) != 0) ret = -1; if (print_vpd) if (dump_vpd(&nvram, print_vpd == 2) != 0) ret = -1; if (print_errlog) if (dump_errlog(&nvram) != 0) ret = -1; if (print_event_scan) if (dump_eventscanlog(&nvram) != 0) ret = -1; if (dump_name) if (dump_raw_partition(&nvram, dump_name) != 0) ret = -1; if (ascii_name) if (dump_ascii_partition(&nvram, ascii_name) != 0) ret = -1; if (zip_name) if (unzip_partition(&nvram, zip_name) != 0) ret = -1; err_exit: if (nvram.data) free(nvram.data); if (nvram.fd != -1) close(nvram.fd); return ret; } powerpc-utils-1.2.26/src/nvram.h0000664000175000017510000000733612527176005013444 00000000000000/** * @file nvram.h * @brief nvram access utility for powerpc platforms. * * Copyright (c) 2003, 2004 International Business Machines * Common Public License Version 1.0 (see COPYRIGHT) * * @author Nathan Fontenot * @author Michael Strosaker * @author Todd Inglett */ #ifndef _DEV_NVRAM_H_ #define _DEV_NVRAM_H_ #define NVRAM_SIG_SP 0x02 /**< support processor signature */ #define NVRAM_SIG_OF 0x50 /**< open firmware config signature */ #define NVRAM_SIG_FW 0x51 /**< general firmware signature */ #define NVRAM_SIG_HW 0x52 /**< hardware (VPD) signature */ #define NVRAM_SIG_SYS 0x70 /**< system env vars signature */ #define NVRAM_SIG_CFG 0x71 /**< config data signature */ #define NVRAM_SIG_ELOG 0x72 /**< error log signature */ #define NVRAM_SIG_VEND 0x7e /**< vendor defined signature */ #define NVRAM_SIG_FREE 0x7f /**< Free space signature */ #define NVRAM_SIG_OS 0xa0 /**< OS defined signature */ /** * @def printmap(ch) * @brief dertermines if 'ch' is a printable character */ #define printmap(ch) (isgraph(ch) ? (ch) : '.') #define NVRAM_BLOCK_SIZE 16 #define NVRAM_READ_SIZE 512 #define NVRAM_FILENAME1 "/dev/nvram" #define NVRAM_FILENAME2 "/dev/misc/nvram" #define DEFAULT_NVRAM_SZ (1024 * 1024) #define OOPS_PARTITION_SZ 4000 /** * @def MAX_CPUS * @brief maximum number of CPUS for errlog dumps */ #define MAX_CPUS 128 /** * @struct partition_header * @brief nvram partition header data */ struct partition_header { unsigned char signature; /**< partition signature */ unsigned char checksum; /**< partition checksum */ unsigned short length; /**< partition length */ char name[12]; /**< partition name */ }; /* sub-header for error-log partitions */ struct err_log_info { int error_type; unsigned int seq_num; }; /* lnx,oops-log header */ struct oops_log_info { unsigned short version; unsigned short report_length; unsigned long long timestamp; }__attribute__((packed)); /* Internal representation of NVRAM. */ #define MAX_PARTITIONS 50 /** * @struct nvram * @brief internal representation of nvram data */ struct nvram { char *filename; /**< original filename */ int fd; /**< file descriptor */ int nparts; /**< number of partitions */ int nbytes; /**< size of data in bytes. This * cannot be changed * (i.e. hardware size) */ struct partition_header *parts[MAX_PARTITIONS]; /**< partition header pointers * into data */ char *data; /**< nvram contents */ }; /** * @var descs * @brief Array of VPD field names and descriptions */ static struct { char *name; char *desc; } descs[] = { {"PN", "Part Number"}, {"FN", "FRU Number"}, {"EC", "EC Level"}, {"MN", "Manufacture ID"}, {"SN", "Serial Number"}, {"LI", "Load ID"}, {"RL", "ROM Level"}, {"RM", "Alterable ROM Level"}, {"NA", "Network Address"}, {"DD", "Device Driver Level"}, {"DG", "Diagnostic Level"}, {"LL", "Loadable Microcode Level"}, {"VI", "Vendor ID/Device ID"}, {"FU", "Function Number"}, {"SI", "Subsystem Vendor ID/Device ID"}, {"VK", "Platform"}, /**< "RS6K" => VPD is present */ {"TM", "Model"}, /**< IBM specific? */ {"YL", "Location Code"}, /**< IBM specific? */ {"BR", "Brand"}, /**< IBM specific */ {"CI", "CEC ID"}, /**< IBM specific */ {"RD", "Rack ID"}, /**< IBM specific */ {"PA", "Op Panel Installed"}, /**< IBM specific */ {"NN", "Node Name"}, /**< IBM specific */ }; #endif powerpc-utils-1.2.26/src/ppc64_cpu.c0000664000175000017510000006574012542266762014131 00000000000000/** * Copyright (C) 2007 Anton Blanchard IBM Corporation * Common Public License Version 1.0 (see COPYRIGHT) * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WITH_LIBRTAS #include #include "librtas_error.h" #endif #ifdef HAVE_LINUX_PERF_EVENT_H #include #endif #include #define PPC64_CPU_VERSION "1.2" #define SYSFS_CPUDIR "/sys/devices/system/cpu/cpu%d" #define SYSFS_SUBCORES "/sys/devices/system/cpu/subcores_per_core" #define DSCR_DEFAULT_PATH "/sys/devices/system/cpu/dscr_default" #define INTSERV_PATH "/proc/device-tree/cpus/%s/ibm,ppc-interrupt-server#s" #define SYSFS_PATH_MAX 128 #define MAX_NR_CPUS 1024 #define DIAGNOSTICS_RUN_MODE 42 #define CPU_OFFLINE -1 #ifdef HAVE_LINUX_PERF_EVENT_H static unsigned long long cpu_freq[MAX_NR_CPUS]; static int counters[MAX_NR_CPUS]; #ifndef __NR_perf_event_open #define __NR_perf_event_open 319 #endif #endif static int threads_per_cpu = 0; static int cpus_in_system = 0; static int threads_in_system = 0; static int do_info(void); static int test_sysattr(char *attribute, int perms) { char path[SYSFS_PATH_MAX]; int i; for (i = 0; i < threads_in_system; i++) { sprintf(path, SYSFS_CPUDIR"/%s", i, attribute); if (access(path, F_OK)) continue; if (access(path, perms)) return 0; } return 1; } static int sysattr_is_readable(char *attribute) { return test_sysattr(attribute, R_OK); } static int sysattr_is_writeable(char *attribute) { return test_sysattr(attribute, W_OK); } static int get_attribute(char *path, const char *fmt, int *value) { FILE *fp; int rc; rc = access(path, F_OK); if (rc) return -1; fp = fopen(path, "r"); if (!fp) return -1; rc = fscanf(fp, fmt, value); fclose(fp); if (rc == EOF) return -1; return 0; } static int set_attribute(const char *path, const char *fmt, int value) { int fd, rc, len; char *str; fd = open(path, O_WRONLY); if (fd < 0) return -1; len = asprintf(&str, fmt, value); if (len < 0) { rc = -1; goto close; } rc = write(fd, str, len); free(str); if (rc == len) rc = 0; close: close(fd); return rc; } static int cpu_online(int thread) { char path[SYSFS_PATH_MAX]; int rc, online; sprintf(path, SYSFS_CPUDIR"/online", thread); rc = get_attribute(path, "%d", &online); if (rc || !online) return 0; return 1; } static int get_system_attribute(char *attribute, const char *fmt, int *value, int *inconsistent) { char path[SYSFS_PATH_MAX]; int i, rc; int system_attribute = -1; for (i = 0; i < threads_in_system; i++) { int cpu_attribute; if (!cpu_online(i)) continue; sprintf(path, SYSFS_CPUDIR"/%s", i, attribute); rc = get_attribute(path, fmt, &cpu_attribute); if (rc) return rc; if (system_attribute == -1) system_attribute = cpu_attribute; else if (system_attribute != cpu_attribute) { *inconsistent = 1; return -1; } } *value = system_attribute; return 0; } static int set_system_attribute(char *attribute, const char *fmt, int state) { char path[SYSFS_PATH_MAX]; int i, rc; for (i = 0; i < threads_in_system; i++) { sprintf(path, SYSFS_CPUDIR"/%s", i, attribute); rc = set_attribute(path, fmt, state); /* When a CPU is offline some sysfs files are removed from the CPU * directory, for example smt_snooze_delay and dscr. The absence of the * file is not an error, so detect and clear the error when * set_attribute indicates ENOENT. */ if (rc == -1 && errno == ENOENT) rc = errno = 0; if (rc) return rc; } return 0; } static int dscr_default_exists(void) { struct stat sb; if (!stat(DSCR_DEFAULT_PATH, &sb)) return 1; return 0; } /* On newer systems we just set the default_dscr value instead of the cpu * specific dscr value. This is because the dscr value is now thread * specific. */ static int set_dscr(int state) { int rc; if (dscr_default_exists()) { if (access(DSCR_DEFAULT_PATH, W_OK)) { perror("Cannot set default dscr value"); return -2; } rc = set_attribute(DSCR_DEFAULT_PATH, "%x", state); } else { if (!sysattr_is_writeable("dscr")) { perror("Cannot set dscr"); return -2; } rc = set_system_attribute("dscr", "%x", state); } return rc; } static int get_dscr(int *value, int *inconsistent) { int rc; if (dscr_default_exists()) { if (access(DSCR_DEFAULT_PATH, R_OK)) { perror("Cannot retrieve default dscr"); return -2; } rc = get_attribute(DSCR_DEFAULT_PATH, "%x", value); } else { if (!sysattr_is_readable("dscr")) { perror("Cannot retrieve dscr"); return -2; } rc = get_system_attribute("dscr", "%x", value, inconsistent); } return rc; } static int set_smt_snooze_delay(int delay) { if (!sysattr_is_writeable("smt_snooze_delay")) { perror("Cannot set smt snooze delay"); return -2; } return set_system_attribute("smt_snooze_delay", "%d", delay); } static int get_smt_snooze_delay(int *delay, int *inconsistent) { if (!sysattr_is_readable("smt_snooze_delay")) { perror("Cannot retrieve smt snooze delay"); return -2; } return get_system_attribute("smt_snooze_delay", "%d", delay, inconsistent); } static int online_thread(const char *path) { return set_attribute(path, "%d", 1); } static int offline_thread(const char *path) { return set_attribute(path, "%d", 0); } static int is_subcore_capable(void) { return access(SYSFS_SUBCORES, F_OK) == 0; } static int num_subcores(void) { int rc, subcores; rc = get_attribute(SYSFS_SUBCORES, "%d", &subcores); if (rc) return -1; return subcores; } static int get_cpu_info(void) { DIR *d; struct dirent *de; int first_cpu = 1; int rc; int subcores; d = opendir("/proc/device-tree/cpus"); if (!d) return -1; while ((de = readdir(d)) != NULL) { if (!strncmp(de->d_name, "PowerPC", 7)) { if (first_cpu) { struct stat sbuf; char path[128]; sprintf(path, INTSERV_PATH, de->d_name); rc = stat(path, &sbuf); if (!rc) threads_per_cpu = sbuf.st_size / 4; first_cpu = 0; } cpus_in_system++; } } closedir(d); threads_in_system = cpus_in_system * threads_per_cpu; subcores = num_subcores(); if (is_subcore_capable() && subcores > 0) { threads_per_cpu /= subcores; cpus_in_system *= subcores; } return 0; } static int is_smt_capable(void) { struct stat sb; char path[SYSFS_PATH_MAX]; int i; for (i = 0; i < threads_in_system; i++) { sprintf(path, SYSFS_CPUDIR"/smt_snooze_delay", i); if (stat(path, &sb)) continue; return 1; } return 0; } static int get_one_smt_state(int primary_thread) { int thread_state; int smt_state = 0; int i; for (i = 0; i < threads_per_cpu; i++) { thread_state = cpu_online(primary_thread + i); smt_state += thread_state; } return smt_state ? smt_state : -1; } static int get_smt_state(void) { int system_state = -1; int i; if (!sysattr_is_readable("online")) { perror("Cannot retrieve smt state"); return -2; } for (i = 0; i < threads_in_system; i += threads_per_cpu) { int cpu_state; cpu_state = get_one_smt_state(i); if (cpu_state == -1) continue; if (system_state == -1) system_state = cpu_state; else if (system_state != cpu_state) return -1; } return system_state; } static int set_one_smt_state(int thread, int online_threads) { char path[SYSFS_PATH_MAX]; int i, rc = 0; for (i = 0; i < threads_per_cpu; i++) { snprintf(path, SYSFS_PATH_MAX, SYSFS_CPUDIR"/%s", thread + i, "online"); if (i < online_threads) rc = online_thread(path); else rc = offline_thread(path); /* The 'online' sysfs file returns EINVAL if set to the current * setting. As this is not an error, reset rc and errno to avoid * returning failure. */ if (rc == -1 && errno == EINVAL) rc = errno = 0; if (rc) break; } return rc; } static int set_smt_state(int smt_state) { int i, j, rc; int ssd, update_ssd = 1; int inconsistent = 0; int error = 0; if (!sysattr_is_writeable("online")) { perror("Cannot set smt state"); return -1; } rc = get_smt_snooze_delay(&ssd, &inconsistent); if (rc) update_ssd = 0; for (i = 0; i < threads_in_system; i += threads_per_cpu) { /* Online means any thread on this core running, so check all * threads in the core, not just the first. */ for (j = 0; j < threads_per_cpu; j++) { if (!cpu_online(i + j)) continue; rc = set_one_smt_state(i, smt_state); /* Record an error, but do not check result: if we * have failed to set this core, keep trying * subsequent ones. */ if (rc) error = 1; break; } } if (update_ssd) set_smt_snooze_delay(ssd); if (error) return -1; return rc; } static int is_dscr_capable(void) { struct stat sb; char path[SYSFS_PATH_MAX]; int i; if (dscr_default_exists()) return 1; for (i = 0; i < threads_in_system; i++) { sprintf(path, SYSFS_CPUDIR"/dscr", i); if (stat(path, &sb)) continue; return 1; } return 0; } static int do_smt(char *state) { int rc = 0; int smt_state; if (!is_smt_capable()) { fprintf(stderr, "Machine is not SMT capable\n"); return -1; } if (!state) { smt_state = get_smt_state(); if (smt_state == -2) return -1; if (smt_state == 1) printf("SMT is off\n"); else if (smt_state == -1) printf("Inconsistent state: mix of ST and SMT cores\n"); else printf("SMT=%d\n", smt_state); } else { if (!strcmp(state, "on")) smt_state = threads_per_cpu; else if (!strcmp(state, "off")) smt_state = 1; else smt_state = strtol(state, NULL, 0); if ((smt_state <= 0) || (smt_state > threads_per_cpu)) { printf("SMT=%s is not valid\n", state); return -1; } rc = set_smt_state(smt_state); } return rc; } static inline void do_threads_per_core() { printf("Threads per core: %d\n", threads_per_cpu); } static int do_subcores_per_core(char *state) { int rc = 0; int subcore_state = 0; /* Check SMT machine. */ if (!is_smt_capable()) { fprintf(stderr, "Machine is not SMT capable\n"); return -1; } /* Check subcore capable machine/kernel. */ if (!is_subcore_capable()) { fprintf(stderr, "Machine is not subcore capable\n"); return -1; } if (!state) { /* Display current status. */ subcore_state = num_subcores(); if (subcore_state < 0) { fprintf(stderr, "Could not read subcore state.\n"); return -1; } printf("Subcores per core: %d\n", subcore_state); } else { /* Kernel decides what values are valid, so no need to * check here. */ subcore_state = strtol(state, NULL, 0); rc = set_attribute(SYSFS_SUBCORES, "%d", subcore_state); if (rc) { fprintf(stderr, "Failed to set subcore option.\n"); return rc; } printf("Subcores per core set to %d\n", subcore_state); } return rc; } #define PTRACE_DSCR 44 static int do_dscr_pid(int dscr_state, pid_t pid) { int rc; rc = ptrace(PTRACE_ATTACH, pid, NULL, NULL); if (rc) { fprintf(stderr, "Could not attach to process %d to %s the " "DSCR value\n%s\n", pid, (dscr_state ? "set" : "get"), strerror(errno)); return rc; } wait(NULL); if (dscr_state) { rc = ptrace(PTRACE_POKEUSER, pid, PTRACE_DSCR << 3, dscr_state); if (rc) { fprintf(stderr, "Could not set the DSCR value for pid " "%d\n%s\n", pid, strerror(errno)); ptrace(PTRACE_DETACH, pid, NULL, NULL); return rc; } } rc = ptrace(PTRACE_PEEKUSER, pid, PTRACE_DSCR << 3, NULL); if (errno) { fprintf(stderr, "Could not get the DSCR value for pid " "%d\n%s\n", pid, strerror(errno)); rc = -1; } else { printf("DSCR for pid %d is %d\n", pid, rc); } ptrace(PTRACE_DETACH, pid, NULL, NULL); return rc; } static int do_dscr(char *state, pid_t pid) { int rc = 0; int dscr_state = 0; if (!is_dscr_capable()) { fprintf(stderr, "Machine is not DSCR capable\n"); return -1; } if (state) dscr_state = strtol(state, NULL, 0); if (pid != -1) return do_dscr_pid(dscr_state, pid); if (!state) { int dscr, inconsistent = 0; rc = get_dscr(&dscr, &inconsistent); if (rc) { if (inconsistent) printf("Inconsistent DSCR\n"); else printf("Could not retrieve DSCR\n"); } else { printf("DSCR is %d\n", dscr); } } else rc = set_dscr(dscr_state); return rc; } static int do_smt_snooze_delay(char *state) { int rc = 0; if (!is_smt_capable()) { fprintf(stderr, "Machine is not SMT capable\n"); return -1; } if (!state) { int ssd, inconsistent = 0; rc = get_smt_snooze_delay(&ssd, &inconsistent); if (rc) { if (inconsistent) printf("Inconsistent smt_snooze_delay\n"); else printf("Could not retrieve smt_snooze_delay\n"); } else { printf("smt_snooze_delay is %d\n", ssd); } } else { int delay; if (!strcmp(state, "off")) delay = -1; else delay = strtol(state, NULL, 0); rc = set_smt_snooze_delay(delay); } return rc; } #ifdef WITH_LIBRTAS static int do_run_mode(char *run_mode) { char mode[3]; int rc; if (getuid() != 0) { fprintf(stderr, "Cannot %s run mode: Permission denied\n", run_mode ? "set" : "get"); return -1; } if (!run_mode) { rc = rtas_get_sysparm(DIAGNOSTICS_RUN_MODE, 3, mode); if (rc) { if (rc == -3) { printf("Machine does not support diagnostic " "run mode\n"); } else if (is_librtas_error(rc)) { char buf[1024]; librtas_error(rc, &buf[0], 1024); printf("Could not retrieve current diagnostics " "mode,\n%s\n", buf); } else { printf("Could not retrieve current diagnostics " "mode\n"); } } else printf("run-mode=%d\n", mode[2]); } else { short rmode = atoi(run_mode); if (rmode < 0 || rmode > 3) { printf("Invalid run-mode=%d\n", rmode); return -1; } *(short *)mode = htobe16(1); mode[2] = rmode; rc = rtas_set_sysparm(DIAGNOSTICS_RUN_MODE, mode); if (rc) { if (rc == -3) { printf("Machine does not support diagnostic " "run mode\n"); } else if (rc == -9002) { printf("Machine is not authorized to set " "diagnostic run mode\n"); } else if (is_librtas_error(rc)) { char buf[1024]; librtas_error(rc, &buf[0], 1024); printf("Could not set diagnostics mode,\n%s\n", buf); } else { printf("Could not set diagnostics mode\n"); } } } return rc; } #else static int do_run_mode(char *run_mode) { printf("Run mode determination is not supported on this platfom.\n"); return -1; } #endif #ifdef HAVE_LINUX_PERF_EVENT_H static int setup_counters(void) { int i; struct perf_event_attr attr; memset(&attr, 0, sizeof(attr)); attr.type = PERF_TYPE_HARDWARE; attr.config = PERF_COUNT_HW_CPU_CYCLES; attr.disabled = 1; attr.size = sizeof(attr); for (i = 0; i < threads_in_system; i++) { if (!cpu_online(i)) continue; counters[i] = syscall(__NR_perf_event_open, &attr, -1, i, -1, 0); if (counters[i] < 0) { if (errno == ENOSYS) fprintf(stderr, "frequency determination " "not supported with this kernel.\n"); else perror("Could not initialize performance " "counters"); return -1; } } return 0; } static void start_counters(void) { int i; for (i = 0; i < threads_in_system; i++) { if (cpu_freq[i] == CPU_OFFLINE) continue; ioctl(counters[i], PERF_EVENT_IOC_ENABLE); } } static void stop_counters(void) { int i; for (i = 0; i < threads_in_system; i++) { if (cpu_freq[i] == CPU_OFFLINE) continue; ioctl(counters[i], PERF_EVENT_IOC_DISABLE); } } static void read_counters(void) { int i; for (i = 0; i < threads_in_system; i++) { size_t res; if (cpu_freq[i] == CPU_OFFLINE) continue; res = read(counters[i], &cpu_freq[i], sizeof(unsigned long long)); assert(res == sizeof(unsigned long long)); close(counters[i]); } } static void *soak(void *arg) { unsigned int cpu = (long)arg; cpu_set_t cpumask; CPU_ZERO(&cpumask); CPU_SET(cpu, &cpumask); if (sched_setaffinity(0, sizeof(cpumask), &cpumask)) { perror("sched_setaffinity"); exit(1); } while (1) ; /* Do Nothing */ } static char *power_mode(uint64_t mode) { switch (mode) { case 0x0001: return "Dynamic, Favor Performance\n"; case 0x0002: return "None\n"; case 0x0003: return "Static\n"; case 0x00ff: return "Dynamic, Favor Power\n"; default: return "Unknown"; } } static void report_system_power_mode(void) { FILE *f; char line[128]; f = fopen("/proc/ppc64/lparcfg", "r"); if (!f) return; while (fgets(line, 128, f) != NULL) { char *name, *value; uint64_t mode, system_mode, partition_mode; if ((line[0] == '\n') || (!strncmp(&line[0], "lparcfg", 7))) continue; name = &line[0]; value = strchr(line, '='); *value = '\0'; value++; if (strcmp(name, "power_mode_data")) continue; /* The power mode result is defined as * XXXX XXXX XXXX XXXX * XXXX : System Power Mode * XXXX : Partition Power Mode * They mode is the first 4 bytes of the value reported in * the lparcfg file. */ mode = strtoul(value, NULL, 16); system_mode = (mode >> 48) & 0xffff; partition_mode = mode & 0xffff; if (system_mode != partition_mode) { printf("System Power Savings Mode: %s", power_mode(system_mode)); printf("Partition Power Savings Mode: %s", power_mode(partition_mode)); } else { printf("Power Savings Mode: %s", power_mode(system_mode)); } } fclose(f); return; } /* We need an FD per CPU, with a few more for stdin/out/err etc */ static void setrlimit_open_files(void) { struct rlimit old_rlim, new_rlim; int new = threads_in_system + 8; getrlimit(RLIMIT_NOFILE, &old_rlim); if (old_rlim.rlim_cur > new) return; new_rlim.rlim_cur = new; new_rlim.rlim_max = old_rlim.rlim_max; setrlimit(RLIMIT_NOFILE, &new_rlim); } #define freq_calc(cycles, time) (1.0 * (cycles) / (time) / 1000000000ULL) static int do_cpu_frequency(int sleep_time) { int i, rc; unsigned long long min = -1ULL; unsigned long min_cpu = -1UL; unsigned long long max = 0; unsigned long max_cpu = -1UL; unsigned long long sum = 0; unsigned long count = 0; setrlimit_open_files(); memset(cpu_freq, 0, sizeof(cpu_freq)); memset(counters, 0, sizeof(counters)); rc = setup_counters(); if (rc) return rc; /* Start a soak thread on each CPU */ for (i = 0; i < threads_in_system; i++) { pthread_t tid; if (!cpu_online(i)) { cpu_freq[i] = CPU_OFFLINE; continue; } if (pthread_create(&tid, NULL, soak, (void *)(long)i)) { perror("pthread_create"); return -1; } } /* Wait for soak threads to start */ usleep(1000000); start_counters(); /* Count for specified timeout in seconds */ usleep(sleep_time * 1000000); stop_counters(); read_counters(); for (i = 0; i < threads_in_system; i++) { if (cpu_freq[i] == CPU_OFFLINE) continue; /* No result - Couldn't schedule on that cpu */ if (cpu_freq[i] == 0) { printf("WARNING: couldn't run on cpu %d\n", i); continue; } if (cpu_freq[i] < min) { min = cpu_freq[i]; min_cpu = i; } if (cpu_freq[i] > max) { max = cpu_freq[i]; max_cpu = i; } sum += cpu_freq[i]; count++; } report_system_power_mode(); printf("min:\t%.3f GHz (cpu %ld)\n", freq_calc(min, sleep_time), min_cpu); printf("max:\t%.3f GHz (cpu %ld)\n", freq_calc(max, sleep_time), max_cpu); printf("avg:\t%.3f GHz\n\n", freq_calc((sum / count), sleep_time)); return 0; } #else static int do_cpu_frequency(void) { printf("CPU Frequency determination is not supported on this " "platfom.\n"); return EINVAL; } #endif static inline void do_cores_present() { printf("Number of cores present = %d\n", cpus_in_system); } static int set_all_threads_off(int cpu, int smt_state) { int i; char path[SYSFS_PATH_MAX]; int rc = 0; for (i = cpu + smt_state - 1; i >= cpu; i--) { snprintf(path, SYSFS_PATH_MAX, SYSFS_CPUDIR"/%s", i, "online"); rc = offline_thread(path); if (rc == -1) printf("Unable to take cpu%d offline", i); } return rc; } static int set_one_core(int smt_state, int core, int state) { int rc = 0; int cpu = core * threads_per_cpu; if (state) { rc = set_one_smt_state(cpu, smt_state); if (rc == -1) printf("Unable to bring core %d online\n", core); } else { rc = set_all_threads_off(cpu, smt_state); if (rc == -1) printf("Unable to take core %d offline\n", core); } return rc; } static int do_cores_online(char *state) { int smt_state; int *core_state; int cores_now_online = 0; int i; int number_to_have, number_to_change = 0, number_changed = 0; int new_state; if (state) { if (!sysattr_is_writeable("online")) { perror("Cannot set cores online"); return -1; } } else { if (!sysattr_is_readable("online")) { perror("Cannot get online cores"); return -1; } } smt_state = get_smt_state(); if (smt_state == -1) { printf("Bad or inconsistent SMT state: use ppc64_cpu --smt=on|off to set all\n" "cores to have the same number of online threads to continue.\n"); do_info(); return -1; } core_state = malloc(sizeof(int) * cpus_in_system); memset(core_state, 0, sizeof(int) * cpus_in_system); for (i = 0; i < cpus_in_system ; i++) { core_state[i] = cpu_online(i * threads_per_cpu); if (core_state[i]) cores_now_online++; } if (!state) { printf("Number of cores online = %d\n", cores_now_online); return 0; } number_to_have = strtol(state, NULL, 0); if (number_to_have == cores_now_online) return 0; if (number_to_have > cpus_in_system) { printf("Cannot online more cores than are present.\n"); do_cores_present(); return -1; } if (number_to_have > cores_now_online) { number_to_change = number_to_have - cores_now_online; new_state = 1; } else { number_to_change = cores_now_online - number_to_have; new_state = 0; } if (new_state) { for (i = 0; i < cpus_in_system; i++) { if (!core_state[i]) { set_one_core(smt_state, i, new_state); number_changed++; if (number_changed >= number_to_change) break; } } } else { for (i = cpus_in_system - 1; i > 0; i--) { if (core_state[i]) { set_one_core(smt_state, i, new_state); number_changed++; if (number_changed >= number_to_change) break; } } } return 0; } static int do_info(void) { int i, j, thread_num; char online; int subcores = 0; if (is_subcore_capable()) subcores = num_subcores(); for (i = 0; i < cpus_in_system; i++) { if (subcores > 1) { if (i % subcores == 0) printf("Core %3d:\n", i/subcores); printf(" Subcore %3d: ", i); } else { printf("Core %3d: ", i); } for (j = 0; j < threads_per_cpu; j++) { thread_num = i*threads_per_cpu + j; online = cpu_online(thread_num) ? '*' : ' '; printf("%4d%c ", thread_num, online); } printf("\n"); } return 0; } static void usage(void) { printf( "Usage: ppc64_cpu [command] [options]\n" "ppc64_cpu --smt # Get current SMT state\n" "ppc64_cpu --smt={on|off} # Turn SMT on/off\n" "ppc64_cpu --smt=X # Set SMT state to X\n\n" "ppc64_cpu --cores-present # Get the number of cores present\n" "ppc64_cpu --cores-on # Get the number of cores currently online\n" "ppc64_cpu --cores-on=X # Put exactly X cores online\n\n" "ppc64_cpu --dscr # Get current DSCR system setting\n" "ppc64_cpu --dscr= # Change DSCR system setting\n" "ppc64_cpu --dscr [-p ] # Get DSCR setting for process \n" "ppc64_cpu --dscr= [-p ] # Change DSCR setting for process \n\n" "ppc64_cpu --smt-snooze-delay # Get current smt-snooze-delay setting\n" "ppc64_cpu --smt-snooze-delay= # Change smt-snooze-delay setting\n\n" "ppc64_cpu --run-mode # Get current diagnostics run mode\n" "ppc64_cpu --run-mode= # Set current diagnostics run mode\n\n" "ppc64_cpu --frequency [-t