Blame lib/ipmi_event.c

Packit Service ed0f68
/*
Packit Service ed0f68
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution and use in source and binary forms, with or without
Packit Service ed0f68
 * modification, are permitted provided that the following conditions
Packit Service ed0f68
 * are met:
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution of source code must retain the above copyright
Packit Service ed0f68
 * notice, this list of conditions and the following disclaimer.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Redistribution in binary form must reproduce the above copyright
Packit Service ed0f68
 * notice, this list of conditions and the following disclaimer in the
Packit Service ed0f68
 * documentation and/or other materials provided with the distribution.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * Neither the name of Sun Microsystems, Inc. or the names of
Packit Service ed0f68
 * contributors may be used to endorse or promote products derived
Packit Service ed0f68
 * from this software without specific prior written permission.
Packit Service ed0f68
 * 
Packit Service ed0f68
 * This software is provided "AS IS," without a warranty of any kind.
Packit Service ed0f68
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
Packit Service ed0f68
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
Packit Service ed0f68
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
Packit Service ed0f68
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
Packit Service ed0f68
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
Packit Service ed0f68
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
Packit Service ed0f68
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
Packit Service ed0f68
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
Packit Service ed0f68
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
Packit Service ed0f68
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
Packit Service ed0f68
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit Service ed0f68
 */
Packit Service ed0f68
#define _BSD_SOURCE
Packit Service ed0f68
Packit Service ed0f68
#include <stdlib.h>
Packit Service ed0f68
#include <stdio.h>
Packit Service ed0f68
#include <string.h>
Packit Service ed0f68
#include <sys/types.h>
Packit Service ed0f68
#include <sys/socket.h>
Packit Service ed0f68
#include <netinet/in.h>
Packit Service ed0f68
#include <arpa/inet.h>
Packit Service ed0f68
#include <errno.h>
Packit Service ed0f68
#include <unistd.h>
Packit Service ed0f68
#include <signal.h>
Packit Service ed0f68
#include <ctype.h>
Packit Service ed0f68
Packit Service ed0f68
#include <ipmitool/ipmi.h>
Packit Service ed0f68
#include <ipmitool/ipmi_intf.h>
Packit Service ed0f68
#include <ipmitool/helper.h>
Packit Service ed0f68
#include <ipmitool/log.h>
Packit Service ed0f68
#include <ipmitool/ipmi_sel.h>
Packit Service ed0f68
#include <ipmitool/ipmi_strings.h>
Packit Service ed0f68
#include <ipmitool/ipmi_channel.h>
Packit Service ed0f68
#include <ipmitool/ipmi_event.h>
Packit Service ed0f68
#include <ipmitool/ipmi_sdr.h>
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static void
Packit Service ed0f68
ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
Packit Service ed0f68
{
Packit Service ed0f68
	struct sel_event_record sel_event;
Packit Service ed0f68
Packit Service ed0f68
	memset(&sel_event, 0, sizeof(struct sel_event_record));
Packit Service ed0f68
Packit Service ed0f68
	sel_event.record_id = 0;
Packit Service ed0f68
	sel_event.sel_type.standard_type.gen_id = 2;
Packit Service ed0f68
Packit Service ed0f68
	sel_event.sel_type.standard_type.evm_rev        = pmsg->evm_rev;
Packit Service ed0f68
	sel_event.sel_type.standard_type.sensor_type    = pmsg->sensor_type;
Packit Service ed0f68
	sel_event.sel_type.standard_type.sensor_num     = pmsg->sensor_num;
Packit Service ed0f68
	sel_event.sel_type.standard_type.event_type     = pmsg->event_type;
Packit Service ed0f68
	sel_event.sel_type.standard_type.event_dir      = pmsg->event_dir;
Packit Service ed0f68
	sel_event.sel_type.standard_type.event_data[0]  = pmsg->event_data[0];
Packit Service ed0f68
	sel_event.sel_type.standard_type.event_data[1]  = pmsg->event_data[1];
Packit Service ed0f68
	sel_event.sel_type.standard_type.event_data[2]  = pmsg->event_data[2];
Packit Service ed0f68
Packit Service ed0f68
	if (verbose)
Packit Service ed0f68
		ipmi_sel_print_extended_entry_verbose(intf, &sel_event);
Packit Service ed0f68
	else
Packit Service ed0f68
		ipmi_sel_print_extended_entry(intf, &sel_event);
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_send_platform_event(struct ipmi_intf * intf, struct platform_event_msg * emsg)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_rs * rsp;
Packit Service ed0f68
	struct ipmi_rq req;
Packit Service ed0f68
	uint8_t rqdata[8];
Packit Service ed0f68
	uint8_t chmed;
Packit Service ed0f68
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	memset(rqdata, 0, 8);
Packit Service ed0f68
Packit Service ed0f68
	req.msg.netfn = IPMI_NETFN_SE;
Packit Service ed0f68
	req.msg.cmd = 0x02;
Packit Service ed0f68
	req.msg.data = rqdata;
Packit Service ed0f68
Packit Service ed0f68
	chmed = ipmi_current_channel_medium(intf);
Packit Service ed0f68
	if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
Packit Service ed0f68
		/* system interface, need extra generator ID */
Packit Service ed0f68
		req.msg.data_len = 8;
Packit Service ed0f68
		rqdata[0] = 0x41;   // As per Fig. 29-2 and Table 5-4
Packit Service ed0f68
		memcpy(rqdata+1, emsg, sizeof(struct platform_event_msg));
Packit Service ed0f68
	}
