1 /** 2 * Copyright © 2024 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "chassis.hpp" 19 #include "power_sequencer_device.hpp" 20 #include "rail.hpp" 21 #include "services.hpp" 22 23 #include <nlohmann/json.hpp> 24 25 #include <cstdint> 26 #include <filesystem> 27 #include <functional> // for reference_wrapper 28 #include <map> 29 #include <memory> 30 #include <string> 31 #include <tuple> 32 #include <vector> 33 34 using json = nlohmann::json; 35 36 namespace phosphor::power::sequencer::config_file_parser 37 { 38 39 /** 40 * Standard JSON configuration file directory on the BMC. 41 */ 42 extern const std::filesystem::path standardConfigFileDirectory; 43 44 /** 45 * Finds the JSON configuration file for the current system based on the 46 * specified compatible system types. 47 * 48 * This is required when a single BMC firmware image supports multiple system 49 * types and some system types require different configuration files. 50 * 51 * The compatible system types must be ordered from most to least specific. 52 * Example: 53 * - com.acme.Hardware.Chassis.Model.MegaServer4CPU 54 * - com.acme.Hardware.Chassis.Model.MegaServer 55 * - com.acme.Hardware.Chassis.Model.Server 56 * 57 * Throws an exception if an error occurs. 58 * 59 * @param compatibleSystemTypes compatible system types for the current system 60 * ordered from most to least specific 61 * @param configFileDir directory containing configuration files 62 * @return path to the JSON configuration file, or an empty path if none was 63 * found 64 */ 65 std::filesystem::path find( 66 const std::vector<std::string>& compatibleSystemTypes, 67 const std::filesystem::path& configFileDir = standardConfigFileDirectory); 68 69 /** 70 * Parses the specified JSON configuration file. 71 * 72 * Returns the corresponding C++ Chassis objects. 73 * 74 * Throws a ConfigFileParserError if an error occurs. 75 * 76 * @param pathName configuration file path name 77 * @param services system services like hardware presence and the journal 78 * @return vector of Chassis objects 79 */ 80 std::vector<std::unique_ptr<Chassis>> parse( 81 const std::filesystem::path& pathName, Services& services); 82 83 /* 84 * Internal implementation details for parse() 85 */ 86 namespace internal 87 { 88 89 using JSONRefWrapper = std::reference_wrapper<const json>; 90 91 /** 92 * Parses a JSON element containing a chassis object. 93 * 94 * Returns the corresponding C++ Chassis object. 95 * 96 * Throws an exception if parsing fails. 97 * 98 * @param element JSON element 99 * @param chassisTemplates chassis templates map 100 * @param services system services like hardware presence and the journal 101 * @return Chassis object 102 */ 103 std::unique_ptr<Chassis> parseChassis( 104 const json& element, 105 const std::map<std::string, JSONRefWrapper>& chassisTemplates, 106 Services& services); 107 108 /** 109 * Parses a JSON element containing an array of chassis objects. 110 * 111 * Returns the corresponding C++ Chassis objects. 112 * 113 * Throws an exception if parsing fails. 114 * 115 * @param element JSON element 116 * @param chassisTemplates chassis templates map 117 * @param services system services like hardware presence and the journal 118 * @return vector of Chassis objects 119 */ 120 std::vector<std::unique_ptr<Chassis>> parseChassisArray( 121 const json& element, 122 const std::map<std::string, JSONRefWrapper>& chassisTemplates, 123 Services& services); 124 125 /** 126 * Parses a JSON element containing the properties of a chassis. 127 * 128 * The JSON element may be a chassis object or chassis_template object. 129 * 130 * Returns the corresponding C++ Chassis object. 131 * 132 * Throws an exception if parsing fails. 133 * 134 * @param element JSON element 135 * @param isChassisTemplate specifies whether element is a chassis_template 136 * @param variables variables map used to expand variables in element value 137 * @param services system services like hardware presence and the journal 138 * @return Chassis object 139 */ 140 std::unique_ptr<Chassis> parseChassisProperties( 141 const json& element, bool isChassisTemplate, 142 const std::map<std::string, std::string>& variables, Services& services); 143 144 /** 145 * Parses a JSON element containing a chassis_template object. 146 * 147 * Returns the template ID and a C++ reference_wrapper to the JSON element. 148 * 149 * A chassis_template object cannot be fully parsed in isolation. It is a 150 * template that contains variables. 151 * 152 * The chassis_template object is used by one or more chassis objects to avoid 153 * duplicate JSON. The chassis objects define chassis-specific values for the 154 * template variables. 155 * 156 * When the chassis object is parsed, the chassis_template JSON will be 157 * re-parsed, and the template variables will be replaced with the 158 * chassis-specific values. 159 * 160 * Throws an exception if parsing fails. 161 * 162 * @param element JSON element 163 * @return template ID and reference_wrapper to JSON element 164 */ 165 std::tuple<std::string, JSONRefWrapper> parseChassisTemplate( 166 const json& element); 167 168 /** 169 * Parses a JSON element containing an array of chassis_template objects. 170 * 171 * Returns a map of template IDs to chassis_template JSON elements. 172 * 173 * Note that chassis_template objects cannot be fully parsed in isolation. See 174 * parseChassisTemplate() for more information. 175 * 176 * Throws an exception if parsing fails. 177 * 178 * @param element JSON element 179 * @return chassis templates map 180 */ 181 std::map<std::string, JSONRefWrapper> parseChassisTemplateArray( 182 const json& element); 183 184 /** 185 * Parses a JSON element containing a gpio object. 186 * 187 * Returns the corresponding C++ PgoodGPIO object. 188 * 189 * Throws an exception if parsing fails. 190 * 191 * @param element JSON element 192 * @param variables variables map used to expand variables in element value 193 * @return PgoodGPIO object 194 */ 195 PgoodGPIO parseGPIO(const json& element, 196 const std::map<std::string, std::string>& variables); 197 198 /** 199 * Parses a JSON element containing an i2c_interface object. 200 * 201 * Returns the corresponding I2C bus and address. 202 * 203 * Throws an exception if parsing fails. 204 * 205 * @param element JSON element 206 * @param variables variables map used to expand variables in element value 207 * @return tuple containing bus and address 208 */ 209 std::tuple<uint8_t, uint16_t> parseI2CInterface( 210 const json& element, const std::map<std::string, std::string>& variables); 211 212 /** 213 * Parses a JSON element containing a power_sequencer object. 214 * 215 * Returns the corresponding C++ PowerSequencerDevice object. 216 * 217 * Throws an exception if parsing fails. 218 * 219 * @param element JSON element 220 * @param variables variables map used to expand variables in element value 221 * @param services system services like hardware presence and the journal 222 * @return PowerSequencerDevice object 223 */ 224 std::unique_ptr<PowerSequencerDevice> parsePowerSequencer( 225 const json& element, const std::map<std::string, std::string>& variables, 226 Services& services); 227 228 /** 229 * Parses a JSON element containing an array of power_sequencer objects. 230 * 231 * Returns the corresponding C++ PowerSequencerDevice objects. 232 * 233 * Throws an exception if parsing fails. 234 * 235 * @param element JSON element 236 * @param variables variables map used to expand variables in element value 237 * @param services system services like hardware presence and the journal 238 * @return vector of PowerSequencerDevice objects 239 */ 240 std::vector<std::unique_ptr<PowerSequencerDevice>> parsePowerSequencerArray( 241 const json& element, const std::map<std::string, std::string>& variables, 242 Services& services); 243 244 /** 245 * Parses a JSON element containing a rail. 246 * 247 * Returns the corresponding C++ Rail object. 248 * 249 * Throws an exception if parsing fails. 250 * 251 * @param element JSON element 252 * @param variables variables map used to expand variables in element value 253 * @return Rail object 254 */ 255 std::unique_ptr<Rail> parseRail( 256 const json& element, const std::map<std::string, std::string>& variables); 257 258 /** 259 * Parses a JSON element containing an array of rails. 260 * 261 * Returns the corresponding C++ Rail objects. 262 * 263 * Throws an exception if parsing fails. 264 * 265 * @param element JSON element 266 * @param variables variables map used to expand variables in element value 267 * @return vector of Rail objects 268 */ 269 std::vector<std::unique_ptr<Rail>> parseRailArray( 270 const json& element, const std::map<std::string, std::string>& variables); 271 272 /** 273 * Parses the JSON root element of the entire configuration file. 274 * 275 * Returns the corresponding C++ Chassis objects. 276 * 277 * Throws an exception if parsing fails. 278 * 279 * @param element JSON element 280 * @param services system services like hardware presence and the journal 281 * @return vector of Chassis objects 282 */ 283 std::vector<std::unique_ptr<Chassis>> parseRoot(const json& element, 284 Services& services); 285 286 /** 287 * Parses a JSON element containing an object with variable names and values. 288 * 289 * Returns the corresponding C++ map of variable names and values. 290 * 291 * Throws an exception if parsing fails. 292 * 293 * @param element JSON element 294 * @return map of variable names and values 295 */ 296 std::map<std::string, std::string> parseVariables(const json& element); 297 298 } // namespace internal 299 300 } // namespace phosphor::power::sequencer::config_file_parser 301