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_capture_bytes")) 84 { 85 action = parseI2CCaptureBytes(element["i2c_capture_bytes"]); 86 ++propertyCount; 87 } 88 else if (element.contains("i2c_compare_bit")) 89 { 90 action = parseI2CCompareBit(element["i2c_compare_bit"]); 91 ++propertyCount; 92 } 93 else if (element.contains("i2c_compare_byte")) 94 { 95 action = parseI2CCompareByte(element["i2c_compare_byte"]); 96 ++propertyCount; 97 } 98 else if (element.contains("i2c_compare_bytes")) 99 { 100 action = parseI2CCompareBytes(element["i2c_compare_bytes"]); 101 ++propertyCount; 102 } 103 else if (element.contains("i2c_write_bit")) 104 { 105 action = parseI2CWriteBit(element["i2c_write_bit"]); 106 ++propertyCount; 107 } 108 else if (element.contains("i2c_write_byte")) 109 { 110 action = parseI2CWriteByte(element["i2c_write_byte"]); 111 ++propertyCount; 112 } 113 else if (element.contains("i2c_write_bytes")) 114 { 115 action = parseI2CWriteBytes(element["i2c_write_bytes"]); 116 ++propertyCount; 117 } 118 else if (element.contains("if")) 119 { 120 action = parseIf(element["if"]); 121 ++propertyCount; 122 } 123 else if (element.contains("log_phase_fault")) 124 { 125 action = parseLogPhaseFault(element["log_phase_fault"]); 126 ++propertyCount; 127 } 128 else if (element.contains("not")) 129 { 130 action = parseNot(element["not"]); 131 ++propertyCount; 132 } 133 else if (element.contains("or")) 134 { 135 action = parseOr(element["or"]); 136 ++propertyCount; 137 } 138 else if (element.contains("pmbus_read_sensor")) 139 { 140 action = parsePMBusReadSensor(element["pmbus_read_sensor"]); 141 ++propertyCount; 142 } 143 else if (element.contains("pmbus_write_vout_command")) 144 { 145 action = 146 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]); 147 ++propertyCount; 148 } 149 else if (element.contains("run_rule")) 150 { 151 action = parseRunRule(element["run_rule"]); 152 ++propertyCount; 153 } 154 else if (element.contains("set_device")) 155 { 156 action = parseSetDevice(element["set_device"]); 157 ++propertyCount; 158 } 159 else 160 { 161 throw std::invalid_argument{"Required action type property missing"}; 162 } 163 164 // Verify no invalid properties exist 165 verifyPropertyCount(element, propertyCount); 166 167 return action; 168 } 169 170 std::vector<std::unique_ptr<Action>> parseActionArray(const json& element) 171 { 172 verifyIsArray(element); 173 std::vector<std::unique_ptr<Action>> actions; 174 for (auto& actionElement : element) 175 { 176 actions.emplace_back(parseAction(actionElement)); 177 } 178 return actions; 179 } 180 181 std::unique_ptr<AndAction> parseAnd(const json& element) 182 { 183 verifyIsArray(element); 184 185 // Verify if array size less than 2 186 if (element.size() < 2) 187 { 188 throw std::invalid_argument{"Array must contain two or more actions"}; 189 } 190 // Array of two or more actions 191 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element); 192 193 return std::make_unique<AndAction>(std::move(actions)); 194 } 195 196 std::unique_ptr<Chassis> parseChassis(const json& element) 197 { 198 verifyIsObject(element); 199 unsigned int propertyCount{0}; 200 201 // Optional comments property; value not stored 202 if (element.contains("comments")) 203 { 204 ++propertyCount; 205 } 206 207 // Required number property 208 const json& numberElement = getRequiredProperty(element, "number"); 209 unsigned int number = parseUnsignedInteger(numberElement); 210 if (number < 1) 211 { 212 throw std::invalid_argument{"Invalid chassis number: Must be > 0"}; 213 } 214 ++propertyCount; 215 216 // Required inventory_path property 217 const json& inventoryPathElement = 218 getRequiredProperty(element, "inventory_path"); 219 std::string inventoryPath = parseInventoryPath(inventoryPathElement); 220 ++propertyCount; 221 222 // Optional devices property 223 std::vector<std::unique_ptr<Device>> devices{}; 224 auto devicesIt = element.find("devices"); 225 if (devicesIt != element.end()) 226 { 227 devices = parseDeviceArray(*devicesIt); 228 ++propertyCount; 229 } 230 231 // Verify no invalid properties exist 232 verifyPropertyCount(element, propertyCount); 233 234 return std::make_unique<Chassis>(number, inventoryPath, std::move(devices)); 235 } 236 237 std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element) 238 { 239 verifyIsArray(element); 240 std::vector<std::unique_ptr<Chassis>> chassis; 241 for (auto& chassisElement : element) 242 { 243 chassis.emplace_back(parseChassis(chassisElement)); 244 } 245 return chassis; 246 } 247 248 std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element) 249 { 250 verifyIsObject(element); 251 unsigned int propertyCount{0}; 252 253 // Required fru property 254 const json& fruElement = getRequiredProperty(element, "fru"); 255 std::string fru = parseInventoryPath(fruElement); 256 ++propertyCount; 257 258 // Required value property 259 const json& valueElement = getRequiredProperty(element, "value"); 260 bool value = parseBoolean(valueElement); 261 ++propertyCount; 262 263 // Verify no invalid properties exist 264 verifyPropertyCount(element, propertyCount); 265 266 return std::make_unique<ComparePresenceAction>(fru, value); 267 } 268 269 std::unique_ptr<CompareVPDAction> parseCompareVPD(const json& element) 270 { 271 verifyIsObject(element); 272 unsigned int propertyCount{0}; 273 274 // Required fru property 275 const json& fruElement = getRequiredProperty(element, "fru"); 276 std::string fru = parseInventoryPath(fruElement); 277 ++propertyCount; 278 279 // Required keyword property 280 const json& keywordElement = getRequiredProperty(element, "keyword"); 281 std::string keyword = parseString(keywordElement); 282 ++propertyCount; 283 284 // Either value or byte_values required property 285 auto valueIt = element.find("value"); 286 std::vector<uint8_t> value{}; 287 auto byteValuesIt = element.find("byte_values"); 288 if ((valueIt != element.end()) && (byteValuesIt == element.end())) 289 { 290 std::string stringValue = parseString(*valueIt, true); 291 value.insert(value.begin(), stringValue.begin(), stringValue.end()); 292 ++propertyCount; 293 } 294 else if ((valueIt == element.end()) && (byteValuesIt != element.end())) 295 { 296 value = parseHexByteArray(*byteValuesIt); 297 ++propertyCount; 298 } 299 else 300 { 301 throw std::invalid_argument{ 302 "Invalid property: Must contain either value or byte_values"}; 303 } 304 305 // Verify no invalid properties exist 306 verifyPropertyCount(element, propertyCount); 307 308 return std::make_unique<CompareVPDAction>(fru, keyword, value); 309 } 310 311 std::unique_ptr<Configuration> parseConfiguration(const json& element) 312 { 313 verifyIsObject(element); 314 unsigned int propertyCount{0}; 315 316 // Optional comments property; value not stored 317 if (element.contains("comments")) 318 { 319 ++propertyCount; 320 } 321 322 // Optional volts property 323 std::optional<double> volts{}; 324 auto voltsIt = element.find("volts"); 325 if (voltsIt != element.end()) 326 { 327 volts = parseDouble(*voltsIt); 328 ++propertyCount; 329 } 330 331 // Required rule_id or actions property 332 std::vector<std::unique_ptr<Action>> actions{}; 333 actions = parseRuleIDOrActionsProperty(element); 334 ++propertyCount; 335 336 // Verify no invalid properties exist 337 verifyPropertyCount(element, propertyCount); 338 339 return std::make_unique<Configuration>(volts, std::move(actions)); 340 } 341 342 std::unique_ptr<Device> parseDevice(const json& element) 343 { 344 verifyIsObject(element); 345 unsigned int propertyCount{0}; 346 347 // Optional comments property; value not stored 348 if (element.contains("comments")) 349 { 350 ++propertyCount; 351 } 352 353 // Required id property 354 const json& idElement = getRequiredProperty(element, "id"); 355 std::string id = parseString(idElement); 356 ++propertyCount; 357 358 // Required is_regulator property 359 const json& isRegulatorElement = 360 getRequiredProperty(element, "is_regulator"); 361 bool isRegulator = parseBoolean(isRegulatorElement); 362 ++propertyCount; 363 364 // Required fru property 365 const json& fruElement = getRequiredProperty(element, "fru"); 366 std::string fru = parseInventoryPath(fruElement); 367 ++propertyCount; 368 369 // Required i2c_interface property 370 const json& i2cInterfaceElement = 371 getRequiredProperty(element, "i2c_interface"); 372 std::unique_ptr<i2c::I2CInterface> i2cInterface = 373 parseI2CInterface(i2cInterfaceElement); 374 ++propertyCount; 375 376 // Optional presence_detection property 377 std::unique_ptr<PresenceDetection> presenceDetection{}; 378 auto presenceDetectionIt = element.find("presence_detection"); 379 if (presenceDetectionIt != element.end()) 380 { 381 presenceDetection = parsePresenceDetection(*presenceDetectionIt); 382 ++propertyCount; 383 } 384 385 // Optional configuration property 386 std::unique_ptr<Configuration> configuration{}; 387 auto configurationIt = element.find("configuration"); 388 if (configurationIt != element.end()) 389 { 390 configuration = parseConfiguration(*configurationIt); 391 ++propertyCount; 392 } 393 394 // Optional phase_fault_detection property 395 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{}; 396 auto phaseFaultDetectionIt = element.find("phase_fault_detection"); 397 if (phaseFaultDetectionIt != element.end()) 398 { 399 if (!isRegulator) 400 { 401 throw std::invalid_argument{"Invalid phase_fault_detection " 402 "property when is_regulator is false"}; 403 } 404 phaseFaultDetection = parsePhaseFaultDetection(*phaseFaultDetectionIt); 405 ++propertyCount; 406 } 407 408 // Optional rails property 409 std::vector<std::unique_ptr<Rail>> rails{}; 410 auto railsIt = element.find("rails"); 411 if (railsIt != element.end()) 412 { 413 if (!isRegulator) 414 { 415 throw std::invalid_argument{ 416 "Invalid rails property when is_regulator is false"}; 417 } 418 rails = parseRailArray(*railsIt); 419 ++propertyCount; 420 } 421 422 // Verify no invalid properties exist 423 verifyPropertyCount(element, propertyCount); 424 425 return std::make_unique<Device>( 426 id, isRegulator, fru, std::move(i2cInterface), 427 std::move(presenceDetection), std::move(configuration), 428 std::move(phaseFaultDetection), std::move(rails)); 429 } 430 431 std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element) 432 { 433 verifyIsArray(element); 434 std::vector<std::unique_ptr<Device>> devices; 435 for (auto& deviceElement : element) 436 { 437 devices.emplace_back(parseDevice(deviceElement)); 438 } 439 return devices; 440 } 441 442 std::vector<uint8_t> parseHexByteArray(const json& element) 443 { 444 verifyIsArray(element); 445 std::vector<uint8_t> values; 446 for (auto& valueElement : element) 447 { 448 values.emplace_back(parseHexByte(valueElement)); 449 } 450 return values; 451 } 452 453 std::unique_ptr<I2CCaptureBytesAction> parseI2CCaptureBytes(const json& element) 454 { 455 verifyIsObject(element); 456 unsigned int propertyCount{0}; 457 458 // Required register property 459 const json& regElement = getRequiredProperty(element, "register"); 460 uint8_t reg = parseHexByte(regElement); 461 ++propertyCount; 462 463 // Required count property 464 const json& countElement = getRequiredProperty(element, "count"); 465 uint8_t count = parseUint8(countElement); 466 if (count < 1) 467 { 468 throw std::invalid_argument{"Invalid byte count: Must be > 0"}; 469 } 470 ++propertyCount; 471 472 // Verify no invalid properties exist 473 verifyPropertyCount(element, propertyCount); 474 475 return std::make_unique<I2CCaptureBytesAction>(reg, count); 476 } 477 478 std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element) 479 { 480 verifyIsObject(element); 481 unsigned int propertyCount{0}; 482 483 // Required register property 484 const json& regElement = getRequiredProperty(element, "register"); 485 uint8_t reg = parseHexByte(regElement); 486 ++propertyCount; 487 488 // Required position property 489 const json& positionElement = getRequiredProperty(element, "position"); 490 uint8_t position = parseBitPosition(positionElement); 491 ++propertyCount; 492 493 // Required value property 494 const json& valueElement = getRequiredProperty(element, "value"); 495 uint8_t value = parseBitValue(valueElement); 496 ++propertyCount; 497 498 // Verify no invalid properties exist 499 verifyPropertyCount(element, propertyCount); 500 501 return std::make_unique<I2CCompareBitAction>(reg, position, value); 502 } 503 504 std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element) 505 { 506 verifyIsObject(element); 507 unsigned int propertyCount{0}; 508 509 // Required register property 510 const json& regElement = getRequiredProperty(element, "register"); 511 uint8_t reg = parseHexByte(regElement); 512 ++propertyCount; 513 514 // Required value property 515 const json& valueElement = getRequiredProperty(element, "value"); 516 uint8_t value = parseHexByte(valueElement); 517 ++propertyCount; 518 519 // Optional mask property 520 uint8_t mask = 0xff; 521 auto maskIt = element.find("mask"); 522 if (maskIt != element.end()) 523 { 524 mask = parseHexByte(*maskIt); 525 ++propertyCount; 526 } 527 528 // Verify no invalid properties exist 529 verifyPropertyCount(element, propertyCount); 530 531 return std::make_unique<I2CCompareByteAction>(reg, value, mask); 532 } 533 534 std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element) 535 { 536 verifyIsObject(element); 537 unsigned int propertyCount{0}; 538 539 // Required register property 540 const json& regElement = getRequiredProperty(element, "register"); 541 uint8_t reg = parseHexByte(regElement); 542 ++propertyCount; 543 544 // Required values property 545 const json& valueElement = getRequiredProperty(element, "values"); 546 std::vector<uint8_t> values = parseHexByteArray(valueElement); 547 ++propertyCount; 548 549 // Optional masks property 550 std::vector<uint8_t> masks{}; 551 auto masksIt = element.find("masks"); 552 if (masksIt != element.end()) 553 { 554 masks = parseHexByteArray(*masksIt); 555 ++propertyCount; 556 } 557 558 // Verify masks array (if specified) was same size as values array 559 if ((!masks.empty()) && (masks.size() != values.size())) 560 { 561 throw std::invalid_argument{"Invalid number of elements in masks"}; 562 } 563 564 // Verify no invalid properties exist 565 verifyPropertyCount(element, propertyCount); 566 567 if (masks.empty()) 568 { 569 return std::make_unique<I2CCompareBytesAction>(reg, values); 570 } 571 return std::make_unique<I2CCompareBytesAction>(reg, values, masks); 572 } 573 574 std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element) 575 { 576 verifyIsObject(element); 577 unsigned int propertyCount{0}; 578 579 // Required bus property 580 const json& busElement = getRequiredProperty(element, "bus"); 581 uint8_t bus = parseUint8(busElement); 582 ++propertyCount; 583 584 // Required address property 585 const json& addressElement = getRequiredProperty(element, "address"); 586 uint8_t address = parseHexByte(addressElement); 587 ++propertyCount; 588 589 verifyPropertyCount(element, propertyCount); 590 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED); 591 } 592 593 std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element) 594 { 595 verifyIsObject(element); 596 unsigned int propertyCount{0}; 597 598 // Required register property 599 const json& regElement = getRequiredProperty(element, "register"); 600 uint8_t reg = parseHexByte(regElement); 601 ++propertyCount; 602 603 // Required position property 604 const json& positionElement = getRequiredProperty(element, "position"); 605 uint8_t position = parseBitPosition(positionElement); 606 ++propertyCount; 607 608 // Required value property 609 const json& valueElement = getRequiredProperty(element, "value"); 610 uint8_t value = parseBitValue(valueElement); 611 ++propertyCount; 612 613 // Verify no invalid properties exist 614 verifyPropertyCount(element, propertyCount); 615 616 return std::make_unique<I2CWriteBitAction>(reg, position, value); 617 } 618 619 std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element) 620 { 621 verifyIsObject(element); 622 unsigned int propertyCount{0}; 623 624 // Required register property 625 const json& regElement = getRequiredProperty(element, "register"); 626 uint8_t reg = parseHexByte(regElement); 627 ++propertyCount; 628 629 // Required value property 630 const json& valueElement = getRequiredProperty(element, "value"); 631 uint8_t value = parseHexByte(valueElement); 632 ++propertyCount; 633 634 // Optional mask property 635 uint8_t mask = 0xff; 636 auto maskIt = element.find("mask"); 637 if (maskIt != element.end()) 638 { 639 mask = parseHexByte(*maskIt); 640 ++propertyCount; 641 } 642 643 // Verify no invalid properties exist 644 verifyPropertyCount(element, propertyCount); 645 646 return std::make_unique<I2CWriteByteAction>(reg, value, mask); 647 } 648 649 std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element) 650 { 651 verifyIsObject(element); 652 unsigned int propertyCount{0}; 653 654 // Required register property 655 const json& regElement = getRequiredProperty(element, "register"); 656 uint8_t reg = parseHexByte(regElement); 657 ++propertyCount; 658 659 // Required values property 660 const json& valueElement = getRequiredProperty(element, "values"); 661 std::vector<uint8_t> values = parseHexByteArray(valueElement); 662 ++propertyCount; 663 664 // Optional masks property 665 std::vector<uint8_t> masks{}; 666 auto masksIt = element.find("masks"); 667 if (masksIt != element.end()) 668 { 669 masks = parseHexByteArray(*masksIt); 670 ++propertyCount; 671 } 672 673 // Verify masks array (if specified) was same size as values array 674 if ((!masks.empty()) && (masks.size() != values.size())) 675 { 676 throw std::invalid_argument{"Invalid number of elements in masks"}; 677 } 678 679 // Verify no invalid properties exist 680 verifyPropertyCount(element, propertyCount); 681 682 if (masks.empty()) 683 { 684 return std::make_unique<I2CWriteBytesAction>(reg, values); 685 } 686 return std::make_unique<I2CWriteBytesAction>(reg, values, masks); 687 } 688 689 std::unique_ptr<IfAction> parseIf(const json& element) 690 { 691 verifyIsObject(element); 692 unsigned int propertyCount{0}; 693 694 // Required condition property 695 const json& conditionElement = getRequiredProperty(element, "condition"); 696 std::unique_ptr<Action> conditionAction = parseAction(conditionElement); 697 ++propertyCount; 698 699 // Required then property 700 const json& thenElement = getRequiredProperty(element, "then"); 701 std::vector<std::unique_ptr<Action>> thenActions = 702 parseActionArray(thenElement); 703 ++propertyCount; 704 705 // Optional else property 706 std::vector<std::unique_ptr<Action>> elseActions{}; 707 auto elseIt = element.find("else"); 708 if (elseIt != element.end()) 709 { 710 elseActions = parseActionArray(*elseIt); 711 ++propertyCount; 712 } 713 714 // Verify no invalid properties exist 715 verifyPropertyCount(element, propertyCount); 716 717 return std::make_unique<IfAction>(std::move(conditionAction), 718 std::move(thenActions), 719 std::move(elseActions)); 720 } 721 722 std::string parseInventoryPath(const json& element) 723 { 724 std::string inventoryPath = parseString(element); 725 std::string absPath = "/xyz/openbmc_project/inventory"; 726 if (inventoryPath.front() != '/') 727 { 728 absPath += '/'; 729 } 730 absPath += inventoryPath; 731 return absPath; 732 } 733 734 std::unique_ptr<LogPhaseFaultAction> parseLogPhaseFault(const json& element) 735 { 736 verifyIsObject(element); 737 unsigned int propertyCount{0}; 738 739 // Required type property 740 const json& typeElement = getRequiredProperty(element, "type"); 741 PhaseFaultType type = parsePhaseFaultType(typeElement); 742 ++propertyCount; 743 744 // Verify no invalid properties exist 745 verifyPropertyCount(element, propertyCount); 746 747 return std::make_unique<LogPhaseFaultAction>(type); 748 } 749 750 std::unique_ptr<NotAction> parseNot(const json& element) 751 { 752 // Required action to execute 753 std::unique_ptr<Action> action = parseAction(element); 754 755 return std::make_unique<NotAction>(std::move(action)); 756 } 757 758 std::unique_ptr<OrAction> parseOr(const json& element) 759 { 760 verifyIsArray(element); 761 762 // Verify if array size less than 2 763 if (element.size() < 2) 764 { 765 throw std::invalid_argument{"Array must contain two or more actions"}; 766 } 767 // Array of two or more actions 768 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element); 769 770 return std::make_unique<OrAction>(std::move(actions)); 771 } 772 773 std::unique_ptr<PhaseFaultDetection> 774 parsePhaseFaultDetection(const json& element) 775 { 776 verifyIsObject(element); 777 unsigned int propertyCount{0}; 778 779 // Optional comments property; value not stored 780 if (element.contains("comments")) 781 { 782 ++propertyCount; 783 } 784 785 // Optional device_id property 786 std::string deviceID{}; 787 auto deviceIDIt = element.find("device_id"); 788 if (deviceIDIt != element.end()) 789 { 790 deviceID = parseString(*deviceIDIt); 791 ++propertyCount; 792 } 793 794 // Required rule_id or actions property 795 std::vector<std::unique_ptr<Action>> actions{}; 796 actions = parseRuleIDOrActionsProperty(element); 797 ++propertyCount; 798 799 // Verify no invalid properties exist 800 verifyPropertyCount(element, propertyCount); 801 802 return std::make_unique<PhaseFaultDetection>(std::move(actions), deviceID); 803 } 804 805 PhaseFaultType parsePhaseFaultType(const json& element) 806 { 807 std::string value = parseString(element); 808 PhaseFaultType type{}; 809 810 if (value == "n") 811 { 812 type = PhaseFaultType::n; 813 } 814 else if (value == "n+1") 815 { 816 type = PhaseFaultType::n_plus_1; 817 } 818 else 819 { 820 throw std::invalid_argument{"Element is not a phase fault type"}; 821 } 822 823 return type; 824 } 825 826 std::unique_ptr<PMBusReadSensorAction> parsePMBusReadSensor(const json& element) 827 { 828 verifyIsObject(element); 829 unsigned int propertyCount{0}; 830 831 // Required type property 832 const json& typeElement = getRequiredProperty(element, "type"); 833 SensorType type = parseSensorType(typeElement); 834 ++propertyCount; 835 836 // Required command property 837 const json& commandElement = getRequiredProperty(element, "command"); 838 uint8_t command = parseHexByte(commandElement); 839 ++propertyCount; 840 841 // Required format property 842 const json& formatElement = getRequiredProperty(element, "format"); 843 pmbus_utils::SensorDataFormat format = parseSensorDataFormat(formatElement); 844 ++propertyCount; 845 846 // Optional exponent property 847 std::optional<int8_t> exponent{}; 848 auto exponentIt = element.find("exponent"); 849 if (exponentIt != element.end()) 850 { 851 exponent = parseInt8(*exponentIt); 852 ++propertyCount; 853 } 854 855 // Verify no invalid properties exist 856 verifyPropertyCount(element, propertyCount); 857 858 return std::make_unique<PMBusReadSensorAction>(type, command, format, 859 exponent); 860 } 861 862 std::unique_ptr<PMBusWriteVoutCommandAction> 863 parsePMBusWriteVoutCommand(const json& element) 864 { 865 verifyIsObject(element); 866 unsigned int propertyCount{0}; 867 868 // Optional volts property 869 std::optional<double> volts{}; 870 auto voltsIt = element.find("volts"); 871 if (voltsIt != element.end()) 872 { 873 volts = parseDouble(*voltsIt); 874 ++propertyCount; 875 } 876 877 // Required format property 878 const json& formatElement = getRequiredProperty(element, "format"); 879 std::string formatString = parseString(formatElement); 880 if (formatString != "linear") 881 { 882 throw std::invalid_argument{"Invalid format value: " + formatString}; 883 } 884 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear; 885 ++propertyCount; 886 887 // Optional exponent property 888 std::optional<int8_t> exponent{}; 889 auto exponentIt = element.find("exponent"); 890 if (exponentIt != element.end()) 891 { 892 exponent = parseInt8(*exponentIt); 893 ++propertyCount; 894 } 895 896 // Optional is_verified property 897 bool isVerified = false; 898 auto isVerifiedIt = element.find("is_verified"); 899 if (isVerifiedIt != element.end()) 900 { 901 isVerified = parseBoolean(*isVerifiedIt); 902 ++propertyCount; 903 } 904 905 // Verify no invalid properties exist 906 verifyPropertyCount(element, propertyCount); 907 908 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format, 909 exponent, isVerified); 910 } 911 912 std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element) 913 { 914 verifyIsObject(element); 915 unsigned int propertyCount{0}; 916 917 // Optional comments property; value not stored 918 if (element.contains("comments")) 919 { 920 ++propertyCount; 921 } 922 923 // Required rule_id or actions property 924 std::vector<std::unique_ptr<Action>> actions{}; 925 actions = parseRuleIDOrActionsProperty(element); 926 ++propertyCount; 927 928 // Verify no invalid properties exist 929 verifyPropertyCount(element, propertyCount); 930 931 return std::make_unique<PresenceDetection>(std::move(actions)); 932 } 933 934 std::unique_ptr<Rail> parseRail(const json& element) 935 { 936 verifyIsObject(element); 937 unsigned int propertyCount{0}; 938 939 // Optional comments property; value not stored 940 if (element.contains("comments")) 941 { 942 ++propertyCount; 943 } 944 945 // Required id property 946 const json& idElement = getRequiredProperty(element, "id"); 947 std::string id = parseString(idElement); 948 ++propertyCount; 949 950 // Optional configuration property 951 std::unique_ptr<Configuration> configuration{}; 952 auto configurationIt = element.find("configuration"); 953 if (configurationIt != element.end()) 954 { 955 configuration = parseConfiguration(*configurationIt); 956 ++propertyCount; 957 } 958 959 // Optional sensor_monitoring property 960 std::unique_ptr<SensorMonitoring> sensorMonitoring{}; 961 auto sensorMonitoringIt = element.find("sensor_monitoring"); 962 if (sensorMonitoringIt != element.end()) 963 { 964 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt); 965 ++propertyCount; 966 } 967 968 // Verify no invalid properties exist 969 verifyPropertyCount(element, propertyCount); 970 971 return std::make_unique<Rail>(id, std::move(configuration), 972 std::move(sensorMonitoring)); 973 } 974 975 std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element) 976 { 977 verifyIsArray(element); 978 std::vector<std::unique_ptr<Rail>> rails; 979 for (auto& railElement : element) 980 { 981 rails.emplace_back(parseRail(railElement)); 982 } 983 return rails; 984 } 985 986 std::tuple<std::vector<std::unique_ptr<Rule>>, 987 std::vector<std::unique_ptr<Chassis>>> 988 parseRoot(const json& element) 989 { 990 verifyIsObject(element); 991 unsigned int propertyCount{0}; 992 993 // Optional comments property; value not stored 994 if (element.contains("comments")) 995 { 996 ++propertyCount; 997 } 998 999 // Optional rules property 1000 std::vector<std::unique_ptr<Rule>> rules{}; 1001 auto rulesIt = element.find("rules"); 1002 if (rulesIt != element.end()) 1003 { 1004 rules = parseRuleArray(*rulesIt); 1005 ++propertyCount; 1006 } 1007 1008 // Required chassis property 1009 const json& chassisElement = getRequiredProperty(element, "chassis"); 1010 std::vector<std::unique_ptr<Chassis>> chassis = 1011 parseChassisArray(chassisElement); 1012 ++propertyCount; 1013 1014 // Verify no invalid properties exist 1015 verifyPropertyCount(element, propertyCount); 1016 1017 return std::make_tuple(std::move(rules), std::move(chassis)); 1018 } 1019 1020 std::unique_ptr<Rule> parseRule(const json& element) 1021 { 1022 verifyIsObject(element); 1023 unsigned int propertyCount{0}; 1024 1025 // Optional comments property; value not stored 1026 if (element.contains("comments")) 1027 { 1028 ++propertyCount; 1029 } 1030 1031 // Required id property 1032 const json& idElement = getRequiredProperty(element, "id"); 1033 std::string id = parseString(idElement); 1034 ++propertyCount; 1035 1036 // Required actions property 1037 const json& actionsElement = getRequiredProperty(element, "actions"); 1038 std::vector<std::unique_ptr<Action>> actions = 1039 parseActionArray(actionsElement); 1040 ++propertyCount; 1041 1042 // Verify no invalid properties exist 1043 verifyPropertyCount(element, propertyCount); 1044 1045 return std::make_unique<Rule>(id, std::move(actions)); 1046 } 1047 1048 std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element) 1049 { 1050 verifyIsArray(element); 1051 std::vector<std::unique_ptr<Rule>> rules; 1052 for (auto& ruleElement : element) 1053 { 1054 rules.emplace_back(parseRule(ruleElement)); 1055 } 1056 return rules; 1057 } 1058 1059 std::vector<std::unique_ptr<Action>> 1060 parseRuleIDOrActionsProperty(const json& element) 1061 { 1062 verifyIsObject(element); 1063 // Required rule_id or actions property 1064 std::vector<std::unique_ptr<Action>> actions{}; 1065 auto ruleIDIt = element.find("rule_id"); 1066 auto actionsIt = element.find("actions"); 1067 if ((actionsIt == element.end()) && (ruleIDIt != element.end())) 1068 { 1069 std::string ruleID = parseString(*ruleIDIt); 1070 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID)); 1071 } 1072 else if ((actionsIt != element.end()) && (ruleIDIt == element.end())) 1073 { 1074 actions = parseActionArray(*actionsIt); 1075 } 1076 else 1077 { 1078 throw std::invalid_argument{"Invalid property combination: Must " 1079 "contain either rule_id or actions"}; 1080 } 1081 1082 return actions; 1083 } 1084 1085 std::unique_ptr<RunRuleAction> parseRunRule(const json& element) 1086 { 1087 // String ruleID 1088 std::string ruleID = parseString(element); 1089 1090 return std::make_unique<RunRuleAction>(ruleID); 1091 } 1092 1093 pmbus_utils::SensorDataFormat parseSensorDataFormat(const json& element) 1094 { 1095 if (!element.is_string()) 1096 { 1097 throw std::invalid_argument{"Element is not a string"}; 1098 } 1099 std::string value = element.get<std::string>(); 1100 pmbus_utils::SensorDataFormat format{}; 1101 1102 if (value == "linear_11") 1103 { 1104 format = pmbus_utils::SensorDataFormat::linear_11; 1105 } 1106 else if (value == "linear_16") 1107 { 1108 format = pmbus_utils::SensorDataFormat::linear_16; 1109 } 1110 else 1111 { 1112 throw std::invalid_argument{"Element is not a sensor data format"}; 1113 } 1114 1115 return format; 1116 } 1117 1118 std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element) 1119 { 1120 verifyIsObject(element); 1121 unsigned int propertyCount{0}; 1122 1123 // Optional comments property; value not stored 1124 if (element.contains("comments")) 1125 { 1126 ++propertyCount; 1127 } 1128 1129 // Required rule_id or actions property 1130 std::vector<std::unique_ptr<Action>> actions{}; 1131 actions = parseRuleIDOrActionsProperty(element); 1132 ++propertyCount; 1133 1134 // Verify no invalid properties exist 1135 verifyPropertyCount(element, propertyCount); 1136 1137 return std::make_unique<SensorMonitoring>(std::move(actions)); 1138 } 1139 1140 SensorType parseSensorType(const json& element) 1141 { 1142 std::string value = parseString(element); 1143 SensorType type{}; 1144 1145 if (value == "iout") 1146 { 1147 type = SensorType::iout; 1148 } 1149 else if (value == "iout_peak") 1150 { 1151 type = SensorType::iout_peak; 1152 } 1153 else if (value == "iout_valley") 1154 { 1155 type = SensorType::iout_valley; 1156 } 1157 else if (value == "pout") 1158 { 1159 type = SensorType::pout; 1160 } 1161 else if (value == "temperature") 1162 { 1163 type = SensorType::temperature; 1164 } 1165 else if (value == "temperature_peak") 1166 { 1167 type = SensorType::temperature_peak; 1168 } 1169 else if (value == "vout") 1170 { 1171 type = SensorType::vout; 1172 } 1173 else if (value == "vout_peak") 1174 { 1175 type = SensorType::vout_peak; 1176 } 1177 else if (value == "vout_valley") 1178 { 1179 type = SensorType::vout_valley; 1180 } 1181 else 1182 { 1183 throw std::invalid_argument{"Element is not a sensor type"}; 1184 } 1185 1186 return type; 1187 } 1188 1189 std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element) 1190 { 1191 // String deviceID 1192 std::string deviceID = parseString(element); 1193 1194 return std::make_unique<SetDeviceAction>(deviceID); 1195 } 1196 1197 pmbus_utils::VoutDataFormat parseVoutDataFormat(const json& element) 1198 { 1199 if (!element.is_string()) 1200 { 1201 throw std::invalid_argument{"Element is not a string"}; 1202 } 1203 std::string value = element.get<std::string>(); 1204 pmbus_utils::VoutDataFormat format{}; 1205 1206 if (value == "linear") 1207 { 1208 format = pmbus_utils::VoutDataFormat::linear; 1209 } 1210 else if (value == "vid") 1211 { 1212 format = pmbus_utils::VoutDataFormat::vid; 1213 } 1214 else if (value == "direct") 1215 { 1216 format = pmbus_utils::VoutDataFormat::direct; 1217 } 1218 else if (value == "ieee") 1219 { 1220 format = pmbus_utils::VoutDataFormat::ieee; 1221 } 1222 else 1223 { 1224 throw std::invalid_argument{"Element is not a vout data format"}; 1225 } 1226 1227 return format; 1228 } 1229 1230 } // namespace internal 1231 1232 } // namespace phosphor::power::regulators::config_file_parser 1233