1 #pragma once 2 3 #include "dbus_types.hpp" 4 #include "dbus_watcher.hpp" 5 6 #include <filesystem> 7 #include <phosphor-logging/log.hpp> 8 #include <sdbusplus/bus.hpp> 9 #include <sdbusplus/bus/match.hpp> 10 11 namespace openpower 12 { 13 namespace pels 14 { 15 16 /** 17 * @class DataInterface 18 * 19 * A base class for gathering data about the system for use 20 * in PELs. Implemented this way to facilitate mocking. 21 */ 22 class DataInterfaceBase 23 { 24 public: 25 DataInterfaceBase() = default; 26 virtual ~DataInterfaceBase() = default; 27 DataInterfaceBase(const DataInterfaceBase&) = default; 28 DataInterfaceBase& operator=(const DataInterfaceBase&) = default; 29 DataInterfaceBase(DataInterfaceBase&&) = default; 30 DataInterfaceBase& operator=(DataInterfaceBase&&) = default; 31 32 /** 33 * @brief Returns the machine Type/Model 34 * 35 * @return string - The machine Type/Model string 36 */ 37 virtual std::string getMachineTypeModel() const 38 { 39 return _machineTypeModel; 40 } 41 42 /** 43 * @brief Returns the machine serial number 44 * 45 * @return string - The machine serial number 46 */ 47 virtual std::string getMachineSerialNumber() const 48 { 49 return _machineSerialNumber; 50 } 51 52 /** 53 * @brief Says if the system is managed by a hardware 54 * management console. 55 * @return bool - If the system is HMC managed 56 */ 57 virtual bool isHMCManaged() const 58 { 59 return _hmcManaged; 60 } 61 62 /** 63 * @brief Says if the host is up and running 64 * 65 * @return bool - If the host is running 66 */ 67 virtual bool isHostUp() const 68 { 69 return _hostUp; 70 } 71 72 using HostStateChangeFunc = std::function<void(bool)>; 73 74 /** 75 * @brief Register a callback function that will get 76 * called on all host on/off transitions. 77 * 78 * The void(bool) function will get passed the new 79 * value of the host state. 80 * 81 * @param[in] name - The subscription name 82 * @param[in] func - The function to run 83 */ 84 void subscribeToHostStateChange(const std::string& name, 85 HostStateChangeFunc func) 86 { 87 _hostChangeCallbacks[name] = func; 88 } 89 90 /** 91 * @brief Unsubscribe from host state changes. 92 * 93 * @param[in] name - The subscription name 94 */ 95 void unsubscribeFromHostStateChange(const std::string& name) 96 { 97 _hostChangeCallbacks.erase(name); 98 } 99 100 /** 101 * @brief Returns the BMC firmware version 102 * 103 * @return std::string - The BMC version 104 */ 105 virtual std::string getBMCFWVersion() const 106 { 107 return _bmcFWVersion; 108 } 109 110 /** 111 * @brief Returns the server firmware version 112 * 113 * @return std::string - The server firmware version 114 */ 115 virtual std::string getServerFWVersion() const 116 { 117 return _serverFWVersion; 118 } 119 120 /** 121 * @brief Returns the BMC FW version ID 122 * 123 * @return std::string - The BMC FW version ID 124 */ 125 virtual std::string getBMCFWVersionID() const 126 { 127 return _bmcFWVersionID; 128 } 129 130 /** 131 * @brief Returns the process name given its PID. 132 * 133 * @param[in] pid - The PID value as a string 134 * 135 * @return std::optional<std::string> - The name, or std::nullopt 136 */ 137 std::optional<std::string> getProcessName(const std::string& pid) const 138 { 139 namespace fs = std::filesystem; 140 141 fs::path path{"/proc"}; 142 path /= fs::path{pid} / "exe"; 143 144 if (fs::exists(path)) 145 { 146 return fs::read_symlink(path); 147 } 148 149 return std::nullopt; 150 } 151 152 /** 153 * @brief Returns the 'send event logs to host' setting. 154 * 155 * @return bool - If sending PELs to the host is enabled. 156 */ 157 virtual bool getHostPELEnablement() const 158 { 159 return _sendPELsToHost; 160 } 161 162 /** 163 * @brief Returns the BMC state 164 * 165 * @return std::string - The BMC state property value 166 */ 167 virtual std::string getBMCState() const 168 { 169 return _bmcState; 170 } 171 172 /** 173 * @brief Returns the Chassis state 174 * 175 * @return std::string - The chassis state property value 176 */ 177 virtual std::string getChassisState() const 178 { 179 return _chassisState; 180 } 181 182 /** 183 * @brief Returns the chassis requested power 184 * transition value. 185 * 186 * @return std::string - The chassis transition property 187 */ 188 virtual std::string getChassisTransition() const 189 { 190 return _chassisTransition; 191 } 192 193 /** 194 * @brief Returns the Host state 195 * 196 * @return std::string - The Host state property value 197 */ 198 virtual std::string getHostState() const 199 { 200 return _hostState; 201 } 202 203 /** 204 * @brief Returns the motherboard CCIN 205 * 206 * @return std::string The motherboard CCIN 207 */ 208 virtual std::string getMotherboardCCIN() const 209 { 210 return _motherboardCCIN; 211 } 212 213 protected: 214 /** 215 * @brief Sets the host on/off state and runs any 216 * callback functions (if there was a change). 217 */ 218 void setHostUp(bool hostUp) 219 { 220 if (_hostUp != hostUp) 221 { 222 _hostUp = hostUp; 223 224 for (auto& [name, func] : _hostChangeCallbacks) 225 { 226 try 227 { 228 func(_hostUp); 229 } 230 catch (std::exception& e) 231 { 232 using namespace phosphor::logging; 233 log<level::ERR>("A host state change callback threw " 234 "an exception"); 235 } 236 } 237 } 238 } 239 240 /** 241 * @brief The machine type-model. Always kept up to date 242 */ 243 std::string _machineTypeModel; 244 245 /** 246 * @brief The machine serial number. Always kept up to date 247 */ 248 std::string _machineSerialNumber; 249 250 /** 251 * @brief The hardware management console status. Always kept 252 * up to date. 253 */ 254 bool _hmcManaged = false; 255 256 /** 257 * @brief The host up status. Always kept up to date. 258 */ 259 bool _hostUp = false; 260 261 /** 262 * @brief The map of host state change subscriber 263 * names to callback functions. 264 */ 265 std::map<std::string, HostStateChangeFunc> _hostChangeCallbacks; 266 267 /** 268 * @brief The BMC firmware version string 269 */ 270 std::string _bmcFWVersion; 271 272 /** 273 * @brief The server firmware version string 274 */ 275 std::string _serverFWVersion; 276 277 /** 278 * @brief The BMC firmware version ID string 279 */ 280 std::string _bmcFWVersionID; 281 282 /** 283 * @brief If sending PELs is enabled. 284 * 285 * This is usually set to false in manufacturing test. 286 */ 287 bool _sendPELsToHost = true; 288 289 /** 290 * @brief The BMC state property 291 */ 292 std::string _bmcState; 293 294 /** 295 * @brief The Chassis current power state property 296 */ 297 std::string _chassisState; 298 299 /** 300 * @brief The Chassis requested power transition property 301 */ 302 std::string _chassisTransition; 303 304 /** 305 * @brief The host state property 306 */ 307 std::string _hostState; 308 309 /** 310 * @brief The motherboard CCIN 311 */ 312 std::string _motherboardCCIN; 313 }; 314 315 /** 316 * @class DataInterface 317 * 318 * Concrete implementation of DataInterfaceBase. 319 */ 320 class DataInterface : public DataInterfaceBase 321 { 322 public: 323 DataInterface() = delete; 324 ~DataInterface() = default; 325 DataInterface(const DataInterface&) = default; 326 DataInterface& operator=(const DataInterface&) = default; 327 DataInterface(DataInterface&&) = default; 328 DataInterface& operator=(DataInterface&&) = default; 329 330 /** 331 * @brief Constructor 332 * 333 * @param[in] bus - The sdbusplus bus object 334 */ 335 explicit DataInterface(sdbusplus::bus::bus& bus); 336 337 /** 338 * @brief Finds the D-Bus service name that hosts the 339 * passed in path and interface. 340 * 341 * @param[in] objectPath - The D-Bus object path 342 * @param[in] interface - The D-Bus interface 343 */ 344 DBusService getService(const std::string& objectPath, 345 const std::string& interface) const; 346 347 /** 348 * @brief Wrapper for the 'GetAll' properties method call 349 * 350 * @param[in] service - The D-Bus service to call it on 351 * @param[in] objectPath - The D-Bus object path 352 * @param[in] interface - The interface to get the props on 353 * 354 * @return DBusPropertyMap - The property results 355 */ 356 DBusPropertyMap getAllProperties(const std::string& service, 357 const std::string& objectPath, 358 const std::string& interface) const; 359 /** 360 * @brief Wrapper for the 'Get' properties method call 361 * 362 * @param[in] service - The D-Bus service to call it on 363 * @param[in] objectPath - The D-Bus object path 364 * @param[in] interface - The interface to get the property on 365 * @param[in] property - The property name 366 * @param[out] value - Filled in with the property value. 367 */ 368 void getProperty(const std::string& service, const std::string& objectPath, 369 const std::string& interface, const std::string& property, 370 DBusValue& value) const; 371 372 private: 373 /** 374 * @brief Reads the BMC firmware version string and puts it into 375 * _bmcFWVersion. 376 */ 377 void readBMCFWVersion(); 378 379 /** 380 * @brief Reads the server firmware version string and puts it into 381 * _serverFWVersion. 382 */ 383 void readServerFWVersion(); 384 385 /** 386 * @brief Reads the BMC firmware version ID and puts it into 387 * _bmcFWVersionID. 388 */ 389 void readBMCFWVersionID(); 390 391 /** 392 * @brief Reads the motherboard CCIN and puts it into _motherboardCCIN. 393 * 394 * It finds the motherboard first, possibly having to wait for it to 395 * show up. 396 */ 397 void readMotherboardCCIN(); 398 399 /** 400 * @brief Finds all D-Bus paths that contain any of the interfaces 401 * passed in, by using GetSubTreePaths. 402 * 403 * @param[in] interfaces - The desired interfaces 404 * 405 * @return The D-Bus paths. 406 */ 407 DBusPathList getPaths(const DBusInterfaceList& interfaces) const; 408 409 /** 410 * @brief The interfacesAdded callback used on the inventory to 411 * find the D-Bus object that has the motherboard interface. 412 * When the motherboard is found, it then adds a PropertyWatcher 413 * for the motherboard CCIN. 414 */ 415 void motherboardIfaceAdded(sdbusplus::message::message& msg); 416 417 /** 418 * @brief Set the motherboard CCIN from the DBus variant that 419 * contains it. 420 * 421 * @param[in] ccin - The CCIN variant, a vector<uint8_t>. 422 */ 423 void setMotherboardCCIN(const DBusValue& ccin) 424 { 425 const auto& c = std::get<std::vector<uint8_t>>(ccin); 426 _motherboardCCIN = std::string{c.begin(), c.end()}; 427 } 428 429 /** 430 * @brief The D-Bus property or interface watchers that have callbacks 431 * registered that will set members in this class when 432 * they change. 433 */ 434 std::vector<std::unique_ptr<DBusWatcher>> _properties; 435 436 /** 437 * @brief The sdbusplus bus object for making D-Bus calls. 438 */ 439 sdbusplus::bus::bus& _bus; 440 441 /** 442 * @brief The interfacesAdded match object used to wait for inventory 443 * interfaces to show up, so that the object with the motherboard 444 * interface can be found. After it is found, this object is 445 * deleted. 446 */ 447 std::unique_ptr<sdbusplus::bus::match_t> _inventoryIfacesAddedMatch; 448 }; 449 450 } // namespace pels 451 } // namespace openpower 452