blob: 6fa34e1f60ce64e7fbe66de9f3f4f2a90c510b33 [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
206 // Optional devices property
207 std::vector<std::unique_ptr<Device>> devices{};
208 auto devicesIt = element.find("devices");
209 if (devicesIt != element.end())
210 {
211 devices = parseDeviceArray(*devicesIt);
212 ++propertyCount;
213 }
214
215 // Verify no invalid properties exist
216 verifyPropertyCount(element, propertyCount);
217
218 return std::make_unique<Chassis>(number, std::move(devices));
219}
220
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500221std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
222{
223 verifyIsArray(element);
224 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800225 for (auto& chassisElement : element)
226 {
227 chassis.emplace_back(parseChassis(chassisElement));
228 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500229 return chassis;
230}
231
Bob Kingb267b7e2020-04-22 14:42:39 +0800232std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element)
233{
234 verifyIsObject(element);
235 unsigned int propertyCount{0};
236
237 // Required fru property
238 const json& fruElement = getRequiredProperty(element, "fru");
239 std::string fru = parseString(fruElement);
240 ++propertyCount;
241
242 // Required value property
243 const json& valueElement = getRequiredProperty(element, "value");
244 bool value = parseBoolean(valueElement);
245 ++propertyCount;
246
247 // Verify no invalid properties exist
248 verifyPropertyCount(element, propertyCount);
249
250 return std::make_unique<ComparePresenceAction>(fru, value);
251}
252
Bob Kingf2134322020-04-27 14:14:56 +0800253std::unique_ptr<CompareVPDAction> parseCompareVPD(const json& element)
254{
255 verifyIsObject(element);
256 unsigned int propertyCount{0};
257
258 // Required fru property
259 const json& fruElement = getRequiredProperty(element, "fru");
260 std::string fru = parseString(fruElement);
261 ++propertyCount;
262
263 // Required keyword property
264 const json& keywordElement = getRequiredProperty(element, "keyword");
265 std::string keyword = parseString(keywordElement);
266 ++propertyCount;
267
268 // Required value property
269 const json& valueElement = getRequiredProperty(element, "value");
270 std::string value = parseString(valueElement);
271 ++propertyCount;
272
273 // Verify no invalid properties exist
274 verifyPropertyCount(element, propertyCount);
275
276 return std::make_unique<CompareVPDAction>(fru, keyword, value);
277}
278
Bob King33e7eaa2020-04-01 18:09:34 +0800279std::unique_ptr<Configuration> parseConfiguration(const json& element)
280{
281 verifyIsObject(element);
282 unsigned int propertyCount{0};
283
284 // Optional comments property; value not stored
285 if (element.contains("comments"))
286 {
287 ++propertyCount;
288 }
289
290 // Optional volts property
291 std::optional<double> volts{};
292 auto voltsIt = element.find("volts");
293 if (voltsIt != element.end())
294 {
295 volts = parseDouble(*voltsIt);
296 ++propertyCount;
297 }
298
299 // Required rule_id or actions property
300 std::vector<std::unique_ptr<Action>> actions{};
301 actions = parseRuleIDOrActionsProperty(element);
302 ++propertyCount;
303
304 // Verify no invalid properties exist
305 verifyPropertyCount(element, propertyCount);
306
307 return std::make_unique<Configuration>(volts, std::move(actions));
308}
309
Bob King9c36c5f2020-04-06 11:34:09 +0800310std::unique_ptr<Device> parseDevice(const json& element)
311{
312 verifyIsObject(element);
313 unsigned int propertyCount{0};
314
315 // Optional comments property; value not stored
316 if (element.contains("comments"))
317 {
318 ++propertyCount;
319 }
320
321 // Required id property
322 const json& idElement = getRequiredProperty(element, "id");
323 std::string id = parseString(idElement);
324 ++propertyCount;
325
326 // Required is_regulator property
327 const json& isRegulatorElement =
328 getRequiredProperty(element, "is_regulator");
329 bool isRegulator = parseBoolean(isRegulatorElement);
330 ++propertyCount;
331
332 // Required fru property
333 const json& fruElement = getRequiredProperty(element, "fru");
334 std::string fru = parseString(fruElement);
335 ++propertyCount;
336
337 // Required i2c_interface property
338 const json& i2cInterfaceElement =
339 getRequiredProperty(element, "i2c_interface");
340 std::unique_ptr<i2c::I2CInterface> i2cInterface =
341 parseI2CInterface(i2cInterfaceElement);
342 ++propertyCount;
343
344 // Optional presence_detection property
Bob King9c36c5f2020-04-06 11:34:09 +0800345 std::unique_ptr<PresenceDetection> presenceDetection{};
Bob King2aafb1c2020-04-16 15:24:32 +0800346 auto presenceDetectionIt = element.find("presence_detection");
347 if (presenceDetectionIt != element.end())
348 {
349 presenceDetection = parsePresenceDetection(*presenceDetectionIt);
350 ++propertyCount;
351 }
Bob King9c36c5f2020-04-06 11:34:09 +0800352
353 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800354 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800355 auto configurationIt = element.find("configuration");
356 if (configurationIt != element.end())
357 {
358 configuration = parseConfiguration(*configurationIt);
359 ++propertyCount;
360 }
Bob King9c36c5f2020-04-06 11:34:09 +0800361
362 // Optional rails property
363 std::vector<std::unique_ptr<Rail>> rails{};
364 auto railsIt = element.find("rails");
365 if (railsIt != element.end())
366 {
367 if (!isRegulator)
368 {
369 throw std::invalid_argument{
370 "Invalid rails property when is_regulator is false"};
371 }
372 rails = parseRailArray(*railsIt);
373 ++propertyCount;
374 }
375
376 // Verify no invalid properties exist
377 verifyPropertyCount(element, propertyCount);
378
379 return std::make_unique<Device>(id, isRegulator, fru,
380 std::move(i2cInterface),
381 std::move(presenceDetection),
382 std::move(configuration), std::move(rails));
383}
384
Bob King0e701132020-04-03 21:50:31 +0800385std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
386{
387 verifyIsArray(element);
388 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800389 for (auto& deviceElement : element)
390 {
391 devices.emplace_back(parseDevice(deviceElement));
392 }
Bob King0e701132020-04-03 21:50:31 +0800393 return devices;
394}
395
Bob Kingbafcb862020-03-31 16:39:00 +0800396std::vector<uint8_t> parseHexByteArray(const json& element)
397{
398 verifyIsArray(element);
399 std::vector<uint8_t> values;
400 for (auto& valueElement : element)
401 {
402 values.emplace_back(parseHexByte(valueElement));
403 }
404 return values;
405}
406
Bob Kingf09bfe02020-04-13 17:21:15 +0800407std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
408{
409 verifyIsObject(element);
410 unsigned int propertyCount{0};
411
412 // Required register property
413 const json& regElement = getRequiredProperty(element, "register");
414 uint8_t reg = parseHexByte(regElement);
415 ++propertyCount;
416
417 // Required position property
418 const json& positionElement = getRequiredProperty(element, "position");
419 uint8_t position = parseBitPosition(positionElement);
420 ++propertyCount;
421
422 // Required value property
423 const json& valueElement = getRequiredProperty(element, "value");
424 uint8_t value = parseBitValue(valueElement);
425 ++propertyCount;
426
427 // Verify no invalid properties exist
428 verifyPropertyCount(element, propertyCount);
429
430 return std::make_unique<I2CCompareBitAction>(reg, position, value);
431}
432
433std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
434{
435 verifyIsObject(element);
436 unsigned int propertyCount{0};
437
438 // Required register property
439 const json& regElement = getRequiredProperty(element, "register");
440 uint8_t reg = parseHexByte(regElement);
441 ++propertyCount;
442
443 // Required value property
444 const json& valueElement = getRequiredProperty(element, "value");
445 uint8_t value = parseHexByte(valueElement);
446 ++propertyCount;
447
448 // Optional mask property
449 uint8_t mask = 0xff;
450 auto maskIt = element.find("mask");
451 if (maskIt != element.end())
452 {
453 mask = parseHexByte(*maskIt);
454 ++propertyCount;
455 }
456
457 // Verify no invalid properties exist
458 verifyPropertyCount(element, propertyCount);
459
460 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
461}
462
463std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
464{
465 verifyIsObject(element);
466 unsigned int propertyCount{0};
467
468 // Required register property
469 const json& regElement = getRequiredProperty(element, "register");
470 uint8_t reg = parseHexByte(regElement);
471 ++propertyCount;
472
473 // Required values property
474 const json& valueElement = getRequiredProperty(element, "values");
475 std::vector<uint8_t> values = parseHexByteArray(valueElement);
476 ++propertyCount;
477
478 // Optional masks property
479 std::vector<uint8_t> masks{};
480 auto masksIt = element.find("masks");
481 if (masksIt != element.end())
482 {
483 masks = parseHexByteArray(*masksIt);
484 ++propertyCount;
485 }
486
487 // Verify masks array (if specified) was same size as values array
488 if ((!masks.empty()) && (masks.size() != values.size()))
489 {
490 throw std::invalid_argument{"Invalid number of elements in masks"};
491 }
492
493 // Verify no invalid properties exist
494 verifyPropertyCount(element, propertyCount);
495
496 if (masks.empty())
497 {
498 return std::make_unique<I2CCompareBytesAction>(reg, values);
499 }
500 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
501}
502
Bob King9c36c5f2020-04-06 11:34:09 +0800503std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
504{
505 verifyIsObject(element);
506 unsigned int propertyCount{0};
507
508 // Required bus property
509 const json& busElement = getRequiredProperty(element, "bus");
510 uint8_t bus = parseUint8(busElement);
511 ++propertyCount;
512
513 // Required address property
514 const json& addressElement = getRequiredProperty(element, "address");
515 uint8_t address = parseHexByte(addressElement);
516 ++propertyCount;
517
518 verifyPropertyCount(element, propertyCount);
519 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
520}
521
Bob Kingf617f892020-03-30 19:03:35 +0800522std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
523{
524 verifyIsObject(element);
525 unsigned int propertyCount{0};
526
527 // Required register property
528 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800529 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800530 ++propertyCount;
531
532 // Required position property
533 const json& positionElement = getRequiredProperty(element, "position");
534 uint8_t position = parseBitPosition(positionElement);
535 ++propertyCount;
536
537 // Required value property
538 const json& valueElement = getRequiredProperty(element, "value");
539 uint8_t value = parseBitValue(valueElement);
540 ++propertyCount;
541
542 // Verify no invalid properties exist
543 verifyPropertyCount(element, propertyCount);
544
545 return std::make_unique<I2CWriteBitAction>(reg, position, value);
546}
547
Bob King87ff9d72020-03-31 14:02:55 +0800548std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
549{
550 verifyIsObject(element);
551 unsigned int propertyCount{0};
552
553 // Required register property
554 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800555 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800556 ++propertyCount;
557
558 // Required value property
559 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800560 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800561 ++propertyCount;
562
563 // Optional mask property
564 uint8_t mask = 0xff;
565 auto maskIt = element.find("mask");
566 if (maskIt != element.end())
567 {
Bob Kingbafcb862020-03-31 16:39:00 +0800568 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800569 ++propertyCount;
570 }
571
572 // Verify no invalid properties exist
573 verifyPropertyCount(element, propertyCount);
574
575 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
576}
577
Bob Kingbafcb862020-03-31 16:39:00 +0800578std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
579{
580 verifyIsObject(element);
581 unsigned int propertyCount{0};
582
583 // Required register property
584 const json& regElement = getRequiredProperty(element, "register");
585 uint8_t reg = parseHexByte(regElement);
586 ++propertyCount;
587
588 // Required values property
589 const json& valueElement = getRequiredProperty(element, "values");
590 std::vector<uint8_t> values = parseHexByteArray(valueElement);
591 ++propertyCount;
592
593 // Optional masks property
594 std::vector<uint8_t> masks{};
595 auto masksIt = element.find("masks");
596 if (masksIt != element.end())
597 {
598 masks = parseHexByteArray(*masksIt);
599 ++propertyCount;
600 }
601
602 // Verify masks array (if specified) was same size as values array
603 if ((!masks.empty()) && (masks.size() != values.size()))
604 {
605 throw std::invalid_argument{"Invalid number of elements in masks"};
606 }
607
608 // Verify no invalid properties exist
609 verifyPropertyCount(element, propertyCount);
610
611 if (masks.empty())
612 {
613 return std::make_unique<I2CWriteBytesAction>(reg, values);
614 }
615 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
616}
617
Bob King93a89d72020-04-15 15:11:11 +0800618std::unique_ptr<IfAction> parseIf(const json& element)
619{
620 verifyIsObject(element);
621 unsigned int propertyCount{0};
622
623 // Required condition property
624 const json& conditionElement = getRequiredProperty(element, "condition");
625 std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
626 ++propertyCount;
627
628 // Required then property
629 const json& thenElement = getRequiredProperty(element, "then");
630 std::vector<std::unique_ptr<Action>> thenActions =
631 parseActionArray(thenElement);
632 ++propertyCount;
633
634 // Optional else property
635 std::vector<std::unique_ptr<Action>> elseActions{};
636 auto elseIt = element.find("else");
637 if (elseIt != element.end())
638 {
639 elseActions = parseActionArray(*elseIt);
640 ++propertyCount;
641 }
642
643 // Verify no invalid properties exist
644 verifyPropertyCount(element, propertyCount);
645
646 return std::make_unique<IfAction>(std::move(conditionAction),
647 std::move(thenActions),
648 std::move(elseActions));
649}
650
Bob Kingf1b58dc2020-04-14 14:53:10 +0800651std::unique_ptr<NotAction> parseNot(const json& element)
652{
653 // Required action to execute
654 std::unique_ptr<Action> action = parseAction(element);
655
656 return std::make_unique<NotAction>(std::move(action));
657}
658
Bob King0b51a9b2020-04-15 13:24:18 +0800659std::unique_ptr<OrAction> parseOr(const json& element)
660{
661 verifyIsArray(element);
662
663 // Verify if array size less than 2
664 if (element.size() < 2)
665 {
666 throw std::invalid_argument{"Array must contain two or more actions"};
667 }
668 // Array of two or more actions
669 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
670
671 return std::make_unique<OrAction>(std::move(actions));
672}
673
Bob King84614882020-04-30 13:13:48 +0800674std::unique_ptr<PMBusReadSensorAction> parsePMBusReadSensor(const json& element)
675{
676 verifyIsObject(element);
677 unsigned int propertyCount{0};
678
679 // Required type property
680 const json& typeElement = getRequiredProperty(element, "type");
681 pmbus_utils::SensorValueType type = parseSensorValueType(typeElement);
682 ++propertyCount;
683
684 // Required command property
685 const json& commandElement = getRequiredProperty(element, "command");
686 uint8_t command = parseHexByte(commandElement);
687 ++propertyCount;
688
689 // Required format property
690 const json& formatElement = getRequiredProperty(element, "format");
691 pmbus_utils::SensorDataFormat format = parseSensorDataFormat(formatElement);
692 ++propertyCount;
693
694 // Optional exponent property
695 std::optional<int8_t> exponent{};
696 auto exponentIt = element.find("exponent");
697 if (exponentIt != element.end())
698 {
699 exponent = parseInt8(*exponentIt);
700 ++propertyCount;
701 }
702
703 // Verify no invalid properties exist
704 verifyPropertyCount(element, propertyCount);
705
706 return std::make_unique<PMBusReadSensorAction>(type, command, format,
707 exponent);
708}
709
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500710std::unique_ptr<PMBusWriteVoutCommandAction>
711 parsePMBusWriteVoutCommand(const json& element)
712{
713 verifyIsObject(element);
714 unsigned int propertyCount{0};
715
716 // Optional volts property
717 std::optional<double> volts{};
718 auto voltsIt = element.find("volts");
719 if (voltsIt != element.end())
720 {
721 volts = parseDouble(*voltsIt);
722 ++propertyCount;
723 }
724
725 // Required format property
726 const json& formatElement = getRequiredProperty(element, "format");
727 std::string formatString = parseString(formatElement);
728 if (formatString != "linear")
729 {
730 throw std::invalid_argument{"Invalid format value: " + formatString};
731 }
732 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
733 ++propertyCount;
734
735 // Optional exponent property
736 std::optional<int8_t> exponent{};
737 auto exponentIt = element.find("exponent");
738 if (exponentIt != element.end())
739 {
740 exponent = parseInt8(*exponentIt);
741 ++propertyCount;
742 }
743
744 // Optional is_verified property
745 bool isVerified = false;
746 auto isVerifiedIt = element.find("is_verified");
747 if (isVerifiedIt != element.end())
748 {
749 isVerified = parseBoolean(*isVerifiedIt);
750 ++propertyCount;
751 }
752
753 // Verify no invalid properties exist
754 verifyPropertyCount(element, propertyCount);
755
756 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
757 exponent, isVerified);
758}
759
Bob King2aafb1c2020-04-16 15:24:32 +0800760std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
761{
762 verifyIsObject(element);
763 unsigned int propertyCount{0};
764
765 // Optional comments property; value not stored
766 if (element.contains("comments"))
767 {
768 ++propertyCount;
769 }
770
771 // Required rule_id or actions property
772 std::vector<std::unique_ptr<Action>> actions{};
773 actions = parseRuleIDOrActionsProperty(element);
774 ++propertyCount;
775
776 // Verify no invalid properties exist
777 verifyPropertyCount(element, propertyCount);
778
779 return std::make_unique<PresenceDetection>(std::move(actions));
780}
781
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800782std::unique_ptr<Rail> parseRail(const json& element)
783{
784 verifyIsObject(element);
785 unsigned int propertyCount{0};
786
787 // Optional comments property; value not stored
788 if (element.contains("comments"))
789 {
790 ++propertyCount;
791 }
792
793 // Required id property
794 const json& idElement = getRequiredProperty(element, "id");
795 std::string id = parseString(idElement);
796 ++propertyCount;
797
798 // Optional configuration property
799 std::unique_ptr<Configuration> configuration{};
800 auto configurationIt = element.find("configuration");
801 if (configurationIt != element.end())
802 {
803 configuration = parseConfiguration(*configurationIt);
804 ++propertyCount;
805 }
806
807 // Optional sensor_monitoring property
808 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
809 auto sensorMonitoringIt = element.find("sensor_monitoring");
810 if (sensorMonitoringIt != element.end())
811 {
812 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
813 ++propertyCount;
814 }
815
816 // Verify no invalid properties exist
817 verifyPropertyCount(element, propertyCount);
818
819 return std::make_unique<Rail>(id, std::move(configuration),
820 std::move(sensorMonitoring));
821}
822
Bob King9c36c5f2020-04-06 11:34:09 +0800823std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
824{
825 verifyIsArray(element);
826 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800827 for (auto& railElement : element)
828 {
829 rails.emplace_back(parseRail(railElement));
830 }
Bob King9c36c5f2020-04-06 11:34:09 +0800831 return rails;
832}
833
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500834std::tuple<std::vector<std::unique_ptr<Rule>>,
835 std::vector<std::unique_ptr<Chassis>>>
836 parseRoot(const json& element)
837{
838 verifyIsObject(element);
839 unsigned int propertyCount{0};
840
841 // Optional comments property; value not stored
842 if (element.contains("comments"))
843 {
844 ++propertyCount;
845 }
846
847 // Optional rules property
848 std::vector<std::unique_ptr<Rule>> rules{};
849 auto rulesIt = element.find("rules");
850 if (rulesIt != element.end())
851 {
852 rules = parseRuleArray(*rulesIt);
853 ++propertyCount;
854 }
855
856 // Required chassis property
857 const json& chassisElement = getRequiredProperty(element, "chassis");
858 std::vector<std::unique_ptr<Chassis>> chassis =
859 parseChassisArray(chassisElement);
860 ++propertyCount;
861
862 // Verify no invalid properties exist
863 verifyPropertyCount(element, propertyCount);
864
865 return std::make_tuple(std::move(rules), std::move(chassis));
866}
867
868std::unique_ptr<Rule> parseRule(const json& element)
869{
870 verifyIsObject(element);
871 unsigned int propertyCount{0};
872
873 // Optional comments property; value not stored
874 if (element.contains("comments"))
875 {
876 ++propertyCount;
877 }
878
879 // Required id property
880 const json& idElement = getRequiredProperty(element, "id");
881 std::string id = parseString(idElement);
882 ++propertyCount;
883
884 // Required actions property
885 const json& actionsElement = getRequiredProperty(element, "actions");
886 std::vector<std::unique_ptr<Action>> actions =
887 parseActionArray(actionsElement);
888 ++propertyCount;
889
890 // Verify no invalid properties exist
891 verifyPropertyCount(element, propertyCount);
892
893 return std::make_unique<Rule>(id, std::move(actions));
894}
895
896std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
897{
898 verifyIsArray(element);
899 std::vector<std::unique_ptr<Rule>> rules;
900 for (auto& ruleElement : element)
901 {
902 rules.emplace_back(parseRule(ruleElement));
903 }
904 return rules;
905}
906
Bob King33e7eaa2020-04-01 18:09:34 +0800907std::vector<std::unique_ptr<Action>>
908 parseRuleIDOrActionsProperty(const json& element)
909{
910 verifyIsObject(element);
911 // Required rule_id or actions property
912 std::vector<std::unique_ptr<Action>> actions{};
913 auto ruleIDIt = element.find("rule_id");
914 auto actionsIt = element.find("actions");
915 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
916 {
917 std::string ruleID = parseString(*ruleIDIt);
918 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
919 }
920 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
921 {
922 actions = parseActionArray(*actionsIt);
923 }
924 else
925 {
926 throw std::invalid_argument{"Invalid property combination: Must "
927 "contain either rule_id or actions"};
928 }
929
930 return actions;
931}
932
Bob King315b0b62020-04-03 21:47:58 +0800933std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
934{
935 // String ruleID
936 std::string ruleID = parseString(element);
937
938 return std::make_unique<RunRuleAction>(ruleID);
939}
940
Bob King84614882020-04-30 13:13:48 +0800941pmbus_utils::SensorDataFormat parseSensorDataFormat(const json& element)
942{
943 if (!element.is_string())
944 {
945 throw std::invalid_argument{"Element is not a string"};
946 }
947 std::string value = element.get<std::string>();
948 pmbus_utils::SensorDataFormat format{};
949
950 if (value == "linear_11")
951 {
952 format = pmbus_utils::SensorDataFormat::linear_11;
953 }
954 else if (value == "linear_16")
955 {
956 format = pmbus_utils::SensorDataFormat::linear_16;
957 }
958 else
959 {
960 throw std::invalid_argument{"Element is not a sensor data format"};
961 }
962
963 return format;
964}
965
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800966std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
967{
968 verifyIsObject(element);
969 unsigned int propertyCount{0};
970
971 // Optional comments property; value not stored
972 if (element.contains("comments"))
973 {
974 ++propertyCount;
975 }
976
977 // Required rule_id or actions property
978 std::vector<std::unique_ptr<Action>> actions{};
979 actions = parseRuleIDOrActionsProperty(element);
980 ++propertyCount;
981
982 // Verify no invalid properties exist
983 verifyPropertyCount(element, propertyCount);
984
985 return std::make_unique<SensorMonitoring>(std::move(actions));
986}
987
Bob King84614882020-04-30 13:13:48 +0800988pmbus_utils::SensorValueType parseSensorValueType(const json& element)
989{
990 if (!element.is_string())
991 {
992 throw std::invalid_argument{"Element is not a string"};
993 }
994 std::string value = element.get<std::string>();
995 pmbus_utils::SensorValueType type{};
996
997 if (value == "iout")
998 {
999 type = pmbus_utils::SensorValueType::iout;
1000 }
1001 else if (value == "iout_peak")
1002 {
1003 type = pmbus_utils::SensorValueType::iout_peak;
1004 }
1005 else if (value == "iout_valley")
1006 {
1007 type = pmbus_utils::SensorValueType::iout_valley;
1008 }
1009 else if (value == "pout")
1010 {
1011 type = pmbus_utils::SensorValueType::pout;
1012 }
1013 else if (value == "temperature")
1014 {
1015 type = pmbus_utils::SensorValueType::temperature;
1016 }
1017 else if (value == "temperature_peak")
1018 {
1019 type = pmbus_utils::SensorValueType::temperature_peak;
1020 }
1021 else if (value == "vout")
1022 {
1023 type = pmbus_utils::SensorValueType::vout;
1024 }
1025 else if (value == "vout_peak")
1026 {
1027 type = pmbus_utils::SensorValueType::vout_peak;
1028 }
1029 else if (value == "vout_valley")
1030 {
1031 type = pmbus_utils::SensorValueType::vout_valley;
1032 }
1033 else
1034 {
1035 throw std::invalid_argument{"Element is not a sensor value type"};
1036 }
1037
1038 return type;
1039}
1040
Bob King18a68502020-04-17 14:19:56 +08001041std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
1042{
1043 // String deviceID
1044 std::string deviceID = parseString(element);
1045
1046 return std::make_unique<SetDeviceAction>(deviceID);
1047}
1048
Bob King84614882020-04-30 13:13:48 +08001049pmbus_utils::VoutDataFormat parseVoutDataFormat(const json& element)
1050{
1051 if (!element.is_string())
1052 {
1053 throw std::invalid_argument{"Element is not a string"};
1054 }
1055 std::string value = element.get<std::string>();
1056 pmbus_utils::VoutDataFormat format{};
1057
1058 if (value == "linear")
1059 {
1060 format = pmbus_utils::VoutDataFormat::linear;
1061 }
1062 else if (value == "vid")
1063 {
1064 format = pmbus_utils::VoutDataFormat::vid;
1065 }
1066 else if (value == "direct")
1067 {
1068 format = pmbus_utils::VoutDataFormat::direct;
1069 }
1070 else if (value == "ieee")
1071 {
1072 format = pmbus_utils::VoutDataFormat::ieee;
1073 }
1074 else
1075 {
1076 throw std::invalid_argument{"Element is not a vout data format"};
1077 }
1078
1079 return format;
1080}
1081
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001082} // namespace internal
1083
1084} // namespace phosphor::power::regulators::config_file_parser