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 = 0; 38 39 /** 40 * @brief Returns the machine serial number 41 * 42 * @return string - The machine serial number 43 */ 44 virtual std::string getMachineSerialNumber() const = 0; 45 46 /** 47 * @brief Says if the system is managed by a hardware 48 * management console. 49 * @return bool - If the system is HMC managed 50 */ 51 virtual bool isHMCManaged() const 52 { 53 return _hmcManaged; 54 } 55 56 /** 57 * @brief Says if the host is up and running 58 * 59 * @return bool - If the host is running 60 */ 61 virtual bool isHostUp() const 62 { 63 return _hostUp; 64 } 65 66 using HostStateChangeFunc = std::function<void(bool)>; 67 68 /** 69 * @brief Register a callback function that will get 70 * called on all host on/off transitions. 71 * 72 * The void(bool) function will get passed the new 73 * value of the host state. 74 * 75 * @param[in] name - The subscription name 76 * @param[in] func - The function to run 77 */ 78 void subscribeToHostStateChange(const std::string& name, 79 HostStateChangeFunc func) 80 { 81 _hostChangeCallbacks[name] = func; 82 } 83 84 /** 85 * @brief Unsubscribe from host state changes. 86 * 87 * @param[in] name - The subscription name 88 */ 89 void unsubscribeFromHostStateChange(const std::string& name) 90 { 91 _hostChangeCallbacks.erase(name); 92 } 93 94 /** 95 * @brief Returns the BMC firmware version 96 * 97 * @return std::string - The BMC version 98 */ 99 virtual std::string getBMCFWVersion() const 100 { 101 return _bmcFWVersion; 102 } 103 104 /** 105 * @brief Returns the server firmware version 106 * 107 * @return std::string - The server firmware version 108 */ 109 virtual std::string getServerFWVersion() const 110 { 111 return _serverFWVersion; 112 } 113 114 /** 115 * @brief Returns the BMC FW version ID 116 * 117 * @return std::string - The BMC FW version ID 118 */ 119 virtual std::string getBMCFWVersionID() const 120 { 121 return _bmcFWVersionID; 122 } 123 124 /** 125 * @brief Returns the process name given its PID. 126 * 127 * @param[in] pid - The PID value as a string 128 * 129 * @return std::optional<std::string> - The name, or std::nullopt 130 */ 131 std::optional<std::string> getProcessName(const std::string& pid) const 132 { 133 namespace fs = std::filesystem; 134 135 fs::path path{"/proc"}; 136 path /= fs::path{pid} / "exe"; 137 138 if (fs::exists(path)) 139 { 140 return fs::read_symlink(path); 141 } 142 143 return std::nullopt; 144 } 145 146 /** 147 * @brief Returns the 'send event logs to host' setting. 148 * 149 * @return bool - If sending PELs to the host is enabled. 150 */ 151 virtual bool getHostPELEnablement() const 152 { 153 return _sendPELsToHost; 154 } 155 156 /** 157 * @brief Returns the BMC state 158 * 159 * @return std::string - The BMC state property value 160 */ 161 virtual std::string getBMCState() const 162 { 163 return _bmcState; 164 } 165 166 /** 167 * @brief Returns the Chassis state 168 * 169 * @return std::string - The chassis state property value 170 */ 171 virtual std::string getChassisState() const 172 { 173 return _chassisState; 174 } 175 176 /** 177 * @brief Returns the chassis requested power 178 * transition value. 179 * 180 * @return std::string - The chassis transition property 181 */ 182 virtual std::string getChassisTransition() const 183 { 184 return _chassisTransition; 185 } 186 187 /** 188 * @brief Returns the Host state 189 * 190 * @return std::string - The Host state property value 191 */ 192 virtual std::string getHostState() const 193 { 194 return _hostState; 195 } 196 197 /** 198 * @brief Returns the motherboard CCIN 199 * 200 * @return std::string The motherboard CCIN 201 */ 202 virtual std::string getMotherboardCCIN() const = 0; 203 204 /** 205 * @brief Get the fields from the inventory necessary for doing 206 * a callout on an inventory path. 207 * 208 * @param[in] inventoryPath - The item to get the data for 209 * @param[out] fruPartNumber - Filled in with the VINI/FN keyword 210 * @param[out] ccin - Filled in with the VINI/CC keyword 211 * @param[out] serialNumber - Filled in with the VINI/SN keyword 212 */ 213 virtual void getHWCalloutFields(const std::string& inventoryPath, 214 std::string& fruPartNumber, 215 std::string& ccin, 216 std::string& serialNumber) const = 0; 217 218 /** 219 * @brief Get the location code for an inventory item. 220 * 221 * @param[in] inventoryPath - The item to get the data for 222 * 223 * @return std::string - The location code 224 */ 225 virtual std::string 226 getLocationCode(const std::string& inventoryPath) const = 0; 227 228 /** 229 * @brief Get the list of system type names the system is called. 230 * 231 * @return std::vector<std::string> - The list of names 232 */ 233 virtual std::vector<std::string> getSystemNames() const = 0; 234 235 /** 236 * @brief Fills in the placeholder 'Ufcs' in the passed in location 237 * code with the machine feature code and serial number, which 238 * is needed to create a valid location code. 239 * 240 * @param[in] locationCode - Location code value starting with Ufcs-, and 241 * if that isn't present it will be added first. 242 * 243 * @param[in] node - The node number the location is on. 244 * 245 * @return std::string - The expanded location code 246 */ 247 virtual std::string expandLocationCode(const std::string& locationCode, 248 uint16_t node) const = 0; 249 250 /** 251 * @brief Returns the inventory path for the FRU that the location 252 * code represents. 253 * 254 * @param[in] locationCode - If an expanded location code, then the 255 * full location code. 256 * If not expanded, a location code value 257 * starting with Ufcs-, and if that isn't 258 * present it will be added first. 259 * 260 * @param[in] node - The node number the location is on. Ignored if the 261 * expanded location code is passed in. 262 * 263 * @param[in] expanded - If the location code already has the relevent 264 * VPD fields embedded in it. 265 * 266 * @return std::string - The inventory D-Bus object 267 */ 268 virtual std::string getInventoryFromLocCode(const std::string& LocationCode, 269 uint16_t node, 270 bool expanded) const = 0; 271 272 /** 273 * @brief Sets the Asserted property on the LED group passed in. 274 * 275 * @param[in] ledGroup - The LED group D-Bus path 276 * @param[in] value - The value to set it to 277 */ 278 virtual void assertLEDGroup(const std::string& ledGroup, 279 bool value) const = 0; 280 281 /** 282 * @brief Sets the Functional property on the OperationalStatus 283 * interface on a D-Bus object. 284 * 285 * @param[in] objectPath - The D-Bus object path 286 * @param[in] functional - The value 287 */ 288 virtual void setFunctional(const std::string& objectPath, 289 bool functional) const = 0; 290 291 protected: 292 /** 293 * @brief Sets the host on/off state and runs any 294 * callback functions (if there was a change). 295 */ 296 void setHostUp(bool hostUp) 297 { 298 if (_hostUp != hostUp) 299 { 300 _hostUp = hostUp; 301 302 for (auto& [name, func] : _hostChangeCallbacks) 303 { 304 try 305 { 306 func(_hostUp); 307 } 308 catch (std::exception& e) 309 { 310 using namespace phosphor::logging; 311 log<level::ERR>("A host state change callback threw " 312 "an exception"); 313 } 314 } 315 } 316 } 317 318 /** 319 * @brief The hardware management console status. Always kept 320 * up to date. 321 */ 322 bool _hmcManaged = false; 323 324 /** 325 * @brief The host up status. Always kept up to date. 326 */ 327 bool _hostUp = false; 328 329 /** 330 * @brief The map of host state change subscriber 331 * names to callback functions. 332 */ 333 std::map<std::string, HostStateChangeFunc> _hostChangeCallbacks; 334 335 /** 336 * @brief The BMC firmware version string 337 */ 338 std::string _bmcFWVersion; 339 340 /** 341 * @brief The server firmware version string 342 */ 343 std::string _serverFWVersion; 344 345 /** 346 * @brief The BMC firmware version ID string 347 */ 348 std::string _bmcFWVersionID; 349 350 /** 351 * @brief If sending PELs is enabled. 352 * 353 * This is usually set to false in manufacturing test. 354 */ 355 bool _sendPELsToHost = true; 356 357 /** 358 * @brief The BMC state property 359 */ 360 std::string _bmcState; 361 362 /** 363 * @brief The Chassis current power state property 364 */ 365 std::string _chassisState; 366 367 /** 368 * @brief The Chassis requested power transition property 369 */ 370 std::string _chassisTransition; 371 372 /** 373 * @brief The host state property 374 */ 375 std::string _hostState; 376 }; 377 378 /** 379 * @class DataInterface 380 * 381 * Concrete implementation of DataInterfaceBase. 382 */ 383 class DataInterface : public DataInterfaceBase 384 { 385 public: 386 DataInterface() = delete; 387 ~DataInterface() = default; 388 DataInterface(const DataInterface&) = default; 389 DataInterface& operator=(const DataInterface&) = default; 390 DataInterface(DataInterface&&) = default; 391 DataInterface& operator=(DataInterface&&) = default; 392 393 /** 394 * @brief Constructor 395 * 396 * @param[in] bus - The sdbusplus bus object 397 */ 398 explicit DataInterface(sdbusplus::bus::bus& bus); 399 400 /** 401 * @brief Finds the D-Bus service name that hosts the 402 * passed in path and interface. 403 * 404 * @param[in] objectPath - The D-Bus object path 405 * @param[in] interface - The D-Bus interface 406 */ 407 DBusService getService(const std::string& objectPath, 408 const std::string& interface) const; 409 410 /** 411 * @brief Wrapper for the 'GetAll' properties method call 412 * 413 * @param[in] service - The D-Bus service to call it on 414 * @param[in] objectPath - The D-Bus object path 415 * @param[in] interface - The interface to get the props on 416 * 417 * @return DBusPropertyMap - The property results 418 */ 419 DBusPropertyMap getAllProperties(const std::string& service, 420 const std::string& objectPath, 421 const std::string& interface) const; 422 /** 423 * @brief Wrapper for the 'Get' properties method call 424 * 425 * @param[in] service - The D-Bus service to call it on 426 * @param[in] objectPath - The D-Bus object path 427 * @param[in] interface - The interface to get the property on 428 * @param[in] property - The property name 429 * @param[out] value - Filled in with the property value. 430 */ 431 void getProperty(const std::string& service, const std::string& objectPath, 432 const std::string& interface, const std::string& property, 433 DBusValue& value) const; 434 /** 435 * @brief Returns the machine Type/Model 436 * 437 * @return string - The machine Type/Model string 438 */ 439 std::string getMachineTypeModel() const override; 440 441 /** 442 * @brief Returns the machine serial number 443 * 444 * @return string - The machine serial number 445 */ 446 std::string getMachineSerialNumber() const override; 447 448 /** 449 * @brief Returns the motherboard CCIN 450 * 451 * @return std::string The motherboard CCIN 452 */ 453 std::string getMotherboardCCIN() const override; 454 455 /** 456 * @brief Get the fields from the inventory necessary for doing 457 * a callout on an inventory path. 458 * 459 * @param[in] inventoryPath - The item to get the data for 460 * @param[out] fruPartNumber - Filled in with the VINI/FN keyword 461 * @param[out] ccin - Filled in with the VINI/CC keyword 462 * @param[out] serialNumber - Filled in with the VINI/SN keyword 463 */ 464 void getHWCalloutFields(const std::string& inventoryPath, 465 std::string& fruPartNumber, std::string& ccin, 466 std::string& serialNumber) const override; 467 468 /** 469 * @brief Get the location code for an inventory item. 470 * 471 * Throws an exception if the inventory item doesn't have the 472 * location code interface. 473 * 474 * @param[in] inventoryPath - The item to get the data for 475 * 476 * @return std::string - The location code 477 */ 478 std::string 479 getLocationCode(const std::string& inventoryPath) const override; 480 481 /** 482 * @brief Get the list of system type names the system is called. 483 * 484 * @return std::vector<std::string> - The list of names 485 */ 486 std::vector<std::string> getSystemNames() const override; 487 488 /** 489 * @brief Fills in the placeholder 'Ufcs' in the passed in location 490 * code with the machine feature code and serial number, which 491 * is needed to create a valid location code. 492 * 493 * @param[in] locationCode - Location code value starting with Ufcs-, and 494 * if that isn't present it will be added first. 495 * 496 * @param[in] node - The node number the location is one. 497 * 498 * @return std::string - The expanded location code 499 */ 500 std::string expandLocationCode(const std::string& locationCode, 501 uint16_t node) const override; 502 503 /** 504 * @brief Returns the inventory path for the FRU that the location 505 * code represents. 506 * 507 * @param[in] locationCode - If an expanded location code, then the 508 * full location code. 509 * If not expanded, a location code value 510 * starting with Ufcs-, and if that isn't 511 * present it will be added first. 512 * 513 * @param[in] node - The node number the location is on. Ignored if the 514 * expanded location code is passed in. 515 * 516 * @param[in] expanded - If the location code already has the relevent 517 * VPD fields embedded in it. 518 * 519 * @return std::string - The inventory D-Bus object 520 */ 521 std::string getInventoryFromLocCode(const std::string& locationCode, 522 uint16_t node, 523 bool expanded) const override; 524 525 /** 526 * @brief Sets the Asserted property on the LED group passed in. 527 * 528 * @param[in] ledGroup - The LED group D-Bus path 529 * @param[in] value - The value to set it to 530 */ 531 void assertLEDGroup(const std::string& ledGroup, bool value) const override; 532 533 /** 534 * @brief Sets the Functional property on the OperationalStatus 535 * interface on a D-Bus object. 536 * 537 * @param[in] objectPath - The D-Bus object path 538 * @param[in] functional - The value 539 */ 540 void setFunctional(const std::string& objectPath, 541 bool functional) const override; 542 543 private: 544 /** 545 * @brief Reads the BMC firmware version string and puts it into 546 * _bmcFWVersion. 547 */ 548 void readBMCFWVersion(); 549 550 /** 551 * @brief Reads the server firmware version string and puts it into 552 * _serverFWVersion. 553 */ 554 void readServerFWVersion(); 555 556 /** 557 * @brief Reads the BMC firmware version ID and puts it into 558 * _bmcFWVersionID. 559 */ 560 void readBMCFWVersionID(); 561 562 /** 563 * @brief Finds all D-Bus paths that contain any of the interfaces 564 * passed in, by using GetSubTreePaths. 565 * 566 * @param[in] interfaces - The desired interfaces 567 * 568 * @return The D-Bus paths. 569 */ 570 DBusPathList getPaths(const DBusInterfaceList& interfaces) const; 571 572 /** 573 * @brief The interfacesAdded callback used on the inventory to 574 * find the D-Bus object that has the motherboard interface. 575 * When the motherboard is found, it then adds a PropertyWatcher 576 * for the motherboard CCIN. 577 */ 578 void motherboardIfaceAdded(sdbusplus::message::message& msg); 579 580 /** 581 * @brief Adds the Ufcs- prefix to the location code passed in 582 * if necessary. 583 * 584 * Needed because the location codes that come back from the 585 * message registry and device callout JSON don't have it. 586 * 587 * @param[in] - The location code without a prefix, like P1-C1 588 * 589 * @return std::string - The location code with the prefix 590 */ 591 static std::string addLocationCodePrefix(const std::string& locationCode); 592 593 /** 594 * @brief The D-Bus property or interface watchers that have callbacks 595 * registered that will set members in this class when 596 * they change. 597 */ 598 std::vector<std::unique_ptr<DBusWatcher>> _properties; 599 600 /** 601 * @brief The sdbusplus bus object for making D-Bus calls. 602 */ 603 sdbusplus::bus::bus& _bus; 604 605 /** 606 * @brief The interfacesAdded match object used to wait for inventory 607 * interfaces to show up, so that the object with the motherboard 608 * interface can be found. After it is found, this object is 609 * deleted. 610 */ 611 std::unique_ptr<sdbusplus::bus::match_t> _inventoryIfacesAddedMatch; 612 }; 613 614 } // namespace pels 615 } // namespace openpower 616