From c52b6e80ba4058927b9b03f4edcb2b2ca3010e4d Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Fri, 27 Aug 2004 16:30:07 +0000 Subject: [PATCH] update the OpenIPMI interface, support sending and receiving from IPMB addresses --- ipmitool/src/plugins/open/open.c | 155 ++++++++++++++++++------------- ipmitool/src/plugins/open/open.h | 76 +++++++++++++-- 2 files changed, 161 insertions(+), 70 deletions(-) diff --git a/ipmitool/src/plugins/open/open.c b/ipmitool/src/plugins/open/open.c index cabdef3..baa31e7 100644 --- a/ipmitool/src/plugins/open/open.c +++ b/ipmitool/src/plugins/open/open.c @@ -45,101 +45,128 @@ #include #include +#include #include +#include -#include +#include -#include "open.h" +#ifdef HAVE_OPENIPMI_H +# include +#else +# include "open.h" +#endif extern int verbose; -struct ipmi_intf ipmi_openipmi_intf = { - .open = ipmi_openipmi_open, - .close = ipmi_openipmi_close, - .sendrecv = ipmi_openipmi_send_cmd, -}; +#define IPMI_OPENIPMI_DEV "/dev/ipmi0" -void ipmi_openipmi_close(struct ipmi_intf * intf) -{ - if (intf && intf->fd >= 0) - close(intf->fd); -} - -int ipmi_openipmi_open(struct ipmi_intf * intf) +static int ipmi_openipmi_open(struct ipmi_intf * intf) { int i = 0; - intf->fd = open(OPENIPMI_DEV, O_RDWR); + intf->fd = open(IPMI_OPENIPMI_DEV, O_RDWR); if (intf->fd < 0) { - perror("Could not open ipmi device"); + lperror(LOG_ERR, "Could not open ipmi device"); return -1; } if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i)) { - perror("Could not set to get events"); + lperror(LOG_ERR, "Could not set to get events"); return -1; } + if (intf->my_addr) { + unsigned int a = intf->my_addr; + if (ioctl(intf->fd, IPMICTL_SET_MY_ADDRESS_CMD, &a)) { + lperror(LOG_ERR, "Could not set IPMB address"); + return -1; + } + lprintf(LOG_DEBUG, "Set my IPMB address to 0x%x", intf->my_addr); + } + + intf->opened = 1; + return intf->fd; } -struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) +static void ipmi_openipmi_close(struct ipmi_intf * intf) +{ + if (intf && intf->fd >= 0) + close(intf->fd); + intf->opened = 0; +} + +static struct ipmi_rs *ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req) { struct ipmi_recv recv; struct ipmi_addr addr; - struct ipmi_system_interface_addr bmc_addr; + struct ipmi_system_interface_addr bmc_addr = { + addr_type: IPMI_SYSTEM_INTERFACE_ADDR_TYPE, + channel: IPMI_BMC_CHANNEL, + }; + struct ipmi_ipmb_addr ipmb_addr = { + addr_type: IPMI_IPMB_ADDR_TYPE, + }; struct ipmi_req _req; static struct ipmi_rs rsp; static int curr_seq = 0; fd_set rset; - if (!intf) + if (!intf || !req) + return NULL; + if (!intf->opened && intf->open && intf->open(intf) < 0) return NULL; - if (!intf->opened) { - intf->opened = 1; - if (intf->open(intf) < 0) { - printf("Unable to open OpenIPMI interface!\n"); - intf->opened = 0; - return NULL; - } - } + if (verbose > 2) + printbuf(req->msg.data, req->msg.data_len, "send_cmd"); - if (!req) - return NULL; + /* + * setup and send message + */ memset(&_req, 0, sizeof(struct ipmi_req)); - if (verbose > 2) - printbuf(req->msg.data, req->msg.data_len, "send_ipmi_cmd_dev"); + if (intf->target_addr && + intf->target_addr != intf->my_addr) { + /* use IPMB address if needed */ + ipmb_addr.slave_addr = intf->target_addr; + _req.addr = (char *) &ipmb_addr; + _req.addr_len = sizeof(ipmb_addr); + lprintf(LOG_DEBUG, "Sending request to IPMB target @ 0x%x", + intf->target_addr); + } else { + /* otherwise use system interface */ + lprintf(LOG_DEBUG, "Sending request to System Interface"); + _req.addr = (char *) &bmc_addr; + _req.addr_len = sizeof(bmc_addr); + } - FD_ZERO(&rset); - FD_SET(intf->fd, &rset); - - bmc_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; - bmc_addr.channel = IPMI_BMC_CHANNEL; - bmc_addr.lun = 0; - - _req.addr = (char *) &bmc_addr; - _req.addr_len = sizeof(bmc_addr); _req.msgid = curr_seq++; - _req.msg.netfn = req->msg.netfn; _req.msg.cmd = req->msg.cmd; _req.msg.data = req->msg.data; _req.msg.data_len = req->msg.data_len; if (ioctl(intf->fd, IPMICTL_SEND_COMMAND, &_req) < 0) { - printf("Error sending command: %s\n", strerror(errno)); + lperror(LOG_ERR, "Error sending command"); return NULL; } + + /* + * wait for and retrieve response + */ + + FD_ZERO(&rset); + FD_SET(intf->fd, &rset); + if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) { - perror("select"); + lperror(LOG_ERR, "Error doing select"); return NULL; } if (!FD_ISSET(intf->fd, &rset)) { - printf("Error no data available\n"); + lprintf(LOG_ERR, "Error no data available"); return NULL; } @@ -150,28 +177,30 @@ struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq /* get data */ if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) { - printf("Error receiving message: %s\n", strerror(errno)); + lperror(LOG_ERR, "Error receiving message"); if (errno != EMSGSIZE) return NULL; } - if (verbose > 1) { - printf("Got message:\n"); - printf(" type = %d\n", recv.recv_type); - printf(" channel = 0x%x\n", addr.channel); - printf(" msgid = %ld\n", recv.msgid); - printf(" netfn = 0x%x\n", recv.msg.netfn); - printf(" cmd = 0x%x\n", recv.msg.cmd); + if (verbose > 4) { + fprintf(stderr, "Got message:"); + fprintf(stderr, " type = %d\n", recv.recv_type); + fprintf(stderr, " channel = 0x%x\n", addr.channel); + fprintf(stderr, " msgid = %ld\n", recv.msgid); + fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn); + fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd); if (recv.msg.data && recv.msg.data_len) { - printf(" data_len = %d\n", recv.msg.data_len); - printf(" data ="); - printbuf(recv.msg.data, recv.msg.data_len, "data"); + fprintf(stderr, " data_len = %d\n", recv.msg.data_len); + fprintf(stderr, " data = %s\n", + buf2str(recv.msg.data, recv.msg.data_len)); } } + /* save completion code */ rsp.ccode = recv.msg.data[0]; rsp.data_len = recv.msg.data_len - 1; + /* save response data for caller */ if (!rsp.ccode && rsp.data_len) { memmove(rsp.data, rsp.data + 1, rsp.data_len); rsp.data[recv.msg.data_len] = 0; @@ -180,10 +209,12 @@ struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq return &rsp; } -int open_intf_setup(struct ipmi_intf ** intf) -{ - *intf = &ipmi_openipmi_intf; - return 0; -} +struct ipmi_intf ipmi_open_intf = { + name: "open", + desc: "Linux OpenIPMI Interface", + open: ipmi_openipmi_open, + close: ipmi_openipmi_close, + sendrecv: ipmi_openipmi_send_cmd, + target_addr: IPMI_BMC_SLAVE_ADDR, +}; -int intf_setup(struct ipmi_intf ** intf) __attribute__ ((weak, alias("open_intf_setup"))); diff --git a/ipmitool/src/plugins/open/open.h b/ipmitool/src/plugins/open/open.h index a61db79..3c0aab5 100644 --- a/ipmitool/src/plugins/open/open.h +++ b/ipmitool/src/plugins/open/open.h @@ -37,14 +37,74 @@ #ifndef IPMI_OPENIPMI_H #define IPMI_OPENIPMI_H -#include -#include +#define IPMI_MAX_ADDR_SIZE 0x20 +#define IPMI_BMC_CHANNEL 0xf +#define IPMI_NUM_CHANNELS 0x10 -#define OPENIPMI_DEV "/dev/ipmi0" +#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE 0x0c +#define IPMI_IPMB_ADDR_TYPE 0x01 +#define IPMI_IPMB_BROADCAST_ADDR_TYPE 0x41 -struct ipmi_rs * ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req); -int ipmi_openipmi_open(struct ipmi_intf * intf); -void ipmi_openipmi_close(struct ipmi_intf * intf); -int open_intf_setup(struct ipmi_intf ** intf); +#define IPMI_RESPONSE_RECV_TYPE 1 +#define IPMI_ASYNC_EVENT_RECV_TYPE 2 +#define IPMI_CMD_RECV_TYPE 3 -#endif +struct ipmi_addr { + int addr_type; + short channel; + char data[IPMI_MAX_ADDR_SIZE]; +}; + +struct ipmi_msg { + unsigned char netfn; + unsigned char cmd; + unsigned short data_len; + unsigned char *data; +}; + +struct ipmi_req { + unsigned char *addr; + unsigned int addr_len; + long msgid; + struct ipmi_msg msg; +}; + +struct ipmi_recv { + int recv_type; + unsigned char *addr; + unsigned int addr_len; + long msgid; + struct ipmi_msg msg; +}; + +struct ipmi_cmdspec { + unsigned char netfn; + unsigned char cmd; +}; + +struct ipmi_system_interface_addr { + int addr_type; + short channel; + unsigned char lun; +}; + +struct ipmi_ipmb_addr { + int addr_type; + short channel; + unsigned char slave_addr; + unsigned char lun; +}; + +#define IPMI_IOC_MAGIC 'i' +#define IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv) +#define IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv) +#define IPMICTL_SEND_COMMAND _IOR(IPMI_IOC_MAGIC, 13, struct ipmi_req) +#define IPMICTL_REGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 14, struct ipmi_cmdspec) +#define IPMICTL_UNREGISTER_FOR_CMD _IOR(IPMI_IOC_MAGIC, 15, struct ipmi_cmdspec) +#define IPMICTL_SET_GETS_EVENTS_CMD _IOR(IPMI_IOC_MAGIC, 16, int) +#define IPMICTL_SET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 17, unsigned int) +#define IPMICTL_GET_MY_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 18, unsigned int) +#define IPMICTL_SET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 19, unsigned int) +#define IPMICTL_GET_MY_LUN_CMD _IOR(IPMI_IOC_MAGIC, 20, unsigned int) + +#endif /*IPMI_OPENIPMI_H*/