Blame src/ipmi.c

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
}