Compare commits

..

1 Commits

Author SHA1 Message Date
57dc21a486 fru: Reduce duplicate code
Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
2019-03-07 19:44:54 +03:00
18 changed files with 382 additions and 1410 deletions

View File

@ -1,37 +1,10 @@
language: C
sudo: enabled
before_install:
- sudo apt-get install -y libssl-dev
before_script:
- ./bootstrap
addons:
apt:
update: true
packages:
- libssl-dev
homebrew:
packages:
- openssl
matrix:
include:
- os: linux
dist: xenial
addons:
apt:
packages:
- libsystemd-dev
script:
- ./configure --enable-intf-dummy --enable-intf-dbus
- make
- sudo make install
- os: linux
dist: trusty
script:
- ./configure --enable-intf-dummy
- make
- sudo make install
- os: osx
osx_image: xcode10.2
script:
- ./configure --enable-intf-dummy
- make
- sudo make install
script:
- ./configure --enable-intf-dummy
- make
- sudo make install

32
INSTALL
View File

@ -9,33 +9,17 @@ are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Prerequisites
=============
This project requires at least gcc 4.8.1 as it uses some GNU
extensions and some C11 features. For `lanplus` interface the OpenSSL
library and development headers are required. As of April 2019, the
project is tested automatically to build cleanly for the following
64-bit operating systems:
- Ubuntu 14.04 Trusty
- Ubuntu 16.04 Xenial
- MacOS X 10.14 (Xcode 10.2)
Basic Installation
==================
Briefly, the followong shell command should configure, build, and
install this package:
`./bootstrap && ./configure && make && make install`
The following more-detailed instructions are generic; see the
`README' file for instructions specific to this package. Some
packages provide this `INSTALL' file but do not implement all of the
features documented below. The lack of an optional feature in a given
package is not necessarily a bug. More recommendations for GNU
packages can be found in *note Makefile Conventions:
(standards)Makefile Conventions.
Briefly, the shell command `./configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses

View File

@ -59,7 +59,6 @@ dnl
xenable_all_options=yes
xenable_intf_bmc=no
xenable_intf_dbus=no
xenable_intf_dummy=no
xenable_intf_imb=yes
xenable_intf_lipmi=yes
@ -192,14 +191,6 @@ AC_CHECK_LIB([crypto], [MD2_Init],
fi],
[], [-lcrypto])
dnl check for libsystemd in case dbus-intf is requested
AC_CHECK_LIB([systemd], [sd_bus_default],
[
LIBS="$LIBS -lsystemd"
have_systemd=yes
],
[ have_systemd=no],[])
dnl enable IPMIv1.5 LAN interface
AC_ARG_ENABLE([intf-lan],
[AC_HELP_STRING([--enable-intf-lan],
@ -563,25 +554,6 @@ if test "x$xenable_intf_bmc" = "xyes"; then
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB bmc/libintf_bmc.la"
fi
dnl enable IPMI dbus interface
AC_ARG_ENABLE([intf-dbus],
[AC_HELP_STRING([--enable-intf-dbus],
[enable IPMI dbus interface [default=no]])],
[xenable_intf_dbus=$enableval],
[xenable_intf_dbus=no])
if test "x$xenable_intf_dbus" != "xno"; then
if test "x$have_systemd" != "xyes"; then
AC_MSG_ERROR([** Unable to find libsystemd required by dbus-intf.])
xenable_intf_dbus=no
fi
fi
if test "x$xenable_intf_dbus" = "xyes"; then
AC_DEFINE(IPMI_INTF_DBUS, [1], [Define to 1 to enable dbus interface.])
AC_SUBST(INTF_DBUS, [dbus])
AC_SUBST(INTF_DBUS_LIB, [libintf_dbus.la])
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB dbus/libintf_dbus.la"
fi
dnl enable Dummy interface for testing
AC_ARG_ENABLE([intf-dummy],
[AC_HELP_STRING([--enable-intf-dummy],
@ -671,25 +643,6 @@ AC_TRY_COMPILE([],[
[Define to 1 if you need to use #pragma pack instead of __attribute__ ((packed))])]
)
dnl if no environment variable is set, set the default value for the default intf
if test "${xenable_intf_open}" = "xyes"; then
DEFAULT_INTF_NO_ENV=open
else dnl macOS does not build open interface, it defaults to lan
DEFAULT_INTF_NO_ENV=lan
fi
dnl allow for a default interface to be set on configure
AC_ARG_VAR(DEFAULT_INTF, [Set the default interface to use (default=${DEFAULT_INTF_NO_ENV})])
dnl set the default value for the default interface environment variable
if test "x${DEFAULT_INTF}" == "x"; then
echo "DEFAULT_INTF not found in environment; setting to ${DEFAULT_INTF_NO_ENV}"
DEFAULT_INTF=${DEFAULT_INTF_NO_ENV}
fi
xdefault_intf_is_enabled="xenable_intf_${DEFAULT_INTF}"
if test "x${!xdefault_intf_is_enabled}" != "xyes"; then
AC_MSG_ERROR([** Cannot set ${DEFAULT_INTF} as default; ${DEFAULT_INTF} is not enabled. :${!xdefault_intf_is_enabled}:])
fi
dnl Generate files for build
AC_CONFIG_FILES([Makefile
@ -711,7 +664,6 @@ AC_CONFIG_FILES([Makefile
src/plugins/free/Makefile
src/plugins/imb/Makefile
src/plugins/bmc/Makefile
src/plugins/dbus/Makefile
src/plugins/usb/Makefile
src/plugins/lipmi/Makefile
src/plugins/serial/Makefile
@ -722,14 +674,13 @@ AC_OUTPUT
AC_MSG_RESULT([])
AC_MSG_RESULT([ipmitool $VERSION])
AC_MSG_RESULT([])
AC_MSG_RESULT([Interfaces (default=$DEFAULT_INTF)])
AC_MSG_RESULT([Interfaces])
AC_MSG_RESULT([ lan : $xenable_intf_lan])
AC_MSG_RESULT([ lanplus : $xenable_intf_lanplus])
AC_MSG_RESULT([ open : $xenable_intf_open])
AC_MSG_RESULT([ free : $xenable_intf_free])
AC_MSG_RESULT([ imb : $xenable_intf_imb])
AC_MSG_RESULT([ bmc : $xenable_intf_bmc])
AC_MSG_RESULT([ dbus : $xenable_intf_dbus])
AC_MSG_RESULT([ usb : $xenable_intf_usb])
AC_MSG_RESULT([ lipmi : $xenable_intf_lipmi])
AC_MSG_RESULT([ serial : $xenable_intf_serial])

View File

@ -1,8 +1,7 @@
[Unit]
Description=Exchange Information between BMC and OS
After=network.target
AssertFileIsExecutable=/usr/bin/ipmitool
AssertPathExistsGlob=/dev/ipmi*
After=ipmi.service network.target
Requires=ipmi.service
[Service]
Type=oneshot

View File

@ -384,23 +384,39 @@ application (ipmi or sol) on the given channel.
\fIstatus\fP
Status information related to power, buttons, cooling, drives and faults.
.RS
.RE
.TP
\fIpower\fP
.RS
.TP
\fIstatus\fP
.RS
.RE
.TP
\fIon\fP
.RS
.RE
.TP
\fIoff\fP
.RS
.RE
.TP
\fIcycle\fP
.RS
.RE
.TP
\fIreset\fP
.RS
.RE
.TP
\fIdiag\fP
.RS
.RE
.TP
\fIsoft\fP
.RS
.RE
.RE
.TP
\fIidentify\fP [<seconds>|force]
@ -412,6 +428,8 @@ Default is 15 seconds.
0 - Off
.br
force - To turn on indefinitely
.RS
.RE
.TP
\fIpolicy\fP
@ -421,22 +439,34 @@ What to do when power is restored.
\fIlist\fP
Show available options.
.RS
.RE
.TP
\fIalways-on\fP
.RS
.RE
.TP
\fIprevious\fP
.RS
.RE
.TP
\fIalways-off\fP
.RS
.RE
.RE
.TP
\fIrestart_cause\fP
Last restart cause.
.RS
.RE
.TP
\fIpoh\fP
Get power on hours.
.RS
.RE
.TP
\fIbootdev\fP
.RS
@ -444,123 +474,95 @@ Get power on hours.
\fInone\fP
Do not change boot device order.
.RS
.RE
.TP
\fIpxe\fP
Force PXE boot.
.RS
.RE
.TP
\fIdisk\fP
Force boot from default Hard-drive.
.RS
.RE
.TP
\fIsafe\fP
Force boot from default Hard-drive, request Safe Mode.
.RS
.RE
.TP
\fIdiag\fP
Force boot from Diagnostic Partition.
.RS
.RE
.TP
\fIcdrom\fP
Force boot from CD/DVD.
.RS
.RE
.TP
\fIbios\fP
Force boot into BIOS Setup.
.RS
.RE
.TP
\fIfloppy\fP
Force boot from Floppy/primary removable media.
.RE
.TP
\fIbootmbox\fP \fIget\fP [text] [block <\fBblock#\fP>]
Read the Boot Initiator Mailbox in hex dump or in text mode.
By default the whole mailbox is read. If block number is specified,
that particular block is read. For block 0 or when the whole
mailbox is read, the Boot Initiator IANA Enterprise Number and
the corresponding enterprise name are printed.
.TP
\fIbootmbox\fP \fIset\fP text [block <\fBblock#\fP>] <\fBIANA_PEN\fP> "<\fBdata_string\fP>"
Write the specified <block> or the entire Boot Initiator Mailbox in text mode.
It is required to specify a decimal IANA Enterprise Number recognized
by the boot initiator on the target system. Refer to your target system
manufacturer for details. The rest of the arguments are a text string.
When single block write is requested, the total length of <data> may not
exceed 13 bytes for block 0, or 16 bytes otherwise.
.TP
\fIbootmbox\fP \fIset\fP [block <\fBblock#\fP>] <\fBIANA_PEN\fP> <\fBdata_byte\fP> [<\fBdata_byte\fP> ...]
Same as above, but the arguments after IANA PEN are separate
data byte values separated by spaces.
.TP
\fIbootparam\fP \fIget\fP <\fBopt_id\fR> [<\fBopt_param\fR>]
Get value of system boot option number <\fBopt_id\fR>. Some boot
options (e.g. option 7) can also take an optional numeric parameter.
.TP
\fIbootparam\fP \fIset\fP bootflag <\fBdevice\fR> [options=...]
Set a boot flag. Valid devices are:
.RS
.IP \fIforce_pxe\fP
.RE
.RE
.TP
\fIbootparam\fP
.RS
.TP
\fIforce_pxe\fP
Force PXE boot
.IP \fIforce_disk\fP
.RS
.RE
.TP
\fIforce_disk\fP
Force boot from default Hard-drive
.IP \fIforce_safe\fP
.RS
.RE
.TP
\fIforce_safe\fP
Force boot from default Hard-drive, request Safe Mode
.IP \fIforce_diag\fP
.RS
.RE
.TP
\fIforce_diag\fP
Force boot from Diagnostic Partition
.IP \fIforce_cdrom\fP
.RS
.RE
.TP
\fIforce_cdrom\fP
Force boot from CD/DVD
.IP \fIforce_bios\fP
.RS
.RE
.TP
\fIforce_bios\fP
Force boot into BIOS Setup
.PP
Valid options are:
.IP \fIPEF\fP
Clear valid bit on reset/power cycle cause by PEF
.IP \fItimeout\fP
Automatically clear boot flag valid bit on timeout
.IP \fIwatchdog\fP
Clear valid bit on reset/power cycle cause by watchdog
.IP \fIreset\fP
Clear valid bit on push button reset/soft reset
.IP \fIpower\fP
Clear valid bit on power up via power push button or wake event
.RS
.RE
.RE
.TP
\fIselftest\fP
Get the chassis self-test results
.RS
.RE
.RE
.TP
\fIdcmi\fP
@ -955,6 +957,8 @@ Shows Extended SD Card information.
\fIecho\fP
For echoing lines to stdout in scripts.
.RS
.RE
.TP
\fIekanalyzer\fP <\fBcommand\fR> <\fBxx=filename1\fR> <\fBxx=filename2\fR> [<\fBrc=filename3\fR>] \fB...\fR
.RS
@ -1506,14 +1510,20 @@ Show firmware upgrade log.
\fIlist\fP
List All Generic Device Locators.
.RS
.RE
.TP
\fIread\fP <\fBsdr name\fR> <\fBfile\fR>
Read to file eeprom specify by Generic Device Locators.
.RS
.RE
.TP
\fIwrite\fP <\fBsdr name\fR> <\fBfile\fR>
Write from file eeprom specify by Generic Device Locators
.RS
.RE
.RE
.TP
\fIhpm\fP
@ -3140,34 +3150,50 @@ or by using the keyword `all' to specify all sessions.
\fIhostname\fP <\fBhost\fR>
Session hostname.
.RS
.RE
.TP
\fIusername\fP <\fBuser\fR>
Session username.
.RS
.RE
.TP
\fIpassword\fP <\fBpass\fR>
Session password.
.RS
.RE
.TP
\fIprivlvl\fP <\fBlevel\fR>
Session privilege level force.
.RS
.RE
.TP
\fIauthtype\fP <\fBtype\fR>
Authentication type force.
.RS
.RE
.TP
\fIlocaladdr\fP <\fBaddr\fR>
Local IPMB address.
.RS
.RE
.TP
\fItargetaddr\fP <\fBaddr\fR>
Remote target IPMB address.
.RS
.RE
.TP
\fIport\fP <\fBport\fR>
Remote RMCP port.
.RS
.RE
.TP
\fIcsv\fP [\fBlevel\fR]
@ -3175,10 +3201,14 @@ Enable output in comma separated format.
Affects following commands:
\fIuser\fP, \fIchannel\fP, \fIisol\fP, \fIsunoem\fP,
\fIsol\fP, \fIsensor\fP, \fIsdr\fP, \fIsel\fP, \fIsession\fP.
.RS
.RE
.TP
\fIverbose\fP [\fBverbose\fR]
Verbosity level.
.RS
.RE
.RE
.TP
\fIshell\fP