Packit Service ed0f68
	else {
Packit Service ed0f68
		req.msg.data_len = 7;
Packit Service ed0f68
		memcpy(rqdata, emsg, sizeof(struct platform_event_msg));
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	ipmi_event_msg_print(intf, emsg);
Packit Service ed0f68
Packit Service ed0f68
	rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
	if (rsp == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Platform Event Message command failed");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
	else if (rsp->ccode > 0) {
Packit Service ed0f68
		lprintf(LOG_ERR, "Platform Event Message command failed: %s",
Packit Service ed0f68
			val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return 0;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
#define EVENT_THRESH_STATE_LNC_LO	0
Packit Service ed0f68
#define EVENT_THRESH_STATE_LNC_HI	1
Packit Service ed0f68
#define EVENT_THRESH_STATE_LCR_LO	2
Packit Service ed0f68
#define EVENT_THRESH_STATE_LCR_HI	3
Packit Service ed0f68
#define EVENT_THRESH_STATE_LNR_LO	4
Packit Service ed0f68
#define EVENT_THRESH_STATE_LNR_HI	5
Packit Service ed0f68
#define EVENT_THRESH_STATE_UNC_LO	6
Packit Service ed0f68
#define EVENT_THRESH_STATE_UNC_HI	7
Packit Service ed0f68
#define EVENT_THRESH_STATE_UCR_LO	8
Packit Service ed0f68
#define EVENT_THRESH_STATE_UCR_HI	9
Packit Service ed0f68
#define EVENT_THRESH_STATE_UNR_LO	10
Packit Service ed0f68
#define EVENT_THRESH_STATE_UNR_HI	11
Packit Service ed0f68
Packit Service ed0f68
static const struct valstr ipmi_event_thresh_lo[] = {
Packit Service ed0f68
	{ EVENT_THRESH_STATE_LNC_LO, "lnc" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_LCR_LO, "lcr" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_LNR_LO, "lnr" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_UNC_LO, "unc" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_UCR_LO, "ucr" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_UNR_LO, "unr" },
Packit Service ed0f68
	{ 0, NULL  },
Packit Service ed0f68
};
Packit Service ed0f68
static const struct valstr ipmi_event_thresh_hi[] = {
Packit Service ed0f68
	{ EVENT_THRESH_STATE_LNC_HI, "lnc" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_LCR_HI, "lcr" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_LNR_HI, "lnr" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_UNC_HI, "unc" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_UCR_HI, "ucr" },
Packit Service ed0f68
	{ EVENT_THRESH_STATE_UNR_HI, "unr" },
Packit Service ed0f68
	{ 0, NULL  },
Packit Service ed0f68
};
Packit Service ed0f68
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_send_platform_event_num(struct ipmi_intf * intf, int num)
Packit Service ed0f68
{
Packit Service ed0f68
	struct platform_event_msg emsg;
Packit Service ed0f68
Packit Service ed0f68
	memset(&emsg, 0, sizeof(struct platform_event_msg));
Packit Service ed0f68
Packit Service ed0f68
	/* IPMB/LAN/etc */
Packit Service ed0f68
	switch (num) {
Packit Service ed0f68
	case 1:			/* temperature */
Packit Service ed0f68
		printf("Sending SAMPLE event: Temperature - "
Packit Service ed0f68
		       "Upper Critical - Going High\n");
Packit Service ed0f68
		emsg.evm_rev       = 0x04;
Packit Service ed0f68
		emsg.sensor_type   = 0x01;
Packit Service ed0f68
		emsg.sensor_num    = 0x30;
Packit Service ed0f68
		emsg.event_dir     = EVENT_DIR_ASSERT;
Packit Service ed0f68
		emsg.event_type    = 0x01;
Packit Service ed0f68
		emsg.event_data[0] = EVENT_THRESH_STATE_UCR_HI;
Packit Service ed0f68
		emsg.event_data[1] = 0xff;
Packit Service ed0f68
		emsg.event_data[2] = 0xff;
Packit Service ed0f68
		break;
Packit Service ed0f68
	case 2:			/* voltage error */
Packit Service ed0f68
		printf("Sending SAMPLE event: Voltage Threshold - "
Packit Service ed0f68
		       "Lower Critical - Going Low\n");
Packit Service ed0f68
		emsg.evm_rev       = 0x04;
Packit Service ed0f68
		emsg.sensor_type   = 0x02;
Packit Service ed0f68
		emsg.sensor_num    = 0x60;
Packit Service ed0f68
		emsg.event_dir     = EVENT_DIR_ASSERT;
Packit Service ed0f68
		emsg.event_type    = 0x01;
Packit Service ed0f68
		emsg.event_data[0] = EVENT_THRESH_STATE_LCR_LO;
Packit Service ed0f68
		emsg.event_data[1] = 0xff;
Packit Service ed0f68
		emsg.event_data[2] = 0xff;
Packit Service ed0f68
		break;
Packit Service ed0f68
	case 3:			/* correctable ECC */
Packit Service ed0f68
		printf("Sending SAMPLE event: Memory - Correctable ECC\n");
Packit Service ed0f68
		emsg.evm_rev       = 0x04;
Packit Service ed0f68
		emsg.sensor_type   = 0x0c;
Packit Service ed0f68
		emsg.sensor_num    = 0x53;
Packit Service ed0f68
		emsg.event_dir     = EVENT_DIR_ASSERT;
Packit Service ed0f68
		emsg.event_type    = 0x6f;
Packit Service ed0f68
		emsg.event_data[0] = 0x00;
Packit Service ed0f68
		emsg.event_data[1] = 0xff;
Packit Service ed0f68
		emsg.event_data[2] = 0xff;
Packit Service ed0f68
		break;
Packit Service ed0f68
	default:
Packit Service ed0f68
		lprintf(LOG_ERR, "Invalid event number: %d", num);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return ipmi_send_platform_event(intf, &emsg;;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_event_find_offset(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type, char *desc)
Packit Service ed0f68
{
Packit Service ed0f68
	const struct ipmi_event_sensor_types *evt;
Packit Service ed0f68
Packit Service ed0f68
	if (desc == NULL || sensor_type == 0  || event_type == 0) {
Packit Service ed0f68
		return 0x00;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	for (evt = ipmi_get_first_event_sensor_type(intf, sensor_type, event_type);
Packit Service ed0f68
			evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) {
Packit Service ed0f68
		if (evt->desc != NULL &&
Packit Service ed0f68
			strncasecmp(desc, evt->desc, __maxlen(desc, evt->desc)) == 0) {
Packit Service ed0f68
			return evt->offset;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	lprintf(LOG_WARN, "Unable to find matching event offset for '%s'", desc);
Packit Service ed0f68
	return -1;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static void
Packit Service ed0f68
print_sensor_states(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type)
Packit Service ed0f68
{
Packit Service ed0f68
	ipmi_sdr_print_discrete_state_mini(intf,
Packit Service ed0f68
			"Sensor States: \n  ", "\n  ", sensor_type,
Packit Service ed0f68
			event_type, 0xff, 0xff);
Packit Service ed0f68
	printf("\n");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * evdir)
Packit Service ed0f68
{
Packit Service ed0f68
	struct ipmi_rs * rsp;
Packit Service ed0f68
	struct sdr_record_list * sdr;
Packit Service ed0f68
	struct platform_event_msg emsg;
Packit Service ed0f68
	int off;
Packit Service ed0f68
	uint8_t target, lun, channel;
Packit Service ed0f68
Packit Service ed0f68
	if (id == NULL) {
Packit Service ed0f68
		lprintf(LOG_ERR, "No sensor ID supplied");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	memset(&emsg, 0, sizeof(struct platform_event_msg));
Packit Service ed0f68
	emsg.evm_rev = 0x04;
Packit Service ed0f68
Packit Service ed0f68
	if (evdir == NULL)
Packit Service ed0f68
		emsg.event_dir = EVENT_DIR_ASSERT;
Packit Service ed0f68
	else if (strncasecmp(evdir, "assert", 6) == 0)
Packit Service ed0f68
		emsg.event_dir = EVENT_DIR_ASSERT;
Packit Service ed0f68
	else if (strncasecmp(evdir, "deassert", 8) == 0)
Packit Service ed0f68
		emsg.event_dir = EVENT_DIR_DEASSERT;
Packit Service ed0f68
	else {
Packit Service ed0f68
		lprintf(LOG_ERR, "Invalid event direction %s.  Must be 'assert' or 'deassert'", evdir);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	printf("Finding sensor %s... ", id);
Packit Service ed0f68
	sdr = ipmi_sdr_find_sdr_byid(intf, id);
Packit Service ed0f68
	if (sdr == NULL) {
Packit Service ed0f68
		printf("not found!\n");
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
	printf("ok\n");
Packit Service ed0f68
Packit Service ed0f68
	switch (sdr->type)
Packit Service ed0f68
	{
Packit Service ed0f68
	case SDR_RECORD_TYPE_FULL_SENSOR:
Packit Service ed0f68
	case SDR_RECORD_TYPE_COMPACT_SENSOR:
Packit Service ed0f68
Packit Service ed0f68
		emsg.sensor_type   = sdr->record.common->sensor.type;
Packit Service ed0f68
		emsg.sensor_num    = sdr->record.common->keys.sensor_num;
Packit Service ed0f68
		emsg.event_type    = sdr->record.common->event_type;
Packit Service ed0f68
		target    = sdr->record.common->keys.owner_id;
Packit Service ed0f68
		lun    = sdr->record.common->keys.lun;
Packit Service ed0f68
		channel = sdr->record.common->keys.channel;
Packit Service ed0f68
		break;
Packit Service ed0f68
	default:
Packit Service ed0f68
		lprintf(LOG_ERR, "Unknown sensor type for id '%s'", id);
Packit Service ed0f68
		return -1;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	emsg.event_data[1] = 0xff;
Packit Service ed0f68
	emsg.event_data[2] = 0xff;
Packit Service ed0f68
Packit Service ed0f68
	switch (emsg.event_type)
Packit Service ed0f68
	{
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * Threshold Class
Packit Service ed0f68
	 */
Packit Service ed0f68
	case 1:
Packit Service ed0f68
	{
Packit Service ed0f68
		int dir = 0;
Packit Service ed0f68
		int hilo = 0;
Packit Service ed0f68
		off = 1;
Packit Service ed0f68
Packit Service ed0f68
		if (state == NULL || strncasecmp(state, "list", 4) == 0) {
Packit Service ed0f68
			printf("Sensor States:\n");
Packit Service ed0f68
			printf("  lnr : Lower Non-Recoverable \n");
Packit Service ed0f68
			printf("  lcr : Lower Critical\n");
Packit Service ed0f68
			printf("  lnc : Lower Non-Critical\n");
Packit Service ed0f68
			printf("  unc : Upper Non-Critical\n");
Packit Service ed0f68
			printf("  ucr : Upper Critical\n");
Packit Service ed0f68
			printf("  unr : Upper Non-Recoverable\n");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		if (0 != strncasecmp(state, "lnr", 3) &&
Packit Service ed0f68
		    0 != strncasecmp(state, "lcr", 3) &&
Packit Service ed0f68
		    0 != strncasecmp(state, "lnc", 3) &&
Packit Service ed0f68
		    0 != strncasecmp(state, "unc", 3) &&
Packit Service ed0f68
		    0 != strncasecmp(state, "ucr", 3) &&
Packit Service ed0f68
		    0 != strncasecmp(state, "unr", 3))
Packit Service ed0f68
		{
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid threshold identifier %s", state);
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		if (state[0] == 'u')
Packit Service ed0f68
			hilo = 1;
Packit Service ed0f68
		else
Packit Service ed0f68
			hilo = 0;
Packit Service ed0f68
Packit Service ed0f68
		if (emsg.event_dir == EVENT_DIR_ASSERT)
Packit Service ed0f68
			dir = hilo;
Packit Service ed0f68
		else
Packit Service ed0f68
			dir = !hilo;
Packit Service ed0f68
Packit Service ed0f68
		if ((emsg.event_dir == EVENT_DIR_ASSERT   && hilo == 1) ||
Packit Service ed0f68
		    (emsg.event_dir == EVENT_DIR_DEASSERT && hilo == 0))
Packit Service ed0f68
			emsg.event_data[0] = (uint8_t)(str2val(state, ipmi_event_thresh_hi) & 0xf);
Packit Service ed0f68
		else if ((emsg.event_dir == EVENT_DIR_ASSERT   && hilo == 0) ||
Packit Service ed0f68
			 (emsg.event_dir == EVENT_DIR_DEASSERT && hilo == 1))
Packit Service ed0f68
			emsg.event_data[0] = (uint8_t)(str2val(state, ipmi_event_thresh_lo) & 0xf);
Packit Service ed0f68
		else {
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid Event");
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		rsp = ipmi_sdr_get_sensor_thresholds(intf, emsg.sensor_num,
Packit Service ed0f68
							target, lun, channel);
Packit Service ed0f68
		if (rsp == NULL) {
Packit Service ed0f68
			lprintf(LOG_ERR,
Packit Service ed0f68
					"Command Get Sensor Thresholds failed: invalid response.");
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
		} else if (rsp->ccode != 0) {
Packit Service ed0f68
			lprintf(LOG_ERR, "Command Get Sensor Thresholds failed: %s",
Packit Service ed0f68
					val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			return (-1);
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		/* threshold reading */
Packit Service ed0f68
		emsg.event_data[2] = rsp->data[(emsg.event_data[0] / 2) + 1];
Packit Service ed0f68
Packit Service ed0f68
		rsp = ipmi_sdr_get_sensor_hysteresis(intf, emsg.sensor_num,
Packit Service ed0f68
							target, lun, channel);
Packit Service ed0f68
		if (rsp != NULL && rsp->ccode == 0)
Packit Service ed0f68
			off = dir ? rsp->data[0] : rsp->data[1];
Packit Service ed0f68
		if (off <= 0)
Packit Service ed0f68
			off = 1;
Packit Service ed0f68
Packit Service ed0f68
		/* trigger reading */
Packit Service ed0f68
		if (dir) {
Packit Service ed0f68
			if ((emsg.event_data[2] + off) > 0xff)
Packit Service ed0f68
				emsg.event_data[1] = 0xff;
Packit Service ed0f68
			else
Packit Service ed0f68
				emsg.event_data[1] = emsg.event_data[2] + off;
Packit Service ed0f68
		}
Packit Service ed0f68
		else {
Packit Service ed0f68
			if ((emsg.event_data[2] - off) < 0)
Packit Service ed0f68
				emsg.event_data[1] = 0;
Packit Service ed0f68
			else
Packit Service ed0f68
				emsg.event_data[1] = emsg.event_data[2] - off;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		/* trigger in byte 2, threshold in byte 3 */
Packit Service ed0f68
		emsg.event_data[0] |= 0x50;
Packit Service ed0f68
	}
Packit Service ed0f68
	break;
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * Digital Discrete
Packit Service ed0f68
	 */
Packit Service ed0f68
	case 3: case 4: case 5: case 6: case 8: case 9:
Packit Service ed0f68
	{
Packit Service ed0f68
		int x;
Packit Service ed0f68
		const char * digi_on[] = { "present", "assert", "limit",
Packit Service ed0f68
					   "fail", "yes", "on", "up" };
Packit Service ed0f68
		const char * digi_off[] = { "absent", "deassert", "nolimit",
Packit Service ed0f68
					    "nofail", "no", "off", "down" };
Packit Service ed0f68
		/* 
Packit Service ed0f68
		 * print list of available states for this sensor
Packit Service ed0f68
		 */
Packit Service ed0f68
		if (state == NULL || strncasecmp(state, "list", 4) == 0) {
Packit Service ed0f68
			print_sensor_states(intf, emsg.sensor_type, emsg.event_type);
Packit Service ed0f68
			printf("Sensor State Shortcuts:\n");
Packit Service ed0f68
			for (x = 0; x < sizeof(digi_on)/sizeof(*digi_on); x++) {
Packit Service ed0f68
				printf("  %-9s  %-9s\n", digi_on[x], digi_off[x]);
Packit Service ed0f68
			}
Packit Service ed0f68
			return 0;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		off = 0;
Packit Service ed0f68
		for (x = 0; x < sizeof(digi_on)/sizeof(*digi_on); x++) {
Packit Service ed0f68
			if (strncasecmp(state, digi_on[x], strlen(digi_on[x])) == 0) {
Packit Service ed0f68
				emsg.event_data[0] = 1;
Packit Service ed0f68
				off = 1;
Packit Service ed0f68
				break;
Packit Service ed0f68
			}
Packit Service ed0f68
			else if (strncasecmp(state, digi_off[x], strlen(digi_off[x])) == 0) {
Packit Service ed0f68
				emsg.event_data[0] = 0;
Packit Service ed0f68
				off = 1;
Packit Service ed0f68
				break;
Packit Service ed0f68
			}
Packit Service ed0f68
		}
Packit Service ed0f68
		if (off == 0) {
Packit Service ed0f68
			off = ipmi_event_find_offset(intf,
Packit Service ed0f68
				emsg.sensor_type, emsg.event_type, state);
Packit Service ed0f68
			if (off < 0)
Packit Service ed0f68
				return -1;
Packit Service ed0f68
			emsg.event_data[0] = off;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
	break;
Packit Service ed0f68
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * Generic Discrete
Packit Service ed0f68
	 */
Packit Service ed0f68
	case 2: case 7: case 10: case 11: case 12:
Packit Service ed0f68
	{
Packit Service ed0f68
		/* 
Packit Service ed0f68
		 * print list of available states for this sensor
Packit Service ed0f68
		 */
Packit Service ed0f68
		if (state == NULL || strncasecmp(state, "list", 4) == 0) {
Packit Service ed0f68
			print_sensor_states(intf, emsg.sensor_type, emsg.event_type);
Packit Service ed0f68
			return 0;
Packit Service ed0f68
		}
Packit Service ed0f68
		off = ipmi_event_find_offset(intf,
Packit Service ed0f68
			emsg.sensor_type, emsg.event_type, state);
Packit Service ed0f68
		if (off < 0)
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		emsg.event_data[0] = off;
Packit Service ed0f68
	}
Packit Service ed0f68
	break;
Packit Service ed0f68
		
Packit Service ed0f68
	/*
Packit Service ed0f68
	 * Sensor-Specific Discrete
Packit Service ed0f68
	 */
Packit Service ed0f68
	case 0x6f:
Packit Service ed0f68
	{
Packit Service ed0f68
		/* 
Packit Service ed0f68
		 * print list of available states for this sensor
Packit Service ed0f68
		 */
Packit Service ed0f68
		if (state == NULL || strncasecmp(state, "list", 4) == 0) {
Packit Service ed0f68
			print_sensor_states(intf, emsg.sensor_type, emsg.event_type);
Packit Service ed0f68
			return 0;
Packit Service ed0f68
		}
Packit Service ed0f68
		off = ipmi_event_find_offset(intf,
Packit Service ed0f68
			emsg.sensor_type, emsg.event_type, state);
Packit Service ed0f68
		if (off < 0)
Packit Service ed0f68
			return -1;
Packit Service ed0f68
		emsg.event_data[0] = off;
Packit Service ed0f68
	}
Packit Service ed0f68
	break;
Packit Service ed0f68
Packit Service ed0f68
	default:
Packit Service ed0f68
		return -1;
Packit Service ed0f68
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	return ipmi_send_platform_event(intf, &emsg;;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static int
Packit Service ed0f68
ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
Packit Service ed0f68
{
Packit Service ed0f68
	FILE * fp;
Packit Service ed0f68
	struct ipmi_rs * rsp;
Packit Service ed0f68
	struct ipmi_rq req;
Packit Service ed0f68
	struct sel_event_record sel_event;
Packit Service ed0f68
	uint8_t rqdata[8];
Packit Service ed0f68
	char buf[1024];
Packit Service ed0f68
	char * ptr, * tok;
Packit Service ed0f68
	int i, j;
Packit Service ed0f68
	uint8_t chmed;
Packit Service ed0f68
	int rc = 0;
Packit Service ed0f68
Packit Service ed0f68
	if (file == NULL)
Packit Service ed0f68
		return -1;
Packit Service ed0f68
Packit Service ed0f68
	memset(rqdata, 0, 8);
Packit Service ed0f68
Packit Service ed0f68
	/* setup Platform Event Message command */
Packit Service ed0f68
	memset(&req, 0, sizeof(req));
Packit Service ed0f68
	req.msg.netfn = IPMI_NETFN_SE;
Packit Service ed0f68
	req.msg.cmd = 0x02;
Packit Service ed0f68
	req.msg.data = rqdata;
Packit Service ed0f68
	req.msg.data_len = 7;
Packit Service ed0f68
Packit Service ed0f68
	chmed = ipmi_current_channel_medium(intf);
Packit Service ed0f68
	if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
Packit Service ed0f68
		/* system interface, need extra generator ID */
Packit Service ed0f68
		rqdata[0] = 0x41;   // As per Fig. 29-2 and Table 5-4
Packit Service ed0f68
		req.msg.data_len = 8;
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	fp = ipmi_open_file_read(file);
Packit Service ed0f68
	if (fp == NULL)
Packit Service ed0f68
		return -1;
Packit Service ed0f68
Packit Service ed0f68
	while (feof(fp) == 0) {
Packit Service ed0f68
		if (fgets(buf, 1024, fp) == NULL)
Packit Service ed0f68
			continue;
Packit Service ed0f68
Packit Service ed0f68
		/* clip off optional comment tail indicated by # */
Packit Service ed0f68
		ptr = strchr(buf, '#');
Packit Service ed0f68
		if (ptr)
Packit Service ed0f68
			*ptr = '\0';
Packit Service ed0f68
		else
Packit Service ed0f68
			ptr = buf + strlen(buf);
Packit Service ed0f68
Packit Service ed0f68
		/* clip off trailing and leading whitespace */
Packit Service ed0f68
		ptr--;
Packit Service ed0f68
		while (isspace((int)*ptr) && ptr >= buf)
Packit Service ed0f68
			*ptr-- = '\0';
Packit Service ed0f68
		ptr = buf;
Packit Service ed0f68
		while (isspace((int)*ptr))
Packit Service ed0f68
			ptr++;
Packit Service ed0f68
		if (strlen(ptr) == 0)
Packit Service ed0f68
			continue;
Packit Service ed0f68
Packit Service ed0f68
		/* parse the event, 7 bytes with optional comment */
Packit Service ed0f68
		/* 0x00 0x00 0x00 0x00 0x00 0x00 0x00 # event */
Packit Service ed0f68
		i = 0;
Packit Service ed0f68
		tok = strtok(ptr, " ");
Packit Service ed0f68
		while (tok) {
Packit Service ed0f68
			if (i == 7)
Packit Service ed0f68
				break;
Packit Service ed0f68
			j = i++;
Packit Service ed0f68
			if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM)
Packit Service ed0f68
				j++;
Packit Service ed0f68
			rqdata[j] = (uint8_t)strtol(tok, NULL, 0);
Packit Service ed0f68
			tok = strtok(NULL, " ");
Packit Service ed0f68
		}
Packit Service ed0f68
		if (i < 7) {
Packit Service ed0f68
			lprintf(LOG_ERR, "Invalid Event: %s",
Packit Service ed0f68
			       buf2str(rqdata, sizeof(rqdata)));
Packit Service ed0f68
			continue;
Packit Service ed0f68
		}
Packit Service ed0f68
Packit Service ed0f68
		memset(&sel_event, 0, sizeof(struct sel_event_record));
Packit Service ed0f68
		sel_event.record_id = 0;
Packit Service ed0f68
		sel_event.sel_type.standard_type.gen_id = 2;
Packit Service ed0f68
Packit Service ed0f68
		j = (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) ? 1 : 0;
Packit Service ed0f68
		sel_event.sel_type.standard_type.evm_rev = rqdata[j++];
Packit Service ed0f68
		sel_event.sel_type.standard_type.sensor_type = rqdata[j++];
Packit Service ed0f68
		sel_event.sel_type.standard_type.sensor_num = rqdata[j++];
Packit Service ed0f68
		sel_event.sel_type.standard_type.event_type = rqdata[j] & 0x7f;
Packit Service ed0f68
		sel_event.sel_type.standard_type.event_dir = (rqdata[j++] & 0x80) >> 7;
Packit Service ed0f68
		sel_event.sel_type.standard_type.event_data[0] = rqdata[j++];
Packit Service ed0f68
		sel_event.sel_type.standard_type.event_data[1] = rqdata[j++];
Packit Service ed0f68
		sel_event.sel_type.standard_type.event_data[2] = rqdata[j++];
Packit Service ed0f68
Packit Service ed0f68
		ipmi_sel_print_std_entry(intf, &sel_event);
Packit Service ed0f68
		
Packit Service ed0f68
		rsp = intf->sendrecv(intf, &req;;
Packit Service ed0f68
		if (rsp == NULL) {
Packit Service ed0f68
			lprintf(LOG_ERR, "Platform Event Message command failed");
Packit Service ed0f68
			rc = -1;
Packit Service ed0f68
		}
Packit Service ed0f68
		else if (rsp->ccode > 0) {
Packit Service ed0f68
			lprintf(LOG_ERR, "Platform Event Message command failed: %s",
Packit Service ed0f68
				val2str(rsp->ccode, completion_code_vals));
Packit Service ed0f68
			rc = -1;
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
Packit Service ed0f68
	fclose(fp);
Packit Service ed0f68
	return rc;
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
static void
Packit Service ed0f68
ipmi_event_usage(void)
Packit Service ed0f68
{
Packit Service ed0f68
	lprintf(LOG_NOTICE, "");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "usage: event <num>");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   Send generic test events");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   1 : Temperature - Upper Critical - Going High");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   2 : Voltage Threshold - Lower Critical - Going Low");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   3 : Memory - Correctable ECC");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "usage: event file <filename>");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   Read and generate events from file");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   Use the 'sel save' command to generate from SEL");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "usage: event <sensorid> <state> [event_dir]");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   sensorid  : Sensor ID string to use for event data");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   state     : Sensor state, use 'list' to see possible states for sensor");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "   event_dir : assert, deassert [default=assert]");
Packit Service ed0f68
	lprintf(LOG_NOTICE, "");
Packit Service ed0f68
}
Packit Service ed0f68
Packit Service ed0f68
int
Packit Service ed0f68
ipmi_event_main(struct ipmi_intf * intf, int argc, char ** argv)
Packit Service ed0f68
{
Packit Service ed0f68
	int rc = 0;
Packit Service ed0f68
Packit Service ed0f68
	if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
Packit Service ed0f68
		ipmi_event_usage();
Packit Service ed0f68
		return 0;
Packit Service ed0f68
	}
Packit Service ed0f68
	if (strncmp(argv[0], "file", 4) == 0) {
Packit Service ed0f68
		if (argc < 2) {
Packit Service ed0f68
			ipmi_event_usage();
Packit Service ed0f68
			return 0;
Packit Service ed0f68
		}
Packit Service ed0f68
		return ipmi_event_fromfile(intf, argv[1]);
Packit Service ed0f68
	}
Packit Service ed0f68
	if (strlen(argv[0]) == 1) {
Packit Service ed0f68
		switch (argv[0][0]) {
Packit Service ed0f68
		case '1': return ipmi_send_platform_event_num(intf, 1);
Packit Service ed0f68
		case '2': return ipmi_send_platform_event_num(intf, 2);
Packit Service ed0f68
		case '3': return ipmi_send_platform_event_num(intf, 3);
Packit Service ed0f68
		}
Packit Service ed0f68
	}
Packit Service ed0f68
	if (argc < 2)
Packit Service ed0f68
		rc = ipmi_event_fromsensor(intf, argv[0], NULL, NULL);
Packit Service ed0f68
	else if (argc < 3)
Packit Service ed0f68
		rc = ipmi_event_fromsensor(intf, argv[0], argv[1], NULL);
Packit Service ed0f68
	else
Packit Service ed0f68
		rc = ipmi_event_fromsensor(intf, argv[0], argv[1], argv[2]);
Packit Service ed0f68
Packit Service ed0f68
	return rc;
Packit Service ed0f68
}