1 #pragma once
2 
3 #include "power_supply.hpp"
4 #include "types.hpp"
5 #include "utility.hpp"
6 
7 #include <phosphor-logging/log.hpp>
8 #include <sdbusplus/bus/match.hpp>
9 #include <sdeventplus/event.hpp>
10 #include <sdeventplus/utility/timer.hpp>
11 
12 struct sys_properties
13 {
14     int maxPowerSupplies;
15 };
16 
17 using namespace phosphor::power::psu;
18 using namespace phosphor::logging;
19 
20 namespace phosphor::power::manager
21 {
22 
23 /**
24  * @class PSUManager
25  *
26  * This class will create an object used to manage and monitor a list of power
27  * supply devices.
28  */
29 class PSUManager
30 {
31   public:
32     PSUManager() = delete;
33     ~PSUManager() = default;
34     PSUManager(const PSUManager&) = delete;
35     PSUManager& operator=(const PSUManager&) = delete;
36     PSUManager(PSUManager&&) = delete;
37     PSUManager& operator=(PSUManager&&) = delete;
38 
39     /**
40      * Constructor to read configuration from D-Bus.
41      *
42      * @param[in] bus - D-Bus bus object
43      * @param[in] e - event object
44      */
45     PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e);
46 
47     /**
48      * Get PSU properties from D-Bus, use that to build a power supply
49      * object.
50      *
51      * @param[in] properties - A map of property names and values
52      *
53      */
54     void getPSUProperties(util::DbusPropertyMap& properties);
55 
56     /**
57      * Get PSU configuration from D-Bus
58      */
59     void getPSUConfiguration();
60 
61     /**
62      * @brief Initialize the system properties from the Supported Configuration
63      *        D-Bus object provided by Entity Manager.
64      */
65     void getSystemProperties();
66 
67     /**
68      * Initializes the manager.
69      *
70      * Get current BMC state, ...
71      */
72     void initialize()
73     {
74         // When state = 1, system is powered on
75         int32_t state = 0;
76 
77         try
78         {
79             // Use getProperty utility function to get power state.
80             util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH,
81                                        powerService, bus, state);
82 
83             if (state)
84             {
85                 powerOn = true;
86             }
87             else
88             {
89                 powerOn = false;
90             }
91         }
92         catch (std::exception& e)
93         {
94             log<level::INFO>("Failed to get power state. Assuming it is off.");
95             powerOn = false;
96         }
97 
98         onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY);
99         clearFaults();
100         updateInventory();
101     }
102 
103     /**
104      * Starts the timer to start monitoring the list of devices.
105      */
106     int run()
107     {
108         return timer->get_event().loop();
109     }
110 
111     /**
112      * Write PMBus ON_OFF_CONFIG
113      *
114      * This function will be called to cause the PMBus device driver to send the
115      * ON_OFF_CONFIG command. Takes one byte of data.
116      */
117     void onOffConfig(const uint8_t data)
118     {
119         for (auto& psu : psus)
120         {
121             psu->onOffConfig(data);
122         }
123     }
124 
125     /**
126      * This function will be called in various situations in order to clear
127      * any fault status bits that may have been set, in order to start over
128      * with a clean state. Presence changes and power state changes will want
129      * to clear any faults logged.
130      */
131     void clearFaults()
132     {
133         for (auto& psu : psus)
134         {
135             psu->clearFaults();
136         }
137     }
138 
139   private:
140     /**
141      * The D-Bus object
142      */
143     sdbusplus::bus::bus& bus;
144 
145     /**
146      * The timer that runs to periodically check the power supplies.
147      */
148     std::unique_ptr<
149         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
150         timer;
151 
152     /**
153      * Create an error
154      *
155      * @param[in] faultName - 'name' message for the BMC error log entry
156      * @param[in] additionalData - The AdditionalData property for the error
157      */
158     void createError(const std::string& faultName,
159                      const std::map<std::string, std::string>& additionalData);
160 
161     /**
162      * Analyze the status of each of the power supplies.
163      *
164      * Log errors for faults, when and where appropriate.
165      */
166     void analyze();
167 
168     /** @brief True if the power is on. */
169     bool powerOn = false;
170 
171     /** @brief Used as part of subscribing to power on state changes*/
172     std::string powerService;
173 
174     /** @brief Used to subscribe to D-Bus power on state changes */
175     std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
176 
177     /** @brief Used to subscribe to Entity Manager interfaces added */
178     std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch;
179 
180     /**
181      * @brief Callback for power state property changes
182      *
183      * Process changes to the powered on state property for the system.
184      *
185      * @param[in] msg - Data associated with the power state signal
186      */
187     void powerStateChanged(sdbusplus::message::message& msg);
188 
189     /**
190      * @brief Callback for entity-manager interface added
191      *
192      * Process the information from the supported configuration and or IBM CFFPS
193      * Connector interface being added.
194      *
195      * @param[in] msg - Data associated with the interfaces added signal
196      */
197     void entityManagerIfaceAdded(sdbusplus::message::message& msg);
198 
199     /**
200      * @brief Adds properties to the inventory.
201      *
202      * Reads the values from the devices and writes them to the associated
203      * power supply D-Bus inventory objects.
204      *
205      * This needs to be done on startup, and each time the presence state
206      * changes.
207      */
208     void updateInventory()
209     {
210         for (auto& psu : psus)
211         {
212             psu->updateInventory();
213         }
214     }
215 
216     /**
217      * @brief Helper function to populate the system properties
218      *
219      * @param[in] properties - A map of property names and values
220      */
221     void populateSysProperties(const util::DbusPropertyMap& properties);
222 
223     /**
224      * @brief The system properties.
225      */
226     sys_properties sysProperties;
227 
228     /**
229      * @brief The vector for power supplies.
230      */
231     std::vector<std::unique_ptr<PowerSupply>> psus;
232 };
233 
234 } // namespace phosphor::power::manager
235