ipmi_event.c 18 KB

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