blob: 7aa36c667fddcc1af8a412c23c9b8ba429430d90 [file] [log] [blame]
Andrew Geissler758e3af2021-04-29 21:38:39 -05001
Patrick Venture46470a32018-09-07 19:26:25 -07002#include "config.h"
3
4#include "host-interface.hpp"
5
6#include "systemintfcmds.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07007
William A. Kennington III194375f2018-12-14 02:14:33 -08008#include <ipmid-host/cmd-utils.hpp>
9#include <ipmid-host/cmd.hpp>
Andrew Geissler758e3af2021-04-29 21:38:39 -050010#include <ipmid/api.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070011#include <ipmid/utils.hpp>
George Liuca424ae2024-07-17 20:32:41 +080012#include <phosphor-logging/lg2.hpp>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050013
14#include <functional>
Andrew Geissler758e3af2021-04-29 21:38:39 -050015#include <memory>
16#include <optional>
Patrick Venture46470a32018-09-07 19:26:25 -070017
Andrew Geisslerdd2c6fd2017-03-16 15:53:20 -050018namespace phosphor
19{
20namespace host
21{
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053022namespace command
Andrew Geissler83159702017-04-03 13:31:13 -050023{
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053024
25// When you see Base:: you know we're referencing our base class
Willy Tu523e2d12023-09-05 11:36:48 -070026namespace Base = sdbusplus::server::xyz::openbmc_project::control;
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053027
28// IPMI OEM command.
29// https://github.com/openbmc/openbmc/issues/2082 for handling
30// Non-OEM commands that need to send SMS_ATN
31using OEMCmd = uint8_t;
32
33// Map of IPMI OEM command to its equivalent interface command.
34// This is needed when invoking the callback handler to indicate
35// the status of the executed command.
36static const std::map<OEMCmd, Host::Command> intfCommand = {
Patrick Venture0b02be92018-08-31 11:55:55 -070037 {CMD_HEARTBEAT, Base::Host::Command::Heartbeat},
38 {CMD_POWER, Base::Host::Command::SoftOff}};
Andrew Geissler83159702017-04-03 13:31:13 -050039
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053040// Map of Interface command to its corresponding IPMI OEM command.
41// This is needed when pushing IPMI commands to command manager's
42// queue. The same pair will be returned when IPMI asks us
43// why a SMS_ATN was sent
44static const std::map<Host::Command, IpmiCmdData> ipmiCommand = {
Patrick Venture0b02be92018-08-31 11:55:55 -070045 {Base::Host::Command::Heartbeat, std::make_pair(CMD_HEARTBEAT, 0x00)},
46 {Base::Host::Command::SoftOff, std::make_pair(CMD_POWER, SOFT_OFF)}};
Andrew Geissler83159702017-04-03 13:31:13 -050047
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053048// Called at user request
49void Host::execute(Base::Host::Command command)
Andrew Geissler83159702017-04-03 13:31:13 -050050{
George Liuca424ae2024-07-17 20:32:41 +080051 lg2::debug("Pushing cmd on to queue, control host cmd: {CONTROL_HOST_CMD}",
52 "CONTROL_HOST_CMD", convertForMessage(command));
Andrew Geissler0c07c322017-03-22 14:02:30 -050053
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053054 auto cmd = std::make_tuple(ipmiCommand.at(command),
Patrick Venture0b02be92018-08-31 11:55:55 -070055 std::bind(&Host::commandStatusHandler, this,
56 std::placeholders::_1,
57 std::placeholders::_2));
Andrew Geissler0c07c322017-03-22 14:02:30 -050058
Chen,Yugang0e862fa2019-09-06 11:03:05 +080059 ipmid_send_cmd_to_host(std::move(cmd));
Andrew Geissler62817fa92017-03-20 14:20:49 -050060}
61
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +053062// Called into by Command Manager
63void Host::commandStatusHandler(IpmiCmdData cmd, bool status)
64{
65 // Need to convert <cmd> to the equivalent one mentioned in spec
66 auto value = status ? Result::Success : Result::Failure;
67
68 // Fire a signal
69 this->commandComplete(intfCommand.at(std::get<0>(cmd)), value);
70}
71
Andrew Geisslerc7021b82021-04-28 15:22:35 -050072Host::FirmwareCondition Host::currentFirmwareCondition() const
73{
Andrew Geissler758e3af2021-04-29 21:38:39 -050074 // shared object used to wait for host response
75 auto hostCondition =
76 std::make_shared<std::optional<Host::FirmwareCondition>>();
77
78 // callback for command to host
Willy Tu11d68892022-01-20 10:37:34 -080079 auto hostAckCallback = [hostCondition](IpmiCmdData, bool status) {
Andrew Geissler758e3af2021-04-29 21:38:39 -050080 auto value = status ? Host::FirmwareCondition::Running
81 : Host::FirmwareCondition::Off;
82
George Liuca424ae2024-07-17 20:32:41 +080083 lg2::debug("currentFirmwareCondition:hostAckCallback fired, "
84 "control host cmd: {CONTROL_HOST_CMD}",
85 "CONTROL_HOST_CMD", value);
Andrew Geissler758e3af2021-04-29 21:38:39 -050086
87 *(hostCondition.get()) = value;
88 return;
89 };
90
91 auto cmd = phosphor::host::command::CommandHandler(
92 ipmiCommand.at(Base::Host::Command::Heartbeat),
93 std::move(hostAckCallback));
94
95 ipmid_send_cmd_to_host(std::move(cmd));
96
97 // Timer to ensure this function returns something within a reasonable time
Patrick Williams95655222023-12-05 12:45:02 -060098 sdbusplus::Timer hostAckTimer([hostCondition]() {
George Liuca424ae2024-07-17 20:32:41 +080099 lg2::debug("currentFirmwareCondition: timer expired!");
Andrew Geissler758e3af2021-04-29 21:38:39 -0500100 *(hostCondition.get()) = Host::FirmwareCondition::Off;
101 });
102
103 // Wait 1 second past the ATN_ACK timeout to ensure we wait for as
104 // long as the timeout
105 hostAckTimer.start(std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS + 1));
106
107 auto io = getIoContext();
108
109 while (!hostCondition.get()->has_value())
110 {
George Liuca424ae2024-07-17 20:32:41 +0800111 lg2::debug("currentFirmwareCondition: waiting for host response");
Andrew Geissler758e3af2021-04-29 21:38:39 -0500112 io->run_for(std::chrono::milliseconds(100));
113 }
114 hostAckTimer.stop();
115
George Liuca424ae2024-07-17 20:32:41 +0800116 lg2::debug("currentFirmwareCondition: hostCondition is ready!");
Andrew Geissler758e3af2021-04-29 21:38:39 -0500117 return hostCondition.get()->value();
Andrew Geisslerc7021b82021-04-28 15:22:35 -0500118}
119
Vishwanatha Subbanna3eb117a2017-07-12 16:13:49 +0530120} // namespace command
Andrew Geisslerdd2c6fd2017-03-16 15:53:20 -0500121} // namespace host
Patrick Venture0b02be92018-08-31 11:55:55 -0700122} // namespace phosphor