xref: /openbmc/phosphor-power/phosphor-power-sequencer/src/config_file_parser.hpp (revision d8d5e2ba7796508eb16c0a31c4531f80608532bb)
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 "chassis_status_monitor.hpp"
20 #include "power_sequencer_device.hpp"
21 #include "rail.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  * Default JSON configuration file name.
46  */
47 extern const std::string defaultConfigFileName;
48 
49 /**
50  * Returns the path to the default JSON configuration file.
51  *
52  * @return default config file path
53  */
54 std::filesystem::path getDefaultConfigFilePath();
55 
56 /**
57  * Finds the JSON configuration file for the current system based on the
58  * specified compatible system types.
59  *
60  * This is required when a single BMC firmware image supports multiple system
61  * types and some system types require different configuration files.
62  *
63  * The compatible system types must be ordered from most to least specific.
64  * Example:
65  *   - com.acme.Hardware.Chassis.Model.MegaServer4CPU
66  *   - com.acme.Hardware.Chassis.Model.MegaServer
67  *   - com.acme.Hardware.Chassis.Model.Server
68  *
69  * Throws an exception if an error occurs.
70  *
71  * @param compatibleSystemTypes compatible system types for the current system
72  *                              ordered from most to least specific
73  * @param configFileDir directory containing configuration files
74  * @return path to the JSON configuration file, or an empty path if none was
75  *         found
76  */
77 std::filesystem::path find(
78     const std::vector<std::string>& compatibleSystemTypes,
79     const std::filesystem::path& configFileDir = standardConfigFileDirectory);
80 
81 /**
82  * Parses the specified JSON configuration file.
83  *
84  * Returns the corresponding C++ Chassis objects.
85  *
86  * Throws a ConfigFileParserError if an error occurs.
87  *
88  * @param pathName configuration file path name
89  * @return vector of Chassis objects
90  */
91 std::vector<std::unique_ptr<Chassis>> parse(
92     const std::filesystem::path& pathName);
93 
94 /*
95  * Internal implementation details for parse()
96  */
97 namespace internal
98 {
99 
100 using JSONRefWrapper = std::reference_wrapper<const json>;
101 
102 /**
103  * Parses a JSON element containing a chassis object.
104  *
105  * Returns the corresponding C++ Chassis object.
106  *
107  * Throws an exception if parsing fails.
108  *
109  * @param element JSON element
110  * @param chassisTemplates chassis templates map
111  * @return Chassis object
112  */
113 std::unique_ptr<Chassis> parseChassis(
114     const json& element,
115     const std::map<std::string, JSONRefWrapper>& chassisTemplates);
116 
117 /**
118  * Parses a JSON element containing an array of chassis objects.
119  *
120  * Returns the corresponding C++ Chassis objects.
121  *
122  * Throws an exception if parsing fails.
123  *
124  * @param element JSON element
125  * @param chassisTemplates chassis templates map
126  * @return vector of Chassis objects
127  */
128 std::vector<std::unique_ptr<Chassis>> parseChassisArray(
129     const json& element,
130     const std::map<std::string, JSONRefWrapper>& chassisTemplates);
131 
132 /**
133  * Parses a JSON element containing the properties of a chassis.
134  *
135  * The JSON element may be a chassis object or chassis_template object.
136  *
137  * Returns the corresponding C++ Chassis object.
138  *
139  * Throws an exception if parsing fails.
140  *
141  * @param element JSON element
142  * @param isChassisTemplate specifies whether element is a chassis_template
143  * @param variables variables map used to expand variables in element value
144  * @return Chassis object
145  */
146 std::unique_ptr<Chassis> parseChassisProperties(
147     const json& element, bool isChassisTemplate,
148     const std::map<std::string, std::string>& variables);
149 
150 /**
151  * Parses a JSON element containing a chassis_template object.
152  *
153  * Returns the template ID and a C++ reference_wrapper to the JSON element.
154  *
155  * A chassis_template object cannot be fully parsed in isolation. It is a
156  * template that contains variables.
157  *
158  * The chassis_template object is used by one or more chassis objects to avoid
159  * duplicate JSON. The chassis objects define chassis-specific values for the
160  * template variables.
161  *
162  * When the chassis object is parsed, the chassis_template JSON will be
163  * re-parsed, and the template variables will be replaced with the
164  * chassis-specific values.
165  *
166  * Throws an exception if parsing fails.
167  *
168  * @param element JSON element
169  * @return template ID and reference_wrapper to JSON element
170  */
171 std::tuple<std::string, JSONRefWrapper> parseChassisTemplate(
172     const json& element);
173 
174 /**
175  * Parses a JSON element containing an array of chassis_template objects.
176  *
177  * Returns a map of template IDs to chassis_template JSON elements.
178  *
179  * Note that chassis_template objects cannot be fully parsed in isolation. See
180  * parseChassisTemplate() for more information.
181  *
182  * Throws an exception if parsing fails.
183  *
184  * @param element JSON element
185  * @return chassis templates map
186  */
187 std::map<std::string, JSONRefWrapper> parseChassisTemplateArray(
188     const json& element);
189 
190 /**
191  * Parses a JSON element containing chassis status monitoring options.
192  *
193  * Returns the corresponding C++ ChassisStatusMonitorOptions object.
194  *
195  * Throws an exception if parsing fails.
196  *
197  * @param element JSON element
198  * @param variables variables map used to expand variables in element value
199  * @return ChassisStatusMonitorOptions object
200  */
201 ChassisStatusMonitorOptions parseStatusMonitoring(
202     const json& element, const std::map<std::string, std::string>& variables);
203 
204 /**
205  * Parses a JSON element containing a gpio object.
206  *
207  * Returns the corresponding C++ PgoodGPIO object.
208  *
209  * Throws an exception if parsing fails.
210  *
211  * @param element JSON element
212  * @param variables variables map used to expand variables in element value
213  * @return PgoodGPIO object
214  */
215 PgoodGPIO parseGPIO(const json& element,
216                     const std::map<std::string, std::string>& variables);
217 
218 /**
219  * Parses a JSON element containing an i2c_interface object.
220  *
221  * Returns the corresponding I2C bus and address.
222  *
223  * Throws an exception if parsing fails.
224  *
225  * @param element JSON element
226  * @param variables variables map used to expand variables in element value
227  * @return tuple containing bus and address
228  */
229 std::tuple<uint8_t, uint16_t> parseI2CInterface(
230     const json& element, const std::map<std::string, std::string>& variables);
231 
232 /**
233  * Parses a JSON element containing a power_sequencer object.
234  *
235  * Returns the corresponding C++ PowerSequencerDevice object.
236  *
237  * Throws an exception if parsing fails.
238  *
239  * @param element JSON element
240  * @param variables variables map used to expand variables in element value
241  * @return PowerSequencerDevice object
242  */
243 std::unique_ptr<PowerSequencerDevice> parsePowerSequencer(
244     const json& element, const std::map<std::string, std::string>& variables);
245 
246 /**
247  * Parses a JSON element containing an array of power_sequencer objects.
248  *
249  * Returns the corresponding C++ PowerSequencerDevice objects.
250  *
251  * Throws an exception if parsing fails.
252  *
253  * @param element JSON element
254  * @param variables variables map used to expand variables in element value
255  * @return vector of PowerSequencerDevice objects
256  */
257 std::vector<std::unique_ptr<PowerSequencerDevice>> parsePowerSequencerArray(
258     const json& element, const std::map<std::string, std::string>& variables);
259 
260 /**
261  * Parses a JSON element containing a rail.
262  *
263  * Returns the corresponding C++ Rail object.
264  *
265  * Throws an exception if parsing fails.
266  *
267  * @param element JSON element
268  * @param variables variables map used to expand variables in element value
269  * @return Rail object
270  */
271 std::unique_ptr<Rail> parseRail(
272     const json& element, const std::map<std::string, std::string>& variables);
273 
274 /**
275  * Parses a JSON element containing an array of rails.
276  *
277  * Returns the corresponding C++ Rail objects.
278  *
279  * Throws an exception if parsing fails.
280  *
281  * @param element JSON element
282  * @param variables variables map used to expand variables in element value
283  * @return vector of Rail objects
284  */
285 std::vector<std::unique_ptr<Rail>> parseRailArray(
286     const json& element, const std::map<std::string, std::string>& variables);
287 
288 /**
289  * Parses the JSON root element of the entire configuration file.
290  *
291  * Returns the corresponding C++ Chassis objects.
292  *
293  * Throws an exception if parsing fails.
294  *
295  * @param element JSON element
296  * @return vector of Chassis objects
297  */
298 std::vector<std::unique_ptr<Chassis>> parseRoot(const json& element);
299 
300 /**
301  * Parses a JSON element containing an object with variable names and values.
302  *
303  * Returns the corresponding C++ map of variable names and values.
304  *
305  * Throws an exception if parsing fails.
306  *
307  * @param element JSON element
308  * @return map of variable names and values
309  */
310 std::map<std::string, std::string> parseVariables(const json& element);
311 
312 } // namespace internal
313 
314 } // namespace phosphor::power::sequencer::config_file_parser
315