| /** |
| * Copyright © 2016 IBM Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include "config.h" |
| |
| #include "softoff.hpp" |
| |
| #include <ipmid/utils.hpp> |
| #include <phosphor-logging/lg2.hpp> |
| #include <xyz/openbmc_project/Control/Host/server.hpp> |
| |
| #include <chrono> |
| namespace phosphor |
| { |
| namespace ipmi |
| { |
| |
| using namespace sdbusplus::server::xyz::openbmc_project::control; |
| |
| void SoftPowerOff::sendHostShutDownCmd() |
| { |
| auto ctrlHostPath = std::string{CONTROL_HOST_OBJ_MGR} + '/' + HOST_NAME + |
| '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()); |
| try |
| { |
| auto reply = bus.call(method); |
| } |
| catch (const std::exception& e) |
| { |
| lg2::error("Error in call to control host Execute: {ERROR}", "ERROR", |
| e); |
| // TODO openbmc/openbmc#851 - Once available, throw returned error |
| throw std::runtime_error("Error in call to control host Execute"); |
| } |
| } |
| |
| // Function called on host control signals |
| void SoftPowerOff::hostControlEvent(sdbusplus::message_t& msg) |
| { |
| std::string cmdCompleted{}; |
| std::string cmdStatus{}; |
| |
| msg.read(cmdCompleted, cmdStatus); |
| |
| lg2::debug( |
| "Host control signal values, command: {COMMAND}, status:{STATUS}", |
| "COMMAND", cmdCompleted, "STATUS", cmdStatus); |
| |
| if (Host::convertResultFromString(cmdStatus) == Host::Result::Success) |
| { |
| // Set our internal property indicating we got host attention |
| sdbusplus::server::xyz::openbmc_project::ipmi::internal::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)); |
| auto r = startTimer(time); |
| if (r < 0) |
| { |
| lg2::error( |
| "Failure to start Host shutdown wait timer, ERRNO: {ERRNO}", |
| "ERRNO", lg2::hex, -r); |
| } |
| else |
| { |
| lg2::info("Timer started waiting for host to shutdown, " |
| "TIMEOUT_IN_MSEC: {TIMEOUT_IN_MSEC}", |
| "TIMEOUT_IN_MSEC", |
| (duration_cast<milliseconds>( |
| seconds(IPMI_HOST_SHUTDOWN_COMPLETE_TIMEOUT_SECS))) |
| .count()); |
| } |
| } |
| else |
| { |
| // An error on the initial attention is not considered an error, just |
| // exit normally and allow remaining shutdown targets to run |
| lg2::info("Timeout on host attention, continue with power down"); |
| completed = true; |
| } |
| return; |
| } |
| |
| // Starts a timer |
| int SoftPowerOff::startTimer(const std::chrono::microseconds& usec) |
| { |
| return timer.start(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 |
| auto r = timer.stop(); |
| if (r < 0) |
| { |
| lg2::error("Failure to STOP the timer, ERRNO: {ERRNO}", "ERRNO", |
| lg2::hex, -r); |
| } |
| |
| // This marks the completion of soft power off sequence. |
| completed = true; |
| } |
| |
| return sdbusplus::server::xyz::openbmc_project::ipmi::internal:: |
| SoftPowerOff::responseReceived(response); |
| } |
| |
| } // namespace ipmi |
| } // namespace phosphor |