129e9e385SMatthew Barth /**
229e9e385SMatthew Barth * Copyright © 2020 IBM Corporation
329e9e385SMatthew Barth *
429e9e385SMatthew Barth * Licensed under the Apache License, Version 2.0 (the "License");
529e9e385SMatthew Barth * you may not use this file except in compliance with the License.
629e9e385SMatthew Barth * You may obtain a copy of the License at
729e9e385SMatthew Barth *
829e9e385SMatthew Barth * http://www.apache.org/licenses/LICENSE-2.0
929e9e385SMatthew Barth *
1029e9e385SMatthew Barth * Unless required by applicable law or agreed to in writing, software
1129e9e385SMatthew Barth * distributed under the License is distributed on an "AS IS" BASIS,
1229e9e385SMatthew Barth * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1329e9e385SMatthew Barth * See the License for the specific language governing permissions and
1429e9e385SMatthew Barth * limitations under the License.
1529e9e385SMatthew Barth */
1629e9e385SMatthew Barth
1729e9e385SMatthew Barth #include "manager.hpp"
1829e9e385SMatthew Barth
19e0c6a2d9SShawn McCarney #include "chassis.hpp"
20e0c6a2d9SShawn McCarney #include "config_file_parser.hpp"
21e0c6a2d9SShawn McCarney #include "exception_utils.hpp"
22e0c6a2d9SShawn McCarney #include "rule.hpp"
23bbc7c583SMatthew Barth #include "utility.hpp"
24bbc7c583SMatthew Barth
25415094c1SShawn McCarney #include <xyz/openbmc_project/Common/error.hpp>
26d9c8be57SShawn McCarney #include <xyz/openbmc_project/State/Chassis/server.hpp>
27415094c1SShawn McCarney
28589c181aSShawn McCarney #include <algorithm>
29f2bcf1f9SMatthew Barth #include <chrono>
30e0c6a2d9SShawn McCarney #include <exception>
31589c181aSShawn McCarney #include <functional>
32589c181aSShawn McCarney #include <map>
338acaf547SShawn McCarney #include <thread>
34e0c6a2d9SShawn McCarney #include <tuple>
35e0c6a2d9SShawn McCarney #include <utility>
36250d0a98SMatthew Barth #include <variant>
37f2bcf1f9SMatthew Barth
3884807b96SShawn McCarney namespace phosphor::power::regulators
3929e9e385SMatthew Barth {
4029e9e385SMatthew Barth
41e0c6a2d9SShawn McCarney namespace fs = std::filesystem;
42e0c6a2d9SShawn McCarney
43589c181aSShawn McCarney constexpr auto busName = "xyz.openbmc_project.Power.Regulators";
44589c181aSShawn McCarney constexpr auto managerObjPath = "/xyz/openbmc_project/power/regulators/manager";
45589c181aSShawn McCarney constexpr auto compatibleIntf =
46589c181aSShawn McCarney "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
47589c181aSShawn McCarney constexpr auto compatibleNamesProp = "Names";
48d9c8be57SShawn McCarney constexpr auto chassisStatePath = "/xyz/openbmc_project/state/chassis0";
49d9c8be57SShawn McCarney constexpr auto chassisStateIntf = "xyz.openbmc_project.State.Chassis";
50d9c8be57SShawn McCarney constexpr auto chassisStateProp = "CurrentPowerState";
518acaf547SShawn McCarney constexpr std::chrono::minutes maxTimeToWaitForCompatTypes{5};
52589c181aSShawn McCarney
53d9c8be57SShawn McCarney using PowerState =
54d9c8be57SShawn McCarney sdbusplus::xyz::openbmc_project::State::server::Chassis::PowerState;
55d9c8be57SShawn McCarney
56589c181aSShawn McCarney /**
57589c181aSShawn McCarney * Default configuration file name. This is used when the system does not
58589c181aSShawn McCarney * implement the D-Bus compatible interface.
59589c181aSShawn McCarney */
60589c181aSShawn McCarney constexpr auto defaultConfigFileName = "config.json";
61589c181aSShawn McCarney
62e0c6a2d9SShawn McCarney /**
63e0c6a2d9SShawn McCarney * Standard configuration file directory. This directory is part of the
64e0c6a2d9SShawn McCarney * firmware install image. It contains the standard version of the config file.
65e0c6a2d9SShawn McCarney */
66e0c6a2d9SShawn McCarney const fs::path standardConfigFileDir{"/usr/share/phosphor-regulators"};
67e0c6a2d9SShawn McCarney
68e0c6a2d9SShawn McCarney /**
69e0c6a2d9SShawn McCarney * Test configuration file directory. This directory can contain a test version
70e0c6a2d9SShawn McCarney * of the config file. The test version will override the standard version.
71e0c6a2d9SShawn McCarney */
72e0c6a2d9SShawn McCarney const fs::path testConfigFileDir{"/etc/phosphor-regulators"};
73e0c6a2d9SShawn McCarney
Manager(sdbusplus::bus_t & bus,const sdeventplus::Event & event)747354ce62SPatrick Williams Manager::Manager(sdbusplus::bus_t& bus, const sdeventplus::Event& event) :
75d1307294SZev Weiss ManagerObject{bus, managerObjPath}, bus{bus}, eventLoop{event},
76*48781aefSPatrick Williams services{bus},
77*48781aefSPatrick Williams phaseFaultTimer{event, std::bind(&Manager::phaseFaultTimerExpired, this)},
78c8cbeac2SShawn McCarney sensorTimer{event, std::bind(&Manager::sensorTimerExpired, this)}
7929e9e385SMatthew Barth {
80589c181aSShawn McCarney // Subscribe to D-Bus interfacesAdded signal from Entity Manager. This
81589c181aSShawn McCarney // notifies us if the compatible interface becomes available later.
82589c181aSShawn McCarney std::string matchStr = sdbusplus::bus::match::rules::interfacesAdded() +
83589c181aSShawn McCarney sdbusplus::bus::match::rules::sender(
84589c181aSShawn McCarney "xyz.openbmc_project.EntityManager");
85a61c1aa0SPatrick Williams std::unique_ptr<sdbusplus::bus::match_t> matchPtr =
86a61c1aa0SPatrick Williams std::make_unique<sdbusplus::bus::match_t>(
87589c181aSShawn McCarney bus, matchStr,
88589c181aSShawn McCarney std::bind(&Manager::interfacesAddedHandler, this,
89250d0a98SMatthew Barth std::placeholders::_1));
90250d0a98SMatthew Barth signals.emplace_back(std::move(matchPtr));
91250d0a98SMatthew Barth
92589c181aSShawn McCarney // Try to find compatible system types using D-Bus compatible interface.
93589c181aSShawn McCarney // Note that it might not be supported on this system, or the service that
94589c181aSShawn McCarney // provides the interface might not be running yet.
95589c181aSShawn McCarney findCompatibleSystemTypes();
9684807b96SShawn McCarney
97589c181aSShawn McCarney // Try to find and load the JSON configuration file
98e0c6a2d9SShawn McCarney loadConfigFile();
9929e9e385SMatthew Barth
100d9c8be57SShawn McCarney // Obtain D-Bus service name
10129e9e385SMatthew Barth bus.request_name(busName);
102d9c8be57SShawn McCarney
103d9c8be57SShawn McCarney // If system is already powered on, enable monitoring
104d9c8be57SShawn McCarney if (isSystemPoweredOn())
105d9c8be57SShawn McCarney {
106d9c8be57SShawn McCarney monitor(true);
107d9c8be57SShawn McCarney }
10829e9e385SMatthew Barth }
10929e9e385SMatthew Barth
configure()11029e9e385SMatthew Barth void Manager::configure()
11129e9e385SMatthew Barth {
1129bd94d36SShawn McCarney // Clear any cached data or error history related to hardware devices
1139bd94d36SShawn McCarney clearHardwareData();
1149bd94d36SShawn McCarney
1158acaf547SShawn McCarney // Wait until the config file has been loaded or hit max wait time
1168acaf547SShawn McCarney waitUntilConfigFileLoaded();
1178acaf547SShawn McCarney
1188acaf547SShawn McCarney // Verify config file has been loaded and System object is valid
1198acaf547SShawn McCarney if (isConfigFileLoaded())
1206345c6c5SShawn McCarney {
1216345c6c5SShawn McCarney // Configure the regulator devices in the system
12223243f84SBob King system->configure(services);
1236345c6c5SShawn McCarney }
1246345c6c5SShawn McCarney else
1256345c6c5SShawn McCarney {
126415094c1SShawn McCarney // Write error message to journal
127b464c8bdSShawn McCarney services.getJournal().logError("Unable to configure regulator devices: "
128b464c8bdSShawn McCarney "Configuration file not loaded");
1296345c6c5SShawn McCarney
130415094c1SShawn McCarney // Log critical error since regulators could not be configured. Could
131415094c1SShawn McCarney // cause hardware damage if default regulator settings are very wrong.
132415094c1SShawn McCarney services.getErrorLogging().logConfigFileError(Entry::Level::Critical,
133415094c1SShawn McCarney services.getJournal());
134415094c1SShawn McCarney
135415094c1SShawn McCarney // Throw InternalFailure to propogate error status to D-Bus client
136415094c1SShawn McCarney throw sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure{};
137415094c1SShawn McCarney }
13829e9e385SMatthew Barth }
13929e9e385SMatthew Barth
interfacesAddedHandler(sdbusplus::message_t & msg)1407354ce62SPatrick Williams void Manager::interfacesAddedHandler(sdbusplus::message_t& msg)
141589c181aSShawn McCarney {
142589c181aSShawn McCarney // Verify message is valid
143589c181aSShawn McCarney if (!msg)
144589c181aSShawn McCarney {
145589c181aSShawn McCarney return;
146589c181aSShawn McCarney }
147589c181aSShawn McCarney
148589c181aSShawn McCarney try
149589c181aSShawn McCarney {
150589c181aSShawn McCarney // Read object path for object that was created or had interface added
151589c181aSShawn McCarney sdbusplus::message::object_path objPath;
152589c181aSShawn McCarney msg.read(objPath);
153589c181aSShawn McCarney
154589c181aSShawn McCarney // Read the dictionary whose keys are interface names and whose values
155589c181aSShawn McCarney // are dictionaries containing the interface property names and values
156589c181aSShawn McCarney std::map<std::string,
157589c181aSShawn McCarney std::map<std::string, std::variant<std::vector<std::string>>>>
158589c181aSShawn McCarney intfProp;
159589c181aSShawn McCarney msg.read(intfProp);
160589c181aSShawn McCarney
161589c181aSShawn McCarney // Find the compatible interface, if present
162589c181aSShawn McCarney auto itIntf = intfProp.find(compatibleIntf);
163589c181aSShawn McCarney if (itIntf != intfProp.cend())
164589c181aSShawn McCarney {
165589c181aSShawn McCarney // Find the Names property of the compatible interface, if present
166589c181aSShawn McCarney auto itProp = itIntf->second.find(compatibleNamesProp);
167589c181aSShawn McCarney if (itProp != itIntf->second.cend())
168589c181aSShawn McCarney {
169589c181aSShawn McCarney // Get value of Names property
170589c181aSShawn McCarney auto propValue = std::get<0>(itProp->second);
171589c181aSShawn McCarney if (!propValue.empty())
172589c181aSShawn McCarney {
173589c181aSShawn McCarney // Store list of compatible system types
174589c181aSShawn McCarney compatibleSystemTypes = propValue;
175589c181aSShawn McCarney
176589c181aSShawn McCarney // Find and load JSON config file based on system types
177589c181aSShawn McCarney loadConfigFile();
178589c181aSShawn McCarney }
179589c181aSShawn McCarney }
180589c181aSShawn McCarney }
181589c181aSShawn McCarney }
182589c181aSShawn McCarney catch (const std::exception&)
183589c181aSShawn McCarney {
184589c181aSShawn McCarney // Error trying to read interfacesAdded message. One possible cause
185589c181aSShawn McCarney // could be a property whose value is not a std::vector<std::string>.
186589c181aSShawn McCarney }
187589c181aSShawn McCarney }
188589c181aSShawn McCarney
monitor(bool enable)1895b19ea51SShawn McCarney void Manager::monitor(bool enable)
19029e9e385SMatthew Barth {
191d9c8be57SShawn McCarney // Check whether already in the requested monitoring state
192d9c8be57SShawn McCarney if (enable == isMonitoringEnabled)
19329e9e385SMatthew Barth {
194d9c8be57SShawn McCarney return;
195d9c8be57SShawn McCarney }
196d9c8be57SShawn McCarney
197d9c8be57SShawn McCarney isMonitoringEnabled = enable;
198d9c8be57SShawn McCarney if (isMonitoringEnabled)
199d9c8be57SShawn McCarney {
200d9c8be57SShawn McCarney services.getJournal().logDebug("Monitoring enabled");
201d9c8be57SShawn McCarney
202c8cbeac2SShawn McCarney // Restart phase fault detection timer with repeating 15 second interval
203c8cbeac2SShawn McCarney phaseFaultTimer.restart(std::chrono::seconds(15));
204c8cbeac2SShawn McCarney
205c8cbeac2SShawn McCarney // Restart sensor monitoring timer with repeating 1 second interval
206c8cbeac2SShawn McCarney sensorTimer.restart(std::chrono::seconds(1));
207d9c8be57SShawn McCarney
208d9c8be57SShawn McCarney // Enable sensors service; put all sensors in an active state
209d9c8be57SShawn McCarney services.getSensors().enable();
21029e9e385SMatthew Barth }
21129e9e385SMatthew Barth else
21229e9e385SMatthew Barth {
213d9c8be57SShawn McCarney services.getJournal().logDebug("Monitoring disabled");
214d9c8be57SShawn McCarney
215c8cbeac2SShawn McCarney // Disable timers
216c8cbeac2SShawn McCarney phaseFaultTimer.setEnabled(false);
217c8cbeac2SShawn McCarney sensorTimer.setEnabled(false);
218d9c8be57SShawn McCarney
219d9c8be57SShawn McCarney // Disable sensors service; put all sensors in an inactive state
220d9c8be57SShawn McCarney services.getSensors().disable();
2215b19ea51SShawn McCarney
2228acaf547SShawn McCarney // Verify config file has been loaded and System object is valid
2238acaf547SShawn McCarney if (isConfigFileLoaded())
2245b19ea51SShawn McCarney {
2255b19ea51SShawn McCarney // Close the regulator devices in the system. Monitoring is
2265b19ea51SShawn McCarney // normally disabled because the system is being powered off. The
2275b19ea51SShawn McCarney // devices should be closed in case hardware is removed or replaced
2289bd94d36SShawn McCarney // while the system is powered off.
229d692d6dfSBob King system->closeDevices(services);
2305b19ea51SShawn McCarney }
2315b19ea51SShawn McCarney }
23229e9e385SMatthew Barth }
23329e9e385SMatthew Barth
phaseFaultTimerExpired()234c8cbeac2SShawn McCarney void Manager::phaseFaultTimerExpired()
235589c181aSShawn McCarney {
236c8cbeac2SShawn McCarney // Verify config file has been loaded and System object is valid
237c8cbeac2SShawn McCarney if (isConfigFileLoaded())
238c8cbeac2SShawn McCarney {
239c8cbeac2SShawn McCarney // Detect redundant phase faults in regulator devices in the system
240c8cbeac2SShawn McCarney system->detectPhaseFaults(services);
241c8cbeac2SShawn McCarney }
242589c181aSShawn McCarney }
243589c181aSShawn McCarney
sensorTimerExpired()244c8cbeac2SShawn McCarney void Manager::sensorTimerExpired()
245f2bcf1f9SMatthew Barth {
246d9c8be57SShawn McCarney // Notify sensors service that a sensor monitoring cycle is starting
247d9c8be57SShawn McCarney services.getSensors().startCycle();
248d9c8be57SShawn McCarney
249d9c8be57SShawn McCarney // Verify config file has been loaded and System object is valid
250d9c8be57SShawn McCarney if (isConfigFileLoaded())
251d9c8be57SShawn McCarney {
252d9c8be57SShawn McCarney // Monitor sensors for the voltage rails in the system
253d9c8be57SShawn McCarney system->monitorSensors(services);
254d9c8be57SShawn McCarney }
255d9c8be57SShawn McCarney
256d9c8be57SShawn McCarney // Notify sensors service that current sensor monitoring cycle has ended
257d9c8be57SShawn McCarney services.getSensors().endCycle();
258f2bcf1f9SMatthew Barth }
259f2bcf1f9SMatthew Barth
sighupHandler(sdeventplus::source::Signal &,const struct signalfd_siginfo *)260c8cbeac2SShawn McCarney void Manager::sighupHandler(sdeventplus::source::Signal& /*sigSrc*/,
261c8cbeac2SShawn McCarney const struct signalfd_siginfo* /*sigInfo*/)
262c8cbeac2SShawn McCarney {
263c8cbeac2SShawn McCarney // Reload the JSON configuration file
264c8cbeac2SShawn McCarney loadConfigFile();
265c8cbeac2SShawn McCarney }
266c8cbeac2SShawn McCarney
clearHardwareData()2679bd94d36SShawn McCarney void Manager::clearHardwareData()
2689bd94d36SShawn McCarney {
2694e0402cbSShawn McCarney // Clear any cached hardware presence data and VPD values
2709bd94d36SShawn McCarney services.getPresenceService().clearCache();
2714e0402cbSShawn McCarney services.getVPD().clearCache();
2729bd94d36SShawn McCarney
2738acaf547SShawn McCarney // Verify config file has been loaded and System object is valid
2748acaf547SShawn McCarney if (isConfigFileLoaded())
2759bd94d36SShawn McCarney {
2769bd94d36SShawn McCarney // Clear any cached hardware data in the System object
2779bd94d36SShawn McCarney system->clearCache();
2789bd94d36SShawn McCarney
279ce540f3cSShawn McCarney // Clear error history related to hardware devices in the System object
280ce540f3cSShawn McCarney system->clearErrorHistory();
281ce540f3cSShawn McCarney }
2829bd94d36SShawn McCarney }
2839bd94d36SShawn McCarney
findCompatibleSystemTypes()284589c181aSShawn McCarney void Manager::findCompatibleSystemTypes()
2857cbc5536SMatthew Barth {
286bbc7c583SMatthew Barth using namespace phosphor::power::util;
287bbc7c583SMatthew Barth
288bbc7c583SMatthew Barth try
289bbc7c583SMatthew Barth {
290589c181aSShawn McCarney // Query object mapper for object paths that implement the compatible
291589c181aSShawn McCarney // interface. Returns a map of object paths to a map of services names
292589c181aSShawn McCarney // to their interfaces.
293589c181aSShawn McCarney DbusSubtree subTree = getSubTree(bus, "/xyz/openbmc_project/inventory",
294589c181aSShawn McCarney compatibleIntf, 0);
295589c181aSShawn McCarney
296589c181aSShawn McCarney // Get the first object path
297589c181aSShawn McCarney auto objectIt = subTree.cbegin();
298589c181aSShawn McCarney if (objectIt != subTree.cend())
299589c181aSShawn McCarney {
300589c181aSShawn McCarney std::string objPath = objectIt->first;
301589c181aSShawn McCarney
302589c181aSShawn McCarney // Get the first service name
303589c181aSShawn McCarney auto serviceIt = objectIt->second.cbegin();
304589c181aSShawn McCarney if (serviceIt != objectIt->second.cend())
305589c181aSShawn McCarney {
306589c181aSShawn McCarney std::string service = serviceIt->first;
307bbc7c583SMatthew Barth if (!service.empty())
308bbc7c583SMatthew Barth {
309589c181aSShawn McCarney // Get compatible system types property value
310589c181aSShawn McCarney getProperty(compatibleIntf, compatibleNamesProp, objPath,
311589c181aSShawn McCarney service, bus, compatibleSystemTypes);
312bbc7c583SMatthew Barth }
313bbc7c583SMatthew Barth }
314589c181aSShawn McCarney }
315589c181aSShawn McCarney }
316589c181aSShawn McCarney catch (const std::exception&)
317bbc7c583SMatthew Barth {
318589c181aSShawn McCarney // Compatible system types information is not available. The current
319589c181aSShawn McCarney // system might not support the interface, or the service that
320589c181aSShawn McCarney // implements the interface might not be running yet.
321bbc7c583SMatthew Barth }
322bbc7c583SMatthew Barth }
323bbc7c583SMatthew Barth
findConfigFile()324e0c6a2d9SShawn McCarney fs::path Manager::findConfigFile()
325e0c6a2d9SShawn McCarney {
326589c181aSShawn McCarney // Build list of possible base file names
327589c181aSShawn McCarney std::vector<std::string> fileNames{};
328589c181aSShawn McCarney
329589c181aSShawn McCarney // Add possible file names based on compatible system types (if any)
330589c181aSShawn McCarney for (const std::string& systemType : compatibleSystemTypes)
331589c181aSShawn McCarney {
332589c181aSShawn McCarney // Replace all spaces and commas in system type name with underscores
333589c181aSShawn McCarney std::string fileName{systemType};
334589c181aSShawn McCarney std::replace(fileName.begin(), fileName.end(), ' ', '_');
335589c181aSShawn McCarney std::replace(fileName.begin(), fileName.end(), ',', '_');
336589c181aSShawn McCarney
337589c181aSShawn McCarney // Append .json suffix and add to list
338589c181aSShawn McCarney fileName.append(".json");
339589c181aSShawn McCarney fileNames.emplace_back(fileName);
340589c181aSShawn McCarney }
341589c181aSShawn McCarney
342589c181aSShawn McCarney // Add default file name for systems that don't use compatible interface
343589c181aSShawn McCarney fileNames.emplace_back(defaultConfigFileName);
344589c181aSShawn McCarney
345589c181aSShawn McCarney // Look for a config file with one of the possible base names
346589c181aSShawn McCarney for (const std::string& fileName : fileNames)
347589c181aSShawn McCarney {
348589c181aSShawn McCarney // Check if file exists in test directory
349e0c6a2d9SShawn McCarney fs::path pathName{testConfigFileDir / fileName};
350589c181aSShawn McCarney if (fs::exists(pathName))
351e0c6a2d9SShawn McCarney {
352589c181aSShawn McCarney return pathName;
353589c181aSShawn McCarney }
354589c181aSShawn McCarney
355589c181aSShawn McCarney // Check if file exists in standard directory
356e0c6a2d9SShawn McCarney pathName = standardConfigFileDir / fileName;
357589c181aSShawn McCarney if (fs::exists(pathName))
358e0c6a2d9SShawn McCarney {
359589c181aSShawn McCarney return pathName;
360e0c6a2d9SShawn McCarney }
361e0c6a2d9SShawn McCarney }
362e0c6a2d9SShawn McCarney
363589c181aSShawn McCarney // No config file found; return empty path
364589c181aSShawn McCarney return fs::path{};
365e0c6a2d9SShawn McCarney }
366e0c6a2d9SShawn McCarney
isSystemPoweredOn()367d9c8be57SShawn McCarney bool Manager::isSystemPoweredOn()
368d9c8be57SShawn McCarney {
369d9c8be57SShawn McCarney bool isOn{false};
370d9c8be57SShawn McCarney
371d9c8be57SShawn McCarney try
372d9c8be57SShawn McCarney {
373d9c8be57SShawn McCarney // Get D-Bus property that contains the current power state for
374d9c8be57SShawn McCarney // chassis0, which represents the entire system (all chassis)
375d9c8be57SShawn McCarney using namespace phosphor::power::util;
376d9c8be57SShawn McCarney auto service = getService(chassisStatePath, chassisStateIntf, bus);
377d9c8be57SShawn McCarney if (!service.empty())
378d9c8be57SShawn McCarney {
379d9c8be57SShawn McCarney PowerState currentPowerState;
380d9c8be57SShawn McCarney getProperty(chassisStateIntf, chassisStateProp, chassisStatePath,
381d9c8be57SShawn McCarney service, bus, currentPowerState);
382d9c8be57SShawn McCarney if (currentPowerState == PowerState::On)
383d9c8be57SShawn McCarney {
384d9c8be57SShawn McCarney isOn = true;
385d9c8be57SShawn McCarney }
386d9c8be57SShawn McCarney }
387d9c8be57SShawn McCarney }
388d9c8be57SShawn McCarney catch (const std::exception& e)
389d9c8be57SShawn McCarney {
390d9c8be57SShawn McCarney // Current power state might not be available yet. The regulators
391d9c8be57SShawn McCarney // application can start before the power state is published on D-Bus.
392d9c8be57SShawn McCarney }
393d9c8be57SShawn McCarney
394d9c8be57SShawn McCarney return isOn;
395d9c8be57SShawn McCarney }
396d9c8be57SShawn McCarney
loadConfigFile()397e0c6a2d9SShawn McCarney void Manager::loadConfigFile()
398e0c6a2d9SShawn McCarney {
399e0c6a2d9SShawn McCarney try
400e0c6a2d9SShawn McCarney {
401e0c6a2d9SShawn McCarney // Find the absolute path to the config file
402e0c6a2d9SShawn McCarney fs::path pathName = findConfigFile();
403589c181aSShawn McCarney if (!pathName.empty())
404589c181aSShawn McCarney {
405e0c6a2d9SShawn McCarney // Log info message in journal; config file path is important
406b464c8bdSShawn McCarney services.getJournal().logInfo("Loading configuration file " +
407b464c8bdSShawn McCarney pathName.string());
408e0c6a2d9SShawn McCarney
409e0c6a2d9SShawn McCarney // Parse the config file
410e0c6a2d9SShawn McCarney std::vector<std::unique_ptr<Rule>> rules{};
411e0c6a2d9SShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{};
412e0c6a2d9SShawn McCarney std::tie(rules, chassis) = config_file_parser::parse(pathName);
413e0c6a2d9SShawn McCarney
414589c181aSShawn McCarney // Store config file information in a new System object. The old
415589c181aSShawn McCarney // System object, if any, is automatically deleted.
416*48781aefSPatrick Williams system = std::make_unique<System>(std::move(rules),
417*48781aefSPatrick Williams std::move(chassis));
418589c181aSShawn McCarney }
419e0c6a2d9SShawn McCarney }
420e0c6a2d9SShawn McCarney catch (const std::exception& e)
421e0c6a2d9SShawn McCarney {
422e0c6a2d9SShawn McCarney // Log error messages in journal
423b464c8bdSShawn McCarney services.getJournal().logError(exception_utils::getMessages(e));
424b464c8bdSShawn McCarney services.getJournal().logError("Unable to load configuration file");
425e0c6a2d9SShawn McCarney
426415094c1SShawn McCarney // Log error
427415094c1SShawn McCarney services.getErrorLogging().logConfigFileError(Entry::Level::Error,
428415094c1SShawn McCarney services.getJournal());
429e0c6a2d9SShawn McCarney }
430e0c6a2d9SShawn McCarney }
431e0c6a2d9SShawn McCarney
waitUntilConfigFileLoaded()4328acaf547SShawn McCarney void Manager::waitUntilConfigFileLoaded()
4338acaf547SShawn McCarney {
4348acaf547SShawn McCarney // If config file not loaded and list of compatible system types is empty
4358acaf547SShawn McCarney if (!isConfigFileLoaded() && compatibleSystemTypes.empty())
4368acaf547SShawn McCarney {
4378acaf547SShawn McCarney // Loop until compatible system types found or waited max amount of time
4388acaf547SShawn McCarney auto start = std::chrono::system_clock::now();
4398acaf547SShawn McCarney std::chrono::system_clock::duration timeWaited{0};
4408acaf547SShawn McCarney while (compatibleSystemTypes.empty() &&
4418acaf547SShawn McCarney (timeWaited <= maxTimeToWaitForCompatTypes))
4428acaf547SShawn McCarney {
4438acaf547SShawn McCarney // Try to find list of compatible system types
4448acaf547SShawn McCarney findCompatibleSystemTypes();
4458acaf547SShawn McCarney if (!compatibleSystemTypes.empty())
4468acaf547SShawn McCarney {
4478acaf547SShawn McCarney // Compatible system types found; try to load config file
4488acaf547SShawn McCarney loadConfigFile();
4498acaf547SShawn McCarney }
4508acaf547SShawn McCarney else
4518acaf547SShawn McCarney {
4528acaf547SShawn McCarney // Sleep 5 seconds
4538acaf547SShawn McCarney using namespace std::chrono_literals;
4548acaf547SShawn McCarney std::this_thread::sleep_for(5s);
4558acaf547SShawn McCarney }
4568acaf547SShawn McCarney timeWaited = std::chrono::system_clock::now() - start;
4578acaf547SShawn McCarney }
4588acaf547SShawn McCarney }
4598acaf547SShawn McCarney }
4608acaf547SShawn McCarney
46184807b96SShawn McCarney } // namespace phosphor::power::regulators
462