#define IPMI_CMD_GET_MSG 0x33
#define IPMI_CMD_SEND_MSG 0x34
#define IPMI_CMD_READ_EVT_MSG_BUF 0x35
+#define IPMI_CMD_GET_CHANNEL_INFO 0x42
#define IPMI_NETFN_STORAGE 0x0a
uint8_t *buf;
uint8_t netfn, rqLun, rsLun, rqSeq;
- if (cmd[2] != 0) {
- /* We only handle channel 0 with no options */
+ if (cmd[2] != IPMI_CHANNEL_IPMB) {
+ /* We only handle channel 0h (IPMB) with no options */
rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
return;
}
}
}
+static void get_channel_info(IPMIBmcSim *ibs,
+ uint8_t *cmd, unsigned int cmd_len,
+ RspBuffer *rsp)
+{
+ IPMIInterface *s = ibs->parent.intf;
+ IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
+ IPMIFwInfo info = {};
+ uint8_t ch = cmd[2] & 0x0f;
+
+ /* Only define channel 0h (IPMB) and Fh (system interface) */
+
+ if (ch == 0x0e) { /* "This channel" */
+ ch = IPMI_CHANNEL_SYSTEM;
+ }
+ rsp_buffer_push(rsp, ch);
+
+ if (ch != IPMI_CHANNEL_IPMB && ch != IPMI_CHANNEL_SYSTEM) {
+ /* Not a supported channel */
+ rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
+ return;
+ }
+
+ if (k->get_fwinfo) {
+ k->get_fwinfo(s, &info);
+ }
+
+ if (ch == IPMI_CHANNEL_IPMB) {
+ rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_IPMB);
+ rsp_buffer_push(rsp, IPMI_CHANNEL_PROTOCOL_IPMB);
+ } else { /* IPMI_CHANNEL_SYSTEM */
+ rsp_buffer_push(rsp, IPMI_CHANNEL_MEDIUM_SYSTEM);
+ rsp_buffer_push(rsp, info.ipmi_channel_protocol);
+ }
+
+ rsp_buffer_push(rsp, 0x00); /* Session-less */
+
+ /* IPMI Enterprise Number for Vendor ID */
+ rsp_buffer_push(rsp, 0xf2);
+ rsp_buffer_push(rsp, 0x1b);
+ rsp_buffer_push(rsp, 0x00);
+
+ if (ch == IPMI_CHANNEL_SYSTEM) {
+ uint8_t irq;
+
+ if (info.irq_source == IPMI_ISA_IRQ) {
+ irq = info.interrupt_number;
+ } else if (info.irq_source == IPMI_PCI_IRQ) {
+ irq = 0x10 + info.interrupt_number;
+ } else {
+ irq = 0xff; /* no interrupt / unspecified */
+ }
+
+ /* Both interrupts use the same irq number */
+ rsp_buffer_push(rsp, irq);
+ rsp_buffer_push(rsp, irq);
+ } else {
+ /* Reserved */
+ rsp_buffer_push(rsp, 0x00);
+ rsp_buffer_push(rsp, 0x00);
+ }
+}
+
static void get_sdr_rep_info(IPMIBmcSim *ibs,
uint8_t *cmd, unsigned int cmd_len,
RspBuffer *rsp)
[IPMI_CMD_RESET_WATCHDOG_TIMER] = { reset_watchdog_timer },
[IPMI_CMD_SET_WATCHDOG_TIMER] = { set_watchdog_timer, 8 },
[IPMI_CMD_GET_WATCHDOG_TIMER] = { get_watchdog_timer },
+ [IPMI_CMD_GET_CHANNEL_INFO] = { get_channel_info, 3 },
};
static const IPMINetfn app_netfn = {
.cmd_nums = ARRAY_SIZE(app_cmds),
IPMI_SEND_NMI
};
+/* Channel properties */
+#define IPMI_CHANNEL_IPMB 0x00
+#define IPMI_CHANNEL_SYSTEM 0x0f
+#define IPMI_CHANNEL_MEDIUM_IPMB 0x01
+#define IPMI_CHANNEL_MEDIUM_SYSTEM 0x0c
+#define IPMI_CHANNEL_PROTOCOL_IPMB 0x01
+#define IPMI_CHANNEL_PROTOCOL_KCS 0x05
+#define IPMI_CHANNEL_PROTOCOL_BT_15 0x08
+
#define IPMI_CC_INVALID_CMD 0xc1
#define IPMI_CC_COMMAND_INVALID_FOR_LUN 0xc2
#define IPMI_CC_TIMEOUT 0xc3
int interface_type;
uint8_t ipmi_spec_major_revision;
uint8_t ipmi_spec_minor_revision;
+ uint8_t ipmi_channel_protocol;
uint8_t i2c_slave_address;
uint32_t uuid;