mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-07-01 18:23:36 +00:00
Compare commits
35 Commits
feature/ad
...
cleanup/nm
Author | SHA1 | Date | |
---|---|---|---|
2bf9964ce5 | |||
b6098c3bdb | |||
0c8ceb78a4 | |||
97da8c83ae | |||
8e4459f3dc | |||
161bb88c6e | |||
67928205e7 | |||
7469522fbb | |||
5372a57297 | |||
be9f1660fb | |||
e0811437a2 | |||
75eada4859 | |||
1724b031b3 | |||
9006f2b26d | |||
b7db637984 | |||
82d6629a66 | |||
c396a310ba | |||
002e1d95f5 | |||
2ee7aca4e4 | |||
efd28d1bc1 | |||
d95775288d | |||
ef78ef3792 | |||
2676ae43fd | |||
54abbaf0e8 | |||
bd0475ce4a | |||
b397a07e9e | |||
8071cf7389 | |||
ca7767793e | |||
a45704e5ea | |||
94f7646a8e | |||
62a04390e1 | |||
de1d5c9924 | |||
73d6af5782 | |||
c9510635d7 | |||
e11f463b4e |
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,6 +1,10 @@
|
||||
.deps
|
||||
.dirstamp
|
||||
.libs
|
||||
.*.swp
|
||||
*.log
|
||||
*.rej
|
||||
*.orig
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
@ -29,6 +33,7 @@ control/prototype
|
||||
control/rpmmacros
|
||||
src/ipmievd
|
||||
src/ipmitool
|
||||
lib/ipmi_pen_list.inc.c
|
||||
doc/ipmievd.8
|
||||
doc/ipmitool.1
|
||||
cscope.out
|
||||
tags
|
||||
|
28
Makefile.am
28
Makefile.am
@ -41,11 +41,37 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure configure-stamp \
|
||||
$(distdir).tar.gz $(distdir).tar.bz2
|
||||
|
||||
SUBDIRS = lib src include doc contrib control
|
||||
IANA_PEN = http://www.iana.org/assignments/enterprise-numbers
|
||||
|
||||
dist-hook:
|
||||
cp control/ipmitool.spec $(distdir)
|
||||
|
||||
install-data-local:
|
||||
.PHONY: install-pen-database
|
||||
|
||||
if DOWNLOAD
|
||||
|
||||
enterprise-numbers:
|
||||
@echo Downloading IANA PEN database...
|
||||
@$(DOWNLOAD) "$(IANA_PEN)" > tmpfile.$$PPID || {\
|
||||
echo "FAILED to download the IANA PEN database"; \
|
||||
rm tmpfile.$$PPID; \
|
||||
false; \
|
||||
}
|
||||
@mv tmpfile.$$PPID $@
|
||||
|
||||
install-pen-database: enterprise-numbers
|
||||
mkdir -m 755 -p $(DESTDIR)$(IANADIR)
|
||||
$(INSTALL_DATA) $< -t $(DESTDIR)$(IANADIR)/
|
||||
|
||||
else
|
||||
|
||||
install-pen-database:
|
||||
@echo "*** NOT installing the IANA PEN database."
|
||||
@echo "*** Don't know how to download it."
|
||||
|
||||
endif
|
||||
|
||||
install-data-local: install-pen-database
|
||||
mkdir -p $(DESTDIR)$(DOCDIR)
|
||||
$(INSTALL_DATA) $(DOCLIST) $(DESTDIR)$(DOCDIR)
|
||||
|
||||
|
2
README
2
README
@ -399,7 +399,7 @@ IPMItool homepage
|
||||
http://github.com/ipmitool/ipmitool
|
||||
|
||||
IPMItool manpage
|
||||
https://github.com/ipmitool/ipmitool/blob/master/doc/ipmitool.1
|
||||
https://github.com/ipmitool/ipmitool/blob/master/doc/ipmitool.1.in
|
||||
|
||||
Intelligent Platform Management Interface specification
|
||||
https://www.intel.com/content/www/us/en/servers/ipmi/ipmi-home.html
|
||||
|
53
configure.ac
53
configure.ac
@ -4,6 +4,7 @@ dnl
|
||||
m4_define([git_suffix], m4_esyscmd_s(./csv-revision))
|
||||
AC_INIT([ipmitool], [1.8.18git_suffix])
|
||||
AC_CONFIG_SRCDIR([src/ipmitool.c])
|
||||
AC_CONFIG_COMMANDS_PRE([export prefix=$prefix])
|
||||
AC_CANONICAL_SYSTEM
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
@ -17,6 +18,8 @@ AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_CHECK_PROG([RPMBUILD], [rpmbuild], [rpmbuild], [rpm])
|
||||
AC_CHECK_PROG([SED], [sed], [sed])
|
||||
AC_CHECK_PROG([WGET], [wget], [wget])
|
||||
AC_CHECK_PROG([CURL], [curl], [curl])
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([stdlib.h string.h sys/ioctl.h sys/stat.h unistd.h paths.h])
|
||||
@ -53,6 +56,23 @@ if test "x$exec_prefix" = "xNONE"; then
|
||||
exec_prefix="$prefix"
|
||||
fi
|
||||
|
||||
if test "x$WGET" = "x"; then
|
||||
if test "x$CURL" = "x"; then
|
||||
AC_MSG_WARN([** Neither wget nor curl could be found.])
|
||||
AC_MSG_WARN([** IANA PEN database will not be installed by `make install` !])
|
||||
else
|
||||
DOWNLOAD="$CURL -#"
|
||||
AM_CONDITIONAL([DOWNLOAD], [true])
|
||||
fi
|
||||
else
|
||||
DOWNLOAD="$WGET -c -nd -O -"
|
||||
AM_CONDITIONAL([DOWNLOAD], [true])
|
||||
fi
|
||||
|
||||
AC_MSG_WARN([** Download is:])
|
||||
AC_MSG_WARN($DOWNLOAD)
|
||||
AC_SUBST(DOWNLOAD, $DOWNLOAD)
|
||||
|
||||
dnl
|
||||
dnl set default option values
|
||||
dnl
|
||||
@ -672,13 +692,13 @@ AC_TRY_COMPILE([],[
|
||||
)
|
||||
|
||||
dnl if no environment variable is set, set the default value for the default intf
|
||||
if test "${xenable_intf_open}" = "xyes"; then
|
||||
if test "${xenable_intf_open}" = "yes"; 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})])
|
||||
AC_ARG_VAR(DEFAULT_INTF, [Set the default interface to use (default='open' if available, 'lan' otherwise)])
|
||||
|
||||
dnl set the default value for the default interface environment variable
|
||||
if test "x${DEFAULT_INTF}" == "x"; then
|
||||
@ -691,6 +711,32 @@ 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
|
||||
|
||||
AC_ARG_VAR(IANADIR, [Configure the path to IANA PEN dictionary (default=DATAROOTDIR/misc)])
|
||||
AC_ARG_VAR(IANAUSERDIR, [Configure the path to IANA PEN dictionary wihtin the user's HOME directory (default=.local/usr/share/misc)])
|
||||
|
||||
if test "x${IANADIR}" == "x"; then
|
||||
echo Set IANA PEN dictionary search path to ${datarootdir}/misc
|
||||
IANADIR="${datarootdir}/misc"
|
||||
fi
|
||||
|
||||
if test "x${IANAUSERDIR}" == "x"; then
|
||||
IANAUSERDIR=".local/usr/share/misc"
|
||||
echo Set user\'s IANA PEN dictionary search path to ${IANAUSERDIR}
|
||||
fi
|
||||
|
||||
AH_TEMPLATE([IANADIR],[The path to system IANA PEN dictionary])
|
||||
AC_DEFINE_UNQUOTED(IANADIR, "`eval "echo ${IANADIR}"`", [])
|
||||
|
||||
AH_TEMPLATE([IANAUSERDIR],[The subpath to user IANA PEN dictionary within the user's HOME])
|
||||
AC_DEFINE_UNQUOTED(IANAUSERDIR, "`eval "echo ${IANAUSERDIR}"`", [])
|
||||
|
||||
AH_TEMPLATE([PATH_SEPARATOR], [The path separator string])
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
AC_DEFINE(PATH_SEPARATOR, "\\")
|
||||
#else
|
||||
AC_DEFINE(PATH_SEPARATOR, "/")
|
||||
#endif
|
||||
|
||||
dnl Generate files for build
|
||||
AC_CONFIG_FILES([Makefile
|
||||
doc/Makefile
|
||||
@ -717,6 +763,9 @@ AC_CONFIG_FILES([Makefile
|
||||
src/plugins/serial/Makefile
|
||||
src/plugins/dummy/Makefile])
|
||||
|
||||
AC_CONFIG_FILES([doc/ipmitool.1], [${SED} -i -e "s%\${prefix}%$prefix%" doc/ipmitool.1])
|
||||
AC_CONFIG_FILES([doc/ipmievd.8], [${SED} -i -e "s%\${prefix}%$prefix%" doc/ipmievd.8])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT([])
|
||||
|
@ -217,6 +217,16 @@ Reading Sensors...
|
||||
.br
|
||||
Waiting for Events...
|
||||
.br
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
.B @IANADIR@/enterprise-numbers
|
||||
system IANA PEN registry taken from http://www.iana.org/assignments/enterprise-numbers
|
||||
.TP
|
||||
.B ~/@IANAUSERDIR@/enterprise-numbers
|
||||
user's override for the system IANA PEN registry, this file if it exists is loaded instead
|
||||
of the system registry (see above).
|
||||
|
||||
.SH "AUTHOR"
|
||||
Duncan Laurie <duncan@iceblink.org>
|
||||
.SH "SEE ALSO"
|
@ -473,36 +473,94 @@ Force boot into BIOS Setup.
|
||||
|
||||
Force boot from Floppy/primary removable media.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
\fIbootparam\fP
|
||||
\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
|
||||
.TP
|
||||
\fIforce_pxe\fP
|
||||
.IP \fIforce_pxe\fP
|
||||
|
||||
Force PXE boot
|
||||
.TP
|
||||
\fIforce_disk\fP
|
||||
.IP \fIforce_disk\fP
|
||||
|
||||
Force boot from default Hard-drive
|
||||
.TP
|
||||
\fIforce_safe\fP
|
||||
.IP \fIforce_safe\fP
|
||||
|
||||
Force boot from default Hard-drive, request Safe Mode
|
||||
.TP
|
||||
\fIforce_diag\fP
|
||||
.IP \fIforce_diag\fP
|
||||
|
||||
Force boot from Diagnostic Partition
|
||||
.TP
|
||||
\fIforce_cdrom\fP
|
||||
.IP \fIforce_cdrom\fP
|
||||
|
||||
Force boot from CD/DVD
|
||||
.TP
|
||||
\fIforce_bios\fP
|
||||
.IP \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
|
||||
.RE
|
||||
|
||||
.TP
|
||||
\fIselftest\fP
|
||||
|
||||
Get the chassis self-test results
|
||||
|
||||
.RE
|
||||
.TP
|
||||
\fIdcmi\fP
|
||||
@ -3760,6 +3818,15 @@ Chassis Power is on
|
||||
.br
|
||||
Chassis Power Control: Up/On
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
.B @IANADIR@/enterprise-numbers
|
||||
system IANA PEN registry taken from http://www.iana.org/assignments/enterprise-numbers
|
||||
.TP
|
||||
.B ~/@IANAUSERDIR@/enterprise-numbers
|
||||
user's override for the system IANA PEN registry, this file if it exists is loaded instead
|
||||
of the system registry (see above).
|
||||
|
||||
.SH "AUTHORS"
|
||||
Originally written by Duncan Laurie <duncan@iceblink.org>.
|
||||
.br
|
@ -38,6 +38,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h> /* For free() */
|
||||
#include <stdbool.h>
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
@ -79,8 +80,12 @@ struct oemvalstr {
|
||||
const char * str;
|
||||
};
|
||||
|
||||
const char * val2str(uint16_t val, const struct valstr * vs);
|
||||
const char * oemval2str(uint32_t oem,uint16_t val, const struct oemvalstr * vs);
|
||||
const char *
|
||||
specific_val2str(uint32_t val,
|
||||
const struct valstr *specific,
|
||||
const struct valstr *generic);
|
||||
const char *val2str(uint32_t val, const struct valstr * vs);
|
||||
const char *oemval2str(uint32_t oem, uint32_t val, const struct oemvalstr * vs);
|
||||
|
||||
int str2double(const char * str, double * double_ptr);
|
||||
int str2long(const char * str, int64_t * lng_ptr);
|
||||
@ -92,6 +97,8 @@ 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);
|
||||
@ -99,7 +106,11 @@ int is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr);
|
||||
int is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr);
|
||||
int is_ipmi_user_priv_limit(const char *argv_ptr, uint8_t *ipmi_priv_limit_ptr);
|
||||
|
||||
uint16_t str2val(const char * str, const struct valstr * vs);
|
||||
uint32_t str2val32(const char *str, const struct valstr *vs);
|
||||
static inline uint16_t str2val(const char *str, const struct valstr *vs)
|
||||
{
|
||||
return (uint16_t)str2val32(str, vs);
|
||||
}
|
||||
void print_valstr(const struct valstr * vs, const char * title, int loglevel);
|
||||
void print_valstr_2col(const struct valstr * vs, const char * title, int loglevel);
|
||||
|
||||
@ -166,6 +177,13 @@ 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;
|
||||
|
@ -283,7 +283,7 @@ typedef enum IPMI_OEM {
|
||||
IPMI_OEM_MAGNUM = 5593,
|
||||
IPMI_OEM_TYAN = 6653,
|
||||
IPMI_OEM_QUANTA = 7244,
|
||||
IPMI_OEM_NEWISYS = 9237,
|
||||
IPMI_OEM_VIKING = 9237,
|
||||
IPMI_OEM_ADVANTECH = 10297,
|
||||
IPMI_OEM_FUJITSU_SIEMENS = 10368,
|
||||
IPMI_OEM_AVOCENT = 10418,
|
||||
|
@ -57,6 +57,28 @@
|
||||
#define IPMI_CHANNEL_SESSION_MULTI 0x80
|
||||
#define IPMI_CHANNEL_SESSION_BASED 0xC0
|
||||
|
||||
/* Fixed channel numbers as per Table 6-1 */
|
||||
typedef enum {
|
||||
CH_PRIMARY_IPMB,
|
||||
CH_IMP_SPECIFIC_1,
|
||||
CH_IMP_SPECIFIC_2,
|
||||
CH_IMP_SPECIFIC_3,
|
||||
CH_IMP_SPECIFIC_4,
|
||||
CH_IMP_SPECIFIC_5,
|
||||
CH_IMP_SPECIFIC_6,
|
||||
CH_IMP_SPECIFIC_7,
|
||||
CH_IMP_SPECIFIC_8,
|
||||
CH_IMP_SPECIFIC_9,
|
||||
CH_IMP_SPECIFIC_A,
|
||||
CH_IMP_SPECIFIC_B,
|
||||
CH_RSVD1,
|
||||
CH_RSVD2,
|
||||
CH_CURRENT,
|
||||
CH_SYSTEM,
|
||||
CH_TOTAL,
|
||||
CH_UNKNOWN = UINT8_MAX
|
||||
} ipmi_channel_num_t;
|
||||
|
||||
/* (22.24) Get Channel Info */
|
||||
struct channel_info_t {
|
||||
uint8_t channel;
|
||||
@ -189,7 +211,8 @@ int _ipmi_set_channel_access(struct ipmi_intf *intf,
|
||||
uint8_t privilege_option);
|
||||
|
||||
uint8_t ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel);
|
||||
uint8_t ipmi_current_channel_medium(struct ipmi_intf * intf);
|
||||
void ipmi_current_channel_info(struct ipmi_intf *intf,
|
||||
struct channel_info_t *chinfo);
|
||||
int ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv);
|
||||
int ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
|
||||
uint8_t channel, uint8_t priv);
|
||||
|
@ -25,22 +25,21 @@
|
||||
/* DCMI commands per DCMI 1.5 SPEC */
|
||||
|
||||
#define IPMI_DCMI 0xDC /* Group Extension Identification */
|
||||
#define IPMI_DCMI_COMPAT 0x01
|
||||
#define IPMI_DCMI_GETRED 0x02
|
||||
#define IPMI_DCMI_GETLMT 0x03
|
||||
#define IPMI_DCMI_SETLMT 0x04
|
||||
#define IPMI_DCMI_PWRACT 0x05
|
||||
#define IPMI_DCMI_GETASSET 0x06
|
||||
#define IPMI_DCMI_SETASSET 0x08
|
||||
#define IPMI_DCMI_GETMNGCTRLIDS 0x09
|
||||
#define IPMI_DCMI_SETMNGCTRLIDS 0x0A
|
||||
#define IPMI_DCMI_SETTERMALLIMIT 0x0B
|
||||
#define IPMI_DCMI_GETTERMALLIMIT 0x0C
|
||||
#define IPMI_DCMI_GETSNSR 0x07
|
||||
#define IPMI_DCMI_PWRMGT 0x08
|
||||
#define IPMI_DCMI_GETTEMPRED 0x10
|
||||
#define IPMI_DCMI_SETCONFPARAM 0x12
|
||||
#define IPMI_DCMI_GETCONFPARAM 0x13
|
||||
#define IPMI_DCMI_GET_CAPS 0x01 /* Get Capabilities */
|
||||
#define IPMI_DCMI_GET_PWR_READING 0x02 /* Get Power Reading */
|
||||
#define IPMI_DCMI_GET_PWR_LIM 0x03 /* Get Power Limit */
|
||||
#define IPMI_DCMI_SET_PWR_LIM 0x04 /* Set Power Limit */
|
||||
#define IPMI_DCMI_ACT_PWR_LIM 0x05 /* Activate/Deactivate Power Limit */
|
||||
#define IPMI_DCMI_GET_ASSET_TAG 0x06 /* Get Asset Tag */
|
||||
#define IPMI_DCMI_SET_ASSET_TAG 0x08 /* Set Asset Tag */
|
||||
#define IPMI_DCMI_GET_MC_ID 0x09 /* Get Management Controller ID String */
|
||||
#define IPMI_DCMI_SET_MC_ID 0x0A /* Set Management Controller ID String */
|
||||
#define IPMI_DCMI_SET_THERM_LIM 0x0B /* Set Thermal Limit */
|
||||
#define IPMI_DCMI_GET_THERM_LIM 0x0C /* Get Thermal Limit */
|
||||
#define IPMI_DCMI_GET_SENSOR_INFO 0x07 /* Get DCMI Sensor Info */
|
||||
#define IPMI_DCMI_GET_TEMP 0x10 /* Get Temperature Readings */
|
||||
#define IPMI_DCMI_SET_CONF_PARAM 0x12 /* Set DCMI Configuration Parameters */
|
||||
#define IPMI_DCMI_GET_CONF_PARAM 0x13 /* Get DCMI Configuration Parameters */
|
||||
|
||||
#define IPMI_DCMI_CONFORM 0x0001
|
||||
#define IPMI_DCMI_1_1_CONFORM 0x0101
|
||||
@ -52,53 +51,6 @@
|
||||
#define GOOD_PWR_GLIMIT_CCODE(ccode) ((ccode = ((ccode == 0x80) ? 0 : ccode)))
|
||||
#define GOOD_ASSET_TAG_CCODE(ccode) ((ccode = (((ccode == 0x80) || (ccode == 0x81) || (ccode == 0x82) || (ccode == 0x83)) ? 0 : ccode)))
|
||||
|
||||
/* External Node Manager Configuration and Control Commands per spec 2.0 */
|
||||
|
||||
#define IPMI_NM_POLICY_CTL 0xC0
|
||||
#define IPMI_NM_SET_POLICY 0xC1
|
||||
#define IPMI_NM_GET_POLICY 0xC2
|
||||
#define IPMI_NM_SET_ALERT_TH 0xC3
|
||||
#define IPMI_NM_GET_ALERT_TH 0xC4
|
||||
#define IPMI_NM_SET_SUSPEND 0xC5
|
||||
#define IPMI_NM_GET_SUSPEND 0xC6
|
||||
#define IPMI_NM_RESET_STATS 0xC7
|
||||
#define IPMI_NM_GET_STATS 0xC8
|
||||
#define IPMI_NM_GET_CAP 0xC9
|
||||
#define IPMI_NM_GET_VERSION 0xCA
|
||||
#define IPMI_NM_SET_POWER 0xCB
|
||||
#define IPMI_NM_SET_ALERT_DS 0xCE
|
||||
#define IPMI_NM_GET_ALERT_DS 0xCF
|
||||
#define IPMI_NM_LIMITING 0xF2
|
||||
|
||||
/* Node Manager Policy Control Flags */
|
||||
#define IPMI_NM_GLOBAL_ENABLE 0x01
|
||||
#define IPMI_NM_DOMAIN_ENABLE 0x02
|
||||
#define IPMI_NM_PER_POLICY_ENABLE 0x04
|
||||
|
||||
/* Node Manager Set Policy Enable */
|
||||
#define IPMI_NM_POLICY_ENABLE 0x10
|
||||
|
||||
/* Node Manager Policy Trigger Codes */
|
||||
#define IPMI_NM_NO_POLICY_TRIG 0x00
|
||||
#define IPMI_NM_TEMP_TRIGGER 0x01
|
||||
#define IPMI_NM_NO_READ_TRIG 0x02
|
||||
#define IPMI_NM_RESET_TRIGGER 0x03
|
||||
#define IPMI_NM_BOOT_TRIGGER 0x04
|
||||
|
||||
/* Policy Exception Actions flags */
|
||||
#define IPMI_NM_POLICY_ALERT 0x01
|
||||
#define IPMI_NM_POLICY_SHUT 0x02
|
||||
|
||||
/* Power Correction codes for Policy action */
|
||||
#define IPMI_NM_PWR_AUTO_CORR 0x00
|
||||
#define IPMI_NM_PWR_SOFT_CORR 0x01
|
||||
#define IPMI_NM_PWR_AGGR_CORR 0x02
|
||||
|
||||
/* Set Threshold message size */
|
||||
#define IPMI_NM_SET_THRESH_LEN 12
|
||||
|
||||
/* Number of Suspend Periods */
|
||||
#define IPMI_NM_SUSPEND_PERIOD_MAX 5
|
||||
|
||||
struct dcmi_cmd {
|
||||
uint16_t val;
|
||||
@ -106,6 +58,13 @@ struct dcmi_cmd {
|
||||
const char * desc;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a termination macro for all struct dcmi_cmd arrays,
|
||||
* def argument is the default value returned by str2val2()
|
||||
* when string is not found in the array
|
||||
*/
|
||||
#define DCMI_CMD_END(def) { (def), NULL, NULL }
|
||||
|
||||
/* make a struct for the return from the get limit command */
|
||||
struct power_limit {
|
||||
uint8_t grp_id; /* first byte: Group Extension ID */
|
||||
@ -172,99 +131,11 @@ struct thermal_limit {
|
||||
} __attribute__ ((packed));
|
||||
|
||||
int ipmi_dcmi_main(struct ipmi_intf * intf, int argc, char ** argv);
|
||||
uint16_t dcmi_str2val(const char *str, const struct dcmi_cmd *vs);
|
||||
const char *dcmi_val2str(uint16_t val, const struct dcmi_cmd *vs);
|
||||
void dcmi_print_strs(const struct dcmi_cmd * vs,
|
||||
const char * title,
|
||||
int loglevel,
|
||||
int verthorz);
|
||||
|
||||
/* Node Manager discover command */
|
||||
struct nm_discover {
|
||||
uint8_t intel_id[3]; /* Always returns 000157 */
|
||||
uint8_t nm_version;
|
||||
uint8_t ipmi_version;
|
||||
uint8_t patch_version;
|
||||
uint8_t major_rev;
|
||||
uint8_t minor_rev;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager get capabilities command */
|
||||
struct nm_capability {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t max_settings;
|
||||
uint16_t max_value; /* max power/thermal/time after reset */
|
||||
uint16_t min_value; /* min "" */
|
||||
uint32_t min_corr; /* min correction time inmillesecs */
|
||||
uint32_t max_corr;
|
||||
uint16_t min_stats;
|
||||
uint16_t max_stats;
|
||||
uint8_t scope;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager get statistics command */
|
||||
struct nm_statistics {
|
||||
uint8_t intel_id[3];
|
||||
uint16_t curr_value;
|
||||
uint16_t min_value;
|
||||
uint16_t max_value;
|
||||
uint16_t ave_value;
|
||||
uint32_t time_stamp;
|
||||
uint32_t stat_period;
|
||||
uint8_t id_state;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager set policy */
|
||||
struct nm_policy {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
||||
uint8_t policy_id;
|
||||
uint8_t policy_type; /* 0:3 trigger type 4 = action 5:6 correction */
|
||||
uint8_t policy_exception; /* exception actions */
|
||||
uint16_t policy_limits;
|
||||
uint32_t corr_time;
|
||||
uint16_t trigger_limit;
|
||||
uint16_t stats_period;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Maager get policy */
|
||||
struct nm_get_policy {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
||||
uint8_t policy_type; /* 0:3 trigger type 4 = action 5:6 correction */
|
||||
uint8_t policy_exception; /* exception actions */
|
||||
uint16_t policy_limits;
|
||||
uint32_t corr_time;
|
||||
uint16_t trigger_limit;
|
||||
uint16_t stats_period;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager set alert destination */
|
||||
struct nm_set_alert {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t chan; /* 0:3 BMC chan, 4:6 reserved, bit 7=0 register alert receiver =1 invalidate */
|
||||
uint8_t dest; /* lan destination */
|
||||
uint8_t string; /* alert string selector */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager set alert threshold */
|
||||
struct nm_thresh {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
||||
uint8_t policy_id;
|
||||
uint8_t count;
|
||||
uint16_t thresholds[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager suspend period struct */
|
||||
struct nm_period {
|
||||
uint8_t start;
|
||||
uint8_t stop;
|
||||
uint8_t repeat;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager set suspend period */
|
||||
struct nm_suspend {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
||||
uint8_t policy_id;
|
||||
uint8_t count;
|
||||
struct nm_period period[IPMI_NM_SUSPEND_PERIOD_MAX];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
int ipmi_nm_main(struct ipmi_intf * intf, int argc, char ** argv);
|
||||
#endif /*IPMI_DCMI_H*/
|
||||
|
@ -61,6 +61,33 @@ struct platform_event_msg {
|
||||
#pragma pack(0)
|
||||
#endif
|
||||
|
||||
/* See IPMI 2.0 Specification, Appendix G, Table G-1, "Event Commands" */
|
||||
typedef enum {
|
||||
IPMI_CMD_SET_EVENT_RCVR = 0,
|
||||
IPMI_CMD_GET_EVENT_RCVR,
|
||||
IPMI_CMD_PLATFORM_EVENT
|
||||
} ipmi_event_cmd_t;
|
||||
|
||||
typedef enum {
|
||||
PLATFORM_EVENT_DATA_LEN_NON_SI = sizeof(struct platform_event_msg),
|
||||
PLATFORM_EVENT_DATA_LEN_SI, /* System interfaces require generator ID */
|
||||
PLATFORM_EVENT_DATA_LEN_MAX = PLATFORM_EVENT_DATA_LEN_SI
|
||||
} ipmi_platform_event_data_len_t;
|
||||
|
||||
/* See Table 5-4 */
|
||||
typedef enum {
|
||||
EVENT_SWID_BIOS_BASE = 0x00, /* BIOS */
|
||||
EVENT_SWID_SMI_BASE = 0x10, /* SMI Handler */
|
||||
EVENT_SWID_SMS_BASE = 0x20, /* System Management Software */
|
||||
EVENT_SWID_OEM_BASE = 0x30, /* OEM */
|
||||
EVENT_SWID_REMOTE_CONSOLE_BASE = 0x40, /* Remote Console SW */
|
||||
EVENT_SWID_TERMINAL_MODE_BASE = 0x47 /* Terminal Mode RC SW */
|
||||
} ipmi_event_swid_t;
|
||||
#define EVENT_SWID(base, index) ((EVENT_SWID_##base##_BASE + index) & 0x7F)
|
||||
|
||||
/* See Figure 29-2, Table 32-1 */
|
||||
#define EVENT_GENERATOR(base, index) (EVENT_SWID(base,index) << 1 | 1)
|
||||
|
||||
int ipmi_event_main(struct ipmi_intf *, int, char **);
|
||||
|
||||
#endif /*IPMI_EVENT_H*/
|
||||
|
@ -241,6 +241,9 @@ struct ipmi_intf {
|
||||
void (*set_max_response_data_size)(struct ipmi_intf * intf, uint16_t size);
|
||||
};
|
||||
|
||||
uint16_t ipmi_intf_get_max_request_data_size(struct ipmi_intf *intf);
|
||||
uint16_t ipmi_intf_get_max_response_data_size(struct ipmi_intf *intf);
|
||||
|
||||
struct ipmi_intf * ipmi_intf_load(char * name);
|
||||
void ipmi_intf_print(struct ipmi_intf_support * intflist);
|
||||
|
||||
|
202
include/ipmitool/ipmi_nm.h
Normal file
202
include/ipmitool/ipmi_nm.h
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Intel Corporation.
|
||||
* All rights reserved
|
||||
*
|
||||
* 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 OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ipmitool/ipmi.h>
|
||||
#include <ipmitool/helper.h>
|
||||
|
||||
/* Configuration and control commands per
|
||||
* Intel Intelligent Power Node Manager 2.0
|
||||
* External Interface Specification Using IPMI
|
||||
*/
|
||||
|
||||
#define IPMI_NM_POLICY_CTL 0xC0
|
||||
#define IPMI_NM_SET_POLICY 0xC1
|
||||
#define IPMI_NM_GET_POLICY 0xC2
|
||||
#define IPMI_NM_SET_ALERT_TH 0xC3
|
||||
#define IPMI_NM_GET_ALERT_TH 0xC4
|
||||
#define IPMI_NM_SET_SUSPEND 0xC5
|
||||
#define IPMI_NM_GET_SUSPEND 0xC6
|
||||
#define IPMI_NM_RESET_STATS 0xC7
|
||||
#define IPMI_NM_GET_STATS 0xC8
|
||||
#define IPMI_NM_GET_CAP 0xC9
|
||||
#define IPMI_NM_GET_VERSION 0xCA
|
||||
#define IPMI_NM_SET_POWER 0xCB
|
||||
#define IPMI_NM_SET_ALERT_DS 0xCE
|
||||
#define IPMI_NM_GET_ALERT_DS 0xCF
|
||||
#define IPMI_NM_LIMITING 0xF2
|
||||
|
||||
/* Node Manager identification */
|
||||
#define IPMI_NM_ID 0x000157 /* Three bytes */
|
||||
|
||||
/* Node Manager Policy Control Flags */
|
||||
#define IPMI_NM_GLOBAL_ENABLE 0x01
|
||||
#define IPMI_NM_DOMAIN_ENABLE 0x02
|
||||
#define IPMI_NM_PER_POLICY_ENABLE 0x04
|
||||
|
||||
/* Node Manager Set Policy Enable */
|
||||
#define IPMI_NM_POLICY_ENABLE 0x10
|
||||
|
||||
/* Node Manager Policy Trigger Codes */
|
||||
#define IPMI_NM_NO_POLICY_TRIG 0x00
|
||||
#define IPMI_NM_TEMP_TRIGGER 0x01
|
||||
#define IPMI_NM_NO_READ_TRIG 0x02
|
||||
#define IPMI_NM_RESET_TRIGGER 0x03
|
||||
#define IPMI_NM_BOOT_TRIGGER 0x04
|
||||
|
||||
/* Node Manager status codes, as per
|
||||
* "Intel Intelligent Power Node Manager 3.0
|
||||
* External Interface Specification using IPMI"
|
||||
*/
|
||||
#define IPMI_NM_CC_POLICY_ID_INVALID 0x80
|
||||
#define IPMI_NM_CC_POLICY_DOMAIN_INVALID 0x81
|
||||
#define IPMI_NM_CC_POLICY_TRIGGER_UNKNOWN 0x82
|
||||
#define IPMI_NM_CC_POLICY_CORRECTION_RANGE 0x85
|
||||
#define IPMI_NM_CC_POLICY_TRIGGER_RANGE 0x86
|
||||
#define IPMI_NM_CC_POLICY_STATS_RANGE 0x89
|
||||
#define IPMI_NM_CC_POLICY_LIMIT_NONE 0xA1
|
||||
#define IPMI_NM_CC_POLICY_PARAM_BUSY 0xD5
|
||||
#define IPMI_NM_CC_POLICY_DOMAIN_ERR 0xD6
|
||||
#define IPMI_NM_CC_POLICY_VALUE_INVALID 0x8B
|
||||
#define IPMI_NM_CC_STATS_MODE_INVALID 0x88
|
||||
#define IPMI_NM_CC_POWER_LIMIT_RANGE 0x84
|
||||
|
||||
/* Policy Exception Actions flags */
|
||||
#define IPMI_NM_POLICY_ALERT 0x01
|
||||
#define IPMI_NM_POLICY_SHUT 0x02
|
||||
|
||||
/* Power Correction codes for Policy action */
|
||||
#define IPMI_NM_PWR_AUTO_CORR 0x00
|
||||
#define IPMI_NM_PWR_SOFT_CORR 0x01
|
||||
#define IPMI_NM_PWR_AGGR_CORR 0x02
|
||||
|
||||
/* Set Threshold message size */
|
||||
#define IPMI_NM_SET_THRESH_LEN 12
|
||||
|
||||
/* Number of Suspend Periods */
|
||||
#define IPMI_NM_SUSPEND_PERIOD_MAX 5
|
||||
|
||||
/* Node Manager discover command */
|
||||
struct nm_discover {
|
||||
uint8_t intel_id[3]; /* Always returns 000157 */
|
||||
uint8_t nm_version;
|
||||
uint8_t ipmi_version;
|
||||
uint8_t patch_version;
|
||||
uint8_t major_rev;
|
||||
uint8_t minor_rev;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager get capabilities command */
|
||||
struct nm_capability {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t max_settings;
|
||||
uint16_t max_value; /* max power/thermal/time after reset */
|
||||
uint16_t min_value; /* min "" */
|
||||
uint32_t min_corr; /* min correction time inmillesecs */
|
||||
uint32_t max_corr;
|
||||
uint16_t min_stats;
|
||||
uint16_t max_stats;
|
||||
uint8_t scope;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager get statistics command */
|
||||
struct nm_statistics {
|
||||
uint8_t intel_id[3];
|
||||
uint16_t curr_value;
|
||||
uint16_t min_value;
|
||||
uint16_t max_value;
|
||||
uint16_t ave_value;
|
||||
uint32_t time_stamp;
|
||||
uint32_t stat_period;
|
||||
uint8_t id_state;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager set policy */
|
||||
struct nm_policy {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
||||
uint8_t policy_id;
|
||||
uint8_t policy_type; /* 0:3 trigger type 4 = action 5:6 correction */
|
||||
uint8_t policy_exception; /* exception actions */
|
||||
uint16_t policy_limits;
|
||||
uint32_t corr_time;
|
||||
uint16_t trigger_limit;
|
||||
uint16_t stats_period;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Maager get policy */
|
||||
struct nm_get_policy {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
||||
uint8_t policy_type; /* 0:3 trigger type 4 = action 5:6 correction */
|
||||
uint8_t policy_exception; /* exception actions */
|
||||
uint16_t policy_limits;
|
||||
uint32_t corr_time;
|
||||
uint16_t trigger_limit;
|
||||
uint16_t stats_period;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager set alert destination */
|
||||
struct nm_set_alert {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t chan; /* 0:3 BMC chan
|
||||
* 4:6 reserved
|
||||
* 7 = 0 register alert receiver
|
||||
* = 1 invalidate
|
||||
*/
|
||||
uint8_t dest; /* LAN destination */
|
||||
uint8_t string; /* alert string selector */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager set alert threshold */
|
||||
struct nm_thresh {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
||||
uint8_t policy_id;
|
||||
uint8_t count;
|
||||
uint16_t thresholds[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager suspend period struct */
|
||||
struct nm_period {
|
||||
uint8_t start;
|
||||
uint8_t stop;
|
||||
uint8_t repeat;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Node Manager set suspend period */
|
||||
struct nm_suspend {
|
||||
uint8_t intel_id[3];
|
||||
uint8_t domain; /* 0:3 are domain, 4 = Policy enabled */
|
||||
uint8_t policy_id;
|
||||
uint8_t count;
|
||||
struct nm_period period[IPMI_NM_SUSPEND_PERIOD_MAX];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
int ipmi_nm_main(struct ipmi_intf *intf, int argc, char **argv);
|
||||
|
||||
static inline void nm_set_id(void *buf)
|
||||
{
|
||||
htoipmi24(IPMI_NM_ID, buf);
|
||||
}
|
||||
|
||||
static inline bool nm_check_id(void *buf)
|
||||
{
|
||||
return IPMI_NM_ID == ipmi24toh(buf);
|
||||
}
|
@ -679,7 +679,7 @@ void ipmi_sel_print_extended_entry_verbose(struct ipmi_intf * intf, struct sel_e
|
||||
void ipmi_get_event_desc(struct ipmi_intf * intf, struct sel_event_record * rec, char ** desc);
|
||||
const char * ipmi_get_sensor_type(struct ipmi_intf *intf, uint8_t code);
|
||||
uint16_t ipmi_sel_get_std_entry(struct ipmi_intf * intf, uint16_t id, struct sel_event_record * evt);
|
||||
char * get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec);
|
||||
char * get_viking_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec);
|
||||
IPMI_OEM ipmi_get_oem(struct ipmi_intf * intf);
|
||||
char * ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec);
|
||||
int ipmi_sel_oem_init(const char * filename);
|
||||
|
@ -53,8 +53,10 @@ extern const struct valstr ipmi_chassis_power_control_vals[];
|
||||
extern const struct valstr ipmi_auth_algorithms[];
|
||||
extern const struct valstr ipmi_integrity_algorithms[];
|
||||
extern const struct valstr ipmi_encryption_algorithms[];
|
||||
extern const struct valstr ipmi_oem_info[];
|
||||
extern const struct valstr ipmi_user_enable_status_vals[];
|
||||
extern const struct valstr *ipmi_oem_info;
|
||||
int ipmi_oem_info_init();
|
||||
void ipmi_oem_info_free();
|
||||
|
||||
extern const struct valstr picmg_frucontrol_vals[];
|
||||
extern const struct valstr picmg_clk_family_vals[];
|
||||
|
@ -59,5 +59,17 @@ int log_level_get(void);
|
||||
void lprintf(int level, const char * format, ...);
|
||||
void lperror(int level, const char * format, ...);
|
||||
|
||||
/**
|
||||
* @brief Print to log or to STDOUT depending on the \p ll argument.
|
||||
* @param[in] ll Log level. Negative values meant "print to stdout".
|
||||
* @param[in] fmt The printf format string. No '\n' is needed at the end.
|
||||
*/
|
||||
#define uprintf(ll, fmt, ...) do { \
|
||||
if (ll < 0) \
|
||||
printf(fmt "\n", ##__VA_ARGS__); \
|
||||
else \
|
||||
lprintf(ll, fmt, ##__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#endif /*IPMITOOL_LOG_H*/
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
PEN_LIST = $(srcdir)/ipmi_pen_list.inc.c
|
||||
|
||||
noinst_LTLIBRARIES = libipmitool.la
|
||||
libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \
|
||||
@ -41,7 +40,7 @@ libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \
|
||||
ipmi_oem.c ipmi_isol.c ipmi_sunoem.c ipmi_fwum.c ipmi_picmg.c \
|
||||
ipmi_main.c ipmi_tsol.c ipmi_firewall.c ipmi_kontronoem.c \
|
||||
ipmi_hpmfwupg.c ipmi_sdradd.c ipmi_ekanalyzer.c ipmi_gendev.c \
|
||||
ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c hpm2.c ipmi_vita.c \
|
||||
ipmi_ime.c ipmi_delloem.c ipmi_dcmi.c ipmi_nm.c hpm2.c ipmi_vita.c \
|
||||
ipmi_lanp6.c ipmi_cfgp.c ipmi_quantaoem.c ipmi_time.c \
|
||||
../src/plugins/lan/md5.c ../src/plugins/lan/md5.h
|
||||
|
||||
@ -49,8 +48,3 @@ libipmitool_la_LDFLAGS = -export-dynamic
|
||||
libipmitool_la_LIBADD = -lm
|
||||
libipmitool_la_DEPENDENCIES =
|
||||
|
||||
$(PEN_LIST):
|
||||
$(srcdir)/create_pen_list $(PEN_LIST)
|
||||
|
||||
ipmi_strings.lo: $(PEN_LIST)
|
||||
|
||||
|
@ -1,77 +0,0 @@
|
||||
#!/bin/bash
|
||||
# vi: set ts=2 sw=2 et :
|
||||
#
|
||||
# IANA PEN List generator
|
||||
#
|
||||
# This script takes the official IANA PEN registry and generates
|
||||
# a C language output for inclusion into ipmi_strings.c
|
||||
#
|
||||
# Copyright (c) 2018 Alexander Amelkin <alexander@amelkin.msk.ru>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
OUTFILE=$1
|
||||
PENLIST_URL=https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
|
||||
|
||||
if [ -z "$OUTFILE" ]; then
|
||||
echo $0: Must specify output file
|
||||
exit
|
||||
fi
|
||||
|
||||
parse_pen_list() {
|
||||
iconv -f utf8 -t ascii//TRANSLIT//IGNORE \
|
||||
| awk '
|
||||
/^[0-9]+/ {
|
||||
if(PEN) {
|
||||
print "{ " PEN ", \"" ENTERPRISE "\" },"
|
||||
}
|
||||
PEN=$1
|
||||
}
|
||||
|
||||
/^ [[:alnum:]]/ {
|
||||
# Remove leading spaces
|
||||
sub(/^[[:space:]]+/,"")
|
||||
# Remove question marks (Chinese characters after iconv)
|
||||
gsub(/\?/,"");
|
||||
# Remove non-printable characters
|
||||
gsub(/[^[:print:]]/,"");
|
||||
# Escape slashes and double quotes
|
||||
gsub(/["\\]/,"\\\\&")
|
||||
ENTERPRISE=$0;
|
||||
}
|
||||
|
||||
END {
|
||||
if(PEN) {
|
||||
print "{ " PEN ", \"" ENTERPRISE "\" },"
|
||||
}
|
||||
}'
|
||||
}
|
||||
|
||||
echo "Generating IANA PEN list..."
|
||||
curl -# "$PENLIST_URL" | parse_pen_list > "$OUTFILE"
|
160
lib/helper.c
160
lib/helper.c
@ -319,26 +319,74 @@ mac2str(const uint8_t *buf)
|
||||
return buf2str_extended(buf, 6, ":");
|
||||
}
|
||||
|
||||
const char * val2str(uint16_t val, const struct valstr *vs)
|
||||
/**
|
||||
* 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(uint32_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;
|
||||
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(uint32_t val)
|
||||
{
|
||||
static char un_str[32];
|
||||
memset(un_str, 0, 32);
|
||||
snprintf(un_str, 32, "Unknown (0x%02X)", val);
|
||||
|
||||
return un_str;
|
||||
}
|
||||
|
||||
const char * oemval2str(uint32_t oem, uint16_t val,
|
||||
const char *
|
||||
specific_val2str(uint32_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(uint32_t val, const struct valstr *vs)
|
||||
{
|
||||
return specific_val2str(val, NULL, vs);
|
||||
}
|
||||
|
||||
|
||||
const char *oemval2str(uint32_t oem, uint32_t val,
|
||||
const struct oemvalstr *vs)
|
||||
{
|
||||
static char un_str[32];
|
||||
int i;
|
||||
|
||||
for (i = 0; vs[i].oem != 0xffffff && vs[i].str; i++) {
|
||||
@ -349,10 +397,7 @@ const char * oemval2str(uint32_t oem, uint16_t val,
|
||||
}
|
||||
}
|
||||
|
||||
memset(un_str, 0, 32);
|
||||
snprintf(un_str, 32, "Unknown (0x%X)", val);
|
||||
|
||||
return un_str;
|
||||
return unknown_val_str(val);
|
||||
}
|
||||
|
||||
/* str2double - safely convert string to double
|
||||
@ -597,7 +642,7 @@ int str2uchar(const char * str, uint8_t * uchr_ptr)
|
||||
return 0;
|
||||
} /* str2uchar(...) */
|
||||
|
||||
uint16_t str2val(const char *str, const struct valstr *vs)
|
||||
uint32_t str2val32(const char *str, const struct valstr *vs)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -624,38 +669,22 @@ print_valstr(const struct valstr * vs, const char * title, int loglevel)
|
||||
return;
|
||||
|
||||
if (title) {
|
||||
if (loglevel < 0)
|
||||
printf("\n%s:\n\n", title);
|
||||
else
|
||||
lprintf(loglevel, "\n%s:\n", title);
|
||||
uprintf(loglevel, "\n%s:\n", title);
|
||||
}
|
||||
|
||||
if (loglevel < 0) {
|
||||
printf(" VALUE\tHEX\tSTRING\n");
|
||||
printf("==============================================\n");
|
||||
} else {
|
||||
lprintf(loglevel, " VAL\tHEX\tSTRING");
|
||||
lprintf(loglevel, "==============================================");
|
||||
}
|
||||
uprintf(loglevel, " VALUE\tHEX\tSTRING");
|
||||
uprintf(loglevel, "==============================================");
|
||||
|
||||
for (i = 0; vs[i].str; i++) {
|
||||
if (loglevel < 0) {
|
||||
if (vs[i].val < 256)
|
||||
printf(" %d\t0x%02x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
|
||||
uprintf(loglevel, " %d\t0x%02x\t%s",
|
||||
vs[i].val, vs[i].val, vs[i].str);
|
||||
else
|
||||
printf(" %d\t0x%04x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
|
||||
} else {
|
||||
if (vs[i].val < 256)
|
||||
lprintf(loglevel, " %d\t0x%02x\t%s", vs[i].val, vs[i].val, vs[i].str);
|
||||
else
|
||||
lprintf(loglevel, " %d\t0x%04x\t%s", vs[i].val, vs[i].val, vs[i].str);
|
||||
}
|
||||
uprintf(loglevel, " %d\t0x%04x\t%s",
|
||||
vs[i].val, vs[i].val, vs[i].str);
|
||||
}
|
||||
|
||||
if (loglevel < 0)
|
||||
printf("\n");
|
||||
else
|
||||
lprintf(loglevel, "");
|
||||
uprintf(loglevel, "");
|
||||
}
|
||||
|
||||
/* print_valstr_2col - print value string list in two columns to log or stdout
|
||||
@ -673,37 +702,22 @@ print_valstr_2col(const struct valstr * vs, const char * title, int loglevel)
|
||||
return;
|
||||
|
||||
if (title) {
|
||||
if (loglevel < 0)
|
||||
printf("\n%s:\n\n", title);
|
||||
else
|
||||
lprintf(loglevel, "\n%s:\n", title);
|
||||
uprintf(loglevel, "\n%s:\n", title);
|
||||
}
|
||||
|
||||
for (i = 0; vs[i].str; i++) {
|
||||
if (!vs[i+1].str) {
|
||||
/* last one */
|
||||
if (loglevel < 0) {
|
||||
printf(" %4d %-32s\n", vs[i].val, vs[i].str);
|
||||
} else {
|
||||
lprintf(loglevel, " %4d %-32s\n", vs[i].val, vs[i].str);
|
||||
}
|
||||
uprintf(loglevel, " %4d %-32s\n", vs[i].val, vs[i].str);
|
||||
}
|
||||
else {
|
||||
if (loglevel < 0) {
|
||||
printf(" %4d %-32s %4d %-32s\n",
|
||||
uprintf(loglevel, " %4d %-32s %4d %-32s\n",
|
||||
vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
|
||||
} else {
|
||||
lprintf(loglevel, " %4d %-32s %4d %-32s\n",
|
||||
vs[i].val, vs[i].str, vs[i+1].val, vs[i+1].str);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (loglevel < 0)
|
||||
printf("\n");
|
||||
else
|
||||
lprintf(loglevel, "");
|
||||
uprintf(loglevel, ""); /* Empty spacer line */
|
||||
}
|
||||
|
||||
/* ipmi_csum - calculate an ipmi checksum
|
||||
@ -1080,3 +1094,35 @@ 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;
|
||||
}
|
||||
|
@ -244,10 +244,28 @@ ipmi_1_5_authtypes(uint8_t n)
|
||||
return supportedTypes;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ipmi_current_channel_medium(struct ipmi_intf *intf)
|
||||
void
|
||||
ipmi_current_channel_info(struct ipmi_intf *intf,
|
||||
struct channel_info_t *chinfo)
|
||||
{
|
||||
return ipmi_get_channel_medium(intf, 0xE);
|
||||
int ccode = 0;
|
||||
|
||||
chinfo->channel = CH_CURRENT;
|
||||
ccode = _ipmi_get_channel_info(intf, chinfo);
|
||||
if (ccode) {
|
||||
if (ccode != IPMI_CC_INV_DATA_FIELD_IN_REQ) {
|
||||
if (ccode > 0) {
|
||||
lprintf(LOG_ERR, "Get Channel Info command failed: %s",
|
||||
val2str(ccode, completion_code_vals));
|
||||
}
|
||||
else {
|
||||
eval_ccode(ccode);
|
||||
}
|
||||
}
|
||||
chinfo->channel = CH_UNKNOWN;
|
||||
chinfo->medium = IPMI_CHANNEL_MEDIUM_RESERVED;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -684,13 +702,16 @@ ipmi_get_channel_medium(struct ipmi_intf *intf, uint8_t channel)
|
||||
|
||||
channel_info.channel = channel;
|
||||
ccode = _ipmi_get_channel_info(intf, &channel_info);
|
||||
if (ccode == 0xCC) {
|
||||
return IPMI_CHANNEL_MEDIUM_RESERVED;
|
||||
} else if (ccode < 0 && eval_ccode(ccode) != 0) {
|
||||
return 0;
|
||||
} else if (ccode) {
|
||||
if (ccode) {
|
||||
if (ccode != IPMI_CC_INV_DATA_FIELD_IN_REQ) {
|
||||
if (ccode > 0) {
|
||||
lprintf(LOG_ERR, "Get Channel Info command failed: %s",
|
||||
val2str(ccode, completion_code_vals));
|
||||
}
|
||||
else {
|
||||
eval_ccode(ccode);
|
||||
}
|
||||
}
|
||||
return IPMI_CHANNEL_MEDIUM_RESERVED;
|
||||
}
|
||||
lprintf(LOG_DEBUG, "Channel type: %s",
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <ipmitool/bswap.h>
|
||||
#include <ipmitool/helper.h>
|
||||
@ -44,8 +46,40 @@
|
||||
#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)
|
||||
{
|
||||
@ -446,61 +480,166 @@ ipmi_chassis_selftest(struct ipmi_intf * intf)
|
||||
}
|
||||
|
||||
static int
|
||||
ipmi_chassis_set_bootparam(struct ipmi_intf * intf, uint8_t param, uint8_t * data, int len)
|
||||
ipmi_chassis_set_bootparam(struct ipmi_intf * intf,
|
||||
uint8_t param, void *data, int len)
|
||||
{
|
||||
struct ipmi_rs * rsp;
|
||||
struct ipmi_rq req;
|
||||
uint8_t msg_data[16];
|
||||
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;
|
||||
|
||||
memset(msg_data, 0, 16);
|
||||
msg_data[0] = param & 0x7f;
|
||||
memcpy(msg_data+1, data, len);
|
||||
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(&req, 0, sizeof(req));
|
||||
req.msg.netfn = IPMI_NETFN_CHASSIS;
|
||||
req.msg.cmd = 0x8;
|
||||
req.msg.data = msg_data;
|
||||
req.msg.data_len = len + 1;
|
||||
req.msg.data = (uint8_t *)msg_data;
|
||||
req.msg.data_len = msgsize;
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (!rsp) {
|
||||
lprintf(LOG_ERR, "Error setting Chassis Boot Parameter %d", param);
|
||||
return -1;
|
||||
}
|
||||
if (rsp->ccode) {
|
||||
|
||||
rc = rsp->ccode;
|
||||
if (rc) {
|
||||
if (param != 0) {
|
||||
lprintf(LOG_ERR, "Set Chassis Boot Parameter %d failed: %s",
|
||||
param, val2str(rsp->ccode, completion_code_vals));
|
||||
lprintf(LOG_ERR,
|
||||
"Set Chassis Boot Parameter %d failed: %s",
|
||||
param,
|
||||
specific_val2str(rsp->ccode,
|
||||
set_bootparam_cc_vals,
|
||||
completion_code_vals));
|
||||
}
|
||||
return rsp->ccode;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lprintf(LOG_DEBUG, "Chassis Set Boot Parameter %d to %s", param, buf2str(data, len));
|
||||
return IPMI_CC_OK;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg)
|
||||
ipmi_chassis_get_bootparam(struct ipmi_intf * intf,
|
||||
int argc, char *argv[], int flags)
|
||||
{
|
||||
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 (!arg)
|
||||
return -1;
|
||||
|
||||
if (str2uchar(arg, ¶m_id) != 0) {
|
||||
lprintf(LOG_ERR, "Invalid parameter '%s' given instead of bootparam.",
|
||||
arg);
|
||||
return (-1);
|
||||
if (argc < 1 || !argv[0]) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (str2uchar(argv[0], ¶m_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;
|
||||
msg_data[1] = 0;
|
||||
msg_data[2] = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.msg.netfn = IPMI_NETFN_CHASSIS;
|
||||
@ -510,12 +649,21 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg)
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (!rsp) {
|
||||
lprintf(LOG_ERR, "Error Getting Chassis Boot Parameter %s", arg);
|
||||
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) {
|
||||
return -1;
|
||||
}
|
||||
if (rsp->ccode) {
|
||||
lprintf(LOG_ERR, "Get Chassis Boot Parameter %s failed: %s",
|
||||
arg, val2str(rsp->ccode, completion_code_vals));
|
||||
lprintf(LOG_ERR,
|
||||
"Get Chassis Boot Parameter %" PRIu8 " failed: %s",
|
||||
msg_data[0],
|
||||
specific_val2str(rsp->ccode,
|
||||
get_bootparam_cc_vals,
|
||||
completion_code_vals));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -525,10 +673,17 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg)
|
||||
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");
|
||||
printf("Boot parameter data: %s\n", buf2str(rsp->data+2, rsp->data_len - 2));
|
||||
(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));
|
||||
}
|
||||
}
|
||||
|
||||
switch(param_id)
|
||||
{
|
||||
@ -716,17 +871,18 @@ ipmi_chassis_get_bootparam(struct ipmi_intf * intf, char * arg)
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
printf(" Selector : %d\n", rsp->data[2] );
|
||||
printf(" Block Data : %s\n", buf2str(rsp->data+3, rsp->data_len - 2));
|
||||
}
|
||||
chassis_bootmailbox_parse(rsp->data + 2,
|
||||
rsp->data_len - 2,
|
||||
flags);
|
||||
break;
|
||||
default:
|
||||
printf(" Undefined byte\n");
|
||||
printf(" Unsupported parameter %" PRIu8 "\n", param_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
rc = IPMI_CC_OK;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -832,7 +988,10 @@ ipmi_chassis_get_bootvalid(struct ipmi_intf * intf)
|
||||
}
|
||||
if (rsp->ccode) {
|
||||
lprintf(LOG_ERR, "Get Chassis Boot Parameter %d failed: %s",
|
||||
param_id, val2str(rsp->ccode, completion_code_vals));
|
||||
param_id,
|
||||
specific_val2str(rsp->ccode,
|
||||
get_bootparam_cc_vals,
|
||||
completion_code_vals));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1001,6 +1160,296 @@ out:
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -1111,7 +1560,10 @@ 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: status, power, identify, policy, restart_cause, poh, bootdev, bootparam, selftest");
|
||||
lprintf(LOG_NOTICE, "Chassis Commands:\n"
|
||||
" status, power, policy, restart_cause\n"
|
||||
" poh, identify, selftest,\n"
|
||||
" bootdev, bootparam, bootmbox");
|
||||
}
|
||||
else if (strncmp(argv[0], "status", 6) == 0) {
|
||||
rc = ipmi_chassis_status(intf);
|
||||
@ -1199,7 +1651,10 @@ 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, argv[2]);
|
||||
rc = ipmi_chassis_get_bootparam(intf,
|
||||
argc - 2,
|
||||
argv + 2,
|
||||
0);
|
||||
}
|
||||
else if (strncmp(argv[1], "set", 3) == 0) {
|
||||
unsigned char set_flag=0;
|
||||
@ -1339,6 +1794,9 @@ 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;
|
||||
|
1932
lib/ipmi_dcmi.c
1932
lib/ipmi_dcmi.c
File diff suppressed because it is too large
Load Diff
123
lib/ipmi_event.c
123
lib/ipmi_event.c
@ -52,6 +52,14 @@
|
||||
#include <ipmitool/ipmi_event.h>
|
||||
#include <ipmitool/ipmi_sdr.h>
|
||||
|
||||
static
|
||||
inline
|
||||
bool
|
||||
is_system(const struct channel_info_t *chinfo)
|
||||
{
|
||||
return (IPMI_CHANNEL_MEDIUM_SYSTEM == chinfo->medium
|
||||
|| CH_SYSTEM == chinfo->channel);
|
||||
}
|
||||
|
||||
static void
|
||||
ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
|
||||
@ -61,7 +69,8 @@ ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
|
||||
memset(&sel_event, 0, sizeof(struct sel_event_record));
|
||||
|
||||
sel_event.record_id = 0;
|
||||
sel_event.sel_type.standard_type.gen_id = 2;
|
||||
htoipmi16(EVENT_GENERATOR(SMS, 0),
|
||||
(void *)&sel_event.sel_type.standard_type.gen_id);
|
||||
|
||||
sel_event.sel_type.standard_type.evm_rev = pmsg->evm_rev;
|
||||
sel_event.sel_type.standard_type.sensor_type = pmsg->sensor_type;
|
||||
@ -83,28 +92,34 @@ ipmi_send_platform_event(struct ipmi_intf * intf, struct platform_event_msg * em
|
||||
{
|
||||
struct ipmi_rs * rsp;
|
||||
struct ipmi_rq req;
|
||||
uint8_t rqdata[8];
|
||||
uint8_t chmed;
|
||||
uint8_t rqdata[PLATFORM_EVENT_DATA_LEN_MAX];
|
||||
uint8_t *rqdata_start = rqdata;
|
||||
struct channel_info_t chinfo;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(rqdata, 0, 8);
|
||||
memset(rqdata, 0, sizeof(rqdata));
|
||||
|
||||
req.msg.netfn = IPMI_NETFN_SE;
|
||||
req.msg.cmd = 0x02;
|
||||
req.msg.cmd = IPMI_CMD_PLATFORM_EVENT;
|
||||
req.msg.data = rqdata;
|
||||
req.msg.data_len = PLATFORM_EVENT_DATA_LEN_NON_SI;
|
||||
|
||||
chmed = ipmi_current_channel_medium(intf);
|
||||
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
|
||||
/* system interface, need extra generator ID */
|
||||
req.msg.data_len = 8;
|
||||
rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
|
||||
memcpy(rqdata+1, emsg, sizeof(struct platform_event_msg));
|
||||
ipmi_current_channel_info(intf, &chinfo);
|
||||
if (chinfo.channel == CH_UNKNOWN) {
|
||||
lprintf(LOG_ERR, "Failed to send the platform event "
|
||||
"via an unknown channel");
|
||||
return -3;
|
||||
}
|
||||
else {
|
||||
req.msg.data_len = 7;
|
||||
memcpy(rqdata, emsg, sizeof(struct platform_event_msg));
|
||||
|
||||
if (is_system(&chinfo)) {
|
||||
/* system interface, need extra generator ID, see Fig. 29-2 */
|
||||
req.msg.data_len = PLATFORM_EVENT_DATA_LEN_SI;
|
||||
rqdata[0] = EVENT_GENERATOR(SMS, 0);
|
||||
rqdata_start++;
|
||||
}
|
||||
|
||||
memcpy(rqdata_start, emsg, sizeof(struct platform_event_msg));
|
||||
|
||||
ipmi_event_msg_print(intf, emsg);
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
@ -484,43 +499,30 @@ static int
|
||||
ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
|
||||
{
|
||||
FILE * fp;
|
||||
struct ipmi_rs * rsp;
|
||||
struct ipmi_rq req;
|
||||
struct sel_event_record sel_event;
|
||||
uint8_t rqdata[8];
|
||||
/* For ease of filling in from file data */
|
||||
union {
|
||||
struct platform_event_msg emsg;
|
||||
uint8_t bytes[sizeof(struct platform_event_msg)];
|
||||
} __attribute__ ((packed)) rqdata;
|
||||
char buf[1024];
|
||||
char * ptr, * tok;
|
||||
int i, j;
|
||||
uint8_t chmed;
|
||||
int rc = 0;
|
||||
|
||||
if (!file)
|
||||
return -1;
|
||||
|
||||
memset(rqdata, 0, 8);
|
||||
|
||||
/* setup Platform Event Message command */
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.msg.netfn = IPMI_NETFN_SE;
|
||||
req.msg.cmd = 0x02;
|
||||
req.msg.data = rqdata;
|
||||
req.msg.data_len = 7;
|
||||
|
||||
chmed = ipmi_current_channel_medium(intf);
|
||||
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) {
|
||||
/* system interface, need extra generator ID */
|
||||
rqdata[0] = 0x41; // As per Fig. 29-2 and Table 5-4
|
||||
req.msg.data_len = 8;
|
||||
}
|
||||
|
||||
fp = ipmi_open_file_read(file);
|
||||
if (!fp)
|
||||
return -1;
|
||||
|
||||
while (feof(fp) == 0) {
|
||||
size_t count = 0;
|
||||
if (!fgets(buf, 1024, fp))
|
||||
continue;
|
||||
|
||||
/* Each line is a new event */
|
||||
memset(&rqdata, 0, sizeof(rqdata));
|
||||
|
||||
/* clip off optional comment tail indicated by # */
|
||||
ptr = strchr(buf, '#');
|
||||
if (ptr)
|
||||
@ -540,49 +542,28 @@ ipmi_event_fromfile(struct ipmi_intf * intf, char * file)
|
||||
|
||||
/* parse the event, 7 bytes with optional comment */
|
||||
/* 0x00 0x00 0x00 0x00 0x00 0x00 0x00 # event */
|
||||
i = 0;
|
||||
tok = strtok(ptr, " ");
|
||||
while (tok) {
|
||||
if (i == 7)
|
||||
if (count == sizeof(struct platform_event_msg))
|
||||
break;
|
||||
if (0 > str2uchar(tok, &rqdata.bytes[count])) {
|
||||
lprintf(LOG_ERR, "Invalid token in file: [%s]", tok);
|
||||
rc = -1;
|
||||
break;
|
||||
j = i++;
|
||||
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM)
|
||||
j++;
|
||||
rqdata[j] = (uint8_t)strtol(tok, NULL, 0);
|
||||
tok = strtok(NULL, " ");
|
||||
}
|
||||
if (i < 7) {
|
||||
tok = strtok(NULL, " ");
|
||||
++count;
|
||||
}
|
||||
if (count < sizeof(struct platform_event_msg)) {
|
||||
lprintf(LOG_ERR, "Invalid Event: %s",
|
||||
buf2str(rqdata, sizeof(rqdata)));
|
||||
buf2str(rqdata.bytes, sizeof(rqdata.bytes)));
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&sel_event, 0, sizeof(struct sel_event_record));
|
||||
sel_event.record_id = 0;
|
||||
sel_event.sel_type.standard_type.gen_id = 2;
|
||||
|
||||
j = (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM) ? 1 : 0;
|
||||
sel_event.sel_type.standard_type.evm_rev = rqdata[j++];
|
||||
sel_event.sel_type.standard_type.sensor_type = rqdata[j++];
|
||||
sel_event.sel_type.standard_type.sensor_num = rqdata[j++];
|
||||
sel_event.sel_type.standard_type.event_type = rqdata[j] & 0x7f;
|
||||
sel_event.sel_type.standard_type.event_dir = (rqdata[j++] & 0x80) >> 7;
|
||||
sel_event.sel_type.standard_type.event_data[0] = rqdata[j++];
|
||||
sel_event.sel_type.standard_type.event_data[1] = rqdata[j++];
|
||||
sel_event.sel_type.standard_type.event_data[2] = rqdata[j++];
|
||||
|
||||
ipmi_sel_print_std_entry(intf, &sel_event);
|
||||
|
||||
rsp = intf->sendrecv(intf, &req);
|
||||
if (!rsp) {
|
||||
lprintf(LOG_ERR, "Platform Event Message command failed");
|
||||
rc = -1;
|
||||
}
|
||||
else if (rsp->ccode) {
|
||||
lprintf(LOG_ERR, "Platform Event Message command failed: %s",
|
||||
val2str(rsp->ccode, completion_code_vals));
|
||||
rc = -1;
|
||||
}
|
||||
/* Now actually send it, failures will be logged by the sender */
|
||||
rc = ipmi_send_platform_event(intf, &rqdata.emsg);
|
||||
if (IPMI_CC_OK != rc)
|
||||
break;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
@ -111,12 +111,6 @@ static inline bool fru_cc_rq2big(int code) {
|
||||
int
|
||||
ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id);
|
||||
|
||||
/* From src/plugins/ipmi_intf.c: */
|
||||
void
|
||||
ipmi_intf_set_max_request_data_size(struct ipmi_intf * intf, uint16_t size);
|
||||
void
|
||||
ipmi_intf_set_max_response_data_size(struct ipmi_intf * intf, uint16_t size);
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static void ipmi_fru_read_to_bin(struct ipmi_intf * intf, char * pFileName, uint8_t fruId);
|
||||
|
@ -48,10 +48,6 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* From src/plugins/ipmi_intf.c: */
|
||||
uint16_t
|
||||
ipmi_intf_get_max_request_data_size(struct ipmi_intf * intf);
|
||||
|
||||
extern int verbose;
|
||||
|
||||
int HpmfwupgUpgrade(struct ipmi_intf *intf, char *imageFilename,
|
||||
|
@ -844,6 +844,12 @@ ipmi_main(int argc, char ** argv,
|
||||
/* setup log */
|
||||
log_init(progname, 0, verbose);
|
||||
|
||||
/* load the IANA PEN registry */
|
||||
if (ipmi_oem_info_init()) {
|
||||
lprintf(LOG_ERR, "Failed to initialize the OEM info dictionary");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* run OEM setup if found */
|
||||
if (oemtype &&
|
||||
ipmi_oem_setup(ipmi_main_intf, oemtype) < 0) {
|
||||
@ -1063,6 +1069,8 @@ ipmi_main(int argc, char ** argv,
|
||||
devfile = NULL;
|
||||
}
|
||||
|
||||
ipmi_oem_info_free();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
1899
lib/ipmi_nm.c
Normal file
1899
lib/ipmi_nm.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -219,10 +219,6 @@ static const char *sensor_type_desc[] = {
|
||||
|
||||
void printf_sdr_usage();
|
||||
|
||||
/* From src/plugins/ipmi_intf.c: */
|
||||
uint16_t
|
||||
ipmi_intf_get_max_response_data_size(struct ipmi_intf * intf);
|
||||
|
||||
/** ipmi_sdr_get_unit_string - return units for base/modifier
|
||||
*
|
||||
* @param[in] pct Indicates that units are a percentage
|
||||
|
@ -454,10 +454,10 @@ get_kontron_evt_desc(struct ipmi_intf *__UNUSED__(intf), struct sel_event_record
|
||||
}
|
||||
|
||||
char *
|
||||
get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
|
||||
get_viking_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
|
||||
{
|
||||
/*
|
||||
* Newisys OEM event descriptions can be retrieved through an
|
||||
* Viking OEM event descriptions can be retrieved through an
|
||||
* OEM IPMI command.
|
||||
*/
|
||||
struct ipmi_rs * rsp;
|
||||
@ -495,17 +495,17 @@ get_newisys_evt_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
|
||||
/* Verify our response before we use it */
|
||||
if (rsp->data_len < 5)
|
||||
{
|
||||
lprintf(LOG_ERR, "Newisys OEM response too short");
|
||||
lprintf(LOG_ERR, "Viking OEM response too short");
|
||||
return NULL;
|
||||
}
|
||||
else if (rsp->data_len != (4 + rsp->data[3]))
|
||||
{
|
||||
lprintf(LOG_ERR, "Newisys OEM response has unexpected length");
|
||||
lprintf(LOG_ERR, "Viking OEM response has unexpected length");
|
||||
return NULL;
|
||||
}
|
||||
else if (IPM_DEV_MANUFACTURER_ID(rsp->data) != IPMI_OEM_NEWISYS)
|
||||
else if (IPM_DEV_MANUFACTURER_ID(rsp->data) != IPMI_OEM_VIKING)
|
||||
{
|
||||
lprintf(LOG_ERR, "Newisys OEM response has unexpected length");
|
||||
lprintf(LOG_ERR, "Viking OEM response has unexpected length");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1205,8 +1205,8 @@ ipmi_get_oem_desc(struct ipmi_intf * intf, struct sel_event_record * rec)
|
||||
|
||||
switch (ipmi_get_oem(intf))
|
||||
{
|
||||
case IPMI_OEM_NEWISYS:
|
||||
desc = get_newisys_evt_desc(intf, rec);
|
||||
case IPMI_OEM_VIKING:
|
||||
desc = get_viking_evt_desc(intf, rec);
|
||||
break;
|
||||
case IPMI_OEM_KONTRON:
|
||||
desc = get_kontron_evt_desc(intf, rec);
|
||||
|
@ -30,29 +30,52 @@
|
||||
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <ipmitool/ipmi_strings.h>
|
||||
#include <ipmitool/ipmi_constants.h>
|
||||
#include <ipmitool/ipmi_sensor.h>
|
||||
#include <ipmitool/ipmi_sel.h> /* for IPMI_OEM */
|
||||
|
||||
const struct valstr ipmi_oem_info[] = {
|
||||
|
||||
/* These are at the top so they are found first */
|
||||
{ IPMI_OEM_UNKNOWN, "Unknown" },
|
||||
{ IPMI_OEM_RESERVED, "Unspecified" },
|
||||
|
||||
/* The included file is auto-generated from official IANA PEN list */
|
||||
#include "ipmi_pen_list.inc.c"
|
||||
#include <ipmitool/log.h>
|
||||
|
||||
/*
|
||||
* This debug ID is at the bottom so that if IANA assigns it to
|
||||
* any entity, that IANA's value is found first and reported.
|
||||
* These are put at the head so they are found first because they
|
||||
* may overlap with IANA specified numbers found in the registry.
|
||||
*/
|
||||
{ IPMI_OEM_DEBUG, "A Debug Assisting Company, Ltd." },
|
||||
{ -1 , NULL },
|
||||
static const struct valstr ipmi_oem_info_head[] = {
|
||||
{ IPMI_OEM_UNKNOWN, "Unknown" }, /* IPMI Unknown */
|
||||
{ IPMI_OEM_RESERVED, "Unspecified" }, /* IPMI Reserved */
|
||||
{ UINT32_MAX , NULL },
|
||||
};
|
||||
|
||||
/*
|
||||
* These are our own technical values. We don't want them to take precedence
|
||||
* over IANA's defined values, so they go at the very end of the array.
|
||||
*/
|
||||
static const struct valstr ipmi_oem_info_tail[] = {
|
||||
{ IPMI_OEM_DEBUG, "A Debug Assisting Company, Ltd." },
|
||||
{ UINT32_MAX , NULL },
|
||||
};
|
||||
|
||||
/*
|
||||
* This is used when ipmi_oem_info couldn't be allocated.
|
||||
* ipmitool would report all OEMs as unknown, but would be functional otherwise.
|
||||
*/
|
||||
static const struct valstr ipmi_oem_info_dummy[] = {
|
||||
{ UINT32_MAX , NULL },
|
||||
};
|
||||
|
||||
/* This will point to an array filled from IANA's enterprise numbers registry */
|
||||
const struct valstr *ipmi_oem_info;
|
||||
|
||||
/* Single-linked list of OEM valstrs */
|
||||
typedef struct oem_valstr_list_s {
|
||||
struct valstr valstr;
|
||||
struct oem_valstr_list_s *next;
|
||||
} oem_valstr_list_t;
|
||||
|
||||
const struct oemvalstr ipmi_oem_product_info[] = {
|
||||
/* Keep OEM grouped together */
|
||||
|
||||
@ -754,3 +777,326 @@ const struct oemvalstr picmg_busres_shmc_status_vals[] = {
|
||||
|
||||
{ 0xffffff, 0x00, NULL }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A helper function to count repetitions of the same byte
|
||||
* at the beginning of a string.
|
||||
*/
|
||||
static
|
||||
size_t count_bytes(const char *s, unsigned char c)
|
||||
{
|
||||
size_t count;
|
||||
|
||||
for (count = 0; s && s[0] == c; ++s, ++count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the IANA PEN registry file.
|
||||
*
|
||||
* See https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
|
||||
* The expected entry format is:
|
||||
*
|
||||
* Decimal
|
||||
* | Organization
|
||||
* | | Contact
|
||||
* | | | Email
|
||||
* | | | |
|
||||
* 0
|
||||
* Reserved
|
||||
* Internet Assigned Numbers Authority
|
||||
* iana&iana.org
|
||||
*
|
||||
* That is, IANA PEN at position 0, enterprise name at position 2.
|
||||
*/
|
||||
#define IANA_NAME_OFFSET 2
|
||||
#define IANA_PEN_REGISTRY "enterprise-numbers"
|
||||
static
|
||||
int oem_info_list_load(oem_valstr_list_t **list)
|
||||
{
|
||||
FILE *in = NULL;
|
||||
char *home;
|
||||
oem_valstr_list_t *oemlist = *list;
|
||||
int count = 0;
|
||||
|
||||
/*
|
||||
* First try to open user's local registry if HOME is set
|
||||
*/
|
||||
if ((home = getenv("HOME"))) {
|
||||
char path[PATH_MAX + 1] = { 0 };
|
||||
snprintf(path, PATH_MAX, "%s%s",
|
||||
home,
|
||||
PATH_SEPARATOR IANAUSERDIR PATH_SEPARATOR IANA_PEN_REGISTRY);
|
||||
in = fopen(path, "r");
|
||||
}
|
||||
|
||||
if (!in) {
|
||||
/*
|
||||
* Now open the system default file
|
||||
*/
|
||||
in = fopen(IANADIR PATH_SEPARATOR IANA_PEN_REGISTRY, "r");
|
||||
if (!in) {
|
||||
lperror(LOG_ERR, "IANA PEN registry open failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the registry file line by line, fill in the linked list,
|
||||
* and count the entries. No sorting is done, entries will come in
|
||||
* reverse registry order.
|
||||
*/
|
||||
while (!feof(in)) {
|
||||
oem_valstr_list_t *item;
|
||||
char *line = NULL;
|
||||
char *endptr = NULL;
|
||||
size_t len = 0;
|
||||
long iana;
|
||||
|
||||
if (!getline(&line, &len, in)) {
|
||||
/* Either an EOF or an empty line. Start over. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the line starts with a digit. If so, take it as IANA PEN.
|
||||
* Any numbers not starting at position 0 are discarded.
|
||||
*/
|
||||
iana = strtol(line, &endptr, 10);
|
||||
if (!isdigit(line[0]) || endptr == line) {
|
||||
free_n(&line);
|
||||
continue;
|
||||
}
|
||||
free_n(&line);
|
||||
|
||||
/*
|
||||
* Now as we have the enterprise number, we're expecting the
|
||||
* organization name to immediately follow.
|
||||
*/
|
||||
len = 0;
|
||||
if (!getline(&line, &len, in)) {
|
||||
/*
|
||||
* Either an EOF or an empty line. Neither one can happen in
|
||||
* a valid registry entry. Start over.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len < IANA_NAME_OFFSET + 1
|
||||
|| count_bytes(line, ' ') != IANA_NAME_OFFSET)
|
||||
{
|
||||
/*
|
||||
* This is not a valid line, it doesn't start with
|
||||
* a correct-sized indentation or is too short.
|
||||
* Start over.
|
||||
*/
|
||||
free_n(&line);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Adjust to real line length, don't count the indentation */
|
||||
len = strnlen(line + IANA_NAME_OFFSET, len - IANA_NAME_OFFSET);
|
||||
|
||||
/* Don't count the trailing newline */
|
||||
if (line[IANA_NAME_OFFSET + len - 1] == '\n') {
|
||||
--len;
|
||||
}
|
||||
|
||||
item = malloc(sizeof(oem_valstr_list_t));
|
||||
if (!item) {
|
||||
lperror(LOG_ERR, "IANA PEN registry entry allocation failed");
|
||||
free_n(&line);
|
||||
/* Just stop reading, and process what has already been read */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks like we have a valid entry, store it in the list.
|
||||
*/
|
||||
item->valstr.val = iana;
|
||||
item->valstr.str = malloc(len + 1); /* Add 1 for \0 terminator */
|
||||
if (!item->valstr.str) {
|
||||
lperror(LOG_ERR, "IANA PEN registry string allocation failed");
|
||||
free_n(&line);
|
||||
free_n(&item);
|
||||
/* Just stop reading, and process what has already been read */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Most other valstr arrays are constant and all of them aren't meant
|
||||
* for modification, so the string inside 'struct valstr' is const.
|
||||
* Here we're loading the strings dynamically so we intentionally
|
||||
* cast to a non-const type to be able to modify data here and
|
||||
* keep the compiler silent about it. Restrictions still apply to
|
||||
* other places where these strings are used.
|
||||
*/
|
||||
snprintf((void *)item->valstr.str, len + 1,
|
||||
"%s", line + IANA_NAME_OFFSET);
|
||||
free_n(&line);
|
||||
item->next = oemlist;
|
||||
oemlist = item;
|
||||
++count;
|
||||
}
|
||||
fclose (in);
|
||||
|
||||
*list = oemlist;
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the allocated list items and, if needed, strings.
|
||||
*/
|
||||
static
|
||||
void
|
||||
oem_info_list_free(oem_valstr_list_t **list, bool free_strings)
|
||||
{
|
||||
while ((*list)->next) {
|
||||
oem_valstr_list_t *item = *list;
|
||||
*list = item->next;
|
||||
if (free_strings) {
|
||||
free_n(&item->valstr.str);
|
||||
}
|
||||
free_n(&item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the ipmi_oem_info array from a list
|
||||
*/
|
||||
static
|
||||
bool
|
||||
oem_info_init_from_list(oem_valstr_list_t *oemlist, size_t count)
|
||||
{
|
||||
/* Do not count terminators */
|
||||
size_t head_entries = ARRAY_SIZE(ipmi_oem_info_head) - 1;
|
||||
size_t tail_entries = ARRAY_SIZE(ipmi_oem_info_tail) - 1;
|
||||
static oem_valstr_list_t *item;
|
||||
bool rc = false;
|
||||
|
||||
/* Include static entries and the terminator */
|
||||
count += head_entries + tail_entries + 1;
|
||||
|
||||
/*
|
||||
* Allocate as much memory as needed to accomodata all the entries
|
||||
* of the loaded linked list, plus the static head and tail, not including
|
||||
* their terminating entries, plus the terminating entry for the new
|
||||
* array.
|
||||
*/
|
||||
ipmi_oem_info = malloc(count * sizeof(*ipmi_oem_info));
|
||||
|
||||
if (!ipmi_oem_info) {
|
||||
/*
|
||||
* We can't identify OEMs without an allocated ipmi_oem_info.
|
||||
* Report an error, set the pointer to dummy and clean up.
|
||||
*/
|
||||
lperror(LOG_ERR, "IANA PEN registry array allocation failed");
|
||||
ipmi_oem_info = ipmi_oem_info_dummy;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lprintf(LOG_DEBUG + 3, " Allocating %6zu entries", count);
|
||||
|
||||
/* Add a terminator at the very end */
|
||||
--count;
|
||||
((struct valstr *)ipmi_oem_info)[count].val = -1;
|
||||
((struct valstr *)ipmi_oem_info)[count].str = NULL;
|
||||
|
||||
/* Add tail entries from the end */
|
||||
while (count-- < SIZE_MAX && tail_entries--) {
|
||||
((struct valstr *)ipmi_oem_info)[count] =
|
||||
ipmi_oem_info_tail[tail_entries];
|
||||
|
||||
lprintf(LOG_DEBUG + 3, " [%6zu] %8d | %s", count,
|
||||
ipmi_oem_info[count].val, ipmi_oem_info[count].str);
|
||||
}
|
||||
|
||||
/* Now add the loaded entries */
|
||||
item = oemlist;
|
||||
while (count < SIZE_MAX && item->next) {
|
||||
((struct valstr *)ipmi_oem_info)[count] =
|
||||
item->valstr;
|
||||
|
||||
lprintf(LOG_DEBUG + 3, " [%6zu] %8d | %s", count,
|
||||
ipmi_oem_info[count].val, ipmi_oem_info[count].str);
|
||||
|
||||
item = item->next;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* Now add head entries */
|
||||
while (count < SIZE_MAX && head_entries--) {
|
||||
((struct valstr *)ipmi_oem_info)[count] =
|
||||
ipmi_oem_info_head[head_entries];
|
||||
lprintf(LOG_DEBUG + 3, " [%6zu] %8d | %s", count,
|
||||
ipmi_oem_info[count].val, ipmi_oem_info[count].str);
|
||||
--count;
|
||||
}
|
||||
|
||||
rc = true;
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ipmi_oem_info_init()
|
||||
{
|
||||
oem_valstr_list_t terminator = { { -1, NULL}, NULL }; /* Terminator */
|
||||
oem_valstr_list_t *oemlist = &terminator;
|
||||
bool free_strings = true;
|
||||
size_t count;
|
||||
int rc = -4;
|
||||
|
||||
lprintf(LOG_INFO, "Loading IANA PEN Registry...");
|
||||
|
||||
if (ipmi_oem_info) {
|
||||
lprintf(LOG_INFO, "IANA PEN Registry is already loaded");
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(count = oem_info_list_load(&oemlist))) {
|
||||
/*
|
||||
* We can't identify OEMs without a loaded registry.
|
||||
* Set the pointer to dummy and return.
|
||||
*/
|
||||
ipmi_oem_info = ipmi_oem_info_dummy;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* In the array was allocated, don't free the strings at cleanup */
|
||||
free_strings = !oem_info_init_from_list(oemlist, count);
|
||||
|
||||
rc = IPMI_CC_OK;
|
||||
|
||||
out:
|
||||
oem_info_list_free(&oemlist, free_strings);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void ipmi_oem_info_free()
|
||||
{
|
||||
/* Start with the dynamically allocated entries */
|
||||
size_t i = ARRAY_SIZE(ipmi_oem_info_head) - 1;
|
||||
|
||||
if (ipmi_oem_info == ipmi_oem_info_dummy) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Proceed dynamically allocated entries until we hit the first
|
||||
* entry of ipmi_oem_info_tail[], which is statically allocated.
|
||||
*/
|
||||
while (ipmi_oem_info
|
||||
&& ipmi_oem_info[i].val < UINT32_MAX
|
||||
&& ipmi_oem_info[i].str != ipmi_oem_info_tail[0].str)
|
||||
{
|
||||
free_n(&((struct valstr *)ipmi_oem_info)[i].str);
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Free the array itself */
|
||||
free_n(&ipmi_oem_info);
|
||||
}
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include <ipmitool/ipmi_ekanalyzer.h>
|
||||
#include <ipmitool/ipmi_ime.h>
|
||||
#include <ipmitool/ipmi_dcmi.h>
|
||||
#include <ipmitool/ipmi_nm.h>
|
||||
#include <ipmitool/ipmi_vita.h>
|
||||
#include <ipmitool/ipmi_quantaoem.h>
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
EXTRA_LTLIBRARIES = libintf_dbus.la
|
||||
noinst_LTLIBRARIES = @INTF_DBUS_LIB@
|
||||
|
@ -761,12 +761,6 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
|
||||
if (payload_size > 8) {
|
||||
printbuf(&rsp->data[offset], (rsp->data_len-offset-1),
|
||||
"bridge command response");
|
||||
/*
|
||||
* decrement payload size
|
||||
* (cks2 for outer Send Message)
|
||||
*/
|
||||
payload_size--;
|
||||
|
||||
/*
|
||||
* need to make a loop for embedded bridged response
|
||||
*/
|
||||
@ -793,6 +787,9 @@ ipmi_lan_poll_single(struct ipmi_intf * intf)
|
||||
if (extra_data_length > 0) {
|
||||
rsp->data_len = extra_data_length;
|
||||
memmove(rsp->data, rsp->data + offset, extra_data_length);
|
||||
offset = 0;
|
||||
payload_start = 0;
|
||||
payload_size = extra_data_length;
|
||||
} else {
|
||||
rsp->data_len = 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user