1 #pragma once
2 
3 #include "utils.hpp"
4 #include "xyz/openbmc_project/State/BMC/server.hpp"
5 
6 #include <linux/watchdog.h>
7 #include <sys/sysinfo.h>
8 
9 #include <sdbusplus/bus.hpp>
10 
11 #include <cassert>
12 #include <chrono>
13 
14 namespace phosphor
15 {
16 namespace state
17 {
18 namespace manager
19 {
20 
21 using BMCInherit = sdbusplus::server::object_t<
22     sdbusplus::server::xyz::openbmc_project::state::BMC>;
23 namespace sdbusRule = sdbusplus::bus::match::rules;
24 
25 /** @class BMC
26  *  @brief OpenBMC BMC state management implementation.
27  *  @details A concrete implementation for xyz.openbmc_project.State.BMC
28  *  DBus API.
29  */
30 class BMC : public BMCInherit
31 {
32   public:
33     /** @brief Constructs BMC State Manager
34      *
35      * @param[in] bus       - The Dbus bus object
36      * @param[in] busName   - The Dbus name to own
37      * @param[in] objPath   - The Dbus object path
38      */
39     BMC(sdbusplus::bus_t& bus, const char* objPath) :
40         BMCInherit(bus, objPath, BMCInherit::action::defer_emit), bus(bus),
41         stateSignal(std::make_unique<decltype(stateSignal)::element_type>(
42             bus,
43             sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
44                 sdbusRule::path("/org/freedesktop/systemd1") +
45                 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
46             [this](sdbusplus::message_t& m) { bmcStateChange(m); }))
47     {
48         utils::subscribeToSystemdSignals(bus);
49         discoverInitialState();
50         discoverLastRebootCause();
51 
52         using namespace std::chrono;
53         struct sysinfo info;
54 
55         auto rc = sysinfo(&info);
56         assert(rc == 0);
57         // Since uptime is in seconds, also get the current time in seconds.
58         auto now = time_point_cast<seconds>(system_clock::now());
59         auto rebootTimeTs = now - seconds(info.uptime);
60         rebootTime =
61             duration_cast<milliseconds>(rebootTimeTs.time_since_epoch())
62                 .count();
63 
64         this->emit_object_added();
65     };
66 
67     /** @brief Set value of BMCTransition **/
68     Transition requestedBMCTransition(Transition value) override;
69 
70     /** @brief Set value of CurrentBMCState **/
71     BMCState currentBMCState(BMCState value) override;
72 
73     /** @brief Returns the last time the BMC was rebooted
74      *
75      *  @details Uses uptime information to determine when
76      *           the BMC was last rebooted.
77      *
78      *  @return uint64_t - Epoch time, in milliseconds, of the
79      *                     last reboot.
80      */
81     uint64_t lastRebootTime() const override;
82 
83     /** @brief Set value of LastRebootCause **/
84     RebootCause lastRebootCause(RebootCause value) override;
85 
86   private:
87     /**
88      * @brief Retrieve input systemd unit state
89      **/
90     std::string getUnitState(const std::string& unitToCheck);
91     /**
92      * @brief discover the state of the bmc
93      **/
94     void discoverInitialState();
95 
96     /** @brief Execute the transition request
97      *
98      *  @param[in] tranReq   - Transition requested
99      */
100     void executeTransition(Transition tranReq);
101 
102     /** @brief Callback function on bmc state change
103      *
104      * Check if the state is relevant to the BMC and if so, update
105      * corresponding BMC object's state
106      *
107      * @param[in]  msg       - Data associated with subscribed signal
108      *
109      */
110     int bmcStateChange(sdbusplus::message_t& msg);
111 
112     /** @brief Persistent sdbusplus DBus bus connection. **/
113     sdbusplus::bus_t& bus;
114 
115     /** @brief Used to subscribe to dbus system state changes **/
116     std::unique_ptr<sdbusplus::bus::match_t> stateSignal;
117 
118     /**
119      * @brief discover the last reboot cause of the bmc
120      **/
121     void discoverLastRebootCause();
122 
123     /**
124      * @brief the lastRebootTime calcuated at startup.
125      **/
126     uint64_t rebootTime;
127 };
128 
129 } // namespace manager
130 } // namespace state
131 } // namespace phosphor
132