|
Packit |
7e09eb |
/*
|
|
Packit |
7e09eb |
* Generic IPMI Interface
|
|
Packit |
7e09eb |
* Copyright (C) 2011, Dell Inc.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This program is free software; you can redistribute it and/or modify it
|
|
Packit |
7e09eb |
* under the terms and conditions of the GNU General Public License,
|
|
Packit |
7e09eb |
* version 2, as published by the Free Software Foundation.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
Packit |
7e09eb |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit |
7e09eb |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
Packit |
7e09eb |
* more details.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
* You should have received a copy of the GNU General Public License along with
|
|
Packit |
7e09eb |
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
7e09eb |
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
7e09eb |
*
|
|
Packit |
7e09eb |
*/
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#include <errno.h>
|
|
Packit |
7e09eb |
#include <fcntl.h>
|
|
Packit |
7e09eb |
#include <limits.h>
|
|
Packit |
7e09eb |
#include <stdint.h>
|
|
Packit |
7e09eb |
#include <stdio.h>
|
|
Packit |
7e09eb |
#include <stdlib.h>
|
|
Packit |
7e09eb |
#include <string.h>
|
|
Packit |
7e09eb |
#include <unistd.h>
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#include <sys/ioctl.h>
|
|
Packit |
7e09eb |
#include <linux/ipmi.h>
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#if _HAVE_DMALLOC_H
|
|
Packit |
7e09eb |
#include <dmalloc.h>
|
|
Packit |
7e09eb |
#endif
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
#include "utils.h"
|
|
Packit |
7e09eb |
#include "ipmi.h"
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
static int ipmi_open(void)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
int fd;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
fd = open("/dev/ipmi0", O_RDWR);
|
|
Packit |
7e09eb |
if (fd >= 0)
|
|
Packit |
7e09eb |
return fd;
|
|
Packit |
7e09eb |
fd = open("/dev/ipmidev/0", O_RDWR);
|
|
Packit |
7e09eb |
if (fd >= 0)
|
|
Packit |
7e09eb |
return fd;
|
|
Packit |
7e09eb |
fd = open("/dev/ipmidev0", O_RDWR);
|
|
Packit |
7e09eb |
if (fd >= 0)
|
|
Packit |
7e09eb |
return fd;
|
|
Packit |
7e09eb |
fd = open("/dev/bmc", O_RDWR);
|
|
Packit |
7e09eb |
if (fd >= 0)
|
|
Packit |
7e09eb |
return fd;
|
|
Packit |
7e09eb |
return -1;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
int ipmicmd(int sa, int lun, int netfn, int cmd, int datalen, void *data,
|
|
Packit |
7e09eb |
int resplen, int *rlen, void *resp)
|
|
Packit |
7e09eb |
{
|
|
Packit |
7e09eb |
static int msgid;
|
|
Packit |
7e09eb |
struct ipmi_system_interface_addr saddr;
|
|
Packit |
7e09eb |
struct ipmi_ipmb_addr iaddr;
|
|
Packit |
7e09eb |
struct ipmi_addr raddr;
|
|
Packit |
7e09eb |
struct ipmi_req req;
|
|
Packit |
7e09eb |
struct ipmi_recv rcv;
|
|
Packit |
7e09eb |
fd_set rfd;
|
|
Packit |
7e09eb |
int fd, rc;
|
|
Packit |
7e09eb |
uint8_t tresp[resplen + 1];
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
fd = ipmi_open();
|
|
Packit |
7e09eb |
if (fd < 0)
|
|
Packit |
7e09eb |
return -1;
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
memset(&req, 0, sizeof(req));
|
|
Packit |
7e09eb |
memset(&rcv, 0, sizeof(rcv));
|
|
Packit |
7e09eb |
if (sa == BMC_SA) {
|
|
Packit |
7e09eb |
memset(&saddr, 0, sizeof(saddr));
|
|
Packit |
7e09eb |
saddr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
|
|
Packit |
7e09eb |
saddr.channel = IPMI_BMC_CHANNEL;
|
|
Packit |
7e09eb |
saddr.lun = 0;
|
|
Packit |
7e09eb |
req.addr = (void *)&saddr;
|
|
Packit |
7e09eb |
req.addr_len = sizeof(saddr);
|
|
Packit |
7e09eb |
} else {
|
|
Packit |
7e09eb |
memset(&iaddr, 0, sizeof(iaddr));
|
|
Packit |
7e09eb |
iaddr.addr_type = IPMI_IPMB_ADDR_TYPE;
|
|
Packit |
7e09eb |
iaddr.channel = 0;
|
|
Packit |
7e09eb |
iaddr.slave_addr = sa;
|
|
Packit |
7e09eb |
iaddr.lun = lun;
|
|
Packit |
7e09eb |
req.addr = (void *)&iaddr;
|
|
Packit |
7e09eb |
req.addr_len = sizeof(iaddr);
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* Issue command */
|
|
Packit |
7e09eb |
req.msgid = ++msgid;
|
|
Packit |
7e09eb |
req.msg.netfn = netfn;
|
|
Packit |
7e09eb |
req.msg.cmd = cmd;
|
|
Packit |
7e09eb |
req.msg.data_len = datalen;
|
|
Packit |
7e09eb |
req.msg.data = data;
|
|
Packit |
7e09eb |
rc = ioctl(fd, IPMICTL_SEND_COMMAND, (void *)&req;;
|
|
Packit |
7e09eb |
if (rc != 0) {
|
|
Packit |
7e09eb |
perror("send");
|
|
Packit |
7e09eb |
goto end;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* Wait for Response */
|
|
Packit |
7e09eb |
FD_ZERO(&rfd;;
|
|
Packit |
7e09eb |
FD_SET(fd, &rfd;;
|
|
Packit |
7e09eb |
rc = select(fd + 1, &rfd, NULL, NULL, NULL);
|
|
Packit |
7e09eb |
if (rc < 0) {
|
|
Packit |
7e09eb |
perror("select");
|
|
Packit |
7e09eb |
goto end;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
|
|
Packit |
7e09eb |
/* Get response */
|
|
Packit |
7e09eb |
rcv.msg.data = tresp;
|
|
Packit |
7e09eb |
rcv.msg.data_len = resplen + 1;
|
|
Packit |
7e09eb |
rcv.addr = (void *)&radd;;
|
|
Packit |
7e09eb |
rcv.addr_len = sizeof(raddr);
|
|
Packit |
7e09eb |
rc = ioctl(fd, IPMICTL_RECEIVE_MSG_TRUNC, (void *)&rcv;;
|
|
Packit |
7e09eb |
if (rc != 0 && errno == EMSGSIZE)
|
|
Packit |
7e09eb |
log_info("too short..\n");
|
|
Packit |
7e09eb |
if (rc != 0 && errno != EMSGSIZE) {
|
|
Packit |
7e09eb |
log_info("%s\n", strerror(errno));
|
|
Packit |
7e09eb |
goto end;
|
|
Packit |
7e09eb |
}
|
|
Packit |
7e09eb |
if (rcv.msg.data[0])
|
|
Packit |
7e09eb |
log_info("IPMI Error: %.2x\n", rcv.msg.data[0]);
|
|
Packit |
7e09eb |
rc = 0;
|
|
Packit |
7e09eb |
*rlen = rcv.msg.data_len - 1;
|
|
Packit |
7e09eb |
memcpy(resp, rcv.msg.data + 1, *rlen);
|
|
Packit |
7e09eb |
end:
|
|
Packit |
7e09eb |
close(fd);
|
|
Packit |
7e09eb |
return rc;
|
|
Packit |
7e09eb |
}
|