blob: 4559c8098c0ef2d95c98bc5aa67401dac5ee8480 [file] [log] [blame]
Josh D. Kingbdd9cb72016-12-19 11:13:43 -06001#include <iostream>
Josh D. King5162a7b2016-12-19 16:15:00 -06002#include <string>
Saqib Khana8006a22017-02-14 11:37:08 -06003#include <phosphor-logging/log.hpp>
Josh D. Kingbdd9cb72016-12-19 11:13:43 -06004#include "bmc_state_manager.hpp"
5
6namespace phosphor
7{
8namespace state
9{
10namespace manager
11{
12
Josh D. King6db38222016-12-19 14:52:40 -060013// When you see server:: you know we're referencing our base class
14namespace server = sdbusplus::xyz::openbmc_project::State::server;
15
16using namespace phosphor::logging;
17
Josh D. Kingd613b812016-12-19 16:47:45 -060018constexpr auto obmcStandbyTarget = "obmc-standby.target";
19constexpr auto signalDone = "done";
Josh D. Kingd3e58472017-02-02 11:09:11 -060020constexpr auto activeState = "active";
Josh D. Kingd613b812016-12-19 16:47:45 -060021
Josh D. King5162a7b2016-12-19 16:15:00 -060022/* Map a transition to it's systemd target */
23const std::map<server::BMC::Transition, const char*> SYSTEMD_TABLE =
24{
25 {server::BMC::Transition::Reboot, "reboot.target"}
26};
27
Josh D. King2b5d8872017-02-21 13:37:17 -060028constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
29constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
30constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
Josh D. Kingd3e58472017-02-02 11:09:11 -060031constexpr auto SYSTEMD_PRP_INTERFACE = "org.freedesktop.DBus.Properties";
Josh D. Kingd3e58472017-02-02 11:09:11 -060032
33void BMC::discoverInitialState()
34{
35 sdbusplus::message::variant<std::string> currentState;
Josh D. King2b5d8872017-02-21 13:37:17 -060036 sdbusplus::message::object_path unitTargetPath;
Josh D. Kingd3e58472017-02-02 11:09:11 -060037
38 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
Josh D. King2b5d8872017-02-21 13:37:17 -060039 SYSTEMD_OBJ_PATH,
40 SYSTEMD_INTERFACE,
41 "GetUnit");
42
43 method.append(obmcStandbyTarget);
44
45 auto result = this->bus.call(method);
46
47 //Check that the bus call didn't result in an error
48 if(result.is_method_error())
49 {
50 log<level::ERR>("Error in bus call.");
51 return;
52 }
53
54 result.read(unitTargetPath);
55
56 method = this->bus.new_method_call(SYSTEMD_SERVICE,
57 static_cast<const std::string&>
58 (unitTargetPath).c_str(),
59 SYSTEMD_PRP_INTERFACE,
60 "Get");
Josh D. Kingd3e58472017-02-02 11:09:11 -060061
62 method.append("org.freedesktop.systemd1.Unit", "ActiveState");
63
Josh D. King2b5d8872017-02-21 13:37:17 -060064 result = this->bus.call(method);
65
66 //Check that the bus call didn't result in an error
67 if(result.is_method_error())
68 {
69 log<level::INFO>("Error in bus call.");
70 return;
71 }
Josh D. Kingd3e58472017-02-02 11:09:11 -060072
73 //Is obmc-standby.target active or inactive?
74 result.read(currentState);
75
76 if(currentState == activeState)
77 {
78 log<level::INFO>("Setting the BMCState field",
79 entry("CURRENT_BMC_STATE=%s",
80 "BMC_READY"));
81 this->currentBMCState(BMCState::Ready);
82
83 //Unsubscribe so we stop processing all other signals
84 method = this->bus.new_method_call(SYSTEMD_SERVICE,
85 SYSTEMD_OBJ_PATH,
86 SYSTEMD_INTERFACE,
87 "Unsubscribe");
88 this->bus.call(method);
89 this->stateSignal.release();
90 }
91 else
92 {
93 log<level::INFO>("Setting the BMCState field",
94 entry("CURRENT_BMC_STATE=%s",
95 "BMC_NOTREADY"));
96 this->currentBMCState(BMCState::NotReady);
97 }
98
99 return;
100}
101
Josh D. King6db38222016-12-19 14:52:40 -0600102void BMC::subscribeToSystemdSignals()
103{
104 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
105 SYSTEMD_OBJ_PATH,
106 SYSTEMD_INTERFACE,
107 "Subscribe");
108 this->bus.call(method);
109
110 return;
111}
112
Josh D. King5162a7b2016-12-19 16:15:00 -0600113void BMC::executeTransition(const Transition tranReq)
114{
115 //Check to make sure it can be found
116 auto iter = SYSTEMD_TABLE.find(tranReq);
117 if (iter == SYSTEMD_TABLE.end()) return;
118
119 const auto& sysdUnit = iter->second;
120
121 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
122 SYSTEMD_OBJ_PATH,
123 SYSTEMD_INTERFACE,
124 "StartUnit");
125
126 method.append(sysdUnit, "replace");
127
128 this->bus.call(method);
129
130 return;
131}
132
Josh D. Kingd613b812016-12-19 16:47:45 -0600133int BMC::bmcStateChangeSignal(sd_bus_message *msg, void *userData,
134 sd_bus_error *retError)
135{
136 return static_cast<BMC*>(userData)->bmcStateChange(msg, retError);
137}
138
139int BMC::bmcStateChange(sd_bus_message *msg,
140 sd_bus_error *retError)
141{
142 uint32_t newStateID {};
143 sdbusplus::message::object_path newStateObjPath;
144 std::string newStateUnit{};
145 std::string newStateResult{};
146
147 auto sdPlusMsg = sdbusplus::message::message(msg);
148 //Read the msg and populate each variable
149 sdPlusMsg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
150
151 //Caught the signal that indicates the BMC is now BMC_READY
152 if((newStateUnit == obmcStandbyTarget) &&
153 (newStateResult == signalDone))
154 {
155 log<level::INFO>("BMC_READY");
156 this->currentBMCState(BMCState::Ready);
157
158 //Unsubscribe so we stop processing all other signals
159 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
160 SYSTEMD_OBJ_PATH,
161 SYSTEMD_INTERFACE,
162 "Unsubscribe");
163 this->bus.call(method);
164 this->stateSignal.release();
165 }
166
167 return 0;
168}
169
Josh D. King6db38222016-12-19 14:52:40 -0600170BMC::Transition BMC::requestedBMCTransition(Transition value)
171{
172 log<level::INFO>(
173 "Setting the RequestedBMCTransition field",
174 entry("REQUESTED_BMC_TRANSITION=0x%s",
175 convertForMessage(value).c_str()));
Josh D. King6db38222016-12-19 14:52:40 -0600176
Josh D. King5162a7b2016-12-19 16:15:00 -0600177 executeTransition(value);
178 return server::BMC::requestedBMCTransition(value);
Josh D. King6db38222016-12-19 14:52:40 -0600179}
180
Josh D. Kingd613b812016-12-19 16:47:45 -0600181BMC::BMCState BMC::currentBMCState(BMCState value)
182{
183 log<level::INFO>(
184 "Setting the BMCState field",
185 entry("CURRENT_BMC_STATE=0x%s",
186 convertForMessage(value).c_str()));
187
188 return server::BMC::currentBMCState(value);
189}
190
Josh D. King6db38222016-12-19 14:52:40 -0600191
Josh D. Kingbdd9cb72016-12-19 11:13:43 -0600192} // namespace manager
193} // namespace state
194} // namepsace phosphor
195