View File

@ -38,7 +38,6 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h> /* For free() */
#include <stdbool.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
@ -80,10 +79,6 @@ struct oemvalstr {
const char * str;
};
const char *
specific_val2str(uint16_t val,
const struct valstr *specific,
const struct valstr *generic);
const char * val2str(uint16_t val, const struct valstr * vs);
const char * oemval2str(uint32_t oem,uint16_t val, const struct oemvalstr * vs);
@ -97,8 +92,6 @@ int str2ushort(const char * str, uint16_t * ushrt_ptr);
int str2char(const char * str, int8_t * chr_ptr);
int str2uchar(const char * str, uint8_t * uchr_ptr);
bool args2buf(int argc, char *argv[], uint8_t *out, size_t len);
int eval_ccode(const int ccode);
int is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr);
@ -173,13 +166,6 @@ static inline uint32_t ipmi24toh(void *ipmi24)
return h;
}
static inline void htoipmi24(uint32_t h, uint8_t *ipmi)
{
ipmi[0] = h & 0xFF; /* LSB */
ipmi[1] = (h >> 8) & 0xFF;
ipmi[2] = (h >> 16) & 0xFF; /* MSB */
}
static inline uint32_t ipmi32toh(void *ipmi32)
{
uint8_t *ipmi = ipmi32;

View File

@ -37,7 +37,6 @@
# include <config.h>
#endif
#include <stdbool.h>
#include <inttypes.h>
#include <math.h>
#include <ipmitool/bswap.h>
@ -382,29 +381,6 @@ struct sdr_record_common_sensor {
struct sdr_record_mask mask;
/* IPMI 2.0, Table 43-1, byte 21[7:6] Analog (numeric) Data Format */
#define SDR_UNIT_FMT_UNSIGNED 0 /* unsigned */
#define SDR_UNIT_FMT_1S_COMPL 1 /* 1's complement (signed) */
#define SDR_UNIT_FMT_2S_COMPL 2 /* 2's complement (signed) */
#define SDR_UNIT_FMT_NA 3 /* does not return analog (numeric) reading */
/* IPMI 2.0, Table 43-1, byte 21[5:3] Rate */
#define SDR_UNIT_RATE_NONE 0 /* none */
#define SDR_UNIT_RATE_MICROSEC 1 /* per us */
#define SDR_UNIT_RATE_MILLISEC 2 /* per ms */
#define SDR_UNIT_RATE_SEC 3 /* per s */
#define SDR_UNIT_RATE_MIN 4 /* per min */
#define SDR_UNIT_RATE_HR 5 /* per hour */
#define SDR_UNIT_RATE_DAY 6 /* per day */
#define SDR_UNIT_RATE_RSVD 7 /* reserved */
/* IPMI 2.0, Table 43-1, byte 21[2:1] Modifier Unit */
#define SDR_UNIT_MOD_NONE 0 /* none */
#define SDR_UNIT_MOD_DIV 1 /* Basic Unit / Modifier Unit */
#define SDR_UNIT_MOD_MUL 2 /* Basic Unit * Mofifier Unit */
#define SDR_UNIT_MOD_RSVD 3 /* Reserved */
/* IPMI 2.0, Table 43-1, byte 21[0] Percentage */
#define SDR_UNIT_PCT_NO 0
#define SDR_UNIT_PCT_YES 1
struct {
#if WORDS_BIGENDIAN
uint8_t analog:2;
@ -418,8 +394,8 @@ struct sdr_record_common_sensor {
uint8_t analog:2;
#endif
struct {
uint8_t base; /* Base unit type code per IPMI 2.0 Table 43-15 */
uint8_t modifier; /* Modifier unit type code per Table 43-15 */
uint8_t base;
uint8_t modifier;
} ATTRIBUTE_PACKING type;
} ATTRIBUTE_PACKING unit;
} ATTRIBUTE_PACKING;
@ -857,8 +833,8 @@ void ipmi_sdr_print_sensor_hysteresis(struct sdr_record_common_sensor *sensor,
struct sdr_record_full_sensor *full,
uint8_t hysteresis_value,
const char *hdrstr);
const char *ipmi_sdr_get_unit_string(bool pct, uint8_t type,
uint8_t base, uint8_t modifier);
const char *ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type,
uint8_t base, uint8_t modifier);
struct sensor_reading *
ipmi_sdr_read_sensor_value(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,

View File

@ -67,9 +67,7 @@ parse_pen_list() {
}
END {
if(PEN) {
print "{ " PEN ", \"" ENTERPRISE "\" },"
}
print "{ " PEN ", \"" ENTERPRISE "\" },"
}'
}

View File

@ -319,74 +319,26 @@ mac2str(const uint8_t *buf)
return buf2str_extended(buf, 6, ":");
}
/**
* Find the index of value in a valstr array
*
* @param[in] val The value to search for
* @param[in] vs The valstr array to search in
* @return >=0 The index into \p vs
* @return -1 Error: value \p val was not found in \p vs
*/
static
inline
off_t find_val_idx(uint16_t val, const struct valstr *vs)
{
if (vs) {
for (off_t i = 0; vs[i].str; ++i) {
if (vs[i].val == val) {
return i;
}
}
}
return -1;
}
/**
* Generate a statically allocated 'Unknown' string for the provided value.
* The function is not thread-safe (as most of ipmitool).
*
* @param[in] val The value to put into the string
* @returns A pointer to a statically allocated string
*/
static
inline
const char *unknown_val_str(uint16_t val)
const char * val2str(uint16_t val, const struct valstr *vs)
{
static char un_str[32];
int i;
for (i = 0; vs[i].str; 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;
}
const char *
specific_val2str(uint16_t val,
const struct valstr *specific,
const struct valstr *generic)
{
int i;
if (0 <= (i = find_val_idx(val, specific))) {
return specific[i].str;
}
if (0 <= (i = find_val_idx(val, generic))) {
return generic[i].str;
}
return unknown_val_str(val);
}
const char * val2str(uint16_t val, const struct valstr *vs)
{
return specific_val2str(val, NULL, vs);
}
const char * oemval2str(uint32_t oem, uint16_t val,
const struct oemvalstr *vs)
{
static char un_str[32];
int i;
for (i = 0; vs[i].oem != 0xffffff && vs[i].str; i++) {
@ -397,7 +349,10 @@ const char * oemval2str(uint32_t oem, uint16_t val,
}
}
return unknown_val_str(val);
memset(un_str, 0, 32);
snprintf(un_str, 32, "Unknown (0x%X)", val);
return un_str;
}
/* str2double - safely convert string to double
@ -1125,35 +1080,3 @@ ipmi_get_oem_id(struct ipmi_intf *intf)
return oem_id;
}
/** Parse command line arguments as numeric byte values (dec or hex)
* and store them in a \p len sized buffer \p out.
*
* @param[in] argc Number of arguments
* @param[in] argv Array of arguments
* @param[out] out The output buffer
* @param[in] len Length of the output buffer in bytes (no null-termination
* is assumed, the input data is treated as raw byte values,
* not as a string.
*
* @returns A success status indicator
* @return false Error
* @return true Success
*/
bool
args2buf(int argc, char *argv[], uint8_t *out, size_t len)
{
size_t i;
for (i = 0; i < len && i < (size_t)argc; ++i) {
uint8_t byte;
if (str2uchar(argv[i], &byte)) {
lprintf(LOG_ERR, "Bad byte value: %s", argv[i]);
return false;
}
out[i] = byte;
}
return true;
}

View File

@ -34,8 +34,6 @@
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <limits.h>
#include <ipmitool/bswap.h>
#include <ipmitool/helper.h>
@ -46,40 +44,8 @@
#include <ipmitool/ipmi_chassis.h>
#include <ipmitool/ipmi_time.h>
#define CHASSIS_BOOT_MBOX_IANA_SZ 3
#define CHASSIS_BOOT_MBOX_BLOCK_SZ 16
#define CHASSIS_BOOT_MBOX_BLOCK0_SZ \
(CHASSIS_BOOT_MBOX_BLOCK_SZ - CHASSIS_BOOT_MBOX_IANA_SZ)
#define CHASSIS_BOOT_MBOX_MAX_BLOCK 0xFF
#define CHASSIS_BOOT_MBOX_MAX_BLOCKS (CHASSIS_BOOT_MBOX_MAX_BLOCK + 1)
typedef struct {
uint8_t iana[CHASSIS_BOOT_MBOX_IANA_SZ];
uint8_t data[CHASSIS_BOOT_MBOX_BLOCK0_SZ];
} mbox_b0_data_t;
typedef struct {
uint8_t block;
union {
uint8_t data[CHASSIS_BOOT_MBOX_BLOCK_SZ];
mbox_b0_data_t b0;
};
} mbox_t;
extern int verbose;
static const struct valstr get_bootparam_cc_vals[] = {
{ 0x80, "Unsupported parameter" },
{ 0x00, NULL }
};
static const struct valstr set_bootparam_cc_vals[] = {
{ 0x80, "Unsupported parameter" },
{ 0x81, "Attempt to set 'in progress' while not in 'complete' state" },
{ 0x82, "Parameter is read-only" },
{ 0x00, NULL }
};
int
ipmi_chassis_power_status(struct ipmi_intf * intf)
{
@ -480,166 +446,61 @@ ipmi_chassis_selftest(struct ipmi_intf * intf)
}
static int
ipmi_chassis_set_bootparam(struct ipmi_intf * intf,
uint8_t param, void *data, int len)
ipmi_chassis_set_bootparam(struct ipmi_intf * intf, uint8_t param, uint8_t * data, int len)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct {
uint8_t param;
uint8_t data[];
} *msg_data;
int rc = -1;
size_t msgsize = 1 + len; /* Single-byte parameter plus the data */
static const uint8_t BOOTPARAM_MASK = 0x7F;
uint8_t msg_data[16];
msg_data = malloc(msgsize);
if (!msg_data) {
goto out;
}
memset(msg_data, 0, msgsize);
msg_data->param = param & BOOTPARAM_MASK;
memcpy(msg_data->data, data, len);
memset(msg_data, 0, 16);
msg_data[0] = param & 0x7f;
memcpy(msg_data+1, data, len);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_CHASSIS;
req.msg.cmd = 0x8;
req.msg.data = (uint8_t *)msg_data;
req.msg.data_len = msgsize;
req.msg.data = msg_data;
req.msg.data_len = len + 1;
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
lprintf(LOG_ERR, "Error setting Chassis Boot Parameter %d", param);
return -1;
}
rc = rsp->ccode;
if (rc) {
if (rsp->ccode) {
if (param != 0) {
lprintf(LOG_ERR,
"Set Chassis Boot Parameter %d failed: %s",
param,
specific_val2str(rsp->ccode,
set_bootparam_cc_vals,
completion_code_vals));
lprintf(LOG_ERR, "Set Chassis Boot Parameter %d failed: %s",
param, val2str(rsp->ccode, completion_code_vals));
}
goto out;
return -1;
}
lprintf(LOG_DEBUG, "Chassis Set Boot Parameter %d to %s", param, buf2str(data, len));
out:
free_n(&msg_data);
return rc;
}
/* Flags to ipmi_chassis_get_bootparam() */
typedef enum {
PARAM_NO_GENERIC_INFO, /* Do not print generic boot parameter info */
PARAM_NO_DATA_DUMP, /* Do not dump parameter data */
PARAM_NO_RANGE_ERROR, /* Do not report out of range info to user */
PARAM_SPECIFIC /* Parameter-specific flags start with this */
} chassis_bootparam_flags_t;
/* Flags to ipmi_chassis_get_bootparam() for Boot Mailbox parameter (7) */
typedef enum {
MBOX_PARSE_USE_TEXT = PARAM_SPECIFIC, /* Use text output vs. hex */
MBOX_PARSE_ALLBLOCKS /* Parse all blocks, not just one */
} chassis_bootmbox_parse_t;
#define BP_FLAG(x) (1 << (x))
static
void
chassis_bootmailbox_parse(void *buf, size_t len, int flags)
{
void *blockdata;
size_t datalen;
bool use_text = flags & BP_FLAG(MBOX_PARSE_USE_TEXT);
bool all_blocks = flags & BP_FLAG(MBOX_PARSE_ALLBLOCKS);
mbox_t *mbox;
if (!buf || !len) {
return;
}
mbox = buf;
blockdata = mbox->data;
datalen = len - sizeof(mbox->block);
if (!all_blocks) {
/* Print block selector only if a single block is printed */
printf(" Selector : %d\n", mbox->block);
}
if (!mbox->block) {
uint32_t iana = ipmi24toh(mbox->b0.iana);
/* For block zero print the IANA Private Enterprise Number */
printf(" IANA PEN : %" PRIu32 " [%s]\n",
iana,
val2str(iana, ipmi_oem_info));
blockdata = mbox->b0.data;
datalen -= sizeof(mbox->b0.iana);
}
printf(" Block ");
if (all_blocks) {
printf("%3" PRIu8 " Data : ", mbox->block);
}
else {
printf("Data : ");
}
if (use_text) {
/* Ensure the data string is null-terminated */
unsigned char text[CHASSIS_BOOT_MBOX_BLOCK_SZ + 1] = { 0 };
memcpy(text, blockdata, datalen);
printf("'%s'\n", text);
}
else {
printf("%s\n", buf2str(blockdata, datalen));
}
return 0;
}
static int
ipmi_chassis_get_bootparam(struct ipmi_intf * intf,
int argc, char *argv[], int flags)
ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[3];
uint8_t param_id = 0;
bool skip_generic = flags & BP_FLAG(PARAM_NO_GENERIC_INFO);
bool skip_data = flags & BP_FLAG(PARAM_NO_DATA_DUMP);
bool skip_range = flags & BP_FLAG(PARAM_NO_RANGE_ERROR);
int rc = -1;
if (argc < 1 || !argv[0]) {
goto out;
if (!arg)
return -1;
if (str2uchar(arg, &param_id) != 0) {
lprintf(LOG_ERR, "Invalid parameter '%s' given instead of bootparam.",
arg);
return (-1);
}
if (str2uchar(argv[0], &param_id)) {
lprintf(LOG_ERR,
"Invalid parameter '%s' given instead of bootparam.",
argv[0]);
goto out;
}
--argc;
++argv;
memset(msg_data, 0, 3);
msg_data[0] = param_id & 0x7f;
if (argc) {
if (str2uchar(argv[0], &msg_data[1])) {
lprintf(LOG_ERR,
"Invalid argument '%s' given to"
" bootparam %" PRIu8,
argv[0], msg_data[1]);
goto out;
}
}
msg_data[1] = 0;
msg_data[2] = 0;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_CHASSIS;
@ -649,21 +510,12 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf,
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
lprintf(LOG_ERR,
"Error Getting Chassis Boot Parameter %" PRIu8,
msg_data[0]);
return -1;
}
if (IPMI_CC_PARAM_OUT_OF_RANGE == rsp->ccode && skip_range) {
lprintf(LOG_ERR, "Error Getting Chassis Boot Parameter %s", arg);
return -1;
}
if (rsp->ccode) {
lprintf(LOG_ERR,
"Get Chassis Boot Parameter %" PRIu8 " failed: %s",
msg_data[0],
specific_val2str(rsp->ccode,
get_bootparam_cc_vals,
completion_code_vals));
lprintf(LOG_ERR, "Get Chassis Boot Parameter %s failed: %s",
arg, val2str(rsp->ccode, completion_code_vals));
return -1;
}
@ -673,17 +525,10 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf,
param_id = 0;
param_id = (rsp->data[1] & 0x7f);
if (!skip_generic) {
printf("Boot parameter version: %d\n", rsp->data[0]);
printf("Boot parameter %d is %s\n", rsp->data[1] & 0x7f,
(rsp->data[1] & 0x80)
? "invalid/locked"
: "valid/unlocked");
if (!skip_data) {
printf("Boot parameter data: %s\n",
buf2str(rsp->data+2, rsp->data_len - 2));
}
}
printf("Boot parameter version: %d\n", rsp->data[0]);
printf("Boot parameter %d is %s\n", rsp->data[1] & 0x7f,
(rsp->data[1] & 0x80) ? "invalid/locked" : "valid/unlocked");
printf("Boot parameter data: %s\n", buf2str(rsp->data+2, rsp->data_len - 2));
switch(param_id)
{
@ -871,18 +716,17 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf,
}
break;
case 7:
chassis_bootmailbox_parse(rsp->data + 2,
rsp->data_len - 2,
flags);
break;
{
printf(" Selector : %d\n", rsp->data[2] );
printf(" Block Data : %s\n", buf2str(rsp->data+3, rsp->data_len - 2));
}
break;
default:
printf(" Unsupported parameter %" PRIu8 "\n", param_id);
printf(" Undefined byte\n");
break;
}
rc = IPMI_CC_OK;
out:
return rc;
return 0;
}
static int
@ -988,10 +832,7 @@ ipmi_chassis_get_bootvalid(struct ipmi_intf * intf)
}
if (rsp->ccode) {
lprintf(LOG_ERR, "Get Chassis Boot Parameter %d failed: %s",
param_id,
specific_val2str(rsp->ccode,
get_bootparam_cc_vals,
completion_code_vals));
param_id, val2str(rsp->ccode, completion_code_vals));
return -1;
}
@ -1001,97 +842,77 @@ ipmi_chassis_get_bootvalid(struct ipmi_intf * intf)
return(rsp->data[2]);
}
typedef enum {
SET_COMPLETE,
SET_IN_PROGRESS,
COMMIT_WRITE,
RESERVED
} progress_t;
static
void
chassis_bootparam_set_in_progress(struct ipmi_intf *intf, progress_t progress)
{
/*
* By default try to set/clear set-in-progress parameter before/after
* changing any boot parameters. If setting fails, the code will set
* this flag to false and stop trying to fiddle with it for future
* requests.
*/
static bool use_progress = true;
uint8_t flag = progress;
int rc;
if (!use_progress) {
return;
}
rc = ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
&flag, 1);
/*
* Only disable future checks if set in progress status setting failed.
* Setting of other statuses may fail legitimately.
*/
if (rc && SET_IN_PROGRESS == progress) {
use_progress = false;
}
}
typedef enum {
BIOS_POST_ACK = 1 << 0,
OS_LOADER_ACK = 1 << 1,
OS_SERVICE_PARTITION_ACK = 1 << 2,
SMS_ACK = 1 << 3,
OEM_ACK = 1 << 4,
RESERVED_ACK_MASK = 7 << 5
} bootinfo_ack_t;
static
int
chassis_bootparam_clear_ack(struct ipmi_intf *intf, bootinfo_ack_t flag)
{
uint8_t flags[2] = { flag & ~RESERVED_ACK_MASK,
flag & ~RESERVED_ACK_MASK };
return ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_INFO_ACK,
flags, 2);
}
static int
ipmi_chassis_set_bootvalid(struct ipmi_intf *intf, uint8_t set_flag, uint8_t clr_flag)
{
int bootvalid;
uint8_t flags[2];
int rc;
uint8_t flags[5];
int rc = 0;
int use_progress = 1;
uint8_t param_id = IPMI_CHASSIS_BOOTPARAM_FLAG_VALID;
chassis_bootparam_set_in_progress(intf, SET_IN_PROGRESS);
rc = chassis_bootparam_clear_ack(intf, BIOS_POST_ACK);
if (use_progress) {
/* set set-in-progress flag */
memset(flags, 0, 5);
flags[0] = 0x01;
rc = ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1);
if (rc < 0)
use_progress = 0;
}
if (rc) {
goto out;
memset(flags, 0, 5);
flags[0] = 0x01;
flags[1] = 0x01;
rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK,
flags, 2);
if (rc < 0) {
if (use_progress) {
/* set-in-progress = set-complete */
memset(flags, 0, 5);
ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
flags, 1);
}
return -1;
}
bootvalid = ipmi_chassis_get_bootvalid(intf);
if (bootvalid < 0) {
lprintf(LOG_ERR, "Failed to read boot valid flag");
rc = bootvalid;
goto out;
if (use_progress) {
/* set-in-progress = set-complete */
memset(flags, 0, 5);
ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
flags, 1);
}
return -1;
}
flags[0] = (bootvalid & ~clr_flag) | set_flag;
rc = ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_FLAG_VALID,
flags, 1);
if (IPMI_CC_OK == rc) {
chassis_bootparam_set_in_progress(intf, COMMIT_WRITE);
rc = ipmi_chassis_set_bootparam(intf, param_id, flags, 1);
if (rc == 0) {
if (use_progress) {
/* set-in-progress = commit-write */
memset(flags, 0, 5);
flags[0] = 0x02;
ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
flags, 1);
}
}
if (use_progress) {
/* set-in-progress = set-complete */
memset(flags, 0, 5);
ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
flags, 1);
}
out:
chassis_bootparam_set_in_progress(intf, SET_COMPLETE);
return rc;
}
@ -1099,17 +920,38 @@ static int
ipmi_chassis_set_bootdev(struct ipmi_intf * intf, char * arg, uint8_t *iflags)
{
uint8_t flags[5];
int rc;
int rc = 0;
int use_progress = 1;
chassis_bootparam_set_in_progress(intf, SET_IN_PROGRESS);
rc = chassis_bootparam_clear_ack(intf, BIOS_POST_ACK);
if (use_progress) {
/* set set-in-progress flag */
memset(flags, 0, 5);
flags[0] = 0x01;
rc = ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS, flags, 1);
if (rc < 0)
use_progress = 0;
}
memset(flags, 0, 5);
flags[0] = 0x01;
flags[1] = 0x01;
rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_INFO_ACK,
flags, 2);
if (rc < 0) {
goto out;
if (use_progress) {
/* set-in-progress = set-complete */
memset(flags, 0, 5);
ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
flags, 1);
}
return -1;
}
if (!iflags)
memset(flags, 0, sizeof(flags));
memset(flags, 0, 5);
else
memcpy(flags, iflags, sizeof (flags));
@ -1140,316 +982,45 @@ ipmi_chassis_set_bootdev(struct ipmi_intf * intf, char * arg, uint8_t *iflags)
flags[1] |= 0x18;
else {
lprintf(LOG_ERR, "Invalid argument: %s", arg);
rc = -1;
goto out;
if (use_progress) {
/* set-in-progress = set-complete */
memset(flags, 0, 5);
ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
flags, 1);
}
return -1;
}
/* set flag valid bit */
flags[0] |= 0x80;
rc = ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_BOOT_FLAGS,
flags, 5);
if (IPMI_CC_OK == rc) {
chassis_bootparam_set_in_progress(intf, COMMIT_WRITE);
rc = ipmi_chassis_set_bootparam(intf, IPMI_CHASSIS_BOOTPARAM_BOOT_FLAGS,
flags, 5);
if (rc == 0) {
if (use_progress) {
/* set-in-progress = commit-write */
memset(flags, 0, 5);
flags[0] = 0x02;
ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
flags, 1);
}
printf("Set Boot Device to %s\n", arg);
}
out:
chassis_bootparam_set_in_progress(intf, SET_COMPLETE);
return rc;
}
static void chassis_bootmailbox_help()
{
lprintf(LOG_NOTICE,
"bootmbox get [text] [block <block>]\n"
" Read the entire Boot Initiator Mailbox or the specified <block>.\n"
" If 'text' option is specified, the data is output as plain text, otherwise\n"
" hex dump mode is used.\n"
"\n"
"bootmbox set text [block <block>] <IANA_PEN> \"<data_string>\"\n"
"bootmbox set [block <block>] <IANA_PEN> <data_byte> [<data_byte> ...]\n"
" Write the specified <block> or the entire Boot Initiator Mailbox.\n"
" It is required to specify a decimal IANA Enterprise Number recognized\n"
" by the boot initiator on the target system. Refer to your target system\n"
" manufacturer for details. The rest of the arguments are either separate\n"
" data byte values separated by spaces, or a single text string argument.\n"
"\n"
" When single block write is requested, the total length of <data> may not\n"
" exceed 13 bytes for block 0, or 16 bytes otherwise.\n"
"\n"
"bootmbox help\n"
" Show this help.");
}
static
int
chassis_set_bootmailbox(struct ipmi_intf *intf, int16_t block, bool use_text,
int argc, char *argv[])
{
int rc = -1;
int32_t iana = 0;
size_t blocks = 0;
size_t datasize = 0;
off_t string_offset = 0;
lprintf(LOG_INFO, "Writing Boot Mailbox...");
if (argc < 1 || str2int(argv[0], &iana)) {
lprintf(LOG_ERR,
"No valid IANA PEN specified!\n");
chassis_bootmailbox_help();
goto out;
}
++argv;
--argc;
if (argc < 1) {
lprintf(LOG_ERR,
"No data provided!\n");
chassis_bootmailbox_help();
goto out;
}
/*
* Initialize the data size. For text mode it is just the
* single argument string length plus one byte for \0 termination.
* For byte mode the length is the number of byte arguments without
* any additional termination.
*/
if (!use_text) {
datasize = argc;
}
else {
datasize = strlen(argv[0]) + 1; /* Include the terminator */
}
lprintf(LOG_INFO, "Data size: %u", datasize);
/* Decide how many blocks we will be writing */
if (block >= 0) {
blocks = 1;
}
else {
/*
* We need to write all data, so calculate the data
* size in blocks and set the starting block to zero.
*/
blocks = datasize;
blocks += CHASSIS_BOOT_MBOX_BLOCK_SZ - 1;
blocks /= CHASSIS_BOOT_MBOX_BLOCK_SZ;
block = 0;
}
lprintf(LOG_INFO, "Blocks to write: %d", blocks);
if (blocks > CHASSIS_BOOT_MBOX_MAX_BLOCKS) {
lprintf(LOG_ERR,
"Data size %zu exceeds maximum (%d)",
datasize,
(CHASSIS_BOOT_MBOX_BLOCK_SZ
* CHASSIS_BOOT_MBOX_MAX_BLOCKS)
- CHASSIS_BOOT_MBOX_IANA_SZ);
goto out;
}
/* Indicate that we're touching the boot parameters */
chassis_bootparam_set_in_progress(intf, SET_IN_PROGRESS);
for (size_t bindex = 0;
datasize > 0 && bindex < blocks;
++bindex, ++block)
{
/* The request data structure */
mbox_t mbox = { .block = block, {{0}} };
/* Destination for input data */
uint8_t *data = mbox.data;
/* The maximum amount of data this block may hold */
size_t maxblocksize = sizeof(mbox.data);
/* The actual amount of data in this block */
size_t blocksize;
off_t unused = 0;
/* Block 0 needs special care as it has IANA PEN specifier */
if (!block) {
data = mbox.b0.data;
maxblocksize = sizeof(mbox.b0.data);
htoipmi24(iana, mbox.b0.iana);
}
/*
* Find out how many bytes we are going to write to this
* block.
*/
if (datasize > maxblocksize) {
blocksize = maxblocksize;
}
else {
blocksize = datasize;
}
/* Remember how much data remains */
datasize -= blocksize;
if (!use_text) {
args2buf(argc, argv, data, blocksize);
argc -= blocksize;
argv += blocksize;
}
else {
memcpy(data, argv[0] + string_offset, blocksize);
string_offset += blocksize;
}
lprintf(LOG_INFO, "Block %3" PRId16 ": %s", block,
buf2str_extended(data, blocksize, " "));
unused = maxblocksize - blocksize;
rc = ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_INIT_MBOX,
&mbox,
sizeof(mbox) - unused);
if (IPMI_CC_PARAM_OUT_OF_RANGE == rc) {
lprintf(LOG_ERR,
"Hit end of mailbox writing block %" PRId16,
block);
}
if (rc) {
goto complete;
}
}
lprintf(LOG_INFO,
"Wrote %zu blocks of Boot Initiator Mailbox",
blocks);
chassis_bootparam_set_in_progress(intf, COMMIT_WRITE);
rc = chassis_bootparam_clear_ack(intf, BIOS_POST_ACK | OS_LOADER_ACK);
complete:
chassis_bootparam_set_in_progress(intf, SET_COMPLETE);
out:
return rc;
}
static
int
chassis_get_bootmailbox(struct ipmi_intf *intf,
int16_t block, bool use_text)
{
int rc = IPMI_CC_UNSPECIFIED_ERROR;
char param_str[2]; /* Max "7" */
char block_str[4]; /* Max "255" */
char *bpargv[] = { param_str, block_str };
int flags;
flags = use_text ? BP_FLAG(MBOX_PARSE_USE_TEXT) : 0;
snprintf(param_str, sizeof(param_str),
"%" PRIu8, IPMI_CHASSIS_BOOTPARAM_INIT_MBOX);
if (block >= 0) {
snprintf(block_str, sizeof(block_str),
"%" PRIu8, (uint8_t)block);
rc = ipmi_chassis_get_bootparam(intf,
ARRAY_SIZE(bpargv),
bpargv,
flags);
}
else {
int currblk;
flags |= BP_FLAG(MBOX_PARSE_ALLBLOCKS);
for (currblk = 0; currblk <= UCHAR_MAX; ++currblk) {
snprintf(block_str, sizeof(block_str),
"%" PRIu8, (uint8_t)currblk);
if (currblk) {
/*
* If block 0 succeeded, we don't want to
* print generic info for each next block,
* and we don't want range error to be
* reported when we hit the end of blocks.
*/
flags |= BP_FLAG(PARAM_NO_GENERIC_INFO);
flags |= BP_FLAG(PARAM_NO_RANGE_ERROR);
}
rc = ipmi_chassis_get_bootparam(intf,
ARRAY_SIZE(bpargv),
bpargv,
flags);
if (rc) {
if (currblk) {
rc = IPMI_CC_OK;
}
break;
}
}
if (use_progress) {
/* set-in-progress = set-complete */
memset(flags, 0, 5);
ipmi_chassis_set_bootparam(intf,
IPMI_CHASSIS_BOOTPARAM_SET_IN_PROGRESS,
flags, 1);
}
return rc;
}
static
int
chassis_bootmailbox(struct ipmi_intf *intf, int argc, char *argv[])
{
int rc = IPMI_CC_UNSPECIFIED_ERROR;
bool use_text = false; /* Default to data dump I/O mode */
int16_t block = -1; /* By default print all blocks */
const char *cmd;
if ((argc < 1) || !strcmp(argv[0], "help")) {
chassis_bootmailbox_help();
goto out;
} else {
cmd = argv[0];
++argv;
--argc;
if (argc > 0 && !strcmp(argv[0], "text")) {
use_text = true;
++argv;
--argc;
}
if (argc > 0 && !strcmp(argv[0], "block")) {
if (argc < 2) {
chassis_bootmailbox_help();
goto out;
}
if(str2short(argv[1], &block)) {
lprintf(LOG_ERR,
"Invalid block %s", argv[1]);
goto out;
}
argv += 2;
argc -= 2;
}
if (!strcmp(cmd, "get")) {
rc = chassis_get_bootmailbox(intf, block, use_text);
}
else if (!strcmp(cmd, "set")) {
rc = chassis_set_bootmailbox(intf, block, use_text,
argc, argv);
}
}
out:
return rc;
}
static int
ipmi_chassis_power_policy(struct ipmi_intf * intf, uint8_t policy)
{
@ -1560,10 +1131,7 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
int rc = 0;
if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0)) {
lprintf(LOG_NOTICE, "Chassis Commands:\n"
" status, power, policy, restart_cause\n"
" poh, identify, selftest,\n"
" bootdev, bootparam, bootmbox");
lprintf(LOG_NOTICE, "Chassis Commands: status, power, identify, policy, restart_cause, poh, bootdev, bootparam, selftest");
}
else if (strncmp(argv[0], "status", 6) == 0) {
rc = ipmi_chassis_status(intf);
@ -1651,10 +1219,7 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
}
else {
if (strncmp(argv[1], "get", 3) == 0) {
rc = ipmi_chassis_get_bootparam(intf,
argc - 2,
argv + 2,
0);
rc = ipmi_chassis_get_bootparam(intf, argv[2]);
}
else if (strncmp(argv[1], "set", 3) == 0) {
unsigned char set_flag=0;
@ -1794,9 +1359,6 @@ ipmi_chassis_main(struct ipmi_intf * intf, int argc, char ** argv)
rc = ipmi_chassis_set_bootdev(intf, argv[1], NULL);
}
}
else if (!strcmp(argv[0], "bootmbox")) {
rc = chassis_bootmailbox(intf, argc -1, argv + 1);
}
else {
lprintf(LOG_ERR, "Invalid chassis command: %s", argv[0]);
return -1;

View File

@ -2872,27 +2872,32 @@ static void ipmi_fru_picmg_ext_print(uint8_t * fru_data, int off, int length)
}
}
/* __ipmi_fru_print - Do actual work to print a FRU by its ID
*
* @intf: ipmi interface
* @id: fru id
*
* returns -1 on error
* returns 0 if successful
* returns 1 if device not present
*/
static int
__ipmi_fru_print(struct ipmi_intf * intf, uint8_t id)
/** __ipmi_get_fru_hdr - read FRU info and header from IPMI interface
*
* @param[in] intf ipmi interface
* @param[in] id fru id
* @param[out] fru fru info structure pointer
* @param[out] size size of the allocated fru structure
*
* @retval 0 error
* @retval 1 success
*/
static int __ipmi_get_fru_hdr(struct ipmi_intf *intf,
uint8_t id,
struct fru_info *fru,
struct fru_header *header)
{
struct ipmi_rs * rsp;
struct ipmi_rs *rsp;
struct ipmi_rq req;
struct fru_info fru;
struct fru_header header;
uint8_t msg_data[4];
memset(&fru, 0, sizeof(struct fru_info));
memset(&header, 0, sizeof(struct fru_header));
/* Sanity checks */
if (!fru) return 0;
if (!header) return 0;
if (!intf) return 0;
memset(fru, 0, sizeof(*fru));
memset(header, 0, sizeof(*header));
/*
* get info about this FRU
@ -2909,66 +2914,63 @@ __ipmi_fru_print(struct ipmi_intf * intf, uint8_t id)
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
printf(" Device not present (No Response)\n");
return -1;
return 0;
}
if (rsp->ccode) {
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
return -1;
val2str(rsp->ccode, completion_code_vals));
return 0;
}
memset(&fru, 0, sizeof(fru));
fru.size = (rsp->data[1] << 8) | rsp->data[0];
fru.access = rsp->data[2] & 0x1;
fru->size = (rsp->data[1] << 8) | rsp->data[0];
fru->access = rsp->data[2] & 0x1;
lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
fru.size, fru.access ? "words" : "bytes");
fru->size, fru->access ? "words" : "bytes");
if (fru.size < 1) {
lprintf(LOG_ERR, " Invalid FRU size %d", fru.size);
return -1;
if (fru->size < 1) {
lprintf(LOG_ERR, " Invalid FRU size %d", fru->size);
return 0;
}
/*
* retrieve the FRU header
*/
msg_data[0] = id;
msg_data[1] = 0;
msg_data[2] = 0;
msg_data[3] = 8;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = GET_FRU_DATA;
req.msg.data = msg_data;
req.msg.data_len = 4;
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
printf(" Device not present (No Response)\n");
return 1;
}
if (rsp->ccode) {
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
return 1;
/* Read the FRU header */
if (read_fru_area(intf, fru, id, 0, sizeof(*header), header)) {
lprintf(LOG_ERR, " Failed to read FRU header");
return 0;
}
if (verbose > 1)
printbuf(rsp->data, rsp->data_len, "FRU DATA");
memcpy(&header, rsp->data + 1, 8);
if (header.version != 1) {
if (header->version != 1) {
lprintf(LOG_ERR, " Unknown FRU header version 0x%02x",
header.version);
header->version);
return 0;
}
return 1;
}
/* __ipmi_fru_print - Do actual work to print a FRU by its ID
*
* @intf: ipmi interface
* @id: fru id
*
* returns -1 on error
* returns 0 if successful
* returns 1 if device not present
*/
static int
__ipmi_fru_print(struct ipmi_intf * intf, uint8_t id)
{
struct fru_info fru;
struct fru_header header;
if (!__ipmi_get_fru_hdr(intf, id, &fru, &header)) {
return -1;
}
/* offsets need converted to bytes
* but that conversion is not done to the structure
* because we may end up with offset > 255
* which would overflow our 1-byte offset field */
* but that conversion is not done to the structure
* because we may end up with offset > 255
* which would overflow our 1-byte offset field */
lprintf(LOG_DEBUG, "fru.header.version: 0x%x",
header.version);
@ -4056,91 +4058,19 @@ ipmi_fru_get_multirec_location_from_fru(struct ipmi_intf * intf,
* returns 1 if device not present
*/
static int
ipmi_fru_get_internal_use_info( struct ipmi_intf * intf,
uint8_t id,
struct fru_info * fru,
uint16_t * size,
uint16_t * offset)
ipmi_fru_get_internal_use_info(struct ipmi_intf *intf,
uint8_t id,
struct fru_info *fru,
uint16_t *size,
uint16_t *offset)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct fru_header header;
uint8_t msg_data[4];
// Init output value
* offset = 0;
* size = 0;
memset(fru, 0, sizeof(struct fru_info));
memset(&header, 0, sizeof(struct fru_header));
/*
* get info about this FRU
*/
memset(msg_data, 0, 4);
msg_data[0] = id;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = GET_FRU_INFO;
req.msg.data = msg_data;
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
printf(" Device not present (No Response)\n");
return -1;
}
if (rsp->ccode) {
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
fru->size = (rsp->data[1] << 8) | rsp->data[0];
fru->access = rsp->data[2] & 0x1;
lprintf(LOG_DEBUG, "fru.size = %d bytes (accessed by %s)",
fru->size, fru->access ? "words" : "bytes");
if (fru->size < 1) {
lprintf(LOG_ERR, " Invalid FRU size %d", fru->size);
return -1;
}
/*
* retrieve the FRU header
*/
msg_data[0] = id;
msg_data[1] = 0;
msg_data[2] = 0;
msg_data[3] = 8;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = GET_FRU_DATA;
req.msg.data = msg_data;
req.msg.data_len = 4;
rsp = intf->sendrecv(intf, &req);
if (!rsp) {
printf(" Device not present (No Response)\n");
return 1;
}
if (rsp->ccode) {
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
return 1;
}
if (verbose > 1)
printbuf(rsp->data, rsp->data_len, "FRU DATA");
memcpy(&header, rsp->data + 1, 8);
if (header.version != 1) {
lprintf(LOG_ERR, " Unknown FRU header version 0x%02x",
header.version);
if (!__ipmi_get_fru_hdr(intf, id, fru, &header)) {
return -1;
}

View File

@ -1486,7 +1486,6 @@ ipmi_pef2_get_info(struct ipmi_intf *intf)
ipmi_pef_print_guid(guid_ptr);
}
ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, pcap.actions);
putchar('\n');
return 0;
}
@ -1538,7 +1537,6 @@ ipmi_pef2_get_status(struct ipmi_intf *intf)
return (-1);
}
ipmi_pef_print_flags(&pef_b2s_actions, P_ACTV, rsp->data[1]);
putchar('\n');
return 0;
}

