| #pragma once |
| |
| #include "config.h" |
| |
| #include <sdbusplus/bus.hpp> |
| #include <sdbusplus/server/object.hpp> |
| #include <sdbusplus/timer.hpp> |
| #include <xyz/openbmc_project/Control/Host/server.hpp> |
| #include <xyz/openbmc_project/Ipmi/Internal/SoftPowerOff/server.hpp> |
| |
| #include <functional> |
| namespace phosphor |
| { |
| namespace ipmi |
| { |
| |
| namespace Base = sdbusplus::server::xyz::openbmc_project::ipmi::internal; |
| using namespace sdbusplus::server::xyz::openbmc_project::control; |
| |
| namespace sdbusRule = sdbusplus::bus::match::rules; |
| |
| namespace |
| { |
| using SoftPowerOffInherit = sdbusplus::server::object_t<Base::SoftPowerOff>; |
| } |
| |
| /** @class SoftPowerOff |
| * @brief Responsible for coordinating Host SoftPowerOff operation |
| */ |
| class SoftPowerOff : public SoftPowerOffInherit |
| { |
| public: |
| /** @brief Constructs SoftPowerOff object. |
| * |
| * @param[in] bus - system dbus handler |
| * @param[in] event - sd_event handler |
| * @param[in] objPath - The Dbus path hosting SoftPowerOff function |
| */ |
| SoftPowerOff(sdbusplus::bus_t& bus, sd_event* event, const char* objPath) : |
| SoftPowerOffInherit(bus, objPath, |
| SoftPowerOffInherit::action::defer_emit), |
| bus(bus), timer(event), |
| hostControlSignal( |
| bus, |
| sdbusRule::type::signal() + sdbusRule::member("CommandComplete") + |
| sdbusRule::path("/xyz/openbmc_project/control/host0") + |
| sdbusRule::interface(CONTROL_HOST_BUSNAME) + |
| sdbusRule::argN(0, convertForMessage(Host::Command::SoftOff)), |
| std::bind(std::mem_fn(&SoftPowerOff::hostControlEvent), this, |
| std::placeholders::_1)) |
| { |
| // Need to announce since we may get the response |
| // very quickly on host shutdown command |
| emit_object_added(); |
| |
| // The whole purpose of this application is to send a host shutdown |
| // command and watch for the soft power off to go through. We need |
| // the interface added signal emitted before we send the shutdown |
| // command just to attend to lightning fast response from host |
| sendHostShutDownCmd(); |
| } |
| |
| /** @brief Tells if the objective of this application is completed */ |
| inline auto isCompleted() |
| { |
| return completed; |
| } |
| |
| /** @brief Tells if the referenced timer is expired or not */ |
| inline auto isTimerExpired() |
| { |
| return timer.isExpired(); |
| } |
| |
| /** @brief overloaded property setter function |
| * |
| * @param[in] value - One of SoftOffReceived / HostShutdown |
| * |
| * @return Success or exception thrown |
| */ |
| HostResponse responseReceived(HostResponse value) override; |
| |
| /** @brief Using the base class's getter method */ |
| using Base::SoftPowerOff::responseReceived; |
| |
| /** @brief Calls to start a timer |
| * |
| * @param[in] usec - Time in microseconds |
| * |
| * @return Success or exception thrown |
| */ |
| int startTimer(const std::chrono::microseconds& usec); |
| |
| private: |
| // Need this to send SMS_ATTN |
| // TODO : Switch over to using mapper service in a different patch |
| static constexpr auto HOST_IPMI_BUS = "org.openbmc.HostIpmi"; |
| static constexpr auto HOST_IPMI_OBJ = "/org/openbmc/HostIpmi/1"; |
| static constexpr auto HOST_IPMI_INTF = "org.openbmc.HostIpmi"; |
| |
| /* @brief sdbusplus handle */ |
| sdbusplus::bus_t& bus; |
| |
| /** @brief Reference to Timer object */ |
| sdbusplus::Timer timer; |
| |
| /** @brief Marks the end of life of this application. |
| * |
| * This is set to true if host gives appropriate responses |
| * for the sequence of commands. |
| */ |
| bool completed = false; |
| |
| /** @brief Subscribe to host control signals |
| * |
| * Protocol is to send the host power off request to the host |
| * control interface and then wait for a signal indicating pass/fail |
| **/ |
| sdbusplus::bus::match_t hostControlSignal; |
| |
| /** @brief Sends host control command to tell host to shut down |
| * |
| * After sending the command, wait for a signal indicating the status |
| * of the command. |
| * |
| * After receiving the initial response, start a timer for 30 minutes |
| * to let host do a clean shutdown of partitions. When the response is |
| * received from the host, it indicates that BMC can do a power off. |
| * If BMC fails to get any response, then a hard power off would |
| * be forced. |
| * |
| * @return - Does not return anything. Error will result in exception |
| * being thrown |
| */ |
| void sendHostShutDownCmd(); |
| |
| /** @brief Callback function on host control signals |
| * |
| * @param[in] msg - Data associated with subscribed signal |
| * |
| */ |
| void hostControlEvent(sdbusplus::message_t& msg); |
| }; |
| } // namespace ipmi |
| } // namespace phosphor |