mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
event: Fix event submission via SSIF
IPMI 2.0 specification is quite inconsistent about system interfaces. They have section 1.7.16 "System Interfaces" that clearly states that there are FOUR system interfaces (KCS, SMIC, BT and SSIF), but then they have section 1.7.31 saying that "It is mandatory to implement a system interface that is compatible with one of the **three** specified system interfaces" without specifying which three of the four interfaces are meant. Then in section 6 "IPMI Messaging interfaces" they again say that "As mentioned earlier, there are three System Interface implementations specified for the BMC: SMIC, KCS, and BT". Is all looks like during update from 1.5 to 2.0 they have updated section 1.7.16, but forgot to update Table 6-3, section 1.7.31 and section 6. Yet again, there is 'Get System Interface Capabilities' command that has a parameter 'System Interface Type' that can specify that SI is of SSIF type. All that have lead to a situation where some BMC manufacturers treated the specification as if it prohibited specifying media type 0xC (which is "System Interface") for system interfaces using SSIF (SMBus Sustem Interface), and so they specified an SMBUS media type for their system interface channels. As a result, ipmitool failed to properly send event data via such system interfaces as it treated them as non-system and didn't add the required Generator ID. To mitigate the inconsistency of IPMI specification and yet not ask BMC manufacturers to alter their code, thus increasing compatibility with legacy BMCs, this commit adds checking of current interface number. The system interface, according to Table 6-1 of IPMI Specification is required to have channel number 15 (0Fh). So with this commit the generator ID is added for any interfaces that are either marked as media type 0Ch 'System Interface' or have channel number 0Fh. Resolves ipmitool/ipmitool#111 Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
This commit is contained in:
parent
002e1d95f5
commit
c396a310ba
@ -57,6 +57,28 @@
|
|||||||
#define IPMI_CHANNEL_SESSION_MULTI 0x80
|
#define IPMI_CHANNEL_SESSION_MULTI 0x80
|
||||||
#define IPMI_CHANNEL_SESSION_BASED 0xC0
|
#define IPMI_CHANNEL_SESSION_BASED 0xC0
|
||||||
|
|
||||||
|
/* Fixed channel numbers as per Table 6-1 */
|
||||||
|
typedef enum {
|
||||||
|
CH_PRIMARY_IPMB,
|
||||||
|
CH_IMP_SPECIFIC_1,
|
||||||
|
CH_IMP_SPECIFIC_2,
|
||||||
|
CH_IMP_SPECIFIC_3,
|
||||||
|
CH_IMP_SPECIFIC_4,
|
||||||
|
CH_IMP_SPECIFIC_5,
|
||||||
|
CH_IMP_SPECIFIC_6,
|
||||||
|
CH_IMP_SPECIFIC_7,
|
||||||
|
CH_IMP_SPECIFIC_8,
|
||||||
|
CH_IMP_SPECIFIC_9,
|
||||||
|
CH_IMP_SPECIFIC_A,
|
||||||
|
CH_IMP_SPECIFIC_B,
|
||||||
|
CH_RSVD1,
|
||||||
|
CH_RSVD2,
|
||||||
|
CH_CURRENT,
|
||||||
|
CH_SYSTEM,
|
||||||
|
CH_TOTAL,
|
||||||
|
CH_UNKNOWN = UINT8_MAX
|
||||||
|
} ipmi_channel_num_t;
|
||||||
|
|
||||||
/* (22.24) Get Channel Info */
|
/* (22.24) Get Channel Info */
|
||||||
struct channel_info_t {
|
struct channel_info_t {
|
||||||
uint8_t channel;
|
uint8_t channel;
|
||||||
@ -189,7 +211,8 @@ int _ipmi_set_channel_access(struct ipmi_intf *intf,
|
|||||||
uint8_t privilege_option);
|
uint8_t privilege_option);
|
||||||
|
|
||||||
uint8_t ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel);
|
uint8_t ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel);
|
||||||
uint8_t ipmi_current_channel_medium(struct ipmi_intf * intf);
|
void ipmi_current_channel_info(struct ipmi_intf *intf,
|
||||||
|
struct channel_info_t *chinfo);
|
||||||
int ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv);
|
int ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv);
|
||||||
int ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
|
int ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
|
||||||
uint8_t channel, uint8_t priv);
|
uint8_t channel, uint8_t priv);
|
||||||
|
@ -244,10 +244,28 @@ ipmi_1_5_authtypes(uint8_t n)
|
|||||||
return supportedTypes;
|
return supportedTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
void
|
||||||
ipmi_current_channel_medium(struct ipmi_intf *intf)
|
ipmi_current_channel_info(struct ipmi_intf *intf,
|
||||||
|
struct channel_info_t *chinfo)
|
||||||
{
|
{
|
||||||
return ipmi_get_channel_medium(intf, 0xE);
|
int ccode = 0;
|
||||||
|
|
||||||
|
chinfo->channel = CH_CURRENT;
|
||||||
|
ccode = _ipmi_get_channel_info(intf, chinfo);
|
||||||
|
if (ccode) {
|
||||||
|
if (ccode != IPMI_CC_INV_DATA_FIELD_IN_REQ) {
|
||||||
|
if (ccode > 0) {
|
||||||
|
lprintf(LOG_ERR, "Get Channel Info command failed: %s",
|
||||||
|
val2str(ccode, completion_code_vals));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
eval_ccode(ccode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chinfo->channel = CH_UNKNOWN;
|
||||||
|
chinfo->medium = IPMI_CHANNEL_MEDIUM_RESERVED;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -684,13 +702,16 @@ ipmi_get_channel_medium(struct ipmi_intf *intf, uint8_t channel)
|
|||||||
|
|
||||||
channel_info.channel = channel;
|
channel_info.channel = channel;
|
||||||
ccode = _ipmi_get_channel_info(intf, &channel_info);
|
ccode = _ipmi_get_channel_info(intf, &channel_info);
|
||||||
if (ccode == 0xCC) {
|
if (ccode) {
|
||||||
return IPMI_CHANNEL_MEDIUM_RESERVED;
|
if (ccode != IPMI_CC_INV_DATA_FIELD_IN_REQ) {
|
||||||
} else if (ccode < 0 && eval_ccode(ccode) != 0) {
|
if (ccode > 0) {
|
||||||
return 0;
|
lprintf(LOG_ERR, "Get Channel Info command failed: %s",
|
||||||
} else if (ccode) {
|
val2str(ccode, completion_code_vals));
|
||||||
lprintf(LOG_ERR, "Get Channel Info command failed: %s",
|
}
|
||||||
val2str(ccode, completion_code_vals));
|
else {
|
||||||
|
eval_ccode(ccode);
|
||||||
|
}
|
||||||
|
}
|
||||||
return IPMI_CHANNEL_MEDIUM_RESERVED;
|
return IPMI_CHANNEL_MEDIUM_RESERVED;
|
||||||
}
|
}
|
||||||
lprintf(LOG_DEBUG, "Channel type: %s",
|
lprintf(LOG_DEBUG, "Channel type: %s",
|
||||||
|
@ -52,6 +52,14 @@
|
|||||||
#include <ipmitool/ipmi_event.h>
|
#include <ipmitool/ipmi_event.h>
|
||||||
#include <ipmitool/ipmi_sdr.h>
|
#include <ipmitool/ipmi_sdr.h>
|
||||||
|
|
||||||
|
static
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
is_system(const struct channel_info_t *chinfo)
|
||||||
|
{
|
||||||
|
return (IPMI_CHANNEL_MEDIUM_SYSTEM == chinfo.medium
|
||||||
|
|| CH_SYSTEM == chinfo.channel);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
|
ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
|
||||||
@ -84,7 +92,7 @@ ipmi_send_platform_event(struct ipmi_intf * intf, struct platform_event_msg * em
|
|||||||
struct ipmi_rs * rsp;
|
struct ipmi_rs * rsp;
|
||||||
struct ipmi_rq req;
|
struct ipmi_rq req;
|
||||||
uint8_t rqdata[8];
|
uint8_t rqdata[8];
|
||||||
uint8_t chmed;
|
struct channel_info_t chinfo;
|
||||||
|
|
||||||
memset(&req, 0, sizeof(req));
|
memset(&req, 0, sizeof(req));
|
||||||
memset(rqdata, 0, 8);
|
memset(rqdata, 0, 8);
|
||||||
@ -93,8 +101,14 @@ ipmi_send_platform_event(struct ipmi_intf * intf, struct platform_event_msg * em
|
|||||||
req.msg.cmd = 0x02;
|
req.msg.cmd = 0x02;
|
||||||
req.msg.data = rqdata;
|
req.msg.data = rqdata;
|
||||||
|
|
||||||
chmed = ipmi_current_channel_medium(intf);
|
ipmi_current_channel_info(intf, &chinfo);
|
||||||
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
|
if (chinfo.channel == CH_UNKNOWN) {
|
||||||
|
lprintf(LOG_ERR, "Failed to send the platform event "
|
||||||
|
"via an unknown channel");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_system(&chinfo)) {
|
||||||
/* system interface, need extra generator ID */
|
/* system interface, need extra generator ID */
|
||||||
req.msg.data_len = 8;
|
req.msg.data_len = 8;
|
||||||
rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
|
rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
|
||||||
@ -491,7 +505,7 @@ ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
|
|||||||
char buf[1024];
|
char buf[1024];
|
||||||
char * ptr, * tok;
|
char * ptr, * tok;
|
||||||
int i, j;
|
int i, j;
|
||||||
uint8_t chmed;
|
struct channel_info_t chinfo;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
@ -506,8 +520,14 @@ ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
|
|||||||
req.msg.data = rqdata;
|
req.msg.data = rqdata;
|
||||||
req.msg.data_len = 7;
|
req.msg.data_len = 7;
|
||||||
|
|
||||||
chmed = ipmi_current_channel_medium(intf);
|
ipmi_current_channel_info(intf, &chinfo);
|
||||||
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
|
if (chinfo.channel == CH_UNKNOWN) {
|
||||||
|
lprintf(LOG_ERR, "Failed to send the event from file "
|
||||||
|
"via an unknown channel");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_system(&chinfo)) {
|
||||||
/* system interface, need extra generator ID */
|
/* system interface, need extra generator ID */
|
||||||
rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
|
rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
|
||||||
req.msg.data_len = 8;
|
req.msg.data_len = 8;
|
||||||
@ -546,8 +566,9 @@ ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
|
|||||||
if (i == 7)
|
if (i == 7)
|
||||||
break;
|
break;
|
||||||
j = i++;
|
j = i++;
|
||||||
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM)
|
if (is_system(&chinfo)) {
|
||||||
j++;
|
j++;
|
||||||
|
}
|
||||||
rqdata[j] = (uint8_t)strtol(tok, NULL, 0);
|
rqdata[j] = (uint8_t)strtol(tok, NULL, 0);
|
||||||
tok = strtok(NULL, " ");
|
tok = strtok(NULL, " ");
|
||||||
}
|
}
|
||||||
@ -561,7 +582,7 @@ ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
|
|||||||
sel_event.record_id = 0;
|
sel_event.record_id = 0;
|
||||||
sel_event.sel_type.standard_type.gen_id = 2;
|
sel_event.sel_type.standard_type.gen_id = 2;
|
||||||
|
|
||||||
j = (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) ? 1 : 0;
|
j = (int)is_system(&chinfo);
|
||||||
sel_event.sel_type.standard_type.evm_rev = rqdata[j++];
|
sel_event.sel_type.standard_type.evm_rev = rqdata[j++];
|
||||||
sel_event.sel_type.standard_type.sensor_type = rqdata[j++];
|
sel_event.sel_type.standard_type.sensor_type = rqdata[j++];
|
||||||
sel_event.sel_type.standard_type.sensor_num = rqdata[j++];
|
sel_event.sel_type.standard_type.sensor_num = rqdata[j++];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user