View File

@ -68,9 +68,8 @@ static struct sdr_record_list *sdr_list_head = NULL;
static struct sdr_record_list *sdr_list_tail = NULL;
static struct ipmi_sdr_iterator *sdr_list_itr = NULL;
/* IPMI 2.0 Table 43-15, Sensor Unit Type Codes */
#define UNIT_TYPE_MAX 92 /* This is the ID of "grams" */
#define UNIT_TYPE_LONGEST_NAME 19 /* This is the length of "color temp deg K" */
/* unit description codes (IPMI v1.5 section 37.16) */
#define UNIT_MAX 0x90
static const char *unit_desc[] = {
"unspecified",
"degrees C",
@ -162,9 +161,7 @@ static const char *unit_desc[] = {
"characters",
"error",
"correctable error",
"uncorrectable error",
"fatal error",
"grams"
"uncorrectable error"
};
/* sensor type codes (IPMI v1.5 table 36.3)
@ -223,60 +220,35 @@ void printf_sdr_usage();
uint16_t
ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf);
/** ipmi_sdr_get_unit_string - return units for base/modifier
/* ipmi_sdr_get_unit_string - return units for base/modifier
*
* @param[in] pct Indicates that units are a percentage
* @param[in] relation Modifier unit to base unit relation
* (SDR_UNIT_MOD_NONE, SDR_UNIT_MOD_MUL,
* or SDR_UNIT_MOD_DIV)
* @param[in] base The base unit type id
* @param[in] modifier The modifier unit type id
* @pct: units are a percentage
* @type: unit type
* @base: base
* @modifier: modifier
*
* @returns a pointer to static string
* returns pointer to static string
*/
const char *
ipmi_sdr_get_unit_string(bool pct, uint8_t relation,
uint8_t base, uint8_t modifier)
ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type, uint8_t base, uint8_t modifier)
{
/*
* Twice as long as the longest possible unit name, plus
* two characters for '%' and relation (either '*' or '/'),
* plus the terminating null-byte.
*/
static char unitstr[2 * UNIT_TYPE_LONGEST_NAME + 2 + 1];
static char unitstr[16];
/*
* By default, if units are supposed to be percent, we will pre-pend
* the percent string to the textual representation of the units.
*/
const char *pctstr = pct ? "% " : "";
const char *basestr;
const char *modstr;
if (base <= UNIT_TYPE_MAX) {
basestr = unit_desc[base];
}
else {
basestr = "invalid";
}
if (modifier <= UNIT_TYPE_MAX) {
modstr = unit_desc[base];
}
else {
modstr = "invalid";
}
switch (relation) {
case SDR_UNIT_MOD_MUL:
snprintf(unitstr, sizeof (unitstr), "%s%s*%s",
pctstr, basestr, modstr);
char *pctstr = pct ? "% " : "";
memset(unitstr, 0, sizeof (unitstr));
switch (type) {
case 2:
snprintf(unitstr, sizeof (unitstr), "%s%s * %s",
pctstr, unit_desc[base], unit_desc[modifier]);
break;
case SDR_UNIT_MOD_DIV:
case 1:
snprintf(unitstr, sizeof (unitstr), "%s%s/%s",
pctstr, basestr, modstr);
pctstr, unit_desc[base], unit_desc[modifier]);
break;
case SDR_UNIT_MOD_NONE:
case 0:
default:
/*
* Display the text "percent" only when the Base unit is
@ -286,7 +258,7 @@ ipmi_sdr_get_unit_string(bool pct, uint8_t relation,
snprintf(unitstr, sizeof(unitstr), "percent");
} else {
snprintf(unitstr, sizeof (unitstr), "%s%s",
pctstr, basestr);
pctstr, unit_desc[base]);
}
break;
}

View File

@ -249,7 +249,6 @@ const struct oemvalstr ipmi_oem_product_info[] = {
/* YADRO */
{ IPMI_OEM_YADRO, 0x0001, "VESNIN BMC" },
{ IPMI_OEM_YADRO, 0x000A, "TATLIN Storage Controller BMC" },
{ 0xffffff , 0xffff , NULL },
};

View File

@ -32,12 +32,11 @@ MAINTAINERCLEANFILES = Makefile.in
AM_CPPFLAGS = -I$(top_srcdir)/include
SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@ @INTF_DBUS@
DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb dbus
SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@
DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb
noinst_LTLIBRARIES = libintf.la
libintf_la_SOURCES = ipmi_intf.c
libintf_la_CFLAGS = -DDEFAULT_INTF='"@DEFAULT_INTF@"'
libintf_la_LDFLAGS = -export-dynamic
libintf_la_LIBADD = @IPMITOOL_INTF_LIB@
libintf_la_DEPENDENCIES = @IPMITOOL_INTF_LIB@

View File

@ -1,41 +0,0 @@
#
# Copyright (c) 2015 IBM Corporation
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification,are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions 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.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_dbus.la
noinst_LTLIBRARIES = @INTF_DBUS_LIB@
libintf_dbus_la_LDFLAGS = -lsystemd
libintf_dbus_la_LIBADD = $(top_builddir)/lib/libipmitool.la
libintf_dbus_la_SOURCES = dbus.c

View File

@ -1,241 +0,0 @@
/*
* Copyright (c) 2015 IBM Corporation
* Copyright (c) 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions 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.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdbool.h>
#include <systemd/sd-bus.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
static sd_bus *bus;
static
struct ipmi_rs *
ipmi_dbus_sendrecv(struct ipmi_intf *intf,
struct ipmi_rq *req)
{
static const char *destination = "xyz.openbmc_project.Ipmi.Host";
static const char *object_path = "/xyz/openbmc_project/Ipmi";
static const char *interface = "xyz.openbmc_project.Ipmi.Server";
static const char *method_name = "execute";
static const char SD_BUS_TYPE_3_BYTES[] = {
SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BYTE, 0
};
static const char SD_BUS_TYPE_4_BYTES[] = {
SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BYTE,
SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BYTE, 0
};
static const char SD_BUS_TYPE_DICT_OF_VARIANTS[] = {
SD_BUS_TYPE_ARRAY,
SD_BUS_TYPE_DICT_ENTRY_BEGIN,
SD_BUS_TYPE_STRING, SD_BUS_TYPE_VARIANT,
SD_BUS_TYPE_DICT_ENTRY_END, 0
};
static const char SD_BUS_TYPE_IPMI_RESPONSE[] = {
SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BYTE,
SD_BUS_TYPE_BYTE, SD_BUS_TYPE_BYTE,
SD_BUS_TYPE_ARRAY, SD_BUS_TYPE_BYTE, 0
};
sd_bus_message *request = NULL;
int rc;
sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message* reply = NULL;
uint8_t recv_netfn;
uint8_t recv_lun;
uint8_t recv_cmd;
uint8_t recv_cc;
const void *data;
size_t data_len;
static struct ipmi_rs rsp;
struct ipmi_rs *ipmi_response = NULL;
if (!intf->opened || !bus)
{
goto out_no_free;
}
rsp.ccode = IPMI_CC_UNSPECIFIED_ERROR;
rsp.data_len = 0;
memset(rsp.data, 0, sizeof(rsp.data));
/* The D-Bus xyz.openbmc_project.Ipmi.Server.execute interface
* looks like this:
*
* Request:
* byte: net function
* byte: lun
* byte: command
* byte array: data (possibly zero length)
* array of (string,variant): options
* Response:
* byte: net function
* byte: lun
* byte: command
* byte: completion code
* byte array: response data (possibly zero length)
*/
rc = sd_bus_message_new_method_call(bus, &request, destination,
object_path, interface,
method_name);
if (rc < 0) {
lprintf(LOG_ERR, "%s: failed to create message: %s\n",
__func__, strerror(-rc));
goto out_no_free;
}
/* pack the header: netfn, lun, cmd */
rc = sd_bus_message_append(request, SD_BUS_TYPE_3_BYTES, req->msg.netfn,
req->msg.lun, req->msg.cmd);
if (rc < 0) {
lprintf(LOG_ERR, "%s: failed to append parameters\n", __func__);
goto out_free_request;
}
/* pack the variable length data */
rc = sd_bus_message_append_array(request, SD_BUS_TYPE_BYTE,
req->msg.data, req->msg.data_len);
if (rc < 0) {
lprintf(LOG_ERR, "%s: failed to append body\n", __func__);
goto out_free_request;
}
/* Options are only needed for session-based channels, but
* in order to fulfill the correct signature, an empty array
* must be packed */
rc = sd_bus_message_append(request, SD_BUS_TYPE_DICT_OF_VARIANTS,
NULL, 0);
if (rc < 0) {
lprintf(LOG_ERR, "%s: failed to append options\n", __func__);
goto out_free_request;
}
rc = sd_bus_call(bus, request, 0, &error, &reply);
if (rc < 0) {
lprintf(LOG_ERR, "%s: failed to send dbus message (%s)\n",
__func__, error.message);
goto out_free_request;
}
/* unpack the response; check that it has the expected types */
rc = sd_bus_message_enter_container(reply, SD_BUS_TYPE_STRUCT,
SD_BUS_TYPE_IPMI_RESPONSE);
if (rc < 0) {
lprintf(LOG_ERR, "%s: failed to parse reply\n", __func__);
goto out_free_reply;
}
/* read the header: CC netfn lun cmd */
rc = sd_bus_message_read(reply, SD_BUS_TYPE_4_BYTES, &recv_netfn,
&recv_lun, &recv_cmd, &recv_cc);
if (rc < 0) {
lprintf(LOG_ERR, "%s: failed to read reply\n", __func__);
goto out_free_reply;
}
/* read the variable length data */
rc = sd_bus_message_read_array(reply, SD_BUS_TYPE_BYTE,
&data, &data_len);
if (rc < 0) {
lprintf(LOG_ERR, "%s: failed to read reply data\n", __func__);
goto out_free_reply;
}
rc = sd_bus_message_exit_container(reply);
if (rc < 0) {
lprintf(LOG_ERR, "%s: final unpack of message failed\n",
__func__);
goto out_free_reply;
}
if (data_len > sizeof(rsp.data)) {
lprintf(LOG_ERR, "%s: data too long!\n", __func__);
goto out_free_reply;
}
/* At this point, all the parts are available for a response
* other than unspecified error. */
rsp.ccode = recv_cc;
rsp.data_len = data_len;
memcpy(rsp.data, data, data_len);
ipmi_response = &rsp;
out_free_reply:
/* message unref will free resources owned by the message */
sd_bus_message_unref(reply);
out_free_request:
sd_bus_message_unref(request);
out_no_free:
return ipmi_response;
}
static
int
ipmi_dbus_setup(struct ipmi_intf *intf)
{
int rc;
rc = sd_bus_default_system(&bus);
if (rc < 0) {
lprintf(LOG_ERR, "Can't connect to session bus: %s\n",
strerror(-rc));
return -1;
}
intf->opened = 1;
return 0;
}
static
void
ipmi_dbus_close(struct ipmi_intf *intf)
{
if (intf->opened)
{
sd_bus_close(bus);
}
intf->opened = 0;
}
struct ipmi_intf ipmi_dbus_intf = {
.name = "dbus",
.desc = "OpenBMC D-Bus interface",
.setup = ipmi_dbus_setup,
.close = ipmi_dbus_close,
.sendrecv = ipmi_dbus_sendrecv,
};

