13f7c5e40SJason M. Bills /* 23f7c5e40SJason M. Bills // Copyright (c) 2018 Intel Corporation 33f7c5e40SJason M. Bills // 43f7c5e40SJason M. Bills // Licensed under the Apache License, Version 2.0 (the "License"); 53f7c5e40SJason M. Bills // you may not use this file except in compliance with the License. 63f7c5e40SJason M. Bills // You may obtain a copy of the License at 73f7c5e40SJason M. Bills // 83f7c5e40SJason M. Bills // http://www.apache.org/licenses/LICENSE-2.0 93f7c5e40SJason M. Bills // 103f7c5e40SJason M. Bills // Unless required by applicable law or agreed to in writing, software 113f7c5e40SJason M. Bills // distributed under the License is distributed on an "AS IS" BASIS, 123f7c5e40SJason M. Bills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133f7c5e40SJason M. Bills // See the License for the specific language governing permissions and 143f7c5e40SJason M. Bills // limitations under the License. 153f7c5e40SJason M. Bills */ 163f7c5e40SJason M. Bills 17*262276f4SPatrick Venture #include "commandutils.hpp" 18*262276f4SPatrick Venture 193f7c5e40SJason M. Bills #include <boost/algorithm/string.hpp> 20a9423b6eSJason M. Bills #include <boost/bimap.hpp> 213f7c5e40SJason M. Bills #include <boost/container/flat_map.hpp> 22*262276f4SPatrick Venture #include <cstdio> 233f7c5e40SJason M. Bills #include <cstring> 24*262276f4SPatrick Venture #include <exception> 25*262276f4SPatrick Venture #include <filesystem> 26*262276f4SPatrick Venture #include <map> 273f7c5e40SJason M. Bills #include <phosphor-logging/log.hpp> 28a9423b6eSJason M. Bills #include <sdbusplus/bus/match.hpp> 29*262276f4SPatrick Venture #include <string> 30*262276f4SPatrick Venture #include <vector> 313f7c5e40SJason M. Bills 323f7c5e40SJason M. Bills #pragma once 333f7c5e40SJason M. Bills 343f7c5e40SJason M. Bills struct CmpStrVersion 353f7c5e40SJason M. Bills { 363f7c5e40SJason M. Bills bool operator()(std::string a, std::string b) const 373f7c5e40SJason M. Bills { 383f7c5e40SJason M. Bills return strverscmp(a.c_str(), b.c_str()) < 0; 393f7c5e40SJason M. Bills } 403f7c5e40SJason M. Bills }; 413f7c5e40SJason M. Bills 423f7c5e40SJason M. Bills using SensorSubTree = boost::container::flat_map< 433f7c5e40SJason M. Bills std::string, 443f7c5e40SJason M. Bills boost::container::flat_map<std::string, std::vector<std::string>>, 453f7c5e40SJason M. Bills CmpStrVersion>; 463f7c5e40SJason M. Bills 47a9423b6eSJason M. Bills using SensorNumMap = boost::bimap<int, std::string>; 48a9423b6eSJason M. Bills 49a9423b6eSJason M. Bills namespace details 503f7c5e40SJason M. Bills { 51a9423b6eSJason M. Bills inline static bool getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree) 52a9423b6eSJason M. Bills { 53a9423b6eSJason M. Bills static std::shared_ptr<SensorSubTree> sensorTreePtr; 543f7c5e40SJason M. Bills sd_bus* bus = NULL; 553f7c5e40SJason M. Bills int ret = sd_bus_default_system(&bus); 563f7c5e40SJason M. Bills if (ret < 0) 573f7c5e40SJason M. Bills { 583f7c5e40SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>( 593f7c5e40SJason M. Bills "Failed to connect to system bus", 603f7c5e40SJason M. Bills phosphor::logging::entry("ERRNO=0x%X", -ret)); 613f7c5e40SJason M. Bills sd_bus_unref(bus); 623f7c5e40SJason M. Bills return false; 633f7c5e40SJason M. Bills } 643f7c5e40SJason M. Bills sdbusplus::bus::bus dbus(bus); 65a9423b6eSJason M. Bills static sdbusplus::bus::match::match sensorAdded( 66a9423b6eSJason M. Bills dbus, 67a9423b6eSJason M. Bills "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/" 68a9423b6eSJason M. Bills "sensors/'", 69a9423b6eSJason M. Bills [](sdbusplus::message::message& m) { sensorTreePtr.reset(); }); 70a9423b6eSJason M. Bills 71a9423b6eSJason M. Bills static sdbusplus::bus::match::match sensorRemoved( 72a9423b6eSJason M. Bills dbus, 73a9423b6eSJason M. Bills "type='signal',member='InterfacesRemoved',arg0path='/xyz/" 74a9423b6eSJason M. Bills "openbmc_project/sensors/'", 75a9423b6eSJason M. Bills [](sdbusplus::message::message& m) { sensorTreePtr.reset(); }); 76a9423b6eSJason M. Bills 77a9423b6eSJason M. Bills bool sensorTreeUpdated = false; 78a9423b6eSJason M. Bills if (sensorTreePtr) 79a9423b6eSJason M. Bills { 80a9423b6eSJason M. Bills subtree = sensorTreePtr; 81a9423b6eSJason M. Bills return sensorTreeUpdated; 82a9423b6eSJason M. Bills } 83a9423b6eSJason M. Bills 84a9423b6eSJason M. Bills sensorTreePtr = std::make_shared<SensorSubTree>(); 85a9423b6eSJason M. Bills 863f7c5e40SJason M. Bills auto mapperCall = 873f7c5e40SJason M. Bills dbus.new_method_call("xyz.openbmc_project.ObjectMapper", 883f7c5e40SJason M. Bills "/xyz/openbmc_project/object_mapper", 893f7c5e40SJason M. Bills "xyz.openbmc_project.ObjectMapper", "GetSubTree"); 9052341e85SJason M. Bills static constexpr const auto depth = 2; 913f7c5e40SJason M. Bills static constexpr std::array<const char*, 3> interfaces = { 923f7c5e40SJason M. Bills "xyz.openbmc_project.Sensor.Value", 933f7c5e40SJason M. Bills "xyz.openbmc_project.Sensor.Threshold.Warning", 943f7c5e40SJason M. Bills "xyz.openbmc_project.Sensor.Threshold.Critical"}; 953f7c5e40SJason M. Bills mapperCall.append("/xyz/openbmc_project/sensors", depth, interfaces); 963f7c5e40SJason M. Bills 973f7c5e40SJason M. Bills try 983f7c5e40SJason M. Bills { 993f7c5e40SJason M. Bills auto mapperReply = dbus.call(mapperCall); 100a9423b6eSJason M. Bills mapperReply.read(*sensorTreePtr); 1013f7c5e40SJason M. Bills } 10252341e85SJason M. Bills catch (sdbusplus::exception_t& e) 1033f7c5e40SJason M. Bills { 10452341e85SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 105a9423b6eSJason M. Bills return sensorTreeUpdated; 106a9423b6eSJason M. Bills } 107a9423b6eSJason M. Bills subtree = sensorTreePtr; 108a9423b6eSJason M. Bills sensorTreeUpdated = true; 109a9423b6eSJason M. Bills return sensorTreeUpdated; 110a9423b6eSJason M. Bills } 111a9423b6eSJason M. Bills 112a9423b6eSJason M. Bills inline static bool getSensorNumMap(std::shared_ptr<SensorNumMap>& sensorNumMap) 113a9423b6eSJason M. Bills { 114a9423b6eSJason M. Bills static std::shared_ptr<SensorNumMap> sensorNumMapPtr; 115a9423b6eSJason M. Bills bool sensorNumMapUpated = false; 116a9423b6eSJason M. Bills 117a9423b6eSJason M. Bills std::shared_ptr<SensorSubTree> sensorTree; 118a9423b6eSJason M. Bills bool sensorTreeUpdated = details::getSensorSubtree(sensorTree); 119a9423b6eSJason M. Bills if (!sensorTree) 120a9423b6eSJason M. Bills { 121a9423b6eSJason M. Bills return sensorNumMapUpated; 122a9423b6eSJason M. Bills } 123a9423b6eSJason M. Bills 124a9423b6eSJason M. Bills if (!sensorTreeUpdated && sensorNumMapPtr) 125a9423b6eSJason M. Bills { 126a9423b6eSJason M. Bills sensorNumMap = sensorNumMapPtr; 127a9423b6eSJason M. Bills return sensorNumMapUpated; 128a9423b6eSJason M. Bills } 129a9423b6eSJason M. Bills 130a9423b6eSJason M. Bills sensorNumMapPtr = std::make_shared<SensorNumMap>(); 131a9423b6eSJason M. Bills 132caed905dSJason M. Bills uint8_t sensorNum = 0; 133a9423b6eSJason M. Bills for (const auto& sensor : *sensorTree) 134a9423b6eSJason M. Bills { 135a9423b6eSJason M. Bills sensorNumMapPtr->insert( 136a9423b6eSJason M. Bills SensorNumMap::value_type(sensorNum++, sensor.first)); 137a9423b6eSJason M. Bills } 138a9423b6eSJason M. Bills sensorNumMap = sensorNumMapPtr; 139a9423b6eSJason M. Bills sensorNumMapUpated = true; 140a9423b6eSJason M. Bills return sensorNumMapUpated; 141a9423b6eSJason M. Bills } 142a9423b6eSJason M. Bills } // namespace details 143a9423b6eSJason M. Bills 144a9423b6eSJason M. Bills inline static bool getSensorSubtree(SensorSubTree& subtree) 145a9423b6eSJason M. Bills { 146a9423b6eSJason M. Bills std::shared_ptr<SensorSubTree> sensorTree; 147a9423b6eSJason M. Bills details::getSensorSubtree(sensorTree); 148a9423b6eSJason M. Bills if (!sensorTree) 149a9423b6eSJason M. Bills { 1503f7c5e40SJason M. Bills return false; 1513f7c5e40SJason M. Bills } 152a9423b6eSJason M. Bills 153a9423b6eSJason M. Bills subtree = *sensorTree; 1543f7c5e40SJason M. Bills return true; 1553f7c5e40SJason M. Bills } 1563f7c5e40SJason M. Bills 1573f7c5e40SJason M. Bills struct CmpStr 1583f7c5e40SJason M. Bills { 1593f7c5e40SJason M. Bills bool operator()(const char* a, const char* b) const 1603f7c5e40SJason M. Bills { 1613f7c5e40SJason M. Bills return std::strcmp(a, b) < 0; 1623f7c5e40SJason M. Bills } 1633f7c5e40SJason M. Bills }; 1643f7c5e40SJason M. Bills 16552341e85SJason M. Bills enum class SensorTypeCodes : uint8_t 16652341e85SJason M. Bills { 16752341e85SJason M. Bills reserved = 0x0, 16852341e85SJason M. Bills temperature = 0x1, 16952341e85SJason M. Bills voltage = 0x2, 17052341e85SJason M. Bills current = 0x3, 17152341e85SJason M. Bills fan = 0x4, 17252341e85SJason M. Bills other = 0xB, 17352341e85SJason M. Bills }; 17452341e85SJason M. Bills 1753f7c5e40SJason M. Bills const static boost::container::flat_map<const char*, SensorTypeCodes, CmpStr> 1763f7c5e40SJason M. Bills sensorTypes{{{"temperature", SensorTypeCodes::temperature}, 1773f7c5e40SJason M. Bills {"voltage", SensorTypeCodes::voltage}, 1783f7c5e40SJason M. Bills {"current", SensorTypeCodes::current}, 1793f7c5e40SJason M. Bills {"fan_tach", SensorTypeCodes::fan}, 180f426f334SJames Feist {"fan_pwm", SensorTypeCodes::fan}, 1813f7c5e40SJason M. Bills {"power", SensorTypeCodes::other}}}; 1823f7c5e40SJason M. Bills 1833f7c5e40SJason M. Bills inline static std::string getSensorTypeStringFromPath(const std::string& path) 1843f7c5e40SJason M. Bills { 1853f7c5e40SJason M. Bills // get sensor type string from path, path is defined as 1863f7c5e40SJason M. Bills // /xyz/openbmc_project/sensors/<type>/label 1873f7c5e40SJason M. Bills size_t typeEnd = path.rfind("/"); 188360f593bSJason M. Bills if (typeEnd == std::string::npos) 1893f7c5e40SJason M. Bills { 1903f7c5e40SJason M. Bills return path; 1913f7c5e40SJason M. Bills } 192360f593bSJason M. Bills size_t typeStart = path.rfind("/", typeEnd - 1); 193360f593bSJason M. Bills if (typeStart == std::string::npos) 194360f593bSJason M. Bills { 195360f593bSJason M. Bills return path; 196360f593bSJason M. Bills } 197360f593bSJason M. Bills // Start at the character after the '/' 198360f593bSJason M. Bills typeStart++; 199360f593bSJason M. Bills return path.substr(typeStart, typeEnd - typeStart); 200360f593bSJason M. Bills } 2013f7c5e40SJason M. Bills 2023f7c5e40SJason M. Bills inline static uint8_t getSensorTypeFromPath(const std::string& path) 2033f7c5e40SJason M. Bills { 2043f7c5e40SJason M. Bills uint8_t sensorType = 0; 2053f7c5e40SJason M. Bills std::string type = getSensorTypeStringFromPath(path); 2063f7c5e40SJason M. Bills auto findSensor = sensorTypes.find(type.c_str()); 2073f7c5e40SJason M. Bills if (findSensor != sensorTypes.end()) 2083f7c5e40SJason M. Bills { 2093f7c5e40SJason M. Bills sensorType = static_cast<uint8_t>(findSensor->second); 2103f7c5e40SJason M. Bills } // else default 0x0 RESERVED 2113f7c5e40SJason M. Bills 2123f7c5e40SJason M. Bills return sensorType; 2133f7c5e40SJason M. Bills } 2143f7c5e40SJason M. Bills 2153f7c5e40SJason M. Bills inline static uint8_t getSensorNumberFromPath(const std::string& path) 2163f7c5e40SJason M. Bills { 217a9423b6eSJason M. Bills std::shared_ptr<SensorNumMap> sensorNumMapPtr; 218a9423b6eSJason M. Bills details::getSensorNumMap(sensorNumMapPtr); 219a9423b6eSJason M. Bills if (!sensorNumMapPtr) 220a9423b6eSJason M. Bills { 2213f7c5e40SJason M. Bills return 0xFF; 222a9423b6eSJason M. Bills } 2233f7c5e40SJason M. Bills 224a9423b6eSJason M. Bills try 2253f7c5e40SJason M. Bills { 226a9423b6eSJason M. Bills return sensorNumMapPtr->right.at(path); 227a9423b6eSJason M. Bills } 228a9423b6eSJason M. Bills catch (std::out_of_range& e) 2293f7c5e40SJason M. Bills { 230a9423b6eSJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 231a9423b6eSJason M. Bills return 0xFF; 2323f7c5e40SJason M. Bills } 2333f7c5e40SJason M. Bills } 2343f7c5e40SJason M. Bills 2353f7c5e40SJason M. Bills inline static uint8_t getSensorEventTypeFromPath(const std::string& path) 2363f7c5e40SJason M. Bills { 2373f7c5e40SJason M. Bills // TODO: Add support for additional reading types as needed 2383f7c5e40SJason M. Bills return 0x1; // reading type = threshold 2393f7c5e40SJason M. Bills } 2403f7c5e40SJason M. Bills 2413f7c5e40SJason M. Bills inline static std::string getPathFromSensorNumber(uint8_t sensorNum) 2423f7c5e40SJason M. Bills { 243a9423b6eSJason M. Bills std::shared_ptr<SensorNumMap> sensorNumMapPtr; 244a9423b6eSJason M. Bills details::getSensorNumMap(sensorNumMapPtr); 245a9423b6eSJason M. Bills if (!sensorNumMapPtr) 2463f7c5e40SJason M. Bills { 247a9423b6eSJason M. Bills return std::string(); 2483f7c5e40SJason M. Bills } 2493f7c5e40SJason M. Bills 250a9423b6eSJason M. Bills try 2513f7c5e40SJason M. Bills { 252a9423b6eSJason M. Bills return sensorNumMapPtr->left.at(sensorNum); 253a9423b6eSJason M. Bills } 254a9423b6eSJason M. Bills catch (std::out_of_range& e) 2553f7c5e40SJason M. Bills { 256a9423b6eSJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 257a9423b6eSJason M. Bills return std::string(); 2583f7c5e40SJason M. Bills } 2593f7c5e40SJason M. Bills } 260*262276f4SPatrick Venture 261*262276f4SPatrick Venture namespace ipmi 262*262276f4SPatrick Venture { 263*262276f4SPatrick Venture 264*262276f4SPatrick Venture static inline std::map<std::string, std::vector<std::string>> 265*262276f4SPatrick Venture getObjectInterfaces(const char* path) 266*262276f4SPatrick Venture { 267*262276f4SPatrick Venture std::map<std::string, std::vector<std::string>> interfacesResponse; 268*262276f4SPatrick Venture std::vector<std::string> interfaces; 269*262276f4SPatrick Venture std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 270*262276f4SPatrick Venture 271*262276f4SPatrick Venture sdbusplus::message::message getObjectMessage = 272*262276f4SPatrick Venture dbus->new_method_call("xyz.openbmc_project.ObjectMapper", 273*262276f4SPatrick Venture "/xyz/openbmc_project/object_mapper", 274*262276f4SPatrick Venture "xyz.openbmc_project.ObjectMapper", "GetObject"); 275*262276f4SPatrick Venture getObjectMessage.append(path, interfaces); 276*262276f4SPatrick Venture 277*262276f4SPatrick Venture try 278*262276f4SPatrick Venture { 279*262276f4SPatrick Venture sdbusplus::message::message response = dbus->call(getObjectMessage); 280*262276f4SPatrick Venture response.read(interfacesResponse); 281*262276f4SPatrick Venture } 282*262276f4SPatrick Venture catch (const std::exception& e) 283*262276f4SPatrick Venture { 284*262276f4SPatrick Venture phosphor::logging::log<phosphor::logging::level::ERR>( 285*262276f4SPatrick Venture "Failed to GetObject", phosphor::logging::entry("PATH=%s", path), 286*262276f4SPatrick Venture phosphor::logging::entry("WHAT=%s", e.what())); 287*262276f4SPatrick Venture } 288*262276f4SPatrick Venture 289*262276f4SPatrick Venture return interfacesResponse; 290*262276f4SPatrick Venture } 291*262276f4SPatrick Venture 292*262276f4SPatrick Venture static inline std::map<std::string, DbusVariant> 293*262276f4SPatrick Venture getEntityManagerProperties(const char* path, const char* interface) 294*262276f4SPatrick Venture { 295*262276f4SPatrick Venture std::map<std::string, DbusVariant> properties; 296*262276f4SPatrick Venture std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 297*262276f4SPatrick Venture 298*262276f4SPatrick Venture sdbusplus::message::message getProperties = 299*262276f4SPatrick Venture dbus->new_method_call("xyz.openbmc_project.EntityManager", path, 300*262276f4SPatrick Venture "org.freedesktop.DBus.Properties", "GetAll"); 301*262276f4SPatrick Venture getProperties.append(interface); 302*262276f4SPatrick Venture 303*262276f4SPatrick Venture try 304*262276f4SPatrick Venture { 305*262276f4SPatrick Venture sdbusplus::message::message response = dbus->call(getProperties); 306*262276f4SPatrick Venture response.read(properties); 307*262276f4SPatrick Venture } 308*262276f4SPatrick Venture catch (const std::exception& e) 309*262276f4SPatrick Venture { 310*262276f4SPatrick Venture phosphor::logging::log<phosphor::logging::level::ERR>( 311*262276f4SPatrick Venture "Failed to GetAll", phosphor::logging::entry("PATH=%s", path), 312*262276f4SPatrick Venture phosphor::logging::entry("INTF=%s", interface), 313*262276f4SPatrick Venture phosphor::logging::entry("WHAT=%s", e.what())); 314*262276f4SPatrick Venture } 315*262276f4SPatrick Venture 316*262276f4SPatrick Venture return properties; 317*262276f4SPatrick Venture } 318*262276f4SPatrick Venture 319*262276f4SPatrick Venture static inline const std::string* getSensorConfigurationInterface( 320*262276f4SPatrick Venture const std::map<std::string, std::vector<std::string>>& 321*262276f4SPatrick Venture sensorInterfacesResponse) 322*262276f4SPatrick Venture { 323*262276f4SPatrick Venture auto entityManagerService = 324*262276f4SPatrick Venture sensorInterfacesResponse.find("xyz.openbmc_project.EntityManager"); 325*262276f4SPatrick Venture if (entityManagerService == sensorInterfacesResponse.end()) 326*262276f4SPatrick Venture { 327*262276f4SPatrick Venture return nullptr; 328*262276f4SPatrick Venture } 329*262276f4SPatrick Venture 330*262276f4SPatrick Venture // Find the fan configuration first (fans can have multiple configuration 331*262276f4SPatrick Venture // interfaces). 332*262276f4SPatrick Venture for (const auto& entry : entityManagerService->second) 333*262276f4SPatrick Venture { 334*262276f4SPatrick Venture if (entry == "xyz.openbmc_project.Configuration.AspeedFan" || 335*262276f4SPatrick Venture entry == "xyz.openbmc_project.Configuration.I2CFan" || 336*262276f4SPatrick Venture entry == "xyz.openbmc_project.Configuration.NuvotonFan") 337*262276f4SPatrick Venture { 338*262276f4SPatrick Venture return &entry; 339*262276f4SPatrick Venture } 340*262276f4SPatrick Venture } 341*262276f4SPatrick Venture 342*262276f4SPatrick Venture for (const auto& entry : entityManagerService->second) 343*262276f4SPatrick Venture { 344*262276f4SPatrick Venture if (boost::algorithm::starts_with(entry, 345*262276f4SPatrick Venture "xyz.openbmc_project.Configuration.")) 346*262276f4SPatrick Venture { 347*262276f4SPatrick Venture return &entry; 348*262276f4SPatrick Venture } 349*262276f4SPatrick Venture } 350*262276f4SPatrick Venture 351*262276f4SPatrick Venture return nullptr; 352*262276f4SPatrick Venture } 353*262276f4SPatrick Venture 354*262276f4SPatrick Venture // Follow Association properties for Sensor back to the Board dbus object to 355*262276f4SPatrick Venture // check for an EntityId and EntityInstance property. 356*262276f4SPatrick Venture static inline void updateIpmiFromAssociation(const std::string& path, 357*262276f4SPatrick Venture const SensorMap& sensorMap, 358*262276f4SPatrick Venture uint8_t& entityId, 359*262276f4SPatrick Venture uint8_t& entityInstance) 360*262276f4SPatrick Venture { 361*262276f4SPatrick Venture namespace fs = std::filesystem; 362*262276f4SPatrick Venture 363*262276f4SPatrick Venture auto sensorAssociationObject = 364*262276f4SPatrick Venture sensorMap.find("xyz.openbmc_project.Association.Definitions"); 365*262276f4SPatrick Venture if (sensorAssociationObject == sensorMap.end()) 366*262276f4SPatrick Venture { 367*262276f4SPatrick Venture if constexpr (debug) 368*262276f4SPatrick Venture { 369*262276f4SPatrick Venture std::fprintf(stderr, "path=%s, no association interface found\n", 370*262276f4SPatrick Venture path.c_str()); 371*262276f4SPatrick Venture } 372*262276f4SPatrick Venture 373*262276f4SPatrick Venture return; 374*262276f4SPatrick Venture } 375*262276f4SPatrick Venture 376*262276f4SPatrick Venture auto associationObject = 377*262276f4SPatrick Venture sensorAssociationObject->second.find("Associations"); 378*262276f4SPatrick Venture if (associationObject == sensorAssociationObject->second.end()) 379*262276f4SPatrick Venture { 380*262276f4SPatrick Venture if constexpr (debug) 381*262276f4SPatrick Venture { 382*262276f4SPatrick Venture std::fprintf(stderr, "path=%s, no association records found\n", 383*262276f4SPatrick Venture path.c_str()); 384*262276f4SPatrick Venture } 385*262276f4SPatrick Venture 386*262276f4SPatrick Venture return; 387*262276f4SPatrick Venture } 388*262276f4SPatrick Venture 389*262276f4SPatrick Venture std::vector<Association> associationValues = 390*262276f4SPatrick Venture std::get<std::vector<Association>>(associationObject->second); 391*262276f4SPatrick Venture 392*262276f4SPatrick Venture // loop through the Associations looking for the right one: 393*262276f4SPatrick Venture for (const auto& entry : associationValues) 394*262276f4SPatrick Venture { 395*262276f4SPatrick Venture // forward, reverse, endpoint 396*262276f4SPatrick Venture const std::string& forward = std::get<0>(entry); 397*262276f4SPatrick Venture const std::string& reverse = std::get<1>(entry); 398*262276f4SPatrick Venture const std::string& endpoint = std::get<2>(entry); 399*262276f4SPatrick Venture 400*262276f4SPatrick Venture // We only currently concern ourselves with chassis+all_sensors. 401*262276f4SPatrick Venture if (!(forward == "chassis" && reverse == "all_sensors")) 402*262276f4SPatrick Venture { 403*262276f4SPatrick Venture continue; 404*262276f4SPatrick Venture } 405*262276f4SPatrick Venture 406*262276f4SPatrick Venture // the endpoint is the board entry provided by 407*262276f4SPatrick Venture // Entity-Manager. so let's grab its properties if it has 408*262276f4SPatrick Venture // the right interface. 409*262276f4SPatrick Venture 410*262276f4SPatrick Venture // just try grabbing the properties first. 411*262276f4SPatrick Venture std::map<std::string, DbusVariant> ipmiProperties = 412*262276f4SPatrick Venture getEntityManagerProperties( 413*262276f4SPatrick Venture endpoint.c_str(), 414*262276f4SPatrick Venture "xyz.openbmc_project.Inventory.Decorator.Ipmi"); 415*262276f4SPatrick Venture 416*262276f4SPatrick Venture auto entityIdProp = ipmiProperties.find("EntityId"); 417*262276f4SPatrick Venture auto entityInstanceProp = ipmiProperties.find("EntityInstance"); 418*262276f4SPatrick Venture if (entityIdProp != ipmiProperties.end()) 419*262276f4SPatrick Venture { 420*262276f4SPatrick Venture entityId = 421*262276f4SPatrick Venture static_cast<uint8_t>(std::get<uint64_t>(entityIdProp->second)); 422*262276f4SPatrick Venture } 423*262276f4SPatrick Venture if (entityInstanceProp != ipmiProperties.end()) 424*262276f4SPatrick Venture { 425*262276f4SPatrick Venture entityInstance = static_cast<uint8_t>( 426*262276f4SPatrick Venture std::get<uint64_t>(entityInstanceProp->second)); 427*262276f4SPatrick Venture } 428*262276f4SPatrick Venture 429*262276f4SPatrick Venture // Now check the entity-manager entry for this sensor to see 430*262276f4SPatrick Venture // if it has its own value and use that instead. 431*262276f4SPatrick Venture // 432*262276f4SPatrick Venture // In theory, checking this first saves us from checking 433*262276f4SPatrick Venture // both, except in most use-cases identified, there won't be 434*262276f4SPatrick Venture // a per sensor override, so we need to always check both. 435*262276f4SPatrick Venture std::string sensorNameFromPath = fs::path(path).filename(); 436*262276f4SPatrick Venture 437*262276f4SPatrick Venture std::string sensorConfigPath = endpoint + "/" + sensorNameFromPath; 438*262276f4SPatrick Venture 439*262276f4SPatrick Venture // Download the interfaces for the sensor from 440*262276f4SPatrick Venture // Entity-Manager to find the name of the configuration 441*262276f4SPatrick Venture // interface. 442*262276f4SPatrick Venture std::map<std::string, std::vector<std::string>> 443*262276f4SPatrick Venture sensorInterfacesResponse = 444*262276f4SPatrick Venture getObjectInterfaces(sensorConfigPath.c_str()); 445*262276f4SPatrick Venture 446*262276f4SPatrick Venture const std::string* configurationInterface = 447*262276f4SPatrick Venture getSensorConfigurationInterface(sensorInterfacesResponse); 448*262276f4SPatrick Venture 449*262276f4SPatrick Venture // We didnt' find a configuration interface for this sensor, but we 450*262276f4SPatrick Venture // followed the Association property to get here, so we're done 451*262276f4SPatrick Venture // searching. 452*262276f4SPatrick Venture if (!configurationInterface) 453*262276f4SPatrick Venture { 454*262276f4SPatrick Venture break; 455*262276f4SPatrick Venture } 456*262276f4SPatrick Venture 457*262276f4SPatrick Venture // We found a configuration interface. 458*262276f4SPatrick Venture std::map<std::string, DbusVariant> configurationProperties = 459*262276f4SPatrick Venture getEntityManagerProperties(sensorConfigPath.c_str(), 460*262276f4SPatrick Venture configurationInterface->c_str()); 461*262276f4SPatrick Venture 462*262276f4SPatrick Venture entityIdProp = configurationProperties.find("EntityId"); 463*262276f4SPatrick Venture entityInstanceProp = configurationProperties.find("EntityInstance"); 464*262276f4SPatrick Venture if (entityIdProp != configurationProperties.end()) 465*262276f4SPatrick Venture { 466*262276f4SPatrick Venture entityId = 467*262276f4SPatrick Venture static_cast<uint8_t>(std::get<uint64_t>(entityIdProp->second)); 468*262276f4SPatrick Venture } 469*262276f4SPatrick Venture if (entityInstanceProp != configurationProperties.end()) 470*262276f4SPatrick Venture { 471*262276f4SPatrick Venture entityInstance = static_cast<uint8_t>( 472*262276f4SPatrick Venture std::get<uint64_t>(entityInstanceProp->second)); 473*262276f4SPatrick Venture } 474*262276f4SPatrick Venture 475*262276f4SPatrick Venture // stop searching Association records. 476*262276f4SPatrick Venture break; 477*262276f4SPatrick Venture } // end for Association vectors. 478*262276f4SPatrick Venture 479*262276f4SPatrick Venture if constexpr (debug) 480*262276f4SPatrick Venture { 481*262276f4SPatrick Venture std::fprintf(stderr, "path=%s, entityId=%d, entityInstance=%d\n", 482*262276f4SPatrick Venture path.c_str(), entityId, entityInstance); 483*262276f4SPatrick Venture } 484*262276f4SPatrick Venture } 485*262276f4SPatrick Venture 486*262276f4SPatrick Venture } // namespace ipmi 487