Move all files one level up in the file hierarcy, to avoid the useless ipmitool directory.

This commit is contained in:
Petter Reinholdtsen
2014-02-05 17:30:32 +01:00
parent b0aad15d67
commit c18ec02f33
171 changed files with 0 additions and 0 deletions

48
lib/Makefile.am Normal file
View File

@@ -0,0 +1,48 @@
# Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistribution of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# Redistribution in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the name of Sun Microsystems, Inc. or the names of
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# This software is provided "AS IS," without a warranty of any kind.
# ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
# INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
# SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
# FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
# SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
# OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
# PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
# LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
# EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
INCLUDES = -I$(top_srcdir)/include
MAINTAINERCLEANFILES = Makefile.in
noinst_LTLIBRARIES = libipmitool.la
libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \
ipmi_lanp.c ipmi_fru.c ipmi_chassis.c ipmi_mc.c log.c \
dimm_spd.c ipmi_sensor.c ipmi_channel.c ipmi_event.c \
ipmi_session.c ipmi_strings.c ipmi_user.c ipmi_raw.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 \
../src/plugins/lan/md5.c ../src/plugins/lan/md5.h
libipmitool_la_LDFLAGS = -export-dynamic
libipmitool_la_LIBADD = -lm
libipmitool_la_DEPENDENCIES =

935
lib/dimm_spd.c Normal file
View File

@@ -0,0 +1,935 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <ipmitool/ipmi.h>
#include <ipmitool/log.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_fru.h>
#include <stdlib.h>
#include <string.h>
extern int verbose;
/*
* Also, see ipmi_fru.c.
*
* Apparently some systems have problems with FRU access greater than 16 bytes
* at a time, even when using byte (not word) access. In order to ensure we
* work with the widest variety of hardware request size is capped at 16 bytes.
* Since this may result in slowdowns on some systems with lots of FRU data you
* can change this define to enable larger (up to 32 bytes at a time) access.
*/
#define FRU_DATA_RQST_SIZE 16;
const struct valstr spd_memtype_vals[] = {
{ 0x01, "STD FPM DRAM" },
{ 0x02, "EDO" },
{ 0x04, "SDRAM" },
{ 0x05, "ROM" },
{ 0x06, "DDR SGRAM" },
{ 0x07, "DDR SDRAM" },
{ 0x08, "DDR2 SDRAM" },
{ 0x09, "DDR2 SDRAM FB-DIMM" },
{ 0x0A, "DDR2 SDRAM FB-DIMM Probe" },
{ 0x0B, "DDR3 SDRAM" },
{ 0x00, NULL },
};
const struct valstr ddr3_density_vals[] =
{
{ 0, "256 Mb" },
{ 1, "512 Mb" },
{ 2, "1 Gb" },
{ 3, "2 Gb" },
{ 4, "4 Gb" },
{ 5, "8 Gb" },
{ 6, "16 Gb" },
{ 0x00, NULL },
};
const struct valstr ddr3_banks_vals[] =
{
{ 0, "3 (8 Banks)" },
{ 1, "4 (16 Banks)" },
{ 2, "5 (32 Banks)" },
{ 3, "6 (64 Banks)" },
{ 0x00, NULL },
};
const struct valstr ddr3_ecc_vals[] =
{
{ 0, "0 bits" },
{ 1, "8 bits" },
{ 0x00, NULL },
};
const struct valstr spd_config_vals[] = {
{ 0x00, "None" },
{ 0x01, "Parity" },
{ 0x02, "ECC" },
{ 0x04, "Addr Cmd Parity" },
{ 0x00, NULL },
};
const struct valstr spd_voltage_vals[] = {
{ 0x00, "5.0V TTL" },
{ 0x01, "LVTTL" },
{ 0x02, "HSTL 1.5V" },
{ 0x03, "SSTL 3.3V" },
{ 0x04, "SSTL 2.5V" },
{ 0x05, "SSTL 1.8V" },
{ 0x00, NULL },
};
/*
* JEDEC Standard Manufacturers Identification Code
* publication JEP106N, December 2003
*/
const struct valstr jedec_id1_vals[] = {
{ 0x01, "AMD" },
{ 0x02, "AMI" },
{ 0x83, "Fairchild" },
{ 0x04, "Fujitsu" },
{ 0x85, "GTE" },
{ 0x86, "Harris" },
{ 0x07, "Hitachi" },
{ 0x08, "Inmos" },
{ 0x89, "Intel" },
{ 0x8a, "I.T.T." },
{ 0x0b, "Intersil" },
{ 0x8c, "Monolithic Memories" },
{ 0x0d, "Mostek" },
{ 0x0e, "Motorola" },
{ 0x8f, "National" },
{ 0x10, "NEC" },
{ 0x91, "RCA" },
{ 0x92, "Raytheon" },
{ 0x13, "Conexant (Rockwell)" },
{ 0x94, "Seeq" },
{ 0x15, "Philips Semi. (Signetics)" },
{ 0x16, "Synertek" },
{ 0x97, "Texas Instruments" },
{ 0x98, "Toshiba" },
{ 0x19, "Xicor" },
{ 0x1a, "Zilog" },
{ 0x9b, "Eurotechnique" },
{ 0x1c, "Mitsubishi" },
{ 0x9d, "Lucent (AT&T)" },
{ 0x9e, "Exel" },
{ 0x1f, "Atmel" },
{ 0x20, "SGS/Thomson" },
{ 0xa1, "Lattice Semi." },
{ 0xa2, "NCR" },
{ 0x23, "Wafer Scale Integration" },
{ 0xa4, "IBM" },
{ 0x25, "Tristar" },
{ 0x26, "Visic" },
{ 0xa7, "Intl. CMOS Technology" },
{ 0xa8, "SSSI" },
{ 0x29, "Microchip Technology" },
{ 0x2a, "Ricoh Ltd." },
{ 0xab, "VLSI" },
{ 0x2c, "Micron Technology" },
{ 0xad, "Hyundai Electronics" },
{ 0xae, "OKI Semiconductor" },
{ 0x2f, "ACTEL" },
{ 0xb0, "Sharp" },
{ 0x31, "Catalyst" },
{ 0x32, "Panasonic" },
{ 0xb3, "IDT" },
{ 0x34, "Cypress" },
{ 0xb5, "DEC" },
{ 0xb6, "LSI Logic" },
{ 0x37, "Zarlink" },
{ 0x38, "UTMC" },
{ 0xb9, "Thinking Machine" },
{ 0xba, "Thomson CSF" },
{ 0x3b, "Integrated CMOS(Vertex)" },
{ 0xbc, "Honeywell" },
{ 0x3d, "Tektronix" },
{ 0x3e, "Sun Microsystems" },
{ 0xbf, "SST" },
{ 0x40, "MOSEL" },
{ 0xc1, "Infineon" },
{ 0xc2, "Macronix" },
{ 0x43, "Xerox" },
{ 0xc4, "Plus Logic" },
{ 0x45, "SunDisk" },
{ 0x46, "Elan Circuit Tech." },
{ 0xc7, "European Silicon Str." },
{ 0xc8, "Apple Computer" },
{ 0xc9, "Xilinx" },
{ 0x4a, "Compaq" },
{ 0xcb, "Protocol Engines" },
{ 0x4c, "SCI" },
{ 0xcd, "Seiko Instruments" },
{ 0xce, "Samsung" },
{ 0x4f, "I3 Design System" },
{ 0xd0, "Klic" },
{ 0x51, "Crosspoint Solutions" },
{ 0x52, "Alliance Semiconductor" },
{ 0xd3, "Tandem" },
{ 0x54, "Hewlett-Packard" },
{ 0xd5, "Intg. Silicon Solutions" },
{ 0xd6, "Brooktree" },
{ 0x57, "New Media" },
{ 0x58, "MHS Electronic" },
{ 0xd9, "Performance Semi." },
{ 0xda, "Winbond Electronic" },
{ 0x5b, "Kawasaki Steel" },
{ 0xdc, "Bright Micro" },
{ 0x5d, "TECMAR" },
{ 0x5e, "Exar" },
{ 0xdf, "PCMCIA" },
{ 0xe0, "LG Semiconductor" },
{ 0x61, "Northern Telecom" },
{ 0x62, "Sanyo" },
{ 0xe3, "Array Microsystems" },
{ 0x64, "Crystal Semiconductor" },
{ 0xe5, "Analog Devices" },
{ 0xe6, "PMC-Sierra" },
{ 0x67, "Asparix" },
{ 0x68, "Convex Computer" },
{ 0xe9, "Quality Semiconductor" },
{ 0xea, "Nimbus Technology" },
{ 0x6b, "Transwitch" },
{ 0xec, "Micronas (ITT Intermetall)" },
{ 0x6d, "Cannon" },
{ 0x6e, "Altera" },
{ 0xef, "NEXCOM" },
{ 0x70, "QUALCOMM" },
{ 0xf1, "Sony" },
{ 0xf2, "Cray Research" },
{ 0x73, "AMS (Austria Micro)" },
{ 0xf4, "Vitesse" },
{ 0x75, "Aster Electronics" },
{ 0x76, "Bay Networks (Synoptic)" },
{ 0xf7, "Zentrum" },
{ 0xf8, "TRW" },
{ 0x79, "Thesys" },
{ 0x7a, "Solbourne Computer" },
{ 0xfb, "Allied-Signal" },
{ 0x7c, "Dialog" },
{ 0xfd, "Media Vision" },
{ 0xfe, "Level One Communication" },
{ 0x00, NULL },
};
const struct valstr jedec_id2_vals[] = {
{ 0x01, "Cirrus Logic" },
{ 0x02, "National Instruments" },
{ 0x83, "ILC Data Device" },
{ 0x04, "Alcatel Mietec" },
{ 0x85, "Micro Linear" },
{ 0x86, "Univ. of NC" },
{ 0x07, "JTAG Technologies" },
{ 0x08, "Loral" },
{ 0x89, "Nchip" },
{ 0x8A, "Galileo Tech" },
{ 0x0B, "Bestlink Systems" },
{ 0x8C, "Graychip" },
{ 0x0D, "GENNUM" },
{ 0x0E, "VideoLogic" },
{ 0x8F, "Robert Bosch" },
{ 0x10, "Chip Express" },
{ 0x91, "DATARAM" },
{ 0x92, "United Microelec Corp." },
{ 0x13, "TCSI" },
{ 0x94, "Smart Modular" },
{ 0x15, "Hughes Aircraft" },
{ 0x16, "Lanstar Semiconductor" },
{ 0x97, "Qlogic" },
{ 0x98, "Kingston" },
{ 0x19, "Music Semi" },
{ 0x1A, "Ericsson Components" },
{ 0x9B, "SpaSE" },
{ 0x1C, "Eon Silicon Devices" },
{ 0x9D, "Programmable Micro Corp" },
{ 0x9E, "DoD" },
{ 0x1F, "Integ. Memories Tech." },
{ 0x20, "Corollary Inc." },
{ 0xA1, "Dallas Semiconductor" },
{ 0xA2, "Omnivision" },
{ 0x23, "EIV(Switzerland)" },
{ 0xA4, "Novatel Wireless" },
{ 0x25, "Zarlink (formerly Mitel)" },
{ 0x26, "Clearpoint" },
{ 0xA7, "Cabletron" },
{ 0xA8, "Silicon Technology" },
{ 0x29, "Vanguard" },
{ 0x2A, "Hagiwara Sys-Com" },
{ 0xAB, "Vantis" },
{ 0x2C, "Celestica" },
{ 0xAD, "Century" },
{ 0xAE, "Hal Computers" },
{ 0x2F, "Rohm Company Ltd." },
{ 0xB0, "Juniper Networks" },
{ 0x31, "Libit Signal Processing" },
{ 0x32, "Enhanced Memories Inc." },
{ 0xB3, "Tundra Semiconductor" },
{ 0x34, "Adaptec Inc." },
{ 0xB5, "LightSpeed Semi." },
{ 0xB6, "ZSP Corp." },
{ 0x37, "AMIC Technology" },
{ 0x38, "Adobe Systems" },
{ 0xB9, "Dynachip" },
{ 0xBA, "PNY Electronics" },
{ 0x3B, "Newport Digital" },
{ 0xBC, "MMC Networks" },
{ 0x3D, "T Square" },
{ 0x3E, "Seiko Epson" },
{ 0xBF, "Broadcom" },
{ 0x40, "Viking Components" },
{ 0xC1, "V3 Semiconductor" },
{ 0xC2, "Flextronics (formerly Orbit)" },
{ 0x43, "Suwa Electronics" },
{ 0xC4, "Transmeta" },
{ 0x45, "Micron CMS" },
{ 0x46, "American Computer & Digital Components Inc" },
{ 0xC7, "Enhance 3000 Inc" },
{ 0xC8, "Tower Semiconductor" },
{ 0x49, "CPU Design" },
{ 0x4A, "Price Point" },
{ 0xCB, "Maxim Integrated Product" },
{ 0x4C, "Tellabs" },
{ 0xCD, "Centaur Technology" },
{ 0xCE, "Unigen Corporation" },
{ 0x4F, "Transcend Information" },
{ 0xD0, "Memory Card Technology" },
{ 0x51, "CKD Corporation Ltd." },
{ 0x52, "Capital Instruments, Inc." },
{ 0xD3, "Aica Kogyo, Ltd." },
{ 0x54, "Linvex Technology" },
{ 0xD5, "MSC Vertriebs GmbH" },
{ 0xD6, "AKM Company, Ltd." },
{ 0x57, "Dynamem, Inc." },
{ 0x58, "NERA ASA" },
{ 0xD9, "GSI Technology" },
{ 0xDA, "Dane-Elec (C Memory)" },
{ 0x5B, "Acorn Computers" },
{ 0xDC, "Lara Technology" },
{ 0x5D, "Oak Technology, Inc." },
{ 0x5E, "Itec Memory" },
{ 0xDF, "Tanisys Technology" },
{ 0xE0, "Truevision" },
{ 0x61, "Wintec Industries" },
{ 0x62, "Super PC Memory" },
{ 0xE3, "MGV Memory" },
{ 0x64, "Galvantech" },
{ 0xE5, "Gadzoox Nteworks" },
{ 0xE6, "Multi Dimensional Cons." },
{ 0x67, "GateField" },
{ 0x68, "Integrated Memory System" },
{ 0xE9, "Triscend" },
{ 0xEA, "XaQti" },
{ 0x6B, "Goldenram" },
{ 0xEC, "Clear Logic" },
{ 0x6D, "Cimaron Communications" },
{ 0x6E, "Nippon Steel Semi. Corp." },
{ 0xEF, "Advantage Memory" },
{ 0x70, "AMCC" },
{ 0xF1, "LeCroy" },
{ 0xF2, "Yamaha Corporation" },
{ 0x73, "Digital Microwave" },
{ 0xF4, "NetLogic Microsystems" },
{ 0x75, "MIMOS Semiconductor" },
{ 0x76, "Advanced Fibre" },
{ 0xF7, "BF Goodrich Data." },
{ 0xF8, "Epigram" },
{ 0x79, "Acbel Polytech Inc." },
{ 0x7A, "Apacer Technology" },
{ 0xFB, "Admor Memory" },
{ 0x7C, "FOXCONN" },
{ 0xFD, "Quadratics Superconductor" },
{ 0xFE, "3COM" },
{ 0x00, NULL },
};
const struct valstr jedec_id3_vals[] = {
{ 0x01, "Camintonn Corporation" },
{ 0x02, "ISOA Incorporated" },
{ 0x83, "Agate Semiconductor" },
{ 0x04, "ADMtek Incorporated" },
{ 0x85, "HYPERTEC" },
{ 0x86, "Adhoc Technologies" },
{ 0x07, "MOSAID Technologies" },
{ 0x08, "Ardent Technologies" },
{ 0x89, "Switchcore" },
{ 0x8A, "Cisco Systems, Inc." },
{ 0x0B, "Allayer Technologies" },
{ 0x8C, "WorkX AG" },
{ 0x0D, "Oasis Semiconductor" },
{ 0x0E, "Novanet Semiconductor" },
{ 0x8F, "E-M Solutions" },
{ 0x10, "Power General" },
{ 0x91, "Advanced Hardware Arch." },
{ 0x92, "Inova Semiconductors GmbH" },
{ 0x13, "Telocity" },
{ 0x94, "Delkin Devices" },
{ 0x15, "Symagery Microsystems" },
{ 0x16, "C-Port Corporation" },
{ 0x97, "SiberCore Technologies" },
{ 0x98, "Southland Microsystems" },
{ 0x19, "Malleable Technologies" },
{ 0x1A, "Kendin Communications" },
{ 0x9B, "Great Technology Microcomputer" },
{ 0x1C, "Sanmina Corporation" },
{ 0x9D, "HADCO Corporation" },
{ 0x9E, "Corsair" },
{ 0x1F, "Actrans System Inc." },
{ 0x20, "ALPHA Technologies" },
{ 0xA1, "Cygnal Integrated Products Incorporated" },
{ 0xA2, "Artesyn Technologies" },
{ 0x23, "Align Manufacturing" },
{ 0xA4, "Peregrine Semiconductor" },
{ 0x25, "Chameleon Systems" },
{ 0x26, "Aplus Flash Technology" },
{ 0xA7, "MIPS Technologies" },
{ 0xA8, "Chrysalis ITS" },
{ 0x29, "ADTEC Corporation" },
{ 0x2A, "Kentron Technologies" },
{ 0xAB, "Win Technologies" },
{ 0x2C, "ASIC Designs Inc" },
{ 0xAD, "Extreme Packet Devices" },
{ 0xAE, "RF Micro Devices" },
{ 0x2F, "Siemens AG" },
{ 0xB0, "Sarnoff Corporation" },
{ 0x31, "Itautec Philco SA" },
{ 0x32, "Radiata Inc." },
{ 0xB3, "Benchmark Elect. (AVEX)" },
{ 0x34, "Legend" },
{ 0xB5, "SpecTek Incorporated" },
{ 0xB6, "Hi/fn" },
{ 0x37, "Enikia Incorporated" },
{ 0x38, "SwitchOn Networks" },
{ 0xB9, "AANetcom Incorporated" },
{ 0xBA, "Micro Memory Bank" },
{ 0x3B, "ESS Technology" },
{ 0xBC, "Virata Corporation" },
{ 0x3D, "Excess Bandwidth" },
{ 0x3E, "West Bay Semiconductor" },
{ 0xBF, "DSP Group" },
{ 0x40, "Newport Communications" },
{ 0xC1, "Chip2Chip Incorporated" },
{ 0xC2, "Phobos Corporation" },
{ 0x43, "Intellitech Corporation" },
{ 0xC4, "Nordic VLSI ASA" },
{ 0x45, "Ishoni Networks" },
{ 0x46, "Silicon Spice" },
{ 0xC7, "Alchemy Semiconductor" },
{ 0xC8, "Agilent Technologies" },
{ 0x49, "Centillium Communications" },
{ 0x4A, "W.L. Gore" },
{ 0xCB, "HanBit Electronics" },
{ 0x4C, "GlobeSpan" },
{ 0xCD, "Element 14" },
{ 0xCE, "Pycon" },
{ 0x4F, "Saifun Semiconductors" },
{ 0xD0, "Sibyte, Incorporated" },
{ 0x51, "MetaLink Technologies" },
{ 0x52, "Feiya Technology" },
{ 0xD3, "I & C Technology" },
{ 0x54, "Shikatronics" },
{ 0xD5, "Elektrobit" },
{ 0xD6, "Megic" },
{ 0x57, "Com-Tier" },
{ 0x58, "Malaysia Micro Solutions" },
{ 0xD9, "Hyperchip" },
{ 0xDA, "Gemstone Communications" },
{ 0x5B, "Anadyne Microelectronics" },
{ 0xDC, "3ParData" },
{ 0x5D, "Mellanox Technologies" },
{ 0x5E, "Tenx Technologies" },
{ 0xDF, "Helix AG" },
{ 0xE0, "Domosys" },
{ 0x61, "Skyup Technology" },
{ 0x62, "HiNT Corporation" },
{ 0xE3, "Chiaro" },
{ 0x64, "MCI Computer GMBH" },
{ 0xE5, "Exbit Technology A/S" },
{ 0xE6, "Integrated Technology Express" },
{ 0x67, "AVED Memory" },
{ 0x68, "Legerity" },
{ 0xE9, "Jasmine Networks" },
{ 0xEA, "Caspian Networks" },
{ 0x6B, "nCUBE" },
{ 0xEC, "Silicon Access Networks" },
{ 0x6D, "FDK Corporation" },
{ 0x6E, "High Bandwidth Access" },
{ 0xEF, "MultiLink Technology" },
{ 0x70, "BRECIS" },
{ 0xF1, "World Wide Packets" },
{ 0xF2, "APW" },
{ 0x73, "Chicory Systems" },
{ 0xF4, "Xstream Logic" },
{ 0x75, "Fast-Chip" },
{ 0x76, "Zucotto Wireless" },
{ 0xF7, "Realchip" },
{ 0xF8, "Galaxy Power" },
{ 0x79, "eSilicon" },
{ 0x7A, "Morphics Technology" },
{ 0xFB, "Accelerant Networks" },
{ 0x7C, "Silicon Wave" },
{ 0xFD, "SandCraft" },
{ 0xFE, "Elpida" },
{ 0x00, NULL },
};
const struct valstr jedec_id4_vals[] = {
{ 0x01, "Solectron" },
{ 0x02, "Optosys Technologies" },
{ 0x83, "Buffalo (Formerly Melco)" },
{ 0x04, "TriMedia Technologies" },
{ 0x85, "Cyan Technologies" },
{ 0x86, "Global Locate" },
{ 0x07, "Optillion" },
{ 0x08, "Terago Communications" },
{ 0x89, "Ikanos Communications" },
{ 0x8A, "Princeton Technology" },
{ 0x0B, "Nanya Technology" },
{ 0x8C, "Elite Flash Storage" },
{ 0x0D, "Mysticom" },
{ 0x0E, "LightSand Communications" },
{ 0x8F, "ATI Technologies" },
{ 0x10, "Agere Systems" },
{ 0x91, "NeoMagic" },
{ 0x92, "AuroraNetics" },
{ 0x13, "Golden Empire" },
{ 0x94, "Muskin" },
{ 0x15, "Tioga Technologies" },
{ 0x16, "Netlist" },
{ 0x97, "TeraLogic" },
{ 0x98, "Cicada Semiconductor" },
{ 0x19, "Centon Electronics" },
{ 0x1A, "Tyco Electronics" },
{ 0x9B, "Magis Works" },
{ 0x1C, "Zettacom" },
{ 0x9D, "Cogency Semiconductor" },
{ 0x9E, "Chipcon AS" },
{ 0x1F, "Aspex Technology" },
{ 0x20, "F5 Networks" },
{ 0xA1, "Programmable Silicon Solutions" },
{ 0xA2, "ChipWrights" },
{ 0x23, "Acorn Networks" },
{ 0xA4, "Quicklogic" },
{ 0x25, "Kingmax Semiconductor" },
{ 0x26, "BOPS" },
{ 0xA7, "Flasys" },
{ 0xA8, "BitBlitz Communications" },
{ 0x29, "eMemory Technology" },
{ 0x2A, "Procket Networks" },
{ 0xAB, "Purple Ray" },
{ 0x2C, "Trebia Networks" },
{ 0xAD, "Delta Electronics" },
{ 0xAE, "Onex Communications" },
{ 0x2F, "Ample Communications" },
{ 0xB0, "Memory Experts Intl" },
{ 0x31, "Astute Networks" },
{ 0x32, "Azanda Network Devices" },
{ 0xB3, "Dibcom" },
{ 0x34, "Tekmos" },
{ 0xB5, "API NetWorks" },
{ 0xB6, "Bay Microsystems" },
{ 0x37, "Firecron Ltd" },
{ 0x38, "Resonext Communications" },
{ 0xB9, "Tachys Technologies" },
{ 0xBA, "Equator Technology" },
{ 0x3B, "Concept Computer" },
{ 0xBC, "SILCOM" },
{ 0x3D, "3Dlabs" },
{ 0x3E, "ct Magazine" },
{ 0xBF, "Sanera Systems" },
{ 0x40, "Silicon Packets" },
{ 0xC1, "Viasystems Group" },
{ 0xC2, "Simtek" },
{ 0x43, "Semicon Devices Singapore" },
{ 0xC4, "Satron Handelsges" },
{ 0x45, "Improv Systems" },
{ 0x46, "INDUSYS GmbH" },
{ 0xC7, "Corrent" },
{ 0xC8, "Infrant Technologies" },
{ 0x49, "Ritek Corp" },
{ 0x4A, "empowerTel Networks" },
{ 0xCB, "Hypertec" },
{ 0x4C, "Cavium Networks" },
{ 0xCD, "PLX Technology" },
{ 0xCE, "Massana Design" },
{ 0x4F, "Intrinsity" },
{ 0xD0, "Valence Semiconductor" },
{ 0x51, "Terawave Communications" },
{ 0x52, "IceFyre Semiconductor" },
{ 0xD3, "Primarion" },
{ 0x54, "Picochip Designs Ltd" },
{ 0xD5, "Silverback Systems" },
{ 0xD6, "Jade Star Technologies" },
{ 0x57, "Pijnenburg Securealink" },
{ 0x58, "MemorySolutioN" },
{ 0xD9, "Cambridge Silicon Radio" },
{ 0xDA, "Swissbit" },
{ 0x5B, "Nazomi Communications" },
{ 0xDC, "eWave System" },
{ 0x5D, "Rockwell Collins" },
{ 0x5E, "PAION" },
{ 0xDF, "Alphamosaic Ltd" },
{ 0xE0, "Sandburst" },
{ 0x61, "SiCon Video" },
{ 0x62, "NanoAmp Solutions" },
{ 0xE3, "Ericsson Technology" },
{ 0x64, "PrairieComm" },
{ 0xE5, "Mitac International" },
{ 0xE6, "Layer N Networks" },
{ 0x67, "Atsana Semiconductor" },
{ 0x68, "Allegro Networks" },
{ 0xE9, "Marvell Semiconductors" },
{ 0xEA, "Netergy Microelectronic" },
{ 0x6B, "NVIDIA" },
{ 0xEC, "Internet Machines" },
{ 0x6D, "Peak Electronics" },
{ 0xEF, "Accton Technology" },
{ 0x70, "Teradiant Networks" },
{ 0xF1, "Europe Technologies" },
{ 0xF2, "Cortina Systems" },
{ 0x73, "RAM Components" },
{ 0xF4, "Raqia Networks" },
{ 0x75, "ClearSpeed" },
{ 0x76, "Matsushita Battery" },
{ 0xF7, "Xelerated" },
{ 0xF8, "SimpleTech" },
{ 0x79, "Utron Technology" },
{ 0x7A, "Astec International" },
{ 0xFB, "AVM gmbH" },
{ 0x7C, "Redux Communications" },
{ 0xFD, "Dot Hill Systems" },
{ 0xFE, "TeraChip" },
{ 0x00, NULL },
};
const struct valstr jedec_id5_vals[] = {
{ 0x01, "T-RAM Incorporated" },
{ 0x02, "Innovics Wireless" },
{ 0x83, "Teknovus" },
{ 0x04, "KeyEye Communications" },
{ 0x85, "Runcom Technologies" },
{ 0x86, "RedSwitch" },
{ 0x07, "Dotcast" },
{ 0x08, "Silicon Mountain Memory" },
{ 0x89, "Signia Technologies" },
{ 0x8A, "Pixim" },
{ 0x0B, "Galazar Networks" },
{ 0x8C, "White Electronic Designs" },
{ 0x0D, "Patriot Scientific" },
{ 0x0E, "Neoaxiom Corporation" },
{ 0x8F, "3Y Power Technology" },
{ 0x10, "Europe Technologies" },
{ 0x91, "Potentia Power Systems" },
{ 0x92, "C-guys Incorporated" },
{ 0x13, "Digital Communications Technology Incorporated" },
{ 0x94, "Silicon-Based Technology" },
{ 0x15, "Fulcrum Microsystems" },
{ 0x16, "Positivo Informatica Ltd" },
{ 0x97, "XIOtech Corporation" },
{ 0x98, "PortalPlayer" },
{ 0x19, "Zhiying Software" },
{ 0x1A, "Direct2Data" },
{ 0x9B, "Phonex Broadband" },
{ 0x1C, "Skyworks Solutions" },
{ 0x9D, "Entropic Communications" },
{ 0x9E, "Pacific Force Technology" },
{ 0x1F, "Zensys A/S" },
{ 0x20, "Legend Silicon Corp." },
{ 0xA1, "sci-worx GmbH" },
{ 0xA2, "Oasis Silicon Systems" },
{ 0x23, "Renesas Technology" },
{ 0xA4, "Raza Microelectronics" },
{ 0x25, "Phyworks" },
{ 0x26, "MediaTek" },
{ 0xA7, "Non-cents Productions" },
{ 0xA8, "US Modular" },
{ 0x29, "Wintegra Ltd" },
{ 0x2A, "Mathstar" },
{ 0xAB, "StarCore" },
{ 0x2C, "Oplus Technologies" },
{ 0xAD, "Mindspeed" },
{ 0xAE, "Just Young Computer" },
{ 0x2F, "Radia Communications" },
{ 0xB0, "OCZ" },
{ 0x31, "Emuzed" },
{ 0x32, "LOGIC Devices" },
{ 0xB3, "Inphi Corporation" },
{ 0x34, "Quake Technologies" },
{ 0xB5, "Vixel" },
{ 0xB6, "SolusTek" },
{ 0x37, "Kongsberg Maritime" },
{ 0x38, "Faraday Technology" },
{ 0xB9, "Altium Ltd." },
{ 0xBA, "Insyte" },
{ 0x3B, "ARM Ltd." },
{ 0xBC, "DigiVision" },
{ 0x3D, "Vativ Technologies" },
{ 0x3E, "Endicott Interconnect Technologies" },
{ 0xBF, "Pericom" },
{ 0x40, "Bandspeed" },
{ 0xC1, "LeWiz Communications" },
{ 0xC2, "CPU Technology" },
{ 0x43, "Ramaxel Technology" },
{ 0xC4, "DSP Group" },
{ 0x45, "Axis Communications" },
{ 0x46, "Legacy Electronics" },
{ 0xC7, "Chrontel" },
{ 0xC8, "Powerchip Semiconductor" },
{ 0x49, "MobilEye Technologies" },
{ 0x4A, "Excel Semiconductor" },
{ 0xCB, "A-DATA Technology" },
{ 0x4C, "VirtualDigm" },
{ 0x00, NULL },
};
int
ipmi_spd_print(uint8_t *spd_data, int len)
{
int size;
if (len < 92)
return -1; /* we need first 91 bytes to do our thing */
printf(" Memory Type : %s\n",
val2str(spd_data[2], spd_memtype_vals));
if (spd_data[2] == 0x0B) /* DDR3 SDRAM */
{
int iPN;
char *pchPN = spd_data+128;
int sdram_cap = 0;
int pri_bus_width = 0;
int sdram_width = 0;
int ranks = 0;
int mem_size = 0;
if (len < 148)
return -1; /* we need first 91 bytes to do our thing */
sdram_cap = ldexp(256,(spd_data[4]&15));
pri_bus_width = ldexp(8,(spd_data[8]&7));
sdram_width = ldexp(4,(spd_data[7]&7));
ranks = ldexp(1,((spd_data[7]&0x3F)>>3));
mem_size = (sdram_cap/8) * (pri_bus_width/sdram_width) * ranks;
printf(" SDRAM Capacity : %d MB\n", sdram_cap );
printf(" Memory Banks : %s\n", val2str(spd_data[4]>>4, ddr3_banks_vals));
printf(" Primary Bus Width : %d bits\n", pri_bus_width );
printf(" SDRAM Device Width : %d bits\n", sdram_width );
printf(" Number of Ranks : %d\n", ranks );
printf(" Memory size : %d MB\n", mem_size );
/* printf(" Memory Density : %s\n", val2str(spd_data[4]&15, ddr3_density_vals)); */
printf(" 1.5 V Nominal Op : %s\n", (((spd_data[6]&1) != 0) ? "No":"Yes" ) );
printf(" 1.35 V Nominal Op : %s\n", (((spd_data[6]&2) != 0) ? "No":"Yes" ) );
printf(" 1.2X V Nominal Op : %s\n", (((spd_data[6]&4) != 0) ? "No":"Yes" ) );
printf(" Error Detect/Cor : %s\n", val2str(spd_data[8]>>3, ddr3_ecc_vals));
printf(" Manufacturer : ");
switch (spd_data[117]&127)
{
case 0:
printf("%s\n", val2str(spd_data[118], jedec_id1_vals));
break;
case 1:
printf("%s\n", val2str(spd_data[118], jedec_id2_vals));
break;
case 2:
printf("%s\n", val2str(spd_data[118], jedec_id3_vals));
break;
case 3:
printf("%s\n", val2str(spd_data[118], jedec_id4_vals));
break;
case 4:
printf("%s\n", val2str(spd_data[118], jedec_id5_vals));
break;
default:
printf("%s\n", "JEDEC JEP106 update required" );
}
printf(" Manufacture Date : year %c%c week %c%c\n",
'0'+(spd_data[120]>>4), '0'+(spd_data[120]&15), '0'+(spd_data[121]>>4), '0'+(spd_data[121]&15) );
printf(" Serial Number : %02x%02x%02x%02x\n",
spd_data[122], spd_data[123], spd_data[124], spd_data[125]);
printf(" Part Number : ");
for (iPN=0; iPN < 19; iPN++)
{
printf( "%c", *pchPN++ );
}
printf("\n");
}
else
{
size = spd_data[5] * (spd_data[31] << 2);
printf(" Memory Size : %d MB\n", size);
printf(" Voltage Intf : %s\n",
val2str(spd_data[8], spd_voltage_vals));
printf(" Error Detect/Cor : %s\n",
val2str(spd_data[11], spd_config_vals));
/* handle jedec table bank continuation values */
printf(" Manufacturer : ");
if (spd_data[64] != 0x7f)
printf("%s\n",
val2str(spd_data[64], jedec_id1_vals));
else {
if (spd_data[65] != 0x7f)
printf("%s\n",
val2str(spd_data[65], jedec_id2_vals));
else {
if (spd_data[66] != 0x7f)
printf("%s\n",
val2str(spd_data[66], jedec_id3_vals));
else {
if (spd_data[67] != 0x7f)
printf("%s\n",
val2str(spd_data[67],
jedec_id4_vals));
else
printf("%s\n",
val2str(spd_data[68],
jedec_id5_vals));
}
}
}
if (spd_data[73]) {
char part[19];
memcpy(part, spd_data+73, 18);
part[18] = 0;
printf(" Part Number : %s\n", part);
}
printf(" Serial Number : %02x%02x%02x%02x\n",
spd_data[95], spd_data[96], spd_data[97], spd_data[98]);
}
if (verbose) {
printf("\n");
printbuf(spd_data, len, "SPD DATA");
}
return 0;
}
int
ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct fru_info fru;
uint8_t spd_data[256], msg_data[4];
int len, offset;
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 == NULL) {
printf(" Device not present (No Response)\n");
return -1;
}
if (rsp->ccode > 0) {
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;
}
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;
offset = 0;
memset(spd_data, 0, 256);
do {
msg_data[0] = id;
msg_data[1] = offset;
msg_data[2] = 0;
msg_data[3] = FRU_DATA_RQST_SIZE;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
printf(" Device not present (No Response)\n");
return -1;
}
if (rsp->ccode > 0) {
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
/* Timeouts are acceptable. No DIMM in the socket */
if (rsp->ccode == 0xc3)
return 1;
return -1;
}
len = rsp->data[0];
memcpy(&spd_data[offset], rsp->data + 1, len);
offset += len;
} while (offset < fru.size);
/* now print spd info */
ipmi_spd_print(spd_data, offset);
return 0;
}

789
lib/helper.c Normal file
View File

@@ -0,0 +1,789 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h> /* For TIOCNOTTY */
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#if HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#else
# define _PATH_VARRUN "/var/run/"
#endif
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
extern int verbose;
uint32_t buf2long(uint8_t * buf)
{
return (uint32_t)(buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]);
}
uint16_t buf2short(uint8_t * buf)
{
return (uint16_t)(buf[1] << 8 | buf[0]);
}
const char * buf2str(uint8_t * buf, int len)
{
static char str[2049];
int i;
if (len <= 0 || len > 1024)
return NULL;
memset(str, 0, 2049);
for (i=0; i<len; i++)
sprintf(str+i+i, "%2.2x", buf[i]);
str[len*2] = '\0';
return (const char *)str;
}
void printbuf(const uint8_t * buf, int len, const char * desc)
{
int i;
if (len <= 0)
return;
if (verbose < 1)
return;
fprintf(stderr, "%s (%d bytes)\n", desc, len);
for (i=0; i<len; i++) {
if (((i%16) == 0) && (i != 0))
fprintf(stderr, "\n");
fprintf(stderr, " %2.2x", buf[i]);
}
fprintf(stderr, "\n");
}
const char * val2str(uint16_t val, const struct valstr *vs)
{
static char un_str[32];
int i;
for (i = 0; vs[i].str != NULL; i++) {
if (vs[i].val == val)
return vs[i].str;
}
memset(un_str, 0, 32);
snprintf(un_str, 32, "Unknown (0x%02X)", val);
return un_str;
}
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 != NULL; i++) {
/* FIXME: for now on we assume PICMG capability on all IANAs */
if ( (vs[i].oem == oem || vs[i].oem == IPMI_OEM_PICMG) &&
vs[i].val == val ) {
return vs[i].str;
}
}
memset(un_str, 0, 32);
snprintf(un_str, 32, "Unknown (0x%X)", val);
return un_str;
}
/* str2double - safely convert string to double
*
* @str: source string to convert from
* @double_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
*/
int str2double(const char * str, double * double_ptr)
{
char * end_ptr = 0;
if (!str || !double_ptr)
return (-1);
*double_ptr = 0;
errno = 0;
*double_ptr = strtod(str, &end_ptr);
if (*end_ptr != '\0')
return (-2);
if (errno != 0)
return (-3);
return 0;
} /* str2double(...) */
/* str2long - safely convert string to int64_t
*
* @str: source string to convert from
* @lng_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
*/
int str2long(const char * str, int64_t * lng_ptr)
{
char * end_ptr = 0;
if (!str || !lng_ptr)
return (-1);
*lng_ptr = 0;
errno = 0;
*lng_ptr = strtol(str, &end_ptr, 0);
if (*end_ptr != '\0')
return (-2);
if (errno != 0)
return (-3);
return 0;
} /* str2long(...) */
/* str2ulong - safely convert string to uint64_t
*
* @str: source string to convert from
* @ulng_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
*/
int str2ulong(const char * str, uint64_t * ulng_ptr)
{
char * end_ptr = 0;
if (!str || !ulng_ptr)
return (-1);
*ulng_ptr = 0;
errno = 0;
*ulng_ptr = strtoul(str, &end_ptr, 0);
if (*end_ptr != '\0')
return (-2);
if (errno != 0)
return (-3);
return 0;
} /* str2ulong(...) */
/* str2int - safely convert string to int32_t
*
* @str: source string to convert from
* @int_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
*/
int str2int(const char * str, int32_t * int_ptr)
{
int rc = 0;
int64_t arg_long = 0;
if (!str || !int_ptr)
return (-1);
if ( (rc = str2long(str, &arg_long)) != 0 ) {
*int_ptr = 0;
return rc;
}
if (arg_long < INT32_MIN || arg_long > INT32_MAX)
return (-3);
*int_ptr = (int32_t)arg_long;
return 0;
} /* str2int(...) */
/* str2uint - safely convert string to uint32_t
*
* @str: source string to convert from
* @uint_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
*/
int str2uint(const char * str, uint32_t * uint_ptr)
{
int rc = 0;
uint64_t arg_ulong = 0;
if (!str || !uint_ptr)
return (-1);
if ( (rc = str2ulong(str, &arg_ulong)) != 0) {
*uint_ptr = 0;
return rc;
}
if (arg_ulong > UINT32_MAX)
return (-3);
*uint_ptr = (uint32_t)arg_ulong;
return 0;
} /* str2uint(...) */
/* str2short - safely convert string to int16_t
*
* @str: source string to convert from
* @shrt_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
*/
int str2short(const char * str, int16_t * shrt_ptr)
{
int rc = (-3);
int64_t arg_long = 0;
if (!str || !shrt_ptr)
return (-1);
if ( (rc = str2long(str, &arg_long)) != 0 ) {
*shrt_ptr = 0;
return rc;
}
if (arg_long < INT16_MIN || arg_long > INT16_MAX)
return (-3);
*shrt_ptr = (int16_t)arg_long;
return 0;
} /* str2short(...) */
/* str2ushort - safely convert string to uint16_t
*
* @str: source string to convert from
* @ushrt_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) invalid input, (-3) for *flow
*/
int str2ushort(const char * str, uint16_t * ushrt_ptr)
{
int rc = (-3);
uint64_t arg_ulong = 0;
if (!str || !ushrt_ptr)
return (-1);
if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) {
*ushrt_ptr = 0;
return rc;
}
if (arg_ulong > UINT16_MAX)
return (-3);
*ushrt_ptr = (uint16_t)arg_ulong;
return 0;
} /* str2ushort(...) */
/* str2char - safely convert string to int8
*
* @str: source string to convert from
* @chr_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails
*/
int str2char(const char *str, int8_t * chr_ptr)
{
int rc = (-3);
int64_t arg_long = 0;
if (!str || !chr_ptr) {
return (-1);
}
if ((rc = str2long(str, &arg_long)) != 0) {
*chr_ptr = 0;
return rc;
}
if (arg_long < INT8_MIN || arg_long > INT8_MAX) {
return (-3);
}
return 0;
} /* str2char(...) */
/* str2uchar - safely convert string to uint8
*
* @str: source string to convert from
* @uchr_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) if one of args is NULL, (-2) or (-3) if conversion fails
*/
int str2uchar(const char * str, uint8_t * uchr_ptr)
{
int rc = (-3);
uint64_t arg_ulong = 0;
if (!str || !uchr_ptr)
return (-1);
if ( (rc = str2ulong(str, &arg_ulong)) != 0 ) {
*uchr_ptr = 0;
return rc;
}
if (arg_ulong > UINT8_MAX)
return (-3);
*uchr_ptr = (uint8_t)arg_ulong;
return 0;
} /* str2uchar(...) */
uint16_t str2val(const char *str, const struct valstr *vs)
{
int i;
for (i = 0; vs[i].str != NULL; i++) {
if (strncasecmp(vs[i].str, str, __maxlen(str, vs[i].str)) == 0)
return vs[i].val;
}
return vs[i].val;
}
/* print_valstr - print value string list to log or stdout
*
* @vs: value string list to print
* @title: name of this value string list
* @loglevel: what log level to print, -1 for stdout
*/
void
print_valstr(const struct valstr * vs, const char * title, int loglevel)
{
int i;
if (vs == NULL)
return;
if (title != NULL) {
if (loglevel < 0)
printf("\n%s:\n\n", title);
else
lprintf(loglevel, "\n%s:\n", title);
}
if (loglevel < 0) {
printf(" VALUE\tHEX\tSTRING\n");
printf("==============================================\n");
} else {
lprintf(loglevel, " VAL\tHEX\tSTRING");
lprintf(loglevel, "==============================================");
}
for (i = 0; vs[i].str != NULL; 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);
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);
}
}
if (loglevel < 0)
printf("\n");
else
lprintf(loglevel, "");
}
/* print_valstr_2col - print value string list in two columns to log or stdout
*
* @vs: value string list to print
* @title: name of this value string list
* @loglevel: what log level to print, -1 for stdout
*/
void
print_valstr_2col(const struct valstr * vs, const char * title, int loglevel)
{
int i;
if (vs == NULL)
return;
if (title != NULL) {
if (loglevel < 0)
printf("\n%s:\n\n", title);
else
lprintf(loglevel, "\n%s:\n", title);
}
for (i = 0; vs[i].str != NULL; i++) {
if (vs[i+1].str == NULL) {
/* 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);
}
}
else {
if (loglevel < 0) {
printf(" %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, "");
}
/* ipmi_csum - calculate an ipmi checksum
*
* @d: buffer to check
* @s: position in buffer to start checksum from
*/
uint8_t
ipmi_csum(uint8_t * d, int s)
{
uint8_t c = 0;
for (; s > 0; s--, d++)
c += *d;
return -c;
}
/* ipmi_open_file - safely open a file for reading or writing
*
* @file: filename
* @rw: read-write flag, 1=write
*
* returns pointer to file handler on success
* returns NULL on error
*/
FILE *
ipmi_open_file(const char * file, int rw)
{
struct stat st1, st2;
FILE * fp;
/* verify existance */
if (lstat(file, &st1) < 0) {
if (rw) {
/* does not exist, ok to create */
fp = fopen(file, "w");
if (fp == NULL) {
lperror(LOG_ERR, "Unable to open file %s "
"for write", file);
return NULL;
}
/* created ok, now return the descriptor */
return fp;
} else {
lprintf(LOG_ERR, "File %s does not exist", file);
return NULL;
}
}
#ifndef ENABLE_FILE_SECURITY
if (!rw) {
/* on read skip the extra checks */
fp = fopen(file, "r");
if (fp == NULL) {
lperror(LOG_ERR, "Unable to open file %s", file);
return NULL;
}
return fp;
}
#endif
/* it exists - only regular files, not links */
if (S_ISREG(st1.st_mode) == 0) {
lprintf(LOG_ERR, "File %s has invalid mode: %d",
file, st1.st_mode);
return NULL;
}
/* allow only files with 1 link (itself) */
if (st1.st_nlink != 1) {
lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
file, (int)st1.st_nlink);
return NULL;
}
fp = fopen(file, rw ? "w+" : "r");
if (fp == NULL) {
lperror(LOG_ERR, "Unable to open file %s", file);
return NULL;
}
/* stat again */
if (fstat(fileno(fp), &st2) < 0) {
lperror(LOG_ERR, "Unable to stat file %s", file);
fclose(fp);
return NULL;
}
/* verify inode */
if (st1.st_ino != st2.st_ino) {
lprintf(LOG_ERR, "File %s has invalid inode: %d != %d",
file, st1.st_ino, st2.st_ino);
fclose(fp);
return NULL;
}
/* verify owner */
if (st1.st_uid != st2.st_uid) {
lprintf(LOG_ERR, "File %s has invalid user id: %d != %d",
file, st1.st_uid, st2.st_uid);
fclose(fp);
return NULL;
}
/* verify inode */
if (st2.st_nlink != 1) {
lprintf(LOG_ERR, "File %s has invalid link count: %d != 1",
file, st2.st_nlink);
fclose(fp);
return NULL;
}
return fp;
}
void
ipmi_start_daemon(struct ipmi_intf *intf)
{
pid_t pid;
int fd;
#ifdef SIGHUP
sigset_t sighup;
#endif
#ifdef SIGHUP
sigemptyset(&sighup);
sigaddset(&sighup, SIGHUP);
if (sigprocmask(SIG_UNBLOCK, &sighup, NULL) < 0)
fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n");
signal(SIGHUP, SIG_IGN);
#endif
#ifdef SIGTTOU
signal(SIGTTOU, SIG_IGN);
#endif
#ifdef SIGTTIN
signal(SIGTTIN, SIG_IGN);
#endif
#ifdef SIGQUIT
signal(SIGQUIT, SIG_IGN);
#endif
#ifdef SIGTSTP
signal(SIGTSTP, SIG_IGN);
#endif
pid = (pid_t) fork();
if (pid < 0 || pid > 0)
exit(0);
#if defined(SIGTSTP) && defined(TIOCNOTTY)
if (setpgid(0, getpid()) == -1)
exit(1);
if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) {
ioctl(fd, TIOCNOTTY, NULL);
close(fd);
}
#else
if (setpgid(0, 0) == -1)
exit(1);
pid = (pid_t) fork();
if (pid < 0 || pid > 0)
exit(0);
#endif
chdir("/");
umask(0);
for (fd=0; fd<64; fd++) {
if (fd != intf->fd)
close(fd);
}
fd = open("/dev/null", O_RDWR);
assert(0 == fd);
dup(fd);
dup(fd);
}
/* is_fru_id - wrapper for str-2-int FRU ID conversion. Message is printed
* on error.
* FRU ID range: <0..255>
*
* @argv_ptr: source string to convert from; usually argv
* @fru_id_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) on error and message is printed on STDERR
*/
int
is_fru_id(const char *argv_ptr, uint8_t *fru_id_ptr)
{
if (!argv_ptr || !fru_id_ptr) {
lprintf(LOG_ERR, "is_fru_id(): invalid argument(s).");
return (-1);
}
if (str2uchar(argv_ptr, fru_id_ptr) == 0) {
return 0;
}
lprintf(LOG_ERR, "FRU ID '%s' is either invalid or out of range.",
argv_ptr);
return (-1);
} /* is_fru_id(...) */
/* is_ipmi_channel_num - wrapper for str-2-int Channel conversion. Message is
* printed on error.
*
* 6.3 Channel Numbers, p. 45, IPMIv2 spec.
* Valid channel numbers are: <0..7>, <E-F>
* Reserved channel numbers: <8-D>
*
* @argv_ptr: source string to convert from; usually argv
* @channel_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) on error and message is printed on STDERR
*/
int
is_ipmi_channel_num(const char *argv_ptr, uint8_t *channel_ptr)
{
if (!argv_ptr || !channel_ptr) {
lprintf(LOG_ERR,
"is_ipmi_channel_num(): invalid argument(s).");
return (-1);
}
if ((str2uchar(argv_ptr, channel_ptr) == 0)
&& ((*channel_ptr >= 0x0 && *channel_ptr <= 0x7)
|| (*channel_ptr >= 0xE && *channel_ptr <= 0xF))) {
return 0;
}
lprintf(LOG_ERR,
"Given Channel number '%s' is either invalid or out of range.",
argv_ptr);
lprintf(LOG_ERR, "Channel number must be from ranges: <0..7>, <0xE..0xF>");
return (-1);
}
/* is_ipmi_user_id() - wrapper for str-2-uint IPMI UID conversion. Message is
* printed on error.
*
* @argv_ptr: source string to convert from; usually argv
* @ipmi_uid_ptr: pointer where to store result
*
* returns zero on success
* returns (-1) on error and message is printed on STDERR
*/
int
is_ipmi_user_id(const char *argv_ptr, uint8_t *ipmi_uid_ptr)
{
if (!argv_ptr || !ipmi_uid_ptr) {
lprintf(LOG_ERR,
"is_ipmi_user_id(): invalid argument(s).");
return (-1);
}
if ((str2uchar(argv_ptr, ipmi_uid_ptr) == 0)
&& *ipmi_uid_ptr >= IPMI_UID_MIN
&& *ipmi_uid_ptr <= IPMI_UID_MAX) {
return 0;
}
lprintf(LOG_ERR,
"Given User ID '%s' is either invalid or out of range.",
argv_ptr);
lprintf(LOG_ERR, "User ID is limited to range <%i..%i>.",
IPMI_UID_MIN, IPMI_UID_MAX);
return (-1);
}
uint16_t
ipmi_get_oem_id(struct ipmi_intf *intf)
{
/* Execute a Get Board ID command to determine the board */
struct ipmi_rs *rsp;
struct ipmi_rq req;
uint16_t oem_id;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_TSOL;
req.msg.cmd = 0x21;
req.msg.data_len = 0;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Get Board ID command failed");
return 0;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get Board ID command failed: %#x %s",
rsp->ccode, val2str(rsp->ccode, completion_code_vals));
return 0;
}
oem_id = rsp->data[0] | (rsp->data[1] << 8);
lprintf(LOG_DEBUG,"Board ID: %x", oem_id);
return oem_id;
}

903
lib/ipmi_channel.c Normal file
View File

@@ -0,0 +1,903 @@
/* -*-mode: C; indent-tabs-mode: t; -*-
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi_lanp.h>
#include <ipmitool/ipmi_channel.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_constants.h>
extern int csv_output;
extern int verbose;
void printf_channel_usage (void);
/**
* ipmi_1_5_authtypes
*
* Create a string describing the supported authentication types as
* specificed by the parameter n
*/
static const char *
ipmi_1_5_authtypes(uint8_t n)
{
uint32_t i;
static char supportedTypes[128];
bzero(supportedTypes, 128);
for (i = 0; ipmi_authtype_vals[i].val != 0; i++) {
if (n & ipmi_authtype_vals[i].val) {
strcat(supportedTypes, ipmi_authtype_vals[i].str);
strcat(supportedTypes, " ");
}
}
return supportedTypes;
}
/**
* ipmi_get_channel_auth_cap
*
* return 0 on success
* -1 on failure
*/
int
ipmi_get_channel_auth_cap(struct ipmi_intf * intf,
uint8_t channel,
uint8_t priv)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct get_channel_auth_cap_rsp auth_cap;
uint8_t msg_data[2];
msg_data[0] = channel | 0x80; // Ask for IPMI v2 data as well
msg_data[1] = priv;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_CHANNEL_AUTH_CAP; // 0x38
req.msg.data = msg_data;
req.msg.data_len = 2;
rsp = intf->sendrecv(intf, &req);
if ((rsp == NULL) || (rsp->ccode > 0)) {
/*
* It's very possible that this failed because we asked for IPMI v2 data
* Ask again, without requesting IPMI v2 data
*/
msg_data[0] &= 0x7F;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Authentication Capabilities");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get Channel Authentication Capabilities failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
}
memcpy(&auth_cap, rsp->data, sizeof(struct get_channel_auth_cap_rsp));
printf("Channel number : %d\n",
auth_cap.channel_number);
printf("IPMI v1.5 auth types : %s\n",
ipmi_1_5_authtypes(auth_cap.enabled_auth_types));
if (auth_cap.v20_data_available)
printf("KG status : %s\n",
(auth_cap.kg_status) ? "non-zero" : "default (all zeroes)");
printf("Per message authentication : %sabled\n",
(auth_cap.per_message_auth) ? "dis" : "en");
printf("User level authentication : %sabled\n",
(auth_cap.user_level_auth) ? "dis" : "en");
printf("Non-null user names exist : %s\n",
(auth_cap.non_null_usernames) ? "yes" : "no");
printf("Null user names exist : %s\n",
(auth_cap.null_usernames) ? "yes" : "no");
printf("Anonymous login enabled : %s\n",
(auth_cap.anon_login_enabled) ? "yes" : "no");
if (auth_cap.v20_data_available) {
printf("Channel supports IPMI v1.5 : %s\n",
(auth_cap.ipmiv15_support) ? "yes" : "no");
printf("Channel supports IPMI v2.0 : %s\n",
(auth_cap.ipmiv20_support) ? "yes" : "no");
}
/*
* If there is support for an OEM authentication type, there is some
* information.
*/
if (auth_cap.enabled_auth_types & IPMI_1_5_AUTH_TYPE_BIT_OEM) {
printf("IANA Number for OEM : %d\n",
auth_cap.oem_id[0] |
auth_cap.oem_id[1] << 8 |
auth_cap.oem_id[2] << 16);
printf("OEM Auxiliary Data : 0x%x\n",
auth_cap.oem_aux_data);
}
return 0;
}
/**
* ipmi_get_channel_info
*
* returns 0 on success
* -1 on failure
*
*/
int
ipmi_get_channel_info(struct ipmi_intf * intf, uint8_t channel)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t rqdata[2];
uint8_t medium;
struct get_channel_info_rsp channel_info;
struct get_channel_access_rsp channel_access;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_CHANNEL_INFO; // 0x42
req.msg.data = &channel;
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Info");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get Channel Info failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
memcpy(&channel_info, rsp->data, sizeof(struct get_channel_info_rsp));
printf("Channel 0x%x info:\n", channel_info.channel_number);
printf(" Channel Medium Type : %s\n",
val2str(channel_info.channel_medium, ipmi_channel_medium_vals));
printf(" Channel Protocol Type : %s\n",
val2str(channel_info.channel_protocol, ipmi_channel_protocol_vals));
printf(" Session Support : ");
switch (channel_info.session_support) {
case 0x0:
printf("session-less\n");
break;
case 0x1:
printf("single-session\n");
break;
case 0x2:
printf("multi-session\n");
break;
case 0x3:
default:
printf("session-based\n");
break;
}
printf(" Active Session Count : %d\n",
channel_info.active_sessions);
printf(" Protocol Vendor ID : %d\n",
channel_info.vendor_id[0] |
channel_info.vendor_id[1] << 8 |
channel_info.vendor_id[2] << 16);
/* only proceed if this is LAN channel */
medium = ipmi_get_channel_medium(intf, channel);
if (medium != IPMI_CHANNEL_MEDIUM_LAN &&
medium != IPMI_CHANNEL_MEDIUM_LAN_OTHER) {
return 0;
}
memset(&req, 0, sizeof(req));
rqdata[0] = channel & 0xf;
/* get volatile settings */
rqdata[1] = 0x80; /* 0x80=active */
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_CHANNEL_ACCESS; // 0x41
req.msg.data = rqdata;
req.msg.data_len = 2;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Access (volatile)");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get Channel Access (volatile) failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp));
printf(" Volatile(active) Settings\n");
printf(" Alerting : %sabled\n",
(channel_access.alerting) ? "dis" : "en");
printf(" Per-message Auth : %sabled\n",
(channel_access.per_message_auth) ? "dis" : "en");
printf(" User Level Auth : %sabled\n",
(channel_access.user_level_auth) ? "dis" : "en");
printf(" Access Mode : ");
switch (channel_access.access_mode) {
case 0:
printf("disabled\n");
break;
case 1:
printf("pre-boot only\n");
break;
case 2:
printf("always available\n");
break;
case 3:
printf("shared\n");
break;
default:
printf("unknown\n");
break;
}
/* get non-volatile settings */
rqdata[1] = 0x40; /* 0x40=non-volatile */
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Access (non-volatile)");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get Channel Access (non-volatile) failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
memcpy(&channel_access, rsp->data, sizeof(struct get_channel_access_rsp));
printf(" Non-Volatile Settings\n");
printf(" Alerting : %sabled\n",
(channel_access.alerting) ? "dis" : "en");
printf(" Per-message Auth : %sabled\n",
(channel_access.per_message_auth) ? "dis" : "en");
printf(" User Level Auth : %sabled\n",
(channel_access.user_level_auth) ? "dis" : "en");
printf(" Access Mode : ");
switch (channel_access.access_mode) {
case 0:
printf("disabled\n");
break;
case 1:
printf("pre-boot only\n");
break;
case 2:
printf("always available\n");
break;
case 3:
printf("shared\n");
break;
default:
printf("unknown\n");
break;
}
return 0;
}
static int
ipmi_get_user_access(struct ipmi_intf * intf, uint8_t channel, uint8_t userid)
{
struct ipmi_rs * rsp;
struct ipmi_rq req1, req2;
uint8_t rqdata[2];
struct get_user_access_rsp user_access;
int curr_uid, max_uid = 0, init = 1;
curr_uid = userid ? : 1;
memset(&req1, 0, sizeof(req1));
req1.msg.netfn = IPMI_NETFN_APP;
req1.msg.cmd = IPMI_GET_USER_ACCESS;
req1.msg.data = rqdata;
req1.msg.data_len = 2;
memset(&req2, 0, sizeof(req2));
req2.msg.netfn = IPMI_NETFN_APP;
req2.msg.cmd = IPMI_GET_USER_NAME;
req2.msg.data = rqdata;
req2.msg.data_len = 1;
do
{
rqdata[0] = channel & 0xf;
rqdata[1] = curr_uid & 0x3f;
rsp = intf->sendrecv(intf, &req1);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get User Access (channel %d id %d)",
rqdata[0], rqdata[1]);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get User Access (channel %d id %d) failed: %s",
rqdata[0], rqdata[1],
val2str(rsp->ccode, completion_code_vals));
return -1;
}
memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp));
rqdata[0] = curr_uid & 0x3f;
rsp = intf->sendrecv(intf, &req2);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get User Name (id %d)", rqdata[0]);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get User Name (id %d) failed: %s",
rqdata[0], val2str(rsp->ccode, completion_code_vals));
return -1;
}
if (init) {
printf("Maximum User IDs : %d\n", user_access.max_user_ids);
printf("Enabled User IDs : %d\n", user_access.enabled_user_ids);
max_uid = user_access.max_user_ids;
init = 0;
}
printf("\n");
printf("User ID : %d\n", curr_uid);
printf("User Name : %s\n", rsp->data);
printf("Fixed Name : %s\n",
(curr_uid <= user_access.fixed_user_ids) ? "Yes" : "No");
printf("Access Available : %s\n",
(user_access.callin_callback) ? "callback" : "call-in / callback");
printf("Link Authentication : %sabled\n",
(user_access.link_auth) ? "en" : "dis");
printf("IPMI Messaging : %sabled\n",
(user_access.ipmi_messaging) ? "en" : "dis");
printf("Privilege Level : %s\n",
val2str(user_access.privilege_limit, ipmi_privlvl_vals));
curr_uid ++;
} while (!userid && curr_uid <= max_uid);
return 0;
}
static int
ipmi_set_user_access(struct ipmi_intf * intf, int argc, char ** argv)
{
uint8_t channel, privilege_limit, userid;
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t rqdata[2];
struct get_user_access_rsp user_access;
struct set_user_access_data set_access;
int i;
if ((argc < 3) || (strncmp(argv[0], "help", 4) == 0)) {
printf_channel_usage();
return 0;
}
if (str2uchar(argv[0], &channel) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[0]);
return (-1);
}
if (str2uchar(argv[1], &userid) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]);
return (-1);
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_GET_USER_ACCESS;
req.msg.data = rqdata;
req.msg.data_len = 2;
rqdata[0] = channel & 0xf;
rqdata[1] = userid & 0x3f;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get User Access (channel %d id %d)",
rqdata[0], rqdata[1]);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get User Access (channel %d id %d) failed: %s",
rqdata[0], rqdata[1],
val2str(rsp->ccode, completion_code_vals));
return -1;
}
memcpy(&user_access, rsp->data, sizeof(struct get_user_access_rsp));
memset(&set_access, 0, sizeof(set_access));
set_access.change_bits = 1;
set_access.callin_callback = user_access.callin_callback;
set_access.link_auth = user_access.link_auth;
set_access.ipmi_messaging = user_access.ipmi_messaging;
set_access.channel = channel;
set_access.user_id = userid;
set_access.privilege_limit = user_access.privilege_limit;
set_access.session_limit = 0;
for (i = 2; i < argc; i ++)
{
if (strncmp(argv[i], "callin=", 7) == 0) {
set_access.callin_callback = !(strncmp (argv[i]+7, "off", 3));
}
else if (strncmp(argv[i], "link=", 5) == 0) {
set_access.link_auth = strncmp (argv[i]+5, "off", 3);
}
else if (strncmp(argv[i], "ipmi=", 5) == 0) {
set_access.ipmi_messaging = strncmp (argv[i]+5, "off", 3);
}
else if (strncmp(argv[i], "privilege=", 10) == 0) {
if (str2uchar(argv[i]+10, &privilege_limit) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[i]+10);
return (-1);
}
set_access.privilege_limit = privilege_limit;
}
else {
printf ("Invalid option: %s\n", argv [i]);
return -1;
}
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_SET_USER_ACCESS;
req.msg.data = (uint8_t *) &set_access;
req.msg.data_len = 4;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Set User Access (channel %d id %d)",
set_access.channel, set_access.user_id);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Set User Access (channel %d id %d) failed: %s",
set_access.channel, set_access.user_id,
val2str(rsp->ccode, completion_code_vals));
return -1;
}
return 0;
}
static const char *
iana_string(uint32_t iana)
{
static char s[10];
if (iana)
{
sprintf(s, "%06x", iana);
return s;
}
else
return "N/A";
}
static int
ipmi_get_channel_cipher_suites(struct ipmi_intf * intf,
const char * payload_type,
uint8_t channel)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t oem_record;
uint8_t rqdata[3];
uint32_t iana;
uint8_t auth_alg, integrity_alg, crypt_alg;
uint8_t cipher_suite_id;
uint8_t list_index = 0;
uint8_t cipher_suite_data[1024]; // 0x40 sets * 16 bytes per set
uint16_t offset = 0;
uint16_t cipher_suite_data_length = 0; // how much was returned, total
memset(cipher_suite_data, 0, sizeof(cipher_suite_data));
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_CHANNEL_CIPHER_SUITES; // 0x54
req.msg.data = rqdata;
req.msg.data_len = 3;
rqdata[0] = channel;
rqdata[1] = ((strncmp(payload_type, "ipmi", 4) == 0)? 0: 1);
rqdata[2] = 0x80; // Always ask for cipher suite format
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
// Grab the returned channel number once. We assume it's the same
// in future calls.
if (rsp->data_len >= 1)
channel = rsp->data[0];
while ((rsp->data_len > 1) && (rsp->data_len == 17) && (list_index < 0x3F))
{
//
// We got back cipher suite data -- store it.
//printf("copying data to offset %d\n", offset);
//printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data");
memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
offset += rsp->data_len - 1;
//
// Increment our list for the next call
//
++list_index;
rqdata[2] = (rqdata[2] & 0x80) + list_index;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
}
/* Copy last chunk */
if(rsp->data_len > 1)
{
//
// We got back cipher suite data -- store it.
//printf("copying data to offset %d\n", offset);
//printbuf(rsp->data + 1, rsp->data_len - 1, "this is the data");
memcpy(cipher_suite_data + offset, rsp->data + 1, rsp->data_len - 1);
offset += rsp->data_len - 1;
}
//
// We can chomp on all our data now.
//
cipher_suite_data_length = offset;
offset = 0;
if (! csv_output)
printf("ID IANA Auth Alg Integrity Alg Confidentiality Alg\n");
while (offset < cipher_suite_data_length)
{
if (cipher_suite_data[offset++] == 0xC0)
{
oem_record = 0; // standard type
iana = 0;
// Verify that we have at least a full record left
if ((cipher_suite_data_length - offset) < 4) // id + 3 algs
{
lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
return -1;
}
cipher_suite_id = cipher_suite_data[offset++];
}
else if (cipher_suite_data[offset++] == 0xC1)
{
oem_record = 1; // OEM record type
// Verify that we have at least a full record left
if ((cipher_suite_data_length - offset) < 4) // id + iana + 3 algs
{
lprintf(LOG_ERR, "Incomplete data record in cipher suite data");
return -1;
}
cipher_suite_id = cipher_suite_data[offset++];
//
// Grab the IANA
//
iana =
cipher_suite_data[offset] |
(cipher_suite_data[offset + 1] << 8) |
(cipher_suite_data[offset + 2] << 16);
offset += 3;
}
else
{
lprintf(LOG_ERR, "Bad start of record byte in cipher suite data");
return -1;
}
//
// Grab the algorithms for this cipher suite. I guess we can't be
// sure of what order they'll come in. Also, I suppose we default
// to the NONE algorithm if one were absent. This part of the spec is
// poorly written -- I have read the errata document. For now, I'm only
// allowing one algorithm per type (auth, integrity, crypt) because I
// don't I understand how it could be otherwise.
//
auth_alg = IPMI_AUTH_RAKP_NONE;
integrity_alg = IPMI_INTEGRITY_NONE;
crypt_alg = IPMI_CRYPT_NONE;
while (((cipher_suite_data[offset] & 0xC0) != 0xC0) &&
((cipher_suite_data_length - offset) > 0))
{
switch (cipher_suite_data[offset] & 0xC0)
{
case 0x00:
// Authentication algorithm specifier
auth_alg = cipher_suite_data[offset++] & 0x3F;
break;
case 0x40:
// Interity algorithm specifier
integrity_alg = cipher_suite_data[offset++] & 0x3F;
break;
case 0x80:
// Confidentiality algorithm specifier
crypt_alg = cipher_suite_data[offset++] & 0x3F;
break;
}
}
//
// We have everything we need to spit out a cipher suite record
//
printf((csv_output? "%d,%s,%s,%s,%s\n" :
"%-4d %-7s %-15s %-15s %-15s\n"),
cipher_suite_id,
iana_string(iana),
val2str(auth_alg, ipmi_auth_algorithms),
val2str(integrity_alg, ipmi_integrity_algorithms),
val2str(crypt_alg, ipmi_encryption_algorithms));
}
return 0;
}
uint8_t
ipmi_get_channel_medium(struct ipmi_intf * intf, uint8_t channel)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct get_channel_info_rsp info;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_GET_CHANNEL_INFO;
req.msg.data = &channel;
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Get Channel Info command failed");
return 0;
}
if (rsp->ccode > 0) {
if (rsp->ccode == 0xcc)
return IPMI_CHANNEL_MEDIUM_RESERVED;
lprintf(LOG_INFO, "Get Channel Info command failed: %s",
val2str(rsp->ccode, completion_code_vals));
return IPMI_CHANNEL_MEDIUM_RESERVED;
}
memcpy(&info, rsp->data, sizeof(struct get_channel_info_rsp));
lprintf(LOG_DEBUG, "Channel type: %s",
val2str(info.channel_medium, ipmi_channel_medium_vals));
return info.channel_medium;
}
uint8_t
ipmi_current_channel_medium(struct ipmi_intf * intf)
{
return ipmi_get_channel_medium(intf, 0xE);
}
void
printf_channel_usage()
{
lprintf(LOG_NOTICE, "Channel Commands: authcap <channel number> <max privilege>");
lprintf(LOG_NOTICE, " getaccess <channel number> [user id]");
lprintf(LOG_NOTICE, " setaccess <channel number> "
"<user id> [callin=on|off] [ipmi=on|off] [link=on|off] [privilege=level]");
lprintf(LOG_NOTICE, " info [channel number]");
lprintf(LOG_NOTICE, " getciphers <ipmi | sol> [channel]\n");
lprintf(LOG_NOTICE, "Possible privilege levels are:");
lprintf(LOG_NOTICE, " 1 Callback level");
lprintf(LOG_NOTICE, " 2 User level");
lprintf(LOG_NOTICE, " 3 Operator level");
lprintf(LOG_NOTICE, " 4 Administrator level");
lprintf(LOG_NOTICE, " 5 OEM Proprietary level");
lprintf(LOG_NOTICE, " 15 No access");
}
int
ipmi_channel_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int retval = 0;
uint8_t channel, priv = 0;
if ((argc == 0) || (strncmp(argv[0], "help", 4) == 0))
{
printf_channel_usage();
}
else if (strncmp(argv[0], "authcap", 7) == 0)
{
if (argc != 3) {
printf_channel_usage();
return (-1);
} else {
if (str2uchar(argv[1], &channel) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]);
return (-1);
}
if (str2uchar(argv[2], &priv) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]);
return (-1);
}
retval = ipmi_get_channel_auth_cap(intf, channel, priv);
}
}
else if (strncmp(argv[0], "getaccess", 10) == 0)
{
if ((argc < 2) || (argc > 3))
printf_channel_usage();
else {
uint8_t ch = 0;
uint8_t id = 0;
if (str2uchar(argv[1], &ch) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]);
return (-1);
}
if (argc == 3) {
if (str2uchar(argv[2], &id) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]);
return (-1);
}
}
retval = ipmi_get_user_access(intf, ch, id);
}
}
else if (strncmp(argv[0], "setaccess", 9) == 0)
{
retval = ipmi_set_user_access(intf, argc-1, &(argv[1]));
}
else if (strncmp(argv[0], "info", 4) == 0)
{
if (argc > 2)
printf_channel_usage();
else {
uint8_t ch = 0xe;
if (argc == 2) {
if (str2uchar(argv[1], &ch) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[1]);
return (-1);
}
}
retval = ipmi_get_channel_info(intf, ch);
}
}
// it channel getciphers <ipmi | sol> [channel]
else if (strncmp(argv[0], "getciphers", 10) == 0)
{
if ((argc < 2) || (argc > 3) ||
(strncmp(argv[1], "ipmi", 4) && strncmp(argv[1], "sol", 3)))
printf_channel_usage();
else
{
uint8_t ch = 0xe;
if (argc == 3) {
if (str2uchar(argv[2], &ch) != 0) {
lprintf(LOG_ERR, "Numeric value expected, but '%s' given.", argv[2]);
return (-1);
}
}
retval = ipmi_get_channel_cipher_suites(intf,
argv[1], // ipmi | sol
ch);
}
}
else
{
printf("Invalid CHANNEL command: %s\n", argv[0]);
printf_channel_usage();
retval = -1;
}
return retval;
}

1188
lib/ipmi_chassis.c Normal file

File diff suppressed because it is too large Load Diff

2066
lib/ipmi_dcmi.c Executable file

File diff suppressed because it is too large Load Diff

4225
lib/ipmi_delloem.c Normal file

File diff suppressed because it is too large Load Diff

4195
lib/ipmi_ekanalyzer.c Normal file

File diff suppressed because it is too large Load Diff

642
lib/ipmi_event.c Normal file
View File

@@ -0,0 +1,642 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi_sel.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_channel.h>
#include <ipmitool/ipmi_event.h>
#include <ipmitool/ipmi_sdr.h>
static void
ipmi_event_msg_print(struct ipmi_intf * intf, struct platform_event_msg * pmsg)
{
struct sel_event_record sel_event;
memset(&sel_event, 0, sizeof(struct sel_event_record));
sel_event.record_id = 0;
sel_event.sel_type.standard_type.gen_id = 2;
sel_event.sel_type.standard_type.evm_rev = pmsg->evm_rev;
sel_event.sel_type.standard_type.sensor_type = pmsg->sensor_type;
sel_event.sel_type.standard_type.sensor_num = pmsg->sensor_num;
sel_event.sel_type.standard_type.event_type = pmsg->event_type;
sel_event.sel_type.standard_type.event_dir = pmsg->event_dir;
sel_event.sel_type.standard_type.event_data[0] = pmsg->event_data[0];
sel_event.sel_type.standard_type.event_data[1] = pmsg->event_data[1];
sel_event.sel_type.standard_type.event_data[2] = pmsg->event_data[2];
if (verbose)
ipmi_sel_print_extended_entry_verbose(intf, &sel_event);
else
ipmi_sel_print_extended_entry(intf, &sel_event);
}
static int
ipmi_send_platform_event(struct ipmi_intf * intf, struct platform_event_msg * emsg)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t rqdata[8];
uint8_t chmed;
memset(&req, 0, sizeof(req));
memset(rqdata, 0, 8);
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = 0x02;
req.msg.data = rqdata;
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));
}
else {
req.msg.data_len = 7;
memcpy(rqdata, emsg, sizeof(struct platform_event_msg));
}
ipmi_event_msg_print(intf, emsg);
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Platform Event Message command failed");
return -1;
}
else if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Platform Event Message command failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
return 0;
}
#define EVENT_THRESH_STATE_LNC_LO 0
#define EVENT_THRESH_STATE_LNC_HI 1
#define EVENT_THRESH_STATE_LCR_LO 2
#define EVENT_THRESH_STATE_LCR_HI 3
#define EVENT_THRESH_STATE_LNR_LO 4
#define EVENT_THRESH_STATE_LNR_HI 5
#define EVENT_THRESH_STATE_UNC_LO 6
#define EVENT_THRESH_STATE_UNC_HI 7
#define EVENT_THRESH_STATE_UCR_LO 8
#define EVENT_THRESH_STATE_UCR_HI 9
#define EVENT_THRESH_STATE_UNR_LO 10
#define EVENT_THRESH_STATE_UNR_HI 11
static const struct valstr ipmi_event_thresh_lo[] = {
{ EVENT_THRESH_STATE_LNC_LO, "lnc" },
{ EVENT_THRESH_STATE_LCR_LO, "lcr" },
{ EVENT_THRESH_STATE_LNR_LO, "lnr" },
{ EVENT_THRESH_STATE_UNC_LO, "unc" },
{ EVENT_THRESH_STATE_UCR_LO, "ucr" },
{ EVENT_THRESH_STATE_UNR_LO, "unr" },
{ 0, NULL },
};
static const struct valstr ipmi_event_thresh_hi[] = {
{ EVENT_THRESH_STATE_LNC_HI, "lnc" },
{ EVENT_THRESH_STATE_LCR_HI, "lcr" },
{ EVENT_THRESH_STATE_LNR_HI, "lnr" },
{ EVENT_THRESH_STATE_UNC_HI, "unc" },
{ EVENT_THRESH_STATE_UCR_HI, "ucr" },
{ EVENT_THRESH_STATE_UNR_HI, "unr" },
{ 0, NULL },
};
static int
ipmi_send_platform_event_num(struct ipmi_intf * intf, int num)
{
struct platform_event_msg emsg;
memset(&emsg, 0, sizeof(struct platform_event_msg));
/* IPMB/LAN/etc */
switch (num) {
case 1: /* temperature */
printf("Sending SAMPLE event: Temperature - "
"Upper Critical - Going High\n");
emsg.evm_rev = 0x04;
emsg.sensor_type = 0x01;
emsg.sensor_num = 0x30;
emsg.event_dir = EVENT_DIR_ASSERT;
emsg.event_type = 0x01;
emsg.event_data[0] = EVENT_THRESH_STATE_UCR_HI;
emsg.event_data[1] = 0xff;
emsg.event_data[2] = 0xff;
break;
case 2: /* voltage error */
printf("Sending SAMPLE event: Voltage Threshold - "
"Lower Critical - Going Low\n");
emsg.evm_rev = 0x04;
emsg.sensor_type = 0x02;
emsg.sensor_num = 0x60;
emsg.event_dir = EVENT_DIR_ASSERT;
emsg.event_type = 0x01;
emsg.event_data[0] = EVENT_THRESH_STATE_LCR_LO;
emsg.event_data[1] = 0xff;
emsg.event_data[2] = 0xff;
break;
case 3: /* correctable ECC */
printf("Sending SAMPLE event: Memory - Correctable ECC\n");
emsg.evm_rev = 0x04;
emsg.sensor_type = 0x0c;
emsg.sensor_num = 0x53;
emsg.event_dir = EVENT_DIR_ASSERT;
emsg.event_type = 0x6f;
emsg.event_data[0] = 0x00;
emsg.event_data[1] = 0xff;
emsg.event_data[2] = 0xff;
break;
default:
lprintf(LOG_ERR, "Invalid event number: %d", num);
return -1;
}
return ipmi_send_platform_event(intf, &emsg);
}
static int
ipmi_event_find_offset(uint8_t code,
struct ipmi_event_sensor_types * evt,
char * desc)
{
if (desc == NULL || code == 0)
return 0x00;
while (evt->type) {
if (evt->code == code && evt->desc != NULL &&
strncasecmp(desc, evt->desc, __maxlen(desc, evt->desc)) == 0)
return evt->offset;
evt++;
}
lprintf(LOG_WARN, "Unable to find matching event offset for '%s'", desc);
return -1;
}
static void
print_sensor_states(uint8_t sensor_type, uint8_t event_type)
{
ipmi_sdr_print_discrete_state_mini(
"Sensor States: \n ", "\n ", sensor_type,
event_type, 0xff, 0xff);
printf("\n");
}
static int
ipmi_event_fromsensor(struct ipmi_intf * intf, char * id, char * state, char * evdir)
{
struct ipmi_rs * rsp;
struct sdr_record_list * sdr;
struct platform_event_msg emsg;
int off;
uint8_t target, lun, channel;
if (id == NULL) {
lprintf(LOG_ERR, "No sensor ID supplied");
return -1;
}
memset(&emsg, 0, sizeof(struct platform_event_msg));
emsg.evm_rev = 0x04;
if (evdir == NULL)
emsg.event_dir = EVENT_DIR_ASSERT;
else if (strncasecmp(evdir, "assert", 6) == 0)
emsg.event_dir = EVENT_DIR_ASSERT;
else if (strncasecmp(evdir, "deassert", 8) == 0)
emsg.event_dir = EVENT_DIR_DEASSERT;
else {
lprintf(LOG_ERR, "Invalid event direction %s. Must be 'assert' or 'deassert'", evdir);
return -1;
}
printf("Finding sensor %s... ", id);
sdr = ipmi_sdr_find_sdr_byid(intf, id);
if (sdr == NULL) {
printf("not found!\n");
return -1;
}
printf("ok\n");
switch (sdr->type)
{
case SDR_RECORD_TYPE_FULL_SENSOR:
case SDR_RECORD_TYPE_COMPACT_SENSOR:
emsg.sensor_type = sdr->record.common->sensor.type;
emsg.sensor_num = sdr->record.common->keys.sensor_num;
emsg.event_type = sdr->record.common->event_type;
target = sdr->record.common->keys.owner_id;
lun = sdr->record.common->keys.lun;
channel = sdr->record.common->keys.channel;
break;
default:
lprintf(LOG_ERR, "Unknown sensor type for id '%s'", id);
return -1;
}
emsg.event_data[1] = 0xff;
emsg.event_data[2] = 0xff;
switch (emsg.event_type)
{
/*
* Threshold Class
*/
case 1:
{
int dir = 0;
int hilo = 0;
off = 1;
if (state == NULL || strncasecmp(state, "list", 4) == 0) {
printf("Sensor States:\n");
printf(" lnr : Lower Non-Recoverable \n");
printf(" lcr : Lower Critical\n");
printf(" lnc : Lower Non-Critical\n");
printf(" unc : Upper Non-Critical\n");
printf(" ucr : Upper Critical\n");
printf(" unr : Upper Non-Recoverable\n");
return -1;
}
if (0 != strncasecmp(state, "lnr", 3) &&
0 != strncasecmp(state, "lcr", 3) &&
0 != strncasecmp(state, "lnc", 3) &&
0 != strncasecmp(state, "unc", 3) &&
0 != strncasecmp(state, "ucr", 3) &&
0 != strncasecmp(state, "unr", 3))
{
lprintf(LOG_ERR, "Invalid threshold identifier %s", state);
return -1;
}
if (state[0] == 'u')
hilo = 1;
else
hilo = 0;
if (emsg.event_dir == EVENT_DIR_ASSERT)
dir = hilo;
else
dir = !hilo;
if ((emsg.event_dir == EVENT_DIR_ASSERT && hilo == 1) ||
(emsg.event_dir == EVENT_DIR_DEASSERT && hilo == 0))
emsg.event_data[0] = (uint8_t)(str2val(state, ipmi_event_thresh_hi) & 0xf);
else if ((emsg.event_dir == EVENT_DIR_ASSERT && hilo == 0) ||
(emsg.event_dir == EVENT_DIR_DEASSERT && hilo == 1))
emsg.event_data[0] = (uint8_t)(str2val(state, ipmi_event_thresh_lo) & 0xf);
else {
lprintf(LOG_ERR, "Invalid Event");
return -1;
}
rsp = ipmi_sdr_get_sensor_thresholds(intf, emsg.sensor_num,
target, lun, channel);
if (rsp == NULL) {
lprintf(LOG_ERR,
"Command Get Sensor Thresholds failed: invalid response.");
return (-1);
} else if (rsp->ccode != 0) {
lprintf(LOG_ERR, "Command Get Sensor Thresholds failed: %s",
val2str(rsp->ccode, completion_code_vals));
return (-1);
}
/* threshold reading */
emsg.event_data[2] = rsp->data[(emsg.event_data[0] / 2) + 1];
rsp = ipmi_sdr_get_sensor_hysteresis(intf, emsg.sensor_num,
target, lun, channel);
if (rsp != NULL && rsp->ccode == 0)
off = dir ? rsp->data[0] : rsp->data[1];
if (off <= 0)
off = 1;
/* trigger reading */
if (dir) {
if ((emsg.event_data[2] + off) > 0xff)
emsg.event_data[1] = 0xff;
else
emsg.event_data[1] = emsg.event_data[2] + off;
}
else {
if ((emsg.event_data[2] - off) < 0)
emsg.event_data[1] = 0;
else
emsg.event_data[1] = emsg.event_data[2] - off;
}
/* trigger in byte 2, threshold in byte 3 */
emsg.event_data[0] |= 0x50;
}
break;
/*
* Digital Discrete
*/
case 3: case 4: case 5: case 6: case 8: case 9:
{
int x;
const char * digi_on[] = { "present", "assert", "limit",
"fail", "yes", "on", "up" };
const char * digi_off[] = { "absent", "deassert", "nolimit",
"nofail", "no", "off", "down" };
/*
* print list of available states for this sensor
*/
if (state == NULL || strncasecmp(state, "list", 4) == 0) {
print_sensor_states(emsg.sensor_type, emsg.event_type);
printf("Sensor State Shortcuts:\n");
for (x = 0; x < sizeof(digi_on)/sizeof(*digi_on); x++) {
printf(" %-9s %-9s\n", digi_on[x], digi_off[x]);
}
return 0;
}
off = 0;
for (x = 0; x < sizeof(digi_on)/sizeof(*digi_on); x++) {
if (strncasecmp(state, digi_on[x], strlen(digi_on[x])) == 0) {
emsg.event_data[0] = 1;
off = 1;
break;
}
else if (strncasecmp(state, digi_off[x], strlen(digi_off[x])) == 0) {
emsg.event_data[0] = 0;
off = 1;
break;
}
}
if (off == 0) {
off = ipmi_event_find_offset(
emsg.event_type, generic_event_types, state);
if (off < 0)
return -1;
emsg.event_data[0] = off;
}
}
break;
/*
* Generic Discrete
*/
case 2: case 7: case 10: case 11: case 12:
{
/*
* print list of available states for this sensor
*/
if (state == NULL || strncasecmp(state, "list", 4) == 0) {
print_sensor_states(emsg.sensor_type, emsg.event_type);
return 0;
}
off = ipmi_event_find_offset(
emsg.event_type, generic_event_types, state);
if (off < 0)
return -1;
emsg.event_data[0] = off;
}
break;
/*
* Sensor-Specific Discrete
*/
case 0x6f:
{
/*
* print list of available states for this sensor
*/
if (state == NULL || strncasecmp(state, "list", 4) == 0) {
print_sensor_states(emsg.sensor_type, emsg.event_type);
return 0;
}
off = ipmi_event_find_offset(
emsg.sensor_type, sensor_specific_types, state);
if (off < 0)
return -1;
emsg.event_data[0] = off;
}
break;
default:
return -1;
}
return ipmi_send_platform_event(intf, &emsg);
}
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];
char buf[1024];
char * ptr, * tok;
int i, j;
uint8_t chmed;
int rc = 0;
if (file == NULL)
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 == NULL)
return -1;
while (feof(fp) == 0) {
if (fgets(buf, 1024, fp) == NULL)
continue;
/* clip off optional comment tail indicated by # */
ptr = strchr(buf, '#');
if (ptr)
*ptr = '\0';
else
ptr = buf + strlen(buf);
/* clip off trailing and leading whitespace */
ptr--;
while (isspace((int)*ptr) && ptr >= buf)
*ptr-- = '\0';
ptr = buf;
while (isspace((int)*ptr))
ptr++;
if (strlen(ptr) == 0)
continue;
/* 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)
break;
j = i++;
if (chmed == IPMI_CHANNEL_MEDIUM_SYSTEM)
j++;
rqdata[j] = (uint8_t)strtol(tok, NULL, 0);
tok = strtok(NULL, " ");
}
if (i < 7) {
lprintf(LOG_ERR, "Invalid Event: %s",
buf2str(rqdata, sizeof(rqdata)));
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 == NULL) {
lprintf(LOG_ERR, "Platform Event Message command failed");
rc = -1;
}
else if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Platform Event Message command failed: %s",
val2str(rsp->ccode, completion_code_vals));
rc = -1;
}
}
fclose(fp);
return rc;
}
static void
ipmi_event_usage(void)
{
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, "usage: event <num>");
lprintf(LOG_NOTICE, " Send generic test events");
lprintf(LOG_NOTICE, " 1 : Temperature - Upper Critical - Going High");
lprintf(LOG_NOTICE, " 2 : Voltage Threshold - Lower Critical - Going Low");
lprintf(LOG_NOTICE, " 3 : Memory - Correctable ECC");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, "usage: event file <filename>");
lprintf(LOG_NOTICE, " Read and generate events from file");
lprintf(LOG_NOTICE, " Use the 'sel save' command to generate from SEL");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, "usage: event <sensorid> <state> [event_dir]");
lprintf(LOG_NOTICE, " sensorid : Sensor ID string to use for event data");
lprintf(LOG_NOTICE, " state : Sensor state, use 'list' to see possible states for sensor");
lprintf(LOG_NOTICE, " event_dir : assert, deassert [default=assert]");
lprintf(LOG_NOTICE, "");
}
int
ipmi_event_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int rc = 0;
if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
ipmi_event_usage();
return 0;
}
if (strncmp(argv[0], "file", 4) == 0) {
if (argc < 2) {
ipmi_event_usage();
return 0;
}
return ipmi_event_fromfile(intf, argv[1]);
}
if (strlen(argv[0]) == 1) {
switch (argv[0][0]) {
case '1': return ipmi_send_platform_event_num(intf, 1);
case '2': return ipmi_send_platform_event_num(intf, 2);
case '3': return ipmi_send_platform_event_num(intf, 3);
}
}
if (argc < 2)
rc = ipmi_event_fromsensor(intf, argv[0], NULL, NULL);
else if (argc < 3)
rc = ipmi_event_fromsensor(intf, argv[0], argv[1], NULL);
else
rc = ipmi_event_fromsensor(intf, argv[0], argv[1], argv[2]);
return rc;
}

1191
lib/ipmi_firewall.c Normal file

File diff suppressed because it is too large Load Diff

5179
lib/ipmi_fru.c Normal file

File diff suppressed because it is too large Load Diff

1132
lib/ipmi_fwum.c Normal file

File diff suppressed because it is too large Load Diff

640
lib/ipmi_gendev.c Normal file
View File

@@ -0,0 +1,640 @@
/*
* Copyright (c) 2003 Kontron Canada, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi_mc.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/ipmi_gendev.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_sel.h>
#include <ipmitool/ipmi_entity.h>
#include <ipmitool/ipmi_constants.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_raw.h>
#if HAVE_CONFIG_H
# include <config.h>
#endif
extern int verbose;
#define GENDEV_RETRY_COUNT 5
#define GENDEV_MAX_SIZE 16
typedef struct gendev_eeprom_info
{
uint32_t size;
uint16_t page_size;
uint8_t address_span;
uint8_t address_length;
}t_gendev_eeprom_info;
static int
ipmi_gendev_get_eeprom_size(
struct ipmi_intf *intf,
struct sdr_record_generic_locator *dev,
t_gendev_eeprom_info *info
)
{
int eeprom_size = 0;
/*
lprintf(LOG_ERR, "Gen Device : %s", dev->id_string);
lprintf(LOG_ERR, "Access Addr: %x", dev->dev_access_addr);
lprintf(LOG_ERR, "Slave Addr : %x", dev->dev_slave_addr);
lprintf(LOG_ERR, "Channel Num: %x", dev->channel_num);
lprintf(LOG_ERR, "Lun : %x", dev->lun);
lprintf(LOG_ERR, "Bus : %x", dev->bus);
lprintf(LOG_ERR, "Addr Span : %x", dev->addr_span);
lprintf(LOG_ERR, "DevType : %x", dev->dev_type);
lprintf(LOG_ERR, "DevType Mod: %x", dev->dev_type_modifier);
*/
if( info != NULL)
{
switch(dev->dev_type)
{
case 0x08: // 24C01
info->size = 128;
info->page_size = 8;
info->address_span = dev->addr_span;
info->address_length = 1;
break;
case 0x09: // 24C02
info->size = 256;
info->page_size = 8;
info->address_span = dev->addr_span;
info->address_length = 1;
break;
case 0x0A: // 24C04
info->size = 512;
info->page_size = 8;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0x0B: // 24C08
info->size = 1024;
info->page_size = 8;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0x0C: // 24C16
info->size = 2048;
info->page_size = 256;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0x0D: // 24C17
info->size = 2048;
info->page_size = 256;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0x0E: // 24C32
info->size = 4096;
info->page_size = 8;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0x0F: // 24C64
info->size = 8192;
info->page_size = 32;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0xC0: // Proposed OEM Code for 24C128
info->size = 16384;
info->page_size = 64;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0xC1: // Proposed OEM Code for 24C256
info->size = 32748;
info->page_size = 64;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0xC2: // Proposed OEM Code for 24C512
info->size = 65536;
info->page_size = 128;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
case 0xC3: // Proposed OEM Code for 24C1024
info->size = 131072;
info->page_size = 128;
info->address_span = dev->addr_span;
info->address_length = 2;
break;
/* Please reserved up to CFh for future update */
default: // Not a eeprom, return size = 0;
info->size = 0;
info->page_size = 0;
info->address_span = 0;
info->address_length = 0;
break;
}
eeprom_size = info->size;
}
return eeprom_size;
}
static int
ipmi_gendev_read_file(
struct ipmi_intf *intf,
struct sdr_record_generic_locator *dev,
const char *ofile
)
{
int rc = 0;
int eeprom_size;
t_gendev_eeprom_info eeprom_info;
eeprom_size = ipmi_gendev_get_eeprom_size(intf, dev, &eeprom_info);
if(eeprom_size > 0)
{
FILE *fp;
/* now write to file */
fp = ipmi_open_file_write(ofile);
if(fp)
{
struct ipmi_rs *rsp;
int numWrite;
uint32_t counter;
uint8_t msize;
uint8_t channel = dev->channel_num;
uint8_t i2cbus = dev->bus;
uint8_t i2caddr = dev->dev_slave_addr;
uint8_t privatebus = 1;
uint32_t address_span_size;
uint8_t percentCompleted = 0;
/* Handle Address Span */
if( eeprom_info.address_span != 0)
{
address_span_size =
(eeprom_info.size / (eeprom_info.address_span+1));
}
else
{
address_span_size = eeprom_info.size;
}
/* Setup read/write size */
if( eeprom_info.page_size < GENDEV_MAX_SIZE)
{
msize = eeprom_info.page_size;
}
else
{
msize = GENDEV_MAX_SIZE;
// All eeprom with page higher than 32 is on the
// 16 bytes boundary
}
/* Setup i2c bus byte */
i2cbus = ((channel & 0xF) << 4) | ((i2cbus & 7) << 1) | privatebus;
/*
lprintf(LOG_ERR, "Generic device: %s", dev->id_string);
lprintf(LOG_ERR, "I2C Chnl: %x", channel);
lprintf(LOG_ERR, "I2C Bus : %x", i2cbus);
lprintf(LOG_ERR, "I2C Addr: %x", i2caddr); */
for (
counter = 0;
(counter < (eeprom_info.size)) && (rc == 0);
counter+= msize
)
{
uint8_t retryCounter;
for(
retryCounter = 0;
retryCounter<GENDEV_RETRY_COUNT;
retryCounter ++
)
{
uint8_t wrByte[GENDEV_MAX_SIZE+2];
wrByte[0] = (uint8_t) (counter>>0);
if(eeprom_info.address_length > 1)
{
wrByte[1] = (uint8_t) (counter>>8);
}
i2caddr+= (((eeprom_info.size) % address_span_size) * 2);
rsp = ipmi_master_write_read(
intf,
i2cbus,
i2caddr,
(uint8_t *) wrByte,
eeprom_info.address_length,
msize
);
if (rsp != NULL)
{
retryCounter = GENDEV_RETRY_COUNT;
rc = 0;
}
else if(retryCounter < GENDEV_RETRY_COUNT)
{
retryCounter ++;
lprintf(LOG_ERR, "Retry");
sleep(1);
rc = -1;
}
else
{
lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
rc = -1;
}
}
if( rc == 0 )
{
static uint8_t previousCompleted = 101;
numWrite = fwrite(rsp->data, 1, msize, fp);
if (numWrite != msize)
{
lprintf(LOG_ERR, "Error writing file %s", ofile);
rc = -1;
break;
}
percentCompleted = ((counter * 100) / eeprom_info.size );
if(percentCompleted != previousCompleted)
{
printf("\r%i percent completed", percentCompleted);
previousCompleted = percentCompleted;
}
}
}
if(counter == (eeprom_info.size))
{
printf("\r%%100 percent completed\n");
}
else
{
printf("\rError: %i percent completed, read not completed \n", percentCompleted);
}
fclose(fp);
}
}
else
{
lprintf(LOG_ERR, "The selected generic device is not an eeprom");
}
return rc;
}
/* ipmi_gendev_write_file - Read raw SDR from binary file
*
* used for writing generic locator device Eeprom type
*
* @intf: ipmi interface
* @dev: generic device to read
* @ofile: output filename
*
* returns 0 on success
* returns -1 on error
*/
static int
ipmi_gendev_write_file(
struct ipmi_intf *intf,
struct sdr_record_generic_locator *dev,
const char *ofile
)
{
int rc = 0;
int eeprom_size;
t_gendev_eeprom_info eeprom_info;
eeprom_size = ipmi_gendev_get_eeprom_size(intf, dev, &eeprom_info);
if(eeprom_size > 0)
{
FILE *fp;
uint32_t fileLength = 0;
/* now write to file */
fp = ipmi_open_file_read(ofile);
if(fp)
{
/* Retreive file length, check if it's fits the Eeprom Size */
fseek(fp, 0 ,SEEK_END);
fileLength = ftell(fp);
lprintf(LOG_ERR, "File Size: %i", fileLength);
lprintf(LOG_ERR, "Eeprom Size: %i", eeprom_size);
if(fileLength != eeprom_size)
{
lprintf(LOG_ERR, "File size does not fit Eeprom Size");
fclose(fp);
fp = NULL;
}
else
{
fseek(fp, 0 ,SEEK_SET);
}
}
if(fp)
{
struct ipmi_rs *rsp;
int numRead;
uint32_t counter;
uint8_t msize;
uint8_t channel = dev->channel_num;
uint8_t i2cbus = dev->bus;
uint8_t i2caddr = dev->dev_slave_addr;
uint8_t privatebus = 1;
uint32_t address_span_size;
uint8_t percentCompleted = 0;
/* Handle Address Span */
if( eeprom_info.address_span != 0)
{
address_span_size =
(eeprom_info.size / (eeprom_info.address_span+1));
}
else
{
address_span_size = eeprom_info.size;
}
/* Setup read/write size */
if( eeprom_info.page_size < GENDEV_MAX_SIZE)
{
msize = eeprom_info.page_size;
}
else
{
msize = GENDEV_MAX_SIZE;
// All eeprom with page higher than 32 is on the
// 16 bytes boundary
}
/* Setup i2c bus byte */
i2cbus = ((channel & 0xF) << 4) | ((i2cbus & 7) << 1) | privatebus;
/*
lprintf(LOG_ERR, "Generic device: %s", dev->id_string);
lprintf(LOG_ERR, "I2C Chnl: %x", channel);
lprintf(LOG_ERR, "I2C Bus : %x", i2cbus);
lprintf(LOG_ERR, "I2C Addr: %x", i2caddr); */
for (
counter = 0;
(counter < (eeprom_info.size)) && (rc == 0);
counter+= msize
)
{
uint8_t retryCounter;
uint8_t readByte[GENDEV_MAX_SIZE];
numRead = fread(readByte, 1, msize, fp);
if (numRead != msize)
{
lprintf(LOG_ERR, "Error reading file %s", ofile);
rc = -1;
break;
}
for(
retryCounter = 0;
retryCounter<GENDEV_RETRY_COUNT;
retryCounter ++
)
{
uint8_t wrByte[GENDEV_MAX_SIZE+2];
wrByte[0] = (uint8_t) (counter>>0);
if(eeprom_info.address_length > 1)
{
wrByte[1] = (uint8_t) (counter>>8);
}
memcpy(&wrByte[eeprom_info.address_length], readByte, msize);
i2caddr+= (((eeprom_info.size) % address_span_size) * 2);
rsp = ipmi_master_write_read(intf, i2cbus, i2caddr, (uint8_t *) wrByte, eeprom_info.address_length+msize, 0);
if (rsp != NULL)
{
retryCounter = GENDEV_RETRY_COUNT;
rc = 0;
}
else if(retryCounter < GENDEV_RETRY_COUNT)
{
retryCounter ++;
lprintf(LOG_ERR, "Retry");
sleep(1);
rc = -1;
}
else
{
lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
rc = -1;
}
}
if( rc == 0 )
{
static uint8_t previousCompleted = 101;
percentCompleted = ((counter * 100) / eeprom_info.size );
if(percentCompleted != previousCompleted)
{
printf("\r%i percent completed", percentCompleted);
previousCompleted = percentCompleted;
}
}
}
if(counter == (eeprom_info.size))
{
printf("\r%%100 percent completed\n");
}
else
{
printf("\rError: %i percent completed, read not completed \n", percentCompleted);
}
fclose(fp);
}
}
else
{
lprintf(LOG_ERR, "The selected generic device is not an eeprom");
}
return rc;
}
/* ipmi_gendev_main - top-level handler for generic device
*
* @intf: ipmi interface
* @argc: number of arguments
* @argv: argument list
*
* returns 0 on success
* returns -1 on error
*/
int
ipmi_gendev_main(struct ipmi_intf *intf, int argc, char **argv)
{
int rc = 0;
/* initialize random numbers used later */
srand(time(NULL));
lprintf(LOG_ERR, "Rx gendev command: %s", argv[0]);
if (
(argc == 0)
||
(strncmp(argv[0], "help", 4) == 0)
)
{
lprintf(LOG_ERR,
"SDR Commands: list read write");
lprintf(LOG_ERR,
" list List All Generic Device Locators");
lprintf(LOG_ERR,
" read <sdr name> <file> Read to file eeprom specify by Generic Device Locators");
lprintf(LOG_ERR,
" write <sdr name> <file> Write from file eeprom specify by Generic Device Locators");
}
else if ( strncmp(argv[0], "list", 4) == 0)
{
rc = ipmi_sdr_print_sdr(intf,
SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
}
else if (strncmp(argv[0], "read", 4) == 0)
{
if (argc < 3)
lprintf(LOG_ERR, "usage: gendev read <gendev> <filename>");
else
{
struct sdr_record_list *sdr;
lprintf(LOG_ERR, "Gendev read sdr name : %s", argv[1]);
printf("Locating sensor record '%s'...\n", argv[1]);
/* lookup by sensor name */
sdr = ipmi_sdr_find_sdr_byid(intf, argv[1]);
if (sdr == NULL)
{
lprintf(LOG_ERR, "Sensor data record not found!");
return -1;
}
if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
{
lprintf(LOG_ERR, "Target SDR is not a generic device locator");
return -1;
}
lprintf(LOG_ERR, "Gendev read file name: %s", argv[2]);
ipmi_gendev_read_file(intf, sdr->record.genloc, argv[2]);
}
}
else if (strncmp(argv[0], "write", 5) == 0)
{
if (argc < 3)
lprintf(LOG_ERR, "usage: gendev write <gendev> <filename>");
else
{
struct sdr_record_list *sdr;
lprintf(LOG_ERR, "Gendev write sdr name : %s", argv[1]);
printf("Locating sensor record '%s'...\n", argv[1]);
/* lookup by sensor name */
sdr = ipmi_sdr_find_sdr_byid(intf, argv[1]);
if (sdr == NULL)
{
lprintf(LOG_ERR, "Sensor data record not found!");
return -1;
}
if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
{
lprintf(LOG_ERR, "Target SDR is not a generic device locator");
return -1;
}
lprintf(LOG_ERR, "Gendev write file name: %s", argv[2]);
ipmi_gendev_write_file(intf, sdr->record.genloc, argv[2]);
}
}
else
{
lprintf(LOG_ERR, "Invalid gendev command: %s", argv[0]);
rc = -1;
}
return rc;
}

2644
lib/ipmi_hpmfwupg.c Normal file

File diff suppressed because it is too large Load Diff

1044
lib/ipmi_ime.c Executable file

File diff suppressed because it is too large Load Diff

828
lib/ipmi_isol.c Normal file
View File

@@ -0,0 +1,828 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <termios.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_isol.h>
static struct termios _saved_tio;
static int _in_raw_mode = 0;
extern int verbose;
#define ISOL_ESCAPE_CHARACTER '~'
/*
* ipmi_get_isol_info
*/
static int ipmi_get_isol_info(struct ipmi_intf * intf,
struct isol_config_parameters * params)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char data[6];
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_ISOL;
req.msg.cmd = GET_ISOL_CONFIG;
req.msg.data = data;
req.msg.data_len = 4;
/* GET ISOL ENABLED CONFIG */
memset(data, 0, 6);
data[0] = 0x00;
data[1] = ISOL_ENABLE_PARAM;
data[2] = 0x00; /* block */
data[3] = 0x00; /* selector */
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Error in Get ISOL Config Command");
return -1;
}
if (rsp->ccode == 0xc1) {
lprintf(LOG_ERR, "IPMI v1.5 Serial Over Lan (ISOL) not supported!");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
params->enabled = rsp->data[1];
/* GET ISOL AUTHENTICATON CONFIG */
memset(data, 0, 6);
data[0] = 0x00;
data[1] = ISOL_AUTHENTICATION_PARAM;
data[2] = 0x00; /* block */
data[3] = 0x00; /* selector */
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Error in Get ISOL Config Command");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
params->privilege_level = rsp->data[1];
/* GET ISOL BAUD RATE CONFIG */
memset(data, 0, 6);
data[0] = 0x00;
data[1] = ISOL_BAUD_RATE_PARAM;
data[2] = 0x00; /* block */
data[3] = 0x00; /* selector */
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Error in Get ISOL Config Command");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Error in Get ISOL Config Command: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
params->bit_rate = rsp->data[1];
return 0;
}
static int ipmi_print_isol_info(struct ipmi_intf * intf)
{
struct isol_config_parameters params = {0};
if (ipmi_get_isol_info(intf, &params))
return -1;
if (csv_output)
{
printf("%s,", (params.enabled & 0x1)?"true": "false");
printf("%s,",
val2str((params.privilege_level & 0xf), ipmi_privlvl_vals));
printf("%s,",
val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals));
}
else
{
printf("Enabled : %s\n",
(params.enabled & 0x1)?"true": "false");
printf("Privilege Level : %s\n",
val2str((params.privilege_level & 0xf), ipmi_privlvl_vals));
printf("Bit Rate (kbps) : %s\n",
val2str((params.bit_rate & 0xf), ipmi_bit_rate_vals));
}
return 0;
}
static int ipmi_isol_set_param(struct ipmi_intf * intf,
const char *param,
const char *value)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char data[6];
struct isol_config_parameters params = {0};
/* We need other values to complete the request */
if (ipmi_get_isol_info(intf, &params))
return -1;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_ISOL;
req.msg.cmd = SET_ISOL_CONFIG;
req.msg.data = data;
req.msg.data_len = 3;
memset(data, 0, 6);
/*
* enabled
*/
if (strcmp(param, "enabled") == 0)
{
data[1] = ISOL_ENABLE_PARAM;
if (strcmp(value, "true") == 0)
data[2] = 0x01;
else if (strcmp(value, "false") == 0)
data[2] = 0x00;
else {
lprintf(LOG_ERR, "Invalid value %s for parameter %s",
value, param);
lprintf(LOG_ERR, "Valid values are true and false");
return -1;
}
}
/*
* privilege-level
*/
else if (strcmp(param, "privilege-level") == 0)
{
data[1] = ISOL_AUTHENTICATION_PARAM;
if (! strcmp(value, "user"))
data[2] = 0x02;
else if (! strcmp(value, "operator"))
data[2] = 0x03;
else if (! strcmp(value, "admin"))
data[2] = 0x04;
else if (! strcmp(value, "oem"))
data[2] = 0x05;
else
{
lprintf(LOG_ERR, "Invalid value %s for parameter %s",
value, param);
lprintf(LOG_ERR, "Valid values are user, operator, admin, and oem");
return -1;
}
/* We need to mask bit7 from the fetched value */
data[2] |= (params.privilege_level & 0x80) ? 0x80 : 0x00;
}
/*
* bit-rate
*/
else if (strcmp(param, "bit-rate") == 0)
{
data[1] = ISOL_BAUD_RATE_PARAM;
if (strncmp(value, "9.6", 3) == 0) {
data[2] = 0x06;
}
else if (strncmp(value, "19.2", 4) == 0) {
data[2] = 0x07;
}
else if (strncmp(value, "38.4", 4) == 0) {
data[2] = 0x08;
}
else if (strncmp(value, "57.6", 4) == 0) {
data[2] = 0x09;
}
else if (strncmp(value, "115.2", 5) == 0) {
data[2] = 0x0A;
}
else {
lprintf(LOG_ERR, "ISOL - Unsupported baud rate: %s", value);
lprintf(LOG_ERR, "Valid values are 9.6, 19.2, 38.4, 57.6 and 115.2");
return -1;
}
}
else
{
lprintf(LOG_ERR, "Error: invalid ISOL parameter %s", param);
return -1;
}
/*
* Execute the request
*/
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Error setting ISOL parameter '%s'", param);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Error setting ISOL parameter '%s': %s",
param, val2str(rsp->ccode, completion_code_vals));
return -1;
}
return 0;
}
static void
leave_raw_mode(void)
{
if (!_in_raw_mode)
return;
if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1)
perror("tcsetattr");
else
_in_raw_mode = 0;
}
static void
enter_raw_mode(void)
{
struct termios tio;
if (tcgetattr(fileno(stdin), &tio) == -1) {
perror("tcgetattr");
return;
}
_saved_tio = tio;
tio.c_iflag |= IGNPAR;
tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF)\
;
tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
// #ifdef IEXTEN
tio.c_lflag &= ~IEXTEN;
// #endif
tio.c_oflag &= ~OPOST;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) == -1)
perror("tcsetattr");
else
_in_raw_mode = 1;
}
static void
sendBreak(struct ipmi_intf * intf)
{
struct ipmi_v2_payload v2_payload;
memset(&v2_payload, 0, sizeof(v2_payload));
v2_payload.payload.sol_packet.character_count = 0;
v2_payload.payload.sol_packet.generate_break = 1;
intf->send_sol(intf, &v2_payload);
}
/*
* suspendSelf
*
* Put ourself in the background
*
* param bRestoreTty specifies whether we will put our self back
* in raw mode when we resume
*/
static void
suspendSelf(int bRestoreTty)
{
leave_raw_mode();
kill(getpid(), SIGTSTP);
if (bRestoreTty)
enter_raw_mode();
}
/*
* printiSolEscapeSequences
*
* Send some useful documentation to the user
*/
static void
printiSolEscapeSequences(void)
{
printf(
"%c?\n\
Supported escape sequences:\n\
%c. - terminate connection\n\
%c^Z - suspend ipmitool\n\
%c^X - suspend ipmitool, but don't restore tty on restart\n\
%cB - send break\n\
%c? - this message\n\
%c%c - send the escape character by typing it twice\n\
(Note that escapes are only recognized immediately after newline.)\n",
ISOL_ESCAPE_CHARACTER,
ISOL_ESCAPE_CHARACTER,
ISOL_ESCAPE_CHARACTER,
ISOL_ESCAPE_CHARACTER,
ISOL_ESCAPE_CHARACTER,
ISOL_ESCAPE_CHARACTER,
ISOL_ESCAPE_CHARACTER,
ISOL_ESCAPE_CHARACTER);
}
/*
* output
*
* Send the specified data to stdout
*/
static void
output(struct ipmi_rs * rsp)
{
if (rsp)
{
int i;
for (i = 0; i < rsp->data_len; ++i)
putc(rsp->data[i], stdout);
fflush(stdout);
}
}
/*
* ipmi_isol_deactivate
*/
static int
ipmi_isol_deactivate(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t data[6];
struct isol_config_parameters params;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_ISOL;
req.msg.cmd = ACTIVATE_ISOL;
req.msg.data = data;
req.msg.data_len = 5;
memset(data, 0, 6);
data[0] = 0x00; /* Deactivate */
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00;
data[5] = 0x00;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Error deactivating ISOL");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Error deactivating ISOL: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
/* response contain 4 additional bytes : 80 00 32 ff
Don't know what to use them for yet... */
return 0;
}
/*
* processiSolUserInput
*
* Act on user input into the ISOL session. The only reason this
* is complicated is that we have to process escape sequences.
*
* return 0 on success
* 1 if we should exit
* < 0 on error (BMC probably closed the session)
*/
static int
processiSolUserInput(struct ipmi_intf * intf,
uint8_t * input,
uint16_t buffer_length)
{
static int escape_pending = 0;
static int last_was_cr = 1;
struct ipmi_v2_payload v2_payload;
int length = 0;
int retval = 0;
char ch;
int i;
memset(&v2_payload, 0, sizeof(v2_payload));
/*
* Our first order of business is to check the input for escape
* sequences to act on.
*/
for (i = 0; i < buffer_length; ++i)
{
ch = input[i];
if (escape_pending){
escape_pending = 0;
/*
* Process a possible escape sequence.
*/
switch (ch) {
case '.':
printf("%c. [terminated ipmitool]\n", ISOL_ESCAPE_CHARACTER);
retval = 1;
break;
case 'Z' - 64:
printf("%c^Z [suspend ipmitool]\n", ISOL_ESCAPE_CHARACTER);
suspendSelf(1); /* Restore tty back to raw */
continue;
case 'X' - 64:
printf("%c^X [suspend ipmitool]\n", ISOL_ESCAPE_CHARACTER);
suspendSelf(0); /* Don't restore to raw mode */
continue;
case 'B':
printf("%cb [send break]\n", ISOL_ESCAPE_CHARACTER);
sendBreak(intf);
continue;
case '?':
printiSolEscapeSequences();
continue;
default:
if (ch != ISOL_ESCAPE_CHARACTER)
v2_payload.payload.sol_packet.data[length++] =
ISOL_ESCAPE_CHARACTER;
v2_payload.payload.sol_packet.data[length++] = ch;
}
}
else
{
if (last_was_cr && (ch == ISOL_ESCAPE_CHARACTER)) {
escape_pending = 1;
continue;
}
v2_payload.payload.sol_packet.data[length++] = ch;
}
/*
* Normal character. Record whether it was a newline.
*/
last_was_cr = (ch == '\r' || ch == '\n');
}
/*
* If there is anything left to process we dispatch it to the BMC,
* send intf->session->sol_data.max_outbound_payload_size bytes
* at a time.
*/
if (length)
{
struct ipmi_rs * rsp;
v2_payload.payload.sol_packet.flush_outbound = 1; /* Not sure if necessary ? */
v2_payload.payload.sol_packet.character_count = length;
rsp = intf->send_sol(intf, &v2_payload);
if (! rsp) {
lprintf(LOG_ERR, "Error sending SOL data");
retval = -1;
}
/* If the sequence number is set we know we have new data */
else if ((rsp->session.payloadtype == IPMI_PAYLOAD_TYPE_SOL) &&
(rsp->payload.sol_packet.packet_sequence_number))
output(rsp);
}
return retval;
}
/*
* ipmi_isol_red_pill
*/
static int
ipmi_isol_red_pill(struct ipmi_intf * intf)
{
char * buffer;
int numRead;
int bShouldExit = 0;
int bBmcClosedSession = 0;
fd_set read_fds;
struct timeval tv;
int retval;
int buffer_size = 255;
int timedout = 0;
buffer = (char*)malloc(buffer_size);
if (buffer == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return -1;
}
enter_raw_mode();
while (! bShouldExit)
{
FD_ZERO(&read_fds);
FD_SET(0, &read_fds);
FD_SET(intf->fd, &read_fds);
/* Wait up to half a second */
tv.tv_sec = 0;
tv.tv_usec = 500000;
retval = select(intf->fd + 1, &read_fds, NULL, NULL, &tv);
if (retval)
{
if (retval == -1)
{
/* ERROR */
perror("select");
return -1;
}
timedout = 0;
/*
* Process input from the user
*/
if (FD_ISSET(0, &read_fds))
{
memset(buffer, 0, buffer_size);
numRead = read(fileno(stdin),
buffer,
buffer_size);
if (numRead > 0)
{
int rc = processiSolUserInput(intf, buffer, numRead);
if (rc)
{
if (rc < 0)
bShouldExit = bBmcClosedSession = 1;
else
bShouldExit = 1;
}
}
else
{
bShouldExit = 1;
}
}
/*
* Process input from the BMC
*/
else if (FD_ISSET(intf->fd, &read_fds))
{
struct ipmi_rs * rs = intf->recv_sol(intf);
if (! rs)
{
bShouldExit = bBmcClosedSession = 1;
}
else
output(rs);
}
/*
* ERROR in select
*/
else
{
lprintf(LOG_ERR, "Error: Select returned with nothing to read");
bShouldExit = 1;
}
}
else
{
if ((++timedout) == 20) /* Every 10 seconds we send a keepalive */
{
intf->keepalive(intf);
timedout = 0;
}
}
}
leave_raw_mode();
if (bBmcClosedSession)
{
lprintf(LOG_ERR, "SOL session closed by BMC");
}
else
ipmi_isol_deactivate(intf);
return 0;
}
/*
* ipmi_isol_activate
*/
static int
ipmi_isol_activate(struct ipmi_intf * intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t data[6];
struct isol_config_parameters params;
if (ipmi_get_isol_info(intf, &params))
return -1;
if (!(params.enabled & 0x1)) {
lprintf(LOG_ERR, "ISOL is not enabled!");
return -1;
}
/*
* Setup a callback so that the lanplus processing knows what
* to do with packets that come unexpectedly (while waiting for
* an ACK, perhaps.
*/
intf->session->sol_data.sol_input_handler = output;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_ISOL;
req.msg.cmd = ACTIVATE_ISOL;
req.msg.data = data;
req.msg.data_len = 5;
memset(data, 0, 6);
data[0] = 0x01;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00;
data[5] = 0x00;
rsp = intf->sendrecv(intf, &req);
if (NULL != rsp) {
switch (rsp->ccode) {
case 0x00:
if (rsp->data_len == 4) {
break;
} else {
lprintf(LOG_ERR, "Error: Unexpected data length (%d) received "
"in ISOL activation response",
rsp->data_len);
return -1;
}
break;
case 0x80:
lprintf(LOG_ERR, "Info: ISOL already active on another session");
return -1;
case 0x81:
lprintf(LOG_ERR, "Info: ISOL disabled");
return -1;
case 0x82:
lprintf(LOG_ERR, "Info: ISOL activation limit reached");
return -1;
default:
lprintf(LOG_ERR, "Error activating ISOL: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
} else {
lprintf(LOG_ERR, "Error: No response activating ISOL");
return -1;
}
/* response contain 4 additional bytes : 80 01 32 ff
Don't know what to use them for yet... */
printf("[SOL Session operational. Use %c? for help]\n",
ISOL_ESCAPE_CHARACTER);
/*
* At this point we are good to go with our SOL session. We
* need to listen to
* 1) STDIN for user input
* 2) The FD for incoming SOL packets
*/
if (ipmi_isol_red_pill(intf)) {
lprintf(LOG_ERR, "Error in SOL session");
return -1;
}
return 0;
}
static void print_isol_set_usage(void) {
lprintf(LOG_NOTICE, "\nISOL set parameters and values: \n");
lprintf(LOG_NOTICE, " enabled true | false");
lprintf(LOG_NOTICE, " privilege-level user | operator | admin | oem");
lprintf(LOG_NOTICE, " bit-rate "
"9.6 | 19.2 | 38.4 | 57.6 | 115.2");
lprintf(LOG_NOTICE, "");
}
static void print_isol_usage(void) {
lprintf(LOG_NOTICE, "ISOL Commands: info");
lprintf(LOG_NOTICE, " set <parameter> <setting>");
lprintf(LOG_NOTICE, " activate");
}
int ipmi_isol_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int ret = 0;
/*
* Help
*/
if (!argc || !strncmp(argv[0], "help", 4))
print_isol_usage();
/*
* Info
*/
else if (!strncmp(argv[0], "info", 4)) {
ret = ipmi_print_isol_info(intf);
}
/*
* Set a parameter value
*/
else if (!strncmp(argv[0], "set", 3)) {
if (argc < 3) {
print_isol_set_usage();
return -1;
}
ret = ipmi_isol_set_param(intf, argv[1], argv[2]);
}
/*
* Activate
*/
else if (!strncmp(argv[0], "activate", 8)) {
ret = ipmi_isol_activate(intf);
}
else {
print_isol_usage();
ret = -1;
}
return ret;
}

808
lib/ipmi_kontronoem.c Normal file
View File

@@ -0,0 +1,808 @@
/*
* Copyright (c) 2004 Kontron Canada, Inc. All Rights Reserved.
*
* Base on code from
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
/*
* Tue Mar 7 14:36:12 2006
* <stephane.filion@ca.kontron.com>
*
* This code implements an Kontron OEM proprietary commands.
*/
#include <string.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_fru.h>
extern int verbose;
extern int read_fru_area(struct ipmi_intf * intf, struct fru_info *fru,
uint8_t id, uint32_t offset, uint32_t length,
uint8_t *frubuf);
extern int write_fru_area(struct ipmi_intf * intf, struct fru_info *fru,
unsigned char id, unsigned int soffset,
unsigned int doffset, unsigned int length,
unsigned char *pFrubuf);
extern char * get_fru_area_str(uint8_t * data, uint32_t * offset);
static void ipmi_kontron_help(void);
static int ipmi_kontron_set_serial_number(struct ipmi_intf * intf);
static int ipmi_kontron_set_mfg_date (struct ipmi_intf * intf);
static void ipmi_kontron_nextboot_help(void);
static int ipmi_kontron_nextboot_set(struct ipmi_intf * intf,
int argc, char **argv);
static int ipmi_kontronoem_send_set_large_buffer(struct ipmi_intf * intf,
unsigned char channel,
unsigned char size);
int
ipmi_kontronoem_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int rc = 0;
if (argc == 0)
ipmi_kontron_help();
else if (strncmp(argv[0], "help", 4) == 0)
ipmi_kontron_help();
else if (!strncmp(argv[0], "setsn", 5))
{
if(argc >= 1)
{
if(ipmi_kontron_set_serial_number(intf) > 0)
{
printf("FRU serial number setted successfully\n");
}
else
{
printf("FRU serial number set failed\n");
}
}
else
{
printf("fru setsn\n");
}
}
else if (!strncmp(argv[0], "setmfgdate", 5))
{
if(argc >= 1)
{
if(ipmi_kontron_set_mfg_date(intf) > 0)
{
printf("FRU manufacturing date setted successfully\n");
}
else
{
printf("FRU manufacturing date set failed\n");
}
}
else
{
printf("fru setmfgdate\n");
}
}
else if (!strncmp(argv[0], "nextboot", sizeof("nextboot")-1))
{
if (argc > 1)
{
if ((rc = ipmi_kontron_nextboot_set(intf, argc-1, argv+1)) == 0)
{
printf("Nextboot set successfully\n");
}
else
{
printf("Nextboot set failed\n");
}
}
else
{
ipmi_kontron_nextboot_help();
}
}
else
{
printf("Invalid Kontron command: %s", argv[0]);
ipmi_kontron_help();
rc = -1;
}
return rc;
}
static void ipmi_kontron_help(void)
{
printf("Kontron Commands: setsn setmfgdate nextboot\n");
}
int ipmi_kontronoem_set_large_buffer(struct ipmi_intf * intf, unsigned char size)
{
uint8_t error_occurs = 0;
uint32_t prev_target_addr = intf->target_addr ;
if ( intf->target_addr > 0 && (intf->target_addr != intf->my_addr) )
{
intf->target_addr = intf->my_addr;
printf("Set local big buffer\n");
if(ipmi_kontronoem_send_set_large_buffer( intf, 0x0e, size ) == 0)
{
printf("Set local big buffer:success\n");
}
else
{
error_occurs = 1;
}
if (error_occurs == 0)
{
if(ipmi_kontronoem_send_set_large_buffer( intf, 0x00, size ) == 0)
{
printf("IPMB was set\n");
}
else
{
/* Revert back the previous set large buffer */
error_occurs = 1;
ipmi_kontronoem_send_set_large_buffer( intf, 0x0e, 0 );
}
}
/* Restore target address */
intf->target_addr = prev_target_addr;
}
if (error_occurs == 0)
{
if(ipmi_kontronoem_send_set_large_buffer( intf, 0x0e, size ) == 0)
{
//printf("Set remote big buffer\n");
}
else
{
if ( intf->target_addr > 0 && (intf->target_addr != intf->my_addr) )
{
/* Error occurs revert back the previous set large buffer*/
intf->target_addr = intf->my_addr;
//ipmi_kontronoem_send_set_large_buffer( intf, 0x00, 0 );
ipmi_kontronoem_send_set_large_buffer( intf, 0x0e, 0 );
intf->target_addr = prev_target_addr;
}
}
}
return error_occurs;
}
int ipmi_kontronoem_send_set_large_buffer(struct ipmi_intf * intf, unsigned char channel,unsigned char size)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
uint8_t msg_data[2];
int i;
memset(msg_data, 0, sizeof(msg_data));
msg_data[0] = channel/*0x0e*/; // Currently running interface
msg_data[1] = size;
memset(&req, 0, sizeof(req));
req.msg.netfn = 0x3E; /* OEM NetFn */
req.msg.cmd = 0x82; /* Set Channel Buffer Length - OEM */
req.msg.data = msg_data;
req.msg.data_len = 2;
req.msg.lun = 0x00;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL)
{
printf("Cannot send large buffer command\n");
return(-1);
}
if (rsp->ccode > 0)
{
printf("Invalid length for the selected interface (%s) %d\n",
val2str(rsp->ccode, completion_code_vals), rsp->ccode);
return(-1);
}
return 0;
}
/* ipmi_fru_set_serial_number - Set the Serial Number in FRU
*
* @intf: ipmi interface
* @id: fru id
*
* returns -1 on error
* returns 1 if successful
*/
static int
ipmi_kontron_set_serial_number(struct ipmi_intf * intf)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
struct fru_info fru;
struct fru_header header;
uint8_t msg_data[4];
char *sn;
uint8_t sn_size, checksum;
uint8_t *fru_data;
char *fru_area;
uint32_t fru_data_offset, fru_data_offset_tmp, board_sec_len, prod_sec_len, i;
sn = NULL;
fru_data = NULL;
memset(msg_data, 0, 4);
msg_data[0] = 0xb4;
msg_data[1] = 0x90;
msg_data[2] = 0x91;
msg_data[3] = 0x8b;
memset(&req, 0, sizeof(req));
req.msg.netfn = 0x3E;
req.msg.cmd = 0x0C;
req.msg.data = msg_data;
req.msg.data_len = 4;
/* Set Lun, necessary for this oem command */
req.msg.lun = 0x03;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL)
{
printf(" Device not present (No Response)\n");
return -11;
}
if (rsp->ccode > 0)
{
printf(" This option is not implemented for this board\n");
return -1;
}
sn_size = rsp->data_len;
sn = malloc(sn_size + 1);
if(sn == NULL)
{
printf("Out of memory!");
return -1;
}
memset(sn, 0, sn_size + 1);
memcpy(sn, rsp->data, sn_size);
if(verbose >= 1)
{
printf("Original serial number is : [%s]\n", sn);
}
memset(msg_data, 0, 4);
msg_data[0] = 0;
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 == NULL) {
printf(" Device not present (No Response)\n");
free(sn);
sn = NULL;
return -1;
}
if (rsp->ccode > 0) {
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
free(sn);
sn = NULL;
return(-1);
}
memset(&fru, 0, sizeof(fru));
fru.size = (rsp->data[1] << 8) | rsp->data[0];
fru.access = rsp->data[2] & 0x1;
if (fru.size < 1) {
printf(" Invalid FRU size %d", fru.size);
free(sn);
sn = NULL;
return -1;
}
/*
* retrieve the FRU header
*/
msg_data[0] = 0;
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 == NULL)
{
printf(" Device not present (No Response)\n");
free(sn);
sn = NULL;
return(-1);
}
if (rsp->ccode > 0)
{
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
free(sn);
sn = NULL;
return(-1);
}
if (verbose > 1)
printbuf(rsp->data, rsp->data_len, "FRU DATA");
memcpy(&header, rsp->data + 1, 8);
if (header.version != 1)
{
printf(" Unknown FRU header version 0x%02x",
header.version);
free(sn);
sn = NULL;
return(-1);
}
/* Set the Board Section */
board_sec_len = (header.offset.product * 8) - (header.offset.board * 8);
fru_data = malloc( fru.size);
if(fru_data == NULL)
{
printf("Out of memory!");
free(sn);
sn = NULL;
return(-1);
}
memset(fru_data, 0, fru.size);
if(read_fru_area(intf ,&fru ,0 ,(header.offset.board * 8) ,board_sec_len , fru_data) < 0)
{
free(sn);
sn = NULL;
free(fru_data);
fru_data = NULL;
return(-1);
}
/*Position at Board Manufacturer*/
fru_data_offset = (header.offset.board * 8) + 6;
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
/*Position at Board Product Name*/
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
fru_data_offset_tmp = fru_data_offset;
/*Position at Serial Number*/
fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp);
fru_data_offset ++;
if(strlen(fru_area) != sn_size)
{
printf("The length of the serial number in the FRU Board Area is wrong.\n");
free(sn);
sn = NULL;
free(fru_data);
fru_data = NULL;
return(-1);
}
/* Copy the new serial number in the board section saved in memory*/
memcpy(fru_data + fru_data_offset, sn, sn_size);
checksum = 0;
/* Calculate Header Checksum */
for( i = (header.offset.board * 8); i < (((header.offset.board * 8)+board_sec_len) - 2) ; i ++ )
{
checksum += fru_data[i];
}
checksum = (~checksum) + 1;
fru_data[(header.offset.board * 8)+board_sec_len - 1] = checksum;
/* Write the new FRU Board section */
if(write_fru_area(intf, &fru, 0, (header.offset.board * 8), (header.offset.board * 8), board_sec_len, fru_data) < 0)
{
free(sn);
sn = NULL;
free(fru_data);
fru_data = NULL;
return(-1);
}
/* Set the Product Section */
prod_sec_len = (header.offset.multi * 8) - (header.offset.product * 8);
if(read_fru_area(intf ,&fru ,0 ,(header.offset.product * 8) ,prod_sec_len , fru_data) < 0)
{
free(sn);
sn = NULL;
free(fru_data);
fru_data = NULL;
return(-1);
}
/*Position at Product Manufacturer*/
fru_data_offset = (header.offset.product * 8) + 3;
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
/*Position at Product Name*/
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
/*Position at Product Part*/
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
/*Position at Product Version*/
fru_area = get_fru_area_str(fru_data, &fru_data_offset);
fru_data_offset_tmp = fru_data_offset;
/*Position at Serial Number*/
fru_area = get_fru_area_str(fru_data, &fru_data_offset_tmp);
fru_data_offset ++;
if(strlen(fru_area) != sn_size)
{
free(sn);
sn = NULL;
free(fru_data);
fru_data = NULL;
printf("The length of the serial number in the FRU Product Area is wrong.\n");
return(-1);
}
/* Copy the new serial number in the product section saved in memory*/
memcpy(fru_data + fru_data_offset, sn, sn_size);
checksum = 0;
/* Calculate Header Checksum */
for( i = (header.offset.product * 8); i < (((header.offset.product * 8)+prod_sec_len) - 2) ; i ++ )
{
checksum += fru_data[i];
}
checksum = (~checksum) + 1;
fru_data[(header.offset.product * 8)+prod_sec_len - 1] = checksum;
/* Write the new FRU Board section */
if(write_fru_area(intf, &fru, 0, (header.offset.product * 8), (header.offset.product * 8), prod_sec_len, fru_data) < 0)
{
free(sn);
sn = NULL;
free(fru_data);
fru_data = NULL;
return -1;
}
free(sn);
sn = NULL;
free(fru_data);
fru_data = NULL;
return(1);
}
/* ipmi_fru_set_mfg_date - Set the Manufacturing Date in FRU
*
* @intf: ipmi interface
* @id: fru id
*
* returns -1 on error
* returns 1 if successful
*/
static int
ipmi_kontron_set_mfg_date (struct ipmi_intf * intf)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
struct fru_info fru;
struct fru_header header;
uint8_t msg_data[4];
uint8_t mfg_date[3];
uint32_t board_sec_len, i;
uint8_t *fru_data, checksum;
memset(msg_data, 0, 4);
msg_data[0] = 0xb4;
msg_data[1] = 0x90;
msg_data[2] = 0x91;
msg_data[3] = 0x8b;
memset(&req, 0, sizeof(req));
req.msg.netfn = 0x3E;
req.msg.cmd = 0x0E;
req.msg.data = msg_data;
req.msg.data_len = 4;
/* Set Lun temporary, necessary for this oem command */
req.msg.lun = 0x03;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL)
{
printf("Device not present (No Response)\n");
return(-1);
}
if (rsp->ccode > 0)
{
printf("This option is not implemented for this board\n");
return(-1);
}
if(rsp->data_len != 3)
{
printf("Invalid response for the Manufacturing date\n");
return(-1);
}
memset(mfg_date, 0, 3);
memcpy(mfg_date, rsp->data, 3);
memset(msg_data, 0, 4);
msg_data[0] = 0;
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 == NULL) {
printf(" Device not present (No Response)\n");
return(-1);
}
if (rsp->ccode > 0) {
printf(" Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
return(-1);
}
memset(&fru, 0, sizeof(fru));
fru.size = (rsp->data[1] << 8) | rsp->data[0];
fru.access = rsp->data[2] & 0x1;
if (fru.size < 1) {
printf(" Invalid FRU size %d", fru.size);
return(-1);
}
/*
* retrieve the FRU header
*/
msg_data[0] = 0;
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 == NULL)
{
printf(" Device not present (No Response)\n");
return(-1);
}
if (rsp->ccode > 0)
{
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)
{
printf(" Unknown FRU header version 0x%02x",
header.version);
return(-1);
}
board_sec_len = (header.offset.product * 8) - (header.offset.board * 8);
fru_data = malloc( fru.size);
if(fru_data == NULL)
{
printf("Out of memory!");
return(-1);
}
memset(fru_data, 0, fru.size);
if(read_fru_area(intf ,&fru ,0 ,(header.offset.board * 8) ,board_sec_len , fru_data) < 0)
{
free(fru_data);
fru_data = NULL;
return(-1);
}
/* Copy the new manufacturing date in the board section saved in memory*/
memcpy(fru_data + (header.offset.board * 8) + 3, mfg_date, 3);
checksum = 0;
/* Calculate Header Checksum */
for( i = (header.offset.board * 8); i < (((header.offset.board * 8)+board_sec_len) - 2) ; i ++ )
{
checksum += fru_data[i];
}
checksum = (~checksum) + 1;
fru_data[(header.offset.board * 8)+board_sec_len - 1] = checksum;
/* Write the new FRU Board section */
if(write_fru_area(intf, &fru, 0, (header.offset.board * 8), (header.offset.board * 8), board_sec_len, fru_data) < 0)
{
free(fru_data);
fru_data = NULL;
return(-1);
}
free(fru_data);
fru_data = NULL;
return(1);
}
static char *bootdev[] = {"BIOS", "FDD", "HDD", "CDROM", "network", 0};
static void
ipmi_kontron_nextboot_help(void)
{
int i;
printf("nextboot <device>\n"
"Supported devices:\n");
for (i = 0; bootdev[i] != 0; i++) {
printf("- %s\n", bootdev[i]);
}
}
/* ipmi_kontron_next_boot_set - Select the next boot order on CP6012
*
* @intf: ipmi interface
* @id: fru id
*
* returns -1 on error
* returns 1 if successful
*/
static int
ipmi_kontron_nextboot_set(struct ipmi_intf * intf, int argc, char **argv)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
uint8_t msg_data[8];
int i;
memset(msg_data, 0, sizeof(msg_data));
msg_data[0] = 0xb4;
msg_data[1] = 0x90;
msg_data[2] = 0x91;
msg_data[3] = 0x8b;
msg_data[4] = 0x9d;
msg_data[5] = 0xFF;
msg_data[6] = 0xFF; /* any */
for (i = 0; bootdev[i] != 0; i++) {
if (strcmp(argv[0], bootdev[i]) == 0) {
msg_data[5] = i;
break;
}
}
/* Invalid device selected? */
if (msg_data[5] == 0xFF) {
printf("Unknown boot device: %s\n", argv[0]);
return -1;
}
memset(&req, 0, sizeof(req));
req.msg.netfn = 0x3E;
req.msg.cmd = 0x02;
req.msg.data = msg_data;
req.msg.data_len = 7;
/* Set Lun temporary, necessary for this oem command */
req.msg.lun = 0x03;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL)
{
printf("Device not present (No Response)\n");
return(-1);
}
if (rsp->ccode > 0) {
printf("Device not present (%s)\n",
val2str(rsp->ccode, completion_code_vals));
return(-1);
}
return 0;
}

2352
lib/ipmi_lanp.c Normal file

File diff suppressed because it is too large Load Diff

1056
lib/ipmi_main.c Normal file

File diff suppressed because it is too large Load Diff

1112
lib/ipmi_mc.c Normal file

File diff suppressed because it is too large Load Diff

164
lib/ipmi_oem.c Normal file
View File

@@ -0,0 +1,164 @@
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <string.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_constants.h>
#include <ipmitool/log.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi_sel.h>
static int ipmi_oem_supermicro(struct ipmi_intf * intf);
static int ipmi_oem_ibm(struct ipmi_intf * intf);
static struct ipmi_oem_handle ipmi_oem_list[] = {
{
name: "supermicro",
desc: "Supermicro IPMIv1.5 BMC with OEM LAN authentication support",
setup: ipmi_oem_supermicro,
},
{
name: "intelwv2",
desc: "Intel SE7501WV2 IPMIv1.5 BMC with extra LAN communication support",
},
{
name: "intelplus",
desc: "Intel IPMI 2.0 BMC with RMCP+ communication support",
},
{
name: "icts",
desc: "IPMI 2.0 ICTS compliance support",
},
{
name: "ibm",
desc: "IBM OEM support",
setup: ipmi_oem_ibm,
},
{
name: "i82571spt",
desc: "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode",
},
{ 0 }
};
/* Supermicro IPMIv2 BMCs use OEM authtype */
static int
ipmi_oem_supermicro(struct ipmi_intf * intf)
{
ipmi_intf_session_set_authtype(intf, IPMI_SESSION_AUTHTYPE_OEM);
return 0;
}
static int
ipmi_oem_ibm(struct ipmi_intf * intf)
{
char * filename;
if ((filename = getenv("IPMI_OEM_IBM_DATAFILE")) == NULL) {
lprintf(LOG_ERR, "Unable to read IPMI_OEM_IBM_DATAFILE from environment");
return -1;
}
return ipmi_sel_oem_init((const char *)filename);
}
/* ipmi_oem_print - print list of OEM handles
*/
void
ipmi_oem_print(void)
{
struct ipmi_oem_handle * oem;
lprintf(LOG_NOTICE, "\nOEM Support:");
for (oem=ipmi_oem_list; oem->name != NULL && oem->desc != NULL; oem++) {
lprintf(LOG_NOTICE, "\t%-12s %s", oem->name, oem->desc);
}
lprintf(LOG_NOTICE, "");
}
/* ipmi_oem_setup - do initial setup of OEM handle
*
* @intf: ipmi interface
* @oemtype: OEM handle name
*
* returns 0 on success
* returns -1 on error
*/
int
ipmi_oem_setup(struct ipmi_intf * intf, char * oemtype)
{
struct ipmi_oem_handle * oem;
int rc = 0;
if (oemtype == NULL ||
strncmp(oemtype, "help", 4) == 0 ||
strncmp(oemtype, "list", 4) == 0) {
ipmi_oem_print();
return -1;
}
for (oem=ipmi_oem_list; oem->name != NULL; oem++) {
if (strncmp(oemtype, oem->name, strlen(oem->name)) == 0)
break;
}
if (oem->name == NULL)
return -1;
/* save pointer for later use */
intf->oem = oem;
/* run optional setup function if it is defined */
if (oem->setup != NULL) {
lprintf(LOG_DEBUG, "Running OEM setup for \"%s\"", oem->desc);
rc = oem->setup(intf);
}
return rc;
}
/* ipmi_oem_active - used to determine if a particular OEM type is set
*
* @intf: ipmi interface
* @oemtype: string containing name of ipmi handle to check
*
* returns 1 if requested ipmi handle is active
* returns 0 otherwise
*/
int
ipmi_oem_active(struct ipmi_intf * intf, const char * oemtype)
{
if (intf->oem == NULL)
return 0;
if (strncmp(intf->oem->name, oemtype, strlen(oemtype)) == 0)
return 1;
return 0;
}

890
lib/ipmi_pef.c Normal file
View File

@@ -0,0 +1,890 @@
/*
* Copyright (c) 2004 Dell Computers. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Dell Computers, or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* DELL COMPUTERS ("DELL") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* DELL OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF DELL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <string.h>
#include <math.h>
#include <time.h>
#include <ipmitool/bswap.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_pef.h>
extern int verbose;
/*
// common kywd/value printf() templates
*/
static const char * pef_fld_fmts[][2] = {
{"%-*s : %u\n", " | %u"}, /* F_DEC: unsigned value */
{"%-*s : %d\n", " | %d"}, /* F_INT: signed value */
{"%-*s : %s\n", " | %s"}, /* F_STR: string value */
{"%-*s : 0x%x\n", " | 0x%x"}, /* F_HEX: "N hex digits" */
{"%-*s : 0x%04x\n", " | 0x%04x"}, /* F_2XD: "2 hex digits" */
{"%-*s : 0x%02x\n", " | 0x%02x"}, /* F_1XD: "1 hex digit" */
{"%-*s : %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
" | %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"},
};
typedef enum {
F_DEC,
F_INT,
F_STR,
F_HEX,
F_2XD,
F_1XD,
F_UID,
} fmt_e;
#define KYWD_LENGTH 24
static int first_field = 1;
static const char * pef_flag_fmts[][3] = {
{"", "false", "true"},
{"supported", "un", ""},
{"active", "in", ""},
{"abled", "dis", "en"},
};
static const char * listitem[] = {" | %s", ",%s", "%s"};
const char *
ipmi_pef_bit_desc(struct bit_desc_map * map, uint32_t value)
{ /*
// return description/text label(s) for the given value.
// NB: uses a static buffer
*/
static char buf[128];
char * p;
struct desc_map * pmap;
uint32_t match, index;
*(p = buf) = '\0';
index = 2;
for (pmap=map->desc_maps; pmap && pmap->desc; pmap++) {
if (map->desc_map_type == BIT_DESC_MAP_LIST)
match = (value == pmap->mask);
else
match = ((value & pmap->mask) == pmap->mask);
if (match) {
sprintf(p, listitem[index], pmap->desc);
p = strchr(p, '\0');
if (map->desc_map_type != BIT_DESC_MAP_ALL)
break;
index = 1;
}
}
if (p == buf)
return("None");
return((const char *)buf);
}
void
ipmi_pef_print_flags(struct bit_desc_map * map, flg_e type, uint32_t val)
{ /*
// print features/flags, using val (a bitmask), according to map.
// observe the verbose flag, and print any labels, etc. based on type
*/
struct desc_map * pmap;
uint32_t maskval, index;
index = 0;
for (pmap=map->desc_maps; pmap && pmap->desc; pmap++) {
maskval = (val & pmap->mask);
if (verbose)
printf("%-*s : %s%s\n", KYWD_LENGTH,
ipmi_pef_bit_desc(map, pmap->mask),
pef_flag_fmts[type][1 + (maskval != 0)],
pef_flag_fmts[type][0]);
else if (maskval != 0) {
printf(listitem[index], ipmi_pef_bit_desc(map, maskval));
index = 1;
}
}
}
static void
ipmi_pef_print_field(const char * fmt[2], const char * label, unsigned long val)
{ /*
// print a 'field' (observes 'verbose' flag)
*/
if (verbose)
printf(fmt[0], KYWD_LENGTH, label, val);
else if (first_field)
printf(&fmt[1][2], val); /* skip field separator */
else
printf(fmt[1], val);
first_field = 0;
}
void
ipmi_pef_print_dec(const char * text, uint32_t val)
{ /* unsigned */
ipmi_pef_print_field(pef_fld_fmts[F_DEC], text, val);
}
void
ipmi_pef_print_int(const char * text, uint32_t val)
{ /* signed */
ipmi_pef_print_field(pef_fld_fmts[F_INT], text, val);
}
void
ipmi_pef_print_hex(const char * text, uint32_t val)
{ /* hex */
ipmi_pef_print_field(pef_fld_fmts[F_HEX], text, val);
}
void
ipmi_pef_print_str(const char * text, const char * val)
{ /* string */
ipmi_pef_print_field(pef_fld_fmts[F_STR], text, (unsigned long)val);
}
void
ipmi_pef_print_2xd(const char * text, uint8_t u1, uint8_t u2)
{ /* 2 hex digits */
uint32_t val = ((u1 << 8) + u2) & 0xffff;
ipmi_pef_print_field(pef_fld_fmts[F_2XD], text, val);
}
void
ipmi_pef_print_1xd(const char * text, uint32_t val)
{ /* 1 hex digit */
ipmi_pef_print_field(pef_fld_fmts[F_1XD], text, val);
}
static struct ipmi_rs *
ipmi_pef_msg_exchange(struct ipmi_intf * intf, struct ipmi_rq * req, char * txt)
{ /*
// common IPMItool rqst/resp handling
*/
struct ipmi_rs * rsp = intf->sendrecv(intf, req);
if (!rsp) {
return(NULL);
} else if (rsp->ccode == 0x80) {
return(NULL); /* Do not output error, just unsupported parameters */
} else if (rsp->ccode) {
lprintf(LOG_ERR, " **Error %x in '%s' command", rsp->ccode, txt);
return(NULL);
}
if (verbose > 2) {
printbuf(rsp->data, rsp->data_len, txt);
}
return(rsp);
}
static uint8_t
ipmi_pef_get_policy_table(struct ipmi_intf * intf,
struct pef_cfgparm_policy_table_entry ** table)
{ /*
// get the PEF policy table: allocate space, fillin, and return its size
// NB: the caller must free the returned area (when returned size > 0)
*/
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_cfgparm_selector psel;
struct pef_cfgparm_policy_table_entry * ptbl, * ptmp;
uint32_t i;
uint8_t tbl_size;
memset(&psel, 0, sizeof(psel));
psel.id = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_SIZE;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS;
req.msg.data = (uint8_t *)&psel;
req.msg.data_len = sizeof(psel);
rsp = ipmi_pef_msg_exchange(intf, &req, "Alert policy table size");
if (!rsp)
return(0);
tbl_size = (rsp->data[1] & PEF_POLICY_TABLE_SIZE_MASK);
i = (tbl_size * sizeof(struct pef_cfgparm_policy_table_entry));
if (!i
|| (ptbl = (struct pef_cfgparm_policy_table_entry *)malloc(i)) == NULL)
return(0);
memset(&psel, 0, sizeof(psel));
psel.id = PEF_CFGPARM_ID_PEF_ALERT_POLICY_TABLE_ENTRY;
for (ptmp=ptbl, i=1; i<=tbl_size; i++) {
psel.set = (i & PEF_POLICY_TABLE_ID_MASK);
rsp = ipmi_pef_msg_exchange(intf, &req, "Alert policy table entry");
if (!rsp
|| i != (rsp->data[1] & PEF_POLICY_TABLE_ID_MASK)) {
lprintf(LOG_ERR, " **Error retrieving %s",
"Alert policy table entry");
free(ptbl);
ptbl = NULL;
tbl_size = 0;
break;
}
memcpy(ptmp, &rsp->data[1], sizeof(*ptmp));
ptmp++;
}
*table = ptbl;
return(tbl_size);
}
static void
ipmi_pef_print_lan_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest)
{ /*
// print LAN alert destination info
*/
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_lan_cfgparm_selector lsel;
struct pef_lan_cfgparm_dest_type * ptype;
struct pef_lan_cfgparm_dest_info * pinfo;
char buf[32];
uint8_t tbl_size, dsttype, timeout, retries;
memset(&lsel, 0, sizeof(lsel));
lsel.id = PEF_LAN_CFGPARM_ID_DEST_COUNT;
lsel.ch = ch;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_TRANSPORT;
req.msg.cmd = IPMI_CMD_LAN_GET_CONFIG;
req.msg.data = (uint8_t *)&lsel;
req.msg.data_len = sizeof(lsel);
rsp = ipmi_pef_msg_exchange(intf, &req, "Alert destination count");
if (!rsp) {
lprintf(LOG_ERR, " **Error retrieving %s",
"Alert destination count");
return;
}
tbl_size = (rsp->data[1] & PEF_LAN_DEST_TABLE_SIZE_MASK);
//if (tbl_size == 0 || dest == 0) /* LAN alerting not supported */
// return;
lsel.id = PEF_LAN_CFGPARM_ID_DESTTYPE;
lsel.set = dest;
rsp = ipmi_pef_msg_exchange(intf, &req, "Alert destination type");
if (!rsp || rsp->data[1] != lsel.set) {
lprintf(LOG_ERR, " **Error retrieving %s",
"Alert destination type");
return;
}
ptype = (struct pef_lan_cfgparm_dest_type *)&rsp->data[1];
dsttype = (ptype->dest_type & PEF_LAN_DEST_TYPE_MASK);
timeout = ptype->alert_timeout;
retries = (ptype->retries & PEF_LAN_RETRIES_MASK);
ipmi_pef_print_str("Alert destination type",
ipmi_pef_bit_desc(&pef_b2s_lan_desttype, dsttype));
if (dsttype == PEF_LAN_DEST_TYPE_PET) {
lsel.id = PEF_LAN_CFGPARM_ID_PET_COMMUNITY;
lsel.set = 0;
rsp = ipmi_pef_msg_exchange(intf, &req, "PET community");
if (!rsp)
lprintf(LOG_ERR, " **Error retrieving %s",
"PET community");
else {
rsp->data[19] = '\0';
ipmi_pef_print_str("PET Community", (const char *)&rsp->data[1]);
}
}
ipmi_pef_print_dec("ACK timeout/retry (secs)", timeout);
ipmi_pef_print_dec("Retries", retries);
lsel.id = PEF_LAN_CFGPARM_ID_DESTADDR;
lsel.set = dest;
rsp = ipmi_pef_msg_exchange(intf, &req, "Alert destination info");
if (!rsp || rsp->data[1] != lsel.set)
lprintf(LOG_ERR, " **Error retrieving %s",
"Alert destination info");
else {
pinfo = (struct pef_lan_cfgparm_dest_info *)&rsp->data[1];
sprintf(buf, "%u.%u.%u.%u",
pinfo->ip[0], pinfo->ip[1], pinfo->ip[2], pinfo->ip[3]);
ipmi_pef_print_str("IP address", buf);
sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
pinfo->mac[0], pinfo->mac[1], pinfo->mac[2],
pinfo->mac[3], pinfo->mac[4], pinfo->mac[5]);
ipmi_pef_print_str("MAC address", buf);
}
}
static void
ipmi_pef_print_serial_dest_dial(struct ipmi_intf * intf, char * label,
struct pef_serial_cfgparm_selector * ssel)
{ /*
// print a dial string
*/
#define BLOCK_SIZE 16
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_serial_cfgparm_selector tmp;
char * p, strval[(6 * BLOCK_SIZE) + 1];
memset(&tmp, 0, sizeof(tmp));
tmp.id = PEF_SERIAL_CFGPARM_ID_DEST_DIAL_STRING_COUNT;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_TRANSPORT;
req.msg.cmd = IPMI_CMD_SERIAL_GET_CONFIG;
req.msg.data = (uint8_t *)&tmp;
req.msg.data_len = sizeof(tmp);
rsp = ipmi_pef_msg_exchange(intf, &req, "Dial string count");
if (!rsp || (rsp->data[1] & PEF_SERIAL_DIAL_STRING_COUNT_MASK) == 0)
return; /* sssh, not supported */
memcpy(&tmp, ssel, sizeof(tmp));
tmp.id = PEF_SERIAL_CFGPARM_ID_DEST_DIAL_STRING;
tmp.block = 1;
memset(strval, 0, sizeof(strval));
p = strval;
for (;;) {
rsp = ipmi_pef_msg_exchange(intf, &req, label);
if (!rsp
|| (rsp->data[1] != ssel->id)
|| (rsp->data[2] != tmp.block)) {
lprintf(LOG_ERR, " **Error retrieving %s", label);
return;
}
memcpy(p, &rsp->data[3], BLOCK_SIZE);
if (strchr(p, '\0') <= (p + BLOCK_SIZE))
break;
if ((p += BLOCK_SIZE) >= &strval[sizeof(strval)-1])
break;
tmp.block++;
}
ipmi_pef_print_str(label, strval);
#undef BLOCK_SIZE
}
static void
ipmi_pef_print_serial_dest_tap(struct ipmi_intf * intf,
struct pef_serial_cfgparm_selector * ssel)
{ /*
// print TAP destination info
*/
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_serial_cfgparm_selector tmp;
struct pef_serial_cfgparm_tap_svc_settings * pset;
uint8_t dialstr_id, setting_id;
memset(&tmp, 0, sizeof(tmp));
tmp.id = PEF_SERIAL_CFGPARM_ID_TAP_ACCT_COUNT;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_TRANSPORT;
req.msg.cmd = IPMI_CMD_SERIAL_GET_CONFIG;
req.msg.data = (uint8_t *)&tmp;
req.msg.data_len = sizeof(tmp);
rsp = ipmi_pef_msg_exchange(intf, &req, "Number of TAP accounts");
if (!rsp || (rsp->data[1] & PEF_SERIAL_TAP_ACCT_COUNT_MASK) == 0)
return; /* sssh, not supported */
memcpy(&tmp, ssel, sizeof(tmp));
tmp.id = PEF_SERIAL_CFGPARM_ID_TAP_ACCT_INFO;
rsp = ipmi_pef_msg_exchange(intf, &req, "TAP account info");
if (!rsp || (rsp->data[1] != tmp.set)) {
lprintf(LOG_ERR, " **Error retrieving %s",
"TAP account info");
return;
}
dialstr_id = (rsp->data[2] & PEF_SERIAL_TAP_ACCT_INFO_DIAL_STRING_ID_MASK);
dialstr_id >>= PEF_SERIAL_TAP_ACCT_INFO_DIAL_STRING_ID_SHIFT;
setting_id = (rsp->data[2] & PEF_SERIAL_TAP_ACCT_INFO_SVC_SETTINGS_ID_MASK);
tmp.set = dialstr_id;
ipmi_pef_print_serial_dest_dial(intf, "TAP Dial string", &tmp);
tmp.set = setting_id;
rsp = ipmi_pef_msg_exchange(intf, &req, "TAP service settings");
if (!rsp || (rsp->data[1] != tmp.set)) {
lprintf(LOG_ERR, " **Error retrieving %s",
"TAP service settings");
return;
}
pset = (struct pef_serial_cfgparm_tap_svc_settings *)&rsp->data[1];
ipmi_pef_print_str("TAP confirmation",
ipmi_pef_bit_desc(&pef_b2s_tap_svc_confirm, pset->confirmation_flags));
/* TODO : additional TAP settings? */
}
static void
ipmi_pef_print_serial_dest_ppp(struct ipmi_intf * intf,
struct pef_serial_cfgparm_selector * ssel)
{ /*
// print PPP destination info
*/
/* TODO */
}
static void
ipmi_pef_print_serial_dest_callback(struct ipmi_intf * intf,
struct pef_serial_cfgparm_selector * ssel)
{ /*
// print callback destination info
*/
/* TODO */
}
static void
ipmi_pef_print_serial_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest)
{ /*
// print Serial/PPP alert destination info
*/
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_serial_cfgparm_selector ssel;
uint8_t tbl_size, wrk;
struct pef_serial_cfgparm_dest_info * pinfo;
memset(&ssel, 0, sizeof(ssel));
ssel.id = PEF_SERIAL_CFGPARM_ID_DEST_COUNT;
ssel.ch = ch;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_TRANSPORT;
req.msg.cmd = IPMI_CMD_SERIAL_GET_CONFIG;
req.msg.data = (uint8_t *)&ssel;
req.msg.data_len = sizeof(ssel);
rsp = ipmi_pef_msg_exchange(intf, &req, "Alert destination count");
if (!rsp) {
lprintf(LOG_ERR, " **Error retrieving %s",
"Alert destination count");
return;
}
tbl_size = (rsp->data[1] & PEF_SERIAL_DEST_TABLE_SIZE_MASK);
if (!dest || tbl_size == 0) /* Page alerting not supported */
return;
ssel.id = PEF_SERIAL_CFGPARM_ID_DESTINFO;
ssel.set = dest;
rsp = ipmi_pef_msg_exchange(intf, &req, "Alert destination info");
if (!rsp || rsp->data[1] != ssel.set)
lprintf(LOG_ERR, " **Error retrieving %s",
"Alert destination info");
else {
pinfo = (struct pef_serial_cfgparm_dest_info *)rsp->data;
wrk = (pinfo->dest_type & PEF_SERIAL_DEST_TYPE_MASK);
ipmi_pef_print_str("Alert destination type",
ipmi_pef_bit_desc(&pef_b2s_serial_desttype, wrk));
ipmi_pef_print_dec("ACK timeout (secs)",
pinfo->alert_timeout);
ipmi_pef_print_dec("Retries",
(pinfo->retries & PEF_SERIAL_RETRIES_MASK));
switch (wrk) {
case PEF_SERIAL_DEST_TYPE_DIAL:
ipmi_pef_print_serial_dest_dial(intf, "Serial dial string", &ssel);
break;
case PEF_SERIAL_DEST_TYPE_TAP:
ipmi_pef_print_serial_dest_tap(intf, &ssel);
break;
case PEF_SERIAL_DEST_TYPE_PPP:
ipmi_pef_print_serial_dest_ppp(intf, &ssel);
break;
case PEF_SERIAL_DEST_TYPE_BASIC_CALLBACK:
case PEF_SERIAL_DEST_TYPE_PPP_CALLBACK:
ipmi_pef_print_serial_dest_callback(intf, &ssel);
break;
}
}
}
static void
ipmi_pef_print_dest(struct ipmi_intf * intf, uint8_t ch, uint8_t dest)
{ /*
// print generic alert destination info
*/
ipmi_pef_print_dec("Destination ID", dest);
}
void
ipmi_pef_print_event_info(struct pef_cfgparm_filter_table_entry * pef, char * buf)
{ /*
// print PEF entry Event info: class, severity, trigger, etc.
*/
static char * classes[] = {"Discrete", "Threshold", "OEM"};
uint16_t offmask;
char * p;
int i;
uint8_t t;
ipmi_pef_print_str("Event severity",
ipmi_pef_bit_desc(&pef_b2s_severities, pef->entry.severity));
t = pef->entry.event_trigger;
if (t == PEF_EVENT_TRIGGER_THRESHOLD)
i = 1;
else if (t > PEF_EVENT_TRIGGER_SENSOR_SPECIFIC)
i = 2;
else
i = 0;
ipmi_pef_print_str("Event class", classes[i]);
offmask = ((pef->entry.event_data_1_offset_mask[1] << 8)
+ pef->entry.event_data_1_offset_mask[0]);
if (offmask == 0xffff || t == PEF_EVENT_TRIGGER_MATCH_ANY)
strcpy(buf, "Any");
else if (t == PEF_EVENT_TRIGGER_UNSPECIFIED)
strcpy(buf, "Unspecified");
else if (t == PEF_EVENT_TRIGGER_SENSOR_SPECIFIC)
strcpy(buf, "Sensor-specific");
else if (t > PEF_EVENT_TRIGGER_SENSOR_SPECIFIC)
strcpy(buf, "OEM");
else {
sprintf(buf, "(0x%02x/0x%04x)", t, offmask);
p = strchr(buf, '\0');
for (i=0; i<PEF_B2S_GENERIC_ER_ENTRIES; i++) {
if (offmask & 1) {
if ((t-1) >= PEF_B2S_GENERIC_ER_ENTRIES) {
sprintf(p, ", Unrecognized event trigger");
} else {
sprintf(p, ",%s", ipmi_pef_bit_desc(pef_b2s_generic_ER[t-1], i));
}
p = strchr(p, '\0');
}
offmask >>= 1;
}
}
ipmi_pef_print_str("Event trigger(s)", buf);
}
static void
ipmi_pef_print_entry(struct ipmi_rs * rsp, uint8_t id,
struct pef_cfgparm_filter_table_entry * pef)
{ /*
// print a PEF table entry
*/
uint8_t wrk, set;
char buf[128];
ipmi_pef_print_dec("PEF table entry", id);
wrk = !!(pef->entry.config & PEF_CONFIG_ENABLED);
sprintf(buf, "%sactive", (wrk ? "" : "in"));
if (pef->entry.config & PEF_CONFIG_PRECONFIGURED)
strcat(buf, ", pre-configured");
ipmi_pef_print_str("Status", buf);
if (wrk != 0) {
ipmi_pef_print_1xd("Version", rsp->data[0]);
ipmi_pef_print_str("Sensor type",
ipmi_pef_bit_desc(&pef_b2s_sensortypes, pef->entry.sensor_type));
if (pef->entry.sensor_number == PEF_SENSOR_NUMBER_MATCH_ANY)
ipmi_pef_print_str("Sensor number", "Any");
else
ipmi_pef_print_dec("Sensor number", pef->entry.sensor_number);
ipmi_pef_print_event_info(pef, buf);
ipmi_pef_print_str("Action",
ipmi_pef_bit_desc(&pef_b2s_actions, pef->entry.action));
if (pef->entry.action & PEF_ACTION_ALERT) {
set = (pef->entry.policy_number & PEF_POLICY_NUMBER_MASK);
ipmi_pef_print_int("Policy set", set);
}
}
}
static void
ipmi_pef_list_entries(struct ipmi_intf * intf)
{ /*
// list all PEF table entries
*/
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_cfgparm_selector psel;
struct pef_cfgparm_filter_table_entry * pcfg;
uint32_t i;
uint8_t max_filters;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = IPMI_CMD_GET_PEF_CAPABILITIES;
rsp = ipmi_pef_msg_exchange(intf, &req, "PEF capabilities");
if (!rsp
|| (max_filters = ((struct pef_capabilities *)rsp->data)->tblsize) == 0)
return; /* sssh, not supported */
memset(&psel, 0, sizeof(psel));
psel.id = PEF_CFGPARM_ID_PEF_FILTER_TABLE_ENTRY;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS;
req.msg.data = (uint8_t *)&psel;
req.msg.data_len = sizeof(psel);
for (i=1; i<=max_filters; i++) {
if (i > 1)
printf("\n");
psel.set = (i & PEF_FILTER_TABLE_ID_MASK);
rsp = ipmi_pef_msg_exchange(intf, &req, "PEF table entry");
if (!rsp
|| (psel.set != (rsp->data[1] & PEF_FILTER_TABLE_ID_MASK))) {
lprintf(LOG_ERR, " **Error retrieving %s",
"PEF table entry");
continue;
}
pcfg = (struct pef_cfgparm_filter_table_entry *)&rsp->data[1];
first_field = 1;
ipmi_pef_print_entry(rsp, psel.set, pcfg);
}
}
static void
ipmi_pef_list_policies(struct ipmi_intf * intf)
{ /*
// list PEF alert policies
*/
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_cfgparm_policy_table_entry * ptbl = NULL;
struct pef_cfgparm_policy_table_entry * ptmp = NULL;
uint32_t i;
uint8_t wrk, ch, medium, tbl_size;
tbl_size = ipmi_pef_get_policy_table(intf, &ptbl);
if (!tbl_size) {
if (!ptbl) {
free(ptbl);
ptbl = NULL;
}
return;
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_CMD_GET_CHANNEL_INFO;
req.msg.data = &ch;
req.msg.data_len = sizeof(ch);
for (ptmp=ptbl, i=1; i<=tbl_size; i++, ptmp++) {
if ((ptmp->entry.policy & PEF_POLICY_ENABLED) == PEF_POLICY_ENABLED) {
if (i > 1)
printf("\n");
first_field = 1;
ipmi_pef_print_dec("Alert policy table entry",
(ptmp->data1 & PEF_POLICY_TABLE_ID_MASK));
ipmi_pef_print_dec("Policy set",
(ptmp->entry.policy & PEF_POLICY_ID_MASK) >> PEF_POLICY_ID_SHIFT);
ipmi_pef_print_str("Policy entry rule",
ipmi_pef_bit_desc(&pef_b2s_policies, (ptmp->entry.policy & PEF_POLICY_FLAGS_MASK)));
if (ptmp->entry.alert_string_key & PEF_POLICY_EVENT_SPECIFIC) {
ipmi_pef_print_str("Event-specific", "true");
// continue;
}
wrk = ptmp->entry.chan_dest;
/* channel/description */
ch = (wrk & PEF_POLICY_CHANNEL_MASK) >> PEF_POLICY_CHANNEL_SHIFT;
rsp = ipmi_pef_msg_exchange(intf, &req, "Channel info");
if (!rsp || rsp->data[0] != ch) {
lprintf(LOG_ERR, " **Error retrieving %s",
"Channel info");
continue;
}
medium = rsp->data[1];
ipmi_pef_print_dec("Channel number", ch);
ipmi_pef_print_str("Channel medium",
ipmi_pef_bit_desc(&pef_b2s_ch_medium, medium));
/* destination/description */
wrk &= PEF_POLICY_DESTINATION_MASK;
switch (medium) {
case PEF_CH_MEDIUM_TYPE_LAN:
ipmi_pef_print_lan_dest(intf, ch, wrk);
break;
case PEF_CH_MEDIUM_TYPE_SERIAL:
ipmi_pef_print_serial_dest(intf, ch, wrk);
break;
default:
ipmi_pef_print_dest(intf, ch, wrk);
break;
}
}
}
free(ptbl);
ptbl = NULL;
}
static void
ipmi_pef_get_status(struct ipmi_intf * intf)
{ /*
// report the PEF status
*/
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_cfgparm_selector psel;
char tbuf[40];
uint32_t timei;
time_t ts;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = IPMI_CMD_GET_LAST_PROCESSED_EVT_ID;
rsp = ipmi_pef_msg_exchange(intf, &req, "Last S/W processed ID");
if (!rsp) {
lprintf(LOG_ERR, " **Error retrieving %s",
"Last S/W processed ID");
return;
}
memcpy(&timei, rsp->data, sizeof(timei));
#if WORDS_BIGENDIAN
timei = BSWAP_32(timei);
#endif
ts = (time_t)timei;
strftime(tbuf, sizeof(tbuf), "%m/%d/%Y %H:%M:%S", gmtime(&ts));
ipmi_pef_print_str("Last SEL addition", tbuf);
ipmi_pef_print_2xd("Last SEL record ID", rsp->data[5], rsp->data[4]);
ipmi_pef_print_2xd("Last S/W processed ID", rsp->data[7], rsp->data[6]);
ipmi_pef_print_2xd("Last BMC processed ID", rsp->data[9], rsp->data[8]);
memset(&psel, 0, sizeof(psel));
psel.id = PEF_CFGPARM_ID_PEF_CONTROL;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS;
req.msg.data = (uint8_t *)&psel;
req.msg.data_len = sizeof(psel);
rsp = ipmi_pef_msg_exchange(intf, &req, "PEF control");
if (!rsp) {
lprintf(LOG_ERR, " **Error retrieving %s",
"PEF control");
return;
}
ipmi_pef_print_flags(&pef_b2s_control, P_ABLE, rsp->data[1]);
psel.id = PEF_CFGPARM_ID_PEF_ACTION;
rsp = ipmi_pef_msg_exchange(intf, &req, "PEF action");
if (!rsp) {
lprintf(LOG_ERR, " **Error retrieving %s",
"PEF action");
return;
}
ipmi_pef_print_flags(&pef_b2s_actions, P_ACTV, rsp->data[1]);
}
static void
ipmi_pef_get_info(struct ipmi_intf * intf)
{ /*
// report PEF capabilities + System GUID
*/
struct ipmi_rs * rsp;
struct ipmi_rq req;
struct pef_capabilities * pcap;
struct pef_cfgparm_selector psel;
struct pef_cfgparm_policy_table_entry * ptbl = NULL;
uint8_t * uid;
uint8_t actions, tbl_size;
tbl_size = ipmi_pef_get_policy_table(intf, &ptbl);
if (!ptbl) {
free(ptbl);
ptbl = NULL;
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = IPMI_CMD_GET_PEF_CAPABILITIES;
rsp = ipmi_pef_msg_exchange(intf, &req, "PEF capabilities");
if (!rsp)
return;
pcap = (struct pef_capabilities *)rsp->data;
ipmi_pef_print_1xd("Version", pcap->version);
ipmi_pef_print_dec("PEF table size", pcap->tblsize);
ipmi_pef_print_dec("Alert policy table size", tbl_size);
actions = pcap->actions;
memset(&psel, 0, sizeof(psel));
psel.id = PEF_CFGPARM_ID_SYSTEM_GUID;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.cmd = IPMI_CMD_GET_PEF_CONFIG_PARMS;
req.msg.data = (uint8_t *)&psel;
req.msg.data_len = sizeof(psel);
rsp = ipmi_pef_msg_exchange(intf, &req, "System GUID");
uid = NULL;
if (rsp && (rsp->data[1] & PEF_SYSTEM_GUID_USED_IN_PET))
uid = &rsp->data[2];
else {
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = IPMI_CMD_GET_SYSTEM_GUID;
rsp = ipmi_pef_msg_exchange(intf, &req, "System GUID");
if (rsp)
uid = &rsp->data[0];
}
if (uid) { /* got GUID? */
if (verbose)
printf(pef_fld_fmts[F_UID][0], KYWD_LENGTH, "System GUID",
uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7],
uid[8], uid[9], uid[10],uid[11],uid[12],uid[13],uid[14],uid[15]);
else
printf(pef_fld_fmts[F_UID][1],
uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7],
uid[8], uid[9], uid[10],uid[11],uid[12],uid[13],uid[14],uid[15]);
}
ipmi_pef_print_flags(&pef_b2s_actions, P_SUPP, actions);
}
int ipmi_pef_main(struct ipmi_intf * intf, int argc, char ** argv)
{ /*
// PEF subcommand handling
*/
int help = 0;
int rc = 0;
if (!argc || !strncmp(argv[0], "info", 4))
ipmi_pef_get_info(intf);
else if (!strncmp(argv[0], "help", 4))
help = 1;
else if (!strncmp(argv[0], "status", 6))
ipmi_pef_get_status(intf);
else if (!strncmp(argv[0], "policy", 6))
ipmi_pef_list_policies(intf);
else if (!strncmp(argv[0], "list", 4))
ipmi_pef_list_entries(intf);
else {
help = 1;
rc = -1;
lprintf(LOG_ERR, "Invalid PEF command: '%s'\n", argv[0]);
}
if (help)
lprintf(LOG_NOTICE, "PEF commands: info status policy list");
else if (!verbose)
printf("\n");
return rc;
}

2371
lib/ipmi_picmg.c Normal file

File diff suppressed because it is too large Load Diff

432
lib/ipmi_raw.c Normal file
View File

@@ -0,0 +1,432 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/log.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_raw.h>
#include <ipmitool/ipmi_fru.h>
#include <ipmitool/ipmi_strings.h>
#define IPMI_I2C_MASTER_MAX_SIZE 0x40 /* 64 bytes */
static int is_valid_param(const char *input_param, uint8_t *uchr_ptr,
const char *label);
/* ipmi_master_write_read - Perform I2C write/read transactions
*
* This function performs an I2C master write-read function through
* IPMI interface. It has a maximum transfer size of 32 bytes.
*
* @intf: ipmi interface
* @bus: channel number, i2c bus id and type
* @addr: i2c slave address
* @wdata: data to write
* @wsize: length of data to write (max 64 bytes)
* @rsize: length of data to read (max 64 bytes)
*
* Returns pointer to IPMI Response
*/
struct ipmi_rs *
ipmi_master_write_read(struct ipmi_intf * intf, uint8_t bus, uint8_t addr,
uint8_t * wdata, uint8_t wsize, uint8_t rsize)
{
struct ipmi_rq req;
struct ipmi_rs * rsp;
uint8_t rqdata[IPMI_I2C_MASTER_MAX_SIZE + 3];
if (rsize > IPMI_I2C_MASTER_MAX_SIZE) {
lprintf(LOG_ERR, "Master Write-Read: Too many bytes (%d) to read", rsize);
return NULL;
}
if (wsize > IPMI_I2C_MASTER_MAX_SIZE) {
lprintf(LOG_ERR, "Master Write-Read: Too many bytes (%d) to write", wsize);
return NULL;
}
memset(&req, 0, sizeof(struct ipmi_rq));
req.msg.netfn = IPMI_NETFN_APP;
req.msg.cmd = 0x52; /* master write-read */
req.msg.data = rqdata;
req.msg.data_len = 3;
memset(rqdata, 0, IPMI_I2C_MASTER_MAX_SIZE + 3);
rqdata[0] = bus; /* channel number, bus id, bus type */
rqdata[1] = addr; /* slave address */
rqdata[2] = rsize; /* number of bytes to read */
if (wsize > 0) {
/* copy in data to write */
memcpy(rqdata+3, wdata, wsize);
req.msg.data_len += wsize;
lprintf(LOG_DEBUG, "Writing %d bytes to i2cdev %02Xh", wsize, addr);
}
if (rsize > 0) {
lprintf(LOG_DEBUG, "Reading %d bytes from i2cdev %02Xh", rsize, addr);
}
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "I2C Master Write-Read command failed");
return NULL;
}
else if (rsp->ccode > 0) {
switch (rsp->ccode) {
case 0x81:
lprintf(LOG_ERR, "I2C Master Write-Read command failed: Lost Arbitration");
break;
case 0x82:
lprintf(LOG_ERR, "I2C Master Write-Read command failed: Bus Error");
break;
case 0x83:
lprintf(LOG_ERR, "I2C Master Write-Read command failed: NAK on Write");
break;
case 0x84:
lprintf(LOG_ERR, "I2C Master Write-Read command failed: Truncated Read");
break;
default:
lprintf(LOG_ERR, "I2C Master Write-Read command failed: %s",
val2str(rsp->ccode, completion_code_vals));
break;
}
return NULL;
}
return rsp;
}
#define RAW_SPD_SIZE 256
int
ipmi_rawspd_main(struct ipmi_intf * intf, int argc, char ** argv)
{
struct ipmi_rs *rsp;
uint8_t msize = IPMI_I2C_MASTER_MAX_SIZE; /* allow to override default */
uint8_t channel = 0;
uint8_t i2cbus = 0;
uint8_t i2caddr = 0;
uint8_t spd_data[RAW_SPD_SIZE];
int i;
memset(spd_data, 0, RAW_SPD_SIZE);
if (argc < 2 || strncmp(argv[0], "help", 4) == 0) {
lprintf(LOG_NOTICE, "usage: spd <i2cbus> <i2caddr> [channel] [maxread]");
return 0;
}
if (is_valid_param(argv[0], &i2cbus, "i2cbus") != 0)
return (-1);
if (is_valid_param(argv[1], &i2caddr, "i2caddr") != 0)
return (-1);
if (argc >= 3) {
if (is_valid_param(argv[2], &channel, "channel") != 0)
return (-1);
}
if (argc >= 4) {
if (is_valid_param(argv[3], &msize, "maxread") != 0)
return (-1);
}
i2cbus = ((channel & 0xF) << 4) | ((i2cbus & 7) << 1) | 1;
for (i = 0; i < RAW_SPD_SIZE; i+= msize) {
rsp = ipmi_master_write_read(intf, i2cbus, i2caddr,
(uint8_t *)&i, 1, msize );
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
return -1;
}
memcpy(spd_data+i, rsp->data, msize);
}
ipmi_spd_print(spd_data, i);
return 0;
}
static void rawi2c_usage(void)
{
lprintf(LOG_NOTICE, "usage: i2c [bus=public|# [chan=#] <i2caddr> <read bytes> [write data]");
lprintf(LOG_NOTICE, " bus=public is default");
lprintf(LOG_NOTICE, " chan=0 is default, bus= must be specified to use chan=");
}
int
ipmi_rawi2c_main(struct ipmi_intf * intf, int argc, char ** argv)
{
struct ipmi_rs * rsp;
uint8_t wdata[IPMI_I2C_MASTER_MAX_SIZE];
uint8_t i2caddr = 0;
uint8_t rsize = 0;
uint8_t wsize = 0;
unsigned int rbus = 0;
uint8_t bus = 0;
int i = 0;
/* handle bus= argument */
if (argc > 2 && strncmp(argv[0], "bus=", 4) == 0) {
i = 1;
if (strncmp(argv[0], "bus=public", 10) == 0)
bus = 0;
else if (sscanf(argv[0], "bus=%u", &rbus) == 1)
bus = ((rbus & 7) << 1) | 1;
else
bus = 0;
/* handle channel= argument
* the bus= argument must be supplied first on command line */
if (argc > 3 && strncmp(argv[1], "chan=", 5) == 0) {
i = 2;
if (sscanf(argv[1], "chan=%u", &rbus) == 1)
bus |= rbus << 4;
}
}
if ((argc-i) < 2 || strncmp(argv[0], "help", 4) == 0) {
rawi2c_usage();
return 0;
}
else if (argc-i-2 > IPMI_I2C_MASTER_MAX_SIZE) {
lprintf(LOG_ERR, "Raw command input limit (%d bytes) exceeded",
IPMI_I2C_MASTER_MAX_SIZE);
return -1;
}
if (is_valid_param(argv[i++], &i2caddr, "i2caddr") != 0)
return (-1);
if (is_valid_param(argv[i++], &rsize, "read size") != 0)
return (-1);
if (i2caddr == 0) {
lprintf(LOG_ERR, "Invalid I2C address 0");
rawi2c_usage();
return -1;
}
memset(wdata, 0, IPMI_I2C_MASTER_MAX_SIZE);
for (; i < argc; i++) {
uint8_t val = 0;
if (is_valid_param(argv[i], &val, "parameter") != 0)
return (-1);
wdata[wsize] = val;
wsize++;
}
lprintf(LOG_INFO, "RAW I2C REQ (i2caddr=%x readbytes=%d writebytes=%d)",
i2caddr, rsize, wsize);
printbuf(wdata, wsize, "WRITE DATA");
rsp = ipmi_master_write_read(intf, bus, i2caddr, wdata, wsize, rsize);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to perform I2C Master Write-Read");
return -1;
}
if (wsize > 0) {
if (verbose || rsize == 0)
printf("Wrote %d bytes to I2C device %02Xh\n", wsize, i2caddr);
}
if (rsize > 0) {
if (verbose || wsize == 0)
printf("Read %d bytes from I2C device %02Xh\n", rsp->data_len, i2caddr);
if (rsp->data_len < rsize)
return -1;
/* print the raw response buffer */
for (i=0; i<rsp->data_len; i++) {
if (((i%16) == 0) && (i != 0))
printf("\n");
printf(" %2.2x", rsp->data[i]);
}
printf("\n");
if (rsp->data_len <= 4) {
uint32_t bit;
int j;
for (i = 0; i < rsp->data_len; i++) {
for (j = 1, bit = 0x80; bit > 0; bit /= 2, j++) {
printf("%s", (rsp->data[i] & bit) ? "1" : "0");
}
printf(" ");
}
printf("\n");
}
}
return 0;
}
/* ipmi_raw_help() - print 'raw' help text
*
* returns void
*/
void
ipmi_raw_help()
{
lprintf(LOG_NOTICE, "RAW Commands: raw <netfn> <cmd> [data]");
print_valstr(ipmi_netfn_vals, "Network Function Codes", LOG_NOTICE);
lprintf(LOG_NOTICE, "(can also use raw hex values)");
} /* ipmi_raw_help() */
int
ipmi_raw_main(struct ipmi_intf * intf, int argc, char ** argv)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t netfn, cmd, lun;
uint16_t netfn_tmp = 0;
int i;
uint8_t data[256];
if (argc == 1 && strncmp(argv[0], "help", 4) == 0) {
ipmi_raw_help();
return 0;
}
else if (argc < 2) {
lprintf(LOG_ERR, "Not enough parameters given.");
ipmi_raw_help();
return (-1);
}
else if (argc > sizeof(data))
{
lprintf(LOG_NOTICE, "Raw command input limit (256 bytes) exceeded");
return -1;
}
ipmi_intf_session_set_timeout(intf, 15);
ipmi_intf_session_set_retry(intf, 1);
lun = intf->target_lun;
netfn_tmp = str2val(argv[0], ipmi_netfn_vals);
if (netfn_tmp == 0xff) {
if (is_valid_param(argv[0], &netfn, "netfn") != 0)
return (-1);
} else {
if (netfn_tmp >= UINT8_MAX) {
lprintf(LOG_ERR, "Given netfn \"%s\" is out of range.", argv[0]);
return (-1);
}
netfn = netfn_tmp;
}
if (is_valid_param(argv[1], &cmd, "command") != 0)
return (-1);
memset(data, 0, sizeof(data));
memset(&req, 0, sizeof(req));
req.msg.netfn = netfn;
req.msg.lun = lun;
req.msg.cmd = cmd;
req.msg.data = data;
for (i=2; i<argc; i++) {
uint8_t val = 0;
if (is_valid_param(argv[i], &val, "data") != 0)
return (-1);
req.msg.data[i-2] = val;
req.msg.data_len++;
}
lprintf(LOG_INFO,
"RAW REQ (channel=0x%x netfn=0x%x lun=0x%x cmd=0x%x data_len=%d)",
intf->target_channel & 0x0f, req.msg.netfn,req.msg.lun ,
req.msg.cmd, req.msg.data_len);
printbuf(req.msg.data, req.msg.data_len, "RAW REQUEST");
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to send RAW command "
"(channel=0x%x netfn=0x%x lun=0x%x cmd=0x%x)",
intf->target_channel & 0x0f, req.msg.netfn, req.msg.lun, req.msg.cmd);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Unable to send RAW command "
"(channel=0x%x netfn=0x%x lun=0x%x cmd=0x%x rsp=0x%x): %s",
intf->target_channel & 0x0f, req.msg.netfn, req.msg.lun, req.msg.cmd, rsp->ccode,
val2str(rsp->ccode, completion_code_vals));
return -1;
}
lprintf(LOG_INFO, "RAW RSP (%d bytes)", rsp->data_len);
/* print the raw response buffer */
for (i=0; i<rsp->data_len; i++) {
if (((i%16) == 0) && (i != 0))
printf("\n");
printf(" %2.2x", rsp->data[i]);
}
printf("\n");
return 0;
}
/* is_valid_param -
*
* @input_param: string to convert from
* @uchr_ptr: pointer where to store converted value
* @label: string used in error message
*
* returns 0 if parameter is valid
* returns (-1) if parameter is invalid/on error
*/
int
is_valid_param(const char *input_param, uint8_t *uchr_ptr, const char *label) {
if (input_param == NULL || label == NULL) {
lprintf(LOG_ERROR, "ERROR: NULL pointer passed.");
return (-1);
}
if (str2uchar(input_param, uchr_ptr) == 0)
return 0;
lprintf(LOG_ERR, "Given %s \"%s\" is invalid.", label, input_param);
return (-1);
}

4824
lib/ipmi_sdr.c Normal file

File diff suppressed because it is too large Load Diff

668
lib/ipmi_sdradd.c Normal file
View File

@@ -0,0 +1,668 @@
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
/*
* Functions to program the SDR repository, from built-in sensors or
* from sensors dumped in a binary file.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <fcntl.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/bswap.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_mc.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_sdr.h>
#define ADD_PARTIAL_SDR 0x25
#ifdef HAVE_PRAGMA_PACK
#pragma pack(1)
#endif
struct sdr_add_rq {
uint16_t reserve_id; /* reservation ID */
uint16_t id; /* record ID */
uint8_t offset; /* offset into SDR */
uint8_t in_progress; /* 0=partial, 1=last */
#define PARTIAL_ADD (0)
#define LAST_RECORD (1)
uint8_t data[1]; /* SDR record data */
} ATTRIBUTE_PACKING;
#ifdef HAVE_PRAGMA_PACK
#pragma pack(0)
#endif
/* This was formerly initialized to 24, reduced this to 19 so the overall
message fits into the recommended 32-byte limit */
static int sdr_max_write_len = 19;
int ipmi_parse_range_list(const char *rangeList, unsigned char *pHexList);
int ipmi_hex_to_dec( char * rangeList, unsigned char * pDecValue);
static int
partial_send(struct ipmi_intf *intf, struct ipmi_rq *req, uint16_t *id)
{
struct ipmi_rs *rsp;
rsp = intf->sendrecv(intf, req);
if (rsp == NULL) {
return -1;
}
if (rsp->ccode || rsp->data_len < 2) {
return -1;
}
*id = rsp->data[0] + (rsp->data[1] << 8);
return 0;
}
int
ipmi_sdr_add_record(struct ipmi_intf *intf, struct sdr_record_list *sdrr)
{
struct ipmi_rq req;
struct sdr_add_rq *sdr_rq;
uint16_t reserve_id;
uint16_t id;
int i;
int len = sdrr->length;
int rc = 0;
/* actually no SDR to program */
if (len < 1 || !sdrr->raw) {
lprintf(LOG_ERR, "ipmitool: bad record , skipped");
return 0;
}
if (ipmi_sdr_get_reservation(intf, 0, &reserve_id)) {
lprintf(LOG_ERR, "ipmitool: reservation failed");
return -1;
}
sdr_rq = (struct sdr_add_rq *)malloc(sizeof(*sdr_rq) + sdr_max_write_len);
if (sdr_rq == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return -1;
}
sdr_rq->reserve_id = reserve_id;
sdr_rq->in_progress = PARTIAL_ADD;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = ADD_PARTIAL_SDR;
req.msg.data = (uint8_t *) sdr_rq;
/* header first */
sdr_rq->id = 0;
sdr_rq->offset = 0;
sdr_rq->data[0] = sdrr->id & 0xFF;
sdr_rq->data[1] = (sdrr->id >> 8) & 0xFF;
sdr_rq->data[2] = sdrr->version;
sdr_rq->data[3] = sdrr->type;
sdr_rq->data[4] = sdrr->length;
req.msg.data_len = 5 + sizeof(*sdr_rq) - 1;
if (partial_send(intf, &req, &id)) {
lprintf(LOG_ERR, "ipmitool: partial send error");
free(sdr_rq);
sdr_rq = NULL;
return -1;
}
i = 0;
/* sdr entry */
while (i < len) {
int data_len = 0;
if ( (len - i) <= sdr_max_write_len) {
/* last crunch */
data_len = len - i;
sdr_rq->in_progress = LAST_RECORD;
} else {
data_len = sdr_max_write_len;
}
sdr_rq->id = id;
sdr_rq->offset = i + 5;
memcpy(sdr_rq->data, sdrr->raw + i, data_len);
req.msg.data_len = data_len + sizeof(*sdr_rq) - 1;
if ((rc = partial_send(intf, &req, &id)) != 0) {
lprintf(LOG_ERR, "ipmitool: partial add failed");
break;
}
i += data_len;
}
free(sdr_rq);
sdr_rq = NULL;
return rc;
}
static int
ipmi_sdr_repo_clear(struct ipmi_intf *intf)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[8];
uint16_t reserve_id;
int try;
if (ipmi_sdr_get_reservation(intf, 0, &reserve_id))
return -1;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_STORAGE;
req.msg.cmd = 0x27; // FIXME
req.msg.data = msg_data;
req.msg.data_len = 6;
msg_data[0] = reserve_id & 0xFF;
msg_data[1] = reserve_id >> 8;
msg_data[2] = 'C';
msg_data[3] = 'L';
msg_data[4] = 'R';
msg_data[5] = 0xAA;
for (try = 0; try < 5; try++) {
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to clear SDRR");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Unable to clear SDRR: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
if ((rsp->data[0] & 1) == 1) {
printf("SDRR successfully erased\n");
return 0;
}
printf("Wait for SDRR erasure completed...\n");
msg_data[5] = 0;
sleep(1);
}
/* if we are here we fed up trying erase */
return -1;
}
struct sdrr_queue {
struct sdr_record_list *head;
struct sdr_record_list *tail;
};
/*
* Fill the SDR repository from built-in sensors
*
*/
/*
* Get all the SDR records stored in <queue>
*/
static int
sdrr_get_records(struct ipmi_intf *intf, struct ipmi_sdr_iterator *itr,
struct sdrr_queue *queue)
{
struct sdr_get_rs *header;
queue->head = NULL;
queue->tail = NULL;
while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) {
struct sdr_record_list *sdrr;
sdrr = malloc(sizeof (struct sdr_record_list));
if (sdrr == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return -1;
}
memset(sdrr, 0, sizeof (struct sdr_record_list));
sdrr->id = header->id;
sdrr->version = header->version;
sdrr->type = header->type;
sdrr->length = header->length;
sdrr->raw = ipmi_sdr_get_record(intf, header, itr);
(void)ipmi_sdr_print_name_from_rawentry(intf, sdrr->id, sdrr->type,sdrr->raw);
/* put in the record queue */
if (queue->head == NULL)
queue->head = sdrr;
else
queue->tail->next = sdrr;
queue->tail = sdrr;
}
return 0;
}
static int
sdr_copy_to_sdrr(struct ipmi_intf *intf, int use_builtin,
int from_addr, int to_addr)
{
int rc;
struct sdrr_queue sdrr_queue;
struct ipmi_sdr_iterator *itr;
struct sdr_record_list *sdrr;
struct sdr_record_list *sdrr_next;
/* generate list of records for this target */
intf->target_addr = from_addr;
/* initialize iterator */
itr = ipmi_sdr_start(intf, use_builtin);
if (itr == 0)
return 0;
printf("Load SDRs from 0x%x\n", from_addr);
rc = sdrr_get_records(intf, itr, &sdrr_queue);
ipmi_sdr_end(intf, itr);
/* ... */
/* write the SDRs to the destination SDR Repository */
intf->target_addr = to_addr;
for (sdrr = sdrr_queue.head; sdrr != NULL; sdrr = sdrr_next) {
sdrr_next = sdrr->next;
rc = ipmi_sdr_add_record(intf, sdrr);
if(rc < 0){
lprintf(LOG_ERR, "Cannot add SDR ID 0x%04x to repository...", sdrr->id);
}
free(sdrr);
sdrr = NULL;
}
return rc;
}
int
ipmi_sdr_add_from_sensors(struct ipmi_intf *intf, int maxslot)
{
int i;
int rc = 0;
int slave_addr;
int myaddr = intf->target_addr;
if (ipmi_sdr_repo_clear(intf)) {
lprintf(LOG_ERR, "Cannot erase SDRR. Give up.");
return -1;
}
/* First fill the SDRR from local built-in sensors */
rc = sdr_copy_to_sdrr(intf, 1, myaddr, myaddr);
/* Now fill the SDRR with remote sensors */
if( maxslot != 0 ) {
for (i = 0, slave_addr = 0xB0; i < maxslot; i++, slave_addr += 2) {
/* Hole in the PICMG 2.9 mapping */
if (slave_addr == 0xC2) slave_addr += 2;
if(sdr_copy_to_sdrr(intf, 0, slave_addr, myaddr) < 0)
{
rc = -1;
}
}
}
return rc;
}
int ipmi_hex_to_dec( char * strchar, unsigned char * pDecValue)
{
int rc = -1;
unsigned char retValue = 0;
if(
(strlen(strchar) == 4)
&&
(strchar[0] == '0')
&&
(strchar[1] == 'x')
)
{
rc = 0;
if((strchar[2] >= '0') && (strchar[2] <= '9'))
{
retValue += ((strchar[2]-'0') * 16);
}
else if((strchar[2] >= 'a') && (strchar[2] <= 'f'))
{
retValue += (((strchar[2]-'a') + 10) * 16);
}
else if((strchar[2] >= 'A') && (strchar[2] <= 'F'))
{
retValue += (((strchar[2]-'A') + 10) * 16);
}
else
{
rc = -1;
}
if((strchar[3] >= '0') && (strchar[3] <= '9'))
{
retValue += ((strchar[3]-'0'));
}
else if((strchar[3] >= 'a') && (strchar[3] <= 'f'))
{
retValue += (((strchar[3]-'a') + 10));
}
else if((strchar[3] >= 'A') && (strchar[3] <= 'F'))
{
retValue += (((strchar[3]-'A') + 10));
}
else
{
rc = -1;
}
}
if(rc == 0)
{
* pDecValue = retValue;
}
else
{
lprintf(LOG_ERR, "Must be Hex value of 4 characters (Ex.: 0x24)");
}
return rc;
}
#define MAX_NUM_SLOT 128
int ipmi_parse_range_list(const char *rangeList, unsigned char * pHexList)
{
int rc = -1;
unsigned char listOffset = 0;
char * nextString;
char * rangeString;
char * inProcessString = (char *) rangeList;
/* Discard empty string */
if(strlen(rangeList) == 0)
{
return rc;
}
/* First, cut to comma separated string */
nextString = strstr( rangeList, "," );
if(nextString != rangeList)
{
unsigned char isLast;
/* We get a valid string so far */
rc = 0;
do
{
if(nextString != NULL)
{
(*nextString)= 0;
nextString ++;
isLast = 0;
}
else
{
isLast = 1;
}
/* At this point, it is a single entry or a range */
rangeString = strstr( inProcessString, "-" );
if(rangeString == NULL)
{
unsigned char decValue = 0;
/* Single entry */
rc = ipmi_hex_to_dec( inProcessString, &decValue);
if(rc == 0)
{
if((decValue % 2) == 0)
{
pHexList[listOffset++] = decValue;
}
else
{
lprintf(LOG_ERR, "I2C address provided value must be even.");
}
}
}
else
{
unsigned char startValue = 0;
unsigned char endValue = 0;
(*rangeString)= 0; /* Cut string*/
rangeString ++;
/* Range */
rc = ipmi_hex_to_dec( inProcessString, &startValue);
if(rc == 0)
rc = ipmi_hex_to_dec( rangeString, &endValue);
if(rc == 0)
{
if(((startValue % 2) == 0) && ((endValue % 2) == 0))
{
do
{
pHexList[listOffset++] = startValue;
startValue += 2;
}
while(startValue != endValue);
pHexList[listOffset++] = endValue;
}
else
{
lprintf(LOG_ERR, "I2C address provided value must be even.");
}
}
}
if(isLast == 0)
{
/* Setup for next string */
inProcessString = nextString;
nextString = strstr( rangeList, "," );
}
}while ((isLast == 0) && (rc == 0));
}
return rc;
}
int
ipmi_sdr_add_from_list(struct ipmi_intf *intf, const char *rangeList)
{
int i;
int rc = 0;
int slave_addr;
int myaddr = intf->target_addr;
unsigned char listValue[MAX_NUM_SLOT];
memset( listValue, 0, MAX_NUM_SLOT );
/* Build list from string */
if(ipmi_parse_range_list(rangeList, listValue) != 0)
{
lprintf(LOG_ERR, "Range - List invalid, cannot be parsed.");
return -1;
}
{
unsigned char counter = 0;
printf("List to scan: (Built-in) ");
while(listValue[counter] != 0)
{
printf("%02x ", listValue[counter]);
counter++;
}
printf("\n");
}
printf("Clearing SDR Repository\n");
if (ipmi_sdr_repo_clear(intf)) {
lprintf(LOG_ERR, "Cannot erase SDRR. Give up.");
return -1;
}
/* First fill the SDRR from local built-in sensors */
printf("Sanning built-in sensors..\n");
rc = sdr_copy_to_sdrr(intf, 1, myaddr, myaddr);
/* Now fill the SDRR with provided sensors list */
{
unsigned char counter = 0;
while((rc == 0) && (listValue[counter] != 0))
{
slave_addr = listValue[counter];
printf("Scanning %02Xh..\n", slave_addr);
if(sdr_copy_to_sdrr(intf, 0, slave_addr, myaddr) < 0)
{
rc = -1;
}
counter++;
}
}
return rc;
}
/*
* Fill the SDR repository from records stored in a binary file
*
*/
static int
ipmi_sdr_read_records(const char *filename, struct sdrr_queue *queue)
{
struct sdr_get_rs header;
int rc = 0;
int fd;
uint8_t binHdr[5];
queue->head = NULL;
queue->tail = NULL;
if ((fd = open(filename, O_RDONLY)) < 0) {
return -1;
}
while (read(fd, binHdr, 5) == 5) {
struct sdr_record_list *sdrr;
lprintf(LOG_DEBUG, "binHdr[0] (id[MSB]) = 0x%02x", binHdr[0]);
lprintf(LOG_DEBUG, "binHdr[1] (id[LSB]) = 0x%02x", binHdr[1]);
lprintf(LOG_DEBUG, "binHdr[2] (version) = 0x%02x", binHdr[2]);
lprintf(LOG_DEBUG, "binHdr[3] (type) = 0x%02x", binHdr[3]);
lprintf(LOG_DEBUG, "binHdr[4] (length) = 0x%02x", binHdr[4]);
sdrr = malloc(sizeof(*sdrr));
if (sdrr == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
rc = -1;
break;
}
sdrr->id = (binHdr[1] << 8) | binHdr[0]; // LS Byte first
sdrr->version = binHdr[2];
sdrr->type = binHdr[3];
sdrr->length = binHdr[4];
if ((sdrr->raw = malloc(sdrr->length)) == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
free(sdrr);
sdrr = NULL;
rc = -1;
break;
}
if (read(fd, sdrr->raw, sdrr->length) != sdrr->length) {
lprintf(LOG_ERR, "SDR from '%s' truncated", filename);
free(sdrr->raw);
sdrr->raw = NULL;
free(sdrr);
sdrr = NULL;
rc = -1;
break;
}
/* put in the record queue */
if (queue->head == NULL)
queue->head = sdrr;
else
queue->tail->next = sdrr;
queue->tail = sdrr;
}
return rc;
}
int
ipmi_sdr_add_from_file(struct ipmi_intf *intf, const char *ifile)
{
int rc;
struct sdrr_queue sdrr_queue;
struct sdr_record_list *sdrr;
struct sdr_record_list *sdrr_next;
/* read the SDR records from file */
rc = ipmi_sdr_read_records(ifile, &sdrr_queue);
if (ipmi_sdr_repo_clear(intf)) {
lprintf(LOG_ERR, "Cannot erase SDRR. Giving up.");
/* FIXME: free sdr list */
return -1;
}
/* write the SDRs to the SDR Repository */
for (sdrr = sdrr_queue.head; sdrr != NULL; sdrr = sdrr_next) {
sdrr_next = sdrr->next;
rc = ipmi_sdr_add_record(intf, sdrr);
if(rc < 0){
lprintf(LOG_ERR, "Cannot add SDR ID 0x%04x to repository...", sdrr->id);
}
free(sdrr);
sdrr = NULL;
}
return rc;
}

3090
lib/ipmi_sel.c Normal file

File diff suppressed because it is too large Load Diff

964
lib/ipmi_sensor.c Normal file
View File

@@ -0,0 +1,964 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <string.h>
#include <math.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/ipmi_sel.h>
#include <ipmitool/ipmi_sensor.h>
extern int verbose;
void printf_sensor_get_usage();
// Macro's for Reading the current sensor Data.
#define SCANNING_DISABLED 0x40
#define READING_UNAVAILABLE 0x20
#define INVALID_THRESHOLD "Invalid Threshold data values. Cannot Set Threshold Data."
// static
int
ipmi_sensor_get_sensor_reading_factors(
struct ipmi_intf * intf,
struct sdr_record_full_sensor * sensor,
uint8_t reading)
{
struct ipmi_rq req;
struct ipmi_rs * rsp;
uint8_t req_data[2];
char id[17];
if (intf == NULL || sensor == NULL)
return -1;
memset(id, 0, sizeof(id));
memcpy(id, sensor->id_string, 16);
req_data[0] = sensor->cmn.keys.sensor_num;
req_data[1] = reading;
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.lun = sensor->cmn.keys.lun;
req.msg.cmd = GET_SENSOR_FACTORS;
req.msg.data = req_data;
req.msg.data_len = sizeof(req_data);
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Error updating reading factor for sensor %s (#%02x)",
id, sensor->cmn.keys.sensor_num);
return -1;
} else if (rsp->ccode) {
return -1;
} else {
/* Update SDR copy with updated Reading Factors for this reading */
/* Note:
* The Format of the returned data is exactly as in the SDR definition (Little Endian Format),
* therefore we can use raw copy operation here.
* Note: rsp->data[0] would point to the next valid entry in the sampling table
*/
// BUGBUG: uses 'hardcoded' length information from SDR Definition
memcpy(&sensor->mtol, &rsp->data[1], sizeof(sensor->mtol));
memcpy(&sensor->bacc, &rsp->data[3], sizeof(sensor->bacc));
return 0;
}
}
static
struct ipmi_rs *
ipmi_sensor_set_sensor_thresholds(struct ipmi_intf *intf,
uint8_t sensor,
uint8_t threshold, uint8_t setting,
uint8_t target, uint8_t lun, uint8_t channel)
{
struct ipmi_rq req;
static struct sensor_set_thresh_rq set_thresh_rq;
struct ipmi_rs *rsp;
uint8_t bridged_request = 0;
uint32_t save_addr;
uint32_t save_channel;
memset(&set_thresh_rq, 0, sizeof (set_thresh_rq));
set_thresh_rq.sensor_num = sensor;
set_thresh_rq.set_mask = threshold;
if (threshold == UPPER_NON_RECOV_SPECIFIED)
set_thresh_rq.upper_non_recov = setting;
else if (threshold == UPPER_CRIT_SPECIFIED)
set_thresh_rq.upper_crit = setting;
else if (threshold == UPPER_NON_CRIT_SPECIFIED)
set_thresh_rq.upper_non_crit = setting;
else if (threshold == LOWER_NON_CRIT_SPECIFIED)
set_thresh_rq.lower_non_crit = setting;
else if (threshold == LOWER_CRIT_SPECIFIED)
set_thresh_rq.lower_crit = setting;
else if (threshold == LOWER_NON_RECOV_SPECIFIED)
set_thresh_rq.lower_non_recov = setting;
else
return NULL;
if (BRIDGE_TO_SENSOR(intf, target, channel)) {
bridged_request = 1;
save_addr = intf->target_addr;
intf->target_addr = target;
save_channel = intf->target_channel;
intf->target_channel = channel;
}
memset(&req, 0, sizeof (req));
req.msg.netfn = IPMI_NETFN_SE;
req.msg.lun = lun;
req.msg.cmd = SET_SENSOR_THRESHOLDS;
req.msg.data = (uint8_t *) & set_thresh_rq;
req.msg.data_len = sizeof (set_thresh_rq);
rsp = intf->sendrecv(intf, &req);
if (bridged_request) {
intf->target_addr = save_addr;
intf->target_channel = save_channel;
}
return rsp;
}
static int
ipmi_sensor_print_fc_discrete(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
uint8_t sdr_record_type)
{
const char *id;
struct sensor_reading *sr;
sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
if (sr == NULL) {
return -1;
}
if (csv_output) {
/* NOT IMPLEMENTED */
} else {
if (verbose == 0) {
/* output format
* id value units status thresholds....
*/
printf("%-16s ", sr->s_id);
if (sr->s_reading_valid) {
if (sr->s_has_analog_value) {
/* don't show discrete component */
printf("| %-10s | %-10s | %-6s",
sr->s_a_str, sr->s_a_units, "ok");
} else {
printf("| 0x%-8x | %-10s | 0x%02x%02x",
sr->s_reading, "discrete",
sr->s_data2, sr->s_data3);
}
} else {
printf("| %-10s | %-10s | %-6s",
"na", "discrete", "na");
}
printf("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
"na", "na", "na", "na", "na", "na");
printf("\n");
} else {
printf("Sensor ID : %s (0x%x)\n",
sr->s_id, sensor->keys.sensor_num);
printf(" Entity ID : %d.%d\n",
sensor->entity.id, sensor->entity.instance);
printf(" Sensor Type (Discrete): %s\n",
ipmi_sdr_get_sensor_type_desc(sensor->sensor.
type));
if( sr->s_reading_valid )
{
if (sr->s_has_analog_value) {
printf(" Sensor Reading : %s %s\n", sr->s_a_str, sr->s_a_units);
}
ipmi_sdr_print_discrete_state("States Asserted",
sensor->sensor.type,
sensor->event_type,
sr->s_data2,
sr->s_data3);
printf("\n");
} else {
printf(" Unable to read sensor: Device Not Present\n\n");
}
}
}
return (sr->s_reading_valid ? 0 : -1 );
}
static void
print_thresh_setting(struct sdr_record_full_sensor *full,
uint8_t thresh_is_avail, uint8_t setting,
const char *field_sep,
const char *analog_fmt,
const char *discrete_fmt,
const char *na_fmt)
{
printf("%s", field_sep);
if (!thresh_is_avail) {
printf(na_fmt, "na");
return;
}
if (full && !UNITS_ARE_DISCRETE(&full->cmn)) {
printf(analog_fmt, sdr_convert_sensor_reading (full, setting));
} else {
printf(discrete_fmt, setting);
}
}
static int
ipmi_sensor_print_fc_threshold(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
uint8_t sdr_record_type)
{
int thresh_available = 1;
struct ipmi_rs *rsp;
struct sensor_reading *sr;
sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 3);
if (sr == NULL) {
return -1;
}
const char *thresh_status = ipmi_sdr_get_thresh_status(sr, "ns");
/*
* Get sensor thresholds
*/
rsp = ipmi_sdr_get_sensor_thresholds(intf,
sensor->keys.sensor_num, sensor->keys.owner_id,
sensor->keys.lun, sensor->keys.channel);
if ((rsp == NULL) || (rsp->ccode > 0) || (rsp->data_len == 0))
thresh_available = 0;
if (csv_output) {
/* NOT IMPLEMENTED */
} else {
if (verbose == 0) {
/* output format
* id value units status thresholds....
*/
printf("%-16s ", sr->s_id);
if (sr->s_reading_valid) {
if (sr->s_has_analog_value)
printf("| %-10.3f | %-10s | %-6s",
sr->s_a_val, sr->s_a_units, thresh_status);
else
printf("| 0x%-8x | %-10s | %-6s",
sr->s_reading, sr->s_a_units, thresh_status);
} else {
printf("| %-10s | %-10s | %-6s",
"na", sr->s_a_units, "na");
}
if (thresh_available && sr->full) {
#define PTS(bit, dataidx) { \
print_thresh_setting(sr->full, rsp->data[0] & (bit), \
rsp->data[(dataidx)], "| ", "%-10.3f", "0x-8x", "%-10s"); \
}
PTS(LOWER_NON_RECOV_SPECIFIED, 3);
PTS(LOWER_CRIT_SPECIFIED, 2);
PTS(LOWER_NON_CRIT_SPECIFIED, 1);
PTS(UPPER_NON_CRIT_SPECIFIED, 4);
PTS(UPPER_CRIT_SPECIFIED, 5);
PTS(UPPER_NON_RECOV_SPECIFIED, 6);
#undef PTS
} else {
printf
("| %-10s| %-10s| %-10s| %-10s| %-10s| %-10s",
"na", "na", "na", "na", "na", "na");
}
printf("\n");
} else {
printf("Sensor ID : %s (0x%x)\n",
sr->s_id, sensor->keys.sensor_num);
printf(" Entity ID : %d.%d\n",
sensor->entity.id, sensor->entity.instance);
printf(" Sensor Type (Threshold) : %s\n",
ipmi_sdr_get_sensor_type_desc(sensor->sensor.
type));
printf(" Sensor Reading : ");
if (sr->s_reading_valid) {
if (sr->full) {
uint16_t raw_tol = __TO_TOL(sr->full->mtol);
if (sr->s_has_analog_value) {
double tol =
sdr_convert_sensor_tolerance(sr->full,
raw_tol);
printf("%.*f (+/- %.*f) %s\n",
(sr->s_a_val == (int)
sr->s_a_val) ? 0 : 3,
sr->s_a_val,
(tol == (int) tol) ? 0 : 3, tol,
sr->s_a_units);
} else {
printf("0x%x (+/- 0x%x) %s\n",
sr->s_reading,
raw_tol,
sr->s_a_units);
}
} else {
printf("0x%x %s\n", sr->s_reading,
sr->s_a_units);
}
printf(" Status : %s\n", thresh_status);
if (thresh_available) {
if (sr->full) {
#define PTS(bit, dataidx, str) { \
print_thresh_setting(sr->full, rsp->data[0] & (bit), \
rsp->data[(dataidx)], \
(str), "%.3f\n", "0x%x\n", "%s\n"); \
}
PTS(LOWER_NON_RECOV_SPECIFIED, 3, " Lower Non-Recoverable : ");
PTS(LOWER_CRIT_SPECIFIED, 2, " Lower Critical : ");
PTS(LOWER_NON_CRIT_SPECIFIED, 1, " Lower Non-Critical : ");
PTS(UPPER_NON_CRIT_SPECIFIED, 4, " Upper Non-Critical : ");
PTS(UPPER_CRIT_SPECIFIED, 5, " Upper Critical : ");
PTS(UPPER_NON_RECOV_SPECIFIED, 6, " Upper Non-Recoverable : ");
#undef PTS
}
ipmi_sdr_print_sensor_hysteresis(sensor, sr->full,
sr->full ? sr->full->threshold.hysteresis.positive :
sr->compact->threshold.hysteresis.positive,
"Positive Hysteresis");
ipmi_sdr_print_sensor_hysteresis(sensor, sr->full,
sr->full ? sr->full->threshold.hysteresis.negative :
sr->compact->threshold.hysteresis.negative,
"Negative Hysteresis");
} else {
printf(" Sensor Threshold Settings not available\n");
}
} else {
printf(" Unable to read sensor: Device Not Present\n\n");
}
ipmi_sdr_print_sensor_event_status(intf,
sensor->keys.
sensor_num,
sensor->sensor.type,
sensor->event_type,
ANALOG_SENSOR,
sensor->keys.owner_id,
sensor->keys.lun,
sensor->keys.channel);
ipmi_sdr_print_sensor_event_enable(intf,
sensor->keys.
sensor_num,
sensor->sensor.type,
sensor->event_type,
ANALOG_SENSOR,
sensor->keys.owner_id,
sensor->keys.lun,
sensor->keys.channel);
printf("\n");
}
}
return (sr->s_reading_valid ? 0 : -1 );
}
int
ipmi_sensor_print_fc(struct ipmi_intf *intf,
struct sdr_record_common_sensor *sensor,
uint8_t sdr_record_type)
{
if (IS_THRESHOLD_SENSOR(sensor))
return ipmi_sensor_print_fc_threshold(intf, sensor, sdr_record_type);
else
return ipmi_sensor_print_fc_discrete(intf, sensor, sdr_record_type);
}
static int
ipmi_sensor_list(struct ipmi_intf *intf)
{
struct sdr_get_rs *header;
struct ipmi_sdr_iterator *itr;
int rc = 0;
lprintf(LOG_DEBUG, "Querying SDR for sensor list");
itr = ipmi_sdr_start(intf, 0);
if (itr == NULL) {
lprintf(LOG_ERR, "Unable to open SDR for reading");
return -1;
}
while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) {
uint8_t *rec;
rec = ipmi_sdr_get_record(intf, header, itr);
if (rec == NULL) {
lprintf(LOG_DEBUG, "rec == NULL");
continue;
}
switch (header->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
case SDR_RECORD_TYPE_COMPACT_SENSOR:
ipmi_sensor_print_fc(intf,
(struct
sdr_record_common_sensor *)
rec,
header->type);
break;
}
free(rec);
rec = NULL;
/* fix for CR6604909: */
/* mask failure of individual reads in sensor list command */
/* rc = (r == 0) ? rc : r; */
}
ipmi_sdr_end(intf, itr);
return rc;
}
static const struct valstr threshold_vals[] = {
{UPPER_NON_RECOV_SPECIFIED, "Upper Non-Recoverable"},
{UPPER_CRIT_SPECIFIED, "Upper Critical"},
{UPPER_NON_CRIT_SPECIFIED, "Upper Non-Critical"},
{LOWER_NON_RECOV_SPECIFIED, "Lower Non-Recoverable"},
{LOWER_CRIT_SPECIFIED, "Lower Critical"},
{LOWER_NON_CRIT_SPECIFIED, "Lower Non-Critical"},
{0x00, NULL},
};
static int
__ipmi_sensor_set_threshold(struct ipmi_intf *intf,
uint8_t num, uint8_t mask, uint8_t setting,
uint8_t target, uint8_t lun, uint8_t channel)
{
struct ipmi_rs *rsp;
rsp = ipmi_sensor_set_sensor_thresholds(intf, num, mask, setting,
target, lun, channel);
if (rsp == NULL) {
lprintf(LOG_ERR, "Error setting threshold");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Error setting threshold: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
return 0;
}
static uint8_t
__ipmi_sensor_threshold_value_to_raw(struct sdr_record_full_sensor *full, double value)
{
if (!UNITS_ARE_DISCRETE(&full->cmn)) { /* Has an analog reading */
/* Has an analog reading and supports mx+b */
return sdr_convert_sensor_value_to_raw(full, value);
}
else {
/* Does not have an analog reading and/or does not support mx+b */
if (value > 255) {
return 255;
}
else if (value < 0) {
return 0;
}
else {
return (uint8_t )value;
}
}
}
static int
ipmi_sensor_set_threshold(struct ipmi_intf *intf, int argc, char **argv)
{
char *id, *thresh;
uint8_t settingMask = 0;
double setting1 = 0.0, setting2 = 0.0, setting3 = 0.0;
int allUpper = 0, allLower = 0;
int ret = 0;
struct ipmi_rs *rsp;
int i =0;
double val[10] = {0};
struct sdr_record_list *sdr;
if (argc < 3 || strncmp(argv[0], "help", 4) == 0) {
lprintf(LOG_NOTICE, "sensor thresh <id> <threshold> <setting>");
lprintf(LOG_NOTICE,
" id : name of the sensor for which threshold is to be set");
lprintf(LOG_NOTICE, " threshold : which threshold to set");
lprintf(LOG_NOTICE,
" unr = upper non-recoverable");
lprintf(LOG_NOTICE, " ucr = upper critical");
lprintf(LOG_NOTICE,
" unc = upper non-critical");
lprintf(LOG_NOTICE,
" lnc = lower non-critical");
lprintf(LOG_NOTICE, " lcr = lower critical");
lprintf(LOG_NOTICE,
" lnr = lower non-recoverable");
lprintf(LOG_NOTICE,
" setting : the value to set the threshold to");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE,
"sensor thresh <id> lower <lnr> <lcr> <lnc>");
lprintf(LOG_NOTICE,
" Set all lower thresholds at the same time");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE,
"sensor thresh <id> upper <unc> <ucr> <unr>");
lprintf(LOG_NOTICE,
" Set all upper thresholds at the same time");
lprintf(LOG_NOTICE, "");
return 0;
}
id = argv[0];
thresh = argv[1];
if (strncmp(thresh, "upper", 5) == 0) {
if (argc < 5) {
lprintf(LOG_ERR,
"usage: sensor thresh <id> upper <unc> <ucr> <unr>");
return -1;
}
allUpper = 1;
if (str2double(argv[2], &setting1) != 0) {
lprintf(LOG_ERR, "Given unc '%s' is invalid.",
argv[2]);
return (-1);
}
if (str2double(argv[3], &setting2) != 0) {
lprintf(LOG_ERR, "Given ucr '%s' is invalid.",
argv[3]);
return (-1);
}
if (str2double(argv[4], &setting3) != 0) {
lprintf(LOG_ERR, "Given unr '%s' is invalid.",
argv[4]);
return (-1);
}
} else if (strncmp(thresh, "lower", 5) == 0) {
if (argc < 5) {
lprintf(LOG_ERR,
"usage: sensor thresh <id> lower <unc> <ucr> <unr>");
return -1;
}
allLower = 1;
if (str2double(argv[2], &setting1) != 0) {
lprintf(LOG_ERR, "Given lnc '%s' is invalid.",
argv[2]);
return (-1);
}
if (str2double(argv[3], &setting2) != 0) {
lprintf(LOG_ERR, "Given lcr '%s' is invalid.",
argv[3]);
return (-1);
}
if (str2double(argv[4], &setting3) != 0) {
lprintf(LOG_ERR, "Given lnr '%s' is invalid.",
argv[4]);
return (-1);
}
} else {
if (strncmp(thresh, "unr", 3) == 0)
settingMask = UPPER_NON_RECOV_SPECIFIED;
else if (strncmp(thresh, "ucr", 3) == 0)
settingMask = UPPER_CRIT_SPECIFIED;
else if (strncmp(thresh, "unc", 3) == 0)
settingMask = UPPER_NON_CRIT_SPECIFIED;
else if (strncmp(thresh, "lnc", 3) == 0)
settingMask = LOWER_NON_CRIT_SPECIFIED;
else if (strncmp(thresh, "lcr", 3) == 0)
settingMask = LOWER_CRIT_SPECIFIED;
else if (strncmp(thresh, "lnr", 3) == 0)
settingMask = LOWER_NON_RECOV_SPECIFIED;
else {
lprintf(LOG_ERR,
"Valid threshold '%s' for sensor '%s' not specified!",
thresh, id);
return -1;
}
if (str2double(argv[2], &setting1) != 0) {
lprintf(LOG_ERR,
"Given %s threshold value '%s' is invalid.",
thresh, argv[2]);
return (-1);
}
}
printf("Locating sensor record '%s'...\n", id);
/* lookup by sensor name */
sdr = ipmi_sdr_find_sdr_byid(intf, id);
if (sdr == NULL) {
lprintf(LOG_ERR, "Sensor data record not found!");
return -1;
}
if (sdr->type != SDR_RECORD_TYPE_FULL_SENSOR) {
lprintf(LOG_ERR, "Invalid sensor type %02x", sdr->type);
return -1;
}
if (!IS_THRESHOLD_SENSOR(sdr->record.common)) {
lprintf(LOG_ERR, "Invalid sensor event type %02x", sdr->record.common->event_type);
return -1;
}
if (allUpper) {
settingMask = UPPER_NON_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting1);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
settingMask = UPPER_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting2);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
settingMask = UPPER_NON_RECOV_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting3);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
} else if (allLower) {
settingMask = LOWER_NON_RECOV_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting1);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
settingMask = LOWER_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting2);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting2),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
settingMask = LOWER_NON_CRIT_SPECIFIED;
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting3);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting3),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
} else {
/*
* Current implementation doesn't check for the valid setting of upper non critical and other thresholds.
* In the below logic:
* Get all the current reading of the sensor i.e. unc, uc, lc,lnc.
* Validate the values given by the user.
* If the values are not correct, then popup with the Error message and return.
*/
/*
* Get current reading
*/
rsp = ipmi_sdr_get_sensor_reading_ipmb(intf,
sdr->record.common->keys.sensor_num,
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,sdr->record.common->keys.channel);
rsp = ipmi_sdr_get_sensor_thresholds(intf,
sdr->record.common->keys.sensor_num,
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
if ((rsp == NULL) || (rsp->ccode > 0)) {
lprintf(LOG_ERR, "Sensor data record not found!");
return -1;
}
for(i=1;i<=6;i++) {
val[i] = sdr_convert_sensor_reading(sdr->record.full, rsp->data[i]);
if(val[i] < 0)
val[i] = 0;
}
/* Check for the valid Upper non recovarable Value.*/
if( (settingMask & UPPER_NON_RECOV_SPECIFIED) ) {
if( (rsp->data[0] & UPPER_NON_RECOV_SPECIFIED) &&
(( (rsp->data[0] & UPPER_CRIT_SPECIFIED) && ( setting1 <= val[5])) ||
( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) && ( setting1 <= val[4]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & UPPER_CRIT_SPECIFIED) ) { /* Check for the valid Upper critical Value.*/
if( (rsp->data[0] & UPPER_CRIT_SPECIFIED) &&
(((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&& ( setting1 >= val[6])) ||
((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 <= val[4]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & UPPER_NON_CRIT_SPECIFIED) ) { /* Check for the valid Upper non critical Value.*/
if( (rsp->data[0] & UPPER_NON_CRIT_SPECIFIED) &&
(((rsp->data[0] & UPPER_NON_RECOV_SPECIFIED)&&( setting1 >= val[6])) ||
((rsp->data[0] & UPPER_CRIT_SPECIFIED)&&( setting1 >= val[5])) ||
((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 <= val[1]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & LOWER_NON_CRIT_SPECIFIED) ) { /* Check for the valid lower non critical Value.*/
if( (rsp->data[0] & LOWER_NON_CRIT_SPECIFIED) &&
(((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 <= val[2])) ||
((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))||
((rsp->data[0] & UPPER_NON_CRIT_SPECIFIED)&&( setting1 >= val[4]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & LOWER_CRIT_SPECIFIED) ) { /* Check for the valid lower critical Value.*/
if( (rsp->data[0] & LOWER_CRIT_SPECIFIED) &&
(((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) ||
((rsp->data[0] & LOWER_NON_RECOV_SPECIFIED)&&( setting1 <= val[3]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else if( (settingMask & LOWER_NON_RECOV_SPECIFIED) ) { /* Check for the valid lower non recovarable Value.*/
if( (rsp->data[0] & LOWER_NON_RECOV_SPECIFIED) &&
(((rsp->data[0] & LOWER_NON_CRIT_SPECIFIED)&&( setting1 >= val[1])) ||
((rsp->data[0] & LOWER_CRIT_SPECIFIED)&&( setting1 >= val[2]))) )
{
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
} else { /* None of this Then Return with error messages.*/
lprintf(LOG_ERR, INVALID_THRESHOLD);
return -1;
}
printf("Setting sensor \"%s\" %s threshold to %.3f\n",
sdr->record.full->id_string,
val2str(settingMask, threshold_vals), setting1);
ret = __ipmi_sensor_set_threshold(intf,
sdr->record.common->keys.
sensor_num, settingMask,
__ipmi_sensor_threshold_value_to_raw(sdr->record.full, setting1),
sdr->record.common->keys.owner_id,
sdr->record.common->keys.lun,
sdr->record.common->keys.channel);
}
return ret;
}
static int
ipmi_sensor_get_reading(struct ipmi_intf *intf, int argc, char **argv)
{
struct sdr_record_list *sdr;
int i, rc=0;
if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
lprintf(LOG_NOTICE, "sensor reading <id> ... [id]");
lprintf(LOG_NOTICE, " id : name of desired sensor");
return -1;
}
for (i = 0; i < argc; i++) {
sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
if (sdr == NULL) {
lprintf(LOG_ERR, "Sensor \"%s\" not found!",
argv[i]);
rc = -1;
continue;
}
switch (sdr->type) {
case SDR_RECORD_TYPE_FULL_SENSOR:
case SDR_RECORD_TYPE_COMPACT_SENSOR:
{
struct sensor_reading *sr;
struct sdr_record_common_sensor *sensor = sdr->record.common;
sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr->type, 3);
if (sr == NULL) {
rc = -1;
continue;
}
if (!sr->full)
continue;
if (!sr->s_reading_valid)
continue;
if (!sr->s_has_analog_value) {
lprintf(LOG_ERR, "Sensor \"%s\" is a discrete sensor!", argv[i]);
continue;
}
if (csv_output)
printf("%s,%s\n", argv[i], sr->s_a_str);
else
printf("%-16s | %s\n", argv[i], sr->s_a_str);
break;
}
default:
continue;
}
}
return rc;
}
static int
ipmi_sensor_get(struct ipmi_intf *intf, int argc, char **argv)
{
int i, v;
int rc = 0;
struct sdr_record_list *sdr;
if (argc < 1) {
lprintf(LOG_ERR, "Not enough parameters given.");
printf_sensor_get_usage();
return (-1);
} else if (strcmp(argv[0], "help") == 0) {
printf_sensor_get_usage();
return 0;
}
printf("Locating sensor record...\n");
/* lookup by sensor name */
for (i = 0; i < argc; i++) {
sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]);
if (sdr == NULL) {
lprintf(LOG_ERR, "Sensor data record \"%s\" not found!",
argv[i]);
rc = -1;
continue;
}
/* need to set verbose level to 1 */
v = verbose;
verbose = 1;
if (ipmi_sdr_print_listentry(intf, sdr) < 0) {
rc = (-1);
}
verbose = v;
sdr = NULL;
}
return rc;
}
int
ipmi_sensor_main(struct ipmi_intf *intf, int argc, char **argv)
{
int rc = 0;
if (argc == 0) {
rc = ipmi_sensor_list(intf);
} else if (strncmp(argv[0], "help", 4) == 0) {
lprintf(LOG_NOTICE, "Sensor Commands: list thresh get reading");
} else if (strncmp(argv[0], "list", 4) == 0) {
rc = ipmi_sensor_list(intf);
} else if (strncmp(argv[0], "thresh", 5) == 0) {
rc = ipmi_sensor_set_threshold(intf, argc - 1, &argv[1]);
} else if (strncmp(argv[0], "get", 3) == 0) {
rc = ipmi_sensor_get(intf, argc - 1, &argv[1]);
} else if (strncmp(argv[0], "reading", 7) == 0) {
rc = ipmi_sensor_get_reading(intf, argc - 1, &argv[1]);
} else {
lprintf(LOG_ERR, "Invalid sensor command: %s", argv[0]);
rc = -1;
}
return rc;
}
/* printf_sensor_get_usage - print usage for # ipmitool sensor get NAC;
*
* @returns: void
*/
void
printf_sensor_get_usage()
{
lprintf(LOG_NOTICE, "sensor get <id> ... [id]");
lprintf(LOG_NOTICE, " id : name of desired sensor");
}

459
lib/ipmi_session.c Normal file
View File

@@ -0,0 +1,459 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi_lanp.h>
#include <ipmitool/ipmi_session.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/bswap.h>
typedef enum {
IPMI_SESSION_REQUEST_CURRENT = 0,
IPMI_SESSION_REQUEST_ALL,
IPMI_SESSION_REQUEST_BY_ID,
IPMI_SESSION_REQUEST_BY_HANDLE
} Ipmi_Session_Request_Type;
/*
* print_session_info_csv
*/
static void
print_session_info_csv(const struct get_session_info_rsp * session_info,
int data_len)
{
char buffer[18];
uint16_t console_port_tmp;
printf("%d", session_info->session_handle);
printf(",%d", session_info->session_slot_count);
printf(",%d", session_info->active_session_count);
if (data_len == 3)
{
/* There is no session data here*/
printf("\n");
return;
}
printf(",%d", session_info->user_id);
printf(",%s", val2str(session_info->privilege_level, ipmi_privlvl_vals));
printf(",%s", session_info->auxiliary_data?
"IPMIv2/RMCP+" : "IPMIv1.5");
printf(",0x%02x", session_info->channel_number);
if (data_len == 18)
{
/* We have 802.3 LAN data */
printf(",%s",
inet_ntop(AF_INET,
&(session_info->channel_data.lan_data.console_ip),
buffer,
16));
printf(",%02x:%02x:%02x:%02x:%02x:%02x",
session_info->channel_data.lan_data.console_mac[0],
session_info->channel_data.lan_data.console_mac[1],
session_info->channel_data.lan_data.console_mac[2],
session_info->channel_data.lan_data.console_mac[3],
session_info->channel_data.lan_data.console_mac[4],
session_info->channel_data.lan_data.console_mac[5]);
console_port_tmp = session_info->channel_data.lan_data.console_port;
#if WORDS_BIGENDIAN
console_port_tmp = BSWAP_16(console_port_tmp);
#endif
printf(",%d", console_port_tmp);
}
else if ((data_len == 12) || (data_len == 14))
{
/* Channel async serial/modem */
printf(",%s",
val2str(session_info->channel_data.modem_data.session_channel_activity_type,
ipmi_channel_activity_type_vals));
printf(",%d",
session_info->channel_data.modem_data.destination_selector);
printf(",%s",
inet_ntop(AF_INET,
&(session_info->channel_data.modem_data.console_ip),
buffer,
16));
if (data_len == 14)
{
/* Connection is PPP */
console_port_tmp = session_info->channel_data.lan_data.console_port;
#if WORDS_BIGENDIAN
console_port_tmp = BSWAP_16(console_port_tmp);
#endif
printf(",%d", console_port_tmp);
}
}
printf("\n");
}
/*
* print_session_info_verbose
*/
static void
print_session_info_verbose(const struct get_session_info_rsp * session_info,
int data_len)
{
char buffer[18];
uint16_t console_port_tmp;
printf("session handle : %d\n", session_info->session_handle);
printf("slot count : %d\n", session_info->session_slot_count);
printf("active sessions : %d\n", session_info->active_session_count);
if (data_len == 3)
{
/* There is no session data here */
printf("\n");
return;
}
printf("user id : %d\n", session_info->user_id);
printf("privilege level : %s\n",
val2str(session_info->privilege_level, ipmi_privlvl_vals));
printf("session type : %s\n", session_info->auxiliary_data?
"IPMIv2/RMCP+" : "IPMIv1.5");
printf("channel number : 0x%02x\n", session_info->channel_number);
if (data_len == 18)
{
/* We have 802.3 LAN data */
printf("console ip : %s\n",
inet_ntop(AF_INET,
&(session_info->channel_data.lan_data.console_ip),
buffer,
16));
printf("console mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
session_info->channel_data.lan_data.console_mac[0],
session_info->channel_data.lan_data.console_mac[1],
session_info->channel_data.lan_data.console_mac[2],
session_info->channel_data.lan_data.console_mac[3],
session_info->channel_data.lan_data.console_mac[4],
session_info->channel_data.lan_data.console_mac[5]);
console_port_tmp = session_info->channel_data.lan_data.console_port;
#if WORDS_BIGENDIAN
console_port_tmp = BSWAP_16(console_port_tmp);
#endif
printf("console port : %d\n", console_port_tmp);
}
else if ((data_len == 12) || (data_len == 14))
{
/* Channel async serial/modem */
printf("Session/Channel Activity Type : %s\n",
val2str(session_info->channel_data.modem_data.session_channel_activity_type,
ipmi_channel_activity_type_vals));
printf("Destination selector : %d\n",
session_info->channel_data.modem_data.destination_selector);
printf("console ip : %s\n",
inet_ntop(AF_INET,
&(session_info->channel_data.modem_data.console_ip),
buffer,
16));
if (data_len == 14)
{
/* Connection is PPP */
console_port_tmp = session_info->channel_data.lan_data.console_port;
#if WORDS_BIGENDIAN
console_port_tmp = BSWAP_16(console_port_tmp);
#endif
printf("console port : %d\n", console_port_tmp);
}
}
printf("\n");
}
static void print_session_info(const struct get_session_info_rsp * session_info,
int data_len)
{
if (csv_output)
print_session_info_csv(session_info, data_len);
else
print_session_info_verbose(session_info, data_len);
}
/*
* ipmi_get_session_info
*
* returns 0 on success
* -1 on error
*/
int
ipmi_get_session_info(struct ipmi_intf * intf,
Ipmi_Session_Request_Type session_request_type,
uint32_t id_or_handle)
{
int i, retval = 0;
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t rqdata[5]; // max length of the variable length request
struct get_session_info_rsp session_info;
memset(&req, 0, sizeof(req));
memset(&session_info, 0, sizeof(session_info));
req.msg.netfn = IPMI_NETFN_APP; // 0x06
req.msg.cmd = IPMI_GET_SESSION_INFO; // 0x3D
req.msg.data = rqdata;
switch (session_request_type)
{
case IPMI_SESSION_REQUEST_CURRENT:
case IPMI_SESSION_REQUEST_BY_ID:
case IPMI_SESSION_REQUEST_BY_HANDLE:
switch (session_request_type)
{
case IPMI_SESSION_REQUEST_CURRENT:
rqdata[0] = 0x00;
req.msg.data_len = 1;
break;
case IPMI_SESSION_REQUEST_BY_ID:
rqdata[0] = 0xFF;
rqdata[1] = id_or_handle & 0x000000FF;
rqdata[2] = (id_or_handle >> 8) & 0x000000FF;
rqdata[3] = (id_or_handle >> 16) & 0x000000FF;
rqdata[4] = (id_or_handle >> 24) & 0x000000FF;
req.msg.data_len = 5;
break;
case IPMI_SESSION_REQUEST_BY_HANDLE:
rqdata[0] = 0xFE;
rqdata[1] = (uint8_t)id_or_handle;
req.msg.data_len = 2;
break;
case IPMI_SESSION_REQUEST_ALL:
break;
}
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL)
{
lprintf(LOG_ERR, "Get Session Info command failed");
retval = -1;
}
else if (rsp->ccode > 0)
{
lprintf(LOG_ERR, "Get Session Info command failed: %s",
val2str(rsp->ccode, completion_code_vals));
retval = -1;
}
if (retval < 0)
{
if ((session_request_type == IPMI_SESSION_REQUEST_CURRENT) &&
(strncmp(intf->name, "lan", 3) != 0))
lprintf(LOG_ERR, "It is likely that the channel in use "
"does not support sessions");
}
else
{
memcpy(&session_info, rsp->data, rsp->data_len);
print_session_info(&session_info, rsp->data_len);
}
break;
case IPMI_SESSION_REQUEST_ALL:
req.msg.data_len = 1;
i = 1;
do
{
rqdata[0] = i++;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL)
{
lprintf(LOG_ERR, "Get Session Info command failed");
retval = -1;
break;
}
else if (rsp->ccode > 0 && rsp->ccode != 0xCC && rsp->ccode != 0xCB)
{
lprintf(LOG_ERR, "Get Session Info command failed: %s",
val2str(rsp->ccode, completion_code_vals));
retval = -1;
break;
}
else if (rsp->data_len < 3)
{
retval = -1;
break;
}
memcpy(&session_info, rsp->data, rsp->data_len);
print_session_info(&session_info, rsp->data_len);
} while (i <= session_info.session_slot_count);
break;
}
return retval;
}
static void
printf_session_usage(void)
{
lprintf(LOG_NOTICE, "Session Commands: info <active | all | id 0xnnnnnnnn | handle 0xnn>");
}
int
ipmi_session_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int retval = 0;
if (argc == 0 || strncmp(argv[0], "help", 4) == 0)
{
printf_session_usage();
}
else if (strncmp(argv[0], "info", 4) == 0)
{
if ((argc < 2) || strncmp(argv[1], "help", 4) == 0)
{
printf_session_usage();
}
else
{
Ipmi_Session_Request_Type session_request_type = 0;
uint32_t id_or_handle = 0;
if (strncmp(argv[1], "active", 6) == 0)
session_request_type = IPMI_SESSION_REQUEST_CURRENT;
else if (strncmp(argv[1], "all", 3) == 0)
session_request_type = IPMI_SESSION_REQUEST_ALL;
else if (strncmp(argv[1], "id", 2) == 0)
{
if (argc >= 3)
{
session_request_type = IPMI_SESSION_REQUEST_BY_ID;
if (str2uint(argv[2], &id_or_handle) != 0) {
lprintf(LOG_ERR, "HEX number expected, but '%s' given.",
argv[2]);
printf_session_usage();
retval = -1;
}
}
else
{
lprintf(LOG_ERR, "Missing id argument");
printf_session_usage();
retval = -1;
}
}
else if (strncmp(argv[1], "handle", 6) == 0)
{
if (argc >= 3)
{
session_request_type = IPMI_SESSION_REQUEST_BY_HANDLE;
if (str2uint(argv[2], &id_or_handle) != 0) {
lprintf(LOG_ERR, "HEX number expected, but '%s' given.",
argv[2]);
printf_session_usage();
retval = -1;
}
}
else
{
lprintf(LOG_ERR, "Missing handle argument");
printf_session_usage();
retval = -1;
}
}
else
{
lprintf(LOG_ERR, "Invalid SESSION info parameter: %s", argv[1]);
printf_session_usage();
retval = -1;
}
if (retval == 0)
retval = ipmi_get_session_info(intf,
session_request_type,
id_or_handle);
}
}
else
{
lprintf(LOG_ERR, "Invalid SESSION command: %s", argv[0]);
printf_session_usage();
retval = -1;
}
return retval;
}

2109
lib/ipmi_sol.c Normal file

File diff suppressed because it is too large Load Diff

578
lib/ipmi_strings.c Normal file
View File

@@ -0,0 +1,578 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <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[] = {
{ IPMI_OEM_UNKNOWN, "Unknown" },
{ IPMI_OEM_HP, "Hewlett-Packard" },
{ IPMI_OEM_SUN, "Sun Microsystems" },
{ IPMI_OEM_INTEL, "Intel Corporation" },
{ IPMI_OEM_LMC, "LMC" },
{ IPMI_OEM_RADISYS, "RadiSys Corporation" },
{ IPMI_OEM_TYAN, "Tyan Computer Corporation" },
{ IPMI_OEM_NEWISYS, "Newisys" },
{ IPMI_OEM_SUPERMICRO, "Supermicro" },
{ IPMI_OEM_GOOGLE, "Google" },
{ IPMI_OEM_KONTRON, "Kontron" },
{ IPMI_OEM_NOKIA, "Nokia" },
{ IPMI_OEM_PICMG, "PICMG" },
{ IPMI_OEM_PEPPERCON, "Peppercon AG" },
{ IPMI_OEM_DELL, "DELL Inc" },
{ IPMI_OEM_NEC, "NEC" },
{ IPMI_OEM_MAGNUM, "Magnum Technologies" },
{ IPMI_OEM_FUJITSU_SIEMENS, "Fujitsu Siemens" },
{ IPMI_OEM_TATUNG, "Tatung" },
{ IPMI_OEM_AMI, "AMI" },
{ IPMI_OEM_RARITAN, "Raritan" },
{ IPMI_OEM_AVOCENT, "Avocent" },
{ IPMI_OEM_OSA, "OSA" },
{ IPMI_OEM_TOSHIBA, "Toshiba" },
{ IPMI_OEM_HITACHI_116, "Hitachi" },
{ IPMI_OEM_HITACHI_399, "Hitachi" },
{ IPMI_OEM_NOKIA_SIEMENS_NETWORKS, "Nokia Siemens Networks" },
{ IPMI_OEM_BULL, "Bull Company" },
{ IPMI_OEM_PPS, "Pigeon Point Systems" },
{ IPMI_OEM_BROADCOM, "Broadcom Corporation" },
{ 0xffff , NULL },
};
const struct oemvalstr ipmi_oem_product_info[] = {
/* Keep OEM grouped together */
/* Intel stuff, thanks to Tim Bell */
{ IPMI_OEM_INTEL, 0x000C, "TSRLT2" },
{ IPMI_OEM_INTEL, 0x001B, "TIGPR2U" },
{ IPMI_OEM_INTEL, 0x0022, "TIGI2U" },
{ IPMI_OEM_INTEL, 0x0026, "Bridgeport" },
{ IPMI_OEM_INTEL, 0x0028, "S5000PAL" },
{ IPMI_OEM_INTEL, 0x0029, "S5000PSL" },
{ IPMI_OEM_INTEL, 0x0100, "Tiger4" },
{ IPMI_OEM_INTEL, 0x0103, "McCarran" },
{ IPMI_OEM_INTEL, 0x0800, "ZT5504" },
{ IPMI_OEM_INTEL, 0x0808, "MPCBL0001" },
{ IPMI_OEM_INTEL, 0x0811, "TIGW1U" },
{ IPMI_OEM_INTEL, 0x4311, "NSI2U" },
/* Kontron */
{ IPMI_OEM_KONTRON,4000, "AM4000 AdvancedMC" },
{ IPMI_OEM_KONTRON,4001, "AM4001 AdvancedMC" },
{ IPMI_OEM_KONTRON,4002, "AM4002 AdvancedMC" },
{ IPMI_OEM_KONTRON,4010, "AM4010 AdvancedMC" },
{ IPMI_OEM_KONTRON,5503, "AM4500/4520 AdvancedMC" },
{ IPMI_OEM_KONTRON,5504, "AM4300 AdvancedMC" },
{ IPMI_OEM_KONTRON,5507, "AM4301 AdvancedMC" },
{ IPMI_OEM_KONTRON,5508, "AM4330 AdvancedMC" },
{ IPMI_OEM_KONTRON,5520, "KTC5520/EATX" },
{ IPMI_OEM_KONTRON,5703, "RTM8020" },
{ IPMI_OEM_KONTRON,5704, "RTM8030" },
{ IPMI_OEM_KONTRON,5705, "RTM8050" },
{ IPMI_OEM_KONTRON,6000, "CP6000" },
{ IPMI_OEM_KONTRON,6006, "DT-64" },
{ IPMI_OEM_KONTRON,6010, "CP6010" },
{ IPMI_OEM_KONTRON,6011, "CP6011" },
{ IPMI_OEM_KONTRON,6012, "CP6012" },
{ IPMI_OEM_KONTRON,6014, "CP6014" },
{ IPMI_OEM_KONTRON,5002, "AT8001" },
{ IPMI_OEM_KONTRON,5003, "AT8010" },
{ IPMI_OEM_KONTRON,5004, "AT8020" },
{ IPMI_OEM_KONTRON,5006, "AT8030 IPMC" },
{ IPMI_OEM_KONTRON,2025, "AT8030 MMC" },
{ IPMI_OEM_KONTRON,5007, "AT8050" },
{ IPMI_OEM_KONTRON,5301, "AT8400" },
{ IPMI_OEM_KONTRON,5303, "AT8901" },
/* Broadcom */
{ IPMI_OEM_BROADCOM, 5725, "BCM5725" },
{ 0xffffff , 0xffff , NULL },
};
const struct oemvalstr ipmi_oem_sdr_type_vals[] = {
/* Keep OEM grouped together */
{ IPMI_OEM_KONTRON , 0xC0 , "OEM Firmware Info" },
{ IPMI_OEM_KONTRON , 0xC2 , "OEM Init Agent" },
{ IPMI_OEM_KONTRON , 0xC3 , "OEM IPMBL Link State" },
{ IPMI_OEM_KONTRON , 0xC4 , "OEM Board Reset" },
{ IPMI_OEM_KONTRON , 0xC5 , "OEM FRU Information Agent" },
{ IPMI_OEM_KONTRON , 0xC6 , "OEM POST Value Sensor" },
{ IPMI_OEM_KONTRON , 0xC7 , "OEM FWUM Status" },
{ IPMI_OEM_KONTRON , 0xC8 , "OEM Switch Mngt Software Status" },
{ IPMI_OEM_KONTRON , 0xC9 , "OEM OEM Diagnostic Status" },
{ IPMI_OEM_KONTRON , 0xCA , "OEM Component Firmware Upgrade" },
{ IPMI_OEM_KONTRON , 0xCB , "OEM FRU Over Current" },
{ IPMI_OEM_KONTRON , 0xCC , "OEM FRU Sensor Error" },
{ IPMI_OEM_KONTRON , 0xCD , "OEM FRU Power Denied" },
{ IPMI_OEM_KONTRON , 0xCE , "OEM Reserved" },
{ IPMI_OEM_KONTRON , 0xCF , "OEM Board Reset" },
{ IPMI_OEM_KONTRON , 0xD0 , "OEM Clock Resource Control" },
{ IPMI_OEM_KONTRON , 0xD1 , "OEM Power State" },
{ IPMI_OEM_KONTRON , 0xD2 , "OEM FRU Mngt Power Failure" },
{ IPMI_OEM_KONTRON , 0xD3 , "OEM Jumper Status" },
{ IPMI_OEM_KONTRON , 0xF2 , "OEM RTM Module Hotswap" },
{ IPMI_OEM_PICMG , 0xF0 , "PICMG FRU Hotswap" },
{ IPMI_OEM_PICMG , 0xF1 , "PICMG IPMB0 Link State" },
{ IPMI_OEM_PICMG , 0xF2 , "PICMG Module Hotswap" },
{ 0xffffff, 0x00, NULL }
};
const struct valstr ipmi_netfn_vals[] = {
{ IPMI_NETFN_CHASSIS, "Chassis" },
{ IPMI_NETFN_BRIDGE, "Bridge" },
{ IPMI_NETFN_SE, "SensorEvent" },
{ IPMI_NETFN_APP, "Application" },
{ IPMI_NETFN_FIRMWARE, "Firmware" },
{ IPMI_NETFN_STORAGE, "Storage" },
{ IPMI_NETFN_TRANSPORT, "Transport" },
{ 0xff, NULL },
};
/*
* From table 26-4 of the IPMI v2 specification
*/
const struct valstr ipmi_bit_rate_vals[] = {
{ 0x00, "IPMI-Over-Serial-Setting"}, /* Using the value in the IPMI Over Serial Config */
{ 0x06, "9.6" },
{ 0x07, "19.2" },
{ 0x08, "38.4" },
{ 0x09, "57.6" },
{ 0x0A, "115.2" },
{ 0x00, NULL },
};
const struct valstr ipmi_channel_activity_type_vals[] = {
{ 0, "IPMI Messaging session active" },
{ 1, "Callback Messaging session active" },
{ 2, "Dial-out Alert active" },
{ 3, "TAP Page Active" },
{ 0x00, NULL },
};
const struct valstr ipmi_privlvl_vals[] = {
{ IPMI_SESSION_PRIV_CALLBACK, "CALLBACK" },
{ IPMI_SESSION_PRIV_USER, "USER" },
{ IPMI_SESSION_PRIV_OPERATOR, "OPERATOR" },
{ IPMI_SESSION_PRIV_ADMIN, "ADMINISTRATOR" },
{ IPMI_SESSION_PRIV_OEM, "OEM" },
{ 0xF, "NO ACCESS" },
{ 0xFF, NULL },
};
const struct valstr ipmi_set_in_progress_vals[] = {
{ IPMI_SET_IN_PROGRESS_SET_COMPLETE, "set-complete" },
{ IPMI_SET_IN_PROGRESS_IN_PROGRESS, "set-in-progress" },
{ IPMI_SET_IN_PROGRESS_COMMIT_WRITE, "commit-write" },
{ 0, NULL },
};
const struct valstr ipmi_authtype_session_vals[] = {
{ IPMI_SESSION_AUTHTYPE_NONE, "NONE" },
{ IPMI_SESSION_AUTHTYPE_MD2, "MD2" },
{ IPMI_SESSION_AUTHTYPE_MD5, "MD5" },
{ IPMI_SESSION_AUTHTYPE_PASSWORD, "PASSWORD" },
{ IPMI_SESSION_AUTHTYPE_OEM, "OEM" },
{ IPMI_SESSION_AUTHTYPE_RMCP_PLUS,"RMCP+" },
{ 0xFF, NULL },
};
const struct valstr ipmi_authtype_vals[] = {
{ IPMI_1_5_AUTH_TYPE_BIT_NONE, "NONE" },
{ IPMI_1_5_AUTH_TYPE_BIT_MD2, "MD2" },
{ IPMI_1_5_AUTH_TYPE_BIT_MD5, "MD5" },
{ IPMI_1_5_AUTH_TYPE_BIT_PASSWORD, "PASSWORD" },
{ IPMI_1_5_AUTH_TYPE_BIT_OEM, "OEM" },
{ 0, NULL },
};
const struct valstr entity_id_vals[] = {
{ 0x00, "Unspecified" },
{ 0x01, "Other" },
{ 0x02, "Unknown" },
{ 0x03, "Processor" },
{ 0x04, "Disk or Disk Bay" },
{ 0x05, "Peripheral Bay" },
{ 0x06, "System Management Module" },
{ 0x07, "System Board" },
{ 0x08, "Memory Module" },
{ 0x09, "Processor Module" },
{ 0x0a, "Power Supply" },
{ 0x0b, "Add-in Card" },
{ 0x0c, "Front Panel Board" },
{ 0x0d, "Back Panel Board" },
{ 0x0e, "Power System Board" },
{ 0x0f, "Drive Backplane" },
{ 0x10, "System Internal Expansion Board" },
{ 0x11, "Other System Board" },
{ 0x12, "Processor Board" },
{ 0x13, "Power Unit" },
{ 0x14, "Power Module" },
{ 0x15, "Power Management" },
{ 0x16, "Chassis Back Panel Board" },
{ 0x17, "System Chassis" },
{ 0x18, "Sub-Chassis" },
{ 0x19, "Other Chassis Board" },
{ 0x1a, "Disk Drive Bay" },
{ 0x1b, "Peripheral Bay" },
{ 0x1c, "Device Bay" },
{ 0x1d, "Fan Device" },
{ 0x1e, "Cooling Unit" },
{ 0x1f, "Cable/Interconnect" },
{ 0x20, "Memory Device" },
{ 0x21, "System Management Software" },
{ 0x22, "BIOS" },
{ 0x23, "Operating System" },
{ 0x24, "System Bus" },
{ 0x25, "Group" },
{ 0x26, "Remote Management Device" },
{ 0x27, "External Environment" },
{ 0x28, "Battery" },
{ 0x29, "Processing Blade" },
{ 0x2A, "Connectivity Switch" },
{ 0x2B, "Processor/Memory Module" },
{ 0x2C, "I/O Module" },
{ 0x2D, "Processor/IO Module" },
{ 0x2E, "Management Controller Firmware" },
{ 0x2F, "IPMI Channel" },
{ 0x30, "PCI Bus" },
{ 0x31, "PCI Express Bus" },
{ 0x32, "SCSI Bus (parallel)" },
{ 0x33, "SATA/SAS Bus" },
{ 0x34, "Processor/Front-Side Bus" },
{ 0x35, "Real Time Clock(RTC)" },
{ 0x36, "Reserved" },
{ 0x37, "Air Inlet" },
{ 0x38, "Reserved" },
{ 0x39, "Reserved" },
{ 0x3A, "Reserved" },
{ 0x3B, "Reserved" },
{ 0x3C, "Reserved" },
{ 0x3D, "Reserved" },
{ 0x3E, "Reserved" },
{ 0x3F, "Reserved" },
{ 0x40, "Air Inlet" },
{ 0x41, "Processor" },
{ 0x42, "Baseboard/Main System Board" },
/* PICMG */
{ 0xA0, "PICMG Front Board" },
{ 0xC0, "PICMG Rear Transition Module" },
{ 0xC1, "PICMG AdvancedMC Module" },
{ 0xF0, "PICMG Shelf Management Controller" },
{ 0xF1, "PICMG Filtration Unit" },
{ 0xF2, "PICMG Shelf FRU Information" },
{ 0xF3, "PICMG Alarm Panel" },
{ 0x00, NULL },
};
const struct valstr entity_device_type_vals[] = {
{ 0x00, "Reserved" },
{ 0x01, "Reserved" },
{ 0x02, "DS1624 temperature sensor" },
{ 0x03, "DS1621 temperature sensor" },
{ 0x04, "LM75 Temperature Sensor" },
{ 0x05, "Heceta ASIC" },
{ 0x06, "Reserved" },
{ 0x07, "Reserved" },
{ 0x08, "EEPROM, 24C01" },
{ 0x09, "EEPROM, 24C02" },
{ 0x0a, "EEPROM, 24C04" },
{ 0x0b, "EEPROM, 24C08" },
{ 0x0c, "EEPROM, 24C16" },
{ 0x0d, "EEPROM, 24C17" },
{ 0x0e, "EEPROM, 24C32" },
{ 0x0f, "EEPROM, 24C64" },
{ 0x1000, "IPMI FRU Inventory" },
{ 0x1001, "DIMM Memory ID" },
{ 0x1002, "IPMI FRU Inventory" },
{ 0x1003, "System Processor Cartridge FRU" },
{ 0x11, "Reserved" },
{ 0x12, "Reserved" },
{ 0x13, "Reserved" },
{ 0x14, "PCF 8570 256 byte RAM" },
{ 0x15, "PCF 8573 clock/calendar" },
{ 0x16, "PCF 8574A I/O Port" },
{ 0x17, "PCF 8583 clock/calendar" },
{ 0x18, "PCF 8593 clock/calendar" },
{ 0x19, "Clock calendar" },
{ 0x1a, "PCF 8591 A/D, D/A Converter" },
{ 0x1b, "I/O Port" },
{ 0x1c, "A/D Converter" },
{ 0x1d, "D/A Converter" },
{ 0x1e, "A/D, D/A Converter" },
{ 0x1f, "LCD Controller/Driver" },
{ 0x20, "Core Logic (Chip set) Device" },
{ 0x21, "LMC6874 Intelligent Battery controller" },
{ 0x22, "Intelligent Batter controller" },
{ 0x23, "Combo Management ASIC" },
{ 0x24, "Maxim 1617 Temperature Sensor" },
{ 0xbf, "Other/Unspecified" },
{ 0x00, NULL },
};
const struct valstr ipmi_channel_protocol_vals[] = {
{ 0x00, "reserved" },
{ 0x01, "IPMB-1.0" },
{ 0x02, "ICMB-1.0" },
{ 0x03, "reserved" },
{ 0x04, "IPMI-SMBus" },
{ 0x05, "KCS" },
{ 0x06, "SMIC" },
{ 0x07, "BT-10" },
{ 0x08, "BT-15" },
{ 0x09, "TMode" },
{ 0x1c, "OEM 1" },
{ 0x1d, "OEM 2" },
{ 0x1e, "OEM 3" },
{ 0x1f, "OEM 4" },
{ 0x00, NULL },
};
const struct valstr ipmi_channel_medium_vals[] = {
{ IPMI_CHANNEL_MEDIUM_RESERVED, "reserved" },
{ IPMI_CHANNEL_MEDIUM_IPMB_I2C, "IPMB (I2C)" },
{ IPMI_CHANNEL_MEDIUM_ICMB_1, "ICMB v1.0" },
{ IPMI_CHANNEL_MEDIUM_ICMB_09, "ICMB v0.9" },
{ IPMI_CHANNEL_MEDIUM_LAN, "802.3 LAN" },
{ IPMI_CHANNEL_MEDIUM_SERIAL, "Serial/Modem" },
{ IPMI_CHANNEL_MEDIUM_LAN_OTHER,"Other LAN" },
{ IPMI_CHANNEL_MEDIUM_SMBUS_PCI,"PCI SMBus" },
{ IPMI_CHANNEL_MEDIUM_SMBUS_1, "SMBus v1.0/v1.1" },
{ IPMI_CHANNEL_MEDIUM_SMBUS_2, "SMBus v2.0" },
{ IPMI_CHANNEL_MEDIUM_USB_1, "USB 1.x" },
{ IPMI_CHANNEL_MEDIUM_USB_2, "USB 2.x" },
{ IPMI_CHANNEL_MEDIUM_SYSTEM, "System Interface" },
{ 0x00, NULL },
};
const struct valstr completion_code_vals[] = {
{ 0x00, "Command completed normally" },
{ 0xc0, "Node busy" },
{ 0xc1, "Invalid command" },
{ 0xc2, "Invalid command on LUN" },
{ 0xc3, "Timeout" },
{ 0xc4, "Out of space" },
{ 0xc5, "Reservation cancelled or invalid" },
{ 0xc6, "Request data truncated" },
{ 0xc7, "Request data length invalid" },
{ 0xc8, "Request data field length limit exceeded" },
{ 0xc9, "Parameter out of range" },
{ 0xca, "Cannot return number of requested data bytes" },
{ 0xcb, "Requested sensor, data, or record not found" },
{ 0xcc, "Invalid data field in request" },
{ 0xcd, "Command illegal for specified sensor or record type" },
{ 0xce, "Command response could not be provided" },
{ 0xcf, "Cannot execute duplicated request" },
{ 0xd0, "SDR Repository in update mode" },
{ 0xd1, "Device firmeware in update mode" },
{ 0xd2, "BMC initialization in progress" },
{ 0xd3, "Destination unavailable" },
{ 0xd4, "Insufficient privilege level" },
{ 0xd5, "Command not supported in present state" },
{ 0xd6, "Cannot execute command, command disabled" },
{ 0xff, "Unspecified error" },
{ 0x00, NULL }
};
const struct valstr ipmi_chassis_power_control_vals[] = {
{ IPMI_CHASSIS_CTL_POWER_DOWN, "Down/Off" },
{ IPMI_CHASSIS_CTL_POWER_UP, "Up/On" },
{ IPMI_CHASSIS_CTL_POWER_CYCLE, "Cycle" },
{ IPMI_CHASSIS_CTL_HARD_RESET, "Reset" },
{ IPMI_CHASSIS_CTL_PULSE_DIAG, "Diag" },
{ IPMI_CHASSIS_CTL_ACPI_SOFT, "Soft" },
{ 0x00, NULL },
};
const struct valstr ipmi_auth_algorithms[] = {
{ IPMI_AUTH_RAKP_NONE, "none" },
{ IPMI_AUTH_RAKP_HMAC_SHA1, "hmac_sha1" },
{ IPMI_AUTH_RAKP_HMAC_MD5, "hmac_md5" },
{ 0x00, NULL }
};
const struct valstr ipmi_integrity_algorithms[] = {
{ IPMI_INTEGRITY_NONE, "none" },
{ IPMI_INTEGRITY_HMAC_SHA1_96, "hmac_sha1_96" },
{ IPMI_INTEGRITY_HMAC_MD5_128, "hmac_md5_128" },
{ IPMI_INTEGRITY_MD5_128 , "md5_128" },
{ 0x00, NULL }
};
const struct valstr ipmi_encryption_algorithms[] = {
{ IPMI_CRYPT_NONE, "none" },
{ IPMI_CRYPT_AES_CBC_128, "aes_cbc_128" },
{ IPMI_CRYPT_XRC4_128, "xrc4_128" },
{ IPMI_CRYPT_XRC4_40, "xrc4_40" },
{ 0x00, NULL }
};
const struct valstr picmg_frucontrol_vals[] = {
{ 0, "Cold Reset" },
{ 1, "Warm Reset" },
{ 2, "Graceful Reboot" },
{ 3, "Issue Diagnostic Interrupt" },
{ 4, "Quiesce" },
{ 5, NULL },
};
const struct valstr picmg_clk_family_vals[] = {
{ 0x00, "Unspecified" },
{ 0x01, "SONET/SDH/PDH" },
{ 0x02, "Reserved for PCI Express" },
{ 0x03, "Reserved" }, /* from 03h to C8h */
{ 0xC9, "Vendor defined clock family" }, /* from C9h to FFh */
{ 0x00, NULL },
};
const struct oemvalstr picmg_clk_accuracy_vals[] = {
{ 0x01, 10, "PRS" },
{ 0x01, 20, "STU" },
{ 0x01, 30, "ST2" },
{ 0x01, 40, "TNC" },
{ 0x01, 50, "ST3E" },
{ 0x01, 60, "ST3" },
{ 0x01, 70, "SMC" },
{ 0x01, 80, "ST4" },
{ 0x01, 90, "DUS" },
{ 0x02, 0xE0, "PCI Express Generation 2" },
{ 0x02, 0xF0, "PCI Express Generation 1" },
{ 0xffffff, 0x00, NULL }
};
const struct oemvalstr picmg_clk_resource_vals[] = {
{ 0x0, 0, "On-Carrier Device 0" },
{ 0x0, 1, "On-Carrier Device 1" },
{ 0x1, 1, "AMC Site 1 - A1" },
{ 0x1, 2, "AMC Site 1 - A2" },
{ 0x1, 3, "AMC Site 1 - A3" },
{ 0x1, 4, "AMC Site 1 - A4" },
{ 0x1, 5, "AMC Site 1 - B1" },
{ 0x1, 6, "AMC Site 1 - B2" },
{ 0x1, 7, "AMC Site 1 - B3" },
{ 0x1, 8, "AMC Site 1 - B4" },
{ 0x2, 0, "ATCA Backplane" },
{ 0xffffff, 0x00, NULL }
};
const struct oemvalstr picmg_clk_id_vals[] = {
{ 0x0, 0, "Clock 0" },
{ 0x0, 1, "Clock 1" },
{ 0x0, 2, "Clock 2" },
{ 0x0, 3, "Clock 3" },
{ 0x0, 4, "Clock 4" },
{ 0x0, 5, "Clock 5" },
{ 0x0, 6, "Clock 6" },
{ 0x0, 7, "Clock 7" },
{ 0x0, 8, "Clock 8" },
{ 0x0, 9, "Clock 9" },
{ 0x0, 10, "Clock 10" },
{ 0x0, 11, "Clock 11" },
{ 0x0, 12, "Clock 12" },
{ 0x0, 13, "Clock 13" },
{ 0x0, 14, "Clock 14" },
{ 0x0, 15, "Clock 15" },
{ 0x1, 1, "TCLKA" },
{ 0x1, 2, "TCLKB" },
{ 0x1, 3, "TCLKC" },
{ 0x1, 4, "TCLKD" },
{ 0x1, 5, "FLCKA" },
{ 0x2, 1, "CLK1A" },
{ 0x2, 2, "CLK1A" },
{ 0x2, 3, "CLK1A" },
{ 0x2, 4, "CLK1A" },
{ 0x2, 5, "CLK1A" },
{ 0x2, 6, "CLK1A" },
{ 0x2, 7, "CLK1A" },
{ 0x2, 8, "CLK1A" },
{ 0x2, 9, "CLK1A" },
{ 0xffffff, 0x00, NULL }
};
const struct valstr picmg_busres_id_vals[] = {
{ 0x0, "Metallic Test Bus pair #1" },
{ 0x1, "Metallic Test Bus pair #2" },
{ 0x2, "Synch clock group 1 (CLK1)" },
{ 0x3, "Synch clock group 2 (CLK2)" },
{ 0x4, "Synch clock group 3 (CLK3)" },
{ 0x5, NULL }
};
const struct valstr picmg_busres_board_cmd_vals[] = {
{ 0x0, "Query" },
{ 0x1, "Release" },
{ 0x2, "Force" },
{ 0x3, "Bus Free" },
{ 0x4, NULL }
};
const struct valstr picmg_busres_shmc_cmd_vals[] = {
{ 0x0, "Request" },
{ 0x1, "Relinquish" },
{ 0x2, "Notify" },
{ 0x3, NULL }
};
const struct oemvalstr picmg_busres_board_status_vals[] = {
{ 0x0, 0x0, "In control" },
{ 0x0, 0x1, "No control" },
{ 0x1, 0x0, "Ack" },
{ 0x1, 0x1, "Refused" },
{ 0x1, 0x2, "No control" },
{ 0x2, 0x0, "Ack" },
{ 0x2, 0x1, "No control" },
{ 0x3, 0x0, "Accept" },
{ 0x3, 0x1, "Not Needed" },
{ 0xffffff, 0x00, NULL }
};
const struct oemvalstr picmg_busres_shmc_status_vals[] = {
{ 0x0, 0x0, "Grant" },
{ 0x0, 0x1, "Busy" },
{ 0x0, 0x2, "Defer" },
{ 0x0, 0x3, "Deny" },
{ 0x1, 0x0, "Ack" },
{ 0x1, 0x1, "Error" },
{ 0x2, 0x0, "Ack" },
{ 0x2, 0x1, "Error" },
{ 0x2, 0x2, "Deny" },
{ 0xffffff, 0x00, NULL }
};

859
lib/ipmi_sunoem.c Normal file
View File

@@ -0,0 +1,859 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi_sel.h>
#include <ipmitool/ipmi_sdr.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_channel.h>
#include <ipmitool/ipmi_sunoem.h>
#include <ipmitool/ipmi_raw.h>
static const struct valstr sunoem_led_type_vals[] = {
{ 0, "OK2RM" },
{ 1, "SERVICE" },
{ 2, "ACT" },
{ 3, "LOCATE" },
{ 0xFF, NULL },
};
static const struct valstr sunoem_led_mode_vals[] = {
{ 0, "OFF" },
{ 1, "ON" },
{ 2, "STANDBY" },
{ 3, "SLOW" },
{ 4, "FAST" },
{ 0xFF, NULL },
};
static const struct valstr sunoem_led_mode_optvals[] = {
{ 0, "STEADY_OFF" },
{ 1, "STEADY_ON" },
{ 2, "STANDBY_BLINK" },
{ 3, "SLOW_BLINK" },
{ 4, "FAST_BLINK" },
{ 0xFF, NULL },
};
int is_sbcmd = 0;
static void
ipmi_sunoem_usage(void)
{
lprintf(LOG_NOTICE, "usage: sunoem <command> [option...]");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " fan speed <0-100>");
lprintf(LOG_NOTICE, " Set system fan speed (PWM duty cycle)");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " sshkey set <userid> <id_rsa.pub>");
lprintf(LOG_NOTICE, " Set ssh key for a userid into authorized_keys,");
lprintf(LOG_NOTICE, " view users with 'user list' command.");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " sshkey del <userid>");
lprintf(LOG_NOTICE, " Delete ssh key for userid from authorized_keys,");
lprintf(LOG_NOTICE, " view users with 'user list' command.");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " led get <sensorid> [ledtype]");
lprintf(LOG_NOTICE,
" Read status of LED found in Generic Device Locator.");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " led set <sensorid> <ledmode> [ledtype]");
lprintf(LOG_NOTICE,
" Set mode of LED found in Generic Device Locator.");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " sbled get <sensorid> [ledtype]");
lprintf(LOG_NOTICE,
" Read status of LED found in Generic Device Locator");
lprintf(LOG_NOTICE, " for Sun Blade Modular Systems.");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " sbled set <sensorid> <ledmode> [ledtype]");
lprintf(LOG_NOTICE, " Set mode of LED found in Generic Device Locator");
lprintf(LOG_NOTICE, " for Sun Blade Modular Systems.");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE,
" Use 'sdr list generic' command to get list of Generic");
lprintf(LOG_NOTICE, " Devices that are controllable LEDs.");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " Required SIS LED Mode:");
lprintf(LOG_NOTICE, " OFF Off");
lprintf(LOG_NOTICE, " ON Steady On");
lprintf(LOG_NOTICE, " STANDBY 100ms on 2900ms off blink rate");
lprintf(LOG_NOTICE, " SLOW 1HZ blink rate");
lprintf(LOG_NOTICE, " FAST 4HZ blink rate");
lprintf(LOG_NOTICE, "");
lprintf(LOG_NOTICE, " Optional SIS LED Type:");
lprintf(LOG_NOTICE, " OK2RM OK to Remove");
lprintf(LOG_NOTICE, " SERVICE Service Required");
lprintf(LOG_NOTICE, " ACT Activity");
lprintf(LOG_NOTICE, " LOCATE Locate");
lprintf(LOG_NOTICE, "");
}
/*
* IPMI Request Data: 1 byte
*
* [byte 0] FanSpeed Fan speed as percentage
*/
static int
ipmi_sunoem_fan_speed(struct ipmi_intf * intf, uint8_t speed)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
/*
* sunoem fan speed <percent>
*/
if (speed > 100) {
lprintf(LOG_NOTICE, "Invalid fan speed: %d", speed);
return -1;
}
req.msg.netfn = IPMI_NETFN_SUNOEM;
req.msg.cmd = IPMI_SUNOEM_SET_FAN_SPEED;
req.msg.data = &speed;
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Sun OEM Set Fan Speed command failed");
return -1;
}
else if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Sun OEM Set Fan Speed command failed: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
printf("Set Fan speed to %d%%\n", speed);
return 0;
}
static void
__sdr_list_empty(struct sdr_record_list * head)
{
struct sdr_record_list * e, * f;
for (e = head; e != NULL; e = f) {
f = e->next;
free(e);
e = NULL;
}
head = NULL;
}
static void
led_print(const char * name, uint8_t state)
{
if (csv_output)
printf("%s,%s\n", name, val2str(state, sunoem_led_mode_vals));
else
printf("%-16s | %s\n", name, val2str(state, sunoem_led_mode_vals));
}
struct ipmi_rs *
sunoem_led_get(struct ipmi_intf * intf,
struct sdr_record_generic_locator * dev,
int ledtype)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t rqdata[7];
int rqdata_len = 5;
if (dev == NULL)
return NULL;
rqdata[0] = dev->dev_slave_addr;
if (ledtype == 0xFF)
rqdata[1] = dev->oem;
else
rqdata[1] = ledtype;
rqdata[2] = dev->dev_access_addr;
rqdata[3] = dev->oem;
if (is_sbcmd) {
rqdata[4] = dev->entity.id;
rqdata[5] = dev->entity.instance;
rqdata[6] = 0;
rqdata_len = 7;
}
else {
rqdata[4] = 0;
}
req.msg.netfn = IPMI_NETFN_SUNOEM;
req.msg.cmd = IPMI_SUNOEM_LED_GET;
req.msg.lun = dev->lun;
req.msg.data = rqdata;
req.msg.data_len = rqdata_len;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Sun OEM Get LED command failed");
return NULL;
}
else if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Sun OEM Get LED command failed: %s",
val2str(rsp->ccode, completion_code_vals));
return NULL;
}
return rsp;
}
struct ipmi_rs *
sunoem_led_set(struct ipmi_intf * intf,
struct sdr_record_generic_locator * dev,
int ledtype, int ledmode)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t rqdata[9];
int rqdata_len = 7;
if (dev == NULL)
return NULL;
rqdata[0] = dev->dev_slave_addr;
if (ledtype == 0xFF)
rqdata[1] = dev->oem;
else
rqdata[1] = ledtype;
rqdata[2] = dev->dev_access_addr;
rqdata[3] = dev->oem;
rqdata[4] = ledmode;
if (is_sbcmd) {
rqdata[5] = dev->entity.id;
rqdata[6] = dev->entity.instance;
rqdata[7] = 0;
rqdata[8] = 0;
rqdata_len = 9;
}
else {
rqdata[5] = 0;
rqdata[6] = 0;
}
req.msg.netfn = IPMI_NETFN_SUNOEM;
req.msg.cmd = IPMI_SUNOEM_LED_SET;
req.msg.lun = dev->lun;
req.msg.data = rqdata;
req.msg.data_len = rqdata_len;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Sun OEM Set LED command failed");
return NULL;
}
else if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Sun OEM Set LED command failed: %s",
val2str(rsp->ccode, completion_code_vals));
return NULL;
}
return rsp;
}
static void
sunoem_led_get_byentity(struct ipmi_intf * intf, uint8_t entity_id,
uint8_t entity_inst, int ledtype)
{
struct ipmi_rs * rsp;
struct sdr_record_list *elist, *e;
struct entity_id entity;
if (entity_id == 0)
return;
/* lookup sdrs with this entity */
memset(&entity, 0, sizeof(struct entity_id));
entity.id = entity_id;
entity.instance = entity_inst;
elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
/* for each generic sensor set its led state */
for (e = elist; e != NULL; e = e->next) {
if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
continue;
rsp = sunoem_led_get(intf, e->record.genloc, ledtype);
if (rsp && rsp->data_len == 1) {
led_print((const char *)e->record.genloc->id_string, rsp->data[0]);
}
}
__sdr_list_empty(elist);
}
static void
sunoem_led_set_byentity(struct ipmi_intf * intf, uint8_t entity_id,
uint8_t entity_inst, int ledtype, int ledmode)
{
struct ipmi_rs * rsp;
struct sdr_record_list *elist, *e;
struct entity_id entity;
if (entity_id == 0)
return;
/* lookup sdrs with this entity */
memset(&entity, 0, sizeof(struct entity_id));
entity.id = entity_id;
entity.instance = entity_inst;
elist = ipmi_sdr_find_sdr_byentity(intf, &entity);
/* for each generic sensor set its led state */
for (e = elist; e != NULL; e = e->next) {
if (e->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
continue;
rsp = sunoem_led_set(intf, e->record.genloc, ledtype, ledmode);
if (rsp && rsp->data_len == 0) {
led_print((const char *)e->record.genloc->id_string, ledmode);
}
}
__sdr_list_empty(elist);
}
/*
* IPMI Request Data: 5 bytes
*
* [byte 0] devAddr Value from the "Device Slave Address" field in
* LED's Generic Device Locator record in the SDR
* [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE
* [byte 2] ctrlrAddr Controller address; value from the "Device
* Access Address" field, 0x20 if the LED is local
* [byte 3] hwInfo The OEM field from the SDR record
* [byte 4] force 1 = directly access the device
* 0 = go thru its controller
* Ignored if LED is local
*
* The format below is for Sun Blade Modular systems only
* [byte 4] entityID The entityID field from the SDR record
* [byte 5] entityIns The entityIns field from the SDR record
* [byte 6] force 1 = directly access the device
* 0 = go thru its controller
* Ignored if LED is local
*/
static int
ipmi_sunoem_led_get(struct ipmi_intf * intf, int argc, char ** argv)
{
struct ipmi_rs * rsp;
struct sdr_record_list *sdr;
struct sdr_record_list *alist, *a;
struct sdr_record_entity_assoc *assoc;
int ledtype = 0xFF;
int i;
/*
* sunoem led/sbled get <id> [type]
*/
if (argc < 1 || strncmp(argv[0], "help", 4) == 0) {
ipmi_sunoem_usage();
return 0;
}
if (argc > 1) {
ledtype = str2val(argv[1], sunoem_led_type_vals);
if (ledtype == 0xFF)
lprintf(LOG_ERR, "Unknow ledtype, will use data from the SDR oem field");
}
if (strncasecmp(argv[0], "all", 3) == 0) {
/* do all generic sensors */
alist = ipmi_sdr_find_sdr_bytype(intf,
SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
for (a = alist; a != NULL; a = a->next) {
if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
continue;
if (a->record.genloc->entity.logical)
continue;
rsp = sunoem_led_get(intf, a->record.genloc, ledtype);
if (rsp && rsp->data_len == 1) {
led_print((const char *)a->record.genloc->id_string, rsp->data[0]);
}
}
__sdr_list_empty(alist);
return 0;
}
/* look up generic device locator record in SDR */
sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
if (sdr == NULL) {
lprintf(LOG_ERR, "No Sensor Data Record found for %s", argv[0]);
return -1;
}
if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
return -1;
}
if (!sdr->record.genloc->entity.logical) {
/*
* handle physical entity
*/
rsp = sunoem_led_get(intf, sdr->record.genloc, ledtype);
if (rsp && rsp->data_len == 1) {
led_print((const char *)sdr->record.genloc->id_string, rsp->data[0]);
}
return 0;
}
/*
* handle logical entity for LED grouping
*/
lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
/* get entity assoc records */
alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
for (a = alist; a != NULL; a = a->next) {
if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
continue;
assoc = a->record.entassoc;
if (assoc == NULL)
continue;
/* check that the entity id/instance matches our generic record */
if (assoc->entity.id != sdr->record.genloc->entity.id ||
assoc->entity.instance != sdr->record.genloc->entity.instance)
continue;
if (assoc->flags.isrange) {
/*
* handle ranged entity associations
*
* the test for non-zero entity id is handled in
* sunoem_led_get_byentity()
*/
/* first range set - id 1 and 2 must be equal */
if (assoc->entity_id_1 == assoc->entity_id_2)
for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
sunoem_led_get_byentity(intf, assoc->entity_id_1, i, ledtype);
/* second range set - id 3 and 4 must be equal */
if (assoc->entity_id_3 == assoc->entity_id_4)
for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
sunoem_led_get_byentity(intf, assoc->entity_id_3, i, ledtype);
}
else {
/*
* handle entity list
*/
sunoem_led_get_byentity(intf, assoc->entity_id_1,
assoc->entity_inst_1, ledtype);
sunoem_led_get_byentity(intf, assoc->entity_id_2,
assoc->entity_inst_2, ledtype);
sunoem_led_get_byentity(intf, assoc->entity_id_3,
assoc->entity_inst_3, ledtype);
sunoem_led_get_byentity(intf, assoc->entity_id_4,
assoc->entity_inst_4, ledtype);
}
}
__sdr_list_empty(alist);
return 0;
}
/*
* IPMI Request Data: 7 bytes
*
* [byte 0] devAddr Value from the "Device Slave Address" field in
* LED's Generic Device Locator record in the SDR
* [byte 1] led LED Type: OK2RM, ACT, LOCATE, SERVICE
* [byte 2] ctrlrAddr Controller address; value from the "Device
* Access Address" field, 0x20 if the LED is local
* [byte 3] hwInfo The OEM field from the SDR record
* [byte 4] mode LED Mode: OFF, ON, STANDBY, SLOW, FAST
* [byte 5] force TRUE - directly access the device
* FALSE - go thru its controller
* Ignored if LED is local
* [byte 6] role Used by BMC for authorization purposes
*
* The format below is for Sun Blade Modular systems only
* [byte 5] entityID The entityID field from the SDR record
* [byte 6] entityIns The entityIns field from the SDR record
* [byte 7] force TRUE - directly access the device
* FALSE - go thru its controller
* Ignored if LED is local
* [byte 8] role Used by BMC for authorization purposes
*
*
* IPMI Response Data: 1 byte
*
* [byte 0] mode LED Mode: OFF, ON, STANDBY, SLOW, FAST
*/
static int
ipmi_sunoem_led_set(struct ipmi_intf * intf, int argc, char ** argv)
{
struct ipmi_rs * rsp;
struct sdr_record_list *sdr;
struct sdr_record_list *alist, *a;
struct sdr_record_entity_assoc *assoc;
int ledmode;
int ledtype = 0xFF;
int i;
/*
* sunoem led/sbled set <id> <mode> [type]
*/
if (argc < 2 || strncmp(argv[0], "help", 4) == 0) {
ipmi_sunoem_usage();
return 0;
}
ledmode = str2val(argv[1], sunoem_led_mode_vals);
if (ledmode == 0xFF) {
ledmode = str2val(argv[1], sunoem_led_mode_optvals);
if (ledmode == 0xFF) {
lprintf(LOG_NOTICE, "Invalid LED Mode: %s", argv[1]);
return -1;
}
}
if (argc > 3) {
ledtype = str2val(argv[2], sunoem_led_type_vals);
if (ledtype == 0xFF)
lprintf(LOG_ERR, "Unknow ledtype, will use data from the SDR oem field");
}
if (strncasecmp(argv[0], "all", 3) == 0) {
/* do all generic sensors */
alist = ipmi_sdr_find_sdr_bytype(intf,
SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR);
for (a = alist; a != NULL; a = a->next) {
if (a->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR)
continue;
if (a->record.genloc->entity.logical)
continue;
rsp = sunoem_led_set(intf, a->record.genloc, ledtype, ledmode);
if (rsp && rsp->ccode == 0) {
led_print((const char *)a->record.genloc->id_string, ledmode);
}
}
__sdr_list_empty(alist);
return 0;
}
/* look up generic device locator records in SDR */
sdr = ipmi_sdr_find_sdr_byid(intf, argv[0]);
if (sdr == NULL) {
lprintf(LOG_ERR, "No Sensor Data Record found for %s",
argv[0]);
return -1;
}
if (sdr->type != SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR) {
lprintf(LOG_ERR, "Invalid SDR type %d", sdr->type);
return -1;
}
if (!sdr->record.genloc->entity.logical) {
/*
* handle physical entity
*/
rsp = sunoem_led_set(intf, sdr->record.genloc, ledtype, ledmode);
if (rsp && rsp->ccode == 0) {
led_print(argv[0], ledmode);
}
return 0;
}
/*
* handle logical entity for LED grouping
*/
lprintf(LOG_INFO, "LED %s is logical device", argv[0]);
/* get entity assoc records */
alist = ipmi_sdr_find_sdr_bytype(intf, SDR_RECORD_TYPE_ENTITY_ASSOC);
for (a = alist; a != NULL; a = a->next) {
if (a->type != SDR_RECORD_TYPE_ENTITY_ASSOC)
continue;
assoc = a->record.entassoc;
if (assoc == NULL)
continue;
/* check that the entity id/instance matches our generic record */
if (assoc->entity.id != sdr->record.genloc->entity.id ||
assoc->entity.instance != sdr->record.genloc->entity.instance)
continue;
if (assoc->flags.isrange) {
/*
* handle ranged entity associations
*
* the test for non-zero entity id is handled in
* sunoem_led_get_byentity()
*/
/* first range set - id 1 and 2 must be equal */
if (assoc->entity_id_1 == assoc->entity_id_2)
for (i = assoc->entity_inst_1; i <= assoc->entity_inst_2; i++)
sunoem_led_set_byentity(intf, assoc->entity_id_1, i, ledtype,
ledmode);
/* second range set - id 3 and 4 must be equal */
if (assoc->entity_id_3 == assoc->entity_id_4)
for (i = assoc->entity_inst_3; i <= assoc->entity_inst_4; i++)
sunoem_led_set_byentity(intf, assoc->entity_id_3, i, ledtype,
ledmode);
}
else {
/*
* handle entity list
*/
sunoem_led_set_byentity(intf, assoc->entity_id_1,
assoc->entity_inst_1, ledtype, ledmode);
sunoem_led_set_byentity(intf, assoc->entity_id_2,
assoc->entity_inst_2, ledtype, ledmode);
sunoem_led_set_byentity(intf, assoc->entity_id_3,
assoc->entity_inst_3, ledtype, ledmode);
sunoem_led_set_byentity(intf, assoc->entity_id_4,
assoc->entity_inst_4, ledtype, ledmode);
}
}
__sdr_list_empty(alist);
return 0;
}
static int
ipmi_sunoem_sshkey_del(struct ipmi_intf * intf, uint8_t uid)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
memset(&req, 0, sizeof(struct ipmi_rq));
req.msg.netfn = IPMI_NETFN_SUNOEM;
req.msg.cmd = IPMI_SUNOEM_DEL_SSH_KEY;
req.msg.data = &uid;
req.msg.data_len = 1;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to delete ssh key for UID %d", uid);
return -1;
}
else if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Unable to delete ssh key for UID %d: %s", uid,
val2str(rsp->ccode, completion_code_vals));
return -1;
}
printf("Deleted SSH key for user id %d\n", uid);
return 0;
}
#define SSHKEY_BLOCK_SIZE 64
static int
ipmi_sunoem_sshkey_set(struct ipmi_intf * intf, uint8_t uid, char * ifile)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
FILE * fp;
int count;
uint16_t i_size, r, size;
uint8_t wbuf[SSHKEY_BLOCK_SIZE + 3];
if (ifile == NULL) {
lprintf(LOG_ERR, "Invalid or misisng input filename");
return -1;
}
fp = ipmi_open_file_read(ifile);
if (fp == NULL) {
lprintf(LOG_ERR, "Unable to open file %s for reading", ifile);
return -1;
}
printf("Setting SSH key for user id %d...", uid);
memset(&req, 0, sizeof(struct ipmi_rq));
req.msg.netfn = IPMI_NETFN_SUNOEM;
req.msg.cmd = IPMI_SUNOEM_SET_SSH_KEY;
req.msg.data = wbuf;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
for (r = 0; r < size; r += i_size) {
i_size = size - r;
if (i_size > SSHKEY_BLOCK_SIZE)
i_size = SSHKEY_BLOCK_SIZE;
memset(wbuf, 0, SSHKEY_BLOCK_SIZE);
if (-1 == fseek(fp, r, SEEK_SET)) {
lprintf(LOG_ERR, "Seek error %s. %s", ifile, strerror(errno));
return -1;
}
count = fread(wbuf+3, 1, i_size, fp);
if (count != i_size) {
lprintf(LOG_ERR, "Unable to read %d bytes from file %s", i_size, ifile);
fclose(fp);
return -1;
}
printf(".");
fflush(stdout);
wbuf[0] = uid;
if ((r + SSHKEY_BLOCK_SIZE) >= size)
wbuf[1] = 0xff;
else
wbuf[1] = (uint8_t)(r / SSHKEY_BLOCK_SIZE);
wbuf[2] = i_size;
req.msg.data_len = i_size + 3;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to set ssh key for UID %d", uid);
break;
}
}
printf("done\n");
fclose(fp);
return 0;
}
int
ipmi_sunoem_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int rc = (-1);
if (argc == 0 || strncmp(argv[0], "help", 4) == 0) {
ipmi_sunoem_usage();
return 0;
}
if (strncmp(argv[0], "fan", 3) == 0) {
if (argc == 3 && strncmp(argv[1], "speed", 5) == 0) {
uint8_t pct = 0;
if (str2uchar(argv[2], &pct) != 0 || pct > 100) {
lprintf(LOG_ERR, "Fan speed is limited to range <0..100>.");
return (-1);
}
rc = ipmi_sunoem_fan_speed(intf, pct);
}
else {
ipmi_sunoem_usage();
return (-1);
}
}
else if ((strncmp(argv[0], "led", 3) == 0)
|| (strncmp(argv[0], "sbled", 5) == 0)) {
if (argc < 2) {
ipmi_sunoem_usage();
return (-1);
}
if (strncmp(argv[0], "sbled", 5) == 0) {
is_sbcmd = 1;
}
if (strncmp(argv[1], "get", 3) == 0) {
if (argc < 3) {
char * arg[] = { "all" };
rc = ipmi_sunoem_led_get(intf, 1, arg);
}
else {
rc = ipmi_sunoem_led_get(intf, argc-2, &(argv[2]));
}
}
else if (strncmp(argv[1], "set", 3) == 0) {
if (argc < 4) {
ipmi_sunoem_usage();
return (-1);
}
rc = ipmi_sunoem_led_set(intf, argc-2, &(argv[2]));
}
else {
ipmi_sunoem_usage();
return (-1);
}
}
else if (strncmp(argv[0], "sshkey", 6) == 0) {
uint8_t uid = 0;
if (argc < 3) {
ipmi_sunoem_usage();
return (-1);
}
if (str2uchar(argv[2], &uid) != 0 || uid < 1 || uid > 63) {
lprintf(LOG_ERR, "User ID is limited to range <1..63>.");
return (-1);
}
if (strncmp(argv[1], "del", 3) == 0) {
rc = ipmi_sunoem_sshkey_del(intf, uid);
}
else if (argc == 4 && strncmp(argv[1], "set", 3) == 0) {
rc = ipmi_sunoem_sshkey_set(intf, uid, argv[3]);
}
else {
ipmi_sunoem_usage();
return (-1);
}
}
else {
ipmi_sunoem_usage();
return (-1);
}
return rc;
}

608
lib/ipmi_tsol.c Normal file
View File

@@ -0,0 +1,608 @@
/*
* Copyright (c) 2005 Tyan Computer Corp. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#if defined(HAVE_CONFIG_H)
# include <config.h>
#endif
#if defined(HAVE_TERMIOS_H)
# include <termios.h>
#elif defined (HAVE_SYS_TERMIOS_H)
# include <sys/termios.h>
#endif
#include <ipmitool/log.h>
#include <ipmitool/helper.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_tsol.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/bswap.h>
static struct timeval _start_keepalive;
static struct termios _saved_tio;
static struct winsize _saved_winsize;
static int _in_raw_mode = 0;
static int _altterm = 0;
extern int verbose;
static int
ipmi_tsol_command(struct ipmi_intf * intf, char *recvip, int port, unsigned char cmd)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
unsigned char data[6];
unsigned ip1, ip2, ip3, ip4;
if (sscanf(recvip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) {
lprintf(LOG_ERR, "Invalid IP address: %s", recvip);
return -1;
}
memset(&req, 0, sizeof(struct ipmi_rq));
req.msg.netfn = IPMI_NETFN_TSOL;
req.msg.cmd = cmd;
req.msg.data_len = 6;
req.msg.data = data;
memset(data, 0, sizeof(data));
data[0] = ip1;
data[1] = ip2;
data[2] = ip3;
data[3] = ip4;
data[4] = (port & 0xff00) >> 8;
data[5] = (port & 0xff);
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to perform TSOL command");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Unable to perform TSOL command: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
return 0;
}
static int
ipmi_tsol_start(struct ipmi_intf * intf, char *recvip, int port)
{
return ipmi_tsol_command(intf, recvip, port, IPMI_TSOL_CMD_START);
}
static int
ipmi_tsol_stop(struct ipmi_intf * intf, char *recvip, int port)
{
return ipmi_tsol_command(intf, recvip, port, IPMI_TSOL_CMD_STOP);
}
static int
ipmi_tsol_send_keystroke(struct ipmi_intf * intf, char *buff, int length)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
unsigned char data[16];
static unsigned char keyseq = 0;
memset(&req, 0, sizeof(struct ipmi_rq));
req.msg.netfn = IPMI_NETFN_TSOL;
req.msg.cmd = IPMI_TSOL_CMD_SENDKEY;
req.msg.data_len = length + 2;
req.msg.data = data;
memset(data, 0, sizeof(data));
data[0] = length + 1;
memcpy(data + 1, buff, length);
data[length + 1] = keyseq++;
rsp = intf->sendrecv(intf, &req);
if (verbose) {
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to send keystroke");
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Unable to send keystroke: %s",
val2str(rsp->ccode, completion_code_vals));
return -1;
}
}
return length;
}
static int
tsol_keepalive(struct ipmi_intf * intf)
{
struct timeval end;
gettimeofday(&end, 0);
if (end.tv_sec - _start_keepalive.tv_sec <= 30)
return 0;
intf->keepalive(intf);
gettimeofday(&_start_keepalive, 0);
return 0;
}
static void
print_escape_seq(struct ipmi_intf *intf)
{
lprintf(LOG_NOTICE,
" %c. - terminate connection\n"
" %c^Z - suspend ipmitool\n"
" %c^X - suspend ipmitool, but don't restore tty on restart\n"
" %c? - this message\n"
" %c%c - send the escape character by typing it twice\n"
" (Note that escapes are only recognized immediately after newline.)",
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char,
intf->session->sol_escape_char);
}
static int
leave_raw_mode(void)
{
if (!_in_raw_mode)
return -1;
else if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1)
lperror(LOG_ERR, "tcsetattr(stdin)");
else if (tcsetattr(fileno(stdout), TCSADRAIN, &_saved_tio) == -1)
lperror(LOG_ERR, "tcsetattr(stdout)");
else
_in_raw_mode = 0;
return 0;
}
static int
enter_raw_mode(void)
{
struct termios tio;
if (tcgetattr(fileno(stdout), &_saved_tio) < 0) {
lperror(LOG_ERR, "tcgetattr failed");
return -1;
}
tio = _saved_tio;
if (_altterm) {
tio.c_iflag &= (ISTRIP | IGNBRK );
tio.c_cflag &= ~(CSIZE | PARENB | IXON | IXOFF | IXANY);
tio.c_cflag |= (CS8 |CREAD) | (IXON|IXOFF|IXANY);
tio.c_lflag &= 0;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
} else {
tio.c_iflag |= IGNPAR;
tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN);
tio.c_oflag &= ~OPOST;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
}
if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0)
lperror(LOG_ERR, "tcsetattr(stdin)");
else if (tcsetattr(fileno(stdout), TCSADRAIN, &tio) < 0)
lperror(LOG_ERR, "tcsetattr(stdout)");
else
_in_raw_mode = 1;
return 0;
}
static void
suspend_self(int restore_tty)
{
leave_raw_mode();
kill(getpid(), SIGTSTP);
if (restore_tty)
enter_raw_mode();
}
static int
do_inbuf_actions(struct ipmi_intf *intf, char *in_buff, int len)
{
static int in_esc = 0;
static int last_was_cr = 1;
int i;
for(i = 0; i < len ;) {
if (!in_esc) {
if (last_was_cr &&
(in_buff[i] == intf->session->sol_escape_char)) {
in_esc = 1;
memmove(in_buff, in_buff + 1, len - i - 1);
len--;
continue;
}
}
if (in_esc) {
if (in_buff[i] == intf->session->sol_escape_char) {
in_esc = 0;
i++;
continue;
}
switch (in_buff[i]) {
case '.':
printf("%c. [terminated ipmitool]\n",
intf->session->sol_escape_char);
return -1;
case 'Z' - 64:
printf("%c^Z [suspend ipmitool]\n",
intf->session->sol_escape_char);
suspend_self(1); /* Restore tty back to raw */
break;
case 'X' - 64:
printf("%c^X [suspend ipmitool]\n",
intf->session->sol_escape_char);
suspend_self(0); /* Don't restore to raw mode */
break;
case '?':
printf("%c? [ipmitool help]\n",
intf->session->sol_escape_char);
print_escape_seq(intf);
break;
}
memmove(in_buff, in_buff + 1, len - i - 1);
len--;
in_esc = 0;
continue;
}
last_was_cr = (in_buff[i] == '\r' || in_buff[i] == '\n');
i++;
}
return len;
}
static void
do_terminal_cleanup(void)
{
if (_saved_winsize.ws_row > 0 && _saved_winsize.ws_col > 0)
ioctl(fileno(stdout), TIOCSWINSZ, &_saved_winsize);
leave_raw_mode();
if (errno)
lprintf(LOG_ERR, "Exiting due to error %d -> %s",
errno, strerror(errno));
}
static void
set_terminal_size(int rows, int cols)
{
struct winsize winsize;
if (rows <= 0 || cols <= 0)
return;
/* save initial winsize */
ioctl(fileno(stdout), TIOCGWINSZ, &_saved_winsize);
/* set new winsize */
winsize.ws_row = rows;
winsize.ws_col = cols;
ioctl(fileno(stdout), TIOCSWINSZ, &winsize);
}
static void
print_tsol_usage(void)
{
struct winsize winsize;
lprintf(LOG_NOTICE, "Usage: tsol [recvip] [port=NUM] [ro|rw] [rows=NUM] [cols=NUM] [altterm]");
lprintf(LOG_NOTICE, " recvip Receiver IP Address [default=local]");
lprintf(LOG_NOTICE, " port=NUM Receiver UDP Port [default=%d]",
IPMI_TSOL_DEF_PORT);
lprintf(LOG_NOTICE, " ro|rw Set Read-Only or Read-Write [default=rw]");
ioctl(fileno(stdout), TIOCGWINSZ, &winsize);
lprintf(LOG_NOTICE, " rows=NUM Set terminal rows [default=%d]",
winsize.ws_row);
lprintf(LOG_NOTICE, " cols=NUM Set terminal columns [default=%d]",
winsize.ws_col);
lprintf(LOG_NOTICE, " altterm Alternate terminal setup [default=off]");
}
int
ipmi_tsol_main(struct ipmi_intf * intf, int argc, char ** argv)
{
struct pollfd fds_wait[3], fds_data_wait[3], *fds;
struct sockaddr_in sin, myaddr, *sa_in;
socklen_t mylen;
char *recvip = NULL;
char out_buff[IPMI_BUF_SIZE * 8], in_buff[IPMI_BUF_SIZE];
char buff[IPMI_BUF_SIZE + 4];
int fd_socket, result, i;
int out_buff_fill, in_buff_fill;
int ip1, ip2, ip3, ip4;
int read_only = 0, rows = 0, cols = 0;
int port = IPMI_TSOL_DEF_PORT;
if (strlen(intf->name) < 3 || strncmp(intf->name, "lan", 3) != 0) {
lprintf(LOG_ERR, "Error: Tyan SOL is only available over lan interface");
return -1;
}
for (i = 0; i<argc; i++) {
if (sscanf(argv[i], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) == 4) {
/* not free'd ...*/
/* recvip = strdup(argv[i]); */
recvip = argv[i];
}
else if (sscanf(argv[i], "port=%d", &ip1) == 1)
port = ip1;
else if (sscanf(argv[i], "rows=%d", &ip1) == 1)
rows = ip1;
else if (sscanf(argv[i], "cols=%d", &ip1) == 1)
cols = ip1;
else if (strlen(argv[i]) == 2 && strncmp(argv[i], "ro", 2) == 0)
read_only = 1;
else if (strlen(argv[i]) == 2 && strncmp(argv[i], "rw", 2) == 0)
read_only = 0;
else if (strlen(argv[i]) == 7 && strncmp(argv[i], "altterm", 7) == 0)
_altterm = 1;
else if (strlen(argv[i]) == 4 && strncmp(argv[i], "help", 4) == 0) {
print_tsol_usage();
return 0;
}
else {
print_tsol_usage();
return 0;
}
}
/* create udp socket to receive the packet */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sa_in = (struct sockaddr_in *)&intf->session->addr;
result = inet_pton(AF_INET, (const char *)intf->session->hostname,
&sa_in->sin_addr);
if (result <= 0) {
struct hostent *host = gethostbyname((const char *)intf->session->hostname);
if (host == NULL ) {
lprintf(LOG_ERR, "Address lookup for %s failed",
intf->session->hostname);
return -1;
}
if (host->h_addrtype != AF_INET) {
lprintf(LOG_ERR,
"Address lookup for %s failed. Got %s, expected IPv4 address.",
intf->session->hostname,
(host->h_addrtype == AF_INET6) ? "IPv6" : "Unknown");
return (-1);
}
sa_in->sin_family = host->h_addrtype;
memcpy(&sa_in->sin_addr, host->h_addr, host->h_length);
}
fd_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd_socket < 0) {
lprintf(LOG_ERR, "Can't open port %d", port);
return -1;
}
if (-1 == bind(fd_socket, (struct sockaddr *)&sin, sizeof(sin))) {
lprintf(LOG_ERR, "Failed to bind socket.");
close(fd_socket);
return -1;
}
/*
* retrieve local IP address if not supplied on command line
*/
if (recvip == NULL) {
result = intf->open(intf); /* must connect first */
if (result < 0) {
close(fd_socket);
return -1;
}
mylen = sizeof(myaddr);
if (getsockname(intf->fd, (struct sockaddr *)&myaddr, &mylen) < 0) {
lperror(LOG_ERR, "getsockname failed");
close(fd_socket);
return -1;
}
recvip = inet_ntoa(myaddr.sin_addr);
if (recvip == NULL) {
lprintf(LOG_ERR, "Unable to find local IP address");
close(fd_socket);
return -1;
}
}
printf("[Starting %sSOL with receiving address %s:%d]\n",
read_only ? "Read-only " : "", recvip, port);
set_terminal_size(rows, cols);
enter_raw_mode();
/*
* talk to smdc to start Console redirect - IP address and port as parameter
* ipmitool -I lan -H 192.168.168.227 -U Administrator raw 0x30 0x06 0xC0 0xA8 0xA8 0x78 0x1A 0x0A
*/
result = ipmi_tsol_start(intf, recvip, port);
if (result < 0) {
lprintf(LOG_ERR, "Error starting SOL");
close(fd_socket);
return -1;
}
printf("[SOL Session operational. Use %c? for help]\n",
intf->session->sol_escape_char);
gettimeofday(&_start_keepalive, 0);
fds_wait[0].fd = fd_socket;
fds_wait[0].events = POLLIN;
fds_wait[0].revents = 0;
fds_wait[1].fd = fileno(stdin);
fds_wait[1].events = POLLIN;
fds_wait[1].revents = 0;
fds_wait[2].fd = -1;
fds_wait[2].events = 0;
fds_wait[2].revents = 0;
fds_data_wait[0].fd = fd_socket;
fds_data_wait[0].events = POLLIN | POLLOUT;
fds_data_wait[0].revents = 0;
fds_data_wait[1].fd = fileno(stdin);
fds_data_wait[1].events = POLLIN;
fds_data_wait[1].revents = 0;
fds_data_wait[2].fd = fileno(stdout);
fds_data_wait[2].events = POLLOUT;
fds_data_wait[2].revents = 0;
out_buff_fill = 0;
in_buff_fill = 0;
fds = fds_wait;
for (;;) {
result = poll(fds, 3, 15*1000);
if (result < 0)
break;
/* send keepalive packet */
tsol_keepalive(intf);
if ((fds[0].revents & POLLIN) && (sizeof(out_buff) > out_buff_fill)){
socklen_t sin_len = sizeof(sin);
result = recvfrom(fd_socket, buff, sizeof(out_buff) - out_buff_fill + 4, 0,
(struct sockaddr *)&sin, &sin_len);
/* read the data from udp socket, skip some bytes in the head */
if((result - 4) > 0 ){
int length = result - 4;
#if 1
length = (unsigned char)buff[2] & 0xff;
length *= 256;
length += ((unsigned char)buff[3] & 0xff);
if ((length <= 0) || (length > (result - 4)))
length = result - 4;
#endif
memcpy(out_buff + out_buff_fill, buff + 4, length);
out_buff_fill += length;
}
}
if ((fds[1].revents & POLLIN) && (sizeof(in_buff) > in_buff_fill)) {
result = read(fileno(stdin), in_buff + in_buff_fill,
sizeof(in_buff) - in_buff_fill); // read from keyboard
if (result > 0) {
int bytes;
bytes = do_inbuf_actions(intf, in_buff + in_buff_fill, result);
if(bytes < 0) {
result = ipmi_tsol_stop(intf, recvip, port);
do_terminal_cleanup();
return result;
}
if (read_only)
bytes = 0;
in_buff_fill += bytes;
}
}
if ((fds[2].revents & POLLOUT) && out_buff_fill) {
result = write(fileno(stdout), out_buff, out_buff_fill); // to screen
if (result > 0) {
out_buff_fill -= result;
if (out_buff_fill) {
memmove(out_buff, out_buff + result, out_buff_fill);
}
}
}
if ((fds[0].revents & POLLOUT) && in_buff_fill) {
/*
* translate key and send that to SMDC using IPMI
* ipmitool -I lan -H 192.168.168.227 -U Administrator raw 0x30 0x03 0x04 0x1B 0x5B 0x43
*/
result = ipmi_tsol_send_keystroke(intf, in_buff, __min(in_buff_fill,14));
if (result > 0) {
gettimeofday(&_start_keepalive, 0);
in_buff_fill -= result;
if (in_buff_fill) {
memmove(in_buff, in_buff + result, in_buff_fill);
}
}
}
fds = (in_buff_fill || out_buff_fill )?
fds_data_wait : fds_wait;
}
return 0;
}

836
lib/ipmi_user.c Normal file
View File

@@ -0,0 +1,836 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_user.h>
#include <ipmitool/ipmi_constants.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/bswap.h>
extern int verbose;
extern int csv_output;
#define IPMI_PASSWORD_DISABLE_USER 0x00
#define IPMI_PASSWORD_ENABLE_USER 0x01
#define IPMI_PASSWORD_SET_PASSWORD 0x02
#define IPMI_PASSWORD_TEST_PASSWORD 0x03
/*
* ipmi_get_user_access
*
* param intf [in]
* param channel_number [in]
* param user_id [in]
* param user_access [out]
*
* return 0 on succes
* 1 on failure
*/
static int
ipmi_get_user_access(
struct ipmi_intf *intf,
uint8_t channel_number,
uint8_t user_id,
struct user_access_rsp *user_access)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[2];
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_GET_USER_ACCESS; /* 0x44 */
req.msg.data = msg_data;
req.msg.data_len = 2;
/* The channel number will remain constant throughout this function */
msg_data[0] = channel_number;
msg_data[1] = user_id;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Get User Access command failed "
"(channel %d, user %d)", channel_number, user_id);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Get User Access command failed "
"(channel %d, user %d): %s", channel_number, user_id,
val2str(rsp->ccode, completion_code_vals));
return -1;
}
memcpy(user_access,
rsp->data,
sizeof(struct user_access_rsp));
return 0;
}
/*
* ipmi_get_user_name
*
* param intf [in]
* param channel_number [in]
* param user_id [in]
* param user_name [out]
*
* return 0 on succes
* 1 on failure
*/
static int
ipmi_get_user_name(
struct ipmi_intf *intf,
uint8_t user_id,
char *user_name)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[1];
memset(user_name, 0, 17);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_GET_USER_NAME; /* 0x45 */
req.msg.data = msg_data;
req.msg.data_len = 1;
msg_data[0] = user_id;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Get User Name command failed (user %d)",
user_id);
return -1;
}
if (rsp->ccode > 0) {
if (rsp->ccode == 0xcc)
return 0;
lprintf(LOG_ERR, "Get User Name command failed (user %d): %s",
user_id, val2str(rsp->ccode, completion_code_vals));
return -1;
}
memcpy(user_name, rsp->data, 16);
return 0;
}
static void
dump_user_access(
uint8_t user_id,
const char * user_name,
struct user_access_rsp * user_access)
{
static int printed_header = 0;
if (! printed_header)
{
printf("ID Name Callin Link Auth IPMI Msg "
"Channel Priv Limit\n");
printed_header = 1;
}
printf("%-4d%-17s%-8s%-11s%-11s%-s\n",
user_id,
user_name,
user_access->no_callin_access? "false": "true ",
user_access->link_auth_access? "true ": "false",
user_access->ipmi_messaging_access? "true ": "false",
val2str(user_access->channel_privilege_limit,
ipmi_privlvl_vals));
}
static void
dump_user_access_csv(
uint8_t user_id,
const char *user_name,
struct user_access_rsp *user_access)
{
printf("%d,%s,%s,%s,%s,%s\n",
user_id,
user_name,
user_access->no_callin_access? "false": "true",
user_access->link_auth_access? "true": "false",
user_access->ipmi_messaging_access? "true": "false",
val2str(user_access->channel_privilege_limit,
ipmi_privlvl_vals));
}
static int
ipmi_print_user_list(
struct ipmi_intf *intf,
uint8_t channel_number)
{
/* This is where you were! */
char user_name[17];
struct user_access_rsp user_access;
uint8_t current_user_id = 1;
do
{
if (ipmi_get_user_access(intf,
channel_number,
current_user_id,
&user_access))
return -1;
if (ipmi_get_user_name(intf,
current_user_id,
user_name))
return -1;
if ((current_user_id == 0) ||
user_access.link_auth_access ||
user_access.ipmi_messaging_access ||
strcmp("", user_name))
{
if (csv_output)
dump_user_access_csv(current_user_id,
user_name, &user_access);
else
dump_user_access(current_user_id,
user_name,
&user_access);
}
++current_user_id;
} while((current_user_id <= user_access.maximum_ids) &&
(current_user_id <= IPMI_UID_MAX)); /* Absolute maximum allowed by spec */
return 0;
}
static int
ipmi_print_user_summary(
struct ipmi_intf * intf,
uint8_t channel_number)
{
struct user_access_rsp user_access;
if (ipmi_get_user_access(intf,
channel_number,
1,
&user_access))
return -1;
if (csv_output)
{
printf("%d,%d,%d\n",
user_access.maximum_ids,
user_access.enabled_user_count,
user_access.fixed_name_count);
}
else
{
printf("Maximum IDs : %d\n",
user_access.maximum_ids);
printf("Enabled User Count : %d\n",
user_access.enabled_user_count);
printf("Fixed Name Count : %d\n",
user_access.fixed_name_count);
}
return 0;
}
/*
* ipmi_user_set_username
*/
static int
ipmi_user_set_username(
struct ipmi_intf *intf,
uint8_t user_id,
const char *name)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[17];
/*
* Ensure there is space for the name in the request message buffer
*/
if (strlen(name) >= sizeof(msg_data)) {
return -1;
}
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_SET_USER_NAME; /* 0x45 */
req.msg.data = msg_data;
req.msg.data_len = sizeof(msg_data);
memset(msg_data, 0, sizeof(msg_data));
/* The channel number will remain constant throughout this function */
msg_data[0] = user_id;
strncpy((char *)(msg_data + 1), name, strlen(name));
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Set User Name command failed (user %d, name %s)",
user_id, name);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Set User Name command failed (user %d, name %s): %s",
user_id, name, val2str(rsp->ccode, completion_code_vals));
return -1;
}
return 0;
}
static int
ipmi_user_set_userpriv(
struct ipmi_intf *intf,
uint8_t channel,
uint8_t user_id,
const unsigned char privLevel)
{
struct ipmi_rs *rsp;
struct ipmi_rq req;
uint8_t msg_data[4] = {0, 0, 0, 0};
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_SET_USER_ACCESS; /* 0x43 */
req.msg.data = msg_data;
req.msg.data_len = 4;
/* The channel number will remain constant throughout this function */
msg_data[0] = (channel & 0x0f);
msg_data[1] = (user_id & 0x3f);
msg_data[2] = (privLevel & 0x0f);
msg_data[3] = 0;
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL)
{
lprintf(LOG_ERR, "Set Privilege Level command failed (user %d)",
user_id);
return -1;
}
if (rsp->ccode > 0)
{
lprintf(LOG_ERR, "Set Privilege Level command failed (user %d): %s",
user_id, val2str(rsp->ccode, completion_code_vals));
return -1;
}
return 0;
}
/*
* ipmi_user_set_password
*
* This function is responsible for 4 things
* Enabling/Disabling users
* Setting/Testing passwords
*/
static int
ipmi_user_set_password(
struct ipmi_intf * intf,
uint8_t user_id,
uint8_t operation,
const char *password,
int is_twenty_byte_password)
{
struct ipmi_rs * rsp;
struct ipmi_rq req;
uint8_t msg_data[22];
int password_length = (is_twenty_byte_password? 20 : 16);
memset(&req, 0, sizeof(req));
req.msg.netfn = IPMI_NETFN_APP; /* 0x06 */
req.msg.cmd = IPMI_SET_USER_PASSWORD; /* 0x47 */
req.msg.data = msg_data;
req.msg.data_len = password_length + 2;
/* The channel number will remain constant throughout this function */
msg_data[0] = user_id;
if (is_twenty_byte_password)
msg_data[0] |= 0x80;
msg_data[1] = operation;
memset(msg_data + 2, 0, password_length);
if (password != NULL)
strncpy((char *)(msg_data + 2), password, password_length);
rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Set User Password command failed (user %d)",
user_id);
return -1;
}
if (rsp->ccode > 0) {
lprintf(LOG_ERR, "Set User Password command failed (user %d): %s",
user_id, val2str(rsp->ccode, completion_code_vals));
return rsp->ccode;
}
return 0;
}
/*
* ipmi_user_test_password
*
* Call ipmi_user_set_password, and interpret the result
*/
static int
ipmi_user_test_password(
struct ipmi_intf * intf,
uint8_t user_id,
const char * password,
int is_twenty_byte_password)
{
int ret;
ret = ipmi_user_set_password(intf,
user_id,
IPMI_PASSWORD_TEST_PASSWORD,
password,
is_twenty_byte_password);
switch (ret) {
case 0:
printf("Success\n");
break;
case 0x80:
printf("Failure: password incorrect\n");
break;
case 0x81:
printf("Failure: wrong password size\n");
break;
default:
printf("Unknown error\n");
}
return ((ret == 0) ? 0 : -1);
}
/*
* print_user_usage
*/
static void
print_user_usage(void)
{
lprintf(LOG_NOTICE, "User Commands:");
lprintf(LOG_NOTICE, " summary [<channel number>]");
lprintf(LOG_NOTICE, " list [<channel number>]");
lprintf(LOG_NOTICE, " set name <user id> <username>");
lprintf(LOG_NOTICE, " set password <user id> [<password>]");
lprintf(LOG_NOTICE, " disable <user id>");
lprintf(LOG_NOTICE, " enable <user id>");
lprintf(LOG_NOTICE,
" priv <user id> <privilege level> [<channel number>]");
lprintf(LOG_NOTICE, " test <user id> <16|20> [<password]>\n");
}
const char *
ipmi_user_build_password_prompt(uint8_t user_id)
{
static char prompt[128];
memset(prompt, 0, 128);
snprintf(prompt, 128, "Password for user %d: ", user_id);
return prompt;
}
/*
* ipmi_user_main
*
* Upon entry to this function argv should contain our arguments
* specific to this subcommand
*/
int
ipmi_user_main(struct ipmi_intf * intf, int argc, char ** argv)
{
int retval = 0;
/*
* Help
*/
if (argc == 0 || strncmp(argv[0], "help", 4) == 0)
{
print_user_usage();
}
/*
* Summary
*/
else if (strncmp(argv[0], "summary", 7) == 0)
{
uint8_t channel;
if (argc == 1)
channel = 0x0E; /* Ask about the current channel */
else if (argc == 2)
{
if (str2uchar(argv[1], &channel) != 0)
{
lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
return (-1);
}
}
else
{
print_user_usage();
return -1;
}
retval = ipmi_print_user_summary(intf, channel);
}
/*
* List
*/
else if (strncmp(argv[0], "list", 4) == 0)
{
uint8_t channel;
if (argc == 1)
channel = 0x0E; /* Ask about the current channel */
else if (argc == 2)
{
if (str2uchar(argv[1], &channel) != 0)
{
lprintf(LOG_ERR, "Invalid channel: %s", argv[1]);
return (-1);
}
}
else
{
print_user_usage();
return -1;
}
retval = ipmi_print_user_list(intf, channel);
}
/*
* Test
*/
else if (strncmp(argv[0], "test", 4) == 0)
{
// a little irritating, isn't it
if (argc == 3 || argc == 4)
{
char * password = NULL;
int password_length = 0;
uint8_t user_id = 0;
if (is_ipmi_user_id(argv[1], &user_id)) {
return (-1);
}
if (str2int(argv[2], &password_length) != 0
|| (password_length != 16 && password_length != 20)) {
lprintf(LOG_ERR,
"Given password length '%s' is invalid.",
argv[2]);
lprintf(LOG_ERR, "Expected value is either 16 or 20.");
return (-1);
}
if (argc == 3)
{
/* We need to prompt for a password */
char * tmp;
const char * password_prompt =
ipmi_user_build_password_prompt(user_id);
# ifdef HAVE_GETPASSPHRASE
tmp = getpassphrase (password_prompt);
# else
tmp = (char*)getpass (password_prompt);
# endif
if (tmp != NULL) {
password = strdup(tmp);
tmp = NULL;
}
if (password == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return -1;
}
}
else {
password = strdup(argv[3]);
}
retval = ipmi_user_test_password(intf,
user_id,
password,
password_length == 20);
if (password != NULL) {
free(password);
password = NULL;
}
}
else
{
print_user_usage();
return -1;
}
}
/*
* Set
*/
else if (strncmp(argv[0], "set", 3) == 0)
{
/*
* Set Password
*/
if ((argc >= 3) &&
(strncmp("password", argv[1], 8) == 0))
{
char * password = NULL;
uint8_t user_id = 0;
if (is_ipmi_user_id(argv[2], &user_id)) {
return (-1);
}
if (argc == 3)
{
/* We need to prompt for a password */
char * tmp;
const char * password_prompt =
ipmi_user_build_password_prompt(user_id);
# ifdef HAVE_GETPASSPHRASE
tmp = getpassphrase (password_prompt);
# else
tmp = (char*)getpass (password_prompt);
# endif
if (tmp != NULL) {
password = strdup(tmp);
tmp = NULL;
}
if (password == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return -1;
}
# ifdef HAVE_GETPASSPHRASE
tmp = getpassphrase (password_prompt);
# else
tmp = (char*)getpass (password_prompt);
# endif
if (tmp == NULL) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return (-1);
}
if (strlen(password) != strlen(tmp)
|| strncmp(password, tmp, strlen(tmp))) {
lprintf(LOG_ERR, "Passwords do not match.");
free(password);
password = NULL;
return -1;
}
tmp = NULL;
} else {
password = strdup(argv[3]);
}
if (password == NULL) {
lprintf(LOG_ERR, "Unable to parse password argument.");
return -1;
}
else if (strlen(password) > 20)
{
lprintf(LOG_ERR, "Password is too long (> 20 bytes)");
return -1;
}
retval = ipmi_user_set_password(intf,
user_id,
IPMI_PASSWORD_SET_PASSWORD,
password,
strlen(password) > 16);
if (password != NULL) {
free(password);
password = NULL;
}
}
/*
* Set Name
*/
else if ((argc >= 2) &&
(strncmp("name", argv[1], 4) == 0))
{
uint8_t user_id = 0;
if (argc != 4)
{
print_user_usage();
return -1;
}
if (is_ipmi_user_id(argv[2], &user_id)) {
return (-1);
}
if (strlen(argv[3]) > 16)
{
lprintf(LOG_ERR, "Username is too long (> 16 bytes)");
return -1;
}
retval = ipmi_user_set_username(intf, user_id, argv[3]);
}
else
{
print_user_usage();
return -1;
}
}
else if (strncmp(argv[0], "priv", 4) == 0)
{
uint8_t user_id;
uint8_t priv_level;
uint8_t channel = 0x0e; /* Use channel running on */
if (argc != 3 && argc != 4)
{
print_user_usage();
return -1;
}
if (argc == 4)
{
if (str2uchar(argv[3], &channel) != 0)
{
lprintf(LOG_ERR, "Invalid channel: %s", argv[3]);
return (-1);
}
channel = (channel & 0x0f);
}
if (str2uchar(argv[2], &priv_level) != 0)
{
lprintf(LOG_ERR, "Invalid privilege level: %s", argv[2]);
return (-1);
}
priv_level = (priv_level & 0x0f);
if (is_ipmi_user_id(argv[1], &user_id)) {
return (-1);
}
retval = ipmi_user_set_userpriv(intf,channel,user_id,priv_level);
}
/*
* Disable / Enable
*/
else if ((strncmp(argv[0], "disable", 7) == 0) ||
(strncmp(argv[0], "enable", 6) == 0))
{
uint8_t user_id;
uint8_t operation;
char null_password[16]; /* Not used, but required */
memset(null_password, 0, sizeof(null_password));
if (argc != 2)
{
print_user_usage();
return -1;
}
if (is_ipmi_user_id(argv[1], &user_id)) {
return (-1);
}
operation = (strncmp(argv[0], "disable", 7) == 0) ?
IPMI_PASSWORD_DISABLE_USER : IPMI_PASSWORD_ENABLE_USER;
retval = ipmi_user_set_password(intf,
user_id,
operation,
null_password,
0); /* This field is ignored */
}
else
{
retval = -1;
lprintf(LOG_ERR, "Invalid user command: '%s'\n", argv[0]);
print_user_usage();
}
return retval;
}

156
lib/log.c Normal file
View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <ipmitool/log.h>
struct logpriv_s {
char * name;
int daemon;
int level;
};
struct logpriv_s *logpriv;
static void log_reinit(void)
{
log_init(NULL, 0, 0);
}
void lprintf(int level, const char * format, ...)
{
static char logmsg[LOG_MSG_LENGTH];
va_list vptr;
if (!logpriv)
log_reinit();
if (logpriv->level < level)
return;
va_start(vptr, format);
vsnprintf(logmsg, LOG_MSG_LENGTH, format, vptr);
va_end(vptr);
if (logpriv->daemon)
syslog(level, "%s", logmsg);
else
fprintf(stderr, "%s\n", logmsg);
return;
}
void lperror(int level, const char * format, ...)
{
static char logmsg[LOG_MSG_LENGTH];
va_list vptr;
if (!logpriv)
log_reinit();
if (logpriv->level < level)
return;
va_start(vptr, format);
vsnprintf(logmsg, LOG_MSG_LENGTH, format, vptr);
va_end(vptr);
if (logpriv->daemon)
syslog(level, "%s: %s", logmsg, strerror(errno));
else
fprintf(stderr, "%s: %s\n", logmsg, strerror(errno));
return;
}
/*
* open connection to syslog if daemon
*/
void log_init(const char * name, int isdaemon, int verbose)
{
if (logpriv)
return;
logpriv = malloc(sizeof(struct logpriv_s));
if (!logpriv)
return;
if (name != NULL)
logpriv->name = strdup(name);
else
logpriv->name = strdup(LOG_NAME_DEFAULT);
if (logpriv->name == NULL)
fprintf(stderr, "ipmitool: malloc failure\n");
logpriv->daemon = isdaemon;
logpriv->level = verbose + LOG_NOTICE;
if (logpriv->daemon)
openlog(logpriv->name, LOG_CONS, LOG_LOCAL4);
}
/*
* stop syslog logging if daemon mode,
* free used memory that stored log service
*/
void log_halt(void)
{
if (!logpriv)
return;
if (logpriv->name) {
free(logpriv->name);
logpriv->name = NULL;
}
if (logpriv->daemon)
closelog();
free(logpriv);
logpriv = NULL;
}
int log_level_get(void)
{
return logpriv->level;
}
void log_level_set(int level)
{
logpriv->level = level;
}