blob: c21bf5dcd0ca507176a28ce5d54bf30d45f5c6cd [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) {
Sumit Kumar2c36fdd2021-09-21 03:12:11 -0500118 this->_bootState = std::get<std::string>(value);
Matt Spinlerf10068d2020-12-02 10:44:08 -0600119 auto status = Progress::convertProgressStagesFromString(
120 std::get<std::string>(value));
Matt Spinler2a28c932020-02-03 14:23:40 -0600121
Matt Spinlerf10068d2020-12-02 10:44:08 -0600122 if ((status == Progress::ProgressStages::SystemInitComplete) ||
123 (status == Progress::ProgressStages::OSStart) ||
124 (status == Progress::ProgressStages::OSRunning))
Matt Spinler2a28c932020-02-03 14:23:40 -0600125 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600126 setHostUp(true);
Matt Spinler2a28c932020-02-03 14:23:40 -0600127 }
128 else
129 {
Matt Spinler4aa23a12020-02-03 15:05:09 -0600130 setHostUp(false);
Matt Spinler2a28c932020-02-03 14:23:40 -0600131 }
132 }));
Matt Spinler9cf3cfd2020-02-03 14:41:55 -0600133
134 // Watch the host PEL enable property
135 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
136 bus, object_path::enableHostPELs, interface::enable, "Enabled", *this,
137 [this](const auto& value) {
138 this->_sendPELsToHost = std::get<bool>(value);
139 }));
Matt Spinler4aa23a12020-02-03 15:05:09 -0600140
141 // Watch the BMCState property
142 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
143 bus, object_path::bmcState, interface::bmcState, "CurrentBMCState",
144 *this, [this](const auto& value) {
145 this->_bmcState = std::get<std::string>(value);
146 }));
147
148 // Watch the chassis current and requested power state properties
149 _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
150 bus, object_path::chassisState, interface::chassisState, *this,
151 [this](const auto& properties) {
152 auto state = properties.find("CurrentPowerState");
153 if (state != properties.end())
154 {
155 this->_chassisState = std::get<std::string>(state->second);
156 }
157
158 auto trans = properties.find("RequestedPowerTransition");
159 if (trans != properties.end())
160 {
161 this->_chassisTransition = std::get<std::string>(trans->second);
162 }
163 }));
164
165 // Watch the CurrentHostState property
166 _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
167 bus, object_path::hostState, interface::hostState, "CurrentHostState",
168 *this, [this](const auto& value) {
169 this->_hostState = std::get<std::string>(value);
170 }));
Matt Spinlerc8705e22019-09-11 12:36:07 -0500171}
172
Matt Spinler2a28c932020-02-03 14:23:40 -0600173DBusPropertyMap
174 DataInterface::getAllProperties(const std::string& service,
175 const std::string& objectPath,
176 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500177{
178 DBusPropertyMap properties;
179
180 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
181 interface::dbusProperty, "GetAll");
182 method.append(interface);
183 auto reply = _bus.call(method);
184
185 reply.read(properties);
186
187 return properties;
188}
189
Matt Spinlera7d9d962019-11-06 15:01:25 -0600190void DataInterface::getProperty(const std::string& service,
191 const std::string& objectPath,
192 const std::string& interface,
Matt Spinler2a28c932020-02-03 14:23:40 -0600193 const std::string& property,
194 DBusValue& value) const
Matt Spinlera7d9d962019-11-06 15:01:25 -0600195{
196
197 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
198 interface::dbusProperty, "Get");
199 method.append(interface, property);
200 auto reply = _bus.call(method);
201
202 reply.read(value);
203}
204
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600205DBusPathList DataInterface::getPaths(const DBusInterfaceList& interfaces) const
206{
207
208 auto method = _bus.new_method_call(
209 service_name::objectMapper, object_path::objectMapper,
210 interface::objectMapper, "GetSubTreePaths");
211
212 method.append(std::string{"/"}, 0, interfaces);
213
214 auto reply = _bus.call(method);
215
216 DBusPathList paths;
217 reply.read(paths);
218
219 return paths;
220}
221
Matt Spinlerc8705e22019-09-11 12:36:07 -0500222DBusService DataInterface::getService(const std::string& objectPath,
Matt Spinlerb3f51862019-12-09 13:55:10 -0600223 const std::string& interface) const
Matt Spinlerc8705e22019-09-11 12:36:07 -0500224{
225 auto method = _bus.new_method_call(service_name::objectMapper,
226 object_path::objectMapper,
227 interface::objectMapper, "GetObject");
228
229 method.append(objectPath, std::vector<std::string>({interface}));
230
231 auto reply = _bus.call(method);
232
233 std::map<DBusService, DBusInterfaceList> response;
234 reply.read(response);
235
236 if (!response.empty())
237 {
238 return response.begin()->first;
239 }
240
241 return std::string{};
242}
Matt Spinlera7d9d962019-11-06 15:01:25 -0600243
Matt Spinler677381b2020-01-23 10:04:29 -0600244void DataInterface::readBMCFWVersion()
245{
Matt Spinlerf61f2922020-06-23 11:32:49 -0500246 _bmcFWVersion =
247 phosphor::logging::util::getOSReleaseValue("VERSION").value_or("");
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600248}
249
250void DataInterface::readServerFWVersion()
251{
Sumit Kumarcad16202021-05-13 04:06:15 -0500252 auto value =
253 phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
254 if ((value != "") && (value.find_last_of(')') != std::string::npos))
255 {
256 std::size_t pos = value.find_first_of('(') + 1;
257 _serverFWVersion = value.substr(pos, value.find_last_of(')') - pos);
258 }
Matt Spinlercad9c2b2019-12-02 15:42:01 -0600259}
260
Matt Spinler677381b2020-01-23 10:04:29 -0600261void DataInterface::readBMCFWVersionID()
262{
Matt Spinlerf61f2922020-06-23 11:32:49 -0500263 _bmcFWVersionID =
264 phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
Matt Spinler677381b2020-01-23 10:04:29 -0600265}
266
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500267std::string DataInterface::getMachineTypeModel() const
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600268{
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500269 std::string model;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600270 try
271 {
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600272
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500273 auto service = getService(object_path::systemInv, interface::invAsset);
274 if (!service.empty())
275 {
276 DBusValue value;
277 getProperty(service, object_path::systemInv, interface::invAsset,
278 "Model", value);
279
280 model = std::get<std::string>(value);
281 }
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600282 }
283 catch (const std::exception& e)
284 {
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500285 log<level::WARNING>(fmt::format("Failed reading Model property from "
286 "Interface: {} exception: {}",
287 interface::invAsset, e.what())
288 .c_str());
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600289 }
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500290
291 return model;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600292}
293
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500294std::string DataInterface::getMachineSerialNumber() const
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600295{
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500296 std::string sn;
297 try
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600298 {
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500299
300 auto service = getService(object_path::systemInv, interface::invAsset);
301 if (!service.empty())
302 {
303 DBusValue value;
304 getProperty(service, object_path::systemInv, interface::invAsset,
305 "SerialNumber", value);
306
307 sn = std::get<std::string>(value);
308 }
309 }
310 catch (const std::exception& e)
311 {
312 log<level::WARNING>(
313 fmt::format("Failed reading SerialNumber property from "
314 "Interface: {} exception: {}",
315 interface::invAsset, e.what())
316 .c_str());
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600317 }
318
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500319 return sn;
320}
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600321
Vijay Lobo81b4dca2021-04-29 00:04:00 -0500322std::string DataInterface::getMotherboardCCIN() const
323{
324 std::string ccin;
325
326 try
327 {
328 auto service =
329 getService(object_path::motherBoardInv, interface::viniRecordVPD);
330 if (!service.empty())
331 {
332 DBusValue value;
333 getProperty(service, object_path::motherBoardInv,
334 interface::viniRecordVPD, "CC", value);
335
336 auto cc = std::get<std::vector<uint8_t>>(value);
337 ccin = std::string{cc.begin(), cc.end()};
338 }
339 }
340 catch (const std::exception& e)
341 {
342 log<level::WARNING>(
343 fmt::format("Failed reading Motherboard CCIN property from "
344 "Interface: {} exception: {}",
345 interface::viniRecordVPD, e.what())
346 .c_str());
347 }
348
349 return ccin;
Matt Spinlerb3d488f2020-02-21 15:30:46 -0600350}
351
Ben Tynere32b7e72021-05-18 12:38:40 -0500352std::vector<uint8_t> DataInterface::getSystemIMKeyword() const
353{
354 std::vector<uint8_t> systemIM;
355
356 try
357 {
358 auto service =
359 getService(object_path::motherBoardInv, interface::vsbpRecordVPD);
360 if (!service.empty())
361 {
362 DBusValue value;
363 getProperty(service, object_path::motherBoardInv,
364 interface::vsbpRecordVPD, "IM", value);
365
366 systemIM = std::get<std::vector<uint8_t>>(value);
367 }
368 }
369 catch (const std::exception& e)
370 {
371 log<level::WARNING>(
372 fmt::format("Failed reading System IM property from "
373 "Interface: {} exception: {}",
374 interface::vsbpRecordVPD, e.what())
375 .c_str());
376 }
377
378 return systemIM;
379}
380
Matt Spinler60c4e792020-03-13 13:45:36 -0500381void DataInterface::getHWCalloutFields(const std::string& inventoryPath,
Matt Spinler60c4e792020-03-13 13:45:36 -0500382 std::string& fruPartNumber,
383 std::string& ccin,
384 std::string& serialNumber) const
385{
386 // For now, attempt to get all of the properties directly on the path
387 // passed in. In the future, may need to make use of an algorithm
388 // to figure out which inventory objects actually hold these
389 // interfaces in the case of non FRUs, or possibly another service
390 // will provide this info. Any missing interfaces will result
391 // in exceptions being thrown.
392
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500393 auto service = getService(inventoryPath, interface::viniRecordVPD);
Matt Spinler60c4e792020-03-13 13:45:36 -0500394
395 auto properties =
396 getAllProperties(service, inventoryPath, interface::viniRecordVPD);
397
398 auto value = std::get<std::vector<uint8_t>>(properties["FN"]);
399 fruPartNumber = std::string{value.begin(), value.end()};
400
401 value = std::get<std::vector<uint8_t>>(properties["CC"]);
402 ccin = std::string{value.begin(), value.end()};
403
404 value = std::get<std::vector<uint8_t>>(properties["SN"]);
405 serialNumber = std::string{value.begin(), value.end()};
406}
407
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500408std::string
409 DataInterface::getLocationCode(const std::string& inventoryPath) const
410{
411 auto service = getService(inventoryPath, interface::locCode);
412
413 DBusValue locCode;
414 getProperty(service, inventoryPath, interface::locCode, "LocationCode",
415 locCode);
416
417 return std::get<std::string>(locCode);
418}
419
Matt Spinler5fb24c12020-06-04 11:21:33 -0500420std::string
421 DataInterface::addLocationCodePrefix(const std::string& locationCode)
422{
423 static const std::string locationCodePrefix{"Ufcs-"};
424
Matt Spinler0e4d72e2020-08-05 12:36:53 -0500425 // Technically there are 2 location code prefixes, Ufcs and Umts, so
426 // if it already starts with a U then don't need to do anything.
427 if (locationCode.front() != 'U')
Matt Spinler5fb24c12020-06-04 11:21:33 -0500428 {
429 return locationCodePrefix + locationCode;
430 }
431
432 return locationCode;
433}
434
435std::string DataInterface::expandLocationCode(const std::string& locationCode,
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500436 uint16_t /*node*/) const
Matt Spinler5fb24c12020-06-04 11:21:33 -0500437{
Matt Spinler0d92b522021-06-16 13:28:17 -0600438 // Location codes for connectors are the location code of the FRU they are
439 // on, plus a '-Tx' segment. Remove this last segment before expanding it
440 // and then add it back in afterwards. This way, the connector doesn't have
441 // to be in the model just so that it can be expanded.
442 auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
443
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500444 auto method =
445 _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
446 interface::vpdManager, "GetExpandedLocationCode");
447
Matt Spinler0d92b522021-06-16 13:28:17 -0600448 method.append(addLocationCodePrefix(baseLoc), static_cast<uint16_t>(0));
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500449
450 auto reply = _bus.call(method);
451
452 std::string expandedLocationCode;
453 reply.read(expandedLocationCode);
454
Matt Spinler0d92b522021-06-16 13:28:17 -0600455 if (!connectorLoc.empty())
456 {
457 expandedLocationCode += connectorLoc;
458 }
459
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500460 return expandedLocationCode;
Matt Spinler5fb24c12020-06-04 11:21:33 -0500461}
462
Matt Spinler2f9225a2020-08-05 12:58:49 -0500463std::string
464 DataInterface::getInventoryFromLocCode(const std::string& locationCode,
465 uint16_t node, bool expanded) const
Matt Spinler5fb24c12020-06-04 11:21:33 -0500466{
Matt Spinler2f9225a2020-08-05 12:58:49 -0500467 std::string methodName = expanded ? "GetFRUsByExpandedLocationCode"
468 : "GetFRUsByUnexpandedLocationCode";
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500469
Matt Spinler0d92b522021-06-16 13:28:17 -0600470 // Remove the connector segment, if present, so that this method call
471 // returns an inventory path that getHWCalloutFields() can be used with.
472 // (The serial number, etc, aren't stored on the connector in the
473 // inventory, and may not even be modeled.)
474 auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
475
Matt Spinler2f9225a2020-08-05 12:58:49 -0500476 auto method =
477 _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
478 interface::vpdManager, methodName.c_str());
479
480 if (expanded)
481 {
Matt Spinler0d92b522021-06-16 13:28:17 -0600482 method.append(baseLoc);
Matt Spinler2f9225a2020-08-05 12:58:49 -0500483 }
484 else
485 {
Matt Spinler0d92b522021-06-16 13:28:17 -0600486 method.append(addLocationCodePrefix(baseLoc), node);
Matt Spinler2f9225a2020-08-05 12:58:49 -0500487 }
Matt Spinlerfcf9a3f2020-07-28 13:21:07 -0500488
489 auto reply = _bus.call(method);
490
491 std::vector<sdbusplus::message::object_path> entries;
492 reply.read(entries);
493
494 // Get the shortest entry from the paths received, as this
495 // would be the path furthest up the inventory hierarchy so
496 // would be the parent FRU. There is guaranteed to at least
497 // be one entry if the call didn't fail.
498 std::string shortest{entries[0]};
499
500 std::for_each(entries.begin(), entries.end(),
501 [&shortest](const auto& path) {
502 if (path.str.size() < shortest.size())
503 {
504 shortest = path;
505 }
506 });
507
508 return shortest;
Matt Spinler5fb24c12020-06-04 11:21:33 -0500509}
510
Matt Spinler34a904c2020-08-05 14:53:28 -0500511void DataInterface::assertLEDGroup(const std::string& ledGroup,
512 bool value) const
513{
514 DBusValue variant = value;
515 auto method =
516 _bus.new_method_call(service_name::ledGroupManager, ledGroup.c_str(),
517 interface::dbusProperty, "Set");
518 method.append(interface::ledGroup, "Asserted", variant);
519 _bus.call(method);
520}
521
Matt Spinler993168d2021-04-07 16:05:03 -0500522void DataInterface::setFunctional(const std::string& objectPath,
523 bool value) const
524{
525 DBusValue variant = value;
526 auto service = getService(objectPath, interface::operationalStatus);
527
528 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
529 interface::dbusProperty, "Set");
530
531 method.append(interface::operationalStatus, "Functional", variant);
532 _bus.call(method);
533}
534
Sumit Kumar76198a22021-07-15 05:59:57 -0500535using AssociationTuple = std::tuple<std::string, std::string, std::string>;
536using AssociationsProperty = std::vector<AssociationTuple>;
537
538void DataInterface::setCriticalAssociation(const std::string& objectPath) const
539{
540 DBusValue getAssociationValue;
541
542 auto service = getService(objectPath, interface::association);
543
544 getProperty(service, objectPath, interface::association, "Associations",
545 getAssociationValue);
546
547 auto association = std::get<AssociationsProperty>(getAssociationValue);
548
549 AssociationTuple critAssociation{
550 "health_rollup", "critical",
551 "/xyz/openbmc_project/inventory/system/chassis"};
552
553 if (std::find(association.begin(), association.end(), critAssociation) ==
554 association.end())
555 {
556 association.push_back(critAssociation);
557 DBusValue setAssociationValue = association;
558
559 auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
560 interface::dbusProperty, "Set");
561
562 method.append(interface::association, "Associations",
563 setAssociationValue);
564 _bus.call(method);
565 }
566}
567
Matt Spinler1ab66962020-10-29 13:21:44 -0500568std::vector<std::string> DataInterface::getSystemNames() const
569{
570 DBusSubTree subtree;
571 DBusValue names;
572
573 auto method = _bus.new_method_call(service_name::objectMapper,
574 object_path::objectMapper,
575 interface::objectMapper, "GetSubTree");
576 method.append(std::string{"/"}, 0,
577 std::vector<std::string>{interface::compatible});
578 auto reply = _bus.call(method);
579
580 reply.read(subtree);
581 if (subtree.empty())
582 {
583 throw std::runtime_error("Compatible interface not on D-Bus");
584 }
585
586 const auto& object = *(subtree.begin());
587 const auto& path = object.first;
588 const auto& service = object.second.begin()->first;
589
590 getProperty(service, path, interface::compatible, "Names", names);
591
592 return std::get<std::vector<std::string>>(names);
593}
594
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -0500595bool DataInterface::getQuiesceOnError() const
596{
597 bool ret = false;
598
599 try
600 {
601 auto service =
602 getService(object_path::logSetting, interface::logSetting);
603 if (!service.empty())
604 {
605 DBusValue value;
606 getProperty(service, object_path::logSetting, interface::logSetting,
607 "QuiesceOnHwError", value);
608
609 ret = std::get<bool>(value);
610 }
611 }
612 catch (const std::exception& e)
613 {
614 log<level::WARNING>(
615 fmt::format("Failed reading QuiesceOnHwError property from "
616 "Interface: {} exception: {}",
617 interface::logSetting, e.what())
618 .c_str());
619 }
620
621 return ret;
622}
623
Sumit Kumar9d43a722021-08-24 09:46:19 -0500624std::vector<bool>
625 DataInterface::checkDumpStatus(const std::vector<std::string>& type) const
626{
627 DBusSubTree subtree;
628 std::vector<bool> result(type.size(), false);
629
630 // Query GetSubTree for the availability of dump interface
631 auto method = _bus.new_method_call(service_name::objectMapper,
632 object_path::objectMapper,
633 interface::objectMapper, "GetSubTree");
634 method.append(std::string{"/"}, 0,
635 std::vector<std::string>{interface::dumpEntry});
636 auto reply = _bus.call(method);
637
638 reply.read(subtree);
639
640 if (subtree.empty())
641 {
642 return result;
643 }
644
645 std::vector<bool>::iterator itDumpStatus = result.begin();
646 uint8_t count = 0;
647 for (const auto& [path, serviceInfo] : subtree)
648 {
649 const auto& service = serviceInfo.begin()->first;
650 // Check for dump type on the object path
651 for (const auto& it : type)
652 {
653 if (path.find(it) != std::string::npos)
654 {
655 DBusValue value, progress;
656
657 // If dump type status is already available go for next path
658 if (*itDumpStatus)
659 {
660 break;
661 }
662
663 // Check for valid dump to be available if following
664 // conditions are met for the dump entry path -
665 // Offloaded == false and Status == Completed
666 getProperty(service, path, interface::dumpEntry, "Offloaded",
667 value);
668 getProperty(service, path, interface::dumpProgress, "Status",
669 progress);
670 auto offload = std::get<bool>(value);
671 auto status = std::get<std::string>(progress);
672 if (!offload && (status.find("Completed") != std::string::npos))
673 {
674 *itDumpStatus = true;
675 count++;
676 if (count >= type.size())
677 {
678 return result;
679 }
680 break;
681 }
682 }
683 itDumpStatus++;
684 }
685 itDumpStatus = result.begin();
686 }
687
688 return result;
689}
690
Matt Spinlerc8705e22019-09-11 12:36:07 -0500691} // namespace pels
692} // namespace openpower