blob: 3b64a35a7568b46027ed4b21b74841aefad9cddc [file] [log] [blame]
/*
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.
*/
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_mc.h>
#include <ipmitool/log.h>
/* Duplicate this into our memory space. Nothing in our code path calls this
* in a critical path.
*/
static IPMI_OEM sel_iana = IPMI_OEM_UNKNOWN;
const struct valstr completion_code_vals[] = {
{0x00, "Command completed normally"},
{0xc0, "Node busy"},
{0xc1, "Invalid command"},
{0xc2, "Invalid command on LUN"},
{0xc3, "Timeout"},
{0xc4, "Out of space"},
{0xc5, "Reservation cancelled or invalid"},
{0xc6, "Request data truncated"},
{0xc7, "Request data length invalid"},
{0xc8, "Request data field length limit exceeded"},
{0xc9, "Parameter out of range"},
{0xca, "Cannot return number of requested data bytes"},
{0xcb, "Requested sensor, data, or record not found"},
{0xcc, "Invalid data field in request"},
{0xcd, "Command illegal for specified sensor or record type"},
{0xce, "Command response could not be provided"},
{0xcf, "Cannot execute duplicated request"},
{0xd0, "SDR Repository in update mode"},
{0xd1, "Device firmeware in update mode"},
{0xd2, "BMC initialization in progress"},
{0xd3, "Destination unavailable"},
{0xd4, "Insufficient privilege level"},
{0xd5, "Command not supported in present state"},
{0xd6, "Cannot execute command, command disabled"},
{0xff, "Unspecified error"},
{0x00, NULL}};
const char* val2str(uint16_t val, const struct valstr* vs)
{
static char un_str[32];
int i;
for (i = 0; vs[i].str != NULL; i++)
{
if (vs[i].val == val)
return vs[i].str;
}
memset(un_str, 0, 32);
snprintf(un_str, 32, "Unknown (0x%02X)", val);
return un_str;
}
void ipmi_intf_session_set_timeout(struct ipmi_intf* intf, uint32_t timeout)
{
intf->ssn_params.timeout = timeout;
}
void ipmi_intf_session_set_retry(struct ipmi_intf* intf, int retry)
{
intf->ssn_params.retry = retry;
}
/* Nullify the methods we don't care about. */
void lprintf(int level, const char* format, ...)
{
return;
}
void lperror(int level, const char* format, ...)
{
return;
}
int verbose = 0;
const char* buf2str_extended(const uint8_t* buf, int len, const char* sep)
{
static char str[BUF2STR_MAXIMUM_OUTPUT_SIZE];
char* cur;
int i;
int sz;
int left;
int sep_len;
if (buf == NULL)
{
snprintf(str, sizeof(str), "<NULL>");
return (const char*)str;
}
cur = str;
left = sizeof(str);
if (sep)
{
sep_len = strlen(sep);
}
else
{
sep_len = 0;
}
for (i = 0; i < len; i++)
{
/* may return more than 2, depending on locale */
sz = snprintf(cur, left, "%2.2x", buf[i]);
if (sz >= left)
{
/* buffer overflow, truncate */
break;
}
cur += sz;
left -= sz;
/* do not write separator after last byte */
if (sep && i != (len - 1))
{
if (sep_len >= left)
{
break;
}
strncpy(cur, sep, left - sz);
cur += sep_len;
left -= sep_len;
}
}
*cur = '\0';
return (const char*)str;
}
const char* buf2str(const uint8_t* buf, int len)
{
return buf2str_extended(buf, len, NULL);
}
uint8_t ipmi_csum(uint8_t* d, int s)
{
uint8_t c = 0;
for (; s > 0; s--, d++)
c += *d;
return -c;
}
void printbuf(const uint8_t* buf, int len, const char* desc)
{
int i;
if (len <= 0)
return;
if (verbose < 1)
return;
fprintf(stderr, "%s (%d bytes)\n", desc, len);
for (i = 0; i < len; i++)
{
if (((i % 16) == 0) && (i != 0))
fprintf(stderr, "\n");
fprintf(stderr, " %2.2x", buf[i]);
}
fprintf(stderr, "\n");
}
IPMI_OEM
ipmi_get_oem(struct ipmi_intf* intf)
{
/* Execute a Get Device ID command to determine the OEM */
struct ipmi_rs* rsp;
struct ipmi_rq req;
struct ipm_devid_rsp* devid;
if (intf->fd == 0)
{
if (sel_iana != IPMI_OEM_UNKNOWN)
{
return sel_iana;
}
return IPMI_OEM_UNKNOWN;
}
/*
* Return the cached manufacturer id if the device is open and
* we got an identified OEM owner. Otherwise just attempt to read
* it.
*/
if (intf->opened && intf->manufacturer_id != IPMI_OEM_UNKNOWN)
{
return intf->manufacturer_id;
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = BMC_GET_DEVICE_ID;
req.msg.data_len = 0;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL)
{
lprintf(LOG_ERR, "Get Device ID command failed");
return IPMI_OEM_UNKNOWN;
}
if (rsp->ccode > 0)
{
lprintf(LOG_ERR, "Get Device ID command failed: %#x %s", rsp->ccode,
val2str(rsp->ccode, completion_code_vals));
return IPMI_OEM_UNKNOWN;
}
devid = (struct ipm_devid_rsp*)rsp->data;
lprintf(LOG_DEBUG, "Iana: %u",
IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id));
return IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id);
}