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