mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 18:47:22 +00:00
Added IPMB dual bridge support (no need for driver support)
This commit is contained in:
parent
50c514e336
commit
e41a6aacb3
103
ipmitool/README
103
ipmitool/README
@ -131,6 +131,109 @@ no problems. The IPMIv1.5 interface will attempt to use OpenSSL for MD5
|
|||||||
hash function at compile time but if that is not found it will use an
|
hash function at compile time but if that is not found it will use an
|
||||||
internal library.
|
internal library.
|
||||||
|
|
||||||
|
IPMB Dual Bridging in IPMITOOL
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
IPMI offers a standard messaging interface.
|
||||||
|
|
||||||
|
The following concepts are related to this messaging interface:
|
||||||
|
|
||||||
|
Channel type : Communication channel type (SMS/KCS, IPMB, LAN)
|
||||||
|
Channel number : Channel descritor
|
||||||
|
Requester : Address of the requester
|
||||||
|
Responder : Address of the responder
|
||||||
|
NetFN : The logical function for the request/response.
|
||||||
|
Command : The command number
|
||||||
|
Sequence : An ID identifiying the request/response pair
|
||||||
|
Message tracking : The ability to match request/response pair.
|
||||||
|
|
||||||
|
When a communication is issued through any of the channels, an application
|
||||||
|
formats a request and expect a response.
|
||||||
|
|
||||||
|
Direct Command
|
||||||
|
--------------
|
||||||
|
The simplest form of communication is a "direct command" using SMS/KCS
|
||||||
|
|
||||||
|
Example:
|
||||||
|
ipmitool raw 6 4
|
||||||
|
55 00
|
||||||
|
|
||||||
|
This send raw command 4 (selftest) from netfn 6(application) to KCS, the driver
|
||||||
|
takes care of 'message tracking' and provides the answer.
|
||||||
|
|
||||||
|
Hopefuly, the application also includes a "human readable" instance of the API:
|
||||||
|
ipmitool mc selftest
|
||||||
|
Selftest: passed
|
||||||
|
|
||||||
|
Bridged Command
|
||||||
|
---------------
|
||||||
|
One slightly more complicated communication mode is the so-called
|
||||||
|
"bridged command" using IPMB.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
ipmitool -m 0x94 -t 0x9a raw 6 4
|
||||||
|
55 00
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
ipmitool -m 0x94 -t 0x9a mc selftest
|
||||||
|
Selftest: passed
|
||||||
|
|
||||||
|
|
||||||
|
This still sends the same command 4 (selftest) from netfn 6(application) to
|
||||||
|
the target. However, to do so, the command is encapsulated (by the driver) and
|
||||||
|
sent using the command 0x34 (send message) from netfn 6(application) to KCS.
|
||||||
|
Then KCS is polled by the driver until a message has been received, then the
|
||||||
|
driver uses command 0x33 (get message). The driver also tracks the message
|
||||||
|
and makes sure the response matches the request. Then it decapsultates the
|
||||||
|
message and gives the response back to the application.
|
||||||
|
|
||||||
|
Dual Bridged Command
|
||||||
|
--------------------
|
||||||
|
Things get a little more ugly when the application needs to reach a management
|
||||||
|
controller sitting on an interface (or channel) not directly connected to the
|
||||||
|
BMC/IPMC. In the case the application must encapsulate its message itself and
|
||||||
|
request the IPMC to deal with message tracking itself.
|
||||||
|
|
||||||
|
Its been working well with IPMITOOL on the LAN interface with:
|
||||||
|
ipmitool -H <ip> -U <user> -P <password> -B 0 -T 0x8a -m 0x20 -t 0x7a -b 7
|
||||||
|
mc selftest
|
||||||
|
|
||||||
|
However, trying to dual bridge commands locally with :
|
||||||
|
ipmitool -B 0 -T 0x9a -m 0x94 -t 0x7a -b 7 mc selftest didn't work
|
||||||
|
(it returned the same data as ipmitool -m 0x20 -t 0x7a -b 7 mc selftest )
|
||||||
|
|
||||||
|
The reason was that the "openipmi" interface pluging didn't
|
||||||
|
encapsulate/decapsulate the message and didn't even detect the intent
|
||||||
|
to double bridge the request.
|
||||||
|
|
||||||
|
./src/ipmitool -B 0 -T 0x8a -m 0x94 -t 0x7a -b 7 mc selftest
|
||||||
|
|
||||||
|
-B 0 : transit channel for first bridge level (channel 0: IPMB-0)
|
||||||
|
-T 0x8a : transit destination address (remote IPMC address)
|
||||||
|
-m 0x94 : source address (local IPMC address on IPMB-0)
|
||||||
|
-t 0x7a : remote target (AMC IPMB-L address)
|
||||||
|
-b 7 : remote channel (channel 7: IPMB-L)
|
||||||
|
|
||||||
|
The transit source address (remote IPMC address on remote channel) is
|
||||||
|
automatically assigned by the remote IPMC.
|
||||||
|
|
||||||
|
Payload Size Limit
|
||||||
|
------------------
|
||||||
|
Vecause some commands return a lot of data (fru read/get sdr) and because 2
|
||||||
|
levels of encapsulation are used, some command will fail.
|
||||||
|
|
||||||
|
For instance this works.
|
||||||
|
|
||||||
|
ipmitool -H <ip> -U <user> -P <password> -B 0 -T 0x8a -m 0x94 -t 0x7a -b 7
|
||||||
|
mc selftest
|
||||||
|
|
||||||
|
but this does not:
|
||||||
|
|
||||||
|
ipmitool -H <ip> -U <user> -P <password> -B 0 -T 0x8a -m 0x94 -t 0x7a -b 7
|
||||||
|
fru print.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
#include <ipmitool/ipmi_pef.h>
|
#include <ipmitool/ipmi_pef.h>
|
||||||
#include <ipmitool/ipmi_oem.h>
|
#include <ipmitool/ipmi_oem.h>
|
||||||
#include <ipmitool/ipmi_ekanalyzer.h>
|
#include <ipmitool/ipmi_ekanalyzer.h>
|
||||||
|
#include <ipmitool/ipmi_picmg.h>
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
@ -242,6 +243,7 @@ ipmi_option_usage(const char * progname, struct ipmi_cmd * cmdlist, struct ipmi_
|
|||||||
lprintf(LOG_NOTICE, " -m address Set local IPMB address");
|
lprintf(LOG_NOTICE, " -m address Set local IPMB address");
|
||||||
lprintf(LOG_NOTICE, " -b channel Set destination channel for bridged request");
|
lprintf(LOG_NOTICE, " -b channel Set destination channel for bridged request");
|
||||||
lprintf(LOG_NOTICE, " -t address Bridge request to remote target address");
|
lprintf(LOG_NOTICE, " -t address Bridge request to remote target address");
|
||||||
|
lprintf(LOG_NOTICE, " -M address Set transit local address for bridge request(dual bridge)");
|
||||||
lprintf(LOG_NOTICE, " -B channel Set transit channel for bridged request (dual bridge)");
|
lprintf(LOG_NOTICE, " -B channel Set transit channel for bridged request (dual bridge)");
|
||||||
lprintf(LOG_NOTICE, " -T address Set transit address for bridge request (dual bridge)");
|
lprintf(LOG_NOTICE, " -T address Set transit address for bridge request (dual bridge)");
|
||||||
lprintf(LOG_NOTICE, " -l lun Set destination lun for raw commands");
|
lprintf(LOG_NOTICE, " -l lun Set destination lun for raw commands");
|
||||||
@ -355,6 +357,7 @@ ipmi_main(int argc, char ** argv,
|
|||||||
int privlvl = 0;
|
int privlvl = 0;
|
||||||
uint8_t target_addr = 0;
|
uint8_t target_addr = 0;
|
||||||
uint8_t target_channel = 0;
|
uint8_t target_channel = 0;
|
||||||
|
|
||||||
uint8_t transit_addr = 0;
|
uint8_t transit_addr = 0;
|
||||||
uint8_t transit_channel = 0;
|
uint8_t transit_channel = 0;
|
||||||
uint8_t target_lun = 0;
|
uint8_t target_lun = 0;
|
||||||
@ -721,9 +724,72 @@ ipmi_main(int argc, char ** argv,
|
|||||||
|
|
||||||
ipmi_main_intf->devnum = devnum;
|
ipmi_main_intf->devnum = devnum;
|
||||||
|
|
||||||
/* setup IPMB local and target address if given */
|
/* setup IPMB local and target address if given */
|
||||||
ipmi_main_intf->my_addr = my_addr ? : IPMI_BMC_SLAVE_ADDR;
|
if( my_addr ) {
|
||||||
if (target_addr > 0) {
|
ipmi_main_intf->my_addr = my_addr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
/* Check if PICMG extension is available to use the function GetDeviceLocator
|
||||||
|
* to retreive i2c address PICMG hack to set right IPMB address,
|
||||||
|
* If extension is not supported, should not give any problems
|
||||||
|
* PICMG Extension Version 2.0 (PICMG 3.0 Revision 1.0 ATCA) to
|
||||||
|
* PICMG Extension Version 2.3 (PICMG 3.0 Revision 3.0 ATCA)
|
||||||
|
*/
|
||||||
|
/* First, check if PICMG extension is available and supported */
|
||||||
|
struct ipmi_rq req;
|
||||||
|
struct ipmi_rs *rsp;
|
||||||
|
char msg_data;
|
||||||
|
unsigned char version_accepted = 0;
|
||||||
|
|
||||||
|
lprintf(LOG_INFO, "Running PICMG GetDeviceLocator" );
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
||||||
|
req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD;
|
||||||
|
msg_data = 0x00;
|
||||||
|
req.msg.data = &msg_data;
|
||||||
|
req.msg.data_len = 1;
|
||||||
|
msg_data = 0;
|
||||||
|
|
||||||
|
rsp = ipmi_main_intf->sendrecv(ipmi_main_intf, &req);
|
||||||
|
if (rsp && !rsp->ccode) {
|
||||||
|
if
|
||||||
|
(
|
||||||
|
(rsp->data[0] == 0)
|
||||||
|
&&
|
||||||
|
((rsp->data[1] & 0x0F ) == PICMG_ATCA_MAJOR_VERSION )
|
||||||
|
){
|
||||||
|
version_accepted = 1;
|
||||||
|
lprintf(LOG_INFO, "Discovered PICMG Extension %d.%d",
|
||||||
|
(rsp->data[1] & 0x0f),(rsp->data[1] >> 4) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(version_accepted == 1){
|
||||||
|
lprintf(LOG_DEBUG, "Running PICMG GetDeviceLocator" );
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
req.msg.netfn = IPMI_NETFN_PICMG;
|
||||||
|
req.msg.cmd = PICMG_GET_ADDRESS_INFO_CMD;
|
||||||
|
msg_data = 0x00;
|
||||||
|
req.msg.data = &msg_data;
|
||||||
|
req.msg.data_len = 1;
|
||||||
|
msg_data = 0;
|
||||||
|
|
||||||
|
rsp = ipmi_main_intf->sendrecv(ipmi_main_intf, &req);
|
||||||
|
if (rsp && !rsp->ccode) {
|
||||||
|
ipmi_main_intf->my_addr = rsp->data[2];
|
||||||
|
ipmi_main_intf->target_addr = ipmi_main_intf->my_addr;
|
||||||
|
lprintf(LOG_INFO, "Discovered IPMB address = 0x%x", ipmi_main_intf->my_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
lprintf(LOG_INFO,
|
||||||
|
"No PICMG Extenstion discovered, keeping IPMB address 0x20");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( target_addr > 0 && (target_addr != my_addr) ) {
|
||||||
/* need to open the interface first */
|
/* need to open the interface first */
|
||||||
if (ipmi_main_intf->open != NULL)
|
if (ipmi_main_intf->open != NULL)
|
||||||
ipmi_main_intf->open(ipmi_main_intf);
|
ipmi_main_intf->open(ipmi_main_intf);
|
||||||
|
@ -44,7 +44,6 @@
|
|||||||
#include <ipmitool/ipmi_intf.h>
|
#include <ipmitool/ipmi_intf.h>
|
||||||
#include <ipmitool/helper.h>
|
#include <ipmitool/helper.h>
|
||||||
#include <ipmitool/log.h>
|
#include <ipmitool/log.h>
|
||||||
#include <ipmitool/ipmi_picmg.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_CONFIG_H)
|
#if defined(HAVE_CONFIG_H)
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
@ -68,9 +67,7 @@ static int
|
|||||||
ipmi_openipmi_open(struct ipmi_intf * intf)
|
ipmi_openipmi_open(struct ipmi_intf * intf)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct ipmi_rq req;
|
|
||||||
struct ipmi_rs *rsp;
|
|
||||||
char msg_data;
|
|
||||||
char ipmi_dev[16];
|
char ipmi_dev[16];
|
||||||
char ipmi_devfs[16];
|
char ipmi_devfs[16];
|
||||||
char ipmi_devfs2[16];
|
char ipmi_devfs2[16];
|
||||||
@ -101,84 +98,21 @@ ipmi_openipmi_open(struct ipmi_intf * intf)
|
|||||||
lperror(LOG_ERR, "Could not enable event receiver");
|
lperror(LOG_ERR, "Could not enable event receiver");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
intf->opened = 1;
|
intf->opened = 1;
|
||||||
|
|
||||||
/* Check if PICMG extension is available to use the function GetDeviceLocator
|
/* This is never set to 0, the default is IPMI_BMC_SLAVE_ADDR */
|
||||||
* to retreive i2c address PICMG hack to set right IPMB address,
|
|
||||||
* If extension is not supported, should not give any problems
|
|
||||||
* PICMG Extension Version 2.0 (PICMG 3.0 Revision 1.0 ATCA) to
|
|
||||||
* PICMG Extension Version 2.3 (PICMG 3.0 Revision 3.0 ATCA)
|
|
||||||
*/
|
|
||||||
if (intf->my_addr == IPMI_BMC_SLAVE_ADDR) {
|
|
||||||
|
|
||||||
/* First, check if PICMG extension is available and supported */
|
|
||||||
unsigned char version_accepted = 0;
|
|
||||||
|
|
||||||
lprintf(LOG_DEBUG, "Running PICMG GetDeviceLocator" );
|
|
||||||
memset(&req, 0, sizeof(req));
|
|
||||||
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
||||||
req.msg.cmd = PICMG_GET_PICMG_PROPERTIES_CMD;
|
|
||||||
msg_data = 0x00;
|
|
||||||
req.msg.data = &msg_data;
|
|
||||||
req.msg.data_len = 1;
|
|
||||||
msg_data = 0;
|
|
||||||
|
|
||||||
rsp = intf->sendrecv(intf, &req);
|
|
||||||
if (rsp && !rsp->ccode) {
|
|
||||||
if
|
|
||||||
(
|
|
||||||
(rsp->data[0] == 0)
|
|
||||||
&&
|
|
||||||
(
|
|
||||||
(rsp->data[1] == 0x02)
|
|
||||||
||
|
|
||||||
(rsp->data[1] == 0x12)
|
|
||||||
||
|
|
||||||
(rsp->data[1] == 0x22)
|
|
||||||
||
|
|
||||||
(rsp->data[1] == 0x32)
|
|
||||||
)
|
|
||||||
){
|
|
||||||
version_accepted = 1;
|
|
||||||
lprintf(LOG_DEBUG, "Discovered PICMG Extension %d.%d",
|
|
||||||
(rsp->data[1] & 0x0f),(rsp->data[1] >> 4) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(version_accepted == 1){
|
|
||||||
lprintf(LOG_DEBUG, "Running PICMG GetDeviceLocator" );
|
|
||||||
memset(&req, 0, sizeof(req));
|
|
||||||
req.msg.netfn = IPMI_NETFN_PICMG;
|
|
||||||
req.msg.cmd = PICMG_GET_ADDRESS_INFO_CMD;
|
|
||||||
msg_data = 0x00;
|
|
||||||
req.msg.data = &msg_data;
|
|
||||||
req.msg.data_len = 1;
|
|
||||||
msg_data = 0;
|
|
||||||
|
|
||||||
rsp = intf->sendrecv(intf, &req);
|
|
||||||
if (rsp && !rsp->ccode) {
|
|
||||||
intf->my_addr = rsp->data[2];
|
|
||||||
intf->target_addr = intf->my_addr;
|
|
||||||
lprintf(LOG_DEBUG, "Discovered IPMB address = 0x%x", intf->my_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
lprintf(LOG_DEBUG,
|
|
||||||
"No PICMG Extenstion discovered, keeping IPMB address 0x20");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intf->my_addr != 0) {
|
if (intf->my_addr != 0) {
|
||||||
unsigned int a = intf->my_addr;
|
unsigned int a = intf->my_addr;
|
||||||
if (ioctl(intf->fd, IPMICTL_SET_MY_ADDRESS_CMD, &a) < 0) {
|
if (ioctl(intf->fd, IPMICTL_SET_MY_ADDRESS_CMD, &a) < 0) {
|
||||||
lperror(LOG_ERR, "Could not set IPMB address");
|
lperror(LOG_ERR, "Could not set IPMB address");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lprintf(LOG_DEBUG, "Set IPMB address to 0x%x",
|
lprintf(LOG_DEBUG, "Set IPMB address to 0x%x",
|
||||||
intf->my_addr);
|
intf->my_addr );
|
||||||
}
|
}
|
||||||
|
|
||||||
return intf->fd;
|
return intf->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,8 +145,13 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|||||||
static int curr_seq = 0;
|
static int curr_seq = 0;
|
||||||
fd_set rset;
|
fd_set rset;
|
||||||
|
|
||||||
|
uint8_t * data = NULL;
|
||||||
|
int data_len = 0;
|
||||||
|
|
||||||
|
|
||||||
if (intf == NULL || req == NULL)
|
if (intf == NULL || req == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (intf->opened == 0 && intf->open != NULL)
|
if (intf->opened == 0 && intf->open != NULL)
|
||||||
if (intf->open(intf) < 0)
|
if (intf->open(intf) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -231,56 +170,130 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|||||||
intf->target_addr != intf->my_addr) {
|
intf->target_addr != intf->my_addr) {
|
||||||
/* use IPMB address if needed */
|
/* use IPMB address if needed */
|
||||||
ipmb_addr.slave_addr = intf->target_addr;
|
ipmb_addr.slave_addr = intf->target_addr;
|
||||||
ipmb_addr.lun = req->msg.lun;
|
ipmb_addr.lun = req->msg.lun;
|
||||||
lprintf(LOG_DEBUG, "Sending request to "
|
lprintf(LOG_DEBUG, "Sending request to "
|
||||||
"IPMB target @ 0x%x (from 0x%x)", intf->target_addr,intf->my_addr);
|
"IPMB target @ 0x%x (from 0x%x)", intf->target_addr,intf->my_addr);
|
||||||
#ifdef ENABLE_INTF_OPEN_DUAL_BRIDGE
|
|
||||||
if(intf->transit_addr != 0 &&
|
if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
|
||||||
intf->transit_addr != intf->my_addr) {
|
uint8_t index = 0;
|
||||||
ipmb_addr.transit_slave_addr = intf->transit_addr;
|
|
||||||
lprintf(LOG_DEBUG, "Sending through transit "
|
lprintf(LOG_DEBUG, "Encapsulating data sent to "
|
||||||
"IPMB target @ 0x%x", intf->transit_addr);
|
"end target [0x%02x,0x%02x] using transit [0x%02x,0x%02x] from 0x%x ",
|
||||||
}
|
(0x40 | intf->target_channel),
|
||||||
#endif
|
intf->target_addr,
|
||||||
|
intf->transit_channel,
|
||||||
|
intf->transit_addr,
|
||||||
|
intf->my_addr
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Convert Message to 'Send Message' */
|
||||||
|
/* Supplied req : req , internal req : _req */
|
||||||
|
|
||||||
|
if (verbose > 4) {
|
||||||
|
fprintf(stderr, "Converting message:\n");
|
||||||
|
fprintf(stderr, " netfn = 0x%x\n", req->msg.netfn );
|
||||||
|
fprintf(stderr, " cmd = 0x%x\n", req->msg.cmd);
|
||||||
|
if (recv.msg.data && recv.msg.data_len) {
|
||||||
|
fprintf(stderr, " data_len = %d\n", req->msg.data_len);
|
||||||
|
fprintf(stderr, " data = %s\n",
|
||||||
|
buf2str(req->msg.data,req->msg.data_len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modify target address to use 'transit' instead */
|
||||||
|
ipmb_addr.slave_addr = intf->transit_addr;
|
||||||
|
ipmb_addr.channel = intf->transit_channel;
|
||||||
|
|
||||||
|
/* FIXME backup "My address" */
|
||||||
|
data_len = req->msg.data_len + 8;
|
||||||
|
data = malloc(data_len);
|
||||||
|
if (data == NULL) {
|
||||||
|
lprintf(LOG_ERR, "ipmitool: malloc failure");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(data, 0, data_len);
|
||||||
|
|
||||||
|
data[index++] = (0x40|intf->target_channel);
|
||||||
|
data[index++] = intf->target_addr;
|
||||||
|
data[index++] = ( req->msg.netfn << 2 ) | req->msg.lun ;
|
||||||
|
data[index++] = ipmi_csum(data+1, 2);
|
||||||
|
data[index++] = 0xFF; /* normally 0x20 , overwritten by IPMC */
|
||||||
|
data[index++] = ( (0) << 2) | 0 ; /* FIXME */
|
||||||
|
data[index++] = req->msg.cmd;
|
||||||
|
memcpy( (data+index) , req->msg.data, req->msg.data_len);
|
||||||
|
index += req->msg.data_len;
|
||||||
|
data[index++] = ipmi_csum( (data+4),(req->msg.data_len + 3) );
|
||||||
|
|
||||||
|
if (verbose > 4) {
|
||||||
|
fprintf(stderr, "Encapsulated message:\n");
|
||||||
|
fprintf(stderr, " netfn = 0x%x\n", IPMI_NETFN_APP );
|
||||||
|
fprintf(stderr, " cmd = 0x%x\n", 0x34 );
|
||||||
|
if (data && data_len) {
|
||||||
|
fprintf(stderr, " data_len = %d\n", data_len);
|
||||||
|
fprintf(stderr, " data = %s\n",
|
||||||
|
buf2str(data,data_len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_req.addr = (unsigned char *) &ipmb_addr;
|
_req.addr = (unsigned char *) &ipmb_addr;
|
||||||
_req.addr_len = sizeof(ipmb_addr);
|
_req.addr_len = sizeof(ipmb_addr);
|
||||||
} else {
|
} else {
|
||||||
/* otherwise use system interface */
|
/* otherwise use system interface */
|
||||||
lprintf(LOG_DEBUG+2, "Sending request to "
|
lprintf(LOG_DEBUG+2, "Sending request to "
|
||||||
"System Interface");
|
"System Interface");
|
||||||
bmc_addr.lun = req->msg.lun;
|
bmc_addr.lun = req->msg.lun;
|
||||||
_req.addr = (unsigned char *) &bmc_addr;
|
_req.addr = (unsigned char *) &bmc_addr;
|
||||||
_req.addr_len = sizeof(bmc_addr);
|
_req.addr_len = sizeof(bmc_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
_req.msgid = curr_seq++;
|
_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;
|
|
||||||
|
|
||||||
|
/* In case of a bridge request */
|
||||||
|
if( data != NULL && data_len != 0 ) {
|
||||||
|
_req.msg.data = data;
|
||||||
|
_req.msg.data_len = data_len;
|
||||||
|
_req.msg.netfn = IPMI_NETFN_APP;
|
||||||
|
_req.msg.cmd = 0x34;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_req.msg.data = req->msg.data;
|
||||||
|
_req.msg.data_len = req->msg.data_len;
|
||||||
|
_req.msg.netfn = req->msg.netfn;
|
||||||
|
_req.msg.cmd = req->msg.cmd;
|
||||||
|
}
|
||||||
|
|
||||||
if (ioctl(intf->fd, IPMICTL_SEND_COMMAND, &_req) < 0) {
|
if (ioctl(intf->fd, IPMICTL_SEND_COMMAND, &_req) < 0) {
|
||||||
lperror(LOG_ERR, "Unable to send command");
|
lperror(LOG_ERR, "Unable to send command");
|
||||||
return NULL;
|
if (data != NULL)
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wait for and retrieve response
|
* wait for and retrieve response
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (intf->noanswer)
|
if (intf->noanswer) {
|
||||||
return NULL;
|
if (data != NULL)
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
FD_ZERO(&rset);
|
FD_ZERO(&rset);
|
||||||
FD_SET(intf->fd, &rset);
|
FD_SET(intf->fd, &rset);
|
||||||
|
|
||||||
if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) {
|
if (select(intf->fd+1, &rset, NULL, NULL, NULL) < 0) {
|
||||||
lperror(LOG_ERR, "I/O Error");
|
lperror(LOG_ERR, "I/O Error");
|
||||||
return NULL;
|
if (data != NULL)
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
if (FD_ISSET(intf->fd, &rset) == 0) {
|
if (FD_ISSET(intf->fd, &rset) == 0) {
|
||||||
lprintf(LOG_ERR, "No data available");
|
lprintf(LOG_ERR, "No data available");
|
||||||
return NULL;
|
if (data != NULL)
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
recv.addr = (unsigned char *) &addr;
|
recv.addr = (unsigned char *) &addr;
|
||||||
@ -290,23 +303,56 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|||||||
|
|
||||||
/* get data */
|
/* get data */
|
||||||
if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
|
if (ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv) < 0) {
|
||||||
lperror(LOG_ERR, "Error receiving message");
|
lperror(LOG_ERR, "Error receiving message");
|
||||||
if (errno != EMSGSIZE)
|
if (errno != EMSGSIZE) {
|
||||||
return NULL;
|
if (data != NULL)
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose > 4) {
|
if (verbose > 4) {
|
||||||
fprintf(stderr, "Got message:");
|
fprintf(stderr, "Got message:");
|
||||||
fprintf(stderr, " type = %d\n", recv.recv_type);
|
fprintf(stderr, " type = %d\n", recv.recv_type);
|
||||||
fprintf(stderr, " channel = 0x%x\n", addr.channel);
|
fprintf(stderr, " channel = 0x%x\n", addr.channel);
|
||||||
fprintf(stderr, " msgid = %ld\n", recv.msgid);
|
fprintf(stderr, " msgid = %ld\n", recv.msgid);
|
||||||
fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn);
|
fprintf(stderr, " netfn = 0x%x\n", recv.msg.netfn);
|
||||||
fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd);
|
fprintf(stderr, " cmd = 0x%x\n", recv.msg.cmd);
|
||||||
if (recv.msg.data && recv.msg.data_len) {
|
if (recv.msg.data && recv.msg.data_len) {
|
||||||
fprintf(stderr, " data_len = %d\n", recv.msg.data_len);
|
fprintf(stderr, " data_len = %d\n", recv.msg.data_len);
|
||||||
fprintf(stderr, " data = %s\n",
|
fprintf(stderr, " data = %s\n",
|
||||||
buf2str(recv.msg.data, recv.msg.data_len));
|
buf2str(recv.msg.data, recv.msg.data_len));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(intf->transit_addr != 0 && intf->transit_addr != intf->my_addr) {
|
||||||
|
uint8_t index = 0;
|
||||||
|
|
||||||
|
/* ipmb_addr.transit_slave_addr = intf->transit_addr; */
|
||||||
|
lprintf(LOG_DEBUG, "Decapsulating data received from transit "
|
||||||
|
"IPMB target @ 0x%x", intf->transit_addr);
|
||||||
|
|
||||||
|
/* comp code */
|
||||||
|
/* Check data */
|
||||||
|
|
||||||
|
if( recv.msg.data[0] == 0 ) {
|
||||||
|
recv.msg.netfn = recv.msg.data[2] >> 2;
|
||||||
|
recv.msg.cmd = recv.msg.data[6];
|
||||||
|
|
||||||
|
recv.msg.data = memmove(recv.msg.data ,recv.msg.data+7 , recv.msg.data_len - 7);
|
||||||
|
recv.msg.data_len -=8;
|
||||||
|
|
||||||
|
if (verbose > 4) {
|
||||||
|
fprintf(stderr, "Decapsulated message:\n");
|
||||||
|
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) {
|
||||||
|
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 */
|
/* save completion code */
|
||||||
@ -315,10 +361,13 @@ ipmi_openipmi_send_cmd(struct ipmi_intf * intf, struct ipmi_rq * req)
|
|||||||
|
|
||||||
/* save response data for caller */
|
/* save response data for caller */
|
||||||
if (rsp.ccode == 0 && rsp.data_len > 0) {
|
if (rsp.ccode == 0 && rsp.data_len > 0) {
|
||||||
memmove(rsp.data, rsp.data + 1, rsp.data_len);
|
memmove(rsp.data, rsp.data + 1, rsp.data_len);
|
||||||
rsp.data[recv.msg.data_len] = 0;
|
rsp.data[recv.msg.data_len] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data != NULL)
|
||||||
|
free(data);
|
||||||
|
|
||||||
return &rsp;
|
return &rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +89,6 @@ struct ipmi_ipmb_addr {
|
|||||||
short channel;
|
short channel;
|
||||||
unsigned char slave_addr;
|
unsigned char slave_addr;
|
||||||
unsigned char lun;
|
unsigned char lun;
|
||||||
#ifdef ENABLE_INTF_OPEN_DUAL_BRIDGE
|
|
||||||
short transit_channel;
|
|
||||||
unsigned char transit_slave_addr;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IPMI_IOC_MAGIC 'i'
|
#define IPMI_IOC_MAGIC 'i'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user