blob: 393c2fedf1263b5303b08736089d39bb3e3952d6 [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>
Sumit Kumar9d43a722021-08-24 09:46:19 -050025#include <iterator>
Vijay Lobo81b4dca2021-04-29 00:04:00 -050026#include <phosphor-logging/log.hpp>
Matt Spinlerf10068d2020-12-02 10:44:08 -060027#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
Matt Spinlera7d9d962019-11-06 15:01:25 -060028
Matt Spinlerc8705e22019-09-11 12:36:07 -050029namespace openpower
30{
31namespace pels
32{
33
34namespace service_name
35{
36constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -050037constexpr auto vpdManager = "com.ibm.VPD.Manager";
Matt Spinler34a904c2020-08-05 14:53:28 -050038constexpr auto ledGroupManager = "xyz.openbmc_project.LED.GroupManager";
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050039constexpr auto logSetting = "xyz.openbmc_project.Settings";
Matt Spinlerc8705e22019-09-11 12:36:07 -050040} // namespace service_name
41
42namespace object_path
43{
44constexpr auto objectMapper = "/xyz/openbmc_project/object_mapper";
45constexpr auto systemInv = "/xyz/openbmc_project/inventory/system";
Matt Spinler6ea4d5f2020-05-20 13:31:07 -050046constexpr auto chassisInv = "/xyz/openbmc_project/inventory/system/chassis";
Vijay Lobo81b4dca2021-04-29 00:04:00 -050047constexpr auto motherBoardInv =
48 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
Matt Spinlerb3d488f2020-02-21 15:30:46 -060049constexpr auto baseInv = "/xyz/openbmc_project/inventory";
Matt Spinler4aa23a12020-02-03 15:05:09 -060050constexpr auto bmcState = "/xyz/openbmc_project/state/bmc0";
51constexpr auto chassisState = "/xyz/openbmc_project/state/chassis0";
Matt Spinlera7d9d962019-11-06 15:01:25 -060052constexpr auto hostState = "/xyz/openbmc_project/state/host0";
Matt Spinlerb3f51862019-12-09 13:55:10 -060053constexpr auto pldm = "/xyz/openbmc_project/pldm";
Matt Spinler9cf3cfd2020-02-03 14:41:55 -060054constexpr auto enableHostPELs =
55 "/xyz/openbmc_project/logging/send_event_logs_to_host";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -050056constexpr auto vpdManager = "/com/ibm/VPD/Manager";
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050057constexpr auto logSetting = "/xyz/openbmc_project/logging/settings";
Matt Spinlerc8705e22019-09-11 12:36:07 -050058} // namespace object_path
59
60namespace interface
61{
62constexpr auto dbusProperty = "org.freedesktop.DBus.Properties";
63constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
64constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset";
Matt Spinlerf10068d2020-12-02 10:44:08 -060065constexpr auto bootProgress = "xyz.openbmc_project.State.Boot.Progress";
Matt Spinlerb3f51862019-12-09 13:55:10 -060066constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
Matt Spinler9cf3cfd2020-02-03 14:41:55 -060067constexpr auto enable = "xyz.openbmc_project.Object.Enable";
Matt Spinler4aa23a12020-02-03 15:05:09 -060068constexpr auto bmcState = "xyz.openbmc_project.State.BMC";
69constexpr auto chassisState = "xyz.openbmc_project.State.Chassis";
70constexpr auto hostState = "xyz.openbmc_project.State.Host";
Matt Spinlerb3d488f2020-02-21 15:30:46 -060071constexpr auto invMotherboard =
72 "xyz.openbmc_project.Inventory.Item.Board.Motherboard";
73constexpr auto viniRecordVPD = "com.ibm.ipzvpd.VINI";
Ben Tynere32b7e72021-05-18 12:38:40 -050074constexpr auto vsbpRecordVPD = "com.ibm.ipzvpd.VSBP";
Matt Spinler60c4e792020-03-13 13:45:36 -050075constexpr auto locCode = "com.ibm.ipzvpd.Location";
Matt Spinler1ab66962020-10-29 13:21:44 -050076constexpr auto compatible =
77 "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -050078constexpr auto vpdManager = "com.ibm.VPD.Manager";
Matt Spinler34a904c2020-08-05 14:53:28 -050079constexpr auto ledGroup = "xyz.openbmc_project.Led.Group";
Matt Spinler993168d2021-04-07 16:05:03 -050080constexpr auto operationalStatus =
81 "xyz.openbmc_project.State.Decorator.OperationalStatus";
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050082constexpr auto logSetting = "xyz.openbmc_project.Logging.Settings";
Sumit Kumar76198a22021-07-15 05:59:57 -050083constexpr auto association = "xyz.openbmc_project.Association.Definitions";
Sumit Kumar9d43a722021-08-24 09:46:19 -050084constexpr auto dumpEntry = "xyz.openbmc_project.Dump.Entry";
85constexpr auto dumpProgress = "xyz.openbmc_project.Common.Progress";
Matt Spinlerc8705e22019-09-11 12:36:07 -050086} // namespace interface
87
Matt Spinlerf10068d2020-12-02 10:44:08 -060088using namespace sdbusplus::xyz::openbmc_project::State::Boot::server;
Vijay Lobo81b4dca2021-04-29 00:04:00 -050089using namespace phosphor::logging;
Matt Spinlera7d9d962019-11-06 15:01:25 -060090
Matt Spinler0d92b522021-06-16 13:28:17 -060091std::pair<std::string, std::string>
92 DataInterfaceBase::extractConnectorFromLocCode(
93 const std::string& locationCode)
94{
95 auto base = locationCode;
96 std::string connector{};
97
98 auto pos = base.find("-T");
99 if (pos != std::string::npos)
100 {
101 connector = base.substr(pos);
102 base = base.substr(0, pos);
103 }
104
105 return {base, connector};
106}
107
Matt Spinlerc8705e22019-09-11 12:36:07 -0500108DataInterface::DataInterface(sdbusplus::bus::bus& bus) : _bus(bus)
109{
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600110 readBMCFWVersion();
111 readServerFWVersion();
Matt Spinler677381b2020-01-23 10:04:29 -0600112 readBMCFWVersionID();
Matt Spinler2a28c932020-02-03 14:23:40 -0600113
Matt Spinlerf10068d2020-12-02 10:44:08 -0600114 // Watch the BootProgress property
Matt Spinler2a28c932020-02-03 14:23:40 -0600115 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
Matt Spinlerf10068d2020-12-02 10:44:08 -0600116 bus, object_path::hostState, interface::bootProgress, "BootProgress",
117 *this, [this](const auto& value) {
118 auto status = Progress::convertProgressStagesFromString(
119 std::get<std::string>(value));
Matt Spinler2a28c932020-02-03 14:23:40 -0600120
Matt Spinlerf10068d2020-12-02 10:44:08 -0600121 if ((status == Progress::ProgressStages::SystemInitComplete) ||
122 (status == Progress::ProgressStages::OSStart) ||
123 (status == Progress::ProgressStages::OSRunning))
Matt Spinler2a28c932020-02-03 14:23:40 -0600124 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600125 setHostUp(true);
Matt Spinler2a28c932020-02-03 14:23:40 -0600126 }
127 else
128 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600129 setHostUp(false);
Matt Spinler2a28c932020-02-03 14:23:40 -0600130 }
131 }));
Matt Spinler9cf3cfd2020-02-03 14:41:55 -0600132
133 // Watch the host PEL enable property
134 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
135 bus, object_path::enableHostPELs, interface::enable, "Enabled", *this,
136 [this](const auto& value) {
137 this->_sendPELsToHost = std::get<bool>(value);
138 }));
Matt Spinler4aa23a12020-02-03 15:05:09 -0600139
140 // Watch the BMCState property
141 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
142 bus, object_path::bmcState, interface::bmcState, "CurrentBMCState",
143 *this, [this](const auto& value) {
144 this->_bmcState = std::get<std::string>(value);
145 }));
146
147 // Watch the chassis current and requested power state properties
148 _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
149 bus, object_path::chassisState, interface::chassisState, *this,
150 [this](const auto& properties) {
151 auto state = properties.find("CurrentPowerState");
152 if (state != properties.end())
153 {
154 this->_chassisState = std::get<std::string>(state->second);
155 }
156
157 auto trans = properties.find("RequestedPowerTransition");
158 if (trans != properties.end())
159 {
160 this->_chassisTransition = std::get<std::string>(trans->second);
161 }
162 }));
163
164 // Watch the CurrentHostState property
165 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
166 bus, object_path::hostState, interface::hostState, "CurrentHostState",
167 *this, [this](const auto& value) {
168 this->_hostState = std::get<std::string>(value);
169 }));
Matt Spinlerc8705e22019-09-11 12:36:07 -0500170}
171
Matt Spinler2a28c932020-02-03 14:23:40 -0600172DBusPropertyMap
173 DataInterface::getAllProperties(const std::string& service,
174 const std::string& objectPath,
175 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500176{
177 DBusPropertyMap properties;
178
179 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
180 interface::dbusProperty, "GetAll");
181 method.append(interface);
182 auto reply = _bus.call(method);
183
184 reply.read(properties);
185
186 return properties;
187}
188
Matt Spinlera7d9d962019-11-06 15:01:25 -0600189void DataInterface::getProperty(const std::string& service,
190 const std::string& objectPath,
191 const std::string& interface,
Matt Spinler2a28c932020-02-03 14:23:40 -0600192 const std::string& property,
193 DBusValue& value) const
Matt Spinlera7d9d962019-11-06 15:01:25 -0600194{
195
196 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
197 interface::dbusProperty, "Get");
198 method.append(interface, property);
199 auto reply = _bus.call(method);
200
201 reply.read(value);
202}
203
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600204DBusPathList DataInterface::getPaths(const DBusInterfaceList& interfaces) const
205{
206
207 auto method = _bus.new_method_call(
208 service_name::objectMapper, object_path::objectMapper,
209 interface::objectMapper, "GetSubTreePaths");
210
211 method.append(std::string{"/"}, 0, interfaces);
212
213 auto reply = _bus.call(method);
214
215 DBusPathList paths;
216 reply.read(paths);
217
218 return paths;
219}
220
Matt Spinlerc8705e22019-09-11 12:36:07 -0500221DBusService DataInterface::getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600222 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500223{
224 auto method = _bus.new_method_call(service_name::objectMapper,
225 object_path::objectMapper,
226 interface::objectMapper, "GetObject");
227
228 method.append(objectPath, std::vector<std::string>({interface}));
229
230 auto reply = _bus.call(method);
231
232 std::map<DBusService, DBusInterfaceList> response;
233 reply.read(response);
234
235 if (!response.empty())
236 {
237 return response.begin()->first;
238 }
239
240 return std::string{};
241}
Matt Spinlera7d9d962019-11-06 15:01:25 -0600242
Matt Spinler677381b2020-01-23 10:04:29 -0600243void DataInterface::readBMCFWVersion()
244{
Matt Spinlerf61f2922020-06-23 11:32:49 -0500245 _bmcFWVersion =
246 phosphor::logging::util::getOSReleaseValue("VERSION").value_or("");
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600247}
248
249void DataInterface::readServerFWVersion()
250{
Sumit Kumarcad16202021-05-13 04:06:15 -0500251 auto value =
252 phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
253 if ((value != "") && (value.find_last_of(')') != std::string::npos))
254 {
255 std::size_t pos = value.find_first_of('(') + 1;
256 _serverFWVersion = value.substr(pos, value.find_last_of(')') - pos);
257 }
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600258}
259
Matt Spinler677381b2020-01-23 10:04:29 -0600260void DataInterface::readBMCFWVersionID()
261{
Matt Spinlerf61f2922020-06-23 11:32:49 -0500262 _bmcFWVersionID =
263 phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
Matt Spinler677381b2020-01-23 10:04:29 -0600264}
265
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500266std::string DataInterface::getMachineTypeModel() const
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600267{
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500268 std::string model;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600269 try
270 {
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600271
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500272 auto service = getService(object_path::systemInv, interface::invAsset);
273 if (!service.empty())
274 {
275 DBusValue value;
276 getProperty(service, object_path::systemInv, interface::invAsset,
277 "Model", value);
278
279 model = std::get<std::string>(value);
280 }
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600281 }
282 catch (const std::exception& e)
283 {
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500284 log<level::WARNING>(fmt::format("Failed reading Model property from "
285 "Interface: {} exception: {}",
286 interface::invAsset, e.what())
287 .c_str());
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600288 }
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500289
290 return model;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600291}
292
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500293std::string DataInterface::getMachineSerialNumber() const
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600294{
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500295 std::string sn;
296 try
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600297 {
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500298
299 auto service = getService(object_path::systemInv, interface::invAsset);
300 if (!service.empty())
301 {
302 DBusValue value;
303 getProperty(service, object_path::systemInv, interface::invAsset,
304 "SerialNumber", value);
305
306 sn = std::get<std::string>(value);
307 }
308 }
309 catch (const std::exception& e)
310 {
311 log<level::WARNING>(
312 fmt::format("Failed reading SerialNumber property from "
313 "Interface: {} exception: {}",
314 interface::invAsset, e.what())
315 .c_str());
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600316 }
317
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500318 return sn;
319}
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600320
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500321std::string DataInterface::getMotherboardCCIN() const
322{
323 std::string ccin;
324
325 try
326 {
327 auto service =
328 getService(object_path::motherBoardInv, interface::viniRecordVPD);
329 if (!service.empty())
330 {
331 DBusValue value;
332 getProperty(service, object_path::motherBoardInv,
333 interface::viniRecordVPD, "CC", value);
334
335 auto cc = std::get<std::vector<uint8_t>>(value);
336 ccin = std::string{cc.begin(), cc.end()};
337 }
338 }
339 catch (const std::exception& e)
340 {
341 log<level::WARNING>(
342 fmt::format("Failed reading Motherboard CCIN property from "
343 "Interface: {} exception: {}",
344 interface::viniRecordVPD, e.what())
345 .c_str());
346 }
347
348 return ccin;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600349}
350
Ben Tynere32b7e72021-05-18 12:38:40 -0500351std::vector<uint8_t> DataInterface::getSystemIMKeyword() const
352{
353 std::vector<uint8_t> systemIM;
354
355 try
356 {
357 auto service =
358 getService(object_path::motherBoardInv, interface::vsbpRecordVPD);
359 if (!service.empty())
360 {
361 DBusValue value;
362 getProperty(service, object_path::motherBoardInv,
363 interface::vsbpRecordVPD, "IM", value);
364
365 systemIM = std::get<std::vector<uint8_t>>(value);
366 }
367 }
368 catch (const std::exception& e)
369 {
370 log<level::WARNING>(
371 fmt::format("Failed reading System IM property from "
372 "Interface: {} exception: {}",
373 interface::vsbpRecordVPD, e.what())
374 .c_str());
375 }
376
377 return systemIM;
378}
379
Matt Spinler60c4e792020-03-13 13:45:36 -0500380void DataInterface::getHWCalloutFields(const std::string& inventoryPath,
Matt Spinler60c4e792020-03-13 13:45:36 -0500381 std::string& fruPartNumber,
382 std::string& ccin,
383 std::string& serialNumber) const
384{
385 // For now, attempt to get all of the properties directly on the path
386 // passed in. In the future, may need to make use of an algorithm
387 // to figure out which inventory objects actually hold these
388 // interfaces in the case of non FRUs, or possibly another service
389 // will provide this info. Any missing interfaces will result
390 // in exceptions being thrown.
391
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500392 auto service = getService(inventoryPath, interface::viniRecordVPD);
Matt Spinler60c4e792020-03-13 13:45:36 -0500393
394 auto properties =
395 getAllProperties(service, inventoryPath, interface::viniRecordVPD);
396
397 auto value = std::get<std::vector<uint8_t>>(properties["FN"]);
398 fruPartNumber = std::string{value.begin(), value.end()};
399
400 value = std::get<std::vector<uint8_t>>(properties["CC"]);
401 ccin = std::string{value.begin(), value.end()};
402
403 value = std::get<std::vector<uint8_t>>(properties["SN"]);
404 serialNumber = std::string{value.begin(), value.end()};
405}
406
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500407std::string
408 DataInterface::getLocationCode(const std::string& inventoryPath) const
409{
410 auto service = getService(inventoryPath, interface::locCode);
411
412 DBusValue locCode;
413 getProperty(service, inventoryPath, interface::locCode, "LocationCode",
414 locCode);
415
416 return std::get<std::string>(locCode);
417}
418
Matt Spinler5fb24c12020-06-04 11:21:33 -0500419std::string
420 DataInterface::addLocationCodePrefix(const std::string& locationCode)
421{
422 static const std::string locationCodePrefix{"Ufcs-"};
423
Matt Spinler0e4d72e2020-08-05 12:36:53 -0500424 // Technically there are 2 location code prefixes, Ufcs and Umts, so
425 // if it already starts with a U then don't need to do anything.
426 if (locationCode.front() != 'U')
Matt Spinler5fb24c12020-06-04 11:21:33 -0500427 {
428 return locationCodePrefix + locationCode;
429 }
430
431 return locationCode;
432}
433
434std::string DataInterface::expandLocationCode(const std::string& locationCode,
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500435 uint16_t /*node*/) const
Matt Spinler5fb24c12020-06-04 11:21:33 -0500436{
Matt Spinler0d92b522021-06-16 13:28:17 -0600437 // Location codes for connectors are the location code of the FRU they are
438 // on, plus a '-Tx' segment. Remove this last segment before expanding it
439 // and then add it back in afterwards. This way, the connector doesn't have
440 // to be in the model just so that it can be expanded.
441 auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
442
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500443 auto method =
444 _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
445 interface::vpdManager, "GetExpandedLocationCode");
446
Matt Spinler0d92b522021-06-16 13:28:17 -0600447 method.append(addLocationCodePrefix(baseLoc), static_cast<uint16_t>(0));
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500448
449 auto reply = _bus.call(method);
450
451 std::string expandedLocationCode;
452 reply.read(expandedLocationCode);
453
Matt Spinler0d92b522021-06-16 13:28:17 -0600454 if (!connectorLoc.empty())
455 {
456 expandedLocationCode += connectorLoc;
457 }
458
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500459 return expandedLocationCode;
Matt Spinler5fb24c12020-06-04 11:21:33 -0500460}
461
Matt Spinler2f9225a2020-08-05 12:58:49 -0500462std::string
463 DataInterface::getInventoryFromLocCode(const std::string& locationCode,
464 uint16_t node, bool expanded) const
Matt Spinler5fb24c12020-06-04 11:21:33 -0500465{
Matt Spinler2f9225a2020-08-05 12:58:49 -0500466 std::string methodName = expanded ? "GetFRUsByExpandedLocationCode"
467 : "GetFRUsByUnexpandedLocationCode";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500468
Matt Spinler0d92b522021-06-16 13:28:17 -0600469 // Remove the connector segment, if present, so that this method call
470 // returns an inventory path that getHWCalloutFields() can be used with.
471 // (The serial number, etc, aren't stored on the connector in the
472 // inventory, and may not even be modeled.)
473 auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
474
Matt Spinler2f9225a2020-08-05 12:58:49 -0500475 auto method =
476 _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
477 interface::vpdManager, methodName.c_str());
478
479 if (expanded)
480 {
Matt Spinler0d92b522021-06-16 13:28:17 -0600481 method.append(baseLoc);
Matt Spinler2f9225a2020-08-05 12:58:49 -0500482 }
483 else
484 {
Matt Spinler0d92b522021-06-16 13:28:17 -0600485 method.append(addLocationCodePrefix(baseLoc), node);
Matt Spinler2f9225a2020-08-05 12:58:49 -0500486 }
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500487
488 auto reply = _bus.call(method);
489
490 std::vector<sdbusplus::message::object_path> entries;
491 reply.read(entries);
492
493 // Get the shortest entry from the paths received, as this
494 // would be the path furthest up the inventory hierarchy so
495 // would be the parent FRU. There is guaranteed to at least
496 // be one entry if the call didn't fail.
497 std::string shortest{entries[0]};
498
499 std::for_each(entries.begin(), entries.end(),
500 [&shortest](const auto& path) {
501 if (path.str.size() < shortest.size())
502 {
503 shortest = path;
504 }
505 });
506
507 return shortest;
Matt Spinler5fb24c12020-06-04 11:21:33 -0500508}
509
Matt Spinler34a904c2020-08-05 14:53:28 -0500510void DataInterface::assertLEDGroup(const std::string& ledGroup,
511 bool value) const
512{
513 DBusValue variant = value;
514 auto method =
515 _bus.new_method_call(service_name::ledGroupManager, ledGroup.c_str(),
516 interface::dbusProperty, "Set");
517 method.append(interface::ledGroup, "Asserted", variant);
518 _bus.call(method);
519}
520
Matt Spinler993168d2021-04-07 16:05:03 -0500521void DataInterface::setFunctional(const std::string& objectPath,
522 bool value) const
523{
524 DBusValue variant = value;
525 auto service = getService(objectPath, interface::operationalStatus);
526
527 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
528 interface::dbusProperty, "Set");
529
530 method.append(interface::operationalStatus, "Functional", variant);
531 _bus.call(method);
532}
533
Sumit Kumar76198a22021-07-15 05:59:57 -0500534using AssociationTuple = std::tuple<std::string, std::string, std::string>;
535using AssociationsProperty = std::vector<AssociationTuple>;
536
537void DataInterface::setCriticalAssociation(const std::string& objectPath) const
538{
539 DBusValue getAssociationValue;
540
541 auto service = getService(objectPath, interface::association);
542
543 getProperty(service, objectPath, interface::association, "Associations",
544 getAssociationValue);
545
546 auto association = std::get<AssociationsProperty>(getAssociationValue);
547
548 AssociationTuple critAssociation{
549 "health_rollup", "critical",
550 "/xyz/openbmc_project/inventory/system/chassis"};
551
552 if (std::find(association.begin(), association.end(), critAssociation) ==
553 association.end())
554 {
555 association.push_back(critAssociation);
556 DBusValue setAssociationValue = association;
557
558 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
559 interface::dbusProperty, "Set");
560
561 method.append(interface::association, "Associations",
562 setAssociationValue);
563 _bus.call(method);
564 }
565}
566
Matt Spinler1ab66962020-10-29 13:21:44 -0500567std::vector<std::string> DataInterface::getSystemNames() const
568{
569 DBusSubTree subtree;
570 DBusValue names;
571
572 auto method = _bus.new_method_call(service_name::objectMapper,
573 object_path::objectMapper,
574 interface::objectMapper, "GetSubTree");
575 method.append(std::string{"/"}, 0,
576 std::vector<std::string>{interface::compatible});
577 auto reply = _bus.call(method);
578
579 reply.read(subtree);
580 if (subtree.empty())
581 {
582 throw std::runtime_error("Compatible interface not on D-Bus");
583 }
584
585 const auto& object = *(subtree.begin());
586 const auto& path = object.first;
587 const auto& service = object.second.begin()->first;
588
589 getProperty(service, path, interface::compatible, "Names", names);
590
591 return std::get<std::vector<std::string>>(names);
592}
593
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -0500594bool DataInterface::getQuiesceOnError() const
595{
596 bool ret = false;
597
598 try
599 {
600 auto service =
601 getService(object_path::logSetting, interface::logSetting);
602 if (!service.empty())
603 {
604 DBusValue value;
605 getProperty(service, object_path::logSetting, interface::logSetting,
606 "QuiesceOnHwError", value);
607
608 ret = std::get<bool>(value);
609 }
610 }
611 catch (const std::exception& e)
612 {
613 log<level::WARNING>(
614 fmt::format("Failed reading QuiesceOnHwError property from "
615 "Interface: {} exception: {}",
616 interface::logSetting, e.what())
617 .c_str());
618 }
619
620 return ret;
621}
622
Sumit Kumar9d43a722021-08-24 09:46:19 -0500623std::vector<bool>
624 DataInterface::checkDumpStatus(const std::vector<std::string>& type) const
625{
626 DBusSubTree subtree;
627 std::vector<bool> result(type.size(), false);
628
629 // Query GetSubTree for the availability of dump interface
630 auto method = _bus.new_method_call(service_name::objectMapper,
631 object_path::objectMapper,
632 interface::objectMapper, "GetSubTree");
633 method.append(std::string{"/"}, 0,
634 std::vector<std::string>{interface::dumpEntry});
635 auto reply = _bus.call(method);
636
637 reply.read(subtree);
638
639 if (subtree.empty())
640 {
641 return result;
642 }
643
644 std::vector<bool>::iterator itDumpStatus = result.begin();
645 uint8_t count = 0;
646 for (const auto& [path, serviceInfo] : subtree)
647 {
648 const auto& service = serviceInfo.begin()->first;
649 // Check for dump type on the object path
650 for (const auto& it : type)
651 {
652 if (path.find(it) != std::string::npos)
653 {
654 DBusValue value, progress;
655
656 // If dump type status is already available go for next path
657 if (*itDumpStatus)
658 {
659 break;
660 }
661
662 // Check for valid dump to be available if following
663 // conditions are met for the dump entry path -
664 // Offloaded == false and Status == Completed
665 getProperty(service, path, interface::dumpEntry, "Offloaded",
666 value);
667 getProperty(service, path, interface::dumpProgress, "Status",
668 progress);
669 auto offload = std::get<bool>(value);
670 auto status = std::get<std::string>(progress);
671 if (!offload && (status.find("Completed") != std::string::npos))
672 {
673 *itDumpStatus = true;
674 count++;
675 if (count >= type.size())
676 {
677 return result;
678 }
679 break;
680 }
681 }
682 itDumpStatus++;
683 }
684 itDumpStatus = result.begin();
685 }
686
687 return result;
688}
689
Matt Spinlerc8705e22019-09-11 12:36:07 -0500690} // namespace pels
691} // namespace openpower