xref: /openbmc/phosphor-power/phosphor-power-sequencer/src/config_file_parser.hpp (revision 984be69cd5b40692f8b7267498533a52c02538f8)
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