ppc64-diag-2.7.0/0000755000000000000000000000000012642205425012056 5ustar rootrootppc64-diag-2.7.0/common/0000755000000000000000000000000012642205425013346 5ustar rootrootppc64-diag-2.7.0/common/Makefile0000644000000000000000000000057012642205425015010 0ustar rootroot# # Makefile for ppc64-diag/common # include ../rules.mk SRC = platform.c utils.c OBJ = $(SRC:.c=.o) SUBDIRS = tests .PHONY: all clean all: $(OBJ) $(CMD) @$(foreach d, $(SUBDIRS), $(MAKE) -C $d;) %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ install: uninstall: clean: @$(foreach d, $(SUBDIRS), $(MAKE) -C $d clean;) @echo "Cleaning up $(WORK_DIR) files..." @rm -f $(OBJ) ppc64-diag-2.7.0/common/run_tests0000755000000000000000000000154212642205425015324 0ustar rootroot#!/bin/sh COMMON_TEST_DIR=$(dirname $0)/tests all_tests="${COMMON_TEST_DIR}/test*" verbose=0 # Test results function msg_failure() { echo "FAIL: $1" exit 1 } function msg_pass() { if [ $verbose -eq 1 ]; then echo "PASS: $1" fi } # Build the test suite if [ ! -e $COMMON_TEST_DIR ]; then msg_failure "Test cases not available" fi if [ ! -x ${COMMON_TEST_DIR}/spopen ]; then msg_failure "Fatal error, cannot execute tests. Did you make?"; fi while getopts ":vt:" opt; do case "$opt" in v) verbose=1 ;; t) all_tests=$OPTARG ;; esac done # Run the actual tests for common_test in $all_tests; do if [ ! -e $common_test ]; then msg_failure "$common_test doesn't exits" fi source $common_test rc=$? if [[ $rc -ne 0 ]]; then msg_failure "$common_test FAILED with RC $rc" else msg_pass $common_test fi done echo "PASS" exit 0 ppc64-diag-2.7.0/common/tests/0000755000000000000000000000000012642205425014510 5ustar rootrootppc64-diag-2.7.0/common/tests/Makefile0000644000000000000000000000044312642205425016151 0ustar rootroot# # Makefile for common utilities test scripts. # CC = gcc CFLAGS = -g -Wall INCLUDE = -I../ PROGS = spopen all : $(PROGS) spopen : spopen.o ../utils.o $(CC) $(CFLAGS) $(INCLUDE) spopen.o ../utils.o -o spopen %.o:%.c $(CC) $(CFLAGS) $(INCLUDE) -c -o $@ $< clean: rm -f *.o $(PROGS) ppc64-diag-2.7.0/common/tests/spopen.c0000644000000000000000000000132012642205425016154 0ustar rootroot#include #include #include #include #include #include "utils.h" int main(int argc, char *argv[]) { int status; FILE *fp; pid_t cpid; char buff[128] = {}; if (argc < 2) { fprintf(stderr, "Usage : ./spopen " " ...\n"); exit(1); } fp = spopen(argv + 1, &cpid); if (fp == NULL) { fprintf(stderr, "spopen() failed : %s\n", strerror(errno)); exit(1); } while (fgets(buff, 128, fp) != NULL) printf("%s", buff); status = spclose(fp, cpid); if (status == -1) { fprintf(stderr, "Failed in spclose() : %s.\n", strerror(errno)); exit(1); } fprintf(stdout, "Child exited with status : %d.\n", status); exit(0); } ppc64-diag-2.7.0/common/tests/test-spopen-0010000644000000000000000000000075612642205425017222 0ustar rootroot#!/bin/bash #WARNING: DO NOT RUN THIS FILE DIRECTLY # This file expects to be a part of ppc64-diag/common test suite # Run this file with ../run_tests -t test-spopen-001 SPOPEN=$(dirname $0)/tests/spopen CAT=`which cat` function do_cat_test() { local _rc _size=0 tmp_file=$(mktemp /tmp/spopen-test.XXX) $SPOPEN $CAT ${SPOPEN}.c > $tmp_file _size=$(stat -c %s ${SPOPEN}.c) cmp -s --bytes=$_size $tmp_file ${SPOPEN}.c _rc=$? rm $tmp_file return $_rc } do_cat_test rc=$? return $rc ppc64-diag-2.7.0/common/platform.c0000644000000000000000000000314312642205425015337 0ustar rootroot/** * @file platform.c * * Copyright (C) 2014 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * @author Aruna Balakrishnaiah */ #include #include #include "platform.h" #define LENGTH 512 const char *__platform_name[] = { "Unknown", "PowerNV", "PowerKVM pSeries Guest", "PowerVM pSeries LPAR", /* Add new platforms name here */ }; 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, "pSeries (emulated by qemu)")) { rc = PLATFORM_POWERKVM_GUEST; break; } else if (strstr(line, "pSeries")) { rc = PLATFORM_PSERIES_LPAR; /* catch model for PowerNV guest */ continue; } } fclose(fp); return rc; } ppc64-diag-2.7.0/common/platform.h0000644000000000000000000000240012642205425015337 0ustar rootroot/** * Copyright (C) 2014 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #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); static inline const char * __power_platform_name(int platform) { if (platform > PLATFORM_UNKNOWN && platform < PLATFORM_MAX) return __platform_name[platform]; return __platform_name[PLATFORM_UNKNOWN]; } #endif ppc64-diag-2.7.0/common/utils.c0000644000000000000000000001003712642205425014653 0ustar rootroot/* * Copyright (C) 2015 IBM Corporation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include "utils.h" static int process_child(char *argv[], int pipefd[]) { int nullfd; close(pipefd[0]); /* stderr to /dev/null redirection */ nullfd = open("/dev/null", O_WRONLY); if (nullfd == -1) { fprintf(stderr, "%s : %d - failed to open " "\'/dev/null\' for redirection : %s\n", __func__, __LINE__, strerror(errno)); close(pipefd[1]); return -1; } /* redirect stdout to write-end of the pipe */ if (dup2(pipefd[1], STDOUT_FILENO) == -1) { fprintf(stderr, "%s : %d - failed to redirect " "pipe write fd to stdout : %s\n", __func__, __LINE__, strerror(errno)); goto err_out; } if (dup2(nullfd, STDERR_FILENO) == -1) { fprintf(stderr, "%s : %d - failed to redirect " "\'/dev/null\' to stderr : %s\n", __func__, __LINE__, strerror(errno)); goto err_out; } execve(argv[0], argv, NULL); /* some failure in exec */ err_out: close(pipefd[1]); close(nullfd); return -1; } /* * This function mimics popen(3). * * Returns: * NULL, if fork(2), pipe(2) and dup2(3) calls fail * * Note: * fclose(3) function shouldn't be used to close the stream * returned here, since it doesn't wait for the child to exit. */ FILE *spopen(char *argv[], pid_t *ppid) { FILE *fp = NULL; int pipefd[2]; pid_t cpid; if (argv == NULL) return fp; if (access(argv[0], F_OK|X_OK) != 0) { fprintf(stderr, "%s : The command \"%s\" is not executable.\n", __func__, argv[0]); return fp; } if (pipe(pipefd) == -1) { fprintf(stderr, "%s : %d - failed in pipe(), error : %s\n", __func__, __LINE__, strerror(errno)); return NULL; } cpid = fork(); switch (cpid) { case -1: /* Still in parent; Failure in fork() */ fprintf(stderr, "%s : %d - fork() failed, error : %s\n", __func__, __LINE__, strerror(errno)); close(pipefd[0]); close(pipefd[1]); return NULL; case 0: /* Code executed by child */ if (process_child(argv, pipefd) == -1) { fprintf(stderr, "%s : %d - Error occured while " "processing write end of the pipe " "(in child).", __func__, __LINE__); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); default: /* Code executed by parent */ /* store the child pid for pclose() */ *ppid = cpid; close(pipefd[1]); fp = fdopen(pipefd[0], "r"); if (fp == NULL) { fprintf(stderr, "%s : %d - fdopen() error : %s\n", __func__, __LINE__, strerror(errno)); close(pipefd[0]); return NULL; } break; } return fp; } /* * This function closely mimics pclose(3). * Returns : * On success : exit status of the command as returned by waitpid(2), * On failure : -1 if waitpid(2) returns an error. * If it cannot obtain the child status, errno is set to ECHILD. */ int spclose(FILE *stream, pid_t cpid) { int status; pid_t pid; /* * Close the stream, fclose() takes care of closing * the underlying fd. */ if (fclose(stream) == EOF) { fprintf(stderr, "%s : %d - Failed in fclose() : %s\n", __func__, __LINE__, strerror(errno)); return -1; } /* Wait for the child to exit */ do { pid = waitpid(cpid, &status, 0); } while (pid == -1 && errno == EINTR); /* Couldn't obtain child status */ if (status == -1) errno = SIGCHLD; return status; } ppc64-diag-2.7.0/common/utils.h0000644000000000000000000000154312642205425014662 0ustar rootroot/* * Copyright (C) 2015 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef UTILS_H #define UTILS_H FILE *spopen(char **, pid_t *); int spclose(FILE *, pid_t); #endif ppc64-diag-2.7.0/rtas_errd/0000755000000000000000000000000012642205425014043 5ustar rootrootppc64-diag-2.7.0/rtas_errd/Makefile0000644000000000000000000000275412642205425015513 0ustar rootroot# # Makefile for ppc64-diag/rtas_errd # include ../rules.mk CMDS = rtas_errd convert_dt_node_props extract_platdump SCRIPTS = rc.powerfail PRRN_HOTPLUG = prrn_hotplug COMMON_UTILS_OBJ = $(COMMON_DIR)/utils.o RTAS_ERRD_OBJS = rtas_errd.o epow.o dump.o guard.o eeh.o update.o \ files.o config.o diag_support.o ela.o v6ela.o servicelog.o \ signal.o prrn.o hotplug.o RTAS_ERRD_LIBS = -lrtas -lrtasevent -lservicelog DT_NODE_OBJS = convert_dt_node_props.o EXTRACT_PLATDUMP_OBJS = extract_platdump.o config.o EXTRACT_PLATDUMP_LIBS = -lrtas DOXYGEN_CFG = doxygen.config all: $(CMDS) $(SCRIPTS) rtas_errd: $(RTAS_ERRD_OBJS) $(COMMON_UTILS_OBJ) @echo "LD $(WORK_DIR)/$@" $(CC) $(CFLAGS) -o $@ $^ $(RTAS_ERRD_LIBS) convert_dt_node_props: $(DT_NODE_OBJS) @echo "LD $(WORK_DIR)/$@" @$(CC) $(CFLAGS) -o $@ $^ extract_platdump: $(EXTRACT_PLATDUMP_OBJS) @echo "LD $(WORK_DIR)/$@" @$(CC) $(CFLAGS) -o $@ $^ $(EXTRACT_PLATDUMP_LIBS) install: all @$(call install_sbin,$(CMDS),$(DESTDIR)) @$(call install_files,$(SCRIPTS),744,$(DESTDIR)/etc) @$(call install_files,$(PRRN_HOTPLUG),744,$(DESTDIR)/etc/ppc64-diag) uninstall: @$(call uninstall_sbin,$(CMDS),$(DESTDIR)) @$(call uninstall_files,$(SCRIPTS),$(DESTDIR)/etc) @$(call uninstall_files,$(PRRN_HOTPLUG),$(DESTDIR)/etc/ppc64-diag) doc: $(DOXYGEN_CFG) @echo "Creating doxygen docs..." @$(DOXYGEN) $(DOXYGEN_CFG) clean: @echo "Cleaning up $(WORK_DIR) files..." @rm -rf $(CMDS) $(RTAS_ERRD_OBJS) $(DT_NODE_OBJS) \ $(EXTRACT_PLATDUMP_OBJS) doc ppc64-diag-2.7.0/rtas_errd/doxygen.config0000644000000000000000000013425012642205425016714 0ustar rootroot# 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_errd # 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 = doc # 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 = # 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 ppc64-diag-2.7.0/rtas_errd/prrn_hotplug0000644000000000000000000000213412642205425016511 0ustar rootroot#!/bin/bash # Script to hotplug remove and add cpus and memory that was updated # due to a PRRN event. PRRN_LOG=/var/log/prrn_log DRMGR=/usr/sbin/drmgr TMPFILE=`mktemp -p /tmp` DATE=`date` MESSAGE_LOG=/var/log/messages # Default to /var/log/messages, but use /var/log/syslog if that is the system default if [ ! -e /var/log/messages -a -e /var/log/syslog ]; then MESSAGE_LOG=/var/log/syslog fi while read line; do # skip comments case $line in \#*) echo $line >> $TMPFILE continue ;; esac type=`echo $line | cut -f 1 -d ' '` drc=`echo $line | cut -f 2 -d ' '` $DRMGR -c $type -r -q 1 -s 0x$drc >/dev/null 2>&1 if [[ "$?" != "0" ]]; then echo "PRRN Update: Could not update $type at drc index $drc" >> $MESSAGE_LOG echo "$type $drc" >> $TMPFILE continue fi sleep 1 $DRMGR -c $type -a -q 1 -s 0x$drc >/dev/null 2>&1 if [[ "$?" != "0" ]]; then echo "PRRN Update: Could not add $type at drc index $drc after PRRN Event" >> $MESSAGE_LOG echo "$type $drc" >> $TMPFILE fi echo "# $type $drc -- Updated $DATE" >> $TMPFILE sleep 1 done < $PRRN_LOG cp $TMPFILE $PRRN_LOG rm $TMPFILE ppc64-diag-2.7.0/rtas_errd/config.c0000644000000000000000000004463312642205425015466 0ustar rootroot/** * @file config.c * @brief Routines for parsing the ppc64-diag.config file * * Copyright (C) 2004 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #define RTAS_PARAM_AUTO_RESTART 21 /** * @var config_file * @brief default ppc64-diag configuration file */ char *config_file = "/etc/ppc64-diag/ppc64-diag.config"; /** * @var d_cfg * @brief ppc64-diag configuration structure */ struct ppc64_diag_config d_cfg; /** * get_token * @brief return the next token from the provided buffer. * * This routine is modified parser/tokenizer for interpreting the * ppc64-diag config file. * * @param str point at which to began looking for tokens * @param str_end end of token buffer * @param tok buffer to be filled in with the found token * @param line_no reference to line number in the config file * @return pointer to where the tokenizer stopped in 'str' */ static char * get_token(char *str, char *str_end, char *tok, int *line_no) { char *start = NULL; while (str < str_end) { switch (*str) { case '#': /* A '#' denotes the beginning of a comment that * continues to the end of the line ('\n') * character. Skip ahead to the next line and * continue searching. */ while ((str < str_end) && (*str++ != '\n')); (*line_no)++; break; case '\\': /* A '\' denotes a multi-line string. If we haven't * started a string yet simply skip ahead to the next * line and continue searching... */ if (start == NULL) { while ((str < str_end) && (*str++ != '\n')); (*line_no)++; break; } /* ...Otherwise, return the token we have already * started then skip ahead to the next line and * return that point as the end of the search. */ snprintf(tok, str - start + 1, "%s", start); while ((str < str_end) && (*str++ != '\n')); (*line_no)++; return str; break; case ' ': case '\t': /* Whitespace is either is token delimiter if we * have started reading a token, or it is igored. */ if (start == NULL) { str++; break; } snprintf(tok, str - start + 1, "%s", start); return str + 1; break; case '\n': /* Newlines are either token delimiters if we * have started reading a token, or a seperate token * on its own. */ if (start == NULL) { tok[0] = '\n'; tok[1] = '\0'; (*line_no)++; str++; } else { snprintf(tok, str - start + 1, "%s", start); } return str; break; case '{': case '}': case '=': /* All three ('{', '}', and '=') are both token * delimiters if we have started reading a token or * a token on their own. */ if (start == NULL) { snprintf(tok, 2, "%s", str); str++; } else { snprintf(tok, str - start + 1, "%s", start); } return str; break; case '"': /* A quoted string is returned as a single token * containing everything in quotes, or a token * delimiter if we have begun reading in a token. * NOTE, we do not allow quoted strings the span * multiple lines. */ if (start == NULL) { start = str++; while ((str < str_end) && (*str != '"')) { if (*str == '\n') return NULL; else str++; } snprintf(tok, str - start + 1, "%s", start); str++; } else { snprintf(tok, str - start + 1, "%s", start); } return str; break; default: /* By default everything else is part of a token */ if (start == NULL) start = str; str++; break; } } return (char *)EOF; } /** * get_config_string * @brief retrieve a string associated with a configuration entry * * For the purposes of parsing the ppc64-diag config file a string is * considered everything that comes after the '=' character up to * the newline ('\n') character. Strings can span multiple lines * if they end in a '\', but this is handled by get_token() and we * only need to look for the newline character here. * * @param start should point to the '=' following an entry name * @param end end of buffer containing the string * @param buf buffer into which the string is copied * @param line_no reference to the line number in the config file * @return pointer to where we stopped parsing or NULL on failure */ static char * get_config_string(char *start, char *end, char *buf, int *line_no) { char tok[1024]; int offset = 0; /* The first token token should be '=' */ start = get_token(start, end, tok, line_no); if ((start == NULL) || (tok[0] != '=')) return NULL; /* Next token should be the string, this string can be a series * of tokens or one string in quotes. We just get everything up * to the newline. The code looks a bit odd here, but that is so * we can add in spaces between tokens which are ignored by the * tokenizer. */ start = get_token(start, end, tok, line_no); if (start == NULL) return NULL; offset += sprintf(buf, "%s", tok); start = get_token(start, end, tok, line_no); while ((start != NULL) && (tok[0] != '\n')) { offset += sprintf(buf + offset, " %s", tok); start = get_token(start, end, tok, line_no); } return start; } /** * get_config_num * @brief Retrieve a numeric value for a configuration entry * * @param start should point to the '=' following an entry name * @param end end of buffer containing thevalue * @param val int reference into which the value is copied * @param line_no reference to the line number in the config file * @return pointer to where we stopped parsing or NULL on failure */ static char * get_config_num(char *start, char *end, int *val, int *line_no) { char tok[1024]; /* The first token should be '=' */ start = get_token(start, end, tok, line_no); if ((start == NULL) || (tok[0] != '=')) return NULL; /* Next token should be the value */ start = get_token(start, end, tok, line_no); if (start != NULL) *val = ((int)strtol(tok, NULL, 10) > 1 ? (int)strtol(tok, NULL, 10) : 1); return start; } /** * get_restart_policy_value * @brief Retrieve Auto Restart Policy value * * Same as get_config_num(), except we handle 0 and negative * values here. */ static char * get_restart_policy_value(char *start, char *end, int *val, int *line_no) { char tok[1024]; char *next_char; /* The first token should be '=' */ start = get_token(start, end, tok, line_no); if ((start == NULL) || (tok[0] != '=')) return NULL; /* Next token should be the value */ start = get_token(start, end, tok, line_no); if (start != NULL) { *val = (int)strtol(tok, &next_char, 10); if (*next_char != '\0') *val = -1; } return start; } /** * config_restart_policy * @brief Configure the Auto Restart Policy for this machine, if present. * * Users can specify an AutoRestartPolicy=X entry in the ppc64-diag * configuration file. This will read in that 'X' value and set the * corresponding service policy. This is done either by setting the * ibm,os-auto-restart parameter in NVRAM (older systems), or by setting * the partition_auto_restart system parameter (more recent systems). * * @param start place to start loking * @param end pointer to end of 'start' buffer * @param line_no refernece to the current line number * @param update_param if zero, the param will not actually be updated * @returns pointer to current position in the config file, or NULL on failure */ static char * config_restart_policy(char *start, char *end, int *line_no, int update_param) { struct stat sbuf; char *cur; char param[3]; pid_t cpid; /* Pid of child */ int rc; /* Holds return value */ int status; /* exit value of child */ cur = get_restart_policy_value(start, end, &d_cfg.restart_policy, line_no); if (cur == NULL) { d_cfg.log_msg("Parsing error for configuration file " "entry \"AutoRestartPolicy\", " "line %d", line_no); return cur; } /* Validate the restart value */ if (! (d_cfg.restart_policy == 0 || d_cfg.restart_policy == 1)) { d_cfg.log_msg("Invalid parameter (%d) specified for the " "AutoRestartPolicy (line %d) in config file " "(%s), expecting a 0 or a 1. The Auto Restart " "Policy has not been configured", d_cfg.restart_policy, *line_no, config_file); d_cfg.restart_policy = -1; return cur; } if (!update_param) return cur; /* Try to set the system parameter with the ibm,set-sysparm RTAS call */ *(uint16_t *)param = htobe16(1); param[2] = (uint8_t)d_cfg.restart_policy; rc = rtas_set_sysparm(RTAS_PARAM_AUTO_RESTART, param); switch (rc) { case 0: /* success */ d_cfg.log_msg("Configuring the Auto Restart Policy to %d", d_cfg.restart_policy); return cur; case -1: /* hardware error */ d_cfg.log_msg("Hardware error while attempting to set the " "Auto Restart Policy via RTAS; attempting " "to set in NVRAM..."); break; case RTAS_UNKNOWN_OP: /* RTAS call not available */ break; case -3: /* system parameter not supported */ break; case -9002: /* not authorized */ d_cfg.log_msg("Not authorized to set the Auto Restart Policy " "via RTAS; attempting to set in NVRAM..."); break; case -9999: /* parameter error */ d_cfg.log_msg("Parameter error setting the Auto Restart Policy " "via RTAS; attempting to set in NVRAM..."); break; default: d_cfg.log_msg("Unknown error (%d) setting the Auto Restart " "Policy via RTAS; attempting to set in NVRAM...", rc); } /* If the auto_partition_restart system parameter does not * exist, check if the nvram command exists */ if (stat("/usr/sbin/nvram", &sbuf) < 0) { d_cfg.log_msg("Could not configure the Auto Restart Policy " "due to a missing requisite (nvram command)"); d_cfg.restart_policy = -1; return cur; } /* See if the ibm,os-auto-restart config variable is in * nvram on this machine */ cpid = fork(); if (cpid == -1) { d_cfg.log_msg("Fork failed, while collecting ibm,os-auto-restart\n"); d_cfg.restart_policy = -1; return cur; } /* fork */ if (cpid == 0) { /* child */ char *system_arg[3]= {NULL, }; system_arg[0] = "/usr/sbin/nvram"; system_arg[1] = "--print-config=ibm,os-auto-restart"; rc = execv(system_arg[0], system_arg); d_cfg.log_msg("The current system does not support the " "Auto Restart Policy; the AutoRestartPolicy " "configuration entry (line %d) is being skipped", line_no); d_cfg.restart_policy = -1; exit(-2); } else {/* parent */ /* * Use wait to make sure we do not update ibm,os-restart-policy, * before reading ibm,os-auto-restart. */ rc = waitpid(cpid, &status, 0); if (rc == -1) { d_cfg.log_msg("wait failed, while collecting" " ibm,os-auto-restart\n"); d_cfg.restart_policy = -1; return cur; } if ((signed char)WEXITSTATUS(status) == -2) return cur; } cpid = fork(); if (cpid == -1) { d_cfg.log_msg("Fork failed, on updating ibm,os-restart-policy\n"); d_cfg.restart_policy = -1; return cur; } /* fork */ if (cpid == 0) { /* child */ char *system_arg[6]= {NULL,}; char tmp_sys_arg[50]; system_arg[0] = "/usr/sbin/nvram"; system_arg[1] = "-p"; system_arg[2] = "common"; system_arg[3] = "--update-config"; sprintf(tmp_sys_arg, "ibm,os-restart-policy=%d", d_cfg.restart_policy); system_arg[4] = tmp_sys_arg; rc = execv(system_arg[0], system_arg); d_cfg.log_msg("The Auto Restart Policy could not be configured " "due to a failure in running the nvram command", d_cfg.restart_policy); d_cfg.restart_policy = -1; exit(-2); } else { /* parent */ rc = waitpid(cpid, &status, 0); if (rc == -1) { d_cfg.log_msg("wait failed, on updating ibm,os-restart-policy\n"); d_cfg.restart_policy = -1; return cur; } /* Return on EXIT_FAILURE */ if ((signed char)WEXITSTATUS(status) == -2) return cur; } d_cfg.log_msg("Configuring the Auto Restart Policy to %d (in NVRAM)", d_cfg.restart_policy); return cur; } /** * parse_config_entries * @brief Parse the ppc64-diag config file entries * * @param buf buffer containg the ppc64-diag config file contents * @param buf_end pointer to the end of 'buf' * @param update_sysconfig if 0, configuration params (in NVRAM) will not update * @returns 0 on success, -1 on error */ static int parse_config_entries(char *buf, char *buf_end, int update_sysconfig) { char *cur = buf; char tok[1024]; int line_no = 1; int rc = 0; do { cur = get_token(cur, buf_end, tok, &line_no); if (cur == (char *)EOF) break; if (cur == NULL) { d_cfg.log_msg("Parsing error in configuration " "file near line %d", line_no); rc = -1; break; } /* Ignore newlines */ if (tok[0] == '\n') { continue; } /* MinProcessors */ if (strcmp(tok, "MinProcessors") == 0) { cur = get_config_num(cur, buf_end, &d_cfg.min_processors, &line_no); if (cur == NULL) { d_cfg.log_msg("Parsing error for " "configuration file entry " "\"MinProcessors\", line %d", line_no); rc = -1; break; } else { d_cfg.log_msg("Configuring Minimum " "Processors to %d", d_cfg.min_processors); } /* MinEntitledCapacity */ } else if (strcmp(tok, "MinEntitledCapacity") == 0) { cur = get_config_num(cur, buf_end, &d_cfg.min_entitled_capacity, &line_no); if (cur == NULL) { d_cfg.log_msg("Parsing error for " "configuration file entry " "\"MinEntitledCapacity\", " "line %d", line_no); rc = -1; break; } else { d_cfg.log_msg("Configuring Minimum " "Entitled Capacity to %d", d_cfg.min_entitled_capacity); } /* ScanlogDumpPath */ } else if (strcmp(tok, "ScanlogDumpPath") == 0) { int len; cur = get_config_string(cur, buf_end, d_cfg.scanlog_dump_path, &line_no); if (cur == NULL) { d_cfg.log_msg("Parsing error for " "configuration file entry " "\"ScanlogDumpPath\", line %d", line_no); rc = -1; break; } /* We need to ensure the path specified ends in a '/' */ len = strlen(d_cfg.scanlog_dump_path); if (d_cfg.scanlog_dump_path[len-1] != '/') { d_cfg.scanlog_dump_path[len] = '/'; d_cfg.scanlog_dump_path[len + 1] = '\0'; } d_cfg.log_msg("Configuring Scanlog Dump Path to " "\"%s\"", d_cfg.scanlog_dump_path); /* PlaformDumpPath */ } else if (strcmp(tok, "PlatformDumpPath") == 0) { int len; cur = get_config_string(cur, buf_end, d_cfg.platform_dump_path, &line_no); if (cur == NULL) { d_cfg.log_msg("Parsing error for " "configuration file entry " "\"PlatformDumpPath\", line %d", line_no); rc = -1; break; } /* We need to ensure the path specified ends in a '/' */ len = strlen(d_cfg.platform_dump_path); if (d_cfg.platform_dump_path[len-1] != '/') { d_cfg.platform_dump_path[len] = '/'; d_cfg.platform_dump_path[len + 1] = '\0'; } d_cfg.log_msg("Configuring Platform Dump Path to " "\"%s\"", d_cfg.platform_dump_path); /* AutoRestartPolicy */ } else if (strcmp(tok, "AutoRestartPolicy") == 0) { cur = config_restart_policy(cur, buf_end, &line_no, update_sysconfig); if (cur == NULL) { rc = -1; break; } } else { d_cfg.log_msg("Configuration error: \"%s\", line %d, " "is not a valid configuration name", tok, line_no); rc = -1; break; } } while ((cur != NULL) && (cur < buf_end)); return rc; } /** * init_d_cfg * @brief initialize the ppc64-diag config structure */ static void init_d_cfg(void (*log_msg)(char *, ...)) { d_cfg.min_processors = 1; d_cfg.min_entitled_capacity = 5; strcpy(d_cfg.scanlog_dump_path, "/var/log/"); strcpy(d_cfg.platform_dump_path, "/var/log/dump/"); d_cfg.restart_policy = -1; d_cfg.log_msg = log_msg; }; /** * diag_cfg * @brief read config components from ppc64-diag config file * * The config file is in the format of variable=data. Comments * in the file are lines beginning with '#' or everything after a '#' * character in a line. * * @param update_sysconfig if 0, NVRAM will not be updated */ int diag_cfg(int update_sysconfig, void (*log_msg)(char *, ...)) { struct stat cfg_sbuf; char *cfg_mmap = NULL; char *cur = NULL, *end; int cfg_fd; /* initialize the configuration variables */ init_d_cfg(log_msg); /* open and map the configuration file */ if ((cfg_fd = open(config_file, O_RDONLY)) < 0) { d_cfg.log_msg("Could not open the ppc64-diag configuration " "file \"%s\", %s", config_file, strerror(errno)); return 0; } if ((fstat(cfg_fd, &cfg_sbuf)) < 0) { d_cfg.log_msg("Could not get status of the ppc64-diag " "configuration file \"%s\", %s. No configuration " "data has been read, using default ppc64-diag " "settings", config_file, strerror(errno)); close(cfg_fd); return 0; } /* If this is a zero-length file, do nothing */ if (cfg_sbuf.st_size == 0) { close(cfg_fd); return 0; } if ((cfg_mmap = mmap(0, cfg_sbuf.st_size, PROT_READ, MAP_PRIVATE, cfg_fd, 0)) == (char *)-1) { d_cfg.log_msg("Could not map ppc64-diag configuration file " "\"%s\", %s. No configuration data has been " "read, using default ppc64-diag settings", config_file, strerror(errno)); close(cfg_fd); return 0; } cur = cfg_mmap; end = cfg_mmap + cfg_sbuf.st_size; if (parse_config_entries(cur, end, update_sysconfig)) { d_cfg.log_msg("Due to an error parsing the ppc64-diag " "configuration file, The default configuration " "settings will be used"); init_d_cfg(log_msg); } munmap(cfg_mmap, cfg_sbuf.st_size); close(cfg_fd); return 0; } ppc64-diag-2.7.0/rtas_errd/config.h0000644000000000000000000000263312642205425015465 0ustar rootroot/** * @file config.h * @brief Header for ppc64-diag config file * * Copyright (C) 2004 IBM Corporation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _CONFIG_H #define _CONFIG_H extern char *config_file; /** * struct ppc64_diag_config * @brief structure to store ppc64-diag configuration variables */ struct ppc64_diag_config { unsigned int flags; int min_processors; int min_entitled_capacity; char scanlog_dump_path[1024]; char platform_dump_path[1024]; int restart_policy; void (*log_msg)(char *, ...); }; #define RE_CFG_RECEIVED_SIGHUP 0x00000001 #define RE_CFG_RECFG_SAFE 0x00000002 extern struct ppc64_diag_config d_cfg; /* config.c */ int diag_cfg(int, void (*log_msg)(char *, ...)); #endif /* _CONFIG_H */ ppc64-diag-2.7.0/rtas_errd/convert_dt_node_props.c0000644000000000000000000003262212642205425020613 0ustar rootroot/** * @file convert_dt_node_props.c * * Copyright (C) 2005 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include "platform.c" #define MAX_IRQ_SERVERS_PER_CPU 16 static struct option long_options[] = { {"context", required_argument, NULL, 'c'}, {"from", required_argument, NULL, 'f'}, {"to", required_argument, NULL, 't'}, {"help", no_argument, NULL, 'h'}, {0,0,0,0} }; int cpu_interruptserver_to_drcindex(uint32_t, uint32_t *); int cpu_drcindex_to_drcname(uint32_t, char *, int); int cpu_drcindex_to_interruptserver(uint32_t, uint32_t *, int); int cpu_drcname_to_drcindex(char *, uint32_t *); void print_usage(char *command) { printf ("Usage: %s --context --from --to \n" "\t--context: currently, must be cpu\n" "\t--from and --to: allowed values for and :\n" "\t\tinterrupt-server\n\t\tdrc-index\n\t\tdrc-name\n" "\tif is a drc-index or interrupt-server, it can be\n" "\tspecified in decimal, hex (with a leading 0x), or octal\n" "\t(with a leading 0); if it is a drc-name, it should be\n" "\tspecified as a string in double quotes\n\n", command); return; } /** * mem_drcindex_to_drcname * @brief converts drcindex of mem type to drcname * * @param drc_idx - drc index whose drc name is to be found. * @param drc_name - buffer for drc_name * @param buf_size - size of buffer. */ static int mem_drcindex_to_drcname(uint32_t drc_idx, char *drc_name, int buf_size) { int fd, offset=0, found=0; uint32_t index; uint8_t ch; if ((fd = open("/proc/device-tree/ibm,drc-indexes", O_RDONLY)) < 0) { fprintf(stderr, "error opening /proc/device-tree/" "ibm,drc-indexes"); return 0; } /* skip the first one; it indicates how many are in the file */ read(fd, &index, 4); while ((read(fd, &index, 4)) != 0) { if (be32toh(index) == drc_idx) { found = 1; break; } offset++; } close(fd); if (found) { if ((fd = open("/proc/device-tree/ibm,drc-names", O_RDONLY)) < 0) { fprintf(stderr, "error opening /proc/device-tree/" "ibm,drc-names"); return 0; } /* skip the first one; it indicates how many are in the file */ read(fd, &index, 4); while (offset > 0) { /* skip to (and one past) the next null char */ do { if ((read(fd, &ch, 1)) != 1) { close(fd); return 0; } } while (ch != 0); offset--; } /* copy the drc-name at the current location to the buffer */ while ((read(fd, &ch, 1)) == 1) { if (offset+1 == buf_size) { drc_name[offset] = '\0'; break; } drc_name[offset++] = ch; if (ch == 0) break; } } close(fd); return found; } int main(int argc, char *argv[]) { int option_index, rc, i; int platform = 0; char *context=NULL, *from=NULL, *to=NULL; uint32_t interruptserver, drcindex; unsigned long drc_tmp_idx; uint32_t intservs_array[MAX_IRQ_SERVERS_PER_CPU]; char drcname[20]; platform = get_platform(); switch (platform) { case PLATFORM_UNKNOWN: case PLATFORM_POWERNV: fprintf(stderr, "%s: is not supported on the %s platform\n", argv[0], __power_platform_name(platform)); return -1; } for (;;) { option_index = 0; rc = getopt_long(argc, argv, "hc:f:t:", long_options, &option_index); if (rc == -1) break; switch (rc) { case 'h': print_usage(argv[0]); return 0; case 'c': /* context */ context = optarg; break; case 'f': /* from */ from = optarg; break; case 't': /* to */ to = optarg; break; case '?': print_usage(argv[0]); return -1; break; default: printf("huh?\n"); break; } } if (!context) { fprintf(stderr, "--context not specified\n"); return 1; } if (!from) { fprintf(stderr, "--from not specified\n"); return 2; } if (!to) { fprintf(stderr, "--to not specified\n"); return 3; } /* * In the cpu context, we can convert between drc name, drc index, * and interrupt server (AKA logical CPU ID). */ if (!strcmp(context, "cpu")) { if (!strcmp(from, "interrupt-server")) { interruptserver = strtol(argv[argc-1], NULL, 0); if (!strcmp(to, "drc-index")) { if (!cpu_interruptserver_to_drcindex( interruptserver, &drcindex)) { fprintf(stderr, "could not find the " "drc-index corresponding to " "interrupt-server 0x%08x\n", interruptserver); return 4; } printf("0x%08x\n", drcindex); } else if (!strcmp(to, "drc-name")) { if (!cpu_interruptserver_to_drcindex( interruptserver, &drcindex)) { fprintf(stderr, "could not find the " "drc-index corresponding to " "interrupt-server 0x%08x\n", interruptserver); return 4; } if (!cpu_drcindex_to_drcname(drcindex, drcname, 20)) { fprintf(stderr, "could not find the " "drc-name corresponding to " "drc-index 0x%08x\n", drcindex); return 4; } printf("%s\n", drcname); } else { fprintf(stderr, "invalid --to flag: %s\n", to); return 3; } } else if (!strcmp(from, "drc-index")) { drcindex = strtol(argv[argc-1], NULL, 0); if (!strcmp(to, "drc-name")) { if (!cpu_drcindex_to_drcname(drcindex, drcname, 20)) { fprintf(stderr, "could not find the " "drc-name corresponding to " "drc-index 0x%08x\n", drcindex); return 4; } printf("%s\n", drcname); } else if (!strcmp(to, "interrupt-server")) { rc = cpu_drcindex_to_interruptserver(drcindex, intservs_array, MAX_IRQ_SERVERS_PER_CPU); if (!rc) { fprintf(stderr, "could not find the " "interrupt-server corresponding" " to drc-index 0x%08x\n", drcindex); return 4; } if (rc > MAX_IRQ_SERVERS_PER_CPU) fprintf(stderr, "warning: only the " "first %d servers in the list " "of %d were returned; increase " "MAX_IRQ_SERVERS_PER_CPU to " "retrieve the entire list\n", MAX_IRQ_SERVERS_PER_CPU, rc); i = 0; while (i < rc) printf("0x%08x\n", intservs_array[i++]); } else { fprintf(stderr, "invalid --to flag: %s\n", to); return 3; } } else if (!strcmp(from, "drc-name")) { strncpy(drcname, argv[argc-1], 20); if (!strcmp(to, "drc-index")) { if (!cpu_drcname_to_drcindex(drcname, &drcindex)) { fprintf(stderr, "could not find the " "drc-index corresponding to " "drc-name %s\n", drcname); return 4; } printf("0x%08x\n", drcindex); } else if (!strcmp(to, "interrupt-server")) { if (!cpu_drcname_to_drcindex(drcname, &drcindex)) { fprintf(stderr, "could not find the " "drc-index corresponding to " "drc-name %s\n", drcname); return 4; } rc = cpu_drcindex_to_interruptserver(drcindex, intservs_array, MAX_IRQ_SERVERS_PER_CPU); if (!rc) { fprintf(stderr, "could not find the " "interrupt-server corresponding" " to drc-index 0x%08x\n", drcindex); return 4; } if (rc > MAX_IRQ_SERVERS_PER_CPU) fprintf(stderr, "warning: only the " "first %d servers in the list " "of %d were returned; increase " "MAX_IRQ_SERVERS_PER_CPU to " "retrieve the entire list\n", MAX_IRQ_SERVERS_PER_CPU, rc); i = 0; while (i < rc) printf("0x%08x\n", intservs_array[i++]); } else { fprintf(stderr, "invalid --to flag: %s\n", to); return 3; } } else { fprintf(stderr, "invalid --from flag: %s\n", from); return 2; } } else if (!strcmp(context, "mem")) { if (!strcmp(from, "drc-index")) { drc_tmp_idx = strtoul(argv[argc-1], NULL, 0); if (!strcmp(to, "drc-name")) { if (!mem_drcindex_to_drcname(drc_tmp_idx, drcname, 20)) { fprintf(stderr, "could not find the " "drc-name corresponding to " "drc-index 0x%08x\n", drcindex); return 4; } printf("%s\n", drcname); } } else { fprintf(stderr, "invalid --to flag: %s\n", to); return 3; } } else { fprintf(stderr, "invalid --context flag: %s\n", context); return 1; } return 0; } int cpu_interruptserver_to_drcindex(uint32_t int_serv, uint32_t *drc_idx) { DIR *dir; struct dirent *entry; int found=0, fd; char buffer[1024]; uint32_t temp; dir = opendir("/proc/device-tree/cpus"); while (!found && (entry = readdir(dir)) != NULL) { if (!strncmp(entry->d_name, "PowerPC,POWER", 13)) { snprintf(buffer, 1024, "/proc/device-tree/cpus/%s/" "ibm,ppc-interrupt-server#s", entry->d_name); if ((fd = open(buffer, O_RDONLY)) < 0) { fprintf(stderr, "error opening %s\n", buffer); goto cleanup; } while ((read(fd, &temp, 4)) != 0) { if (be32toh(temp) == int_serv) { close(fd); snprintf(buffer, 1024, "/proc/device-" "tree/cpus/%s/ibm,my-drc-index", entry->d_name); if ((fd = open(buffer, O_RDONLY)) < 0) { fprintf(stderr, "error opening" " %s\n", buffer); goto cleanup; } if ((read(fd, &temp, 4)) == 4) { *drc_idx = be32toh(temp); found = 1; } /* if read */ break; } /* if be32toh */ } /* while */ close(fd); } } /* readdir */ cleanup: closedir(dir); return found; } int cpu_drcindex_to_drcname(uint32_t drc_idx, char *drc_name, int buf_size) { int fd, offset=0, found=0; uint32_t index; uint8_t ch; if ((fd = open("/proc/device-tree/cpus/ibm,drc-indexes", O_RDONLY)) < 0) { fprintf(stderr, "error opening /proc/device-tree/cpus/" "ibm,drc-indexes"); return 0; } /* skip the first one; it indicates how many are in the file */ read(fd, &index, 4); while ((read(fd, &index, 4)) != 0) { if (be32toh(index) == drc_idx) { found = 1; break; } offset++; } close(fd); if (found) { if ((fd = open("/proc/device-tree/cpus/ibm,drc-names", O_RDONLY)) < 0) { fprintf(stderr, "error opening /proc/device-tree/cpus/" "ibm,drc-names"); return 0; } /* skip the first one; it indicates how many are in the file */ read(fd, &index, 4); while (offset > 0) { /* skip to (and one past) the next null char */ do { if ((read(fd, &ch, 1)) != 1) { close(fd); return 0; } } while (ch != 0); offset--; } /* copy the drc-name at the current location to the buffer */ while ((read(fd, &ch, 1)) == 1) { if (offset+1 == buf_size) { drc_name[offset] = '\0'; break; } drc_name[offset++] = ch; if (ch == 0) break; } } close(fd); return found; } /* returns # of interrupt-server numbers found, rather than a boolean value */ int cpu_drcindex_to_interruptserver(uint32_t drc_idx, uint32_t *int_servs, int array_elements) { DIR *dir; struct dirent *entry; int intr_fd, drc_fd, found=0; char buffer[1024]; uint32_t temp; dir = opendir("/proc/device-tree/cpus"); if (!dir) return 0; while (!found && (entry = readdir(dir)) != NULL) { if (!strncmp(entry->d_name, "PowerPC,POWER", 13)) { snprintf(buffer, 1024, "/proc/device-tree/cpus/%s/" "ibm,my-drc-index", entry->d_name); if ((drc_fd = open(buffer, O_RDONLY)) < 0) { fprintf(stderr, "error opening %s\n", buffer); closedir(dir); return 0; } while ((read(drc_fd, &temp, 4)) != 0) { if (be32toh(temp) == drc_idx) { snprintf(buffer, 1024, "/proc/device-" "tree/cpus/%s/" "ibm,ppc-interrupt-server#s", entry->d_name); if ((intr_fd = open(buffer, O_RDONLY)) < 0) { fprintf(stderr, "error opening" " %s\n", buffer); closedir(dir); return 0; } while (found < array_elements && (read(intr_fd, &temp, 4)) == 4) int_servs[found++] = temp; close(intr_fd); break; } } close(drc_fd); } } closedir(dir); return found; } int cpu_drcname_to_drcindex(char *drc_name, uint32_t *drc_idx) { int fd, offset=0, found=0, i, rc; uint32_t index; uint8_t ch; char buffer[64]; if ((fd = open("/proc/device-tree/cpus/ibm,drc-names", O_RDONLY)) < 0) { fprintf(stderr, "error opening /proc/device-tree/cpus/" "ibm,drc-names"); return 0; } /* skip the first one; it indicates how many are in the file */ read(fd, &index, 4); do { i = 0; while ((rc = read(fd, &ch, 1)) == 1) { buffer[i++] = ch; if (ch == 0) break; } if (!strcmp(buffer, drc_name)) { found = 1; break; } offset++; } while (rc); close(fd); if (found) { if ((fd = open("/proc/device-tree/cpus/ibm,drc-indexes", O_RDONLY)) < 0) { fprintf(stderr, "error opening /proc/device-tree/cpus/" "ibm,drc-indexes"); return 0; } /* * skip the first one (indicating the number of entries) * + offset number of indices */ if (lseek(fd, (1 + offset) * 4, SEEK_SET) != (1 + offset ) * 4) { close(fd); return 0; } if ((read(fd, &index, 4)) == 4) *drc_idx = be32toh(index); else found = 0; close(fd); } return found; } ppc64-diag-2.7.0/rtas_errd/dchrp.h0000644000000000000000000002215412642205425015320 0ustar rootroot/** * @file dchrp.h * * Copyright (C) 2005 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _H_DCHRP #define _H_DCHRP /* * Error log identifiers that are built as follows: * * bit number: * 3322222222221111111111 * 10987654321098765432109876543210 * -------------------------------- * 0000 * ---- * | -------- * | | * | | -------- * | | | -------- * | | | | * | | | if cpu, mem, post or io format * | | | extended log byte 12 * | | | if epow format * | | | extended log byte 15 * | | | if sp format * | | | extended log byte 16 * | | | * | | if mem, post or io format * | | extended log byte 13 * | | if sp format * | | extended log byte 17 * | | if epow format * | | extended log byte 16 * | | * | if sp format * | extended log byte 18 * | if epow format * | extended log byte 17 * | * extended log byte 2, bits 4:7 * * * and each ID is labeled xxxByybz where xxx= format,yy=byte #,z=bit # * and Byybz is repeated as often as necessary * */ #define CPUB12b0 0x01000080 #define CPUB12b1 0x01000040 #define CPUB12b2 0x01000020 #define CPUB12b3 0x01000010 #define CPUB12b4 0x01000008 #define CPUB12b5 0x01000004 #define CPUB12b6 0x01000002 #define CPUB12b7 0x01000001 #define CPUALLZERO 0x01000000 #define MEMB12b0 0x02000080 #define MEMB12b1 0x02000040 #define MEMB12b2 0x02000020 #define MEMB12b3 0x02000010 #define MEMB12b4 0x02000008 #define MEMB12b4B13b3 0x02001008 #define MEMB12b5 0x02000004 #define MEMB12b6 0x02000002 #define MEMB12b7 0x02000001 #define MEMB13b0 0x02008000 #define MEMB13b1 0x02004000 #define MEMB13b2 0x02002000 #define MEMB13b3 0x02001000 #define MEMB13b4 0x02000800 #define MEMALLZERO 0x02000000 #define IOB12b0 0x03000080 #define IOB12b1 0x03000040 #define IOB12b2 0x03000020 #define IOB12b3 0x03000010 #define IOB12b3B13b2 0x03002010 #define IOB12b4 0x03000008 #define IOB12b5 0x03000004 #define IOB12b6 0x03000002 #define IOB12b7 0x03000001 #define IOB12b5B13b0 0x03008004 #define IOB12b6B13b0 0x03008002 #define IOB12b7B13b0 0x03008001 #define IOB12b5B13b1 0x03004004 #define IOB12b6B13b1 0x03004002 #define IOB12b7B13b1 0x03004001 #define IOB12b5B13b2 0x03002004 #define IOB12b6B13b2 0x03002002 #define IOB12b7B13b2 0x03002001 #define IOB12b6B13b3 0x03001002 #define IOB13b4 0x03000800 #define IOB13b5 0x03000400 #define IOB13b6 0x03000200 #define IOB13b7 0x03000100 #define IOALLZERO 0x03000000 #define POSTALLZERO 0x04000000 #define POSTB12b0 0x04000080 #define POSTB12b1 0x04000040 #define POSTB12b2 0x04000020 #define POSTB12b3 0x04000010 #define POSTB12b4 0x04000008 #define POSTB12b5 0x04000004 #define POSTB12b6 0x04000002 #define POSTB12b7 0x04000001 #define POSTB13b0 0x04008000 #define POSTB13b1 0x04004000 #define POSTB13b2 0x04002000 #define POSTB13b3 0x04001000 #define POSTB13b4 0x04000800 #define POSTB13b5 0x04000400 #define POSTB13b7 0x04000100 #define EPOWB1501 0x05000001 #define EPOWB1501B16b2b4 0x05002801 #define EPOWB1502 0x05000002 #define EPOWB1502B16b4 0x05000802 #define EPOWB1503 0x05000003 #define EPOWB1503B16b23 0x05003003 #define EPOWB1503B16b3 0x05001003 #define EPOWB1504 0x05000004 #define EPOWB1505 0x05000005 #define EPOWB1505B16b1B17b1 0x05404005 #define EPOWB1505B16b1B17b2 0x05204005 #define EPOWB1505B16b1B17b3 0x05104005 #define EPOWB1502B16b4B17b2 0x05200802 #define EPOWB1502B16b1b4B17b2 0x05204802 #define EPOWB1507 0x05000007 #define SPB16b0 0x0D000080 #define SPB16b1 0x0D000040 #define SPB16b2 0x0D000020 #define SPB16b3 0x0D000010 #define SPB16b4 0x0D000008 #define SPB16b5 0x0D000004 #define SPB16b6 0x0D000002 #define SPB16b7 0x0D000001 #define SPB17b0 0x0D008000 #define SPB17b1 0x0D004000 #define SPB17b2 0x0D002000 #define SPB17b3 0x0D001000 #define SPB17b4 0x0D000800 #define SPB17b5 0x0D000400 #define SPB17b6 0x0D000200 #define SPB17b7 0x0D000100 #define SPB18b0 0x0D800000 #define SPB18b1 0x0D400000 #define SPB18b2 0x0D200000 #define SPB18b3 0x0D100000 #define SPB18b4 0x0D080000 #define SPB18b5 0x0D040000 #define SPB18b6 0x0D020000 #define SPB18b7 0x0D010000 #define EPOWLOGB16b0 0x05008000 #define LOGB16b4 0x00000800 #define EPOWLOG 0x05000000 #define SPLOG 0x0D000000 /* * Bits analyzed in Version 2 EPOW logs. */ #define EPOWB16b0 0x00008000 #define EPOWB16b1 0x00004000 #define EPOWB16b2 0x00002000 #define EPOWB16b3 0x00001000 #define EPOWB16b2b3 0x00003000 #define EPOWB16b4 0x00000800 #define EPOWB17b0 0x00800000 #define EPOWB17b1 0x00400000 #define EPOWB17b2 0x00200000 #define EPOWB17b3 0x00100000 #define EPOWB17b4 0x00080000 /* * Extened EPOW codes, found after the location codes. The sensor nibble * is ignored. */ #define XEPOW1n11 0x1011 #define XEPOW1n64 0x1064 #define XEPOW2n32 0x2032 #define XEPOW2n52 0x2052 #define XEPOW3n21 0x3021 #define XEPOW3n73 0x3073 #define IGNORE_SENSOR_MASK 0xF0FF /* * PCI EPOW Register values for bits 13:15 */ #define PCIEPOW111 0x00070000 #define PCIEPOW100 0x00040000 #define PCIEPOW011 0x00030000 #define PCIEPOW010 0x00020000 #define PCIEPOW001 0x00010000 #define PCIEPOWMASK 0x00070000 #define CRITHI 13 #define CRITLO 9 #define WARNHI 12 #define WARNLO 10 #define NORMAL 11 #define GS_SUCCESS 0 #define THERM 3 #define POWER 9004 #define VOLT 9002 #define FAN 9001 /* * Offsets into the chrp error log */ #define I_EXTENDED 8 /* index to extended error log */ #define I_BYTE0 0 + I_EXTENDED /* contains predicative error bit */ #define I_BYTE1 1 + I_EXTENDED /* has platform specific error bit */ #define I_FORMAT 2 + I_EXTENDED /* to log format indicator */ #define I_BYTE3 3 + I_EXTENDED /* has modifier bits */ #define I_BYTE12 12+ I_EXTENDED /* to bytes describing error, where */ #define I_BYTE13 13+ I_EXTENDED /* most formats use bytes 12 & 13 */ #define I_BYTE15 15+ I_EXTENDED /* for epow errors */ #define I_BYTE16 16+ I_EXTENDED /* for sp errors */ #define I_BYTE17 17+ I_EXTENDED /* for sp errors */ #define I_BYTE18 18+ I_EXTENDED /* for sp errors */ #define I_BYTE19 19+ I_EXTENDED /* for sp errors */ #define I_BYTE24 24+ I_EXTENDED /* for repair pending bit */ #define I_BYTE28 28+ I_EXTENDED /* for sp errors */ #define I_CPU 13+ I_EXTENDED /* to for physical cpu number */ #define I_POSTCODE 26+ I_EXTENDED /* to post error code */ #define I_FWREV 30+ I_EXTENDED /* to firmware revision level */ #define I_IBM 40+ I_EXTENDED /* to IBM id for location codes */ #define I_TOKEN 20+I_EXTENDED #define I_INDEX 24+I_EXTENDED #define I_STATUS 32+I_EXTENDED #define IGNORE_SENSOR_MASK 0xF0FF /* for extended epow, a 2 byte value */ #define SENSOR_MASK 0x0F00 #define EXT_EPOW_REG_ID 0x3031 /* ascii for 01 */ #define SRC_REG_ID_02 0x3032 /* Ascii for 02 */ #define PCI_EPOW_REG_ID 0x3033 #define SRC_REG_ID_04 0x3034 /* Ascii for 04 */ /* Structure to describe i/o device from i/o detected chrp log */ struct device_ela { int status; /* 0=no data;1=bus only;2=device ok */ char bus; char devfunc; short deviceid; short vendorid; char revisionid; char slot; char name[NAMESIZE]; char busname[NAMESIZE]; char loc[LOCSIZE]; short led; }; #define DEVICE_NONE 0 #define DEVICE_BUS 1 #define DEVICE_OK 2 #define FIRST_LOC 1 /* mode for first location code */ #define NEXT_LOC 2 /* mode for next location code */ #define FIRST_REG 1 /* mode for first register data */ #define NEXT_REG 2 /* mode for next register data */ #define LOC_HIDE_CHAR '>' /* special meaning in location code buffer */ /* Return codes from get_cpu_frus */ #define RC_INVALID 0 #define RC_PLANAR 1 #define RC_PLANAR_CPU 2 #define RC_PLANAR_2CPU 3 #define MAXREFCODES 5 #define REFCODE_REASON_CUST 0x880 /* * The following name is a flag for the diag controller to format * the error description into a "special" SRN, i.e. containing refcodes */ #define REFCODE_FNAME "REF-CODE" #define MAX_MENUGOAL_SIZE 2000 #endif ppc64-diag-2.7.0/rtas_errd/dchrp_frus.h0000644000000000000000000013001212642205425016350 0ustar rootroot/** * @file dchrp_frus.h * * Copyright (C) 2005, 2008 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _H_DCHRP_FRUS #define _H_DCHRP_FRUS #include "ela_msg.h" /* * In the following #defines, x is the probability (confidence) that this * callout represents the actual failure */ #define FRU_MEMORY_CONTROLLER(x) { x, "", " ", 1} #define FRU_PROCESSOR(x) { x, "procx", " ", 127} #define FRU_L2CACHE(x) { x, "L2Cache0", " ", 33} #define FRU_MISSING_L2(x) { x, "L2Cache0", " ", 33} #define FRU_HOST_BRIDGE(x) { x, "", " ", 2} #define FRU_SYSTEM_BUS_CONNECTOR(x) { x, "", " ", 192} #define FRU_MEMORY_MODULE(x) { x, "Memory module", " ", 4} #define FRU_MEMORY_CARD(x) { x, "", " ", 5} #define FRU_MEZZANINE_BUS(x) { x, "", " ", 7} #define FRU_PCI_DEVICE(x) { x, "", " ", 3} #define FRU_PCI_BUS(x) { x, "", " ", 192} #define FRU_ISA_DEVICE(x) { x, "", " ", 8} #define FRU_ISA_BRIDGE(x) { x, "", " ", 9} #define FRU_ISA_BUS(x) { x, "", " ", 10} #define FRU_MEZZANINE_BUS_ARBITER(x) { x, "", " ", 11} #define FRU_SERVICE_PROCESSOR(x) { x, "", " ", 12} #define FRU_SP_SYSTEM_INTERFACE(x) { x, "", " ", 13} #define FRU_SP_PRIMARY_BUS(x) { x, "", " ", 14} #define FRU_SP_SECONDARY_BUS(x) { x, "", " ", 15} #define FRU_VPD_MODULE(x) { x, "", " ", 16} #define FRU_POWER_CONTROLLER(x) { x, "", " ", 18} #define FRU_FAN_SENSOR(x) { x, "Fan Sensor", " ", 19} #define FRU_THERMAL_SENSOR(x) { x, "Sensor", " ", 20} #define FRU_VOLTAGE_SENSOR(x) { x, "Sensor", " ", 21} #define FRU_POWER_SENSOR(x) { x, "sensor", " ", 179} #define FRU_SERIAL_PORT_CONTROLLER(x) { x, "", " ", 22} #define FRU_NVRAM(x) { x, "", " ", 23} #define FRU_RTC_TOD(x) { x, "", " ", 24} #define FRU_JTAG(x) { x, "", " ", 25} #define FRU_SOFTWARE(x) { x, "", " ", 26} #define FRU_HARDWARE(x) { x, "", " ", 27} #define FRU_FAN(x) { x, "Fan", " ", 28} #define FRU_POWER_SUPPLY(x) { x, "", " ", 29} #define FRU_BATTERY(x) { x, "", " ", 30} #define FRU_IO_EXPANSION_UNIT(x) { x, "", " ", 128} #define FRU_IO_EXPANSION_BUS(x) { x, "", " ", 129} #define FRU_34_POWER_SUPPLY(x) { x, "", " ", 130} #define FRU_14_POWER_SUPPLY(x) { x, "", " ", 131} #define FRU_RIO_BRIDGE(x) { x, "", " ", 185} #define FRU_RTASFRU(x) { x, "", " ", 192} #define FRU_OPERATOR_PANEL(x) { x, "", " ", 213} #define FRU_IO_PLANAR(x) { x, "", " ", 31} /* * If there are two entries for a given failure, the first should be * used in the case of an actual failure, and the second should be used * in the case of a predictive failure (i.e. the repair can be deferred) * * Some of the io??? failures have three entries. */ struct event_description_pre_v6 cpu610[] = /* CPU internal error */ { { "", ERRD1, 0x651, 0x610, MSGCPUB12b0, { FRU_PROCESSOR(100) } }, { "", ERRD1, 0x652, 0x610, DEFER_MSGCPUB12b0, { FRU_PROCESSOR(100) } } }; struct event_description_pre_v6 cpu611[] = /* CPU internal cache error */ { { "", ERRD1, 0x651, 0x611, MSGCPUB12b1, { FRU_PROCESSOR(100) } }, { "", ERRD1, 0x652, 0x611, DEFER_MSGCPUB12b1, { FRU_PROCESSOR(100) } } }; struct event_description_pre_v6 cpu612[] = /* L2 cache parity or mult-bit ecc error */ { { "", ERRD1, 0x651, 0x612, MSGCPUB12b2, { FRU_L2CACHE(100) } }, { "", ERRD1, 0x652, 0x612, DEFER_MSGCPUB12b2, { FRU_L2CACHE(100) } } }; struct event_description_pre_v6 cpu613[] = /* L2 cache ECC single-bit error */ { { "", ERRD1, 0x651, 0x613, MSGCPUB12b3, { FRU_L2CACHE(100) } }, { "", ERRD1, 0x652, 0x613, DEFER_MSGCPUB12b3, { FRU_L2CACHE(100) } } }; struct event_description_pre_v6 cpu614[] = /* Time-out error waiting for mem controller */ { { "", ERRD1, 0x651, 0x614, MSGCPUB12b4, { FRU_MEMORY_CONTROLLER(100) } } }; struct event_description_pre_v6 cpu615[] = /* Time-out error waiting for I/O */ { { "", ERRD1, 0x651, 0x615, MSGCPUB12b5, { FRU_HOST_BRIDGE(100) } } }; struct event_description_pre_v6 cpu619[] = /* Unknown error in CPU Error log */ { { "", ERRD1, 0x651, 0x619, MSGCPUALLZERO, { { 0, "", "", 36}, { 0, "", "", 36}, { 0, "", "", 36}, { 0, "", "", 36} } } }; struct event_description_pre_v6 cpu710[] = /* Address/Data parity error on Processor bus */ { { "", ERRD1, 0x651, 0x710, MSGCPUB12b6, { FRU_RTASFRU(60), FRU_SYSTEM_BUS_CONNECTOR(40) } } }; struct event_description_pre_v6 cpu711[] = /* Address/Data parity error on Processor bus */ { { "", ERRD1, 0x651, 0x711, MSGCPUB12b6, { FRU_RTASFRU(40), FRU_RTASFRU(35), FRU_SYSTEM_BUS_CONNECTOR(25) } } }; struct event_description_pre_v6 cpu712[] = /* Address/Data parity error on Processor bus */ { { "", ERRD1, 0x651, 0x712, MSGCPUB12b6, { FRU_RTASFRU(40), FRU_RTASFRU(25), FRU_RTASFRU(25), FRU_SYSTEM_BUS_CONNECTOR(10) } } }; struct event_description_pre_v6 cpu713[] = /* Transfer error on Processor bus */ { { "", ERRD1, 0x651, 0x713, MSGCPUB12b7, { FRU_RTASFRU(60), FRU_SYSTEM_BUS_CONNECTOR(40) } } }; struct event_description_pre_v6 cpu714[] = /* Transfer error on Processor bus */ { { "", ERRD1, 0x651, 0x714, MSGCPUB12b7, { FRU_RTASFRU(40), FRU_RTASFRU(35), FRU_SYSTEM_BUS_CONNECTOR(25) } } }; struct event_description_pre_v6 cpu715[] = /* Transfer error on Processor bus */ { { "", ERRD1, 0x651, 0x715, MSGCPUB12b7, { FRU_RTASFRU(40), FRU_RTASFRU(25), FRU_RTASFRU(25), FRU_SYSTEM_BUS_CONNECTOR(10) } } }; struct event_description_pre_v6 mem720[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x720, MSGMEMB12b0, { FRU_MEMORY_MODULE(85), FRU_MEMORY_CARD(10), FRU_MEMORY_CONTROLLER(5) } } }; struct event_description_pre_v6 mem721[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x721, MSGMEMB12b0, { FRU_MEMORY_MODULE(85), FRU_MEMORY_CARD(10), FRU_MEMORY_CONTROLLER(5) } } }; struct event_description_pre_v6 mem780[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x780, MSGMEMB12b0, { FRU_MEMORY_MODULE(85), FRU_MEMORY_CARD(10), FRU_MEMORY_CONTROLLER(5) } } }; struct event_description_pre_v6 mem781[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x781, MSGMEMB12b0, { FRU_MEMORY_MODULE(85), FRU_MEMORY_CARD(10), FRU_MEMORY_CONTROLLER(5) } } }; struct event_description_pre_v6 mem782[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x782, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem783[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x783, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem784[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x784, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem785[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x785, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem786[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x786, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem787[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x787, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem788[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x788, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem789[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x789, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem78A[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x78A, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem78B[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x78B, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem78C[] = /* Uncorrectable Memory Error */ { { "", ERRD1, 0x651, 0x78C, MSGMEMB12b0, { FRU_MEMORY_CARD(90), FRU_MEMORY_CONTROLLER(10) } } }; struct event_description_pre_v6 mem620[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x620, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem621[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x621, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem622[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x622, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x622, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem623[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x623, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x623, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem624[] = /* Memory Controller internal error */ { { "", ERRD1, 0x651, 0x624, MSGMEMB12b3, { FRU_MEMORY_CONTROLLER(100) } } }; struct event_description_pre_v6 mem625[] = /* Memory Address (Bad address to memory) */ { { "", ERRD1, 0x651, 0x625, MSGMEMB12b4, { FRU_MEMORY_CONTROLLER(100) } } }; struct event_description_pre_v6 mem626[] = /* Memory Data error (Bad data to memory) */ { { "", ERRD1, 0x651, 0x626, MSGMEMB12b5, { FRU_MEMORY_CONTROLLER(100) } } }; struct event_description_pre_v6 mem627[] = /* Memory time-out error */ { { "", ERRD1, 0x651, 0x627, MSGMEMB12b7, { FRU_MEMORY_CONTROLLER(100) } } }; struct event_description_pre_v6 mem628[] = /* Processor time-out error */ { { "", ERRD1, 0x651, 0x628, MSGMEMB13b1, { FRU_PROCESSOR(100) } } }; struct event_description_pre_v6 mem629[] = /* Unknown error detected by mem. controller */ { { "", ERRD1, 0x651, 0x629, MSGMEMALLZERO, { { 0, "", "", 36}, { 0, "", "", 36}, { 0, "", "", 36}, { 0, "", "", 36} } } }; struct event_description_pre_v6 io630[] = /* I/O Expansion Bus Parity Error */ { { "", ERRD1, 0x651, 0x630, MSGIOB13b4, { FRU_IO_EXPANSION_UNIT(100) } }, { "", ERRD1, 0x652, 0x630, DEFER_MSGIOB13b4, { FRU_IO_EXPANSION_UNIT(100) } } }; struct event_description_pre_v6 io631[] = /* I/O Expansion Bus Time-out Error */ { { "", ERRD1, 0x651, 0x631, MSGIOB13b5, { FRU_IO_EXPANSION_UNIT(100) } }, { "", ERRD1, 0x652, 0x631, DEFER_MSGIOB13b5, { FRU_IO_EXPANSION_UNIT(100) } } }; struct event_description_pre_v6 io632[] = /* I/O Expansion Bus Connect Failure */ { { "", ERRD1, 0x651, 0x632, MSGIOB13b6, { FRU_IO_EXPANSION_BUS(70), FRU_IO_EXPANSION_UNIT(20), FRU_RIO_BRIDGE(10) } }, { "", ERRD1, 0x652, 0x632, DEFER_MSGIOB13b6, { FRU_IO_EXPANSION_BUS(70), FRU_IO_EXPANSION_UNIT(20), FRU_RIO_BRIDGE(10) } } }; struct event_description_pre_v6 io633[] = /* I/O Expansion Unit not in operationg state.*/ { { "", ERRD1, 0x651, 0x633, MSGIOB13b7, { FRU_IO_EXPANSION_UNIT(70), FRU_IO_EXPANSION_BUS(30) } }, { "", ERRD1, 0x652, 0x633, DEFER_MSGIOB13b7, { FRU_IO_EXPANSION_UNIT(70), FRU_IO_EXPANSION_BUS(30) } } }; struct event_description_pre_v6 io634[] = /* Int Error, bridge conn. to i/o exp. bus */ { { "", ERRD1, 0x651, 0x634, MSGIOB12b3, { FRU_IO_EXPANSION_UNIT(100) } }, { "", ERRD1, 0x652, 0x634, DEFER_MSGIOB12b3, { FRU_IO_EXPANSION_UNIT(100) } } }; struct event_description_pre_v6 mem650[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x650, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem651[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x651, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem652[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x652, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem653[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x653, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem654[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x654, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem655[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x655, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem656[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x656, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem657[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x657, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem658[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x658, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem659[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x659, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem65A[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x65A, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem65B[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x65B, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem65C[] = /* ECC correctable error */ { { "", ERRD1, 0x651, 0x65C, MSGMEMB12b1, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem660[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x660, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x660, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem661[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x661, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x661, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem662[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x662, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x662, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem663[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x663, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x663, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem664[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x664, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x664, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem665[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x665, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x665, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem666[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x666, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x666, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem667[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x667, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x667, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem668[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x668, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x668, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem669[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x669, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x669, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem66A[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x66A, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x66A, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem66B[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x66B, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x66B, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 mem66C[] = /* Correctable error threshold exceeded */ { { "", ERRD1, 0x651, 0x66C, MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } }, { "", ERRD1, 0x652, 0x66C, DEFER_MSGMEMB12b2, { FRU_MEMORY_MODULE(100), /* Pct to be adjusted later */ FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0), FRU_MEMORY_MODULE(0) } } }; struct event_description_pre_v6 memtest670[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x670, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(90), FRU_MEMORY_CARD(10) } } }; struct event_description_pre_v6 memtest671[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x671, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(90), FRU_MEMORY_CARD(10) } } }; struct event_description_pre_v6 memtest672[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x672, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest673[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x673, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest674[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x674, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest675[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x675, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest676[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x676, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest677[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x677, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest678[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x678, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest679[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x679, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(90), FRU_MEMORY_CARD(10) } } }; struct event_description_pre_v6 memtest67A[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x67A, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(90), FRU_MEMORY_CARD(10) } } }; struct event_description_pre_v6 mem67B[] = /* Failed memory module */ { { "", ERRD1, 0x651, 0x67B, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(90), FRU_MEMORY_CARD(10) } } }; struct event_description_pre_v6 mem67C[] = /* Failed memory module */ { { "", ERRD1, 0x651, 0x67C, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(90), FRU_MEMORY_CARD(10) } } }; struct event_description_pre_v6 mem722[] = /* Processor Bus parity error */ { { "", ERRD1, 0x651, 0x722, MSGMEMB13b0, { FRU_PROCESSOR(40), FRU_SYSTEM_BUS_CONNECTOR(35), FRU_MEMORY_CONTROLLER(25) } } }; struct event_description_pre_v6 mem723[] = /* Processor bus Transfer error */ { { "", ERRD1, 0x651, 0x723, MSGMEMB13b2, { FRU_PROCESSOR(40), FRU_SYSTEM_BUS_CONNECTOR(35), FRU_MEMORY_CONTROLLER(25) } } }; struct event_description_pre_v6 mem724[] = /* I/O Host Bridge time-out error */ { { "", ERRD1, 0x651, 0x724, MSGMEMB13b3, { FRU_HOST_BRIDGE(40), FRU_MEZZANINE_BUS(35), FRU_MEMORY_CONTROLLER(25) } } }; struct event_description_pre_v6 mem725[] = /* I/O Host Bridge address/data parity error */ { { "", ERRD1, 0x651, 0x725, MSGMEMB13b4, { FRU_HOST_BRIDGE(40), FRU_MEZZANINE_BUS(35), FRU_MEMORY_CONTROLLER(25) } } }; struct event_description_pre_v6 mem726[] = /* I/O Host Bridge and Bad Memory Address */ { { "", ERRD1, 0x651, 0x726, MSGMEMB12b4B13b3, } }; struct event_description_pre_v6 io833[] = { { "", ERRD1, 0x833, 0x0, MSGIOB12b0, /* I/O Bus Address Parity Error */ { { 40, "", " ", 192}, /* the fru name will be inserted, as will the */ /* reason code, which will be the led of the device */ FRU_PCI_DEVICE(35), FRU_PCI_BUS(25) } }, { "", ERRD1, 0x833, 0x0, MSGIOB12b1, /* I/O Bus Data Parity Error */ { { 40, "", " ", 192}, /* the fru name will be inserted, as will the */ /* reason code, which will be the led of the device */ FRU_PCI_DEVICE(35), FRU_PCI_BUS(25) } }, { "", ERRD1, 0x833, 0x0, MSGIOB12b2, /* I/O Time-out error */ { { 40, "", " ", 192}, /* the fru name will be inserted, as will the */ /* reason code, which will be the led of the device */ FRU_PCI_DEVICE(35), FRU_PCI_BUS(25) } } }; #define SN9CC 0x9aa /* 9CC was assigned, so internally I must */ /* use 9AA. The DIMB should read 9CC-xxx */ struct event_description_pre_v6 io9CC[] = { { "", ERRD1, SN9CC, 0x0, MSGIOB12b0, /* I/O Bus Address Parity Error */ { { 60, "", " ", 192}, /* the fru name will be inserted, as will the */ /* reason code, which will be the led of the device */ FRU_PCI_BUS(40) } }, { "", ERRD1, SN9CC, 0x0, MSGIOB12b1, /* I/O Bus Data Parity Error */ { { 60, "", " ", 192}, /* the fru name will be inserted, as will the */ /* reason code, which will be the led of the device */ FRU_PCI_BUS(40) } }, { "", ERRD1, SN9CC, 0x0, MSGIOB12b2, /* I/O Time-out error */ { { 60, "", " ", 192}, /* the fru name will be inserted, as will the */ /* reason code, which will be the led of the device */ FRU_PCI_BUS(40) } } }; struct event_description_pre_v6 iobusonly[] = { { "", ERRD1, SN9CC, 0x0, MSGIOB12b0, /* I/O Bus Address Parity Error */ { FRU_PCI_BUS(100) } }, { "", ERRD1, SN9CC, 0x0, MSGIOB12b1, /* I/O Bus Data Parity Error */ { FRU_PCI_BUS(100) } }, { "", ERRD1, SN9CC, 0x0, MSGIOB12b2, /* I/O Time-out error */ { FRU_PCI_BUS(100) } } }; struct event_description_pre_v6 io832[] = /* I/O Device Internal Error */ { { "", ERRD1, 0x832, 0x0, MSGIOB12b3, { { 100, "", " ", 192} /* the fru name will be inserted, as will the */ /* reason code, which will be the led of the device */ } } }; struct event_description_pre_v6 io639[] = /* Unknown error detected by I/O device */ { { "", ERRD1, 0x651, 0x639, MSGIOALLZERO, { { 0, "", "", 36}, { 0, "", "", 36}, { 0, "", "", 36}, { 0, "", "", 36} } } }; struct event_description_pre_v6 io730[] = /* I/O Error on non-PCI bus */ { { "", ERRD1, 0x651, 0x730, MSGIOB12b4, { FRU_ISA_BUS(100) } } }; struct event_description_pre_v6 io731[] = /* Mezzanine/Processor Bus Addr. Parity Error */ { { "", ERRD1, 0x651, 0x731, MSGIOB12b5, { FRU_MEZZANINE_BUS(60), FRU_HOST_BRIDGE(40) } }, { "", ERRD1, 0x652, 0x731, DEFER_MSGIOB12b5, { FRU_MEZZANINE_BUS(60), FRU_HOST_BRIDGE(40) } } }; struct event_description_pre_v6 io732[] = /* Mezzanine/Processor Bus Data Parity Error */ { { "", ERRD1, 0x651, 0x732, MSGIOB12b6, { FRU_MEZZANINE_BUS(60), FRU_HOST_BRIDGE(40) } }, { "", ERRD1, 0x652, 0x732, DEFER_MSGIOB12b6, { FRU_MEZZANINE_BUS(60), FRU_HOST_BRIDGE(40) } } }; struct event_description_pre_v6 io733[] = /* Mezzanine/Processor Bus Addr. Parity Error */ { { "", ERRD1, 0x651, 0x733, MSGIOB12b5, { FRU_MEMORY_CONTROLLER(40), FRU_MEZZANINE_BUS(35), FRU_HOST_BRIDGE(25) } }, { "", ERRD1, 0x652, 0x733, DEFER_MSGIOB12b5, { FRU_MEMORY_CONTROLLER(40), FRU_MEZZANINE_BUS(35), FRU_HOST_BRIDGE(25) } } }; struct event_description_pre_v6 io734[] = /* Mezzanine/Processor Bus Data Parity Error */ { { "", ERRD1, 0x651, 0x734, MSGIOB12b6, { FRU_MEMORY_CONTROLLER(40), FRU_MEZZANINE_BUS(35), FRU_HOST_BRIDGE(25) } }, { "", ERRD1, 0x652, 0x734, DEFER_MSGIOB12b6, { FRU_MEMORY_CONTROLLER(40), FRU_MEZZANINE_BUS(35), FRU_HOST_BRIDGE(25) } } }; struct event_description_pre_v6 io735[] = /* Mezzanine/Processor Bus Time-out Error */ { { "", ERRD1, 0x651, 0x735, MSGIOB12b7, { FRU_MEZZANINE_BUS_ARBITER(60), FRU_HOST_BRIDGE(40) } }, { "", ERRD1, 0x652, 0x735, DEFER_MSGIOB12b7, { FRU_MEZZANINE_BUS_ARBITER(60), FRU_HOST_BRIDGE(40) } } }; struct event_description_pre_v6 io736[] = /* Mezzanine/Processor Bus Time-out Error */ { { "", ERRD1, 0x651, 0x736, MSGIOB12b7, { FRU_MEZZANINE_BUS_ARBITER(40), FRU_HOST_BRIDGE(35), FRU_MEMORY_CONTROLLER(25) } }, { "", ERRD1, 0x652, 0x736, DEFER_MSGIOB12b7, { FRU_MEZZANINE_BUS_ARBITER(40), FRU_HOST_BRIDGE(35), FRU_MEMORY_CONTROLLER(25) } } }; struct event_description_pre_v6 sp740[] = /* T.O. on communication response from SP */ { { "", ERRD1, 0x651, 0x740, MSGSPB16b0, { FRU_SERVICE_PROCESSOR(60), FRU_SP_SYSTEM_INTERFACE(40) } } }; struct event_description_pre_v6 sp640[] = /* I/O (I2C) general bus error */ { { "", ERRD1, 0x651, 0x640, MSGSPB16b1, { FRU_SP_PRIMARY_BUS(100) } } }; struct event_description_pre_v6 sp641[] = /* Secondary I/O (I2C) general bus error */ { { "", ERRD1, 0x651, 0x641, MSGSPB16b2, { FRU_SP_SECONDARY_BUS(100) } } }; struct event_description_pre_v6 sp642[] = /* Internal Service Processor memory error */ { { "", ERRD1, 0x651, 0x642, MSGSPB16b3, { FRU_SERVICE_PROCESSOR(100) } } }; struct event_description_pre_v6 sp741[] = /* SP error accessing special registers */ { { "", ERRD1, 0x651, 0x741, MSGSPB16b4, { FRU_SERVICE_PROCESSOR(60), FRU_SP_SYSTEM_INTERFACE(40) } } }; struct event_description_pre_v6 sp742[] = /* SP reports unknown communication error */ { { "", ERRD1, 0x651, 0x742, MSGSPB16b5, { FRU_SERVICE_PROCESSOR(60), FRU_SP_SYSTEM_INTERFACE(40) } } }; struct event_description_pre_v6 sp643[] = /* Internal Service Processor firmware error */ { { "", ERRD1, 0x651, 0x643, MSGSPB16b6, { FRU_SERVICE_PROCESSOR(100) } } }; struct event_description_pre_v6 sp644[] = /* Other internal SP hardware error */ { { "", ERRD1, 0x651, 0x644, MSGSPB16b7, { FRU_SERVICE_PROCESSOR(100) } } }; struct event_description_pre_v6 sp743[] = /* SP error accessing VPD EEPROM */ { { "", ERRD1, 0x651, 0x743, MSGSPB17b0, { FRU_VPD_MODULE(75), FRU_SP_PRIMARY_BUS(25) } } }; struct event_description_pre_v6 sp744[] = /* SP error accessing Operator Panel */ { { "", ERRD1, 0x651, 0x744, MSGSPB17b1, { FRU_OPERATOR_PANEL(75), FRU_SP_PRIMARY_BUS(25) } } }; struct event_description_pre_v6 sp745[] = /* SP error accessing Power Controller */ { { "", ERRD1, 0x651, 0x745, MSGSPB17b2, { FRU_POWER_CONTROLLER(75), FRU_SP_PRIMARY_BUS(25) } } }; struct event_description_pre_v6 sp746[] = /* SP error accessing Fan Sensor */ { { "", ERRD1, 0x651, 0x746, MSGSPB17b3, { FRU_FAN_SENSOR(75), FRU_SP_PRIMARY_BUS(25) } } }; struct event_description_pre_v6 sp747[] = /* SP error accessing Thermal Sensor */ { { "", ERRD1, 0x651, 0x747, MSGSPB17b4, { FRU_THERMAL_SENSOR(75), FRU_SP_PRIMARY_BUS(25) } } }; struct event_description_pre_v6 sp748[] = /* SP error accessing Voltage Sensor */ { { "", ERRD1, 0x651, 0x748, MSGSPB17b5, { FRU_VOLTAGE_SENSOR(75), FRU_SP_PRIMARY_BUS(25) } } }; struct event_description_pre_v6 sp749[] = /* SP error accessing serial port */ { { "", ERRD1, 0x651, 0x749, MSGSPB18b0, { FRU_SERIAL_PORT_CONTROLLER(75), FRU_SP_SYSTEM_INTERFACE(25) } } }; struct event_description_pre_v6 sp750[] = /* SP error accessing NVRAM */ { { "", ERRD1, 0x651, 0x750, MSGSPB18b1, { FRU_NVRAM(75), FRU_SP_SYSTEM_INTERFACE(25) } } }; struct event_description_pre_v6 sp751[] = /* SP error accessing RTC/TOD clock */ { { "", ERRD1, 0x651, 0x751, MSGSPB18b2, { FRU_RTC_TOD(75), FRU_SP_SYSTEM_INTERFACE(25) } } }; struct event_description_pre_v6 sp752[] = /* SP error accessing JTAG/COP controller */ { { "", ERRD1, 0x651, 0x752, MSGSPB18b3, { FRU_JTAG(75), FRU_SP_SYSTEM_INTERFACE(25) } } }; struct event_description_pre_v6 sp753[] = /* SP detect error with tod battery */ { { "", ERRD1, 0x651, 0x753, MSGSPB18b4, { FRU_BATTERY(75), FRU_SP_SYSTEM_INTERFACE(25) } } }; struct event_description_pre_v6 sp754[] = /* SP detect SPCN link failure */ { { "", ERRD1, 0x651, 0x754, MSGSPB19b0, } }; struct event_description_pre_v6 sp760[] = /* SP reboot system due to surveillance T.O. */ { { "", ERRD1, 0x651, 0x760, MSGSPB18b7, { FRU_SOFTWARE(60), FRU_HARDWARE(40) } } }; struct event_description_pre_v6 io770[] = /* Mezzanine/Processor Bus Addr. Parity Error */ { { "", ERRD1, 0x651, 0x770, MSGIOB12b5, { FRU_MEZZANINE_BUS(40), FRU_HOST_BRIDGE(35), FRU_IO_EXPANSION_BUS(25) } }, { "", ERRD1, 0x652, 0x770, DEFER_MSGIOB12b5, { FRU_MEZZANINE_BUS(40), FRU_HOST_BRIDGE(35), FRU_IO_EXPANSION_BUS(25) } } }; struct event_description_pre_v6 io771[] = /* Mezzanine/Processor Bus Data Parity Error */ { { "", ERRD1, 0x651, 0x771, MSGIOB12b6, { FRU_MEZZANINE_BUS(40), FRU_HOST_BRIDGE(35), FRU_IO_EXPANSION_BUS(25) } }, { "", ERRD1, 0x652, 0x771, DEFER_MSGIOB12b6, { FRU_MEZZANINE_BUS(40), FRU_HOST_BRIDGE(35), FRU_IO_EXPANSION_BUS(25) } } }; struct event_description_pre_v6 io772[] = /* Mezzanine/Processor Bus Time-out Error */ { { "", ERRD1, 0x651, 0x772, MSGIOB12b7, { FRU_MEZZANINE_BUS(40), FRU_HOST_BRIDGE(35), FRU_MEZZANINE_BUS_ARBITER(25) } }, { "", ERRD1, 0x652, 0x772, DEFER_MSGIOB12b7, { FRU_MEZZANINE_BUS(40), FRU_HOST_BRIDGE(35), FRU_MEZZANINE_BUS_ARBITER(25) } } }; struct event_description_pre_v6 io773[] = /* Err detected by i/o exp. bus controller */ { { "", ERRD1, 0x651, 0x773, MSGIOB12b6, { FRU_RIO_BRIDGE(100) } }, { "", ERRD1, 0x652, 0x773, DEFER_MSGIOB12b6, { FRU_RIO_BRIDGE(100) } } }; struct event_description_pre_v6 epow800[] = /* Fan is turning slower than expected */ { { "", ERRD1, 0x651, 0x800, MSGXEPOW1n11, { FRU_FAN(60), FRU_FAN_SENSOR(40) } } }; struct event_description_pre_v6 epow801[] = /* Fan stop was detected */ { { "", ERRD1, 0x651, 0x801, MSGXEPOW1n64, { FRU_FAN(60), FRU_FAN_SENSOR(40) } } }; struct event_description_pre_v6 epow802[] = /* Fan failure */ { { "", ERRD1, 0x651, 0x802, MSGEPOWB16b2C12 } }; struct event_description_pre_v6 epow809[] = /* Power fault due to unspecified cause */ { { "", ERRD1, 0x651, 0x809, MSGEPOWB17b0C12 } }; struct event_description_pre_v6 epow810[] = /* Over voltage condition was detected */ { { "", ERRD1, 0x651, 0x810, MSGXEPOW2n32, { FRU_POWER_SUPPLY(60), FRU_VOLTAGE_SENSOR(40) } } }; struct event_description_pre_v6 epow811[] = /* Under voltage condition was detected */ { { "", ERRD1, 0x651, 0x811, MSGXEPOW2n52, { FRU_POWER_SUPPLY(60), FRU_VOLTAGE_SENSOR(40) } } }; struct event_description_pre_v6 epow812[] = /* System shutdown due to loss of power */ { { "", ERRD1, 0x651, 0x812, MSGEPOWB1505, { FRU_POWER_SUPPLY(100) } } }; struct event_description_pre_v6 epow813[] = /* System shutdown due to loss of power to site*/ { { "", ERRD1, 0x651, 0x813, MSGEPOWPCI111 } }; struct event_description_pre_v6 epow814[] = /* System shutdown due to loss of power to CEC */ { { "", ERRD1, 0x651, 0x814, MSGEPOWPCI100 } }; struct event_description_pre_v6 epow815[] = /* System shutdown due to loss of power to I/O Rack */ { { "", ERRD1, 0x651, 0x815, MSGEPOWPCI011, { FRU_34_POWER_SUPPLY(50), FRU_14_POWER_SUPPLY(50) } } }; struct event_description_pre_v6 epow816[] = /* Power fault due to internal power supply */ { { "", ERRD1, 0x651, 0x816, MSGEPOWPCI001, { FRU_34_POWER_SUPPLY(100) } } }; struct event_description_pre_v6 epow817[] = /* Power fault due to internal power supply */ { { "", ERRD1, 0x651, 0x817, MSGEPOWPCI010, { FRU_14_POWER_SUPPLY(100) } } }; struct event_description_pre_v6 epow818[] = /* Power fault due to power-off request */ { { "", ERRD1, 0x651, 0x818, MSGEPOWB16b1B17b3 } }; struct event_description_pre_v6 epow819[] = /* Power fault due to internal power supply */ { { "", ERRD1, 0x651, 0x819, MSGEPOWPCI001, { FRU_RTASFRU(100) } } }; struct event_description_pre_v6 epow819red[] = /* Power fault due to internal redundant PS */ { { "", ERRD1, 0x652, 0x819, MSGEPOWB17b2RED } }; struct event_description_pre_v6 epow820[] = /* Over temperature condition was detected */ { { "", ERRD1, 0x651, 0x820, MSGXEPOW3n21, { FRU_THERMAL_SENSOR(100) } } }; struct event_description_pre_v6 epow821[] = /* System shutdown due to over max temp. */ { { "", ERRD1, 0x651, 0x821, MSGXEPOW3n73, { FRU_THERMAL_SENSOR(100) } } }; struct event_description_pre_v6 epow822[] = /* System shutdown due to thermal and fan fail */ { { "", ERRD1, 0x651, 0x822, MSGEPOWB16b23 } }; struct event_description_pre_v6 epow823[] = /* System shutdown due to fan failure */ { { "", ERRD1, 0x651, 0x823, MSGEPOWB16b2C37 } }; struct event_description_pre_v6 epow824[] = /* System shutdown:Power fault-unspecified cause*/ { { "", ERRD1, 0x651, 0x824, MSGEPOWB17b0C37 } }; struct event_description_pre_v6 epow652810[] = /* Loss of redundant power supply. */ { { "", ERRD1, 0x652, 0x810, MSGEPOW1502B16b4 } }; struct event_description_pre_v6 epow652820[] = /* Loss of redundant cec blower. */ { { "", ERRD1, 0x652, 0x820, MSGEPOW1501B16b4 } }; struct event_description_pre_v6 post[] = /* POST 8 digit code */ { { "", ERRD1, -2, 0x0, MSGPOSTALL, /* -2 = DAVars has 8 digit hex code */ { { 0, "", "", 36}, { 0, "", "", 36}, { 0, "", "", 36}, { 0, "", "", 36} } } }; struct event_description_pre_v6 postfw[] = /* POST 8 digit code that is fw error*/ { { "", ERRD1, -2, 0x0, MSGPOSTALL, /* -2 = DAVars has 8 digit hex code */ { { 50, " ", " ", 35}, { 50, " ", " ", 34} } } }; struct event_description_pre_v6 memtest600[] = /* Uncorrectable/unsupported memory */ { { "", ERRD1, 0x651, 0x600, MSG_UNSUPPORTED_MEM, { FRU_MEMORY_MODULE(100) } }, { "", ERRD1, 0x652, 0x600, DEFER_MSG_UNSUPPORTED_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest601[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x601, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(100) } } }; struct event_description_pre_v6 memtest602[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x602, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(90), FRU_MEMORY_CARD(10) } } }; struct event_description_pre_v6 memtest603[] = /* Missing or bad memory */ { { "", ERRD1, 0x651, 0x603, MSG_MISSING_MEM, { FRU_MEMORY_MODULE(90), FRU_MEMORY_CARD(10) } } }; struct event_description_pre_v6 l2test608[] = /* Bad L2 Cache */ { { "", ERRD1, 0x651, 0x608, MSG_BAD_L2, { FRU_L2CACHE(100) } } }; struct event_description_pre_v6 l2test609[] = /* Missing L2 Cache */ { { "", ERRD1, 0x651, 0x609, MSG_MISSING_L2, { FRU_MISSING_L2(100) } } }; /* * Source Number to match dresid and DIMB */ struct event_description_pre_v6 optest140[] = /* Op panel display test failed */ { { "", ERRD1, 0x651, 0x140, MSG_OP_PANEL_FAIL, { FRU_OPERATOR_PANEL(95), FRU_IO_PLANAR(5) } } }; /* * Event that is filled with ref. codes (in conf. field) and location * codes. The SRN will be formatted differently because the conf. * value is greater than 100. */ struct event_description_pre_v6 cec_src[] = /* SRC and ref. codes from CEC */ { { "", ERRD1, 0x651, 0, "", { { 0, "", "", 0}, { 0, "", "", 0}, { 0, "", "", 0}, { 0, "", "", 0} } } }; struct event_description_pre_v6 fan_epow[] = /* SRN for fan epow */ { { "", ERRD1, 0x651, 0, "", { FRU_FAN(60), FRU_FAN_SENSOR(40) } } }; struct event_description_pre_v6 volt_epow[] = /* SRN for voltage sensor epow */ { { "", ERRD1, 0x651, 0, "", { FRU_POWER_SUPPLY(60), FRU_VOLTAGE_SENSOR(40) } } }; struct event_description_pre_v6 therm_epow[] = /* SRN for thermal sensor epow */ { { "", ERRD1, 0x651, 0, "", { FRU_THERMAL_SENSOR(100) } } }; struct event_description_pre_v6 pow_epow[] = /* SRN for power epow */ { { "", ERRD1, 0x651, 0, "", { FRU_POWER_SUPPLY(60), FRU_POWER_SENSOR(40) } } }; struct event_description_pre_v6 unknown_epow[] = /* SRN for unknown epow */ { { "", ERRD1, 0x651, 0, "", { { 100, "", "", 180} } } }; /* Version 3 error descriptions */ struct event_description_pre_v6 platform_error[] = /* SRN for platform specific error */ { { "", ERRD1, 0x651, 0x900, MSG_PLATFORM_ERROR, { { 0, "", "", 0}, { 0, "", "", 0}, { 0, "", "", 0}, { 0, "", "", 0} } } }; #define SN_V3ELA 0xA00 /* source number for V3 ELA */ struct event_description_pre_v6 v3_errdscr[] = /* SRN for V3 error logs */ { { "", ERRD1, SN_V3ELA, 0, "", { { 0, "", "", 0}, { 0, "", "", 0}, { 0, "", "", 0}, { 0, "", "", 0} } } }; struct event_description_pre_v6 dt_errdscr[] = /* SRN for deconfig resources in device tree */ { { "", ERRD1, 0xA10, 0x200, FAIL_BY_PLATFORM, { { 100, "", "", 0}, } } }; struct event_description_pre_v6 bypass_errdscr[] = /* SRN for deconfig resource from error log */ { { "", ERRD1, 0xA10, 0x100, MSG_BYPASS, { { 100, "", "", 0}, } } }; #endif ppc64-diag-2.7.0/rtas_errd/diag_support.c0000644000000000000000000002472112642205425016715 0ustar rootroot/** * @file diag_support.c * * Copyright (C) 2005, 2008 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "rtas_errd.h" #define CMD_LSVPD "/usr/sbin/lsvpd" char target_status[80]; void free_diag_vpd(struct event *event) { if (event->diag_vpd.ds != NULL) { free(event->diag_vpd.ds); event->diag_vpd.ds = NULL; } if (event->diag_vpd.yl != NULL) { free(event->diag_vpd.yl); event->diag_vpd.yl = NULL; } if (event->diag_vpd.fn != NULL) { free(event->diag_vpd.fn); event->diag_vpd.fn = NULL; } if (event->diag_vpd.sn != NULL) { free(event->diag_vpd.sn); event->diag_vpd.sn = NULL; } if (event->diag_vpd.se != NULL) { free(event->diag_vpd.se); event->diag_vpd.se = NULL; } if (event->diag_vpd.tm != NULL) { free(event->diag_vpd.tm); event->diag_vpd.tm = NULL; } } /* * Execute the 'lsvpd' command and open a pipe to read the data */ static int lsvpd_init(FILE **fp, pid_t *cpid) { char *system_args[2] = {CMD_LSVPD, NULL,}; /* execv arguments */ dbg("start lsvpd_init"); *fp = spopen(system_args, cpid); if (!*fp) { perror("popen"); dbg("lsvpd_init failed popen (%s)", CMD_LSVPD); return -1; } dbg("end lsvpd_init"); return 0; } /* * Close the open a pipe on 'lsvpd'. */ static int lsvpd_term(FILE *fp, pid_t *cpid) { int rc = 0; char line[512]; /* If pipe was opened read all vpd */ /* entries until pipe is empty. */ if (fp) { while (fgets(line, sizeof(line), fp)); rc = spclose(fp, *cpid); } return rc; } /* * Read the next lsvpd keyword, value pair */ static int lsvpd_read(struct event *event, FILE *fp) { int rc = 1; char line[512]; dbg("start lsvpd_read"); if (!fp) return rc; /* clear all residual data */ free_diag_vpd(event); while (fgets(line, sizeof(line), fp)) { if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; if (! strncmp(line, "*DS", 3)) { event->diag_vpd.ds = malloc(strlen (line) + 1); if (event->diag_vpd.ds == NULL) return rc; strcpy(event->diag_vpd.ds, &line[4]); dbg("found DS: \"%s\"", event->diag_vpd.ds); } if (! strncmp(line, "*YL", 3)) { event->diag_vpd.yl = malloc(strlen (line) + 1); if (event->diag_vpd.yl == NULL) return rc; strcpy(event->diag_vpd.yl, &line[4]); dbg("found YL: \"%s\"", event->diag_vpd.yl); } if (! strncmp(line, "*FN", 3)) { event->diag_vpd.fn = malloc(strlen (line) + 1); if (event->diag_vpd.fn == NULL) return rc; strcpy(event->diag_vpd.fn, &line[4]); dbg("found FN: \"%s\"", event->diag_vpd.fn); } if (! strncmp(line, "*SN", 3)) { event->diag_vpd.sn = malloc(strlen (line) + 1); if (event->diag_vpd.sn == NULL) return rc; strcpy(event->diag_vpd.sn, &line[4]); dbg("found SN: \"%s\"", event->diag_vpd.sn); } if (! strncmp(line, "*SE", 3)) { event->diag_vpd.se = malloc(strlen (line) + 1); if (event->diag_vpd.se == NULL) return rc; strcpy(event->diag_vpd.se, &line[4]); dbg("found SE: \"%s\"", event->diag_vpd.se); } if (! strncmp(line, "*TM", 3)) { event->diag_vpd.tm = malloc(strlen (line) + 1); if (event->diag_vpd.tm == NULL) return rc; strcpy(event->diag_vpd.tm, &line[4]); dbg("found TM: \"%s\"", event->diag_vpd.tm); } if (! strncmp(line, "*FC", 3)) { /* start of next record */ dbg("found FC - start next record"); return 0; } } dbg("end lsvpd_read"); return 1; } int get_diag_vpd(struct event *event, char *phyloc) { int rc = 0; FILE *fp = NULL; pid_t cpid; /* child pid */ dbg("start get_diag_vpd"); if (event->diag_vpd.yl != NULL) free_diag_vpd(event); /* sigchld_handler() messes up pclose(). */ restore_sigchld_default(); if (lsvpd_init(&fp, &cpid) != 0) { setup_sigchld_handler(); return 1; } while (event->diag_vpd.yl == NULL || strcmp(event->diag_vpd.yl, phyloc)) { if (lsvpd_read(event, fp)) { dbg("end get_diag_vpd, failure"); rc = lsvpd_term(fp, &cpid); setup_sigchld_handler(); return 1; } } rc = lsvpd_term(fp, &cpid); if (rc) dbg("end get_diag_vpd, pclose failure"); else dbg("end get_diag_vpd, success"); setup_sigchld_handler(); return rc; } char * get_dt_status(char *dev) { FILE *fp1 = NULL, *fp2 = NULL; char loc_file[80]; char target[80]; char *ptr; char *system_args[6] = {NULL, }; /* execv args */ char tmp_file[] = "/tmp/get_dt_files-XXXXXX"; int fd; pid_t cpid; /* child pid */ int rc; /* return value */ int status; /* child exit status */ system_args[0] = "/usr/bin/find"; system_args[1] = "/proc/device-tree"; system_args[2] = "-name"; system_args[3] = "status"; system_args[4] = "-print"; fd = mkstemp(tmp_file); if (fd == -1) { log_msg(NULL, "tmp file creation failed, at " "get_dt_status\n"); exit (-2); } /* open */ cpid = fork(); if (cpid == -1) { close(fd); log_msg(NULL, "Fork failed, at get_dt_status\n"); return NULL; } /* fork */ if (cpid == 0) { /* child */ int fd = open(tmp_file, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); if (fd == -1) { log_msg(NULL, "tmp file creation failed, at " "get_dt_status\n"); exit (-2); } /* open */ rc = dup2(fd, STDOUT_FILENO); if (rc == -1) { log_msg(NULL, "STDOUT redirection failed, at " "get_dt_status\n"); close(fd); exit (-2); } rc = execv(system_args[0], system_args); log_msg(NULL, "get_dt_status find command failed\n"); close(fd); exit (-2); } else { /* parent */ close(fd); rc = waitpid(cpid, &status, 0); if (rc == -1) { log_msg(NULL, "wait on child failed at, " "get_dt_status\n"); return NULL; } /* waitpid */ /* Return on EXIT_FAILURE */ if ((signed char)WEXITSTATUS(status) == -2) return NULL; } /* results of the find command */ fp1 = fopen(tmp_file, "r"); if (fp1 == 0) { fprintf(stderr, "open failed on %s\n", tmp_file); return NULL; } while (fscanf (fp1, "%s", loc_file) != EOF) { dbg("read from /%s, \"%s\"", tmp_file, loc_file); /* read the status in case this is the one */ fp2 = fopen(loc_file, "r"); if (fp2 == 0) { fprintf(stderr, "open failed on %s\n", loc_file); goto out; } if (fscanf(fp2, "%s", target_status)) { dbg("target_status = \"%s\", loc_file = \"%s\"", target_status, loc_file); } else { fprintf(stderr, "read failed on %s\n", loc_file); goto out; } fclose(fp2); /* read the loc-code file to determine if found dev */ ptr = strstr(loc_file, "status"); strcpy(ptr, "ibm,loc-code"); fp2 = fopen(loc_file, "r"); if (fp2 == 0) { fprintf(stderr, "open failed on %s\n", loc_file); goto out; } if (fscanf(fp2, "%s", target)) { dbg("target = \"%s\", loc_file = \"%s\"", target, loc_file); if (strcmp(dev, target) == 0) { dbg("status = \"%s\"", target_status); fclose (fp2); fclose (fp1); return target_status; } } else { fprintf(stderr, "read failed on %s\n", loc_file); goto out; } } fprintf(stderr, "error: status NOT FOUND\n"); out: if (fp2) fclose(fp2); if (fp1) fclose(fp1); return NULL; } /** * is_integrated * @brief This function determines if the device is an integrated device or not. * * RETURNS: * 0 - Not integrated * 1 - Is integrated * -1 - System error obtaining data * */ int is_integrated(char *phy_loc) { int rc; int index = -1; dbg("phy_loc = \"%s\"", phy_loc); rc = 0; index = strlen(phy_loc); /* Start at the end of the location code looking for */ /* a slash or a dash. If the beginning of the */ /* location code is reached without finding either, */ /* then the resource is not integrated. */ while (index > 0) { if (phy_loc[index] == '/') { dbg("found slash, resource may be integrated"); index--; /* Now find planar. Only allowable */ /* characters between here and 'P' */ /* are numerics and '.' */ while (index >= 0) { if (phy_loc[index] == 'P') { rc = 1; break; } else if (phy_loc[index] == '.') index--; else if (phy_loc[index] >= '0' && phy_loc[index] <= '9') index--; else { rc = 0; break; } } break; } if (phy_loc[index] == '-') { dbg("found dash, so resource is not integrated"); rc = 0; break; } index--; } /* while index > 0 */ return rc; } /** * get_base_loc * * FUNCTION: Reduce the given location code to the base physical FRU, thus * removing the extended functional location information. Currently * this works for CHRP physical location codes, but will need to * updated for converged location codes. */ void get_base_loc(char *phyloc, char *base) { /* Char by char copy until reaching a slash ('/) or the end */ while (*phyloc != 0 && *phyloc != '/') { *base = *phyloc; base++; phyloc++; } /* Now the terminating null */ *base = 0; } /** * diag_fru_pn_by_ploc * * Returns the FRU part number from VPD, as defined by the "FN" vpd keyword, * for the FRU given by the physical location code * * RETURNS: * 0 if not found information. * 1 if found information. * -1 if error found during search */ char * diag_get_fru_pn(struct event *event, char *phyloc) { char baseloc[80]; if (is_integrated(phyloc)) { /* Use the base location code */ get_base_loc(phyloc, baseloc); if (get_diag_vpd(event, baseloc)) return NULL; if (event->diag_vpd.fn == NULL) /* not found for base loc. code */ return NULL; } else { /* not integrated */ if (get_diag_vpd(event, phyloc)) return NULL; if (event->diag_vpd.fn == NULL) /* not found */ return NULL; } /* found for given location code */ return event->diag_vpd.fn; } ppc64-diag-2.7.0/rtas_errd/dump.c0000644000000000000000000002251512642205425015161 0ustar rootroot/** * @file dump.c * @brief Routines to handle platform dump and scanlog dump RTAS events * * Copyright (C) 2004 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "rtas_errd.h" #define DUMP_MAX_FNAME_LEN 40 #define DUMP_BUF_SZ 4096 #define EXTRACT_PLATDUMP_CMD "/usr/sbin/extract_platdump" #define SCANLOG_DUMP_FILE "/proc/ppc64/scan-log-dump" #define SCANLOG_DUMP_EXISTS "/proc/device-tree/chosen/ibm,scan-log-data" #define SYSID_FILE "/proc/device-tree/system-id" #define SCANLOG_MODULE "scanlog" #define MODPROBE_PROGRAM "/sbin/modprobe" /** * get_machine_serial * @brief Retrieve a machines serial number * * Return a string containing the machine's serial number, obtained * from procfs (the file named SYSID_FILE). This routine mallocs a * new string; it is the caller's responsibility to ensure that the * string is freed. * * @return pointer to (allocated) string, NULL on failure */ static char * get_machine_serial() { FILE *fp; char buf[20] = {0,}, *ret = NULL; /* * Odds of SYSID_FILE, open failing is almost none. * But, better to catch the odds. */ fp = fopen(SYSID_FILE, "r"); if (!fp) { log_msg(NULL, "%s: Failed to open %s, %s", __func__, SYSID_FILE, strerror(errno)); return ret; } if (fgets(buf, sizeof(buf), fp) == NULL) { log_msg(NULL, "%s: Reading file %s failed, %s", __func__, SYSID_FILE, strerror(errno)); } else { ret = strdup(buf + 4); if (!ret) { log_msg(NULL, "%s: Memory allocation failed, %s", __func__, strerror(errno)); } /* strdup */ } fclose(fp); return ret; } /** * load_scanlog_module * @brief Load/Unload scanlog module * * Loads or unloads the scanlog module. The load parameter should * be 1 to load the module, or 0 to unload it. * * @param load directive to load/unload module * @return 0 on success, !0 on failure. */ static int load_scanlog_module(int load) { int rc, i = 0; pid_t cpid; /* child pid */ char *system_args[5] = {NULL,}; /* **argv passed to execv */ int status; /* exit status of child */ /* If SCANLOG_DUMP_FILE exists, then the module is either already * loaded, or the procfs interface is built into the kernel rather * than as a module. */ if (load && !access(SCANLOG_DUMP_FILE, F_OK)) return 0; system_args[i++] = MODPROBE_PROGRAM; system_args[i++] = "-q"; if (!load) system_args[i++] = "-r"; system_args[i++] = SCANLOG_MODULE; cpid = fork(); if (cpid == -1) { log_msg(NULL, "Fork failed, while probing for scanlog\n"); return 1; } /* fork */ if (cpid == 0 ) { /* child */ rc = execv(system_args[0], system_args); if (errno != ENOENT) { log_msg(NULL, "%s module could not be %s, could not run " "%s; system call returned %d", SCANLOG_MODULE, (load ? "loaded" : "unloaded"), MODPROBE_PROGRAM, rc); } else { log_msg(NULL, "module %s not found", SCANLOG_MODULE); } exit(-2); } else { /* parent */ rc = waitpid(cpid, &status, 0); if (rc == -1) { log_msg(NULL, "wait failed, while probing for " "scanlog\n"); return 1; } if ((signed char)WEXITSTATUS(status) == -2) /* exit on failure */ return 1; } return 0; } /** * check_scanlog_dump * @brief Check for new scanlog dumps * * This routine checks to see if a new scanlog dump is available, and * if so, copies it to the filesystem. The return value is the filename * of the new scanlog dump, or NULL if one is not copied. This routine * will malloc space for the returned string; it is up to the caller to * free it. * * This routine should be invoked once when the daemon is started. */ void check_scanlog_dump(void) { int rc, in = -1, out = -1, bytes; char *temp; char scanlog_filename[80], scanlog_filename_bak[85]; char *dump_buf = NULL; rc = load_scanlog_module(1); if (rc || access(SCANLOG_DUMP_EXISTS, F_OK)) goto scanlog_out; /* A dump exists; copy it off to the filesystem */ if ((temp = get_machine_serial()) != 0) { sprintf(scanlog_filename, "%sscanoutlog.%s", d_cfg.scanlog_dump_path, temp); free(temp); } else { sprintf(scanlog_filename, "%sscanoutlog.NOSERIAL", d_cfg.scanlog_dump_path); } if (!access(scanlog_filename, F_OK)) { /* A scanlog dump already exists on the filesystem; * rename it with a .bak extension. */ sprintf(scanlog_filename_bak, "%s.bak", scanlog_filename); rc = rename(scanlog_filename, scanlog_filename_bak); if (rc) { log_msg(NULL, "Could not rename %s, an existing " "scanlog dump will be copied over by a new " "dump, %s", scanlog_filename, strerror(errno)); } } in = open(SCANLOG_DUMP_FILE, O_RDONLY); if (in <= 0) { log_msg(NULL, "Could not open %s for reading, %s", SCANLOG_DUMP_FILE, strerror(errno)); goto scanlog_error; } out = open(scanlog_filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (out <= 0) { log_msg(NULL, "Could not open %s for writing, %s", scanlog_filename, strerror(errno)); goto scanlog_error; } dump_buf = malloc(DUMP_BUF_SZ); if (dump_buf == NULL) { log_msg(NULL, "Could not allocate buffer to read in " "scanlog dump, %s", strerror(errno)); goto scanlog_error; } while ((bytes = read(in, dump_buf, DUMP_BUF_SZ)) > 0) { rc = write(out, dump_buf, bytes); if (rc < bytes) { log_msg(NULL, "Could not write to %s, %s", scanlog_filename, strerror(errno)); goto scanlog_error; } } if (bytes < 0) log_msg(NULL, "Could not read from %s, %s", SCANLOG_DUMP_FILE, strerror(errno)); temp = scanlog_filename + strlen(d_cfg.scanlog_dump_path); scanlog = strdup(temp); if (scanlog == NULL) { log_msg(NULL, "Could not allocate space for scanlog filename, " "%s. A scanlog dump could not be copied to the " "filesystem", strerror(errno)); } /* strdup(scanlog) */ scanlog_out: if (in != -1) close(in); if (out != -1) close(out); if (dump_buf != NULL) free(dump_buf); load_scanlog_module(0); return; scanlog_error: log_msg(NULL, "Due to previous error a scanlog dump could not be" "copied to the filesystem"); goto scanlog_out; } /** * check_platform_dump * @brief Check RTAS event for a platform dump * * Parses error information to determine if it indicates the availability * of a platform dump. The platform dump is copied to the filesystem, * and the error log is updated to indicate the path to the dump. * * This should be invoked _before_ the error information is written to * LOG_FILE, because the error may need to be updated with the path to * the dump. * * @param event pointer to struct event */ void check_platform_dump(struct event *event) { struct rtas_dump_scn *dump_scn; uint64_t dump_tag; char filename[DUMP_MAX_FNAME_LEN + 20], *pos; char pathname[DUMP_MAX_FNAME_LEN + 40]; FILE *f; int rc, bytes; char *system_args[3] = {NULL, }; /* execv arguments */ char tmp_sys_arg[60]; /* tmp sys_args */ pid_t cpid; /* child pid */ dump_scn = rtas_get_dump_scn(event->rtas_event); if (dump_scn == NULL) return; dbg("platform dump found"); snprintf(event->addl_text, ADDL_TEXT_MAX, "Platform Dump " "(could not be retrieved to filesystem)"); if (dump_scn->v6hdr.subtype == 0) { dbg("ignoring platform dump with subtype 0"); return; } /* Retrieve the dump */ dump_tag = dump_scn->id; dump_tag |= ((uint64_t)dump_scn->v6hdr.subtype << 32); dbg("Dump ID: 0x%016LX", dump_tag); snprintf(tmp_sys_arg, 60, "0x%016LX", (long long unsigned int)dump_tag); system_args[0] = EXTRACT_PLATDUMP_CMD; system_args[1] = tmp_sys_arg; /* sigchld_handler() messes up pclose(). */ restore_sigchld_default(); f = spopen(system_args, &cpid); if (f == NULL) { log_msg(event, "Failed to open pipe to %s.", EXTRACT_PLATDUMP_CMD); setup_sigchld_handler(); return; } fgets(filename, DUMP_MAX_FNAME_LEN + 20, f); rc = spclose(f, cpid); setup_sigchld_handler(); if (rc) { dbg("%s failed to extract the dump", EXTRACT_PLATDUMP_CMD); return; } if ((pos = strchr(filename, '\n')) != NULL) *pos = '\0'; dbg("Dump Filename: %s", filename); event->flags |= RE_PLATDUMP_AVAIL; /* Update the raw and parsed events with the dump path and length */ update_os_id_scn(event->rtas_event, filename); memcpy(dump_scn->os_id, filename, DUMP_MAX_FNAME_LEN); bytes = strlen(filename); if ((bytes % 4) > 0) bytes += (4 - (bytes % 4)); dump_scn->id_len = bytes; snprintf(pathname, DUMP_MAX_FNAME_LEN + 40, "%s/%s", d_cfg.platform_dump_path, filename); platform_log_write("Platform Dump Notification\n"); platform_log_write(" Dump Location: %s\n", pathname); return; } ppc64-diag-2.7.0/rtas_errd/eeh.c0000644000000000000000000000734512642205425014761 0ustar rootroot/* * @file eeh.c * @brief Routine to handle EEH notification RTAS events * * Copyright (C) 2004 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include "rtas_errd.h" /** * @struct event_desc * @brief Definition for a SRC value and its corresponding description. */ struct event_desc { char *src_code; char *desc; }; /** * @var event_descs * @brief Array of event_desc structs for the SRC values to search * in an EEH related RTAS event. */ struct event_desc event_descs[] = { {"BA188001", "EEH recovered a failing I/O adapter"}, {"BA188002", "EEH could not recover the failed I/O adapter"}, {"BA180010", "PCI probe error, bridge in freeze state"}, {"BA180011", "PCI bridge probe error, bridge is not usable"}, {"BA180012", "PCI device runtime error, bridge in freeze state"}, {NULL, NULL} }; /** * check_eeh * @brief Check a RTAS event for EEH event notification. * * Parse a RTAS event to see if this is an EEH event notification. * If so, then update the platform log file with additional * information about the EEH event. * * @param event pointer to the RTAS event */ void check_eeh(struct event *event) { struct rtas_event_hdr *rtas_hdr = event->rtas_hdr; struct rtas_priv_hdr_scn *privhdr; struct rtas_src_scn *src; int index = 0; if (rtas_hdr->version != 6) { return; } src = rtas_get_src_scn(event->rtas_event); if (src == NULL) { log_msg(event, "Could not retrieve SRC section to check for " "an EEH event, skipping"); return; } /* * Check for a known EEH event described above in the * events description array. */ while (event_descs[index].src_code != NULL) { if (strncmp((char *)src->primary_refcode, event_descs[index].src_code, 8) == 0) break; index++; } if (event_descs[index].src_code == NULL) return; /* * Write the EEH Event notification out to /var/log/platform * Please trust the compiler to get this right */ platform_log_write("EEH Event Notification\n"); privhdr = rtas_get_priv_hdr_scn(event->rtas_event); if (privhdr == NULL) { log_msg(event, "Could not retrieve the RTAS Event information " "to report EEH failure date/time"); platform_log_write("Could not retrieve RTAS Event Date/Time\n"); } else { platform_log_write("%02x/%02x/%04x %02x:%02x:%02x\n", privhdr->date.month, privhdr->date.day, privhdr->date.year, privhdr->time.hour, privhdr->time.minutes, privhdr->time.seconds); } platform_log_write("Event SRC Code: %s\n", event_descs[index].src_code); platform_log_write(" %s\n", event_descs[index].desc); if (src->fru_scns != NULL) { struct rtas_fru_scn *fru = src->fru_scns; platform_log_write(" Device Location Code: %s\n", fru->loc_code); snprintf(event->addl_text, ADDL_TEXT_MAX, "%s, Location %s", event_descs[index].desc, fru->loc_code); } else { platform_log_write(" No Device Location Code provided.\n"); snprintf(event->addl_text, ADDL_TEXT_MAX, "%s, no " "location code provided", event_descs[index].desc); } return; } ppc64-diag-2.7.0/rtas_errd/ela.c0000644000000000000000000024012512642205425014754 0ustar rootroot/** * @file ela.c * * Copyright (C) 2005 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fru_prev6.h" #include "dchrp.h" #include "dchrp_frus.h" #include "rtas_errd.h" #include "ela_msg.h" /* Function prototypes */ static int analyze_io_bus_error(struct event *, int, int); static int get_error_type(struct event *, int); static int report_srn(struct event *, int, struct event_description_pre_v6 *); static char *get_loc_code(struct event *, int, int *); static int report_menugoal(struct event *, char *, ...); static int report_io_error_frus(struct event *, int, struct event_description_pre_v6 *, struct device_ela *, struct device_ela *); static int get_cpu_frus(struct event *); static int process_v1_epow(struct event *, int); static int process_v2_epow(struct event *, int); static int process_v3_epow(struct event *, int, int); static int sensor_epow(struct event *, int, int); static void unknown_epow_ela(struct event *, int); static int process_v2_sp(struct event *, int); static int process_v3_logs(struct event *, int); static int convert_symptom(struct event *, int, int, char **); static int process_refcodes(struct event *, short *, int); extern char *optarg; /* Macro to determine if there location codes in the buffer */ #define LOC_CODES_OK ((event->loc_codes != NULL) && strlen(event->loc_codes)) /* Global saved io error type with Bridge Connection bits. */ int io_error_type = 0; #define IO_BRIDGE_MASK 0x0FFF0FFF /* mask off byte 13, bits 0-3 */ /* of error_type to get io_error_type */ #define PTABLE_SIZE 4 int pct_index = 0; int percent_table[2][PTABLE_SIZE+1][PTABLE_SIZE] = { {{0,0,0,0}, {100,0,0,0}, {67,33,0,0}, {50,30,20,0}, {40,30,20,10}}, {{0,0,0,0}, {100,0,0,0}, {50,50,0,0}, {33,33,33,0}, {25,25,25,25}} }; /* * Table to hold ref codes from the error log entry prior * to filling out the error description. */ short rctab[MAXREFCODES+1]; /* * And a "shadow" table to hold number of location codes per ref code */ char rctabloc[MAXREFCODES+1]; char * get_tod() { time_t t; time(&t); return (asctime(localtime(&t))); } /** * convert_bcd * @brief Convert decimal number to hex number * * Converts num into hex number that will display as decimal. * i.e. binary 0x1010 becomes 0x10000 * A 10 * * @param num decimal number to convert * @returns converted number */ static int convert_bcd(int num) { char tempnum[10]; sprintf(tempnum, "%d", num); num = strtol(tempnum, NULL, 16); return num; } /** * get_refcode * */ static char * get_refcode(struct event_description_pre_v6 *event, int index) { static char rfc[80]; if (strcmp(event->frus[index].fname, "REF-CODE") == 0) { sprintf(rfc, "%04hX%04hX", event->frus[index].fmsg, event->frus[index].conf); dbg("reference code \"%s\"", rfc); return rfc; } return NULL; } /** * add_more_descrs * */ int add_more_descrs(struct event *event, struct event_description_pre_v6 *ptr) { int i, rc = 0; char *frupn = NULL; char *refcode; char na[] = "n/a"; i = 0; while (i < MAXFRUS && ptr->frus[i].conf != 0) { if (ptr->frus[i].floc[0]) frupn = diag_get_fru_pn(event, ptr->frus[i].floc); else strcpy(ptr->frus[i].floc, na); if (frupn == NULL) frupn = na; refcode = get_refcode(ptr, i); if (refcode == NULL) refcode = na; add_callout(event, ' ', 0, refcode, ptr->frus[i].floc, frupn, NULL, NULL); dbg("loc = \"%s\",\nfrupn = \"%s\",\nrefcode = \"%s\"", ptr->frus[i].floc, frupn, refcode); i++; } return rc; } /** * set_srn_and_callouts * @brief Determines the SRN and creates callout structs * * Note that the sl_entry struct in event struct (1st parameter) must be * allocated before calling this routing. * * @param event the event on which to operate * @param ptr the description of the event as established by ELA * @param post_error 0 if not a post error; post error code otherwise * @return 0 on success, -1 on failure. */ int set_srn_and_callouts(struct event *event, struct event_description_pre_v6 *ptr, unsigned post_error) { char srn[80]; int i; char *frupn = NULL; char *refcode; char na[] = "n/a"; dbg("pre-v6 event: flags = %d, sn = %d, rcode = %d, rmsg = %d\n" "dname = \"%s\"", ptr->flags, ptr->sn, ptr->rcode, ptr->rmsg, ptr->dname); if (post_error == 0) snprintf(srn, 80, "%03hX-%03hX", ptr->sn, ptr->rcode); else snprintf(srn, 80, "%0X", post_error); event->sl_entry->refcode = strdup(srn); if (!event->sl_entry->refcode) { log_msg(event, "Memory allocation failed, at " "event->l_entry->refcode"); return -1; } /* strdup(sl_entry->refcode) */ dbg("SRN: \"%s\"", event->sl_entry->refcode); i = 0; while (i < MAXFRUS && ptr->frus[i].conf != 0) { if (ptr->frus[i].floc[0]) frupn = diag_get_fru_pn(event, ptr->frus[i].floc); else strcpy(ptr->frus[i].floc, na); if (frupn == NULL) frupn = na; refcode = get_refcode(ptr, i); if (refcode == NULL) refcode = na; dbg("formatting fru list \"%s\", frupn = \"%s\"\n" "refcode = \"%s\"", ptr->frus[i].floc, frupn, refcode); add_callout(event, ' ', 0, refcode, ptr->frus[i].floc, frupn, NULL, NULL); i++; } return 0; } /** * add_cpu_id * * Adds the physical cpu id number to the logical name procx for an * event that calls out a processor. * * @returns 0 if valid cpuid was added to the event data * @returns 1 if invalid cpuid was input, so event data changed to proc0 */ int add_cpu_id(struct event_description_pre_v6 *ptr, int fru_num, int cpuid) { int rc = 0; if (cpuid > 0) cpuid--; /* physical cpu id indexed from 1 */ else { cpuid = 0; rc = 1; } /* Stuff the cpuid in for the 'x' of "procx" */ ptr->frus[fru_num].fname[4] = '0' + cpuid; /* Set the fru name is not in the db */ ptr->frus[fru_num].fname[0] = '\0'; return rc; } /** * set_fru_percentages * * Sets the fru percentages (probablity of failure) from the global * table that is based on the number of FRUs. Used for unknown events * and post errors when want to report the physical location codes * from RTAS. */ void set_fru_percentages(struct event_description_pre_v6 *event, int nfrus) { int *percent; int i; if (nfrus > MAXFRUS) nfrus = MAXFRUS; if (nfrus < PTABLE_SIZE) percent = percent_table[pct_index][nfrus]; else percent = percent_table[pct_index][PTABLE_SIZE]; i = 0; while (i < nfrus) { event->frus[i].conf = *(percent + i); i++; } while (i < MAXFRUS) { event->frus[i].conf = 0; i++; } return; } /** * get_register_data * * Look in the product specific area of the CHRP error log for the * register data. The format of the vendor specific area is: * "IBM" NULL location_code_string NULL register_data * where register_data begins on a 4 byte boundary and is (any number of): * length (2 bytes, which includes the length) id (2 bytes) * and register (length - 4). * The register_data is terminated by length = 2, i.e. no id and no data. * * RETURNS: * NULL if register for id is not found * Otherwise an integer pointer to the data portion (not the length * or id) of the register data, and rlen is set to the length of the * data returned. */ int * get_register_data(struct event *event, int rid, int *rlen) { char *p, *q; char *end; int length_id; int length; int id; int *rdata; *rlen = 0; rdata = NULL; end = event->event_buf + event->length; /* Find start of register data fields * look for location code id and string */ if ((p = strstr(&event->event_buf[I_IBM], "IBM")) != NULL) { q = p + strlen(p) + 1; /* step over "IBM" */ /* * The location codes are padded to end on 4 byte * boundary. So look for NULL as last byte of 4 bytes. */ while ((*(int *)q & 0xFF && q < end)) q += 4; p = q + 4; /* points to 1st register data field */ /* Make sure pointing to meaningful data */ if (p >= end) return NULL; } else /* There is no register data */ return NULL; /* Look at each register data field until * the requested id is found. * */ do { length_id = *(int *)p; /* 2 bytes length, 2 bytes id */ length = length_id >> 16; dbg("found register data in log, length = 0x%x", length); /* Make sure pointing can reach meaningful data */ if (length <= 0) return NULL; id = length_id & 0xFFFF; dbg("id = 0x%x", id); p += sizeof(int); /* next 4 bytes after length_id */ length -= 2; /* subtract the length of the length */ if (length > 0) { /* is there data to inspect? */ length -= 2; /* subtract the length of the id */ if (id == rid) { /* This is the requested register */ *rlen = length; rdata = (int *)p; break; /* found, so out of loop */ } else { /* Not it, so ignore this register data */ p = p + length; } } /* nothing found, and going beyond the data */ if (p >= end) return NULL; } while (length > 0); return rdata; } /* * Data to manage the EPOW reset error log entries. */ struct epow_reset { struct epow_reset *next; unsigned err_type; int valid_reset; uint err_sequence; uint err_id; }; static struct epow_reset *epow_reset_list = NULL; /** * save_epow_reset * * If this is Auto ELA, go ahead and search for the original EPOW this * one is reseting. If not Auto ELA, save the reset for reference when * the original EPOW is processed. * * RETURNS: * 1 if diagnostic conclusion, * otherwise 0, unless an error, then -1. * */ int save_epow_reset(struct event *event, int error_type) { struct epow_reset *new_reset; new_reset = malloc(sizeof(*new_reset)); if (new_reset == NULL) return -1; new_reset->err_type = error_type; new_reset->valid_reset = 1; new_reset->err_sequence = event->errdata.sequence; new_reset->err_id = event->errdata.err_id; /* Add to the front of the list */ new_reset->next = epow_reset_list; epow_reset_list = new_reset; return 0; } /** * has_epow_reset * * Determine if this error (the input) has been reset by an earilier * EPOW reset. * * RETURNS: * 1 if diagnostic conclusion, * otherwise 0. unless an error, then -1. */ int has_epow_reset(struct event *event, int error_type) { struct epow_reset *erptr; uint corrected_seq; erptr = epow_reset_list; /* Search for an occurance of the error_type */ while (erptr != NULL) { if (erptr->err_type == (error_type & 0xFFFFFF00)) { /* found a match */ erptr->valid_reset = 0; /* don't report again */ /* Store the sequence number of the EPOW_SUS_CHRP. This sequence number is used in the menugoal text. */ corrected_seq = event->errdata.sequence; /* Link the menugoal with the sequence number and error ID of the EPOW_RES_CHRP. */ event->errdata.sequence = erptr->err_sequence; event->errdata.err_id = erptr->err_id; report_menugoal(event, MSGMENUG202, corrected_seq); return 1; } erptr = erptr->next; } return 0; } /** * process_epow * * @brief Determine the version of the EPOW error log and process accordingly. * */ int process_epow(struct event *event, int error_type) { int rc = 0; if ((error_type & 0xFF000000) == EPOWLOG) { if ((error_type & 0x0F) == 0) { /* This is an EPOW reset, so save it */ /* and go to the next (older) error */ rc = save_epow_reset(event, error_type); } else if ((rc = has_epow_reset(event, error_type))) { /* this error has been reset */ /* continue */ } else if (event->event_buf[0] == 0x01) { /* Version 1 EPOW Log */ rc = process_v1_epow(event, error_type); } else /* Version 2 EPOW Log */ rc = process_v2_epow(event, error_type); } return rc; } /** * process_pre_v6 * @brief Handle older (pre-v6) style events * * @param event the event to be parsed * @return always returns 0 */ int process_pre_v6(struct event *event) { int error_fmt; int error_type; char *loc; int cpuid; struct event_description_pre_v6 *e_desc; int fru_index; struct device_ela sigdev; struct device_ela sendev; int sid, sed; int post_error_code; int i; short *refc; int rlen; int deconfig_error = 0; int predictive_error = 0; int repair_pending = 0; int rc; int loc_mode; int ignore_fru; char *devtree = NULL; char target[80]; struct rtas_event_exthdr *exthdr; dbg("Processing pre-v6 event"); /* Reset for this analysis */ if (event->loc_codes != NULL) { free(event->loc_codes); event->loc_codes = NULL; } exthdr = rtas_get_event_exthdr_scn(event->rtas_event); if (exthdr == NULL) { log_msg(event, "Could not retrieve extended event data"); return 0; } /* create and populate an entry to be logged to servicelog */ event->sl_entry = calloc(1, sizeof(struct sl_event)); if (event->sl_entry == NULL) { log_msg(event, "Memory allocation failed"); return -1; } event->sl_entry->time_event = get_event_date(event); event->sl_entry->type = SL_TYPE_BASIC; event->sl_entry->severity = servicelog_sev(event->rtas_hdr->severity); event->sl_entry->serviceable = 1; exthdr = rtas_get_event_exthdr_scn(event->rtas_event); if (exthdr) { if (exthdr->predictive) event->sl_entry->predictive = 1; if (exthdr->recoverable) event->sl_entry->disposition = SL_DISP_RECOVERABLE; else if (exthdr->unrecoverable_bypassed) event->sl_entry->disposition = SL_DISP_BYPASSED; else if (exthdr->unrecoverable) event->sl_entry->disposition = SL_DISP_UNRECOVERABLE; } event->sl_entry->raw_data_len = event->length; event->sl_entry->raw_data = malloc(event->length); if (event->sl_entry->raw_data == NULL) { free(event->sl_entry); log_msg(event, "Memory allocation failed"); return -1; } memcpy(event->sl_entry->raw_data, event->event_buf, event->length); deconfig_error = exthdr->unrecoverable_bypassed; predictive_error = exthdr->predictive; dbg("CHRP log data: recovered_error = 0x%x, deconfigured_error = 0x%x\n" "predictive_error = 0x%x", exthdr->recoverable, deconfig_error, predictive_error); /* * Look for the "IBM" vendor tag at end of chrp error log. * Copy location code string into re->loc_codes. */ if ((loc = strstr((char *)&event->event_buf[I_IBM], "IBM")) != NULL) { /* loc code is a null terminated string beginning at loc + 4 */ if (strlen(loc + 4)) { event->loc_codes = strdup(loc+4); if (!event->loc_codes) { log_msg(event, "Memory allocation failed, at event->loc_codes"); return 0; } /* strdup (event->loc_codes) */ } } /* vendor tag */ /* * First, see if there is any SRC data with the "02" id. * If so, create an error description from the ref. codes. */ refc = (short *)get_register_data(event, SRC_REG_ID_02, &rlen); if (refc != NULL) { process_refcodes(event, refc, rlen); return 0; } /* Otherwise process the sympton bits in the CHRP error log. */ io_error_type = 0; error_fmt = get_error_fmt(event); error_type = get_error_type(event, error_fmt); dbg("CHRP log data: error_fmt = 0x%x, error_type = 0x%x, \n" "io_error_type = 0x%x", error_fmt, error_type, io_error_type); /* * Any predictive, unrecoverable error-degraded mode error will be * reported in V3 style SRN, regardless of error log format, so * check for it here. */ if (deconfig_error && predictive_error) { /* * Make sure the FRUs in this log have not already been * deconfigured by the platform. Search the device tree for * deconfigured status for all FRUs listed in this error log. * Should only be one FRU, but will handle multiple FRUs. Only * if all FRUs are deconfigured, is this error log ignored. */ loc_mode = FIRST_LOC; ignore_fru = FALSE; while ((loc = get_loc_code(event, loc_mode, NULL)) != NULL) { loc_mode = NEXT_LOC; if (devtree == NULL) devtree = get_dt_status(NULL); if (devtree) { sprintf(target, "%s fail-offline", loc); if (strstr(devtree, target)) { /* found FRU and status in devtree */ /* can ignore this fru */ ignore_fru = TRUE; continue; } else { /* fru not disabled */ /* can not ignore this error log */ ignore_fru = FALSE; break; } } } if (ignore_fru == TRUE) return 0; /* FRUs have not been disabled by the platform */ v3_errdscr[0].sn = SN_V3ELA + error_fmt; v3_errdscr[0].sn |= 0x010; /* encode the predictive/deferred bit */ v3_errdscr[0].rcode = 0x500; v3_errdscr[0].rmsg = PREDICT_UNRECOV; if (error_fmt == RTAS_EXTHDR_FMT_CPU) { /* check if the "repair pending an IPL" bit is set */ repair_pending = event->event_buf[I_BYTE24] & 0x80; if (repair_pending) { v3_errdscr[0].rcode = 0x560; v3_errdscr[0].rmsg = PREDICT_REPAIR_PENDING; } } report_srn(event, 0, v3_errdscr); return 0; } else if (deconfig_error && error_fmt == RTAS_EXTHDR_FMT_IBM_SP && event->loc_codes != NULL) { /* * An error was found and the resource has been * deconfigured to bypass the error. */ report_srn(event, 0, &bypass_errdscr[0]); return 0; } if ( ! process_v3_logs(event, error_type) && /* v3 and beyond */ ! process_epow(event, error_type) && /* v1 and v2 EPOWs */ ! process_v2_sp(event, error_type)) { if (predictive_error) fru_index = 1; else fru_index = 0; /* all POST and version 1 non-EPOW error logs */ switch (error_type) { case CPUB12b0: /* CPU internal error */ cpuid = event->event_buf[I_CPU]; e_desc = &cpu610[fru_index]; add_cpu_id(e_desc, 0, cpuid); report_srn(event, 0, e_desc); break; case CPUB12b1: /* CPU internal cache error */ cpuid = event->event_buf[I_CPU]; e_desc = &cpu611[fru_index]; add_cpu_id(e_desc, 0, cpuid); report_srn(event, 0, e_desc); break; case CPUB12b2: /* L2 cache parity or multi-bit ECC error */ e_desc = &cpu612[fru_index]; report_srn(event, 0, e_desc); break; case CPUB12b3: /* L2 cache ECC single-bit error */ report_srn(event, 0, &cpu613[fru_index]); break; case CPUB12b4: /* TO error waiting for memory controller */ report_srn(event, 0, &cpu614[0]); break; case CPUB12b5: /* Time-out error waiting for I/O */ report_srn(event, 0, &cpu615[0]); break; case CPUB12b6: /* Address/Data parity error on Processor bus */ case CPUB12b7: /* Transfer error on Processor bus */ /* * The RTAS frus can be planar,cpu,[cpu] in any order. * The err descriptions require planar,cpu,[cpu], so * parse location codes to determine which error * descriptions then arrange RTAS data to fit * error description. */ rc = get_cpu_frus(event); if (rc == RC_PLANAR) { if (error_type == CPUB12b6) e_desc = &cpu710[0]; else e_desc = &cpu713[0]; report_srn(event, 0, e_desc); } else if (rc == RC_PLANAR_CPU) { if (error_type == CPUB12b6) e_desc = &cpu711[0]; else e_desc = &cpu714[0]; report_srn(event, 0, e_desc); } else if (rc == RC_PLANAR_2CPU) { if (error_type == CPUB12b6) e_desc = &cpu712[0]; else e_desc = &cpu715[0]; report_srn(event, 0, e_desc); } else { report_srn(event, 0, &cpu619[0]); } break; case CPUALLZERO:/* Unknown error detected by CPU Error log */ case MEMALLZERO:/* Unknown error detected by mem. controller */ case IOALLZERO: /* Unknown error detected by I/O device */ if (error_type == CPUALLZERO) e_desc = &cpu619[0]; else if (error_type == MEMALLZERO) e_desc = &mem629[0]; else e_desc = &io639[0]; report_srn(event, 0, e_desc); break; case MEMB12b0: /* Uncorrectable Memory Error */ /* log didn't contain dimm element # */ /* or dimm type is unknown, then */ /* check memory status */ report_srn(event, 0, &memtest600[0]); break; case MEMB12b1: /* ECC correctable error */ case MEMB12b2: /* Correctable error threshold exceeded */ pct_index = 1; /* * log didn't contain dimm element # or dimm type is * unknown, then check memory status */ report_srn(event, 0, &memtest600[0]); pct_index = 0; break; case MEMB12b3: /* Memory Controller internal error */ report_srn(event, 0, &mem624[0]); break; case MEMB12b4: /* Memory Address (Bad addr going to memory) */ report_srn(event, 0, &mem625[0]); break; case MEMB12b4B13b3: /* I/O Bridge T/O and Bad Memory Address */ report_menugoal(event, MSGMENUG174); return 0; break; case MEMB12b5: /* Memory Data (Bad data going to memory) */ report_srn(event, 0, &mem626[0]); break; case MEMB12b6: /* Memory bus/switch internal error */ /* memory bus/switch not yet implemented. */ break; case MEMB12b7: /* Memory time-out error */ report_srn(event, 0, &mem627[0]); break; case MEMB13b0: /* Processor Bus parity error */ add_cpu_id(&mem722[0], 0, 0); /* * calling out processor, but don't know which * one, so default to proc0 and let location * code point out failing proc */ report_srn(event, 0, &mem722[0]); break; case MEMB13b1: /* Processor time-out error */ add_cpu_id(&mem628[0], 0, 0); /* * calling out processor, but don't know which * one, so default to proc0 and let location * code point out failing proc */ report_srn(event, 0, &mem628[0]); break; case MEMB13b2: /* Processor bus Transfer error */ add_cpu_id(&mem723[0], 0, 0); /* * calling out processor, but don't know which * one, so default to proc0 and let location * code point out failing proc */ report_srn(event, 0, &mem723[0]); break; case MEMB13b3: /* I/O Host Bridge time-out error */ report_srn(event, 0, &mem724[0]); break; case MEMB13b4: /* I/O Host Bridge address/data parity error */ report_srn(event, 0, &mem725[0]); break; case IOB12b0: /* I/O Bus Address Parity Error */ case IOB12b1: /* I/O Bus Data Parity Error */ case IOB12b2: /* I/O Time-out error */ /* Version 1 and 2 look the same here. */ analyze_io_bus_error(event, 1, error_type); break; case IOB12b3: /* I/O Device Internal Error */ if (io_error_type == IOB12b3B13b2) { /* Int Err, bridge conn. to i/o exp. bus */ report_srn(event, 0, &io634[fru_index]); break; /* out of switch statement */ } e_desc = &io832[0]; sid = 0; sed = 0; if (sid == 0) { e_desc->rcode = sigdev.led; } else if (sed == 0) { e_desc->rcode = sendev.led; } else { /* isolated only to pci bus */ e_desc->rcode = 0x2C9; } report_srn(event, 0, e_desc); break; case IOB12b4: /* I/O Error on non-PCI bus */ report_srn(event, 0, &io730[0]); break; case IOB12b5: /* Mezzanine/Processor Bus Addr. Parity Error */ if (io_error_type == IOB12b5B13b1) { /* Mezzanine/Proc. Bus Addr. Parity Error */ report_srn(event, 0, &io733[fru_index]); break; } if (io_error_type == IOB12b5B13b2) { /* Mezzanine/Proc. Bus Addr. Parity Error */ report_srn(event, 0, &io770[fru_index]); break; } /* Default for IOB12b5, including IOB12b5B13b0. */ report_srn(event, 0, &io731[fru_index]); break; case IOB12b6: /* Mezzanine/Processor Bus Data Parity Error */ if (io_error_type == IOB12b6B13b1) { /* Mezzanine/Proc. Bus Data Parity Error */ report_srn(event, 0, &io734[fru_index]); break; } if (io_error_type == IOB12b6B13b2) { /* Mezzanine/Proc. Bus Addr. Parity Error */ report_srn(event, 0, &io771[fru_index]); break; } if (io_error_type == IOB12b6B13b3) { /* Err detected by i/o exp. bus controller */ report_srn(event, 0, &io773[fru_index]); break; } /* Default for IOB12b6, including IOB12b6B13b0. */ report_srn(event, 0, &io732[fru_index]); break; case IOB12b7: /* Mezzanine/Processor Bus Time-out Error */ if (io_error_type == IOB12b7B13b1) { /* Mezzanine/Processor Bus Time-out Error */ report_srn(event, 0, &io736[fru_index]); break; } if (io_error_type == IOB12b7B13b2) { /* Mezzanine/Proc. Bus Addr. Parity Error */ report_srn(event, 0, &io772[fru_index]); break; } /* Default for IOB12b7, including IOB12b7B13b0. */ report_srn(event, 0, &io735[fru_index]); break; case IOB13b4: /* I/O Expansion Bus Parity Error */ report_srn(event, 0, &io630[fru_index]); break; case IOB13b5: /* I/O Expansion Bus Time-out Error */ report_srn(event, 0, &io631[fru_index]); break; case IOB13b6: /* I/O Expansion Bus Connection Failure */ report_srn(event, 0, &io632[fru_index]); break; case IOB13b7: /* I/O Expansion Bus Connection Failure */ report_srn(event, 0, &io633[fru_index]); break; case SPB16b0: /* T.O. communication response from SP */ report_srn(event, 0, &sp740[0]); break; case SPB16b1: /* I/O (I2C) general bus error */ report_srn(event, 0, &sp640[0]); break; case SPB16b2: /* Secondary I/O (I2C) general bus error */ report_srn(event, 0, &sp641[0]); break; case SPB16b3: /* Internal Service Processor memory error */ report_srn(event, 0, &sp642[0]); break; case SPB16b4: /* SP error accessing special registers */ report_srn(event, 0, &sp741[0]); break; case SPB16b5: /* SP reports unknown communication error */ report_srn(event, 0, &sp742[0]); break; case SPB16b6: /* Internal Service Processor firmware error */ report_srn(event, 0, &sp643[0]); break; case SPB16b7: /* Other internal SP hardware error */ report_srn(event, 0, &sp644[0]); break; case SPB17b0: /* SP error accessing VPD EEPROM */ report_srn(event, 0, &sp743[0]); break; case SPB17b1: /* SP error accessing Operator Panel */ report_srn(event, 0, &sp744[0]); break; case SPB17b2: /* SP error accessing Power Controller */ report_srn(event, 0, &sp745[0]); break; case SPB17b3: /* SP error accessing Fan Sensor */ report_srn(event, 0, &sp746[0]); break; case SPB17b4: /* SP error accessing Thermal Sensor */ report_srn(event, 0, &sp747[0]); break; case SPB17b5: /* SP error accessing Voltage Sensor */ report_srn(event, 0, &sp748[0]); break; case SPB18b0: /* SP error accessing serial port */ report_srn(event, 0, &sp749[0]); break; case SPB18b1: /* SP error accessing NVRAM */ report_srn(event, 0, &sp750[0]); break; case SPB18b2: /* SP error accessing RTC/TOD */ report_srn(event, 0, &sp751[0]); break; case SPB18b3: /* SP error accessing JTAG/COP controller */ report_srn(event, 0, &sp752[0]); break; case SPB18b4: /* SP detect error with tod battery */ report_srn(event, 0, &sp753[0]); break; case SPB18b7: /* SP reboot system due to surv. time-out */ report_srn(event, 0, &sp760[0]); break; case POSTALLZERO: case POSTB12b0: /* Firmware error, revision level %s */ case POSTB12b1: /* Configuration error */ case POSTB12b2: /* CPU POST error */ case POSTB12b3: /* Memory POST error */ case POSTB12b4: /* I/O Subsystem POST error */ case POSTB12b5: /* Keyboard POST error */ case POSTB12b6: /* Mouse POST error */ case POSTB12b7: /* Graphic Adapter/Display POST error */ case POSTB13b0: /* Diskette Initial Program Load error */ case POSTB13b1: /* Drive Controller IPL error */ case POSTB13b2: /* CD-ROM Initial Program Load error */ case POSTB13b3: /* Hard disk Initial Program Load error */ case POSTB13b4: /* Network Initial Program Load error */ case POSTB13b5: /* Other Initial Program Load error */ case POSTB13b7: /* Self-test error in FW extended diagnostics */ /* All of the post error processing goes here. */ e_desc = &post[0]; e_desc->sn = -2; /* have to reset after insert_errdscr */ e_desc->rcode = 0; post_error_code = *(int *)&event->event_buf[I_POSTCODE]; /* Add any (upto 4) chrp location codes from the log */ loc = get_loc_code(event, FIRST_LOC, NULL); i = 0; while (loc && i < 4) { strcpy(e_desc->frus[i++].floc, loc); loc = get_loc_code(event, NEXT_LOC, NULL); } set_fru_percentages(e_desc, i); if (set_srn_and_callouts(event, e_desc, post_error_code)) return -1; break; } } return 0; } /** * analyze_io_bus_error * @brief Analyze the io bus errors, i.e. IOB12b0, IOB12b1, or IOB12b2. */ static int analyze_io_bus_error(struct event *event, int version, int error_type) { struct event_description_pre_v6 *e_desc; int fru_index; struct device_ela sigdev; struct device_ela sendev; int sid, sed; int rc = 0; memset(&sigdev, 0, sizeof(struct device_ela)); memset(&sendev, 0, sizeof(struct device_ela)); /* * if this is version 3 or beyond, and there is a physical location * code in the log, then just return for SRN encoding */ if (version >= 3 && LOC_CODES_OK) return 0; if (error_type == IOB12b0) fru_index = 0; else if (error_type == IOB12b1) fru_index = 1; else if (error_type == IOB12b2) fru_index = 2; else return 0; /* can't analyze this error type */ sid = 0; sed = 0; if (sid == 0 && sed == 0) { /* check if a device is parent (the bus) of the other device */ if ( ! strcmp(sigdev.busname, sendev.name)|| ! strcmp(sendev.busname, sigdev.name) ) { e_desc = &io9CC[fru_index]; report_io_error_frus(event, SN9CC, e_desc, &sigdev, &sendev); rc = 1; } else { /* 2 devices from error log */ e_desc = &io833[fru_index]; report_io_error_frus(event, 0x833, e_desc, &sigdev, &sendev); rc = 1; } } else if (sid == 0 || sed == 0) { /* 1 device only */ e_desc = &io9CC[fru_index]; report_io_error_frus(event, SN9CC, e_desc, &sigdev, &sendev); rc = 1; } else { /* bus only */ e_desc = &iobusonly[fru_index]; report_io_error_frus(event, SN9CC, e_desc, &sigdev, &sendev); rc = 1; } return rc; } /** * get_error_fmt * @brief Extract the error log format indicator from the chrp error log. * * @return An integer that is the error log format indicator. */ int get_error_fmt(struct event *event) { return (event->event_buf[I_FORMAT] & 0x0F); } /** * get_error_type * * Uses the error format to return the error bits as an unique * constant for each error. * * @return The error format and error bits as an unique integer. */ static int get_error_type(struct event *event, int fmt) { int error_type; switch (fmt) { case RTAS_EXTHDR_FMT_IBM_SP: error_type = fmt << 24 | event->event_buf[I_BYTE18] << 16 | event->event_buf[I_BYTE17] << 8 | event->event_buf[I_BYTE16]; break; case RTAS_EXTHDR_FMT_EPOW: error_type = fmt << 24 | event->event_buf[I_BYTE17] << 16 | event->event_buf[I_BYTE16] << 8 | (event->event_buf[I_BYTE15] & 0x0F); break; case RTAS_EXTHDR_FMT_CPU: error_type = fmt << 24 | event->event_buf[I_BYTE12]; break; case RTAS_EXTHDR_FMT_IO: /* * First, get the complete io error type, which * includes some info bits. */ io_error_type = fmt << 24 | event->event_buf[I_BYTE13] << 8 | event->event_buf[I_BYTE12]; /* But, return just the sympton bits. */ error_type = io_error_type & IO_BRIDGE_MASK; break; default: error_type = fmt << 24 | event->event_buf[I_BYTE13] << 8 | event->event_buf[I_BYTE12]; } return error_type; } /** * report_srn */ int report_srn(struct event *event, int nlocs, struct event_description_pre_v6 *e_desc) { int i; char *loc; short save_sn; int numLocCodes; /* used in case there are more FRUs than MAXFRUS */ struct event_description_pre_v6 *temp_event; save_sn = e_desc->sn; /* save before insert_errdscr */ /* Add the chrp location codes if nlocs != 0 */ for (i = 0; i < nlocs; i++) { if (i == 0) loc = get_loc_code(event, FIRST_LOC, NULL); else loc = get_loc_code(event, NEXT_LOC, NULL); if (loc) strcpy(e_desc->frus[i].floc, loc); else break; } if (nlocs == 0) { /* * Build a error description that contains a fru for * each of the physical location codes. */ loc = get_loc_code(event, FIRST_LOC, &numLocCodes); i = 0; while (i < MAXFRUS) { if (loc != NULL) { strcpy(e_desc->frus[i].floc, loc); loc = get_loc_code(event, NEXT_LOC, NULL); } e_desc->frus[i].fmsg = 36; i++; } set_fru_percentages(e_desc, numLocCodes); } e_desc->sn = save_sn; if (set_srn_and_callouts(event, e_desc, 0)) return -1; /* if loc is not null, then there are more FRUs than MAXFRUS */ while (loc != NULL) { i = 0; numLocCodes = numLocCodes - MAXFRUS; /* allocate space for more FRUs */ temp_event = (struct event_description_pre_v6 *) calloc(1, sizeof(struct event_description_pre_v6)); /* copy everything over from the original event */ strcpy(temp_event->dname, e_desc->dname); temp_event->flags = e_desc->flags; temp_event->sn = e_desc->sn; temp_event->rcode = e_desc->rcode; temp_event->rmsg = e_desc->rmsg; /* Prepare to add more FRUs */ while (i < MAXFRUS) { if (loc != NULL) { strcpy(temp_event->frus[i].floc, loc); loc = get_loc_code(event, NEXT_LOC, NULL); } temp_event->frus[i].fmsg = 36; i++; } set_fru_percentages(temp_event, numLocCodes); temp_event->sn = save_sn; /* Log additional error descriptions */ if (add_more_descrs(event, temp_event)) return -1; free(temp_event); } event->sl_entry->call_home_status = SL_CALLHOME_CANDIDATE; event->sl_entry->description = malloc(strlen(e_desc->rmsg)+1); if (event->sl_entry->description == NULL) { log_msg(event, "Memory allocation failed"); return -1; } strcpy(event->sl_entry->description, e_desc->rmsg); dbg("srn: \"%s\"", event->sl_entry->refcode); return 0; } /** * get_loc_code * * Gets a physical location codes from the chrp error log. This is * called to get either the first location code or the next location * code. When called to get the first location code, the number of * location codes present in the log is returned. * * The string of location codes is null terminated. However a special * character, ">", means that the location codes that follow should not * be reported to the user via diagnostics. Therefore, processing of * location codes will stop at the first occurance of ">" or a null * terminator. * * RETURNS: * If nlocs is not NULL, returns the count of location codes in the buffer. * NULL if location code not found. * Otherwise a pointer to location code string. * */ char * get_loc_code(struct event *event, int mode, int *nlocs) { char *loc; int prev_space = 0; static char *copyLCB = NULL; static char *save_copyLCB = NULL; static char *start_loc = NULL; /* start or next pointer for loc code */ static char *end_loc = NULL; /* end of location code buffer */ if (! LOC_CODES_OK) { if (nlocs) *nlocs = 0; return NULL; } if (mode == FIRST_LOC) { if (save_copyLCB) { /* throw away the previous allocation of buffer */ /* even though not used up by get next calls */ free(save_copyLCB); copyLCB = NULL; } copyLCB = malloc(strlen(event->loc_codes) + 1); if (copyLCB == NULL) return NULL; save_copyLCB = copyLCB; strcpy(copyLCB, event->loc_codes); start_loc = copyLCB; /* Force processing to stop at special "Hide" character */ loc = strchr(copyLCB, LOC_HIDE_CHAR); if (loc != NULL) *loc = 0; end_loc = copyLCB + strlen(copyLCB); /* * The number of location codes is determined by the number * of (non-consecutive) spaces in the log, i.e. * 1 space = 2 location codes */ if (nlocs != NULL) { loc = copyLCB; if (*loc) { *nlocs = 0; /* nothing found until !space */ prev_space = 1; /* handle leading spaces */ while (*loc) { if (*loc == ' ') { if (! prev_space) *nlocs = *nlocs + 1; prev_space = 1; } else prev_space = 0; loc++; } if (! prev_space) /* count last location code */ *nlocs = *nlocs + 1; } else *nlocs = 0; /* null means no loc. codes */ } } loc = start_loc; if (loc < end_loc && *loc != 0x0) { /* loc is the start of a location code */ /* use start_loc to find end of location code string */ /* find 1st occurance of null or blank, the loc. code delimit */ while (*loc == ' ') loc++; /* skip leading blanks */ start_loc = loc; while (*start_loc && *start_loc != ' ') start_loc++; *start_loc = 0x0; /* terminate loc string */ start_loc++; /* ready for next call */ return loc; /* return loc */ } else { return NULL; } } /** * get_ext_epow * @brief Get the extended epow status bytes from the chrp log. * * The extended epow data is 2 bytes stored as the MSB of an integer. * * @return the extended epow register from the vendor specific area. */ int get_ext_epow(struct event *event) { int *extepow; int extepowlen; extepow = get_register_data(event, EXT_EPOW_REG_ID, &extepowlen); if (extepow == NULL) return 0; /* I have 0xaabbccdd */ /* I want 0x0000aabb */ return (*extepow >> 16); } /** * get_fan_number */ int get_fan_number(int ext_epow) { int fan; fan = ext_epow & SENSOR_MASK; fan = fan >> 8; return fan; } /** * report_menugoal * @brief Report a menu goal with optional variable substitution into the text. * * The second paramater must always be the menu number (as an uint). * * @returns Always returns 0 */ int report_menugoal(struct event *event, char *fmt, ...) { va_list argp; int offset; char buffer[MAX_MENUGOAL_SIZE], *msg, menu_num_str[20]; int rlen; short *refc; unsigned refcode; buffer[0]='\0'; va_start(argp, fmt); offset = sprintf(buffer, fmt, argp); va_end(argp); if (strlen(buffer)) { /* * There is a menugoal. If this menugoal is from ELA, * check if a ref. code exists in the error log. */ if (event->errdata.sequence) { refc = (short *)get_register_data(event, SRC_REG_ID_04, &rlen); if (refc) { int msglen; /* There is a refcode; append to the menugoal */ refcode = *(uint *)refc; msglen = strlen(MSGMENUG_REFC) + 2 * sizeof(refcode) + 1; if (strlen(buffer) + msglen < MAX_MENUGOAL_SIZE) { offset += sprintf(buffer + offset, MSGMENUG_REFC, refcode); } /* * Check if there are location codes * supporting the refcode */ if (LOC_CODES_OK) { /* * append to menugoal as * supporting data */ msglen = strlen(MSGMENUG_LOC) + strlen(event->loc_codes) + 1; if (strlen(buffer) + msglen < MAX_MENUGOAL_SIZE) { offset += sprintf( buffer + offset, MSGMENUG_LOC, event->loc_codes); } } } } snprintf(menu_num_str, 20, "#%d", atoi(buffer)); event->sl_entry->refcode = malloc( strlen(menu_num_str)+1); if (event->sl_entry->refcode == NULL) { log_msg(event, "Memory allocation failed.\n"); return -1; } strcpy(event->sl_entry->refcode, menu_num_str); msg = strchr(buffer, ' ') + 1; event->sl_entry->description = malloc(strlen(msg)+1); if (event->sl_entry->description == NULL) { free(event->sl_entry->refcode); log_msg(event, "Memory allocation failed.\n"); return -1; } strcpy(event->sl_entry->description, msg); dbg("menugoal: number = %s, message = \"%s\"", menu_num_str, msg); } return 0; } /** * report_io_error_frus * * Build error description for i/o detected errors. The number of frus is * determined by the number of devices returned in the error log. */ int report_io_error_frus(struct event *event, int sn, struct event_description_pre_v6 *e_desc, struct device_ela *sig, struct device_ela *sen) { char *loc; int i; char *p; int swap_locs = 0; if (sig->status == DEVICE_OK && sen->status == DEVICE_OK) { /* 2 devices returned from error log */ /* if one is non integrated, use it for the srn */ /* otherwise if one is not a bridge device use if the for srn */ if (sen->slot != 0) { e_desc->rcode = sen->led; strcpy(e_desc->frus[0].fname, sen->name); strcpy(e_desc->frus[1].fname, sig->name); if (sn == 0x833) strcpy(e_desc->frus[2].fname, sen->busname); } else if (sig->slot != 0) { e_desc->rcode = sig->led; strcpy(e_desc->frus[0].fname, sig->name); strcpy(e_desc->frus[1].fname, sen->name); if (sn == 0x833) strcpy(e_desc->frus[2].fname, sig->busname); swap_locs = 1; /* f/w list the sender 1st in log */ } else if (sen->devfunc != 0 || sig->devfunc == 0) { e_desc->rcode = sen->led; strcpy(e_desc->frus[0].fname, sen->name); strcpy(e_desc->frus[1].fname, sig->name); if (sn == 0x833) strcpy(e_desc->frus[2].fname, sen->busname); } else { e_desc->rcode = sig->led; strcpy(e_desc->frus[0].fname, sig->name); strcpy(e_desc->frus[1].fname, sen->name); if (sn == 0x833) strcpy(e_desc->frus[2].fname, sig->busname); swap_locs = 1; /* f/w list the sender 1st in log */ } } else if (sig->status == DEVICE_OK) { /* 1 device returned from error log */ e_desc->rcode = sig->led; strcpy(e_desc->frus[0].fname, sig->name); strcpy(e_desc->frus[1].fname, sig->busname); swap_locs = 1; /* f/w list the sender 1st in log */ } else if (sen->status == DEVICE_OK) { /* 1 device returned from error log */ e_desc->rcode = sen->led; strcpy(e_desc->frus[0].fname, sen->name); strcpy(e_desc->frus[1].fname, sen->busname); } else { if (sig->status == DEVICE_BUS) { strcpy(e_desc->frus[0].fname, sig->busname); p = sig->busname; swap_locs = 1; /* f/w list the sender 1st in log */ } else { strcpy(e_desc->frus[0].fname, sen->busname); p = sen->busname; } /* Convert number in busname, i.e. pcixx, */ /* where xx is 0 to 99, */ /* to integer 1xx for the reason code. */ while (! isdigit (*p) && *p != 0) p++; e_desc->rcode = atoi(p) + 0x100; } /* * Add any chrp location code from the log */ loc = get_loc_code(event, FIRST_LOC, NULL); i = 0; while (loc && i < 2) { /* this error description is for 2 frus */ /* * For the case when the signaling device is non-integrated, * the location codes must be swapped. */ if (swap_locs) { if (i == 0) { /* 1st loc code goes in 2nd fru */ /* but also puting loc in 1st fru */ /* in case there is only 1 loc. */ strcpy(e_desc->frus[0].floc, loc); strcpy(e_desc->frus[1].floc, loc); } else if ( i == 1 ) { /* 2nd loc code goes in 1st fru */ strcpy(e_desc->frus[0].floc, loc); } } else { /* Here if not swap_locs */ strcpy(e_desc->frus[i].floc, loc); } i++; loc = get_loc_code(event, NEXT_LOC, NULL); } if (i) set_fru_percentages(e_desc, i); if (set_srn_and_callouts(event, e_desc, 0)) return -1; return 0; } /* Its a planar if P and (not - and not /) */ #define is_planar(x) (x != NULL && strchr(x, 'P') && (!strchr(x,'-') && !strchr( x,'/'))) /* Its a CPU if 'C' */ #define is_cpu(x) (x != NULL && strchr(x, 'C')) #define is_not_fru(x) (x == NULL || strlen(x) == 0) /** * get_cpu_frus * * Gets the RTAS generated FRUs from a CPU detected error log * and arranges the frus to match the awaiting error description. * This should be called for CPUB12Bb6 and CPUB12b7 errors. * * OUTPUTS: The location code buffer is rearranged if necessary. * * RETURNS: RC_INVALID - if invalid or unknown combination of frus * RC_PLANAR - if only a planar fru is found * RC_PLANAR_CPU - if a planar and a CPU fru are found * RC_PLANAR_2CPU -if a planar and 2 CPUs frus are found */ static int get_cpu_frus(struct event *event) { char *buf, *tbuf = NULL, *free_me = NULL; char *loc1 = NULL, *loc2 = NULL, *loc3 = NULL; int nlocs = 0; int rc = RC_INVALID; buf = malloc(strlen(event->loc_codes)+4); if (buf == NULL) return 0; loc1 = buf; tbuf = get_loc_code(event, FIRST_LOC, &nlocs); if ((tbuf == NULL) || (nlocs < 1)) goto out; free_me = tbuf; strcpy(loc1, tbuf); if (nlocs > 1) { loc2 = loc1 + strlen(loc1) + 1; tbuf = get_loc_code(event, NEXT_LOC, NULL); if (tbuf == NULL) goto out; strcpy(loc2, tbuf); } if ( nlocs > 2 ) { loc3 = loc2 + strlen(loc2) + 1; tbuf = get_loc_code(event, NEXT_LOC, NULL); if (tbuf == NULL) goto out; strcpy(loc3, tbuf); } if (is_planar(loc1)) { if (is_not_fru(loc2)) rc = RC_PLANAR; else if (is_cpu(loc2)) { if (is_not_fru(loc3)) rc = RC_PLANAR_CPU; else if (is_cpu(loc3)) rc = RC_PLANAR_2CPU; } } else if (is_cpu(loc1)) { if (is_planar(loc2)) { if (is_not_fru(loc3)) { /* Rearrange locs as loc2, loc1 */ if (event->loc_codes != NULL) free(event->loc_codes); event->loc_codes = malloc(strlen(loc1) + strlen(loc2) + 2); if (event->loc_codes == NULL) goto out; sprintf(event->loc_codes, "%s %s", loc2, loc1); rc = RC_PLANAR_CPU; } else if (is_cpu(loc3)) { /* Rearrange loc as loc2, loc1, loc3 */ if (event->loc_codes != NULL) free(event->loc_codes); event->loc_codes = malloc(strlen(loc1) + strlen(loc2) + strlen(loc3) + 3); if (event->loc_codes == NULL) goto out; sprintf(event->loc_codes, "%s %s %s", loc2, loc1, loc3); rc = RC_PLANAR_2CPU; } /* is_cpu(loc3) */ } /* is_planar(loc2) */ } /* is_cpu(loc1) */ out: free(buf); free(free_me); return rc; } /** * process_v1_epow * @brief Analyze the Version 1 EPOW error log. * * INPUTS: * The encoded error type. * * RETURNS: * 1 if diagnostic conclusion, * otherwise 0. */ int process_v1_epow(struct event *event, int error_type) { int rc = 1; int class; int ext_epow; int ext_epow_nofan; int fan_num; /* * The following EPOW error logs found in CHRP, Ver. 1 * error logs. */ class = error_type & 0xFF; ext_epow = get_ext_epow(event); ext_epow_nofan = ext_epow & IGNORE_SENSOR_MASK; if (ext_epow == 0) { if (class == 5) { /* System shutdown due loss of AC power */ report_srn(event, 0, epow812); } else { /* This error log is unknow to ELA */ unknown_epow_ela(event, class); rc = -1; } } else switch (ext_epow_nofan) { case XEPOW1n11: /* Fan turning slow */ fan_num = get_fan_number(ext_epow); report_srn(event, 0, epow800); break; case XEPOW1n64: /* Fan stop was detected */ fan_num = get_fan_number(ext_epow); report_srn(event, 0, epow801); break; case XEPOW2n32: /* Over voltage condition */ report_srn(event, 0, epow810); break; case XEPOW2n52: /* Under voltage condition */ report_srn(event, 0, epow811); break; case XEPOW3n21: /* Over temperature condition */ report_srn(event, 0, epow820); break; case XEPOW3n73: /* Shutdown over max temp. */ report_srn(event, 0, epow821); break; default: /* This error log is unknow to ELA */ unknown_epow_ela(event, class); rc = -1; } return rc; } /** * loss_power_MG * * Displays the menu goal used for a Loss of Power EPOW. * Used by both V2 and V3 EPOW ELA. */ void loss_power_MG(struct event *event) { if (LOC_CODES_OK) report_menugoal(event, MSGMENUG150, event->loc_codes); else report_menugoal(event, MSGMENUG151); } /** * manual_power_off_MG * * Displays the menu goal used for Manual activation of power off button. * Used by both V2 and V3 EPOW ELA. */ void manual_power_off_MG(struct event *event) { /* need the timestamp from the error log */ /* need the error log sequence number */ /* and report this as a menugoal */ report_menugoal(event, MSGMENUG162, event->errdata.time_stamp, event->errdata.sequence); } /** * process_v2_epow * @brief Analyze the Version 2 and Version 3 EPOW error logs. * * @returns 1 if diagnostic conclusion, otherwise 0. */ int process_v2_epow(struct event *event, int error_type) { int rc = 1; int class; int *reg, rlen, ext_epow; class = error_type & 0xFF; /* * Look for an EPOW detected by a defined sensor. */ if (error_type & EPOWB16b0) rc = sensor_epow(event, error_type, 2); else if (error_type & EPOWB16b1) { /* look for power fault epow */ /* look for extended debug data in case necessary */ reg = get_register_data(event, PCI_EPOW_REG_ID, &rlen); if (reg) ext_epow = *reg & PCIEPOWMASK; if (error_type & EPOWB17b0) { /* unspecified cause for power fault */ /* report SRN only if frus in error log */ if (class < 3) { if (LOC_CODES_OK) report_srn(event, 0, epow809); else report_menugoal(event, MSGMENUG175); } else { if (LOC_CODES_OK) report_srn(event, 0, epow824); else report_menugoal(event, MSGMENUG175); } } else if (error_type & EPOWB17b1) { /* loss of power source */ /* first checking system specific data */ if (ext_epow == PCIEPOW111) /* AC power to entire system */ report_srn(event, 0, epow813); else if (ext_epow == PCIEPOW100) /* AC power to CEC */ report_srn(event, 0, epow814); else if (ext_epow == PCIEPOW011) /* AC power to I/O Rack */ report_srn(event, 0, epow815); else /* here if no system specific data */ loss_power_MG(event); } else if (error_type & EPOWB17b2) { /* internal power supply failure */ if (ext_epow == PCIEPOW001) /* 3/4 ps in I/O rack */ report_srn(event, 0, epow816); else if (ext_epow == PCIEPOW010) /* 1/4 ps in I/O rack */ report_srn(event, 0, epow817); else if (error_type & EPOWB16b4) { report_srn(event, 0, epow819red); } else report_srn(event, 0, epow819); } else if (error_type & EPOWB17b3) /* manual power off via op panel */ manual_power_off_MG(event); else { /* Reserved bits in EPOW log */ /* This error log is unknow to ELA */ unknown_epow_ela(event, class); rc = -1; } } else if (error_type & EPOWB16b2) { if (error_type & EPOWB16b4) { /* Loss of redundant fan */ report_srn(event, 0, epow652820); } else if (error_type & EPOWB16b3) { /* System shutdown - thermal & fan */ report_srn(event, 0, epow822); } else { if (class < 3) report_srn(event, 0, epow802); else report_srn(event, 0, epow823); } } else if (error_type & EPOWB16b3) { /* look for Over temperature conditions */ /* Over temperature condition */ report_srn(event, 0, epow821); } else if (error_type & EPOWB16b4) { /* look for loss of redundancy, without any other indication */ /* Loss of redundant power supply */ report_srn(event, 0, epow652810); } else /* This error log is unknown */ unknown_epow_ela(event, class); rc = -1; return rc; } /** * sensor_epow * * Analysis EPOW error logs that were detected by a defined sensor. * The resulting error description is different depending on the error log * version. Supports version 2 and 3. * * INPUTS: * The encoded error type. * * @returns 1 if diagnostic conclusion, otherwise 0. * */ int sensor_epow(struct event *event, int error_type, int version) { int class, token, index, redundancy, status; struct event_description_pre_v6 *e_desc; char sensor_name [256]; char fru_name[256]; int rc = 1; class = error_type & 0xFF; token = *(int*)&event->event_buf[I_TOKEN]; index = *(int*)&event->event_buf[I_INDEX]; redundancy = (error_type & LOGB16b4); status = *(int*)&event->event_buf[I_STATUS]; dbg("EPOW class = %d, token = %d, index = %d", class, token, index); switch (token) { case FAN: if (version == 3) { e_desc = v3_errdscr; e_desc->rcode = 0x10; } else { e_desc = fan_epow; e_desc->rcode = 0x830; } break; case VOLT: sprintf(fru_name, "%s", F_POWER_SUPPLY); sprintf(sensor_name, F_EPOW_ONE, F_VOLT_SEN_2, index + 1); if (version == 3) { e_desc = v3_errdscr; e_desc->rcode = 0x30; } else { e_desc = volt_epow; strcpy(e_desc->frus[0].fname, fru_name); strcpy(e_desc->frus[1].fname, sensor_name); e_desc->rcode = 0x831; } break; case THERM: sprintf(sensor_name, F_EPOW_ONE, F_THERM_SEN, index + 1); if (version == 3) { e_desc = v3_errdscr; e_desc->rcode = 0x50; } else { e_desc = therm_epow; strcpy(e_desc->frus[0].fname, sensor_name); e_desc->rcode = 0x832; } break; case POWER: sprintf(fru_name, F_EPOW_ONE, F_POWER_SUPPLY, index + 1); sprintf(sensor_name, "%s", F_POW_SEN); if (version == 3) { e_desc = v3_errdscr; e_desc->rcode = 0x70; } else { e_desc = pow_epow; strcpy(e_desc->frus[0].fname, fru_name); strcpy(e_desc->frus[1].fname, sensor_name); e_desc->rcode = 0x833; } break; default: if (version == 3) { e_desc = v3_errdscr; e_desc->rcode = 0x90; } else { e_desc = unknown_epow; e_desc->rcode += 0x839; } break; } if (version != 3) e_desc->sn = 0x651; if (redundancy) { if (version == 3) e_desc->sn |= 0x010; else e_desc->sn = 0x652; switch (token) { case FAN: if (version == 3) e_desc->rcode = 0x110; e_desc->rmsg = MSGRED_FAN; break; case POWER: if (version == 3) e_desc->rcode = 0x120; e_desc->rmsg = MSGRED_POWER; break; default: if (version == 3) e_desc->rcode = 0x130; e_desc->rmsg = MSGRED_UNK; break; } } else { switch (status) { case CRITHI: case CRITLO: switch (token) { case FAN: e_desc->rmsg = MSGCRIT_FAN; if (version == 3) { if (class > 2) { e_desc->rcode = 0x20; e_desc->rmsg = MSGCRIT_FAN_SHUT; } } break; case VOLT: e_desc->rmsg = MSGCRIT_VOLT; if (version == 3) { if (class > 2) { e_desc->rcode = 0x40; e_desc->rmsg = MSGCRIT_VOLT_SHUT; } } break; case THERM: e_desc->rmsg = MSGCRIT_THERM; if (version == 3) { if (class > 2) { e_desc->rcode = 0x60; e_desc->rmsg = MSGCRIT_THERM_SHUT; } } break; case POWER: e_desc->rmsg = MSGCRIT_POWER; if (version == 3) { if (class > 2) { e_desc->rcode = 0x80; e_desc->rmsg = MSGCRIT_POWER_SHUT; } } break; default: e_desc->rmsg = MSGCRIT_UNK; if (version == 3) { if (class > 2) { e_desc->rcode = 0x100; e_desc->rmsg = MSGCRIT_UNK_SHUT; } } break; } break; case WARNHI: case WARNLO: if (version == 3) e_desc->sn += 0x10; else e_desc->rcode += 0x10; switch (token) { case FAN: e_desc->rmsg = MSGWARN_FAN; break; case VOLT: e_desc->rmsg = MSGCRIT_VOLT; break; case THERM: e_desc->rmsg = MSGCRIT_THERM; break; case POWER: e_desc->rmsg = MSGCRIT_POWER; break; default: e_desc->rmsg = MSGCRIT_UNK; break; } break; default: if (status == NORMAL || status == GS_SUCCESS) return 0; /* ignore; not error */ else { /* here if error log indicates error */ /* from get-sensor-status */ if (LOC_CODES_OK) report_menugoal(event, MSGMENUG152, event->loc_codes); else report_menugoal(event, MSGMENUG153); return 0; /* don't report err */ } break; } } if (version != 3) /* adds any location codes from log */ report_srn(event, 0, e_desc); /* * Version 3 will be reported after return because there is more to * add to event */ return rc; } /** * unknown_epow_ela * * Makes a diagnostic conclusion, i.e. menu goal, for an error log that * is unknown to ELA for any of the following: * - non-product specific Version 1 logs * - unknown register debug data in log * - (thought to be) reserved bits set in log * * INPUTS: * the EPOW class */ void unknown_epow_ela(struct event *event, int class) { if (class < 3) { if (LOC_CODES_OK) report_menugoal(event, MSGMENUG156, event->loc_codes); else report_menugoal(event, MSGMENUG157); } else if ( class == 3 ) { if (LOC_CODES_OK) report_menugoal(event, MSGMENUG158, event->loc_codes, get_tod()); else report_menugoal(event, MSGMENUG159, get_tod); } else { if (LOC_CODES_OK) report_menugoal(event, MSGMENUG160, event->loc_codes); else report_menugoal(event, MSGMENUG161); } } /** * process_v2_sp * @brief Analyze the Version 2 SP error logs. * * INPUTS: * The encoded error type. * * @returns 1 if diagnostic conclusion, otherwise 0. */ int process_v2_sp(struct event *event, int error_type) { if (event->event_buf[0] != 0x02) return 0; /* not a version 2 log */ if ((error_type & 0xFF000000) != SPLOG) return 0; /* not a SP log */ if (event->event_buf[I_BYTE19] & 0x80) { /* Byte 19, bit 0 */ report_srn(event, 0, sp754); return 1; } dbg("Found unknown version 2 SP log"); return 0; } /** * process_v3_logs * @brief Analyze the Version 3 and beyond error logs. * * INPUTS: * The encoded error type. * * @returns 1 if diagnostic conclusion, otherwise 0. */ int process_v3_logs(struct event *event, int error_type) { int version; int platform_specific; int predictive; int replace_all; int concurrent; int sw_also; int format_type; int errdscr_ready = 0; int seqn; char *msg; version = event->event_buf[0]; if (version < 0x03) return 0; /* not a version 3 or beyond log */ /* Does log contain platform specific error code? */ platform_specific = event->event_buf[I_BYTE1] & 0x80; if (platform_specific) { /* get the error code nibble */ platform_specific = event->event_buf[I_BYTE1] & 0x0F; platform_error[0].rcode += platform_specific; report_srn(event, 0, platform_error); /* reset rcode to be correct for additional errors */ platform_error[0].rcode -= platform_specific; return 1; } /* Get error format type from log */ format_type = (error_type & 0xFF000000) >> 24; /* Treat POST detected errors as Version 1. */ if (format_type == RTAS_EXTHDR_FMT_POST) return 0; /* Encode the log format type into the SRN */ v3_errdscr[0].sn = SN_V3ELA + format_type; /* If predictive error, then modify source number */ predictive = event->event_buf[I_BYTE0] & 0x08; if (format_type == RTAS_EXTHDR_FMT_EPOW) { /* if ok, errdscr needs only modifier bits */ errdscr_ready = process_v3_epow(event, error_type, version); if (errdscr_ready == 2) return 1; /* refcode, so skip the rest */ } else { /* Convert symptom bits to sequence number. */ seqn = convert_symptom(event, format_type, predictive, &msg); if (seqn == 0x100) /* a menugoal was used in lieu of a SRN */ return 1; v3_errdscr[0].rcode = (seqn << 4); v3_errdscr[0].rmsg = msg; if (seqn == 0xFF) { /* Check for SRC (ref-code) data */ short *refc; int rlen; refc = (short *)get_register_data(event, SRC_REG_ID_04, &rlen); if (refc != NULL) { process_refcodes(event, refc, rlen); return 1; } /* Don't modify the SRN any further because of */ /* unknown symptom bits or error log format. */ report_srn(event, 0, v3_errdscr); return 1; } errdscr_ready = 1; } /* Ok to continue encoding the SRN. */ if (predictive) v3_errdscr[0].sn |= 0x010; /* Get other modifiers from the error log header */ /* replace all frus in list */ replace_all = event->event_buf[I_BYTE3] & 0x20; /* repair as system running */ concurrent = event->event_buf[I_BYTE3] & 0x40; /* sw also a probable cause */ sw_also = event->event_buf[I_BYTE3] & 0x80; while (sw_also) { /* using while statement so can break out if canceled */ /* further analysis needed for s/w also as a cause */ report_menugoal(event, MSGMENUG171); break; } /* Combine repair modifiers to nibble for the reason code. */ v3_errdscr[0].rcode += ((sw_also + concurrent + replace_all) >> 5); if (errdscr_ready > 0) report_srn(event, 0, v3_errdscr); return 1; } /** * convert_symptom * * FUNCTION: * Converts the symptom bits into a unique sequence number for the * error log format, and finds the reason code message for the SRN. * * INPUTS: * format_type - the format of the error log * predictive - flag used to determine type of message * * OUTPUTS: * The message number of the reason code message. * predictive indicates whether the SRN should reflect deferred repair. * * RETURNS: * The BCD sequence number, 0 to 0x99 for encoding into a SRN. * * If there is any error, the sequence number returned will be 0xFF. * The error could be unknown unknow error log format. * Unknown symptom bits will be defaulted to ALL ZEROS in the * symptom bits, which will be sequence number 0. * * 0x100 will be returned if a menugoal, or another SRN type was * displayed in lieu of encoding a SRN. * */ #define NCPUSYMPTOMS 9 #define NMEMSYMPTOMS 17 #define NIOSYMPTOMS 17 #define NSPSYMPTOMS 33 #define NSPSYMPTOMS_ADDITIONAL 9 int convert_symptom(struct event *event, int format_type, int predictive, char **msg) { int seqn; int sbits; int signature; int msg_index; int error_type; /* Look up tables for sequence number to reason code messages. */ int cpu_log_sig[NCPUSYMPTOMS] = {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; char *cpu_log[NCPUSYMPTOMS][2]= { { MSGCPUALLZERO, DEFER_MSGALLZERO}, { MSGCPUB12b0, DEFER_MSGCPUB12b0}, { MSGCPUB12b1, DEFER_MSGCPUB12b1}, { MSGCPUB12b2, DEFER_MSGCPUB12b2}, { MSGCPUB12b3, DEFER_MSGCPUB12b3}, { MSGCPUB12b4, DEFER_MSGCPUB12b4}, { MSGCPUB12b5, DEFER_MSGCPUB12b5}, { MSGCPUB12b6, DEFER_MSGCPUB12b6}, { MSGCPUB12b7, DEFER_MSGCPUB12b7} }; int mem_log_sig[NMEMSYMPTOMS] = {0x0000, 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001}; char *mem_log[NMEMSYMPTOMS][2] = { { MSGMEMALLZERO, DEFER_MSGALLZERO}, { MSGMEMB12b0, DEFER_MSGMEMB12b0}, { MSGMEMB12b1, DEFER_MSGMEMB12b1}, { MSGMEMB12b2, DEFER_MSGMEMB12b2}, { MSGMEMB12b3, DEFER_MSGMEMB12b3}, { MSGMEMB12b4, DEFER_MSGMEMB12b4}, { MSGMEMB12b5, DEFER_MSGMEMB12b5}, { MSGMEMB12b6, DEFER_MSGMEMB12b6}, { MSGMEMB12b7, DEFER_MSGMEMB12b7}, { MSGMEMB13b0, DEFER_MSGMEMB13b0}, { MSGMEMB13b1, DEFER_MSGMEMB13b1}, { MSGMEMB13b2, DEFER_MSGMEMB13b2}, { MSGMEMB13b3, DEFER_MSGMEMB13b3}, { MSGMEMB13b4, DEFER_MSGMEMB13b4}, { MSGRESERVED, DEFER_MSGRESERVED}, { MSGMEMB13b6, DEFER_MSGMEMB13b6}, { MSGMEMB13b7, DEFER_MSGMEMB13b7}, }; /* I/O Byte 13, bits 0-2 are describtions */ /* that are masked off the symptom bits. */ int io_log_sig[NIOSYMPTOMS] = {0x0000, 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0410, 0x0200, 0x0210, 0x0100, 0x0110, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001}; char * io_log[NIOSYMPTOMS][3] = { { MSGIOALLZERO, DEFER_MSGALLZERO}, { MSGIOB12b0, DEFER_MSGIOB12b0}, { MSGIOB12b1, DEFER_MSGIOB12b1}, { MSGIOB12b2, DEFER_MSGIOB12b2}, { MSGIOB12b3, DEFER_MSGIOB12b3}, { MSGIOB12b4, DEFER_MSGIOB12b4}, { MSGIOB12b5, DEFER_MSGIOB12b5}, { MSGIOB12b5B13b3, DEFER_MSGIOB12b5B13b3}, { MSGIOB12b6, DEFER_MSGIOB12b6}, { MSGIOB12b6B13b3, DEFER_MSGIOB12b6B13b3}, { MSGIOB12b7, DEFER_MSGIOB12b7}, { MSGIOB12b7B13b3, DEFER_MSGIOB12b7B13b3}, { MSGIOB13b3, DEFER_MSGIOB13b3}, { MSGIOB13b4, DEFER_MSGIOB13b4}, { MSGIOB13b5, DEFER_MSGIOB13b5}, { MSGIOB13b6, DEFER_MSGIOB13b6}, { MSGIOB13b7, DEFER_MSGIOB13b7}, }; int sp_log_sig[NSPSYMPTOMS] = { 0x00000000, 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000, 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000, 0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100, 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001}; char *sp_log[NSPSYMPTOMS][2] = { { MSGSPALLZERO, DEFER_MSGALLZERO}, { MSGSPB16b0, DEFER_MSGSPB16b0}, { MSGSPB16b1, DEFER_MSGSPB16b1}, { MSGSPB16b2, DEFER_MSGSPB16b2}, { MSGSPB16b3, DEFER_MSGSPB16b3}, { MSGSPB16b4, DEFER_MSGSPB16b4}, { MSGSPB16b5, DEFER_MSGSPB16b5}, { MSGSPB16b6, DEFER_MSGSPB16b6}, { MSGSPB16b7, DEFER_MSGSPB16b7}, { MSGSPB17b0, DEFER_MSGSPB17b0}, { MSGSPB17b1, DEFER_MSGSPB17b1}, { MSGSPB17b2, DEFER_MSGSPB17b2}, { MSGSPB17b3, DEFER_MSGSPB17b3}, { MSGSPB17b4, DEFER_MSGSPB17b4}, { MSGSPB17b5, DEFER_MSGSPB17b5}, { MSGRESERVED,DEFER_MSGRESERVED}, { MSGRESERVED,DEFER_MSGRESERVED}, { MSGSPB18b0, DEFER_MSGSPB18b0}, { MSGSPB18b1, DEFER_MSGSPB18b1}, { MSGSPB18b2, DEFER_MSGSPB18b2}, { MSGSPB18b3, DEFER_MSGSPB18b3}, { MSGSPB18b4, DEFER_MSGSPB18b4}, { MSGRESERVED,DEFER_MSGRESERVED}, { MSGSPB18b6, DEFER_MSGSPB18b6}, { MSGSPB18b7, DEFER_MSGSPB18b7}, { MSGSPB19b0, DEFER_MSGSPB19b0}, { MSGSPB19b1, DEFER_MSGSPB19b1}, { MSGRESERVED, DEFER_MSGRESERVED}, { MSGRESERVED, DEFER_MSGRESERVED}, { MSGSPB19b4, DEFER_MSGSPB19b4}, { MSGSPB19b5, DEFER_MSGSPB19b5}, { MSGSPB19b6, DEFER_MSGSPB19b6}, { MSGRESERVED, DEFER_MSGRESERVED}, }; int sp_log_additional_sig[NSPSYMPTOMS_ADDITIONAL] = {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; char *sp_log_additional[NSPSYMPTOMS_ADDITIONAL][2] = { { MSGSPALLZERO, DEFER_MSGALLZERO}, { MSGSPB28b0, DEFER_MSGSPB28b0}, { MSGSPB28b1, DEFER_MSGSPB28b1}, { MSGSPB28b2, DEFER_MSGSPB28b2}, { MSGSPB28b3, DEFER_MSGSPB28b3}, { MSGSPB28b4, DEFER_MSGSPB28b4}, { MSGSPB28b5, DEFER_MSGSPB28b5}, { MSGSPB28b6, DEFER_MSGSPB28b6}, { MSGSPB28b7, DEFER_MSGSPB28b7}, }; *msg = NULL; seqn = 1; msg_index = 0; if (predictive) msg_index = 1; switch (format_type) { case RTAS_EXTHDR_FMT_CPU: sbits = event->event_buf[I_BYTE12]; while (seqn < NCPUSYMPTOMS) { signature = cpu_log_sig[seqn]; if ((sbits & signature) == signature) break; seqn++; } if (seqn == NCPUSYMPTOMS) seqn = 0; *msg = cpu_log[seqn][msg_index]; break; case RTAS_EXTHDR_FMT_MEMORY: sbits = (event->event_buf[I_BYTE12] << 8) | event->event_buf[I_BYTE13]; while (seqn < NMEMSYMPTOMS) { signature = mem_log_sig[seqn]; if ((sbits & signature) == signature) break; seqn++; } if (seqn == NMEMSYMPTOMS) seqn = 0; *msg = mem_log[seqn][msg_index]; break; case RTAS_EXTHDR_FMT_IO: /* first check for io bus error that isolates */ /* only to a bus, i.e. produces SRN 9CC-1xx */ error_type = get_error_type(event, format_type); if (analyze_io_bus_error(event, 3, error_type)) { return 0x100; } sbits = (event->event_buf[I_BYTE12] << 8) | event->event_buf[I_BYTE13]; sbits &= 0x0FF1F; while (seqn < NIOSYMPTOMS) { signature = io_log_sig[seqn]; if ((sbits & signature) == signature) break; seqn++; } if (seqn == NIOSYMPTOMS) seqn = 0; *msg = io_log[seqn][msg_index]; break; case RTAS_EXTHDR_FMT_IBM_SP: sbits =((event->event_buf[I_BYTE16] << 24) | (event->event_buf[I_BYTE17] << 16) | (event->event_buf[I_BYTE18] << 8 ) | event->event_buf[I_BYTE19]); if (sbits) { while (seqn < NSPSYMPTOMS) { signature = sp_log_sig[seqn]; if ((sbits & signature) == signature) break; seqn++; } if (seqn >= NSPSYMPTOMS) seqn = 0; *msg = sp_log[seqn][msg_index]; break; } else { /* use additional symptom bits */ sbits = event->event_buf[I_BYTE28]; if (!sbits) { seqn = 0; *msg = sp_log_additional[seqn][msg_index]; } else { while ((seqn < NSPSYMPTOMS_ADDITIONAL)) { signature = sp_log_additional_sig[seqn]; if ((sbits & signature) == signature) break; seqn++; } if (seqn >= NSPSYMPTOMS_ADDITIONAL) { seqn = 0; *msg = sp_log_additional[seqn][msg_index]; } else { *msg = sp_log_additional[seqn][msg_index]; seqn += (NSPSYMPTOMS - 1); /* after original symptom bits */ } } break; } default: /* * Should not get here unless the format is * unsupported for Version 3 logs. It would * be an architecture violation by RTAS. * * Assign a sequence number of FF and a * message that indicates the error log is * unknown, and the SRN will be undocumented. * The SRN will look like: * A00-FF0 */ seqn = 0xFF; *msg = MSG_UNKNOWN_V3; return seqn; } /* convert sequence number to BCD */ seqn = convert_bcd(seqn); return seqn; } /** * process_v3_epow * @brief Analyze Versions 3 and beyond EPOW error logs. * * INPUTS: * The encoded error type. * The version of the RPA error log format. * * OUTPUTS: * Fills in the v3_errdscr or reports SRN with refcodes. * * RETURNS: * 1 if errdscr is ready, * 2 if refcode was reported * otherwise 0, i.e. a menu goal was reported instead. * */ /* * This macro will process any "04" tagged debug data for Ref Codes, * contained in a Version 4 or greater RPA error log. The intend is * to call out the ref codes, unless the analysis would be a menugoal only. * For a menugoal, any ref code will be appended to the menugoal for * reference if the problem can not be solved by report_menugoal. */ #define PROCESS_V4_REFCODE \ if (version > 3 && \ (refc = (short *)get_register_data(event, SRC_REG_ID_04, &rlen)) != NULL )\ { \ process_refcodes(event, refc, rlen); \ return 2; \ } int process_v3_epow(struct event *event, int error_type, int version) { int rc = 1; int class; int rlen; short *refc; class = error_type & 0xFF; if (class == 0) { /* * This is an EPOW reset, so save it and go to the next * (older) error */ save_epow_reset(event, error_type); return 0; } else if (has_epow_reset(event, error_type)) { /* this error has been reset */ return 0; /* continue */ } v3_errdscr[0].rcode = 0; v3_errdscr[0].rmsg = MSGEPOWALLZERO; /* Look for an EPOW detected by a defined sensor. */ if (error_type & EPOWB16b0) { PROCESS_V4_REFCODE /* returns if callout is refcode */ rc = sensor_epow(event, error_type, version); } else if (error_type & EPOWB16b1) { /* look for power fault epow */ if (error_type & EPOWB17b0) { /* unspecified cause for power fault */ PROCESS_V4_REFCODE /* returns if callout is refcode */ v3_errdscr[0].rcode = 0x140; if (class < 3) { v3_errdscr[0].sn |= 0x10; v3_errdscr[0].rmsg = MSGEPOWB17b0C12; } else { v3_errdscr[0].rmsg = MSGEPOWB17b0C37; } } else if (error_type & EPOWB17b1) { if (error_type & EPOWB16b4) { /* loss of redundant input */ report_menugoal(event, MSGMENUG204); rc = 0; } else if (class == 2 && version == 4) { /* this is Version 4, so refer to * possible battery backup */ report_menugoal(event, MSGMENUG205); rc = 0; } else { /* loss of power source */ loss_power_MG(event); rc = 0; } } else if (error_type & EPOWB17b2) { /* internal power supply failure */ PROCESS_V4_REFCODE /* returns if callout is refcode */ v3_errdscr[0].rcode = 0x160; if (error_type & EPOWB16b4) { v3_errdscr[0].sn |= 0x10; v3_errdscr[0].rcode = 0x170; v3_errdscr[0].rmsg = MSGEPOWB17b2RED; } else if ( class < 3 ) { v3_errdscr[0].sn |= 0x10; v3_errdscr[0].rmsg = MSGEPOWB17b2C12; } else { v3_errdscr[0].rmsg = MSGEPOWB17b2C37; } } else if (error_type & EPOWB17b3) { /* manual power off via op panel */ manual_power_off_MG(event); rc = 0; } else if (error_type & EPOWB17b4) { /* internal battery failure */ PROCESS_V4_REFCODE /* returns if callout is refcode */ v3_errdscr[0].rcode = 0x240; v3_errdscr[0].rmsg = MSGEPOWB16b1B17b4; if (class < 3) v3_errdscr[0].sn |= 0x10; } else { /* Reserved bits in EPOW log */ /* This error log is unknow to ELA */ PROCESS_V4_REFCODE /* returns if callout is refcode */ unknown_epow_ela(event, class); rc = 0; } } else if (error_type & EPOWB16b2) { /* look for fan failures */ if (error_type & EPOWB16b4) { /* Loss of redundant fan */ PROCESS_V4_REFCODE /* returns if callout is refcode */ v3_errdscr[0].sn |= 0x10; v3_errdscr[0].rcode = 0x200; v3_errdscr[0].rmsg = MSGEPOW1501B16b4; } else if (error_type & EPOWB16b3) { /* look for Over temperature and fan failure */ /* System shutdown - thermal & fan */ PROCESS_V4_REFCODE /* returns if callout is refcode */ v3_errdscr[0].rcode = 0x220; v3_errdscr[0].rmsg = MSGEPOWB16b23; if (class < 3) { v3_errdscr[0].sn |= 0x10; v3_errdscr[0].rmsg = MSGEPOWB16b2b3; } } else { PROCESS_V4_REFCODE /* returns if callout is refcode */ v3_errdscr[0].rcode = 0x190; if (class < 3) { v3_errdscr[0].sn |= 0x10; v3_errdscr[0].rmsg = MSGEPOWB16b2C12; } else { v3_errdscr[0].rmsg = MSGEPOWB16b2C37; } } } else if (error_type & EPOWB16b3) { /* look for Over temperature conditions */ if (class == 1) { /* over temp. warning */ report_menugoal(event, MSGMENUG102); rc = 0; } else { /* Over temperature condition */ PROCESS_V4_REFCODE /* returns if callout is refcode */ v3_errdscr[0].rcode = 0x210; v3_errdscr[0].rmsg = MSGXEPOW3n73; if (class < 3) { v3_errdscr[0].rmsg = MSGEPOWB16b3; v3_errdscr[0].sn |= 0x10; } } } else if (error_type & EPOWB16b4) { /* look for loss of redundancy, without any other indication */ if (error_type & EPOWB17b1) { report_menugoal(event, MSGMENUG204); rc = 0; } else { /* Loss of redundant power supply */ PROCESS_V4_REFCODE /* returns if callout is refcode */ v3_errdscr[0].sn |= 0x10; v3_errdscr[0].rcode = 0x230; v3_errdscr[0].rmsg = MSGEPOW1502B16b4; } } else { /* This error log is unknow to ELA */ PROCESS_V4_REFCODE /* returns if callout is refcode */ unknown_epow_ela(event, class); rc = 0; } return rc; } /** * clear_edesc_struct * * Clear the frus out of the event description. This allows the caller to * recycle the same event to report more than 4 frus. */ void clear_edesc_struct(struct event_description_pre_v6 *event) { int k; for (k = 0; k < MAXFRUS; k++) { event->frus[k].conf = 0; event->frus[k].fmsg = 0; strcpy(event->frus[k].floc, ""); strcpy(event->frus[k].fname, ""); } return; } /** * make_refcode_errdscr * * The first time this function is called for a given error log entry, * this function will call adderrdscr and save_davars_ela. Subsequent * calls to this function for the same error log entry result in * add_more_descrs being called. * * INPUTS: * Pointer to an erro description containing the information to be logged * Pointer to an integer flag that allows this function to know * whether or not it has already been called for this error log entry. * * OUTPUTS: * Pointer to an integer flag that allows this function to know * whether or not it has already been called for this error log entry. * * RETURNS: * 0 if the errdscr information was added successfully. * -1 if adderrdscr or add_more_descrs failed. */ int make_refcode_errdscr(struct event *event, struct event_description_pre_v6 *e_desc, int *adderrdscr_called) { int rc = 0; if (! (*adderrdscr_called)) { *adderrdscr_called = 1; if (set_srn_and_callouts(event, e_desc, 0)) rc = -1; /* adderrdscr error. */ } else { if (add_more_descrs(event, e_desc)) rc = -1; /* add_more_descrs error. */ } return rc; } int process_refcodes(struct event *event, short *refc, int rlen) { int i, j; short src_type; int one2one; char *lcc; int predictive_error = 0; struct event_description_pre_v6 *e_desc; char *loc; int nlocs; int adderrdscr_called = 0; /* * refc points to SRC data in the error log, that looks like: * byte: 0 2 4 6 8 10 12 14 16 18 * data: B4xx RRR1 xxxx xxxx xxxx xxxx RRR2 RRR3 RRR4 RRR5 * byte: 20 22 24 26 28 30 32 34 36 38 * data: xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx L1L2 L3L4 * byte: 40 42 * data: L500 0000 * where xx is don't care for ELA, and RRRn are the ref codes. * * L1-L5 are the number of location codes corresponding to * ref codes RRR1-RRR5. If Ln = 0 then ref code 'n' does not * have any location codes, otherwise, for each ref code, the * next 'n' location codes should be extract and reported with * the ref. code. * * Extract the SRC type, that is, the 1st 2 bytes of the * register data. * * Extract the ref codes and save in rctab. Compare against * any previously reported ref code group. Do not report the * same identical group of ref codes again. * * Concerning location codes, when comparing ref code groups, * I am assuming it is sufficient to compare only the number * of location codes per ref code. The exposure is the same * ref code has the same number of location codes, but * different locations. * * If rlen == 36, then location codes are 1-1 correlated. * If rlen == 44, then location codes are not 1-1 correlated, * and the table rctabloc is used. */ src_type = *refc; /* SRC type */ if (rlen == 36) one2one = 1; /* refc 1-1 with loc codes */ else one2one = 0; /* Ceate/use shadow table b/c not 1-1 */ dbg("reg data rlen = %d, one2one = %d", rlen, one2one); if (! one2one) /* point to start of loc. code counts */ lcc = (char *)refc + 36; refc++; /* refc now is RRR1, which must be defined. */ rctab[0] = 1; /* holds number of ref codes in group */ rctab[1] = *refc; dbg("SRC: type = 0x%x, ref code = 0x%x", src_type, *refc); if (! one2one) { rctabloc[0] = 0; /* not used */ rctabloc[1] = *lcc; /* num of loc codes for first ref code */ dbg("number of loc codes = 0x%x", *lcc); lcc++; /* next loc code count */ } /* * Put the rest of the ref codes into the table. * Stop when a ref. code is zero. */ refc += 5; /* now refc points to RRR2 */ while (*refc && rctab[0] < MAXREFCODES) { rctab[0]++; /* increment count of ref codes */ rctab[rctab[0]] = *refc; dbg("ref code = 0x%x", *refc); refc++; /* pointer to next ref code */ if (! one2one) { rctabloc[rctab[0]] = *lcc; dbg("number of loc codes = 0x%x", *lcc); lcc++; /* next loc code count */ } } dbg("ref code count = 0x%x", rctab[0]); /* Here to report an SRN using group of ref codes. */ e_desc = &cec_src[0]; /* flag predictive errors */ predictive_error = event->event_buf[I_BYTE0] & 0x08; if (predictive_error) e_desc->sn = 0x652; else e_desc->sn = 0x651; e_desc->rcode = REFCODE_REASON_CUST; if (predictive_error) e_desc->rmsg = DEFER_MSGREFCODE_CUST; else e_desc->rmsg = MSGREFCODE_CUST; loc = get_loc_code(event, FIRST_LOC, NULL); i = 0; /* counts ref codes in event */ j = -1; /* counts frus added to event, will incr. to use */ /* Clear frus in case this is the second time through. */ clear_edesc_struct(e_desc); /* While there are ref codes to add to this event */ while (i < rctab[0]) { /* Make sure there is room in the event. */ j++; if (j == MAXFRUS) { /* This error description structure is full. Log the * info and then clear out the structure. */ if (make_refcode_errdscr(event, e_desc, &adderrdscr_called)) return -1; clear_edesc_struct(e_desc); j = 0; } /* * Put the ref code into the fru's confidence field * And the src type into the fru's fmsg, and lastly, * flag the controller by setting fname to a "special" * string, i.e. "REF-CODE". */ e_desc->frus[j].conf = rctab[i+1]; e_desc->frus[j].fmsg = src_type; strcpy(e_desc->frus[j].fname, REFCODE_FNAME); /* Check if there are any location codes? */ if (one2one) nlocs = 1; else nlocs = rctabloc[i+1]; while (nlocs) { /* Put loc code into fru */ if (loc != NULL) strcpy(e_desc->frus[j].floc, loc); else e_desc->frus[j].floc[0] = '\0'; /* Get ready with next location code */ loc = get_loc_code(event, NEXT_LOC, NULL); nlocs--; if (nlocs) { /* * More loc codes means add another * fru with same ref code */ j++; if (j == MAXFRUS) { /* This err descr structure is full. * Log the info and then clear * out the structure. */ if (make_refcode_errdscr(event, e_desc, &adderrdscr_called)) return -1; clear_edesc_struct(e_desc); j = 0; } /* Repeat the ref code */ e_desc->frus[j].conf = rctab[i+1]; e_desc->frus[j].fmsg = src_type; strcpy(e_desc->frus[j].fname, REFCODE_FNAME); } } i++; /* Look for next ref code */ } if (make_refcode_errdscr(event, e_desc, &adderrdscr_called)) return -1; /* End of processing SRC data */ return 1; } ppc64-diag-2.7.0/rtas_errd/ela_msg.h0000644000000000000000000021567712642205425015645 0ustar rootroot/** * @file ela_msg.h * * Copyright (C) 2005 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _H_RPA_ELA_MSG #define _H_RPA_ELA_MSG #define F_POWER_SUPPLY "Power Supply" #define MSGCPUB12b0 "CPU internal error" #define MSGCPUB12b5 "Time-out error waiting for I/O" #define MSGCPUALLZERO "An error has been detected by the CPU. The error " \ "log indicates the following physical FRU location(s) as the probable "\ "cause(s)." #define MSGMEMB12b0 "Uncorrectable Memory Error" #define MSGMEMB12b1 "ECC correctable error" #define MSGMEMB12b2 "Correctable error threshold exceeded" #define MSGMEMB12b5 "Memory Data error (Bad data going to memory)" #define MSGMEMB12b6 "Memory bus/switch internal error" #define MSGMEMB12b7 "Memory time-out error" #define MSGMEMB13b3 "I/O Host Bridge time-out error" #define MSGMEMB13b4 "I/O Host Bridge address/data parity error" #define MSGMEMALLZERO "An error has been detected by the memory controller. " \ "The error log indicates the following physical FRU location(s) as the " \ "probable cause(s)." #define MSGIOB12b0 "I/O Bus Address Parity Error" #define MSGIOB12b1 "I/O Bus Data Parity Error" #define MSGIOB12b4 "I/O Error on ISA bus" #define MSGIOB12b5 "Intermediate or System Bus Address Parity Error" #define MSGIOB12b6 "Intermediate or System Bus Data Parity Error" #define MSGIOB12b7 "Intermediate or System Bus Time-out Error" #define MSGIOALLZERO "An error has been detected by the I/O. The error " \ "log indicates the following physical FRU location(s) as the probable " \ "cause(s)." #define MSGSPB16b0 "Time-out on communication response from Service Processor" #define MSGSPB16b1 "I/O general bus error" #define MSGSPB16b2 "Secondary I/O general bus error" #define MSGSPB16b3 "Internal Service Processor memory error" #define MSGSPB16b4 "Service Processor error accessing special registers" #define MSGSPB16b5 "Service Processor reports unknown communication error" #define MSGSPB16b7 "Other internal Service Processor hardware error" #define MSGSPB17b0 "Service Processor error accessing Vital Product Data EEPROM" #define MSGSPB17b1 "Service Processor error accessing Operator Panel" #define MSGSPB17b2 "Service Processor error accessing Power Controller" #define MSGSPB17b3 "Service Processor error accessing Fan Sensor" #define MSGSPB17b4 "Service Processor error accessing Thermal Sensor" #define MSGSPB17b5 "Service Processor error accessing Voltage Sensor" #define MSGSPB18b0 "Service Processor error accessing serial port" #define MSGSPB18b2 "Service Processor error accessing " \ "Real-Time Clock/Time-of-day clock" #define MSGSPB18b4 "Service Processor detects loss of voltage from the battery" #define MSGXEPOW1n11 "Fan is turning slower than expected" #define MSGXEPOW1n64 "Fan stop was detected" #define MSGXEPOW2n32 "Over voltage condition was detected" #define MSGXEPOW2n52 "Under voltage condition was detected" #define MSGXEPOW3n21 "Over temperature condition was detected" #define MSGXEPOW3n73 "System shutdown due to over maximum temperature condition" #define MSGEPOWB1505 "System shutdown due to: 1) Loss of AC power,\n " \ "2) Power button was pushed without proper system\n" \ "shutdown, 3) Power supply failure." #define MSG_UNSUPPORTED_MEM "Uncorrectable memory or unsupported memory" #define MSG_MISSING_MEM "Missing or bad memory" #define MSG_BAD_L2 "Bad L2 Cache" #define MSG_MISSING_L2 "Missing L2 cache" #define MSGMENUG102 "651102 "\ "A non-critical system cooling problem has been detected.\n" \ "The system temperature appears to be above the expected range.\n"\ "Check for elevated room temperatures, restricted air flow\n"\ "around the system or any system covers that are opened.\n"\ "If no problem is found, contact your service provider." #define MSGIOB13b4 "I/O Expansion Bus Parity Error." #define MSGIOB13b5 "I/O Expansion Bus Time-out Error." #define MSGIOB13b6 "I/O Expansion Bus Connection Failure." #define MSGIOB13b7 "I/O Expansion Unit not in an operating state." #define MSGEPOWPCI111 "System shutdown due to loss of AC Power to the site." #define MSGEPOWPCI100 "CEC Rack shutdown due to: 1) Loss of AC power " \ "to the CEC Rack,\n" \ "2) Open or disconnected SPCN cable between racks\n" \ "3) AC module, Bulk power, regulator or SPCN card failure." #define MSGEPOWPCI011 "I/O Rack shutdown due to: 1) Loss of AC power " \ "to the I/O Rack,\n" \ "2) Open or disconnected SPCN cable between racks,\n" \ "3) Power supply failure." #define MSGEPOWPCI001 "Power fault due to internal power supply failure." #define MSGEPOWPCI010 "Power fault due to internal power supply failure." #define MSGEPOWB16b1B17b3 "Power fault due to manual activation of " \ "power-off op-panel request." #define MSGEPOWB16b23 "System shutdown due to over temperature condition " \ "and fan failure. Use the physical FRU location(s) as the probable " \ "cause(s)." #define MSGEPOW1502B16b4 "Non-critical power problem, loss of redundant " \ "power supply. Use the physical FRU location(s) as the probable cause(s)." #define MSGEPOW1501B16b4 "Non-critical cooling problem, loss of redundant " \ "fan. Use the physical FRU location(s) as the probable cause(s)." #define MSGCRIT_FAN "Sensor indicates a fan has failed." #define MSGCRIT_VOLT "Sensor indicates a voltage is outside the normal range." #define MSGCRIT_THERM "Sensor indicates an abnormally high internal temperature." #define MSGCRIT_POWER "Sensor indicates a power supply has failed." #define MSGCRIT_UNK "Sensor indicates a FRU has failed." #define MSGWARN_FAN "Sensor indicates a fan is turning too slowly." #define MSGRED_FAN "Sensor detected a redundant fan failure." #define MSGRED_POWER "Sensor detected a redundant power supply failure." #define MSGRED_UNK "Sensor detected a redundant FRU failure." #define F_EPOW_ONE "%1$s %2$d" #define F_VOLT_SEN_2 "Volt Sensor" #define F_THERM_SEN "Temp sensor" #define F_POW_SEN "PS sensor" #define MSGREFCODE_CUST "" \ "The CEC or SPCN reported an error. Report the SRN and the following reference and physical location codes to your service provider." #define DEFER_MSGREFCODE_CUST ""\ "The CEC or SPCN reported a non-critical error. Report the SRN and the following reference and physical location codes to your service provider." #define MSGMENUG150 "651150 ANALYZING SYSTEM ERROR LOG\n" \ "A loss of power was detected by one or more\n" \ "devices with the following physical location codes:\n\n" \ "%s\n\n" \ "Check for the following:\n" \ " 1. Loose or disconnected power source connections.\n" \ " 2. Loss of site power.\n" \ " 3. For multiple enclosure systems, loose or\n" \ " disconnected power and signal connections\n" \ " between enclosures.\n\n" \ "If the cause cannot be determined from the list above,\n" \ "then replace the FRUs identified by the physical\n" \ "locations given above. Refer to the System Service Guide." #define MSGMENUG151 "651151 ANALYZING SYSTEM ERROR LOG\n "\ "A loss of power was detected.\n\n" \ "Check for the following:\n" \ " 1. Loose or disconnected power source connections.\n" \ " 2. Loss of site power.\n" \ " 3. For multiple enclosure systems, loose or\n" \ " disconnected power and/or signal connections\n" \ " between enclosures." #define MSGMENUG152 "651152 ANALYZING SYSTEM ERROR LOG\n" \ "Environmental sensor analysis is reporting an unknown\n" \ "status, with the following physical location codes.\n\n%s\n\n" \ "Run the Display System Environmental Sensors Service Aid." #define MSGMENUG153 "651153 ANALYZING SYSTEM ERROR LOG\n" \ "Environmental sensor analysis is reporting an unknown\n" \ "status. Run the Display System Environmental Sensors Service Aid." #define MSGMENUG156 "651156 ANALYZING SYSTEM ERROR LOG\n" \ "A non-critical environmental and power warning was logged.\n" \ "The following physical location codes were reported:\n\n%s" #define MSGMENUG157 "651157 ANALYZING SYSTEM ERROR LOG\n" \ "A non-critical environmental and power warning was logged." #define MSGMENUG158 "651158 ANALYZING SYSTEM ERROR LOG\n "\ "A critical environmental and power warning was logged.\n" \ "The following physical location codes were reported:\n" \ "\n%s\n\n%s\n\nThe system will shutdown in 10 minutes." #define MSGMENUG159 "651159 ANALYZING SYSTEM ERROR LOG\n" \ "A critical environmental and power warning was logged.\n" \ "\n%s\n\nThe system will shutdown in 10 minutes." #define MSGMENUG160 "651160 ANALYZING SYSTEM ERROR LOG\n" \ "A system shutdown occured due to a critical \n" \ "environmental and power warning.\n" \ "The following physical location codes were reported:\n\n%s" #define MSGMENUG161 "651161 ANALYZING SYSTEM ERROR LOG\n" \ "A system shutdown occured due to a critical \n" \ "environmental and power warning." #define MSGEPOWB17b0C12 "Power fault due to unspecified cause." #define MSGEPOWB17b0C37 "System shutdown due to power fault with unspecified cause." #define MSGEPOWB16b2C12 "Fan failure. Use the physical FRU location(s) as the probable cause(s)." #define MSGEPOWB16b2C37 "System shutdown due to fan failure. Use the physical FRU location(s) as the probable cause(s)." #define MSGEPOWB17b2RED "Power fault due to internal redundant power supply failure." #define MSG_OP_PANEL_FAIL "Display character test failed." #define F_OP_PANEL "character display logic" #define MSGMENUG162 "651162 ANALYZING SYSTEM ERROR LOG\n" \ "An error was logged on %s" \ "that indicates the Power-off button was pressed \n" \ "without performing a proper shutdown.\n" \ "To remove this error from the error log, execute\n" \ "the following command from the command line.\n\n" \ " errclear -l %d 0" #define DEFER_MSG_UNSUPPORTED_MEM ""\ "A non-critical error has been detected: "\ "Uncorrectable memory or unsupported memory." #define DEFER_MSGCPUB12b0 "A non-critical error has been detected: "\ "CPU internal error." #define DEFER_MSGMEMB12b0 "A non-critical error has been detected: "\ "Uncorrectable Memory Error." #define DEFER_MSGMEMB12b1 "A non-critical error has been detected: "\ "ECC correctable error." #define DEFER_MSGMEMB12b2 "A non-critical error has been detected: "\ "Correctable error threshold exceeded." #define DEFER_MSGIOB13b4 "A non-critical error has been detected: "\ "I/O Expansion Bus Parity Error." #define DEFER_MSGIOB13b5 "A non-critical error has been detected: "\ "I/O Expansion Bus Time-out Error." #define DEFER_MSGIOB13b6 "A non-critical error has been detected: "\ "I/O Expansion Bus Connection Failure." #define DEFER_MSGIOB13b7 "A non-critical error has been detected: "\ "I/O Expansion Unit not in an operating state." #define DEFER_MSGIOB12b5 "A non-critical error has been detected: "\ "Intermediate or System Bus Address Parity Error." #define DEFER_MSGIOB12b6 "A non-critical error has been detected: "\ "Intermediate or System Bus Data Parity Error." #define DEFER_MSGIOB12b7 "A non-critical error has been detected: "\ "Intermediate or System Bus Time-out Error." #define MSGPOSTALL "Refer to the Error Code to FRU Index in the system service guide." #define MSGCPUB12b1 "CPU internal cache or cache controller error" #define DEFER_MSGCPUB12b1 "A non-critical error has been detected: "\ "CPU internal cache or cache controller error." #define MSGCPUB12b2 "External cache parity or multi-bit ECC error" #define DEFER_MSGCPUB12b2 "A non-critical error has been detected: "\ "External cache parity or multi-bit ECC error." #define MSGCPUB12b3 "External cache ECC single-bit error" #define DEFER_MSGCPUB12b3 "A non-critical error has been detected: "\ "External cache ECC single-bit error." #define MSGIOB12b3 "I/O bridge/device internal error" #define DEFER_MSGIOB12b3 "A non-critical error has been detected: "\ "I/O bridge/device internal error" #define MSG_PLATFORM_ERROR "Platform specific error. Refer to the System " \ "Service Guide for this system unit." #define DEFER_MSGALLZERO "A non-critical error has been detected. The error " \ "log indicates the following physical FRU location(s) as the probable " \ "cause(s)." #define MSGCPUB12b4 "System bus time-out error" #define DEFER_MSGCPUB12b4 "A non-critical error has been detected: " \ "System bus time-out error." #define DEFER_MSGCPUB12b5 "A non-critical error has been detected: " \ "Time-out error waiting for I/O." #define MSGCPUB12b6 "System bus parity error" #define DEFER_MSGCPUB12b6 "A non-critical error has been detected: "\ "System bus parity error." #define MSGCPUB12b7 "System bus protocol/transfer error" #define DEFER_MSGCPUB12b7 "A non-critical error has been detected: "\ "System bus protocol/transfer error." #define MSGMEMB12b3 "Memory Controller subsystem internal error" #define DEFER_MSGMEMB12b3 "A non-critical error has been detected: "\ "Memory Controller subsystem internal error." #define MSGMEMB12b4 "Memory Address Error (Invalid address or access attempt)" #define DEFER_MSGMEMB12b4 "A non-critical error has been detected: " \ "Memory Address (Bad address going to memory)." #define DEFER_MSGMEMB12b5 "A non-critical error has been detected: "\ "Memory Data error (Bad data going to memory)." #define DEFER_MSGMEMB12b6 "A non-critical error has been detected: "\ "Memory bus/switch internal error." #define DEFER_MSGMEMB12b7 "A non-critical error has been detected: "\ "Memory time-out error." #define MSGMEMB13b0 "System bus parity error" #define DEFER_MSGMEMB13b0 "A non-critical error has been detected: "\ "System bus parity error." #define MSGMEMB13b1 "System bus time-out error" #define DEFER_MSGMEMB13b1 "A non-critical error has been detected: " \ "System bus time-out error." #define MSGMEMB13b2 "System bus protocol/transfer error" #define DEFER_MSGMEMB13b2 "A non-critical error has been detected: " \ "System bus protocol/transfer error." #define DEFER_MSGMEMB13b3 "A non-critical error has been detected: " \ "I/O Host Bridge time-out error." #define DEFER_MSGMEMB13b4 "A non-critical error has been detected: "\ "I/O Host Bridge address/data parity error." #define MSGMEMB13b6 "System support function error." #define DEFER_MSGMEMB13b6 "A non-critical error has been detected: "\ "System support function error." #define MSGMEMB13b7 "System bus internal hardware/switch error." #define DEFER_MSGMEMB13b7 "A non-critical error has been detected: "\ "System bus internal hardware/switch error." #define DEFER_MSGIOB12b0 "A non-critical error has been detected: "\ "I/O Bus Address Parity Error" #define DEFER_MSGIOB12b1 "A non-critical error has been detected: "\ "I/O Bus Data Parity Error" #define MSGIOB12b2 "I/O bus time-out, access, or other error" #define DEFER_MSGIOB12b2 "A non-critical error has been detected: " \ "I/O Bus time-out, access or other error" #define DEFER_MSGIOB12b4 "A non-critical error has been detected: "\ "I/O Error on ISA bus" #define MSG_UNKNOWN_V3 "Error log analysis is unable to determine the " \ "error. The error log indicates the following physical FRU location(s) " \ "as the probable cause(s)." #define MSGCRIT_FAN_SHUT "System shutdown due to a fan failure." #define MSGCRIT_VOLT_SHUT "System shutdown due to voltage outside the " \ "normal range." #define MSGCRIT_THERM_SHUT "System shutdown due to an abnormally high " \ "internal temperature." #define MSGCRIT_POWER_SHUT "System shutdown due to a power supply failure." #define MSGSPB19b0 "Power Control Network general connection failure." #define DEFER_MSGSPB19b0 "A non-critical error has been detected: "\ "Power Control Network general connection failure." #define MSGSPB19b1 "Power Control Network node failure." #define DEFER_MSGSPB19b1 "A non-critical error has been detected: "\ "Power Control Network node failure." #define MSGSPB19b4 "Service Processor error accessing Power Control Network." #define DEFER_MSGSPB19b4 "A non-critical error has been detected: "\ "Service Processor error accessing Power Control Network." #define MSGRESERVED "Error with reserved description." #define DEFER_MSGRESERVED "A non-critical error has been detected: "\ "Error with reserved description." #define MSGCRIT_UNK_SHUT "System shutdown due to FRU that has failed." #define MSGIOB12b5B13b3 "System bus address parity error" #define DEFER_MSGIOB12b5B13b3 "A non-critical error has been detected: " \ "System bus address parity error" #define MSGIOB12b6B13b3 "System bus data parity error" #define DEFER_MSGIOB12b6B13b3 "A non-critical error has been detected: " \ "System bus data parity error" #define MSGIOB12b7B13b3 "System bus time-out error" #define DEFER_MSGIOB12b7B13b3 "A non-critical error has been detected: " \ "System bus time-out error" #define MSGIOB13b3 "Error on system bus" #define DEFER_MSGIOB13b3 "A non-critical error has been detected: "\ "Error on system bus" #define MSGEPOWALLZERO "An environmental and power warning has been detected. "\ "The error log indicates the following physical FRU location(s) as the " \ "probable cause(s)." #define MSGEPOWB16b2 "Fan failure" #define MSGEPOWB17b2C12 "Internal power supply failure" #define MSGEPOWB17b2C37 "System shutdown due to internal power supply failure" #define MSGEPOWB16b3 "Over temperature condition" #define MSGEPOWB16b2b3 "Over temperature and fan failure" #define MSGSPALLZERO "An error has been detected by the Service Processor. " \ "The error log indicates the following physical FRU location(s) as the " \ "probable cause(s)." #define DEFER_MSGSPB16b0 "A non-critical error has been detected: " \ "Time-out on communication response from Service Processor" #define DEFER_MSGSPB16b1 "A non-critical error has been detected: " \ "I/O general bus error" #define DEFER_MSGSPB16b2 "A non-critical error has been detected: " \ "Secondary I/O general bus error" #define DEFER_MSGSPB16b3 "A non-critical error has been detected: " \ "internal Service Processor memory error" #define DEFER_MSGSPB16b4 "A non-critical error has been detected: " \ "Service Processor error accessing special registers" #define DEFER_MSGSPB16b5 "A non-critical error has been detected: " \ "Service Processor reports unknown communication error" #define DEFER_MSGSPB16b7 "A non-critical error has been detected: " \ "Other internal Service Processor hardware error" #define DEFER_MSGSPB17b0 "A non-critical error has been detected: " \ "Service Processor error accessing Vital Product Data EEPROM" #define DEFER_MSGSPB17b1 "A non-critical error has been detected: " \ "Service Processor error accessing Operator Panel" #define DEFER_MSGSPB17b2 "A non-critical error has been detected: " \ "Service Processor error accessing Power Controller" #define DEFER_MSGSPB17b3 "A non-critical error has been detected: " \ "Service Processor error accessing Fan Sensor" #define DEFER_MSGSPB17b4 "A non-critical error has been detected: " \ "Service Processor error accessing Thermal Sensor" #define DEFER_MSGSPB17b5 "A non-critical error has been detected: " \ "Service Processor error accessing Voltage Sensor" #define DEFER_MSGSPB18b0 "A non-critical error has been detected: " \ "Service Processor error accessing serial port" #define MSGSPB18b1 "Service Processor detected NVRAM error" #define DEFER_MSGSPB18b1 "A non-critical error has been detected: " \ "Service Processor detected NVRAM error" #define DEFER_MSGSPB18b2 "A non-critical error has been detected: " \ "Service Processor error accessing Real-Time Clock/Time-of-day clock" #define DEFER_MSGSPB18b4 "A non-critical error has been detected: " \ "Service Processor detects loss of voltage from the battery" #define MSGSPB18b7 "Service Processor detected a surveillance time-out" #define DEFER_MSGSPB18b7 "A non-critical error has been detected: " \ "Service Processor detected a surveillance time-out" #define MSGMENUG171 "651171 ANALYZING SYSTEM ERROR LOG\n" \ "A problem was logged that could be either hardware, software\n" \ "or firmware. If new software or firmware has been recently\n" \ "installed, check if there are any known problems. To further\n" \ "analyze the problem, enter the following command from the\n" \ "command line.\n\n" \ " diag -ed sysplanar0" #define PREDICT_UNRECOV "Recoverable errors on resource indicate trend " \ "toward unrecoverable error. However the resource could not be " \ "deconfigured and is still in use." #define FAIL_BY_PLATFORM "Resource was marked failed by the platform. "\ "System is operating in degraded mode." #define MSGMEMB12b4B13b3 "I/O Host Bridge Time-out caused by software" #define MSGMENUG174 "651174 ANALYZING SYSTEM ERROR LOG\n" \ "Error log analysis indicates an I/O Host Bridge time-out\n" \ "that was caused by software. This error is caused by an\n" \ "attempt to access an invalid I/O device address. Contact\n" \ "the software support structure for assistance if needed.\n" #define MSGMENUG175 "651175 ANALYZING SYSTEM ERROR LOG\n" \ "Error log analysis indicates a power fault that was\n" \ "caused by either using the Power-off button without \n" \ "performing a proper shutdown, or a loss of power to \nthe system.\n" #define MSGSPB16b6 "Internal Service Processor firmware error or incorrect " \ "version" #define DEFER_MSGSPB16b6 "A non-critical error has been detected: "\ "Internal Service Processor firmware error or incorrect version" #define MSGSPB18b3 "Service Processor error accessing Scan controller/hardware" #define DEFER_MSGSPB18b3 "A non-critical error has been detected: "\ "Service Processor error accessing Scan controller/hardware" #define MSGSPB18b6 "Loss of heart beat from Service Processor" #define DEFER_MSGSPB18b6 "A non-critical error has been detected: " \ "Loss of heart beat from Service Processor" #define MSGSPB19b5 "Non-supported hardware" #define DEFER_MSGSPB19b5 "A non-critical error has been detected: "\ "Non-supported hardware" #define MSGSPB19b6 "Error detected while handling an attention/interrupt " \ "from the system hardware" #define DEFER_MSGSPB19b6 "A non-critical error has been detected: " \ "Error detected while handling an attention/interrupt from the " \ "system hardware" #define MSGSPB28b1 "Wire Test Error" #define DEFER_MSGSPB28b1 "A non-critical error has been detected: "\ "Wire Test Error" #define MSGSPB28b2 "Mainstore or Cache IPL Diagnositc Error" #define DEFER_MSGSPB28b2 "A non-critical error has been detected: " \ "Mainstore or Cache IPL Diagnositc Error" #define MSGSPB28b3 "Other IPL Diagnostic Error" #define DEFER_MSGSPB28b3 "A non-critical error has been detected: "\ "Other IPL Diagnostic Error" #define MSGSPB28b4 "Clock or PLL Error" #define DEFER_MSGSPB28b4 "A non-critical error has been detected: "\ "Clock or PLL Error" #define MSGSPB28b5 "Hardware Scan or Initialization Error" #define DEFER_MSGSPB28b5 "A non-critical error has been detected: "\ "Hardware Scan or Initialization Error" #define MSGSPB28b6 "Chip ID Verification Error" #define DEFER_MSGSPB28b6 "A non-critical error has been detected: " \ "Chip ID Verification Error" #define MSGSPB28b7 "FRU Presence/Detect Error (Mis-Plugged)" #define DEFER_MSGSPB28b7 "A non-critical error has been detected: " \ "FRU Presence/Detect Error (Mis-Plugged)" #define MSGEPOWB16b1B17b4 "Power fault specifically due to internal " \ "battery failure" #define MSGMENUG202 "651202 ANALYZING SYSTEM ERROR LOG\n" \ "An environmental problem has been corrected and is \n" \ "no longer a problem. The problem that was corrected \n" \ "can be viewed by using the command:\n" \ "\t errpt -a -l %d" #define MSGMENUG203 "651203 ANALYZING SYSTEM ERROR LOG\n" \ "An environmental problem has been corrected and is no longer a problem." #define MSGMENUG204 "651204 ANALYZING SYSTEM ERROR LOG\n" \ "A loss of redundancy on input power was detected.\n\n" \ "Check for the following:\n" \ " 1. Loose or disconnected power source connections.\n" \ " 2. Loss of the power source.\n" \ " 3. For multiple enclosure systems, loose or\n" \ " disconnected power and/or signal connections\n" \ " between enclosures." #define MSGSPB28b0 "Array or Logic Built in Self Test Error" #define DEFER_MSGSPB28b0 "A non-critical error has been detected: " \ "Array or Logic Built in Self Test Error" #define PREDICT_REPAIR_PENDING "Recoverable errors on a resource indicate " \ "a potential for an unrecoverable error. The resource cannot be " \ "deconfigured and is still in use. The problem may be corrected by "\ "array bit steering. Use map 0235." #define MSGMENUG205 "651205 ANALYZING SYSTEM ERROR LOG\n" \ "The system lost input power.\n\n" \ "If the system has battery backup and input power is\n" \ "not restored, then the system will lose all power in\n" \ "a few minutes. Take the necessary precautions with\n" \ "running applications for a system shut down due to\n" \ "loss of power.\n\n" \ "If the system does not have battery backup, then this\n" \ "message is displayed after power has already been\n" \ "restored and your system rebooted successfully.\n\n" \ "Check the following for the cause of lost input power:\n" \ " 1. Loose or disconnected power source connections.\n" \ " 2. Loss of site power.\n" \ " 3. For multiple enclosure systems, loose or\n" \ " disconnected power and/or signal connections\n "\ " between enclosures." #define MSG_BYPASS "The following resource is unavailable due to an error. "\ "System is operating in degraded mode." #define MSGMENUG_REFC "\n\nSupporting data:\nRef. Code:\t%X" #define MSGMENUG_LOC "\nLocation Codes:\t%s" #define MSGMENUG206 "651206 ANALYZING SYSTEM ERROR LOG\n" \ "The system shutdown because the battery backup\n" \ "lost power. The system was running on battery\n" \ "backup because of loss of input power." #define MSGMENUGPEL_ERROR "651300 ANALYZING SYSTEM ERROR LOG\n" \ "\nThe platform reports the following error:\n\n" #define MSGMENUG_SRC "\n\nSupporting data:\n\nSRC: %s\n" #define MSGMENUG_PRIORITY "Priority: %c %s\n" #define MSGMENUG_FRU "FRU: %s" #define MSGMENUG_EXT_FRU "External FRU: %s" #define MSGMENUG_CODEFRU "Code FRU Procedure: %s" #define MSGMENUG_EXT_CODEFRU "External Code FRU Procedure: %s" #define MSGMENUG_TOOL_FRU "Tool FRU: %s" #define MSGMENUG_SYM_FRU "Symbolic FRU Id: %s" #define MSGMENUG_CFG "Configuration Procedure Id: %s" #define MSGMENUG_MAINT "Maintenance Procedure Id: %s" #define MSGMENUG_RESERVED "Reserved FRU Type: %s" #define MSGMENUG_SERIAL " Serial Number: %s" #define MSGMENUG_CCIN " CCIN: %s" #define MSGMENUG_LOCATION "\nLocation: %s\n" #define MSGMENUGPEL_EVENT "651301 ANALYZING PLATFORM EVENT\n\n" #define V6_INVALID_SUBID "Invalid subsystem ID, cannot determine message." #define V6_RESERVED_SUBID "Reserved subsystem ID, cannot determine message." #define V6_ER_10_00 "Processor subsystem including internal cache " \ "Informational (non-error) Event. Refer to the system service " \ "documentation for more information." #define V6_ER_10_10 "Processor subsystem including internal cache " \ "Recovered Error, general. Refer to the system service documentation " \ "for more information." #define V6_ER_10_20 "Processor subsystem including internal cache " \ "Predictive Error, general. Refer to the system service documentation " \ "for more information." #define V6_ER_10_21 "Processor subsystem including internal cache " \ "Predictive Error, degraded performance. Refer to the system service " \ "documentation for more information." #define V6_ER_10_22 "Processor subsystem including internal cache " \ "Predictive Error, fault may be corrected after platform re-IPL. "\ "Refer to the system service documentation for more information." #define V6_ER_10_23 "Processor subsystem including internal cache " \ "Predictive Error, fault may be corrected after IPL, degraded " \ "performance. Refer to the system service documentation for more " \ "information." #define V6_ER_10_24 "Processor subsystem including internal cache " \ "Predictive Error, loss of redundancy. Refer to the system service " \ "documentation for more information." #define V6_ER_10_40 "Processor subsystem including internal cache " \ "Unrecovered Error, general. Refer to the system service documentation " \ "for more information." #define V6_ER_10_41 "Processor subsystem including internal cache " \ "Unrecovered Error, bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_10_44 "Processor subsystem including internal cache " \ "Unrecovered Error, bypassed with loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_10_45 "Processor subsystem including internal cache " \ "Unrecovered Error, bypassed with loss of redundancy and performance. "\ "Refer to the system service documentation for more information." #define V6_ER_10_48 "Processor subsystem including internal cache " \ "Unrecovered Error, bypassed with loss of function. Refer to the " \ "system service documentation for more information." #define V6_ER_10_60 "Processor subsystem including internal cache " \ "Error on diagnostic test, general. Refer to the system service " \ "documentation for more information." #define V6_ER_10_61 "Processor subsystem including internal cache " \ "Error on diagnostic test, resource may produce incorrect result. "\ "Refer to the system service documentation for more information." #define V6_ER_20_00 "Memory subsystem including external cache " \ "Informational (non-error) Event. "\ "Refer to the system service documentation for more information." #define V6_ER_20_10 "Memory subsystem including external cache " \ "Recovered Error, general. "\ "Refer to the system service documentation for more information." #define V6_ER_20_20 "Memory subsystem including external cache " \ "Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_20_21 "Memory subsystem including external cache " \ "Predictive Error, degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_20_22 "Memory subsystem including external cache " \ "Predictive Error, fault may be corrected after platform re-IPL. "\ "Refer to the system service documentation for more information." #define V6_ER_20_23 "Memory subsystem including external cache " \ "Predictive Error, fault may be corrected after IPL, degraded " \ "performance. Refer to the system service documentation for more " \ "information." #define V6_ER_20_24 "Memory subsystem including external cache " \ "Predictive Error, loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_20_40 "Memory subsystem including external cache " \ "Unrecovered Error, general. "\ "Refer to the system service documentation for more information." #define V6_ER_20_41 "Memory subsystem including external cache " \ "Unrecovered Error, bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_20_44 "Memory subsystem including external cache " \ "Unrecovered Error, bypassed with loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_20_45 "Memory subsystem including external cache " \ "Unrecovered Error, bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_20_48 "Memory subsystem including external cache " \ "Unrecovered Error, bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_20_60 "Memory subsystem including external cache " \ "Error on diagnostic test, general. " \ "Refer to the system service documentation for more information." #define V6_ER_20_61 "Memory subsystem including external cache Error on " \ "diagnostic test, resource may produce incorrect result. "\ "Refer to the system service documentation for more information." #define V6_ER_30_00 "I/O subsystem (hub, bridge, bus) Informational " \ "(non-error) Event. " \ "Refer to the system service documentation for more information." #define V6_ER_30_10 "I/O subsystem (hub, bridge, bus) Recovered " \ "Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_30_20 "I/O subsystem (hub, bridge, bus) Predictive " \ "Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_30_21 "I/O subsystem (hub, bridge, bus) Predictive Error, " \ "degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_30_22 "I/O subsystem (hub, bridge, bus) Predictive Error, " \ "fault may be corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_30_23 "I/O subsystem (hub, bridge, bus) Predictive Error, " \ "fault may be corrected after IPL, degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_30_24 "I/O subsystem (hub, bridge, bus) Predictive Error, " \ "loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_30_40 "I/O subsystem (hub, bridge, bus) Unrecovered Error, " \ "general. " \ "Refer to the system service documentation for more information." #define V6_ER_30_41 "I/O subsystem (hub, bridge, bus) Unrecovered Error, " \ "bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_30_44 "I/O subsystem (hub, bridge, bus) Unrecovered Error, " \ "bypassed with loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_30_45 "I/O subsystem (hub, bridge, bus) Unrecovered Error, " \ "bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_30_48 "I/O subsystem (hub, bridge, bus) Unrecovered Error, " \ "bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_30_60 "I/O subsystem (hub, bridge, bus) Error on " \ "diagnostic test, general. " \ "Refer to the system service documentation for more information." #define V6_ER_30_61 "I/O subsystem (hub, bridge, bus) Error on " \ "diagnostic test, resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_40_00 "I/O adapter, device and peripheral Informational " \ "(non-error) Event. " \ "Refer to the system service documentation for more information." #define V6_ER_40_10 "I/O adapter, device and peripheral Recovered Error, " \ "general. "\ "Refer to the system service documentation for more information." #define V6_ER_40_20 "I/O adapter, device and peripheral Predictive Error, " \ "general. "\ "Refer to the system service documentation for more information." #define V6_ER_40_21 "I/O adapter, device and peripheral Predictive Error, " \ "degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_40_22 "I/O adapter, device and peripheral Predictive Error, " \ "fault may be corrected after platform re-IPL. "\ "Refer to the system service documentation for more information." #define V6_ER_40_23 "I/O adapter, device and peripheral Predictive Error, " \ "fault may be corrected after IPL, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_40_24 "I/O adapter, device and peripheral Predictive Error, " \ "loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_40_40 "I/O adapter, device and peripheral Unrecovered Error, " \ "general. "\ "Refer to the system service documentation for more information." #define V6_ER_40_41 "I/O adapter, device and peripheral Unrecovered Error, " \ "bypassed with degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_40_44 "I/O adapter, device and peripheral Unrecovered Error, " \ "bypassed with loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_40_45 "I/O adapter, device and peripheral Unrecovered Error, " \ "bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_40_48 "I/O adapter, device and peripheral Unrecovered Error, " \ "bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_40_60 "I/O adapter, device and peripheral Error on diagnostic " \ "test, general. "\ "Refer to the system service documentation for more information." #define V6_ER_40_61 "I/O adapter, device and peripheral Error on diagnostic " \ "test, resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_50_00 "CEC hardware Informational (non-error) Event. "\ "Refer to the system service documentation for more information." #define V6_ER_50_10 "CEC hardware Recovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_50_20 "CEC hardware Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_50_21 "CEC hardware Predictive Error, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_50_22 "CEC hardware Predictive Error, fault may be " \ "corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_50_23 "CEC hardware Predictive Error, fault may be " \ "corrected after IPL, degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_50_24 "CEC hardware Predictive Error, loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_50_40 "CEC hardware Unrecovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_50_41 "CEC hardware Unrecovered Error, bypassed with " \ "degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_50_44 "CEC hardware Unrecovered Error, bypassed with " \ "loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_50_45 "CEC hardware Unrecovered Error, bypassed with " \ "loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_50_48 "CEC hardware Unrecovered Error, bypassed with " \ "loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_50_60 "CEC hardware Error on diagnostic test, general. " \ "Refer to the system service documentation for more information." #define V6_ER_50_61 "CEC hardware Error on diagnostic test, resource " \ "may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_60_00 "Power/Cooling subsystem Informational (non-error) Event."\ "Refer to the system service documentation for more information." #define V6_ER_60_10 "Power/Cooling subsystem Recovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_60_20 "Power/Cooling subsystem Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_60_21 "Power/Cooling subsystem Predictive Error, " \ "degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_60_22 "Power/Cooling subsystem Predictive Error, " \ "fault may be corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_60_23 "Power/Cooling subsystem Predictive Error, " \ "fault may be corrected after IPL, degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_60_24 "Power/Cooling subsystem Predictive Error, " \ "loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_60_40 "Power/Cooling subsystem Unrecovered Error, general. "\ "Refer to the system service documentation for more information." #define V6_ER_60_41 "Power/Cooling subsystem Unrecovered Error, " \ "bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_60_44 "Power/Cooling subsystem Unrecovered Error, " \ "bypassed with loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_60_45 "Power/Cooling subsystem Unrecovered Error, " \ "bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_60_48 "Power/Cooling subsystem Unrecovered Error, " \ "bypassed with loss of function. "\ "Refer to the system service documentation for more information." #define V6_ER_60_60 "Power/Cooling subsystem Error on diagnostic test, " \ "general. "\ "Refer to the system service documentation for more information." #define V6_ER_60_61 "Power/Cooling subsystem Error on diagnostic test, " \ "resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_70_00 "Other subsystem Informational (non-error) Event. " \ "Refer to the system service documentation for more information." #define V6_ER_70_10 "Other subsystem Recovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_70_20 "Other subsystem Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_70_21 "Other subsystem Predictive Error, degraded performance."\ "Refer to the system service documentation for more information." #define V6_ER_70_22 "Other subsystem Predictive Error, " \ "fault may be corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_70_23 "Other subsystem Predictive Error, " \ "fault may be corrected after IPL, degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_70_24 "Other subsystem Predictive Error, loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_70_40 "Other subsystem Unrecovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_70_41 "Other subsystem Unrecovered Error, " \ "bypassed with degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_70_44 "Other subsystem Unrecovered Error, " \ "bypassed with loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_70_45 "Other subsystem Unrecovered Error, " \ "bypassed with loss of redundancy and performance. "\ "Refer to the system service documentation for more information." #define V6_ER_70_48 "Other subsystem Unrecovered Error, " \ "bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_70_60 "Other subsystem Error on diagnostic test, general. " \ "Refer to the system service documentation for more information." #define V6_ER_70_61 "Other subsystem Error on diagnostic test, " \ "resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_00 "Surveillance Error Informational (non-error) Event. "\ "Refer to the system service documentation for more information." #define V6_ER_7A_10 "Surveillance Error Recovered Error, general. "\ "Refer to the system service documentation for more information." #define V6_ER_7A_20 "Surveillance Error Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_21 "Surveillance Error Predictive Error, " \ "degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_22 "Surveillance Error Predictive Error, " \ "fault may be corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_23 "Surveillance Error Predictive Error, " \ "fault may be corrected after IPL, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_24 "Surveillance Error Predictive Error, " \ "loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_40 "Surveillance Error Unrecovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_41 "Surveillance Error Unrecovered Error, " \ "bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_44 "Surveillance Error Unrecovered Error, " \ "bypassed with loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_7A_45 "Surveillance Error Unrecovered Error, " \ "bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_48 "Surveillance Error Unrecovered Error, " \ "bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_60 "Surveillance Error Error on diagnostic test, general. " \ "Refer to the system service documentation for more information." #define V6_ER_7A_61 "Surveillance Error Error on diagnostic test, " \ "resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_80_00 "Platform Firmware Informational (non-error) Event. " \ "Refer to the system service documentation for more information." #define V6_ER_80_10 "Platform Firmware Recovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_80_20 "Platform Firmware Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_80_21 "Platform Firmware Predictive Error, " \ "degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_80_22 "Platform Firmware Predictive Error, " \ "fault may be corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_80_23 "Platform Firmware Predictive Error, " \ "fault may be corrected after IPL, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_80_24 "Platform Firmware Predictive Error, loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_80_40 "Platform Firmware Unrecovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_80_41 "Platform Firmware Unrecovered Error, " \ "bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_80_44 "Platform Firmware Unrecovered Error, " \ "bypassed with loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_80_45 "Platform Firmware Unrecovered Error, " \ "bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_80_48 "Platform Firmware Unrecovered Error, " \ "bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_80_60 "Platform Firmware Error on diagnostic test, general. " \ "Refer to the system service documentation for more information." #define V6_ER_80_61 "Platform Firmware Error on diagnostic test, " \ "resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_90_00 "Software Informational (non-error) Event. " \ "Refer to the system service documentation for more information." #define V6_ER_90_10 "Software Recovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_90_20 "Software Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_90_21 "Software Predictive Error, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_90_22 "Software Predictive Error, " \ "fault may be corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_90_23 "Software Predictive Error, " \ "fault may be corrected after IPL, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_90_24 "Software Predictive Error, loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_90_40 "Software Unrecovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_90_41 "Software Unrecovered Error, " \ "bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_90_44 "Software Unrecovered Error, "\ "bypassed with loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_90_45 "Software Unrecovered Error, " \ "bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_90_48 "Software Unrecovered Error, " \ "bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_90_60 "Software Error on diagnostic test, general. "\ "Refer to the system service documentation for more information." #define V6_ER_90_61 "Software Error on diagnostic test, " \ "resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_00 "External environment Informational (non-error) Event. "\ "Refer to the system service documentation for more information." #define V6_ER_A0_10 "External environment Recovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_20 "External environment Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_21 "External environment Predictive Error, " \ "degraded performance. "\ "Refer to the system service documentation for more information." #define V6_ER_A0_22 "External environment Predictive Error, " \ "fault may be corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_23 "External environment Predictive Error, " \ "fault may be corrected after IPL, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_24 "External environment Predictive Error, " \ "loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_40 "External environment Unrecovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_41 "External environment Unrecovered Error, " \ "bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_44 "External environment Unrecovered Error, " \ "bypassed with loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_45 "External environment Unrecovered Error, " \ "bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_48 "External environment Unrecovered Error, " \ "bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_A0_60 "External environment Error on diagnostic test, general. "\ "Refer to the system service documentation for more information." #define V6_ER_A0_61 "External environment Error on diagnostic test, " \ "resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_00 "Reserved Informational (non-error) Event. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_10 "Reserved Recovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_20 "Reserved Predictive Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_21 "Reserved Predictive Error, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_22 "Reserved Predictive Error, " \ "fault may be corrected after platform re-IPL. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_23 "Reserved Predictive Error, " \ "fault may be corrected after IPL, degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_24 "Reserved Predictive Error, loss of redundancy. "\ "Refer to the system service documentation for more information." #define V6_ER_B0_40 "Reserved Unrecovered Error, general. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_41 "Reserved Unrecovered Error, " \ "bypassed with degraded performance. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_44 "Reserved Unrecovered Error, " \ "bypassed with loss of redundancy. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_45 "Reserved Unrecovered Error, " \ "bypassed with loss of redundancy and performance. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_48 "Reserved Unrecovered Error, " \ "bypassed with loss of function. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_60 "Reserved Error on diagnostic test, general. " \ "Refer to the system service documentation for more information." #define V6_ER_B0_61 "Reserved Error on diagnostic test, " \ "resource may produce incorrect result. " \ "Refer to the system service documentation for more information." #define V6_EV_10_00 "Processor subsystem including internal cache Not " \ "applicable." #define V6_EV_10_01 "Processor subsystem including internal cache " \ "Miscellaneous, Information Only." #define V6_EV_10_08 "Processor subsystem including internal cache " \ "Dump Notification." #define V6_EV_10_10 "Processor subsystem including internal cache " \ "Previously reported error has been corrected by the system." #define V6_EV_10_20 "Processor subsystem including internal cache " \ "System resources manually deconfigured by user." #define V6_EV_10_21 "Processor subsystem including internal cache " \ "System resources deconfigured by system due to prior error event." #define V6_EV_10_22 "Processor subsystem including internal cache " \ "Resource deallocation event notification." #define V6_EV_10_30 "Processor subsystem including internal cache " \ "Customer environmental problem has returned to normal." #define V6_EV_10_40 "Processor subsystem including internal cache " \ "Concurrent Maintenance Event." #define V6_EV_10_60 "Processor subsystem including internal cache " \ "Capacity Upgrade Event." #define V6_EV_10_70 "Processor subsystem including internal cache " \ "Resource Sparing Event." #define V6_EV_10_80 "Processor subsystem including internal cache " \ "Dynamic Reconfiguration Event." #define V6_EV_10_D0 "Processor subsystem including internal cache " \ "Normal system/platform shutdown or powered off." #define V6_EV_10_E0 "Processor subsystem including internal cache " \ "Platform powered off by user with normal shutdown." #define V6_EV_20_00 "Memory subsystem including external cache " \ "Not applicable." #define V6_EV_20_01 "Memory subsystem including external cache " \ "Miscellaneous, Information Only." #define V6_EV_20_08 "Memory subsystem including external cache " \ "Dump Notification." #define V6_EV_20_10 "Memory subsystem including external cache " \ "Previously reported error has been corrected by the system." #define V6_EV_20_20 "Memory subsystem including external cache " \ "System resources manually deconfigured by user." #define V6_EV_20_21 "Memory subsystem including external cache " \ "System resources deconfigured by system due to prior error event." #define V6_EV_20_22 "Memory subsystem including external cache " \ "Resource deallocation event notification." #define V6_EV_20_30 "Memory subsystem including external cache " \ "Customer environmental problem has returned to normal." #define V6_EV_20_40 "Memory subsystem including external cache " \ "Concurrent Maintenance Event." #define V6_EV_20_60 "Memory subsystem including external cache " \ "Capacity Upgrade Event." #define V6_EV_20_70 "Memory subsystem including external cache " \ "Resource Sparing Event." #define V6_EV_20_80 "Memory subsystem including external cache " \ "Dynamic Reconfiguration Event." #define V6_EV_20_D0 "Memory subsystem including external cache " \ "Normal system/platform shutdown or powered off." #define V6_EV_20_E0 "Memory subsystem including external cache " \ "Platform powered off by user with normal shutdown." #define V6_EV_30_00 "I/O subsystem (hub, bridge, bus) Not applicable." #define V6_EV_30_01 "I/O subsystem (hub, bridge, bus) " \ "Miscellaneous, Information Only." #define V6_EV_30_08 "I/O subsystem (hub, bridge, bus) " \ "Dump Notification." #define V6_EV_30_10 "I/O subsystem (hub, bridge, bus) " \ "Previously reported error has been corrected by the system." #define V6_EV_30_20 "I/O subsystem (hub, bridge, bus) " \ "System resources manually deconfigured by user." #define V6_EV_30_21 "I/O subsystem (hub, bridge, bus) " \ "System resources deconfigured by system due to prior error event." #define V6_EV_30_22 "I/O subsystem (hub, bridge, bus) " \ "Resource deallocation event notification." #define V6_EV_30_30 "I/O subsystem (hub, bridge, bus) " \ "Customer environmental problem has returned to normal." #define V6_EV_30_40 "I/O subsystem (hub, bridge, bus) " \ "Concurrent Maintenance Event." #define V6_EV_30_60 "I/O subsystem (hub, bridge, bus) Capacity Upgrade Event." #define V6_EV_30_70 "I/O subsystem (hub, bridge, bus) Resource Sparing Event." #define V6_EV_30_80 "I/O subsystem (hub, bridge, bus) " \ "Dynamic Reconfiguration Event." #define V6_EV_30_D0 "I/O subsystem (hub, bridge, bus) " \ "Normal system/platform shutdown or powered off." #define V6_EV_30_E0 "I/O subsystem (hub, bridge, bus) " \ "Platform powered off by user with normal shutdown." #define V6_EV_40_00 "I/O adapter, device and peripheral Not applicable." #define V6_EV_40_01 "I/O adapter, device and peripheral " \ "Miscellaneous, Information Only." #define V6_EV_40_08 "I/O adapter, device and peripheral " \ "Dump Notification." #define V6_EV_40_10 "I/O adapter, device and peripheral " \ "Previously reported error has been corrected by the system." #define V6_EV_40_20 "I/O adapter, device and peripheral " \ "System resources manually deconfigured by user." #define V6_EV_40_21 "I/O adapter, device and peripheral " \ "System resources deconfigured by system due to prior error event." #define V6_EV_40_22 "I/O adapter, device and peripheral " \ "Resource deallocation event notification." #define V6_EV_40_30 "I/O adapter, device and peripheral " \ "Customer environmental problem has returned to normal." #define V6_EV_40_40 "I/O adapter, device and peripheral " \ "Concurrent Maintenance Event." #define V6_EV_40_60 "I/O adapter, device and peripheral " \ "Capacity Upgrade Event." #define V6_EV_40_70 "I/O adapter, device and peripheral " \ "Resource Sparing Event." #define V6_EV_40_80 "I/O adapter, device and peripheral " \ "Dynamic Reconfiguration Event." #define V6_EV_40_D0 "I/O adapter, device and peripheral " \ "Normal system/platform shutdown or powered off." #define V6_EV_40_E0 "I/O adapter, device and peripheral " \ "Platform powered off by user with normal shutdown." #define V6_EV_50_00 "CEC hardware Not applicable." #define V6_EV_50_01 "CEC hardware Miscellaneous, Information Only." #define V6_EV_50_08 "CEC hardware Dump Notification." #define V6_EV_50_10 "CEC hardware " \ "Previously reported error has been corrected by the system." #define V6_EV_50_20 "CEC hardware " \ "System resources manually deconfigured by user." #define V6_EV_50_21 "CEC hardware " \ "System resources deconfigured by system due to prior error event." #define V6_EV_50_22 "CEC hardware Resource deallocation event notification." #define V6_EV_50_30 "CEC hardware " \ "Customer environmental problem has returned to normal." #define V6_EV_50_40 "CEC hardware Concurrent Maintenance Event." #define V6_EV_50_60 "CEC hardware Capacity Upgrade Event." #define V6_EV_50_70 "CEC hardware Resource Sparing Event." #define V6_EV_50_80 "CEC hardware Dynamic Reconfiguration Event." #define V6_EV_50_D0 "CEC hardware " \ "Normal system/platform shutdown or powered off." #define V6_EV_50_E0 "CEC hardware " \ "Platform powered off by user with normal shutdown." #define V6_EV_60_00 "Power/Cooling subsystem Not applicable." #define V6_EV_60_01 "Power/Cooling subsystem Miscellaneous, Information Only." #define V6_EV_60_08 "Power/Cooling subsystem Dump Notification." #define V6_EV_60_10 "Power/Cooling subsystem " \ "Previously reported error has been corrected by the system." #define V6_EV_60_20 "Power/Cooling subsystem " \ "System resources manually deconfigured by user." #define V6_EV_60_21 "Power/Cooling subsystem " \ "System resources deconfigured by system due to prior error event." #define V6_EV_60_22 "Power/Cooling subsystem " \ "Resource deallocation event notification." #define V6_EV_60_30 "Power/Cooling subsystem " \ "Customer environmental problem has returned to normal." #define V6_EV_60_40 "Power/Cooling subsystem Concurrent Maintenance Event." #define V6_EV_60_60 "Power/Cooling subsystem Capacity Upgrade Event." #define V6_EV_60_70 "Power/Cooling subsystem Resource Sparing Event." #define V6_EV_60_80 "Power/Cooling subsystem Dynamic Reconfiguration Event." #define V6_EV_60_D0 "Power/Cooling subsystem " \ "Normal system/platform shutdown or powered off." #define V6_EV_60_E0 "Power/Cooling subsystem " \ "Platform powered off by user with normal shutdown." #define V6_EV_70_00 "Other subsystem Not applicable." #define V6_EV_70_01 "Other subsystem Miscellaneous, Information Only." #define V6_EV_70_08 "Other subsystem Dump Notification." #define V6_EV_70_10 "Other subsystem " \ "Previously reported error has been corrected by the system." #define V6_EV_70_20 "Other subsystem " \ "System resources manually deconfigured by user." #define V6_EV_70_21 "Other subsystem " \ "System resources deconfigured by system due to prior error event." #define V6_EV_70_22 "Other subsystem Resource deallocation event notification." #define V6_EV_70_30 "Other subsystem " \ "Customer environmental problem has returned to normal." #define V6_EV_70_40 "Other subsystem Concurrent Maintenance Event." #define V6_EV_70_60 "Other subsystem Capacity Upgrade Event." #define V6_EV_70_70 "Other subsystem Resource Sparing Event." #define V6_EV_70_80 "Other subsystem Dynamic Reconfiguration Event." #define V6_EV_70_D0 "Other subsystem " \ "Normal system/platform shutdown or powered off." #define V6_EV_70_E0 "Other subsystem " \ "Platform powered off by user with normal shutdown." #define V6_EV_7A_00 "Surveillance Error Not applicable." #define V6_EV_7A_01 "Surveillance Error Miscellaneous, Information Only." #define V6_EV_7A_08 "Surveillance Error Dump Notification." #define V6_EV_7A_10 "Surveillance Error " \ "Previously reported error has been corrected by the system." #define V6_EV_7A_20 "Surveillance Error " \ "System resources manually deconfigured by user." #define V6_EV_7A_21 "Surveillance Error " \ "System resources deconfigured by system due to prior error event." #define V6_EV_7A_22 "Surveillance Error " \ "Resource deallocation event notification." #define V6_EV_7A_30 "Surveillance Error " \ "Customer environmental problem has returned to normal." #define V6_EV_7A_40 "Surveillance Error Concurrent Maintenance Event." #define V6_EV_7A_60 "Surveillance Error Capacity Upgrade Event." #define V6_EV_7A_70 "Surveillance Error Resource Sparing Event." #define V6_EV_7A_80 "Surveillance Error Dynamic Reconfiguration Event." #define V6_EV_7A_D0 "Surveillance Error " \ "Normal system/platform shutdown or powered off." #define V6_EV_7A_E0 "Surveillance Error " \ "Platform powered off by user with normal shutdown." #define V6_EV_80_00 "Platform Firmware Not applicable." #define V6_EV_80_01 "Platform Firmware Miscellaneous, Information Only." #define V6_EV_80_08 "Platform Firmware Dump Notification." #define V6_EV_80_10 "Platform Firmware " \ "Previously reported error has been corrected by the system." #define V6_EV_80_20 "Platform Firmware " \ "System resources manually deconfigured by user." #define V6_EV_80_21 "Platform Firmware " \ "System resources deconfigured by system due to prior error event." #define V6_EV_80_22 "Platform Firmware " \ "Resource deallocation event notification." #define V6_EV_80_30 "Platform Firmware " \ "Customer environmental problem has returned to normal." #define V6_EV_80_40 "Platform Firmware Concurrent Maintenance Event." #define V6_EV_80_60 "Platform Firmware Capacity Upgrade Event." #define V6_EV_80_70 "Platform Firmware Resource Sparing Event." #define V6_EV_80_80 "Platform Firmware Dynamic Reconfiguration Event." #define V6_EV_80_D0 "Platform Firmware " \ "Normal system/platform shutdown or powered off." #define V6_EV_80_E0 "Platform Firmware " \ "Platform powered off by user with normal shutdown." #define V6_EV_90_00 "Software Not applicable." #define V6_EV_90_01 "Software Miscellaneous, Information Only." #define V6_EV_90_08 "Software Dump Notification." #define V6_EV_90_10 "Software " \ "Previously reported error has been corrected by the system." #define V6_EV_90_20 "Software " \ "System resources manually deconfigured by user." #define V6_EV_90_21 "Software " \ "System resources deconfigured by system due to prior error event." #define V6_EV_90_22 "Software Resource deallocation event notification." #define V6_EV_90_30 "Software " \ "Customer environmental problem has returned to normal." #define V6_EV_90_40 "Software Concurrent Maintenance Event." #define V6_EV_90_60 "Software Capacity Upgrade Event." #define V6_EV_90_70 "Software Resource Sparing Event." #define V6_EV_90_80 "Software Dynamic Reconfiguration Event." #define V6_EV_90_D0 "Software Normal system/platform shutdown or powered off." #define V6_EV_90_E0 "Software " \ "Platform powered off by user with normal shutdown." #define V6_EV_A0_00 "External environment Not applicable." #define V6_EV_A0_01 "External environment Miscellaneous, Information Only." #define V6_EV_A0_08 "External environment Dump Notification." #define V6_EV_A0_10 "External environment " \ "Previously reported error has been corrected by the system." #define V6_EV_A0_20 "External environment " \ "System resources manually deconfigured by user." #define V6_EV_A0_21 "External environment " \ "System resources deconfigured by system due to prior error event." #define V6_EV_A0_22 "External environment " \ "Resource deallocation event notification." #define V6_EV_A0_30 "External environment " \ "Customer environmental problem has returned to normal." #define V6_EV_A0_40 "External environment Concurrent Maintenance Event." #define V6_EV_A0_60 "External environment Capacity Upgrade Event." #define V6_EV_A0_70 "External environment Resource Sparing Event." #define V6_EV_A0_80 "External environment Dynamic Reconfiguration Event." #define V6_EV_A0_D0 "External environment " \ "Normal system/platform shutdown or powered off." #define V6_EV_A0_E0 "External environment " \ "Platform powered off by user with normal shutdown." #define V6_EV_B0_00 "Reserved Not applicable." #define V6_EV_B0_01 "Reserved Miscellaneous, Information Only." #define V6_EV_B0_08 "Reserved Dump Notification." #define V6_EV_B0_10 "Reserved " \ "Previously reported error has been corrected by the system." #define V6_EV_B0_20 "Reserved System resources manually deconfigured by user." #define V6_EV_B0_21 "Reserved " \ "System resources deconfigured by system due to prior error event." #define V6_EV_B0_22 "Reserved Resource deallocation event notification." #define V6_EV_B0_30 "Reserved " \ "Customer environmental problem has returned to normal." #define V6_EV_B0_40 "Reserved Concurrent Maintenance Event." #define V6_EV_B0_60 "Reserved Capacity Upgrade Event." #define V6_EV_B0_70 "Reserved Resource Sparing Event." #define V6_EV_B0_80 "Reserved Dynamic Reconfiguration Event." #define V6_EV_B0_D0 "Reserved Normal system/platform shutdown or powered off." #define V6_EV_B0_E0 "Reserved " \ "Platform powered off by user with normal shutdown." #endif ppc64-diag-2.7.0/rtas_errd/epow.c0000644000000000000000000002663612642205425015176 0ustar rootroot/** * @file epow.c * @brief Routines to handle EPOW RTAS events * * Copyright (C) 2004 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include "rtas_errd.h" /* Sensor tokens, from RPA section 7.3.7.5 (get-sensor-state) */ #define SENSOR_TOKEN_KEY_SWITCH 1 #define SENSOR_TOKEN_ENCLOSURE_SWITCH 2 #define SENSOR_TOKEN_THERMAL_SENSOR 3 #define SENSOR_TOKEN_POWER_SOURCE 5 #define SENSOR_TOKEN_EPOW_SENSOR 9 /* File paths */ #define EPOW_PROGRAM "/etc/rc.powerfail" #define EPOW_PROGRAM_NOPATH "rc.powerfail" /** * @var time_remaining * @brief Time remaining until a system shutdown. * * The time_remaining variable is used by the epow timer * to track the time remaining until a system shutdown */ static int time_remaining = 0; /** * epow_timer_handler * @brief Routine to handle SIGALRM timer interrupts. * * @param sig unused * @param siginfo unused * @param context unused */ void epow_timer_handler(int sig, siginfo_t siginfo, void *context) { int rc, state; struct itimerval tv; if (time_remaining <= 0) { /* * Time is up; disable the interval timer. * The EPOW_PROGRAM should have already shut the * system down by this point. */ tv.it_interval.tv_sec = 0; tv.it_interval.tv_usec = 0; tv.it_value = tv.it_interval; rc = setitimer(ITIMER_REAL, &tv, NULL); return; } rc = rtas_get_sensor(SENSOR_TOKEN_EPOW_SENSOR, 0, &state); if (state < RTAS_EPOW_ACTION_SYSTEM_SHUTDOWN) { /* * Problem resolved; disable the interval timer and * update the epow status file. */ tv.it_interval.tv_sec = 0; tv.it_interval.tv_usec = 0; tv.it_value = tv.it_interval; rc = setitimer(ITIMER_REAL, &tv, NULL); if (state == RTAS_EPOW_ACTION_RESET) update_epow_status_file(0); else if (state == RTAS_EPOW_ACTION_WARN_COOLING) update_epow_status_file(8); else if (state == RTAS_EPOW_ACTION_WARN_POWER) update_epow_status_file(9); time_remaining = 0; return; } /* * If we make it this far, the problem (or a worse one) * still exists. If the problem is worse, the system will * probably shut down within 20 seconds. We shouldn't * overwrite the status so that if a worse problem exists, * it can be handled appropriately. */ time_remaining -= 5; return; } static void log_epow(struct event *event, char *fmt, ...) { va_list ap; char buf[1024]; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); log_msg(event, buf); snprintf(event->addl_text, ADDL_TEXT_MAX, "%s", buf); } /** * parse_epow * @brief Retrieve the epow status from an RTAS event. * * This routine returns the value that will be written to the epow_status * file. The value will be used by the EPOW_PROGRAM script (which can * be modified by a system administrator) to establish actions to be * taken for certain EPOW conditions. The return value must be 7 digits * or less. * * @param event pointer to the RTAS event * @return *
 *  Return Value					Action
 *  ==========================			=====================
 *  0   normal state				none
 *  1   loss of primary power			4 ms to shutdown
 *  2   power supply failure			4 ms to shutdown
 *  3   manual power-off switch	activated	4 ms to shutdown
 *  4   thermal high				20 seconds to shutdown
 *  5   primary fan failure			20 seconds to shutdown
 *  6   secondary fan failure			10 minutes to shutdown
 *  7   battery backup				10 minutes to shutdown
 *  8   non-critical cooling problem		none
 *  9   non-critical power problem		none
 *  10  (v6) normal shutdown requested		initiate shutdown immediately
 *  11  (v6) loss of critical system functions	initiate shutdown immediately
 * 
* */ static int parse_epow(struct event *event) { struct rtas_event_hdr *rtas_hdr = event->rtas_hdr; struct rtas_epow_scn *epow; struct itimerval tv; char *event_type; int rc, state; /* * Check the sensor state; this will be used to ensure * that the problem in question is current, and isn't being retrieved * from NVRAM after a reboot when there wasn't time to handle the * problem (e.g. the power cable was yanked). */ rc = rtas_get_sensor(SENSOR_TOKEN_EPOW_SENSOR, 0, &state); if (rtas_hdr->extended == 0) { if (state > 0) { /* Assume a system halt */ log_epow(event, "Recieved shortened EPOW event, " "assuming power failure"); return 10; } else { log_epow(event, "Received shortened EPOW event, EPOW " "sensor not in shutdown mode"); return 0; } } epow = rtas_get_epow_scn(event->rtas_event); if (epow == NULL) { log_msg(event, "Could not retrieve EPOW section to handle " "incoming EPOW event, skipping"); return 0; } switch (epow->action_code) { case RTAS_EPOW_ACTION_RESET: log_epow(event, "Received EPOW action code reset (no action)"); return 0; break; case RTAS_EPOW_ACTION_WARN_COOLING: log_epow(event, "Received non-critical cooling EPOW action " "code (8)"); return 8; break; case RTAS_EPOW_ACTION_WARN_POWER: log_epow(event, "Received non-critical power EPOW action " "code (9)"); return 9; break; case RTAS_EPOW_ACTION_SYSTEM_SHUTDOWN: if (state != RTAS_EPOW_ACTION_SYSTEM_SHUTDOWN) { log_epow(event, "EPOW event: system shutdown " "requested, but the sensor state indicates " "the problem was resolved"); return 0; } /* * We have 10 minutes to shutdown. If we are already running * an interval timer we'll just just increase the length of * time we check for status updates instead of starting a new * timer. */ if (time_remaining <= 0) { /* Set up an interval timer to update the epow * status file every 5 seconds. */ tv.it_interval.tv_sec = 5; tv.it_interval.tv_usec = 0; tv.it_value = tv.it_interval; rc = setitimer(ITIMER_REAL, &tv, NULL); } time_remaining = 600; /* in seconds */ if (epow->fan) { log_epow(event, "EPOW event: system shutdown will " "begin in %d seconds due to a fan failure", time_remaining); return 6; } if (epow->power_fault) { log_epow(event, "EPOW event: system shutdown will " "begin in %d seconds due to a power fault", time_remaining); return 7; } if (epow->event_modifier == RTAS_EPOW_MOD_NORMAL_SHUTDOWN) { log_epow(event, "EPOW event: system shutdown will " "begin in %d seconds due to a normal " "shutdown request", time_remaining); return 10; } if (epow->event_modifier == RTAS_EPOW_MOD_UTILITY_POWER_LOSS) { log_epow(event, "EPOW event: system shutdown will " "begin in %d seconds due to a battery " "failure", time_remaining); return 7; } if (epow->event_modifier == RTAS_EPOW_MOD_CRIT_FUNC_LOSS) { log_epow(event, "EPOW event: system shutdown will " "begin in %d seconds due to a loss of system " "critical functions", time_remaining); return 11; } #ifdef RTAS_EPOW_MOD_AMBIENT_TEMP if (epow->event_modifier == RTAS_EPOW_MOD_AMBIENT_TEMP) { log_epow(event, "EPOW event: system shutdown will " "begin in %d seconds due to ambient " "temperature being too high", time_remaining); return 4; } #endif log_epow(event, "EPOW event: system shutdown will begin in %d " "seconds due to an unknown cause", time_remaining); return 7; break; case RTAS_EPOW_ACTION_SYSTEM_HALT: if (state != RTAS_EPOW_ACTION_SYSTEM_HALT) { log_epow(event, "EPOW event: system halt requested, " "but the sensor state indicates the problem " "was resolved"); return 0; } if (rtas_hdr->version < 6) { if (epow->fan) { log_epow(event, "EPOW event: system halting " "due to a fan failure"); return 5; } if (epow->temp) { log_epow(event, "EPOW event: system halting " "due to a thermal condition"); return 4; } log_epow(event, "EPOW event: system halting due to " "an unknown condition"); return 4; } else { log_epow(event, "EPOW event: system halting due to " "an unspecified condition"); return 4; } break; case RTAS_EPOW_ACTION_MAIN_ENCLOSURE: event_type = "main enclosure"; /* fall through */ case RTAS_EPOW_ACTION_POWER_OFF: event_type = "power off"; if (state != RTAS_EPOW_ACTION_MAIN_ENCLOSURE && state != RTAS_EPOW_ACTION_POWER_OFF) { log_epow(event, "EPOW event: %s requested, but the " "sensor state indicates the problem was " "resolved", event_type); return 0; } /* System will likely lose power before this code is ever run */ if ((rtas_hdr->version < 6) && (epow->power_fault)) { if (epow->power_loss) { log_epow(event, "EPOW event: power loss due " "to a power source fault"); return 1; } if (epow->power_supply) { log_epow(event, "EPOW event: power loss due " "to a power failure"); return 2; } if (epow->power_switch) { log_epow(event, "EPOW event: power loss due " "to a power switch fault"); return 3; } } else { log_epow(event, "EPOW event: power loss due to a %s " "event", event_type); return 1; } if (epow->action_code == RTAS_EPOW_ACTION_MAIN_ENCLOSURE) log_epow(event, "EPOW event: power loss due to an " "unknown main enclosure condition"); else log_epow(event, "EPOW event: power loss due to an " "unknown poer supply condition"); return 2; break; default: /* Unknown action code */ log_epow(event, "EPOW event: unknown action code (%d); " "event cannot be handled", epow->action_code); return 0; break; } return 0; } /** * check_epow * @brief Check an RTAS event for EPOW data. * * Parses error information to determine if it represents an EPOW event. * If it is, the epow_status_file is updated with the appropriate * condition, and EPOW_PROGRAM is invoked to take the appropriate system * action (shutdown, etc). * * @param event pointer to the RTAS event */ int check_epow(struct event *event) { pid_t child; char *childargs[2]; int rc, current_status; /* * Dissect the EPOW extended error information; * if the error is serious enough to warrant further action, * fork and exec the script to handle it */ current_status = parse_epow(event); update_epow_status_file(current_status); if (current_status > 0) { childargs[0] = EPOW_PROGRAM_NOPATH; childargs[1] = NULL; child = fork(); if (child == -1) { log_msg(event, "Fork error, %s cannot be run to handle" "an incoming EPOW event, %s", EPOW_PROGRAM, strerror(errno)); } else if (child == 0) { /* child process */ rc = execv(EPOW_PROGRAM, childargs); /* shouldn't get here */ log_msg(event, "Could not exec %s, %s. Could not " "handle an incoming EPOW event", EPOW_PROGRAM, strerror(errno)); exit(1); } } return current_status; } ppc64-diag-2.7.0/rtas_errd/extract_platdump.c0000644000000000000000000002533112642205425017573 0ustar rootroot/** * @file extract_platdump.c * @brief Command to extract a platform dump and copy it to the filesystem * * Copyright (C) 2007 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "rtas_errd.h" #include "platform.c" #define DUMP_HDR_PREFIX_OFFSET 0x16 /* prefix size in dump header */ #define DUMP_HDR_FNAME_OFFSET 0x18 /* suggested filename in dump header */ #define DUMP_MAX_FNAME_LEN 40 #define TOKEN_PLATDUMP_MAXSIZE 32 #define DUMP_BUF_SZ 4096 int flag_v = 0; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"verbose", no_argument, NULL, 'v'}, {0,0,0,0} }; /** * msg * @brief Print message if verbose flag is set * * @param fmt format string a la printf() * @param ... additional args a la printf() */ void msg(char *fmt, ...) { va_list ap; if (flag_v) { va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); } return; } /** * print_usage * @brief Print the usage message for this command * * @param name the name of this executable */ static void print_usage(const char *name) { printf("Usage: %s [-h] [-v] \n" "\t-h: print this help message\n" "\t-v: verbose output\n" "\t: the tag of the dump(s) to extract, in hex\n", name); return; } /** * handle_platform_dump_error * @brief Interpret librtas return codes * * Interpret a return code from librtas for any librtas specific messages. * * @param e return code from librtas * @param err_buf buffer to write librtas message to * @param sz size of the err_buf parameter */ static void handle_platform_dump_error(int e, char *err_buf, int sz) { char *err = "Library error during ibm,platform-dump call: "; switch (e) { case RTAS_KERNEL_INT: /* no kernel interface to firmware */ snprintf(err_buf, sz, "%s%s", err, "No kernel interface to firmware"); break; case RTAS_KERNEL_IMP: /* no kernel implementation of function */ snprintf(err_buf, sz, "%s%s", err, "No kernel implementation of function"); break; case RTAS_PERM: /* non-root caller */ snprintf(err_buf, sz, "%s%s", err, "Permission denied (non-root caller)"); break; case RTAS_NO_MEM: /* out of heap memory */ snprintf(err_buf, sz, "%s%s", err, "Out of heap memory"); break; case RTAS_NO_LOWMEM: /* kernel out of low memory */ snprintf(err_buf, sz, "%s%s", err, "Kernel out of low memory"); break; case RTAS_FREE_ERR: /* attempt to free nonexistant rmo buffer */ snprintf(err_buf, sz, "%s%s", err, "Attempt to free nonexistant rmo buffer"); break; case RTAS_IO_ASSERT: /* unexpected I/O error */ snprintf(err_buf, sz, "%s%s", err, "Unexpected I/O error"); break; case RTAS_UNKNOWN_OP: /* no firmware implementation of function */ snprintf(err_buf, sz, "%s%s", err, "No firmware implementation of function"); break; case -1: /* hardware error */ snprintf(err_buf, sz, "%s%s", err, "RTAS call returned a hardware error"); break; case -9002: /* platform has decided to deliver dump elsewhere */ snprintf(err_buf, sz, "%s%s", err, "Not authorized (platform " "will deliver dump elsewhere)"); break; default: snprintf(err_buf, sz, "%sUnknown error (%d)", err, e); break; } } /** * remove_old_dumpfiles * @brief if needed, remove any old dumpfiles * * Users can specify the number of old dumpfiles they wish to save * via the config file PlatformDumpMax entry. This routine will search * through and removeany dump files of the specified type if the count * exceeds the maximum value. * * @param dumpname suggested filename of the platform dump * @param prefix_size length of the prefix */ void remove_old_dumpfiles(char *dumpname, int prefix_size) { struct dirent *entry; DIR *dir; char pathname[DUMP_MAX_FNAME_LEN + 40]; dir = opendir(d_cfg.platform_dump_path); while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, "..") == 0) continue; if (strcmp(entry->d_name, ".") == 0) continue; if (strncmp(dumpname, entry->d_name, prefix_size) == 0) { sprintf(pathname, "%s%s", d_cfg.platform_dump_path, entry->d_name); msg("Deleting file %s", pathname); if (unlink(pathname) < 0) { msg("Could not delete file \"%s\" " "to make room for incoming platform " "dump \"%s\" (%s). The new dump will " "be saved anyways.", pathname, dumpname, strerror(errno)); } } } closedir(dir); } /** * extract_platform_dump * @brief Extract a platform dump with a given tag to the filesystem * * @param dump_tag tag of the platform dump to extract * @return 0 on success, 1 on failure */ int extract_platform_dump(uint64_t dump_tag) { uint64_t seq=0, seq_next, bytes; uint16_t prefix_size = 7; char *dump_buf = NULL; char filename[DUMP_MAX_FNAME_LEN + 1]; char pathname[DUMP_MAX_FNAME_LEN + 40]; char dump_err[RTAS_ERROR_LOG_MAX]; char dumpid[5]; int out=-1, rc, librtas_rc, dump_complete=0, ret=0; msg("Dump tag: 0x%016LX", dump_tag); dump_buf = malloc(DUMP_BUF_SZ); if (dump_buf == NULL) { msg("Could not allocate buffer to retrieve dump: %s", strerror(errno)); ret = 1; goto platdump_error_out; } msg("Calling rtas_platform_dump, seq 0x%016LX", seq); librtas_rc = rtas_platform_dump(dump_tag, 0, dump_buf, DUMP_BUF_SZ, &seq_next, &bytes); if (librtas_rc == 0) { dump_complete = 1; } if (librtas_rc < 0) { handle_platform_dump_error(librtas_rc, dump_err, 1024); msg("%s\nThe platform dump header could not be " "retrieved from firmware", dump_err); ret = 1; goto platdump_error_out; } /* If we didn't read enough bytes, handle it */ if (bytes <= 0) { msg("Platform dump with id: 0x%016LX is either invalid " "or empty\n", dump_tag); ret = 1; goto platdump_error_out; } seq = seq_next; /* * Retreive the prefix size and suggested filename for the dump * from the dump header */ if (bytes >= DUMP_HDR_PREFIX_OFFSET + sizeof(uint16_t)) { prefix_size = *(uint16_t *)(dump_buf + DUMP_HDR_PREFIX_OFFSET); prefix_size = be16toh(prefix_size); } if (bytes >= DUMP_HDR_FNAME_OFFSET + DUMP_MAX_FNAME_LEN) { strncpy(filename, dump_buf + DUMP_HDR_FNAME_OFFSET, DUMP_MAX_FNAME_LEN); } else { strcpy(filename, "dumpid."); strcat(filename, dumpid); } filename[DUMP_MAX_FNAME_LEN - 1] = '\0'; msg("Suggested filename: %s, prefix size: %d", filename, prefix_size); /* Create the platform dump directory if necessary */ if (mkdir(d_cfg.platform_dump_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0) { if (errno != EEXIST) { msg("Could not create %s: %s.\nThe platform dump " "could not be copied to the platform dump " "directory", d_cfg.platform_dump_path, strerror(errno)); ret = 1; goto platdump_error_out; } } /* * Before writing the new dump out, we need to see if any older * dumps need to be removed first */ remove_old_dumpfiles(filename, prefix_size); /* Copy the dump off to the filesystem */ pathname[0] = '\0'; strcpy(pathname, d_cfg.platform_dump_path); strcat(pathname, filename); msg("Dump path/filename: %s", pathname); out = creat(pathname, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (out <= 0) { msg("Could not open %s for writing: %s.\nThe platform dump " "could not be retrieved", pathname, strerror(errno)); ret = 1; goto platdump_error_out; } rc = write(out, dump_buf, (size_t)bytes); if (rc < 0) { msg("Could not write to %s: %s.\nThe platform dump " "could not be retrieved", pathname, strerror(errno)); ret = 1; goto platdump_error_out; } while (dump_complete == 0) { msg("Calling rtas_platform_dump, seq 0x%016LX", seq); librtas_rc = rtas_platform_dump(dump_tag, seq, dump_buf, DUMP_BUF_SZ, &seq_next, &bytes); if (librtas_rc < 0) { handle_platform_dump_error(librtas_rc, dump_err, 1024); msg("%s\nThe platform dump could not be " "retrieved from firmware", dump_err); ret = 1; goto platdump_error_out; } if (librtas_rc == 0) { dump_complete = 1; } seq = seq_next; rc = write(out, dump_buf, (size_t)bytes); if (rc < 0) { msg("Could not write to %s: %s\nThe platform " "dump could not be retrieved", pathname, strerror(errno)); ret = 1; goto platdump_error_out; } } /* * Got the dump; signal the platform that it is okay for * them to delete/invalidate their copy */ msg("Sigalling that the dump has been retrieved, seq 0x%016LX", seq); librtas_rc = rtas_platform_dump(dump_tag, seq, NULL, 0, &seq_next, &bytes); if (librtas_rc < 0) { handle_platform_dump_error(librtas_rc, dump_err, 1024); msg("%s\nThe platform could not be notified to " "delete its copy of a platform dump", dump_err); } /* rtas_errd depends on this line being printed */ printf("%s\n", filename); platdump_error_out: if (out != -1) close(out); if (dump_buf != NULL) free(dump_buf); return ret; } int main(int argc, char *argv[]) { int option_index, rc, fail=0; int platform = 0; uint64_t dump_tag; platform = get_platform(); switch (platform) { case PLATFORM_UNKNOWN: case PLATFORM_POWERNV: fprintf(stderr, "%s: is not supported on the %s platform\n", argv[0], __power_platform_name(platform)); return -1; } for (;;) { option_index = 0; rc = getopt_long(argc, argv, "hv", long_options, &option_index); if (rc == -1) break; switch (rc) { case 'h': print_usage(argv[0]); return 0; case 'v': flag_v = 1; break; case '?': print_usage(argv[0]); return -1; break; default: printf("huh?\n"); break; } } if (optind < argc) { /* Parse ppc64-diag config file */ rc = diag_cfg(0, &msg); if (rc) { fprintf(stderr, "Could not parse configuration file " "%s\n", config_file); return -2; } while (optind < argc) { dump_tag = strtoll(argv[optind++], NULL, 16); fail += extract_platform_dump(dump_tag); } } else { fprintf(stderr, "No dump tag specified\n"); print_usage(argv[0]); return -1; } return fail; } ppc64-diag-2.7.0/rtas_errd/files.c0000644000000000000000000005245512642205425015324 0ustar rootroot/** * @file files.c * @brief File Manipulation routines for files used by rtas_errd * * Copyright (C) 2004 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rtas_errd.h" char *platform_log = "/var/log/platform"; int platform_log_fd = -1; /** * @var proc_error_log1 * @brief File to read RTAS events from. */ /** * @var proc_error_log2 * @brief Alternate file to read RTAS events from. */ /** * @var proc_error_log_fd * @brief File descriptor for proc_error_log. */ char *proc_error_log1 = "/proc/ppc64/rtas/error_log"; char *proc_error_log2 = "/proc/ppc64/error_log"; static int proc_error_log_fd = -1; /** * @var rtas_errd_log * @brief Message log for the rtas_errd daemon. * */ /** * @var rtas_errd_log0 * @brief Saved ("rolled over") messages log for rtas_errd daemon. */ /** * @var rtas_errd_log_fd * @brief File descriptor for rtas_errd_log */ /** * @def RTAS_ERRD_LOGSZ * @brief Maximum size of the rtas_errd_log */ char *rtas_errd_log = "/var/log/rtas_errd.log"; char *rtas_errd_log0 = "/var/log/rtas_errd.log0"; static int rtas_errd_log_fd = -1; #define RTAS_ERRD_LOGSZ 25000 /* * @var epow_status_file * @brief File used to communicate the current state of an epow event * to rc.powerfail. */ static int epow_status_fd = -1; char *epow_status_file = "/var/log/epow_status"; /** * @var scanlog * @brief buffer to hold scanlog dump path * * This is a buffer that is allocated and filled when rtas_errd is * intially exec()'ed via check_scanlog_dump(). The buffer will contain * the path to a scanlog dump and is reported with the first RTAS event * we receive from the kernel. */ char *scanlog = NULL; #ifdef DEBUG /** * @var scenario_file * @brief filename specified with the -s option */ /** * @var scenario_buf * @brief buffer of data read in from scenario_file */ /** * @var scenario_files * @brief Array of files listed in the scenario_file */ /* * @var scenario_index * @brief Current index into scenario_files */ /* * @var scenario_count * @brief Total number of entries in scenario_files */ char *scenario_file = NULL; char *scenario_buf = NULL; char **scenario_files = NULL; int scenario_index = 0; int scenario_count = 0; /** * @var testing_finished * @brief Indicates the last test scenario has been read. */ int testing_finished = 0; /** * event_dump * @brief Dump an RTAS event * * Mainly used for debugging porppuses to get a dump of a RTAS event * * @param re pointer to a struct event to dump. */ void event_dump(struct event *event) { int i; char *bufp = (char *)event->rtas_hdr; int len = event->length; /* Print 16 bytes/line in hex, with a space after every 4 bytes */ for (i = 0; i < len; i++) { if ((i % 16) == 0) printf("RTAS %d:", i/16); if ((i % 4) == 0) printf(" "); printf("%02x", bufp[i]); if ((i % 16) == 15) printf("\n"); } if ((i % 16) != 0) printf("\n"); } /** * setup_rtas_event_scenario * @brief Create a testcase scenario * * A scenario file contains a list of files containing RTAS events * (one per line, no blank lines) that are used to inject a series * of RTAS events into the rtas_errd daemon. * * If a scenario is specified this will setup an array of filenames * specified by the file. * * @return 0 on success, !0 otherwise */ int setup_rtas_event_scenario(void) { struct stat sbuf; char *tmp; int fd, len; int i; if (scenario_file == NULL) return 0; fd = open(scenario_file, O_RDONLY); if (fd == -1) { log_msg(NULL, "Could not open scenario file %s, %s", scenario_file, strerror(errno)); return -1; } if ((fstat(fd, &sbuf)) < 0) { log_msg(NULL, "Could not get status of scenario file %s, %s", scenario_file, strerror(errno)); close(fd); return -1; } scenario_buf = malloc(sbuf.st_size); if (scenario_buf == NULL) { log_msg(NULL, "Could not allocate space for RTAS injection " "scenario, %s", strerror(errno)); close(fd); return -1; } len = read(fd, scenario_buf, sbuf.st_size); if (len == -1) { log_msg(NULL, "Could not read from scenario file %s, %s", scenario_file, strerror(errno)); close(fd); return -1; } close(fd); /* Now, convert all '\n' and EOF chars to '\0' */ for (i = 0; i < len; i++) { if (scenario_buf[i] == '\n') { scenario_buf[i] = '\0'; scenario_count++; } } /* Allocate the scenario array */ scenario_files = malloc(scenario_count * sizeof(char *)); if (scenario_files == NULL) { log_msg(NULL, "Could not allocate memory for scenario " "files, %s", strerror(errno)); return -1; } tmp = scenario_buf; dbg("Setting up RTAS event injection scenario.."); for (i = 0; i < scenario_count; i++) { scenario_files[i] = tmp; dbg(" %s\n", scenario_files[i]); tmp += strlen(tmp) + 1; } proc_error_log1 = scenario_files[scenario_index++]; proc_error_log2 = NULL; return 0; } #endif /* DEBUG */ /** * init_files * @brief Initialize files used by rtas_errd * * Open the following files needed by the rtas_errd daemon: * rtas_errd_log * proc_error_log * platform_log * epow_status * * Note: This should only be called once before any rtas_events * are read. * * @return 0 on success, !0 on failure */ int init_files(void) { int rc = 0; /* First, open the rtas_errd log file */ rtas_errd_log_fd = open(rtas_errd_log, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP /*0640*/); if (rtas_errd_log_fd == -1 && debug) fprintf(stderr, "Could not open rtas_errd log file \"%s\".\n", rtas_errd_log); /* Next, open the /proc file */ #ifdef DEBUG rc = setup_rtas_event_scenario(); if (rc) return rc; #endif proc_error_log_fd = open(proc_error_log1, O_RDONLY); if (proc_error_log_fd <= 0) proc_error_log_fd = open(proc_error_log2, O_RDONLY); if (proc_error_log_fd <= 0) { log_msg(NULL, "Could not open error log file at either %s or " "%s, %s\nThe rtas_errd daemon cannot continue and will " "exit", proc_error_log1, proc_error_log2, strerror(errno)); return -1; } /* Next, open /var/log/platform */ platform_log_fd = open(platform_log, O_RDWR | O_SYNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP /*0640*/); if (platform_log_fd <= 0) { log_msg(NULL, "Could not open log file %s, %s\nThe daemon " "cannot continue and will exit", platform_log, strerror(errno)); return -1; } /* Now, the epow status file. Updating the status to zero will * have the side effect of also opening the file. */ update_epow_status_file(0); return rc; } /** * close_files * @brief Close all the files used by rtas_errd * * Perform any file cleanup (i.e. close()) and possibly free()'ing * buffers needed by rtas_errd before exiting. */ void close_files(void) { #ifdef DEBUG if (scenario_buf != NULL) free(scenario_buf); if (scenario_files != NULL) free(scenario_files); #endif if (rtas_errd_log_fd) close(rtas_errd_log_fd); if (proc_error_log_fd) close(proc_error_log_fd); if (platform_log_fd) close(platform_log_fd); if (epow_status_fd) close(epow_status_fd); } /** * read_proc_error_log * @brief Read data from proc_error_log * * Read the data in from the /proc error log file. This routine * also handles the debug case of reading in a test file that * contains an ascii representation of a RTAS event. * * @param buf buffer to read RTAS event in to. * @param buflen length of buffer parameter * @return number of bytes read. */ int read_proc_error_log(char *buf, int buflen) { int len = 0; #ifdef DEBUG /* If we are reading in a test file with an ascii RTAS event, * we need to convert it to binary. proc_error_log2 should * only be NULL when a debug proc_error_log file is specified */ if (proc_error_log2 == NULL) { struct stat tf_sbuf; char *data; char *tf_mmap; int seq_num = 1000 + scenario_index; int j = 0, k = 0, ch; char str[4]; if ((fstat(proc_error_log_fd, &tf_sbuf)) < 0) { log_msg(NULL, "Cannot get status of test file %s, %s", proc_error_log1, strerror(errno)); return -1; } tf_mmap = mmap(0, tf_sbuf.st_size, PROT_READ, MAP_PRIVATE, proc_error_log_fd, 0); if (tf_mmap == MAP_FAILED) { log_msg(NULL, "Cannot map test file %s, %s", proc_error_log1, strerror(errno)); return -1; } memcpy(buf, &seq_num, sizeof(int)); buf += sizeof(int); data = tf_mmap; str[2] = ' '; str[3] = '\0'; while (&data[j] != (tf_mmap + tf_sbuf.st_size)) { if (strncmp(&data[j], "RTAS:", 5) == 0) { /* This is either an event begin or an * event end line, move on to the '\n' */ while (data[j++] != '\n'); continue; } if (strncmp(&data[j], "RTAS ", 5) == 0) { /* this is fluff at the beginning * of the event output line, get rid of it. */ /* first skip past the 'RTAS X:'. The X * part may be multiple digits so we have * to search for the ':' afterwards. */ j += 6; while (data[j++] != ':'); /* go past the extra space */ j++; } if ((data[j] == '\n') || (data[j] == ' ')) { j++; continue; } str[0] = data[j]; str[1] = data[j + 1]; j += 2; sscanf(str, "%02x", &ch); buf[k++] = ch; if (k >= buflen) { /* Buffer overflow */ log_msg(NULL, "Invalid test file"); return -1; } } len = tf_sbuf.st_size; if (scenario_files != NULL) { if (scenario_index < scenario_count) { char *tmp; close(proc_error_log_fd); tmp = scenario_files[scenario_index++]; proc_error_log_fd = open(tmp, O_RDONLY); if (proc_error_log_fd <= 0) log_msg(NULL, "Could not open scenario " "file %s, %s", tmp, strerror(errno)); } else { testing_finished = 1; } } else testing_finished = 1; if (tf_mmap) munmap(tf_mmap, tf_sbuf.st_size); } else #endif len = read(proc_error_log_fd, buf, buflen); /* event_dump(event); */ return len; } /** * reformat_msg * @brief Re-format a log message to wrap at 80 characters. * * In order to ease the formatting of messages in the rtas_errd daemon * this will automatically format the messages to wrap at 80 characters. * * @param msg buffer containing the message to re-format * @return new buffer length */ int reformat_msg(char *msg) { char buf[RTAS_ERROR_LOG_MAX], *pos, *next, temp, temp2; int len = strlen(msg); if (len < 80) { /* no need to reformat */ msg[len++] = '\n'; return len; } memset(buf, 0, RTAS_ERROR_LOG_MAX); /* first copy the msg into our buffer */ memcpy(buf, msg, len); /* zero out the old buffer */ memset(msg, 0, RTAS_ERROR_LOG_MAX); pos = buf; while (strlen(pos) > 80) { next = pos+80; do { if (*next == ' ') *next = '\n'; if (*next == '\n') { temp = *(next + 1); *(next + 1) = '\0'; strcat(msg, pos); *(next + 1) = temp; pos = next + 1; break; } next--; } while (next > pos); if (next == pos) { /* word is longer than line length */ next = pos+79; temp = *next; temp2 = *(next + 1); *next = '\n'; *(next + 1) = '\0'; strcat(msg, pos); *next = temp; *(next + 1) = temp2; pos = next; } } strcat(msg, pos); len = strlen(msg); msg[len++] = '\n'; return len; } /** * _log_msg * @brief The real routine to write messages to rtas_errd_log * * This is a common routine for formatting messages that go to the * /var/log/rtas_errd.log file. Users should pass in a reference to * the rtas_event structure if this message is directly related a rtas * event and a formatted message a la printf() style. Please make sure * that the message passed in does not have any ending punctuation or * ends with a newline. It sould also not have any internal newlines. * * This routine will do several things to the message before printing * it out; * - Add a timestamp * - If a rtas_event reference is passed in, a sequenbce number is added * - If errno is set, the results of perror are added. * - The entire message is then formatted to fit in 80 cols. * * @param event reference to event * @param fmt formatted string a la printf() * @param ... additional args a la printf() */ static void _log_msg(struct event *event, const char *fmt, va_list ap) { struct stat sbuf; char buf[RTAS_ERROR_LOG_MAX]; int len = 0, rc; char *dir_name; char *rtas_errd_log_c; /* Both rtas_errd_log/rtas_errd_log0 are global, so make a copy. */ if (rtas_errd_log_fd == -1) { dbg("rtas_errd log file is not available"); vsprintf(buf, fmt, ap); _dbg(buf); return; } #ifndef DEBUG { time_t cal; /* In order to make testing easier we don't print the date * to the log file for debug versions of rtas_errd. This helps * avoid lots of ugly date munging when comparing files. */ cal = time(NULL); len = sprintf(buf, "%s ", ctime(&cal)); } #endif /* Add the sequence number */ if (event) len += sprintf(buf, "(Sequence #%d) ", event->seq_num); /* Add the actual message */ len += vsprintf(buf + len, fmt, ap); /* Add ending punctuation */ len += sprintf(buf + len, "."); _dbg(buf); /* reformat the new message */ len = reformat_msg(buf); rc = write(rtas_errd_log_fd, buf, len); if (rc == -1) dbg("rtas_errd: write to rtas_errd log failed"); /* After each write check to see if we need to to do log rotation */ rc = fstat(rtas_errd_log_fd, &sbuf); if (rc == -1) { dbg("rtas_errd: Cannot stat rtas_errd log file " "to rotate logs"); return; } if (sbuf.st_size >= RTAS_ERRD_LOGSZ) { int rc; /* return code */ struct stat log_file; /* file stat */ int dir_fd; /* fsync */ close(rtas_errd_log_fd); /* * Remove log file /var/log/rtas_errd.log0 */ rc = stat(rtas_errd_log0, &log_file); if (rc == 0) { rc = unlink(rtas_errd_log0); if (rc == -1) { log_msg(NULL, "An error occured during the " "rotation of the rtas_errd logs:\n " "cmd = rm %s\nexit status: %d)", rtas_errd_log0, errno); } } /* stat */ /* * rotate /var/log/rtas_errd.log to /var/log/rtas_errd.log0 */ rc = rename(rtas_errd_log, rtas_errd_log0); if (rc == -1) { log_msg(NULL, "An error occured during rotation of " "rtas_errd logs (logger alive):\n cmd = rename" " %s %s\nexit status: %d)", rtas_errd_log, rtas_errd_log0, errno); } /* * fsync /var/log/ to be on safer side. */ rtas_errd_log_c = strdup(rtas_errd_log); if (!rtas_errd_log_c) { log_msg(NULL, "%s, Memory allocation failed, %s", __func__, strerror(errno)); rtas_errd_log_fd = -1; dbg("Could not re-open %s", rtas_errd_log); return; } dir_name = dirname(rtas_errd_log_c); dir_fd = open(dir_name, O_RDONLY|O_DIRECTORY); rc = fsync(dir_fd); if (rc == -1) { log_msg(NULL, "fsync failed, on %s\nexit status: %d", dir_name, errno); } close(dir_fd); rtas_errd_log_fd = open(rtas_errd_log, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP); if (rtas_errd_log_fd == -1) dbg("Could not re-open %s", rtas_errd_log); } return; } /** * cfg_log * @brief dummy interface for calls to diag_cfg * * @param fmt formatted string a la printf() * @param ... additional args a la printf() */ void cfg_log(char *fmt, ...) { va_list ap; va_start(ap, fmt); _log_msg(NULL, fmt, ap); va_end(ap); } /** * log_msg * @brief Log messages to rtas_errd_log * * @param event reference to event * @param fmt formatted string a la printf() * @param ... additional args a la printf() */ void log_msg(struct event *event, char *fmt, ...) { va_list ap; va_start(ap, fmt); _log_msg(event, fmt, ap); va_end(ap); } /** * dbg * @brief Write debug messages to stdout * * Provide utility to print debug statements if the debug flag * is specified. * * @param fmt format string a la printf() * @param ... args a la printf() */ void _dbg(const char *fmt, ...) { va_list ap; char buf[RTAS_ERROR_LOG_MAX + 8]; int len; if (debug == 0) return; memset(buf, 0, sizeof(buf)); va_start(ap, fmt); len = sprintf(buf, "DEBUG: "); len += vsnprintf(buf + len, RTAS_ERROR_LOG_MAX, fmt, ap); buf[len] = '\0'; va_end(ap); len = reformat_msg(buf); fprintf(stdout, "%s", buf); fflush(stdout); } /** * print_rtas_event * @brief Print an RTAS event to the platform log * * Prints the binary hexdump of an RTAS event to the PLATFORM_LOG file. * * @param event pointer to the struct event to print * @return 0 on success, !0 on failure */ int print_rtas_event(struct event *event) { char *out_buf; int len, buf_size, offset; int i, rc, nlines; /* Determine the length of the log */ len = event->length; /* Some RTAS events (i.e. shortened epow events) only consist * of the rtas header and an extended length of zero. For these * assume a length of 32. */ if (len == 0) len = 32; /* We need to allocate a buffer big enough to hold all the data * from the RTAS event plus the additional strings printed * before and after the RTAS event (roughly 0x40 in length) * _and_ the strings printed in front of every line (roughly 0x10 * in length). * * We calculate the number of lines needed to print the RTAS event, * mulitply that by the space for the strings then add in the * beginning/end strings. For a little extra padding we double the * len value also. * * size = (len * 2) + (number of lines * 0x10) + (2 * 0x40) */ nlines = len / 0x10; if (len % 0x10) nlines++; buf_size = (len * 2) + (nlines * 0x10) + (2 * 0x40); /* event_dump(event); */ out_buf = calloc(1, buf_size); if (out_buf == NULL) { log_msg(NULL, "Could not allocate buffer to print RTAS event " "%d, %s. The event will not copied to %s", event->seq_num, strerror(errno), platform_log); return -1; } offset = sprintf(out_buf, "RTAS: %d -------- RTAS event begin --------\n", event->seq_num); if (event->flags & RE_SCANLOG_AVAIL) { offset += sprintf(out_buf + offset, "RTAS: %s\n", scanlog); free(scanlog); scanlog = NULL; } /* Print 16 bytes/line in hex, with a space after every 4 bytes */ for (i = 0; i < len; i++) { if ((i % 16) == 0) offset += sprintf(out_buf + offset, "RTAS %d:", i/16); if ((i % 4) == 0) offset += sprintf(out_buf + offset, " "); offset += sprintf(out_buf + offset, "%02x", event->event_buf[i]); if ((i % 16) == 15) offset += sprintf(out_buf + offset, "\n"); } if ((i % 16) != 0) offset += sprintf(out_buf + offset, "\n"); offset += sprintf(out_buf + offset, "RTAS: %d -------- RTAS event end ----------\n", event->seq_num); dbg("Writing RTAS event %d to %s", event->seq_num, platform_log); lseek(platform_log_fd, 0, SEEK_END); rc = write(platform_log_fd, out_buf, offset); if (rc != offset) { log_msg(NULL, "Writing RTAS event %d to %s failed." "expected to write %d, only wrote %d. %s", event->seq_num, platform_log, offset, rc, strerror(errno)); } free(out_buf); return rc; } /** * platform_log_write * @brief Write messages to the platform log * * Provide a printf() style interface to write messages to platform_log. * All messages are prepended with "ppc64-diag" to match the expected * format of the platform log. * * @param fmt format string a la printf() * @param ... additional args a la printf() * @return return code from write() call */ int platform_log_write(char *fmt, ...) { va_list ap; char buf[1024]; /* should be big enough */ int len, rc; len = sprintf(buf, "%s ", "ppc64-diag:"); va_start(ap, fmt); len += vsnprintf(buf + len, (1024 - len), fmt, ap); va_end(ap); rc = write(platform_log_fd, &buf, len); return rc; } /** * update_epow_status_file * @brief Update the epow status file. * * Used to write the current EPOW status (as defined in the * parse_epow() function (epow.c) comment) to the epow_status file. * * @param status value to update epow_status file to. */ void update_epow_status_file(int status) { int flags = O_CREAT | O_WRONLY | O_TRUNC; int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH /* 0644 */; int size; char buf[15]; if (epow_status_fd < 0) { epow_status_fd = open(epow_status_file, flags, mode); if (epow_status_fd <= 0) { log_msg(NULL, "Could not open EPOW status file %s, %s", epow_status_file, strerror(errno)); return; } } if (lseek(epow_status_fd, 0, SEEK_SET) == -1) { log_msg(NULL, "Could not seek in EPOW status file %s, %s", epow_status_file, strerror(errno)); return; } size = sprintf(buf, "%d", status); if (size > (sizeof(buf)-1)) { log_msg(NULL, "Could not write data to EPOW status file %s, %s", epow_status_file, strerror(errno)); return; } if (write(epow_status_fd, buf, size) < size) { log_msg(NULL, "Could not write data to EPOW status file %s, %s", epow_status_file, strerror(errno)); } return; } ppc64-diag-2.7.0/rtas_errd/fru_prev6.h0000644000000000000000000000511112642205425016130 0ustar rootroot/** * @file fru_prev6.h * * Copyright (C) 2008 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _H_FRU_PREV6 #define _H_FRU_PREV6 #define NAMESIZE 16 #define LOCSIZE 80 #define MAXFRUS 4 #define ERRD1 4 #define ERRD2 5 /* * A fru_callout_pre_v6 represents a field replaceable unit callout that * is associated with an RTAS event (prior to version 6, which is handled * differently). * * conf confidence (probability) associated with the FRU callout. * * fname device name or configuration database keyword associated * with the field replaceable unit that is being reported. * * floc location associated with fname */ struct fru_callout_pre_v6{ int conf; /* probability of failure */ char fname[NAMESIZE]; /* FRU name */ char floc[LOCSIZE]; /* location of fname */ short fmsg; /* text message number for fname */ }; /* * An event_description_pre_v6 struct represents the outcome of the * analysis of an RTAS event (prior to version 6 events, which are * handled differently). * * flags indicates the type of error description being added to the * system. The following values are defined. * * ERRD1 The Error Description identifies the * resource that failed, its parent, and any cables * needed to attach the resource to its parent. * * ERRD2 Similar to ERRD1, but does not include the * parent resource. * * sn source number of the failure. * * rcode reason code associated with the failure. * * rmsg message number of the reason code text. * * frus an array identifying the field replaceable unit callouts * associated with this event. */ struct event_description_pre_v6 { char dname[NAMESIZE]; /* device name */ short flags; short sn; /* source number of the failure */ short rcode; /* reason code for the failure */ char *rmsg; /* failure description */ struct fru_callout_pre_v6 frus[MAXFRUS]; }; #endif ppc64-diag-2.7.0/rtas_errd/guard.c0000644000000000000000000004313512642205425015317 0ustar rootroot/** * @file guard.c * @brief Routines to handle CPU guard RTAS events * * Copyright (C) 2004 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "rtas_errd.h" #define DRMGR_PROGRAM "/usr/sbin/drmgr" #define DRMGR_PROGRAM_NOPATH "drmgr" #define CONVERT_DT_PROPS_PROGRAM "/usr/sbin/convert_dt_node_props" #define RTAS_V6_TYPE_RESOURCE_DEALLOC 0xE3 enum resource_dealloc_type {CPU_GUARD, SP_CPU_GUARD, MEM_PAGE, MEM_LMB}; enum event_type {CPUTYPE, MEMTYPE}; /** * run_drmgr * @brief build correct options followed by fork and exec drmgr * * @param resource type to deallocate. * @param specific drc_name to be de-allocted. * @param either quatity or capacity to be deallocated. * @param wait do we do a waitpid? */ void run_drmgr(enum resource_dealloc_type resource_type, char *drc_name, unsigned int value, int wait) { pid_t child; int status, rc; char capacity[6], quant_str[5]; char *drmgr_args[] = {DRMGR_PROGRAM_NOPATH, "-r", "-c", NULL, NULL, NULL, NULL, NULL, NULL}; dbg("in run_drmgr command: %d %s %d %d", resource_type, drc_name, value, wait); if (resource_type == CPU_GUARD) { drmgr_args[3] = "cpu"; if (drc_name != NULL) { drmgr_args[4] = "-s"; drmgr_args[5] = drc_name; } else { drmgr_args[4] = "-q"; snprintf(quant_str, 5, "%d", value); drmgr_args[5] = quant_str; } /* end else */ } else if (resource_type == SP_CPU_GUARD) { drmgr_args[3] = "cpu"; drmgr_args[4] = "-p"; drmgr_args[5] = "ent_capacity"; drmgr_args[6] = "-q"; snprintf(capacity, 5, "%d", value); drmgr_args[7] = capacity; } else if (resource_type == MEM_PAGE) { log_msg(NULL, "We should not reach this code path " "error in handling of MEM_PAGE"); /* place holder for future expansion */ } else if (resource_type == MEM_LMB) { drmgr_args[3] = "mem"; drmgr_args[4] = "-s"; drmgr_args[5] = drc_name; }/* end building of drmgr command */ dbg("Running: %s %s %s %s %s %s %s %s", drmgr_args[0], drmgr_args[1], drmgr_args[2], drmgr_args[3], drmgr_args[4], drmgr_args[5], drmgr_args[6], drmgr_args[7]); #ifdef DEBUG if (no_drmgr) return; #endif child = fork(); if (child == -1) { log_msg(NULL, "%s cannot be run to handle a predictive CPU " "failure, %s", DRMGR_PROGRAM, strerror(errno)); return; } else if (child == 0) { /* child process */ rc = execv(DRMGR_PROGRAM, drmgr_args); /* shouldn't get here */ log_msg(NULL, "Could not exec %s to in response to a " "predictive CPU failure, %s", DRMGR_PROGRAM, strerror(errno)); exit(1); } if (wait) { child = waitpid(child, &status, 0); } } /** * can_delete_lmb * @brief Counts the number of lmb's and returns an appropriate value * * This function returns true or false. It counts the lmb's in the system * and returns true if there is more than one lmb in the system. Which allows * us to call the appropriate delete function. * @return true if deletion can occur or false if it is the last lmb. */ static int can_delete_lmb(void) { DIR *dir; struct dirent *entry; int ret_val, fd, ctr=0; char buffer[1024], state[7]; ret_val = 0; /* default state is false, unless count is positive */ dir = opendir("/sys/devices/system/memory"); while ((entry = readdir(dir)) != NULL) { /* ignore memory@0 situation */ if (!strncmp(entry->d_name, "memory@0", 8)) continue; if (!strncmp(entry->d_name, "memory", 6)) { snprintf(buffer, 1024, "/sys/devices/system/memory/%s/" "state", entry->d_name); if ((fd = open(buffer, O_RDONLY)) < 0 ) { log_msg(NULL, "Could not open %s, %s", buffer, strerror(errno)); continue; } if ((read(fd, state, 6)) != 0 ) { if(!strncmp(state, "online", 6)) ctr++; /* make sure its not the last lmb */ if (ctr >= 2) { ret_val = 1; close(fd); break; } } close(fd); } } closedir(dir); return ret_val; } /** * retrieve_drc_name * @brief retrieve the drc-name of a cpu * * Retrieves a string containing the drc-name of the CPU specified by the ID * passed as a parameter. Returns 1 on success, 0 on failure. * * @param event rtas event pointer * @param id interrupt server number of the cpu * @param buffer storeage for drc-name * @param bufsize size of buffer * @return 1 on success, 0 on failure */ static int retrieve_drc_name(enum event_type type, struct event *event, unsigned int id, char *buffer, size_t bufsize) { struct stat sbuf; int rc, ret=1; FILE *fp; uint8_t status; char *system_args[9] = {NULL,}; /* execv arguments */ char tmp_sys_arg[100]; /* tmp sys_arg for snprintf */ pid_t cpid; /* child pid */ if (stat(CONVERT_DT_PROPS_PROGRAM, &sbuf) < 0) { log_msg(event, "The command \"%s\" does not exist, %s", CONVERT_DT_PROPS_PROGRAM, strerror(errno)); return 0; } system_args[0] = CONVERT_DT_PROPS_PROGRAM; system_args[1] = "--context"; if (type == CPUTYPE) { system_args[2] = "cpu"; system_args[3] = "--from"; system_args[4] = "interrupt-server"; system_args[5] = "--to"; system_args[6] = "drc-name"; snprintf(tmp_sys_arg, 100, "%u", id); system_args[7] = tmp_sys_arg; } else { /* event type is mem */ system_args[2] = "mem"; system_args[3] = "--from"; system_args[4] = "drc-index"; system_args[5] = "--to"; system_args[6] = "drc-name"; snprintf(tmp_sys_arg, 100, "0x%08x", id); system_args[7] = tmp_sys_arg; } /* Note : * rtas_errd sets up child signal handler * (setup_sigchld_handler()) which cleanup child process when it * exited. This caused pclose() to return non-zero value always * (No child process ). Resulted this function to return 0 * (failure) always. To overcome this issue we will restore * SIGCHLD handler to default action before doing popen() and * setup again after completing pclose(). */ restore_sigchld_default(); fp = spopen(system_args, &cpid); if (fp == NULL) { if (type == CPUTYPE) { log_msg(event, "Cannot obtain the drc-name for the " "CPU with ID %u; Could not run %s. %s", id, CONVERT_DT_PROPS_PROGRAM, strerror(errno)); } else { log_msg(event, "Cannot obtain the drc-name for the " "Memory with ID %u; Could not run %s. %s", id, CONVERT_DT_PROPS_PROGRAM, strerror(errno)); } setup_sigchld_handler(); return 0; } /* fp == NULL */ rc = fread(buffer, 1, bufsize, fp); if (rc == bufsize) { log_msg(event, "Cannot obtain the drc-name for the " "%s with ID %u; Buffer overflow in " "retrieve_drc_name", (type == CPUTYPE) ? "CPU" : "MEMORY", id); buffer[bufsize-1] = '\0'; ret = 0; } else if (rc > 0) { buffer[rc-1] = '\0'; /* overwrite the newline at the end */ } else buffer[0] = '\0'; status = spclose(fp, cpid); setup_sigchld_handler(); if (status != 0) { log_msg(event, "Cannot obtain the drc-name for the " "%s with ID %u; %s returned %d", (type == CPUTYPE) ? "CPU" : "MEMORY", id, CONVERT_DT_PROPS_PROGRAM, rc); ret = 0; } return ret; } /** * parse_lparcfg * @brief Retrieves the value of the specified parameter from the lparcfg file. * * @param param lparcfg parameter * @return value of param from lparcfg, -1 on error */ static long parse_lparcfg(char *param) { FILE *fp; int len; char buffer[128], *pos; if ((fp = fopen("/proc/ppc64/lparcfg", "r")) == NULL) { log_msg(NULL, "Could not open /proc/ppc64/lparcfg, %s", strerror(errno)); return -1; } len = strlen(param); while ((fgets(buffer, 128, fp)) != NULL) { if (!strncmp(param, buffer, len)) { if ((pos = strchr(buffer, '=')) == NULL) { log_msg(NULL, "Could not retrieve the value " "for %s from /proc/ppc64/lparcfg", param); fclose(fp); return -1; } pos++; buffer[strlen(buffer)-1] = '\0'; fclose(fp); return strtol(pos, NULL, 0); } } fclose(fp); log_msg(NULL, "Could not find the parameter %s in /proc/ppc64/lparcfg", param); return -1; } /** * guard_cpu * @brief Parse RTAS event for CPU guard information. * * Parses error information to determine if it represents a predictive CPU * failure, which should cause a CPU Guard operation. DRMGR_PROGRAM is * forked to actually remove the CPU from the system. * * @param event rtas event * @param cpu id to locate drc_name */ static void guard_cpu(struct event *event, int cpu_id) { char drc_name[30]; int n_cpus; if (! retrieve_drc_name(CPUTYPE, event, cpu_id, drc_name, 30)) { log_msg(event, "A CPU could not be guarded off in " "response to a received predictive CPU " "failure event %d", cpu_id); return; } /* check to make sure this isn't the last CPU */ n_cpus = parse_lparcfg("partition_active_processors"); if (n_cpus == 1) { log_msg(event, "A request was received to deallocate a " "processor due to a predictive CPU failure. " "The request cannot be carried out because " "there is only one CPU on this system"); return; } else if (n_cpus <= d_cfg.min_processors) { log_msg(event, "A request was received to deallocate a " "processor due to a predictive CPU failure. " "The request is not being carried out because " "ppc64-diag is configured to keep a minimum of " "%d processors", d_cfg.min_processors); return; } run_drmgr(CPU_GUARD, drc_name, 0, 0); log_msg(event, "The following CPU has been offlined due to the " "reporting of a predictive CPU failure: logical ID " "%d, drc-name %s", cpu_id, drc_name); platform_log_write("CPU Deallocation Notification\n"); platform_log_write("(resulting from a predictive CPU failure)\n"); platform_log_write(" Logical ID: %d\n", cpu_id); platform_log_write(" drc-name: %s\n", drc_name); snprintf(event->addl_text, ADDL_TEXT_MAX, "Predictive CPU Failure: deallocated CPU ID %d " "(drc-name \"%s\")", cpu_id, drc_name); return; } /** * guard_spcpu * @brief Parse RTAS event for SP_CPU guard information. * * Parses error information to determine if it represents a predictive SPCPU * failure, which should cause a SPCPU Guard operation. DRMGR_PROGRAM is * forked to actually remove the virtual cpu from the system. * * @param event rtas event * @param entitiled shared processor loss. */ static void guard_spcpu(struct event *event, int ent_loss) { int n_cpus, quant, ent_cap; int min_ent_cap = d_cfg.min_entitled_capacity; /* * Ensure that this event will not cause the entitled * capacity to drop below 10 per CPU. If so, we need to * start dropping virtual CPUs to accommodate the reduced * entitled capacity. System minimum is one virtual CPU * with 10 units of entitled capacity. */ ent_cap = parse_lparcfg("partition_entitled_capacity"); if (ent_cap <= min_ent_cap) { log_msg(event, "A request was received to deallocate " "entitled capacity due to a predictive CPU " "failure. The request cannot be carried out " "because this partition is already at the " "minimum allowable entitled capacity"); return; } n_cpus = parse_lparcfg("partition_active_processors"); if ((ent_cap - ent_loss) < min_ent_cap) { ent_loss = ent_cap - min_ent_cap; } if ((ent_cap - ent_loss) < (n_cpus * min_ent_cap)) { /* need to deallocate virtual CPUs */ quant = (ent_cap - ent_loss)/10; run_drmgr(CPU_GUARD, NULL, quant, 1); log_msg(event, "A request was received to deallocate " "entitled capacity due to a predictive CPU " "failure. %d virtual CPUs were deallocated " "in order to fulfill this request", quant); platform_log_write("CPU Deallocation Notification\n"); platform_log_write("(resulting from a predictive CPU " "failure)\n"); platform_log_write(" number of virtual CPUs " "offlined: %d\n", quant); platform_log_write(" number of virtual CPUs " "remaining: %d\n", n_cpus - quant); snprintf(event->addl_text, ADDL_TEXT_MAX, "Predictive CPU Failure: deallocated %d " "virtual CPUs", quant); } run_drmgr(SP_CPU_GUARD, NULL, ent_loss, 0); log_msg(event, "Entitled capacity in the amount of %d has been " "offlined due to the reporting of a predictive CPU " "failure", ent_loss); platform_log_write("Entitled Capacity Deallocation " "Notification\n"); platform_log_write("(resulting from a predictive CPU failure)\n"); platform_log_write(" entitled capacity units offlined: " "%d\n", ent_loss); platform_log_write(" entitled capacity units remaining: " "%d\n", ent_cap - ent_loss); snprintf(event->addl_text, ADDL_TEXT_MAX, "Predictive CPU Failure: deallocated %d entitled " "capacity units", ent_loss); return; } /** * guard_mempage * @brief Perform mempage guard operation. Currently not supported. * * A placeholder function. This dealloc type operation is currently * not supported. MEMPAGE events cannot be guarded at present. * * @param event rtas event. * @param memory address page that needs to be de-allocated. */ static void guard_mempage( struct event *event, uint64_t memory_address) { log_msg(event, "A request was received to deallocate a memory page, " "which is not currently a supported operation."); return; } /** * guard_memlmb * @brief Perform lmb guard operation after proper validation * * parses error information to determine the lmb that requires * guarding operation. At this time only MEMLMB operations may * be guarded. DRMGR_PROGRAM is forked to actually remove * the LMB from the system. * * @param event rtas event * @param drc index to be guarded. */ static void guard_memlmb(struct event *event, unsigned int drc_index) { char drc_name[30]; /* check to make sure there is more than one lmb to delete */ if (can_delete_lmb()==FALSE) { log_msg(event, "A request was received to deallocate a " "LMB partition due to a predictive MEM failure " "The request cannot be carried out because " "there is only one LMB on this system"); return; } if (!retrieve_drc_name(MEMTYPE, event, drc_index, drc_name, 30)) { log_msg(event, "A LMB could not be guarded off in " "response to a received predictive MEM " "failure event 0x%08x", drc_index); return; } run_drmgr(MEM_LMB, drc_name, 0,0); log_msg(event, "The following LMB has been offlined due to the " "reporting of a predictive memory failure:" "0x%08x, drc-name %s", drc_index, drc_name); platform_log_write("MEM Deallocation Notification\n"); platform_log_write("(resulting from a predictive MEM failure)\n"); platform_log_write(" Logical ID: 0x%08x\n", drc_index); platform_log_write(" drc-name: %s\n", drc_name); snprintf(event->addl_text, ADDL_TEXT_MAX, "Predictive MEM Failure: deallocated LMB ID %u " "(drc-name \"%s\")", drc_index, drc_name); return; } /** * handle_resource_dealloc * @brief Parse RTAS event for CPU guard information. * * Parses error information to determine if it represents a predictive CPU * failure, which should cause a CPU Guard operation. DRMGR_PROGRAM is * forked to actually remove the CPU from the system. * * @param event rtas event */ void handle_resource_dealloc(struct event *event) { struct rtas_event_hdr *rtas_hdr = event->rtas_hdr; struct rtas_event_exthdr *exthdr; struct rtas_cpu_scn *cpu; struct rtas_lri_scn *lri; uint64_t address_range; /* * The following conditional is to handle pre-v6 predictive CPU * failure events; it has been designed to specification, but has * not been tested. version 1 to 5. */ if (rtas_hdr->severity == RTAS_HDR_SEV_WARNING && rtas_hdr->disposition == RTAS_HDR_DISP_FULLY_RECOVERED && rtas_hdr->extended && rtas_hdr->initiator == RTAS_HDR_INIT_CPU && rtas_hdr->type == RTAS_HDR_TYPE_CACHE_PARITY && rtas_hdr->version < 6) { /* Check extended error information */ exthdr = rtas_get_event_exthdr_scn(event->rtas_event); cpu = rtas_get_cpu_scn(event->rtas_event); if (cpu == NULL) { log_msg(event, "Could not retrieve CPU section to " "check for a CPU guard event"); return; } if (exthdr->unrecoverable_bypassed && exthdr->predictive && exthdr->power_pc && cpu->extcache_ecc) { guard_cpu(event, cpu->id); } } if (rtas_hdr->version >= 6) { if (rtas_hdr->type == RTAS_V6_TYPE_RESOURCE_DEALLOC) { lri = rtas_get_lri_scn(event->rtas_event); if (lri == NULL) { log_msg(event, "Could not retrieve a Logical " "Resource Identification section from " "a v6 event to determine the resource " "to be deallocated"); return; } switch (lri->resource) { case RTAS_LRI_RES_PROC: /* invoke a CPU guard operation */ guard_cpu(event, lri->lri_cpu_id); break; case RTAS_LRI_RES_SHARED_PROC: /* shared processor CPU guard operation */ guard_spcpu(event, lri->capacity); break; case RTAS_LRI_RES_MEM_PAGE: /* Mem page remove operation */ address_range = lri->lri_mem_addr_hi; address_range <<= 32; address_range |= lri->lri_mem_addr_lo; guard_mempage(event, address_range); break; case RTAS_LRI_RES_MEM_LMB: /* LMB remove operation */ guard_memlmb(event, lri->lri_drc_index); break; } } } } ppc64-diag-2.7.0/rtas_errd/hotplug.c0000644000000000000000000001105112642205425015667 0ustar rootroot/** * @file hotplug.c * * Copyright (C) 2013 IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include "rtas_errd.h" #define DRMGR_PROGRAM "/usr/sbin/drmgr" #define DRMGR_PROGRAM_NOPATH "drmgr" void handle_hotplug_event(struct event *re) { struct rtas_event_hdr *rtas_hdr = re->rtas_hdr; struct rtas_hotplug_scn *hotplug; pid_t child; int status, rc; char drc_index[11]; char count[4]; char *drmgr_args[] = { DRMGR_PROGRAM_NOPATH, "-c", NULL, NULL, NULL, NULL, NULL, "-d4", "-V", NULL}; /* Retrieve Hotplug section */ if (rtas_hdr->version >= 6) { hotplug = rtas_get_hotplug_scn(re->rtas_event); /* Build drmgr argument list */ dbg("Build drmgr command\n"); switch (hotplug->type) { case RTAS_HP_TYPE_PCI: drmgr_args[2] = "pci"; drmgr_args[6] = "-n"; break; case RTAS_HP_TYPE_CPU: drmgr_args[2] = "cpu"; break; case RTAS_HP_TYPE_MEMORY: drmgr_args[2] = "mem"; break; case RTAS_HP_TYPE_PHB: drmgr_args[2] = "phb"; break; default: dbg("Unknown or unsupported hotplug type %d\n", hotplug->type); return; } switch (hotplug->action) { case RTAS_HP_ACTION_ADD: drmgr_args[3] = "-a"; break; case RTAS_HP_ACTION_REMOVE: drmgr_args[3] = "-r"; break; default: dbg("Unknown hotplug action %d\n", hotplug->action); return; } switch (hotplug->identifier) { case RTAS_HP_ID_DRC_INDEX: drmgr_args[4] = "-s"; snprintf(drc_index, 11, "%#x", hotplug->u1.drc_index); drmgr_args[5] = drc_index; break; case RTAS_HP_ID_DRC_COUNT: drmgr_args[4] = "-q"; snprintf(count, 4, "%u", hotplug->u1.count); drmgr_args[5] = count; break; default: dbg("Unknown or unsupported hotplug identifier %d\n", hotplug->identifier); return; } dbg("run: %s %s %s %s %s %s %s\n", drmgr_args[0], drmgr_args[1], drmgr_args[2], drmgr_args[3], drmgr_args[4], drmgr_args[5], drmgr_args[6]); #ifdef DEBUG if(no_drmgr) return; #endif /* invoke drmgr */ dbg("Invoke drmgr command\n"); child = fork(); if (child == -1) { log_msg(NULL, "%s cannot be run to handle a hotplug event, %s", DRMGR_PROGRAM, strerror(errno)); return; } else if (child == 0) { /* child process */ rc = execv(DRMGR_PROGRAM, drmgr_args); /* shouldn't get here */ log_msg(NULL, "Couldn not exec %s in response to hotplug event, %s", DRMGR_PROGRAM, strerror(errno)); exit(1); } child = waitpid(child, &status, 0); dbg("drmgr call exited with %d\n", WEXITSTATUS(status)); } } ppc64-diag-2.7.0/rtas_errd/prrn.c0000644000000000000000000003140412642205425015172 0ustar rootroot/** * @file prrn.c * * Copyright (C) IBM Corporation * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "rtas_errd.h" struct pmap_struct { struct pmap_struct *next; /* The fields below are stored in host endian */ uint32_t phandle; uint32_t drc_index; char *name; }; struct drconf_cell { uint64_t base_addr; uint32_t drc_index; uint32_t reserved; uint32_t aa_index; uint32_t flags; }; static struct pmap_struct *plist; static int prrn_log_fd; #define OFDT_BASE "/proc/device-tree" #define OFDTPATH "/proc/ppc64/ofdt" #define PRRN_HOTPLUG "/etc/ppc64-diag/prrn_hotplug" #define DRCONF_PATH "/proc/device-tree/ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory" static int write_prrn_log(const char *buf, int len) { if (prrn_log_fd) return write(prrn_log_fd, buf, len); return -1; } static void open_prrn_log(void) { time_t now; int len; char buf[128]; prrn_log_fd = open("/var/log/prrn_log", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); if (prrn_log_fd == -1) { prrn_log_fd = 0; dbg("Could not open PRRN log file"); return; } now = time(0); len = sprintf(buf, "# PRRN Event Recieved: %s", ctime(&now)); write_prrn_log(buf, len); } static void close_prrn_log(void) { if (prrn_log_fd) close(prrn_log_fd); } uint32_t get_drc_index(const char *path) { char drc_path[256]; FILE *fp; uint32_t drc_index; int rc; sprintf(drc_path, "%s/%s", path, "ibm,my-drc-index"); fp = fopen(drc_path, "r"); if (!fp) return 0; rc = fread(&drc_index, sizeof(drc_index), 1, fp); if (rc != 1) drc_index = 0; fclose(fp); return be32toh(drc_index); } /** * add_phandle_to_list * * @param name * @param phandle */ static void add_phandle_to_list(char *name, uint32_t phandle, uint32_t drc_index) { struct pmap_struct *pm; pm = calloc(1, sizeof(struct pmap_struct)); if (!pm) return; pm->name = malloc(strlen(name) + 1); if (!pm->name) { free(pm); return; } sprintf(pm->name, "%s", name); pm->phandle = phandle; pm->drc_index = drc_index; pm->next = plist; plist = pm; } /** * phandle_to_name * * @param ph * @returns */ static struct pmap_struct *phandle_to_pms(uint32_t phandle) { struct pmap_struct *pms = plist; while (pms && pms->phandle != phandle) pms = pms->next; return pms; } /** * add_std_phandles * * @param parent * @param p * @returns */ static int add_std_phandles(char *parent, char *p) { DIR *d; struct dirent *de; char path[PATH_MAX]; uint32_t phandle; char *pend; FILE *fd; strcpy(path, parent); if (p) { strcat(path, "/"); strcat(path, p); } pend = path + strlen(path); d = opendir(path); if (!d) { perror(path); return -1; } while ((de = readdir(d))) { if ((de->d_type == DT_DIR) && (strcmp(de->d_name, ".")) && (strcmp(de->d_name, ".."))) add_std_phandles(path, de->d_name); } strcpy(pend, "/ibm,phandle"); fd = fopen(path, "r"); if (fd) { uint32_t drc_index; if (fread(&phandle, sizeof(phandle), 1, fd) != 1) { dbg("Error reading phandle data!"); fclose(fd); return -1; } *pend = '\0'; drc_index = get_drc_index(path); add_phandle_to_list(path + strlen(OFDT_BASE), be32toh(phandle), drc_index); fclose(fd); } closedir(d); return 0; } /** * add_drconf_phandles * * @returns */ static int add_drconf_phandles() { FILE *fd; int *membuf; int i, rc, entries; struct stat sbuf; struct drconf_cell *mem; /* For PRRN Events the LMBs in dynamic-reconfiguration-memory that * will get updated have their drc-index reported instead of the * phandle in the list of phandles to update reported by * rtas_update_nodes(). So we need to build a list of the possible * LMBs. */ rc = stat(DRCONF_PATH, &sbuf); if (rc) return 0; fd = fopen(DRCONF_PATH, "r"); if (!fd) { /* This is fine, older systems don't have this property */ return 0; } membuf = malloc(sbuf.st_size); if (!membuf) { fclose(fd); return -1; } fread(membuf, sbuf.st_size, 1, fd); if (ferror(fd)) { fclose(fd); free(membuf); return -1; } fclose(fd); entries = be32toh(membuf[0]); mem = (struct drconf_cell *)&membuf[1]; for (i = 0; i < entries; i++) { /* See comment above about rtas reporting drc_indexes. */ add_phandle_to_list("LMB", be32toh(mem->drc_index), be32toh(mem->drc_index)); mem++; /* trust your compiler */ } free(membuf); return 0; } /** * free_phandles * */ static void free_phandles() { struct pmap_struct *pm; while (plist) { pm = plist; plist = plist->next; free(pm->name); free(pm); } } /** * add_phandles * * @returns */ static int add_phandles() { int rc; rc = add_std_phandles(OFDT_BASE, NULL); if (rc) { free_phandles(); return rc; } rc = add_drconf_phandles(); if (rc) free_phandles(); return rc; } /** * 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) { dbg("Failed to open %s: %s", OFDTPATH, strerror(errno)); rc = errno; return rc; } if ((rc = write(fd, cmd, len)) != len) dbg("Error writing to ofdt file! rc %d errno %d", rc, errno); close(fd); /* The reamining code only formats the cmd buffer to make it * human readable when printed via dbg(). */ for (i = 0; i < len; i++) { if (!isprint(cmd[i])) cmd[i] = '.'; if (isspace(cmd[i])) cmd[i] = ' '; } cmd[len-1] = 0x00; dbg("<%s>", cmd); return rc; } /** * update_properties * * @param phandle * @returns 0 on success, !0 otherwise */ static int update_properties(uint32_t phandle) { int rc; char cmd[1024]; 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; struct pmap_struct *pms = phandle_to_pms(phandle); /* * First call to the udpate-properties call, expects the following : * [phandle (4bytes)] * [ 0x0 (4bytes) ] - Indicates the first call for the phandle * [ 0x0 (8bytes) ] - Reserved */ memset(wa, 0x00, 16); wa[0] = htobe32(phandle); do { dbg("about to call rtas_update_properties.\nphandle: %8.8x," " node: %s\nwork area: %8.8x %8.8x %8.8x %8.8x", phandle, pms->name, wa[0], wa[1], wa[2], wa[3]); rc = rtas_update_properties((char *)wa, 1); if (rc && rc != 1) { dbg("Error %d from rtas_update_properties()", rc); return 1; } dbg("successful rtas_update_properties (more %d)", rc); op = wa+4; nprop = be32toh(*op++); /* Should just be on property to update, the affinity. Except * for reconfig memory, that is a single property for * all possible LMBs on the system. */ /* Layout of the workarea returned from rtas, see PAPR for * detailed explanation: * u32 phandle of node * u32 state variable * u64 reserved * u32 number of updated properties * null terminated property name * vd - u32 len of property * actual property */ for (i = 0; i < nprop; i++) { pname = (char *)op; op = (unsigned int *)(pname + strlen(pname) + 1); vd = be32toh(*op++); switch (vd) { case 0x00000000: dbg("%s - name only property %s", pms->name, pname); break; case 0x80000000: dbg("%s - delete property %s", pms->name, pname); sprintf(cmd,"remove_property %u %s", phandle, pname); do_update(cmd, strlen(cmd)); break; default: /* * A negative value indicates incomplete property * and requires one or more followup calls to read * completely. The current length of the data is the * 2's complement of the value. */ if (vd & 0x80000000) { dbg("partial property!"); /* twos compliment of length */ vd = ~vd + 1; more = 1; } else { more = 0; } dbg("%s - updating property %s length %d", pms->name, pname, vd); /* See if we have a partially completed * command */ if (longcmd) { newcmd = malloc(cmdlen + vd); if (!newcmd) { free(longcmd); return -1; } memcpy(newcmd, longcmd, cmdlen); free(longcmd); longcmd = newcmd; } else { longcmd = malloc(vd+128); if (!longcmd) return -1; /* 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; } /** * do_node_update * * Not all nodes can be updated via a DLPAR operation, only those with * a valid drc-index. For nodes without a drc-index we just update the * prrn log file indicating that the node was updated in te device tree * but that we cannot do a DLPAR operation. * @param type * @param pms */ static void do_node_update(struct pmap_struct *pms, const char *type) { char buf[128]; int len; if (pms->drc_index == 0) len = sprintf(buf, "# %s %x - %s (%x)\n", type, pms->drc_index, pms->name, pms->phandle); else len = sprintf(buf, "%s %x\n", type, pms->drc_index); write_prrn_log(buf, len); dbg("Updating property for %s (%08x)", pms->name, pms->phandle); update_properties(pms->phandle); } /** * update_nodes * * @param op * @param n */ static void update_nodes(unsigned int *op, unsigned int n) { int i, len; uint32_t phandle; char buf[128]; struct pmap_struct *pms; for (i = 0; i < n; i++) { phandle = be32toh(*op++); dbg("Updating node with phandle %08x", phandle); pms = phandle_to_pms(phandle); if (!pms) continue; if (!strcmp(pms->name, "LMB")) { len = sprintf(buf, "mem %x\n", pms->drc_index); write_prrn_log(buf, len); } else if (!strncmp(pms->name, "/memory@", 8)) { do_node_update(pms, "mem"); } else { do_node_update(pms, "cpu"); } } } /** * devtree_update * */ static void devtree_update(uint scope) { int rc; unsigned int wa[1024]; unsigned int *op; dbg("Updating device_tree"); if (add_phandles()) return; /* First 16 bytes of work area must be initialized to zero */ memset(wa, 0x00, 16); do { rc = rtas_update_nodes((char *)wa, -scope); if (rc && rc != 1) { dbg("Error %d from rtas_update_nodes()", rc); break; } op = wa+4; /* * The o/p buffer has the following format. * Operation - 1 byte * Number of operands(N) - 3bytes * Operand_1, Operand_2, ... Operand_N - 4bytes each */ while (*(char *)op) { unsigned int n = be32toh(*op) & 0x0FFFFFF; switch (*(char *)op) { case 0x01: dbg("Received unsupported node deletion " "request, trying to continue"); break; case 0x02: update_nodes(op+1, n); break; case 0x03: dbg("Received unsupported node addition " "request, trying to continue"); break; default: dbg("Unknown update_nodes op %8.8x", *(char *)op); } op += 1 + n; } } while (rc == 1); free_phandles(); dbg("Finished devtree update"); } void handle_prrn_event(struct event *re) { pid_t pid; uint scope = re->rtas_hdr->ext_log_length; open_prrn_log(); devtree_update(scope); close_prrn_log(); /* Kick off script to do required hotplug add/remove */ pid = fork(); if (pid == -1) { dbg("Could not exec prrn hotplug script!"); return; } if (pid == 0) { /* Child */ dbg("Kicking off %s script", PRRN_HOTPLUG); execl(PRRN_HOTPLUG, "prrn_hotplug", NULL); /* Should not get here */ dbg("Failed PRRN Hotplug exec: %s", strerror(errno)); exit(0); } /* Nothing to do for the parent, just return */ } ppc64-diag-2.7.0/rtas_errd/rc.powerfail0000755000000000000000000002357212642205425016375 0ustar rootroot#!/bin/sh # # Copyright (C) 2005 IBM Corporation # # 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 # 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # # This is a customizable file for responding to EPOW (Environmental and Power # Warning) events. These events are issued in response to various # environmental conditions such as power or temperature problems, or fan # failures. # # When this script is executed, the /var/log/epow_status file will contain a # number indicating the current status of the system. The following is a list # of values that may appear in that file: # # Status Description Action # ------ ----------- ------ # 0 Normal state no action # 1 Loss of Primary Power 4 ms to shutdown* # 2 Power Supply Failure 4 ms to shutdown* # 3 Manual Power-Off Switch Activated 4 ms to shutdown* # 4 Thermal High 20 seconds to shutdown # 5 Primary Fan Failure 20 seconds to shutdown # 6 Secondary Fan Failure 10 minutes to shutdown # 7 Battery Backup 10 minutes to shutdown # 8 Non-Critical Cooling Problem no action # 9 Non-Critical Power Problem no action # 10 (v6) Normal system shutdown initiate an OS shutdown # 11 (v6) Loss of critical functions initiate an OS shutdown # # * this script is not likely to be invoked in this short timespan # # In the more severe cases, there will not be enough time to invoke this # script (or update the epow_status file, for that matter). A 20-second # warning indicates that the machine should be shut down immediately; power # will be automatically removed in 20 seconds. A 10-minute warning indicates # that a less severe problem exists; the epow_status file will be updated every # 5 seconds. If the status improves to "no action", there is no need to shut # down; otherwise, the system should be shut down within 10 minutes. # # The exit status of this script is as follows: # # Status Description # ------ ----------- # 0 system condition is normal, no shutdown is necessary # 1 system is shutting down or halting # 2 halt -fn failed # 3 shutdown -hF now failed # 4 reached the end of the script, which should never occur # 5 script entered an undefined state # # Current EPOW sensor information may also be obtained from reading # /proc/ppc64/rtas/sensors. # # The rtas_errd daemon must be running for this script to be invoked and for the # epow_status file to be updated. msg="" detail="" status=0 # # notify() # # This function walls the following information to all attached terminals: #