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 17262276f4SPatrick Venture #include "commandutils.hpp" 18262276f4SPatrick 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*fcd2d3a9SJames Feist #include <phosphor-logging/log.hpp> 23*fcd2d3a9SJames Feist #include <sdbusplus/bus/match.hpp> 24*fcd2d3a9SJames Feist 25262276f4SPatrick Venture #include <cstdio> 263f7c5e40SJason M. Bills #include <cstring> 27262276f4SPatrick Venture #include <exception> 28262276f4SPatrick Venture #include <filesystem> 29262276f4SPatrick Venture #include <map> 30262276f4SPatrick Venture #include <string> 31262276f4SPatrick Venture #include <vector> 323f7c5e40SJason M. Bills 333f7c5e40SJason M. Bills #pragma once 343f7c5e40SJason M. Bills 353f7c5e40SJason M. Bills struct CmpStrVersion 363f7c5e40SJason M. Bills { 373f7c5e40SJason M. Bills bool operator()(std::string a, std::string b) const 383f7c5e40SJason M. Bills { 393f7c5e40SJason M. Bills return strverscmp(a.c_str(), b.c_str()) < 0; 403f7c5e40SJason M. Bills } 413f7c5e40SJason M. Bills }; 423f7c5e40SJason M. Bills 433f7c5e40SJason M. Bills using SensorSubTree = boost::container::flat_map< 443f7c5e40SJason M. Bills std::string, 453f7c5e40SJason M. Bills boost::container::flat_map<std::string, std::vector<std::string>>, 463f7c5e40SJason M. Bills CmpStrVersion>; 473f7c5e40SJason M. Bills 48a9423b6eSJason M. Bills using SensorNumMap = boost::bimap<int, std::string>; 49a9423b6eSJason M. Bills 50a9423b6eSJason M. Bills namespace details 513f7c5e40SJason M. Bills { 52a9423b6eSJason M. Bills inline static bool getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree) 53a9423b6eSJason M. Bills { 54a9423b6eSJason M. Bills static std::shared_ptr<SensorSubTree> sensorTreePtr; 553f7c5e40SJason M. Bills sd_bus* bus = NULL; 563f7c5e40SJason M. Bills int ret = sd_bus_default_system(&bus); 573f7c5e40SJason M. Bills if (ret < 0) 583f7c5e40SJason M. Bills { 593f7c5e40SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>( 603f7c5e40SJason M. Bills "Failed to connect to system bus", 613f7c5e40SJason M. Bills phosphor::logging::entry("ERRNO=0x%X", -ret)); 623f7c5e40SJason M. Bills sd_bus_unref(bus); 633f7c5e40SJason M. Bills return false; 643f7c5e40SJason M. Bills } 653f7c5e40SJason M. Bills sdbusplus::bus::bus dbus(bus); 66a9423b6eSJason M. Bills static sdbusplus::bus::match::match sensorAdded( 67a9423b6eSJason M. Bills dbus, 68a9423b6eSJason M. Bills "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/" 69a9423b6eSJason M. Bills "sensors/'", 70a9423b6eSJason M. Bills [](sdbusplus::message::message& m) { sensorTreePtr.reset(); }); 71a9423b6eSJason M. Bills 72a9423b6eSJason M. Bills static sdbusplus::bus::match::match sensorRemoved( 73a9423b6eSJason M. Bills dbus, 74a9423b6eSJason M. Bills "type='signal',member='InterfacesRemoved',arg0path='/xyz/" 75a9423b6eSJason M. Bills "openbmc_project/sensors/'", 76a9423b6eSJason M. Bills [](sdbusplus::message::message& m) { sensorTreePtr.reset(); }); 77a9423b6eSJason M. Bills 78a9423b6eSJason M. Bills bool sensorTreeUpdated = false; 79a9423b6eSJason M. Bills if (sensorTreePtr) 80a9423b6eSJason M. Bills { 81a9423b6eSJason M. Bills subtree = sensorTreePtr; 82a9423b6eSJason M. Bills return sensorTreeUpdated; 83a9423b6eSJason M. Bills } 84a9423b6eSJason M. Bills 85a9423b6eSJason M. Bills sensorTreePtr = std::make_shared<SensorSubTree>(); 86a9423b6eSJason M. Bills 873f7c5e40SJason M. Bills auto mapperCall = 883f7c5e40SJason M. Bills dbus.new_method_call("xyz.openbmc_project.ObjectMapper", 893f7c5e40SJason M. Bills "/xyz/openbmc_project/object_mapper", 903f7c5e40SJason M. Bills "xyz.openbmc_project.ObjectMapper", "GetSubTree"); 9152341e85SJason M. Bills static constexpr const auto depth = 2; 923f7c5e40SJason M. Bills static constexpr std::array<const char*, 3> interfaces = { 933f7c5e40SJason M. Bills "xyz.openbmc_project.Sensor.Value", 943f7c5e40SJason M. Bills "xyz.openbmc_project.Sensor.Threshold.Warning", 953f7c5e40SJason M. Bills "xyz.openbmc_project.Sensor.Threshold.Critical"}; 963f7c5e40SJason M. Bills mapperCall.append("/xyz/openbmc_project/sensors", depth, interfaces); 973f7c5e40SJason M. Bills 983f7c5e40SJason M. Bills try 993f7c5e40SJason M. Bills { 1003f7c5e40SJason M. Bills auto mapperReply = dbus.call(mapperCall); 101a9423b6eSJason M. Bills mapperReply.read(*sensorTreePtr); 1023f7c5e40SJason M. Bills } 10352341e85SJason M. Bills catch (sdbusplus::exception_t& e) 1043f7c5e40SJason M. Bills { 10552341e85SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 106a9423b6eSJason M. Bills return sensorTreeUpdated; 107a9423b6eSJason M. Bills } 108a9423b6eSJason M. Bills subtree = sensorTreePtr; 109a9423b6eSJason M. Bills sensorTreeUpdated = true; 110a9423b6eSJason M. Bills return sensorTreeUpdated; 111a9423b6eSJason M. Bills } 112a9423b6eSJason M. Bills 113a9423b6eSJason M. Bills inline static bool getSensorNumMap(std::shared_ptr<SensorNumMap>& sensorNumMap) 114a9423b6eSJason M. Bills { 115a9423b6eSJason M. Bills static std::shared_ptr<SensorNumMap> sensorNumMapPtr; 116a9423b6eSJason M. Bills bool sensorNumMapUpated = false; 117a9423b6eSJason M. Bills 118a9423b6eSJason M. Bills std::shared_ptr<SensorSubTree> sensorTree; 119a9423b6eSJason M. Bills bool sensorTreeUpdated = details::getSensorSubtree(sensorTree); 120a9423b6eSJason M. Bills if (!sensorTree) 121a9423b6eSJason M. Bills { 122a9423b6eSJason M. Bills return sensorNumMapUpated; 123a9423b6eSJason M. Bills } 124a9423b6eSJason M. Bills 125a9423b6eSJason M. Bills if (!sensorTreeUpdated && sensorNumMapPtr) 126a9423b6eSJason M. Bills { 127a9423b6eSJason M. Bills sensorNumMap = sensorNumMapPtr; 128a9423b6eSJason M. Bills return sensorNumMapUpated; 129a9423b6eSJason M. Bills } 130a9423b6eSJason M. Bills 131a9423b6eSJason M. Bills sensorNumMapPtr = std::make_shared<SensorNumMap>(); 132a9423b6eSJason M. Bills 133caed905dSJason M. Bills uint8_t sensorNum = 0; 134a9423b6eSJason M. Bills for (const auto& sensor : *sensorTree) 135a9423b6eSJason M. Bills { 136a9423b6eSJason M. Bills sensorNumMapPtr->insert( 137a9423b6eSJason M. Bills SensorNumMap::value_type(sensorNum++, sensor.first)); 138a9423b6eSJason M. Bills } 139a9423b6eSJason M. Bills sensorNumMap = sensorNumMapPtr; 140a9423b6eSJason M. Bills sensorNumMapUpated = true; 141a9423b6eSJason M. Bills return sensorNumMapUpated; 142a9423b6eSJason M. Bills } 143a9423b6eSJason M. Bills } // namespace details 144a9423b6eSJason M. Bills 145a9423b6eSJason M. Bills inline static bool getSensorSubtree(SensorSubTree& subtree) 146a9423b6eSJason M. Bills { 147a9423b6eSJason M. Bills std::shared_ptr<SensorSubTree> sensorTree; 148a9423b6eSJason M. Bills details::getSensorSubtree(sensorTree); 149a9423b6eSJason M. Bills if (!sensorTree) 150a9423b6eSJason M. Bills { 1513f7c5e40SJason M. Bills return false; 1523f7c5e40SJason M. Bills } 153a9423b6eSJason M. Bills 154a9423b6eSJason M. Bills subtree = *sensorTree; 1553f7c5e40SJason M. Bills return true; 1563f7c5e40SJason M. Bills } 1573f7c5e40SJason M. Bills 1583f7c5e40SJason M. Bills struct CmpStr 1593f7c5e40SJason M. Bills { 1603f7c5e40SJason M. Bills bool operator()(const char* a, const char* b) const 1613f7c5e40SJason M. Bills { 1623f7c5e40SJason M. Bills return std::strcmp(a, b) < 0; 1633f7c5e40SJason M. Bills } 1643f7c5e40SJason M. Bills }; 1653f7c5e40SJason M. Bills 16652341e85SJason M. Bills enum class SensorTypeCodes : uint8_t 16752341e85SJason M. Bills { 16852341e85SJason M. Bills reserved = 0x0, 16952341e85SJason M. Bills temperature = 0x1, 17052341e85SJason M. Bills voltage = 0x2, 17152341e85SJason M. Bills current = 0x3, 17252341e85SJason M. Bills fan = 0x4, 17352341e85SJason M. Bills other = 0xB, 17452341e85SJason M. Bills }; 17552341e85SJason M. Bills 1763f7c5e40SJason M. Bills const static boost::container::flat_map<const char*, SensorTypeCodes, CmpStr> 1773f7c5e40SJason M. Bills sensorTypes{{{"temperature", SensorTypeCodes::temperature}, 1783f7c5e40SJason M. Bills {"voltage", SensorTypeCodes::voltage}, 1793f7c5e40SJason M. Bills {"current", SensorTypeCodes::current}, 1803f7c5e40SJason M. Bills {"fan_tach", SensorTypeCodes::fan}, 181f426f334SJames Feist {"fan_pwm", SensorTypeCodes::fan}, 1823f7c5e40SJason M. Bills {"power", SensorTypeCodes::other}}}; 1833f7c5e40SJason M. Bills 1843f7c5e40SJason M. Bills inline static std::string getSensorTypeStringFromPath(const std::string& path) 1853f7c5e40SJason M. Bills { 1863f7c5e40SJason M. Bills // get sensor type string from path, path is defined as 1873f7c5e40SJason M. Bills // /xyz/openbmc_project/sensors/<type>/label 1883f7c5e40SJason M. Bills size_t typeEnd = path.rfind("/"); 189360f593bSJason M. Bills if (typeEnd == std::string::npos) 1903f7c5e40SJason M. Bills { 1913f7c5e40SJason M. Bills return path; 1923f7c5e40SJason M. Bills } 193360f593bSJason M. Bills size_t typeStart = path.rfind("/", typeEnd - 1); 194360f593bSJason M. Bills if (typeStart == std::string::npos) 195360f593bSJason M. Bills { 196360f593bSJason M. Bills return path; 197360f593bSJason M. Bills } 198360f593bSJason M. Bills // Start at the character after the '/' 199360f593bSJason M. Bills typeStart++; 200360f593bSJason M. Bills return path.substr(typeStart, typeEnd - typeStart); 201360f593bSJason M. Bills } 2023f7c5e40SJason M. Bills 2033f7c5e40SJason M. Bills inline static uint8_t getSensorTypeFromPath(const std::string& path) 2043f7c5e40SJason M. Bills { 2053f7c5e40SJason M. Bills uint8_t sensorType = 0; 2063f7c5e40SJason M. Bills std::string type = getSensorTypeStringFromPath(path); 2073f7c5e40SJason M. Bills auto findSensor = sensorTypes.find(type.c_str()); 2083f7c5e40SJason M. Bills if (findSensor != sensorTypes.end()) 2093f7c5e40SJason M. Bills { 2103f7c5e40SJason M. Bills sensorType = static_cast<uint8_t>(findSensor->second); 2113f7c5e40SJason M. Bills } // else default 0x0 RESERVED 2123f7c5e40SJason M. Bills 2133f7c5e40SJason M. Bills return sensorType; 2143f7c5e40SJason M. Bills } 2153f7c5e40SJason M. Bills 2163f7c5e40SJason M. Bills inline static uint8_t getSensorNumberFromPath(const std::string& path) 2173f7c5e40SJason M. Bills { 218a9423b6eSJason M. Bills std::shared_ptr<SensorNumMap> sensorNumMapPtr; 219a9423b6eSJason M. Bills details::getSensorNumMap(sensorNumMapPtr); 220a9423b6eSJason M. Bills if (!sensorNumMapPtr) 221a9423b6eSJason M. Bills { 2223f7c5e40SJason M. Bills return 0xFF; 223a9423b6eSJason M. Bills } 2243f7c5e40SJason M. Bills 225a9423b6eSJason M. Bills try 2263f7c5e40SJason M. Bills { 227a9423b6eSJason M. Bills return sensorNumMapPtr->right.at(path); 228a9423b6eSJason M. Bills } 229a9423b6eSJason M. Bills catch (std::out_of_range& e) 2303f7c5e40SJason M. Bills { 231a9423b6eSJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 232a9423b6eSJason M. Bills return 0xFF; 2333f7c5e40SJason M. Bills } 2343f7c5e40SJason M. Bills } 2353f7c5e40SJason M. Bills 2363f7c5e40SJason M. Bills inline static uint8_t getSensorEventTypeFromPath(const std::string& path) 2373f7c5e40SJason M. Bills { 2383f7c5e40SJason M. Bills // TODO: Add support for additional reading types as needed 2393f7c5e40SJason M. Bills return 0x1; // reading type = threshold 2403f7c5e40SJason M. Bills } 2413f7c5e40SJason M. Bills 2423f7c5e40SJason M. Bills inline static std::string getPathFromSensorNumber(uint8_t sensorNum) 2433f7c5e40SJason M. Bills { 244a9423b6eSJason M. Bills std::shared_ptr<SensorNumMap> sensorNumMapPtr; 245a9423b6eSJason M. Bills details::getSensorNumMap(sensorNumMapPtr); 246a9423b6eSJason M. Bills if (!sensorNumMapPtr) 2473f7c5e40SJason M. Bills { 248a9423b6eSJason M. Bills return std::string(); 2493f7c5e40SJason M. Bills } 2503f7c5e40SJason M. Bills 251a9423b6eSJason M. Bills try 2523f7c5e40SJason M. Bills { 253a9423b6eSJason M. Bills return sensorNumMapPtr->left.at(sensorNum); 254a9423b6eSJason M. Bills } 255a9423b6eSJason M. Bills catch (std::out_of_range& e) 2563f7c5e40SJason M. Bills { 257a9423b6eSJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 258a9423b6eSJason M. Bills return std::string(); 2593f7c5e40SJason M. Bills } 2603f7c5e40SJason M. Bills } 261262276f4SPatrick Venture 262262276f4SPatrick Venture namespace ipmi 263262276f4SPatrick Venture { 264262276f4SPatrick Venture 265262276f4SPatrick Venture static inline std::map<std::string, std::vector<std::string>> 266262276f4SPatrick Venture getObjectInterfaces(const char* path) 267262276f4SPatrick Venture { 268262276f4SPatrick Venture std::map<std::string, std::vector<std::string>> interfacesResponse; 269262276f4SPatrick Venture std::vector<std::string> interfaces; 270262276f4SPatrick Venture std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 271262276f4SPatrick Venture 272262276f4SPatrick Venture sdbusplus::message::message getObjectMessage = 273262276f4SPatrick Venture dbus->new_method_call("xyz.openbmc_project.ObjectMapper", 274262276f4SPatrick Venture "/xyz/openbmc_project/object_mapper", 275262276f4SPatrick Venture "xyz.openbmc_project.ObjectMapper", "GetObject"); 276262276f4SPatrick Venture getObjectMessage.append(path, interfaces); 277262276f4SPatrick Venture 278262276f4SPatrick Venture try 279262276f4SPatrick Venture { 280262276f4SPatrick Venture sdbusplus::message::message response = dbus->call(getObjectMessage); 281262276f4SPatrick Venture response.read(interfacesResponse); 282262276f4SPatrick Venture } 283262276f4SPatrick Venture catch (const std::exception& e) 284262276f4SPatrick Venture { 285262276f4SPatrick Venture phosphor::logging::log<phosphor::logging::level::ERR>( 286262276f4SPatrick Venture "Failed to GetObject", phosphor::logging::entry("PATH=%s", path), 287262276f4SPatrick Venture phosphor::logging::entry("WHAT=%s", e.what())); 288262276f4SPatrick Venture } 289262276f4SPatrick Venture 290262276f4SPatrick Venture return interfacesResponse; 291262276f4SPatrick Venture } 292262276f4SPatrick Venture 293262276f4SPatrick Venture static inline std::map<std::string, DbusVariant> 294262276f4SPatrick Venture getEntityManagerProperties(const char* path, const char* interface) 295262276f4SPatrick Venture { 296262276f4SPatrick Venture std::map<std::string, DbusVariant> properties; 297262276f4SPatrick Venture std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 298262276f4SPatrick Venture 299262276f4SPatrick Venture sdbusplus::message::message getProperties = 300262276f4SPatrick Venture dbus->new_method_call("xyz.openbmc_project.EntityManager", path, 301262276f4SPatrick Venture "org.freedesktop.DBus.Properties", "GetAll"); 302262276f4SPatrick Venture getProperties.append(interface); 303262276f4SPatrick Venture 304262276f4SPatrick Venture try 305262276f4SPatrick Venture { 306262276f4SPatrick Venture sdbusplus::message::message response = dbus->call(getProperties); 307262276f4SPatrick Venture response.read(properties); 308262276f4SPatrick Venture } 309262276f4SPatrick Venture catch (const std::exception& e) 310262276f4SPatrick Venture { 311262276f4SPatrick Venture phosphor::logging::log<phosphor::logging::level::ERR>( 312262276f4SPatrick Venture "Failed to GetAll", phosphor::logging::entry("PATH=%s", path), 313262276f4SPatrick Venture phosphor::logging::entry("INTF=%s", interface), 314262276f4SPatrick Venture phosphor::logging::entry("WHAT=%s", e.what())); 315262276f4SPatrick Venture } 316262276f4SPatrick Venture 317262276f4SPatrick Venture return properties; 318262276f4SPatrick Venture } 319262276f4SPatrick Venture 320262276f4SPatrick Venture static inline const std::string* getSensorConfigurationInterface( 321262276f4SPatrick Venture const std::map<std::string, std::vector<std::string>>& 322262276f4SPatrick Venture sensorInterfacesResponse) 323262276f4SPatrick Venture { 324262276f4SPatrick Venture auto entityManagerService = 325262276f4SPatrick Venture sensorInterfacesResponse.find("xyz.openbmc_project.EntityManager"); 326262276f4SPatrick Venture if (entityManagerService == sensorInterfacesResponse.end()) 327262276f4SPatrick Venture { 328262276f4SPatrick Venture return nullptr; 329262276f4SPatrick Venture } 330262276f4SPatrick Venture 331262276f4SPatrick Venture // Find the fan configuration first (fans can have multiple configuration 332262276f4SPatrick Venture // interfaces). 333262276f4SPatrick Venture for (const auto& entry : entityManagerService->second) 334262276f4SPatrick Venture { 335262276f4SPatrick Venture if (entry == "xyz.openbmc_project.Configuration.AspeedFan" || 336262276f4SPatrick Venture entry == "xyz.openbmc_project.Configuration.I2CFan" || 337262276f4SPatrick Venture entry == "xyz.openbmc_project.Configuration.NuvotonFan") 338262276f4SPatrick Venture { 339262276f4SPatrick Venture return &entry; 340262276f4SPatrick Venture } 341262276f4SPatrick Venture } 342262276f4SPatrick Venture 343262276f4SPatrick Venture for (const auto& entry : entityManagerService->second) 344262276f4SPatrick Venture { 345262276f4SPatrick Venture if (boost::algorithm::starts_with(entry, 346262276f4SPatrick Venture "xyz.openbmc_project.Configuration.")) 347262276f4SPatrick Venture { 348262276f4SPatrick Venture return &entry; 349262276f4SPatrick Venture } 350262276f4SPatrick Venture } 351262276f4SPatrick Venture 352262276f4SPatrick Venture return nullptr; 353262276f4SPatrick Venture } 354262276f4SPatrick Venture 355262276f4SPatrick Venture // Follow Association properties for Sensor back to the Board dbus object to 356262276f4SPatrick Venture // check for an EntityId and EntityInstance property. 357262276f4SPatrick Venture static inline void updateIpmiFromAssociation(const std::string& path, 358262276f4SPatrick Venture const SensorMap& sensorMap, 359262276f4SPatrick Venture uint8_t& entityId, 360262276f4SPatrick Venture uint8_t& entityInstance) 361262276f4SPatrick Venture { 362262276f4SPatrick Venture namespace fs = std::filesystem; 363262276f4SPatrick Venture 364262276f4SPatrick Venture auto sensorAssociationObject = 365262276f4SPatrick Venture sensorMap.find("xyz.openbmc_project.Association.Definitions"); 366262276f4SPatrick Venture if (sensorAssociationObject == sensorMap.end()) 367262276f4SPatrick Venture { 368262276f4SPatrick Venture if constexpr (debug) 369262276f4SPatrick Venture { 370262276f4SPatrick Venture std::fprintf(stderr, "path=%s, no association interface found\n", 371262276f4SPatrick Venture path.c_str()); 372262276f4SPatrick Venture } 373262276f4SPatrick Venture 374262276f4SPatrick Venture return; 375262276f4SPatrick Venture } 376262276f4SPatrick Venture 377262276f4SPatrick Venture auto associationObject = 378262276f4SPatrick Venture sensorAssociationObject->second.find("Associations"); 379262276f4SPatrick Venture if (associationObject == sensorAssociationObject->second.end()) 380262276f4SPatrick Venture { 381262276f4SPatrick Venture if constexpr (debug) 382262276f4SPatrick Venture { 383262276f4SPatrick Venture std::fprintf(stderr, "path=%s, no association records found\n", 384262276f4SPatrick Venture path.c_str()); 385262276f4SPatrick Venture } 386262276f4SPatrick Venture 387262276f4SPatrick Venture return; 388262276f4SPatrick Venture } 389262276f4SPatrick Venture 390262276f4SPatrick Venture std::vector<Association> associationValues = 391262276f4SPatrick Venture std::get<std::vector<Association>>(associationObject->second); 392262276f4SPatrick Venture 393262276f4SPatrick Venture // loop through the Associations looking for the right one: 394262276f4SPatrick Venture for (const auto& entry : associationValues) 395262276f4SPatrick Venture { 396262276f4SPatrick Venture // forward, reverse, endpoint 397262276f4SPatrick Venture const std::string& forward = std::get<0>(entry); 398262276f4SPatrick Venture const std::string& reverse = std::get<1>(entry); 399262276f4SPatrick Venture const std::string& endpoint = std::get<2>(entry); 400262276f4SPatrick Venture 401262276f4SPatrick Venture // We only currently concern ourselves with chassis+all_sensors. 402262276f4SPatrick Venture if (!(forward == "chassis" && reverse == "all_sensors")) 403262276f4SPatrick Venture { 404262276f4SPatrick Venture continue; 405262276f4SPatrick Venture } 406262276f4SPatrick Venture 407262276f4SPatrick Venture // the endpoint is the board entry provided by 408262276f4SPatrick Venture // Entity-Manager. so let's grab its properties if it has 409262276f4SPatrick Venture // the right interface. 410262276f4SPatrick Venture 411262276f4SPatrick Venture // just try grabbing the properties first. 412262276f4SPatrick Venture std::map<std::string, DbusVariant> ipmiProperties = 413262276f4SPatrick Venture getEntityManagerProperties( 414262276f4SPatrick Venture endpoint.c_str(), 415262276f4SPatrick Venture "xyz.openbmc_project.Inventory.Decorator.Ipmi"); 416262276f4SPatrick Venture 417262276f4SPatrick Venture auto entityIdProp = ipmiProperties.find("EntityId"); 418262276f4SPatrick Venture auto entityInstanceProp = ipmiProperties.find("EntityInstance"); 419262276f4SPatrick Venture if (entityIdProp != ipmiProperties.end()) 420262276f4SPatrick Venture { 421262276f4SPatrick Venture entityId = 422262276f4SPatrick Venture static_cast<uint8_t>(std::get<uint64_t>(entityIdProp->second)); 423262276f4SPatrick Venture } 424262276f4SPatrick Venture if (entityInstanceProp != ipmiProperties.end()) 425262276f4SPatrick Venture { 426262276f4SPatrick Venture entityInstance = static_cast<uint8_t>( 427262276f4SPatrick Venture std::get<uint64_t>(entityInstanceProp->second)); 428262276f4SPatrick Venture } 429262276f4SPatrick Venture 430262276f4SPatrick Venture // Now check the entity-manager entry for this sensor to see 431262276f4SPatrick Venture // if it has its own value and use that instead. 432262276f4SPatrick Venture // 433262276f4SPatrick Venture // In theory, checking this first saves us from checking 434262276f4SPatrick Venture // both, except in most use-cases identified, there won't be 435262276f4SPatrick Venture // a per sensor override, so we need to always check both. 436262276f4SPatrick Venture std::string sensorNameFromPath = fs::path(path).filename(); 437262276f4SPatrick Venture 438262276f4SPatrick Venture std::string sensorConfigPath = endpoint + "/" + sensorNameFromPath; 439262276f4SPatrick Venture 440262276f4SPatrick Venture // Download the interfaces for the sensor from 441262276f4SPatrick Venture // Entity-Manager to find the name of the configuration 442262276f4SPatrick Venture // interface. 443262276f4SPatrick Venture std::map<std::string, std::vector<std::string>> 444262276f4SPatrick Venture sensorInterfacesResponse = 445262276f4SPatrick Venture getObjectInterfaces(sensorConfigPath.c_str()); 446262276f4SPatrick Venture 447262276f4SPatrick Venture const std::string* configurationInterface = 448262276f4SPatrick Venture getSensorConfigurationInterface(sensorInterfacesResponse); 449262276f4SPatrick Venture 450262276f4SPatrick Venture // We didnt' find a configuration interface for this sensor, but we 451262276f4SPatrick Venture // followed the Association property to get here, so we're done 452262276f4SPatrick Venture // searching. 453262276f4SPatrick Venture if (!configurationInterface) 454262276f4SPatrick Venture { 455262276f4SPatrick Venture break; 456262276f4SPatrick Venture } 457262276f4SPatrick Venture 458262276f4SPatrick Venture // We found a configuration interface. 459262276f4SPatrick Venture std::map<std::string, DbusVariant> configurationProperties = 460262276f4SPatrick Venture getEntityManagerProperties(sensorConfigPath.c_str(), 461262276f4SPatrick Venture configurationInterface->c_str()); 462262276f4SPatrick Venture 463262276f4SPatrick Venture entityIdProp = configurationProperties.find("EntityId"); 464262276f4SPatrick Venture entityInstanceProp = configurationProperties.find("EntityInstance"); 465262276f4SPatrick Venture if (entityIdProp != configurationProperties.end()) 466262276f4SPatrick Venture { 467262276f4SPatrick Venture entityId = 468262276f4SPatrick Venture static_cast<uint8_t>(std::get<uint64_t>(entityIdProp->second)); 469262276f4SPatrick Venture } 470262276f4SPatrick Venture if (entityInstanceProp != configurationProperties.end()) 471262276f4SPatrick Venture { 472262276f4SPatrick Venture entityInstance = static_cast<uint8_t>( 473262276f4SPatrick Venture std::get<uint64_t>(entityInstanceProp->second)); 474262276f4SPatrick Venture } 475262276f4SPatrick Venture 476262276f4SPatrick Venture // stop searching Association records. 477262276f4SPatrick Venture break; 478262276f4SPatrick Venture } // end for Association vectors. 479262276f4SPatrick Venture 480262276f4SPatrick Venture if constexpr (debug) 481262276f4SPatrick Venture { 482262276f4SPatrick Venture std::fprintf(stderr, "path=%s, entityId=%d, entityInstance=%d\n", 483262276f4SPatrick Venture path.c_str(), entityId, entityInstance); 484262276f4SPatrick Venture } 485262276f4SPatrick Venture } 486262276f4SPatrick Venture 487262276f4SPatrick Venture } // namespace ipmi 488