blob: 99abd6c89ef4bed2ac0734c226c5e9f59bc41be4 [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");
Bob Kinga76898f2020-10-13 15:08:33 +0800239 std::string fru = parseInventoryPath(fruElement);
Bob Kingb267b7e2020-04-22 14:42:39 +0800240 ++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");
Bob Kinga76898f2020-10-13 15:08:33 +0800260 std::string fru = parseInventoryPath(fruElement);
Bob Kingf2134322020-04-27 14:14:56 +0800261 ++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");
Bob Kinga76898f2020-10-13 15:08:33 +0800334 std::string fru = parseInventoryPath(fruElement);
Bob King9c36c5f2020-04-06 11:34:09 +0800335 ++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 Kinga76898f2020-10-13 15:08:33 +0800651std::string parseInventoryPath(const json& element)
652{
653 std::string inventoryPath = parseString(element);
654 std::string absPath = "/xyz/openbmc_project/inventory";
655 if (inventoryPath.front() != '/')
656 {
657 absPath += '/';
658 }
659 absPath += inventoryPath;
660 return absPath;
661}
662
Bob Kingf1b58dc2020-04-14 14:53:10 +0800663std::unique_ptr<NotAction> parseNot(const json& element)
664{
665 // Required action to execute
666 std::unique_ptr<Action> action = parseAction(element);
667
668 return std::make_unique<NotAction>(std::move(action));
669}
670
Bob King0b51a9b2020-04-15 13:24:18 +0800671std::unique_ptr<OrAction> parseOr(const json& element)
672{
673 verifyIsArray(element);
674
675 // Verify if array size less than 2
676 if (element.size() < 2)
677 {
678 throw std::invalid_argument{"Array must contain two or more actions"};
679 }
680 // Array of two or more actions
681 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
682
683 return std::make_unique<OrAction>(std::move(actions));
684}
685
Bob King84614882020-04-30 13:13:48 +0800686std::unique_ptr<PMBusReadSensorAction> parsePMBusReadSensor(const json& element)
687{
688 verifyIsObject(element);
689 unsigned int propertyCount{0};
690
691 // Required type property
692 const json& typeElement = getRequiredProperty(element, "type");
Shawn McCarney2f9e14f2021-04-29 02:45:18 -0500693 SensorType type = parseSensorType(typeElement);
Bob King84614882020-04-30 13:13:48 +0800694 ++propertyCount;
695
696 // Required command property
697 const json& commandElement = getRequiredProperty(element, "command");
698 uint8_t command = parseHexByte(commandElement);
699 ++propertyCount;
700
701 // Required format property
702 const json& formatElement = getRequiredProperty(element, "format");
703 pmbus_utils::SensorDataFormat format = parseSensorDataFormat(formatElement);
704 ++propertyCount;
705
706 // Optional exponent property
707 std::optional<int8_t> exponent{};
708 auto exponentIt = element.find("exponent");
709 if (exponentIt != element.end())
710 {
711 exponent = parseInt8(*exponentIt);
712 ++propertyCount;
713 }
714
715 // Verify no invalid properties exist
716 verifyPropertyCount(element, propertyCount);
717
718 return std::make_unique<PMBusReadSensorAction>(type, command, format,
719 exponent);
720}
721
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500722std::unique_ptr<PMBusWriteVoutCommandAction>
723 parsePMBusWriteVoutCommand(const json& element)
724{
725 verifyIsObject(element);
726 unsigned int propertyCount{0};
727
728 // Optional volts property
729 std::optional<double> volts{};
730 auto voltsIt = element.find("volts");
731 if (voltsIt != element.end())
732 {
733 volts = parseDouble(*voltsIt);
734 ++propertyCount;
735 }
736
737 // Required format property
738 const json& formatElement = getRequiredProperty(element, "format");
739 std::string formatString = parseString(formatElement);
740 if (formatString != "linear")
741 {
742 throw std::invalid_argument{"Invalid format value: " + formatString};
743 }
744 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
745 ++propertyCount;
746
747 // Optional exponent property
748 std::optional<int8_t> exponent{};
749 auto exponentIt = element.find("exponent");
750 if (exponentIt != element.end())
751 {
752 exponent = parseInt8(*exponentIt);
753 ++propertyCount;
754 }
755
756 // Optional is_verified property
757 bool isVerified = false;
758 auto isVerifiedIt = element.find("is_verified");
759 if (isVerifiedIt != element.end())
760 {
761 isVerified = parseBoolean(*isVerifiedIt);
762 ++propertyCount;
763 }
764
765 // Verify no invalid properties exist
766 verifyPropertyCount(element, propertyCount);
767
768 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
769 exponent, isVerified);
770}
771
Bob King2aafb1c2020-04-16 15:24:32 +0800772std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
773{
774 verifyIsObject(element);
775 unsigned int propertyCount{0};
776
777 // Optional comments property; value not stored
778 if (element.contains("comments"))
779 {
780 ++propertyCount;
781 }
782
783 // Required rule_id or actions property
784 std::vector<std::unique_ptr<Action>> actions{};
785 actions = parseRuleIDOrActionsProperty(element);
786 ++propertyCount;
787
788 // Verify no invalid properties exist
789 verifyPropertyCount(element, propertyCount);
790
791 return std::make_unique<PresenceDetection>(std::move(actions));
792}
793
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800794std::unique_ptr<Rail> parseRail(const json& element)
795{
796 verifyIsObject(element);
797 unsigned int propertyCount{0};
798
799 // Optional comments property; value not stored
800 if (element.contains("comments"))
801 {
802 ++propertyCount;
803 }
804
805 // Required id property
806 const json& idElement = getRequiredProperty(element, "id");
807 std::string id = parseString(idElement);
808 ++propertyCount;
809
810 // Optional configuration property
811 std::unique_ptr<Configuration> configuration{};
812 auto configurationIt = element.find("configuration");
813 if (configurationIt != element.end())
814 {
815 configuration = parseConfiguration(*configurationIt);
816 ++propertyCount;
817 }
818
819 // Optional sensor_monitoring property
820 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
821 auto sensorMonitoringIt = element.find("sensor_monitoring");
822 if (sensorMonitoringIt != element.end())
823 {
824 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
825 ++propertyCount;
826 }
827
828 // Verify no invalid properties exist
829 verifyPropertyCount(element, propertyCount);
830
831 return std::make_unique<Rail>(id, std::move(configuration),
832 std::move(sensorMonitoring));
833}
834
Bob King9c36c5f2020-04-06 11:34:09 +0800835std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
836{
837 verifyIsArray(element);
838 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800839 for (auto& railElement : element)
840 {
841 rails.emplace_back(parseRail(railElement));
842 }
Bob King9c36c5f2020-04-06 11:34:09 +0800843 return rails;
844}
845
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500846std::tuple<std::vector<std::unique_ptr<Rule>>,
847 std::vector<std::unique_ptr<Chassis>>>
848 parseRoot(const json& element)
849{
850 verifyIsObject(element);
851 unsigned int propertyCount{0};
852
853 // Optional comments property; value not stored
854 if (element.contains("comments"))
855 {
856 ++propertyCount;
857 }
858
859 // Optional rules property
860 std::vector<std::unique_ptr<Rule>> rules{};
861 auto rulesIt = element.find("rules");
862 if (rulesIt != element.end())
863 {
864 rules = parseRuleArray(*rulesIt);
865 ++propertyCount;
866 }
867
868 // Required chassis property
869 const json& chassisElement = getRequiredProperty(element, "chassis");
870 std::vector<std::unique_ptr<Chassis>> chassis =
871 parseChassisArray(chassisElement);
872 ++propertyCount;
873
874 // Verify no invalid properties exist
875 verifyPropertyCount(element, propertyCount);
876
877 return std::make_tuple(std::move(rules), std::move(chassis));
878}
879
880std::unique_ptr<Rule> parseRule(const json& element)
881{
882 verifyIsObject(element);
883 unsigned int propertyCount{0};
884
885 // Optional comments property; value not stored
886 if (element.contains("comments"))
887 {
888 ++propertyCount;
889 }
890
891 // Required id property
892 const json& idElement = getRequiredProperty(element, "id");
893 std::string id = parseString(idElement);
894 ++propertyCount;
895
896 // Required actions property
897 const json& actionsElement = getRequiredProperty(element, "actions");
898 std::vector<std::unique_ptr<Action>> actions =
899 parseActionArray(actionsElement);
900 ++propertyCount;
901
902 // Verify no invalid properties exist
903 verifyPropertyCount(element, propertyCount);
904
905 return std::make_unique<Rule>(id, std::move(actions));
906}
907
908std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
909{
910 verifyIsArray(element);
911 std::vector<std::unique_ptr<Rule>> rules;
912 for (auto& ruleElement : element)
913 {
914 rules.emplace_back(parseRule(ruleElement));
915 }
916 return rules;
917}
918
Bob King33e7eaa2020-04-01 18:09:34 +0800919std::vector<std::unique_ptr<Action>>
920 parseRuleIDOrActionsProperty(const json& element)
921{
922 verifyIsObject(element);
923 // Required rule_id or actions property
924 std::vector<std::unique_ptr<Action>> actions{};
925 auto ruleIDIt = element.find("rule_id");
926 auto actionsIt = element.find("actions");
927 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
928 {
929 std::string ruleID = parseString(*ruleIDIt);
930 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
931 }
932 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
933 {
934 actions = parseActionArray(*actionsIt);
935 }
936 else
937 {
938 throw std::invalid_argument{"Invalid property combination: Must "
939 "contain either rule_id or actions"};
940 }
941
942 return actions;
943}
944
Bob King315b0b62020-04-03 21:47:58 +0800945std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
946{
947 // String ruleID
948 std::string ruleID = parseString(element);
949
950 return std::make_unique<RunRuleAction>(ruleID);
951}
952
Bob King84614882020-04-30 13:13:48 +0800953pmbus_utils::SensorDataFormat parseSensorDataFormat(const json& element)
954{
955 if (!element.is_string())
956 {
957 throw std::invalid_argument{"Element is not a string"};
958 }
959 std::string value = element.get<std::string>();
960 pmbus_utils::SensorDataFormat format{};
961
962 if (value == "linear_11")
963 {
964 format = pmbus_utils::SensorDataFormat::linear_11;
965 }
966 else if (value == "linear_16")
967 {
968 format = pmbus_utils::SensorDataFormat::linear_16;
969 }
970 else
971 {
972 throw std::invalid_argument{"Element is not a sensor data format"};
973 }
974
975 return format;
976}
977
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800978std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
979{
980 verifyIsObject(element);
981 unsigned int propertyCount{0};
982
983 // Optional comments property; value not stored
984 if (element.contains("comments"))
985 {
986 ++propertyCount;
987 }
988
989 // Required rule_id or actions property
990 std::vector<std::unique_ptr<Action>> actions{};
991 actions = parseRuleIDOrActionsProperty(element);
992 ++propertyCount;
993
994 // Verify no invalid properties exist
995 verifyPropertyCount(element, propertyCount);
996
997 return std::make_unique<SensorMonitoring>(std::move(actions));
998}
999
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001000SensorType parseSensorType(const json& element)
Bob King84614882020-04-30 13:13:48 +08001001{
1002 if (!element.is_string())
1003 {
1004 throw std::invalid_argument{"Element is not a string"};
1005 }
1006 std::string value = element.get<std::string>();
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001007 SensorType type{};
Bob King84614882020-04-30 13:13:48 +08001008
1009 if (value == "iout")
1010 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001011 type = SensorType::iout;
Bob King84614882020-04-30 13:13:48 +08001012 }
1013 else if (value == "iout_peak")
1014 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001015 type = SensorType::iout_peak;
Bob King84614882020-04-30 13:13:48 +08001016 }
1017 else if (value == "iout_valley")
1018 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001019 type = SensorType::iout_valley;
Bob King84614882020-04-30 13:13:48 +08001020 }
1021 else if (value == "pout")
1022 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001023 type = SensorType::pout;
Bob King84614882020-04-30 13:13:48 +08001024 }
1025 else if (value == "temperature")
1026 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001027 type = SensorType::temperature;
Bob King84614882020-04-30 13:13:48 +08001028 }
1029 else if (value == "temperature_peak")
1030 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001031 type = SensorType::temperature_peak;
Bob King84614882020-04-30 13:13:48 +08001032 }
1033 else if (value == "vout")
1034 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001035 type = SensorType::vout;
Bob King84614882020-04-30 13:13:48 +08001036 }
1037 else if (value == "vout_peak")
1038 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001039 type = SensorType::vout_peak;
Bob King84614882020-04-30 13:13:48 +08001040 }
1041 else if (value == "vout_valley")
1042 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001043 type = SensorType::vout_valley;
Bob King84614882020-04-30 13:13:48 +08001044 }
1045 else
1046 {
Shawn McCarney2f9e14f2021-04-29 02:45:18 -05001047 throw std::invalid_argument{"Element is not a sensor type"};
Bob King84614882020-04-30 13:13:48 +08001048 }
1049
1050 return type;
1051}
1052
Bob King18a68502020-04-17 14:19:56 +08001053std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
1054{
1055 // String deviceID
1056 std::string deviceID = parseString(element);
1057
1058 return std::make_unique<SetDeviceAction>(deviceID);
1059}
1060
Bob King84614882020-04-30 13:13:48 +08001061pmbus_utils::VoutDataFormat parseVoutDataFormat(const json& element)
1062{
1063 if (!element.is_string())
1064 {
1065 throw std::invalid_argument{"Element is not a string"};
1066 }
1067 std::string value = element.get<std::string>();
1068 pmbus_utils::VoutDataFormat format{};
1069
1070 if (value == "linear")
1071 {
1072 format = pmbus_utils::VoutDataFormat::linear;
1073 }
1074 else if (value == "vid")
1075 {
1076 format = pmbus_utils::VoutDataFormat::vid;
1077 }
1078 else if (value == "direct")
1079 {
1080 format = pmbus_utils::VoutDataFormat::direct;
1081 }
1082 else if (value == "ieee")
1083 {
1084 format = pmbus_utils::VoutDataFormat::ieee;
1085 }
1086 else
1087 {
1088 throw std::invalid_argument{"Element is not a vout data format"};
1089 }
1090
1091 return format;
1092}
1093
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001094} // namespace internal
1095
1096} // namespace phosphor::power::regulators::config_file_parser