mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
update the OpenIPMI interface,
support sending and receiving from IPMB addresses
This commit is contained in:
parent
d5b598c93d
commit
c52b6e80ba
@ -45,101 +45,128 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#include <ipmitool/helper.h>
|
||||
#include <ipmitool/log.h>
|
||||
|
||||
#include <linux/ipmi.h>
|
||||
#include <config.h>
|
||||
|
||||
#include "open.h"
|
||||
#ifdef HAVE_OPENIPMI_H
|
||||
# include <linux/ipmi.h>
|
||||
#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")));
|
||||
|
@ -37,14 +37,74 @@
|
||||
#ifndef IPMI_OPENIPMI_H
|
||||
#define IPMI_OPENIPMI_H
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/ipmi_intf.h>
|
||||
#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*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user