blob: f8b701f65c9c446b3224d67ec668ed8448db6224 [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;
Vijay Lobo81b4dca2021-04-29 00:04:00 -050086using namespace phosphor::logging;
Matt Spinlera7d9d962019-11-06 15:01:25 -060087
Matt Spinler0d92b522021-06-16 13:28:17 -060088std::pair<std::string, std::string>
89 DataInterfaceBase::extractConnectorFromLocCode(
90 const std::string& locationCode)
91{
92 auto base = locationCode;
93 std::string connector{};
94
95 auto pos = base.find("-T");
96 if (pos != std::string::npos)
97 {
98 connector = base.substr(pos);
99 base = base.substr(0, pos);
100 }
101
102 return {base, connector};
103}
104
Matt Spinlerc8705e22019-09-11 12:36:07 -0500105DataInterface::DataInterface(sdbusplus::bus::bus& bus) : _bus(bus)
106{
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600107 readBMCFWVersion();
108 readServerFWVersion();
Matt Spinler677381b2020-01-23 10:04:29 -0600109 readBMCFWVersionID();
Matt Spinler2a28c932020-02-03 14:23:40 -0600110
Matt Spinlerf10068d2020-12-02 10:44:08 -0600111 // Watch the BootProgress property
Matt Spinler2a28c932020-02-03 14:23:40 -0600112 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
Matt Spinlerf10068d2020-12-02 10:44:08 -0600113 bus, object_path::hostState, interface::bootProgress, "BootProgress",
114 *this, [this](const auto& value) {
115 auto status = Progress::convertProgressStagesFromString(
116 std::get<std::string>(value));
Matt Spinler2a28c932020-02-03 14:23:40 -0600117
Matt Spinlerf10068d2020-12-02 10:44:08 -0600118 if ((status == Progress::ProgressStages::SystemInitComplete) ||
119 (status == Progress::ProgressStages::OSStart) ||
120 (status == Progress::ProgressStages::OSRunning))
Matt Spinler2a28c932020-02-03 14:23:40 -0600121 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600122 setHostUp(true);
Matt Spinler2a28c932020-02-03 14:23:40 -0600123 }
124 else
125 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600126 setHostUp(false);
Matt Spinler2a28c932020-02-03 14:23:40 -0600127 }
128 }));
Matt Spinler9cf3cfd2020-02-03 14:41:55 -0600129
130 // Watch the host PEL enable property
131 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
132 bus, object_path::enableHostPELs, interface::enable, "Enabled", *this,
133 [this](const auto& value) {
134 this->_sendPELsToHost = std::get<bool>(value);
135 }));
Matt Spinler4aa23a12020-02-03 15:05:09 -0600136
137 // Watch the BMCState property
138 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
139 bus, object_path::bmcState, interface::bmcState, "CurrentBMCState",
140 *this, [this](const auto& value) {
141 this->_bmcState = std::get<std::string>(value);
142 }));
143
144 // Watch the chassis current and requested power state properties
145 _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
146 bus, object_path::chassisState, interface::chassisState, *this,
147 [this](const auto& properties) {
148 auto state = properties.find("CurrentPowerState");
149 if (state != properties.end())
150 {
151 this->_chassisState = std::get<std::string>(state->second);
152 }
153
154 auto trans = properties.find("RequestedPowerTransition");
155 if (trans != properties.end())
156 {
157 this->_chassisTransition = std::get<std::string>(trans->second);
158 }
159 }));
160
161 // Watch the CurrentHostState property
162 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
163 bus, object_path::hostState, interface::hostState, "CurrentHostState",
164 *this, [this](const auto& value) {
165 this->_hostState = std::get<std::string>(value);
166 }));
Matt Spinlerc8705e22019-09-11 12:36:07 -0500167}
168
Matt Spinler2a28c932020-02-03 14:23:40 -0600169DBusPropertyMap
170 DataInterface::getAllProperties(const std::string& service,
171 const std::string& objectPath,
172 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500173{
174 DBusPropertyMap properties;
175
176 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
177 interface::dbusProperty, "GetAll");
178 method.append(interface);
179 auto reply = _bus.call(method);
180
181 reply.read(properties);
182
183 return properties;
184}
185
Matt Spinlera7d9d962019-11-06 15:01:25 -0600186void DataInterface::getProperty(const std::string& service,
187 const std::string& objectPath,
188 const std::string& interface,
Matt Spinler2a28c932020-02-03 14:23:40 -0600189 const std::string& property,
190 DBusValue& value) const
Matt Spinlera7d9d962019-11-06 15:01:25 -0600191{
192
193 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
194 interface::dbusProperty, "Get");
195 method.append(interface, property);
196 auto reply = _bus.call(method);
197
198 reply.read(value);
199}
200
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600201DBusPathList DataInterface::getPaths(const DBusInterfaceList& interfaces) const
202{
203
204 auto method = _bus.new_method_call(
205 service_name::objectMapper, object_path::objectMapper,
206 interface::objectMapper, "GetSubTreePaths");
207
208 method.append(std::string{"/"}, 0, interfaces);
209
210 auto reply = _bus.call(method);
211
212 DBusPathList paths;
213 reply.read(paths);
214
215 return paths;
216}
217
Matt Spinlerc8705e22019-09-11 12:36:07 -0500218DBusService DataInterface::getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600219 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500220{
221 auto method = _bus.new_method_call(service_name::objectMapper,
222 object_path::objectMapper,
223 interface::objectMapper, "GetObject");
224
225 method.append(objectPath, std::vector<std::string>({interface}));
226
227 auto reply = _bus.call(method);
228
229 std::map<DBusService, DBusInterfaceList> response;
230 reply.read(response);
231
232 if (!response.empty())
233 {
234 return response.begin()->first;
235 }
236
237 return std::string{};
238}
Matt Spinlera7d9d962019-11-06 15:01:25 -0600239
Matt Spinler677381b2020-01-23 10:04:29 -0600240void DataInterface::readBMCFWVersion()
241{
Matt Spinlerf61f2922020-06-23 11:32:49 -0500242 _bmcFWVersion =
243 phosphor::logging::util::getOSReleaseValue("VERSION").value_or("");
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600244}
245
246void DataInterface::readServerFWVersion()
247{
Sumit Kumarcad16202021-05-13 04:06:15 -0500248 auto value =
249 phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
250 if ((value != "") && (value.find_last_of(')') != std::string::npos))
251 {
252 std::size_t pos = value.find_first_of('(') + 1;
253 _serverFWVersion = value.substr(pos, value.find_last_of(')') - pos);
254 }
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600255}
256
Matt Spinler677381b2020-01-23 10:04:29 -0600257void DataInterface::readBMCFWVersionID()
258{
Matt Spinlerf61f2922020-06-23 11:32:49 -0500259 _bmcFWVersionID =
260 phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
Matt Spinler677381b2020-01-23 10:04:29 -0600261}
262
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500263std::string DataInterface::getMachineTypeModel() const
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600264{
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500265 std::string model;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600266 try
267 {
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600268
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500269 auto service = getService(object_path::systemInv, interface::invAsset);
270 if (!service.empty())
271 {
272 DBusValue value;
273 getProperty(service, object_path::systemInv, interface::invAsset,
274 "Model", value);
275
276 model = std::get<std::string>(value);
277 }
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600278 }
279 catch (const std::exception& e)
280 {
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500281 log<level::WARNING>(fmt::format("Failed reading Model property from "
282 "Interface: {} exception: {}",
283 interface::invAsset, e.what())
284 .c_str());
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600285 }
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500286
287 return model;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600288}
289
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500290std::string DataInterface::getMachineSerialNumber() const
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600291{
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500292 std::string sn;
293 try
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600294 {
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500295
296 auto service = getService(object_path::systemInv, interface::invAsset);
297 if (!service.empty())
298 {
299 DBusValue value;
300 getProperty(service, object_path::systemInv, interface::invAsset,
301 "SerialNumber", value);
302
303 sn = std::get<std::string>(value);
304 }
305 }
306 catch (const std::exception& e)
307 {
308 log<level::WARNING>(
309 fmt::format("Failed reading SerialNumber property from "
310 "Interface: {} exception: {}",
311 interface::invAsset, e.what())
312 .c_str());
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600313 }
314
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500315 return sn;
316}
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600317
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500318std::string DataInterface::getMotherboardCCIN() const
319{
320 std::string ccin;
321
322 try
323 {
324 auto service =
325 getService(object_path::motherBoardInv, interface::viniRecordVPD);
326 if (!service.empty())
327 {
328 DBusValue value;
329 getProperty(service, object_path::motherBoardInv,
330 interface::viniRecordVPD, "CC", value);
331
332 auto cc = std::get<std::vector<uint8_t>>(value);
333 ccin = std::string{cc.begin(), cc.end()};
334 }
335 }
336 catch (const std::exception& e)
337 {
338 log<level::WARNING>(
339 fmt::format("Failed reading Motherboard CCIN property from "
340 "Interface: {} exception: {}",
341 interface::viniRecordVPD, e.what())
342 .c_str());
343 }
344
345 return ccin;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600346}
347
Ben Tynere32b7e72021-05-18 12:38:40 -0500348std::vector<uint8_t> DataInterface::getSystemIMKeyword() const
349{
350 std::vector<uint8_t> systemIM;
351
352 try
353 {
354 auto service =
355 getService(object_path::motherBoardInv, interface::vsbpRecordVPD);
356 if (!service.empty())
357 {
358 DBusValue value;
359 getProperty(service, object_path::motherBoardInv,
360 interface::vsbpRecordVPD, "IM", value);
361
362 systemIM = std::get<std::vector<uint8_t>>(value);
363 }
364 }
365 catch (const std::exception& e)
366 {
367 log<level::WARNING>(
368 fmt::format("Failed reading System IM property from "
369 "Interface: {} exception: {}",
370 interface::vsbpRecordVPD, e.what())
371 .c_str());
372 }
373
374 return systemIM;
375}
376
Matt Spinler60c4e792020-03-13 13:45:36 -0500377void DataInterface::getHWCalloutFields(const std::string& inventoryPath,
Matt Spinler60c4e792020-03-13 13:45:36 -0500378 std::string& fruPartNumber,
379 std::string& ccin,
380 std::string& serialNumber) const
381{
382 // For now, attempt to get all of the properties directly on the path
383 // passed in. In the future, may need to make use of an algorithm
384 // to figure out which inventory objects actually hold these
385 // interfaces in the case of non FRUs, or possibly another service
386 // will provide this info. Any missing interfaces will result
387 // in exceptions being thrown.
388
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500389 auto service = getService(inventoryPath, interface::viniRecordVPD);
Matt Spinler60c4e792020-03-13 13:45:36 -0500390
391 auto properties =
392 getAllProperties(service, inventoryPath, interface::viniRecordVPD);
393
394 auto value = std::get<std::vector<uint8_t>>(properties["FN"]);
395 fruPartNumber = std::string{value.begin(), value.end()};
396
397 value = std::get<std::vector<uint8_t>>(properties["CC"]);
398 ccin = std::string{value.begin(), value.end()};
399
400 value = std::get<std::vector<uint8_t>>(properties["SN"]);
401 serialNumber = std::string{value.begin(), value.end()};
402}
403
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500404std::string
405 DataInterface::getLocationCode(const std::string& inventoryPath) const
406{
407 auto service = getService(inventoryPath, interface::locCode);
408
409 DBusValue locCode;
410 getProperty(service, inventoryPath, interface::locCode, "LocationCode",
411 locCode);
412
413 return std::get<std::string>(locCode);
414}
415
Matt Spinler5fb24c12020-06-04 11:21:33 -0500416std::string
417 DataInterface::addLocationCodePrefix(const std::string& locationCode)
418{
419 static const std::string locationCodePrefix{"Ufcs-"};
420
Matt Spinler0e4d72e2020-08-05 12:36:53 -0500421 // Technically there are 2 location code prefixes, Ufcs and Umts, so
422 // if it already starts with a U then don't need to do anything.
423 if (locationCode.front() != 'U')
Matt Spinler5fb24c12020-06-04 11:21:33 -0500424 {
425 return locationCodePrefix + locationCode;
426 }
427
428 return locationCode;
429}
430
431std::string DataInterface::expandLocationCode(const std::string& locationCode,
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500432 uint16_t /*node*/) const
Matt Spinler5fb24c12020-06-04 11:21:33 -0500433{
Matt Spinler0d92b522021-06-16 13:28:17 -0600434 // Location codes for connectors are the location code of the FRU they are
435 // on, plus a '-Tx' segment. Remove this last segment before expanding it
436 // and then add it back in afterwards. This way, the connector doesn't have
437 // to be in the model just so that it can be expanded.
438 auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
439
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500440 auto method =
441 _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
442 interface::vpdManager, "GetExpandedLocationCode");
443
Matt Spinler0d92b522021-06-16 13:28:17 -0600444 method.append(addLocationCodePrefix(baseLoc), static_cast<uint16_t>(0));
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500445
446 auto reply = _bus.call(method);
447
448 std::string expandedLocationCode;
449 reply.read(expandedLocationCode);
450
Matt Spinler0d92b522021-06-16 13:28:17 -0600451 if (!connectorLoc.empty())
452 {
453 expandedLocationCode += connectorLoc;
454 }
455
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500456 return expandedLocationCode;
Matt Spinler5fb24c12020-06-04 11:21:33 -0500457}
458
Matt Spinler2f9225a2020-08-05 12:58:49 -0500459std::string
460 DataInterface::getInventoryFromLocCode(const std::string& locationCode,
461 uint16_t node, bool expanded) const
Matt Spinler5fb24c12020-06-04 11:21:33 -0500462{
Matt Spinler2f9225a2020-08-05 12:58:49 -0500463 std::string methodName = expanded ? "GetFRUsByExpandedLocationCode"
464 : "GetFRUsByUnexpandedLocationCode";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500465
Matt Spinler0d92b522021-06-16 13:28:17 -0600466 // Remove the connector segment, if present, so that this method call
467 // returns an inventory path that getHWCalloutFields() can be used with.
468 // (The serial number, etc, aren't stored on the connector in the
469 // inventory, and may not even be modeled.)
470 auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
471
Matt Spinler2f9225a2020-08-05 12:58:49 -0500472 auto method =
473 _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
474 interface::vpdManager, methodName.c_str());
475
476 if (expanded)
477 {
Matt Spinler0d92b522021-06-16 13:28:17 -0600478 method.append(baseLoc);
Matt Spinler2f9225a2020-08-05 12:58:49 -0500479 }
480 else
481 {
Matt Spinler0d92b522021-06-16 13:28:17 -0600482 method.append(addLocationCodePrefix(baseLoc), node);
Matt Spinler2f9225a2020-08-05 12:58:49 -0500483 }
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500484
485 auto reply = _bus.call(method);
486
487 std::vector<sdbusplus::message::object_path> entries;
488 reply.read(entries);
489
490 // Get the shortest entry from the paths received, as this
491 // would be the path furthest up the inventory hierarchy so
492 // would be the parent FRU. There is guaranteed to at least
493 // be one entry if the call didn't fail.
494 std::string shortest{entries[0]};
495
496 std::for_each(entries.begin(), entries.end(),
497 [&shortest](const auto& path) {
498 if (path.str.size() < shortest.size())
499 {
500 shortest = path;
501 }
502 });
503
504 return shortest;
Matt Spinler5fb24c12020-06-04 11:21:33 -0500505}
506
Matt Spinler34a904c2020-08-05 14:53:28 -0500507void DataInterface::assertLEDGroup(const std::string& ledGroup,
508 bool value) const
509{
510 DBusValue variant = value;
511 auto method =
512 _bus.new_method_call(service_name::ledGroupManager, ledGroup.c_str(),
513 interface::dbusProperty, "Set");
514 method.append(interface::ledGroup, "Asserted", variant);
515 _bus.call(method);
516}
517
Matt Spinler993168d2021-04-07 16:05:03 -0500518void DataInterface::setFunctional(const std::string& objectPath,
519 bool value) const
520{
521 DBusValue variant = value;
522 auto service = getService(objectPath, interface::operationalStatus);
523
524 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
525 interface::dbusProperty, "Set");
526
527 method.append(interface::operationalStatus, "Functional", variant);
528 _bus.call(method);
529}
530
Sumit Kumar76198a22021-07-15 05:59:57 -0500531using AssociationTuple = std::tuple<std::string, std::string, std::string>;
532using AssociationsProperty = std::vector<AssociationTuple>;
533
534void DataInterface::setCriticalAssociation(const std::string& objectPath) const
535{
536 DBusValue getAssociationValue;
537
538 auto service = getService(objectPath, interface::association);
539
540 getProperty(service, objectPath, interface::association, "Associations",
541 getAssociationValue);
542
543 auto association = std::get<AssociationsProperty>(getAssociationValue);
544
545 AssociationTuple critAssociation{
546 "health_rollup", "critical",
547 "/xyz/openbmc_project/inventory/system/chassis"};
548
549 if (std::find(association.begin(), association.end(), critAssociation) ==
550 association.end())
551 {
552 association.push_back(critAssociation);
553 DBusValue setAssociationValue = association;
554
555 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
556 interface::dbusProperty, "Set");
557
558 method.append(interface::association, "Associations",
559 setAssociationValue);
560 _bus.call(method);
561 }
562}
563
Matt Spinler1ab66962020-10-29 13:21:44 -0500564std::vector<std::string> DataInterface::getSystemNames() const
565{
566 DBusSubTree subtree;
567 DBusValue names;
568
569 auto method = _bus.new_method_call(service_name::objectMapper,
570 object_path::objectMapper,
571 interface::objectMapper, "GetSubTree");
572 method.append(std::string{"/"}, 0,
573 std::vector<std::string>{interface::compatible});
574 auto reply = _bus.call(method);
575
576 reply.read(subtree);
577 if (subtree.empty())
578 {
579 throw std::runtime_error("Compatible interface not on D-Bus");
580 }
581
582 const auto& object = *(subtree.begin());
583 const auto& path = object.first;
584 const auto& service = object.second.begin()->first;
585
586 getProperty(service, path, interface::compatible, "Names", names);
587
588 return std::get<std::vector<std::string>>(names);
589}
590
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -0500591bool DataInterface::getQuiesceOnError() const
592{
593 bool ret = false;
594
595 try
596 {
597 auto service =
598 getService(object_path::logSetting, interface::logSetting);
599 if (!service.empty())
600 {
601 DBusValue value;
602 getProperty(service, object_path::logSetting, interface::logSetting,
603 "QuiesceOnHwError", value);
604
605 ret = std::get<bool>(value);
606 }
607 }
608 catch (const std::exception& e)
609 {
610 log<level::WARNING>(
611 fmt::format("Failed reading QuiesceOnHwError property from "
612 "Interface: {} exception: {}",
613 interface::logSetting, e.what())
614 .c_str());
615 }
616
617 return ret;
618}
619
Matt Spinlerc8705e22019-09-11 12:36:07 -0500620} // namespace pels
621} // namespace openpower