blob: e7ed3478a9f6c8da2714d594d4bdf9ad7bab42e4 [file] [log] [blame]
Willy Tude54f482021-01-26 15:59:09 -08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include "dbus-sdr/sdrutils.hpp"
18
Johnathan Mantey04b0b072023-10-10 12:30:35 -070019#include <nlohmann/json.hpp>
20
21#include <fstream>
Willy Tu4eca2512022-06-20 21:14:51 -070022#include <optional>
23#include <unordered_set>
24
Scron Chang2703b022021-07-06 15:47:45 +080025#ifdef FEATURE_HYBRID_SENSORS
26
27#include <ipmid/utils.hpp>
28namespace ipmi
29{
30namespace sensor
31{
32extern const IdInfoMap sensors;
33} // namespace sensor
34} // namespace ipmi
35
36#endif
37
Willy Tude54f482021-01-26 15:59:09 -080038namespace details
39{
Johnathan Mantey04b0b072023-10-10 12:30:35 -070040
41// IPMI supports a smaller number of sensors than are available via Redfish.
42// Trim the list of sensors, via a configuration file.
43// Read the IPMI Sensor Filtering section in docs/configuration.md for
44// a more detailed description.
45static void filterSensors(SensorSubTree& subtree)
46{
47 constexpr const char* filterFilename =
48 "/usr/share/ipmi-providers/sensor_filter.json";
49 std::ifstream filterFile(filterFilename);
50 if (!filterFile.good())
51 {
52 return;
53 }
54 nlohmann::json sensorFilterJSON = nlohmann::json::parse(filterFile, nullptr,
55 false);
56 nlohmann::json::iterator svcFilterit =
57 sensorFilterJSON.find("ServiceFilter");
58 if (svcFilterit == sensorFilterJSON.end())
59 {
60 return;
61 }
62
63 subtree.erase(std::remove_if(subtree.begin(), subtree.end(),
64 [svcFilterit](SensorSubTree::value_type& kv) {
65 auto& [_, serviceToIfaces] = kv;
66
67 for (auto service = svcFilterit->begin(); service != svcFilterit->end();
68 ++service)
69 {
70 serviceToIfaces.erase(*service);
71 }
72 return serviceToIfaces.empty();
73 }),
74 subtree.end());
75}
76
Kuiying Wanga8b5b262021-02-06 23:38:22 +080077uint16_t getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree)
Willy Tude54f482021-01-26 15:59:09 -080078{
79 static std::shared_ptr<SensorSubTree> sensorTreePtr;
Kuiying Wanga8b5b262021-02-06 23:38:22 +080080 static uint16_t sensorUpdatedIndex = 0;
Willy Tude54f482021-01-26 15:59:09 -080081 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
Patrick Williams5d82f472022-07-22 19:26:53 -050082 static sdbusplus::bus::match_t sensorAdded(
Willy Tude54f482021-01-26 15:59:09 -080083 *dbus,
84 "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/"
85 "sensors/'",
Patrick Williams5d82f472022-07-22 19:26:53 -050086 [](sdbusplus::message_t&) { sensorTreePtr.reset(); });
Willy Tude54f482021-01-26 15:59:09 -080087
Patrick Williams5d82f472022-07-22 19:26:53 -050088 static sdbusplus::bus::match_t sensorRemoved(
Willy Tude54f482021-01-26 15:59:09 -080089 *dbus,
90 "type='signal',member='InterfacesRemoved',arg0path='/xyz/"
91 "openbmc_project/sensors/'",
Patrick Williams5d82f472022-07-22 19:26:53 -050092 [](sdbusplus::message_t&) { sensorTreePtr.reset(); });
Willy Tude54f482021-01-26 15:59:09 -080093
Willy Tude54f482021-01-26 15:59:09 -080094 if (sensorTreePtr)
95 {
96 subtree = sensorTreePtr;
Kuiying Wanga8b5b262021-02-06 23:38:22 +080097 return sensorUpdatedIndex;
Willy Tude54f482021-01-26 15:59:09 -080098 }
99
100 sensorTreePtr = std::make_shared<SensorSubTree>();
101
Willy Tude54f482021-01-26 15:59:09 -0800102 static constexpr const int32_t depth = 2;
Hao Jiang9a5b51e2021-01-06 10:32:22 -0800103
Patrick Williams369824e2023-10-20 11:18:23 -0500104 auto lbdUpdateSensorTree = [&dbus](const char* path,
105 const auto& interfaces) {
Hao Jiang9a5b51e2021-01-06 10:32:22 -0800106 auto mapperCall = dbus->new_method_call(
107 "xyz.openbmc_project.ObjectMapper",
108 "/xyz/openbmc_project/object_mapper",
109 "xyz.openbmc_project.ObjectMapper", "GetSubTree");
110 SensorSubTree sensorTreePartial;
111
112 mapperCall.append(path, depth, interfaces);
113
114 try
115 {
116 auto mapperReply = dbus->call(mapperCall);
117 mapperReply.read(sensorTreePartial);
118 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500119 catch (const sdbusplus::exception_t& e)
Hao Jiang9a5b51e2021-01-06 10:32:22 -0800120 {
121 phosphor::logging::log<phosphor::logging::level::ERR>(
122 "fail to update subtree",
123 phosphor::logging::entry("PATH=%s", path),
124 phosphor::logging::entry("WHAT=%s", e.what()));
125 return false;
126 }
127 if constexpr (debug)
128 {
129 std::fprintf(stderr, "IPMI updated: %zu sensors under %s\n",
130 sensorTreePartial.size(), path);
131 }
132 sensorTreePtr->merge(std::move(sensorTreePartial));
133 return true;
134 };
135
136 // Add sensors to SensorTree
137 static constexpr const std::array sensorInterfaces = {
Willy Tude54f482021-01-26 15:59:09 -0800138 "xyz.openbmc_project.Sensor.Value",
Jie Yangf0a89942021-07-29 15:30:25 -0700139 "xyz.openbmc_project.Sensor.ValueMutability",
Willy Tude54f482021-01-26 15:59:09 -0800140 "xyz.openbmc_project.Sensor.Threshold.Warning",
141 "xyz.openbmc_project.Sensor.Threshold.Critical"};
Hao Jiang9a5b51e2021-01-06 10:32:22 -0800142 static constexpr const std::array vrInterfaces = {
143 "xyz.openbmc_project.Control.VoltageRegulatorMode"};
Willy Tude54f482021-01-26 15:59:09 -0800144
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500145 bool sensorRez = lbdUpdateSensorTree("/xyz/openbmc_project/sensors",
146 sensorInterfaces);
Hao Jiang9a5b51e2021-01-06 10:32:22 -0800147
Scron Chang2703b022021-07-06 15:47:45 +0800148#ifdef FEATURE_HYBRID_SENSORS
149
150 if (!ipmi::sensor::sensors.empty())
151 {
152 for (const auto& sensor : ipmi::sensor::sensors)
153 {
154 // Threshold sensors should not be emplaced in here.
155 if (boost::starts_with(sensor.second.sensorPath,
156 "/xyz/openbmc_project/sensors/"))
157 {
158 continue;
159 }
160
161 // The bus service name is not listed in ipmi::sensor::Info. Give it
162 // an empty string. For those function using non-threshold sensors,
163 // the bus service name will be retrieved in an alternative way.
164 boost::container::flat_map<std::string, std::vector<std::string>>
165 connectionMap{
166 {"", {sensor.second.propertyInterfaces.begin()->first}}};
167 sensorTreePtr->emplace(sensor.second.sensorPath, connectionMap);
168 }
169 }
170
171#endif
172
Hao Jiang9a5b51e2021-01-06 10:32:22 -0800173 // Error if searching for sensors failed.
174 if (!sensorRez)
Willy Tude54f482021-01-26 15:59:09 -0800175 {
Kuiying Wanga8b5b262021-02-06 23:38:22 +0800176 return sensorUpdatedIndex;
Willy Tude54f482021-01-26 15:59:09 -0800177 }
Hao Jiang9a5b51e2021-01-06 10:32:22 -0800178
Johnathan Mantey04b0b072023-10-10 12:30:35 -0700179 filterSensors(*sensorTreePtr);
Hao Jiang9a5b51e2021-01-06 10:32:22 -0800180 // Add VR control as optional search path.
181 (void)lbdUpdateSensorTree("/xyz/openbmc_project/vr", vrInterfaces);
182
Willy Tude54f482021-01-26 15:59:09 -0800183 subtree = sensorTreePtr;
Kuiying Wanga8b5b262021-02-06 23:38:22 +0800184 sensorUpdatedIndex++;
Josh Lehana55c9532020-10-28 21:59:06 -0700185 // The SDR is being regenerated, wipe the old stats
186 sdrStatsTable.wipeTable();
Jie Yangf0a89942021-07-29 15:30:25 -0700187 sdrWriteTable.wipeTable();
Kuiying Wanga8b5b262021-02-06 23:38:22 +0800188 return sensorUpdatedIndex;
Willy Tude54f482021-01-26 15:59:09 -0800189}
190
191bool getSensorNumMap(std::shared_ptr<SensorNumMap>& sensorNumMap)
192{
193 static std::shared_ptr<SensorNumMap> sensorNumMapPtr;
194 bool sensorNumMapUpated = false;
Kuiying Wanga8b5b262021-02-06 23:38:22 +0800195 static uint16_t prevSensorUpdatedIndex = 0;
Willy Tude54f482021-01-26 15:59:09 -0800196 std::shared_ptr<SensorSubTree> sensorTree;
Kuiying Wanga8b5b262021-02-06 23:38:22 +0800197 uint16_t curSensorUpdatedIndex = details::getSensorSubtree(sensorTree);
Willy Tude54f482021-01-26 15:59:09 -0800198 if (!sensorTree)
199 {
200 return sensorNumMapUpated;
201 }
202
Kuiying Wanga8b5b262021-02-06 23:38:22 +0800203 if ((curSensorUpdatedIndex == prevSensorUpdatedIndex) && sensorNumMapPtr)
Willy Tude54f482021-01-26 15:59:09 -0800204 {
205 sensorNumMap = sensorNumMapPtr;
206 return sensorNumMapUpated;
207 }
Kuiying Wanga8b5b262021-02-06 23:38:22 +0800208 prevSensorUpdatedIndex = curSensorUpdatedIndex;
Willy Tude54f482021-01-26 15:59:09 -0800209
210 sensorNumMapPtr = std::make_shared<SensorNumMap>();
211
212 uint16_t sensorNum = 0;
213 uint16_t sensorIndex = 0;
214 for (const auto& sensor : *sensorTree)
215 {
216 sensorNumMapPtr->insert(
217 SensorNumMap::value_type(sensorNum, sensor.first));
218 sensorIndex++;
219 if (sensorIndex == maxSensorsPerLUN)
220 {
221 sensorIndex = lun1Sensor0;
222 }
223 else if (sensorIndex == (lun1Sensor0 | maxSensorsPerLUN))
224 {
225 // Skip assigning LUN 0x2 any sensors
226 sensorIndex = lun3Sensor0;
227 }
228 else if (sensorIndex == (lun3Sensor0 | maxSensorsPerLUN))
229 {
230 // this is an error, too many IPMI sensors
231 throw std::out_of_range("Maximum number of IPMI sensors exceeded.");
232 }
233 sensorNum = sensorIndex;
234 }
235 sensorNumMap = sensorNumMapPtr;
236 sensorNumMapUpated = true;
237 return sensorNumMapUpated;
238}
239} // namespace details
240
241bool getSensorSubtree(SensorSubTree& subtree)
242{
243 std::shared_ptr<SensorSubTree> sensorTree;
244 details::getSensorSubtree(sensorTree);
245 if (!sensorTree)
246 {
247 return false;
248 }
249
250 subtree = *sensorTree;
251 return true;
252}
253
Scron Chang2703b022021-07-06 15:47:45 +0800254#ifdef FEATURE_HYBRID_SENSORS
255// Static sensors are listed in sensor-gen.cpp.
256ipmi::sensor::IdInfoMap::const_iterator
257 findStaticSensor(const std::string& path)
258{
259 return std::find_if(
260 ipmi::sensor::sensors.begin(), ipmi::sensor::sensors.end(),
261 [&path](const ipmi::sensor::IdInfoMap::value_type& findSensor) {
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500262 return findSensor.second.sensorPath == path;
Patrick Williams369824e2023-10-20 11:18:23 -0500263 });
Scron Chang2703b022021-07-06 15:47:45 +0800264}
265#endif
266
Willy Tude54f482021-01-26 15:59:09 -0800267std::string getSensorTypeStringFromPath(const std::string& path)
268{
269 // get sensor type string from path, path is defined as
270 // /xyz/openbmc_project/sensors/<type>/label
271 size_t typeEnd = path.rfind("/");
272 if (typeEnd == std::string::npos)
273 {
274 return path;
275 }
276 size_t typeStart = path.rfind("/", typeEnd - 1);
277 if (typeStart == std::string::npos)
278 {
279 return path;
280 }
281 // Start at the character after the '/'
282 typeStart++;
283 return path.substr(typeStart, typeEnd - typeStart);
284}
285
286uint8_t getSensorTypeFromPath(const std::string& path)
287{
288 uint8_t sensorType = 0;
289 std::string type = getSensorTypeStringFromPath(path);
290 auto findSensor = sensorTypes.find(type.c_str());
291 if (findSensor != sensorTypes.end())
292 {
Scron Chang2b42d7e2021-07-06 15:45:47 +0800293 sensorType =
294 static_cast<uint8_t>(std::get<sensorTypeCodes>(findSensor->second));
Willy Tude54f482021-01-26 15:59:09 -0800295 } // else default 0x0 RESERVED
296
297 return sensorType;
298}
299
300uint16_t getSensorNumberFromPath(const std::string& path)
301{
302 std::shared_ptr<SensorNumMap> sensorNumMapPtr;
303 details::getSensorNumMap(sensorNumMapPtr);
304 if (!sensorNumMapPtr)
305 {
306 return invalidSensorNumber;
307 }
308
309 try
310 {
311 return sensorNumMapPtr->right.at(path);
312 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500313 catch (const std::out_of_range& e)
Willy Tude54f482021-01-26 15:59:09 -0800314 {
Willy Tude54f482021-01-26 15:59:09 -0800315 return invalidSensorNumber;
316 }
317}
318
319uint8_t getSensorEventTypeFromPath(const std::string& path)
320{
Scron Chang2b42d7e2021-07-06 15:45:47 +0800321 uint8_t sensorEventType = 0;
322 std::string type = getSensorTypeStringFromPath(path);
323 auto findSensor = sensorTypes.find(type.c_str());
324 if (findSensor != sensorTypes.end())
325 {
326 sensorEventType = static_cast<uint8_t>(
327 std::get<sensorEventTypeCodes>(findSensor->second));
328 }
329
330 return sensorEventType;
Willy Tude54f482021-01-26 15:59:09 -0800331}
332
333std::string getPathFromSensorNumber(uint16_t sensorNum)
334{
335 std::shared_ptr<SensorNumMap> sensorNumMapPtr;
336 details::getSensorNumMap(sensorNumMapPtr);
337 if (!sensorNumMapPtr)
338 {
339 return std::string();
340 }
341
342 try
343 {
344 return sensorNumMapPtr->left.at(sensorNum);
345 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500346 catch (const std::out_of_range& e)
Willy Tude54f482021-01-26 15:59:09 -0800347 {
Willy Tude54f482021-01-26 15:59:09 -0800348 return std::string();
349 }
350}
351
352namespace ipmi
353{
354
Alexander Hansen8fb5b892023-11-02 17:29:34 +0100355std::optional<std::map<std::string, std::vector<std::string>>>
Willy Tude54f482021-01-26 15:59:09 -0800356 getObjectInterfaces(const char* path)
357{
358 std::map<std::string, std::vector<std::string>> interfacesResponse;
359 std::vector<std::string> interfaces;
360 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
361
Patrick Williams5d82f472022-07-22 19:26:53 -0500362 sdbusplus::message_t getObjectMessage =
Willy Tude54f482021-01-26 15:59:09 -0800363 dbus->new_method_call("xyz.openbmc_project.ObjectMapper",
364 "/xyz/openbmc_project/object_mapper",
365 "xyz.openbmc_project.ObjectMapper", "GetObject");
366 getObjectMessage.append(path, interfaces);
367
368 try
369 {
Patrick Williams5d82f472022-07-22 19:26:53 -0500370 sdbusplus::message_t response = dbus->call(getObjectMessage);
Willy Tude54f482021-01-26 15:59:09 -0800371 response.read(interfacesResponse);
372 }
373 catch (const std::exception& e)
374 {
Alexander Hansen8fb5b892023-11-02 17:29:34 +0100375 return std::nullopt;
Willy Tude54f482021-01-26 15:59:09 -0800376 }
377
378 return interfacesResponse;
379}
380
381std::map<std::string, Value> getEntityManagerProperties(const char* path,
382 const char* interface)
383{
384 std::map<std::string, Value> properties;
385 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
386
Patrick Williams5d82f472022-07-22 19:26:53 -0500387 sdbusplus::message_t getProperties =
Willy Tude54f482021-01-26 15:59:09 -0800388 dbus->new_method_call("xyz.openbmc_project.EntityManager", path,
389 "org.freedesktop.DBus.Properties", "GetAll");
390 getProperties.append(interface);
391
392 try
393 {
Patrick Williams5d82f472022-07-22 19:26:53 -0500394 sdbusplus::message_t response = dbus->call(getProperties);
Willy Tude54f482021-01-26 15:59:09 -0800395 response.read(properties);
396 }
397 catch (const std::exception& e)
398 {
399 phosphor::logging::log<phosphor::logging::level::ERR>(
400 "Failed to GetAll", phosphor::logging::entry("PATH=%s", path),
401 phosphor::logging::entry("INTF=%s", interface),
402 phosphor::logging::entry("WHAT=%s", e.what()));
403 }
404
405 return properties;
406}
407
Willy Tu4eca2512022-06-20 21:14:51 -0700408// Fetch the ipmiDecoratorPaths to get the list of dbus objects that
409// have ipmi decorator to prevent unnessary dbus call to fetch the info
410std::optional<std::unordered_set<std::string>>&
411 getIpmiDecoratorPaths(const std::optional<ipmi::Context::ptr>& ctx)
412{
413 static std::optional<std::unordered_set<std::string>> ipmiDecoratorPaths;
414
415 if (!ctx.has_value() || ipmiDecoratorPaths != std::nullopt)
416 {
417 return ipmiDecoratorPaths;
418 }
419
420 boost::system::error_code ec;
421 std::vector<std::string> paths =
422 (*ctx)->bus->yield_method_call<std::vector<std::string>>(
423 (*ctx)->yield, ec, "xyz.openbmc_project.ObjectMapper",
424 "/xyz/openbmc_project/object_mapper",
425 "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/",
426 int32_t(0),
427 std::array<const char*, 1>{
428 "xyz.openbmc_project.Inventory.Decorator.Ipmi"});
429 if (ec)
430 {
431 return ipmiDecoratorPaths;
432 }
433
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500434 ipmiDecoratorPaths = std::unordered_set<std::string>(paths.begin(),
435 paths.end());
Willy Tu4eca2512022-06-20 21:14:51 -0700436 return ipmiDecoratorPaths;
437}
438
Willy Tude54f482021-01-26 15:59:09 -0800439const std::string* getSensorConfigurationInterface(
440 const std::map<std::string, std::vector<std::string>>&
441 sensorInterfacesResponse)
442{
443 auto entityManagerService =
444 sensorInterfacesResponse.find("xyz.openbmc_project.EntityManager");
445 if (entityManagerService == sensorInterfacesResponse.end())
446 {
447 return nullptr;
448 }
449
450 // Find the fan configuration first (fans can have multiple configuration
451 // interfaces).
452 for (const auto& entry : entityManagerService->second)
453 {
454 if (entry == "xyz.openbmc_project.Configuration.AspeedFan" ||
455 entry == "xyz.openbmc_project.Configuration.I2CFan" ||
456 entry == "xyz.openbmc_project.Configuration.NuvotonFan")
457 {
458 return &entry;
459 }
460 }
461
462 for (const auto& entry : entityManagerService->second)
463 {
464 if (boost::algorithm::starts_with(entry,
465 "xyz.openbmc_project.Configuration."))
466 {
467 return &entry;
468 }
469 }
470
471 return nullptr;
472}
473
474// Follow Association properties for Sensor back to the Board dbus object to
475// check for an EntityId and EntityInstance property.
Willy Tu4eca2512022-06-20 21:14:51 -0700476void updateIpmiFromAssociation(
477 const std::string& path,
478 const std::unordered_set<std::string>& ipmiDecoratorPaths,
479 const DbusInterfaceMap& sensorMap, uint8_t& entityId,
480 uint8_t& entityInstance)
Willy Tude54f482021-01-26 15:59:09 -0800481{
482 namespace fs = std::filesystem;
483
484 auto sensorAssociationObject =
485 sensorMap.find("xyz.openbmc_project.Association.Definitions");
486 if (sensorAssociationObject == sensorMap.end())
487 {
488 if constexpr (debug)
489 {
490 std::fprintf(stderr, "path=%s, no association interface found\n",
491 path.c_str());
492 }
493
494 return;
495 }
496
497 auto associationObject =
498 sensorAssociationObject->second.find("Associations");
499 if (associationObject == sensorAssociationObject->second.end())
500 {
501 if constexpr (debug)
502 {
503 std::fprintf(stderr, "path=%s, no association records found\n",
504 path.c_str());
505 }
506
507 return;
508 }
509
510 std::vector<Association> associationValues =
511 std::get<std::vector<Association>>(associationObject->second);
512
513 // loop through the Associations looking for the right one:
514 for (const auto& entry : associationValues)
515 {
516 // forward, reverse, endpoint
517 const std::string& forward = std::get<0>(entry);
518 const std::string& reverse = std::get<1>(entry);
519 const std::string& endpoint = std::get<2>(entry);
520
521 // We only currently concern ourselves with chassis+all_sensors.
522 if (!(forward == "chassis" && reverse == "all_sensors"))
523 {
524 continue;
525 }
526
527 // the endpoint is the board entry provided by
528 // Entity-Manager. so let's grab its properties if it has
529 // the right interface.
530
531 // just try grabbing the properties first.
Willy Tu4eca2512022-06-20 21:14:51 -0700532 ipmi::PropertyMap::iterator entityIdProp;
533 ipmi::PropertyMap::iterator entityInstanceProp;
534 if (ipmiDecoratorPaths.contains(endpoint))
535 {
536 std::map<std::string, Value> ipmiProperties =
537 getEntityManagerProperties(
538 endpoint.c_str(),
539 "xyz.openbmc_project.Inventory.Decorator.Ipmi");
Willy Tude54f482021-01-26 15:59:09 -0800540
Willy Tu4eca2512022-06-20 21:14:51 -0700541 entityIdProp = ipmiProperties.find("EntityId");
542 entityInstanceProp = ipmiProperties.find("EntityInstance");
543 if (entityIdProp != ipmiProperties.end())
544 {
545 entityId = static_cast<uint8_t>(
546 std::get<uint64_t>(entityIdProp->second));
547 }
548 if (entityInstanceProp != ipmiProperties.end())
549 {
550 entityInstance = static_cast<uint8_t>(
551 std::get<uint64_t>(entityInstanceProp->second));
552 }
Willy Tude54f482021-01-26 15:59:09 -0800553 }
554
555 // Now check the entity-manager entry for this sensor to see
556 // if it has its own value and use that instead.
557 //
558 // In theory, checking this first saves us from checking
559 // both, except in most use-cases identified, there won't be
560 // a per sensor override, so we need to always check both.
561 std::string sensorNameFromPath = fs::path(path).filename();
562
563 std::string sensorConfigPath = endpoint + "/" + sensorNameFromPath;
564
565 // Download the interfaces for the sensor from
566 // Entity-Manager to find the name of the configuration
567 // interface.
Alexander Hansen8fb5b892023-11-02 17:29:34 +0100568 std::optional<std::map<std::string, std::vector<std::string>>>
569 sensorInterfacesResponseOpt =
Willy Tude54f482021-01-26 15:59:09 -0800570 getObjectInterfaces(sensorConfigPath.c_str());
571
Alexander Hansen8fb5b892023-11-02 17:29:34 +0100572 if (!sensorInterfacesResponseOpt.has_value())
573 {
574 phosphor::logging::log<phosphor::logging::level::DEBUG>(
575 "Failed to GetObject",
576 phosphor::logging::entry("PATH=%s", sensorConfigPath.c_str()));
577 continue;
578 }
579
Willy Tude54f482021-01-26 15:59:09 -0800580 const std::string* configurationInterface =
Alexander Hansen8fb5b892023-11-02 17:29:34 +0100581 getSensorConfigurationInterface(
582 sensorInterfacesResponseOpt.value());
Willy Tude54f482021-01-26 15:59:09 -0800583
Harvey Wu7bb84db2023-06-26 10:02:08 +0800584 // If there are multi association path settings and only one path exist,
585 // we need to continue if cannot find configuration interface for this
586 // sensor.
Willy Tude54f482021-01-26 15:59:09 -0800587 if (!configurationInterface)
588 {
Harvey Wu7bb84db2023-06-26 10:02:08 +0800589 continue;
Willy Tude54f482021-01-26 15:59:09 -0800590 }
591
592 // We found a configuration interface.
593 std::map<std::string, Value> configurationProperties =
594 getEntityManagerProperties(sensorConfigPath.c_str(),
595 configurationInterface->c_str());
596
597 entityIdProp = configurationProperties.find("EntityId");
598 entityInstanceProp = configurationProperties.find("EntityInstance");
599 if (entityIdProp != configurationProperties.end())
600 {
601 entityId =
602 static_cast<uint8_t>(std::get<uint64_t>(entityIdProp->second));
603 }
604 if (entityInstanceProp != configurationProperties.end())
605 {
606 entityInstance = static_cast<uint8_t>(
607 std::get<uint64_t>(entityInstanceProp->second));
608 }
609
610 // stop searching Association records.
611 break;
612 } // end for Association vectors.
613
614 if constexpr (debug)
615 {
616 std::fprintf(stderr, "path=%s, entityId=%d, entityInstance=%d\n",
617 path.c_str(), entityId, entityInstance);
618 }
619}
620
621} // namespace ipmi