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