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 74f2bcf1f9SMatthew Barth Manager::Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event) : 75*d1307294SZev Weiss ManagerObject{bus, managerObjPath}, bus{bus}, eventLoop{event}, 76*d1307294SZev Weiss services{bus}, phaseFaultTimer{event, 77*d1307294SZev Weiss std::bind(&Manager::phaseFaultTimerExpired, 78*d1307294SZev Weiss this)}, 79c8cbeac2SShawn McCarney sensorTimer{event, std::bind(&Manager::sensorTimerExpired, this)} 8029e9e385SMatthew Barth { 81589c181aSShawn McCarney // Subscribe to D-Bus interfacesAdded signal from Entity Manager. This 82589c181aSShawn McCarney // notifies us if the compatible interface becomes available later. 83589c181aSShawn McCarney std::string matchStr = sdbusplus::bus::match::rules::interfacesAdded() + 84589c181aSShawn McCarney sdbusplus::bus::match::rules::sender( 85589c181aSShawn McCarney "xyz.openbmc_project.EntityManager"); 86a61c1aa0SPatrick Williams std::unique_ptr<sdbusplus::bus::match_t> matchPtr = 87a61c1aa0SPatrick Williams std::make_unique<sdbusplus::bus::match_t>( 88589c181aSShawn McCarney bus, matchStr, 89589c181aSShawn McCarney std::bind(&Manager::interfacesAddedHandler, this, 90250d0a98SMatthew Barth std::placeholders::_1)); 91250d0a98SMatthew Barth signals.emplace_back(std::move(matchPtr)); 92250d0a98SMatthew Barth 93589c181aSShawn McCarney // Try to find compatible system types using D-Bus compatible interface. 94589c181aSShawn McCarney // Note that it might not be supported on this system, or the service that 95589c181aSShawn McCarney // provides the interface might not be running yet. 96589c181aSShawn McCarney findCompatibleSystemTypes(); 9784807b96SShawn McCarney 98589c181aSShawn McCarney // Try to find and load the JSON configuration file 99e0c6a2d9SShawn McCarney loadConfigFile(); 10029e9e385SMatthew Barth 101d9c8be57SShawn McCarney // Obtain D-Bus service name 10229e9e385SMatthew Barth bus.request_name(busName); 103d9c8be57SShawn McCarney 104d9c8be57SShawn McCarney // If system is already powered on, enable monitoring 105d9c8be57SShawn McCarney if (isSystemPoweredOn()) 106d9c8be57SShawn McCarney { 107d9c8be57SShawn McCarney monitor(true); 108d9c8be57SShawn McCarney } 10929e9e385SMatthew Barth } 11029e9e385SMatthew Barth 11129e9e385SMatthew Barth void Manager::configure() 11229e9e385SMatthew Barth { 1139bd94d36SShawn McCarney // Clear any cached data or error history related to hardware devices 1149bd94d36SShawn McCarney clearHardwareData(); 1159bd94d36SShawn McCarney 1168acaf547SShawn McCarney // Wait until the config file has been loaded or hit max wait time 1178acaf547SShawn McCarney waitUntilConfigFileLoaded(); 1188acaf547SShawn McCarney 1198acaf547SShawn McCarney // Verify config file has been loaded and System object is valid 1208acaf547SShawn McCarney if (isConfigFileLoaded()) 1216345c6c5SShawn McCarney { 1226345c6c5SShawn McCarney // Configure the regulator devices in the system 12323243f84SBob King system->configure(services); 1246345c6c5SShawn McCarney } 1256345c6c5SShawn McCarney else 1266345c6c5SShawn McCarney { 127415094c1SShawn McCarney // Write error message to journal 128b464c8bdSShawn McCarney services.getJournal().logError("Unable to configure regulator devices: " 129b464c8bdSShawn McCarney "Configuration file not loaded"); 1306345c6c5SShawn McCarney 131415094c1SShawn McCarney // Log critical error since regulators could not be configured. Could 132415094c1SShawn McCarney // cause hardware damage if default regulator settings are very wrong. 133415094c1SShawn McCarney services.getErrorLogging().logConfigFileError(Entry::Level::Critical, 134415094c1SShawn McCarney services.getJournal()); 135415094c1SShawn McCarney 136415094c1SShawn McCarney // Throw InternalFailure to propogate error status to D-Bus client 137415094c1SShawn McCarney throw sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure{}; 138415094c1SShawn McCarney } 13929e9e385SMatthew Barth } 14029e9e385SMatthew Barth 141589c181aSShawn McCarney void Manager::interfacesAddedHandler(sdbusplus::message::message& msg) 142589c181aSShawn McCarney { 143589c181aSShawn McCarney // Verify message is valid 144589c181aSShawn McCarney if (!msg) 145589c181aSShawn McCarney { 146589c181aSShawn McCarney return; 147589c181aSShawn McCarney } 148589c181aSShawn McCarney 149589c181aSShawn McCarney try 150589c181aSShawn McCarney { 151589c181aSShawn McCarney // Read object path for object that was created or had interface added 152589c181aSShawn McCarney sdbusplus::message::object_path objPath; 153589c181aSShawn McCarney msg.read(objPath); 154589c181aSShawn McCarney 155589c181aSShawn McCarney // Read the dictionary whose keys are interface names and whose values 156589c181aSShawn McCarney // are dictionaries containing the interface property names and values 157589c181aSShawn McCarney std::map<std::string, 158589c181aSShawn McCarney std::map<std::string, std::variant<std::vector<std::string>>>> 159589c181aSShawn McCarney intfProp; 160589c181aSShawn McCarney msg.read(intfProp); 161589c181aSShawn McCarney 162589c181aSShawn McCarney // Find the compatible interface, if present 163589c181aSShawn McCarney auto itIntf = intfProp.find(compatibleIntf); 164589c181aSShawn McCarney if (itIntf != intfProp.cend()) 165589c181aSShawn McCarney { 166589c181aSShawn McCarney // Find the Names property of the compatible interface, if present 167589c181aSShawn McCarney auto itProp = itIntf->second.find(compatibleNamesProp); 168589c181aSShawn McCarney if (itProp != itIntf->second.cend()) 169589c181aSShawn McCarney { 170589c181aSShawn McCarney // Get value of Names property 171589c181aSShawn McCarney auto propValue = std::get<0>(itProp->second); 172589c181aSShawn McCarney if (!propValue.empty()) 173589c181aSShawn McCarney { 174589c181aSShawn McCarney // Store list of compatible system types 175589c181aSShawn McCarney compatibleSystemTypes = propValue; 176589c181aSShawn McCarney 177589c181aSShawn McCarney // Find and load JSON config file based on system types 178589c181aSShawn McCarney loadConfigFile(); 179589c181aSShawn McCarney } 180589c181aSShawn McCarney } 181589c181aSShawn McCarney } 182589c181aSShawn McCarney } 183589c181aSShawn McCarney catch (const std::exception&) 184589c181aSShawn McCarney { 185589c181aSShawn McCarney // Error trying to read interfacesAdded message. One possible cause 186589c181aSShawn McCarney // could be a property whose value is not a std::vector<std::string>. 187589c181aSShawn McCarney } 188589c181aSShawn McCarney } 189589c181aSShawn McCarney 1905b19ea51SShawn McCarney void Manager::monitor(bool enable) 19129e9e385SMatthew Barth { 192d9c8be57SShawn McCarney // Check whether already in the requested monitoring state 193d9c8be57SShawn McCarney if (enable == isMonitoringEnabled) 19429e9e385SMatthew Barth { 195d9c8be57SShawn McCarney return; 196d9c8be57SShawn McCarney } 197d9c8be57SShawn McCarney 198d9c8be57SShawn McCarney isMonitoringEnabled = enable; 199d9c8be57SShawn McCarney if (isMonitoringEnabled) 200d9c8be57SShawn McCarney { 201d9c8be57SShawn McCarney services.getJournal().logDebug("Monitoring enabled"); 202d9c8be57SShawn McCarney 203c8cbeac2SShawn McCarney // Restart phase fault detection timer with repeating 15 second interval 204c8cbeac2SShawn McCarney phaseFaultTimer.restart(std::chrono::seconds(15)); 205c8cbeac2SShawn McCarney 206c8cbeac2SShawn McCarney // Restart sensor monitoring timer with repeating 1 second interval 207c8cbeac2SShawn McCarney sensorTimer.restart(std::chrono::seconds(1)); 208d9c8be57SShawn McCarney 209d9c8be57SShawn McCarney // Enable sensors service; put all sensors in an active state 210d9c8be57SShawn McCarney services.getSensors().enable(); 21129e9e385SMatthew Barth } 21229e9e385SMatthew Barth else 21329e9e385SMatthew Barth { 214d9c8be57SShawn McCarney services.getJournal().logDebug("Monitoring disabled"); 215d9c8be57SShawn McCarney 216c8cbeac2SShawn McCarney // Disable timers 217c8cbeac2SShawn McCarney phaseFaultTimer.setEnabled(false); 218c8cbeac2SShawn McCarney sensorTimer.setEnabled(false); 219d9c8be57SShawn McCarney 220d9c8be57SShawn McCarney // Disable sensors service; put all sensors in an inactive state 221d9c8be57SShawn McCarney services.getSensors().disable(); 2225b19ea51SShawn McCarney 2238acaf547SShawn McCarney // Verify config file has been loaded and System object is valid 2248acaf547SShawn McCarney if (isConfigFileLoaded()) 2255b19ea51SShawn McCarney { 2265b19ea51SShawn McCarney // Close the regulator devices in the system. Monitoring is 2275b19ea51SShawn McCarney // normally disabled because the system is being powered off. The 2285b19ea51SShawn McCarney // devices should be closed in case hardware is removed or replaced 2299bd94d36SShawn McCarney // while the system is powered off. 230d692d6dfSBob King system->closeDevices(services); 2315b19ea51SShawn McCarney } 2325b19ea51SShawn McCarney } 23329e9e385SMatthew Barth } 23429e9e385SMatthew Barth 235c8cbeac2SShawn McCarney void Manager::phaseFaultTimerExpired() 236589c181aSShawn McCarney { 237c8cbeac2SShawn McCarney // Verify config file has been loaded and System object is valid 238c8cbeac2SShawn McCarney if (isConfigFileLoaded()) 239c8cbeac2SShawn McCarney { 240c8cbeac2SShawn McCarney // Detect redundant phase faults in regulator devices in the system 241c8cbeac2SShawn McCarney system->detectPhaseFaults(services); 242c8cbeac2SShawn McCarney } 243589c181aSShawn McCarney } 244589c181aSShawn McCarney 245c8cbeac2SShawn McCarney void Manager::sensorTimerExpired() 246f2bcf1f9SMatthew Barth { 247d9c8be57SShawn McCarney // Notify sensors service that a sensor monitoring cycle is starting 248d9c8be57SShawn McCarney services.getSensors().startCycle(); 249d9c8be57SShawn McCarney 250d9c8be57SShawn McCarney // Verify config file has been loaded and System object is valid 251d9c8be57SShawn McCarney if (isConfigFileLoaded()) 252d9c8be57SShawn McCarney { 253d9c8be57SShawn McCarney // Monitor sensors for the voltage rails in the system 254d9c8be57SShawn McCarney system->monitorSensors(services); 255d9c8be57SShawn McCarney } 256d9c8be57SShawn McCarney 257d9c8be57SShawn McCarney // Notify sensors service that current sensor monitoring cycle has ended 258d9c8be57SShawn McCarney services.getSensors().endCycle(); 259f2bcf1f9SMatthew Barth } 260f2bcf1f9SMatthew Barth 261c8cbeac2SShawn McCarney void Manager::sighupHandler(sdeventplus::source::Signal& /*sigSrc*/, 262c8cbeac2SShawn McCarney const struct signalfd_siginfo* /*sigInfo*/) 263c8cbeac2SShawn McCarney { 264c8cbeac2SShawn McCarney // Reload the JSON configuration file 265c8cbeac2SShawn McCarney loadConfigFile(); 266c8cbeac2SShawn McCarney } 267c8cbeac2SShawn McCarney 2689bd94d36SShawn McCarney void Manager::clearHardwareData() 2699bd94d36SShawn McCarney { 2704e0402cbSShawn McCarney // Clear any cached hardware presence data and VPD values 2719bd94d36SShawn McCarney services.getPresenceService().clearCache(); 2724e0402cbSShawn McCarney services.getVPD().clearCache(); 2739bd94d36SShawn McCarney 2748acaf547SShawn McCarney // Verify config file has been loaded and System object is valid 2758acaf547SShawn McCarney if (isConfigFileLoaded()) 2769bd94d36SShawn McCarney { 2779bd94d36SShawn McCarney // Clear any cached hardware data in the System object 2789bd94d36SShawn McCarney system->clearCache(); 2799bd94d36SShawn McCarney 280ce540f3cSShawn McCarney // Clear error history related to hardware devices in the System object 281ce540f3cSShawn McCarney system->clearErrorHistory(); 282ce540f3cSShawn McCarney } 2839bd94d36SShawn McCarney } 2849bd94d36SShawn McCarney 285589c181aSShawn McCarney void Manager::findCompatibleSystemTypes() 2867cbc5536SMatthew Barth { 287bbc7c583SMatthew Barth using namespace phosphor::power::util; 288bbc7c583SMatthew Barth 289bbc7c583SMatthew Barth try 290bbc7c583SMatthew Barth { 291589c181aSShawn McCarney // Query object mapper for object paths that implement the compatible 292589c181aSShawn McCarney // interface. Returns a map of object paths to a map of services names 293589c181aSShawn McCarney // to their interfaces. 294589c181aSShawn McCarney DbusSubtree subTree = getSubTree(bus, "/xyz/openbmc_project/inventory", 295589c181aSShawn McCarney compatibleIntf, 0); 296589c181aSShawn McCarney 297589c181aSShawn McCarney // Get the first object path 298589c181aSShawn McCarney auto objectIt = subTree.cbegin(); 299589c181aSShawn McCarney if (objectIt != subTree.cend()) 300589c181aSShawn McCarney { 301589c181aSShawn McCarney std::string objPath = objectIt->first; 302589c181aSShawn McCarney 303589c181aSShawn McCarney // Get the first service name 304589c181aSShawn McCarney auto serviceIt = objectIt->second.cbegin(); 305589c181aSShawn McCarney if (serviceIt != objectIt->second.cend()) 306589c181aSShawn McCarney { 307589c181aSShawn McCarney std::string service = serviceIt->first; 308bbc7c583SMatthew Barth if (!service.empty()) 309bbc7c583SMatthew Barth { 310589c181aSShawn McCarney // Get compatible system types property value 311589c181aSShawn McCarney getProperty(compatibleIntf, compatibleNamesProp, objPath, 312589c181aSShawn McCarney service, bus, compatibleSystemTypes); 313bbc7c583SMatthew Barth } 314bbc7c583SMatthew Barth } 315589c181aSShawn McCarney } 316589c181aSShawn McCarney } 317589c181aSShawn McCarney catch (const std::exception&) 318bbc7c583SMatthew Barth { 319589c181aSShawn McCarney // Compatible system types information is not available. The current 320589c181aSShawn McCarney // system might not support the interface, or the service that 321589c181aSShawn McCarney // implements the interface might not be running yet. 322bbc7c583SMatthew Barth } 323bbc7c583SMatthew Barth } 324bbc7c583SMatthew Barth 325e0c6a2d9SShawn McCarney fs::path Manager::findConfigFile() 326e0c6a2d9SShawn McCarney { 327589c181aSShawn McCarney // Build list of possible base file names 328589c181aSShawn McCarney std::vector<std::string> fileNames{}; 329589c181aSShawn McCarney 330589c181aSShawn McCarney // Add possible file names based on compatible system types (if any) 331589c181aSShawn McCarney for (const std::string& systemType : compatibleSystemTypes) 332589c181aSShawn McCarney { 333589c181aSShawn McCarney // Replace all spaces and commas in system type name with underscores 334589c181aSShawn McCarney std::string fileName{systemType}; 335589c181aSShawn McCarney std::replace(fileName.begin(), fileName.end(), ' ', '_'); 336589c181aSShawn McCarney std::replace(fileName.begin(), fileName.end(), ',', '_'); 337589c181aSShawn McCarney 338589c181aSShawn McCarney // Append .json suffix and add to list 339589c181aSShawn McCarney fileName.append(".json"); 340589c181aSShawn McCarney fileNames.emplace_back(fileName); 341589c181aSShawn McCarney } 342589c181aSShawn McCarney 343589c181aSShawn McCarney // Add default file name for systems that don't use compatible interface 344589c181aSShawn McCarney fileNames.emplace_back(defaultConfigFileName); 345589c181aSShawn McCarney 346589c181aSShawn McCarney // Look for a config file with one of the possible base names 347589c181aSShawn McCarney for (const std::string& fileName : fileNames) 348589c181aSShawn McCarney { 349589c181aSShawn McCarney // Check if file exists in test directory 350e0c6a2d9SShawn McCarney fs::path pathName{testConfigFileDir / fileName}; 351589c181aSShawn McCarney if (fs::exists(pathName)) 352e0c6a2d9SShawn McCarney { 353589c181aSShawn McCarney return pathName; 354589c181aSShawn McCarney } 355589c181aSShawn McCarney 356589c181aSShawn McCarney // Check if file exists in standard directory 357e0c6a2d9SShawn McCarney pathName = standardConfigFileDir / fileName; 358589c181aSShawn McCarney if (fs::exists(pathName)) 359e0c6a2d9SShawn McCarney { 360589c181aSShawn McCarney return pathName; 361e0c6a2d9SShawn McCarney } 362e0c6a2d9SShawn McCarney } 363e0c6a2d9SShawn McCarney 364589c181aSShawn McCarney // No config file found; return empty path 365589c181aSShawn McCarney return fs::path{}; 366e0c6a2d9SShawn McCarney } 367e0c6a2d9SShawn McCarney 368d9c8be57SShawn McCarney bool Manager::isSystemPoweredOn() 369d9c8be57SShawn McCarney { 370d9c8be57SShawn McCarney bool isOn{false}; 371d9c8be57SShawn McCarney 372d9c8be57SShawn McCarney try 373d9c8be57SShawn McCarney { 374d9c8be57SShawn McCarney // Get D-Bus property that contains the current power state for 375d9c8be57SShawn McCarney // chassis0, which represents the entire system (all chassis) 376d9c8be57SShawn McCarney using namespace phosphor::power::util; 377d9c8be57SShawn McCarney auto service = getService(chassisStatePath, chassisStateIntf, bus); 378d9c8be57SShawn McCarney if (!service.empty()) 379d9c8be57SShawn McCarney { 380d9c8be57SShawn McCarney PowerState currentPowerState; 381d9c8be57SShawn McCarney getProperty(chassisStateIntf, chassisStateProp, chassisStatePath, 382d9c8be57SShawn McCarney service, bus, currentPowerState); 383d9c8be57SShawn McCarney if (currentPowerState == PowerState::On) 384d9c8be57SShawn McCarney { 385d9c8be57SShawn McCarney isOn = true; 386d9c8be57SShawn McCarney } 387d9c8be57SShawn McCarney } 388d9c8be57SShawn McCarney } 389d9c8be57SShawn McCarney catch (const std::exception& e) 390d9c8be57SShawn McCarney { 391d9c8be57SShawn McCarney // Current power state might not be available yet. The regulators 392d9c8be57SShawn McCarney // application can start before the power state is published on D-Bus. 393d9c8be57SShawn McCarney } 394d9c8be57SShawn McCarney 395d9c8be57SShawn McCarney return isOn; 396d9c8be57SShawn McCarney } 397d9c8be57SShawn McCarney 398e0c6a2d9SShawn McCarney void Manager::loadConfigFile() 399e0c6a2d9SShawn McCarney { 400e0c6a2d9SShawn McCarney try 401e0c6a2d9SShawn McCarney { 402e0c6a2d9SShawn McCarney // Find the absolute path to the config file 403e0c6a2d9SShawn McCarney fs::path pathName = findConfigFile(); 404589c181aSShawn McCarney if (!pathName.empty()) 405589c181aSShawn McCarney { 406e0c6a2d9SShawn McCarney // Log info message in journal; config file path is important 407b464c8bdSShawn McCarney services.getJournal().logInfo("Loading configuration file " + 408b464c8bdSShawn McCarney pathName.string()); 409e0c6a2d9SShawn McCarney 410e0c6a2d9SShawn McCarney // Parse the config file 411e0c6a2d9SShawn McCarney std::vector<std::unique_ptr<Rule>> rules{}; 412e0c6a2d9SShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{}; 413e0c6a2d9SShawn McCarney std::tie(rules, chassis) = config_file_parser::parse(pathName); 414e0c6a2d9SShawn McCarney 415589c181aSShawn McCarney // Store config file information in a new System object. The old 416589c181aSShawn McCarney // System object, if any, is automatically deleted. 417589c181aSShawn McCarney system = 418589c181aSShawn McCarney std::make_unique<System>(std::move(rules), std::move(chassis)); 419589c181aSShawn McCarney } 420e0c6a2d9SShawn McCarney } 421e0c6a2d9SShawn McCarney catch (const std::exception& e) 422e0c6a2d9SShawn McCarney { 423e0c6a2d9SShawn McCarney // Log error messages in journal 424b464c8bdSShawn McCarney services.getJournal().logError(exception_utils::getMessages(e)); 425b464c8bdSShawn McCarney services.getJournal().logError("Unable to load configuration file"); 426e0c6a2d9SShawn McCarney 427415094c1SShawn McCarney // Log error 428415094c1SShawn McCarney services.getErrorLogging().logConfigFileError(Entry::Level::Error, 429415094c1SShawn McCarney services.getJournal()); 430e0c6a2d9SShawn McCarney } 431e0c6a2d9SShawn McCarney } 432e0c6a2d9SShawn McCarney 4338acaf547SShawn McCarney void Manager::waitUntilConfigFileLoaded() 4348acaf547SShawn McCarney { 4358acaf547SShawn McCarney // If config file not loaded and list of compatible system types is empty 4368acaf547SShawn McCarney if (!isConfigFileLoaded() && compatibleSystemTypes.empty()) 4378acaf547SShawn McCarney { 4388acaf547SShawn McCarney // Loop until compatible system types found or waited max amount of time 4398acaf547SShawn McCarney auto start = std::chrono::system_clock::now(); 4408acaf547SShawn McCarney std::chrono::system_clock::duration timeWaited{0}; 4418acaf547SShawn McCarney while (compatibleSystemTypes.empty() && 4428acaf547SShawn McCarney (timeWaited <= maxTimeToWaitForCompatTypes)) 4438acaf547SShawn McCarney { 4448acaf547SShawn McCarney // Try to find list of compatible system types 4458acaf547SShawn McCarney findCompatibleSystemTypes(); 4468acaf547SShawn McCarney if (!compatibleSystemTypes.empty()) 4478acaf547SShawn McCarney { 4488acaf547SShawn McCarney // Compatible system types found; try to load config file 4498acaf547SShawn McCarney loadConfigFile(); 4508acaf547SShawn McCarney } 4518acaf547SShawn McCarney else 4528acaf547SShawn McCarney { 4538acaf547SShawn McCarney // Sleep 5 seconds 4548acaf547SShawn McCarney using namespace std::chrono_literals; 4558acaf547SShawn McCarney std::this_thread::sleep_for(5s); 4568acaf547SShawn McCarney } 4578acaf547SShawn McCarney timeWaited = std::chrono::system_clock::now() - start; 4588acaf547SShawn McCarney } 4598acaf547SShawn McCarney } 4608acaf547SShawn McCarney } 4618acaf547SShawn McCarney 46284807b96SShawn McCarney } // namespace phosphor::power::regulators 463