X86通过BMC控灯实现

1、背景介绍

目前板上有x86和bmc,bmc通过gpio进行控灯,x86和bmc之间通过lpc总线连接,示意图如下:

X86通过BMC控灯实现_第1张图片

这里BMC采用Pentail提供的解决方案,芯片为smartfusion。X86采用Intel E5V4芯片,上面运行Redhat操作系统。

2、方法介绍

目前linux提供了open ipmi驱动和ipmitool来实现X86与BMC交互,安装完驱动后使用ipmitool可以获取BMC的状态,相关命令参考如下:https://docs.oracle.com/cd/E40705_01/html/E40351/z400000c1016683.html

可以执行ipmitool raw +自定义的netfn和cmd给BMC发命令,BMC收到ipmi命令后根据netfn和cmd进行闪灯即可。

一种方法是直接使用system("ipmitool raw xx xx"),不过使用system系统函数会创建线程,对系统性能造成影响。另一种方法就是根据ipmitool中提供的源码进行个性化修改,具体如下。

3、自定义闪灯

通过查阅代码可以发现执行Ipmitool raw使用的是open.c和open.h这两个文件中的函数。于是可以修改这两个文件,如下:

led.h

/*
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistribution of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * Redistribution in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */



int led_open();
void led_close();
int led_trigger(int index);
int led_on(int index);
int led_off(int index);

led.c


/*
 * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistribution of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * Redistribution in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */
#define _POSIX_C_SOURCE 1

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "led.h"

#define IPMI_BMC_CHANNEL		0xf
#define IPMI_SYSTEM_INTERFACE_ADDR_TYPE	0x0c

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_system_interface_addr {
	int addr_type;
	short channel;
	unsigned char lun;
};

#define IPMI_IOC_MAGIC			'i'
#define IPMICTL_SEND_COMMAND		_IOR(IPMI_IOC_MAGIC, 13, struct ipmi_req)

int fd=-1;

int led_open()
{
	fd=open("/dev/ipmi0", O_RDWR);
	if(fd<0)
	{
		printf("open ipmidev failed\n");
		return -1;
	}
	return fd;
}

void led_close()
{
	if (fd >= 0)
	{
		close(fd);
	}
}

int ledA_trigger()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=2;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x18;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledB_trigger()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=2;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x20;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledC_trigger()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=2;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x14;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledD_trigger()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=2;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x16;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int led_trigger(int index)
{
	if(index==0)
	{
		ledA_trigger();
	}
	else if(index==1)
	{
		ledB_trigger();
	}
	else if(index==2)
	{
		ledC_trigger();
	}
	else if(index==3)
	{
		ledD_trigger();
	}
	else
	{
		printf("index invalid 0-3 is ok\n");
	}
}

int ledA_on()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=1;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x18;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledB_on()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=1;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x20;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledC_on()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=1;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x14;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledD_on()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=1;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x16;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int led_on(int index)
{
	if(index==0)
	{
		ledA_on();
	}
	else if(index==1)
	{
		ledB_on();
	}
	else if(index==2)
	{
		ledC_on();
	}
	else if(index==3)
	{
		ledD_on();
	}
	else
	{
		printf("index invalid 0-3 is ok\n");
	}
}

int ledA_off()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=0;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x18;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledB_off()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=0;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x20;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledC_off()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=0;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x14;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int ledD_off()
{
	struct ipmi_system_interface_addr bmc_addr = {
		.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE,
		.channel = IPMI_BMC_CHANNEL,
	};
	struct ipmi_req _req;

	char dd[2];
	dd[0]=0;
	memset(&_req, 0, sizeof(struct ipmi_req));

	bmc_addr.lun =0;

	_req.addr = (unsigned char *) &bmc_addr;
	_req.addr_len = sizeof(bmc_addr);
	_req.msgid = 0;

    _req.msg.data = dd;
    _req.msg.data_len = 0x1;
    _req.msg.netfn =0x6;
    _req.msg.cmd =0x16;

	if(ioctl(fd, IPMICTL_SEND_COMMAND, &_req) < 0)
	{
	   printf( "Unable to send command\n");
	   return -1;
	}
	return 1;
}

int led_off(int index)
{
	if(index==0)
	{
		ledA_off();
	}
	else if(index==1)
	{
		ledB_off();
	}
	else if(index==2)
	{
		ledC_off();
	}
	else if(index==3)
	{
		ledD_off();
	}
	else
	{
		printf("index invalid 0-3 is ok\n");
	}
}

调用接口如下

/*
 ============================================================================
 Name        : led_example.c
 Author      : 123
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include 
#include 

#include "led.h"

int main(void) {
	led_open();

	led_on(0);
	led_on(1);
	led_on(2);
	led_on(3);
	sleep(2);

	led_off(0);
	led_off(1);
	led_off(2);
	led_off(3);

	sleep(2);

	led_trigger(0);
	led_trigger(1);
	led_trigger(2);
	led_trigger(3);

	sleep(2);

	led_trigger(0);
	led_trigger(1);
	led_trigger(2);
	led_trigger(3);


	led_close();
	return EXIT_SUCCESS;
}

这样就能直接控灯了。

你可能感兴趣的:(Felven在职场)