1 /**
2  * Copyright © 2020 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "services.hpp"
19 #include "system.hpp"
20 
21 #include <interfaces/manager_interface.hpp>
22 #include <sdbusplus/bus.hpp>
23 #include <sdbusplus/bus/match.hpp>
24 #include <sdbusplus/server/object.hpp>
25 #include <sdeventplus/event.hpp>
26 #include <sdeventplus/source/signal.hpp>
27 #include <sdeventplus/utility/timer.hpp>
28 
29 #include <filesystem>
30 #include <memory>
31 #include <string>
32 #include <vector>
33 
34 namespace phosphor::power::regulators
35 {
36 
37 using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;
38 
39 using ManagerObject = sdbusplus::server::object::object<
40     phosphor::power::regulators::interface::ManagerInterface>;
41 
42 class Manager : public ManagerObject
43 {
44   public:
45     Manager() = delete;
46     Manager(const Manager&) = delete;
47     Manager(Manager&&) = delete;
48     Manager& operator=(const Manager&) = delete;
49     Manager& operator=(Manager&&) = delete;
50     ~Manager() = default;
51 
52     /**
53      * Constructor
54      * Creates a manager over the regulators.
55      *
56      * @param bus the D-Bus bus
57      * @param event the sdevent event
58      */
59     Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event);
60 
61     /**
62      * Implements the D-Bus "configure" method.
63      *
64      * Configures all the voltage regulators in the system.
65      *
66      * This method should be called when the system is being powered on.  It
67      * needs to occur before the regulators have been enabled/turned on.
68      */
69     void configure() override;
70 
71     /**
72      * Callback function to handle interfacesAdded D-Bus signals
73      *
74      * @param msg Expanded sdbusplus message data
75      */
76     void interfacesAddedHandler(sdbusplus::message::message& msg);
77 
78     /**
79      * Implements the D-Bus "monitor" method.
80      *
81      * Sets whether regulator monitoring is enabled.
82      *
83      * When monitoring is enabled:
84      *   - regulator sensors will be read and published on D-Bus
85      *   - phase fault detection will be performed
86      *
87      * Regulator monitoring should be enabled when the system is being powered
88      * on.  It needs to occur after the regulators have been configured and
89      * enabled/turned on.
90      *
91      * Regulator monitoring should be disabled when the system is being powered
92      * off.  It needs to occur before the regulators have been disabled/turned
93      * off.
94      *
95      * Regulator monitoring can also be temporarily disabled and then re-enabled
96      * while the system is powered on.  This allows other applications or tools
97      * to temporarily communicate with the regulators for testing or debug.
98      * Monitoring should be disabled for only short periods of time; other
99      * applications, such as fan control, may be dependent on regulator sensors.
100      *
101      * @param enable true if monitoring should be enabled, false if it should be
102      *               disabled
103      */
104     void monitor(bool enable) override;
105 
106     /**
107      * Phase fault detection timer expired callback function.
108      */
109     void phaseFaultTimerExpired();
110 
111     /**
112      * Sensor monitoring timer expired callback function.
113      */
114     void sensorTimerExpired();
115 
116     /**
117      * Callback function to handle receiving a HUP signal
118      * to reload the configuration data.
119      *
120      * @param sigSrc sd_event_source signal wrapper
121      * @param sigInfo signal info on signal fd
122      */
123     void sighupHandler(sdeventplus::source::Signal& sigSrc,
124                        const struct signalfd_siginfo* sigInfo);
125 
126   private:
127     /**
128      * Clear any cached data or error history related to hardware devices.
129      *
130      * This method should be called when the system is powering on (booting).
131      * While the system was powered off, hardware could have been added,
132      * removed, or replaced.
133      */
134     void clearHardwareData();
135 
136     /**
137      * Finds the list of compatible system types using D-Bus methods.
138      *
139      * This list is used to find the correct JSON configuration file for the
140      * current system.
141      *
142      * Note that some systems do not support the D-Bus compatible interface.
143      *
144      * If a list of compatible system types is found, it is stored in the
145      * compatibleSystemTypes data member.
146      */
147     void findCompatibleSystemTypes();
148 
149     /**
150      * Finds the JSON configuration file.
151      *
152      * Looks for a configuration file based on the list of compatible system
153      * types.  If no file is found, looks for a file with the default name.
154      *
155      * Looks for the file in the test directory and standard directory.
156      *
157      * Throws an exception if an operating system error occurs while checking
158      * for the existence of a file.
159      *
160      * @return absolute path to config file, or an empty path if none found
161      */
162     std::filesystem::path findConfigFile();
163 
164     /**
165      * Returns whether the JSON configuration file has been loaded.
166      *
167      * @return true if config file loaded, false otherwise
168      */
169     bool isConfigFileLoaded() const
170     {
171         // If System object exists, the config file has been loaded
172         return (system != nullptr);
173     }
174 
175     /**
176      * Returns whether the system is currently powered on.
177      *
178      * @return true if system is powered on, false otherwise
179      */
180     bool isSystemPoweredOn();
181 
182     /**
183      * Loads the JSON configuration file.
184      *
185      * Looks for the config file using findConfigFile().
186      *
187      * If the config file is found, it is parsed and the resulting information
188      * is stored in the system data member.  If parsing fails, an error is
189      * logged.
190      */
191     void loadConfigFile();
192 
193     /**
194      * Waits until the JSON configuration file has been loaded.
195      *
196      * If the config file has not yet been loaded, waits until one of the
197      * following occurs:
198      * - config file is loaded
199      * - maximum amount of time to wait has elapsed
200      */
201     void waitUntilConfigFileLoaded();
202 
203     /**
204      * The D-Bus bus
205      */
206     sdbusplus::bus::bus& bus;
207 
208     /**
209      * Event to loop on
210      */
211     const sdeventplus::Event& eventLoop;
212 
213     /**
214      * System services like error logging and the journal.
215      */
216     BMCServices services;
217 
218     /**
219      * Event timer used to initiate phase fault detection.
220      */
221     Timer phaseFaultTimer;
222 
223     /**
224      * Event timer used to initiate sensor monitoring.
225      */
226     Timer sensorTimer;
227 
228     /**
229      * List of D-Bus signal matches
230      */
231     std::vector<std::unique_ptr<sdbusplus::bus::match::match>> signals{};
232 
233     /**
234      * Indicates whether regulator monitoring is enabled.
235      */
236     bool isMonitoringEnabled{false};
237 
238     /**
239      * List of compatible system types for the current system.
240      *
241      * Used to find the JSON configuration file.
242      */
243     std::vector<std::string> compatibleSystemTypes{};
244 
245     /**
246      * Computer system being controlled and monitored by the BMC.
247      *
248      * Contains the information loaded from the JSON configuration file.
249      * Contains nullptr if the configuration file has not been loaded.
250      */
251     std::unique_ptr<System> system{};
252 };
253 
254 } // namespace phosphor::power::regulators
255