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