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     int 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             }
88             else
89             {
90                 powerOn = false;
91             }
92         }
93         catch (std::exception& e)
94         {
95             log<level::INFO>("Failed to get power state. Assuming it is off.");
96             powerOn = false;
97         }
98 
99         onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY);
100         clearFaults();
101         updateInventory();
102     }
103 
104     /**
105      * Starts the timer to start monitoring the list of devices.
106      */
107     int run()
108     {
109         return timer->get_event().loop();
110     }
111 
112     /**
113      * Write PMBus ON_OFF_CONFIG
114      *
115      * This function will be called to cause the PMBus device driver to send the
116      * ON_OFF_CONFIG command. Takes one byte of data.
117      */
118     void onOffConfig(const uint8_t data)
119     {
120         for (auto& psu : psus)
121         {
122             psu->onOffConfig(data);
123         }
124     }
125 
126     /**
127      * This function will be called in various situations in order to clear
128      * any fault status bits that may have been set, in order to start over
129      * with a clean state. Presence changes and power state changes will want
130      * to clear any faults logged.
131      */
132     void clearFaults()
133     {
134         for (auto& psu : psus)
135         {
136             psu->clearFaults();
137         }
138     }
139 
140   private:
141     /**
142      * The D-Bus object
143      */
144     sdbusplus::bus::bus& bus;
145 
146     /**
147      * The timer that runs to periodically check the power supplies.
148      */
149     std::unique_ptr<
150         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
151         timer;
152 
153     /**
154      * Create an error
155      *
156      * @param[in] faultName - 'name' message for the BMC error log entry
157      * @param[in] additionalData - The AdditionalData property for the error
158      */
159     void createError(const std::string& faultName,
160                      const std::map<std::string, std::string>& additionalData);
161 
162     /**
163      * Analyze the status of each of the power supplies.
164      *
165      * Log errors for faults, when and where appropriate.
166      */
167     void analyze();
168 
169     /** @brief True if the power is on. */
170     bool powerOn = false;
171 
172     /** @brief Used as part of subscribing to power on state changes*/
173     std::string powerService;
174 
175     /** @brief Used to subscribe to D-Bus power on state changes */
176     std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
177 
178     /** @brief Used to subscribe to Entity Manager interfaces added */
179     std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch;
180 
181     /**
182      * @brief Callback for power state property changes
183      *
184      * Process changes to the powered on state property for the system.
185      *
186      * @param[in] msg - Data associated with the power state signal
187      */
188     void powerStateChanged(sdbusplus::message::message& msg);
189 
190     /**
191      * @brief Callback for entity-manager interface added
192      *
193      * Process the information from the supported configuration and or IBM CFFPS
194      * Connector interface being added.
195      *
196      * @param[in] msg - Data associated with the interfaces added signal
197      */
198     void entityManagerIfaceAdded(sdbusplus::message::message& msg);
199 
200     /**
201      * @brief Adds properties to the inventory.
202      *
203      * Reads the values from the devices and writes them to the associated
204      * power supply D-Bus inventory objects.
205      *
206      * This needs to be done on startup, and each time the presence state
207      * changes.
208      */
209     void updateInventory()
210     {
211         for (auto& psu : psus)
212         {
213             psu->updateInventory();
214         }
215     }
216 
217     /**
218      * @brief Helper function to populate the system properties
219      *
220      * @param[in] properties - A map of property names and values
221      */
222     void populateSysProperties(const util::DbusPropertyMap& properties);
223 
224     /**
225      * @brief Map of supported PSU configurations that include the model name
226      * and their properties.
227      */
228     std::multimap<std::string, sys_properties> supportedConfigs;
229 
230     /**
231      * @brief The vector for power supplies.
232      */
233     std::vector<std::unique_ptr<PowerSupply>> psus;
234 };
235 
236 } // namespace phosphor::power::manager
237