summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Knight <rjknight@us.ibm.com>2014-10-27 18:14:07 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2014-11-17 12:02:50 -0600
commitc64777ce5b38e87e02850bdbf480b100fe32df45 (patch)
tree774625afaa3ff2d03e0f4a12514ce1e84721459c
parent87b7664dd21fe492c0ff70b86ea53a661216663e (diff)
downloadblackbird-hostboot-c64777ce5b38e87e02850bdbf480b100fe32df45.tar.gz
blackbird-hostboot-c64777ce5b38e87e02850bdbf480b100fe32df45.zip
Update present/functional state for DIMMs/COREs/PROCs
add interfaces to handle updating various sensors use new interfaces to update sensor state for DIMM/CORE/PROC targets. Change-Id: I71a5792f80617b1baa46319565c6742507a0b667 RTC:108827 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14207 Tested-by: Jenkins Server Reviewed-by: Brian H. Horton <brianh@linux.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/include/usr/ipmi/ipmi_reasoncodes.H7
-rw-r--r--src/include/usr/ipmi/ipmiif.H14
-rw-r--r--src/include/usr/ipmi/ipmisensor.H555
-rw-r--r--src/usr/hwas/common/deconfigGard.C24
-rw-r--r--src/usr/hwas/hostbootIstep.C13
-rw-r--r--src/usr/ipmi/ipmisensor.C669
-rw-r--r--src/usr/ipmi/makefile1
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types.xml4
8 files changed, 1281 insertions, 6 deletions
diff --git a/src/include/usr/ipmi/ipmi_reasoncodes.H b/src/include/usr/ipmi/ipmi_reasoncodes.H
index 3e66dbcd8..4ac310db3 100644
--- a/src/include/usr/ipmi/ipmi_reasoncodes.H
+++ b/src/include/usr/ipmi/ipmi_reasoncodes.H
@@ -33,6 +33,7 @@ namespace IPMI
{
MOD_IPMISRV_SEND = 0x01, // IPMI::send/IPMI::sendrecv
MOD_IPMISRV_REPLY = 0x02, // IPMI::respond
+ MOD_IPMISENSOR = 0x03, // IPMI::sensor
};
enum IPMIReasonCode
@@ -42,6 +43,12 @@ namespace IPMI
RC_INVALID_SEND = IPMI_COMP_ID | 0x03,
RC_WAITER_NOT_FOUND = IPMI_COMP_ID | 0x04,
RC_ASYNC_BAD_CC = IPMI_COMP_ID | 0x05,
+ RC_INVALID_SENSOR_CMD = IPMI_COMP_ID | 0x06,
+ RC_SENSOR_NOT_SETTABLE = IPMI_COMP_ID | 0x07,
+ RC_EVENT_DATA_NOT_SETTABLE = IPMI_COMP_ID | 0x08,
+ RC_SENSOR_NOT_PRESENT = IPMI_COMP_ID | 0x09,
+ RC_SET_SENSOR_FAILURE = IPMI_COMP_ID | 0x0a,
+
};
};
diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H
index 040244041..5c6bb6ee8 100644
--- a/src/include/usr/ipmi/ipmiif.H
+++ b/src/include/usr/ipmi/ipmiif.H
@@ -79,6 +79,8 @@ namespace IPMI
enum completion_code
{
CC_OK = 0x00,
+ CC_CMDSPC1 = 0x80, // command specific completion code
+ CC_CMDSPC2 = 0x81, // command specific completion code
CC_BUSY = 0xc0,
CC_INVALID = 0xc1,
CC_CMDLUN = 0xc2,
@@ -121,16 +123,21 @@ namespace IPMI
inline const command_t get_capabilities(void)
{ return std::make_pair(NETFUN_APP, 0x36); }
-
// Storage messages
inline const command_t set_sel_time(void)
{ return std::make_pair(NETFUN_STORAGE, 0x49); }
-
- // Sensor messages
+ // event messages
inline const command_t platform_event(void)
{ return std::make_pair(NETFUN_SENSOR, 0x02); }
+ // sensor messages
+ inline const command_t set_sensor_reading(void)
+ { return std::make_pair(NETFUN_SENSOR, 0x30); }
+
+ // sensor messages
+ inline const command_t get_sensor_reading(void)
+ { return std::make_pair(NETFUN_SENSOR, 0x2D); }
// Some helper messages
// Used to create an empty message for reception
@@ -200,6 +207,7 @@ namespace IPMI
*/
inline size_t max_buffer(void);
+
}; // end namespace IPMI
#endif
diff --git a/src/include/usr/ipmi/ipmisensor.H b/src/include/usr/ipmi/ipmisensor.H
new file mode 100644
index 000000000..74e9da09f
--- /dev/null
+++ b/src/include/usr/ipmi/ipmisensor.H
@@ -0,0 +1,555 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/include/usr/ipmi/ipmisensor.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file ipmisensor.H
+ *
+ * @brief Interface for the Sensor class
+ *
+ * This header file contains the interfaces for the sensor class which
+ * is used to handle setting the virtual sensors maintained by the BMC.
+ */
+
+#include <attributeenums.H>
+#include <targeting/common/target.H>
+#include <errl/errlentry.H>
+#include <targeting/common/targetservice.H>
+#include <ipmi/ipmiif.H>
+
+#ifndef __IPMI_IPMISENSOR_H
+#define __IPMI_IPMISENSOR_H
+
+namespace SENSOR
+{
+ //** Bit definition for set sensor reading cmd operation field
+ // [7:6] 10b - write given values to event data bytes let BMC handle
+ // offset in event data 1 when an external event is
+ // triggered based on the new data.
+ // [5:4] 10b - a one causes a one in the corresponding position of
+ // the event assertion bits, zeros are ignored.
+ // [3:2] 10b - a one causes a one in the corresponding position of
+ // the event deassertion bits, zeros are ignored.
+ // [0:1] 01b - write the given value to the sensor reading byte.
+ //
+ // default operation = 1010 1001
+ static const uint8_t DEFAULT_OPERATION = 0xA9; // see IPMI Spec. "Set
+ // Sensor Reading and Event
+ // Status command" for
+ // details on this byte.
+
+
+ // sensors have the range 0x0-0xFE - 0xFF is reserved for invalid sensor
+ static const uint16_t INVALID_SENSOR = 0xFF;
+
+ /**
+ * @struct set_sensor_reading_request
+ * structure holding the data for the set sensor reading command which
+ * Hostboot will send to the BMC to update sensor status/readings.
+ *
+ */
+ struct setSensorReadingRequest
+ {
+ uint8_t iv_sensor_number;
+ uint8_t iv_operation;
+ uint8_t iv_sensor_reading;
+ uint16_t iv_assertion_mask;
+ uint16_t iv_deassertion_mask;
+ uint8_t iv_event_data[3];
+
+ // constructor for our data set
+ setSensorReadingRequest()
+ :iv_sensor_number(0),iv_operation(DEFAULT_OPERATION),
+ iv_sensor_reading(0), iv_assertion_mask(0), iv_deassertion_mask(0)
+ {
+ memset(iv_event_data,0, sizeof(iv_event_data));
+ };
+ }PACKED;
+
+
+ /**
+ * @enum completionCode
+ * Sensor specific completion codes, defined in IPMI Spec.
+ *
+ */
+ enum completionCode
+ {
+ CC_SENSOR_READING_NOT_SETTABLE = 0x80,
+ CC_EVENT_DATA_BYTES_NOT_SETTABLE = 0x81
+ };
+
+ /**
+ * @enum procStatusSensorOffsets
+ * Sensor specific completion codes, defined in IPMI Spec.
+ *
+ */
+ enum procStatusSensorOfffsets
+ {
+ PROC_PRESENT = 0x07,
+ PROC_FUNCTIONAL_OFFSET = 0x08,
+ };
+
+ /**
+ * @enum dimmStatusSensorOffsets
+ * Dimm specific offsets for status sensor, defined in IPMI Spec.
+ *
+ */
+ enum dimmStatusSensorOffsets
+ {
+ DIMM_PRESENT_OFFSET = 0x06,
+ DIMM_FUNCTIONAL_OFFSET = 0x04,
+ };
+
+ /**
+ * @class SensorBase
+ *
+ * @brief Base class for sensors
+ *
+ * @par Detailed Description:
+ * Provides the base functionality to set IPMI sensor from Hostboot
+ * including finding the sensor number given a specific target type.
+ * The constructor takes a SENSOR_NAME and a target pointer. If a null
+ * is passed in as the target pointer, the system target will be used
+ * to search for the requested sensor name.
+ */
+ class SensorBase
+ {
+
+ public:
+ /**
+ * @brief Generic base class constructor for sensor objects
+ *
+ * @brief Base class for sensor derivation - takes a sensor name,
+ * and a target* as input.
+ *
+ * @par Detailed Description:
+ */
+ SensorBase(TARGETING::SENSOR_NAME i_name,
+ TARGETING::Target * i_target);
+
+ /**
+ * @brief Destructor for the base sensor object
+ *
+ * Destroys the sensor object and any owned resources, does not
+ * alter the state on the BMC
+ *
+ * @post Sensor object is destroyed, and all resources are
+ * reclaimed
+ */
+ virtual ~SensorBase();
+
+ // low level communication to update sensor readings on the BMC
+
+ /**
+ * @brief write sensor data
+ * Low level interface to send the set sensor and event data
+ * reading command to the BMC through the BT interface.
+ *
+ * @return Errorlog handle
+ *
+ */
+ virtual errlHndl_t writeSensorData();
+
+ /**
+ * @brief read sensor data
+ * Low level interface to send get sensor and event data reading
+ * command to the BMC through the BT interface.
+ *
+ * @param[out] o_data - buffer containing the response data from the
+ * BMC,
+ * NOTE: caller is responsible for deleting the memory pointed to
+ * by o_data.
+ *
+ * @return Errorlog handle
+ *
+ */
+ virtual errlHndl_t readSensorData(uint8_t *& o_data);
+
+
+ /**
+ * @brief process completion codes
+ * Converts completion code values returned from the IPMI
+ * transport layer into an error log.
+ *
+ * @param[in] i_cc - completion code returned from the IPMI
+ * transport layer.
+ *
+ * @return Errorlog handle
+ *
+ */
+ errlHndl_t processCompletionCode(IPMI::completion_code i_cc);
+
+ /**
+ * @brief Send set sensor reading and event status command
+ * Helper function to send the sensor reading to the BMC, this
+ * command executes synchronously.
+ *
+ * @param[inout] io_data - Initially contains the command and data
+ * to send to the BMC, will hold the BMC
+ * response when the command returns.
+ *
+ * @param[out] o_completion_code - Return value defined by the IPMI
+ * spec and returned in the message
+ * from the BMC to indicate if the
+ * command processing completed
+ * successfully.
+ *
+ * @return Errorlog handle
+ *
+ */
+ errlHndl_t sendSetSensorReading(
+ setSensorReadingRequest *& io_data,
+ IPMI::completion_code& o_completion_code );
+
+ protected:
+
+ /**
+ * @brief setup mask for event assertion/deassertion
+ *
+ * Translate the passed in offset into a mask for use in
+ * as an assertion or deassertion mask.
+ *
+ * @param[in] = i_offset - offset for event do be signaled
+ *
+ * @return eventMask - event status mask with correctly set bit
+ * matching the offset passed in.
+ *
+ */
+ static uint16_t setMask( uint8_t i_offset );
+
+ /**
+ * @brief return the event offset from an assertion/deassertion mask
+ *
+ * Translate the assertion/deassertion mask into the correct event
+ * offset.
+ *
+ * @param[in] = i_mask - offset for event do be signaled
+ *
+ * @return offset - offset of the bit which is set in the passed in
+ * mask.
+ *
+ */
+ static uint8_t getOffset( uint16_t i_mask );
+
+ // Name of this sensor, name is used to find the sensor number in
+ // the IPMI_SENSORS attribute.
+ TARGETING::SENSOR_NAME iv_name;
+
+ // Target associated with this sensor.
+ TARGETING::Target * iv_target;
+
+ // data structure for the send sensor reading command.
+ setSensorReadingRequest * iv_msg;
+
+ private:
+ //disable default constructor, copy constructor and the assignment
+ // operator.
+ SensorBase();
+
+ SensorBase& operator=(const SensorBase& i_right);
+
+ SensorBase(const SensorBase& thing );
+
+ // helper function to get sensor number attribute
+ // of passed in target
+ uint16_t getSensorNumber();
+
+ };
+
+ /**
+ * @class FirmwareProgressSensor
+ *
+ * @brief Specialized sensor class for the firmware progress sensor
+ *
+ * @par Detailed Description:
+ * Provides the functionality needed to set the firmware progress
+ * virtual sensor maintained by the BMC.
+ */
+ class FirmwareProgressSensor : public SensorBase
+ {
+
+ public:
+
+ /**
+ * @enum firmwareProgressPhase
+ *
+ * Current firmware progress phase
+ *
+ */
+ enum firmwareProgressPhase
+ {
+ MEMORY_INIT = 0x01, //< isteps 10->14
+ SEC_PROCESSOR_INIT = 0x03, //< isteps 15->16
+ STARTING_OS = 0x13, //< isteps 17->21
+ BASE_INITIALIZATION = 0x14, //< isteps 6-> 9
+ PHASE_NA = 0xFF, // Not applicable
+
+ };
+
+ /**
+ * @brief Constructor for the FirmwareProgressSensor
+ *
+ * The firmware progress sensor is used to update the BMC
+ * with the current firmware phase.
+ * The system target holds the IPMI sensor number for this sensor.
+ *
+ */
+ FirmwareProgressSensor();
+
+ /**
+ * @brief destructor for the FirmwareProgressSensor
+ *
+ * The firmware progress sensor is used to update the BMC
+ */
+ ~FirmwareProgressSensor();
+
+ /**
+ *
+ * @brief Set the current firmware boot progress phase
+ * Interface used to update the event status for the system
+ * firmware progress sensor. phases are defined by the enum
+ * firmware_progress_phase. Further information can be found in
+ * the IPMI specification.
+ *
+ * @param[in] i_phase - current firmware progress phase.
+ *
+ * @return Errorlog handle
+ *
+ */
+ errlHndl_t setBootProgressPhase(firmwareProgressPhase i_phase);
+
+ private:
+ // @enum firmwareProgressOfsets
+ //
+ // sensor specific offset used to specify that the event which is
+ // being signaled is for the system firmware progress sensor.
+ enum firmwareProgressOffsets
+ {
+ SYSTEM_FIRMWARE_PROGRESS = 0x02 //< Sensor specific offset
+ //< for system firmware
+ //< progress event.
+ };
+
+ };
+
+ /**
+ * @class HostStatusSensor
+ *
+ * @brief Specialized class for the host status sensor.
+ *
+ * @par Detailed Description:
+ * Provides the functionality needed to set the Host_Status sensor also
+ * known as the ACPI power state. The Host_status sensor is a virtual
+ * sensor maintained by the BMC,
+ */
+ class HostStatusSensor : public SensorBase
+ {
+ public:
+
+ /**
+ * @enum hostStatus
+ * enum to define the ACPI power state of the system, this
+ * sensor will be updated by Hostboot and opal.
+ */
+ enum hostStatus
+ {
+ S0_G0_WORKING = 0x00, //< Host up
+ S5_G2_SOFT_OFF = 0x05, //< Soft power off
+ LEGACY_ON_STATE = 0x0B //< Host not up, but started
+ };
+
+ /**
+ * @brief Constructor for the HostStatusSensor
+ *
+ * The firmware progress sensor is used to update the BMC
+ * with the current ACIP power state of the system.
+ * The system target holds the IPMI sensor number for this sensor.
+ *
+ */
+ HostStatusSensor();
+
+ /**
+ * @brief Destructor for the HostStatusSensor
+ *
+ */
+ ~HostStatusSensor();
+
+ /**
+ *
+ * @brief Set the current HostStatus
+ * Interface used to update the event status for the ACPI
+ * power state of the system. States are defined by the enum
+ * host_status. Further information can be found in the IPMI
+ * specification.
+ *
+ *
+ * @param[in] i_phase - current firmware progress phase.
+ *
+ * @return Errorlog handle
+ *
+ */
+ errlHndl_t updateHostStatus( hostStatus status );
+
+ };
+
+ /**
+ * @class RebootCountSensor
+ *
+ * @brief Specialized class for the system reboot count.
+ *
+ * @par Detailed Description:
+ * Provides the functionality needed to set the reboot count. The
+ * reboot count is a special sensor maintained by the BMC.
+ *
+ * Usage:
+ * reboot_count_t count = 3;
+ * RebootCountSensor l_sensor;
+ * l_sensor.setRebootCount( count );
+ *
+ */
+ class RebootCountSensor : public SensorBase
+ {
+
+ //< reboot count type
+ typedef uint8_t rebootCount_t;
+
+ public:
+
+ /**
+ * @brief Constructor for the RebootCountSensor
+ *
+ * The reboot count sensor is used to update the reboot count
+ * sensor maintained by the BMC.
+ *
+ * The system target holds the IPMI sensor number for this sensor.
+ *
+ */
+ RebootCountSensor();
+
+ /**
+ * @brief Destructor for the RebootCountSensor
+ *
+ */
+ ~RebootCountSensor();
+
+ /**
+ * @brief Sent a value for the reboot count to the BMC.
+ *
+ * @param[in] i_count - new reboot count value.
+ *
+ * @return Errorlog handle
+ *
+ */
+ errlHndl_t setRebootCount( rebootCount_t i_count );
+
+ };
+
+ /**
+ * @class StatusSensor
+ *
+ * @brief Specialized class to handle DIMM, PROC and Core status.
+ *
+ * @par Detailed Description:
+ * Provides the functionality needed to set the status of DIMMS, Cores,
+ * and processors. The object will determine from the Target* what
+ * sensor offsets should be used, and configure itself accordingly.
+ */
+
+ class StatusSensor : public SensorBase
+ {
+
+ public:
+
+ /**
+ * @enum statusEnum
+ *
+ * enum defining the status of targets which use the
+ * status sensor to report functional and present states.
+ */
+ enum statusEnum
+ {
+ NOT_PRESENT = 0x0000,
+ PRESENT = 0x0001,
+ FUNCTIONAL = 0x0002,
+ PRESENT_FUNCTIONAL = 0x0003,
+ NON_FUNCTIONAL = 0x0004,
+ PRESENT_NONFUNCTIONAL = 0x0005,
+ };
+
+ /**
+ * @brief Constructor for a status sensor
+ *
+ * The status sensor is used for DIMMS, Cores and Procs. Hostboot
+ * will update the present and functional state for the status
+ * sensor associated with each instance of these target types.
+ *
+ *
+ * The IPMI sensor number for these sensors are associated with
+ * each instance of the DIMM, CORE and Processor targets.
+ *
+ */
+ StatusSensor( TARGETING::Target * );
+
+ /**
+ * @brief Destructor for the StatusSensor
+ *
+ */
+ ~StatusSensor();
+
+ errlHndl_t setStatus( statusEnum status );
+
+ private:
+ // disable the default constructor
+ StatusSensor();
+
+ // internal offset data which is configured based on target type
+ // used in construction.
+ uint8_t iv_presentOffset;
+ uint8_t iv_functionalOffset;
+
+ };
+
+ /**
+ * @brief Update DIMM/CORE/Processor status sensors on the BMC.
+ * Update the present/functional status on the BMC for status sensors
+ * monitored by Hostboot. The sensor will be updated based on the
+ * HWAS state of the target. Currently handles DIMM/CORE/PROC present
+ * and functional status.
+ *
+ */
+ void updateBMCSensorStatus(void);
+
+
+ /**
+ * Helper function to update the status sensor for a specific target
+ * type. Currently supports DIMM, CORE and Processor target types.
+ *
+ * @param[in] - i_type, target type to set the status for
+ *
+ */
+ void updateBMCSensorStatus( TARGETING::TYPE i_type );
+
+
+}; // end namespace
+
+#endif
diff --git a/src/usr/hwas/common/deconfigGard.C b/src/usr/hwas/common/deconfigGard.C
index d3d82a141..89ae8d235 100644
--- a/src/usr/hwas/common/deconfigGard.C
+++ b/src/usr/hwas/common/deconfigGard.C
@@ -39,6 +39,10 @@
#include <targeting/common/commontargeting.H>
#include <targeting/common/utilFilter.H>
+#include <ipmi/ipmisensor.H>
+#include <config.h>
+
+
// Trace definition
#define __COMP_TD__ g_trac_deconf
@@ -1415,7 +1419,27 @@ void DeconfigGard::_deconfigureTarget(
//******************************************************************************
void DeconfigGard::_doDeconfigureActions(Target & i_target)
{
+
// Placeholder for any necessary deconfigure actions
+
+
+#ifdef CONFIG_BMC_IPMI
+ // set the BMC status for this target
+ SENSOR::StatusSensor l_sensor( &i_target );
+
+ // can assume the presence sensor is in the correct state, just
+ // assert that it is now non functional.
+ errlHndl_t err = l_sensor.setStatus( SENSOR::StatusSensor::NON_FUNCTIONAL );
+
+ if(err)
+ {
+ HWAS_ERR("Error returned from call to set sensor status for HUID 0x%x",
+ TARGETING::get_huid( &i_target) );
+ err->collectTrace(HWAS_COMP_NAME, 512);
+ errlCommit(err, HWAS_COMP_ID);
+ }
+#endif
+
}
//******************************************************************************
diff --git a/src/usr/hwas/hostbootIstep.C b/src/usr/hwas/hostbootIstep.C
index 5de7a739e..6c33c0a7c 100644
--- a/src/usr/hwas/hostbootIstep.C
+++ b/src/usr/hwas/hostbootIstep.C
@@ -62,6 +62,10 @@
#include <proc_enable_reconfig.H>
+
+#include <ipmi/ipmisensor.H>
+#include <config.h>
+
namespace HWAS
{
@@ -94,8 +98,6 @@ void* host_set_ipl_parms( void *io_pArgs )
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_set_ipl_parms entry" );
errlHndl_t errl = NULL;
- // stub -- nothing here currently
-
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_set_ipl_parms exit" );
return errl;
@@ -130,8 +132,13 @@ void* host_discover_targets( void *io_pArgs )
errl = discoverTargets();
}
+#ifdef CONFIG_BMC_IPMI
+ // send DIMM/CORE/PROC sensor status to the BMC
+ SENSOR::updateBMCSensorStatus();
+#endif
+
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
- "host_discover_targets exit" );
+ "host_discover_targets exit" );
return errl;
}
diff --git a/src/usr/ipmi/ipmisensor.C b/src/usr/ipmi/ipmisensor.C
new file mode 100644
index 000000000..c6b118850
--- /dev/null
+++ b/src/usr/ipmi/ipmisensor.C
@@ -0,0 +1,669 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/ipmi/ipmisensor.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2014 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/**
+ * @file ipmisensor.C
+ * @brief IPMI sensor manipulation
+ */
+
+#include <ipmi/ipmisensor.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <targeting/common/target.H>
+#include <attributetraits.H>
+#include <targeting/common/utilFilter.H>
+#include <ipmi/ipmi_reasoncodes.H>
+#include <endian.h>
+
+extern trace_desc_t * g_trac_ipmi;
+
+namespace SENSOR
+{
+ //
+ // Base class for sensor construction. It is expected that this object will
+ // be used as the base for any additional sensors defined.
+ //
+ SensorBase::SensorBase( TARGETING::SENSOR_NAME i_name,
+ TARGETING::Target * i_target)
+ :iv_name(i_name) ,iv_target(i_target)
+ {
+ // allocate a new message structure to use with our sensors
+ // this will be the payload for the IPMI send/sendrecv sensor message.
+ iv_msg = new setSensorReadingRequest;
+ };
+
+ // base class destructor
+ SensorBase::~SensorBase()
+ {
+ // The memory allocated for the set sensor reading command is deleted
+ // by the IPMI transport layer, this delete will get delete the memory
+ // allocated by the IPMI transport layer which contains the response
+ // to the set sensor reading command.
+ if( iv_msg )
+ {
+ delete[] iv_msg;
+ }
+ };
+
+ //
+ // Helper function to process completion codes returned from the BMC.
+ // If the completion code warrants a PEL the function will build and
+ // return an error log with the correct data captured.
+ //
+ errlHndl_t SensorBase::processCompletionCode( IPMI::completion_code i_rc )
+ {
+ errlHndl_t l_err = NULL;
+
+ IPMI::IPMIReasonCode l_reasonCode;
+
+ if( i_rc != IPMI::CC_OK )
+ {
+ // bad rc from the BMC
+ TRACFCOMP(g_trac_ipmi,"completion code 0x%x returned from the BMC"
+ " , creating error log", i_rc);
+
+ switch(i_rc)
+ {
+ case SENSOR::CC_SENSOR_READING_NOT_SETTABLE:
+ {
+ /* @errorlog tag
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid IPMI::MOD_IPMISENSOR
+ * @reasoncode IPMI::RC_SENSOR_NOT_SETTABLE
+ * @userdata1 BMC IPMI Completion code.
+ * @userdata2 bytes [0-3]sensor number
+ * bytes [4-7]HUID of target.
+ * @devdesc Set sensor reading command failed.
+ */
+ l_reasonCode = IPMI::RC_SENSOR_NOT_SETTABLE;
+ TRACFCOMP(g_trac_ipmi,"Attempt to change sensor reading or"
+ "set/clear status bits that are not settable"
+ " via this command");
+ break;
+ }
+
+ case SENSOR::CC_EVENT_DATA_BYTES_NOT_SETTABLE:
+ {
+ /* @errorlog tag
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid IPMI::MOD_IPMISENSOR
+ * @reasoncode IPMI::RC_EVENT_DATA_NOT_SETTABLE
+ * @userdata1 BMC IPMI Completion code.
+ * @userdata2 bytes[0-3]sensor number
+ * bytes[4-7]HUID of target.
+ * @devdesc Set sensor reading command failed.
+ */
+ l_reasonCode = IPMI::RC_EVENT_DATA_NOT_SETTABLE;
+ TRACFCOMP(g_trac_ipmi,"Attempted to set event data bytes but"
+ "setting event data bytes is not supported for"
+ " this sensor");
+ break;
+ }
+
+ case IPMI::CC_CMDSENSOR:
+ {
+ /* @errorlog tag
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid IPMI::MOD_IPMISENSOR
+ * @reasoncode IPMI::RC_INVALID_SENSOR_CMD
+ * @userdata1 BMC IPMI Completion code.
+ * @userdata2 bytes [0-3]sensor number
+ * bytes [4-7]HUID of target.
+ * @devdesc Command not valid for this sensor.
+ */
+ l_reasonCode = IPMI::RC_INVALID_SENSOR_CMD;
+ TRACFCOMP(g_trac_ipmi,"Command not valid for this sensor");
+ break;
+ }
+
+ case IPMI::CC_BADSENSOR:
+ {
+ /* @errorlog tag
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid IPMI::MOD_IPMISENSOR
+ * @reasoncode IPMI::RC_SENSOR_NOT_PRESENT
+ * @userdata1 BMC IPMI Completion code.
+ * @userdata2 bytes [0-3]sensor number
+ * bytes [4-7]HUID of target.
+ * @devdesc Requested sensor is not present.
+ */
+ l_reasonCode = IPMI::RC_SENSOR_NOT_PRESENT;
+ TRACFCOMP(g_trac_ipmi,"Requested sensor not present");
+ break;
+ }
+
+ default:
+ {
+ // lump everything else into a general failure for
+ // now.
+ /* @errorlog tag
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid IPMI::MOD_IPMISENSOR
+ * @reasoncode IPMI::RC_SET_SENSOR_FAILURE
+ * @userdata1 BMC IPMI Completion code.
+ * @userdata2 bytes [0-3]sensor number
+ * bytes [4-7]HUID of target.
+ * @devdesc Set sensor reading command failed.
+ */
+ TRACFCOMP(g_trac_ipmi,"Set sensor reading command failed");
+ l_reasonCode = IPMI::RC_SET_SENSOR_FAILURE;
+ break;
+ }
+ }
+ // shift the sensor number into to bytes 0-3 and then
+ // or in the HUID to bytes 4-7
+ uint64_t userdata2 = getSensorNumber();
+
+ userdata2 = (userdata2 << 32) | TARGETING::get_huid(iv_target);
+
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ IPMI::MOD_IPMISENSOR,
+ l_reasonCode,
+ i_rc, userdata2, true);
+
+ l_err->collectTrace(IPMI_COMP_NAME);
+
+ }
+
+ return l_err;
+ }
+
+ //
+ // Helper function to send the data to the BMC using the correct interface
+ // protocol
+ //
+ errlHndl_t SensorBase::writeSensorData()
+ {
+
+ errlHndl_t l_err = NULL;
+
+ iv_msg->iv_sensor_number = getSensorNumber();
+
+ if( iv_msg->iv_sensor_number != INVALID_SENSOR )
+ {
+
+ IPMI::completion_code l_rc = IPMI::CC_UNKBAD;
+
+ // iv_msg is deleted by the destructor
+ l_err = sendSetSensorReading( iv_msg, l_rc);
+
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_ipmi,"error returned from "
+ "sendSetSensorReading() for sensor number 0x%x",
+ getSensorNumber());
+
+ // return error log to caller
+ }
+ else
+ {
+ // check the completion code to see if we need to generate a
+ // PEL.
+ l_err = processCompletionCode( l_rc );
+ }
+ }
+ else
+ {
+ TRACFCOMP(g_trac_ipmi,"We were not able to find a sensor number in"
+ " the IPMI_SENSORS attribute for sensor_name=0x%x"
+ "for target with huid=0x%x, skipping call to "
+ "sendSetSensorReading()",
+ iv_name, TARGETING::get_huid( iv_target ));
+
+ assert(false);
+
+ }
+
+ return l_err;
+ };
+
+ //
+ // Helper function to set the bit in the assertion/deassertion mask
+ // associated with the desired sensor specific offset
+ //
+ uint16_t SensorBase::setMask( const uint8_t offset )
+ {
+ const uint16_t mask = (0x0001 << offset);
+
+ // need to byte swap the mask (see set sensor reading in spec)
+ return le16toh(mask);
+ };
+
+ //
+ // Helper function to translate the assertion/deassertion mask into
+ // the correct event offset.
+ //
+ uint8_t SensorBase::getOffset( uint16_t mask )
+ {
+ // $TODO RTC:117872
+ return 0;
+ };
+
+ // read data from the sensor.
+ errlHndl_t SensorBase::readSensorData(uint8_t *& o_data)
+ {
+
+ // get sensor reading command only requires one byte of extra data,
+ // which will be the sensor number, the command will return between
+ // 3 and 5 bytes of data.
+ size_t len = 1;
+
+ // need to allocate some me to hold the sensor number this will be
+ // deleted by the IPMI transport layer
+ o_data = new uint8_t[len];
+
+ o_data[0] = getSensorNumber();
+
+ IPMI::completion_code cc = IPMI::CC_UNKBAD;
+
+ // o_data will hold the response when this returns
+ errlHndl_t l_err = sendrecv(IPMI::get_sensor_reading(), cc, len,
+ (uint8_t *&)o_data);
+
+ // if we didn't get an error back from the BT interface, but see a
+ // bad completion code from the BMC, process the CC to see if we
+ // need to create a PEL
+ if( (l_err == NULL ) && (cc != IPMI::CC_OK) )
+ {
+ l_err = processCompletionCode( cc );
+ }
+
+ return l_err;
+ };
+
+ //
+ // Synchronously send a set sensor reading command to the BMC,
+ // the response is returned with the io_data pointer
+ //
+ errlHndl_t SensorBase::sendSetSensorReading(
+ setSensorReadingRequest *& io_data,
+ IPMI::completion_code& o_completion_code )
+ {
+
+ size_t l_len = sizeof( setSensorReadingRequest );
+
+ o_completion_code = IPMI::CC_UNKBAD;
+
+ // i_data will hold the response when this returns
+ errlHndl_t l_err = sendrecv(IPMI::set_sensor_reading(),
+ o_completion_code, l_len, (uint8_t *&)io_data);
+
+ return l_err;
+ }
+
+
+ // given an array[][2] compare the number in the first column to the passed
+ // in key value
+ static inline bool compare_it( uint16_t (&a)[2], uint16_t key )
+ {
+ return a[0] < key;
+ };
+
+ //
+ // Helper function to search the sensor data for the correct sensor number
+ // based on the sensor name.
+ //
+ uint16_t SensorBase::getSensorNumber()
+ {
+
+ uint16_t l_sensor_number = INVALID_SENSOR;
+
+ if( iv_target == NULL )
+ {
+ // use the system target
+ TARGETING::targetService().getTopLevelTarget(iv_target);
+
+ // die if there is no system target
+ assert(iv_target);
+
+ }
+
+ TARGETING::AttributeTraits<TARGETING::ATTR_IPMI_SENSORS>::Type
+ l_sensors;
+
+ if( iv_target->tryGetAttr<TARGETING::ATTR_IPMI_SENSORS>(l_sensors) )
+ {
+
+ // get the number of rows by dividing the total size by the size of
+ // the first row
+ uint16_t array_rows = (sizeof(l_sensors)/sizeof(l_sensors[0]));
+
+ // create an iterator pointing to the first element of the array
+ uint16_t (*begin)[2] = &l_sensors[0];
+
+ // using the number entries as the index into the array will set the
+ // end iterator to the correct position or one entry past the last
+ // element of the array
+ uint16_t (*end)[2] = &l_sensors[array_rows];
+
+ uint16_t (*ptr)[2] =
+ std::lower_bound(begin, end, iv_name, &compare_it);
+
+ // we have not reached the end of the array and the iterator
+ // returned from lower_bound is pointing to an entry which equals
+ // the one we are searching for.
+ if( ( ptr != end ) && ( (*ptr)[0] == iv_name ) )
+ {
+ // found it
+ l_sensor_number = (*ptr)[1];
+
+ TRACFCOMP(g_trac_ipmi,"Found sensor number %d for HUID=0x%x",
+ l_sensor_number, TARGETING::get_huid(iv_target));
+ }
+ }
+ else
+ {
+ // bug here...
+ assert(0,"no IPMI_SENSOR attribute check target HUID=0x%x",
+ TARGETING::get_huid(iv_target));
+ }
+
+ return l_sensor_number;
+ }
+
+ ///
+ // FirmwareProgressSensor constructor - uses system target
+ //
+ FirmwareProgressSensor::FirmwareProgressSensor( )
+ :SensorBase(TARGETING::SENSOR_NAME_FW_BOOT_PROGRESS, NULL)
+ {
+ // message buffer created and initialized in base object.
+
+ // assert the system firmware progress offset.
+ iv_msg->iv_assertion_mask = setMask( SYSTEM_FIRMWARE_PROGRESS );
+ };
+
+ //
+ // FirmwareProgressSensor destructor
+ //
+ FirmwareProgressSensor::~FirmwareProgressSensor( )
+ {
+
+ };
+
+
+ //
+ // setBootProgressPhase - update the boot progress sensor of the BMC
+ //
+ errlHndl_t FirmwareProgressSensor::setBootProgressPhase(
+ firmwareProgressPhase phase )
+ {
+ // event data 2 holds the progress info
+ iv_msg->iv_event_data[1] = phase;
+
+ return writeSensorData();
+ };
+
+ //
+ // RebootCountSensor constructor - uses system target
+ //
+ RebootCountSensor::RebootCountSensor()
+ :SensorBase(TARGETING::SENSOR_NAME_REBOOT_COUNT, NULL)
+ {
+ // message buffer created and initialized in base object.
+ }
+
+ //
+ // RebootCountSensor destructor
+ //
+ RebootCountSensor::~RebootCountSensor(){};
+
+ //
+ // setRebootCount - send a new value for the reboot count to the BMC.
+ //
+ errlHndl_t RebootCountSensor::setRebootCount( rebootCount_t i_count )
+ {
+
+ // put the reboot count into the sensor
+ // reading byte of the message
+ iv_msg->iv_sensor_reading = i_count;
+
+ return writeSensorData();
+
+ }
+
+ //
+ // StatusSensor constructor - uses system DIMM/CORE/PROC target
+ //
+ StatusSensor::StatusSensor( TARGETING::Target * i_target )
+ :SensorBase(TARGETING::SENSOR_NAME_STATE, i_target)
+ {
+
+ switch ( i_target->getAttr<TARGETING::ATTR_TYPE>() )
+ {
+ case TARGETING::TYPE_DIMM:
+ {
+ iv_functionalOffset = 0x04;
+ iv_presentOffset = 0x06;
+ break;
+ }
+
+ case TARGETING::TYPE_PROC:
+ case TARGETING::TYPE_CORE:
+ {
+ iv_functionalOffset = 0x08;
+ iv_presentOffset = 0x07;
+ break;
+ }
+
+ default:
+ iv_presentOffset = 0xFF;
+ iv_functionalOffset = 0xFF;
+ break;
+ }
+
+ };
+
+ //
+ // StatusSensor destructor
+ //
+ //
+ StatusSensor::~StatusSensor()
+ {};
+
+
+ // Convert the input status to the correct sensor offset value, then
+ // send the message to the BMC to update the event status for this sensor.
+ errlHndl_t StatusSensor::setStatus( statusEnum i_state )
+ {
+
+ errlHndl_t l_err = NULL;
+ // if the offset isn't configured then the target does not have
+ // one of these sensors.
+ if( iv_functionalOffset != 0xFF && iv_presentOffset != 0xFF )
+ {
+
+ uint16_t func_mask = setMask( iv_functionalOffset );
+ uint16_t pres_mask = setMask( iv_presentOffset );
+
+ switch ( i_state )
+ {
+ case NOT_PRESENT:
+ // turn off the present bit
+ iv_msg->iv_deassertion_mask = pres_mask;
+ // turn on the disabled bit
+ iv_msg->iv_assertion_mask = func_mask;
+ break;
+
+ case PRESENT:
+ // turn on the present bit
+ iv_msg->iv_assertion_mask = pres_mask;
+ break;
+
+ case FUNCTIONAL:
+ // turn off the disabled bit
+ iv_msg->iv_deassertion_mask = func_mask;
+ break;
+
+ case PRESENT_FUNCTIONAL:
+ // assert the present bit
+ iv_msg->iv_assertion_mask = pres_mask;
+ // turn off the disabled bit
+ iv_msg->iv_deassertion_mask = func_mask;
+ break;
+
+ case PRESENT_NONFUNCTIONAL:
+ // assert the present bit
+ iv_msg->iv_assertion_mask = pres_mask;
+ // assert the disabled bit
+ iv_msg->iv_assertion_mask |= func_mask;
+ break;
+
+ case NON_FUNCTIONAL:
+ // assert the disabled bit
+ iv_msg->iv_assertion_mask = func_mask;
+ break;
+
+ default:
+ // mark as not present
+ iv_msg->iv_deassertion_mask = pres_mask;
+ iv_msg->iv_assertion_mask = func_mask;
+ break;
+ }
+
+ l_err = writeSensorData();
+
+ }
+
+ return l_err;
+
+ };
+
+
+ //
+ // HostStausSensor constructor - uses system target
+ //
+ //
+ HostStatusSensor::HostStatusSensor()
+ :SensorBase(TARGETING::SENSOR_NAME_HOST_STATUS, NULL)
+ {
+
+ };
+
+ //
+ // HostStatusSensor destructor
+ //
+ //
+ HostStatusSensor::~HostStatusSensor(){};
+
+ //
+ // updateHostStaus - update the BMC HostStatus sensor with the passed in
+ // value.
+ //
+ //
+ errlHndl_t HostStatusSensor::updateHostStatus( hostStatus status )
+ {
+ iv_msg->iv_assertion_mask = setMask((uint8_t)status);
+
+ return writeSensorData();
+ };
+
+ //
+ // Used to update the sensor status for a specific set of target types
+ // currently supported types are TYPE_DIMM, TYPE_CORE, TYPE_PROC. These
+ // are virtual sensors where Hostboot updates the present and functional
+ // states and the BMC maintains the sensor.
+ //
+ void updateBMCSensorStatus(TARGETING::TYPE i_type)
+ {
+
+ TARGETING::TargetHandleList l_tList;
+
+ // get all targets of the passed in type, functional or not
+ switch( i_type )
+ {
+ case TARGETING::TYPE_PROC:
+ getAllChips( l_tList, TARGETING::TYPE_PROC, false );
+ break;
+
+ case TARGETING::TYPE_DIMM:
+ getAllLogicalCards( l_tList, TARGETING::TYPE_DIMM, false );
+ break;
+
+ case TARGETING::TYPE_CORE:
+ getAllChiplets( l_tList, TARGETING::TYPE_CORE, false);
+ break;
+
+ default:
+ assert(0, "invalid target type for BMC update");
+
+ }
+
+ // have a list of targets now set the status sensor on the BMC for each
+ // one.
+ for(TARGETING::TargetHandleList::const_iterator pTargetIt =
+ l_tList.begin();
+ pTargetIt != l_tList.end();
+ ++pTargetIt )
+ {
+
+ StatusSensor::statusEnum l_status
+ = StatusSensor::PRESENT_FUNCTIONAL;
+
+ // create a status sensor for our needs
+ StatusSensor l_sensor((*pTargetIt));
+
+ TARGETING::HwasState l_state =
+ (*pTargetIt)->getAttr<TARGETING::ATTR_HWAS_STATE>();
+
+ if( l_state.present == true )
+ {
+ if( l_state.functional == false )
+ {
+ l_status = StatusSensor::PRESENT_NONFUNCTIONAL;
+ }
+ }
+ else
+ {
+ l_status = StatusSensor::NOT_PRESENT;
+ }
+
+ // send the status to the BMC
+ errlHndl_t l_err = l_sensor.setStatus( l_status );
+
+ // commit the error and move to the next target
+ if( l_err )
+ {
+ errlCommit( l_err, IPMI_COMP_ID );
+ }
+ }
+
+ }
+
+ void updateBMCSensorStatus()
+ {
+ // send status of all DIMM targets
+ updateBMCSensorStatus(TARGETING::TYPE_DIMM);
+
+ // send status for all PROC targets
+ updateBMCSensorStatus(TARGETING::TYPE_PROC);
+
+ updateBMCSensorStatus(TARGETING::TYPE_CORE);
+
+ };
+
+}; // end name space
+
+
diff --git a/src/usr/ipmi/makefile b/src/usr/ipmi/makefile
index 3d8ca3a8c..92cf4362b 100644
--- a/src/usr/ipmi/makefile
+++ b/src/usr/ipmi/makefile
@@ -30,6 +30,7 @@ OBJS += $(if $(CONFIG_BMC_BT_LPC_IPMI),ipmibt.o)
OBJS += ipmirp.o
OBJS += $(if $(CONFIG_BMC_BT_LPC_IPMI),ipmidd.o)
OBJS += ipmiconfig.o
+OBJS += ipmisensor.o
#SUBDIRS += test.d
diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml
index 1cdf89a4f..31deb9ff3 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types.xml
@@ -455,6 +455,10 @@
<name>SYSTEM_FIRMWARE_PROGRESS</name>
<value>0x0F</value>
</enumerator>
+ <enumerator>
+ <name>REBOOT_COUNT</name>
+ <value>0xC0</value>
+ </enumerator>
</enumerationType>
<attribute>
OpenPOWER on IntegriCloud