diff options
Diffstat (limited to 'softoff')
-rw-r--r-- | softoff/Makefile.am | 3 | ||||
-rw-r--r-- | softoff/elog-gen-softoff.hpp | 61 | ||||
-rw-r--r-- | softoff/softoff.cpp | 96 | ||||
-rw-r--r-- | softoff/softoff.hpp | 61 |
4 files changed, 174 insertions, 47 deletions
diff --git a/softoff/Makefile.am b/softoff/Makefile.am index b7f4c92..cf50cdb 100644 --- a/softoff/Makefile.am +++ b/softoff/Makefile.am @@ -8,7 +8,8 @@ phosphor_softpoweroff_SOURCES = \ softoff.cpp \ ../timer.cpp \ mainapp.cpp \ - xyz/openbmc_project/Ipmi/Internal/SoftPowerOff/server.cpp + xyz/openbmc_project/Ipmi/Internal/SoftPowerOff/server.cpp \ + ../utils.cpp BUILT_SOURCES = xyz/openbmc_project/Ipmi/Internal/SoftPowerOff/server.cpp \ xyz/openbmc_project/Ipmi/Internal/SoftPowerOff/server.hpp diff --git a/softoff/elog-gen-softoff.hpp b/softoff/elog-gen-softoff.hpp new file mode 100644 index 0000000..e863633 --- /dev/null +++ b/softoff/elog-gen-softoff.hpp @@ -0,0 +1,61 @@ +// This file was autogenerated. Do not edit! +// See elog-gen.py for more details +#pragma once + +#include <string> +#include <tuple> +#include <type_traits> +#include <sdbusplus/exception.hpp> +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog.hpp> + + +namespace phosphor +{ + +namespace logging +{ + +namespace xyz +{ +namespace openbmc_project +{ +namespace SoftPowerOff +{ +namespace Internal +{ +namespace _SoftOffFailed +{ + +} // namespace _SoftOffFailed + +struct SoftOffFailed : public sdbusplus::exception_t +{ + static constexpr auto errName = "xyz.openbmc_project.SoftPowerOff.Internal.SoftOffFailed"; + static constexpr auto errDesc = "The SoftOff command to the host control object returned an error"; + static constexpr auto L = level::ERR; + using metadata_types = std::tuple<>; + + const char* name() const noexcept + { + return errName; + } + + const char* description() const noexcept + { + return errDesc; + } + + const char* what() const noexcept + { + return errName; + } +}; + +} // namespace Internal +} // namespace SoftPowerOff +} // namespace openbmc_project +} // namespace xyz + +} // namespace logging +} // namespace phosphor diff --git a/softoff/softoff.cpp b/softoff/softoff.cpp index 88aa6cf..3511814 100644 --- a/softoff/softoff.cpp +++ b/softoff/softoff.cpp @@ -15,54 +15,70 @@ */ #include <chrono> #include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog.hpp> +#include <xyz/openbmc_project/Control/Host/server.hpp> +#include <utils.hpp> #include "softoff.hpp" +#include "elog-gen-softoff.hpp" #include "config.h" namespace phosphor { namespace ipmi { -// Sends the SMS_ATN to host if value is set -void SoftPowerOff::sendSMSAttn() +using namespace phosphor::logging; +using namespace sdbusplus::xyz::openbmc_project::Control::server; + +void SoftPowerOff::sendHostShutDownCmd() { - using namespace std::chrono; - auto method = bus.new_method_call(HOST_IPMI_BUS, - HOST_IPMI_OBJ, - HOST_IPMI_INTF, - "setAttention"); - - // If there is any exception, would be thrown here. - // BT returns '0' on success and bus_error on failure. - bus.call_noreply(method); - - // Start the timer - auto time = duration_cast<microseconds>( - seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS)); - auto r = timer.startTimer(time); - if (r < 0) + std::string ctrlHostPath{CONTROL_HOST_OBJPATH}; + ctrlHostPath += "0"; + auto host = ::ipmi::getService(this->bus, + CONTROL_HOST_BUSNAME, + ctrlHostPath.c_str()); + + auto method = bus.new_method_call(host.c_str(), + ctrlHostPath.c_str(), + CONTROL_HOST_BUSNAME, + "Execute"); + + method.append(convertForMessage(Host::Command::SoftOff).c_str()); + + auto reply = bus.call(method); + if (reply.is_method_error()) { - throw std::runtime_error("Error starting timer"); + log<level::ERR>("Error in call to control host Execute"); + // TODO openbmc/openbmc#851 - Once available, throw returned error + throw std::runtime_error("Error in call to control host Execute"); } + return; } -// Starts a timer -int SoftPowerOff::startTimer(const std::chrono::microseconds& usec) -{ - return timer.startTimer(usec); -} -// Host Response handler -auto SoftPowerOff::responseReceived(HostResponse response) -> HostResponse +// Function called on host control signals +void SoftPowerOff::hostControlEvent(sdbusplus::message::message& msg) { - using namespace std::chrono; - using namespace phosphor::logging; + std::string cmdCompleted{}; + std::string cmdStatus{}; + + msg.read(cmdCompleted, cmdStatus); - if (response == HostResponse::SoftOffReceived) + log<level::DEBUG>("Host control signal values", + entry("COMMAND=%s",cmdCompleted.c_str()), + entry("STATUS=%s",cmdStatus.c_str())); + + if(Host::convertResultFromString(cmdStatus) == Host::Result::Success) { - // Need to stop the running timer and then start a new timer + // Set our internal property indicating we got host attention + sdbusplus::xyz::openbmc_project::Ipmi::Internal + ::server::SoftPowerOff::responseReceived( + HostResponse::SoftOffReceived); + + // Start timer for host shutdown + using namespace std::chrono; auto time = duration_cast<microseconds>( - seconds(IPMI_HOST_SHUTDOWN_COMPLETE_TIMEOUT_SECS)); + seconds(IPMI_HOST_SHUTDOWN_COMPLETE_TIMEOUT_SECS)); auto r = startTimer(time); if (r < 0) { @@ -77,7 +93,25 @@ auto SoftPowerOff::responseReceived(HostResponse response) -> HostResponse (IPMI_HOST_SHUTDOWN_COMPLETE_TIMEOUT_SECS)))); } } - else if (response == HostResponse::HostShutdown) + else + { + elog<xyz::openbmc_project::SoftPowerOff::Internal::SoftOffFailed>(); + } + return; +} + +// Starts a timer +int SoftPowerOff::startTimer(const std::chrono::microseconds& usec) +{ + return timer.startTimer(usec); +} + +// Host Response handler +auto SoftPowerOff::responseReceived(HostResponse response) -> HostResponse +{ + using namespace std::chrono; + + if (response == HostResponse::HostShutdown) { // Disable the timer since Host has quiesced and we are // done with soft power off part diff --git a/softoff/softoff.hpp b/softoff/softoff.hpp index f0e992c..43bc303 100644 --- a/softoff/softoff.hpp +++ b/softoff/softoff.hpp @@ -2,14 +2,20 @@ #include <sdbusplus/bus.hpp> #include <sdbusplus/server/object.hpp> +#include <functional> +#include <xyz/openbmc_project/Control/Host/server.hpp> #include <xyz/openbmc_project/Ipmi/Internal/SoftPowerOff/server.hpp> #include "timer.hpp" +#include "config.h" namespace phosphor { namespace ipmi { namespace Base = sdbusplus::xyz::openbmc_project::Ipmi::Internal::server; +using namespace sdbusplus::xyz::openbmc_project::Control::server; + +namespace sdbusRule = sdbusplus::bus::match::rules; /** @class SoftPowerOff * @brief Responsible for coordinating Host SoftPowerOff operation @@ -30,17 +36,27 @@ class SoftPowerOff : public sdbusplus::server::object::object< sdbusplus::server::object::object< Base::SoftPowerOff>(bus, objPath, false), bus(bus), - timer(event) + 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 SMS_ATN + // very quickly on host shutdown command emit_object_added(); - // The whole purpose of this application is to send SMS_ATTN - // and watch for the soft power off to go through. We need the - // interface added signal emitted before we send SMS_ATN just to - // attend to lightning fast response from host - sendSMSAttn(); + // 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 */ @@ -94,21 +110,36 @@ class SoftPowerOff : public sdbusplus::server::object::object< */ bool completed = false; - /** @brief Sends SMS_ATN to host to initiate soft power off process. + /** @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 SMS_ATN, starts a timer for 30 - * seconds and expects a initial response from the host. - * After receiving the initial response, starts another - * timer for 30 minutes to let host do a clean shutdown of - * partitions. When the second response is received from the - * host, it indicates that BMC can do a power off. + * 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 sendSMSAttn(); + void sendHostShutDownCmd(); + + /** @brief Callback function on host control signals + * + * @param[in] msg - Data associated with subscribed signal + * + */ + void hostControlEvent(sdbusplus::message::message& msg); + }; } // namespace ipmi } // namespace phosphor |