blob: 5238741073e388737125f957767281ae171c783a [file] [log] [blame]
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001/**
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 "config_file_parser.hpp"
18
19#include "config_file_parser_error.hpp"
Bob Kingf617f892020-03-30 19:03:35 +080020#include "i2c_interface.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050021#include "pmbus_utils.hpp"
22
23#include <exception>
24#include <fstream>
25#include <optional>
26#include <utility>
27
28using json = nlohmann::json;
29
30namespace phosphor::power::regulators::config_file_parser
31{
32
33std::tuple<std::vector<std::unique_ptr<Rule>>,
34 std::vector<std::unique_ptr<Chassis>>>
35 parse(const std::filesystem::path& pathName)
36{
37 try
38 {
39 // Use standard JSON parser to create tree of JSON elements
40 std::ifstream file{pathName};
41 json rootElement = json::parse(file);
42
43 // Parse tree of JSON elements and return corresponding C++ objects
44 return internal::parseRoot(rootElement);
45 }
46 catch (const std::exception& e)
47 {
48 throw ConfigFileParserError{pathName, e.what()};
49 }
50}
51
52namespace internal
53{
54
55std::unique_ptr<Action> parseAction(const json& element)
56{
57 verifyIsObject(element);
58 unsigned int propertyCount{0};
59
60 // Optional comments property; value not stored
61 if (element.contains("comments"))
62 {
63 ++propertyCount;
64 }
65
66 // Required action type property; there must be exactly one specified
67 std::unique_ptr<Action> action{};
68 if (element.contains("and"))
69 {
Bob King3a787542020-04-14 13:45:01 +080070 action = parseAnd(element["and"]);
71 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050072 }
73 else if (element.contains("compare_presence"))
74 {
Bob Kingb267b7e2020-04-22 14:42:39 +080075 action = parseComparePresence(element["compare_presence"]);
76 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050077 }
78 else if (element.contains("compare_vpd"))
79 {
Bob Kingf2134322020-04-27 14:14:56 +080080 action = parseCompareVPD(element["compare_vpd"]);
81 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050082 }
83 else if (element.contains("i2c_compare_bit"))
84 {
Bob Kingf09bfe02020-04-13 17:21:15 +080085 action = parseI2CCompareBit(element["i2c_compare_bit"]);
86 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050087 }
88 else if (element.contains("i2c_compare_byte"))
89 {
Bob Kingf09bfe02020-04-13 17:21:15 +080090 action = parseI2CCompareByte(element["i2c_compare_byte"]);
91 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050092 }
93 else if (element.contains("i2c_compare_bytes"))
94 {
Bob Kingf09bfe02020-04-13 17:21:15 +080095 action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
96 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050097 }
98 else if (element.contains("i2c_write_bit"))
99 {
Bob Kingf617f892020-03-30 19:03:35 +0800100 action = parseI2CWriteBit(element["i2c_write_bit"]);
101 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500102 }
103 else if (element.contains("i2c_write_byte"))
104 {
Bob King87ff9d72020-03-31 14:02:55 +0800105 action = parseI2CWriteByte(element["i2c_write_byte"]);
106 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500107 }
108 else if (element.contains("i2c_write_bytes"))
109 {
Bob Kingbafcb862020-03-31 16:39:00 +0800110 action = parseI2CWriteBytes(element["i2c_write_bytes"]);
111 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500112 }
113 else if (element.contains("if"))
114 {
Bob King93a89d72020-04-15 15:11:11 +0800115 action = parseIf(element["if"]);
116 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500117 }
118 else if (element.contains("not"))
119 {
Bob Kingf1b58dc2020-04-14 14:53:10 +0800120 action = parseNot(element["not"]);
121 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500122 }
123 else if (element.contains("or"))
124 {
Bob King0b51a9b2020-04-15 13:24:18 +0800125 action = parseOr(element["or"]);
126 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500127 }
128 else if (element.contains("pmbus_read_sensor"))
129 {
Bob King84614882020-04-30 13:13:48 +0800130 action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
131 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500132 }
133 else if (element.contains("pmbus_write_vout_command"))
134 {
135 action =
136 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
137 ++propertyCount;
138 }
139 else if (element.contains("run_rule"))
140 {
Bob King315b0b62020-04-03 21:47:58 +0800141 action = parseRunRule(element["run_rule"]);
142 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500143 }
144 else if (element.contains("set_device"))
145 {
Bob King18a68502020-04-17 14:19:56 +0800146 action = parseSetDevice(element["set_device"]);
147 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500148 }
149 else
150 {
151 throw std::invalid_argument{"Required action type property missing"};
152 }
153
154 // Verify no invalid properties exist
155 verifyPropertyCount(element, propertyCount);
156
157 return action;
158}
159
160std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
161{
162 verifyIsArray(element);
163 std::vector<std::unique_ptr<Action>> actions;
164 for (auto& actionElement : element)
165 {
166 actions.emplace_back(parseAction(actionElement));
167 }
168 return actions;
169}
170
Bob King3a787542020-04-14 13:45:01 +0800171std::unique_ptr<AndAction> parseAnd(const json& element)
172{
173 verifyIsArray(element);
174
175 // Verify if array size less than 2
176 if (element.size() < 2)
177 {
178 throw std::invalid_argument{"Array must contain two or more actions"};
179 }
180 // Array of two or more actions
181 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
182
183 return std::make_unique<AndAction>(std::move(actions));
184}
185
Bob King0e701132020-04-03 21:50:31 +0800186std::unique_ptr<Chassis> parseChassis(const json& element)
187{
188 verifyIsObject(element);
189 unsigned int propertyCount{0};
190
191 // Optional comments property; value not stored
192 if (element.contains("comments"))
193 {
194 ++propertyCount;
195 }
196
197 // Required number property
198 const json& numberElement = getRequiredProperty(element, "number");
199 unsigned int number = parseUnsignedInteger(numberElement);
200 if (number < 1)
201 {
202 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
203 }
204 ++propertyCount;
205
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500206 // Optional inventory_path property. Will be required in future.
207 std::string inventoryPath{"/xyz/openbmc_project/inventory/system/chassis"};
208 auto inventoryPathIt = element.find("inventory_path");
209 if (inventoryPathIt != element.end())
210 {
211 inventoryPath = parseInventoryPath(*inventoryPathIt);
212 ++propertyCount;
213 }
214
Bob King0e701132020-04-03 21:50:31 +0800215 // Optional devices property
216 std::vector<std::unique_ptr<Device>> devices{};
217 auto devicesIt = element.find("devices");
218 if (devicesIt != element.end())
219 {
220 devices = parseDeviceArray(*devicesIt);
221 ++propertyCount;
222 }
223
224 // Verify no invalid properties exist
225 verifyPropertyCount(element, propertyCount);
226
Shawn McCarneycb3f6a62021-04-30 10:54:30 -0500227 return std::make_unique<Chassis>(number, inventoryPath, std::move(devices));
Bob King0e701132020-04-03 21:50:31 +0800228}
229
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500230std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
231{
232 verifyIsArray(element);
233 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800234 for (auto& chassisElement : element)
235 {
236 chassis.emplace_back(parseChassis(chassisElement));
237 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500238 return chassis;
239}
240
Bob Kingb267b7e2020-04-22 14:42:39 +0800241std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element)
242{
243 verifyIsObject(element);
244 unsigned int propertyCount{0};
245
246 // Required fru property
247 const json& fruElement = getRequiredProperty(element, "fru");
Bob Kinga76898f2020-10-13 15:08:33 +0800248 std::string fru = parseInventoryPath(fruElement);
Bob Kingb267b7e2020-04-22 14:42:39 +0800249 ++propertyCount;
250
251 // Required value property
252 const json& valueElement = getRequiredProperty(element, "value");
253 bool value = parseBoolean(valueElement);
254 ++propertyCount;
255
256 // Verify no invalid properties exist
257 verifyPropertyCount(element, propertyCount);
258
259 return std::make_unique<ComparePresenceAction>(fru, value);
260}
261
Bob Kingf2134322020-04-27 14:14:56 +0800262std::unique_ptr<CompareVPDAction> parseCompareVPD(const json& element)
263{
264 verifyIsObject(element);
265 unsigned int propertyCount{0};
266
267 // Required fru property
268 const json& fruElement = getRequiredProperty(element, "fru");
Bob Kinga76898f2020-10-13 15:08:33 +0800269 std::string fru = parseInventoryPath(fruElement);
Bob Kingf2134322020-04-27 14:14:56 +0800270 ++propertyCount;
271
272 // Required keyword property
273 const json& keywordElement = getRequiredProperty(element, "keyword");
274 std::string keyword = parseString(keywordElement);
275 ++propertyCount;
276
277 // Required value property
278 const json& valueElement = getRequiredProperty(element, "value");
279 std::string value = parseString(valueElement);
280 ++propertyCount;
281
282 // Verify no invalid properties exist
283 verifyPropertyCount(element, propertyCount);
284
285 return std::make_unique<CompareVPDAction>(fru, keyword, value);
286}
287
Bob King33e7eaa2020-04-01 18:09:34 +0800288std::unique_ptr<Configuration> parseConfiguration(const json& element)
289{
290 verifyIsObject(element);
291 unsigned int propertyCount{0};
292
293 // Optional comments property; value not stored
294 if (element.contains("comments"))
295 {
296 ++propertyCount;
297 }
298
299 // Optional volts property
300 std::optional<double> volts{};
301 auto voltsIt = element.find("volts");
302 if (voltsIt != element.end())
303 {
304 volts = parseDouble(*voltsIt);
305 ++propertyCount;
306 }
307
308 // Required rule_id or actions property
309 std::vector<std::unique_ptr<Action>> actions{};
310 actions = parseRuleIDOrActionsProperty(element);
311 ++propertyCount;
312
313 // Verify no invalid properties exist
314 verifyPropertyCount(element, propertyCount);
315
316 return std::make_unique<Configuration>(volts, std::move(actions));
317}
318
Bob King9c36c5f2020-04-06 11:34:09 +0800319std::unique_ptr<Device> parseDevice(const json& element)
320{
321 verifyIsObject(element);
322 unsigned int propertyCount{0};
323
324 // Optional comments property; value not stored
325 if (element.contains("comments"))
326 {
327 ++propertyCount;
328 }
329
330 // Required id property
331 const json& idElement = getRequiredProperty(element, "id");
332 std::string id = parseString(idElement);
333 ++propertyCount;
334
335 // Required is_regulator property
336 const json& isRegulatorElement =
337 getRequiredProperty(element, "is_regulator");
338 bool isRegulator = parseBoolean(isRegulatorElement);
339 ++propertyCount;
340
341 // Required fru property
342 const json& fruElement = getRequiredProperty(element, "fru");
Bob Kinga76898f2020-10-13 15:08:33 +0800343 std::string fru = parseInventoryPath(fruElement);
Bob King9c36c5f2020-04-06 11:34:09 +0800344 ++propertyCount;
345
346 // Required i2c_interface property
347 const json& i2cInterfaceElement =
348 getRequiredProperty(element, "i2c_interface");
349 std::unique_ptr<i2c::I2CInterface> i2cInterface =
350 parseI2CInterface(i2cInterfaceElement);
351 ++propertyCount;
352
353 // Optional presence_detection property
Bob King9c36c5f2020-04-06 11:34:09 +0800354 std::unique_ptr<PresenceDetection> presenceDetection{};
Bob King2aafb1c2020-04-16 15:24:32 +0800355 auto presenceDetectionIt = element.find("presence_detection");
356 if (presenceDetectionIt != element.end())
357 {
358 presenceDetection = parsePresenceDetection(*presenceDetectionIt);
359 ++propertyCount;
360 }
Bob King9c36c5f2020-04-06 11:34:09 +0800361
362 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800363 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800364 auto configurationIt = element.find("configuration");
365 if (configurationIt != element.end())
366 {
367 configuration = parseConfiguration(*configurationIt);
368 ++propertyCount;
369 }
Bob King9c36c5f2020-04-06 11:34:09 +0800370
371 // Optional rails property
372 std::vector<std::unique_ptr<Rail>> rails{};
373 auto railsIt = element.find("rails");
374 if (railsIt != element.end())
375 {
376 if (!isRegulator)
377 {
378 throw std::invalid_argument{
379 "Invalid rails property when is_regulator is false"};
380 }
381 rails = parseRailArray(*railsIt);
382 ++propertyCount;
383 }
384
385 // Verify no invalid properties exist
386 verifyPropertyCount(element, propertyCount);
387
388 return std::make_unique<Device>(id, isRegulator, fru,
389 std::move(i2cInterface),
390 std::move(presenceDetection),
391 std::move(configuration), std::move(rails));
392}
393
Bob King0e701132020-04-03 21:50:31 +0800394std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
395{
396 verifyIsArray(element);
397 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800398 for (auto& deviceElement : element)
399 {
400 devices.emplace_back(parseDevice(deviceElement));
401 }
Bob King0e701132020-04-03 21:50:31 +0800402 return devices;
403}
404
Bob Kingbafcb862020-03-31 16:39:00 +0800405std::vector<uint8_t> parseHexByteArray(const json& element)
406{
407 verifyIsArray(element);
408 std::vector<uint8_t> values;
409 for (auto& valueElement : element)
410 {
411 values.emplace_back(parseHexByte(valueElement));
412 }
413 return values;
414}
415
Bob Kingf09bfe02020-04-13 17:21:15 +0800416std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
417{
418 verifyIsObject(element);
419 unsigned int propertyCount{0};
420
421 // Required register property
422 const json& regElement = getRequiredProperty(element, "register");
423 uint8_t reg = parseHexByte(regElement);
424 ++propertyCount;
425
426 // Required position property
427 const json& positionElement = getRequiredProperty(element, "position");
428 uint8_t position = parseBitPosition(positionElement);
429 ++propertyCount;
430
431 // Required value property
432 const json& valueElement = getRequiredProperty(element, "value");
433 uint8_t value = parseBitValue(valueElement);
434 ++propertyCount;
435
436 // Verify no invalid properties exist
437 verifyPropertyCount(element, propertyCount);
438
439 return std::make_unique<I2CCompareBitAction>(reg, position, value);
440}
441
442std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
443{
444 verifyIsObject(element);
445 unsigned int propertyCount{0};
446
447 // Required register property
448 const json& regElement = getRequiredProperty(element, "register");
449 uint8_t reg = parseHexByte(regElement);
450 ++propertyCount;
451
452 // Required value property
453 const json& valueElement = getRequiredProperty(element, "value");
454 uint8_t value = parseHexByte(valueElement);
455 ++propertyCount;
456
457 // Optional mask property
458 uint8_t mask = 0xff;
459 auto maskIt = element.find("mask");
460 if (maskIt != element.end())
461 {
462 mask = parseHexByte(*maskIt);
463 ++propertyCount;
464 }
465
466 // Verify no invalid properties exist
467 verifyPropertyCount(element, propertyCount);
468
469 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
470}
471
472std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
473{
474 verifyIsObject(element);
475 unsigned int propertyCount{0};
476
477 // Required register property
478 const json& regElement = getRequiredProperty(element, "register");
479 uint8_t reg = parseHexByte(regElement);
480 ++propertyCount;
481
482 // Required values property
483 const json& valueElement = getRequiredProperty(element, "values");
484 std::vector<uint8_t> values = parseHexByteArray(valueElement);
485 ++propertyCount;
486
487 // Optional masks property
488 std::vector<uint8_t> masks{};
489 auto masksIt = element.find("masks");
490 if (masksIt != element.end())
491 {
492 masks = parseHexByteArray(*masksIt);
493 ++propertyCount;
494 }
495
496 // Verify masks array (if specified) was same size as values array
497 if ((!masks.empty()) && (masks.size() != values.size()))
498 {
499 throw std::invalid_argument{"Invalid number of elements in masks"};
500 }
501
502 // Verify no invalid properties exist
503 verifyPropertyCount(element, propertyCount);
504
505 if (masks.empty())
506 {
507 return std::make_unique<I2CCompareBytesAction>(reg, values);
508 }
509 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
510}
511
Bob King9c36c5f2020-04-06 11:34:09 +0800512std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
513{
514 verifyIsObject(element);
515 unsigned int propertyCount{0};
516
517 // Required bus property
518 const json& busElement = getRequiredProperty(element, "bus");
519 uint8_t bus = parseUint8(busElement);
520 ++propertyCount;
521
522 // Required address property
523 const json& addressElement = getRequiredProperty(element, "address");
524 uint8_t address = parseHexByte(addressElement);
525 ++propertyCount;
526
527 verifyPropertyCount(element, propertyCount);
528 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
529}
530
Bob Kingf617f892020-03-30 19:03:35 +0800531std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
532{
533 verifyIsObject(element);
534 unsigned int propertyCount{0};
535
536 // Required register property
537 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800538 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800539 ++propertyCount;
540
541 // Required position property
542 const json& positionElement = getRequiredProperty(element, "position");
543 uint8_t position = parseBitPosition(positionElement);
544 ++propertyCount;
545
546 // Required value property
547 const json& valueElement = getRequiredProperty(element, "value");
548 uint8_t value = parseBitValue(valueElement);
549 ++propertyCount;
550
551 // Verify no invalid properties exist
552 verifyPropertyCount(element, propertyCount);
553
554 return std::make_unique<I2CWriteBitAction>(reg, position, value);
555}
556
Bob King87ff9d72020-03-31 14:02:55 +0800557std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
558{
559 verifyIsObject(element);
560 unsigned int propertyCount{0};
561
562 // Required register property
563 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800564 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800565 ++propertyCount;
566
567 // Required value property
568 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800569 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800570 ++propertyCount;
571
572 // Optional mask property
573 uint8_t mask = 0xff;
574 auto maskIt = element.find("mask");
575 if (maskIt != element.end())
576 {
Bob Kingbafcb862020-03-31 16:39:00 +0800577 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800578 ++propertyCount;
579 }
580
581 // Verify no invalid properties exist
582 verifyPropertyCount(element, propertyCount);
583
584 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
585}
586
Bob Kingbafcb862020-03-31 16:39:00 +0800587std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
588{
589 verifyIsObject(element);
590 unsigned int propertyCount{0};
591
592 // Required register property
593 const json& regElement = getRequiredProperty(element, "register");
594 uint8_t reg = parseHexByte(regElement);
595 ++propertyCount;
596
597 // Required values property
598 const json& valueElement = getRequiredProperty(element, "values");
599 std::vector<uint8_t> values = parseHexByteArray(valueElement);
600 ++propertyCount;
601
602 // Optional masks property
603 std::vector<uint8_t> masks{};
604 auto masksIt = element.find("masks");
605 if (masksIt != element.end())
606 {
607 masks = parseHexByteArray(*masksIt);
608 ++propertyCount;
609 }
610
611 // Verify masks array (if specified) was same size as values array
612 if ((!masks.empty()) && (masks.size() != values.size()))
613 {
614 throw std::invalid_argument{"Invalid number of elements in masks"};
615 }
616
617 // Verify no invalid properties exist
618 verifyPropertyCount(element, propertyCount);
619
620 if (masks.empty())
621 {
622 return std::make_unique<I2CWriteBytesAction>(reg, values);
623 }
624 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
625}
626
Bob King93a89d72020-04-15 15:11:11 +0800627std::unique_ptr<IfAction> parseIf(const json& element)
628{
629 verifyIsObject(element);
630 unsigned int propertyCount{0};
631
632 // Required condition property
633 const json& conditionElement = getRequiredProperty(element, "condition");
634 std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
635 ++propertyCount;
636
637 // Required then property
638 const json& thenElement = getRequiredProperty(element, "then");
639 std::vector<std::unique_ptr<Action>> thenActions =
640 parseActionArray(thenElement);
641 ++propertyCount;
642
643 // Optional else property
644 std::vector<std::unique_ptr<Action>> elseActions{};
645 auto elseIt = element.find("else");
646 if (elseIt != element.end())
647 {
648 elseActions = parseActionArray(*elseIt);
649 ++propertyCount;
650 }
651
652 // Verify no invalid properties exist
653 verifyPropertyCount(element, propertyCount);
654
655 return std::make_unique<IfAction>(std::move(conditionAction),
656 std::move(thenActions),
657 std::move(elseActions));
658}
659
Bob Kinga76898f2020-10-13 15:08:33 +0800660std::string parseInventoryPath(const json& element)
661{
662 std::string inventoryPath = parseString(element);
663 std::string absPath = "/xyz/openbmc_project/inventory";
664 if (inventoryPath.front() != '/')
665 {
666 absPath += '/';
667 }
668 absPath += inventoryPath;
669 return absPath;
670}
671
Bob Kingf1b58dc2020-04-14 14:53:10 +0800672std::unique_ptr<NotAction> parseNot(const json& element)
673{
674 // Required action to execute
675 std::unique_ptr<Action> action = parseAction(element);
676
677 return std::make_unique<NotAction>(std::move(action));
678}
679
Bob King0b51a9b2020-04-15 13:24:18 +0800680std::unique_ptr<OrAction> parseOr(const json& element)
681{
682 verifyIsArray(element);
683
684 // Verify if array size less than 2
685 if (element.size() < 2)
686 {
687 throw std::invalid_argument{"Array must contain two or more actions"};
688 }
689 // Array of two or more actions
690 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
691
692 return std::make_unique<OrAction>(std::move(actions));
693}
694
Bob King84614882020-04-30 13:13:48 +0800695std::unique_ptr<PMBusReadSensorAction> parsePMBusReadSensor(const json& element)
696{
697 verifyIsObject(element);
698 unsigned int propertyCount{0};
699
700 // Required type property
701 const json& typeElement = getRequiredProperty(element, "type");
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500702 SensorType type = parseSensorType(typeElement);
Bob King84614882020-04-30 13:13:48 +0800703 ++propertyCount;
704
705 // Required command property
706 const json& commandElement = getRequiredProperty(element, "command");
707 uint8_t command = parseHexByte(commandElement);
708 ++propertyCount;
709
710 // Required format property
711 const json& formatElement = getRequiredProperty(element, "format");
712 pmbus_utils::SensorDataFormat format = parseSensorDataFormat(formatElement);
713 ++propertyCount;
714
715 // Optional exponent property
716 std::optional<int8_t> exponent{};
717 auto exponentIt = element.find("exponent");
718 if (exponentIt != element.end())
719 {
720 exponent = parseInt8(*exponentIt);
721 ++propertyCount;
722 }
723
724 // Verify no invalid properties exist
725 verifyPropertyCount(element, propertyCount);
726
727 return std::make_unique<PMBusReadSensorAction>(type, command, format,
728 exponent);
729}
730
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500731std::unique_ptr<PMBusWriteVoutCommandAction>
732 parsePMBusWriteVoutCommand(const json& element)
733{
734 verifyIsObject(element);
735 unsigned int propertyCount{0};
736
737 // Optional volts property
738 std::optional<double> volts{};
739 auto voltsIt = element.find("volts");
740 if (voltsIt != element.end())
741 {
742 volts = parseDouble(*voltsIt);
743 ++propertyCount;
744 }
745
746 // Required format property
747 const json& formatElement = getRequiredProperty(element, "format");
748 std::string formatString = parseString(formatElement);
749 if (formatString != "linear")
750 {
751 throw std::invalid_argument{"Invalid format value: " + formatString};
752 }
753 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
754 ++propertyCount;
755
756 // Optional exponent property
757 std::optional<int8_t> exponent{};
758 auto exponentIt = element.find("exponent");
759 if (exponentIt != element.end())
760 {
761 exponent = parseInt8(*exponentIt);
762 ++propertyCount;
763 }
764
765 // Optional is_verified property
766 bool isVerified = false;
767 auto isVerifiedIt = element.find("is_verified");
768 if (isVerifiedIt != element.end())
769 {
770 isVerified = parseBoolean(*isVerifiedIt);
771 ++propertyCount;
772 }
773
774 // Verify no invalid properties exist
775 verifyPropertyCount(element, propertyCount);
776
777 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
778 exponent, isVerified);
779}
780
Bob King2aafb1c2020-04-16 15:24:32 +0800781std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
782{
783 verifyIsObject(element);
784 unsigned int propertyCount{0};
785
786 // Optional comments property; value not stored
787 if (element.contains("comments"))
788 {
789 ++propertyCount;
790 }
791
792 // Required rule_id or actions property
793 std::vector<std::unique_ptr<Action>> actions{};
794 actions = parseRuleIDOrActionsProperty(element);
795 ++propertyCount;
796
797 // Verify no invalid properties exist
798 verifyPropertyCount(element, propertyCount);
799
800 return std::make_unique<PresenceDetection>(std::move(actions));
801}
802
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800803std::unique_ptr<Rail> parseRail(const json& element)
804{
805 verifyIsObject(element);
806 unsigned int propertyCount{0};
807
808 // Optional comments property; value not stored
809 if (element.contains("comments"))
810 {
811 ++propertyCount;
812 }
813
814 // Required id property
815 const json& idElement = getRequiredProperty(element, "id");
816 std::string id = parseString(idElement);
817 ++propertyCount;
818
819 // Optional configuration property
820 std::unique_ptr<Configuration> configuration{};
821 auto configurationIt = element.find("configuration");
822 if (configurationIt != element.end())
823 {
824 configuration = parseConfiguration(*configurationIt);
825 ++propertyCount;
826 }
827
828 // Optional sensor_monitoring property
829 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
830 auto sensorMonitoringIt = element.find("sensor_monitoring");
831 if (sensorMonitoringIt != element.end())
832 {
833 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
834 ++propertyCount;
835 }
836
837 // Verify no invalid properties exist
838 verifyPropertyCount(element, propertyCount);
839
840 return std::make_unique<Rail>(id, std::move(configuration),
841 std::move(sensorMonitoring));
842}
843
Bob King9c36c5f2020-04-06 11:34:09 +0800844std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
845{
846 verifyIsArray(element);
847 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800848 for (auto& railElement : element)
849 {
850 rails.emplace_back(parseRail(railElement));
851 }
Bob King9c36c5f2020-04-06 11:34:09 +0800852 return rails;
853}
854
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500855std::tuple<std::vector<std::unique_ptr<Rule>>,
856 std::vector<std::unique_ptr<Chassis>>>
857 parseRoot(const json& element)
858{
859 verifyIsObject(element);
860 unsigned int propertyCount{0};
861
862 // Optional comments property; value not stored
863 if (element.contains("comments"))
864 {
865 ++propertyCount;
866 }
867
868 // Optional rules property
869 std::vector<std::unique_ptr<Rule>> rules{};
870 auto rulesIt = element.find("rules");
871 if (rulesIt != element.end())
872 {
873 rules = parseRuleArray(*rulesIt);
874 ++propertyCount;
875 }
876
877 // Required chassis property
878 const json& chassisElement = getRequiredProperty(element, "chassis");
879 std::vector<std::unique_ptr<Chassis>> chassis =
880 parseChassisArray(chassisElement);
881 ++propertyCount;
882
883 // Verify no invalid properties exist
884 verifyPropertyCount(element, propertyCount);
885
886 return std::make_tuple(std::move(rules), std::move(chassis));
887}
888
889std::unique_ptr<Rule> parseRule(const json& element)
890{
891 verifyIsObject(element);
892 unsigned int propertyCount{0};
893
894 // Optional comments property; value not stored
895 if (element.contains("comments"))
896 {
897 ++propertyCount;
898 }
899
900 // Required id property
901 const json& idElement = getRequiredProperty(element, "id");
902 std::string id = parseString(idElement);
903 ++propertyCount;
904
905 // Required actions property
906 const json& actionsElement = getRequiredProperty(element, "actions");
907 std::vector<std::unique_ptr<Action>> actions =
908 parseActionArray(actionsElement);
909 ++propertyCount;
910
911 // Verify no invalid properties exist
912 verifyPropertyCount(element, propertyCount);
913
914 return std::make_unique<Rule>(id, std::move(actions));
915}
916
917std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
918{
919 verifyIsArray(element);
920 std::vector<std::unique_ptr<Rule>> rules;
921 for (auto& ruleElement : element)
922 {
923 rules.emplace_back(parseRule(ruleElement));
924 }
925 return rules;
926}
927
Bob King33e7eaa2020-04-01 18:09:34 +0800928std::vector<std::unique_ptr<Action>>
929 parseRuleIDOrActionsProperty(const json& element)
930{
931 verifyIsObject(element);
932 // Required rule_id or actions property
933 std::vector<std::unique_ptr<Action>> actions{};
934 auto ruleIDIt = element.find("rule_id");
935 auto actionsIt = element.find("actions");
936 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
937 {
938 std::string ruleID = parseString(*ruleIDIt);
939 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
940 }
941 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
942 {
943 actions = parseActionArray(*actionsIt);
944 }
945 else
946 {
947 throw std::invalid_argument{"Invalid property combination: Must "
948 "contain either rule_id or actions"};
949 }
950
951 return actions;
952}
953
Bob King315b0b62020-04-03 21:47:58 +0800954std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
955{
956 // String ruleID
957 std::string ruleID = parseString(element);
958
959 return std::make_unique<RunRuleAction>(ruleID);
960}
961
Bob King84614882020-04-30 13:13:48 +0800962pmbus_utils::SensorDataFormat parseSensorDataFormat(const json& element)
963{
964 if (!element.is_string())
965 {
966 throw std::invalid_argument{"Element is not a string"};
967 }
968 std::string value = element.get<std::string>();
969 pmbus_utils::SensorDataFormat format{};
970
971 if (value == "linear_11")
972 {
973 format = pmbus_utils::SensorDataFormat::linear_11;
974 }
975 else if (value == "linear_16")
976 {
977 format = pmbus_utils::SensorDataFormat::linear_16;
978 }
979 else
980 {
981 throw std::invalid_argument{"Element is not a sensor data format"};
982 }
983
984 return format;
985}
986
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800987std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
988{
989 verifyIsObject(element);
990 unsigned int propertyCount{0};
991
992 // Optional comments property; value not stored
993 if (element.contains("comments"))
994 {
995 ++propertyCount;
996 }
997
998 // Required rule_id or actions property
999 std::vector<std::unique_ptr<Action>> actions{};
1000 actions = parseRuleIDOrActionsProperty(element);
1001 ++propertyCount;
1002
1003 // Verify no invalid properties exist
1004 verifyPropertyCount(element, propertyCount);
1005
1006 return std::make_unique<SensorMonitoring>(std::move(actions));
1007}
1008
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001009SensorType parseSensorType(const json& element)
Bob King84614882020-04-30 13:13:48 +08001010{
1011 if (!element.is_string())
1012 {
1013 throw std::invalid_argument{"Element is not a string"};
1014 }
1015 std::string value = element.get<std::string>();
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001016 SensorType type{};
Bob King84614882020-04-30 13:13:48 +08001017
1018 if (value == "iout")
1019 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001020 type = SensorType::iout;
Bob King84614882020-04-30 13:13:48 +08001021 }
1022 else if (value == "iout_peak")
1023 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001024 type = SensorType::iout_peak;
Bob King84614882020-04-30 13:13:48 +08001025 }
1026 else if (value == "iout_valley")
1027 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001028 type = SensorType::iout_valley;
Bob King84614882020-04-30 13:13:48 +08001029 }
1030 else if (value == "pout")
1031 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001032 type = SensorType::pout;
Bob King84614882020-04-30 13:13:48 +08001033 }
1034 else if (value == "temperature")
1035 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001036 type = SensorType::temperature;
Bob King84614882020-04-30 13:13:48 +08001037 }
1038 else if (value == "temperature_peak")
1039 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001040 type = SensorType::temperature_peak;
Bob King84614882020-04-30 13:13:48 +08001041 }
1042 else if (value == "vout")
1043 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001044 type = SensorType::vout;
Bob King84614882020-04-30 13:13:48 +08001045 }
1046 else if (value == "vout_peak")
1047 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001048 type = SensorType::vout_peak;
Bob King84614882020-04-30 13:13:48 +08001049 }
1050 else if (value == "vout_valley")
1051 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001052 type = SensorType::vout_valley;
Bob King84614882020-04-30 13:13:48 +08001053 }
1054 else
1055 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001056 throw std::invalid_argument{"Element is not a sensor type"};
Bob King84614882020-04-30 13:13:48 +08001057 }
1058
1059 return type;
1060}
1061
Bob King18a68502020-04-17 14:19:56 +08001062std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
1063{
1064 // String deviceID
1065 std::string deviceID = parseString(element);
1066
1067 return std::make_unique<SetDeviceAction>(deviceID);
1068}
1069
Bob King84614882020-04-30 13:13:48 +08001070pmbus_utils::VoutDataFormat parseVoutDataFormat(const json& element)
1071{
1072 if (!element.is_string())
1073 {
1074 throw std::invalid_argument{"Element is not a string"};
1075 }
1076 std::string value = element.get<std::string>();
1077 pmbus_utils::VoutDataFormat format{};
1078
1079 if (value == "linear")
1080 {
1081 format = pmbus_utils::VoutDataFormat::linear;
1082 }
1083 else if (value == "vid")
1084 {
1085 format = pmbus_utils::VoutDataFormat::vid;
1086 }
1087 else if (value == "direct")
1088 {
1089 format = pmbus_utils::VoutDataFormat::direct;
1090 }
1091 else if (value == "ieee")
1092 {
1093 format = pmbus_utils::VoutDataFormat::ieee;
1094 }
1095 else
1096 {
1097 throw std::invalid_argument{"Element is not a vout data format"};
1098 }
1099
1100 return format;
1101}
1102
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001103} // namespace internal
1104
1105} // namespace phosphor::power::regulators::config_file_parser