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 Boot state 199 * 200 * @return std::string - The Boot state property value 201 */ 202 virtual std::string getBootState() const 203 { 204 return _bootState; 205 } 206 207 /** 208 * @brief Returns the motherboard CCIN 209 * 210 * @return std::string The motherboard CCIN 211 */ 212 virtual std::string getMotherboardCCIN() const = 0; 213 214 /** 215 * @brief Returns the system IM 216 * 217 * @return std::string The system IM 218 */ 219 virtual std::vector<uint8_t> getSystemIMKeyword() const = 0; 220 221 /** 222 * @brief Get the fields from the inventory necessary for doing 223 * a callout on an inventory path. 224 * 225 * @param[in] inventoryPath - The item to get the data for 226 * @param[out] fruPartNumber - Filled in with the VINI/FN keyword 227 * @param[out] ccin - Filled in with the VINI/CC keyword 228 * @param[out] serialNumber - Filled in with the VINI/SN keyword 229 */ 230 virtual void getHWCalloutFields(const std::string& inventoryPath, 231 std::string& fruPartNumber, 232 std::string& ccin, 233 std::string& serialNumber) const = 0; 234 235 /** 236 * @brief Get the location code for an inventory item. 237 * 238 * @param[in] inventoryPath - The item to get the data for 239 * 240 * @return std::string - The location code 241 */ 242 virtual std::string 243 getLocationCode(const std::string& inventoryPath) const = 0; 244 245 /** 246 * @brief Get the list of system type names the system is called. 247 * 248 * @return std::vector<std::string> - The list of names 249 */ 250 virtual std::vector<std::string> getSystemNames() const = 0; 251 252 /** 253 * @brief Fills in the placeholder 'Ufcs' in the passed in location 254 * code with the machine feature code and serial number, which 255 * is needed to create a valid location code. 256 * 257 * @param[in] locationCode - Location code value starting with Ufcs-, and 258 * if that isn't present it will be added first. 259 * 260 * @param[in] node - The node number the location is on. 261 * 262 * @return std::string - The expanded location code 263 */ 264 virtual std::string expandLocationCode(const std::string& locationCode, 265 uint16_t node) const = 0; 266 267 /** 268 * @brief Returns the inventory path for the FRU that the location 269 * code represents. 270 * 271 * @param[in] locationCode - If an expanded location code, then the 272 * full location code. 273 * If not expanded, a location code value 274 * starting with Ufcs-, and if that isn't 275 * present it will be added first. 276 * 277 * @param[in] node - The node number the location is on. Ignored if the 278 * expanded location code is passed in. 279 * 280 * @param[in] expanded - If the location code already has the relevent 281 * VPD fields embedded in it. 282 * 283 * @return std::string - The inventory D-Bus object 284 */ 285 virtual std::string getInventoryFromLocCode(const std::string& LocationCode, 286 uint16_t node, 287 bool expanded) const = 0; 288 289 /** 290 * @brief Sets the Asserted property on the LED group passed in. 291 * 292 * @param[in] ledGroup - The LED group D-Bus path 293 * @param[in] value - The value to set it to 294 */ 295 virtual void assertLEDGroup(const std::string& ledGroup, 296 bool value) const = 0; 297 298 /** 299 * @brief Sets the Functional property on the OperationalStatus 300 * interface on a D-Bus object. 301 * 302 * @param[in] objectPath - The D-Bus object path 303 * @param[in] functional - The value 304 */ 305 virtual void setFunctional(const std::string& objectPath, 306 bool functional) const = 0; 307 308 /** 309 * @brief Sets the critical association on the D-Bus object. 310 * 311 * @param[in] objectPath - The D-Bus object path 312 */ 313 virtual void 314 setCriticalAssociation(const std::string& objectPath) const = 0; 315 316 /** 317 * @brief Returns the manufacturing QuiesceOnError property 318 * 319 * @return bool - Manufacturing QuiesceOnError property 320 */ 321 virtual bool getQuiesceOnError() const = 0; 322 323 /** 324 * @brief Split location code into base and connector segments 325 * 326 * A location code that ends in '-Tx', where 'x' is a number, 327 * represents a connector, such as a USB cable connector. 328 * 329 * This function splits the passed in location code into a 330 * base and connector segment. e.g.: 331 * P0-T1 -> ['P0', '-T1'] 332 * P0 -> ['P0', ''] 333 * 334 * @param[in] locationCode - location code to split 335 * @return pair<string, string> - The base and connector segments 336 */ 337 static std::pair<std::string, std::string> 338 extractConnectorFromLocCode(const std::string& locationCode); 339 340 /** 341 * @brief Returns the dump status 342 * 343 * @return bool dump status 344 */ 345 virtual std::vector<bool> 346 checkDumpStatus(const std::vector<std::string>& type) const = 0; 347 348 /** 349 * @brief Create guard record 350 * 351 * @param[in] binPath: phal devtree binary path used as key 352 * @param[in] type: Guard type 353 * @param[in] logPath: error log entry object path 354 */ 355 virtual void createGuardRecord(const std::vector<uint8_t>& binPath, 356 const std::string& type, 357 const std::string& logPath) const = 0; 358 359 /** 360 * @brief Create Progress SRC property on the boot progress 361 * interface on a D-Bus object. 362 * 363 * @param[in] priSRC - Primary SRC value (e.g. BD8D1001) 364 * @param[in] srcStruct - Full SRC base structure 365 */ 366 virtual void 367 createProgressSRC(const uint64_t& priSRC, 368 const std::vector<uint8_t>& srcStruct) const = 0; 369 370 /** 371 * @brief Get the list of unresolved OpenBMC event log ids that have an 372 * associated hardware isolation entry. 373 * 374 * @return std::vector<uint32_t> - The list of log ids 375 */ 376 virtual std::vector<uint32_t> getLogIDWithHwIsolation() const = 0; 377 378 protected: 379 /** 380 * @brief Sets the host on/off state and runs any 381 * callback functions (if there was a change). 382 */ 383 void setHostUp(bool hostUp) 384 { 385 if (_hostUp != hostUp) 386 { 387 _hostUp = hostUp; 388 389 for (auto& [name, func] : _hostChangeCallbacks) 390 { 391 try 392 { 393 func(_hostUp); 394 } 395 catch (const std::exception& e) 396 { 397 using namespace phosphor::logging; 398 log<level::ERR>("A host state change callback threw " 399 "an exception"); 400 } 401 } 402 } 403 } 404 405 /** 406 * @brief The hardware management console status. Always kept 407 * up to date. 408 */ 409 bool _hmcManaged = false; 410 411 /** 412 * @brief The host up status. Always kept up to date. 413 */ 414 bool _hostUp = false; 415 416 /** 417 * @brief The map of host state change subscriber 418 * names to callback functions. 419 */ 420 std::map<std::string, HostStateChangeFunc> _hostChangeCallbacks; 421 422 /** 423 * @brief The BMC firmware version string 424 */ 425 std::string _bmcFWVersion; 426 427 /** 428 * @brief The server firmware version string 429 */ 430 std::string _serverFWVersion; 431 432 /** 433 * @brief The BMC firmware version ID string 434 */ 435 std::string _bmcFWVersionID; 436 437 /** 438 * @brief If sending PELs is enabled. 439 * 440 * This is usually set to false in manufacturing test. 441 */ 442 bool _sendPELsToHost = true; 443 444 /** 445 * @brief The BMC state property 446 */ 447 std::string _bmcState; 448 449 /** 450 * @brief The Chassis current power state property 451 */ 452 std::string _chassisState; 453 454 /** 455 * @brief The Chassis requested power transition property 456 */ 457 std::string _chassisTransition; 458 459 /** 460 * @brief The host state property 461 */ 462 std::string _hostState; 463 464 /** 465 * @brief The boot state property 466 */ 467 std::string _bootState; 468 }; 469 470 /** 471 * @class DataInterface 472 * 473 * Concrete implementation of DataInterfaceBase. 474 */ 475 class DataInterface : public DataInterfaceBase 476 { 477 public: 478 DataInterface() = delete; 479 ~DataInterface() = default; 480 DataInterface(const DataInterface&) = default; 481 DataInterface& operator=(const DataInterface&) = default; 482 DataInterface(DataInterface&&) = default; 483 DataInterface& operator=(DataInterface&&) = default; 484 485 /** 486 * @brief Constructor 487 * 488 * @param[in] bus - The sdbusplus bus object 489 */ 490 explicit DataInterface(sdbusplus::bus::bus& bus); 491 492 /** 493 * @brief Finds the D-Bus service name that hosts the 494 * passed in path and interface. 495 * 496 * @param[in] objectPath - The D-Bus object path 497 * @param[in] interface - The D-Bus interface 498 */ 499 DBusService getService(const std::string& objectPath, 500 const std::string& interface) const; 501 502 /** 503 * @brief Wrapper for the 'GetAll' properties method call 504 * 505 * @param[in] service - The D-Bus service to call it on 506 * @param[in] objectPath - The D-Bus object path 507 * @param[in] interface - The interface to get the props on 508 * 509 * @return DBusPropertyMap - The property results 510 */ 511 DBusPropertyMap getAllProperties(const std::string& service, 512 const std::string& objectPath, 513 const std::string& interface) const; 514 /** 515 * @brief Wrapper for the 'Get' properties method call 516 * 517 * @param[in] service - The D-Bus service to call it on 518 * @param[in] objectPath - The D-Bus object path 519 * @param[in] interface - The interface to get the property on 520 * @param[in] property - The property name 521 * @param[out] value - Filled in with the property value. 522 */ 523 void getProperty(const std::string& service, const std::string& objectPath, 524 const std::string& interface, const std::string& property, 525 DBusValue& value) const; 526 /** 527 * @brief Returns the machine Type/Model 528 * 529 * @return string - The machine Type/Model string 530 */ 531 std::string getMachineTypeModel() const override; 532 533 /** 534 * @brief Returns the machine serial number 535 * 536 * @return string - The machine serial number 537 */ 538 std::string getMachineSerialNumber() const override; 539 540 /** 541 * @brief Returns the motherboard CCIN 542 * 543 * @return std::string The motherboard CCIN 544 */ 545 std::string getMotherboardCCIN() const override; 546 547 /** 548 * @brief Returns the system IM 549 * 550 * @return std::vector The system IM keyword in 4 byte vector 551 */ 552 std::vector<uint8_t> getSystemIMKeyword() const override; 553 554 /** 555 * @brief Get the fields from the inventory necessary for doing 556 * a callout on an inventory path. 557 * 558 * @param[in] inventoryPath - The item to get the data for 559 * @param[out] fruPartNumber - Filled in with the VINI/FN keyword 560 * @param[out] ccin - Filled in with the VINI/CC keyword 561 * @param[out] serialNumber - Filled in with the VINI/SN keyword 562 */ 563 void getHWCalloutFields(const std::string& inventoryPath, 564 std::string& fruPartNumber, std::string& ccin, 565 std::string& serialNumber) const override; 566 567 /** 568 * @brief Get the location code for an inventory item. 569 * 570 * Throws an exception if the inventory item doesn't have the 571 * location code interface. 572 * 573 * @param[in] inventoryPath - The item to get the data for 574 * 575 * @return std::string - The location code 576 */ 577 std::string 578 getLocationCode(const std::string& inventoryPath) const override; 579 580 /** 581 * @brief Get the list of system type names the system is called. 582 * 583 * @return std::vector<std::string> - The list of names 584 */ 585 std::vector<std::string> getSystemNames() const override; 586 587 /** 588 * @brief Fills in the placeholder 'Ufcs' in the passed in location 589 * code with the machine feature code and serial number, which 590 * is needed to create a valid location code. 591 * 592 * @param[in] locationCode - Location code value starting with Ufcs-, and 593 * if that isn't present it will be added first. 594 * 595 * @param[in] node - The node number the location is one. 596 * 597 * @return std::string - The expanded location code 598 */ 599 std::string expandLocationCode(const std::string& locationCode, 600 uint16_t node) const override; 601 602 /** 603 * @brief Returns the inventory path for the FRU that the location 604 * code represents. 605 * 606 * @param[in] locationCode - If an expanded location code, then the 607 * full location code. 608 * If not expanded, a location code value 609 * starting with Ufcs-, and if that isn't 610 * present it will be added first. 611 * 612 * @param[in] node - The node number the location is on. Ignored if the 613 * expanded location code is passed in. 614 * 615 * @param[in] expanded - If the location code already has the relevent 616 * VPD fields embedded in it. 617 * 618 * @return std::string - The inventory D-Bus object 619 */ 620 std::string getInventoryFromLocCode(const std::string& locationCode, 621 uint16_t node, 622 bool expanded) const override; 623 624 /** 625 * @brief Sets the Asserted property on the LED group passed in. 626 * 627 * @param[in] ledGroup - The LED group D-Bus path 628 * @param[in] value - The value to set it to 629 */ 630 void assertLEDGroup(const std::string& ledGroup, bool value) const override; 631 632 /** 633 * @brief Sets the Functional property on the OperationalStatus 634 * interface on a D-Bus object. 635 * 636 * @param[in] objectPath - The D-Bus object path 637 * @param[in] functional - The value 638 */ 639 void setFunctional(const std::string& objectPath, 640 bool functional) const override; 641 642 /** 643 * @brief Sets the critical association on the D-Bus object. 644 * 645 * @param[in] objectPath - The D-Bus object path 646 */ 647 void setCriticalAssociation(const std::string& objectPath) const override; 648 649 /** 650 * @brief Returns the manufacturing QuiesceOnError property 651 * 652 * @return bool - Manufacturing QuiesceOnError property 653 */ 654 bool getQuiesceOnError() const override; 655 656 /** 657 * @brief Returns the dump status 658 * 659 * @param[in] type - The dump type to check for 660 * 661 * @return bool dump status 662 */ 663 std::vector<bool> 664 checkDumpStatus(const std::vector<std::string>& type) const override; 665 666 /** 667 * @brief Create guard record 668 * 669 * @param[in] binPath: phal devtree binary path used as key 670 * @param[in] type: Guard type 671 * @param[in] logPath: error log entry object path 672 */ 673 void createGuardRecord(const std::vector<uint8_t>& binPath, 674 const std::string& type, 675 const std::string& logPath) const override; 676 677 /** 678 * @brief Create Progress SRC property on the boot progress 679 * interface on a D-Bus object. 680 * 681 * @param[in] priSRC - Primary SRC value 682 * @param[in] srcStruct - Full SRC base structure 683 */ 684 void 685 createProgressSRC(const uint64_t& priSRC, 686 const std::vector<uint8_t>& srcStruct) const override; 687 688 /** 689 * @brief Get the list of unresolved OpenBMC event log ids that have an 690 * associated hardware isolation entry. 691 * 692 * @return std::vector<uint32_t> - The list of log ids 693 */ 694 std::vector<uint32_t> getLogIDWithHwIsolation() const override; 695 696 private: 697 /** 698 * @brief Reads the BMC firmware version string and puts it into 699 * _bmcFWVersion. 700 */ 701 void readBMCFWVersion(); 702 703 /** 704 * @brief Reads the server firmware version string and puts it into 705 * _serverFWVersion. 706 */ 707 void readServerFWVersion(); 708 709 /** 710 * @brief Reads the BMC firmware version ID and puts it into 711 * _bmcFWVersionID. 712 */ 713 void readBMCFWVersionID(); 714 715 /** 716 * @brief Finds all D-Bus paths that contain any of the interfaces 717 * passed in, by using GetSubTreePaths. 718 * 719 * @param[in] interfaces - The desired interfaces 720 * 721 * @return The D-Bus paths. 722 */ 723 DBusPathList getPaths(const DBusInterfaceList& interfaces) const; 724 725 /** 726 * @brief The interfacesAdded callback used on the inventory to 727 * find the D-Bus object that has the motherboard interface. 728 * When the motherboard is found, it then adds a PropertyWatcher 729 * for the motherboard CCIN. 730 */ 731 void motherboardIfaceAdded(sdbusplus::message::message& msg); 732 733 /** 734 * @brief Adds the Ufcs- prefix to the location code passed in 735 * if necessary. 736 * 737 * Needed because the location codes that come back from the 738 * message registry and device callout JSON don't have it. 739 * 740 * @param[in] - The location code without a prefix, like P1-C1 741 * 742 * @return std::string - The location code with the prefix 743 */ 744 static std::string addLocationCodePrefix(const std::string& locationCode); 745 746 /** 747 * @brief The D-Bus property or interface watchers that have callbacks 748 * registered that will set members in this class when 749 * they change. 750 */ 751 std::vector<std::unique_ptr<DBusWatcher>> _properties; 752 753 /** 754 * @brief The sdbusplus bus object for making D-Bus calls. 755 */ 756 sdbusplus::bus::bus& _bus; 757 758 /** 759 * @brief The interfacesAdded match object used to wait for inventory 760 * interfaces to show up, so that the object with the motherboard 761 * interface can be found. After it is found, this object is 762 * deleted. 763 */ 764 std::unique_ptr<sdbusplus::bus::match_t> _inventoryIfacesAddedMatch; 765 }; 766 767 } // namespace pels 768 } // namespace openpower 769