View File

@ -86,9 +86,6 @@ extern struct ipmi_intf ipmi_dummy_intf;
#ifdef IPMI_INTF_USB
extern struct ipmi_intf ipmi_usb_intf;
#endif
#ifdef IPMI_INTF_DBUS
extern struct ipmi_intf ipmi_dbus_intf;
#endif
struct ipmi_intf * ipmi_intf_table[] = {
#ifdef IPMI_INTF_OPEN
@ -121,33 +118,10 @@ struct ipmi_intf * ipmi_intf_table[] = {
#endif
#ifdef IPMI_INTF_USB
&ipmi_usb_intf,
#endif
#ifdef IPMI_INTF_DBUS
&ipmi_dbus_intf,
#endif
NULL
};
/* get_default_interface - return the interface that was chosen by configure
*
* returns a valid interface pointer
*/
static struct ipmi_intf *get_default_interface(void)
{
static const char *default_intf_name = DEFAULT_INTF;
struct ipmi_intf ** intf;
for (intf = ipmi_intf_table; intf && *intf; intf++) {
if (!strcmp(default_intf_name, (*intf)->name)) {
return *intf;
}
}
/* code should never reach this because the configure script checks
* to see that the default interface is actually enabled, but we have
* to return some valid value here, so the first entry works
*/
return ipmi_intf_table[0];
}
/* ipmi_intf_print - Print list of interfaces
*
* no meaningful return code
@ -155,11 +129,10 @@ static struct ipmi_intf *get_default_interface(void)
void ipmi_intf_print(struct ipmi_intf_support * intflist)
{
struct ipmi_intf ** intf;
struct ipmi_intf *def_intf;
struct ipmi_intf_support * sup;
int def = 1;
int found;
def_intf = get_default_interface();
lprintf(LOG_NOTICE, "Interfaces:");
for (intf = ipmi_intf_table; intf && *intf; intf++) {
@ -178,7 +151,8 @@ void ipmi_intf_print(struct ipmi_intf_support * intflist)
lprintf(LOG_NOTICE, "\t%-12s %s %s",
(*intf)->name, (*intf)->desc,
def_intf == (*intf) ? "[default]" : "");
def ? "[default]" : "");
def = 0;
}
lprintf(LOG_NOTICE, "");
}
@ -197,7 +171,7 @@ struct ipmi_intf * ipmi_intf_load(char * name)
struct ipmi_intf * i;
if (!name) {
i = get_default_interface();
i = ipmi_intf_table[0];
if (i->setup && (i->setup(i) < 0)) {
lprintf(LOG_ERR, "Unable to setup "
"interface %s", name);