From e0af7209c748794b867bce6901f834d10d47773f Mon Sep 17 00:00:00 2001 From: Dhruvaraj Subhashchandran Date: Wed, 12 Jul 2017 06:35:20 -0500 Subject: IPMI: Virtual sensor support in host ipmid Resolves openbmc/openbmc#1608 Change-Id: Id76446061fd0fa6dc3dead702538e424293af7ce Signed-off-by: Dhruvaraj Subhashchandran --- sensordatahandler.cpp | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 sensordatahandler.cpp (limited to 'sensordatahandler.cpp') diff --git a/sensordatahandler.cpp b/sensordatahandler.cpp new file mode 100644 index 0000000..6c7b9ac --- /dev/null +++ b/sensordatahandler.cpp @@ -0,0 +1,258 @@ +#include +#include +#include +#include "xyz/openbmc_project/Common/error.hpp" +#include "types.hpp" +#include "sensordatahandler.hpp" + +namespace ipmi +{ +namespace sensor +{ + +using namespace phosphor::logging; +using InternalFailure = + sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; + +static constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; +static constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; +static constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; + +/** @brief get the D-Bus service and service path + * @param[in] bus - The Dbus bus object + * @param[in] interface - interface to the service + * @param[in] path - interested path in the list of objects + * @return pair of service path and service + */ +ServicePath getServiceAndPath(sdbusplus::bus::bus& bus, + const std::string& interface, + const std::string& path) +{ + auto depth = 0; + auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, + MAPPER_PATH, + MAPPER_INTERFACE, + "GetSubTree"); + mapperCall.append("/"); + mapperCall.append(depth); + mapperCall.append(std::vector({interface})); + + auto mapperResponseMsg = bus.call(mapperCall); + if (mapperResponseMsg.is_method_error()) + { + std::string err = "Error in mapper GetSubTree " + "Interface: " + interface; + log(err.c_str()); + elog(); + } + + MapperResponseType mapperResponse; + mapperResponseMsg.read(mapperResponse); + if (mapperResponse.empty()) + { + std::string err = "Invalid response from mapper " + "Command: GetSubTree " + "Interface:" + interface; + log(err.c_str()); + elog(); + } + + if (path.empty()) + { + //Get the first one if the path is not in list. + return std::make_pair(mapperResponse.begin()->first, + mapperResponse.begin()->second.begin()->first); + } + const auto& iter = mapperResponse.find(path); + if (iter == mapperResponse.end()) + { + std::string err = "Error in finding sensor dbus" + "Command: GetSubTree " + "Interface:" + interface; + log(err.c_str()); + elog(); + } + return std::make_pair(iter->first, iter->second.begin()->first); +} + +AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData) +{ + Assertion assertionStates = + (static_cast(cmdData.assertOffset8_14)) << 8 | + cmdData.assertOffset0_7; + Deassertion deassertionStates = + (static_cast(cmdData.deassertOffset8_14)) << 8 | + cmdData.deassertOffset0_7; + return std::make_pair(assertionStates, deassertionStates); +} + +ipmi_ret_t updateToDbus(IpmiUpdateData& msg) +{ + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + try + { + auto serviceResponseMsg = bus.call(msg); + if (serviceResponseMsg.is_method_error()) + { + log("Error in D-Bus call"); + return IPMI_CC_UNSPECIFIED_ERROR; + } + } + catch (InternalFailure& e) + { + commit(); + return IPMI_CC_UNSPECIFIED_ERROR; + } + return IPMI_CC_OK; +} + +namespace set +{ + +IpmiUpdateData makeDbusMsg(const std::string& updateInterface, + const std::string& sensorPath, + const std::string& command, + const std::string& sensorInterface) +{ + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + using namespace std::string_literals; + + std::string dbusService; + std::string dbusPath; + + std::tie(dbusPath, dbusService) = getServiceAndPath(bus, + sensorInterface, + sensorPath); + return bus.new_method_call(dbusService.c_str(), + dbusPath.c_str(), + updateInterface.c_str(), + command.c_str()); +} + +ipmi_ret_t appendDiscreteSignalData(IpmiUpdateData& msg, + const DbusInterfaceMap& interfaceMap, + uint8_t data) +{ + const auto& interface = interfaceMap.begin(); + msg.append(interface->first); + for (const auto& property : interface->second) + { + msg.append(property.first); + const auto& iter = property.second.find(data); + if (iter == property.second.end()) + { + log("Invalid event data"); + return IPMI_CC_PARM_OUT_OF_RANGE; + } + msg.append(iter->second.assert); + } + return IPMI_CC_OK; +} + +ipmi_ret_t appendReadingData(IpmiUpdateData& msg, + const DbusInterfaceMap& interfaceMap, + const Value &data) +{ + const auto& interface = interfaceMap.begin(); + msg.append(interface->first); + for (const auto& property : interface->second) + { + msg.append(property.first); + msg.append(data); + } + return IPMI_CC_OK; +} + +ipmi_ret_t appendAssertion(IpmiUpdateData& msg, + const DbusInterfaceMap& interfaceMap, + const std::string& sensorPath, + const SetSensorReadingReq& cmdData) +{ + std::bitset<16> assertionSet(getAssertionSet(cmdData).first); + std::bitset<16> deassertionSet(getAssertionSet(cmdData).second); + + const auto& interface = interfaceMap.begin(); + msg.append(interface->first); + for (const auto& property : interface->second) + { + msg.append(property.first); + for (const auto& value : property.second) + { + if (assertionSet.test(value.first)) + { + msg.append(value.second.assert); + } + if (deassertionSet.test(value.first)) + { + msg.append(value.second.deassert); + } + } + } + return IPMI_CC_OK; +} +}//namespace set + +namespace notify +{ + +IpmiUpdateData makeDbusMsg(const std::string& updateInterface, + const std::string& sensorPath, + const std::string& command, + const std::string& sensorInterface) +{ + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + using namespace std::string_literals; + + std::string dbusService; + std::string dbusPath; + + std::tie(dbusPath, dbusService) = getServiceAndPath(bus, + updateInterface); + + return bus.new_method_call(dbusService.c_str(), + dbusPath.c_str(), + updateInterface.c_str(), + command.c_str()); +} + +ipmi_ret_t appendAssertion(IpmiUpdateData& msg, + const DbusInterfaceMap& interfaceMap, + const std::string& sensorPath, + const SetSensorReadingReq& cmdData) +{ + std::bitset<16> assertionSet(getAssertionSet(cmdData).first); + std::bitset<16> deassertionSet(getAssertionSet(cmdData).second); + ipmi::sensor::ObjectMap objects; + ipmi::sensor::InterfaceMap interfaces; + for (const auto& interface : interfaceMap) + { + for (const auto& property : interface.second) + { + ipmi::sensor::PropertyMap props; + bool valid = false; + for (const auto& value : property.second) + { + if (assertionSet.test(value.first)) + { + props.emplace(property.first, value.second.assert); + valid = true; + } + else if (deassertionSet.test(value.first)) + { + props.emplace(property.first, value.second.deassert); + valid = true; + } + } + if (valid) + { + interfaces.emplace(interface.first, std::move(props)); + } + } + } + objects.emplace(sensorPath, std::move(interfaces)); + msg.append(std::move(objects)); + return IPMI_CC_OK; +} +}//namespace notify +}//namespace sensor +}//namespace ipmi -- cgit v1.2.1