blob: fe9c6611da0310bf775b8f480a99195ca5f6cfc0 [file] [log] [blame]
Shawn McCarney6a957f62024-01-10 16:15:19 -06001/**
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
17#include "config_file_parser.hpp"
18
19#include "config_file_parser_error.hpp"
20
21#include <exception>
22#include <fstream>
23#include <optional>
24
25using json = nlohmann::json;
26
27namespace phosphor::power::sequencer::config_file_parser
28{
29
30std::vector<std::unique_ptr<Rail>> parse(const std::filesystem::path& pathName)
31{
32 try
33 {
34 // Use standard JSON parser to create tree of JSON elements
35 std::ifstream file{pathName};
36 json rootElement = json::parse(file);
37
38 // Parse tree of JSON elements and return corresponding C++ objects
39 return internal::parseRoot(rootElement);
40 }
41 catch (const std::exception& e)
42 {
43 throw ConfigFileParserError{pathName, e.what()};
44 }
45}
46
47namespace internal
48{
49
50GPIO parseGPIO(const json& element)
51{
52 verifyIsObject(element);
53 unsigned int propertyCount{0};
54
55 // Required line property
56 const json& lineElement = getRequiredProperty(element, "line");
57 unsigned int line = parseUnsignedInteger(lineElement);
58 ++propertyCount;
59
60 // Optional active_low property
61 bool activeLow{false};
62 auto activeLowIt = element.find("active_low");
63 if (activeLowIt != element.end())
64 {
65 activeLow = parseBoolean(*activeLowIt);
66 ++propertyCount;
67 }
68
69 // Verify no invalid properties exist
70 verifyPropertyCount(element, propertyCount);
71
72 return GPIO(line, activeLow);
73}
74
75std::unique_ptr<Rail> parseRail(const json& element)
76{
77 verifyIsObject(element);
78 unsigned int propertyCount{0};
79
80 // Required name property
81 const json& nameElement = getRequiredProperty(element, "name");
82 std::string name = parseString(nameElement);
83 ++propertyCount;
84
85 // Optional presence property
86 std::optional<std::string> presence{};
87 auto presenceIt = element.find("presence");
88 if (presenceIt != element.end())
89 {
90 presence = parseString(*presenceIt);
91 ++propertyCount;
92 }
93
94 // Optional page property
95 std::optional<uint8_t> page{};
96 auto pageIt = element.find("page");
97 if (pageIt != element.end())
98 {
99 page = parseUint8(*pageIt);
100 ++propertyCount;
101 }
102
Shawn McCarney16e493a2024-01-29 14:20:32 -0600103 // Optional is_power_supply_rail property
104 bool isPowerSupplyRail{false};
105 auto isPowerSupplyRailIt = element.find("is_power_supply_rail");
106 if (isPowerSupplyRailIt != element.end())
107 {
108 isPowerSupplyRail = parseBoolean(*isPowerSupplyRailIt);
109 ++propertyCount;
110 }
111
Shawn McCarney6a957f62024-01-10 16:15:19 -0600112 // Optional check_status_vout property
113 bool checkStatusVout{false};
114 auto checkStatusVoutIt = element.find("check_status_vout");
115 if (checkStatusVoutIt != element.end())
116 {
117 checkStatusVout = parseBoolean(*checkStatusVoutIt);
118 ++propertyCount;
119 }
120
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600121 // Optional compare_voltage_to_limit property
122 bool compareVoltageToLimit{false};
123 auto compareVoltageToLimitIt = element.find("compare_voltage_to_limit");
124 if (compareVoltageToLimitIt != element.end())
Shawn McCarney6a957f62024-01-10 16:15:19 -0600125 {
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600126 compareVoltageToLimit = parseBoolean(*compareVoltageToLimitIt);
Shawn McCarney6a957f62024-01-10 16:15:19 -0600127 ++propertyCount;
128 }
129
130 // Optional gpio property
131 std::optional<GPIO> gpio{};
132 auto gpioIt = element.find("gpio");
133 if (gpioIt != element.end())
134 {
135 gpio = parseGPIO(*gpioIt);
136 ++propertyCount;
137 }
138
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600139 // If check_status_vout or compare_voltage_to_limit property is true, the
140 // page property is required; verify page was specified
141 if ((checkStatusVout || compareVoltageToLimit) && !page.has_value())
Shawn McCarney6a957f62024-01-10 16:15:19 -0600142 {
143 throw std::invalid_argument{"Required property missing: page"};
144 }
145
146 // Verify no invalid properties exist
147 verifyPropertyCount(element, propertyCount);
148
Shawn McCarney16e493a2024-01-29 14:20:32 -0600149 return std::make_unique<Rail>(name, presence, page, isPowerSupplyRail,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600150 checkStatusVout, compareVoltageToLimit, gpio);
Shawn McCarney6a957f62024-01-10 16:15:19 -0600151}
152
153std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
154{
155 verifyIsArray(element);
156 std::vector<std::unique_ptr<Rail>> rails;
157 for (auto& railElement : element)
158 {
159 rails.emplace_back(parseRail(railElement));
160 }
161 return rails;
162}
163
164std::vector<std::unique_ptr<Rail>> parseRoot(const json& element)
165{
166 verifyIsObject(element);
167 unsigned int propertyCount{0};
168
169 // Required rails property
170 const json& railsElement = getRequiredProperty(element, "rails");
171 std::vector<std::unique_ptr<Rail>> rails = parseRailArray(railsElement);
172 ++propertyCount;
173
174 // Verify no invalid properties exist
175 verifyPropertyCount(element, propertyCount);
176
177 return rails;
178}
179
180} // namespace internal
181
182} // namespace phosphor::power::sequencer::config_file_parser