| Matt Spinler | 711d51d | 2019-11-06 09:36:51 -0600 | [diff] [blame] | 1 | /** | 
|  | 2 | * Copyright © 2019 IBM Corporation | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
| Matt Spinler | cad9c2b | 2019-12-02 15:42:01 -0600 | [diff] [blame] | 16 | #include "config.h" | 
|  | 17 |  | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 18 | #include "data_interface.hpp" | 
|  | 19 |  | 
| Matt Spinler | f61f292 | 2020-06-23 11:32:49 -0500 | [diff] [blame] | 20 | #include "util.hpp" | 
|  | 21 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 22 | #include <fmt/format.h> | 
|  | 23 |  | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 24 | #include <phosphor-logging/lg2.hpp> | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 25 | #include <xyz/openbmc_project/State/BMC/server.hpp> | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 26 | #include <xyz/openbmc_project/State/Boot/Progress/server.hpp> | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 27 |  | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 28 | #include <fstream> | 
|  | 29 | #include <iterator> | 
|  | 30 |  | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 31 | // Use a timeout of 10s for D-Bus calls so if there are | 
|  | 32 | // timeouts the callers of the PEL creation method won't | 
|  | 33 | // also timeout. | 
|  | 34 | constexpr auto dbusTimeout = 10000000; | 
|  | 35 |  | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 36 | namespace openpower | 
|  | 37 | { | 
|  | 38 | namespace pels | 
|  | 39 | { | 
|  | 40 |  | 
|  | 41 | namespace service_name | 
|  | 42 | { | 
|  | 43 | constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper"; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 44 | constexpr auto vpdManager = "com.ibm.VPD.Manager"; | 
| Matt Spinler | 34a904c | 2020-08-05 14:53:28 -0500 | [diff] [blame] | 45 | constexpr auto ledGroupManager = "xyz.openbmc_project.LED.GroupManager"; | 
| Sumit Kumar | 3b8ed7f | 2021-05-18 12:38:35 -0500 | [diff] [blame] | 46 | constexpr auto logSetting = "xyz.openbmc_project.Settings"; | 
| Jayanth Othayoth | ecaa2fc | 2021-11-05 02:02:52 -0500 | [diff] [blame] | 47 | constexpr auto hwIsolation = "org.open_power.HardwareIsolation"; | 
| Matt Spinler | 744d851 | 2022-06-08 08:25:47 -0500 | [diff] [blame] | 48 | constexpr auto biosConfigMgr = "xyz.openbmc_project.BIOSConfigManager"; | 
| Vijay Lobo | 875b6c7 | 2021-10-20 17:38:56 -0500 | [diff] [blame] | 49 | constexpr auto bootRawProgress = "xyz.openbmc_project.State.Boot.Raw"; | 
| Matt Spinler | 52ee3a4 | 2023-07-27 14:54:48 -0500 | [diff] [blame^] | 50 | constexpr auto pldm = "xyz.openbmc_project.PLDM"; | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 51 | } // namespace service_name | 
|  | 52 |  | 
|  | 53 | namespace object_path | 
|  | 54 | { | 
|  | 55 | constexpr auto objectMapper = "/xyz/openbmc_project/object_mapper"; | 
|  | 56 | constexpr auto systemInv = "/xyz/openbmc_project/inventory/system"; | 
| Matt Spinler | 6ea4d5f | 2020-05-20 13:31:07 -0500 | [diff] [blame] | 57 | constexpr auto chassisInv = "/xyz/openbmc_project/inventory/system/chassis"; | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 58 | constexpr auto motherBoardInv = | 
|  | 59 | "/xyz/openbmc_project/inventory/system/chassis/motherboard"; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 60 | constexpr auto baseInv = "/xyz/openbmc_project/inventory"; | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 61 | constexpr auto bmcState = "/xyz/openbmc_project/state/bmc0"; | 
|  | 62 | constexpr auto chassisState = "/xyz/openbmc_project/state/chassis0"; | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 63 | constexpr auto hostState = "/xyz/openbmc_project/state/host0"; | 
| Matt Spinler | b3f5186 | 2019-12-09 13:55:10 -0600 | [diff] [blame] | 64 | constexpr auto pldm = "/xyz/openbmc_project/pldm"; | 
| Matt Spinler | 9cf3cfd | 2020-02-03 14:41:55 -0600 | [diff] [blame] | 65 | constexpr auto enableHostPELs = | 
|  | 66 | "/xyz/openbmc_project/logging/send_event_logs_to_host"; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 67 | constexpr auto vpdManager = "/com/ibm/VPD/Manager"; | 
| Sumit Kumar | 3b8ed7f | 2021-05-18 12:38:35 -0500 | [diff] [blame] | 68 | constexpr auto logSetting = "/xyz/openbmc_project/logging/settings"; | 
| Jayanth Othayoth | ecaa2fc | 2021-11-05 02:02:52 -0500 | [diff] [blame] | 69 | constexpr auto hwIsolation = "/xyz/openbmc_project/hardware_isolation"; | 
| Matt Spinler | 744d851 | 2022-06-08 08:25:47 -0500 | [diff] [blame] | 70 | constexpr auto biosConfigMgr = "/xyz/openbmc_project/bios_config/manager"; | 
| Vijay Lobo | 875b6c7 | 2021-10-20 17:38:56 -0500 | [diff] [blame] | 71 | constexpr auto bootRawProgress = "/xyz/openbmc_project/state/boot/raw0"; | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 72 | } // namespace object_path | 
|  | 73 |  | 
|  | 74 | namespace interface | 
|  | 75 | { | 
|  | 76 | constexpr auto dbusProperty = "org.freedesktop.DBus.Properties"; | 
|  | 77 | constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper"; | 
|  | 78 | constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset"; | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 79 | constexpr auto bootProgress = "xyz.openbmc_project.State.Boot.Progress"; | 
| Matt Spinler | b3f5186 | 2019-12-09 13:55:10 -0600 | [diff] [blame] | 80 | constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester"; | 
| Matt Spinler | 9cf3cfd | 2020-02-03 14:41:55 -0600 | [diff] [blame] | 81 | constexpr auto enable = "xyz.openbmc_project.Object.Enable"; | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 82 | constexpr auto bmcState = "xyz.openbmc_project.State.BMC"; | 
|  | 83 | constexpr auto chassisState = "xyz.openbmc_project.State.Chassis"; | 
|  | 84 | constexpr auto hostState = "xyz.openbmc_project.State.Host"; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 85 | constexpr auto invMotherboard = | 
|  | 86 | "xyz.openbmc_project.Inventory.Item.Board.Motherboard"; | 
|  | 87 | constexpr auto viniRecordVPD = "com.ibm.ipzvpd.VINI"; | 
| Ben Tyner | e32b7e7 | 2021-05-18 12:38:40 -0500 | [diff] [blame] | 88 | constexpr auto vsbpRecordVPD = "com.ibm.ipzvpd.VSBP"; | 
| Matt Spinler | cc8b111 | 2021-12-15 09:30:35 -0600 | [diff] [blame] | 89 | constexpr auto locCode = "xyz.openbmc_project.Inventory.Decorator.LocationCode"; | 
| Matt Spinler | 1ab6696 | 2020-10-29 13:21:44 -0500 | [diff] [blame] | 90 | constexpr auto compatible = | 
|  | 91 | "xyz.openbmc_project.Configuration.IBMCompatibleSystem"; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 92 | constexpr auto vpdManager = "com.ibm.VPD.Manager"; | 
| Matt Spinler | 34a904c | 2020-08-05 14:53:28 -0500 | [diff] [blame] | 93 | constexpr auto ledGroup = "xyz.openbmc_project.Led.Group"; | 
| Matt Spinler | 993168d | 2021-04-07 16:05:03 -0500 | [diff] [blame] | 94 | constexpr auto operationalStatus = | 
|  | 95 | "xyz.openbmc_project.State.Decorator.OperationalStatus"; | 
| Sumit Kumar | 3b8ed7f | 2021-05-18 12:38:35 -0500 | [diff] [blame] | 96 | constexpr auto logSetting = "xyz.openbmc_project.Logging.Settings"; | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 97 | constexpr auto associationDef = "xyz.openbmc_project.Association.Definitions"; | 
| Sumit Kumar | 9d43a72 | 2021-08-24 09:46:19 -0500 | [diff] [blame] | 98 | constexpr auto dumpEntry = "xyz.openbmc_project.Dump.Entry"; | 
|  | 99 | constexpr auto dumpProgress = "xyz.openbmc_project.Common.Progress"; | 
| Jayanth Othayoth | ecaa2fc | 2021-11-05 02:02:52 -0500 | [diff] [blame] | 100 | constexpr auto hwIsolationCreate = "org.open_power.HardwareIsolation.Create"; | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 101 | constexpr auto hwIsolationEntry = "xyz.openbmc_project.HardwareIsolation.Entry"; | 
|  | 102 | constexpr auto association = "xyz.openbmc_project.Association"; | 
| Matt Spinler | 744d851 | 2022-06-08 08:25:47 -0500 | [diff] [blame] | 103 | constexpr auto biosConfigMgr = "xyz.openbmc_project.BIOSConfig.Manager"; | 
| Vijay Lobo | 875b6c7 | 2021-10-20 17:38:56 -0500 | [diff] [blame] | 104 | constexpr auto bootRawProgress = "xyz.openbmc_project.State.Boot.Raw"; | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 105 | constexpr auto invItem = "xyz.openbmc_project.Inventory.Item"; | 
|  | 106 | constexpr auto invFan = "xyz.openbmc_project.Inventory.Item.Fan"; | 
|  | 107 | constexpr auto invPowerSupply = | 
|  | 108 | "xyz.openbmc_project.Inventory.Item.PowerSupply"; | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 109 | } // namespace interface | 
|  | 110 |  | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 111 | using namespace sdbusplus::xyz::openbmc_project::State::Boot::server; | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 112 | using namespace sdbusplus::xyz::openbmc_project::State::server; | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 113 | namespace match_rules = sdbusplus::bus::match::rules; | 
|  | 114 |  | 
|  | 115 | const DBusInterfaceList hotplugInterfaces{interface::invFan, | 
|  | 116 | interface::invPowerSupply}; | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 117 |  | 
| Matt Spinler | 0d92b52 | 2021-06-16 13:28:17 -0600 | [diff] [blame] | 118 | std::pair<std::string, std::string> | 
|  | 119 | DataInterfaceBase::extractConnectorFromLocCode( | 
|  | 120 | const std::string& locationCode) | 
|  | 121 | { | 
|  | 122 | auto base = locationCode; | 
|  | 123 | std::string connector{}; | 
|  | 124 |  | 
|  | 125 | auto pos = base.find("-T"); | 
|  | 126 | if (pos != std::string::npos) | 
|  | 127 | { | 
|  | 128 | connector = base.substr(pos); | 
|  | 129 | base = base.substr(0, pos); | 
|  | 130 | } | 
|  | 131 |  | 
|  | 132 | return {base, connector}; | 
|  | 133 | } | 
|  | 134 |  | 
| Patrick Williams | 45e8352 | 2022-07-22 19:26:52 -0500 | [diff] [blame] | 135 | DataInterface::DataInterface(sdbusplus::bus_t& bus) : _bus(bus) | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 136 | { | 
| Matt Spinler | cad9c2b | 2019-12-02 15:42:01 -0600 | [diff] [blame] | 137 | readBMCFWVersion(); | 
|  | 138 | readServerFWVersion(); | 
| Matt Spinler | 677381b | 2020-01-23 10:04:29 -0600 | [diff] [blame] | 139 | readBMCFWVersionID(); | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 140 |  | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 141 | // Watch the BootProgress property | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 142 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 143 | bus, object_path::hostState, interface::bootProgress, "BootProgress", | 
|  | 144 | *this, [this](const auto& value) { | 
| Sumit Kumar | 2c36fdd | 2021-09-21 03:12:11 -0500 | [diff] [blame] | 145 | this->_bootState = std::get<std::string>(value); | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 146 | auto status = Progress::convertProgressStagesFromString( | 
|  | 147 | std::get<std::string>(value)); | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 148 |  | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 149 | if ((status == Progress::ProgressStages::SystemInitComplete) || | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 150 | (status == Progress::ProgressStages::OSRunning)) | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 151 | { | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 152 | setHostUp(true); | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 153 | } | 
|  | 154 | else | 
|  | 155 | { | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 156 | setHostUp(false); | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 157 | } | 
|  | 158 | })); | 
| Matt Spinler | 9cf3cfd | 2020-02-03 14:41:55 -0600 | [diff] [blame] | 159 |  | 
|  | 160 | // Watch the host PEL enable property | 
|  | 161 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
|  | 162 | bus, object_path::enableHostPELs, interface::enable, "Enabled", *this, | 
|  | 163 | [this](const auto& value) { | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 164 | if (std::get<bool>(value) != this->_sendPELsToHost) | 
|  | 165 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 166 | lg2::info("The send PELs to host setting changed to {VAL}", "VAL", | 
|  | 167 | std::get<bool>(value)); | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 168 | } | 
|  | 169 | this->_sendPELsToHost = std::get<bool>(value); | 
| Matt Spinler | 9cf3cfd | 2020-02-03 14:41:55 -0600 | [diff] [blame] | 170 | })); | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 171 |  | 
|  | 172 | // Watch the BMCState property | 
|  | 173 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
|  | 174 | bus, object_path::bmcState, interface::bmcState, "CurrentBMCState", | 
|  | 175 | *this, [this](const auto& value) { | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 176 | const auto& state = std::get<std::string>(value); | 
|  | 177 | this->_bmcState = state; | 
|  | 178 |  | 
|  | 179 | // Wait for BMC ready to start watching for | 
|  | 180 | // plugs so things calm down first. | 
|  | 181 | if (BMC::convertBMCStateFromString(state) == BMC::BMCState::Ready) | 
|  | 182 | { | 
|  | 183 | startFruPlugWatch(); | 
|  | 184 | } | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 185 | })); | 
|  | 186 |  | 
|  | 187 | // Watch the chassis current and requested power state properties | 
|  | 188 | _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>( | 
|  | 189 | bus, object_path::chassisState, interface::chassisState, *this, | 
|  | 190 | [this](const auto& properties) { | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 191 | auto state = properties.find("CurrentPowerState"); | 
|  | 192 | if (state != properties.end()) | 
|  | 193 | { | 
|  | 194 | this->_chassisState = std::get<std::string>(state->second); | 
|  | 195 | } | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 196 |  | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 197 | auto trans = properties.find("RequestedPowerTransition"); | 
|  | 198 | if (trans != properties.end()) | 
|  | 199 | { | 
|  | 200 | this->_chassisTransition = std::get<std::string>(trans->second); | 
|  | 201 | } | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 202 | })); | 
|  | 203 |  | 
|  | 204 | // Watch the CurrentHostState property | 
|  | 205 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
|  | 206 | bus, object_path::hostState, interface::hostState, "CurrentHostState", | 
|  | 207 | *this, [this](const auto& value) { | 
|  | 208 | this->_hostState = std::get<std::string>(value); | 
|  | 209 | })); | 
| Matt Spinler | 744d851 | 2022-06-08 08:25:47 -0500 | [diff] [blame] | 210 |  | 
|  | 211 | // Watch the BaseBIOSTable property for the hmc managed attribute | 
|  | 212 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
|  | 213 | bus, object_path::biosConfigMgr, interface::biosConfigMgr, | 
|  | 214 | "BaseBIOSTable", service_name::biosConfigMgr, *this, | 
|  | 215 | [this](const auto& value) { | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 216 | const auto& attributes = std::get<BiosAttributes>(value); | 
| Matt Spinler | 744d851 | 2022-06-08 08:25:47 -0500 | [diff] [blame] | 217 |  | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 218 | auto it = attributes.find("pvm_hmc_managed"); | 
|  | 219 | if (it != attributes.end()) | 
|  | 220 | { | 
|  | 221 | const auto& currentValVariant = std::get<5>(it->second); | 
|  | 222 | auto currentVal = std::get_if<std::string>(¤tValVariant); | 
|  | 223 | if (currentVal) | 
| Matt Spinler | 744d851 | 2022-06-08 08:25:47 -0500 | [diff] [blame] | 224 | { | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 225 | this->_hmcManaged = (*currentVal == "Enabled") ? true : false; | 
| Matt Spinler | 744d851 | 2022-06-08 08:25:47 -0500 | [diff] [blame] | 226 | } | 
| Patrick Williams | ac1ba3f | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 227 | } | 
| Matt Spinler | 744d851 | 2022-06-08 08:25:47 -0500 | [diff] [blame] | 228 | })); | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 229 | } | 
|  | 230 |  | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 231 | DBusPropertyMap | 
|  | 232 | DataInterface::getAllProperties(const std::string& service, | 
|  | 233 | const std::string& objectPath, | 
|  | 234 | const std::string& interface) const | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 235 | { | 
|  | 236 | DBusPropertyMap properties; | 
|  | 237 |  | 
|  | 238 | auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(), | 
|  | 239 | interface::dbusProperty, "GetAll"); | 
|  | 240 | method.append(interface); | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 241 | auto reply = _bus.call(method, dbusTimeout); | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 242 |  | 
|  | 243 | reply.read(properties); | 
|  | 244 |  | 
|  | 245 | return properties; | 
|  | 246 | } | 
|  | 247 |  | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 248 | void DataInterface::getProperty(const std::string& service, | 
|  | 249 | const std::string& objectPath, | 
|  | 250 | const std::string& interface, | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 251 | const std::string& property, | 
|  | 252 | DBusValue& value) const | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 253 | { | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 254 | auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(), | 
|  | 255 | interface::dbusProperty, "Get"); | 
|  | 256 | method.append(interface, property); | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 257 | auto reply = _bus.call(method, dbusTimeout); | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 258 |  | 
|  | 259 | reply.read(value); | 
|  | 260 | } | 
|  | 261 |  | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 262 | DBusPathList DataInterface::getPaths(const DBusInterfaceList& interfaces) const | 
|  | 263 | { | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 264 | auto method = _bus.new_method_call( | 
|  | 265 | service_name::objectMapper, object_path::objectMapper, | 
|  | 266 | interface::objectMapper, "GetSubTreePaths"); | 
|  | 267 |  | 
|  | 268 | method.append(std::string{"/"}, 0, interfaces); | 
|  | 269 |  | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 270 | auto reply = _bus.call(method, dbusTimeout); | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 271 |  | 
|  | 272 | DBusPathList paths; | 
|  | 273 | reply.read(paths); | 
|  | 274 |  | 
|  | 275 | return paths; | 
|  | 276 | } | 
|  | 277 |  | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 278 | DBusService DataInterface::getService(const std::string& objectPath, | 
| Matt Spinler | b3f5186 | 2019-12-09 13:55:10 -0600 | [diff] [blame] | 279 | const std::string& interface) const | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 280 | { | 
|  | 281 | auto method = _bus.new_method_call(service_name::objectMapper, | 
|  | 282 | object_path::objectMapper, | 
|  | 283 | interface::objectMapper, "GetObject"); | 
|  | 284 |  | 
|  | 285 | method.append(objectPath, std::vector<std::string>({interface})); | 
|  | 286 |  | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 287 | auto reply = _bus.call(method, dbusTimeout); | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 288 |  | 
|  | 289 | std::map<DBusService, DBusInterfaceList> response; | 
|  | 290 | reply.read(response); | 
|  | 291 |  | 
|  | 292 | if (!response.empty()) | 
|  | 293 | { | 
|  | 294 | return response.begin()->first; | 
|  | 295 | } | 
|  | 296 |  | 
|  | 297 | return std::string{}; | 
|  | 298 | } | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 299 |  | 
| Matt Spinler | 677381b | 2020-01-23 10:04:29 -0600 | [diff] [blame] | 300 | void DataInterface::readBMCFWVersion() | 
|  | 301 | { | 
| Matt Spinler | f61f292 | 2020-06-23 11:32:49 -0500 | [diff] [blame] | 302 | _bmcFWVersion = | 
|  | 303 | phosphor::logging::util::getOSReleaseValue("VERSION").value_or(""); | 
| Matt Spinler | cad9c2b | 2019-12-02 15:42:01 -0600 | [diff] [blame] | 304 | } | 
|  | 305 |  | 
|  | 306 | void DataInterface::readServerFWVersion() | 
|  | 307 | { | 
| Sumit Kumar | cad1620 | 2021-05-13 04:06:15 -0500 | [diff] [blame] | 308 | auto value = | 
|  | 309 | phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or(""); | 
|  | 310 | if ((value != "") && (value.find_last_of(')') != std::string::npos)) | 
|  | 311 | { | 
|  | 312 | std::size_t pos = value.find_first_of('(') + 1; | 
|  | 313 | _serverFWVersion = value.substr(pos, value.find_last_of(')') - pos); | 
|  | 314 | } | 
| Matt Spinler | cad9c2b | 2019-12-02 15:42:01 -0600 | [diff] [blame] | 315 | } | 
|  | 316 |  | 
| Matt Spinler | 677381b | 2020-01-23 10:04:29 -0600 | [diff] [blame] | 317 | void DataInterface::readBMCFWVersionID() | 
|  | 318 | { | 
| Matt Spinler | f61f292 | 2020-06-23 11:32:49 -0500 | [diff] [blame] | 319 | _bmcFWVersionID = | 
|  | 320 | phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or(""); | 
| Matt Spinler | 677381b | 2020-01-23 10:04:29 -0600 | [diff] [blame] | 321 | } | 
|  | 322 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 323 | std::string DataInterface::getMachineTypeModel() const | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 324 | { | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 325 | std::string model; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 326 | try | 
|  | 327 | { | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 328 | auto service = getService(object_path::systemInv, interface::invAsset); | 
|  | 329 | if (!service.empty()) | 
|  | 330 | { | 
|  | 331 | DBusValue value; | 
|  | 332 | getProperty(service, object_path::systemInv, interface::invAsset, | 
|  | 333 | "Model", value); | 
|  | 334 |  | 
|  | 335 | model = std::get<std::string>(value); | 
|  | 336 | } | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 337 | } | 
|  | 338 | catch (const std::exception& e) | 
|  | 339 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 340 | lg2::warning("Failed reading Model property from " | 
|  | 341 | "interface: {IFACE} exception: {ERROR}", | 
|  | 342 | "IFACE", interface::invAsset, "ERROR", e); | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 343 | } | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 344 |  | 
|  | 345 | return model; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 346 | } | 
|  | 347 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 348 | std::string DataInterface::getMachineSerialNumber() const | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 349 | { | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 350 | std::string sn; | 
|  | 351 | try | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 352 | { | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 353 | auto service = getService(object_path::systemInv, interface::invAsset); | 
|  | 354 | if (!service.empty()) | 
|  | 355 | { | 
|  | 356 | DBusValue value; | 
|  | 357 | getProperty(service, object_path::systemInv, interface::invAsset, | 
|  | 358 | "SerialNumber", value); | 
|  | 359 |  | 
|  | 360 | sn = std::get<std::string>(value); | 
|  | 361 | } | 
|  | 362 | } | 
|  | 363 | catch (const std::exception& e) | 
|  | 364 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 365 | lg2::warning("Failed reading SerialNumber property from " | 
|  | 366 | "interface: {IFACE} exception: {ERROR}", | 
|  | 367 | "IFACE", interface::invAsset, "ERROR", e); | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 368 | } | 
|  | 369 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 370 | return sn; | 
|  | 371 | } | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 372 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 373 | std::string DataInterface::getMotherboardCCIN() const | 
|  | 374 | { | 
|  | 375 | std::string ccin; | 
|  | 376 |  | 
|  | 377 | try | 
|  | 378 | { | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 379 | auto service = getService(object_path::motherBoardInv, | 
|  | 380 | interface::viniRecordVPD); | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 381 | if (!service.empty()) | 
|  | 382 | { | 
|  | 383 | DBusValue value; | 
|  | 384 | getProperty(service, object_path::motherBoardInv, | 
|  | 385 | interface::viniRecordVPD, "CC", value); | 
|  | 386 |  | 
|  | 387 | auto cc = std::get<std::vector<uint8_t>>(value); | 
|  | 388 | ccin = std::string{cc.begin(), cc.end()}; | 
|  | 389 | } | 
|  | 390 | } | 
|  | 391 | catch (const std::exception& e) | 
|  | 392 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 393 | lg2::warning("Failed reading Motherboard CCIN property from " | 
|  | 394 | "interface: {IFACE} exception: {ERROR}", | 
|  | 395 | "IFACE", interface::viniRecordVPD, "ERROR", e); | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 396 | } | 
|  | 397 |  | 
|  | 398 | return ccin; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 399 | } | 
|  | 400 |  | 
| Ben Tyner | e32b7e7 | 2021-05-18 12:38:40 -0500 | [diff] [blame] | 401 | std::vector<uint8_t> DataInterface::getSystemIMKeyword() const | 
|  | 402 | { | 
|  | 403 | std::vector<uint8_t> systemIM; | 
|  | 404 |  | 
|  | 405 | try | 
|  | 406 | { | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 407 | auto service = getService(object_path::motherBoardInv, | 
|  | 408 | interface::vsbpRecordVPD); | 
| Ben Tyner | e32b7e7 | 2021-05-18 12:38:40 -0500 | [diff] [blame] | 409 | if (!service.empty()) | 
|  | 410 | { | 
|  | 411 | DBusValue value; | 
|  | 412 | getProperty(service, object_path::motherBoardInv, | 
|  | 413 | interface::vsbpRecordVPD, "IM", value); | 
|  | 414 |  | 
|  | 415 | systemIM = std::get<std::vector<uint8_t>>(value); | 
|  | 416 | } | 
|  | 417 | } | 
|  | 418 | catch (const std::exception& e) | 
|  | 419 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 420 | lg2::warning("Failed reading System IM property from " | 
|  | 421 | "interface: {IFACE} exception: {ERROR}", | 
|  | 422 | "IFACE", interface::vsbpRecordVPD, "ERROR", e); | 
| Ben Tyner | e32b7e7 | 2021-05-18 12:38:40 -0500 | [diff] [blame] | 423 | } | 
|  | 424 |  | 
|  | 425 | return systemIM; | 
|  | 426 | } | 
|  | 427 |  | 
| Matt Spinler | 60c4e79 | 2020-03-13 13:45:36 -0500 | [diff] [blame] | 428 | void DataInterface::getHWCalloutFields(const std::string& inventoryPath, | 
| Matt Spinler | 60c4e79 | 2020-03-13 13:45:36 -0500 | [diff] [blame] | 429 | std::string& fruPartNumber, | 
|  | 430 | std::string& ccin, | 
|  | 431 | std::string& serialNumber) const | 
|  | 432 | { | 
|  | 433 | // For now, attempt to get all of the properties directly on the path | 
|  | 434 | // passed in.  In the future, may need to make use of an algorithm | 
|  | 435 | // to figure out which inventory objects actually hold these | 
|  | 436 | // interfaces in the case of non FRUs, or possibly another service | 
|  | 437 | // will provide this info.  Any missing interfaces will result | 
|  | 438 | // in exceptions being thrown. | 
|  | 439 |  | 
| Matt Spinler | 9b90e2a | 2020-04-14 10:59:04 -0500 | [diff] [blame] | 440 | auto service = getService(inventoryPath, interface::viniRecordVPD); | 
| Matt Spinler | 60c4e79 | 2020-03-13 13:45:36 -0500 | [diff] [blame] | 441 |  | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 442 | auto properties = getAllProperties(service, inventoryPath, | 
|  | 443 | interface::viniRecordVPD); | 
| Matt Spinler | 60c4e79 | 2020-03-13 13:45:36 -0500 | [diff] [blame] | 444 |  | 
|  | 445 | auto value = std::get<std::vector<uint8_t>>(properties["FN"]); | 
|  | 446 | fruPartNumber = std::string{value.begin(), value.end()}; | 
|  | 447 |  | 
|  | 448 | value = std::get<std::vector<uint8_t>>(properties["CC"]); | 
|  | 449 | ccin = std::string{value.begin(), value.end()}; | 
|  | 450 |  | 
|  | 451 | value = std::get<std::vector<uint8_t>>(properties["SN"]); | 
|  | 452 | serialNumber = std::string{value.begin(), value.end()}; | 
|  | 453 | } | 
|  | 454 |  | 
| Matt Spinler | 9b90e2a | 2020-04-14 10:59:04 -0500 | [diff] [blame] | 455 | std::string | 
|  | 456 | DataInterface::getLocationCode(const std::string& inventoryPath) const | 
|  | 457 | { | 
|  | 458 | auto service = getService(inventoryPath, interface::locCode); | 
|  | 459 |  | 
|  | 460 | DBusValue locCode; | 
|  | 461 | getProperty(service, inventoryPath, interface::locCode, "LocationCode", | 
|  | 462 | locCode); | 
|  | 463 |  | 
|  | 464 | return std::get<std::string>(locCode); | 
|  | 465 | } | 
|  | 466 |  | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 467 | std::string | 
|  | 468 | DataInterface::addLocationCodePrefix(const std::string& locationCode) | 
|  | 469 | { | 
|  | 470 | static const std::string locationCodePrefix{"Ufcs-"}; | 
|  | 471 |  | 
| Matt Spinler | 0e4d72e | 2020-08-05 12:36:53 -0500 | [diff] [blame] | 472 | // Technically there are 2 location code prefixes, Ufcs and Umts, so | 
|  | 473 | // if it already starts with a U then don't need to do anything. | 
|  | 474 | if (locationCode.front() != 'U') | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 475 | { | 
|  | 476 | return locationCodePrefix + locationCode; | 
|  | 477 | } | 
|  | 478 |  | 
|  | 479 | return locationCode; | 
|  | 480 | } | 
|  | 481 |  | 
|  | 482 | std::string DataInterface::expandLocationCode(const std::string& locationCode, | 
| Patrick Williams | d26fa3e | 2021-04-21 15:22:23 -0500 | [diff] [blame] | 483 | uint16_t /*node*/) const | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 484 | { | 
| Matt Spinler | 0d92b52 | 2021-06-16 13:28:17 -0600 | [diff] [blame] | 485 | // Location codes for connectors are the location code of the FRU they are | 
|  | 486 | // on, plus a '-Tx' segment.  Remove this last segment before expanding it | 
|  | 487 | // and then add it back in afterwards.  This way, the connector doesn't have | 
|  | 488 | // to be in the model just so that it can be expanded. | 
|  | 489 | auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode); | 
|  | 490 |  | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 491 | auto method = | 
|  | 492 | _bus.new_method_call(service_name::vpdManager, object_path::vpdManager, | 
|  | 493 | interface::vpdManager, "GetExpandedLocationCode"); | 
|  | 494 |  | 
| Matt Spinler | 0d92b52 | 2021-06-16 13:28:17 -0600 | [diff] [blame] | 495 | method.append(addLocationCodePrefix(baseLoc), static_cast<uint16_t>(0)); | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 496 |  | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 497 | auto reply = _bus.call(method, dbusTimeout); | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 498 |  | 
|  | 499 | std::string expandedLocationCode; | 
|  | 500 | reply.read(expandedLocationCode); | 
|  | 501 |  | 
| Matt Spinler | 0d92b52 | 2021-06-16 13:28:17 -0600 | [diff] [blame] | 502 | if (!connectorLoc.empty()) | 
|  | 503 | { | 
|  | 504 | expandedLocationCode += connectorLoc; | 
|  | 505 | } | 
|  | 506 |  | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 507 | return expandedLocationCode; | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 508 | } | 
|  | 509 |  | 
| Matt Spinler | bad056b | 2023-01-25 14:16:57 -0600 | [diff] [blame] | 510 | std::vector<std::string> | 
| Matt Spinler | 2f9225a | 2020-08-05 12:58:49 -0500 | [diff] [blame] | 511 | DataInterface::getInventoryFromLocCode(const std::string& locationCode, | 
|  | 512 | uint16_t node, bool expanded) const | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 513 | { | 
| Matt Spinler | 2f9225a | 2020-08-05 12:58:49 -0500 | [diff] [blame] | 514 | std::string methodName = expanded ? "GetFRUsByExpandedLocationCode" | 
|  | 515 | : "GetFRUsByUnexpandedLocationCode"; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 516 |  | 
| Matt Spinler | 0d92b52 | 2021-06-16 13:28:17 -0600 | [diff] [blame] | 517 | // Remove the connector segment, if present, so that this method call | 
|  | 518 | // returns an inventory path that getHWCalloutFields() can be used with. | 
|  | 519 | // (The serial number, etc, aren't stored on the connector in the | 
|  | 520 | // inventory, and may not even be modeled.) | 
|  | 521 | auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode); | 
|  | 522 |  | 
| Matt Spinler | 2f9225a | 2020-08-05 12:58:49 -0500 | [diff] [blame] | 523 | auto method = | 
|  | 524 | _bus.new_method_call(service_name::vpdManager, object_path::vpdManager, | 
|  | 525 | interface::vpdManager, methodName.c_str()); | 
|  | 526 |  | 
|  | 527 | if (expanded) | 
|  | 528 | { | 
| Matt Spinler | 0d92b52 | 2021-06-16 13:28:17 -0600 | [diff] [blame] | 529 | method.append(baseLoc); | 
| Matt Spinler | 2f9225a | 2020-08-05 12:58:49 -0500 | [diff] [blame] | 530 | } | 
|  | 531 | else | 
|  | 532 | { | 
| Matt Spinler | 0d92b52 | 2021-06-16 13:28:17 -0600 | [diff] [blame] | 533 | method.append(addLocationCodePrefix(baseLoc), node); | 
| Matt Spinler | 2f9225a | 2020-08-05 12:58:49 -0500 | [diff] [blame] | 534 | } | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 535 |  | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 536 | auto reply = _bus.call(method, dbusTimeout); | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 537 |  | 
|  | 538 | std::vector<sdbusplus::message::object_path> entries; | 
|  | 539 | reply.read(entries); | 
|  | 540 |  | 
| Matt Spinler | bad056b | 2023-01-25 14:16:57 -0600 | [diff] [blame] | 541 | std::vector<std::string> paths; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 542 |  | 
| Matt Spinler | bad056b | 2023-01-25 14:16:57 -0600 | [diff] [blame] | 543 | // Note: The D-Bus method will fail if nothing found. | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 544 | std::for_each(entries.begin(), entries.end(), | 
| Matt Spinler | bad056b | 2023-01-25 14:16:57 -0600 | [diff] [blame] | 545 | [&paths](const auto& path) { paths.push_back(path); }); | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 546 |  | 
| Matt Spinler | bad056b | 2023-01-25 14:16:57 -0600 | [diff] [blame] | 547 | return paths; | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 548 | } | 
|  | 549 |  | 
| Matt Spinler | 34a904c | 2020-08-05 14:53:28 -0500 | [diff] [blame] | 550 | void DataInterface::assertLEDGroup(const std::string& ledGroup, | 
|  | 551 | bool value) const | 
|  | 552 | { | 
|  | 553 | DBusValue variant = value; | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 554 | auto method = _bus.new_method_call(service_name::ledGroupManager, | 
|  | 555 | ledGroup.c_str(), | 
|  | 556 | interface::dbusProperty, "Set"); | 
| Matt Spinler | 34a904c | 2020-08-05 14:53:28 -0500 | [diff] [blame] | 557 | method.append(interface::ledGroup, "Asserted", variant); | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 558 | _bus.call(method, dbusTimeout); | 
| Matt Spinler | 34a904c | 2020-08-05 14:53:28 -0500 | [diff] [blame] | 559 | } | 
|  | 560 |  | 
| Matt Spinler | 993168d | 2021-04-07 16:05:03 -0500 | [diff] [blame] | 561 | void DataInterface::setFunctional(const std::string& objectPath, | 
|  | 562 | bool value) const | 
|  | 563 | { | 
|  | 564 | DBusValue variant = value; | 
|  | 565 | auto service = getService(objectPath, interface::operationalStatus); | 
|  | 566 |  | 
|  | 567 | auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(), | 
|  | 568 | interface::dbusProperty, "Set"); | 
|  | 569 |  | 
|  | 570 | method.append(interface::operationalStatus, "Functional", variant); | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 571 | _bus.call(method, dbusTimeout); | 
| Matt Spinler | 993168d | 2021-04-07 16:05:03 -0500 | [diff] [blame] | 572 | } | 
|  | 573 |  | 
| Sumit Kumar | 76198a2 | 2021-07-15 05:59:57 -0500 | [diff] [blame] | 574 | using AssociationTuple = std::tuple<std::string, std::string, std::string>; | 
|  | 575 | using AssociationsProperty = std::vector<AssociationTuple>; | 
|  | 576 |  | 
|  | 577 | void DataInterface::setCriticalAssociation(const std::string& objectPath) const | 
|  | 578 | { | 
|  | 579 | DBusValue getAssociationValue; | 
|  | 580 |  | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 581 | auto service = getService(objectPath, interface::associationDef); | 
| Sumit Kumar | 76198a2 | 2021-07-15 05:59:57 -0500 | [diff] [blame] | 582 |  | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 583 | getProperty(service, objectPath, interface::associationDef, "Associations", | 
| Sumit Kumar | 76198a2 | 2021-07-15 05:59:57 -0500 | [diff] [blame] | 584 | getAssociationValue); | 
|  | 585 |  | 
|  | 586 | auto association = std::get<AssociationsProperty>(getAssociationValue); | 
|  | 587 |  | 
|  | 588 | AssociationTuple critAssociation{ | 
|  | 589 | "health_rollup", "critical", | 
|  | 590 | "/xyz/openbmc_project/inventory/system/chassis"}; | 
|  | 591 |  | 
|  | 592 | if (std::find(association.begin(), association.end(), critAssociation) == | 
|  | 593 | association.end()) | 
|  | 594 | { | 
|  | 595 | association.push_back(critAssociation); | 
|  | 596 | DBusValue setAssociationValue = association; | 
|  | 597 |  | 
|  | 598 | auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(), | 
|  | 599 | interface::dbusProperty, "Set"); | 
|  | 600 |  | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 601 | method.append(interface::associationDef, "Associations", | 
| Sumit Kumar | 76198a2 | 2021-07-15 05:59:57 -0500 | [diff] [blame] | 602 | setAssociationValue); | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 603 | _bus.call(method, dbusTimeout); | 
| Sumit Kumar | 76198a2 | 2021-07-15 05:59:57 -0500 | [diff] [blame] | 604 | } | 
|  | 605 | } | 
|  | 606 |  | 
| Matt Spinler | 1ab6696 | 2020-10-29 13:21:44 -0500 | [diff] [blame] | 607 | std::vector<std::string> DataInterface::getSystemNames() const | 
|  | 608 | { | 
|  | 609 | DBusSubTree subtree; | 
|  | 610 | DBusValue names; | 
|  | 611 |  | 
|  | 612 | auto method = _bus.new_method_call(service_name::objectMapper, | 
|  | 613 | object_path::objectMapper, | 
|  | 614 | interface::objectMapper, "GetSubTree"); | 
|  | 615 | method.append(std::string{"/"}, 0, | 
|  | 616 | std::vector<std::string>{interface::compatible}); | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 617 | auto reply = _bus.call(method, dbusTimeout); | 
| Matt Spinler | 1ab6696 | 2020-10-29 13:21:44 -0500 | [diff] [blame] | 618 |  | 
|  | 619 | reply.read(subtree); | 
|  | 620 | if (subtree.empty()) | 
|  | 621 | { | 
|  | 622 | throw std::runtime_error("Compatible interface not on D-Bus"); | 
|  | 623 | } | 
|  | 624 |  | 
|  | 625 | const auto& object = *(subtree.begin()); | 
|  | 626 | const auto& path = object.first; | 
|  | 627 | const auto& service = object.second.begin()->first; | 
|  | 628 |  | 
|  | 629 | getProperty(service, path, interface::compatible, "Names", names); | 
|  | 630 |  | 
|  | 631 | return std::get<std::vector<std::string>>(names); | 
|  | 632 | } | 
|  | 633 |  | 
| Sumit Kumar | 3b8ed7f | 2021-05-18 12:38:35 -0500 | [diff] [blame] | 634 | bool DataInterface::getQuiesceOnError() const | 
|  | 635 | { | 
|  | 636 | bool ret = false; | 
|  | 637 |  | 
|  | 638 | try | 
|  | 639 | { | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 640 | auto service = getService(object_path::logSetting, | 
|  | 641 | interface::logSetting); | 
| Sumit Kumar | 3b8ed7f | 2021-05-18 12:38:35 -0500 | [diff] [blame] | 642 | if (!service.empty()) | 
|  | 643 | { | 
|  | 644 | DBusValue value; | 
|  | 645 | getProperty(service, object_path::logSetting, interface::logSetting, | 
|  | 646 | "QuiesceOnHwError", value); | 
|  | 647 |  | 
|  | 648 | ret = std::get<bool>(value); | 
|  | 649 | } | 
|  | 650 | } | 
|  | 651 | catch (const std::exception& e) | 
|  | 652 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 653 | lg2::warning("Failed reading QuiesceOnHwError property from " | 
|  | 654 | "interface: {IFACE} exception: {ERROR}", | 
|  | 655 | "IFACE", interface::logSetting, "ERROR", e); | 
| Sumit Kumar | 3b8ed7f | 2021-05-18 12:38:35 -0500 | [diff] [blame] | 656 | } | 
|  | 657 |  | 
|  | 658 | return ret; | 
|  | 659 | } | 
|  | 660 |  | 
| Sumit Kumar | 9d43a72 | 2021-08-24 09:46:19 -0500 | [diff] [blame] | 661 | std::vector<bool> | 
|  | 662 | DataInterface::checkDumpStatus(const std::vector<std::string>& type) const | 
|  | 663 | { | 
|  | 664 | DBusSubTree subtree; | 
|  | 665 | std::vector<bool> result(type.size(), false); | 
|  | 666 |  | 
|  | 667 | // Query GetSubTree for the availability of dump interface | 
|  | 668 | auto method = _bus.new_method_call(service_name::objectMapper, | 
|  | 669 | object_path::objectMapper, | 
|  | 670 | interface::objectMapper, "GetSubTree"); | 
|  | 671 | method.append(std::string{"/"}, 0, | 
|  | 672 | std::vector<std::string>{interface::dumpEntry}); | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 673 | auto reply = _bus.call(method, dbusTimeout); | 
| Sumit Kumar | 9d43a72 | 2021-08-24 09:46:19 -0500 | [diff] [blame] | 674 |  | 
|  | 675 | reply.read(subtree); | 
|  | 676 |  | 
|  | 677 | if (subtree.empty()) | 
|  | 678 | { | 
|  | 679 | return result; | 
|  | 680 | } | 
|  | 681 |  | 
|  | 682 | std::vector<bool>::iterator itDumpStatus = result.begin(); | 
|  | 683 | uint8_t count = 0; | 
|  | 684 | for (const auto& [path, serviceInfo] : subtree) | 
|  | 685 | { | 
|  | 686 | const auto& service = serviceInfo.begin()->first; | 
|  | 687 | // Check for dump type on the object path | 
|  | 688 | for (const auto& it : type) | 
|  | 689 | { | 
|  | 690 | if (path.find(it) != std::string::npos) | 
|  | 691 | { | 
|  | 692 | DBusValue value, progress; | 
|  | 693 |  | 
|  | 694 | // If dump type status is already available go for next path | 
|  | 695 | if (*itDumpStatus) | 
|  | 696 | { | 
|  | 697 | break; | 
|  | 698 | } | 
|  | 699 |  | 
|  | 700 | // Check for valid dump to be available if following | 
|  | 701 | // conditions are met for the dump entry path - | 
|  | 702 | // Offloaded == false and Status == Completed | 
|  | 703 | getProperty(service, path, interface::dumpEntry, "Offloaded", | 
|  | 704 | value); | 
|  | 705 | getProperty(service, path, interface::dumpProgress, "Status", | 
|  | 706 | progress); | 
|  | 707 | auto offload = std::get<bool>(value); | 
|  | 708 | auto status = std::get<std::string>(progress); | 
|  | 709 | if (!offload && (status.find("Completed") != std::string::npos)) | 
|  | 710 | { | 
|  | 711 | *itDumpStatus = true; | 
|  | 712 | count++; | 
|  | 713 | if (count >= type.size()) | 
|  | 714 | { | 
|  | 715 | return result; | 
|  | 716 | } | 
|  | 717 | break; | 
|  | 718 | } | 
|  | 719 | } | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 720 | ++itDumpStatus; | 
| Sumit Kumar | 9d43a72 | 2021-08-24 09:46:19 -0500 | [diff] [blame] | 721 | } | 
|  | 722 | itDumpStatus = result.begin(); | 
|  | 723 | } | 
|  | 724 |  | 
|  | 725 | return result; | 
|  | 726 | } | 
|  | 727 |  | 
| Jayanth Othayoth | ecaa2fc | 2021-11-05 02:02:52 -0500 | [diff] [blame] | 728 | void DataInterface::createGuardRecord(const std::vector<uint8_t>& binPath, | 
|  | 729 | const std::string& type, | 
|  | 730 | const std::string& logPath) const | 
|  | 731 | { | 
|  | 732 | try | 
|  | 733 | { | 
|  | 734 | auto method = _bus.new_method_call( | 
|  | 735 | service_name::hwIsolation, object_path::hwIsolation, | 
|  | 736 | interface::hwIsolationCreate, "CreateWithEntityPath"); | 
|  | 737 | method.append(binPath, type, sdbusplus::message::object_path(logPath)); | 
|  | 738 | // Note: hw isolation "CreateWithEntityPath" got dependency on logging | 
|  | 739 | // api's. Making d-bus call no reply type to avoid cyclic dependency. | 
|  | 740 | // Added minimal timeout to catch initial failures. | 
|  | 741 | // Need to revisit this design later to avoid cyclic dependency. | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 742 | constexpr auto hwIsolationTimeout = 100000; // in micro seconds | 
|  | 743 | _bus.call_noreply(method, hwIsolationTimeout); | 
| Jayanth Othayoth | ecaa2fc | 2021-11-05 02:02:52 -0500 | [diff] [blame] | 744 | } | 
|  | 745 |  | 
| Patrick Williams | 45e8352 | 2022-07-22 19:26:52 -0500 | [diff] [blame] | 746 | catch (const sdbusplus::exception_t& e) | 
| Jayanth Othayoth | ecaa2fc | 2021-11-05 02:02:52 -0500 | [diff] [blame] | 747 | { | 
|  | 748 | std::string errName = e.name(); | 
|  | 749 | // SD_BUS_ERROR_TIMEOUT error is expected, due to PEL api dependency | 
|  | 750 | // mentioned above. Ignoring the error. | 
|  | 751 | if (errName != SD_BUS_ERROR_TIMEOUT) | 
|  | 752 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 753 | lg2::error("GUARD D-Bus call exception. Path={PATH}, " | 
|  | 754 | "interface = {IFACE}, exception = {ERROR}", | 
|  | 755 | "PATH", object_path::hwIsolation, "IFACE", | 
|  | 756 | interface::hwIsolationCreate, "ERROR", e); | 
| Jayanth Othayoth | ecaa2fc | 2021-11-05 02:02:52 -0500 | [diff] [blame] | 757 | } | 
|  | 758 | } | 
|  | 759 | } | 
| Sumit Kumar | 3e27443 | 2021-09-14 06:37:56 -0500 | [diff] [blame] | 760 |  | 
|  | 761 | void DataInterface::createProgressSRC( | 
|  | 762 | const uint64_t& priSRC, const std::vector<uint8_t>& srcStruct) const | 
|  | 763 | { | 
|  | 764 | DBusValue variant = std::make_tuple(priSRC, srcStruct); | 
|  | 765 |  | 
|  | 766 | auto method = _bus.new_method_call(service_name::bootRawProgress, | 
| Vijay Lobo | 875b6c7 | 2021-10-20 17:38:56 -0500 | [diff] [blame] | 767 | object_path::bootRawProgress, | 
| Sumit Kumar | 3e27443 | 2021-09-14 06:37:56 -0500 | [diff] [blame] | 768 | interface::dbusProperty, "Set"); | 
|  | 769 |  | 
|  | 770 | method.append(interface::bootRawProgress, "Value", variant); | 
|  | 771 |  | 
| Matt Spinler | 35a405b | 2022-03-02 11:42:42 -0600 | [diff] [blame] | 772 | _bus.call(method, dbusTimeout); | 
| Sumit Kumar | 3e27443 | 2021-09-14 06:37:56 -0500 | [diff] [blame] | 773 | } | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 774 |  | 
|  | 775 | std::vector<uint32_t> DataInterface::getLogIDWithHwIsolation() const | 
|  | 776 | { | 
|  | 777 | std::vector<std::string> association = {"xyz.openbmc_project.Association"}; | 
|  | 778 | std::string hwErrorLog = "/isolated_hw_errorlog"; | 
|  | 779 | std::string errorLog = "/error_log"; | 
|  | 780 | DBusPathList paths; | 
|  | 781 | std::vector<uint32_t> ids; | 
|  | 782 |  | 
|  | 783 | // Get all latest mapper associations | 
|  | 784 | paths = getPaths(association); | 
|  | 785 | for (auto& path : paths) | 
|  | 786 | { | 
|  | 787 | // Look for object path with hardware isolation entry if any | 
|  | 788 | size_t pos = path.find(hwErrorLog); | 
|  | 789 | if (pos != std::string::npos) | 
|  | 790 | { | 
|  | 791 | // Get the object path | 
|  | 792 | std::string ph = path; | 
|  | 793 | ph.erase(pos, hwErrorLog.length()); | 
|  | 794 | auto service = getService(ph, interface::hwIsolationEntry); | 
|  | 795 | if (!service.empty()) | 
|  | 796 | { | 
|  | 797 | bool status; | 
|  | 798 | DBusValue value; | 
|  | 799 |  | 
|  | 800 | // Read the Resolved property from object path | 
|  | 801 | getProperty(service, ph, interface::hwIsolationEntry, | 
|  | 802 | "Resolved", value); | 
|  | 803 |  | 
|  | 804 | status = std::get<bool>(value); | 
|  | 805 |  | 
|  | 806 | // If the entry isn't resolved | 
|  | 807 | if (!status) | 
|  | 808 | { | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 809 | auto assocService = getService(path, | 
|  | 810 | interface::association); | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 811 | if (!assocService.empty()) | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 812 | { | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 813 | DBusValue endpoints; | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 814 |  | 
|  | 815 | // Read Endpoints property | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 816 | getProperty(assocService, path, interface::association, | 
|  | 817 | "endpoints", endpoints); | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 818 |  | 
|  | 819 | auto logPath = | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 820 | std::get<std::vector<std::string>>(endpoints); | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 821 | if (!logPath.empty()) | 
|  | 822 | { | 
|  | 823 | // Get OpenBMC event log Id | 
|  | 824 | uint32_t id = stoi(logPath[0].substr( | 
|  | 825 | logPath[0].find_last_of('/') + 1)); | 
|  | 826 | ids.push_back(id); | 
|  | 827 | } | 
|  | 828 | } | 
|  | 829 | } | 
|  | 830 | } | 
|  | 831 | } | 
|  | 832 |  | 
|  | 833 | // Look for object path with error_log entry if any | 
|  | 834 | pos = path.find(errorLog); | 
|  | 835 | if (pos != std::string::npos) | 
|  | 836 | { | 
|  | 837 | auto service = getService(path, interface::association); | 
|  | 838 | if (!service.empty()) | 
|  | 839 | { | 
|  | 840 | DBusValue value; | 
|  | 841 |  | 
|  | 842 | // Read Endpoints property | 
|  | 843 | getProperty(service, path, interface::association, "endpoints", | 
|  | 844 | value); | 
|  | 845 |  | 
|  | 846 | auto logPath = std::get<std::vector<std::string>>(value); | 
|  | 847 | if (!logPath.empty()) | 
|  | 848 | { | 
|  | 849 | // Get OpenBMC event log Id | 
|  | 850 | uint32_t id = stoi( | 
|  | 851 | logPath[0].substr(logPath[0].find_last_of('/') + 1)); | 
|  | 852 | ids.push_back(id); | 
|  | 853 | } | 
|  | 854 | } | 
|  | 855 | } | 
|  | 856 | } | 
|  | 857 |  | 
|  | 858 | if (ids.size() > 1) | 
|  | 859 | { | 
|  | 860 | // remove duplicates to have only unique ids | 
|  | 861 | std::sort(ids.begin(), ids.end()); | 
|  | 862 | ids.erase(std::unique(ids.begin(), ids.end()), ids.end()); | 
|  | 863 | } | 
|  | 864 | return ids; | 
|  | 865 | } | 
| Vijay Lobo | 875b6c7 | 2021-10-20 17:38:56 -0500 | [diff] [blame] | 866 |  | 
|  | 867 | std::vector<uint8_t> DataInterface::getRawProgressSRC(void) const | 
|  | 868 | { | 
|  | 869 | using RawProgressProperty = std::tuple<uint64_t, std::vector<uint8_t>>; | 
|  | 870 |  | 
|  | 871 | DBusValue value; | 
|  | 872 | getProperty(service_name::bootRawProgress, object_path::bootRawProgress, | 
|  | 873 | interface::bootRawProgress, "Value", value); | 
|  | 874 |  | 
|  | 875 | const auto& rawProgress = std::get<RawProgressProperty>(value); | 
|  | 876 | return std::get<1>(rawProgress); | 
|  | 877 | } | 
|  | 878 |  | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 879 | void DataInterface::startFruPlugWatch() | 
|  | 880 | { | 
|  | 881 | // Add a watch on inventory InterfacesAdded and then find all | 
|  | 882 | // existing hotpluggable interfaces and add propertiesChanged | 
|  | 883 | // watches on them. | 
|  | 884 |  | 
|  | 885 | _invIaMatch = std::make_unique<sdbusplus::bus::match_t>( | 
|  | 886 | _bus, match_rules::interfacesAdded(object_path::baseInv), | 
|  | 887 | std::bind(&DataInterface::inventoryIfaceAdded, this, | 
|  | 888 | std::placeholders::_1)); | 
|  | 889 | try | 
|  | 890 | { | 
|  | 891 | auto paths = getPaths(hotplugInterfaces); | 
|  | 892 |  | 
|  | 893 | _invPresentMatches.clear(); | 
|  | 894 |  | 
|  | 895 | std::for_each(paths.begin(), paths.end(), | 
|  | 896 | [this](const auto& path) { addHotplugWatch(path); }); | 
|  | 897 | } | 
|  | 898 | catch (const sdbusplus::exception_t& e) | 
|  | 899 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 900 | lg2::warning("Failed getting FRU paths to watch: {ERROR}", "ERROR", e); | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 901 | } | 
|  | 902 | } | 
|  | 903 |  | 
|  | 904 | void DataInterface::addHotplugWatch(const std::string& path) | 
|  | 905 | { | 
|  | 906 | if (!_invPresentMatches.contains(path)) | 
|  | 907 | { | 
|  | 908 | _invPresentMatches.emplace( | 
|  | 909 | path, | 
|  | 910 | std::make_unique<sdbusplus::bus::match_t>( | 
|  | 911 | _bus, match_rules::propertiesChanged(path, interface::invItem), | 
|  | 912 | std::bind(&DataInterface::presenceChanged, this, | 
|  | 913 | std::placeholders::_1))); | 
|  | 914 | } | 
|  | 915 | } | 
|  | 916 |  | 
|  | 917 | void DataInterface::inventoryIfaceAdded(sdbusplus::message_t& msg) | 
|  | 918 | { | 
|  | 919 | sdbusplus::message::object_path path; | 
|  | 920 | DBusInterfaceMap interfaces; | 
|  | 921 |  | 
|  | 922 | msg.read(path, interfaces); | 
|  | 923 |  | 
|  | 924 | // Check if any of the new interfaces are for hot pluggable FRUs. | 
|  | 925 | if (std::find_if(interfaces.begin(), interfaces.end(), | 
|  | 926 | [](const auto& interfacePair) { | 
|  | 927 | return std::find(hotplugInterfaces.begin(), hotplugInterfaces.end(), | 
|  | 928 | interfacePair.first) != hotplugInterfaces.end(); | 
|  | 929 | }) == interfaces.end()) | 
|  | 930 | { | 
|  | 931 | return; | 
|  | 932 | } | 
|  | 933 |  | 
|  | 934 | addHotplugWatch(path.str); | 
|  | 935 |  | 
|  | 936 | // If an Inventory.Item interface was also added, check presence now. | 
|  | 937 |  | 
|  | 938 | // Notes: | 
|  | 939 | // * This assumes the Inv.Item and Inv.Fan/PS are added together which | 
|  | 940 | //   is currently the case. | 
|  | 941 | // * If the code ever switches to something without a Present | 
|  | 942 | //   property, then the IA signal itself would probably indicate presence. | 
|  | 943 |  | 
|  | 944 | auto itemIt = interfaces.find(interface::invItem); | 
|  | 945 | if (itemIt != interfaces.end()) | 
|  | 946 | { | 
|  | 947 | notifyPresenceSubsribers(path.str, itemIt->second); | 
|  | 948 | } | 
|  | 949 | } | 
|  | 950 |  | 
|  | 951 | void DataInterface::presenceChanged(sdbusplus::message_t& msg) | 
|  | 952 | { | 
|  | 953 | DBusInterface interface; | 
|  | 954 | DBusPropertyMap properties; | 
|  | 955 |  | 
|  | 956 | msg.read(interface, properties); | 
|  | 957 | if (interface != interface::invItem) | 
|  | 958 | { | 
|  | 959 | return; | 
|  | 960 | } | 
|  | 961 |  | 
|  | 962 | std::string path = msg.get_path(); | 
|  | 963 | notifyPresenceSubsribers(path, properties); | 
|  | 964 | } | 
|  | 965 |  | 
|  | 966 | void DataInterface::notifyPresenceSubsribers(const std::string& path, | 
|  | 967 | const DBusPropertyMap& properties) | 
|  | 968 | { | 
| Matt Spinler | 5ee3605 | 2023-05-30 14:20:56 -0500 | [diff] [blame] | 969 | auto prop = properties.find("Present"); | 
|  | 970 | if ((prop == properties.end()) || (!std::get<bool>(prop->second))) | 
|  | 971 | { | 
|  | 972 | return; | 
|  | 973 | } | 
|  | 974 |  | 
|  | 975 | std::string locCode; | 
|  | 976 |  | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 977 | try | 
|  | 978 | { | 
| Matt Spinler | 52ee3a4 | 2023-07-27 14:54:48 -0500 | [diff] [blame^] | 979 | auto service = getService(path, interface::locCode); | 
|  | 980 |  | 
|  | 981 | // If the hotplugged FRU is hosted by PLDM, then it is | 
|  | 982 | // in an IO expansion drawer and we don't care about it. | 
|  | 983 | if (service == service_name::pldm) | 
|  | 984 | { | 
|  | 985 | return; | 
|  | 986 | } | 
|  | 987 |  | 
| Matt Spinler | 5ee3605 | 2023-05-30 14:20:56 -0500 | [diff] [blame] | 988 | locCode = getLocationCode(path); | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 989 | } | 
| Matt Spinler | 5ee3605 | 2023-05-30 14:20:56 -0500 | [diff] [blame] | 990 | catch (const sdbusplus::exception_t& e) | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 991 | { | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 992 | lg2::debug("Could not get location code for {PATH}: {ERROR}", "PATH", | 
|  | 993 | path, "ERROR", e); | 
| Matt Spinler | 5ee3605 | 2023-05-30 14:20:56 -0500 | [diff] [blame] | 994 | return; | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 995 | } | 
| Matt Spinler | 5ee3605 | 2023-05-30 14:20:56 -0500 | [diff] [blame] | 996 |  | 
| Matt Spinler | a167a7d | 2023-06-30 15:14:25 -0500 | [diff] [blame] | 997 | lg2::debug("Detected FRU {PATH} ({LOC}) present ", "PATH", path, "LOC", | 
|  | 998 | locCode); | 
| Matt Spinler | 5ee3605 | 2023-05-30 14:20:56 -0500 | [diff] [blame] | 999 |  | 
|  | 1000 | // Tell the subscribers. | 
|  | 1001 | setFruPresent(locCode); | 
| Matt Spinler | 5b42365 | 2023-05-04 13:08:44 -0500 | [diff] [blame] | 1002 | } | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 1003 | } // namespace pels | 
|  | 1004 | } // namespace openpower |