| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 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 |  | 
 | 17 | #include "manager.hpp" | 
 | 18 |  | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 19 | #include "chassis.hpp" | 
 | 20 | #include "config_file_parser.hpp" | 
 | 21 | #include "exception_utils.hpp" | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 22 | #include "rule.hpp" | 
| Matthew Barth | bbc7c58 | 2020-02-03 15:55:15 -0600 | [diff] [blame] | 23 | #include "utility.hpp" | 
 | 24 |  | 
| Shawn McCarney | 415094c | 2021-02-15 11:08:19 -0600 | [diff] [blame] | 25 | #include <xyz/openbmc_project/Common/error.hpp> | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 26 | #include <xyz/openbmc_project/State/Chassis/server.hpp> | 
| Shawn McCarney | 415094c | 2021-02-15 11:08:19 -0600 | [diff] [blame] | 27 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 28 | #include <algorithm> | 
| Matthew Barth | f2bcf1f | 2020-01-29 14:42:47 -0600 | [diff] [blame] | 29 | #include <chrono> | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 30 | #include <exception> | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 31 | #include <functional> | 
 | 32 | #include <map> | 
| Shawn McCarney | 8acaf54 | 2021-03-30 10:38:37 -0500 | [diff] [blame] | 33 | #include <thread> | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 34 | #include <tuple> | 
 | 35 | #include <utility> | 
