| 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 | cad9c2b | 2019-12-02 15:42:01 -0600 | [diff] [blame] | 24 | #include <fstream> | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 25 | #include <phosphor-logging/log.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 |  | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 28 | namespace openpower | 
|  | 29 | { | 
|  | 30 | namespace pels | 
|  | 31 | { | 
|  | 32 |  | 
|  | 33 | namespace service_name | 
|  | 34 | { | 
|  | 35 | constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper"; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 36 | constexpr auto vpdManager = "com.ibm.VPD.Manager"; | 
| Matt Spinler | 34a904c | 2020-08-05 14:53:28 -0500 | [diff] [blame] | 37 | constexpr auto ledGroupManager = "xyz.openbmc_project.LED.GroupManager"; | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 38 | } // namespace service_name | 
|  | 39 |  | 
|  | 40 | namespace object_path | 
|  | 41 | { | 
|  | 42 | constexpr auto objectMapper = "/xyz/openbmc_project/object_mapper"; | 
|  | 43 | constexpr auto systemInv = "/xyz/openbmc_project/inventory/system"; | 
| Matt Spinler | 6ea4d5f | 2020-05-20 13:31:07 -0500 | [diff] [blame] | 44 | constexpr auto chassisInv = "/xyz/openbmc_project/inventory/system/chassis"; | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 45 | constexpr auto motherBoardInv = | 
|  | 46 | "/xyz/openbmc_project/inventory/system/chassis/motherboard"; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 47 | constexpr auto baseInv = "/xyz/openbmc_project/inventory"; | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 48 | constexpr auto bmcState = "/xyz/openbmc_project/state/bmc0"; | 
|  | 49 | constexpr auto chassisState = "/xyz/openbmc_project/state/chassis0"; | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 50 | constexpr auto hostState = "/xyz/openbmc_project/state/host0"; | 
| Matt Spinler | b3f5186 | 2019-12-09 13:55:10 -0600 | [diff] [blame] | 51 | constexpr auto pldm = "/xyz/openbmc_project/pldm"; | 
| Matt Spinler | 9cf3cfd | 2020-02-03 14:41:55 -0600 | [diff] [blame] | 52 | constexpr auto enableHostPELs = | 
|  | 53 | "/xyz/openbmc_project/logging/send_event_logs_to_host"; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 54 | constexpr auto vpdManager = "/com/ibm/VPD/Manager"; | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 55 | } // namespace object_path | 
|  | 56 |  | 
|  | 57 | namespace interface | 
|  | 58 | { | 
|  | 59 | constexpr auto dbusProperty = "org.freedesktop.DBus.Properties"; | 
|  | 60 | constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper"; | 
|  | 61 | constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset"; | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 62 | constexpr auto bootProgress = "xyz.openbmc_project.State.Boot.Progress"; | 
| Matt Spinler | b3f5186 | 2019-12-09 13:55:10 -0600 | [diff] [blame] | 63 | constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester"; | 
| Matt Spinler | 9cf3cfd | 2020-02-03 14:41:55 -0600 | [diff] [blame] | 64 | constexpr auto enable = "xyz.openbmc_project.Object.Enable"; | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 65 | constexpr auto bmcState = "xyz.openbmc_project.State.BMC"; | 
|  | 66 | constexpr auto chassisState = "xyz.openbmc_project.State.Chassis"; | 
|  | 67 | constexpr auto hostState = "xyz.openbmc_project.State.Host"; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 68 | constexpr auto invMotherboard = | 
|  | 69 | "xyz.openbmc_project.Inventory.Item.Board.Motherboard"; | 
|  | 70 | constexpr auto viniRecordVPD = "com.ibm.ipzvpd.VINI"; | 
| Matt Spinler | 60c4e79 | 2020-03-13 13:45:36 -0500 | [diff] [blame] | 71 | constexpr auto locCode = "com.ibm.ipzvpd.Location"; | 
| Matt Spinler | 1ab6696 | 2020-10-29 13:21:44 -0500 | [diff] [blame] | 72 | constexpr auto compatible = | 
|  | 73 | "xyz.openbmc_project.Configuration.IBMCompatibleSystem"; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 74 | constexpr auto vpdManager = "com.ibm.VPD.Manager"; | 
| Matt Spinler | 34a904c | 2020-08-05 14:53:28 -0500 | [diff] [blame] | 75 | constexpr auto ledGroup = "xyz.openbmc_project.Led.Group"; | 
| Matt Spinler | 993168d | 2021-04-07 16:05:03 -0500 | [diff] [blame] | 76 | constexpr auto operationalStatus = | 
|  | 77 | "xyz.openbmc_project.State.Decorator.OperationalStatus"; | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 78 | } // namespace interface | 
|  | 79 |  | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 80 | using namespace sdbusplus::xyz::openbmc_project::State::Boot::server; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 81 | using sdbusplus::exception::SdBusError; | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 82 | using namespace phosphor::logging; | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 83 |  | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 84 | DataInterface::DataInterface(sdbusplus::bus::bus& bus) : _bus(bus) | 
|  | 85 | { | 
| Matt Spinler | cad9c2b | 2019-12-02 15:42:01 -0600 | [diff] [blame] | 86 | readBMCFWVersion(); | 
|  | 87 | readServerFWVersion(); | 
| Matt Spinler | 677381b | 2020-01-23 10:04:29 -0600 | [diff] [blame] | 88 | readBMCFWVersionID(); | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 89 |  | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 90 | // Watch the BootProgress property | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 91 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 92 | bus, object_path::hostState, interface::bootProgress, "BootProgress", | 
|  | 93 | *this, [this](const auto& value) { | 
|  | 94 | auto status = Progress::convertProgressStagesFromString( | 
|  | 95 | std::get<std::string>(value)); | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 96 |  | 
| Matt Spinler | f10068d | 2020-12-02 10:44:08 -0600 | [diff] [blame] | 97 | if ((status == Progress::ProgressStages::SystemInitComplete) || | 
|  | 98 | (status == Progress::ProgressStages::OSStart) || | 
|  | 99 | (status == Progress::ProgressStages::OSRunning)) | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 100 | { | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 101 | setHostUp(true); | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 102 | } | 
|  | 103 | else | 
|  | 104 | { | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 105 | setHostUp(false); | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 106 | } | 
|  | 107 | })); | 
| Matt Spinler | 9cf3cfd | 2020-02-03 14:41:55 -0600 | [diff] [blame] | 108 |  | 
|  | 109 | // Watch the host PEL enable property | 
|  | 110 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
|  | 111 | bus, object_path::enableHostPELs, interface::enable, "Enabled", *this, | 
|  | 112 | [this](const auto& value) { | 
|  | 113 | this->_sendPELsToHost = std::get<bool>(value); | 
|  | 114 | })); | 
| Matt Spinler | 4aa23a1 | 2020-02-03 15:05:09 -0600 | [diff] [blame] | 115 |  | 
|  | 116 | // Watch the BMCState property | 
|  | 117 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
|  | 118 | bus, object_path::bmcState, interface::bmcState, "CurrentBMCState", | 
|  | 119 | *this, [this](const auto& value) { | 
|  | 120 | this->_bmcState = std::get<std::string>(value); | 
|  | 121 | })); | 
|  | 122 |  | 
|  | 123 | // Watch the chassis current and requested power state properties | 
|  | 124 | _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>( | 
|  | 125 | bus, object_path::chassisState, interface::chassisState, *this, | 
|  | 126 | [this](const auto& properties) { | 
|  | 127 | auto state = properties.find("CurrentPowerState"); | 
|  | 128 | if (state != properties.end()) | 
|  | 129 | { | 
|  | 130 | this->_chassisState = std::get<std::string>(state->second); | 
|  | 131 | } | 
|  | 132 |  | 
|  | 133 | auto trans = properties.find("RequestedPowerTransition"); | 
|  | 134 | if (trans != properties.end()) | 
|  | 135 | { | 
|  | 136 | this->_chassisTransition = std::get<std::string>(trans->second); | 
|  | 137 | } | 
|  | 138 | })); | 
|  | 139 |  | 
|  | 140 | // Watch the CurrentHostState property | 
|  | 141 | _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>( | 
|  | 142 | bus, object_path::hostState, interface::hostState, "CurrentHostState", | 
|  | 143 | *this, [this](const auto& value) { | 
|  | 144 | this->_hostState = std::get<std::string>(value); | 
|  | 145 | })); | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 146 | } | 
|  | 147 |  | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 148 | DBusPropertyMap | 
|  | 149 | DataInterface::getAllProperties(const std::string& service, | 
|  | 150 | const std::string& objectPath, | 
|  | 151 | const std::string& interface) const | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 152 | { | 
|  | 153 | DBusPropertyMap properties; | 
|  | 154 |  | 
|  | 155 | auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(), | 
|  | 156 | interface::dbusProperty, "GetAll"); | 
|  | 157 | method.append(interface); | 
|  | 158 | auto reply = _bus.call(method); | 
|  | 159 |  | 
|  | 160 | reply.read(properties); | 
|  | 161 |  | 
|  | 162 | return properties; | 
|  | 163 | } | 
|  | 164 |  | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 165 | void DataInterface::getProperty(const std::string& service, | 
|  | 166 | const std::string& objectPath, | 
|  | 167 | const std::string& interface, | 
| Matt Spinler | 2a28c93 | 2020-02-03 14:23:40 -0600 | [diff] [blame] | 168 | const std::string& property, | 
|  | 169 | DBusValue& value) const | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 170 | { | 
|  | 171 |  | 
|  | 172 | auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(), | 
|  | 173 | interface::dbusProperty, "Get"); | 
|  | 174 | method.append(interface, property); | 
|  | 175 | auto reply = _bus.call(method); | 
|  | 176 |  | 
|  | 177 | reply.read(value); | 
|  | 178 | } | 
|  | 179 |  | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 180 | DBusPathList DataInterface::getPaths(const DBusInterfaceList& interfaces) const | 
|  | 181 | { | 
|  | 182 |  | 
|  | 183 | auto method = _bus.new_method_call( | 
|  | 184 | service_name::objectMapper, object_path::objectMapper, | 
|  | 185 | interface::objectMapper, "GetSubTreePaths"); | 
|  | 186 |  | 
|  | 187 | method.append(std::string{"/"}, 0, interfaces); | 
|  | 188 |  | 
|  | 189 | auto reply = _bus.call(method); | 
|  | 190 |  | 
|  | 191 | DBusPathList paths; | 
|  | 192 | reply.read(paths); | 
|  | 193 |  | 
|  | 194 | return paths; | 
|  | 195 | } | 
|  | 196 |  | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 197 | DBusService DataInterface::getService(const std::string& objectPath, | 
| Matt Spinler | b3f5186 | 2019-12-09 13:55:10 -0600 | [diff] [blame] | 198 | const std::string& interface) const | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 199 | { | 
|  | 200 | auto method = _bus.new_method_call(service_name::objectMapper, | 
|  | 201 | object_path::objectMapper, | 
|  | 202 | interface::objectMapper, "GetObject"); | 
|  | 203 |  | 
|  | 204 | method.append(objectPath, std::vector<std::string>({interface})); | 
|  | 205 |  | 
|  | 206 | auto reply = _bus.call(method); | 
|  | 207 |  | 
|  | 208 | std::map<DBusService, DBusInterfaceList> response; | 
|  | 209 | reply.read(response); | 
|  | 210 |  | 
|  | 211 | if (!response.empty()) | 
|  | 212 | { | 
|  | 213 | return response.begin()->first; | 
|  | 214 | } | 
|  | 215 |  | 
|  | 216 | return std::string{}; | 
|  | 217 | } | 
| Matt Spinler | a7d9d96 | 2019-11-06 15:01:25 -0600 | [diff] [blame] | 218 |  | 
| Matt Spinler | 677381b | 2020-01-23 10:04:29 -0600 | [diff] [blame] | 219 | void DataInterface::readBMCFWVersion() | 
|  | 220 | { | 
| Matt Spinler | f61f292 | 2020-06-23 11:32:49 -0500 | [diff] [blame] | 221 | _bmcFWVersion = | 
|  | 222 | phosphor::logging::util::getOSReleaseValue("VERSION").value_or(""); | 
| Matt Spinler | cad9c2b | 2019-12-02 15:42:01 -0600 | [diff] [blame] | 223 | } | 
|  | 224 |  | 
|  | 225 | void DataInterface::readServerFWVersion() | 
|  | 226 | { | 
| Sumit Kumar | cad1620 | 2021-05-13 04:06:15 -0500 | [diff] [blame] | 227 | auto value = | 
|  | 228 | phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or(""); | 
|  | 229 | if ((value != "") && (value.find_last_of(')') != std::string::npos)) | 
|  | 230 | { | 
|  | 231 | std::size_t pos = value.find_first_of('(') + 1; | 
|  | 232 | _serverFWVersion = value.substr(pos, value.find_last_of(')') - pos); | 
|  | 233 | } | 
| Matt Spinler | cad9c2b | 2019-12-02 15:42:01 -0600 | [diff] [blame] | 234 | } | 
|  | 235 |  | 
| Matt Spinler | 677381b | 2020-01-23 10:04:29 -0600 | [diff] [blame] | 236 | void DataInterface::readBMCFWVersionID() | 
|  | 237 | { | 
| Matt Spinler | f61f292 | 2020-06-23 11:32:49 -0500 | [diff] [blame] | 238 | _bmcFWVersionID = | 
|  | 239 | phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or(""); | 
| Matt Spinler | 677381b | 2020-01-23 10:04:29 -0600 | [diff] [blame] | 240 | } | 
|  | 241 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 242 | std::string DataInterface::getMachineTypeModel() const | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 243 | { | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 244 | std::string model; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 245 | try | 
|  | 246 | { | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 247 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 248 | auto service = getService(object_path::systemInv, interface::invAsset); | 
|  | 249 | if (!service.empty()) | 
|  | 250 | { | 
|  | 251 | DBusValue value; | 
|  | 252 | getProperty(service, object_path::systemInv, interface::invAsset, | 
|  | 253 | "Model", value); | 
|  | 254 |  | 
|  | 255 | model = std::get<std::string>(value); | 
|  | 256 | } | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 257 | } | 
|  | 258 | catch (const std::exception& e) | 
|  | 259 | { | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 260 | log<level::WARNING>(fmt::format("Failed reading Model property from " | 
|  | 261 | "Interface: {} exception: {}", | 
|  | 262 | interface::invAsset, e.what()) | 
|  | 263 | .c_str()); | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 264 | } | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 265 |  | 
|  | 266 | return model; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 267 | } | 
|  | 268 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 269 | std::string DataInterface::getMachineSerialNumber() const | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 270 | { | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 271 | std::string sn; | 
|  | 272 | try | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 273 | { | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 274 |  | 
|  | 275 | auto service = getService(object_path::systemInv, interface::invAsset); | 
|  | 276 | if (!service.empty()) | 
|  | 277 | { | 
|  | 278 | DBusValue value; | 
|  | 279 | getProperty(service, object_path::systemInv, interface::invAsset, | 
|  | 280 | "SerialNumber", value); | 
|  | 281 |  | 
|  | 282 | sn = std::get<std::string>(value); | 
|  | 283 | } | 
|  | 284 | } | 
|  | 285 | catch (const std::exception& e) | 
|  | 286 | { | 
|  | 287 | log<level::WARNING>( | 
|  | 288 | fmt::format("Failed reading SerialNumber property from " | 
|  | 289 | "Interface: {} exception: {}", | 
|  | 290 | interface::invAsset, e.what()) | 
|  | 291 | .c_str()); | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 292 | } | 
|  | 293 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 294 | return sn; | 
|  | 295 | } | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 296 |  | 
| Vijay Lobo | 81b4dca | 2021-04-29 00:04:00 -0500 | [diff] [blame] | 297 | std::string DataInterface::getMotherboardCCIN() const | 
|  | 298 | { | 
|  | 299 | std::string ccin; | 
|  | 300 |  | 
|  | 301 | try | 
|  | 302 | { | 
|  | 303 | auto service = | 
|  | 304 | getService(object_path::motherBoardInv, interface::viniRecordVPD); | 
|  | 305 | if (!service.empty()) | 
|  | 306 | { | 
|  | 307 | DBusValue value; | 
|  | 308 | getProperty(service, object_path::motherBoardInv, | 
|  | 309 | interface::viniRecordVPD, "CC", value); | 
|  | 310 |  | 
|  | 311 | auto cc = std::get<std::vector<uint8_t>>(value); | 
|  | 312 | ccin = std::string{cc.begin(), cc.end()}; | 
|  | 313 | } | 
|  | 314 | } | 
|  | 315 | catch (const std::exception& e) | 
|  | 316 | { | 
|  | 317 | log<level::WARNING>( | 
|  | 318 | fmt::format("Failed reading Motherboard CCIN property from " | 
|  | 319 | "Interface: {} exception: {}", | 
|  | 320 | interface::viniRecordVPD, e.what()) | 
|  | 321 | .c_str()); | 
|  | 322 | } | 
|  | 323 |  | 
|  | 324 | return ccin; | 
| Matt Spinler | b3d488f | 2020-02-21 15:30:46 -0600 | [diff] [blame] | 325 | } | 
|  | 326 |  | 
| Matt Spinler | 60c4e79 | 2020-03-13 13:45:36 -0500 | [diff] [blame] | 327 | void DataInterface::getHWCalloutFields(const std::string& inventoryPath, | 
| Matt Spinler | 60c4e79 | 2020-03-13 13:45:36 -0500 | [diff] [blame] | 328 | std::string& fruPartNumber, | 
|  | 329 | std::string& ccin, | 
|  | 330 | std::string& serialNumber) const | 
|  | 331 | { | 
|  | 332 | // For now, attempt to get all of the properties directly on the path | 
|  | 333 | // passed in.  In the future, may need to make use of an algorithm | 
|  | 334 | // to figure out which inventory objects actually hold these | 
|  | 335 | // interfaces in the case of non FRUs, or possibly another service | 
|  | 336 | // will provide this info.  Any missing interfaces will result | 
|  | 337 | // in exceptions being thrown. | 
|  | 338 |  | 
| Matt Spinler | 9b90e2a | 2020-04-14 10:59:04 -0500 | [diff] [blame] | 339 | auto service = getService(inventoryPath, interface::viniRecordVPD); | 
| Matt Spinler | 60c4e79 | 2020-03-13 13:45:36 -0500 | [diff] [blame] | 340 |  | 
|  | 341 | auto properties = | 
|  | 342 | getAllProperties(service, inventoryPath, interface::viniRecordVPD); | 
|  | 343 |  | 
|  | 344 | auto value = std::get<std::vector<uint8_t>>(properties["FN"]); | 
|  | 345 | fruPartNumber = std::string{value.begin(), value.end()}; | 
|  | 346 |  | 
|  | 347 | value = std::get<std::vector<uint8_t>>(properties["CC"]); | 
|  | 348 | ccin = std::string{value.begin(), value.end()}; | 
|  | 349 |  | 
|  | 350 | value = std::get<std::vector<uint8_t>>(properties["SN"]); | 
|  | 351 | serialNumber = std::string{value.begin(), value.end()}; | 
|  | 352 | } | 
|  | 353 |  | 
| Matt Spinler | 9b90e2a | 2020-04-14 10:59:04 -0500 | [diff] [blame] | 354 | std::string | 
|  | 355 | DataInterface::getLocationCode(const std::string& inventoryPath) const | 
|  | 356 | { | 
|  | 357 | auto service = getService(inventoryPath, interface::locCode); | 
|  | 358 |  | 
|  | 359 | DBusValue locCode; | 
|  | 360 | getProperty(service, inventoryPath, interface::locCode, "LocationCode", | 
|  | 361 | locCode); | 
|  | 362 |  | 
|  | 363 | return std::get<std::string>(locCode); | 
|  | 364 | } | 
|  | 365 |  | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 366 | std::string | 
|  | 367 | DataInterface::addLocationCodePrefix(const std::string& locationCode) | 
|  | 368 | { | 
|  | 369 | static const std::string locationCodePrefix{"Ufcs-"}; | 
|  | 370 |  | 
| Matt Spinler | 0e4d72e | 2020-08-05 12:36:53 -0500 | [diff] [blame] | 371 | // Technically there are 2 location code prefixes, Ufcs and Umts, so | 
|  | 372 | // if it already starts with a U then don't need to do anything. | 
|  | 373 | if (locationCode.front() != 'U') | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 374 | { | 
|  | 375 | return locationCodePrefix + locationCode; | 
|  | 376 | } | 
|  | 377 |  | 
|  | 378 | return locationCode; | 
|  | 379 | } | 
|  | 380 |  | 
|  | 381 | std::string DataInterface::expandLocationCode(const std::string& locationCode, | 
| Patrick Williams | d26fa3e | 2021-04-21 15:22:23 -0500 | [diff] [blame] | 382 | uint16_t /*node*/) const | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 383 | { | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 384 | auto method = | 
|  | 385 | _bus.new_method_call(service_name::vpdManager, object_path::vpdManager, | 
|  | 386 | interface::vpdManager, "GetExpandedLocationCode"); | 
|  | 387 |  | 
|  | 388 | method.append(addLocationCodePrefix(locationCode), | 
|  | 389 | static_cast<uint16_t>(0)); | 
|  | 390 |  | 
|  | 391 | auto reply = _bus.call(method); | 
|  | 392 |  | 
|  | 393 | std::string expandedLocationCode; | 
|  | 394 | reply.read(expandedLocationCode); | 
|  | 395 |  | 
|  | 396 | return expandedLocationCode; | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 397 | } | 
|  | 398 |  | 
| Matt Spinler | 2f9225a | 2020-08-05 12:58:49 -0500 | [diff] [blame] | 399 | std::string | 
|  | 400 | DataInterface::getInventoryFromLocCode(const std::string& locationCode, | 
|  | 401 | uint16_t node, bool expanded) const | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 402 | { | 
| Matt Spinler | 2f9225a | 2020-08-05 12:58:49 -0500 | [diff] [blame] | 403 | std::string methodName = expanded ? "GetFRUsByExpandedLocationCode" | 
|  | 404 | : "GetFRUsByUnexpandedLocationCode"; | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 405 |  | 
| Matt Spinler | 2f9225a | 2020-08-05 12:58:49 -0500 | [diff] [blame] | 406 | auto method = | 
|  | 407 | _bus.new_method_call(service_name::vpdManager, object_path::vpdManager, | 
|  | 408 | interface::vpdManager, methodName.c_str()); | 
|  | 409 |  | 
|  | 410 | if (expanded) | 
|  | 411 | { | 
|  | 412 | method.append(locationCode); | 
|  | 413 | } | 
|  | 414 | else | 
|  | 415 | { | 
|  | 416 | method.append(addLocationCodePrefix(locationCode), node); | 
|  | 417 | } | 
| Matt Spinler | fcf9a3f | 2020-07-28 13:21:07 -0500 | [diff] [blame] | 418 |  | 
|  | 419 | auto reply = _bus.call(method); | 
|  | 420 |  | 
|  | 421 | std::vector<sdbusplus::message::object_path> entries; | 
|  | 422 | reply.read(entries); | 
|  | 423 |  | 
|  | 424 | // Get the shortest entry from the paths received, as this | 
|  | 425 | // would be the path furthest up the inventory hierarchy so | 
|  | 426 | // would be the parent FRU.  There is guaranteed to at least | 
|  | 427 | // be one entry if the call didn't fail. | 
|  | 428 | std::string shortest{entries[0]}; | 
|  | 429 |  | 
|  | 430 | std::for_each(entries.begin(), entries.end(), | 
|  | 431 | [&shortest](const auto& path) { | 
|  | 432 | if (path.str.size() < shortest.size()) | 
|  | 433 | { | 
|  | 434 | shortest = path; | 
|  | 435 | } | 
|  | 436 | }); | 
|  | 437 |  | 
|  | 438 | return shortest; | 
| Matt Spinler | 5fb24c1 | 2020-06-04 11:21:33 -0500 | [diff] [blame] | 439 | } | 
|  | 440 |  | 
| Matt Spinler | 34a904c | 2020-08-05 14:53:28 -0500 | [diff] [blame] | 441 | void DataInterface::assertLEDGroup(const std::string& ledGroup, | 
|  | 442 | bool value) const | 
|  | 443 | { | 
|  | 444 | DBusValue variant = value; | 
|  | 445 | auto method = | 
|  | 446 | _bus.new_method_call(service_name::ledGroupManager, ledGroup.c_str(), | 
|  | 447 | interface::dbusProperty, "Set"); | 
|  | 448 | method.append(interface::ledGroup, "Asserted", variant); | 
|  | 449 | _bus.call(method); | 
|  | 450 | } | 
|  | 451 |  | 
| Matt Spinler | 993168d | 2021-04-07 16:05:03 -0500 | [diff] [blame] | 452 | void DataInterface::setFunctional(const std::string& objectPath, | 
|  | 453 | bool value) const | 
|  | 454 | { | 
|  | 455 | DBusValue variant = value; | 
|  | 456 | auto service = getService(objectPath, interface::operationalStatus); | 
|  | 457 |  | 
|  | 458 | auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(), | 
|  | 459 | interface::dbusProperty, "Set"); | 
|  | 460 |  | 
|  | 461 | method.append(interface::operationalStatus, "Functional", variant); | 
|  | 462 | _bus.call(method); | 
|  | 463 | } | 
|  | 464 |  | 
| Matt Spinler | 1ab6696 | 2020-10-29 13:21:44 -0500 | [diff] [blame] | 465 | std::vector<std::string> DataInterface::getSystemNames() const | 
|  | 466 | { | 
|  | 467 | DBusSubTree subtree; | 
|  | 468 | DBusValue names; | 
|  | 469 |  | 
|  | 470 | auto method = _bus.new_method_call(service_name::objectMapper, | 
|  | 471 | object_path::objectMapper, | 
|  | 472 | interface::objectMapper, "GetSubTree"); | 
|  | 473 | method.append(std::string{"/"}, 0, | 
|  | 474 | std::vector<std::string>{interface::compatible}); | 
|  | 475 | auto reply = _bus.call(method); | 
|  | 476 |  | 
|  | 477 | reply.read(subtree); | 
|  | 478 | if (subtree.empty()) | 
|  | 479 | { | 
|  | 480 | throw std::runtime_error("Compatible interface not on D-Bus"); | 
|  | 481 | } | 
|  | 482 |  | 
|  | 483 | const auto& object = *(subtree.begin()); | 
|  | 484 | const auto& path = object.first; | 
|  | 485 | const auto& service = object.second.begin()->first; | 
|  | 486 |  | 
|  | 487 | getProperty(service, path, interface::compatible, "Names", names); | 
|  | 488 |  | 
|  | 489 | return std::get<std::vector<std::string>>(names); | 
|  | 490 | } | 
|  | 491 |  | 
| Matt Spinler | c8705e2 | 2019-09-11 12:36:07 -0500 | [diff] [blame] | 492 | } // namespace pels | 
|  | 493 | } // namespace openpower |