1 /*
2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistribution of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistribution in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * Neither the name of Sun Microsystems, Inc. or the names of
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * This software is provided "AS IS," without a warranty of any kind.
20 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
26 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 */
32 #define _BSD_SOURCE
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #include <signal.h>
44 #include <ctype.h>
45
46 #include <ipmitool/ipmi.h>
47 #include <ipmitool/ipmi_intf.h>
48 #include <ipmitool/helper.h>
49 #include <ipmitool/log.h>
50 #include <ipmitool/ipmi_sel.h>
51 #include <ipmitool/ipmi_strings.h>
52 #include <ipmitool/ipmi_channel.h>
53 #include <ipmitool/ipmi_event.h>
54 #include <ipmitool/ipmi_sdr.h>
55
56
57 static void
ipmi_event_msg_print(struct ipmi_intf * intf,struct platform_event_msg * pmsg)58 ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
59 {
60 struct sel_event_record sel_event;
61
62 memset(&sel_event, 0, sizeof(struct sel_event_record));
63
64 sel_event.record_id = 0;
65 sel_event.sel_type.standard_type.gen_id = 2;
66
67 sel_event.sel_type.standard_type.evm_rev = pmsg->evm_rev;
68 sel_event.sel_type.standard_type.sensor_type = pmsg->sensor_type;
69 sel_event.sel_type.standard_type.sensor_num = pmsg->sensor_num;
70 sel_event.sel_type.standard_type.event_type = pmsg->event_type;
71 sel_event.sel_type.standard_type.event_dir = pmsg->event_dir;
72 sel_event.sel_type.standard_type.event_data[0] = pmsg->event_data[0];
73 sel_event.sel_type.standard_type.event_data[1] = pmsg->event_data[1];
74 sel_event.sel_type.standard_type.event_data[2] = pmsg->event_data[2];
75
76 if (verbose)
77 ipmi_sel_print_extended_entry_verbose(intf, &sel_event);
78 else
79 ipmi_sel_print_extended_entry(intf, &sel_event);
80 }
81
82 static int
ipmi_send_platform_event(struct ipmi_intf * intf,struct platform_event_msg * emsg)83 ipmi_send_platform_event(struct ipmi_intf * intf, struct platform_event_msg * emsg)
84 {
85 struct ipmi_rs * rsp;
86 struct ipmi_rq req;
87 uint8_t rqdata[8];
88 uint8_t chmed;
89
90 memset(&req, 0, sizeof(req));
91 memset(rqdata, 0, 8);
92
93 req.msg.netfn = IPMI_NETFN_SE;
94 req.msg.cmd = 0x02;
95 req.msg.data = rqdata;
96
97 chmed = ipmi_current_channel_medium(intf);
98 if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
99 /* system interface, need extra generator ID */
100 req.msg.data_len = 8;
101 rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
102 memcpy(rqdata+1, emsg, sizeof(struct platform_event_msg));
103 }
104 else {
105 req.msg.data_len = 7;
106 memcpy(rqdata, emsg, sizeof(struct platform_event_msg));
107 }
108
109 ipmi_event_msg_print(intf, emsg);
110
111 rsp = intf->sendrecv(intf, &req);
112 if (rsp == NULL) {
113 lprintf(LOG_ERR, "Platform Event Message command failed");
114 return -1;
115 }
116 else if (rsp->ccode > 0) {
117 lprintf(LOG_ERR, "Platform Event Message command failed: %s",
118 val2str(rsp->ccode, completion_code_vals));
119 return -1;
120 }
121
122 return 0;
123 }
124
125 #define EVENT_THRESH_STATE_LNC_LO 0
126 #define EVENT_THRESH_STATE_LNC_HI 1
127 #define EVENT_THRESH_STATE_LCR_LO 2
128 #define EVENT_THRESH_STATE_LCR_HI 3
129 #define EVENT_THRESH_STATE_LNR_LO 4
130 #define EVENT_THRESH_STATE_LNR_HI 5
131 #define EVENT_THRESH_STATE_UNC_LO 6
132 #define EVENT_THRESH_STATE_UNC_HI 7
133 #define EVENT_THRESH_STATE_UCR_LO 8
134 #define EVENT_THRESH_STATE_UCR_HI 9
135 #define EVENT_THRESH_STATE_UNR_LO 10
136 #define EVENT_THRESH_STATE_UNR_HI 11
137
138 static const struct valstr ipmi_event_thresh_lo[] = {
139 { EVENT_THRESH_STATE_LNC_LO, "lnc" },
140 { EVENT_THRESH_STATE_LCR_LO, "lcr" },
141 { EVENT_THRESH_STATE_LNR_LO, "lnr" },
142 { EVENT_THRESH_STATE_UNC_LO, "unc" },
143 { EVENT_THRESH_STATE_UCR_LO, "ucr" },
144 { EVENT_THRESH_STATE_UNR_LO, "unr" },
145 { 0, NULL },
146 };
147 static const struct valstr ipmi_event_thresh_hi[] = {
148 { EVENT_THRESH_STATE_LNC_HI, "lnc" },
149 { EVENT_THRESH_STATE_LCR_HI, "lcr" },
150 { EVENT_THRESH_STATE_LNR_HI, "lnr" },
151 { EVENT_THRESH_STATE_UNC_HI, "unc" },
152 { EVENT_THRESH_STATE_UCR_HI, "ucr" },
153 { EVENT_THRESH_STATE_UNR_HI, "unr" },
154 { 0, NULL },
155 };
156
157 static int
ipmi_send_platform_event_num(struct ipmi_intf * intf,int num)158 ipmi_send_platform_event_num(struct ipmi_intf * intf, int num)
159 {
160 struct platform_event_msg emsg;
161
162 memset(&emsg, 0, sizeof(struct platform_event_msg));
163
164 /* IPMB/LAN/etc */
165 switch (num) {
166 case 1: /* temperature */
167 printf("Sending SAMPLE event: Temperature - "
168 "Upper Critical - Going High\n");
169 emsg.evm_rev = 0x04;
170 emsg.sensor_type = 0x01;
171 emsg.sensor_num = 0x30;
172 emsg.event_dir = EVENT_DIR_ASSERT;
173 emsg.event_type = 0x01;
174 emsg.event_data[0] = EVENT_THRESH_STATE_UCR_HI;
175 emsg.event_data[1] = 0xff;
176 emsg.event_data[2] = 0xff;
177 break;
178 case 2: /* voltage error */
179 printf("Sending SAMPLE event: Voltage Threshold - "
180 "Lower Critical - Going Low\n");
181 emsg.evm_rev = 0x04;
182 emsg.sensor_type = 0x02;
183 emsg.sensor_num = 0x60;
184 emsg.event_dir = EVENT_DIR_ASSERT;
185 emsg.event_type = 0x01;
186 emsg.event_data[0] = EVENT_THRESH_STATE_LCR_LO;
187 emsg.event_data[1] = 0xff;
188 emsg.event_data[2] = 0xff;
189 break;
190 case 3: /* correctable ECC */
191 printf("Sending SAMPLE event: Memory - Correctable ECC\n");
192 emsg.evm_rev = 0x04;
193 emsg.sensor_type = 0x0c;
194 emsg.sensor_num = 0x53;
195 emsg.event_dir = EVENT_DIR_ASSERT;
196 emsg.event_type = 0x6f;
197 emsg.event_data[0] = 0x00;
198 emsg.event_data[1] = 0xff;
199 emsg.event_data[2] = 0xff;
200 break;
201 default:
202 lprintf(LOG_ERR, "Invalid event number: %d", num);
203 return -1;
204 }
205
206 return ipmi_send_platform_event(intf, &emsg);
207 }
208
209 static int
ipmi_event_find_offset(struct ipmi_intf * intf,uint8_t sensor_type,uint8_t event_type,char * desc)210 ipmi_event_find_offset(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type, char *desc)
211 {
212 const struct ipmi_event_sensor_types *evt;
213
214 if (desc == NULL || sensor_type == 0 || event_type == 0) {
215 return 0x00;
216 }
217
218 for (evt = ipmi_get_first_event_sensor_type(intf, sensor_type, event_type);
219 evt != NULL; evt = ipmi_get_next_event_sensor_type(evt)) {
220 if (evt->desc != NULL &&
221 strncasecmp(desc, evt->desc, __maxlen(desc, evt->desc)) == 0) {
222 return evt->offset;
223 }
224 }
225
226 lprintf(LOG_WARN, "Unable to find matching event offset for '%s'", desc);
227 return -1;
228 }
229
230 static void
print_sensor_states(struct ipmi_intf * intf,uint8_t sensor_type,uint8_t event_type)231 print_sensor_states(struct ipmi_intf *intf, uint8_t sensor_type, uint8_t event_type)
232 {
233 ipmi_sdr_print_discrete_state_mini(intf,
234 "Sensor States: \n ", "\n ", sensor_type,
235 event_type, 0xff, 0xff);
236 printf("\n");
237 }
238
239
240 static int
ipmi_event_fromsensor(struct ipmi_intf * intf,char * id,char * state,char * evdir)241 ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * evdir)
242 {
243 struct ipmi_rs * rsp;
244 struct sdr_record_list * sdr;
245 struct platform_event_msg emsg;
246 int off;
247 uint8_t target, lun, channel;
248
249 if (id == NULL) {
250 lprintf(LOG_ERR, "No sensor ID supplied");
251 return -1;
252 }
253
254 memset(&emsg, 0, sizeof(struct platform_event_msg));
255 emsg.evm_rev = 0x04;
256
257 if (evdir == NULL)
258 emsg.event_dir = EVENT_DIR_ASSERT;
259 else if (strncasecmp(evdir, "assert", 6) == 0)
260 emsg.event_dir = EVENT_DIR_ASSERT;
261 else if (strncasecmp(evdir, "deassert", 8) == 0)
262 emsg.event_dir = EVENT_DIR_DEASSERT;
263 else {
264 lprintf(LOG_ERR, "Invalid event direction %s. Must be 'assert' or 'deassert'", evdir);
265 return -1;
266 }
267
268 printf("Finding sensor %s... ", id);
269 sdr = ipmi_sdr_find_sdr_byid(intf, id);
270 if (sdr == NULL) {
271 printf("not found!\n");
272 return -1;
273 }
274 printf("ok\n");
275
276 switch (sdr->type)
277 {
278 case SDR_RECORD_TYPE_FULL_SENSOR:
279 case SDR_RECORD_TYPE_COMPACT_SENSOR:
280
281 emsg.sensor_type = sdr->record.common->sensor.type;
282 emsg.sensor_num = sdr->record.common->keys.sensor_num;
283 emsg.event_type = sdr->record.common->event_type;
284 target = sdr->record.common->keys.owner_id;
285 lun = sdr->record.common->keys.lun;
286 channel = sdr->record.common->keys.channel;
287 break;
288 default:
289 lprintf(LOG_ERR, "Unknown sensor type for id '%s'", id);
290 return -1;
291 }
292
293 emsg.event_data[1] = 0xff;
294 emsg.event_data[2] = 0xff;
295
296 switch (emsg.event_type)
297 {
298 /*
299 * Threshold Class
300 */
301 case 1:
302 {
303 int dir = 0;
304 int hilo = 0;
305 off = 1;
306
307 if (state == NULL || strncasecmp(state, "list", 4) == 0) {
308 printf("Sensor States:\n");
309 printf(" lnr : Lower Non-Recoverable \n");
310 printf(" lcr : Lower Critical\n");
311 printf(" lnc : Lower Non-Critical\n");
312 printf(" unc : Upper Non-Critical\n");
313 printf(" ucr : Upper Critical\n");
314 printf(" unr : Upper Non-Recoverable\n");
315 return -1;
316 }
317
318 if (0 != strncasecmp(state, "lnr", 3) &&
319 0 != strncasecmp(state, "lcr", 3) &&
320 0 != strncasecmp(state, "lnc", 3) &&
321 0 != strncasecmp(state, "unc", 3) &&
322 0 != strncasecmp(state, "ucr", 3) &&
323 0 != strncasecmp(state, "unr", 3))
324 {
325 lprintf(LOG_ERR, "Invalid threshold identifier %s", state);
326 return -1;
327 }
328
329 if (state[0] == 'u')
330 hilo = 1;
331 else
332 hilo = 0;
333
334 if (emsg.event_dir == EVENT_DIR_ASSERT)
335 dir = hilo;
336 else
337 dir = !hilo;
338
339 if ((emsg.event_dir == EVENT_DIR_ASSERT && hilo == 1) ||
340 (emsg.event_dir == EVENT_DIR_DEASSERT && hilo == 0))
341 emsg.event_data[0] = (uint8_t)(str2val(state, ipmi_event_thresh_hi) & 0xf);
342 else if ((emsg.event_dir == EVENT_DIR_ASSERT && hilo == 0) ||
343 (emsg.event_dir == EVENT_DIR_DEASSERT && hilo == 1))
344 emsg.event_data[0] = (uint8_t)(str2val(state, ipmi_event_thresh_lo) & 0xf);
345 else {
346 lprintf(LOG_ERR, "Invalid Event");
347 return -1;
348 }
349
350 rsp = ipmi_sdr_get_sensor_thresholds(intf, emsg.sensor_num,
351 target, lun, channel);
352 if (rsp == NULL) {
353 lprintf(LOG_ERR,
354 "Command Get Sensor Thresholds failed: invalid response.");
355 return (-1);
356 } else if (rsp->ccode != 0) {
357 lprintf(LOG_ERR, "Command Get Sensor Thresholds failed: %s",
358 val2str(rsp->ccode, completion_code_vals));
359 return (-1);
360 }
361
362 /* threshold reading */
363 emsg.event_data[2] = rsp->data[(emsg.event_data[0] / 2) + 1];
364
365 rsp = ipmi_sdr_get_sensor_hysteresis(intf, emsg.sensor_num,
366 target, lun, channel);
367 if (rsp != NULL && rsp->ccode == 0)
368 off = dir ? rsp->data[0] : rsp->data[1];
369 if (off <= 0)
370 off = 1;
371
372 /* trigger reading */
373 if (dir) {
374 if ((emsg.event_data[2] + off) > 0xff)
375 emsg.event_data[1] = 0xff;
376 else
377 emsg.event_data[1] = emsg.event_data[2] + off;
378 }
379 else {
380 if ((emsg.event_data[2] - off) < 0)
381 emsg.event_data[1] = 0;
382 else
383 emsg.event_data[1] = emsg.event_data[2] - off;
384 }
385
386 /* trigger in byte 2, threshold in byte 3 */
387 emsg.event_data[0] |= 0x50;
388 }
389 break;
390
391 /*
392 * Digital Discrete
393 */
394 case 3: case 4: case 5: case 6: case 8: case 9:
395 {
396 int x;
397 const char * digi_on[] = { "present", "assert", "limit",
398 "fail", "yes", "on", "up" };
399 const char * digi_off[] = { "absent", "deassert", "nolimit",
400 "nofail", "no", "off", "down" };
401 /*
402 * print list of available states for this sensor
403 */
404 if (state == NULL || strncasecmp(state, "list", 4) == 0) {
405 print_sensor_states(intf, emsg.sensor_type, emsg.event_type);
406 printf("Sensor State Shortcuts:\n");
407 for (x = 0; x < sizeof(digi_on)/sizeof(*digi_on); x++) {
408 printf(" %-9s %-9s\n", digi_on[x], digi_off[x]);
409 }
410 return 0;
411 }
412
413 off = 0;
414 for (x = 0; x < sizeof(digi_on)/sizeof(*digi_on); x++) {
415 if (strncasecmp(state, digi_on[x], strlen(digi_on[x])) == 0) {
416 emsg.event_data[0] = 1;
417 off = 1;
418 break;
419 }
420 else if (strncasecmp(state, digi_off[x], strlen(digi_off[x])) == 0) {
421 emsg.event_data[0] = 0;
422 off = 1;
423 break;
424 }
425 }
426 if (off == 0) {
427 off = ipmi_event_find_offset(intf,
428 emsg.sensor_type, emsg.event_type, state);
429 if (off < 0)
430 return -1;
431 emsg.event_data[0] = off;
432 }
433 }
434 break;
435
436 /*
437 * Generic Discrete
438 */
439 case 2: case 7: case 10: case 11: case 12:
440 {
441 /*
442 * print list of available states for this sensor
443 */
444 if (state == NULL || strncasecmp(state, "list", 4) == 0) {
445 print_sensor_states(intf, emsg.sensor_type, emsg.event_type);
446 return 0;
447 }
448 off = ipmi_event_find_offset(intf,
449 emsg.sensor_type, emsg.event_type, state);
450 if (off < 0)
451 return -1;
452 emsg.event_data[0] = off;
453 }
454 break;
455
456 /*
457 * Sensor-Specific Discrete
458 */
459 case 0x6f:
460 {
461 /*
462 * print list of available states for this sensor
463 */
464 if (state == NULL || strncasecmp(state, "list", 4) == 0) {
465 print_sensor_states(intf, emsg.sensor_type, emsg.event_type);
466 return 0;
467 }
468 off = ipmi_event_find_offset(intf,
469 emsg.sensor_type, emsg.event_type, state);
470 if (off < 0)
471 return -1;
472 emsg.event_data[0] = off;
473 }
474 break;
475
476 default:
477 return -1;
478
479 }
480
481 return ipmi_send_platform_event(intf, &emsg);
482 }
483
484 static int
ipmi_event_fromfile(struct ipmi_intf * intf,char * file)485 ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
486 {
487 FILE * fp;
488 struct ipmi_rs * rsp;
489 struct ipmi_rq req;
490 struct sel_event_record sel_event;
491 uint8_t rqdata[8];
492 char buf[1024];
493 char * ptr, * tok;
494 int i, j;
495 uint8_t chmed;
496 int rc = 0;
497
498 if (file == NULL)
499 return -1;
500
501 memset(rqdata, 0, 8);
502
503 /* setup Platform Event Message command */
504 memset(&req, 0, sizeof(req));
505 req.msg.netfn = IPMI_NETFN_SE;
506 req.msg.cmd = 0x02;
507 req.msg.data = rqdata;
508 req.msg.data_len = 7;
509
510 chmed = ipmi_current_channel_medium(intf);
511 if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
512 /* system interface, need extra generator ID */
513 rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
514 req.msg.data_len = 8;
515 }
516
517 fp = ipmi_open_file_read(file);
518 if (fp == NULL)
519 return -1;
520
521 while (feof(fp) == 0) {
522 if (fgets(buf, 1024, fp) == NULL)
523 continue;
524
525 /* clip off optional comment tail indicated by # */
526 ptr = strchr(buf, '#');
527 if (ptr)
528 *ptr = '\0';
529 else
530 ptr = buf + strlen(buf);
531
532 /* clip off trailing and leading whitespace */
533 ptr--;
534 while (isspace((int)*ptr) && ptr >= buf)
535 *ptr-- = '\0';
536 ptr = buf;
537 while (isspace((int)*ptr))
538 ptr++;
539 if (strlen(ptr) == 0)
540 continue;
541
542 /* parse the event, 7 bytes with optional comment */
543 /* 0x00 0x00 0x00 0x00 0x00 0x00 0x00 # event */
544 i = 0;
545 tok = strtok(ptr, " ");
546 while (tok) {
547 if (i == 7)
548 break;
549 j = i++;
550 if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM)
551 j++;
552 rqdata[j] = (uint8_t)strtol(tok, NULL, 0);
553 tok = strtok(NULL, " ");
554 }
555 if (i < 7) {
556 lprintf(LOG_ERR, "Invalid Event: %s",
557 buf2str(rqdata, sizeof(rqdata)));
558 continue;
559 }
560
561 memset(&sel_event, 0, sizeof(struct sel_event_record));
562 sel_event.record_id = 0;
563 sel_event.sel_type.standard_type.gen_id = 2;
564
565 j = (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) ? 1 : 0;
566 sel_event.sel_type.standard_type.evm_rev = rqdata[j++];
567 sel_event.sel_type.standard_type.sensor_type = rqdata[j++];
568 sel_event.sel_type.standard_type.sensor_num = rqdata[j++];
569 sel_event.sel_type.standard_type.event_type = rqdata[j] & 0x7f;
570 sel_event.sel_type.standard_type.event_dir = (rqdata[j++] & 0x80) >> 7;
571 sel_event.sel_type.standard_type.event_data[0] = rqdata[j++];
572 sel_event.sel_type.standard_type.event_data[1] = rqdata[j++];
573 sel_event.sel_type.standard_type.event_data[2] = rqdata[j++];
574
575 ipmi_sel_print_std_entry(intf, &sel_event);
576
577 rsp = intf->sendrecv(intf, &req);
578 if (rsp == NULL) {
579 lprintf(LOG_ERR, "Platform Event Message command failed");
580 rc = -1;
581 }
582 else if (rsp->ccode > 0) {
583 lprintf(LOG_ERR, "Platform Event Message command failed: %s",
584 val2str(rsp->ccode, completion_code_vals));
585 rc = -1;
586 }
587 }
588
589 fclose(fp);
590 return rc;
591 }
592
593 static void
ipmi_event_usage(void)594 ipmi_event_usage(void)
595 {
596 lprintf(LOG_NOTICE, "");
597 lprintf(LOG_NOTICE, "usage: event <num>");
598 lprintf(LOG_NOTICE, " Send generic test events");
599 lprintf(LOG_NOTICE, " 1 : Temperature - Upper Critical - Going High");
600 lprintf(LOG_NOTICE, " 2 : Voltage Threshold - Lower Critical - Going Low");
601 lprintf(LOG_NOTICE, " 3 : Memory - Correctable ECC");
602 lprintf(LOG_NOTICE, "");
603 lprintf(LOG_NOTICE, "usage: event file <filename>");
604 lprintf(LOG_NOTICE, " Read and generate events from file");
605 lprintf(LOG_NOTICE, " Use the 'sel save' command to generate from SEL");
606 lprintf(LOG_NOTICE, "");
607 lprintf(LOG_NOTICE, "usage: event <sensorid> <state> [event_dir]");
608 lprintf(LOG_NOTICE, " sensorid : Sensor ID string to use for event data");
609 lprintf(LOG_NOTICE, " state : Sensor state, use 'list' to see possible states for sensor");
610 lprintf(LOG_NOTICE, " event_dir : assert, deassert [default=assert]");
611 lprintf(LOG_NOTICE, "");
612 }
613
614 int
ipmi_event_main(struct ipmi_intf * intf,int argc,char ** argv)615 ipmi_event_main(struct ipmi_intf * intf, int argc, char ** argv)
616 {
617 int rc = 0;
618
619 if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
620 ipmi_event_usage();
621 return 0;
622 }
623 if (strncmp(argv[0], "file", 4) == 0) {
624 if (argc < 2) {
625 ipmi_event_usage();
626 return 0;
627 }
628 return ipmi_event_fromfile(intf, argv[1]);
629 }
630 if (strlen(argv[0]) == 1) {
631 switch (argv[0][0]) {
632 case '1': return ipmi_send_platform_event_num(intf, 1);
633 case '2': return ipmi_send_platform_event_num(intf, 2);
634 case '3': return ipmi_send_platform_event_num(intf, 3);
635 }
636 }
637 if (argc < 2)
638 rc = ipmi_event_fromsensor(intf, argv[0], NULL, NULL);
639 else if (argc < 3)
640 rc = ipmi_event_fromsensor(intf, argv[0], argv[1], NULL);
641 else
642 rc = ipmi_event_fromsensor(intf, argv[0], argv[1], argv[2]);
643
644 return rc;
645 }
646