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