| Josh D. King | bdd9cb7 | 2016-12-19 11:13:43 -0600 | [diff] [blame] | 1 | #include "bmc_state_manager.hpp" | 
| Andrew Geissler | e426b58 | 2020-05-28 12:40:55 -0500 | [diff] [blame] | 2 |  | 
| Andrew Geissler | 98e64e6 | 2022-01-25 16:02:56 -0600 | [diff] [blame^] | 3 | #include "utils.hpp" | 
| Andrew Geissler | 2f60aae | 2019-09-12 13:25:21 -0500 | [diff] [blame] | 4 | #include "xyz/openbmc_project/Common/error.hpp" | 
| Josh D. King | bdd9cb7 | 2016-12-19 11:13:43 -0600 | [diff] [blame] | 5 |  | 
| Andrew Geissler | 98e64e6 | 2022-01-25 16:02:56 -0600 | [diff] [blame^] | 6 | #include <gpiod.h> | 
| Andrew Geissler | e426b58 | 2020-05-28 12:40:55 -0500 | [diff] [blame] | 7 | #include <sys/sysinfo.h> | 
|  | 8 |  | 
|  | 9 | #include <phosphor-logging/elog-errors.hpp> | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 10 | #include <phosphor-logging/lg2.hpp> | 
| Andrew Geissler | e426b58 | 2020-05-28 12:40:55 -0500 | [diff] [blame] | 11 | #include <sdbusplus/exception.hpp> | 
|  | 12 |  | 
|  | 13 | #include <cassert> | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 14 | #include <filesystem> | 
|  | 15 | #include <fstream> | 
|  | 16 | #include <iostream> | 
| Andrew Geissler | e426b58 | 2020-05-28 12:40:55 -0500 | [diff] [blame] | 17 |  | 
| Josh D. King | bdd9cb7 | 2016-12-19 11:13:43 -0600 | [diff] [blame] | 18 | namespace phosphor | 
|  | 19 | { | 
|  | 20 | namespace state | 
|  | 21 | { | 
|  | 22 | namespace manager | 
|  | 23 | { | 
|  | 24 |  | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 25 | PHOSPHOR_LOG2_USING; | 
|  | 26 |  | 
| Josh D. King | 6db3822 | 2016-12-19 14:52:40 -0600 | [diff] [blame] | 27 | // When you see server:: you know we're referencing our base class | 
|  | 28 | namespace server = sdbusplus::xyz::openbmc_project::State::server; | 
|  | 29 |  | 
|  | 30 | using namespace phosphor::logging; | 
| Andrew Geissler | 2f60aae | 2019-09-12 13:25:21 -0500 | [diff] [blame] | 31 | using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; | 
| Josh D. King | 6db3822 | 2016-12-19 14:52:40 -0600 | [diff] [blame] | 32 |  | 
| Anthony Wilson | eef31f8 | 2019-04-23 17:04:09 -0500 | [diff] [blame] | 33 | constexpr auto obmcStandbyTarget = "multi-user.target"; | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 34 | constexpr auto signalDone = "done"; | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 35 | constexpr auto activeState = "active"; | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 36 |  | 
| Josh D. King | 5162a7b | 2016-12-19 16:15:00 -0600 | [diff] [blame] | 37 | /* Map a transition to it's systemd target */ | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 38 | const std::map<server::BMC::Transition, const char*> SYSTEMD_TABLE = { | 
|  | 39 | {server::BMC::Transition::Reboot, "reboot.target"}}; | 
| Josh D. King | 5162a7b | 2016-12-19 16:15:00 -0600 | [diff] [blame] | 40 |  | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 41 | constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; | 
|  | 42 | constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1"; | 
|  | 43 | constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager"; | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 44 | constexpr auto SYSTEMD_PRP_INTERFACE = "org.freedesktop.DBus.Properties"; | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 45 |  | 
|  | 46 | void BMC::discoverInitialState() | 
|  | 47 | { | 
| Patrick Williams | 2975e26 | 2020-05-13 18:01:09 -0500 | [diff] [blame] | 48 | std::variant<std::string> currentState; | 
| Josh D. King | 2b5d887 | 2017-02-21 13:37:17 -0600 | [diff] [blame] | 49 | sdbusplus::message::object_path unitTargetPath; | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 50 |  | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 51 | auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, | 
|  | 52 | SYSTEMD_INTERFACE, "GetUnit"); | 
| Josh D. King | 2b5d887 | 2017-02-21 13:37:17 -0600 | [diff] [blame] | 53 |  | 
|  | 54 | method.append(obmcStandbyTarget); | 
|  | 55 |  | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 56 | try | 
| Josh D. King | 2b5d887 | 2017-02-21 13:37:17 -0600 | [diff] [blame] | 57 | { | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 58 | auto result = this->bus.call(method); | 
|  | 59 | result.read(unitTargetPath); | 
|  | 60 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 61 | catch (const sdbusplus::exception::exception& e) | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 62 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 63 | error("Error in GetUnit call: {ERROR}", "ERROR", e); | 
| Josh D. King | 2b5d887 | 2017-02-21 13:37:17 -0600 | [diff] [blame] | 64 | return; | 
|  | 65 | } | 
|  | 66 |  | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 67 | method = this->bus.new_method_call( | 
|  | 68 | SYSTEMD_SERVICE, | 
|  | 69 | static_cast<const std::string&>(unitTargetPath).c_str(), | 
|  | 70 | SYSTEMD_PRP_INTERFACE, "Get"); | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 71 |  | 
|  | 72 | method.append("org.freedesktop.systemd1.Unit", "ActiveState"); | 
|  | 73 |  | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 74 | try | 
| Josh D. King | 2b5d887 | 2017-02-21 13:37:17 -0600 | [diff] [blame] | 75 | { | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 76 | auto result = this->bus.call(method); | 
|  | 77 |  | 
|  | 78 | // Is obmc-standby.target active or inactive? | 
|  | 79 | result.read(currentState); | 
|  | 80 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 81 | catch (const sdbusplus::exception::exception& e) | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 82 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 83 | info("Error in ActiveState Get: {ERROR}", "ERROR", e); | 
| Josh D. King | 2b5d887 | 2017-02-21 13:37:17 -0600 | [diff] [blame] | 84 | return; | 
|  | 85 | } | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 86 |  | 
| Patrick Williams | 37413dc | 2020-05-13 11:29:54 -0500 | [diff] [blame] | 87 | auto currentStateStr = std::get<std::string>(currentState); | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 88 | if (currentStateStr == activeState) | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 89 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 90 | info("Setting the BMCState field to BMC_READY"); | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 91 | this->currentBMCState(BMCState::Ready); | 
|  | 92 |  | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 93 | // Unsubscribe so we stop processing all other signals | 
|  | 94 | method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, | 
|  | 95 | SYSTEMD_INTERFACE, "Unsubscribe"); | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 96 | try | 
|  | 97 | { | 
|  | 98 | this->bus.call(method); | 
|  | 99 | this->stateSignal.release(); | 
|  | 100 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 101 | catch (const sdbusplus::exception::exception& e) | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 102 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 103 | info("Error in Unsubscribe: {ERROR}", "ERROR", e); | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 104 | } | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 105 | } | 
|  | 106 | else | 
|  | 107 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 108 | info("Setting the BMCState field to BMC_NOTREADY"); | 
| Josh D. King | d3e5847 | 2017-02-02 11:09:11 -0600 | [diff] [blame] | 109 | this->currentBMCState(BMCState::NotReady); | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | return; | 
|  | 113 | } | 
|  | 114 |  | 
| Josh D. King | 6db3822 | 2016-12-19 14:52:40 -0600 | [diff] [blame] | 115 | void BMC::subscribeToSystemdSignals() | 
|  | 116 | { | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 117 | auto method = this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, | 
|  | 118 | SYSTEMD_INTERFACE, "Subscribe"); | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 119 |  | 
|  | 120 | try | 
|  | 121 | { | 
|  | 122 | this->bus.call(method); | 
|  | 123 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 124 | catch (const sdbusplus::exception::exception& e) | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 125 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 126 | error("Failed to subscribe to systemd signals: {ERROR}", "ERROR", e); | 
| Andrew Geissler | 2f60aae | 2019-09-12 13:25:21 -0500 | [diff] [blame] | 127 | elog<InternalFailure>(); | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 128 | } | 
| Josh D. King | 6db3822 | 2016-12-19 14:52:40 -0600 | [diff] [blame] | 129 |  | 
|  | 130 | return; | 
|  | 131 | } | 
|  | 132 |  | 
| Josh D. King | 5162a7b | 2016-12-19 16:15:00 -0600 | [diff] [blame] | 133 | void BMC::executeTransition(const Transition tranReq) | 
|  | 134 | { | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 135 | // HardReboot does not shutdown any services and immediately transitions | 
|  | 136 | // into the reboot process | 
|  | 137 | if (server::BMC::Transition::HardReboot == tranReq) | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 138 | { | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 139 | auto method = this->bus.new_method_call( | 
|  | 140 | SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, SYSTEMD_INTERFACE, "Reboot"); | 
|  | 141 | try | 
|  | 142 | { | 
|  | 143 | this->bus.call(method); | 
|  | 144 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 145 | catch (const sdbusplus::exception::exception& e) | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 146 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 147 | info("Error in HardReboot: {ERROR}", "ERROR", e); | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 148 | } | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 149 | } | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 150 | else | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 151 | { | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 152 | // Check to make sure it can be found | 
|  | 153 | auto iter = SYSTEMD_TABLE.find(tranReq); | 
|  | 154 | if (iter == SYSTEMD_TABLE.end()) | 
|  | 155 | return; | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 156 |  | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 157 | const auto& sysdUnit = iter->second; | 
|  | 158 |  | 
|  | 159 | auto method = this->bus.new_method_call( | 
|  | 160 | SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, SYSTEMD_INTERFACE, "StartUnit"); | 
|  | 161 | // The only valid transition is reboot and that | 
|  | 162 | // needs to be irreversible once started | 
|  | 163 |  | 
|  | 164 | method.append(sysdUnit, "replace-irreversibly"); | 
|  | 165 |  | 
|  | 166 | try | 
|  | 167 | { | 
|  | 168 | this->bus.call(method); | 
|  | 169 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 170 | catch (const sdbusplus::exception::exception& e) | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 171 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 172 | info("Error in StartUnit - replace-irreversibly: {ERROR}", "ERROR", | 
|  | 173 | e); | 
| Jayaprakash Mutyala | 44c223c | 2020-08-14 00:08:03 +0000 | [diff] [blame] | 174 | } | 
|  | 175 | } | 
| Josh D. King | 5162a7b | 2016-12-19 16:15:00 -0600 | [diff] [blame] | 176 | return; | 
|  | 177 | } | 
|  | 178 |  | 
| Patrick Williams | d32f818 | 2017-05-05 15:55:24 -0500 | [diff] [blame] | 179 | int BMC::bmcStateChange(sdbusplus::message::message& msg) | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 180 | { | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 181 | uint32_t newStateID{}; | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 182 | sdbusplus::message::object_path newStateObjPath; | 
|  | 183 | std::string newStateUnit{}; | 
|  | 184 | std::string newStateResult{}; | 
|  | 185 |  | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 186 | // Read the msg and populate each variable | 
| Patrick Williams | d32f818 | 2017-05-05 15:55:24 -0500 | [diff] [blame] | 187 | msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult); | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 188 |  | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 189 | // Caught the signal that indicates the BMC is now BMC_READY | 
|  | 190 | if ((newStateUnit == obmcStandbyTarget) && (newStateResult == signalDone)) | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 191 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 192 | info("BMC_READY"); | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 193 | this->currentBMCState(BMCState::Ready); | 
|  | 194 |  | 
| Andrew Geissler | 58a1801 | 2018-01-19 19:36:05 -0800 | [diff] [blame] | 195 | // Unsubscribe so we stop processing all other signals | 
|  | 196 | auto method = | 
|  | 197 | this->bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, | 
|  | 198 | SYSTEMD_INTERFACE, "Unsubscribe"); | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 199 |  | 
|  | 200 | try | 
|  | 201 | { | 
|  | 202 | this->bus.call(method); | 
|  | 203 | this->stateSignal.release(); | 
|  | 204 | } | 
| Patrick Williams | 0a67521 | 2021-09-02 09:49:43 -0500 | [diff] [blame] | 205 | catch (const sdbusplus::exception::exception& e) | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 206 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 207 | info("Error in Unsubscribe: {ERROR}", "ERROR", e); | 
| Anthony Wilson | 32c532e | 2018-10-25 21:56:07 -0500 | [diff] [blame] | 208 | } | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 209 | } | 
|  | 210 |  | 
|  | 211 | return 0; | 
|  | 212 | } | 
|  | 213 |  | 
| Josh D. King | 6db3822 | 2016-12-19 14:52:40 -0600 | [diff] [blame] | 214 | BMC::Transition BMC::requestedBMCTransition(Transition value) | 
|  | 215 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 216 | info("Setting the RequestedBMCTransition field to " | 
|  | 217 | "{REQUESTED_BMC_TRANSITION}", | 
|  | 218 | "REQUESTED_BMC_TRANSITION", value); | 
| Josh D. King | 6db3822 | 2016-12-19 14:52:40 -0600 | [diff] [blame] | 219 |  | 
| Josh D. King | 5162a7b | 2016-12-19 16:15:00 -0600 | [diff] [blame] | 220 | executeTransition(value); | 
|  | 221 | return server::BMC::requestedBMCTransition(value); | 
| Josh D. King | 6db3822 | 2016-12-19 14:52:40 -0600 | [diff] [blame] | 222 | } | 
|  | 223 |  | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 224 | BMC::BMCState BMC::currentBMCState(BMCState value) | 
|  | 225 | { | 
| Andrew Geissler | 429100a | 2021-09-09 12:50:24 -0500 | [diff] [blame] | 226 |  | 
|  | 227 | info("Setting the BMCState field to {CURRENT_BMC_STATE}", | 
|  | 228 | "CURRENT_BMC_STATE", value); | 
| Josh D. King | d613b81 | 2016-12-19 16:47:45 -0600 | [diff] [blame] | 229 |  | 
|  | 230 | return server::BMC::currentBMCState(value); | 
|  | 231 | } | 
|  | 232 |  | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 233 | BMC::RebootCause BMC::lastRebootCause(RebootCause value) | 
|  | 234 | { | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 235 | info("Setting the RebootCause field to {LAST_REBOOT_CAUSE}", | 
|  | 236 | "LAST_REBOOT_CAUSE", value); | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 237 |  | 
|  | 238 | return server::BMC::lastRebootCause(value); | 
|  | 239 | } | 
|  | 240 |  | 
| Matt Spinler | e6710b7 | 2018-07-12 16:05:55 -0500 | [diff] [blame] | 241 | uint64_t BMC::lastRebootTime() const | 
|  | 242 | { | 
|  | 243 | using namespace std::chrono; | 
|  | 244 | struct sysinfo info; | 
|  | 245 |  | 
|  | 246 | auto rc = sysinfo(&info); | 
|  | 247 | assert(rc == 0); | 
|  | 248 |  | 
|  | 249 | // Since uptime is in seconds, also get the current time in seconds. | 
|  | 250 | auto now = time_point_cast<seconds>(system_clock::now()); | 
|  | 251 | auto rebootTime = now - seconds(info.uptime); | 
|  | 252 |  | 
|  | 253 | return duration_cast<milliseconds>(rebootTime.time_since_epoch()).count(); | 
|  | 254 | } | 
|  | 255 |  | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 256 | void BMC::discoverLastRebootCause() | 
|  | 257 | { | 
|  | 258 | uint64_t bootReason = 0; | 
|  | 259 | std::ifstream file; | 
|  | 260 | auto bootstatusPath = "/sys/class/watchdog/watchdog0/bootstatus"; | 
|  | 261 |  | 
|  | 262 | file.exceptions(std::ifstream::failbit | std::ifstream::badbit | | 
|  | 263 | std::ifstream::eofbit); | 
|  | 264 |  | 
|  | 265 | try | 
|  | 266 | { | 
|  | 267 | file.open(bootstatusPath); | 
|  | 268 | file >> bootReason; | 
|  | 269 | } | 
|  | 270 | catch (const std::exception& e) | 
|  | 271 | { | 
|  | 272 | auto rc = errno; | 
| Andrew Geissler | 8ffdb26 | 2021-09-20 15:25:19 -0500 | [diff] [blame] | 273 | error("Failed to read sysfs file {FILE} with errno {ERRNO}", "FILE", | 
|  | 274 | bootstatusPath, "ERRNO", rc); | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 275 | } | 
|  | 276 |  | 
|  | 277 | switch (bootReason) | 
|  | 278 | { | 
|  | 279 | case WDIOF_EXTERN1: | 
|  | 280 | this->lastRebootCause(RebootCause::Watchdog); | 
| Andrew Geissler | 98e64e6 | 2022-01-25 16:02:56 -0600 | [diff] [blame^] | 281 | return; | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 282 | case WDIOF_CARDRESET: | 
|  | 283 | this->lastRebootCause(RebootCause::POR); | 
| Andrew Geissler | 98e64e6 | 2022-01-25 16:02:56 -0600 | [diff] [blame^] | 284 | return; | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 285 | default: | 
|  | 286 | this->lastRebootCause(RebootCause::Unknown); | 
| Andrew Geissler | 98e64e6 | 2022-01-25 16:02:56 -0600 | [diff] [blame^] | 287 | // Continue below to see if more details can be found | 
|  | 288 | // on reason for reboot | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 289 | break; | 
|  | 290 | } | 
|  | 291 |  | 
| Andrew Geissler | 98e64e6 | 2022-01-25 16:02:56 -0600 | [diff] [blame^] | 292 | // If the above code could not detect a reason, look for a the | 
|  | 293 | // reset-cause-pinhole gpio to see if it is the reason for the reboot | 
|  | 294 | auto gpioval = | 
|  | 295 | phosphor::state::manager::utils::getGpioValue("reset-cause-pinhole"); | 
|  | 296 |  | 
|  | 297 | if (1 == gpioval) | 
|  | 298 | { | 
|  | 299 | info("The BMC reset was caused by a pinhole reset"); | 
|  | 300 | this->lastRebootCause(RebootCause::PinholeReset); | 
|  | 301 | } | 
|  | 302 |  | 
| Tim Lee | 2bfb1ef | 2021-03-17 09:50:35 +0800 | [diff] [blame] | 303 | return; | 
|  | 304 | } | 
|  | 305 |  | 
| Josh D. King | bdd9cb7 | 2016-12-19 11:13:43 -0600 | [diff] [blame] | 306 | } // namespace manager | 
|  | 307 | } // namespace state | 
| Andrew Geissler | a965cf0 | 2018-08-31 08:37:05 -0700 | [diff] [blame] | 308 | } // namespace phosphor |