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 // Verify no invalid properties exist 590 verifyPropertyCount(element, propertyCount); 591 592 // Create I2CInterface object; retry failed I2C operations a max of 3 times. 593 int maxRetries{3}; 594 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED, 595 maxRetries); 596 } 597 598 std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element) 599 { 600 verifyIsObject(element); 601 unsigned int propertyCount{0}; 602 603 // Required register property 604 const json& regElement = getRequiredProperty(element, "register"); 605 uint8_t reg = parseHexByte(regElement); 606 ++propertyCount; 607 608 // Required position property 609 const json& positionElement = getRequiredProperty(element, "position"); 610 uint8_t position = parseBitPosition(positionElement); 611 ++propertyCount; 612 613 // Required value property 614 const json& valueElement = getRequiredProperty(element, "value"); 615 uint8_t value = parseBitValue(valueElement); 616 ++propertyCount; 617 618 // Verify no invalid properties exist 619 verifyPropertyCount(element, propertyCount); 620 621 return std::make_unique<I2CWriteBitAction>(reg, position, value); 622 } 623 624 std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element) 625 { 626 verifyIsObject(element); 627 unsigned int propertyCount{0}; 628 629 // Required register property 630 const json& regElement = getRequiredProperty(element, "register"); 631 uint8_t reg = parseHexByte(regElement); 632 ++propertyCount; 633 634 // Required value property 635 const json& valueElement = getRequiredProperty(element, "value"); 636 uint8_t value = parseHexByte(valueElement); 637 ++propertyCount; 638 639 // Optional mask property 640 uint8_t mask = 0xff; 641 auto maskIt = element.find("mask"); 642 if (maskIt != element.end()) 643 { 644 mask = parseHexByte(*maskIt); 645 ++propertyCount; 646 } 647 648 // Verify no invalid properties exist 649 verifyPropertyCount(element, propertyCount); 650 651 return std::make_unique<I2CWriteByteAction>(reg, value, mask); 652 } 653 654 std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element) 655 { 656 verifyIsObject(element); 657 unsigned int propertyCount{0}; 658 659 // Required register property 660 const json& regElement = getRequiredProperty(element, "register"); 661 uint8_t reg = parseHexByte(regElement); 662 ++propertyCount; 663 664 // Required values property 665 const json& valueElement = getRequiredProperty(element, "values"); 666 std::vector<uint8_t> values = parseHexByteArray(valueElement); 667 ++propertyCount; 668 669 // Optional masks property 670 std::vector<uint8_t> masks{}; 671 auto masksIt = element.find("masks"); 672 if (masksIt != element.end()) 673 { 674 masks = parseHexByteArray(*masksIt); 675 ++propertyCount; 676 } 677 678 // Verify masks array (if specified) was same size as values array 679 if ((!masks.empty()) && (masks.size() != values.size())) 680 { 681 throw std::invalid_argument{"Invalid number of elements in masks"}; 682 } 683 684 // Verify no invalid properties exist 685 verifyPropertyCount(element, propertyCount); 686 687 if (masks.empty()) 688 { 689 return std::make_unique<I2CWriteBytesAction>(reg, values); 690 } 691 return std::make_unique<I2CWriteBytesAction>(reg, values, masks); 692 } 693 694 std::unique_ptr<IfAction> parseIf(const json& element) 695 { 696 verifyIsObject(element); 697 unsigned int propertyCount{0}; 698 699 // Required condition property 700 const json& conditionElement = getRequiredProperty(element, "condition"); 701 std::unique_ptr<Action> conditionAction = parseAction(conditionElement); 702 ++propertyCount; 703 704 // Required then property 705 const json& thenElement = getRequiredProperty(element, "then"); 706 std::vector<std::unique_ptr<Action>> thenActions = 707 parseActionArray(thenElement); 708 ++propertyCount; 709 710 // Optional else property 711 std::vector<std::unique_ptr<Action>> elseActions{}; 712 auto elseIt = element.find("else"); 713 if (elseIt != element.end()) 714 { 715 elseActions = parseActionArray(*elseIt); 716 ++propertyCount; 717 } 718 719 // Verify no invalid properties exist 720 verifyPropertyCount(element, propertyCount); 721 722 return std::make_unique<IfAction>(std::move(conditionAction), 723 std::move(thenActions), 724 std::move(elseActions)); 725 } 726 727 std::string parseInventoryPath(const json& element) 728 { 729 std::string inventoryPath = parseString(element); 730 std::string absPath = "/xyz/openbmc_project/inventory"; 731 if (inventoryPath.front() != '/') 732 { 733 absPath += '/'; 734 } 735 absPath += inventoryPath; 736 return absPath; 737 } 738 739 std::unique_ptr<LogPhaseFaultAction> parseLogPhaseFault(const json& element) 740 { 741 verifyIsObject(element); 742 unsigned int propertyCount{0}; 743 744 // Required type property 745 const json& typeElement = getRequiredProperty(element, "type"); 746 PhaseFaultType type = parsePhaseFaultType(typeElement); 747 ++propertyCount; 748 749 // Verify no invalid properties exist 750 verifyPropertyCount(element, propertyCount); 751 752 return std::make_unique<LogPhaseFaultAction>(type); 753 } 754 755 std::unique_ptr<NotAction> parseNot(const json& element) 756 { 757 // Required action to execute 758 std::unique_ptr<Action> action = parseAction(element); 759 760 return std::make_unique<NotAction>(std::move(action)); 761 } 762 763 std::unique_ptr<OrAction> parseOr(const json& element) 764 { 765 verifyIsArray(element); 766 767 // Verify if array size less than 2 768 if (element.size() < 2) 769 { 770 throw std::invalid_argument{"Array must contain two or more actions"}; 771 } 772 // Array of two or more actions 773 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element); 774 775 return std::make_unique<OrAction>(std::move(actions)); 776 } 777 778 std::unique_ptr<PhaseFaultDetection> 779 parsePhaseFaultDetection(const json& element) 780 { 781 verifyIsObject(element); 782 unsigned int propertyCount{0}; 783 784 // Optional comments property; value not stored 785 if (element.contains("comments")) 786 { 787 ++propertyCount; 788 } 789 790 // Optional device_id property 791 std::string deviceID{}; 792 auto deviceIDIt = element.find("device_id"); 793 if (deviceIDIt != element.end()) 794 { 795 deviceID = parseString(*deviceIDIt); 796 ++propertyCount; 797 } 798 799 // Required rule_id or actions property 800 std::vector<std::unique_ptr<Action>> actions{}; 801 actions = parseRuleIDOrActionsProperty(element); 802 ++propertyCount; 803 804 // Verify no invalid properties exist 805 verifyPropertyCount(element, propertyCount); 806 807 return std::make_unique<PhaseFaultDetection>(std::move(actions), deviceID); 808 } 809 810 PhaseFaultType parsePhaseFaultType(const json& element) 811 { 812 std::string value = parseString(element); 813 PhaseFaultType type{}; 814 815 if (value == "n") 816 { 817 type = PhaseFaultType::n; 818 } 819 else if (value == "n+1") 820 { 821 type = PhaseFaultType::n_plus_1; 822 } 823 else 824 { 825 throw std::invalid_argument{"Element is not a phase fault type"}; 826 } 827 828 return type; 829 } 830 831 std::unique_ptr<PMBusReadSensorAction> parsePMBusReadSensor(const json& element) 832 { 833 verifyIsObject(element); 834 unsigned int propertyCount{0}; 835 836 // Required type property 837 const json& typeElement = getRequiredProperty(element, "type"); 838 SensorType type = parseSensorType(typeElement); 839 ++propertyCount; 840 841 // Required command property 842 const json& commandElement = getRequiredProperty(element, "command"); 843 uint8_t command = parseHexByte(commandElement); 844 ++propertyCount; 845 846 // Required format property 847 const json& formatElement = getRequiredProperty(element, "format"); 848 pmbus_utils::SensorDataFormat format = parseSensorDataFormat(formatElement); 849 ++propertyCount; 850 851 // Optional exponent property 852 std::optional<int8_t> exponent{}; 853 auto exponentIt = element.find("exponent"); 854 if (exponentIt != element.end()) 855 { 856 exponent = parseInt8(*exponentIt); 857 ++propertyCount; 858 } 859 860 // Verify no invalid properties exist 861 verifyPropertyCount(element, propertyCount); 862 863 return std::make_unique<PMBusReadSensorAction>(type, command, format, 864 exponent); 865 } 866 867 std::unique_ptr<PMBusWriteVoutCommandAction> 868 parsePMBusWriteVoutCommand(const json& element) 869 { 870 verifyIsObject(element); 871 unsigned int propertyCount{0}; 872 873 // Optional volts property 874 std::optional<double> volts{}; 875 auto voltsIt = element.find("volts"); 876 if (voltsIt != element.end()) 877 { 878 volts = parseDouble(*voltsIt); 879 ++propertyCount; 880 } 881 882 // Required format property 883 const json& formatElement = getRequiredProperty(element, "format"); 884 std::string formatString = parseString(formatElement); 885 if (formatString != "linear") 886 { 887 throw std::invalid_argument{"Invalid format value: " + formatString}; 888 } 889 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear; 890 ++propertyCount; 891 892 // Optional exponent property 893 std::optional<int8_t> exponent{}; 894 auto exponentIt = element.find("exponent"); 895 if (exponentIt != element.end()) 896 { 897 exponent = parseInt8(*exponentIt); 898 ++propertyCount; 899 } 900 901 // Optional is_verified property 902 bool isVerified = false; 903 auto isVerifiedIt = element.find("is_verified"); 904 if (isVerifiedIt != element.end()) 905 { 906 isVerified = parseBoolean(*isVerifiedIt); 907 ++propertyCount; 908 } 909 910 // Verify no invalid properties exist 911 verifyPropertyCount(element, propertyCount); 912 913 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format, 914 exponent, isVerified); 915 } 916 917 std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element) 918 { 919 verifyIsObject(element); 920 unsigned int propertyCount{0}; 921 922 // Optional comments property; value not stored 923 if (element.contains("comments")) 924 { 925 ++propertyCount; 926 } 927 928 // Required rule_id or actions property 929 std::vector<std::unique_ptr<Action>> actions{}; 930 actions = parseRuleIDOrActionsProperty(element); 931 ++propertyCount; 932 933 // Verify no invalid properties exist 934 verifyPropertyCount(element, propertyCount); 935 936 return std::make_unique<PresenceDetection>(std::move(actions)); 937 } 938 939 std::unique_ptr<Rail> parseRail(const json& element) 940 { 941 verifyIsObject(element); 942 unsigned int propertyCount{0}; 943 944 // Optional comments property; value not stored 945 if (element.contains("comments")) 946 { 947 ++propertyCount; 948 } 949 950 // Required id property 951 const json& idElement = getRequiredProperty(element, "id"); 952 std::string id = parseString(idElement); 953 ++propertyCount; 954 955 // Optional configuration property 956 std::unique_ptr<Configuration> configuration{}; 957 auto configurationIt = element.find("configuration"); 958 if (configurationIt != element.end()) 959 { 960 configuration = parseConfiguration(*configurationIt); 961 ++propertyCount; 962 } 963 964 // Optional sensor_monitoring property 965 std::unique_ptr<SensorMonitoring> sensorMonitoring{}; 966 auto sensorMonitoringIt = element.find("sensor_monitoring"); 967 if (sensorMonitoringIt != element.end()) 968 { 969 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt); 970 ++propertyCount; 971 } 972 973 // Verify no invalid properties exist 974 verifyPropertyCount(element, propertyCount); 975 976 return std::make_unique<Rail>(id, std::move(configuration), 977 std::move(sensorMonitoring)); 978 } 979 980 std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element) 981 { 982 verifyIsArray(element); 983 std::vector<std::unique_ptr<Rail>> rails; 984 for (auto& railElement : element) 985 { 986 rails.emplace_back(parseRail(railElement)); 987 } 988 return rails; 989 } 990 991 std::tuple<std::vector<std::unique_ptr<Rule>>, 992 std::vector<std::unique_ptr<Chassis>>> 993 parseRoot(const json& element) 994 { 995 verifyIsObject(element); 996 unsigned int propertyCount{0}; 997 998 // Optional comments property; value not stored 999 if (element.contains("comments")) 1000 { 1001 ++propertyCount; 1002 } 1003 1004 // Optional rules property 1005 std::vector<std::unique_ptr<Rule>> rules{}; 1006 auto rulesIt = element.find("rules"); 1007 if (rulesIt != element.end()) 1008 { 1009 rules = parseRuleArray(*rulesIt); 1010 ++propertyCount; 1011 } 1012 1013 // Required chassis property 1014 const json& chassisElement = getRequiredProperty(element, "chassis"); 1015 std::vector<std::unique_ptr<Chassis>> chassis = 1016 parseChassisArray(chassisElement); 1017 ++propertyCount; 1018 1019 // Verify no invalid properties exist 1020 verifyPropertyCount(element, propertyCount); 1021 1022 return std::make_tuple(std::move(rules), std::move(chassis)); 1023 } 1024 1025 std::unique_ptr<Rule> parseRule(const json& element) 1026 { 1027 verifyIsObject(element); 1028 unsigned int propertyCount{0}; 1029 1030 // Optional comments property; value not stored 1031 if (element.contains("comments")) 1032 { 1033 ++propertyCount; 1034 } 1035 1036 // Required id property 1037 const json& idElement = getRequiredProperty(element, "id"); 1038 std::string id = parseString(idElement); 1039 ++propertyCount; 1040 1041 // Required actions property 1042 const json& actionsElement = getRequiredProperty(element, "actions"); 1043 std::vector<std::unique_ptr<Action>> actions = 1044 parseActionArray(actionsElement); 1045 ++propertyCount; 1046 1047 // Verify no invalid properties exist 1048 verifyPropertyCount(element, propertyCount); 1049 1050 return std::make_unique<Rule>(id, std::move(actions)); 1051 } 1052 1053 std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element) 1054 { 1055 verifyIsArray(element); 1056 std::vector<std::unique_ptr<Rule>> rules; 1057 for (auto& ruleElement : element) 1058 { 1059 rules.emplace_back(parseRule(ruleElement)); 1060 } 1061 return rules; 1062 } 1063 1064 std::vector<std::unique_ptr<Action>> 1065 parseRuleIDOrActionsProperty(const json& element) 1066 { 1067 verifyIsObject(element); 1068 // Required rule_id or actions property 1069 std::vector<std::unique_ptr<Action>> actions{}; 1070 auto ruleIDIt = element.find("rule_id"); 1071 auto actionsIt = element.find("actions"); 1072 if ((actionsIt == element.end()) && (ruleIDIt != element.end())) 1073 { 1074 std::string ruleID = parseString(*ruleIDIt); 1075 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID)); 1076 } 1077 else if ((actionsIt != element.end()) && (ruleIDIt == element.end())) 1078 { 1079 actions = parseActionArray(*actionsIt); 1080 } 1081 else 1082 { 1083 throw std::invalid_argument{"Invalid property combination: Must " 1084 "contain either rule_id or actions"}; 1085 } 1086 1087 return actions; 1088 } 1089 1090 std::unique_ptr<RunRuleAction> parseRunRule(const json& element) 1091 { 1092 // String ruleID 1093 std::string ruleID = parseString(element); 1094 1095 return std::make_unique<RunRuleAction>(ruleID); 1096 } 1097 1098 pmbus_utils::SensorDataFormat parseSensorDataFormat(const json& element) 1099 { 1100 if (!element.is_string()) 1101 { 1102 throw std::invalid_argument{"Element is not a string"}; 1103 } 1104 std::string value = element.get<std::string>(); 1105 pmbus_utils::SensorDataFormat format{}; 1106 1107 if (value == "linear_11") 1108 { 1109 format = pmbus_utils::SensorDataFormat::linear_11; 1110 } 1111 else if (value == "linear_16") 1112 { 1113 format = pmbus_utils::SensorDataFormat::linear_16; 1114 } 1115 else 1116 { 1117 throw std::invalid_argument{"Element is not a sensor data format"}; 1118 } 1119 1120 return format; 1121 } 1122 1123 std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element) 1124 { 1125 verifyIsObject(element); 1126 unsigned int propertyCount{0}; 1127 1128 // Optional comments property; value not stored 1129 if (element.contains("comments")) 1130 { 1131 ++propertyCount; 1132 } 1133 1134 // Required rule_id or actions property 1135 std::vector<std::unique_ptr<Action>> actions{}; 1136 actions = parseRuleIDOrActionsProperty(element); 1137 ++propertyCount; 1138 1139 // Verify no invalid properties exist 1140 verifyPropertyCount(element, propertyCount); 1141 1142 return std::make_unique<SensorMonitoring>(std::move(actions)); 1143 } 1144 1145 SensorType parseSensorType(const json& element) 1146 { 1147 std::string value = parseString(element); 1148 SensorType type{}; 1149 1150 if (value == "iout") 1151 { 1152 type = SensorType::iout; 1153 } 1154 else if (value == "iout_peak") 1155 { 1156 type = SensorType::iout_peak; 1157 } 1158 else if (value == "iout_valley") 1159 { 1160 type = SensorType::iout_valley; 1161 } 1162 else if (value == "pout") 1163 { 1164 type = SensorType::pout; 1165 } 1166 else if (value == "temperature") 1167 { 1168 type = SensorType::temperature; 1169 } 1170 else if (value == "temperature_peak") 1171 { 1172 type = SensorType::temperature_peak; 1173 } 1174 else if (value == "vout") 1175 { 1176 type = SensorType::vout; 1177 } 1178 else if (value == "vout_peak") 1179 { 1180 type = SensorType::vout_peak; 1181 } 1182 else if (value == "vout_valley") 1183 { 1184 type = SensorType::vout_valley; 1185 } 1186 else 1187 { 1188 throw std::invalid_argument{"Element is not a sensor type"}; 1189 } 1190 1191 return type; 1192 } 1193 1194 std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element) 1195 { 1196 // String deviceID 1197 std::string deviceID = parseString(element); 1198 1199 return std::make_unique<SetDeviceAction>(deviceID); 1200 } 1201 1202 pmbus_utils::VoutDataFormat parseVoutDataFormat(const json& element) 1203 { 1204 if (!element.is_string()) 1205 { 1206 throw std::invalid_argument{"Element is not a string"}; 1207 } 1208 std::string value = element.get<std::string>(); 1209 pmbus_utils::VoutDataFormat format{}; 1210 1211 if (value == "linear") 1212 { 1213 format = pmbus_utils::VoutDataFormat::linear; 1214 } 1215 else if (value == "vid") 1216 { 1217 format = pmbus_utils::VoutDataFormat::vid; 1218 } 1219 else if (value == "direct") 1220 { 1221 format = pmbus_utils::VoutDataFormat::direct; 1222 } 1223 else if (value == "ieee") 1224 { 1225 format = pmbus_utils::VoutDataFormat::ieee; 1226 } 1227 else 1228 { 1229 throw std::invalid_argument{"Element is not a vout data format"}; 1230 } 1231 1232 return format; 1233 } 1234 1235 } // namespace internal 1236 1237 } // namespace phosphor::power::regulators::config_file_parser 1238