1 #pragma once 2 3 #include "config.h" 4 5 #include <sdbusplus/bus.hpp> 6 #include <sdbusplus/server/object.hpp> 7 #include <sdbusplus/timer.hpp> 8 #include <xyz/openbmc_project/Control/Host/server.hpp> 9 #include <xyz/openbmc_project/Ipmi/Internal/SoftPowerOff/server.hpp> 10 11 #include <functional> 12 namespace phosphor 13 { 14 namespace ipmi 15 { 16 17 namespace Base = sdbusplus::server::xyz::openbmc_project::ipmi::internal; 18 using namespace sdbusplus::server::xyz::openbmc_project::control; 19 20 namespace sdbusRule = sdbusplus::bus::match::rules; 21 22 namespace 23 { 24 using SoftPowerOffInherit = sdbusplus::server::object_t<Base::SoftPowerOff>; 25 } 26 27 /** @class SoftPowerOff 28 * @brief Responsible for coordinating Host SoftPowerOff operation 29 */ 30 class SoftPowerOff : public SoftPowerOffInherit 31 { 32 public: 33 /** @brief Constructs SoftPowerOff object. 34 * 35 * @param[in] bus - system dbus handler 36 * @param[in] event - sd_event handler 37 * @param[in] objPath - The Dbus path hosting SoftPowerOff function 38 */ SoftPowerOff(sdbusplus::bus_t & bus,sd_event * event,const char * objPath)39 SoftPowerOff(sdbusplus::bus_t& bus, sd_event* event, const char* objPath) : 40 SoftPowerOffInherit(bus, objPath, 41 SoftPowerOffInherit::action::defer_emit), 42 bus(bus), timer(event), 43 hostControlSignal( 44 bus, 45 sdbusRule::type::signal() + sdbusRule::member("CommandComplete") + 46 sdbusRule::path("/xyz/openbmc_project/control/host0") + 47 sdbusRule::interface(CONTROL_HOST_BUSNAME) + 48 sdbusRule::argN(0, convertForMessage(Host::Command::SoftOff)), 49 std::bind(std::mem_fn(&SoftPowerOff::hostControlEvent), this, 50 std::placeholders::_1)) 51 { 52 // Need to announce since we may get the response 53 // very quickly on host shutdown command 54 emit_object_added(); 55 56 // The whole purpose of this application is to send a host shutdown 57 // command and watch for the soft power off to go through. We need 58 // the interface added signal emitted before we send the shutdown 59 // command just to attend to lightning fast response from host 60 sendHostShutDownCmd(); 61 } 62 63 /** @brief Tells if the objective of this application is completed */ isCompleted()64 inline auto isCompleted() 65 { 66 return completed; 67 } 68 69 /** @brief Tells if the referenced timer is expired or not */ isTimerExpired()70 inline auto isTimerExpired() 71 { 72 return timer.isExpired(); 73 } 74 75 /** @brief overloaded property setter function 76 * 77 * @param[in] value - One of SoftOffReceived / HostShutdown 78 * 79 * @return Success or exception thrown 80 */ 81 HostResponse responseReceived(HostResponse value) override; 82 83 /** @brief Using the base class's getter method */ 84 using Base::SoftPowerOff::responseReceived; 85 86 /** @brief Calls to start a timer 87 * 88 * @param[in] usec - Time in microseconds 89 * 90 * @return Success or exception thrown 91 */ 92 int startTimer(const std::chrono::microseconds& usec); 93 94 private: 95 // Need this to send SMS_ATTN 96 // TODO : Switch over to using mapper service in a different patch 97 static constexpr auto HOST_IPMI_BUS = "org.openbmc.HostIpmi"; 98 static constexpr auto HOST_IPMI_OBJ = "/org/openbmc/HostIpmi/1"; 99 static constexpr auto HOST_IPMI_INTF = "org.openbmc.HostIpmi"; 100 101 /* @brief sdbusplus handle */ 102 sdbusplus::bus_t& bus; 103 104 /** @brief Reference to Timer object */ 105 sdbusplus::Timer timer; 106 107 /** @brief Marks the end of life of this application. 108 * 109 * This is set to true if host gives appropriate responses 110 * for the sequence of commands. 111 */ 112 bool completed = false; 113 114 /** @brief Subscribe to host control signals 115 * 116 * Protocol is to send the host power off request to the host 117 * control interface and then wait for a signal indicating pass/fail 118 **/ 119 sdbusplus::bus::match_t hostControlSignal; 120 121 /** @brief Sends host control command to tell host to shut down 122 * 123 * After sending the command, wait for a signal indicating the status 124 * of the command. 125 * 126 * After receiving the initial response, start a timer for 30 minutes 127 * to let host do a clean shutdown of partitions. When the response is 128 * received from the host, it indicates that BMC can do a power off. 129 * If BMC fails to get any response, then a hard power off would 130 * be forced. 131 * 132 * @return - Does not return anything. Error will result in exception 133 * being thrown 134 */ 135 void sendHostShutDownCmd(); 136 137 /** @brief Callback function on host control signals 138 * 139 * @param[in] msg - Data associated with subscribed signal 140 * 141 */ 142 void hostControlEvent(sdbusplus::message_t& msg); 143 }; 144 } // namespace ipmi 145 } // namespace phosphor 146