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 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 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 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 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 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 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 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 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 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 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 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 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 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