summaryrefslogtreecommitdiff
path: root/hpiutil/hpisel.c
diff options
context:
space:
mode:
Diffstat (limited to 'hpiutil/hpisel.c')
-rw-r--r--hpiutil/hpisel.c934
1 files changed, 934 insertions, 0 deletions
diff --git a/hpiutil/hpisel.c b/hpiutil/hpisel.c
new file mode 100644
index 0000000..e922b81
--- /dev/null
+++ b/hpiutil/hpisel.c
@@ -0,0 +1,934 @@
+/*
+ * hpisel.c
+ *
+ * Author: Andy Cress arcress at users.sourceforge.net
+ * Copyright (c) 2003-2005 Intel Corporation.
+ *
+ * 04/28/03 Andy Cress - created
+ * 04/30/03 Andy Cress v0.6 first good run with common use cases
+ * 05/06/03 Andy Cress v0.7 added -c option to clear it
+ * 05/29/03 Andy Cress v0.8 fixed pstr warnings
+ * 06/13/03 Andy Cress v0.9 fixed strcpy bug,
+ * workaround for SensorEvent.data3
+ * 06/19/03 Andy Cress 0.91 added low SEL free space warning
+ * 06/25/03 Andy Cress v1.0 rework event data logic
+ * 07/23/03 Andy Cress workaround for OpenHPI BUGGY stuff
+ * 11/12/03 Andy Cress v1.1 check for CAPABILITY_SEL
+ * 03/03/04 Andy Cress v1.2 use better free space logic now
+ * 10/14/04 Andy Cress v1.3 added HPI_A/HPI_B logic
+ * 02/11/05 Andy Cress v1.4 added decode routines from showsel.c
+ * 03/30/05 Dave Howell v1.5 added support to enable displaying domain
+ * event log for HPI_B
+ * 04/07/05 Andy Cress v1.6 fix domain resourceid & HPI_A/B flags,
+ * add logic to clear domain event log.
+ *
+ * Note that hpiutil 1.0.0 did not return all event data fields, so event
+ * types other than 'user' did not have all bytes filled in as they
+ * would have from IPMI alone. A patch to the Intel HPI library in
+ * version 1.0.1 resolved this.
+ */
+/*M*
+Copyright (c) 2003-2005, Intel Corporation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ a.. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ b.. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ c.. Neither the name of Intel Corporation nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *M*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <time.h>
+#include "SaHpi.h"
+
+#ifdef HPI_A
+/* HPI A (1.0) spec */
+char progver[] = "1.6 HPI-A";
+#else
+/* HPI B name changes */
+#define SaHpiSelEntryT SaHpiEventLogEntryT
+#define SaHpiSelEntryIdT SaHpiEventLogEntryIdT
+#define SaHpiSelInfoT SaHpiEventLogInfoT
+#define SAHPI_CAPABILITY_SEL SAHPI_CAPABILITY_EVENT_LOG /*0x00000004*/
+#define SAHPI_EC_USER SAHPI_EC_SENSOR_SPECIFIC /*0x7E*/
+char progver[] = "1.6 HPI-B";
+#endif
+int fdebug = 0;
+int fclear = 0;
+int fdomain = 0;
+
+#ifdef HPI_A
+#define NEVTYPES 5
+char *evtypes[NEVTYPES] = {"sensor","hotswap","watchdog","oem ","user "};
+#else
+#define NEVTYPES 9
+char *evtypes[NEVTYPES] = {"resource","domain","sensor","sens_enable",
+ "hotswap","watchdog","HPI sw", "oem ","user "};
+#endif
+
+#define NECODES 27
+struct { int code; char *str;
+} ecodes[NECODES] = {
+ { 0, "Success" },
+ { -1001, "HPI unspecified error" },
+ { -1002, "HPI unsupported function" },
+ { -1003, "HPI busy" },
+ { -1004, "HPI request invalid" },
+ { -1005, "HPI command invalid" },
+ { -1006, "HPI timeout" },
+ { -1007, "HPI out of space" },
+ { -1008, "HPI data truncated" },
+#ifdef HPI_A
+ { -1009, "HPI data length invalid" },
+#else
+ { -1009, "HPI invalid parameter" },
+#endif
+ { -1010, "HPI data exceeds limits" },
+ { -1011, "HPI invalid params" },
+ { -1012, "HPI invalid data" },
+ { -1013, "HPI not present" },
+ { -1014, "HPI invalid data field" },
+ { -1015, "HPI invalid sensor command" },
+ { -1016, "HPI no response" },
+ { -1017, "HPI duplicate request" },
+ { -1018, "HPI updating" },
+ { -1019, "HPI initializing" },
+ { -1020, "HPI unknown error" },
+ { -1021, "HPI invalid session" },
+ { -1022, "HPI invalid domain" },
+ { -1023, "HPI invalid resource id" },
+ { -1024, "HPI invalid request" },
+ { -1025, "HPI entity not present" },
+ { -1026, "HPI uninitialized" }
+};
+char def_estr[15] = "HPI error %d ";
+
+#define NUM_EC 14
+struct { int val; char *str;
+} eventcats[NUM_EC] = {
+{ /*0x00*/ SAHPI_EC_UNSPECIFIED, "unspecified"},
+{ /*0x01*/ SAHPI_EC_THRESHOLD, "Threshold"},
+{ /*0x02*/ SAHPI_EC_USAGE, "Usage "},
+{ /*0x03*/ SAHPI_EC_STATE, "State "},
+{ /*0x04*/ SAHPI_EC_PRED_FAIL, "Predictive"},
+{ /*0x05*/ SAHPI_EC_LIMIT, "Limit "},
+{ /*0x06*/ SAHPI_EC_PERFORMANCE, "Performnc"},
+{ /*0x07*/ SAHPI_EC_SEVERITY, "Severity "},
+{ /*0x08*/ SAHPI_EC_PRESENCE, "DevPresen"},
+{ /*0x09*/ SAHPI_EC_ENABLE, "DevEnable"},
+{ /*0x0a*/ SAHPI_EC_AVAILABILITY, "Availabil"},
+{ /*0x0b*/ SAHPI_EC_REDUNDANCY, "Redundanc"},
+{ /*0x7e*/ SAHPI_EC_USER, "SensorSpc"}, /*UserDefin*/
+{ /*0x7f*/ SAHPI_EC_GENERIC, "OemDefin " }};
+
+#define NUM_ES 6
+struct { int val; char *str; } eventstates[NUM_ES] = {
+{ SAHPI_ES_LOWER_MINOR , "lo-min" },
+{ SAHPI_ES_LOWER_MAJOR , "lo-maj" },
+{ SAHPI_ES_LOWER_CRIT , "lo-crt" },
+{ SAHPI_ES_UPPER_MINOR , "hi-min" },
+{ SAHPI_ES_UPPER_MAJOR , "hi-maj" },
+{ SAHPI_ES_UPPER_CRIT , "hi-crt" } };
+
+#define uchar unsigned char
+#define ushort unsigned short
+#define uint unsigned int
+#define ulong unsigned long
+typedef struct
+{
+ short record_id;
+ uchar record_type;
+ uint timestamp;
+ short generator_id; /*slave_addr/channel*/
+ uchar evm_rev; //event message revision
+ uchar sensor_type;
+ uchar sensor_number;
+ uchar event_trigger;
+ uchar event_data1;
+ uchar event_data2;
+ uchar event_data3;
+} SEL_RECORD;
+
+/* sensor_types: See IPMI 1.5 Table 36-3, IPMI 2.0 Table 42-3 */
+#define NSTYPES 0x2D
+static char *sensor_types[NSTYPES] = {
+/* 00h */ "reserved",
+/* 01h */ "Temperature",
+/* 02h */ "Voltage",
+/* 03h */ "Current",
+/* 04h */ "Fan",
+/* 05h */ "Platform Chassis Intrusion",
+/* 06h */ "Security Violation",
+/* 07h */ "Processor",
+/* 08h */ "Power Supply",
+/* 09h */ "Power Unit",
+/* 0Ah */ "Cooling Device",
+/* 0Bh */ "FRU Sensor",
+/* 0Ch */ "Memory",
+/* 0Dh */ "Drive Slot",
+/* 0Eh */ "POST Memory Resize",
+/* 0Fh */ "System Firmware", /*incl POST code errors*/
+/* 10h */ "SEL Disabled",
+/* 11h */ "Watchdog 1",
+/* 12h */ "System Event", /* offset 0,1,2 */
+/* 13h */ "Critical Interrupt", /* offset 0,1,2 */
+/* 14h */ "Button", /* offset 0,1,2 */
+/* 15h */ "Board",
+/* 16h */ "Microcontroller",
+/* 17h */ "Add-in Card",
+/* 18h */ "Chassis",
+/* 19h */ "Chip Set",
+/* 1Ah */ "Other FRU",
+/* 1Bh */ "Cable/Interconnect",
+/* 1Ch */ "Terminator",
+/* 1Dh */ "System Boot Initiated",
+/* 1Eh */ "Boot Error",
+/* 1Fh */ "OS Boot",
+/* 20h */ "OS Critical Stop",
+/* 21h */ "Slot/Connector",
+/* 22h */ "ACPI Power State",
+/* 23h */ "Watchdog 2",
+/* 24h */ "Platform Alert",
+/* 25h */ "Entity Presence",
+/* 26h */ "Monitor ASIC",
+/* 27h */ "LAN",
+/* 28h */ "Management Subsystem Health",
+/* 29h */ "Battery",
+/* 2Ah */ "Session Audit",
+/* 2Bh */ "Version Change",
+/* 2Ch */ "FRU State"
+};
+
+#define NFWERRS 15
+static struct { /* See Table 36-3, type 0Fh, offset 00h */
+ int code; char *msg;
+ } fwerrs[NFWERRS] = {
+ { 0x00, "Unspecified"},
+ { 0x01, "No system memory"},
+ { 0x02, "No usable memory"},
+ { 0x03, "Unrecovered Hard Disk"},
+ { 0x04, "Unrecovered System Board"},
+ { 0x05, "Unrecovered Diskette"},
+ { 0x06, "Unrecovered Hard Disk Ctlr"},
+ { 0x07, "Unrecovered PS2 USB"},
+ { 0x08, "Boot media not found"},
+ { 0x09, "Unrecovered video controller"},
+ { 0x0A, "No video device"},
+ { 0x0B, "Firmware ROM corruption"},
+ { 0x0C, "CPU voltage mismatch"},
+ { 0x0D, "CPU speed mismatch"},
+ { 0x0E, "Reserved" }
+};
+
+#define NFWSTAT 27
+static struct { /* See Table 36-3, type 0Fh, offset 01h & 02h */
+ int code; char *msg;
+ } fwstat[NFWSTAT] = {
+ { 0x00, "Unspecified"},
+ { 0x01, "Memory init"},
+ { 0x02, "Hard disk init"},
+ { 0x03, "Secondary processor"},
+ { 0x04, "User authentication"},
+ { 0x05, "User-init sys setup"},
+ { 0x06, "USB configuration"},
+ { 0x07, "PCI configuration"},
+ { 0x08, "Option ROM init"},
+ { 0x09, "Video init"},
+ { 0x0a, "Cache init"},
+ { 0x0b, "SM Bus init"},
+ { 0x0c, "Keyboard init"},
+ { 0x0d, "Mgt controller"},
+ { 0x0e, "Docking attach"},
+ { 0x0f, "Enabling docking"},
+ { 0x10, "Docking eject"},
+ { 0x11, "Disabling docking"},
+ { 0x12, "OS wake-up"},
+ { 0x13, "Starting OS boot"},
+ { 0x14, "Baseboard init"},
+ { 0x15, "reserved"},
+ { 0x16, "Floppy init"},
+ { 0x17, "Keyboard test"},
+ { 0x18, "Mouse test"},
+ { 0x19, "Primary processor"},
+ { 0x1A, "Reserved"}
+};
+
+#define NGDESC 7
+struct {
+ ushort g_id;
+ char desc[10];
+} gen_desc[NGDESC] = { /*empirical, format defined in IPMI 1.5 Table 23-5 */
+ { 0x0000, "IPMB"},
+ { 0x0001, "EFI "},
+ { 0x0003, "BIOS"},
+ { 0x0020, "BMC "},
+ { 0x0021, "SMI "},
+ { 0x0028, "CHAS"}, /* Chassis Bridge Controller */
+/*{0x0031, "SMI/IPMB"}, * ia64/mBMC POST errors (rqSa/rqLun) */
+/*{0x0033, "MemCtlr"}, * ia64 memory controller? (rqSa/rqLun) */
+ { 0x00c0, "HSC "} /* SAF-TE Hot-Swap Controller*/
+};
+
+#define NCRITS 10
+char * crit_int_str[NCRITS] = { /* Critical Interrupt descriptions */
+ /*00*/ "FP NMI ", /* Front Panel NMI */
+ /*01*/ "Bus Timout",
+ /*02*/ "IOch NMI ", /* IO channel check NMI */
+ /*03*/ "Soft NMI ",
+ /*04*/ "PCI PERR ",
+ /*05*/ "PCI SERR ",
+ /*06*/ "EISA Timout",
+ /*07*/ "Bus Warn ", /* Bus Correctable Error */
+ /*08*/ "Bus Error", /* Bus Uncorrectable Error */
+ /*09*/ "Fatal NMI" };
+
+#define NSLOTC 9
+char * slot_str[NSLOTC] = { /* Slot/Connector descriptions */
+ /*00*/ "Fault ",
+ /*01*/ "Identify",
+ /*02*/ "Inserted",
+ /*03*/ "InsReady",
+ /*04*/ "RemReady",
+ /*05*/ "PowerOff",
+ /*06*/ "RemRequest",
+ /*07*/ "Interlock",
+ /*08*/ "Disabled" };
+
+#define NSDESC 47
+struct {
+ ushort genid; /*generator id: BIOS, BMC, etc. (slave_addr/channel)*/
+ uchar s_typ; /*1=temp,2=voltage,4=fan,... */
+ uchar s_num;
+ uchar evtrg; /*event trigger/type, see IPMI 1.5 table 36.1 & 36.2 */
+ uchar data1;
+ uchar data2;
+ uchar data3;
+ char desc[40];
+} sens_desc[NSDESC] = {
+{0xffff,0x05, 0x05, 0x6f, 0x44, 0xff, 0xff, "LAN unplugged"}, /*chassis*/
+{0xffff,0x05, 0x05, 0xef, 0x44, 0xff, 0xff, "LAN restored "}, /*chassis*/
+{0xffff,0x06, 0xff, 0xff, 0x45, 0xff, 0xff, "Password"}, /*security*/
+{0xffff,0x07, 0xff, 0xff, 0x41, 0xff, 0xff, "Thermal trip"}, /*processor*/
+{0xffff,0x08, 0xff, 0x6f, 0x40, 0xff, 0xff, "Presence detected"},/*PowerSupply*/
+{0xffff,0x08, 0xff, 0x6f, 0x41, 0xff, 0xff, "Failure detected"},/*power supply*/
+{0xffff,0x08, 0xff, 0x6f, 0x42, 0xff, 0xff, "Predictive failure"},
+{0xffff,0x08, 0xff, 0x6f, 0x43, 0xff, 0xff, "AC Lost"},
+{0xffff,0x08, 0xff, 0xef, 0x40, 0xff, 0xff, "not present"}, /*power supply*/
+{0xffff,0x08, 0xff, 0xef, 0x41, 0xff, 0xff, "is OK "}, /*power supply*/
+{0xffff,0x08, 0xff, 0xef, 0x42, 0xff, 0xff, "Predictive OK"},
+{0xffff,0x08, 0xff, 0xef, 0x43, 0xff, 0xff, "AC Regained"}, /*power supply*/
+{0xffff,0x09, 0xff, 0xff, 0x40, 0xff, 0xff, "Redundancy OK "}, /*power unit*/
+{0xffff,0x09, 0xff, 0xff, 0x41, 0xff, 0xff, "Redundancy Lost"},
+{0xffff,0x09, 0xff, 0xff, 0x44, 0xff, 0xff, "AC Lost"},
+{0xffff,0x09, 0xff, 0xff, 0x46, 0xff, 0xff, "Failure detected"},
+{0xffff,0x09, 0xff, 0xff, 0x47, 0xff, 0xff, "Predictive failure"},/*power unit*/
+{0xffff,0x0c, 0xff, 0xff, 0x00, 0xff, 0xff, "Correctable ECC"}, /*memory*/
+{0xffff,0x0f, 0x06, 0xff, 0xff, 0xff, 0xff, "POST Code"},
+{0xffff,0x10, 0x09, 0xff, 0x42, 0x0f, 0xff, "Log Cleared"},
+{0xffff,0x10, 0x09, 0xff, 0xc0, 0x03, 0xff, "ECC Memory Errors"},
+ /* Often see these 3 Boot records with reboot:
+ * 12 83 6f 05 00 ff = System/SEL Time Sync 1 (going down)
+ * 12 83 6f 05 80 ff = System/SEL Time Sync 2 (coming up)
+ * 12 83 6f 01 ff ff = OEM System Boot Event (Completed POST) */
+{0xffff,0x12, 0x83, 0xff, 0x05, 0x00, 0xff, "Boot: ClockSync 1"},
+{0xffff,0x12, 0x83, 0xff, 0x05, 0x80, 0xff, "Boot: ClockSync 2"},
+{0xffff,0x12, 0x83, 0xff, 0x01, 0xff, 0xff, "OEM System Booted"},
+{0xffff,0x12, 0x08, 0xff, 0x01, 0xff, 0xff, "OEM System Booted"}, /*ia64*/
+{0xffff,0x12, 0x00, 0x6f, 0xff, 0xff, 0xff, "PEF Action"}, /*ia64*/
+{0xffff,0x12, 0x83, 0x6f, 0x80, 0xff, 0xff, "System Reconfigured"}, /*BMC*/
+{0x00c0,0x0d, 0xff, 0x08, 0x00, 0xff, 0xff, "Device Removed"}, /*HSC*/
+{0x00c0,0x0d, 0xff, 0x08, 0x01, 0xff, 0xff, "Device Inserted"}, /*HSC*/
+{0xffff,0x14, 0xff, 0xff, 0x42, 0xff, 0xff, "Reset Button pressed"},
+{0xffff,0x14, 0xff, 0xff, 0x40, 0xff, 0xff, "Power Button pressed"},
+{0xffff,0x14, 0xff, 0xff, 0x01, 0xff, 0xff, "ID Button pressed"},
+{0xffff,0x23, 0xff, 0xff, 0x40, 0xff, 0xff, "Expired, no action"},/*watchdog2*/
+{0xffff,0x23, 0xff, 0xff, 0x41, 0xff, 0xff, "Hard Reset action"}, /*watchdog2*/
+{0xffff,0x23, 0xff, 0xff, 0x42, 0xff, 0xff, "Power down action"}, /*watchdog2*/
+{0xffff,0x23, 0xff, 0xff, 0x43, 0xff, 0xff, "Power cycle action"},/*watchdog2*/
+{0xffff,0x23, 0xff, 0xff, 0x48, 0xff, 0xff, "Timer interrupt"}, /*watchdog2*/
+{0xffff,0xf3, 0x85, 0xff, 0x41, 0xff, 0xff, "State is now OK"},
+{0xffff,0x20, 0x00, 0xff, 0xff, 0xff, 0xff, "OS Kernel Panic"},
+{0xffff,0xff, 0xff, 0x01, 0x57, 0xff, 0xff, "Hi Noncrit thresh"},
+{0xffff,0xff, 0xff, 0x01, 0x59, 0xff, 0xff, "Hi Crit thresh"},
+{0xffff,0xff, 0xff, 0x01, 0x50, 0xff, 0xff, "Lo Noncrit thresh"},
+{0xffff,0xff, 0xff, 0x01, 0x52, 0xff, 0xff, "Lo Crit thresh"},
+{0xffff,0xff, 0xff, 0x81, 0x57, 0xff, 0xff, "HiN thresh OK now"},
+{0xffff,0xff, 0xff, 0x81, 0x59, 0xff, 0xff, "HiC thresh OK now"},
+{0xffff,0xff, 0xff, 0x81, 0x50, 0xff, 0xff, "LoN thresh OK now"},
+{0xffff,0xff, 0xff, 0x81, 0x52, 0xff, 0xff, "LoC thresh OK now"}
+ /*Thresholds apply to sensor types 1=temp, 2=voltage, 4=fan */
+ /*Note that last 2 bytes usu show actual & threshold values*/
+ /*evtrg: 0x01=thresh, 0x81=restored */
+};
+
+/*------------------------------------------------------------------------
+ * get_misc_desc
+ * Uses the sens_desc array to decode misc entries not otherwise handled.
+ * Called by decode_sel_entry
+ *------------------------------------------------------------------------*/
+char * get_misc_desc(uchar type, uchar num, ushort genid, uchar trig,
+ uchar data1, uchar data2, uchar data3);
+char *
+get_misc_desc(uchar type, uchar num, ushort genid, uchar trig,
+ uchar data1, uchar data2, uchar data3)
+{
+ int i;
+ char *pstr = NULL;
+
+ /* Use sens_desc array for other misc descriptions */
+ data1 &= 0x0f; /*ignore top half of sensor offset for matching */
+ for (i = 0; i < NSDESC; i++) {
+ if ((sens_desc[i].s_typ == 0xff) ||
+ (sens_desc[i].s_typ == type)) {
+ if (sens_desc[i].s_num != 0xff &&
+ sens_desc[i].s_num != num)
+ continue;
+ if (sens_desc[i].genid != 0xffff &&
+ sens_desc[i].genid != genid)
+ continue;
+ if (sens_desc[i].evtrg != 0xff &&
+ sens_desc[i].evtrg != trig)
+ continue;
+ if (sens_desc[i].data1 != 0xff &&
+ (sens_desc[i].data1 & 0x0f) != data1)
+ continue;
+ if (sens_desc[i].data2 != 0xff &&
+ sens_desc[i].data2 != data2)
+ continue;
+ if (sens_desc[i].data3 != 0xff &&
+ sens_desc[i].data3 != data3)
+ continue;
+ /* have a match, use description */
+ pstr = (char *)sens_desc[i].desc;
+ break;
+ }
+ } /*end for*/
+ return(pstr);
+} /* end get_misc_desc() */
+
+void decode_sensor_event(uchar sensor_type, uchar sensor_number, ushort gen_id,
+ uchar event_trigger, uchar data1, uchar data2, uchar data3,
+ char *outbuf);
+void
+decode_sensor_event(uchar sensor_type, uchar sensor_number, ushort gen_id,
+ uchar event_trigger, uchar data1, uchar data2, uchar data3,
+ char *outbuf)
+{
+ char mystr[26] = "(123)"; /*for panic string*/
+ char poststr[24] = "OEM Post Code = %x%x";
+ char genstr[10] = "03 ";
+ char *gstr;
+ char *pstr;
+ uchar dtype;
+ int i;
+
+ /* set dtype, used as array index below */
+ if (sensor_type >= NSTYPES) dtype = 0;
+ else dtype = sensor_type;
+ switch(sensor_type) {
+ case 0x20: /*OS Crit Stop*/
+ /* Show first 3 chars of panic string */
+ mystr[0] = '(';
+ mystr[1] = sensor_number & 0x7f;
+ mystr[2] = data2 & 0x7f;
+ mystr[3] = data3 & 0x7f;
+ mystr[4] = ')';
+ mystr[5] = 0;
+ pstr = mystr;
+ if (sensor_number & 0x80) strcat(mystr,"Oops!");
+ if (data2 & 0x80) strcat(mystr,"Int!");
+ if (data3 & 0x80) strcat(mystr,"NullPtr!");
+ break;
+ case 0x0f: /*Post Errs*/
+ switch (data1)
+ {
+ case 0x00: /* System firmware errors */
+ i = data2;
+ if (i >= NFWERRS) i = NFWERRS - 1;
+ pstr = fwerrs[i].msg;
+ break;
+ case 0x01: /* System firmware hang */
+ i = data2;
+ if (i >= NFWSTAT) i = NFWSTAT - 1;
+ sprintf(poststr,"hang, %s",fwstat[i].msg);
+ pstr = poststr;
+ break;
+ case 0x02: /* System firmware progress */
+ i = data2;
+ if (i >= NFWSTAT) i = NFWSTAT - 1;
+ sprintf(poststr,"prog, %s",fwstat[i].msg);
+ pstr = poststr;
+ break;
+ case 0xa0: /* OEM post codes */
+ /* OEM post codes in bytes 2 & 3 (lo-hi) */
+ sprintf(poststr,"POST Code %02x%02x",
+ data3,data2);
+ pstr = poststr;
+ break;
+ default:
+ pstr = "POST Error"; /*default string*/
+ } /*end switch(data1)*/
+ break;
+ case 0x13: /*Crit Int*/
+ i = data1 & 0x0f;
+ if (i >= NCRITS) i = NCRITS - 1;
+ pstr = crit_int_str[i];
+ break;
+ case 0x21: /*Slot/Con*/
+ i = data1 & 0x0f;
+ if (i >= NSLOTC) i = NSLOTC - 1;
+ sprintf(mystr,"%s",slot_str[i]);
+ /* could also decode data2/data3 here if valid */
+ pstr = mystr;
+ break;
+ default: /* all other sensor types, see sens_desc */
+ pstr = get_misc_desc( sensor_type,
+ sensor_number, gen_id,
+ event_trigger, data1, data2, data3);
+ if (pstr == NULL) {
+ mystr[0] = '-'; mystr[1] = 0;
+ pstr = mystr;
+ }
+
+ } /*end switch(sensor_type)*/
+
+ /* show the Generator ID */
+ sprintf(genstr,"%04x",gen_id);
+ gstr = genstr; /* default */
+ for (i = 0; i < NGDESC; i++)
+ {
+ if (gen_desc[i].g_id == gen_id)
+ gstr = (char *)gen_desc[i].desc;
+ }
+
+ /*firmware timestamp is #seconds since 1/1/1970 localtime*/
+ /* timestamp handled by caller in HPI */
+
+ if ((event_trigger == 0x01) || /*threshold*/
+ (event_trigger == 0x81)) { /*threshold ok*/
+ sprintf(outbuf,
+ "%s %02x %s act=%02x thr=%02x",
+ sensor_types[dtype], sensor_number, pstr,
+ data2, /*actual reading*/
+ data3 ); /*threshold value*/
+ } else {
+ sprintf(outbuf,
+ "%s %02x %s %02x [%02x %02x %02x]",
+ sensor_types[dtype] , sensor_number, pstr,
+ event_trigger, data1, data2, data3 );
+ }
+}
+
+/*------------------------------------------------------------------------
+ * decode_ipmi_event
+ * Parse and decode the SEL record into readable format.
+ * This routine is constructed so that it could be used as a library
+ * function.
+ * Input: psel, a pointer to the IPMI SEL record
+ * Output: outbuf, a description of the event, max 80 chars.
+ * Called by ReadSEL
+ *------------------------------------------------------------------------*/
+void decode_ipmi_event( SEL_RECORD *psel, char *outbuf);
+void decode_ipmi_event( SEL_RECORD *psel, char *outbuf)
+{
+ char genstr[10] = "03 ";
+ int i, j;
+
+ if (psel->record_type >= 0xe0) { /*OEM Record 26.3*/
+ char *pc;
+ pc = (char *)&psel->timestamp; /*bytes 4:16*/
+ sprintf(outbuf," OEM Event %02x %02x ", pc[0], pc[1]);
+ j = strlen(outbuf);
+ for (i = 2; i < 13; i++) { /* 4:16 = 13 bytes data */
+ if (psel->record_type == 0xf0) {
+ /* panic string will be type 0xf0 */
+ if (pc[i] == 0) break;
+ outbuf[j++] = pc[i];
+ } else {
+ sprintf(&outbuf[j],"%02x ",pc[i]);
+ j += 3;
+ }
+ }
+ outbuf[j++] = '\n';
+ outbuf[j++] = 0;
+ } else if (psel->record_type == 0x02) {
+ /* most records are record type 2 */
+ decode_sensor_event(psel->sensor_type,
+ psel->sensor_number, psel->generator_id,
+ psel->event_trigger, psel->event_data1,
+ psel->event_data2, psel->event_data3, outbuf);
+
+ } /*endif type 2 */
+ else { /* other misc record type */
+ uchar *pc;
+ pc = (uchar *)&psel->record_type;
+ sprintf(outbuf," Type%02x ", pc[0]);
+ j = strlen(outbuf);
+ for (i = 1; i < 14; i++) {
+ sprintf(genstr,"%02x ",pc[i]);
+ strcat(outbuf,genstr);
+ }
+ } /*endif misc type*/
+ return;
+} /*end decode_ipmi_event()*/
+
+#define IF_IPMI 0 /* other interfaces, like H8, have diff numbers */
+ /*Note that OpenHPI 2.0.0 does not yet fill this in*/
+
+/*------------------------------------------------------------------------
+ * decode_hpi_event
+ * Parse and decode the SensorEvent record into readable format.
+ * Input: pevent, a pointer to the HPI SensorEvent record
+ * Output: outbuf, a description of the event, max 80 chars.
+ * Called by ReadSEL
+ *------------------------------------------------------------------------*/
+void decode_hpi_event( SaHpiSensorEventT *pevent, char *outbuf);
+void decode_hpi_event( SaHpiSensorEventT *pevent, char *outbuf)
+{
+ int ec, eci;
+ int es, esi;
+ int styp;
+ uchar data1, data2, data3, if_type;
+ uchar etrig;
+ ushort genid;
+ char estag[8];
+ char sbuf[80];
+ char *ecstr;
+ // char *pstr;
+
+ /* decode event category */
+ ec = pevent->EventCategory;
+ for (eci = 0; eci < NUM_EC; eci++)
+ if (eventcats[eci].val == ec) break;
+ if (eci >= NUM_EC) eci = 0;
+ ecstr = eventcats[eci].str;
+ genid = 0x0020; /* default to BMC */
+ etrig = 0x6f; /* default to sensor-specific*/
+ /* decode event state */
+ es = pevent->EventState;
+ if (ec == SAHPI_EC_USER) { /*OpenHPI usu returns this (0x7e)*/
+ sprintf(estag,"%02x",es);
+ } else if (eci == SAHPI_EC_THRESHOLD ) { /*0x01*/
+ for (esi = 0; esi < NUM_ES; esi++)
+ if (eventstates[esi].val == es) break;
+ if (esi >= NUM_ES) esi = 0;
+ strcpy(estag,eventstates[esi].str);
+ if (pevent->Assertion) etrig = 0x01;
+ else etrig = 0x81;
+ } else {
+ sprintf(estag,"%02x:%02x",ec,es);
+ }
+
+ /* decode sensor type */
+ styp = pevent->SensorType;
+ if (styp >= NSTYPES) { styp = 0; }
+
+ /* get if_type from SensorSpecific h.o. byte */
+ if_type = (pevent->SensorSpecific & 0xff000000) >> 24;
+ data3 = (pevent->SensorSpecific & 0x00ff0000) >> 16;
+ data2 = (pevent->SensorSpecific & 0x0000ff00) >> 8;
+ data1 = (pevent->SensorSpecific & 0x000000ff);
+ if (if_type == IF_IPMI) { /* handle IPMI SensorSpecific stuff */
+ /* fortunately, HPI & IPMI have the same sensor_type values */
+ decode_sensor_event(styp, pevent->SensorNum, genid,
+ etrig, data1, data2, data3, sbuf);
+ sprintf(outbuf,"%s %s", estag, sbuf);
+ }
+ else {
+ sprintf(outbuf,"%s, %s %s %x [%02x %02x %02x]",
+ sensor_types[styp], ecstr, estag,
+ pevent->SensorNum, data1, data2, data3);
+ }
+
+ return;
+}
+
+static
+char *decode_error(SaErrorT code)
+{
+ int i;
+ char *str = NULL;
+ for (i = 0; i < NECODES; i++) {
+ if (code == ecodes[i].code) { str = ecodes[i].str; break; }
+ }
+ if (str == NULL) {
+ sprintf(&def_estr[10],"%d",code);
+ str = &def_estr[0];
+ }
+ return(str);
+}
+
+void ShowSel( SaHpiSelEntryT *sel, SaHpiRdrT *rdr, SaHpiRptEntryT *rptentry);
+void ShowSel( SaHpiSelEntryT *sel, SaHpiRdrT *rdr,
+ SaHpiRptEntryT *rptentry )
+{
+ unsigned char evtype;
+ char timestr[40];
+ time_t tt1;
+ char *srctag;
+ char *rdrtag;
+ char *pstr;
+ unsigned char *pd;
+ int outlen;
+ char outbuf[132];
+ int styp;
+ unsigned char data3;
+
+ /*format & print the EventLog entry*/
+ if (sel->Event.Timestamp > SAHPI_TIME_MAX_RELATIVE) { /*absolute time*/
+ tt1 = sel->Event.Timestamp / 1000000000;
+ strftime(timestr,sizeof(timestr),"%x %H:%M:%S", localtime(&tt1));
+ } else if (sel->Event.Timestamp > SAHPI_TIME_UNSPECIFIED) { /*invalid time*/
+ strcpy(timestr,"invalid time ");
+ } else { /*relative time*/
+ tt1 = sel->Event.Timestamp / 1000000000;
+ sprintf(timestr,"rel(%lx)", (unsigned long)tt1);
+ }
+ if (rptentry->ResourceId == sel->Event.Source)
+ srctag = rptentry->ResourceTag.Data;
+ else srctag = "unspec "; /* SAHPI_UNSPECIFIED_RESOURCE_ID */
+ evtype = sel->Event.EventType;
+ if (evtype > NEVTYPES) evtype = NEVTYPES - 1;
+ if (rdr->RdrType == SAHPI_NO_RECORD) rdrtag = "rdr-unkn";
+ else {
+ rdr->IdString.Data[rdr->IdString.DataLength] = 0;
+ rdrtag = &rdr->IdString.Data[0];
+ }
+ sprintf(outbuf,"%04x %s %s ", sel->EntryId, timestr, evtypes[evtype] );
+ outlen = strlen(outbuf);
+ pstr = "";
+#ifdef HPI_A
+ pd = &sel->Event.EventDataUnion.UserEvent.UserEventData[0];
+#else
+ pd = &sel->Event.EventDataUnion.UserEvent.UserEventData.Data[0];
+#endif
+
+ switch(evtype)
+ {
+ case SAHPI_ET_SENSOR: /*Sensor*/
+ pd = (void *)&(sel->Event.EventDataUnion.SensorEvent);
+ decode_hpi_event((void *)pd,&outbuf[outlen]);
+ break;
+ case SAHPI_ET_USER: /*User, usu 16-byte IPMI SEL record */
+ decode_ipmi_event((void *)pd,&outbuf[outlen]);
+ break;
+ default:
+ // decode_ipmi_event((void *)pd,&outbuf[outlen]);
+ styp = pd[10];
+ data3 = pd[15];
+ /* *sel->Event.EventDataUnion.SensorEvent.SensorSpecific+1 */
+ if (styp >= NSTYPES) {
+ if (fdebug) printf("sensor type %d >= max %d\n",styp,NSTYPES);
+ styp = 0;
+ }
+ pstr = (char *)sensor_types[styp];
+ sprintf(&outbuf[outlen], "%s, %x %x, %02x %02x %02x [%02x %02x %02x/%02x]",
+ pstr, pd[0], pd[7], pd[10], pd[11], pd[12],
+ pd[13], pd[14], pd[15], data3);
+ break;
+ }
+ printf("%s\n",outbuf);
+}
+
+static SaErrorT
+DoEventLogForResource(SaHpiSessionIdT sessionid,
+ SaHpiResourceIdT resourceid,
+ char *tagname)
+{
+ SaErrorT rv;
+ SaHpiSelInfoT info;
+ int free = 50;
+ SaHpiSelEntryIdT entryid;
+ SaHpiSelEntryIdT nextentryid;
+ SaHpiSelEntryIdT preventryid;
+ SaHpiSelEntryT sel;
+ SaHpiRdrT rdr;
+ SaHpiRptEntryT rptentry;
+
+ printf("rptentry[%d] tag: %s\n", resourceid, tagname);
+
+ rv = saHpiEventLogInfoGet(sessionid, resourceid, &info);
+ if (fdebug)
+ printf("saHpiEventLogInfoGet %s\n", decode_error(rv));
+ if (rv == SA_OK) {
+ free = info.Size - info.Entries;
+ printf("EventLog entries=%d, size=%d, enabled=%d, free=%d\n",
+ info.Entries, info.Size, info.Enabled, free);
+ }
+
+ entryid = SAHPI_OLDEST_ENTRY;
+ while ((rv == SA_OK) && (entryid != SAHPI_NO_MORE_ENTRIES))
+ {
+ /* rv = saHpiEventLogEntryGet(sessionid,SAHPI_DOMAIN_CONTROLLER_ID,entryid, */
+ rv = saHpiEventLogEntryGet(sessionid, resourceid, entryid,
+ &preventryid, &nextentryid, &sel, &rdr, &rptentry);
+ if (fdebug)
+ printf("saHpiEventLogEntryGet[%x] %s, next=%x\n",
+ entryid, decode_error(rv), nextentryid);
+ if (rv == SA_OK) {
+ ShowSel(&sel, &rdr, &rptentry);
+ if (entryid == nextentryid)
+ break;
+ preventryid = entryid;
+ entryid = nextentryid;
+ }
+ }
+
+ if (free < 6) {
+ /*
+ * This test could be more generic if the log info fields above
+ * were accurate. IPMI SEL logs have a fixed size of 0x10000
+ * bytes. New log records are thrown away when it gets full.
+ * (OLDEST = 0, NO_MORE = fffffffe , so these are ok.)
+ */
+ /* free = (0x10000 - 20) - preventryid; */
+ printf( "WARNING: Log free space is very low (%d records)\n"
+ " Clear log with hpisel -c\n", free);
+ }
+
+ return SA_OK;
+}
+
+int
+main(int argc, char **argv)
+{
+ int c;
+ SaErrorT rv;
+ SaHpiSessionIdT sessionid;
+#ifdef HPI_A
+ SaHpiVersionT hpiVer;
+ SaHpiRptInfoT rptinfo;
+#endif
+ SaHpiRptEntryT rptentry;
+ SaHpiEntryIdT rptentryid;
+ SaHpiEntryIdT nextrptentryid;
+ SaHpiResourceIdT resourceid;
+
+ printf("%s: version %s\n",argv[0],progver);
+
+#ifdef HPI_A
+#define ARGSTR "cx?"
+#else
+#define ARGSTR "cdx?"
+#endif
+
+ while ( (c = getopt( argc, argv, ARGSTR)) != EOF )
+ switch(c) {
+ case 'c': fclear = 1; break;
+#ifndef HPI_A
+ case 'd': fdomain = 1; break;
+#endif
+ case 'x': fdebug = 1; break;
+ default:
+ printf("Usage %s [-cx]\n",argv[0]);
+ printf("where -c clears the event log\n");
+#ifndef HPI_A
+ printf(" -d displays the domain event log\n");
+#endif
+ printf(" -x displays eXtra debug messages\n");
+ exit(1);
+ }
+#ifdef HPI_A
+ rv = saHpiInitialize(&hpiVer);
+ if (rv != SA_OK) {
+ printf("saHpiInitialize: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ rv = saHpiSessionOpen(SAHPI_DEFAULT_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ if (rv == SA_ERR_HPI_ERROR)
+ printf("saHpiSessionOpen: error %d, SpiLibd not running\n",rv);
+ else
+ printf("saHpiSessionOpen: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ rv = saHpiResourcesDiscover(sessionid);
+ if (fdebug) printf("saHpiResourcesDiscover %s\n",decode_error(rv));
+ rv = saHpiRptInfoGet(sessionid,&rptinfo);
+ if (fdebug) printf("saHpiRptInfoGet %s\n",decode_error(rv));
+ printf("RptInfo: UpdateCount = %x, UpdateTime = %lx\n",
+ rptinfo.UpdateCount, (unsigned long)rptinfo.UpdateTimestamp);
+#else
+ rv = saHpiSessionOpen(SAHPI_UNSPECIFIED_DOMAIN_ID,&sessionid,NULL);
+ if (rv != SA_OK) {
+ printf("saHpiSessionOpen: %s\n",decode_error(rv));
+ exit(-1);
+ }
+ rv = saHpiDiscover(sessionid);
+ if (fdebug) printf("saHpiDiscover %s\n",decode_error(rv));
+#endif
+
+#ifndef HPI_A
+ if (fdomain != 0) /* saw option for domain event log */
+ {
+ /* resourceid = 1; * oh_get_default_domain_id() */
+ resourceid = SAHPI_UNSPECIFIED_DOMAIN_ID;
+ if (fclear) {
+ rv = saHpiEventLogClear(sessionid,resourceid);
+ if (rv == SA_OK) printf("Domain EventLog successfully cleared\n");
+ else printf("Domain EventLog clear, error = %d\n",rv);
+ } else {
+ rv = DoEventLogForResource(sessionid, resourceid, "Domain Event Log");
+ }
+ }
+ else /* walk the RPT list */
+#endif
+ {
+ rptentryid = SAHPI_OLDEST_ENTRY;
+ while ((rv == SA_OK) && (rptentryid != SAHPI_LAST_ENTRY))
+ {
+ rv = saHpiRptEntryGet(sessionid,rptentryid,&nextrptentryid,&rptentry);
+ if (fdebug)
+ printf("saHpiRptEntryGet[%d] %s\n",rptentryid,decode_error(rv));
+ if (rv != SA_OK)
+ goto skip_to_next;
+ resourceid = rptentry.ResourceId;
+ if (fdebug) printf("RPT %x capabilities = %x\n", resourceid,
+ rptentry.ResourceCapabilities);
+ if ((rptentry.ResourceCapabilities & SAHPI_CAPABILITY_SEL) == 0)
+ goto skip_to_next;
+ if (fclear) {
+ rv = saHpiEventLogClear(sessionid,resourceid);
+ if (rv == SA_OK) printf("EventLog successfully cleared\n");
+ else printf("EventLog clear, error = %d\n",rv);
+ break;
+ }
+ // rptentry.ResourceTag.Data[rptentry.ResourceTag.DataLength] = 0;
+
+ rv = DoEventLogForResource(sessionid, resourceid,
+ rptentry.ResourceTag.Data);
+ skip_to_next:
+ rptentryid = nextrptentryid;
+ }
+ }
+
+ rv = saHpiSessionClose(sessionid);
+#ifdef HPI_A
+ rv = saHpiFinalize();
+#endif
+
+ exit(0);
+}
+
+/* end hpisel.c */