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>(¤tValVariant);
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