blob: f4e761aeb2af310490d627102d4167911ca9132b [file] [log] [blame]
Andrew Geisslere426b582020-05-28 12:40:55 -05001#include "config.h"
2
3#include "chassis_state_manager.hpp"
4
5#include "xyz/openbmc_project/Common/error.hpp"
6#include "xyz/openbmc_project/State/Shutdown/Power/error.hpp"
7
8#include <cereal/archives/json.hpp>
9#include <phosphor-logging/elog-errors.hpp>
Andrew Geissler8ffdb262021-09-20 15:25:19 -050010#include <phosphor-logging/lg2.hpp>
Andrew Geissler0029a5d2017-01-24 14:48:35 -060011#include <sdbusplus/bus.hpp>
William A. Kennington III09568ff2018-05-11 00:03:12 -070012#include <sdbusplus/exception.hpp>
William A. Kennington IIId998f822018-10-17 23:17:57 -070013#include <sdeventplus/event.hpp>
14#include <sdeventplus/exception.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -050015
Andrew Geisslerf2b22e82021-03-12 14:47:03 -060016#include <filesystem>
Andrew Geisslere426b582020-05-28 12:40:55 -050017#include <fstream>
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -050018
Andrew Geisslera90a31a2016-12-13 16:16:28 -060019namespace phosphor
20{
21namespace state
22{
23namespace manager
24{
25
Andrew Geissler8ffdb262021-09-20 15:25:19 -050026PHOSPHOR_LOG2_USING;
27
Andrew Geisslera90a31a2016-12-13 16:16:28 -060028// When you see server:: you know we're referencing our base class
29namespace server = sdbusplus::xyz::openbmc_project::State::server;
30
31using namespace phosphor::logging;
William A. Kennington IIId998f822018-10-17 23:17:57 -070032using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Aatir Manzur27115ae2019-07-23 16:25:38 -050033using sdbusplus::xyz::openbmc_project::State::Shutdown::Power::Error::Blackout;
Josh D. King6838ea92017-04-11 13:39:18 -050034constexpr auto CHASSIS_STATE_POWEROFF_TGT = "obmc-chassis-poweroff@0.target";
Andrew Geissler58a18012018-01-19 19:36:05 -080035constexpr auto CHASSIS_STATE_HARD_POWEROFF_TGT =
36 "obmc-chassis-hard-poweroff@0.target";
Josh D. King6838ea92017-04-11 13:39:18 -050037constexpr auto CHASSIS_STATE_POWERON_TGT = "obmc-chassis-poweron@0.target";
Andrew Geissler0029a5d2017-01-24 14:48:35 -060038
Josh D. King697474c2017-03-02 11:15:55 -060039constexpr auto ACTIVE_STATE = "active";
40constexpr auto ACTIVATING_STATE = "activating";
41
Andrew Geisslerce80f242017-01-24 13:25:33 -060042/* Map a transition to it's systemd target */
Andrew Geissler58a18012018-01-19 19:36:05 -080043const std::map<server::Chassis::Transition, std::string> SYSTEMD_TARGET_TABLE =
44 {
Andrew Geissler8cf2f9a2017-07-21 11:58:04 -050045 // Use the hard off target to ensure we shutdown immediately
46 {server::Chassis::Transition::Off, CHASSIS_STATE_HARD_POWEROFF_TGT},
Andrew Geissler58a18012018-01-19 19:36:05 -080047 {server::Chassis::Transition::On, CHASSIS_STATE_POWERON_TGT}};
Andrew Geisslerce80f242017-01-24 13:25:33 -060048
Andrew Geissler58a18012018-01-19 19:36:05 -080049constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
50constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
Andrew Geisslerce80f242017-01-24 13:25:33 -060051constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
52
Josh D. King697474c2017-03-02 11:15:55 -060053constexpr auto SYSTEMD_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
54constexpr auto SYSTEMD_INTERFACE_UNIT = "org.freedesktop.systemd1.Unit";
55
Andrew Geissler0029a5d2017-01-24 14:48:35 -060056void Chassis::subscribeToSystemdSignals()
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060057{
Andrew Geissler3a30b052019-05-14 15:54:37 -050058 try
59 {
60 auto method = this->bus.new_method_call(
61 SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, SYSTEMD_INTERFACE, "Subscribe");
Andrew Geissler5b950272019-05-24 12:27:51 -050062 this->bus.call(method);
Andrew Geissler3a30b052019-05-14 15:54:37 -050063 }
Andrew Geissler8ffdb262021-09-20 15:25:19 -050064 catch (const sdbusplus::exception::exception& e)
Andrew Geissler3a30b052019-05-14 15:54:37 -050065 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050066 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR", e);
Andrew Geissler3a30b052019-05-14 15:54:37 -050067 elog<InternalFailure>();
68 }
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060069
Andrew Geissler0029a5d2017-01-24 14:48:35 -060070 return;
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060071}
72
Andrew Geisslerdff50ed2016-12-13 20:39:04 -060073// TODO - Will be rewritten once sdbusplus client bindings are in place
74// and persistent storage design is in place and sdbusplus
75// has read property function
76void Chassis::determineInitialState()
77{
Patrick Williams2975e262020-05-13 18:01:09 -050078 std::variant<int> pgood = -1;
Andrew Geissler58a18012018-01-19 19:36:05 -080079 auto method = this->bus.new_method_call(
80 "org.openbmc.control.Power", "/org/openbmc/control/power0",
81 "org.freedesktop.DBus.Properties", "Get");
Andrew Geisslerdff50ed2016-12-13 20:39:04 -060082
83 method.append("org.openbmc.control.Power", "pgood");
William A. Kennington III09568ff2018-05-11 00:03:12 -070084 try
85 {
William A. Kennington III9a2f37c2018-06-28 16:18:37 -070086 auto reply = this->bus.call(method);
Anthony Wilson32c532e2018-10-25 21:56:07 -050087 reply.read(pgood);
William A. Kennington III9a2f37c2018-06-28 16:18:37 -070088
Patrick Williams37413dc2020-05-13 11:29:54 -050089 if (std::get<int>(pgood) == 1)
William A. Kennington III9a2f37c2018-06-28 16:18:37 -070090 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050091 info("Initial Chassis State will be On");
William A. Kennington III9a2f37c2018-06-28 16:18:37 -070092 server::Chassis::currentPowerState(PowerState::On);
93 server::Chassis::requestedPowerTransition(Transition::On);
94 return;
95 }
Matt Spinler9eab9862018-07-11 14:13:52 -050096 else
97 {
98 // The system is off. If we think it should be on then
99 // we probably lost AC while up, so set a new state
100 // change time.
101 uint64_t lastTime;
102 PowerState lastState;
103
104 if (deserializeStateChangeTime(lastTime, lastState))
105 {
106 if (lastState == PowerState::On)
107 {
Aatir Manzur27115ae2019-07-23 16:25:38 -0500108 report<Blackout>();
Matt Spinler9eab9862018-07-11 14:13:52 -0500109 setStateChangeTime();
110 }
111 }
112 }
William A. Kennington III09568ff2018-05-11 00:03:12 -0700113 }
Patrick Williams0a675212021-09-02 09:49:43 -0500114 catch (const sdbusplus::exception::exception& e)
William A. Kennington III09568ff2018-05-11 00:03:12 -0700115 {
William A. Kennington III9a2f37c2018-06-28 16:18:37 -0700116 // It's acceptable for the pgood state service to not be available
117 // since it will notify us of the pgood state when it comes up.
118 if (e.name() != nullptr &&
119 strcmp("org.freedesktop.DBus.Error.ServiceUnknown", e.name()) == 0)
120 {
121 goto fail;
122 }
Andrew Geisslerdff50ed2016-12-13 20:39:04 -0600123
William A. Kennington III9a2f37c2018-06-28 16:18:37 -0700124 // Only log for unexpected error types.
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500125 error("Error performing call to get pgood: {ERROR}", "ERROR", e);
William A. Kennington III9a2f37c2018-06-28 16:18:37 -0700126 goto fail;
Andrew Geisslerdff50ed2016-12-13 20:39:04 -0600127 }
William A. Kennington III09568ff2018-05-11 00:03:12 -0700128
129fail:
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500130 info("Initial Chassis State will be Off");
William A. Kennington III09568ff2018-05-11 00:03:12 -0700131 server::Chassis::currentPowerState(PowerState::Off);
132 server::Chassis::requestedPowerTransition(Transition::Off);
Andrew Geisslerdff50ed2016-12-13 20:39:04 -0600133
134 return;
135}
136
Andrew Geisslerce80f242017-01-24 13:25:33 -0600137void Chassis::executeTransition(Transition tranReq)
138{
139 auto sysdTarget = SYSTEMD_TARGET_TABLE.find(tranReq)->second;
140
Andrew Geissler58a18012018-01-19 19:36:05 -0800141 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
142 SYSTEMD_INTERFACE, "StartUnit");
Andrew Geisslerce80f242017-01-24 13:25:33 -0600143
144 method.append(sysdTarget);
145 method.append("replace");
146
147 this->bus.call_noreply(method);
148
149 return;
150}
151
Josh D. King697474c2017-03-02 11:15:55 -0600152bool Chassis::stateActive(const std::string& target)
153{
Patrick Williams2975e262020-05-13 18:01:09 -0500154 std::variant<std::string> currentState;
Josh D. King697474c2017-03-02 11:15:55 -0600155 sdbusplus::message::object_path unitTargetPath;
156
Andrew Geissler58a18012018-01-19 19:36:05 -0800157 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
158 SYSTEMD_INTERFACE, "GetUnit");
Josh D. King697474c2017-03-02 11:15:55 -0600159
160 method.append(target);
Josh D. King697474c2017-03-02 11:15:55 -0600161
William A. Kennington III09568ff2018-05-11 00:03:12 -0700162 try
163 {
Anthony Wilson32c532e2018-10-25 21:56:07 -0500164 auto result = this->bus.call(method);
William A. Kennington III09568ff2018-05-11 00:03:12 -0700165 result.read(unitTargetPath);
166 }
Patrick Williams0a675212021-09-02 09:49:43 -0500167 catch (const sdbusplus::exception::exception& e)
William A. Kennington III09568ff2018-05-11 00:03:12 -0700168 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500169 error("Error in GetUnit call: {ERROR}", "ERROR", e);
William A. Kennington III09568ff2018-05-11 00:03:12 -0700170 return false;
171 }
Josh D. King697474c2017-03-02 11:15:55 -0600172
Andrew Geissler58a18012018-01-19 19:36:05 -0800173 method = this->bus.new_method_call(
174 SYSTEMD_SERVICE,
175 static_cast<const std::string&>(unitTargetPath).c_str(),
176 SYSTEMD_PROPERTY_IFACE, "Get");
Josh D. King697474c2017-03-02 11:15:55 -0600177
178 method.append(SYSTEMD_INTERFACE_UNIT, "ActiveState");
Josh D. King697474c2017-03-02 11:15:55 -0600179
Anthony Wilson32c532e2018-10-25 21:56:07 -0500180 try
Josh D. King697474c2017-03-02 11:15:55 -0600181 {
Anthony Wilson32c532e2018-10-25 21:56:07 -0500182 auto result = this->bus.call(method);
183 result.read(currentState);
184 }
Patrick Williams0a675212021-09-02 09:49:43 -0500185 catch (const sdbusplus::exception::exception& e)
Anthony Wilson32c532e2018-10-25 21:56:07 -0500186 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500187 error("Error in ActiveState Get: {ERROR}", "ERROR", e);
Josh D. King697474c2017-03-02 11:15:55 -0600188 return false;
189 }
190
Patrick Williams37413dc2020-05-13 11:29:54 -0500191 const auto& currentStateStr = std::get<std::string>(currentState);
William A. Kennington III7a0689a2018-11-12 17:19:33 -0800192 return currentStateStr == ACTIVE_STATE ||
193 currentStateStr == ACTIVATING_STATE;
Josh D. King697474c2017-03-02 11:15:55 -0600194}
195
Patrick Williams8f8ba392017-05-05 15:47:39 -0500196int Chassis::sysStateChange(sdbusplus::message::message& msg)
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600197{
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600198 sdbusplus::message::object_path newStateObjPath;
199 std::string newStateUnit{};
200 std::string newStateResult{};
201
Andrew Geissler58a18012018-01-19 19:36:05 -0800202 // Read the msg and populate each variable
William A. Kennington III09568ff2018-05-11 00:03:12 -0700203 try
204 {
Andrew Geissler9b8af4f2019-09-12 14:19:14 -0500205 // newStateID is a throwaway that is needed in order to read the
206 // parameters that are useful out of the dbus message
207 uint32_t newStateID{};
William A. Kennington III09568ff2018-05-11 00:03:12 -0700208 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
209 }
Patrick Williams0a675212021-09-02 09:49:43 -0500210 catch (const sdbusplus::exception::exception& e)
William A. Kennington III09568ff2018-05-11 00:03:12 -0700211 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500212 error("Error in state change - bad encoding: {ERROR} {REPLY_SIG}",
213 "ERROR", e, "REPLY_SIG", msg.get_signature());
William A. Kennington III09568ff2018-05-11 00:03:12 -0700214 return 0;
215 }
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600216
Andrew Geissler58a18012018-01-19 19:36:05 -0800217 if ((newStateUnit == CHASSIS_STATE_POWEROFF_TGT) &&
218 (newStateResult == "done") && (!stateActive(CHASSIS_STATE_POWERON_TGT)))
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600219 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500220 info("Received signal that power OFF is complete");
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600221 this->currentPowerState(server::Chassis::PowerState::Off);
Matt Spinler9eab9862018-07-11 14:13:52 -0500222 this->setStateChangeTime();
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600223 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800224 else if ((newStateUnit == CHASSIS_STATE_POWERON_TGT) &&
225 (newStateResult == "done") &&
226 (stateActive(CHASSIS_STATE_POWERON_TGT)))
227 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500228 info("Received signal that power ON is complete");
Andrew Geissler58a18012018-01-19 19:36:05 -0800229 this->currentPowerState(server::Chassis::PowerState::On);
Matt Spinler9eab9862018-07-11 14:13:52 -0500230 this->setStateChangeTime();
Andrew Geisslerf2b22e82021-03-12 14:47:03 -0600231
232 // Remove temporary file which is utilized for scenarios where the
233 // BMC is rebooted while the chassis power is still on.
234 // This file is used to indicate to chassis related systemd services
235 // that the chassis is already on and they should skip running.
236 // Once the chassis state is back to on we can clear this file.
237 auto size = std::snprintf(nullptr, 0, CHASSIS_ON_FILE, 0);
238 size++; // null
239 std::unique_ptr<char[]> chassisFile(new char[size]);
240 std::snprintf(chassisFile.get(), size, CHASSIS_ON_FILE, 0);
241 if (std::filesystem::exists(chassisFile.get()))
242 {
243 std::filesystem::remove(chassisFile.get());
244 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800245 }
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600246
247 return 0;
248}
249
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600250Chassis::Transition Chassis::requestedPowerTransition(Transition value)
251{
252
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500253 info("Change to Chassis Requested Power State: {REQ_POWER_TRAN}",
254 "REQ_POWER_TRAN", value);
Andrew Geisslerce80f242017-01-24 13:25:33 -0600255 executeTransition(value);
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600256 return server::Chassis::requestedPowerTransition(value);
257}
258
259Chassis::PowerState Chassis::currentPowerState(PowerState value)
260{
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500261 PowerState chassisPowerState;
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500262 info("Change to Chassis Power State: {CUR_POWER_STATE}", "CUR_POWER_STATE",
263 value);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500264
265 chassisPowerState = server::Chassis::currentPowerState(value);
Patrick Williams45a1ed72021-04-30 21:02:43 -0500266 pohTimer.setEnabled(chassisPowerState == PowerState::On);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500267 return chassisPowerState;
268}
269
Patrick Williams45a1ed72021-04-30 21:02:43 -0500270uint32_t Chassis::pohCounter(uint32_t value)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500271{
Patrick Williams45a1ed72021-04-30 21:02:43 -0500272 if (value != pohCounter())
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500273 {
Patrick Williams45a1ed72021-04-30 21:02:43 -0500274 ChassisInherit::pohCounter(value);
Matt Spinler81957842018-07-11 10:37:12 -0500275 serializePOH();
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500276 }
Patrick Williams45a1ed72021-04-30 21:02:43 -0500277 return pohCounter();
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500278}
279
Patrick Williams45a1ed72021-04-30 21:02:43 -0500280void Chassis::pohCallback()
William A. Kennington IIId998f822018-10-17 23:17:57 -0700281{
282 if (ChassisInherit::currentPowerState() == PowerState::On)
283 {
Patrick Williams45a1ed72021-04-30 21:02:43 -0500284 pohCounter(pohCounter() + 1);
William A. Kennington IIId998f822018-10-17 23:17:57 -0700285 }
286}
287
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500288void Chassis::restorePOHCounter()
289{
290 uint32_t counter;
Matt Spinler81957842018-07-11 10:37:12 -0500291 if (!deserializePOH(POH_COUNTER_PERSIST_PATH, counter))
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500292 {
293 // set to default value
Patrick Williams45a1ed72021-04-30 21:02:43 -0500294 pohCounter(0);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500295 }
296 else
297 {
Patrick Williams45a1ed72021-04-30 21:02:43 -0500298 pohCounter(counter);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500299 }
300}
301
Matt Spinler81957842018-07-11 10:37:12 -0500302fs::path Chassis::serializePOH(const fs::path& path)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500303{
304 std::ofstream os(path.c_str(), std::ios::binary);
305 cereal::JSONOutputArchive oarchive(os);
Patrick Williams45a1ed72021-04-30 21:02:43 -0500306 oarchive(pohCounter());
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500307 return path;
308}
309
Patrick Williams45a1ed72021-04-30 21:02:43 -0500310bool Chassis::deserializePOH(const fs::path& path, uint32_t& pohCounter)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500311{
312 try
313 {
314 if (fs::exists(path))
315 {
316 std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
317 cereal::JSONInputArchive iarchive(is);
Patrick Williams45a1ed72021-04-30 21:02:43 -0500318 iarchive(pohCounter);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500319 return true;
320 }
321 return false;
322 }
323 catch (cereal::Exception& e)
324 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500325 error("deserialize exception: {ERROR}", "ERROR", e);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500326 fs::remove(path);
327 return false;
328 }
329 catch (const fs::filesystem_error& e)
330 {
331 return false;
332 }
333
334 return false;
335}
336
337void Chassis::startPOHCounter()
338{
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500339 auto dir = fs::path(POH_COUNTER_PERSIST_PATH).parent_path();
340 fs::create_directories(dir);
341
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500342 try
343 {
William A. Kennington IIId998f822018-10-17 23:17:57 -0700344 auto event = sdeventplus::Event::get_default();
345 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
346 event.loop();
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500347 }
William A. Kennington IIId998f822018-10-17 23:17:57 -0700348 catch (const sdeventplus::SdEventError& e)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500349 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500350 error("Error occurred during the sdeventplus loop: {ERROR}", "ERROR",
351 e);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500352 phosphor::logging::commit<InternalFailure>();
353 }
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600354}
355
Matt Spinler9eab9862018-07-11 14:13:52 -0500356void Chassis::serializeStateChangeTime()
357{
358 fs::path path{CHASSIS_STATE_CHANGE_PERSIST_PATH};
359 std::ofstream os(path.c_str(), std::ios::binary);
360 cereal::JSONOutputArchive oarchive(os);
361
362 oarchive(ChassisInherit::lastStateChangeTime(),
363 ChassisInherit::currentPowerState());
364}
365
366bool Chassis::deserializeStateChangeTime(uint64_t& time, PowerState& state)
367{
368 fs::path path{CHASSIS_STATE_CHANGE_PERSIST_PATH};
369
370 try
371 {
372 if (fs::exists(path))
373 {
374 std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
375 cereal::JSONInputArchive iarchive(is);
376 iarchive(time, state);
377 return true;
378 }
379 }
380 catch (std::exception& e)
381 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500382 error("deserialize exception: {ERROR}", "ERROR", e);
Matt Spinler9eab9862018-07-11 14:13:52 -0500383 fs::remove(path);
384 }
385
386 return false;
387}
388
389void Chassis::restoreChassisStateChangeTime()
390{
391 uint64_t time;
392 PowerState state;
393
394 if (!deserializeStateChangeTime(time, state))
395 {
396 ChassisInherit::lastStateChangeTime(0);
397 }
398 else
399 {
400 ChassisInherit::lastStateChangeTime(time);
401 }
402}
403
404void Chassis::setStateChangeTime()
405{
406 using namespace std::chrono;
407 uint64_t lastTime;
408 PowerState lastState;
409
410 auto now =
411 duration_cast<milliseconds>(system_clock::now().time_since_epoch())
412 .count();
413
414 // If power is on when the BMC is rebooted, this function will get called
415 // because sysStateChange() runs. Since the power state didn't change
416 // in this case, neither should the state change time, so check that
417 // the power state actually did change here.
418 if (deserializeStateChangeTime(lastTime, lastState))
419 {
420 if (lastState == ChassisInherit::currentPowerState())
421 {
422 return;
423 }
424 }
425
426 ChassisInherit::lastStateChangeTime(now);
427 serializeStateChangeTime();
428}
429
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600430} // namespace manager
431} // namespace state
Andrew Geisslera965cf02018-08-31 08:37:05 -0700432} // namespace phosphor