blob: 0365b8bfd3a175f4faeb7f5434f85847fad2e218 [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -06001/**
2 * Copyright © 2019 IBM 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 */
Matt Spinlercad9c2b2019-12-02 15:42:01 -060016#include "config.h"
17
Matt Spinlerc8705e22019-09-11 12:36:07 -050018#include "data_interface.hpp"
19
Matt Spinlerf61f2922020-06-23 11:32:49 -050020#include "util.hpp"
21
Vijay Lobo81b4dca2021-04-29 00:04:00 -050022#include <fmt/format.h>
23
Matt Spinlercad9c2b2019-12-02 15:42:01 -060024#include <fstream>
Vijay Lobo81b4dca2021-04-29 00:04:00 -050025#include <phosphor-logging/log.hpp>
Matt Spinlerf10068d2020-12-02 10:44:08 -060026#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
Matt Spinlera7d9d962019-11-06 15:01:25 -060027
Matt Spinlerc8705e22019-09-11 12:36:07 -050028namespace openpower
29{
30namespace pels
31{
32
33namespace service_name
34{
35constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -050036constexpr auto vpdManager = "com.ibm.VPD.Manager";
Matt Spinler34a904c2020-08-05 14:53:28 -050037constexpr auto ledGroupManager = "xyz.openbmc_project.LED.GroupManager";
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050038constexpr auto logSetting = "xyz.openbmc_project.Settings";
Matt Spinlerc8705e22019-09-11 12:36:07 -050039} // namespace service_name
40
41namespace object_path
42{
43constexpr auto objectMapper = "/xyz/openbmc_project/object_mapper";
44constexpr auto systemInv = "/xyz/openbmc_project/inventory/system";
Matt Spinler6ea4d5f2020-05-20 13:31:07 -050045constexpr auto chassisInv = "/xyz/openbmc_project/inventory/system/chassis";
Vijay Lobo81b4dca2021-04-29 00:04:00 -050046constexpr auto motherBoardInv =
47 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
Matt Spinlerb3d488f2020-02-21 15:30:46 -060048constexpr auto baseInv = "/xyz/openbmc_project/inventory";
Matt Spinler4aa23a12020-02-03 15:05:09 -060049constexpr auto bmcState = "/xyz/openbmc_project/state/bmc0";
50constexpr auto chassisState = "/xyz/openbmc_project/state/chassis0";
Matt Spinlera7d9d962019-11-06 15:01:25 -060051constexpr auto hostState = "/xyz/openbmc_project/state/host0";
Matt Spinlerb3f51862019-12-09 13:55:10 -060052constexpr auto pldm = "/xyz/openbmc_project/pldm";
Matt Spinler9cf3cfd2020-02-03 14:41:55 -060053constexpr auto enableHostPELs =
54 "/xyz/openbmc_project/logging/send_event_logs_to_host";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -050055constexpr auto vpdManager = "/com/ibm/VPD/Manager";
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050056constexpr auto logSetting = "/xyz/openbmc_project/logging/settings";
Matt Spinlerc8705e22019-09-11 12:36:07 -050057} // namespace object_path
58
59namespace interface
60{
61constexpr auto dbusProperty = "org.freedesktop.DBus.Properties";
62constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
63constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset";
Matt Spinlerf10068d2020-12-02 10:44:08 -060064constexpr auto bootProgress = "xyz.openbmc_project.State.Boot.Progress";
Matt Spinlerb3f51862019-12-09 13:55:10 -060065constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
Matt Spinler9cf3cfd2020-02-03 14:41:55 -060066constexpr auto enable = "xyz.openbmc_project.Object.Enable";
Matt Spinler4aa23a12020-02-03 15:05:09 -060067constexpr auto bmcState = "xyz.openbmc_project.State.BMC";
68constexpr auto chassisState = "xyz.openbmc_project.State.Chassis";
69constexpr auto hostState = "xyz.openbmc_project.State.Host";
Matt Spinlerb3d488f2020-02-21 15:30:46 -060070constexpr auto invMotherboard =
71 "xyz.openbmc_project.Inventory.Item.Board.Motherboard";
72constexpr auto viniRecordVPD = "com.ibm.ipzvpd.VINI";
Ben Tynere32b7e72021-05-18 12:38:40 -050073constexpr auto vsbpRecordVPD = "com.ibm.ipzvpd.VSBP";
Matt Spinler60c4e792020-03-13 13:45:36 -050074constexpr auto locCode = "com.ibm.ipzvpd.Location";
Matt Spinler1ab66962020-10-29 13:21:44 -050075constexpr auto compatible =
76 "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -050077constexpr auto vpdManager = "com.ibm.VPD.Manager";
Matt Spinler34a904c2020-08-05 14:53:28 -050078constexpr auto ledGroup = "xyz.openbmc_project.Led.Group";
Matt Spinler993168d2021-04-07 16:05:03 -050079constexpr auto operationalStatus =
80 "xyz.openbmc_project.State.Decorator.OperationalStatus";
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050081constexpr auto logSetting = "xyz.openbmc_project.Logging.Settings";
Sumit Kumar76198a22021-07-15 05:59:57 -050082constexpr auto association = "xyz.openbmc_project.Association.Definitions";
Matt Spinlerc8705e22019-09-11 12:36:07 -050083} // namespace interface
84
Matt Spinlerf10068d2020-12-02 10:44:08 -060085using namespace sdbusplus::xyz::openbmc_project::State::Boot::server;
Matt Spinlerb3d488f2020-02-21 15:30:46 -060086using sdbusplus::exception::SdBusError;
Vijay Lobo81b4dca2021-04-29 00:04:00 -050087using namespace phosphor::logging;
Matt Spinlera7d9d962019-11-06 15:01:25 -060088
Matt Spinler0d92b522021-06-16 13:28:17 -060089std::pair<std::string, std::string>
90 DataInterfaceBase::extractConnectorFromLocCode(
91 const std::string& locationCode)
92{
93 auto base = locationCode;
94 std::string connector{};
95
96 auto pos = base.find("-T");
97 if (pos != std::string::npos)
98 {
99 connector = base.substr(pos);
100 base = base.substr(0, pos);
101 }
102
103 return {base, connector};
104}
105
Matt Spinlerc8705e22019-09-11 12:36:07 -0500106DataInterface::DataInterface(sdbusplus::bus::bus& bus) : _bus(bus)
107{
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600108 readBMCFWVersion();
109 readServerFWVersion();
Matt Spinler677381b2020-01-23 10:04:29 -0600110 readBMCFWVersionID();
Matt Spinler2a28c932020-02-03 14:23:40 -0600111
Matt Spinlerf10068d2020-12-02 10:44:08 -0600112 // Watch the BootProgress property
Matt Spinler2a28c932020-02-03 14:23:40 -0600113 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
Matt Spinlerf10068d2020-12-02 10:44:08 -0600114 bus, object_path::hostState, interface::bootProgress, "BootProgress",
115 *this, [this](const auto& value) {
116 auto status = Progress::convertProgressStagesFromString(
117 std::get<std::string>(value));
Matt Spinler2a28c932020-02-03 14:23:40 -0600118
Matt Spinlerf10068d2020-12-02 10:44:08 -0600119 if ((status == Progress::ProgressStages::SystemInitComplete) ||
120 (status == Progress::ProgressStages::OSStart) ||
121 (status == Progress::ProgressStages::OSRunning))
Matt Spinler2a28c932020-02-03 14:23:40 -0600122 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600123 setHostUp(true);
Matt Spinler2a28c932020-02-03 14:23:40 -0600124 }
125 else
126 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600127 setHostUp(false);
Matt Spinler2a28c932020-02-03 14:23:40 -0600128 }
129 }));
Matt Spinler9cf3cfd2020-02-03 14:41:55 -0600130
131 // Watch the host PEL enable property
132 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
133 bus, object_path::enableHostPELs, interface::enable, "Enabled", *this,
134 [this](const auto& value) {
135 this->_sendPELsToHost = std::get<bool>(value);
136 }));
Matt Spinler4aa23a12020-02-03 15:05:09 -0600137
138 // Watch the BMCState property
139 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
140 bus, object_path::bmcState, interface::bmcState, "CurrentBMCState",
141 *this, [this](const auto& value) {
142 this->_bmcState = std::get<std::string>(value);
143 }));
144
145 // Watch the chassis current and requested power state properties
146 _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
147 bus, object_path::chassisState, interface::chassisState, *this,
148 [this](const auto& properties) {
149 auto state = properties.find("CurrentPowerState");
150 if (state != properties.end())
151 {
152 this->_chassisState = std::get<std::string>(state->second);
153 }
154
155 auto trans = properties.find("RequestedPowerTransition");
156 if (trans != properties.end())
157 {
158 this->_chassisTransition = std::get<std::string>(trans->second);
159 }
160 }));
161
162 // Watch the CurrentHostState property
163 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
164 bus, object_path::hostState, interface::hostState, "CurrentHostState",
165 *this, [this](const auto& value) {
166 this->_hostState = std::get<std::string>(value);
167 }));
Matt Spinlerc8705e22019-09-11 12:36:07 -0500168}
169
Matt Spinler2a28c932020-02-03 14:23:40 -0600170DBusPropertyMap
171 DataInterface::getAllProperties(const std::string& service,
172 const std::string& objectPath,
173 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500174{
175 DBusPropertyMap properties;
176
177 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
178 interface::dbusProperty, "GetAll");
179 method.append(interface);
180 auto reply = _bus.call(method);
181
182 reply.read(properties);
183
184 return properties;
185}
186
Matt Spinlera7d9d962019-11-06 15:01:25 -0600187void DataInterface::getProperty(const std::string& service,
188 const std::string& objectPath,
189 const std::string& interface,
Matt Spinler2a28c932020-02-03 14:23:40 -0600190 const std::string& property,
191 DBusValue& value) const
Matt Spinlera7d9d962019-11-06 15:01:25 -0600192{
193
194 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
195 interface::dbusProperty, "Get");
196 method.append(interface, property);
197 auto reply = _bus.call(method);
198
199 reply.read(value);
200}
201
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600202DBusPathList DataInterface::getPaths(const DBusInterfaceList& interfaces) const
203{
204
205 auto method = _bus.new_method_call(
206 service_name::objectMapper, object_path::objectMapper,
207 interface::objectMapper, "GetSubTreePaths");
208
209 method.append(std::string{"/"}, 0, interfaces);
210
211 auto reply = _bus.call(method);
212
213 DBusPathList paths;
214 reply.read(paths);
215
216 return paths;
217}
218
Matt Spinlerc8705e22019-09-11 12:36:07 -0500219DBusService DataInterface::getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600220 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500221{
222 auto method = _bus.new_method_call(service_name::objectMapper,
223 object_path::objectMapper,
224 interface::objectMapper, "GetObject");
225
226 method.append(objectPath, std::vector<std::string>({interface}));
227
228 auto reply = _bus.call(method);
229
230 std::map<DBusService, DBusInterfaceList> response;
231 reply.read(response);
232
233 if (!response.empty())
234 {
235 return response.begin()->first;
236 }
237
238 return std::string{};
239}
Matt Spinlera7d9d962019-11-06 15:01:25 -0600240
Matt Spinler677381b2020-01-23 10:04:29 -0600241void DataInterface::readBMCFWVersion()
242{
Matt Spinlerf61f2922020-06-23 11:32:49 -0500243 _bmcFWVersion =
244 phosphor::logging::util::getOSReleaseValue("VERSION").value_or("");
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600245}
246
247void DataInterface::readServerFWVersion()
248{
Sumit Kumarcad16202021-05-13 04:06:15 -0500249 auto value =
250 phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
251 if ((value != "") && (value.find_last_of(')') != std::string::npos))
252 {
253 std::size_t pos = value.find_first_of('(') + 1;
254 _serverFWVersion = value.substr(pos, value.find_last_of(')') - pos);
255 }
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600256}
257
Matt Spinler677381b2020-01-23 10:04:29 -0600258void DataInterface::readBMCFWVersionID()
259{
Matt Spinlerf61f2922020-06-23 11:32:49 -0500260 _bmcFWVersionID =
261 phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
Matt Spinler677381b2020-01-23 10:04:29 -0600262}
263
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500264std::string DataInterface::getMachineTypeModel() const
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600265{
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500266 std::string model;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600267 try
268 {
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600269
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500270 auto service = getService(object_path::systemInv, interface::invAsset);
271 if (!service.empty())
272 {
273 DBusValue value;
274 getProperty(service, object_path::systemInv, interface::invAsset,
275 "Model", value);
276
277 model = std::get<std::string>(value);
278 }
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600279 }
280 catch (const std::exception& e)
281 {
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500282 log<level::WARNING>(fmt::format("Failed reading Model property from "
283 "Interface: {} exception: {}",
284 interface::invAsset, e.what())
285 .c_str());
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600286 }
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500287
288 return model;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600289}
290
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500291std::string DataInterface::getMachineSerialNumber() const
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600292{
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500293 std::string sn;
294 try
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600295 {
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500296
297 auto service = getService(object_path::systemInv, interface::invAsset);
298 if (!service.empty())
299 {
300 DBusValue value;
301 getProperty(service, object_path::systemInv, interface::invAsset,
302 "SerialNumber", value);
303
304 sn = std::get<std::string>(value);
305 }
306 }
307 catch (const std::exception& e)
308 {
309 log<level::WARNING>(
310 fmt::format("Failed reading SerialNumber property from "
311 "Interface: {} exception: {}",
312 interface::invAsset, e.what())
313 .c_str());
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600314 }
315
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500316 return sn;
317}
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600318
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500319std::string DataInterface::getMotherboardCCIN() const
320{
321 std::string ccin;
322
323 try
324 {
325 auto service =
326 getService(object_path::motherBoardInv, interface::viniRecordVPD);
327 if (!service.empty())
328 {
329 DBusValue value;
330 getProperty(service, object_path::motherBoardInv,
331 interface::viniRecordVPD, "CC", value);
332
333 auto cc = std::get<std::vector<uint8_t>>(value);
334 ccin = std::string{cc.begin(), cc.end()};
335 }
336 }
337 catch (const std::exception& e)
338 {
339 log<level::WARNING>(
340 fmt::format("Failed reading Motherboard CCIN property from "
341 "Interface: {} exception: {}",
342 interface::viniRecordVPD, e.what())
343 .c_str());
344 }
345
346 return ccin;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600347}
348
Ben Tynere32b7e72021-05-18 12:38:40 -0500349std::vector<uint8_t> DataInterface::getSystemIMKeyword() const
350{
351 std::vector<uint8_t> systemIM;
352
353 try
354 {
355 auto service =
356 getService(object_path::motherBoardInv, interface::vsbpRecordVPD);
357 if (!service.empty())
358 {
359 DBusValue value;
360 getProperty(service, object_path::motherBoardInv,
361 interface::vsbpRecordVPD, "IM", value);
362
363 systemIM = std::get<std::vector<uint8_t>>(value);
364 }
365 }
366 catch (const std::exception& e)
367 {
368 log<level::WARNING>(
369 fmt::format("Failed reading System IM property from "
370 "Interface: {} exception: {}",
371 interface::vsbpRecordVPD, e.what())
372 .c_str());
373 }
374
375 return systemIM;
376}
377
Matt Spinler60c4e792020-03-13 13:45:36 -0500378void DataInterface::getHWCalloutFields(const std::string& inventoryPath,
Matt Spinler60c4e792020-03-13 13:45:36 -0500379 std::string& fruPartNumber,
380 std::string& ccin,
381 std::string& serialNumber) const
382{
383 // For now, attempt to get all of the properties directly on the path
384 // passed in. In the future, may need to make use of an algorithm
385 // to figure out which inventory objects actually hold these
386 // interfaces in the case of non FRUs, or possibly another service
387 // will provide this info. Any missing interfaces will result
388 // in exceptions being thrown.
389
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500390 auto service = getService(inventoryPath, interface::viniRecordVPD);
Matt Spinler60c4e792020-03-13 13:45:36 -0500391
392 auto properties =
393 getAllProperties(service, inventoryPath, interface::viniRecordVPD);
394
395 auto value = std::get<std::vector<uint8_t>>(properties["FN"]);
396 fruPartNumber = std::string{value.begin(), value.end()};
397
398 value = std::get<std::vector<uint8_t>>(properties["CC"]);
399 ccin = std::string{value.begin(), value.end()};
400
401 value = std::get<std::vector<uint8_t>>(properties["SN"]);
402 serialNumber = std::string{value.begin(), value.end()};
403}
404
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500405std::string
406 DataInterface::getLocationCode(const std::string& inventoryPath) const
407{
408 auto service = getService(inventoryPath, interface::locCode);
409
410 DBusValue locCode;
411 getProperty(service, inventoryPath, interface::locCode, "LocationCode",
412 locCode);
413
414 return std::get<std::string>(locCode);
415}
416
Matt Spinler5fb24c12020-06-04 11:21:33 -0500417std::string
418 DataInterface::addLocationCodePrefix(const std::string& locationCode)
419{
420 static const std::string locationCodePrefix{"Ufcs-"};
421
Matt Spinler0e4d72e2020-08-05 12:36:53 -0500422 // Technically there are 2 location code prefixes, Ufcs and Umts, so
423 // if it already starts with a U then don't need to do anything.
424 if (locationCode.front() != 'U')
Matt Spinler5fb24c12020-06-04 11:21:33 -0500425 {
426 return locationCodePrefix + locationCode;
427 }
428
429 return locationCode;
430}
431
432std::string DataInterface::expandLocationCode(const std::string& locationCode,
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500433 uint16_t /*node*/) const
Matt Spinler5fb24c12020-06-04 11:21:33 -0500434{
Matt Spinler0d92b522021-06-16 13:28:17 -0600435 // Location codes for connectors are the location code of the FRU they are
436 // on, plus a '-Tx' segment. Remove this last segment before expanding it
437 // and then add it back in afterwards. This way, the connector doesn't have
438 // to be in the model just so that it can be expanded.
439 auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
440
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500441 auto method =
442 _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
443 interface::vpdManager, "GetExpandedLocationCode");
444
Matt Spinler0d92b522021-06-16 13:28:17 -0600445 method.append(addLocationCodePrefix(baseLoc), static_cast<uint16_t>(0));
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500446
447 auto reply = _bus.call(method);
448
449 std::string expandedLocationCode;
450 reply.read(expandedLocationCode);
451
Matt Spinler0d92b522021-06-16 13:28:17 -0600452 if (!connectorLoc.empty())
453 {
454 expandedLocationCode += connectorLoc;
455 }
456
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500457 return expandedLocationCode;
Matt Spinler5fb24c12020-06-04 11:21:33 -0500458}
459
Matt Spinler2f9225a2020-08-05 12:58:49 -0500460std::string
461 DataInterface::getInventoryFromLocCode(const std::string& locationCode,
462 uint16_t node, bool expanded) const
Matt Spinler5fb24c12020-06-04 11:21:33 -0500463{
Matt Spinler2f9225a2020-08-05 12:58:49 -0500464 std::string methodName = expanded ? "GetFRUsByExpandedLocationCode"
465 : "GetFRUsByUnexpandedLocationCode";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500466
Matt Spinler0d92b522021-06-16 13:28:17 -0600467 // Remove the connector segment, if present, so that this method call
468 // returns an inventory path that getHWCalloutFields() can be used with.
469 // (The serial number, etc, aren't stored on the connector in the
470 // inventory, and may not even be modeled.)
471 auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
472
Matt Spinler2f9225a2020-08-05 12:58:49 -0500473 auto method =
474 _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
475 interface::vpdManager, methodName.c_str());
476
477 if (expanded)
478 {
Matt Spinler0d92b522021-06-16 13:28:17 -0600479 method.append(baseLoc);
Matt Spinler2f9225a2020-08-05 12:58:49 -0500480 }
481 else
482 {
Matt Spinler0d92b522021-06-16 13:28:17 -0600483 method.append(addLocationCodePrefix(baseLoc), node);
Matt Spinler2f9225a2020-08-05 12:58:49 -0500484 }
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500485
486 auto reply = _bus.call(method);
487
488 std::vector<sdbusplus::message::object_path> entries;
489 reply.read(entries);
490
491 // Get the shortest entry from the paths received, as this
492 // would be the path furthest up the inventory hierarchy so
493 // would be the parent FRU. There is guaranteed to at least
494 // be one entry if the call didn't fail.
495 std::string shortest{entries[0]};
496
497 std::for_each(entries.begin(), entries.end(),
498 [&shortest](const auto& path) {
499 if (path.str.size() < shortest.size())
500 {
501 shortest = path;
502 }
503 });
504
505 return shortest;
Matt Spinler5fb24c12020-06-04 11:21:33 -0500506}
507
Matt Spinler34a904c2020-08-05 14:53:28 -0500508void DataInterface::assertLEDGroup(const std::string& ledGroup,
509 bool value) const
510{
511 DBusValue variant = value;
512 auto method =
513 _bus.new_method_call(service_name::ledGroupManager, ledGroup.c_str(),
514 interface::dbusProperty, "Set");
515 method.append(interface::ledGroup, "Asserted", variant);
516 _bus.call(method);
517}
518
Matt Spinler993168d2021-04-07 16:05:03 -0500519void DataInterface::setFunctional(const std::string& objectPath,
520 bool value) const
521{
522 DBusValue variant = value;
523 auto service = getService(objectPath, interface::operationalStatus);
524
525 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
526 interface::dbusProperty, "Set");
527
528 method.append(interface::operationalStatus, "Functional", variant);
529 _bus.call(method);
530}
531
Sumit Kumar76198a22021-07-15 05:59:57 -0500532using AssociationTuple = std::tuple<std::string, std::string, std::string>;
533using AssociationsProperty = std::vector<AssociationTuple>;
534
535void DataInterface::setCriticalAssociation(const std::string& objectPath) const
536{
537 DBusValue getAssociationValue;
538
539 auto service = getService(objectPath, interface::association);
540
541 getProperty(service, objectPath, interface::association, "Associations",
542 getAssociationValue);
543
544 auto association = std::get<AssociationsProperty>(getAssociationValue);
545
546 AssociationTuple critAssociation{
547 "health_rollup", "critical",
548 "/xyz/openbmc_project/inventory/system/chassis"};
549
550 if (std::find(association.begin(), association.end(), critAssociation) ==
551 association.end())
552 {
553 association.push_back(critAssociation);
554 DBusValue setAssociationValue = association;
555
556 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
557 interface::dbusProperty, "Set");
558
559 method.append(interface::association, "Associations",
560 setAssociationValue);
561 _bus.call(method);
562 }
563}
564
Matt Spinler1ab66962020-10-29 13:21:44 -0500565std::vector<std::string> DataInterface::getSystemNames() const
566{
567 DBusSubTree subtree;
568 DBusValue names;
569
570 auto method = _bus.new_method_call(service_name::objectMapper,
571 object_path::objectMapper,
572 interface::objectMapper, "GetSubTree");
573 method.append(std::string{"/"}, 0,
574 std::vector<std::string>{interface::compatible});
575 auto reply = _bus.call(method);
576
577 reply.read(subtree);
578 if (subtree.empty())
579 {
580 throw std::runtime_error("Compatible interface not on D-Bus");
581 }
582
583 const auto& object = *(subtree.begin());
584 const auto& path = object.first;
585 const auto& service = object.second.begin()->first;
586
587 getProperty(service, path, interface::compatible, "Names", names);
588
589 return std::get<std::vector<std::string>>(names);
590}
591
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -0500592bool DataInterface::getQuiesceOnError() const
593{
594 bool ret = false;
595
596 try
597 {
598 auto service =
599 getService(object_path::logSetting, interface::logSetting);
600 if (!service.empty())
601 {
602 DBusValue value;
603 getProperty(service, object_path::logSetting, interface::logSetting,
604 "QuiesceOnHwError", value);
605
606 ret = std::get<bool>(value);
607 }
608 }
609 catch (const std::exception& e)
610 {
611 log<level::WARNING>(
612 fmt::format("Failed reading QuiesceOnHwError property from "
613 "Interface: {} exception: {}",
614 interface::logSetting, e.what())
615 .c_str());
616 }
617
618 return ret;
619}
620
Matt Spinlerc8705e22019-09-11 12:36:07 -0500621} // namespace pels
622} // namespace openpower