1 /** 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" 20 #include "i2c_interface.hpp" 21 #include "pmbus_utils.hpp" 22 23 #include <exception> 24 #include <fstream> 25 #include <optional> 26 #include <utility> 27 28 using json = nlohmann::json; 29 30 namespace phosphor::power::regulators::config_file_parser 31 { 32 33 std::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 52 namespace internal 53 { 54 55 std::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 { 70 action = parseAnd(element["and"]); 71 ++propertyCount; 72 } 73 else if (element.contains("compare_presence")) 74 { 75 action = parseComparePresence(element["compare_presence"]); 76 ++propertyCount; 77 } 78 else if (element.contains("compare_vpd")) 79 { 80 action = parseCompareVPD(element["compare_vpd"]); 81 ++propertyCount; 82 } 83 else if (element.contains("i2c_compare_bit")) 84 { 85 action = parseI2CCompareBit(element["i2c_compare_bit"]); 86 ++propertyCount; 87 } 88 else if (element.contains("i2c_compare_byte")) 89 { 90 action = parseI2CCompareByte(element["i2c_compare_byte"]); 91 ++propertyCount; 92 } 93 else if (element.contains("i2c_compare_bytes")) 94 { 95 action = parseI2CCompareBytes(element["i2c_compare_bytes"]); 96 ++propertyCount; 97 } 98 else if (element.contains("i2c_write_bit")) 99 { 100 action = parseI2CWriteBit(element["i2c_write_bit"]); 101 ++propertyCount; 102 } 103 else if (element.contains("i2c_write_byte")) 104 { 105 action = parseI2CWriteByte(element["i2c_write_byte"]); 106 ++propertyCount; 107 } 108 else if (element.contains("i2c_write_bytes")) 109 { 110 action = parseI2CWriteBytes(element["i2c_write_bytes"]); 111 ++propertyCount; 112 } 113 else if (element.contains("if")) 114 { 115 action = parseIf(element["if"]); 116 ++propertyCount; 117 } 118 else if (element.contains("not")) 119 { 120 action = parseNot(element["not"]); 121 ++propertyCount; 122 } 123 else if (element.contains("or")) 124 { 125 action = parseOr(element["or"]); 126 ++propertyCount; 127 } 128 else if (element.contains("pmbus_read_sensor")) 129 { 130 action = parsePMBusReadSensor(element["pmbus_read_sensor"]); 131 ++propertyCount; 132 } 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 { 141 action = parseRunRule(element["run_rule"]); 142 ++propertyCount; 143 } 144 else if (element.contains("set_device")) 145 { 146 action = parseSetDevice(element["set_device"]); 147 ++propertyCount; 148 } 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 160 std::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 171 std::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 186 std::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 221 std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element) 222 { 223 verifyIsArray(element); 224 std::vector<std::unique_ptr<Chassis>> chassis; 225 for (auto& chassisElement : element) 226 { 227 chassis.emplace_back(parseChassis(chassisElement)); 228 } 229 return chassis; 230 } 231 232 std::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 = parseInventoryPath(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 253 std::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 = parseInventoryPath(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 279 std::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 310 std::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 = parseInventoryPath(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 345 std::unique_ptr<PresenceDetection> presenceDetection{}; 346 auto presenceDetectionIt = element.find("presence_detection"); 347 if (presenceDetectionIt != element.end()) 348 { 349 presenceDetection = parsePresenceDetection(*presenceDetectionIt); 350 ++propertyCount; 351 } 352 353 // Optional configuration property 354 std::unique_ptr<Configuration> configuration{}; 355 auto configurationIt = element.find("configuration"); 356 if (configurationIt != element.end()) 357 { 358 configuration = parseConfiguration(*configurationIt); 359 ++propertyCount; 360 } 361 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 385 std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element) 386 { 387 verifyIsArray(element); 388 std::vector<std::unique_ptr<Device>> devices; 389 for (auto& deviceElement : element) 390 { 391 devices.emplace_back(parseDevice(deviceElement)); 392 } 393 return devices; 394 } 395 396 std::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 407 std::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 433 std::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 463 std::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 503 std::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 522 std::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"); 529 uint8_t reg = parseHexByte(regElement); 530 ++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 548 std::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"); 555 uint8_t reg = parseHexByte(regElement); 556 ++propertyCount; 557 558 // Required value property 559 const json& valueElement = getRequiredProperty(element, "value"); 560 uint8_t value = parseHexByte(valueElement); 561 ++propertyCount; 562 563 // Optional mask property 564 uint8_t mask = 0xff; 565 auto maskIt = element.find("mask"); 566 if (maskIt != element.end()) 567 { 568 mask = parseHexByte(*maskIt); 569 ++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 578 std::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 618 std::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 651 std::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 663 std::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 671 std::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 686 std::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"); 693 pmbus_utils::SensorValueType type = parseSensorValueType(typeElement); 694 ++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 722 std::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 772 std::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 794 std::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 835 std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element) 836 { 837 verifyIsArray(element); 838 std::vector<std::unique_ptr<Rail>> rails; 839 for (auto& railElement : element) 840 { 841 rails.emplace_back(parseRail(railElement)); 842 } 843 return rails; 844 } 845 846 std::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 880 std::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 908 std::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 919 std::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 945 std::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 953 pmbus_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 978 std::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 1000 pmbus_utils::SensorValueType parseSensorValueType(const json& element) 1001 { 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>(); 1007 pmbus_utils::SensorValueType type{}; 1008 1009 if (value == "iout") 1010 { 1011 type = pmbus_utils::SensorValueType::iout; 1012 } 1013 else if (value == "iout_peak") 1014 { 1015 type = pmbus_utils::SensorValueType::iout_peak; 1016 } 1017 else if (value == "iout_valley") 1018 { 1019 type = pmbus_utils::SensorValueType::iout_valley; 1020 } 1021 else if (value == "pout") 1022 { 1023 type = pmbus_utils::SensorValueType::pout; 1024 } 1025 else if (value == "temperature") 1026 { 1027 type = pmbus_utils::SensorValueType::temperature; 1028 } 1029 else if (value == "temperature_peak") 1030 { 1031 type = pmbus_utils::SensorValueType::temperature_peak; 1032 } 1033 else if (value == "vout") 1034 { 1035 type = pmbus_utils::SensorValueType::vout; 1036 } 1037 else if (value == "vout_peak") 1038 { 1039 type = pmbus_utils::SensorValueType::vout_peak; 1040 } 1041 else if (value == "vout_valley") 1042 { 1043 type = pmbus_utils::SensorValueType::vout_valley; 1044 } 1045 else 1046 { 1047 throw std::invalid_argument{"Element is not a sensor value type"}; 1048 } 1049 1050 return type; 1051 } 1052 1053 std::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 1061 pmbus_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 1094 } // namespace internal 1095 1096 } // namespace phosphor::power::regulators::config_file_parser 1097