diff --git a/ipmitool/lib/ipmi_event.c b/ipmitool/lib/ipmi_event.c index 68d87ca..55860e5 100644 --- a/ipmitool/lib/ipmi_event.c +++ b/ipmitool/lib/ipmi_event.c @@ -37,11 +37,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -49,6 +49,42 @@ #include #include #include +#include +#include + +static int +ipmi_current_channel_medium(struct ipmi_intf * intf) +{ + struct ipmi_rs * rsp; + struct ipmi_rq req; + unsigned char channel = 0xE; + struct get_channel_info_rsp info; + + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_APP; + req.msg.cmd = IPMI_GET_CHANNEL_INFO; + req.msg.data = &channel; + req.msg.data_len = 1; + + rsp = intf->sendrecv(intf, &req); + if (!rsp) { + printf("Error in Get Channel Info command\n"); + return -1; + } + else if (rsp->ccode) { + printf("Error in Get Channel Info command: %s\n", + val2str(rsp->ccode, completion_code_vals)); + return -1; + } + + memcpy(&info, rsp->data, sizeof(struct get_channel_info_rsp)); + + if (verbose) + printf("Channel type: %s\n", + val2str(info.channel_medium, ipmi_channel_medium_vals)); + + return info.channel_medium; +} static int ipmi_send_platform_event(struct ipmi_intf * intf, int num) @@ -56,45 +92,58 @@ ipmi_send_platform_event(struct ipmi_intf * intf, int num) struct ipmi_rs * rsp; struct ipmi_rq req; unsigned char rqdata[8]; + int chmed; + int p = 0; ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN); memset(&req, 0, sizeof(req)); memset(rqdata, 0, 8); - printf("Sending "); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = 0x02; + req.msg.data = rqdata; + req.msg.data_len = 7; + chmed = ipmi_current_channel_medium(intf); + if (chmed == 0xc) { + /* system interface, need extra generator ID */ + req.msg.data_len = 8; + rqdata[p++] = 0x20; + } + + printf("Sending "); /* IPMB/LAN/etc */ switch (num) { case 1: /* temperature */ printf("Temperature - Upper Critical - Going High"); - rqdata[0] = 0x04; /* EvMRev */ - rqdata[1] = 0x01; /* Sensor Type */ - rqdata[2] = 0x30; /* Sensor # */ - rqdata[3] = 0x01; /* Event Dir / Event Type */ - rqdata[4] = 0x59; /* Event Data 1 */ - rqdata[5] = 0x00; /* Event Data 2 */ - rqdata[6] = 0x00; /* Event Data 3 */ + rqdata[p++] = 0x04; /* EvMRev */ + rqdata[p++] = 0x01; /* Sensor Type */ + rqdata[p++] = 0x30; /* Sensor # */ + rqdata[p++] = 0x01; /* Event Dir / Event Type */ + rqdata[p++] = 0x59; /* Event Data 1 */ + rqdata[p++] = 0x00; /* Event Data 2 */ + rqdata[p++] = 0x00; /* Event Data 3 */ break; case 2: /* voltage error */ printf("Voltage Threshold - Lower Critical - Going Low"); - rqdata[0] = 0x04; /* EvMRev */ - rqdata[1] = 0x02; /* Sensor Type */ - rqdata[2] = 0x60; /* Sensor # */ - rqdata[3] = 0x01; /* Event Dir / Event Type */ - rqdata[4] = 0x52; /* Event Data 1 */ - rqdata[5] = 0x00; /* Event Data 2 */ - rqdata[6] = 0x00; /* Event Data 3 */ + rqdata[p++] = 0x04; /* EvMRev */ + rqdata[p++] = 0x02; /* Sensor Type */ + rqdata[p++] = 0x60; /* Sensor # */ + rqdata[p++] = 0x01; /* Event Dir / Event Type */ + rqdata[p++] = 0x52; /* Event Data 1 */ + rqdata[p++] = 0x00; /* Event Data 2 */ + rqdata[p++] = 0x00; /* Event Data 3 */ break; case 3: /* correctable ECC */ printf("Memory - Correctable ECC"); - rqdata[0] = 0x04; /* EvMRev */ - rqdata[1] = 0x0c; /* Sensor Type */ - rqdata[2] = 0x01; /* Sensor # */ - rqdata[3] = 0x6f; /* Event Dir / Event Type */ - rqdata[4] = 0x00; /* Event Data 1 */ - rqdata[5] = 0x00; /* Event Data 2 */ - rqdata[6] = 0x00; /* Event Data 3 */ + rqdata[p++] = 0x04; /* EvMRev */ + rqdata[p++] = 0x0c; /* Sensor Type */ + rqdata[p++] = 0x53; /* Sensor # */ + rqdata[p++] = 0x6f; /* Event Dir / Event Type */ + rqdata[p++] = 0x00; /* Event Data 1 */ + rqdata[p++] = 0x00; /* Event Data 2 */ + rqdata[p++] = 0x00; /* Event Data 3 */ break; default: printf("Invalid event number: %d\n", num); @@ -103,12 +152,6 @@ ipmi_send_platform_event(struct ipmi_intf * intf, int num) printf(" event to BMC\n"); - req.msg.netfn = IPMI_NETFN_SE; - req.msg.cmd = 0x02; - req.msg.data = rqdata; - req.msg.data_len = 7; - - rsp = intf->sendrecv(intf, &req); if (!rsp || rsp->ccode) { printf("Error:%x Platform Event Message Command\n", rsp?rsp->ccode:0); @@ -118,6 +161,111 @@ ipmi_send_platform_event(struct ipmi_intf * intf, int num) return 0; } +static void +ipmi_event_fromfile(struct ipmi_intf * intf, char * file) +{ + FILE * fp; + struct ipmi_rs * rsp; + struct ipmi_rq req; + struct sel_event_record sel_event; + unsigned char rqdata[8]; + char buf[1024]; + char * ptr, * tok; + int i, j, chmed; + + if (!file) + return; + + /* must be admin privilege to do this */ + ipmi_intf_session_set_privlvl(intf, IPMI_SESSION_PRIV_ADMIN); + + memset(rqdata, 0, 8); + + /* setup Platform Event Message command */ + memset(&req, 0, sizeof(req)); + req.msg.netfn = IPMI_NETFN_SE; + req.msg.cmd = 0x02; + req.msg.data = rqdata; + req.msg.data_len = 7; + + chmed = ipmi_current_channel_medium(intf); + if (chmed == 0xc) { + /* system interface, need extra generator ID */ + rqdata[0] = 0x20; + req.msg.data_len = 8; + } + + fp = ipmi_open_file_read(file); + if (!fp) + return; + + while (!feof(fp)) { + if (!fgets(buf, 1024, fp)) + continue; + + /* clip off optional comment tail indicated by # */ + ptr = strchr(buf, '#'); + if (ptr) + *ptr = '\0'; + else + ptr = buf + strlen(buf); + + /* clip off trailing and leading whitespace */ + ptr--; + while (isspace(*ptr) && ptr >= buf) + *ptr-- = '\0'; + ptr = buf; + while (isspace(*ptr)) + ptr++; + if (!strlen(ptr)) + continue; + + /* parse the event, 7 bytes with optional comment */ + /* 0x00 0x00 0x00 0x00 0x00 0x00 0x00 # event */ + i = 0; + tok = strtok(ptr, " "); + while (tok) { + if (i == 7) + break; + j = i++; + if (chmed == 0xc) + j++; + rqdata[j] = (unsigned char)strtol(tok, NULL, 0); + tok = strtok(NULL, " "); + } + if (i < sizeof(rqdata)) { + printf("Invalid Event: %s\n", + buf2str(rqdata, sizeof(rqdata))); + continue; + } + + memset(&sel_event, 0, sizeof(struct sel_event_record)); + sel_event.record_id = 0; + sel_event.gen_id = 2; + + j = (chmed == 0xc) ? 1 : 0; + sel_event.evm_rev = rqdata[j++]; + sel_event.sensor_type = rqdata[j++]; + sel_event.sensor_num = rqdata[j++]; + sel_event.event_type = rqdata[j] & 0x7f; + sel_event.event_dir = (rqdata[j++] & 0x80) >> 7; + sel_event.event_data[0] = rqdata[j++]; + sel_event.event_data[1] = rqdata[j++]; + sel_event.event_data[2] = rqdata[j++]; + + ipmi_sel_print_std_entry(&sel_event); + + rsp = intf->sendrecv(intf, &req); + if (!rsp) + printf("Error in Platform Event Message Command\n"); + else if (rsp->ccode) + printf("Error in Platform Event Message Command: %s\n", + val2str(rsp->ccode, completion_code_vals)); + } + + fclose(fp); +} + int ipmi_event_main(struct ipmi_intf * intf, int argc, char ** argv) { unsigned char c; @@ -127,6 +275,16 @@ int ipmi_event_main(struct ipmi_intf * intf, int argc, char ** argv) printf(" 1 : Temperature - Upper Critical - Going High\n"); printf(" 2 : Voltage Threshold - Lower Critical - Going Low\n"); printf(" 3 : Memory - Correctable ECC\n"); + printf("usage: event file \n"); + printf(" Will read list of events from file\n"); + return 0; + } + + if (!strncmp(argv[0], "file", 4)) { + if (argc < 2) + printf("usage: event file \n"); + else + ipmi_event_fromfile(intf, argv[1]); } else { c = (unsigned char)strtol(argv[0], NULL, 0); ipmi_send_platform_event(intf, c);