blob: e6513fa949ad3d4346eb465bb2b5f70480f004fe [file] [log] [blame]
Andrew Geissler0029a5d2017-01-24 14:48:35 -06001#include <sdbusplus/bus.hpp>
Saqib Khana8006a22017-02-14 11:37:08 -06002#include <phosphor-logging/log.hpp>
Andrew Geisslera90a31a2016-12-13 16:16:28 -06003#include "chassis_state_manager.hpp"
4
5namespace phosphor
6{
7namespace state
8{
9namespace manager
10{
11
12// When you see server:: you know we're referencing our base class
13namespace server = sdbusplus::xyz::openbmc_project::State::server;
14
15using namespace phosphor::logging;
16
Andrew Geissler0029a5d2017-01-24 14:48:35 -060017constexpr auto CHASSIS_STATE_POWEROFF_TGT = "obmc-power-chassis-off@0.target";
18constexpr auto CHASSIS_STATE_POWERON_TGT = "obmc-power-chassis-on@0.target";
19
Andrew Geisslerce80f242017-01-24 13:25:33 -060020/* Map a transition to it's systemd target */
21const std::map<server::Chassis::Transition,std::string> SYSTEMD_TARGET_TABLE =
22{
Andrew Geissler0029a5d2017-01-24 14:48:35 -060023 {server::Chassis::Transition::Off, CHASSIS_STATE_POWEROFF_TGT},
24 {server::Chassis::Transition::On, CHASSIS_STATE_POWERON_TGT}
Andrew Geisslerce80f242017-01-24 13:25:33 -060025};
26
27constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
28constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
29constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
30
Andrew Geissler0029a5d2017-01-24 14:48:35 -060031void Chassis::subscribeToSystemdSignals()
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060032{
Andrew Geissler0029a5d2017-01-24 14:48:35 -060033 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
34 SYSTEMD_OBJ_PATH,
35 SYSTEMD_INTERFACE,
36 "Subscribe");
37 this->bus.call_noreply(method);
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060038
Andrew Geissler0029a5d2017-01-24 14:48:35 -060039 return;
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060040}
41
Andrew Geisslerdff50ed2016-12-13 20:39:04 -060042// TODO - Will be rewritten once sdbusplus client bindings are in place
43// and persistent storage design is in place and sdbusplus
44// has read property function
45void Chassis::determineInitialState()
46{
47 sdbusplus::message::variant<int> pgood = -1;
48 auto method = this->bus.new_method_call("org.openbmc.control.Power",
49 "/org/openbmc/control/power0",
50 "org.freedesktop.DBus.Properties",
51 "Get");
52
53 method.append("org.openbmc.control.Power", "pgood");
54 auto reply = this->bus.call(method);
55 reply.read(pgood);
56
57 if(pgood == 1)
58 {
59 log<level::INFO>("Initial Chassis State will be On",
60 entry("CHASSIS_CURRENT_POWER_STATE=%s",
61 convertForMessage(PowerState::On).c_str()));
62 server::Chassis::currentPowerState(PowerState::On);
63 server::Chassis::requestedPowerTransition(Transition::On);
64 }
65 else
66 {
67 log<level::INFO>("Initial Chassis State will be Off",
68 entry("CHASSIS_CURRENT_POWER_STATE=%s",
69 convertForMessage(PowerState::Off).c_str()));
70 server::Chassis::currentPowerState(PowerState::Off);
71 server::Chassis::requestedPowerTransition(Transition::Off);
72 }
73
74 return;
75}
76
Andrew Geisslerce80f242017-01-24 13:25:33 -060077void Chassis::executeTransition(Transition tranReq)
78{
79 auto sysdTarget = SYSTEMD_TARGET_TABLE.find(tranReq)->second;
80
81 auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
82 SYSTEMD_OBJ_PATH,
83 SYSTEMD_INTERFACE,
84 "StartUnit");
85
86 method.append(sysdTarget);
87 method.append("replace");
88
89 this->bus.call_noreply(method);
90
91 return;
92}
93
Andrew Geissler0029a5d2017-01-24 14:48:35 -060094int Chassis::sysStateChangeSignal(sd_bus_message *msg, void *userData,
95 sd_bus_error *retError)
96{
97 return static_cast<Chassis*>(userData)->sysStateChange(msg, retError);
98}
99
100int Chassis::sysStateChange(sd_bus_message* msg,
101 sd_bus_error* retError)
102{
103 uint32_t newStateID {};
104 sdbusplus::message::object_path newStateObjPath;
105 std::string newStateUnit{};
106 std::string newStateResult{};
107
108 auto sdPlusMsg = sdbusplus::message::message(msg);
109 //Read the msg and populate each variable
110 sdPlusMsg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
111
112 if((newStateUnit == CHASSIS_STATE_POWEROFF_TGT) &&
113 (newStateResult == "done"))
114 {
115 log<level::INFO>("Recieved signal that power OFF is complete");
116 this->currentPowerState(server::Chassis::PowerState::Off);
117 }
118 else if((newStateUnit == CHASSIS_STATE_POWERON_TGT) &&
119 (newStateResult == "done"))
120 {
121 log<level::INFO>("Recieved signal that power ON is complete");
122 this->currentPowerState(server::Chassis::PowerState::On);
123 }
124
125 return 0;
126}
127
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600128Chassis::Transition Chassis::requestedPowerTransition(Transition value)
129{
130
131 log<level::INFO>("Change to Chassis Requested Power State",
132 entry("CHASSIS_REQUESTED_POWER_STATE=%s",
133 convertForMessage(value).c_str()));
Andrew Geisslerce80f242017-01-24 13:25:33 -0600134 executeTransition(value);
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600135 return server::Chassis::requestedPowerTransition(value);
136}
137
138Chassis::PowerState Chassis::currentPowerState(PowerState value)
139{
140 log<level::INFO>("Change to Chassis Power State",
141 entry("CHASSIS_CURRENT_POWER_STATE=%s",
142 convertForMessage(value).c_str()));
143 return server::Chassis::currentPowerState(value);
144}
145
146} // namespace manager
147} // namespace state
148} // namepsace phosphor