blob: fd2ef227e5a6056a2ca82c1760f77221e0daf7c5 [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
Ben Tyner2c36e5a2021-07-12 14:56:49 -05008#include <gpiod.h>
9
Andrew Geisslere426b582020-05-28 12:40:55 -050010#include <cereal/archives/json.hpp>
11#include <phosphor-logging/elog-errors.hpp>
Andrew Geissler8ffdb262021-09-20 15:25:19 -050012#include <phosphor-logging/lg2.hpp>
Andrew Geissler0029a5d2017-01-24 14:48:35 -060013#include <sdbusplus/bus.hpp>
William A. Kennington III09568ff2018-05-11 00:03:12 -070014#include <sdbusplus/exception.hpp>
William A. Kennington IIId998f822018-10-17 23:17:57 -070015#include <sdeventplus/event.hpp>
16#include <sdeventplus/exception.hpp>
Andrew Geisslere426b582020-05-28 12:40:55 -050017
Andrew Geisslerf2b22e82021-03-12 14:47:03 -060018#include <filesystem>
Andrew Geisslere426b582020-05-28 12:40:55 -050019#include <fstream>
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -050020
Andrew Geisslera90a31a2016-12-13 16:16:28 -060021namespace phosphor
22{
23namespace state
24{
25namespace manager
26{
27
Andrew Geissler8ffdb262021-09-20 15:25:19 -050028PHOSPHOR_LOG2_USING;
29
Andrew Geisslera90a31a2016-12-13 16:16:28 -060030// When you see server:: you know we're referencing our base class
31namespace server = sdbusplus::xyz::openbmc_project::State::server;
32
33using namespace phosphor::logging;
William A. Kennington IIId998f822018-10-17 23:17:57 -070034using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Aatir Manzur27115ae2019-07-23 16:25:38 -050035using sdbusplus::xyz::openbmc_project::State::Shutdown::Power::Error::Blackout;
Ben Tyner2c36e5a2021-07-12 14:56:49 -050036using sdbusplus::xyz::openbmc_project::State::Shutdown::Power::Error::Regulator;
Josh D. King6838ea92017-04-11 13:39:18 -050037constexpr auto CHASSIS_STATE_POWEROFF_TGT = "obmc-chassis-poweroff@0.target";
Andrew Geissler58a18012018-01-19 19:36:05 -080038constexpr auto CHASSIS_STATE_HARD_POWEROFF_TGT =
39 "obmc-chassis-hard-poweroff@0.target";
Josh D. King6838ea92017-04-11 13:39:18 -050040constexpr auto CHASSIS_STATE_POWERON_TGT = "obmc-chassis-poweron@0.target";
Andrew Geissler0029a5d2017-01-24 14:48:35 -060041
Josh D. King697474c2017-03-02 11:15:55 -060042constexpr auto ACTIVE_STATE = "active";
43constexpr auto ACTIVATING_STATE = "activating";
44
Andrew Geisslerce80f242017-01-24 13:25:33 -060045/* Map a transition to it's systemd target */
Andrew Geissler58a18012018-01-19 19:36:05 -080046const std::map<server::Chassis::Transition, std::string> SYSTEMD_TARGET_TABLE =
47 {
Andrew Geissler8cf2f9a2017-07-21 11:58:04 -050048 // Use the hard off target to ensure we shutdown immediately
49 {server::Chassis::Transition::Off, CHASSIS_STATE_HARD_POWEROFF_TGT},
Andrew Geissler58a18012018-01-19 19:36:05 -080050 {server::Chassis::Transition::On, CHASSIS_STATE_POWERON_TGT}};
Andrew Geisslerce80f242017-01-24 13:25:33 -060051
Andrew Geissler58a18012018-01-19 19:36:05 -080052constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
53constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
Andrew Geisslerce80f242017-01-24 13:25:33 -060054constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
55
Josh D. King697474c2017-03-02 11:15:55 -060056constexpr auto SYSTEMD_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
57constexpr auto SYSTEMD_INTERFACE_UNIT = "org.freedesktop.systemd1.Unit";
58
Andrew Geissler0029a5d2017-01-24 14:48:35 -060059void Chassis::subscribeToSystemdSignals()
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060060{
Andrew Geissler3a30b052019-05-14 15:54:37 -050061 try
62 {
63 auto method = this->bus.new_method_call(
64 SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, SYSTEMD_INTERFACE, "Subscribe");
Andrew Geissler5b950272019-05-24 12:27:51 -050065 this->bus.call(method);
Andrew Geissler3a30b052019-05-14 15:54:37 -050066 }
Andrew Geissler8ffdb262021-09-20 15:25:19 -050067 catch (const sdbusplus::exception::exception& e)
Andrew Geissler3a30b052019-05-14 15:54:37 -050068 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050069 error("Failed to subscribe to systemd signals: {ERROR}", "ERROR", e);
Andrew Geissler3a30b052019-05-14 15:54:37 -050070 elog<InternalFailure>();
71 }
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060072
Andrew Geissler0029a5d2017-01-24 14:48:35 -060073 return;
Andrew Geissler2ec3a7e2016-12-13 22:01:28 -060074}
75
Andrew Geisslerdff50ed2016-12-13 20:39:04 -060076// TODO - Will be rewritten once sdbusplus client bindings are in place
77// and persistent storage design is in place and sdbusplus
78// has read property function
79void Chassis::determineInitialState()
80{
Patrick Williams2975e262020-05-13 18:01:09 -050081 std::variant<int> pgood = -1;
Andrew Geissler58a18012018-01-19 19:36:05 -080082 auto method = this->bus.new_method_call(
83 "org.openbmc.control.Power", "/org/openbmc/control/power0",
84 "org.freedesktop.DBus.Properties", "Get");
Andrew Geisslerdff50ed2016-12-13 20:39:04 -060085
86 method.append("org.openbmc.control.Power", "pgood");
William A. Kennington III09568ff2018-05-11 00:03:12 -070087 try
88 {
William A. Kennington III9a2f37c2018-06-28 16:18:37 -070089 auto reply = this->bus.call(method);
Anthony Wilson32c532e2018-10-25 21:56:07 -050090 reply.read(pgood);
William A. Kennington III9a2f37c2018-06-28 16:18:37 -070091
Patrick Williams37413dc2020-05-13 11:29:54 -050092 if (std::get<int>(pgood) == 1)
William A. Kennington III9a2f37c2018-06-28 16:18:37 -070093 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -050094 info("Initial Chassis State will be On");
William A. Kennington III9a2f37c2018-06-28 16:18:37 -070095 server::Chassis::currentPowerState(PowerState::On);
96 server::Chassis::requestedPowerTransition(Transition::On);
97 return;
98 }
Matt Spinler9eab9862018-07-11 14:13:52 -050099 else
100 {
101 // The system is off. If we think it should be on then
102 // we probably lost AC while up, so set a new state
103 // change time.
104 uint64_t lastTime;
105 PowerState lastState;
106
107 if (deserializeStateChangeTime(lastTime, lastState))
108 {
109 if (lastState == PowerState::On)
110 {
Ben Tyner2c36e5a2021-07-12 14:56:49 -0500111 if (standbyVoltageRegulatorFault())
112 {
113 report<Regulator>();
114 }
115 else
116 {
117 report<Blackout>();
118 }
119
Matt Spinler9eab9862018-07-11 14:13:52 -0500120 setStateChangeTime();
121 }
122 }
123 }
William A. Kennington III09568ff2018-05-11 00:03:12 -0700124 }
Patrick Williams0a675212021-09-02 09:49:43 -0500125 catch (const sdbusplus::exception::exception& e)
William A. Kennington III09568ff2018-05-11 00:03:12 -0700126 {
William A. Kennington III9a2f37c2018-06-28 16:18:37 -0700127 // It's acceptable for the pgood state service to not be available
128 // since it will notify us of the pgood state when it comes up.
129 if (e.name() != nullptr &&
130 strcmp("org.freedesktop.DBus.Error.ServiceUnknown", e.name()) == 0)
131 {
132 goto fail;
133 }
Andrew Geisslerdff50ed2016-12-13 20:39:04 -0600134
William A. Kennington III9a2f37c2018-06-28 16:18:37 -0700135 // Only log for unexpected error types.
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500136 error("Error performing call to get pgood: {ERROR}", "ERROR", e);
William A. Kennington III9a2f37c2018-06-28 16:18:37 -0700137 goto fail;
Andrew Geisslerdff50ed2016-12-13 20:39:04 -0600138 }
William A. Kennington III09568ff2018-05-11 00:03:12 -0700139
140fail:
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500141 info("Initial Chassis State will be Off");
William A. Kennington III09568ff2018-05-11 00:03:12 -0700142 server::Chassis::currentPowerState(PowerState::Off);
143 server::Chassis::requestedPowerTransition(Transition::Off);
Andrew Geisslerdff50ed2016-12-13 20:39:04 -0600144
145 return;
146}
147
Andrew Geisslerce80f242017-01-24 13:25:33 -0600148void Chassis::executeTransition(Transition tranReq)
149{
150 auto sysdTarget = SYSTEMD_TARGET_TABLE.find(tranReq)->second;
151
Andrew Geissler58a18012018-01-19 19:36:05 -0800152 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
153 SYSTEMD_INTERFACE, "StartUnit");
Andrew Geisslerce80f242017-01-24 13:25:33 -0600154
155 method.append(sysdTarget);
156 method.append("replace");
157
158 this->bus.call_noreply(method);
159
160 return;
161}
162
Josh D. King697474c2017-03-02 11:15:55 -0600163bool Chassis::stateActive(const std::string& target)
164{
Patrick Williams2975e262020-05-13 18:01:09 -0500165 std::variant<std::string> currentState;
Josh D. King697474c2017-03-02 11:15:55 -0600166 sdbusplus::message::object_path unitTargetPath;
167
Andrew Geissler58a18012018-01-19 19:36:05 -0800168 auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
169 SYSTEMD_INTERFACE, "GetUnit");
Josh D. King697474c2017-03-02 11:15:55 -0600170
171 method.append(target);
Josh D. King697474c2017-03-02 11:15:55 -0600172
William A. Kennington III09568ff2018-05-11 00:03:12 -0700173 try
174 {
Anthony Wilson32c532e2018-10-25 21:56:07 -0500175 auto result = this->bus.call(method);
William A. Kennington III09568ff2018-05-11 00:03:12 -0700176 result.read(unitTargetPath);
177 }
Patrick Williams0a675212021-09-02 09:49:43 -0500178 catch (const sdbusplus::exception::exception& e)
William A. Kennington III09568ff2018-05-11 00:03:12 -0700179 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500180 error("Error in GetUnit call: {ERROR}", "ERROR", e);
William A. Kennington III09568ff2018-05-11 00:03:12 -0700181 return false;
182 }
Josh D. King697474c2017-03-02 11:15:55 -0600183
Andrew Geissler58a18012018-01-19 19:36:05 -0800184 method = this->bus.new_method_call(
185 SYSTEMD_SERVICE,
186 static_cast<const std::string&>(unitTargetPath).c_str(),
187 SYSTEMD_PROPERTY_IFACE, "Get");
Josh D. King697474c2017-03-02 11:15:55 -0600188
189 method.append(SYSTEMD_INTERFACE_UNIT, "ActiveState");
Josh D. King697474c2017-03-02 11:15:55 -0600190
Anthony Wilson32c532e2018-10-25 21:56:07 -0500191 try
Josh D. King697474c2017-03-02 11:15:55 -0600192 {
Anthony Wilson32c532e2018-10-25 21:56:07 -0500193 auto result = this->bus.call(method);
194 result.read(currentState);
195 }
Patrick Williams0a675212021-09-02 09:49:43 -0500196 catch (const sdbusplus::exception::exception& e)
Anthony Wilson32c532e2018-10-25 21:56:07 -0500197 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500198 error("Error in ActiveState Get: {ERROR}", "ERROR", e);
Josh D. King697474c2017-03-02 11:15:55 -0600199 return false;
200 }
201
Patrick Williams37413dc2020-05-13 11:29:54 -0500202 const auto& currentStateStr = std::get<std::string>(currentState);
William A. Kennington III7a0689a2018-11-12 17:19:33 -0800203 return currentStateStr == ACTIVE_STATE ||
204 currentStateStr == ACTIVATING_STATE;
Josh D. King697474c2017-03-02 11:15:55 -0600205}
206
Patrick Williams8f8ba392017-05-05 15:47:39 -0500207int Chassis::sysStateChange(sdbusplus::message::message& msg)
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600208{
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600209 sdbusplus::message::object_path newStateObjPath;
210 std::string newStateUnit{};
211 std::string newStateResult{};
212
Andrew Geissler58a18012018-01-19 19:36:05 -0800213 // Read the msg and populate each variable
William A. Kennington III09568ff2018-05-11 00:03:12 -0700214 try
215 {
Andrew Geissler9b8af4f2019-09-12 14:19:14 -0500216 // newStateID is a throwaway that is needed in order to read the
217 // parameters that are useful out of the dbus message
218 uint32_t newStateID{};
William A. Kennington III09568ff2018-05-11 00:03:12 -0700219 msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
220 }
Patrick Williams0a675212021-09-02 09:49:43 -0500221 catch (const sdbusplus::exception::exception& e)
William A. Kennington III09568ff2018-05-11 00:03:12 -0700222 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500223 error("Error in state change - bad encoding: {ERROR} {REPLY_SIG}",
224 "ERROR", e, "REPLY_SIG", msg.get_signature());
William A. Kennington III09568ff2018-05-11 00:03:12 -0700225 return 0;
226 }
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600227
Andrew Geissler58a18012018-01-19 19:36:05 -0800228 if ((newStateUnit == CHASSIS_STATE_POWEROFF_TGT) &&
229 (newStateResult == "done") && (!stateActive(CHASSIS_STATE_POWERON_TGT)))
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600230 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500231 info("Received signal that power OFF is complete");
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600232 this->currentPowerState(server::Chassis::PowerState::Off);
Matt Spinler9eab9862018-07-11 14:13:52 -0500233 this->setStateChangeTime();
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600234 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800235 else if ((newStateUnit == CHASSIS_STATE_POWERON_TGT) &&
236 (newStateResult == "done") &&
237 (stateActive(CHASSIS_STATE_POWERON_TGT)))
238 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500239 info("Received signal that power ON is complete");
Andrew Geissler58a18012018-01-19 19:36:05 -0800240 this->currentPowerState(server::Chassis::PowerState::On);
Matt Spinler9eab9862018-07-11 14:13:52 -0500241 this->setStateChangeTime();
Andrew Geisslerf2b22e82021-03-12 14:47:03 -0600242
243 // Remove temporary file which is utilized for scenarios where the
244 // BMC is rebooted while the chassis power is still on.
245 // This file is used to indicate to chassis related systemd services
246 // that the chassis is already on and they should skip running.
247 // Once the chassis state is back to on we can clear this file.
248 auto size = std::snprintf(nullptr, 0, CHASSIS_ON_FILE, 0);
249 size++; // null
250 std::unique_ptr<char[]> chassisFile(new char[size]);
251 std::snprintf(chassisFile.get(), size, CHASSIS_ON_FILE, 0);
252 if (std::filesystem::exists(chassisFile.get()))
253 {
254 std::filesystem::remove(chassisFile.get());
255 }
Andrew Geissler58a18012018-01-19 19:36:05 -0800256 }
Andrew Geissler0029a5d2017-01-24 14:48:35 -0600257
258 return 0;
259}
260
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600261Chassis::Transition Chassis::requestedPowerTransition(Transition value)
262{
263
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500264 info("Change to Chassis Requested Power State: {REQ_POWER_TRAN}",
265 "REQ_POWER_TRAN", value);
Andrew Geisslerce80f242017-01-24 13:25:33 -0600266 executeTransition(value);
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600267 return server::Chassis::requestedPowerTransition(value);
268}
269
270Chassis::PowerState Chassis::currentPowerState(PowerState value)
271{
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500272 PowerState chassisPowerState;
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500273 info("Change to Chassis Power State: {CUR_POWER_STATE}", "CUR_POWER_STATE",
274 value);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500275
276 chassisPowerState = server::Chassis::currentPowerState(value);
Patrick Williams45a1ed72021-04-30 21:02:43 -0500277 pohTimer.setEnabled(chassisPowerState == PowerState::On);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500278 return chassisPowerState;
279}
280
Patrick Williams45a1ed72021-04-30 21:02:43 -0500281uint32_t Chassis::pohCounter(uint32_t value)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500282{
Patrick Williams45a1ed72021-04-30 21:02:43 -0500283 if (value != pohCounter())
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500284 {
Patrick Williams45a1ed72021-04-30 21:02:43 -0500285 ChassisInherit::pohCounter(value);
Matt Spinler81957842018-07-11 10:37:12 -0500286 serializePOH();
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500287 }
Patrick Williams45a1ed72021-04-30 21:02:43 -0500288 return pohCounter();
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500289}
290
Patrick Williams45a1ed72021-04-30 21:02:43 -0500291void Chassis::pohCallback()
William A. Kennington IIId998f822018-10-17 23:17:57 -0700292{
293 if (ChassisInherit::currentPowerState() == PowerState::On)
294 {
Patrick Williams45a1ed72021-04-30 21:02:43 -0500295 pohCounter(pohCounter() + 1);
William A. Kennington IIId998f822018-10-17 23:17:57 -0700296 }
297}
298
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500299void Chassis::restorePOHCounter()
300{
301 uint32_t counter;
Matt Spinler81957842018-07-11 10:37:12 -0500302 if (!deserializePOH(POH_COUNTER_PERSIST_PATH, counter))
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500303 {
304 // set to default value
Patrick Williams45a1ed72021-04-30 21:02:43 -0500305 pohCounter(0);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500306 }
307 else
308 {
Patrick Williams45a1ed72021-04-30 21:02:43 -0500309 pohCounter(counter);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500310 }
311}
312
Matt Spinler81957842018-07-11 10:37:12 -0500313fs::path Chassis::serializePOH(const fs::path& path)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500314{
315 std::ofstream os(path.c_str(), std::ios::binary);
316 cereal::JSONOutputArchive oarchive(os);
Patrick Williams45a1ed72021-04-30 21:02:43 -0500317 oarchive(pohCounter());
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500318 return path;
319}
320
Patrick Williams45a1ed72021-04-30 21:02:43 -0500321bool Chassis::deserializePOH(const fs::path& path, uint32_t& pohCounter)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500322{
323 try
324 {
325 if (fs::exists(path))
326 {
327 std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
328 cereal::JSONInputArchive iarchive(is);
Patrick Williams45a1ed72021-04-30 21:02:43 -0500329 iarchive(pohCounter);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500330 return true;
331 }
332 return false;
333 }
Patrick Williams8583b3b2021-10-06 12:19:20 -0500334 catch (const cereal::Exception& e)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500335 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500336 error("deserialize exception: {ERROR}", "ERROR", e);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500337 fs::remove(path);
338 return false;
339 }
340 catch (const fs::filesystem_error& e)
341 {
342 return false;
343 }
344
345 return false;
346}
347
348void Chassis::startPOHCounter()
349{
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500350 auto dir = fs::path(POH_COUNTER_PERSIST_PATH).parent_path();
351 fs::create_directories(dir);
352
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500353 try
354 {
William A. Kennington IIId998f822018-10-17 23:17:57 -0700355 auto event = sdeventplus::Event::get_default();
356 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
357 event.loop();
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500358 }
William A. Kennington IIId998f822018-10-17 23:17:57 -0700359 catch (const sdeventplus::SdEventError& e)
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500360 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500361 error("Error occurred during the sdeventplus loop: {ERROR}", "ERROR",
362 e);
Nagaraju Goruganticb781fe2018-04-06 13:41:01 -0500363 phosphor::logging::commit<InternalFailure>();
364 }
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600365}
366
Matt Spinler9eab9862018-07-11 14:13:52 -0500367void Chassis::serializeStateChangeTime()
368{
369 fs::path path{CHASSIS_STATE_CHANGE_PERSIST_PATH};
370 std::ofstream os(path.c_str(), std::ios::binary);
371 cereal::JSONOutputArchive oarchive(os);
372
373 oarchive(ChassisInherit::lastStateChangeTime(),
374 ChassisInherit::currentPowerState());
375}
376
377bool Chassis::deserializeStateChangeTime(uint64_t& time, PowerState& state)
378{
379 fs::path path{CHASSIS_STATE_CHANGE_PERSIST_PATH};
380
381 try
382 {
383 if (fs::exists(path))
384 {
385 std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
386 cereal::JSONInputArchive iarchive(is);
387 iarchive(time, state);
388 return true;
389 }
390 }
Patrick Williams8583b3b2021-10-06 12:19:20 -0500391 catch (const std::exception& e)
Matt Spinler9eab9862018-07-11 14:13:52 -0500392 {
Andrew Geissler8ffdb262021-09-20 15:25:19 -0500393 error("deserialize exception: {ERROR}", "ERROR", e);
Matt Spinler9eab9862018-07-11 14:13:52 -0500394 fs::remove(path);
395 }
396
397 return false;
398}
399
400void Chassis::restoreChassisStateChangeTime()
401{
402 uint64_t time;
403 PowerState state;
404
405 if (!deserializeStateChangeTime(time, state))
406 {
407 ChassisInherit::lastStateChangeTime(0);
408 }
409 else
410 {
411 ChassisInherit::lastStateChangeTime(time);
412 }
413}
414
415void Chassis::setStateChangeTime()
416{
417 using namespace std::chrono;
418 uint64_t lastTime;
419 PowerState lastState;
420
421 auto now =
422 duration_cast<milliseconds>(system_clock::now().time_since_epoch())
423 .count();
424
425 // If power is on when the BMC is rebooted, this function will get called
426 // because sysStateChange() runs. Since the power state didn't change
427 // in this case, neither should the state change time, so check that
428 // the power state actually did change here.
429 if (deserializeStateChangeTime(lastTime, lastState))
430 {
431 if (lastState == ChassisInherit::currentPowerState())
432 {
433 return;
434 }
435 }
436
437 ChassisInherit::lastStateChangeTime(now);
438 serializeStateChangeTime();
439}
440
Ben Tyner2c36e5a2021-07-12 14:56:49 -0500441bool Chassis::standbyVoltageRegulatorFault()
442{
443 bool regulatorFault = false;
444
445 // find standby voltage regulator fault via gpio
446 gpiod_line* line = gpiod_line_find("regulator-standby-faulted");
447
448 if (nullptr != line)
449 {
450 // take ownership of gpio
451 if (0 != gpiod_line_request_input(line, "chassis"))
452 {
453 error("Failed request for regulator-standby-faulted GPIO");
454 }
455 else
456 {
457 // get gpio value
458 auto gpioval = gpiod_line_get_value(line);
459
460 // release ownership of gpio
461 gpiod_line_close_chip(line);
462
463 if (-1 == gpioval)
464 {
465 error("Failed reading regulator-standby-faulted GPIO");
466 }
467
468 if (1 == gpioval)
469 {
470 info("Detected standby voltage regulator fault");
471 regulatorFault = true;
472 }
473 }
474 }
475 return regulatorFault;
476}
477
Andrew Geisslera90a31a2016-12-13 16:16:28 -0600478} // namespace manager
479} // namespace state
Andrew Geisslera965cf02018-08-31 08:37:05 -0700480} // namespace phosphor