| Matthew Barth | 250d0a9 | 2020-02-28 13:04:24 -0600 | [diff] [blame] | 36 | #include <variant> | 
| Matthew Barth | f2bcf1f | 2020-01-29 14:42:47 -0600 | [diff] [blame] | 37 |  | 
| Shawn McCarney | 84807b9 | 2020-04-30 18:40:03 -0500 | [diff] [blame] | 38 | namespace phosphor::power::regulators | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 39 | { | 
 | 40 |  | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 41 | namespace fs = std::filesystem; | 
 | 42 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 43 | constexpr auto busName = "xyz.openbmc_project.Power.Regulators"; | 
 | 44 | constexpr auto managerObjPath = "/xyz/openbmc_project/power/regulators/manager"; | 
 | 45 | constexpr auto compatibleIntf = | 
 | 46 |     "xyz.openbmc_project.Configuration.IBMCompatibleSystem"; | 
 | 47 | constexpr auto compatibleNamesProp = "Names"; | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 48 | constexpr auto chassisStatePath = "/xyz/openbmc_project/state/chassis0"; | 
 | 49 | constexpr auto chassisStateIntf = "xyz.openbmc_project.State.Chassis"; | 
 | 50 | constexpr auto chassisStateProp = "CurrentPowerState"; | 
| Shawn McCarney | 8acaf54 | 2021-03-30 10:38:37 -0500 | [diff] [blame] | 51 | constexpr std::chrono::minutes maxTimeToWaitForCompatTypes{5}; | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 52 |  | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 53 | using PowerState = | 
 | 54 |     sdbusplus::xyz::openbmc_project::State::server::Chassis::PowerState; | 
 | 55 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 56 | /** | 
 | 57 |  * Default configuration file name.  This is used when the system does not | 
 | 58 |  * implement the D-Bus compatible interface. | 
 | 59 |  */ | 
 | 60 | constexpr auto defaultConfigFileName = "config.json"; | 
 | 61 |  | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 62 | /** | 
 | 63 |  * Standard configuration file directory.  This directory is part of the | 
 | 64 |  * firmware install image.  It contains the standard version of the config file. | 
 | 65 |  */ | 
 | 66 | const fs::path standardConfigFileDir{"/usr/share/phosphor-regulators"}; | 
 | 67 |  | 
 | 68 | /** | 
 | 69 |  * Test configuration file directory.  This directory can contain a test version | 
 | 70 |  * of the config file.  The test version will override the standard version. | 
 | 71 |  */ | 
 | 72 | const fs::path testConfigFileDir{"/etc/phosphor-regulators"}; | 
 | 73 |  | 
| Patrick Williams | 7354ce6 | 2022-07-22 19:26:56 -0500 | [diff] [blame] | 74 | Manager::Manager(sdbusplus::bus_t& bus, const sdeventplus::Event& event) : | 
| Zev Weiss | d130729 | 2022-04-19 17:13:28 -0700 | [diff] [blame] | 75 |     ManagerObject{bus, managerObjPath}, bus{bus}, eventLoop{event}, | 
 | 76 |     services{bus}, phaseFaultTimer{event, | 
 | 77 |                                    std::bind(&Manager::phaseFaultTimerExpired, | 
 | 78 |                                              this)}, | 
| Shawn McCarney | c8cbeac | 2021-09-10 15:42:56 -0500 | [diff] [blame] | 79 |     sensorTimer{event, std::bind(&Manager::sensorTimerExpired, this)} | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 80 | { | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 81 |     // Subscribe to D-Bus interfacesAdded signal from Entity Manager.  This | 
 | 82 |     // notifies us if the compatible interface becomes available later. | 
 | 83 |     std::string matchStr = sdbusplus::bus::match::rules::interfacesAdded() + | 
 | 84 |                            sdbusplus::bus::match::rules::sender( | 
 | 85 |                                "xyz.openbmc_project.EntityManager"); | 
| Patrick Williams | a61c1aa | 2021-11-19 12:25:21 -0600 | [diff] [blame] | 86 |     std::unique_ptr<sdbusplus::bus::match_t> matchPtr = | 
 | 87 |         std::make_unique<sdbusplus::bus::match_t>( | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 88 |             bus, matchStr, | 
 | 89 |             std::bind(&Manager::interfacesAddedHandler, this, | 
 | 90 |                       std::placeholders::_1)); | 
 | 91 |     signals.emplace_back(std::move(matchPtr)); | 
| Matthew Barth | 250d0a9 | 2020-02-28 13:04:24 -0600 | [diff] [blame] | 92 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 93 |     // Try to find compatible system types using D-Bus compatible interface. | 
 | 94 |     // Note that it might not be supported on this system, or the service that | 
 | 95 |     // provides the interface might not be running yet. | 
 | 96 |     findCompatibleSystemTypes(); | 
| Shawn McCarney | 84807b9 | 2020-04-30 18:40:03 -0500 | [diff] [blame] | 97 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 98 |     // Try to find and load the JSON configuration file | 
 | 99 |     loadConfigFile(); | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 100 |  | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 101 |     // Obtain D-Bus service name | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 102 |     bus.request_name(busName); | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 103 |  | 
 | 104 |     // If system is already powered on, enable monitoring | 
 | 105 |     if (isSystemPoweredOn()) | 
 | 106 |     { | 
 | 107 |         monitor(true); | 
 | 108 |     } | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 109 | } | 
 | 110 |  | 
 | 111 | void Manager::configure() | 
 | 112 | { | 
| Shawn McCarney | 9bd94d3 | 2021-01-25 19:40:42 -0600 | [diff] [blame] | 113 |     // Clear any cached data or error history related to hardware devices | 
 | 114 |     clearHardwareData(); | 
 | 115 |  | 
| Shawn McCarney | 8acaf54 | 2021-03-30 10:38:37 -0500 | [diff] [blame] | 116 |     // Wait until the config file has been loaded or hit max wait time | 
 | 117 |     waitUntilConfigFileLoaded(); | 
 | 118 |  | 
 | 119 |     // Verify config file has been loaded and System object is valid | 
 | 120 |     if (isConfigFileLoaded()) | 
| Shawn McCarney | 6345c6c | 2020-05-04 10:35:05 -0500 | [diff] [blame] | 121 |     { | 
 | 122 |         // Configure the regulator devices in the system | 
| Bob King | 23243f8 | 2020-07-29 10:38:57 +0800 | [diff] [blame] | 123 |         system->configure(services); | 
| Shawn McCarney | 6345c6c | 2020-05-04 10:35:05 -0500 | [diff] [blame] | 124 |     } | 
 | 125 |     else | 
 | 126 |     { | 
| Shawn McCarney | 415094c | 2021-02-15 11:08:19 -0600 | [diff] [blame] | 127 |         // Write error message to journal | 
| Shawn McCarney | b464c8b | 2020-07-16 17:51:38 -0500 | [diff] [blame] | 128 |         services.getJournal().logError("Unable to configure regulator devices: " | 
 | 129 |                                        "Configuration file not loaded"); | 
| Shawn McCarney | 6345c6c | 2020-05-04 10:35:05 -0500 | [diff] [blame] | 130 |  | 
| Shawn McCarney | 415094c | 2021-02-15 11:08:19 -0600 | [diff] [blame] | 131 |         // Log critical error since regulators could not be configured.  Could | 
 | 132 |         // cause hardware damage if default regulator settings are very wrong. | 
 | 133 |         services.getErrorLogging().logConfigFileError(Entry::Level::Critical, | 
 | 134 |                                                       services.getJournal()); | 
 | 135 |  | 
 | 136 |         // Throw InternalFailure to propogate error status to D-Bus client | 
 | 137 |         throw sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure{}; | 
 | 138 |     } | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 139 | } | 
 | 140 |  | 
| Patrick Williams | 7354ce6 | 2022-07-22 19:26:56 -0500 | [diff] [blame] | 141 | void Manager::interfacesAddedHandler(sdbusplus::message_t& msg) | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 142 | { | 
 | 143 |     // Verify message is valid | 
 | 144 |     if (!msg) | 
 | 145 |     { | 
 | 146 |         return; | 
 | 147 |     } | 
 | 148 |  | 
 | 149 |     try | 
 | 150 |     { | 
 | 151 |         // Read object path for object that was created or had interface added | 
 | 152 |         sdbusplus::message::object_path objPath; | 
 | 153 |         msg.read(objPath); | 
 | 154 |  | 
 | 155 |         // Read the dictionary whose keys are interface names and whose values | 
 | 156 |         // are dictionaries containing the interface property names and values | 
 | 157 |         std::map<std::string, | 
 | 158 |                  std::map<std::string, std::variant<std::vector<std::string>>>> | 
 | 159 |             intfProp; | 
 | 160 |         msg.read(intfProp); | 
 | 161 |  | 
 | 162 |         // Find the compatible interface, if present | 
 | 163 |         auto itIntf = intfProp.find(compatibleIntf); | 
 | 164 |         if (itIntf != intfProp.cend()) | 
 | 165 |         { | 
 | 166 |             // Find the Names property of the compatible interface, if present | 
 | 167 |             auto itProp = itIntf->second.find(compatibleNamesProp); | 
 | 168 |             if (itProp != itIntf->second.cend()) | 
 | 169 |             { | 
 | 170 |                 // Get value of Names property | 
 | 171 |                 auto propValue = std::get<0>(itProp->second); | 
 | 172 |                 if (!propValue.empty()) | 
 | 173 |                 { | 
 | 174 |                     // Store list of compatible system types | 
 | 175 |                     compatibleSystemTypes = propValue; | 
 | 176 |  | 
 | 177 |                     // Find and load JSON config file based on system types | 
 | 178 |                     loadConfigFile(); | 
 | 179 |                 } | 
 | 180 |             } | 
 | 181 |         } | 
 | 182 |     } | 
 | 183 |     catch (const std::exception&) | 
 | 184 |     { | 
 | 185 |         // Error trying to read interfacesAdded message.  One possible cause | 
 | 186 |         // could be a property whose value is not a std::vector<std::string>. | 
 | 187 |     } | 
 | 188 | } | 
 | 189 |  | 
| Shawn McCarney | 5b19ea5 | 2020-06-02 18:52:56 -0500 | [diff] [blame] | 190 | void Manager::monitor(bool enable) | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 191 | { | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 192 |     // Check whether already in the requested monitoring state | 
 | 193 |     if (enable == isMonitoringEnabled) | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 194 |     { | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 195 |         return; | 
 | 196 |     } | 
 | 197 |  | 
 | 198 |     isMonitoringEnabled = enable; | 
 | 199 |     if (isMonitoringEnabled) | 
 | 200 |     { | 
 | 201 |         services.getJournal().logDebug("Monitoring enabled"); | 
 | 202 |  | 
| Shawn McCarney | c8cbeac | 2021-09-10 15:42:56 -0500 | [diff] [blame] | 203 |         // Restart phase fault detection timer with repeating 15 second interval | 
 | 204 |         phaseFaultTimer.restart(std::chrono::seconds(15)); | 
 | 205 |  | 
 | 206 |         // Restart sensor monitoring timer with repeating 1 second interval | 
 | 207 |         sensorTimer.restart(std::chrono::seconds(1)); | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 208 |  | 
 | 209 |         // Enable sensors service; put all sensors in an active state | 
 | 210 |         services.getSensors().enable(); | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 211 |     } | 
 | 212 |     else | 
 | 213 |     { | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 214 |         services.getJournal().logDebug("Monitoring disabled"); | 
 | 215 |  | 
| Shawn McCarney | c8cbeac | 2021-09-10 15:42:56 -0500 | [diff] [blame] | 216 |         // Disable timers | 
 | 217 |         phaseFaultTimer.setEnabled(false); | 
 | 218 |         sensorTimer.setEnabled(false); | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 219 |  | 
 | 220 |         // Disable sensors service; put all sensors in an inactive state | 
 | 221 |         services.getSensors().disable(); | 
| Shawn McCarney | 5b19ea5 | 2020-06-02 18:52:56 -0500 | [diff] [blame] | 222 |  | 
| Shawn McCarney | 8acaf54 | 2021-03-30 10:38:37 -0500 | [diff] [blame] | 223 |         // Verify config file has been loaded and System object is valid | 
 | 224 |         if (isConfigFileLoaded()) | 
| Shawn McCarney | 5b19ea5 | 2020-06-02 18:52:56 -0500 | [diff] [blame] | 225 |         { | 
 | 226 |             // Close the regulator devices in the system.  Monitoring is | 
 | 227 |             // normally disabled because the system is being powered off.  The | 
 | 228 |             // devices should be closed in case hardware is removed or replaced | 
| Shawn McCarney | 9bd94d3 | 2021-01-25 19:40:42 -0600 | [diff] [blame] | 229 |             // while the system is powered off. | 
| Bob King | d692d6d | 2020-09-14 13:42:57 +0800 | [diff] [blame] | 230 |             system->closeDevices(services); | 
| Shawn McCarney | 5b19ea5 | 2020-06-02 18:52:56 -0500 | [diff] [blame] | 231 |         } | 
| Matthew Barth | 29e9e38 | 2020-01-23 13:40:49 -0600 | [diff] [blame] | 232 |     } | 
 | 233 | } | 
 | 234 |  | 
| Shawn McCarney | c8cbeac | 2021-09-10 15:42:56 -0500 | [diff] [blame] | 235 | void Manager::phaseFaultTimerExpired() | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 236 | { | 
| Shawn McCarney | c8cbeac | 2021-09-10 15:42:56 -0500 | [diff] [blame] | 237 |     // Verify config file has been loaded and System object is valid | 
 | 238 |     if (isConfigFileLoaded()) | 
 | 239 |     { | 
 | 240 |         // Detect redundant phase faults in regulator devices in the system | 
 | 241 |         system->detectPhaseFaults(services); | 
 | 242 |     } | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 243 | } | 
 | 244 |  | 
| Shawn McCarney | c8cbeac | 2021-09-10 15:42:56 -0500 | [diff] [blame] | 245 | void Manager::sensorTimerExpired() | 
| Matthew Barth | f2bcf1f | 2020-01-29 14:42:47 -0600 | [diff] [blame] | 246 | { | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 247 |     // Notify sensors service that a sensor monitoring cycle is starting | 
 | 248 |     services.getSensors().startCycle(); | 
 | 249 |  | 
 | 250 |     // Verify config file has been loaded and System object is valid | 
 | 251 |     if (isConfigFileLoaded()) | 
 | 252 |     { | 
 | 253 |         // Monitor sensors for the voltage rails in the system | 
 | 254 |         system->monitorSensors(services); | 
 | 255 |     } | 
 | 256 |  | 
 | 257 |     // Notify sensors service that current sensor monitoring cycle has ended | 
 | 258 |     services.getSensors().endCycle(); | 
| Matthew Barth | f2bcf1f | 2020-01-29 14:42:47 -0600 | [diff] [blame] | 259 | } | 
 | 260 |  | 
| Shawn McCarney | c8cbeac | 2021-09-10 15:42:56 -0500 | [diff] [blame] | 261 | void Manager::sighupHandler(sdeventplus::source::Signal& /*sigSrc*/, | 
 | 262 |                             const struct signalfd_siginfo* /*sigInfo*/) | 
 | 263 | { | 
 | 264 |     // Reload the JSON configuration file | 
 | 265 |     loadConfigFile(); | 
 | 266 | } | 
 | 267 |  | 
| Shawn McCarney | 9bd94d3 | 2021-01-25 19:40:42 -0600 | [diff] [blame] | 268 | void Manager::clearHardwareData() | 
 | 269 | { | 
| Shawn McCarney | 4e0402c | 2021-02-05 00:08:33 -0600 | [diff] [blame] | 270 |     // Clear any cached hardware presence data and VPD values | 
| Shawn McCarney | 9bd94d3 | 2021-01-25 19:40:42 -0600 | [diff] [blame] | 271 |     services.getPresenceService().clearCache(); | 
| Shawn McCarney | 4e0402c | 2021-02-05 00:08:33 -0600 | [diff] [blame] | 272 |     services.getVPD().clearCache(); | 
| Shawn McCarney | 9bd94d3 | 2021-01-25 19:40:42 -0600 | [diff] [blame] | 273 |  | 
| Shawn McCarney | 8acaf54 | 2021-03-30 10:38:37 -0500 | [diff] [blame] | 274 |     // Verify config file has been loaded and System object is valid | 
 | 275 |     if (isConfigFileLoaded()) | 
| Shawn McCarney | 9bd94d3 | 2021-01-25 19:40:42 -0600 | [diff] [blame] | 276 |     { | 
 | 277 |         // Clear any cached hardware data in the System object | 
 | 278 |         system->clearCache(); | 
| Shawn McCarney | 9bd94d3 | 2021-01-25 19:40:42 -0600 | [diff] [blame] | 279 |  | 
| Shawn McCarney | ce540f3 | 2021-05-14 17:08:41 -0500 | [diff] [blame] | 280 |         // Clear error history related to hardware devices in the System object | 
 | 281 |         system->clearErrorHistory(); | 
 | 282 |     } | 
| Shawn McCarney | 9bd94d3 | 2021-01-25 19:40:42 -0600 | [diff] [blame] | 283 | } | 
 | 284 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 285 | void Manager::findCompatibleSystemTypes() | 
| Matthew Barth | 7cbc553 | 2020-01-29 15:13:13 -0600 | [diff] [blame] | 286 | { | 
| Matthew Barth | bbc7c58 | 2020-02-03 15:55:15 -0600 | [diff] [blame] | 287 |     using namespace phosphor::power::util; | 
 | 288 |  | 
 | 289 |     try | 
 | 290 |     { | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 291 |         // Query object mapper for object paths that implement the compatible | 
 | 292 |         // interface.  Returns a map of object paths to a map of services names | 
 | 293 |         // to their interfaces. | 
 | 294 |         DbusSubtree subTree = getSubTree(bus, "/xyz/openbmc_project/inventory", | 
 | 295 |                                          compatibleIntf, 0); | 
 | 296 |  | 
 | 297 |         // Get the first object path | 
 | 298 |         auto objectIt = subTree.cbegin(); | 
 | 299 |         if (objectIt != subTree.cend()) | 
| Matthew Barth | bbc7c58 | 2020-02-03 15:55:15 -0600 | [diff] [blame] | 300 |         { | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 301 |             std::string objPath = objectIt->first; | 
 | 302 |  | 
 | 303 |             // Get the first service name | 
 | 304 |             auto serviceIt = objectIt->second.cbegin(); | 
 | 305 |             if (serviceIt != objectIt->second.cend()) | 
 | 306 |             { | 
 | 307 |                 std::string service = serviceIt->first; | 
 | 308 |                 if (!service.empty()) | 
 | 309 |                 { | 
 | 310 |                     // Get compatible system types property value | 
 | 311 |                     getProperty(compatibleIntf, compatibleNamesProp, objPath, | 
 | 312 |                                 service, bus, compatibleSystemTypes); | 
 | 313 |                 } | 
 | 314 |             } | 
| Matthew Barth | bbc7c58 | 2020-02-03 15:55:15 -0600 | [diff] [blame] | 315 |         } | 
 | 316 |     } | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 317 |     catch (const std::exception&) | 
| Matthew Barth | bbc7c58 | 2020-02-03 15:55:15 -0600 | [diff] [blame] | 318 |     { | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 319 |         // Compatible system types information is not available.  The current | 
 | 320 |         // system might not support the interface, or the service that | 
 | 321 |         // implements the interface might not be running yet. | 
| Matthew Barth | bbc7c58 | 2020-02-03 15:55:15 -0600 | [diff] [blame] | 322 |     } | 
| Matthew Barth | bbc7c58 | 2020-02-03 15:55:15 -0600 | [diff] [blame] | 323 | } | 
 | 324 |  | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 325 | fs::path Manager::findConfigFile() | 
 | 326 | { | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 327 |     // Build list of possible base file names | 
 | 328 |     std::vector<std::string> fileNames{}; | 
 | 329 |  | 
 | 330 |     // Add possible file names based on compatible system types (if any) | 
 | 331 |     for (const std::string& systemType : compatibleSystemTypes) | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 332 |     { | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 333 |         // Replace all spaces and commas in system type name with underscores | 
 | 334 |         std::string fileName{systemType}; | 
 | 335 |         std::replace(fileName.begin(), fileName.end(), ' ', '_'); | 
 | 336 |         std::replace(fileName.begin(), fileName.end(), ',', '_'); | 
 | 337 |  | 
 | 338 |         // Append .json suffix and add to list | 
 | 339 |         fileName.append(".json"); | 
 | 340 |         fileNames.emplace_back(fileName); | 
 | 341 |     } | 
 | 342 |  | 
 | 343 |     // Add default file name for systems that don't use compatible interface | 
 | 344 |     fileNames.emplace_back(defaultConfigFileName); | 
 | 345 |  | 
 | 346 |     // Look for a config file with one of the possible base names | 
 | 347 |     for (const std::string& fileName : fileNames) | 
 | 348 |     { | 
 | 349 |         // Check if file exists in test directory | 
 | 350 |         fs::path pathName{testConfigFileDir / fileName}; | 
 | 351 |         if (fs::exists(pathName)) | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 352 |         { | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 353 |             return pathName; | 
 | 354 |         } | 
 | 355 |  | 
 | 356 |         // Check if file exists in standard directory | 
 | 357 |         pathName = standardConfigFileDir / fileName; | 
 | 358 |         if (fs::exists(pathName)) | 
 | 359 |         { | 
 | 360 |             return pathName; | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 361 |         } | 
 | 362 |     } | 
 | 363 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 364 |     // No config file found; return empty path | 
 | 365 |     return fs::path{}; | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 366 | } | 
 | 367 |  | 
| Shawn McCarney | d9c8be5 | 2021-05-18 10:07:53 -0500 | [diff] [blame] | 368 | bool Manager::isSystemPoweredOn() | 
 | 369 | { | 
 | 370 |     bool isOn{false}; | 
 | 371 |  | 
 | 372 |     try | 
 | 373 |     { | 
 | 374 |         // Get D-Bus property that contains the current power state for | 
 | 375 |         // chassis0, which represents the entire system (all chassis) | 
 | 376 |         using namespace phosphor::power::util; | 
 | 377 |         auto service = getService(chassisStatePath, chassisStateIntf, bus); | 
 | 378 |         if (!service.empty()) | 
 | 379 |         { | 
 | 380 |             PowerState currentPowerState; | 
 | 381 |             getProperty(chassisStateIntf, chassisStateProp, chassisStatePath, | 
 | 382 |                         service, bus, currentPowerState); | 
 | 383 |             if (currentPowerState == PowerState::On) | 
 | 384 |             { | 
 | 385 |                 isOn = true; | 
 | 386 |             } | 
 | 387 |         } | 
 | 388 |     } | 
 | 389 |     catch (const std::exception& e) | 
 | 390 |     { | 
 | 391 |         // Current power state might not be available yet.  The regulators | 
 | 392 |         // application can start before the power state is published on D-Bus. | 
 | 393 |     } | 
 | 394 |  | 
 | 395 |     return isOn; | 
 | 396 | } | 
 | 397 |  | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 398 | void Manager::loadConfigFile() | 
 | 399 | { | 
 | 400 |     try | 
 | 401 |     { | 
 | 402 |         // Find the absolute path to the config file | 
 | 403 |         fs::path pathName = findConfigFile(); | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 404 |         if (!pathName.empty()) | 
 | 405 |         { | 
 | 406 |             // Log info message in journal; config file path is important | 
 | 407 |             services.getJournal().logInfo("Loading configuration file " + | 
 | 408 |                                           pathName.string()); | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 409 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 410 |             // Parse the config file | 
 | 411 |             std::vector<std::unique_ptr<Rule>> rules{}; | 
 | 412 |             std::vector<std::unique_ptr<Chassis>> chassis{}; | 
 | 413 |             std::tie(rules, chassis) = config_file_parser::parse(pathName); | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 414 |  | 
| Shawn McCarney | 589c181 | 2021-01-14 12:13:26 -0600 | [diff] [blame] | 415 |             // Store config file information in a new System object.  The old | 
 | 416 |             // System object, if any, is automatically deleted. | 
 | 417 |             system = | 
 | 418 |                 std::make_unique<System>(std::move(rules), std::move(chassis)); | 
 | 419 |         } | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 420 |     } | 
 | 421 |     catch (const std::exception& e) | 
 | 422 |     { | 
 | 423 |         // Log error messages in journal | 
| Shawn McCarney | b464c8b | 2020-07-16 17:51:38 -0500 | [diff] [blame] | 424 |         services.getJournal().logError(exception_utils::getMessages(e)); | 
 | 425 |         services.getJournal().logError("Unable to load configuration file"); | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 426 |  | 
| Shawn McCarney | 415094c | 2021-02-15 11:08:19 -0600 | [diff] [blame] | 427 |         // Log error | 
 | 428 |         services.getErrorLogging().logConfigFileError(Entry::Level::Error, | 
 | 429 |                                                       services.getJournal()); | 
| Shawn McCarney | e0c6a2d | 2020-05-01 11:37:08 -0500 | [diff] [blame] | 430 |     } | 
 | 431 | } | 
 | 432 |  | 
| Shawn McCarney | 8acaf54 | 2021-03-30 10:38:37 -0500 | [diff] [blame] | 433 | void Manager::waitUntilConfigFileLoaded() | 
 | 434 | { | 
 | 435 |     // If config file not loaded and list of compatible system types is empty | 
 | 436 |     if (!isConfigFileLoaded() && compatibleSystemTypes.empty()) | 
 | 437 |     { | 
 | 438 |         // Loop until compatible system types found or waited max amount of time | 
 | 439 |         auto start = std::chrono::system_clock::now(); | 
 | 440 |         std::chrono::system_clock::duration timeWaited{0}; | 
 | 441 |         while (compatibleSystemTypes.empty() && | 
 | 442 |                (timeWaited <= maxTimeToWaitForCompatTypes)) | 
 | 443 |         { | 
 | 444 |             // Try to find list of compatible system types | 
 | 445 |             findCompatibleSystemTypes(); | 
 | 446 |             if (!compatibleSystemTypes.empty()) | 
 | 447 |             { | 
 | 448 |                 // Compatible system types found; try to load config file | 
 | 449 |                 loadConfigFile(); | 
 | 450 |             } | 
 | 451 |             else | 
 | 452 |             { | 
 | 453 |                 // Sleep 5 seconds | 
 | 454 |                 using namespace std::chrono_literals; | 
 | 455 |                 std::this_thread::sleep_for(5s); | 
 | 456 |             } | 
 | 457 |             timeWaited = std::chrono::system_clock::now() - start; | 
 | 458 |         } | 
 | 459 |     } | 
 | 460 | } | 
 | 461 |  | 
| Shawn McCarney | 84807b9 | 2020-04-30 18:40:03 -0500 | [diff] [blame] | 462 | } // namespace phosphor::power::regulators |