blob: 7a3d497a18c0c78c0d5ecd1bd38e74343b881b59 [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 {
80 // TODO: Not implemented yet
81 // action = parseCompareVPD(element["compare_vpd"]);
82 // ++propertyCount;
83 }
84 else if (element.contains("i2c_compare_bit"))
85 {
Bob Kingf09bfe02020-04-13 17:21:15 +080086 action = parseI2CCompareBit(element["i2c_compare_bit"]);
87 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050088 }
89 else if (element.contains("i2c_compare_byte"))
90 {
Bob Kingf09bfe02020-04-13 17:21:15 +080091 action = parseI2CCompareByte(element["i2c_compare_byte"]);
92 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050093 }
94 else if (element.contains("i2c_compare_bytes"))
95 {
Bob Kingf09bfe02020-04-13 17:21:15 +080096 action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
97 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050098 }
99 else if (element.contains("i2c_write_bit"))
100 {
Bob Kingf617f892020-03-30 19:03:35 +0800101 action = parseI2CWriteBit(element["i2c_write_bit"]);
102 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500103 }
104 else if (element.contains("i2c_write_byte"))
105 {
Bob King87ff9d72020-03-31 14:02:55 +0800106 action = parseI2CWriteByte(element["i2c_write_byte"]);
107 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500108 }
109 else if (element.contains("i2c_write_bytes"))
110 {
Bob Kingbafcb862020-03-31 16:39:00 +0800111 action = parseI2CWriteBytes(element["i2c_write_bytes"]);
112 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500113 }
114 else if (element.contains("if"))
115 {
Bob King93a89d72020-04-15 15:11:11 +0800116 action = parseIf(element["if"]);
117 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500118 }
119 else if (element.contains("not"))
120 {
Bob Kingf1b58dc2020-04-14 14:53:10 +0800121 action = parseNot(element["not"]);
122 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500123 }
124 else if (element.contains("or"))
125 {
Bob King0b51a9b2020-04-15 13:24:18 +0800126 action = parseOr(element["or"]);
127 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500128 }
129 else if (element.contains("pmbus_read_sensor"))
130 {
131 // TODO: Not implemented yet
132 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
133 // ++propertyCount;
134 }
135 else if (element.contains("pmbus_write_vout_command"))
136 {
137 action =
138 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
139 ++propertyCount;
140 }
141 else if (element.contains("run_rule"))
142 {
Bob King315b0b62020-04-03 21:47:58 +0800143 action = parseRunRule(element["run_rule"]);
144 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500145 }
146 else if (element.contains("set_device"))
147 {
Bob King18a68502020-04-17 14:19:56 +0800148 action = parseSetDevice(element["set_device"]);
149 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500150 }
151 else
152 {
153 throw std::invalid_argument{"Required action type property missing"};
154 }
155
156 // Verify no invalid properties exist
157 verifyPropertyCount(element, propertyCount);
158
159 return action;
160}
161
162std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
163{
164 verifyIsArray(element);
165 std::vector<std::unique_ptr<Action>> actions;
166 for (auto& actionElement : element)
167 {
168 actions.emplace_back(parseAction(actionElement));
169 }
170 return actions;
171}
172
Bob King3a787542020-04-14 13:45:01 +0800173std::unique_ptr<AndAction> parseAnd(const json& element)
174{
175 verifyIsArray(element);
176
177 // Verify if array size less than 2
178 if (element.size() < 2)
179 {
180 throw std::invalid_argument{"Array must contain two or more actions"};
181 }
182 // Array of two or more actions
183 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
184
185 return std::make_unique<AndAction>(std::move(actions));
186}
187
Bob King0e701132020-04-03 21:50:31 +0800188std::unique_ptr<Chassis> parseChassis(const json& element)
189{
190 verifyIsObject(element);
191 unsigned int propertyCount{0};
192
193 // Optional comments property; value not stored
194 if (element.contains("comments"))
195 {
196 ++propertyCount;
197 }
198
199 // Required number property
200 const json& numberElement = getRequiredProperty(element, "number");
201 unsigned int number = parseUnsignedInteger(numberElement);
202 if (number < 1)
203 {
204 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
205 }
206 ++propertyCount;
207
208 // Optional devices property
209 std::vector<std::unique_ptr<Device>> devices{};
210 auto devicesIt = element.find("devices");
211 if (devicesIt != element.end())
212 {
213 devices = parseDeviceArray(*devicesIt);
214 ++propertyCount;
215 }
216
217 // Verify no invalid properties exist
218 verifyPropertyCount(element, propertyCount);
219
220 return std::make_unique<Chassis>(number, std::move(devices));
221}
222
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500223std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
224{
225 verifyIsArray(element);
226 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800227 for (auto& chassisElement : element)
228 {
229 chassis.emplace_back(parseChassis(chassisElement));
230 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500231 return chassis;
232}
233
Bob Kingb267b7e2020-04-22 14:42:39 +0800234std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element)
235{
236 verifyIsObject(element);
237 unsigned int propertyCount{0};
238
239 // Required fru property
240 const json& fruElement = getRequiredProperty(element, "fru");
241 std::string fru = parseString(fruElement);
242 ++propertyCount;
243
244 // Required value property
245 const json& valueElement = getRequiredProperty(element, "value");
246 bool value = parseBoolean(valueElement);
247 ++propertyCount;
248
249 // Verify no invalid properties exist
250 verifyPropertyCount(element, propertyCount);
251
252 return std::make_unique<ComparePresenceAction>(fru, value);
253}
254
Bob King33e7eaa2020-04-01 18:09:34 +0800255std::unique_ptr<Configuration> parseConfiguration(const json& element)
256{
257 verifyIsObject(element);
258 unsigned int propertyCount{0};
259
260 // Optional comments property; value not stored
261 if (element.contains("comments"))
262 {
263 ++propertyCount;
264 }
265
266 // Optional volts property
267 std::optional<double> volts{};
268 auto voltsIt = element.find("volts");
269 if (voltsIt != element.end())
270 {
271 volts = parseDouble(*voltsIt);
272 ++propertyCount;
273 }
274
275 // Required rule_id or actions property
276 std::vector<std::unique_ptr<Action>> actions{};
277 actions = parseRuleIDOrActionsProperty(element);
278 ++propertyCount;
279
280 // Verify no invalid properties exist
281 verifyPropertyCount(element, propertyCount);
282
283 return std::make_unique<Configuration>(volts, std::move(actions));
284}
285
Bob King9c36c5f2020-04-06 11:34:09 +0800286std::unique_ptr<Device> parseDevice(const json& element)
287{
288 verifyIsObject(element);
289 unsigned int propertyCount{0};
290
291 // Optional comments property; value not stored
292 if (element.contains("comments"))
293 {
294 ++propertyCount;
295 }
296
297 // Required id property
298 const json& idElement = getRequiredProperty(element, "id");
299 std::string id = parseString(idElement);
300 ++propertyCount;
301
302 // Required is_regulator property
303 const json& isRegulatorElement =
304 getRequiredProperty(element, "is_regulator");
305 bool isRegulator = parseBoolean(isRegulatorElement);
306 ++propertyCount;
307
308 // Required fru property
309 const json& fruElement = getRequiredProperty(element, "fru");
310 std::string fru = parseString(fruElement);
311 ++propertyCount;
312
313 // Required i2c_interface property
314 const json& i2cInterfaceElement =
315 getRequiredProperty(element, "i2c_interface");
316 std::unique_ptr<i2c::I2CInterface> i2cInterface =
317 parseI2CInterface(i2cInterfaceElement);
318 ++propertyCount;
319
320 // Optional presence_detection property
Bob King9c36c5f2020-04-06 11:34:09 +0800321 std::unique_ptr<PresenceDetection> presenceDetection{};
Bob King2aafb1c2020-04-16 15:24:32 +0800322 auto presenceDetectionIt = element.find("presence_detection");
323 if (presenceDetectionIt != element.end())
324 {
325 presenceDetection = parsePresenceDetection(*presenceDetectionIt);
326 ++propertyCount;
327 }
Bob King9c36c5f2020-04-06 11:34:09 +0800328
329 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800330 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800331 auto configurationIt = element.find("configuration");
332 if (configurationIt != element.end())
333 {
334 configuration = parseConfiguration(*configurationIt);
335 ++propertyCount;
336 }
Bob King9c36c5f2020-04-06 11:34:09 +0800337
338 // Optional rails property
339 std::vector<std::unique_ptr<Rail>> rails{};
340 auto railsIt = element.find("rails");
341 if (railsIt != element.end())
342 {
343 if (!isRegulator)
344 {
345 throw std::invalid_argument{
346 "Invalid rails property when is_regulator is false"};
347 }
348 rails = parseRailArray(*railsIt);
349 ++propertyCount;
350 }
351
352 // Verify no invalid properties exist
353 verifyPropertyCount(element, propertyCount);
354
355 return std::make_unique<Device>(id, isRegulator, fru,
356 std::move(i2cInterface),
357 std::move(presenceDetection),
358 std::move(configuration), std::move(rails));
359}
360
Bob King0e701132020-04-03 21:50:31 +0800361std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
362{
363 verifyIsArray(element);
364 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800365 for (auto& deviceElement : element)
366 {
367 devices.emplace_back(parseDevice(deviceElement));
368 }
Bob King0e701132020-04-03 21:50:31 +0800369 return devices;
370}
371
Bob Kingbafcb862020-03-31 16:39:00 +0800372std::vector<uint8_t> parseHexByteArray(const json& element)
373{
374 verifyIsArray(element);
375 std::vector<uint8_t> values;
376 for (auto& valueElement : element)
377 {
378 values.emplace_back(parseHexByte(valueElement));
379 }
380 return values;
381}
382
Bob Kingf09bfe02020-04-13 17:21:15 +0800383std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
384{
385 verifyIsObject(element);
386 unsigned int propertyCount{0};
387
388 // Required register property
389 const json& regElement = getRequiredProperty(element, "register");
390 uint8_t reg = parseHexByte(regElement);
391 ++propertyCount;
392
393 // Required position property
394 const json& positionElement = getRequiredProperty(element, "position");
395 uint8_t position = parseBitPosition(positionElement);
396 ++propertyCount;
397
398 // Required value property
399 const json& valueElement = getRequiredProperty(element, "value");
400 uint8_t value = parseBitValue(valueElement);
401 ++propertyCount;
402
403 // Verify no invalid properties exist
404 verifyPropertyCount(element, propertyCount);
405
406 return std::make_unique<I2CCompareBitAction>(reg, position, value);
407}
408
409std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
410{
411 verifyIsObject(element);
412 unsigned int propertyCount{0};
413
414 // Required register property
415 const json& regElement = getRequiredProperty(element, "register");
416 uint8_t reg = parseHexByte(regElement);
417 ++propertyCount;
418
419 // Required value property
420 const json& valueElement = getRequiredProperty(element, "value");
421 uint8_t value = parseHexByte(valueElement);
422 ++propertyCount;
423
424 // Optional mask property
425 uint8_t mask = 0xff;
426 auto maskIt = element.find("mask");
427 if (maskIt != element.end())
428 {
429 mask = parseHexByte(*maskIt);
430 ++propertyCount;
431 }
432
433 // Verify no invalid properties exist
434 verifyPropertyCount(element, propertyCount);
435
436 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
437}
438
439std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
440{
441 verifyIsObject(element);
442 unsigned int propertyCount{0};
443
444 // Required register property
445 const json& regElement = getRequiredProperty(element, "register");
446 uint8_t reg = parseHexByte(regElement);
447 ++propertyCount;
448
449 // Required values property
450 const json& valueElement = getRequiredProperty(element, "values");
451 std::vector<uint8_t> values = parseHexByteArray(valueElement);
452 ++propertyCount;
453
454 // Optional masks property
455 std::vector<uint8_t> masks{};
456 auto masksIt = element.find("masks");
457 if (masksIt != element.end())
458 {
459 masks = parseHexByteArray(*masksIt);
460 ++propertyCount;
461 }
462
463 // Verify masks array (if specified) was same size as values array
464 if ((!masks.empty()) && (masks.size() != values.size()))
465 {
466 throw std::invalid_argument{"Invalid number of elements in masks"};
467 }
468
469 // Verify no invalid properties exist
470 verifyPropertyCount(element, propertyCount);
471
472 if (masks.empty())
473 {
474 return std::make_unique<I2CCompareBytesAction>(reg, values);
475 }
476 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
477}
478
Bob King9c36c5f2020-04-06 11:34:09 +0800479std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
480{
481 verifyIsObject(element);
482 unsigned int propertyCount{0};
483
484 // Required bus property
485 const json& busElement = getRequiredProperty(element, "bus");
486 uint8_t bus = parseUint8(busElement);
487 ++propertyCount;
488
489 // Required address property
490 const json& addressElement = getRequiredProperty(element, "address");
491 uint8_t address = parseHexByte(addressElement);
492 ++propertyCount;
493
494 verifyPropertyCount(element, propertyCount);
495 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
496}
497
Bob Kingf617f892020-03-30 19:03:35 +0800498std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
499{
500 verifyIsObject(element);
501 unsigned int propertyCount{0};
502
503 // Required register property
504 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800505 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800506 ++propertyCount;
507
508 // Required position property
509 const json& positionElement = getRequiredProperty(element, "position");
510 uint8_t position = parseBitPosition(positionElement);
511 ++propertyCount;
512
513 // Required value property
514 const json& valueElement = getRequiredProperty(element, "value");
515 uint8_t value = parseBitValue(valueElement);
516 ++propertyCount;
517
518 // Verify no invalid properties exist
519 verifyPropertyCount(element, propertyCount);
520
521 return std::make_unique<I2CWriteBitAction>(reg, position, value);
522}
523
Bob King87ff9d72020-03-31 14:02:55 +0800524std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
525{
526 verifyIsObject(element);
527 unsigned int propertyCount{0};
528
529 // Required register property
530 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800531 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800532 ++propertyCount;
533
534 // Required value property
535 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800536 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800537 ++propertyCount;
538
539 // Optional mask property
540 uint8_t mask = 0xff;
541 auto maskIt = element.find("mask");
542 if (maskIt != element.end())
543 {
Bob Kingbafcb862020-03-31 16:39:00 +0800544 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800545 ++propertyCount;
546 }
547
548 // Verify no invalid properties exist
549 verifyPropertyCount(element, propertyCount);
550
551 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
552}
553
Bob Kingbafcb862020-03-31 16:39:00 +0800554std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
555{
556 verifyIsObject(element);
557 unsigned int propertyCount{0};
558
559 // Required register property
560 const json& regElement = getRequiredProperty(element, "register");
561 uint8_t reg = parseHexByte(regElement);
562 ++propertyCount;
563
564 // Required values property
565 const json& valueElement = getRequiredProperty(element, "values");
566 std::vector<uint8_t> values = parseHexByteArray(valueElement);
567 ++propertyCount;
568
569 // Optional masks property
570 std::vector<uint8_t> masks{};
571 auto masksIt = element.find("masks");
572 if (masksIt != element.end())
573 {
574 masks = parseHexByteArray(*masksIt);
575 ++propertyCount;
576 }
577
578 // Verify masks array (if specified) was same size as values array
579 if ((!masks.empty()) && (masks.size() != values.size()))
580 {
581 throw std::invalid_argument{"Invalid number of elements in masks"};
582 }
583
584 // Verify no invalid properties exist
585 verifyPropertyCount(element, propertyCount);
586
587 if (masks.empty())
588 {
589 return std::make_unique<I2CWriteBytesAction>(reg, values);
590 }
591 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
592}
593
Bob King93a89d72020-04-15 15:11:11 +0800594std::unique_ptr<IfAction> parseIf(const json& element)
595{
596 verifyIsObject(element);
597 unsigned int propertyCount{0};
598
599 // Required condition property
600 const json& conditionElement = getRequiredProperty(element, "condition");
601 std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
602 ++propertyCount;
603
604 // Required then property
605 const json& thenElement = getRequiredProperty(element, "then");
606 std::vector<std::unique_ptr<Action>> thenActions =
607 parseActionArray(thenElement);
608 ++propertyCount;
609
610 // Optional else property
611 std::vector<std::unique_ptr<Action>> elseActions{};
612 auto elseIt = element.find("else");
613 if (elseIt != element.end())
614 {
615 elseActions = parseActionArray(*elseIt);
616 ++propertyCount;
617 }
618
619 // Verify no invalid properties exist
620 verifyPropertyCount(element, propertyCount);
621
622 return std::make_unique<IfAction>(std::move(conditionAction),
623 std::move(thenActions),
624 std::move(elseActions));
625}
626
Bob Kingf1b58dc2020-04-14 14:53:10 +0800627std::unique_ptr<NotAction> parseNot(const json& element)
628{
629 // Required action to execute
630 std::unique_ptr<Action> action = parseAction(element);
631
632 return std::make_unique<NotAction>(std::move(action));
633}
634
Bob King0b51a9b2020-04-15 13:24:18 +0800635std::unique_ptr<OrAction> parseOr(const json& element)
636{
637 verifyIsArray(element);
638
639 // Verify if array size less than 2
640 if (element.size() < 2)
641 {
642 throw std::invalid_argument{"Array must contain two or more actions"};
643 }
644 // Array of two or more actions
645 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
646
647 return std::make_unique<OrAction>(std::move(actions));
648}
649
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500650std::unique_ptr<PMBusWriteVoutCommandAction>
651 parsePMBusWriteVoutCommand(const json& element)
652{
653 verifyIsObject(element);
654 unsigned int propertyCount{0};
655
656 // Optional volts property
657 std::optional<double> volts{};
658 auto voltsIt = element.find("volts");
659 if (voltsIt != element.end())
660 {
661 volts = parseDouble(*voltsIt);
662 ++propertyCount;
663 }
664
665 // Required format property
666 const json& formatElement = getRequiredProperty(element, "format");
667 std::string formatString = parseString(formatElement);
668 if (formatString != "linear")
669 {
670 throw std::invalid_argument{"Invalid format value: " + formatString};
671 }
672 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
673 ++propertyCount;
674
675 // Optional exponent property
676 std::optional<int8_t> exponent{};
677 auto exponentIt = element.find("exponent");
678 if (exponentIt != element.end())
679 {
680 exponent = parseInt8(*exponentIt);
681 ++propertyCount;
682 }
683
684 // Optional is_verified property
685 bool isVerified = false;
686 auto isVerifiedIt = element.find("is_verified");
687 if (isVerifiedIt != element.end())
688 {
689 isVerified = parseBoolean(*isVerifiedIt);
690 ++propertyCount;
691 }
692
693 // Verify no invalid properties exist
694 verifyPropertyCount(element, propertyCount);
695
696 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
697 exponent, isVerified);
698}
699
Bob King2aafb1c2020-04-16 15:24:32 +0800700std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
701{
702 verifyIsObject(element);
703 unsigned int propertyCount{0};
704
705 // Optional comments property; value not stored
706 if (element.contains("comments"))
707 {
708 ++propertyCount;
709 }
710
711 // Required rule_id or actions property
712 std::vector<std::unique_ptr<Action>> actions{};
713 actions = parseRuleIDOrActionsProperty(element);
714 ++propertyCount;
715
716 // Verify no invalid properties exist
717 verifyPropertyCount(element, propertyCount);
718
719 return std::make_unique<PresenceDetection>(std::move(actions));
720}
721
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800722std::unique_ptr<Rail> parseRail(const json& element)
723{
724 verifyIsObject(element);
725 unsigned int propertyCount{0};
726
727 // Optional comments property; value not stored
728 if (element.contains("comments"))
729 {
730 ++propertyCount;
731 }
732
733 // Required id property
734 const json& idElement = getRequiredProperty(element, "id");
735 std::string id = parseString(idElement);
736 ++propertyCount;
737
738 // Optional configuration property
739 std::unique_ptr<Configuration> configuration{};
740 auto configurationIt = element.find("configuration");
741 if (configurationIt != element.end())
742 {
743 configuration = parseConfiguration(*configurationIt);
744 ++propertyCount;
745 }
746
747 // Optional sensor_monitoring property
748 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
749 auto sensorMonitoringIt = element.find("sensor_monitoring");
750 if (sensorMonitoringIt != element.end())
751 {
752 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
753 ++propertyCount;
754 }
755
756 // Verify no invalid properties exist
757 verifyPropertyCount(element, propertyCount);
758
759 return std::make_unique<Rail>(id, std::move(configuration),
760 std::move(sensorMonitoring));
761}
762
Bob King9c36c5f2020-04-06 11:34:09 +0800763std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
764{
765 verifyIsArray(element);
766 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800767 for (auto& railElement : element)
768 {
769 rails.emplace_back(parseRail(railElement));
770 }
Bob King9c36c5f2020-04-06 11:34:09 +0800771 return rails;
772}
773
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500774std::tuple<std::vector<std::unique_ptr<Rule>>,
775 std::vector<std::unique_ptr<Chassis>>>
776 parseRoot(const json& element)
777{
778 verifyIsObject(element);
779 unsigned int propertyCount{0};
780
781 // Optional comments property; value not stored
782 if (element.contains("comments"))
783 {
784 ++propertyCount;
785 }
786
787 // Optional rules property
788 std::vector<std::unique_ptr<Rule>> rules{};
789 auto rulesIt = element.find("rules");
790 if (rulesIt != element.end())
791 {
792 rules = parseRuleArray(*rulesIt);
793 ++propertyCount;
794 }
795
796 // Required chassis property
797 const json& chassisElement = getRequiredProperty(element, "chassis");
798 std::vector<std::unique_ptr<Chassis>> chassis =
799 parseChassisArray(chassisElement);
800 ++propertyCount;
801
802 // Verify no invalid properties exist
803 verifyPropertyCount(element, propertyCount);
804
805 return std::make_tuple(std::move(rules), std::move(chassis));
806}
807
808std::unique_ptr<Rule> parseRule(const json& element)
809{
810 verifyIsObject(element);
811 unsigned int propertyCount{0};
812
813 // Optional comments property; value not stored
814 if (element.contains("comments"))
815 {
816 ++propertyCount;
817 }
818
819 // Required id property
820 const json& idElement = getRequiredProperty(element, "id");
821 std::string id = parseString(idElement);
822 ++propertyCount;
823
824 // Required actions property
825 const json& actionsElement = getRequiredProperty(element, "actions");
826 std::vector<std::unique_ptr<Action>> actions =
827 parseActionArray(actionsElement);
828 ++propertyCount;
829
830 // Verify no invalid properties exist
831 verifyPropertyCount(element, propertyCount);
832
833 return std::make_unique<Rule>(id, std::move(actions));
834}
835
836std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
837{
838 verifyIsArray(element);
839 std::vector<std::unique_ptr<Rule>> rules;
840 for (auto& ruleElement : element)
841 {
842 rules.emplace_back(parseRule(ruleElement));
843 }
844 return rules;
845}
846
Bob King33e7eaa2020-04-01 18:09:34 +0800847std::vector<std::unique_ptr<Action>>
848 parseRuleIDOrActionsProperty(const json& element)
849{
850 verifyIsObject(element);
851 // Required rule_id or actions property
852 std::vector<std::unique_ptr<Action>> actions{};
853 auto ruleIDIt = element.find("rule_id");
854 auto actionsIt = element.find("actions");
855 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
856 {
857 std::string ruleID = parseString(*ruleIDIt);
858 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
859 }
860 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
861 {
862 actions = parseActionArray(*actionsIt);
863 }
864 else
865 {
866 throw std::invalid_argument{"Invalid property combination: Must "
867 "contain either rule_id or actions"};
868 }
869
870 return actions;
871}
872
Bob King315b0b62020-04-03 21:47:58 +0800873std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
874{
875 // String ruleID
876 std::string ruleID = parseString(element);
877
878 return std::make_unique<RunRuleAction>(ruleID);
879}
880
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800881std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
882{
883 verifyIsObject(element);
884 unsigned int propertyCount{0};
885
886 // Optional comments property; value not stored
887 if (element.contains("comments"))
888 {
889 ++propertyCount;
890 }
891
892 // Required rule_id or actions property
893 std::vector<std::unique_ptr<Action>> actions{};
894 actions = parseRuleIDOrActionsProperty(element);
895 ++propertyCount;
896
897 // Verify no invalid properties exist
898 verifyPropertyCount(element, propertyCount);
899
900 return std::make_unique<SensorMonitoring>(std::move(actions));
901}
902
Bob King18a68502020-04-17 14:19:56 +0800903std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
904{
905 // String deviceID
906 std::string deviceID = parseString(element);
907
908 return std::make_unique<SetDeviceAction>(deviceID);
909}
910
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500911} // namespace internal
912
913} // namespace phosphor::power::regulators::config_file_parser