xref: /openbmc/phosphor-logging/extensions/openpower-pels/data_interface.cpp (revision 25291157927273a4ac459c6479c1d3090ddc6a16)
1711d51d8SMatt Spinler /**
2711d51d8SMatt Spinler  * Copyright © 2019 IBM Corporation
3711d51d8SMatt Spinler  *
4711d51d8SMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
5711d51d8SMatt Spinler  * you may not use this file except in compliance with the License.
6711d51d8SMatt Spinler  * You may obtain a copy of the License at
7711d51d8SMatt Spinler  *
8711d51d8SMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
9711d51d8SMatt Spinler  *
10711d51d8SMatt Spinler  * Unless required by applicable law or agreed to in writing, software
11711d51d8SMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
12711d51d8SMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13711d51d8SMatt Spinler  * See the License for the specific language governing permissions and
14711d51d8SMatt Spinler  * limitations under the License.
15711d51d8SMatt Spinler  */
16cad9c2bdSMatt Spinler 
17c8705e2bSMatt Spinler #include "data_interface.hpp"
18c8705e2bSMatt Spinler 
19f61f2921SMatt Spinler #include "util.hpp"
20f61f2921SMatt Spinler 
21a167a7d9SMatt Spinler #include <phosphor-logging/lg2.hpp>
225b423651SMatt Spinler #include <xyz/openbmc_project/State/BMC/server.hpp>
23f10068d3SMatt Spinler #include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
24a7d9d961SMatt Spinler 
25afba316cSArya K Padman #include <filesystem>
26afba316cSArya K Padman 
27d8ae618aSArya K Padman #ifdef PEL_ENABLE_PHAL
28afba316cSArya K Padman #include <libekb.H>
29afba316cSArya K Padman #include <libpdbg.h>
30d8ae618aSArya K Padman #include <libphal.H>
31d8ae618aSArya K Padman #endif
32d8ae618aSArya K Padman 
3335a405b8SMatt Spinler // Use a timeout of 10s for D-Bus calls so if there are
3435a405b8SMatt Spinler // timeouts the callers of the PEL creation method won't
3535a405b8SMatt Spinler // also timeout.
3635a405b8SMatt Spinler constexpr auto dbusTimeout = 10000000;
3735a405b8SMatt Spinler 
38c8705e2bSMatt Spinler namespace openpower
39c8705e2bSMatt Spinler {
40c8705e2bSMatt Spinler namespace pels
41c8705e2bSMatt Spinler {
42c8705e2bSMatt Spinler 
43c8705e2bSMatt Spinler namespace service_name
44c8705e2bSMatt Spinler {
45c8705e2bSMatt Spinler constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
46fcf9a3f4SMatt Spinler constexpr auto vpdManager = "com.ibm.VPD.Manager";
4734a904cfSMatt Spinler constexpr auto ledGroupManager = "xyz.openbmc_project.LED.GroupManager";
48ecaa2fceSJayanth Othayoth constexpr auto hwIsolation = "org.open_power.HardwareIsolation";
49744d8515SMatt Spinler constexpr auto biosConfigMgr = "xyz.openbmc_project.BIOSConfigManager";
50875b6c7bSVijay Lobo constexpr auto bootRawProgress = "xyz.openbmc_project.State.Boot.Raw";
5152ee3a4fSMatt Spinler constexpr auto pldm = "xyz.openbmc_project.PLDM";
52412f50edSMatt Spinler constexpr auto inventoryManager = "xyz.openbmc_project.Inventory.Manager";
53bbc11ef9SMatt Spinler constexpr auto entityManager = "xyz.openbmc_project.EntityManager";
54afba316cSArya K Padman constexpr auto systemd = "org.freedesktop.systemd1";
55c8705e2bSMatt Spinler } // namespace service_name
56c8705e2bSMatt Spinler 
57c8705e2bSMatt Spinler namespace object_path
58c8705e2bSMatt Spinler {
59c8705e2bSMatt Spinler constexpr auto objectMapper = "/xyz/openbmc_project/object_mapper";
60c8705e2bSMatt Spinler constexpr auto systemInv = "/xyz/openbmc_project/inventory/system";
6181b4dcabSVijay Lobo constexpr auto motherBoardInv =
6281b4dcabSVijay Lobo     "/xyz/openbmc_project/inventory/system/chassis/motherboard";
63b3d488fdSMatt Spinler constexpr auto baseInv = "/xyz/openbmc_project/inventory";
644aa23a1fSMatt Spinler constexpr auto bmcState = "/xyz/openbmc_project/state/bmc0";
654aa23a1fSMatt Spinler constexpr auto chassisState = "/xyz/openbmc_project/state/chassis0";
66a7d9d961SMatt Spinler constexpr auto hostState = "/xyz/openbmc_project/state/host0";
679cf3cfdaSMatt Spinler constexpr auto enableHostPELs =
689cf3cfdaSMatt Spinler     "/xyz/openbmc_project/logging/send_event_logs_to_host";
69fcf9a3f4SMatt Spinler constexpr auto vpdManager = "/com/ibm/VPD/Manager";
703b8ed7f2SSumit Kumar constexpr auto logSetting = "/xyz/openbmc_project/logging/settings";
71ecaa2fceSJayanth Othayoth constexpr auto hwIsolation = "/xyz/openbmc_project/hardware_isolation";
72744d8515SMatt Spinler constexpr auto biosConfigMgr = "/xyz/openbmc_project/bios_config/manager";
73875b6c7bSVijay Lobo constexpr auto bootRawProgress = "/xyz/openbmc_project/state/boot/raw0";
74afba316cSArya K Padman constexpr auto systemd = "/org/freedesktop/systemd1";
75c8705e2bSMatt Spinler } // namespace object_path
76c8705e2bSMatt Spinler 
77c8705e2bSMatt Spinler namespace interface
78c8705e2bSMatt Spinler {
79c8705e2bSMatt Spinler constexpr auto dbusProperty = "org.freedesktop.DBus.Properties";
80c8705e2bSMatt Spinler constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
81c8705e2bSMatt Spinler constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset";
82f10068d3SMatt Spinler constexpr auto bootProgress = "xyz.openbmc_project.State.Boot.Progress";
839cf3cfdaSMatt Spinler constexpr auto enable = "xyz.openbmc_project.Object.Enable";
844aa23a1fSMatt Spinler constexpr auto bmcState = "xyz.openbmc_project.State.BMC";
854aa23a1fSMatt Spinler constexpr auto chassisState = "xyz.openbmc_project.State.Chassis";
864aa23a1fSMatt Spinler constexpr auto hostState = "xyz.openbmc_project.State.Host";
87b3d488fdSMatt Spinler constexpr auto viniRecordVPD = "com.ibm.ipzvpd.VINI";
88e32b7e76SBen Tyner constexpr auto vsbpRecordVPD = "com.ibm.ipzvpd.VSBP";
89cc8b1116SMatt Spinler constexpr auto locCode = "xyz.openbmc_project.Inventory.Decorator.LocationCode";
901ab6696fSMatt Spinler constexpr auto compatible =
91bbc11ef9SMatt Spinler     "xyz.openbmc_project.Inventory.Decorator.Compatible";
92fcf9a3f4SMatt Spinler constexpr auto vpdManager = "com.ibm.VPD.Manager";
9334a904cfSMatt Spinler constexpr auto ledGroup = "xyz.openbmc_project.Led.Group";
94993168deSMatt Spinler constexpr auto operationalStatus =
95993168deSMatt Spinler     "xyz.openbmc_project.State.Decorator.OperationalStatus";
963b8ed7f2SSumit Kumar constexpr auto logSetting = "xyz.openbmc_project.Logging.Settings";
97027bf285SSumit Kumar constexpr auto associationDef = "xyz.openbmc_project.Association.Definitions";
98027bf285SSumit Kumar constexpr auto hwIsolationEntry = "xyz.openbmc_project.HardwareIsolation.Entry";
99027bf285SSumit Kumar constexpr auto association = "xyz.openbmc_project.Association";
100744d8515SMatt Spinler constexpr auto biosConfigMgr = "xyz.openbmc_project.BIOSConfig.Manager";
101875b6c7bSVijay Lobo constexpr auto bootRawProgress = "xyz.openbmc_project.State.Boot.Raw";
1025b423651SMatt Spinler constexpr auto invItem = "xyz.openbmc_project.Inventory.Item";
1035b423651SMatt Spinler constexpr auto invFan = "xyz.openbmc_project.Inventory.Item.Fan";
1045b423651SMatt Spinler constexpr auto invPowerSupply =
1055b423651SMatt Spinler     "xyz.openbmc_project.Inventory.Item.PowerSupply";
106412f50edSMatt Spinler constexpr auto inventoryManager = "xyz.openbmc_project.Inventory.Manager";
107afba316cSArya K Padman constexpr auto systemdMgr = "org.freedesktop.systemd1.Manager";
108c8705e2bSMatt Spinler } // namespace interface
109c8705e2bSMatt Spinler 
1106ddbf69eSWilly Tu using namespace sdbusplus::server::xyz::openbmc_project::state::boot;
1116ddbf69eSWilly Tu using namespace sdbusplus::server::xyz::openbmc_project::state;
1125b423651SMatt Spinler namespace match_rules = sdbusplus::bus::match::rules;
1135b423651SMatt Spinler 
1145b423651SMatt Spinler const DBusInterfaceList hotplugInterfaces{interface::invFan,
1155b423651SMatt Spinler                                           interface::invPowerSupply};
116afba316cSArya K Padman static constexpr auto PDBG_DTB_PATH =
117afba316cSArya K Padman     "/var/lib/phosphor-software-manager/hostfw/running/DEVTREE";
118a7d9d961SMatt Spinler 
1190d92b528SMatt Spinler std::pair<std::string, std::string>
extractConnectorFromLocCode(const std::string & locationCode)1200d92b528SMatt Spinler     DataInterfaceBase::extractConnectorFromLocCode(
1210d92b528SMatt Spinler         const std::string& locationCode)
1220d92b528SMatt Spinler {
1230d92b528SMatt Spinler     auto base = locationCode;
1240d92b528SMatt Spinler     std::string connector{};
1250d92b528SMatt Spinler 
1260d92b528SMatt Spinler     auto pos = base.find("-T");
1270d92b528SMatt Spinler     if (pos != std::string::npos)
1280d92b528SMatt Spinler     {
1290d92b528SMatt Spinler         connector = base.substr(pos);
1300d92b528SMatt Spinler         base = base.substr(0, pos);
1310d92b528SMatt Spinler     }
1320d92b528SMatt Spinler 
1330d92b528SMatt Spinler     return {base, connector};
1340d92b528SMatt Spinler }
1350d92b528SMatt Spinler 
DataInterface(sdbusplus::bus_t & bus)136afba316cSArya K Padman DataInterface::DataInterface(sdbusplus::bus_t& bus) :
137afba316cSArya K Padman     _bus(bus), _systemdSlot(nullptr)
138c8705e2bSMatt Spinler {
139cad9c2bdSMatt Spinler     readBMCFWVersion();
140cad9c2bdSMatt Spinler     readServerFWVersion();
141677381b8SMatt Spinler     readBMCFWVersionID();
1422a28c936SMatt Spinler 
143f10068d3SMatt Spinler     // Watch the BootProgress property
1442a28c936SMatt Spinler     _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
145f10068d3SMatt Spinler         bus, object_path::hostState, interface::bootProgress, "BootProgress",
146f10068d3SMatt Spinler         *this, [this](const auto& value) {
1472c36fddcSSumit Kumar             this->_bootState = std::get<std::string>(value);
148f10068d3SMatt Spinler             auto status = Progress::convertProgressStagesFromString(
149f10068d3SMatt Spinler                 std::get<std::string>(value));
1502a28c936SMatt Spinler 
151f10068d3SMatt Spinler             if ((status == Progress::ProgressStages::SystemInitComplete) ||
152f10068d3SMatt Spinler                 (status == Progress::ProgressStages::OSRunning))
1532a28c936SMatt Spinler             {
1544aa23a1fSMatt Spinler                 setHostUp(true);
1552a28c936SMatt Spinler             }
1562a28c936SMatt Spinler             else
1572a28c936SMatt Spinler             {
1584aa23a1fSMatt Spinler                 setHostUp(false);
1592a28c936SMatt Spinler             }
1602a28c936SMatt Spinler         }));
1619cf3cfdaSMatt Spinler 
1629cf3cfdaSMatt Spinler     // Watch the host PEL enable property
1639cf3cfdaSMatt Spinler     _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
1649cf3cfdaSMatt Spinler         bus, object_path::enableHostPELs, interface::enable, "Enabled", *this,
1659cf3cfdaSMatt Spinler         [this](const auto& value) {
166c6ee7c54SMatt Spinler             if (std::get<bool>(value) != this->_sendPELsToHost)
167c6ee7c54SMatt Spinler             {
168075c7923SPatrick Williams                 lg2::info("The send PELs to host setting changed to {VAL}",
169075c7923SPatrick Williams                           "VAL", std::get<bool>(value));
170c6ee7c54SMatt Spinler             }
1719cf3cfdaSMatt Spinler             this->_sendPELsToHost = std::get<bool>(value);
1729cf3cfdaSMatt Spinler         }));
1734aa23a1fSMatt Spinler 
1744aa23a1fSMatt Spinler     // Watch the BMCState property
1754aa23a1fSMatt Spinler     _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
1764aa23a1fSMatt Spinler         bus, object_path::bmcState, interface::bmcState, "CurrentBMCState",
1774aa23a1fSMatt Spinler         *this, [this](const auto& value) {
1785b423651SMatt Spinler             const auto& state = std::get<std::string>(value);
1795b423651SMatt Spinler             this->_bmcState = state;
1805b423651SMatt Spinler 
1815b423651SMatt Spinler             // Wait for BMC ready to start watching for
1825b423651SMatt Spinler             // plugs so things calm down first.
1835b423651SMatt Spinler             if (BMC::convertBMCStateFromString(state) == BMC::BMCState::Ready)
1845b423651SMatt Spinler             {
1855b423651SMatt Spinler                 startFruPlugWatch();
1865b423651SMatt Spinler             }
1874aa23a1fSMatt Spinler         }));
1884aa23a1fSMatt Spinler 
1894aa23a1fSMatt Spinler     // Watch the chassis current and requested power state properties
1904aa23a1fSMatt Spinler     _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
1914aa23a1fSMatt Spinler         bus, object_path::chassisState, interface::chassisState, *this,
1924aa23a1fSMatt Spinler         [this](const auto& properties) {
1934aa23a1fSMatt Spinler             auto state = properties.find("CurrentPowerState");
1944aa23a1fSMatt Spinler             if (state != properties.end())
1954aa23a1fSMatt Spinler             {
1964aa23a1fSMatt Spinler                 this->_chassisState = std::get<std::string>(state->second);
1974aa23a1fSMatt Spinler             }
1984aa23a1fSMatt Spinler 
1994aa23a1fSMatt Spinler             auto trans = properties.find("RequestedPowerTransition");
2004aa23a1fSMatt Spinler             if (trans != properties.end())
2014aa23a1fSMatt Spinler             {
2024aa23a1fSMatt Spinler                 this->_chassisTransition = std::get<std::string>(trans->second);
2034aa23a1fSMatt Spinler             }
2044aa23a1fSMatt Spinler         }));
2054aa23a1fSMatt Spinler 
2064aa23a1fSMatt Spinler     // Watch the CurrentHostState property
2074aa23a1fSMatt Spinler     _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
2084aa23a1fSMatt Spinler         bus, object_path::hostState, interface::hostState, "CurrentHostState",
2094aa23a1fSMatt Spinler         *this, [this](const auto& value) {
2104aa23a1fSMatt Spinler             this->_hostState = std::get<std::string>(value);
2114aa23a1fSMatt Spinler         }));
212744d8515SMatt Spinler 
213744d8515SMatt Spinler     // Watch the BaseBIOSTable property for the hmc managed attribute
214744d8515SMatt Spinler     _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
215744d8515SMatt Spinler         bus, object_path::biosConfigMgr, interface::biosConfigMgr,
216744d8515SMatt Spinler         "BaseBIOSTable", service_name::biosConfigMgr, *this,
217744d8515SMatt Spinler         [this](const auto& value) {
218744d8515SMatt Spinler             const auto& attributes = std::get<BiosAttributes>(value);
219744d8515SMatt Spinler 
220744d8515SMatt Spinler             auto it = attributes.find("pvm_hmc_managed");
221744d8515SMatt Spinler             if (it != attributes.end())
222744d8515SMatt Spinler             {
223744d8515SMatt Spinler                 const auto& currentValVariant = std::get<5>(it->second);
224744d8515SMatt Spinler                 auto currentVal = std::get_if<std::string>(&currentValVariant);
225744d8515SMatt Spinler                 if (currentVal)
226744d8515SMatt Spinler                 {
227075c7923SPatrick Williams                     this->_hmcManaged =
228075c7923SPatrick Williams                         (*currentVal == "Enabled") ? true : false;
229744d8515SMatt Spinler                 }
230744d8515SMatt Spinler             }
231744d8515SMatt Spinler         }));
232afba316cSArya K Padman 
233afba316cSArya K Padman     if (isPHALDevTreeExist())
234afba316cSArya K Padman     {
2350b758fb0SArya K Padman #ifdef PEL_ENABLE_PHAL
236afba316cSArya K Padman         initPHAL();
2370b758fb0SArya K Padman #endif
238afba316cSArya K Padman     }
239afba316cSArya K Padman     else
240afba316cSArya K Padman     {
241afba316cSArya K Padman         // Watch the "openpower-update-bios-attr-table" service to init
242afba316cSArya K Padman         // PHAL libraries
243afba316cSArya K Padman         subscribeToSystemdSignals();
244afba316cSArya K Padman     }
245c8705e2bSMatt Spinler }
246c8705e2bSMatt Spinler 
getAllProperties(const std::string & service,const std::string & objectPath,const std::string & interface) const247075c7923SPatrick Williams DBusPropertyMap DataInterface::getAllProperties(
248075c7923SPatrick Williams     const std::string& service, const std::string& objectPath,
2492a28c936SMatt Spinler     const std::string& interface) const
250c8705e2bSMatt Spinler {
251c8705e2bSMatt Spinler     DBusPropertyMap properties;
252c8705e2bSMatt Spinler 
253c8705e2bSMatt Spinler     auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
254c8705e2bSMatt Spinler                                        interface::dbusProperty, "GetAll");
255c8705e2bSMatt Spinler     method.append(interface);
25635a405b8SMatt Spinler     auto reply = _bus.call(method, dbusTimeout);
257c8705e2bSMatt Spinler 
258c8705e2bSMatt Spinler     reply.read(properties);
259c8705e2bSMatt Spinler 
260c8705e2bSMatt Spinler     return properties;
261c8705e2bSMatt Spinler }
262c8705e2bSMatt Spinler 
getProperty(const std::string & service,const std::string & objectPath,const std::string & interface,const std::string & property,DBusValue & value) const263075c7923SPatrick Williams void DataInterface::getProperty(
264075c7923SPatrick Williams     const std::string& service, const std::string& objectPath,
265075c7923SPatrick Williams     const std::string& interface, const std::string& property,
2662a28c936SMatt Spinler     DBusValue& value) const
267a7d9d961SMatt Spinler {
268a7d9d961SMatt Spinler     auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
269a7d9d961SMatt Spinler                                        interface::dbusProperty, "Get");
270a7d9d961SMatt Spinler     method.append(interface, property);
27135a405b8SMatt Spinler     auto reply = _bus.call(method, dbusTimeout);
272a7d9d961SMatt Spinler 
273a7d9d961SMatt Spinler     reply.read(value);
274a7d9d961SMatt Spinler }
275a7d9d961SMatt Spinler 
getPaths(const DBusInterfaceList & interfaces) const276b3d488fdSMatt Spinler DBusPathList DataInterface::getPaths(const DBusInterfaceList& interfaces) const
277b3d488fdSMatt Spinler {
278b3d488fdSMatt Spinler     auto method = _bus.new_method_call(
279b3d488fdSMatt Spinler         service_name::objectMapper, object_path::objectMapper,
280b3d488fdSMatt Spinler         interface::objectMapper, "GetSubTreePaths");
281b3d488fdSMatt Spinler 
282b3d488fdSMatt Spinler     method.append(std::string{"/"}, 0, interfaces);
283b3d488fdSMatt Spinler 
28435a405b8SMatt Spinler     auto reply = _bus.call(method, dbusTimeout);
285b3d488fdSMatt Spinler 
286b3d488fdSMatt Spinler     DBusPathList paths;
287b3d488fdSMatt Spinler     reply.read(paths);
288b3d488fdSMatt Spinler 
289b3d488fdSMatt Spinler     return paths;
290b3d488fdSMatt Spinler }
291b3d488fdSMatt Spinler 
getService(const std::string & objectPath,const std::string & interface) const292c8705e2bSMatt Spinler DBusService DataInterface::getService(const std::string& objectPath,
293b3f5186eSMatt Spinler                                       const std::string& interface) const
294c8705e2bSMatt Spinler {
295c8705e2bSMatt Spinler     auto method = _bus.new_method_call(service_name::objectMapper,
296c8705e2bSMatt Spinler                                        object_path::objectMapper,
297c8705e2bSMatt Spinler                                        interface::objectMapper, "GetObject");
298c8705e2bSMatt Spinler 
299c8705e2bSMatt Spinler     method.append(objectPath, std::vector<std::string>({interface}));
300c8705e2bSMatt Spinler 
30135a405b8SMatt Spinler     auto reply = _bus.call(method, dbusTimeout);
302c8705e2bSMatt Spinler 
303c8705e2bSMatt Spinler     std::map<DBusService, DBusInterfaceList> response;
304c8705e2bSMatt Spinler     reply.read(response);
305c8705e2bSMatt Spinler 
306c8705e2bSMatt Spinler     if (!response.empty())
307c8705e2bSMatt Spinler     {
308c8705e2bSMatt Spinler         return response.begin()->first;
309c8705e2bSMatt Spinler     }
310c8705e2bSMatt Spinler 
311c8705e2bSMatt Spinler     return std::string{};
312c8705e2bSMatt Spinler }
313a7d9d961SMatt Spinler 
readBMCFWVersion()314677381b8SMatt Spinler void DataInterface::readBMCFWVersion()
315677381b8SMatt Spinler {
316f61f2921SMatt Spinler     _bmcFWVersion =
317f61f2921SMatt Spinler         phosphor::logging::util::getOSReleaseValue("VERSION").value_or("");
318cad9c2bdSMatt Spinler }
319cad9c2bdSMatt Spinler 
readServerFWVersion()320cad9c2bdSMatt Spinler void DataInterface::readServerFWVersion()
321cad9c2bdSMatt Spinler {
322cad16201SSumit Kumar     auto value =
323cad16201SSumit Kumar         phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
324cad16201SSumit Kumar     if ((value != "") && (value.find_last_of(')') != std::string::npos))
325cad16201SSumit Kumar     {
326cad16201SSumit Kumar         std::size_t pos = value.find_first_of('(') + 1;
327cad16201SSumit Kumar         _serverFWVersion = value.substr(pos, value.find_last_of(')') - pos);
328cad16201SSumit Kumar     }
329cad9c2bdSMatt Spinler }
330cad9c2bdSMatt Spinler 
readBMCFWVersionID()331677381b8SMatt Spinler void DataInterface::readBMCFWVersionID()
332677381b8SMatt Spinler {
333f61f2921SMatt Spinler     _bmcFWVersionID =
334f61f2921SMatt Spinler         phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
335677381b8SMatt Spinler }
336677381b8SMatt Spinler 
getMachineTypeModel() const33781b4dcabSVijay Lobo std::string DataInterface::getMachineTypeModel() const
338b3d488fdSMatt Spinler {
33981b4dcabSVijay Lobo     std::string model;
340b3d488fdSMatt Spinler     try
341b3d488fdSMatt Spinler     {
34281b4dcabSVijay Lobo         auto service = getService(object_path::systemInv, interface::invAsset);
34381b4dcabSVijay Lobo         if (!service.empty())
34481b4dcabSVijay Lobo         {
34581b4dcabSVijay Lobo             DBusValue value;
34681b4dcabSVijay Lobo             getProperty(service, object_path::systemInv, interface::invAsset,
34781b4dcabSVijay Lobo                         "Model", value);
34881b4dcabSVijay Lobo 
34981b4dcabSVijay Lobo             model = std::get<std::string>(value);
35081b4dcabSVijay Lobo         }
351b3d488fdSMatt Spinler     }
352b3d488fdSMatt Spinler     catch (const std::exception& e)
353b3d488fdSMatt Spinler     {
354a167a7d9SMatt Spinler         lg2::warning("Failed reading Model property from "
355a167a7d9SMatt Spinler                      "interface: {IFACE} exception: {ERROR}",
356a167a7d9SMatt Spinler                      "IFACE", interface::invAsset, "ERROR", e);
357b3d488fdSMatt Spinler     }
358b3d488fdSMatt Spinler 
35981b4dcabSVijay Lobo     return model;
36081b4dcabSVijay Lobo }
36181b4dcabSVijay Lobo 
getMachineSerialNumber() const36281b4dcabSVijay Lobo std::string DataInterface::getMachineSerialNumber() const
363b3d488fdSMatt Spinler {
36481b4dcabSVijay Lobo     std::string sn;
36581b4dcabSVijay Lobo     try
366b3d488fdSMatt Spinler     {
36781b4dcabSVijay Lobo         auto service = getService(object_path::systemInv, interface::invAsset);
36881b4dcabSVijay Lobo         if (!service.empty())
36981b4dcabSVijay Lobo         {
37081b4dcabSVijay Lobo             DBusValue value;
37181b4dcabSVijay Lobo             getProperty(service, object_path::systemInv, interface::invAsset,
37281b4dcabSVijay Lobo                         "SerialNumber", value);
37381b4dcabSVijay Lobo 
37481b4dcabSVijay Lobo             sn = std::get<std::string>(value);
37581b4dcabSVijay Lobo         }
37681b4dcabSVijay Lobo     }
37781b4dcabSVijay Lobo     catch (const std::exception& e)
37881b4dcabSVijay Lobo     {
379a167a7d9SMatt Spinler         lg2::warning("Failed reading SerialNumber property from "
380a167a7d9SMatt Spinler                      "interface: {IFACE} exception: {ERROR}",
381a167a7d9SMatt Spinler                      "IFACE", interface::invAsset, "ERROR", e);
382b3d488fdSMatt Spinler     }
383b3d488fdSMatt Spinler 
38481b4dcabSVijay Lobo     return sn;
38581b4dcabSVijay Lobo }
386b3d488fdSMatt Spinler 
getMotherboardCCIN() const38781b4dcabSVijay Lobo std::string DataInterface::getMotherboardCCIN() const
38881b4dcabSVijay Lobo {
38981b4dcabSVijay Lobo     std::string ccin;
39081b4dcabSVijay Lobo 
39181b4dcabSVijay Lobo     try
39281b4dcabSVijay Lobo     {
393075c7923SPatrick Williams         auto service =
394075c7923SPatrick Williams             getService(object_path::motherBoardInv, interface::viniRecordVPD);
39581b4dcabSVijay Lobo         if (!service.empty())
39681b4dcabSVijay Lobo         {
39781b4dcabSVijay Lobo             DBusValue value;
39881b4dcabSVijay Lobo             getProperty(service, object_path::motherBoardInv,
39981b4dcabSVijay Lobo                         interface::viniRecordVPD, "CC", value);
40081b4dcabSVijay Lobo 
40181b4dcabSVijay Lobo             auto cc = std::get<std::vector<uint8_t>>(value);
40281b4dcabSVijay Lobo             ccin = std::string{cc.begin(), cc.end()};
40381b4dcabSVijay Lobo         }
40481b4dcabSVijay Lobo     }
40581b4dcabSVijay Lobo     catch (const std::exception& e)
40681b4dcabSVijay Lobo     {
407a167a7d9SMatt Spinler         lg2::warning("Failed reading Motherboard CCIN property from "
408a167a7d9SMatt Spinler                      "interface: {IFACE} exception: {ERROR}",
409a167a7d9SMatt Spinler                      "IFACE", interface::viniRecordVPD, "ERROR", e);
41081b4dcabSVijay Lobo     }
41181b4dcabSVijay Lobo 
41281b4dcabSVijay Lobo     return ccin;
413b3d488fdSMatt Spinler }
414b3d488fdSMatt Spinler 
getSystemIMKeyword() const415e32b7e76SBen Tyner std::vector<uint8_t> DataInterface::getSystemIMKeyword() const
416e32b7e76SBen Tyner {
417e32b7e76SBen Tyner     std::vector<uint8_t> systemIM;
418e32b7e76SBen Tyner 
419e32b7e76SBen Tyner     try
420e32b7e76SBen Tyner     {
421075c7923SPatrick Williams         auto service =
422075c7923SPatrick Williams             getService(object_path::motherBoardInv, interface::vsbpRecordVPD);
423e32b7e76SBen Tyner         if (!service.empty())
424e32b7e76SBen Tyner         {
425e32b7e76SBen Tyner             DBusValue value;
426e32b7e76SBen Tyner             getProperty(service, object_path::motherBoardInv,
427e32b7e76SBen Tyner                         interface::vsbpRecordVPD, "IM", value);
428e32b7e76SBen Tyner 
429e32b7e76SBen Tyner             systemIM = std::get<std::vector<uint8_t>>(value);
430e32b7e76SBen Tyner         }
431e32b7e76SBen Tyner     }
432e32b7e76SBen Tyner     catch (const std::exception& e)
433e32b7e76SBen Tyner     {
434a167a7d9SMatt Spinler         lg2::warning("Failed reading System IM property from "
435a167a7d9SMatt Spinler                      "interface: {IFACE} exception: {ERROR}",
436a167a7d9SMatt Spinler                      "IFACE", interface::vsbpRecordVPD, "ERROR", e);
437e32b7e76SBen Tyner     }
438e32b7e76SBen Tyner 
439e32b7e76SBen Tyner     return systemIM;
440e32b7e76SBen Tyner }
441e32b7e76SBen Tyner 
getHWCalloutFields(const std::string & inventoryPath,std::string & fruPartNumber,std::string & ccin,std::string & serialNumber) const442075c7923SPatrick Williams void DataInterface::getHWCalloutFields(
443075c7923SPatrick Williams     const std::string& inventoryPath, std::string& fruPartNumber,
444075c7923SPatrick Williams     std::string& ccin, std::string& serialNumber) const
44560c4e797SMatt Spinler {
44660c4e797SMatt Spinler     // For now, attempt to get all of the properties directly on the path
44760c4e797SMatt Spinler     // passed in.  In the future, may need to make use of an algorithm
44860c4e797SMatt Spinler     // to figure out which inventory objects actually hold these
44960c4e797SMatt Spinler     // interfaces in the case of non FRUs, or possibly another service
45060c4e797SMatt Spinler     // will provide this info.  Any missing interfaces will result
45160c4e797SMatt Spinler     // in exceptions being thrown.
45260c4e797SMatt Spinler 
4539b90e2a2SMatt Spinler     auto service = getService(inventoryPath, interface::viniRecordVPD);
45460c4e797SMatt Spinler 
455075c7923SPatrick Williams     auto properties =
456075c7923SPatrick Williams         getAllProperties(service, inventoryPath, interface::viniRecordVPD);
45760c4e797SMatt Spinler 
45860c4e797SMatt Spinler     auto value = std::get<std::vector<uint8_t>>(properties["FN"]);
45960c4e797SMatt Spinler     fruPartNumber = std::string{value.begin(), value.end()};
46060c4e797SMatt Spinler 
46160c4e797SMatt Spinler     value = std::get<std::vector<uint8_t>>(properties["CC"]);
46260c4e797SMatt Spinler     ccin = std::string{value.begin(), value.end()};
46360c4e797SMatt Spinler 
46460c4e797SMatt Spinler     value = std::get<std::vector<uint8_t>>(properties["SN"]);
46560c4e797SMatt Spinler     serialNumber = std::string{value.begin(), value.end()};
46660c4e797SMatt Spinler }
46760c4e797SMatt Spinler 
getLocationCode(const std::string & inventoryPath) const468*25291157SPatrick Williams std::string DataInterface::getLocationCode(
469*25291157SPatrick Williams     const std::string& inventoryPath) const
4709b90e2a2SMatt Spinler {
4719b90e2a2SMatt Spinler     auto service = getService(inventoryPath, interface::locCode);
4729b90e2a2SMatt Spinler 
4739b90e2a2SMatt Spinler     DBusValue locCode;
4749b90e2a2SMatt Spinler     getProperty(service, inventoryPath, interface::locCode, "LocationCode",
4759b90e2a2SMatt Spinler                 locCode);
4769b90e2a2SMatt Spinler 
4779b90e2a2SMatt Spinler     return std::get<std::string>(locCode);
4789b90e2a2SMatt Spinler }
4799b90e2a2SMatt Spinler 
addLocationCodePrefix(const std::string & locationCode)480*25291157SPatrick Williams std::string DataInterface::addLocationCodePrefix(
481*25291157SPatrick Williams     const std::string& locationCode)
4825fb24c11SMatt Spinler {
4835fb24c11SMatt Spinler     static const std::string locationCodePrefix{"Ufcs-"};
4845fb24c11SMatt Spinler 
4850e4d72edSMatt Spinler     // Technically there are 2 location code prefixes, Ufcs and Umts, so
4860e4d72edSMatt Spinler     // if it already starts with a U then don't need to do anything.
4870e4d72edSMatt Spinler     if (locationCode.front() != 'U')
4885fb24c11SMatt Spinler     {
4895fb24c11SMatt Spinler         return locationCodePrefix + locationCode;
4905fb24c11SMatt Spinler     }
4915fb24c11SMatt Spinler 
4925fb24c11SMatt Spinler     return locationCode;
4935fb24c11SMatt Spinler }
4945fb24c11SMatt Spinler 
expandLocationCode(const std::string & locationCode,uint16_t) const4955fb24c11SMatt Spinler std::string DataInterface::expandLocationCode(const std::string& locationCode,
496d26fa3e7SPatrick Williams                                               uint16_t /*node*/) const
4975fb24c11SMatt Spinler {
4980d92b528SMatt Spinler     // Location codes for connectors are the location code of the FRU they are
4990d92b528SMatt Spinler     // on, plus a '-Tx' segment.  Remove this last segment before expanding it
5000d92b528SMatt Spinler     // and then add it back in afterwards.  This way, the connector doesn't have
5010d92b528SMatt Spinler     // to be in the model just so that it can be expanded.
5020d92b528SMatt Spinler     auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
5030d92b528SMatt Spinler 
504fcf9a3f4SMatt Spinler     auto method =
505fcf9a3f4SMatt Spinler         _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
506fcf9a3f4SMatt Spinler                              interface::vpdManager, "GetExpandedLocationCode");
507fcf9a3f4SMatt Spinler 
5080d92b528SMatt Spinler     method.append(addLocationCodePrefix(baseLoc), static_cast<uint16_t>(0));
509fcf9a3f4SMatt Spinler 
51035a405b8SMatt Spinler     auto reply = _bus.call(method, dbusTimeout);
511fcf9a3f4SMatt Spinler 
512fcf9a3f4SMatt Spinler     std::string expandedLocationCode;
513fcf9a3f4SMatt Spinler     reply.read(expandedLocationCode);
514fcf9a3f4SMatt Spinler 
5150d92b528SMatt Spinler     if (!connectorLoc.empty())
5160d92b528SMatt Spinler     {
5170d92b528SMatt Spinler         expandedLocationCode += connectorLoc;
5180d92b528SMatt Spinler     }
5190d92b528SMatt Spinler 
520fcf9a3f4SMatt Spinler     return expandedLocationCode;
5215fb24c11SMatt Spinler }
5225fb24c11SMatt Spinler 
getInventoryFromLocCode(const std::string & locationCode,uint16_t node,bool expanded) const523075c7923SPatrick Williams std::vector<std::string> DataInterface::getInventoryFromLocCode(
524075c7923SPatrick Williams     const std::string& locationCode, uint16_t node, bool expanded) const
5255fb24c11SMatt Spinler {
5262f9225a4SMatt Spinler     std::string methodName = expanded ? "GetFRUsByExpandedLocationCode"
5272f9225a4SMatt Spinler                                       : "GetFRUsByUnexpandedLocationCode";
528fcf9a3f4SMatt Spinler 
5290d92b528SMatt Spinler     // Remove the connector segment, if present, so that this method call
5300d92b528SMatt Spinler     // returns an inventory path that getHWCalloutFields() can be used with.
5310d92b528SMatt Spinler     // (The serial number, etc, aren't stored on the connector in the
5320d92b528SMatt Spinler     // inventory, and may not even be modeled.)
5330d92b528SMatt Spinler     auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);
5340d92b528SMatt Spinler 
5352f9225a4SMatt Spinler     auto method =
5362f9225a4SMatt Spinler         _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
5372f9225a4SMatt Spinler                              interface::vpdManager, methodName.c_str());
5382f9225a4SMatt Spinler 
5392f9225a4SMatt Spinler     if (expanded)
5402f9225a4SMatt Spinler     {
5410d92b528SMatt Spinler         method.append(baseLoc);
5422f9225a4SMatt Spinler     }
5432f9225a4SMatt Spinler     else
5442f9225a4SMatt Spinler     {
5450d92b528SMatt Spinler         method.append(addLocationCodePrefix(baseLoc), node);
5462f9225a4SMatt Spinler     }
547fcf9a3f4SMatt Spinler 
54835a405b8SMatt Spinler     auto reply = _bus.call(method, dbusTimeout);
549fcf9a3f4SMatt Spinler 
550fcf9a3f4SMatt Spinler     std::vector<sdbusplus::message::object_path> entries;
551fcf9a3f4SMatt Spinler     reply.read(entries);
552fcf9a3f4SMatt Spinler 
553bad056beSMatt Spinler     std::vector<std::string> paths;
554fcf9a3f4SMatt Spinler 
555bad056beSMatt Spinler     // Note: The D-Bus method will fail if nothing found.
556fcf9a3f4SMatt Spinler     std::for_each(entries.begin(), entries.end(),
557bad056beSMatt Spinler                   [&paths](const auto& path) { paths.push_back(path); });
558fcf9a3f4SMatt Spinler 
559bad056beSMatt Spinler     return paths;
5605fb24c11SMatt Spinler }
5615fb24c11SMatt Spinler 
assertLEDGroup(const std::string & ledGroup,bool value) const56234a904cfSMatt Spinler void DataInterface::assertLEDGroup(const std::string& ledGroup,
56334a904cfSMatt Spinler                                    bool value) const
56434a904cfSMatt Spinler {
56534a904cfSMatt Spinler     DBusValue variant = value;
566075c7923SPatrick Williams     auto method =
567075c7923SPatrick Williams         _bus.new_method_call(service_name::ledGroupManager, ledGroup.c_str(),
56834a904cfSMatt Spinler                              interface::dbusProperty, "Set");
56934a904cfSMatt Spinler     method.append(interface::ledGroup, "Asserted", variant);
57035a405b8SMatt Spinler     _bus.call(method, dbusTimeout);
57134a904cfSMatt Spinler }
57234a904cfSMatt Spinler 
setFunctional(const std::string & objectPath,bool value) const573993168deSMatt Spinler void DataInterface::setFunctional(const std::string& objectPath,
574993168deSMatt Spinler                                   bool value) const
575993168deSMatt Spinler {
576412f50edSMatt Spinler     DBusPropertyMap prop{{"Functional", value}};
577412f50edSMatt Spinler     DBusInterfaceMap iface{{interface::operationalStatus, prop}};
578993168deSMatt Spinler 
579412f50edSMatt Spinler     // PIM takes a relative path like /system/chassis so remove
580412f50edSMatt Spinler     // /xyz/openbmc_project/inventory if present.
581412f50edSMatt Spinler     std::string path{objectPath};
582412f50edSMatt Spinler     if (path.starts_with(object_path::baseInv))
583412f50edSMatt Spinler     {
584412f50edSMatt Spinler         path = objectPath.substr(strlen(object_path::baseInv));
585412f50edSMatt Spinler     }
586412f50edSMatt Spinler     DBusObjectMap object{{path, iface}};
587993168deSMatt Spinler 
588412f50edSMatt Spinler     auto method = _bus.new_method_call(service_name::inventoryManager,
589412f50edSMatt Spinler                                        object_path::baseInv,
590412f50edSMatt Spinler                                        interface::inventoryManager, "Notify");
591412f50edSMatt Spinler     method.append(std::move(object));
59235a405b8SMatt Spinler     _bus.call(method, dbusTimeout);
593993168deSMatt Spinler }
594993168deSMatt Spinler 
59576198a2eSSumit Kumar using AssociationTuple = std::tuple<std::string, std::string, std::string>;
59676198a2eSSumit Kumar using AssociationsProperty = std::vector<AssociationTuple>;
59776198a2eSSumit Kumar 
setCriticalAssociation(const std::string & objectPath) const59876198a2eSSumit Kumar void DataInterface::setCriticalAssociation(const std::string& objectPath) const
59976198a2eSSumit Kumar {
60076198a2eSSumit Kumar     DBusValue getAssociationValue;
60176198a2eSSumit Kumar 
602027bf285SSumit Kumar     auto service = getService(objectPath, interface::associationDef);
60376198a2eSSumit Kumar 
604027bf285SSumit Kumar     getProperty(service, objectPath, interface::associationDef, "Associations",
60576198a2eSSumit Kumar                 getAssociationValue);
60676198a2eSSumit Kumar 
60776198a2eSSumit Kumar     auto association = std::get<AssociationsProperty>(getAssociationValue);
60876198a2eSSumit Kumar 
60976198a2eSSumit Kumar     AssociationTuple critAssociation{
61076198a2eSSumit Kumar         "health_rollup", "critical",
61176198a2eSSumit Kumar         "/xyz/openbmc_project/inventory/system/chassis"};
61276198a2eSSumit Kumar 
61376198a2eSSumit Kumar     if (std::find(association.begin(), association.end(), critAssociation) ==
61476198a2eSSumit Kumar         association.end())
61576198a2eSSumit Kumar     {
61676198a2eSSumit Kumar         association.push_back(critAssociation);
61776198a2eSSumit Kumar         DBusValue setAssociationValue = association;
61876198a2eSSumit Kumar 
61976198a2eSSumit Kumar         auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
62076198a2eSSumit Kumar                                            interface::dbusProperty, "Set");
62176198a2eSSumit Kumar 
622027bf285SSumit Kumar         method.append(interface::associationDef, "Associations",
62376198a2eSSumit Kumar                       setAssociationValue);
62435a405b8SMatt Spinler         _bus.call(method, dbusTimeout);
62576198a2eSSumit Kumar     }
62676198a2eSSumit Kumar }
62776198a2eSSumit Kumar 
getSystemNames() const6281ab6696fSMatt Spinler std::vector<std::string> DataInterface::getSystemNames() const
6291ab6696fSMatt Spinler {
6301ab6696fSMatt Spinler     DBusSubTree subtree;
6311ab6696fSMatt Spinler     DBusValue names;
6321ab6696fSMatt Spinler 
6331ab6696fSMatt Spinler     auto method = _bus.new_method_call(service_name::objectMapper,
6341ab6696fSMatt Spinler                                        object_path::objectMapper,
6351ab6696fSMatt Spinler                                        interface::objectMapper, "GetSubTree");
6361ab6696fSMatt Spinler     method.append(std::string{"/"}, 0,
6371ab6696fSMatt Spinler                   std::vector<std::string>{interface::compatible});
63835a405b8SMatt Spinler     auto reply = _bus.call(method, dbusTimeout);
6391ab6696fSMatt Spinler 
6401ab6696fSMatt Spinler     reply.read(subtree);
6411ab6696fSMatt Spinler     if (subtree.empty())
6421ab6696fSMatt Spinler     {
6431ab6696fSMatt Spinler         throw std::runtime_error("Compatible interface not on D-Bus");
6441ab6696fSMatt Spinler     }
6451ab6696fSMatt Spinler 
646bbc11ef9SMatt Spinler     for (const auto& [path, interfaceMap] : subtree)
647bbc11ef9SMatt Spinler     {
648bbc11ef9SMatt Spinler         auto iface = interfaceMap.find(service_name::entityManager);
649bbc11ef9SMatt Spinler         if (iface == interfaceMap.end())
650bbc11ef9SMatt Spinler         {
651bbc11ef9SMatt Spinler             continue;
652bbc11ef9SMatt Spinler         }
6531ab6696fSMatt Spinler 
654bbc11ef9SMatt Spinler         getProperty(iface->first, path, interface::compatible, "Names", names);
6551ab6696fSMatt Spinler 
6561ab6696fSMatt Spinler         return std::get<std::vector<std::string>>(names);
6571ab6696fSMatt Spinler     }
6581ab6696fSMatt Spinler 
659bbc11ef9SMatt Spinler     throw std::runtime_error("EM Compatible interface not on D-Bus");
660bbc11ef9SMatt Spinler }
661bbc11ef9SMatt Spinler 
getQuiesceOnError() const6623b8ed7f2SSumit Kumar bool DataInterface::getQuiesceOnError() const
6633b8ed7f2SSumit Kumar {
6643b8ed7f2SSumit Kumar     bool ret = false;
6653b8ed7f2SSumit Kumar 
6663b8ed7f2SSumit Kumar     try
6673b8ed7f2SSumit Kumar     {
668075c7923SPatrick Williams         auto service =
669075c7923SPatrick Williams             getService(object_path::logSetting, interface::logSetting);
6703b8ed7f2SSumit Kumar         if (!service.empty())
6713b8ed7f2SSumit Kumar         {
6723b8ed7f2SSumit Kumar             DBusValue value;
6733b8ed7f2SSumit Kumar             getProperty(service, object_path::logSetting, interface::logSetting,
6743b8ed7f2SSumit Kumar                         "QuiesceOnHwError", value);
6753b8ed7f2SSumit Kumar 
6763b8ed7f2SSumit Kumar             ret = std::get<bool>(value);
6773b8ed7f2SSumit Kumar         }
6783b8ed7f2SSumit Kumar     }
6793b8ed7f2SSumit Kumar     catch (const std::exception& e)
6803b8ed7f2SSumit Kumar     {
681a167a7d9SMatt Spinler         lg2::warning("Failed reading QuiesceOnHwError property from "
682a167a7d9SMatt Spinler                      "interface: {IFACE} exception: {ERROR}",
683a167a7d9SMatt Spinler                      "IFACE", interface::logSetting, "ERROR", e);
6843b8ed7f2SSumit Kumar     }
6853b8ed7f2SSumit Kumar 
6863b8ed7f2SSumit Kumar     return ret;
6873b8ed7f2SSumit Kumar }
6883b8ed7f2SSumit Kumar 
689ff35be3eSDeepa Karthikeyan #ifdef PEL_ENABLE_PHAL
createGuardRecord(const std::vector<uint8_t> & binPath,GardType eGardType,uint32_t plid) const690ecaa2fceSJayanth Othayoth void DataInterface::createGuardRecord(const std::vector<uint8_t>& binPath,
691ff35be3eSDeepa Karthikeyan                                       GardType eGardType, uint32_t plid) const
692ecaa2fceSJayanth Othayoth {
693ecaa2fceSJayanth Othayoth     try
694ecaa2fceSJayanth Othayoth     {
695c6396da5SDeepa Karthikeyan         libguard::libguard_init(false);
696ff35be3eSDeepa Karthikeyan         libguard::create(binPath, plid, eGardType);
697ecaa2fceSJayanth Othayoth     }
698ff35be3eSDeepa Karthikeyan     catch (libguard::exception::GuardException& e)
699ecaa2fceSJayanth Othayoth     {
700c6396da5SDeepa Karthikeyan         lg2::error("Exception in libguard {ERROR}", "ERROR", e);
701ecaa2fceSJayanth Othayoth     }
702ecaa2fceSJayanth Othayoth }
703ff35be3eSDeepa Karthikeyan #endif
7043e274432SSumit Kumar 
createProgressSRC(const uint64_t & priSRC,const std::vector<uint8_t> & srcStruct) const7053e274432SSumit Kumar void DataInterface::createProgressSRC(
7063e274432SSumit Kumar     const uint64_t& priSRC, const std::vector<uint8_t>& srcStruct) const
7073e274432SSumit Kumar {
7083e274432SSumit Kumar     DBusValue variant = std::make_tuple(priSRC, srcStruct);
7093e274432SSumit Kumar 
7103e274432SSumit Kumar     auto method = _bus.new_method_call(service_name::bootRawProgress,
711875b6c7bSVijay Lobo                                        object_path::bootRawProgress,
7123e274432SSumit Kumar                                        interface::dbusProperty, "Set");
7133e274432SSumit Kumar 
7143e274432SSumit Kumar     method.append(interface::bootRawProgress, "Value", variant);
7153e274432SSumit Kumar 
71635a405b8SMatt Spinler     _bus.call(method, dbusTimeout);
7173e274432SSumit Kumar }
718027bf285SSumit Kumar 
getLogIDWithHwIsolation() const719027bf285SSumit Kumar std::vector<uint32_t> DataInterface::getLogIDWithHwIsolation() const
720027bf285SSumit Kumar {
721027bf285SSumit Kumar     std::vector<std::string> association = {"xyz.openbmc_project.Association"};
722027bf285SSumit Kumar     std::string hwErrorLog = "/isolated_hw_errorlog";
723027bf285SSumit Kumar     std::string errorLog = "/error_log";
724027bf285SSumit Kumar     DBusPathList paths;
725027bf285SSumit Kumar     std::vector<uint32_t> ids;
726027bf285SSumit Kumar 
727027bf285SSumit Kumar     // Get all latest mapper associations
728027bf285SSumit Kumar     paths = getPaths(association);
729027bf285SSumit Kumar     for (auto& path : paths)
730027bf285SSumit Kumar     {
731027bf285SSumit Kumar         // Look for object path with hardware isolation entry if any
732027bf285SSumit Kumar         size_t pos = path.find(hwErrorLog);
733027bf285SSumit Kumar         if (pos != std::string::npos)
734027bf285SSumit Kumar         {
735027bf285SSumit Kumar             // Get the object path
736027bf285SSumit Kumar             std::string ph = path;
737027bf285SSumit Kumar             ph.erase(pos, hwErrorLog.length());
738027bf285SSumit Kumar             auto service = getService(ph, interface::hwIsolationEntry);
739027bf285SSumit Kumar             if (!service.empty())
740027bf285SSumit Kumar             {
741027bf285SSumit Kumar                 bool status;
742027bf285SSumit Kumar                 DBusValue value;
743027bf285SSumit Kumar 
744027bf285SSumit Kumar                 // Read the Resolved property from object path
745027bf285SSumit Kumar                 getProperty(service, ph, interface::hwIsolationEntry,
746027bf285SSumit Kumar                             "Resolved", value);
747027bf285SSumit Kumar 
748027bf285SSumit Kumar                 status = std::get<bool>(value);
749027bf285SSumit Kumar 
750027bf285SSumit Kumar                 // If the entry isn't resolved
751027bf285SSumit Kumar                 if (!status)
752027bf285SSumit Kumar                 {
753075c7923SPatrick Williams                     auto assocService =
754075c7923SPatrick Williams                         getService(path, interface::association);
75545796e82SMatt Spinler                     if (!assocService.empty())
756027bf285SSumit Kumar                     {
75745796e82SMatt Spinler                         DBusValue endpoints;
758027bf285SSumit Kumar 
759027bf285SSumit Kumar                         // Read Endpoints property
76045796e82SMatt Spinler                         getProperty(assocService, path, interface::association,
76145796e82SMatt Spinler                                     "endpoints", endpoints);
762027bf285SSumit Kumar 
763027bf285SSumit Kumar                         auto logPath =
76445796e82SMatt Spinler                             std::get<std::vector<std::string>>(endpoints);
765027bf285SSumit Kumar                         if (!logPath.empty())
766027bf285SSumit Kumar                         {
767027bf285SSumit Kumar                             // Get OpenBMC event log Id
768027bf285SSumit Kumar                             uint32_t id = stoi(logPath[0].substr(
769027bf285SSumit Kumar                                 logPath[0].find_last_of('/') + 1));
770027bf285SSumit Kumar                             ids.push_back(id);
771027bf285SSumit Kumar                         }
772027bf285SSumit Kumar                     }
773027bf285SSumit Kumar                 }
774027bf285SSumit Kumar             }
775027bf285SSumit Kumar         }
776027bf285SSumit Kumar 
777027bf285SSumit Kumar         // Look for object path with error_log entry if any
778027bf285SSumit Kumar         pos = path.find(errorLog);
779027bf285SSumit Kumar         if (pos != std::string::npos)
780027bf285SSumit Kumar         {
781027bf285SSumit Kumar             auto service = getService(path, interface::association);
782027bf285SSumit Kumar             if (!service.empty())
783027bf285SSumit Kumar             {
784027bf285SSumit Kumar                 DBusValue value;
785027bf285SSumit Kumar 
786027bf285SSumit Kumar                 // Read Endpoints property
787027bf285SSumit Kumar                 getProperty(service, path, interface::association, "endpoints",
788027bf285SSumit Kumar                             value);
789027bf285SSumit Kumar 
790027bf285SSumit Kumar                 auto logPath = std::get<std::vector<std::string>>(value);
791027bf285SSumit Kumar                 if (!logPath.empty())
792027bf285SSumit Kumar                 {
793027bf285SSumit Kumar                     // Get OpenBMC event log Id
794027bf285SSumit Kumar                     uint32_t id = stoi(
795027bf285SSumit Kumar                         logPath[0].substr(logPath[0].find_last_of('/') + 1));
796027bf285SSumit Kumar                     ids.push_back(id);
797027bf285SSumit Kumar                 }
798027bf285SSumit Kumar             }
799027bf285SSumit Kumar         }
800027bf285SSumit Kumar     }
801027bf285SSumit Kumar 
802027bf285SSumit Kumar     if (ids.size() > 1)
803027bf285SSumit Kumar     {
804027bf285SSumit Kumar         // remove duplicates to have only unique ids
805027bf285SSumit Kumar         std::sort(ids.begin(), ids.end());
806027bf285SSumit Kumar         ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
807027bf285SSumit Kumar     }
808027bf285SSumit Kumar     return ids;
809027bf285SSumit Kumar }
810875b6c7bSVijay Lobo 
getRawProgressSRC(void) const811875b6c7bSVijay Lobo std::vector<uint8_t> DataInterface::getRawProgressSRC(void) const
812875b6c7bSVijay Lobo {
813875b6c7bSVijay Lobo     using RawProgressProperty = std::tuple<uint64_t, std::vector<uint8_t>>;
814875b6c7bSVijay Lobo 
815875b6c7bSVijay Lobo     DBusValue value;
816875b6c7bSVijay Lobo     getProperty(service_name::bootRawProgress, object_path::bootRawProgress,
817875b6c7bSVijay Lobo                 interface::bootRawProgress, "Value", value);
818875b6c7bSVijay Lobo 
819875b6c7bSVijay Lobo     const auto& rawProgress = std::get<RawProgressProperty>(value);
820875b6c7bSVijay Lobo     return std::get<1>(rawProgress);
821875b6c7bSVijay Lobo }
822875b6c7bSVijay Lobo 
getDIProperty(const std::string & locationCode) const823*25291157SPatrick Williams std::optional<std::vector<uint8_t>> DataInterface::getDIProperty(
824*25291157SPatrick Williams     const std::string& locationCode) const
825d8ae618aSArya K Padman {
826d8ae618aSArya K Padman     std::vector<uint8_t> viniDI;
827d8ae618aSArya K Padman 
828d8ae618aSArya K Padman     try
829d8ae618aSArya K Padman     {
830d8ae618aSArya K Padman         // Note : The hardcoded value 0 should be changed when comes to
831d8ae618aSArya K Padman         // multinode system.
832d8ae618aSArya K Padman         auto objectPath = getInventoryFromLocCode(locationCode, 0, true);
833d8ae618aSArya K Padman 
834d8ae618aSArya K Padman         DBusValue value;
835d8ae618aSArya K Padman         getProperty(service_name::inventoryManager, objectPath[0],
836d8ae618aSArya K Padman                     interface::viniRecordVPD, "DI", value);
837d8ae618aSArya K Padman 
838d8ae618aSArya K Padman         viniDI = std::get<std::vector<uint8_t>>(value);
839d8ae618aSArya K Padman     }
840d8ae618aSArya K Padman     catch (const std::exception& e)
841d8ae618aSArya K Padman     {
842d8ae618aSArya K Padman         lg2::warning(
843d8ae618aSArya K Padman             "Failed reading DI property for the location code : {LOC_CODE} from "
844d8ae618aSArya K Padman             "interface: {IFACE} exception: {ERROR}",
845d8ae618aSArya K Padman             "LOC_CODE", locationCode, "IFACE", interface::viniRecordVPD,
846d8ae618aSArya K Padman             "ERROR", e);
847d8ae618aSArya K Padman         return std::nullopt;
848d8ae618aSArya K Padman     }
849d8ae618aSArya K Padman 
850d8ae618aSArya K Padman     return viniDI;
851d8ae618aSArya K Padman }
852d8ae618aSArya K Padman 
isDIMMLocCode(const std::string & locCode) const853*25291157SPatrick Williams std::optional<bool> DataInterfaceBase::isDIMMLocCode(
854*25291157SPatrick Williams     const std::string& locCode) const
855d8ae618aSArya K Padman {
856d8ae618aSArya K Padman     if (_locationCache.contains(locCode))
857d8ae618aSArya K Padman     {
858d8ae618aSArya K Padman         return _locationCache.at(locCode);
859d8ae618aSArya K Padman     }
860d8ae618aSArya K Padman     else
861d8ae618aSArya K Padman     {
862d8ae618aSArya K Padman         return std::nullopt;
863d8ae618aSArya K Padman     }
864d8ae618aSArya K Padman }
865d8ae618aSArya K Padman 
addDIMMLocCode(const std::string & locCode,bool isFRUDIMM)866d8ae618aSArya K Padman void DataInterfaceBase::addDIMMLocCode(const std::string& locCode,
867d8ae618aSArya K Padman                                        bool isFRUDIMM)
868d8ae618aSArya K Padman {
869d8ae618aSArya K Padman     _locationCache.insert({locCode, isFRUDIMM});
870d8ae618aSArya K Padman }
871d8ae618aSArya K Padman 
isDIMM(const std::string & locCode)872ced8ed77SArya K Padman bool DataInterfaceBase::isDIMM(const std::string& locCode)
873d8ae618aSArya K Padman {
874d8ae618aSArya K Padman     auto isDIMMType = isDIMMLocCode(locCode);
875d8ae618aSArya K Padman     if (isDIMMType.has_value())
876d8ae618aSArya K Padman     {
877d8ae618aSArya K Padman         return isDIMMType.value();
878d8ae618aSArya K Padman     }
879d8ae618aSArya K Padman #ifndef PEL_ENABLE_PHAL
880ced8ed77SArya K Padman     return false;
881d8ae618aSArya K Padman #else
882d8ae618aSArya K Padman     else
883d8ae618aSArya K Padman     {
884d8ae618aSArya K Padman         // Invoke pHAL API inorder to fetch the FRU Type
885d8ae618aSArya K Padman         auto fruType = openpower::phal::pdbg::getFRUType(locCode);
886ced8ed77SArya K Padman         bool isDIMMFRU{false};
887d8ae618aSArya K Padman         if (fruType.has_value())
888d8ae618aSArya K Padman         {
889d8ae618aSArya K Padman             if (fruType.value() == ENUM_ATTR_TYPE_DIMM)
890d8ae618aSArya K Padman             {
891d8ae618aSArya K Padman                 isDIMMFRU = true;
892d8ae618aSArya K Padman             }
893d8ae618aSArya K Padman             addDIMMLocCode(locCode, isDIMMFRU);
894ced8ed77SArya K Padman         }
895d8ae618aSArya K Padman         return isDIMMFRU;
896d8ae618aSArya K Padman     }
897d8ae618aSArya K Padman #endif
898d8ae618aSArya K Padman }
899d8ae618aSArya K Padman 
getAssociatedPaths(const DBusPath & associatedPath,const DBusPath & subtree,int32_t depth,const DBusInterfaceList & interfaces) const900d763db35Sharsh-agarwal1 DBusPathList DataInterface::getAssociatedPaths(
901d763db35Sharsh-agarwal1     const DBusPath& associatedPath, const DBusPath& subtree, int32_t depth,
902d763db35Sharsh-agarwal1     const DBusInterfaceList& interfaces) const
903d763db35Sharsh-agarwal1 {
904d763db35Sharsh-agarwal1     DBusPathList paths;
905d763db35Sharsh-agarwal1     try
906d763db35Sharsh-agarwal1     {
907d763db35Sharsh-agarwal1         auto method = _bus.new_method_call(
908d763db35Sharsh-agarwal1             service_name::objectMapper, object_path::objectMapper,
909d763db35Sharsh-agarwal1             interface::objectMapper, "GetAssociatedSubTreePaths");
910d763db35Sharsh-agarwal1         method.append(sdbusplus::message::object_path(associatedPath),
911d763db35Sharsh-agarwal1                       sdbusplus::message::object_path(subtree), depth,
912d763db35Sharsh-agarwal1                       interfaces);
913d763db35Sharsh-agarwal1 
914d763db35Sharsh-agarwal1         auto reply = _bus.call(method, dbusTimeout);
915d763db35Sharsh-agarwal1         reply.read(paths);
916d763db35Sharsh-agarwal1     }
917d763db35Sharsh-agarwal1     catch (const std::exception& e)
918d763db35Sharsh-agarwal1     {
919d763db35Sharsh-agarwal1         std::string ifaces(
920d763db35Sharsh-agarwal1             std::ranges::fold_left_first(
921d763db35Sharsh-agarwal1                 interfaces,
922d763db35Sharsh-agarwal1                 [](std::string ifaces, const std::string& iface) {
923d763db35Sharsh-agarwal1                     return ifaces + ", " + iface;
924d763db35Sharsh-agarwal1                 })
925d763db35Sharsh-agarwal1                 .value_or(""));
926d763db35Sharsh-agarwal1 
927d763db35Sharsh-agarwal1         lg2::error("Failed getting associated paths: {ERROR}. "
928d763db35Sharsh-agarwal1                    "AssociatedPath: {ASSOIC_PATH} Subtree: {SUBTREE} "
929d763db35Sharsh-agarwal1                    "Interfaces: {IFACES}",
930d763db35Sharsh-agarwal1                    "ERROR", e, "ASSOIC_PATH", associatedPath, "SUBTREE",
931d763db35Sharsh-agarwal1                    subtree, "IFACES", ifaces);
932d763db35Sharsh-agarwal1     }
933d763db35Sharsh-agarwal1     return paths;
934d763db35Sharsh-agarwal1 }
935d763db35Sharsh-agarwal1 
startFruPlugWatch()9365b423651SMatt Spinler void DataInterface::startFruPlugWatch()
9375b423651SMatt Spinler {
9385b423651SMatt Spinler     // Add a watch on inventory InterfacesAdded and then find all
9395b423651SMatt Spinler     // existing hotpluggable interfaces and add propertiesChanged
9405b423651SMatt Spinler     // watches on them.
9415b423651SMatt Spinler 
9425b423651SMatt Spinler     _invIaMatch = std::make_unique<sdbusplus::bus::match_t>(
9435b423651SMatt Spinler         _bus, match_rules::interfacesAdded(object_path::baseInv),
9445b423651SMatt Spinler         std::bind(&DataInterface::inventoryIfaceAdded, this,
9455b423651SMatt Spinler                   std::placeholders::_1));
9465b423651SMatt Spinler     try
9475b423651SMatt Spinler     {
9485b423651SMatt Spinler         auto paths = getPaths(hotplugInterfaces);
9495b423651SMatt Spinler 
9505b423651SMatt Spinler         _invPresentMatches.clear();
9515b423651SMatt Spinler 
9525b423651SMatt Spinler         std::for_each(paths.begin(), paths.end(),
9535b423651SMatt Spinler                       [this](const auto& path) { addHotplugWatch(path); });
9545b423651SMatt Spinler     }
9555b423651SMatt Spinler     catch (const sdbusplus::exception_t& e)
9565b423651SMatt Spinler     {
957a167a7d9SMatt Spinler         lg2::warning("Failed getting FRU paths to watch: {ERROR}", "ERROR", e);
9585b423651SMatt Spinler     }
9595b423651SMatt Spinler }
9605b423651SMatt Spinler 
addHotplugWatch(const std::string & path)9615b423651SMatt Spinler void DataInterface::addHotplugWatch(const std::string& path)
9625b423651SMatt Spinler {
9635b423651SMatt Spinler     if (!_invPresentMatches.contains(path))
9645b423651SMatt Spinler     {
9655b423651SMatt Spinler         _invPresentMatches.emplace(
9665b423651SMatt Spinler             path,
9675b423651SMatt Spinler             std::make_unique<sdbusplus::bus::match_t>(
9685b423651SMatt Spinler                 _bus, match_rules::propertiesChanged(path, interface::invItem),
9695b423651SMatt Spinler                 std::bind(&DataInterface::presenceChanged, this,
9705b423651SMatt Spinler                           std::placeholders::_1)));
9715b423651SMatt Spinler     }
9725b423651SMatt Spinler }
9735b423651SMatt Spinler 
inventoryIfaceAdded(sdbusplus::message_t & msg)9745b423651SMatt Spinler void DataInterface::inventoryIfaceAdded(sdbusplus::message_t& msg)
9755b423651SMatt Spinler {
9765b423651SMatt Spinler     sdbusplus::message::object_path path;
9775b423651SMatt Spinler     DBusInterfaceMap interfaces;
9785b423651SMatt Spinler 
9795b423651SMatt Spinler     msg.read(path, interfaces);
9805b423651SMatt Spinler 
9815b423651SMatt Spinler     // Check if any of the new interfaces are for hot pluggable FRUs.
9825b423651SMatt Spinler     if (std::find_if(interfaces.begin(), interfaces.end(),
9835b423651SMatt Spinler                      [](const auto& interfacePair) {
984075c7923SPatrick Williams                          return std::find(hotplugInterfaces.begin(),
985075c7923SPatrick Williams                                           hotplugInterfaces.end(),
986075c7923SPatrick Williams                                           interfacePair.first) !=
987075c7923SPatrick Williams                                 hotplugInterfaces.end();
9885b423651SMatt Spinler                      }) == interfaces.end())
9895b423651SMatt Spinler     {
9905b423651SMatt Spinler         return;
9915b423651SMatt Spinler     }
9925b423651SMatt Spinler 
9935b423651SMatt Spinler     addHotplugWatch(path.str);
9945b423651SMatt Spinler 
9955b423651SMatt Spinler     // If an Inventory.Item interface was also added, check presence now.
9965b423651SMatt Spinler 
9975b423651SMatt Spinler     // Notes:
9985b423651SMatt Spinler     // * This assumes the Inv.Item and Inv.Fan/PS are added together which
9995b423651SMatt Spinler     //   is currently the case.
10005b423651SMatt Spinler     // * If the code ever switches to something without a Present
10015b423651SMatt Spinler     //   property, then the IA signal itself would probably indicate presence.
10025b423651SMatt Spinler 
10035b423651SMatt Spinler     auto itemIt = interfaces.find(interface::invItem);
10045b423651SMatt Spinler     if (itemIt != interfaces.end())
10055b423651SMatt Spinler     {
10065b423651SMatt Spinler         notifyPresenceSubsribers(path.str, itemIt->second);
10075b423651SMatt Spinler     }
10085b423651SMatt Spinler }
10095b423651SMatt Spinler 
presenceChanged(sdbusplus::message_t & msg)10105b423651SMatt Spinler void DataInterface::presenceChanged(sdbusplus::message_t& msg)
10115b423651SMatt Spinler {
10125b423651SMatt Spinler     DBusInterface interface;
10135b423651SMatt Spinler     DBusPropertyMap properties;
10145b423651SMatt Spinler 
10155b423651SMatt Spinler     msg.read(interface, properties);
10165b423651SMatt Spinler     if (interface != interface::invItem)
10175b423651SMatt Spinler     {
10185b423651SMatt Spinler         return;
10195b423651SMatt Spinler     }
10205b423651SMatt Spinler 
10215b423651SMatt Spinler     std::string path = msg.get_path();
10225b423651SMatt Spinler     notifyPresenceSubsribers(path, properties);
10235b423651SMatt Spinler }
10245b423651SMatt Spinler 
notifyPresenceSubsribers(const std::string & path,const DBusPropertyMap & properties)10255b423651SMatt Spinler void DataInterface::notifyPresenceSubsribers(const std::string& path,
10265b423651SMatt Spinler                                              const DBusPropertyMap& properties)
10275b423651SMatt Spinler {
10285ee3605dSMatt Spinler     auto prop = properties.find("Present");
10295ee3605dSMatt Spinler     if ((prop == properties.end()) || (!std::get<bool>(prop->second)))
10305ee3605dSMatt Spinler     {
10315ee3605dSMatt Spinler         return;
10325ee3605dSMatt Spinler     }
10335ee3605dSMatt Spinler 
10345ee3605dSMatt Spinler     std::string locCode;
10355ee3605dSMatt Spinler 
10365b423651SMatt Spinler     try
10375b423651SMatt Spinler     {
103852ee3a4fSMatt Spinler         auto service = getService(path, interface::locCode);
103952ee3a4fSMatt Spinler 
104052ee3a4fSMatt Spinler         // If the hotplugged FRU is hosted by PLDM, then it is
104152ee3a4fSMatt Spinler         // in an IO expansion drawer and we don't care about it.
104252ee3a4fSMatt Spinler         if (service == service_name::pldm)
104352ee3a4fSMatt Spinler         {
104452ee3a4fSMatt Spinler             return;
104552ee3a4fSMatt Spinler         }
104652ee3a4fSMatt Spinler 
10475ee3605dSMatt Spinler         locCode = getLocationCode(path);
10485ee3605dSMatt Spinler     }
10495ee3605dSMatt Spinler     catch (const sdbusplus::exception_t& e)
10505b423651SMatt Spinler     {
1051a167a7d9SMatt Spinler         lg2::debug("Could not get location code for {PATH}: {ERROR}", "PATH",
1052a167a7d9SMatt Spinler                    path, "ERROR", e);
10535ee3605dSMatt Spinler         return;
10545ee3605dSMatt Spinler     }
10555ee3605dSMatt Spinler 
1056a167a7d9SMatt Spinler     lg2::debug("Detected FRU {PATH} ({LOC}) present ", "PATH", path, "LOC",
1057a167a7d9SMatt Spinler                locCode);
10585ee3605dSMatt Spinler 
10595b423651SMatt Spinler     // Tell the subscribers.
10605b423651SMatt Spinler     setFruPresent(locCode);
10615b423651SMatt Spinler }
1062afba316cSArya K Padman 
isPHALDevTreeExist() const1063afba316cSArya K Padman bool DataInterface::isPHALDevTreeExist() const
1064afba316cSArya K Padman {
1065afba316cSArya K Padman     try
1066afba316cSArya K Padman     {
1067afba316cSArya K Padman         if (std::filesystem::exists(PDBG_DTB_PATH))
1068afba316cSArya K Padman         {
1069afba316cSArya K Padman             return true;
1070afba316cSArya K Padman         }
1071afba316cSArya K Padman     }
1072afba316cSArya K Padman     catch (const std::exception& e)
1073afba316cSArya K Padman     {
1074afba316cSArya K Padman         lg2::error("Failed to check device tree {PHAL_DEVTREE_PATH} existence, "
1075afba316cSArya K Padman                    "{ERROR}",
1076afba316cSArya K Padman                    "PHAL_DEVTREE_PATH", PDBG_DTB_PATH, "ERROR", e);
1077afba316cSArya K Padman     }
1078afba316cSArya K Padman     return false;
1079afba316cSArya K Padman }
1080afba316cSArya K Padman 
10810b758fb0SArya K Padman #ifdef PEL_ENABLE_PHAL
initPHAL()1082afba316cSArya K Padman void DataInterface::initPHAL()
1083afba316cSArya K Padman {
1084afba316cSArya K Padman     if (setenv("PDBG_DTB", PDBG_DTB_PATH, 1))
1085afba316cSArya K Padman     {
1086afba316cSArya K Padman         // Log message and continue,
1087afba316cSArya K Padman         // This is to help continue creating PEL in raw format.
1088afba316cSArya K Padman         lg2::error("Failed to set PDBG_DTB: ({ERRNO})", "ERRNO",
1089afba316cSArya K Padman                    strerror(errno));
1090afba316cSArya K Padman     }
1091afba316cSArya K Padman 
1092afba316cSArya K Padman     if (!pdbg_targets_init(NULL))
1093afba316cSArya K Padman     {
1094afba316cSArya K Padman         lg2::error("pdbg_targets_init failed");
1095afba316cSArya K Padman         return;
1096afba316cSArya K Padman     }
1097afba316cSArya K Padman 
1098afba316cSArya K Padman     if (libekb_init())
1099afba316cSArya K Padman     {
1100afba316cSArya K Padman         lg2::error("libekb_init failed, skipping ffdc processing");
1101afba316cSArya K Padman         return;
1102afba316cSArya K Padman     }
1103afba316cSArya K Padman }
11040b758fb0SArya K Padman #endif
1105afba316cSArya K Padman 
subscribeToSystemdSignals()1106afba316cSArya K Padman void DataInterface::subscribeToSystemdSignals()
1107afba316cSArya K Padman {
1108afba316cSArya K Padman     try
1109afba316cSArya K Padman     {
1110afba316cSArya K Padman         auto method =
1111afba316cSArya K Padman             _bus.new_method_call(service_name::systemd, object_path::systemd,
1112afba316cSArya K Padman                                  interface::systemdMgr, "Subscribe");
1113afba316cSArya K Padman         _systemdSlot = method.call_async([this](sdbusplus::message_t&& msg) {
1114afba316cSArya K Padman             // Initializing with nullptr to indicate that it is not subscribed
1115afba316cSArya K Padman             // to any signal.
1116afba316cSArya K Padman             this->_systemdSlot = sdbusplus::slot_t(nullptr);
1117afba316cSArya K Padman             if (msg.is_method_error())
1118afba316cSArya K Padman             {
1119afba316cSArya K Padman                 auto* error = msg.get_error();
1120afba316cSArya K Padman                 lg2::error("Failed to subscribe JobRemoved systemd signal, "
1121ea001074SArya K Padman                            "errorName: {ERR_NAME}, errorMsg: {ERR_MSG} ",
11220b758fb0SArya K Padman                            "ERR_NAME", error->name, "ERR_MSG", error->message);
1123afba316cSArya K Padman                 return;
1124afba316cSArya K Padman             }
1125afba316cSArya K Padman 
1126afba316cSArya K Padman             namespace sdbusRule = sdbusplus::bus::match::rules;
1127afba316cSArya K Padman             this->_systemdMatch =
1128afba316cSArya K Padman                 std::make_unique<decltype(this->_systemdMatch)::element_type>(
1129afba316cSArya K Padman                     this->_bus,
1130afba316cSArya K Padman                     sdbusRule::type::signal() +
1131afba316cSArya K Padman                         sdbusRule::member("JobRemoved") +
1132afba316cSArya K Padman                         sdbusRule::path(object_path::systemd) +
1133afba316cSArya K Padman                         sdbusRule::interface(interface::systemdMgr),
1134afba316cSArya K Padman                     [this](sdbusplus::message_t& msg) {
1135afba316cSArya K Padman                         uint32_t jobID;
1136afba316cSArya K Padman                         sdbusplus::message::object_path jobObjPath;
1137afba316cSArya K Padman                         std::string jobUnitName, jobUnitResult;
1138afba316cSArya K Padman 
1139afba316cSArya K Padman                         msg.read(jobID, jobObjPath, jobUnitName, jobUnitResult);
1140afba316cSArya K Padman                         if ((jobUnitName ==
1141afba316cSArya K Padman                              "openpower-update-bios-attr-table.service") &&
1142afba316cSArya K Padman                             (jobUnitResult == "done"))
1143afba316cSArya K Padman                         {
1144ea001074SArya K Padman #ifdef PEL_ENABLE_PHAL
1145ea001074SArya K Padman                             this->initPHAL();
1146ea001074SArya K Padman #endif
1147ea001074SArya K Padman                             // Invoke unsubscribe method to stop monitoring for
1148ea001074SArya K Padman                             // JobRemoved signals.
1149afba316cSArya K Padman                             this->unsubscribeFromSystemdSignals();
1150afba316cSArya K Padman                         }
1151afba316cSArya K Padman                     });
1152afba316cSArya K Padman         });
1153afba316cSArya K Padman     }
1154afba316cSArya K Padman     catch (const sdbusplus::exception_t& e)
1155afba316cSArya K Padman     {
1156afba316cSArya K Padman         lg2::error(
1157afba316cSArya K Padman             "Exception occured while handling JobRemoved systemd signal, "
1158afba316cSArya K Padman             "exception: {ERROR}",
1159afba316cSArya K Padman             "ERROR", e);
1160afba316cSArya K Padman     }
1161afba316cSArya K Padman }
1162afba316cSArya K Padman 
unsubscribeFromSystemdSignals()1163afba316cSArya K Padman void DataInterface::unsubscribeFromSystemdSignals()
1164afba316cSArya K Padman {
1165afba316cSArya K Padman     try
1166afba316cSArya K Padman     {
1167afba316cSArya K Padman         auto method =
1168afba316cSArya K Padman             _bus.new_method_call(service_name::systemd, object_path::systemd,
1169afba316cSArya K Padman                                  interface::systemdMgr, "Unsubscribe");
1170afba316cSArya K Padman         _systemdSlot = method.call_async([this](sdbusplus::message_t&& msg) {
1171afba316cSArya K Padman             // Unsubscribing the _systemdSlot from the subscribed signal
1172afba316cSArya K Padman             this->_systemdSlot = sdbusplus::slot_t(nullptr);
1173afba316cSArya K Padman             if (msg.is_method_error())
1174afba316cSArya K Padman             {
1175afba316cSArya K Padman                 auto* error = msg.get_error();
1176afba316cSArya K Padman                 lg2::error(
1177afba316cSArya K Padman                     "Failed to unsubscribe from JobRemoved systemd signal, "
1178ea001074SArya K Padman                     "errorName: {ERR_NAME}, errorMsg: {ERR_MSG} ",
11790b758fb0SArya K Padman                     "ERR_NAME", error->name, "ERR_MSG", error->message);
1180afba316cSArya K Padman                 return;
1181afba316cSArya K Padman             }
1182ea001074SArya K Padman             // Reset _systemdMatch to avoid reception of further JobRemoved
1183ea001074SArya K Padman             // signals
1184ea001074SArya K Padman             this->_systemdMatch.reset();
1185afba316cSArya K Padman         });
1186afba316cSArya K Padman     }
1187afba316cSArya K Padman     catch (const sdbusplus::exception_t& e)
1188afba316cSArya K Padman     {
1189afba316cSArya K Padman         lg2::error(
1190afba316cSArya K Padman             "Exception occured while unsubscribing from JobRemoved systemd signal, "
1191afba316cSArya K Padman             "exception: {ERROR}",
1192afba316cSArya K Padman             "ERROR", e);
1193afba316cSArya K Padman     }
1194afba316cSArya K Padman }
1195afba316cSArya K Padman 
1196c8705e2bSMatt Spinler } // namespace pels
1197c8705e2bSMatt Spinler } // namespace openpower
1198