10e8c68abSShawn McCarney /**
20e8c68abSShawn McCarney * Copyright © 2020 IBM Corporation
30e8c68abSShawn McCarney *
40e8c68abSShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License");
50e8c68abSShawn McCarney * you may not use this file except in compliance with the License.
60e8c68abSShawn McCarney * You may obtain a copy of the License at
70e8c68abSShawn McCarney *
80e8c68abSShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0
90e8c68abSShawn McCarney *
100e8c68abSShawn McCarney * Unless required by applicable law or agreed to in writing, software
110e8c68abSShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS,
120e8c68abSShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130e8c68abSShawn McCarney * See the License for the specific language governing permissions and
140e8c68abSShawn McCarney * limitations under the License.
150e8c68abSShawn McCarney */
160e8c68abSShawn McCarney
170e8c68abSShawn McCarney #include "config_file_parser.hpp"
180e8c68abSShawn McCarney
190e8c68abSShawn McCarney #include "config_file_parser_error.hpp"
20f617f893SBob King #include "i2c_interface.hpp"
210e8c68abSShawn McCarney #include "pmbus_utils.hpp"
220e8c68abSShawn McCarney
230e8c68abSShawn McCarney #include <exception>
240e8c68abSShawn McCarney #include <fstream>
250e8c68abSShawn McCarney #include <optional>
260e8c68abSShawn McCarney #include <utility>
270e8c68abSShawn McCarney
280e8c68abSShawn McCarney using json = nlohmann::json;
290e8c68abSShawn McCarney
300e8c68abSShawn McCarney namespace phosphor::power::regulators::config_file_parser
310e8c68abSShawn McCarney {
320e8c68abSShawn McCarney
330e8c68abSShawn McCarney std::tuple<std::vector<std::unique_ptr<Rule>>,
340e8c68abSShawn McCarney std::vector<std::unique_ptr<Chassis>>>
parse(const std::filesystem::path & pathName)350e8c68abSShawn McCarney parse(const std::filesystem::path& pathName)
360e8c68abSShawn McCarney {
370e8c68abSShawn McCarney try
380e8c68abSShawn McCarney {
390e8c68abSShawn McCarney // Use standard JSON parser to create tree of JSON elements
400e8c68abSShawn McCarney std::ifstream file{pathName};
410e8c68abSShawn McCarney json rootElement = json::parse(file);
420e8c68abSShawn McCarney
430e8c68abSShawn McCarney // Parse tree of JSON elements and return corresponding C++ objects
440e8c68abSShawn McCarney return internal::parseRoot(rootElement);
450e8c68abSShawn McCarney }
460e8c68abSShawn McCarney catch (const std::exception& e)
470e8c68abSShawn McCarney {
480e8c68abSShawn McCarney throw ConfigFileParserError{pathName, e.what()};
490e8c68abSShawn McCarney }
500e8c68abSShawn McCarney }
510e8c68abSShawn McCarney
520e8c68abSShawn McCarney namespace internal
530e8c68abSShawn McCarney {
540e8c68abSShawn McCarney
parseAction(const json & element)550e8c68abSShawn McCarney std::unique_ptr<Action> parseAction(const json& element)
560e8c68abSShawn McCarney {
570e8c68abSShawn McCarney verifyIsObject(element);
580e8c68abSShawn McCarney unsigned int propertyCount{0};
590e8c68abSShawn McCarney
600e8c68abSShawn McCarney // Optional comments property; value not stored
610e8c68abSShawn McCarney if (element.contains("comments"))
620e8c68abSShawn McCarney {
630e8c68abSShawn McCarney ++propertyCount;
640e8c68abSShawn McCarney }
650e8c68abSShawn McCarney
660e8c68abSShawn McCarney // Required action type property; there must be exactly one specified
670e8c68abSShawn McCarney std::unique_ptr<Action> action{};
680e8c68abSShawn McCarney if (element.contains("and"))
690e8c68abSShawn McCarney {
703a787540SBob King action = parseAnd(element["and"]);
713a787540SBob King ++propertyCount;
720e8c68abSShawn McCarney }
730e8c68abSShawn McCarney else if (element.contains("compare_presence"))
740e8c68abSShawn McCarney {
75b267b7ebSBob King action = parseComparePresence(element["compare_presence"]);
76b267b7ebSBob King ++propertyCount;
770e8c68abSShawn McCarney }
780e8c68abSShawn McCarney else if (element.contains("compare_vpd"))
790e8c68abSShawn McCarney {
80f2134320SBob King action = parseCompareVPD(element["compare_vpd"]);
81f2134320SBob King ++propertyCount;
820e8c68abSShawn McCarney }
8391f87a56SShawn McCarney else if (element.contains("i2c_capture_bytes"))
8491f87a56SShawn McCarney {
8591f87a56SShawn McCarney action = parseI2CCaptureBytes(element["i2c_capture_bytes"]);
8691f87a56SShawn McCarney ++propertyCount;
8791f87a56SShawn McCarney }
880e8c68abSShawn McCarney else if (element.contains("i2c_compare_bit"))
890e8c68abSShawn McCarney {
90f09bfe07SBob King action = parseI2CCompareBit(element["i2c_compare_bit"]);
91f09bfe07SBob King ++propertyCount;
920e8c68abSShawn McCarney }
930e8c68abSShawn McCarney else if (element.contains("i2c_compare_byte"))
940e8c68abSShawn McCarney {
95f09bfe07SBob King action = parseI2CCompareByte(element["i2c_compare_byte"]);
96f09bfe07SBob King ++propertyCount;
970e8c68abSShawn McCarney }
980e8c68abSShawn McCarney else if (element.contains("i2c_compare_bytes"))
990e8c68abSShawn McCarney {
100f09bfe07SBob King action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
101f09bfe07SBob King ++propertyCount;
1020e8c68abSShawn McCarney }
1030e8c68abSShawn McCarney else if (element.contains("i2c_write_bit"))
1040e8c68abSShawn McCarney {
105f617f893SBob King action = parseI2CWriteBit(element["i2c_write_bit"]);
106f617f893SBob King ++propertyCount;
1070e8c68abSShawn McCarney }
1080e8c68abSShawn McCarney else if (element.contains("i2c_write_byte"))
1090e8c68abSShawn McCarney {
11087ff9d7dSBob King action = parseI2CWriteByte(element["i2c_write_byte"]);
11187ff9d7dSBob King ++propertyCount;
1120e8c68abSShawn McCarney }
1130e8c68abSShawn McCarney else if (element.contains("i2c_write_bytes"))
1140e8c68abSShawn McCarney {
115bafcb86cSBob King action = parseI2CWriteBytes(element["i2c_write_bytes"]);
116bafcb86cSBob King ++propertyCount;
1170e8c68abSShawn McCarney }
1180e8c68abSShawn McCarney else if (element.contains("if"))
1190e8c68abSShawn McCarney {
12093a89d72SBob King action = parseIf(element["if"]);
12193a89d72SBob King ++propertyCount;
1220e8c68abSShawn McCarney }
1231115785fSShawn McCarney else if (element.contains("log_phase_fault"))
1241115785fSShawn McCarney {
1251115785fSShawn McCarney action = parseLogPhaseFault(element["log_phase_fault"]);
1261115785fSShawn McCarney ++propertyCount;
1271115785fSShawn McCarney }
1280e8c68abSShawn McCarney else if (element.contains("not"))
1290e8c68abSShawn McCarney {
130f1b58dc4SBob King action = parseNot(element["not"]);
131f1b58dc4SBob King ++propertyCount;
1320e8c68abSShawn McCarney }
1330e8c68abSShawn McCarney else if (element.contains("or"))
1340e8c68abSShawn McCarney {
1350b51a9b2SBob King action = parseOr(element["or"]);
1360b51a9b2SBob King ++propertyCount;
1370e8c68abSShawn McCarney }
1380e8c68abSShawn McCarney else if (element.contains("pmbus_read_sensor"))
1390e8c68abSShawn McCarney {
14084614882SBob King action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
14184614882SBob King ++propertyCount;
1420e8c68abSShawn McCarney }
1430e8c68abSShawn McCarney else if (element.contains("pmbus_write_vout_command"))
1440e8c68abSShawn McCarney {
1450e8c68abSShawn McCarney action =
1460e8c68abSShawn McCarney parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
1470e8c68abSShawn McCarney ++propertyCount;
1480e8c68abSShawn McCarney }
1490e8c68abSShawn McCarney else if (element.contains("run_rule"))
1500e8c68abSShawn McCarney {
151315b0b62SBob King action = parseRunRule(element["run_rule"]);
152315b0b62SBob King ++propertyCount;
1530e8c68abSShawn McCarney }
1540e8c68abSShawn McCarney else if (element.contains("set_device"))
1550e8c68abSShawn McCarney {
15618a68505SBob King action = parseSetDevice(element["set_device"]);
15718a68505SBob King ++propertyCount;
1580e8c68abSShawn McCarney }
1590e8c68abSShawn McCarney else
1600e8c68abSShawn McCarney {
1610e8c68abSShawn McCarney throw std::invalid_argument{"Required action type property missing"};
1620e8c68abSShawn McCarney }
1630e8c68abSShawn McCarney
1640e8c68abSShawn McCarney // Verify no invalid properties exist
1650e8c68abSShawn McCarney verifyPropertyCount(element, propertyCount);
1660e8c68abSShawn McCarney
1670e8c68abSShawn McCarney return action;
1680e8c68abSShawn McCarney }
1690e8c68abSShawn McCarney
parseActionArray(const json & element)1700e8c68abSShawn McCarney std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
1710e8c68abSShawn McCarney {
1720e8c68abSShawn McCarney verifyIsArray(element);
1730e8c68abSShawn McCarney std::vector<std::unique_ptr<Action>> actions;
1740e8c68abSShawn McCarney for (auto& actionElement : element)
1750e8c68abSShawn McCarney {
1760e8c68abSShawn McCarney actions.emplace_back(parseAction(actionElement));
1770e8c68abSShawn McCarney }
1780e8c68abSShawn McCarney return actions;
1790e8c68abSShawn McCarney }
1800e8c68abSShawn McCarney
parseAnd(const json & element)1813a787540SBob King std::unique_ptr<AndAction> parseAnd(const json& element)
1823a787540SBob King {
1833a787540SBob King verifyIsArray(element);
1843a787540SBob King
1853a787540SBob King // Verify if array size less than 2
1863a787540SBob King if (element.size() < 2)
1873a787540SBob King {
1883a787540SBob King throw std::invalid_argument{"Array must contain two or more actions"};
1893a787540SBob King }
1903a787540SBob King // Array of two or more actions
1913a787540SBob King std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
1923a787540SBob King
1933a787540SBob King return std::make_unique<AndAction>(std::move(actions));
1943a787540SBob King }
1953a787540SBob King
parseChassis(const json & element)1960e70113dSBob King std::unique_ptr<Chassis> parseChassis(const json& element)
1970e70113dSBob King {
1980e70113dSBob King verifyIsObject(element);
1990e70113dSBob King unsigned int propertyCount{0};
2000e70113dSBob King
2010e70113dSBob King // Optional comments property; value not stored
2020e70113dSBob King if (element.contains("comments"))
2030e70113dSBob King {
2040e70113dSBob King ++propertyCount;
2050e70113dSBob King }
2060e70113dSBob King
2070e70113dSBob King // Required number property
2080e70113dSBob King const json& numberElement = getRequiredProperty(element, "number");
2090e70113dSBob King unsigned int number = parseUnsignedInteger(numberElement);
2100e70113dSBob King if (number < 1)
2110e70113dSBob King {
2120e70113dSBob King throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
2130e70113dSBob King }
2140e70113dSBob King ++propertyCount;
2150e70113dSBob King
2164c88a4c2SShawn McCarney // Required inventory_path property
217f5402197SPatrick Williams const json& inventoryPathElement =
218f5402197SPatrick Williams getRequiredProperty(element, "inventory_path");
2194c88a4c2SShawn McCarney std::string inventoryPath = parseInventoryPath(inventoryPathElement);
220cb3f6a63SShawn McCarney ++propertyCount;
221cb3f6a63SShawn McCarney
2220e70113dSBob King // Optional devices property
2230e70113dSBob King std::vector<std::unique_ptr<Device>> devices{};
2240e70113dSBob King auto devicesIt = element.find("devices");
2250e70113dSBob King if (devicesIt != element.end())
2260e70113dSBob King {
2270e70113dSBob King devices = parseDeviceArray(*devicesIt);
2280e70113dSBob King ++propertyCount;
2290e70113dSBob King }
2300e70113dSBob King
2310e70113dSBob King // Verify no invalid properties exist
2320e70113dSBob King verifyPropertyCount(element, propertyCount);
2330e70113dSBob King
234cb3f6a63SShawn McCarney return std::make_unique<Chassis>(number, inventoryPath, std::move(devices));
2350e70113dSBob King }
2360e70113dSBob King
parseChassisArray(const json & element)2370e8c68abSShawn McCarney std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
2380e8c68abSShawn McCarney {
2390e8c68abSShawn McCarney verifyIsArray(element);
2400e8c68abSShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis;
2410e70113dSBob King for (auto& chassisElement : element)
2420e70113dSBob King {
2430e70113dSBob King chassis.emplace_back(parseChassis(chassisElement));
2440e70113dSBob King }
2450e8c68abSShawn McCarney return chassis;
2460e8c68abSShawn McCarney }
2470e8c68abSShawn McCarney
parseComparePresence(const json & element)248b267b7ebSBob King std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element)
249b267b7ebSBob King {
250b267b7ebSBob King verifyIsObject(element);
251b267b7ebSBob King unsigned int propertyCount{0};
252b267b7ebSBob King
253b267b7ebSBob King // Required fru property
254b267b7ebSBob King const json& fruElement = getRequiredProperty(element, "fru");
255a76898f1SBob King std::string fru = parseInventoryPath(fruElement);
256b267b7ebSBob King ++propertyCount;
257b267b7ebSBob King
258b267b7ebSBob King // Required value property
259b267b7ebSBob King const json& valueElement = getRequiredProperty(element, "value");
260b267b7ebSBob King bool value = parseBoolean(valueElement);
261b267b7ebSBob King ++propertyCount;
262b267b7ebSBob King
263b267b7ebSBob King // Verify no invalid properties exist
264b267b7ebSBob King verifyPropertyCount(element, propertyCount);
265b267b7ebSBob King
266b267b7ebSBob King return std::make_unique<ComparePresenceAction>(fru, value);
267b267b7ebSBob King }
268b267b7ebSBob King
parseCompareVPD(const json & element)269f2134320SBob King std::unique_ptr<CompareVPDAction> parseCompareVPD(const json& element)
270f2134320SBob King {
271f2134320SBob King verifyIsObject(element);
272f2134320SBob King unsigned int propertyCount{0};
273f2134320SBob King
274f2134320SBob King // Required fru property
275f2134320SBob King const json& fruElement = getRequiredProperty(element, "fru");
276a76898f1SBob King std::string fru = parseInventoryPath(fruElement);
277f2134320SBob King ++propertyCount;
278f2134320SBob King
279f2134320SBob King // Required keyword property
280f2134320SBob King const json& keywordElement = getRequiredProperty(element, "keyword");
281f2134320SBob King std::string keyword = parseString(keywordElement);
282f2134320SBob King ++propertyCount;
283f2134320SBob King
284aacc2aafSMatt Spinler // Either value or byte_values required property
285aacc2aafSMatt Spinler auto valueIt = element.find("value");
286aacc2aafSMatt Spinler std::vector<uint8_t> value{};
287aacc2aafSMatt Spinler auto byteValuesIt = element.find("byte_values");
288aacc2aafSMatt Spinler if ((valueIt != element.end()) && (byteValuesIt == element.end()))
289aacc2aafSMatt Spinler {
290a2a830b1SShawn McCarney std::string stringValue = parseString(*valueIt, true);
291aacc2aafSMatt Spinler value.insert(value.begin(), stringValue.begin(), stringValue.end());
292f2134320SBob King ++propertyCount;
293aacc2aafSMatt Spinler }
294aacc2aafSMatt Spinler else if ((valueIt == element.end()) && (byteValuesIt != element.end()))
295aacc2aafSMatt Spinler {
296aacc2aafSMatt Spinler value = parseHexByteArray(*byteValuesIt);
297aacc2aafSMatt Spinler ++propertyCount;
298aacc2aafSMatt Spinler }
299aacc2aafSMatt Spinler else
300aacc2aafSMatt Spinler {
301aacc2aafSMatt Spinler throw std::invalid_argument{
302aacc2aafSMatt Spinler "Invalid property: Must contain either value or byte_values"};
303aacc2aafSMatt Spinler }
304f2134320SBob King
305f2134320SBob King // Verify no invalid properties exist
306f2134320SBob King verifyPropertyCount(element, propertyCount);
307f2134320SBob King
308f2134320SBob King return std::make_unique<CompareVPDAction>(fru, keyword, value);
309f2134320SBob King }
310f2134320SBob King
parseConfiguration(const json & element)31133e7eaa5SBob King std::unique_ptr<Configuration> parseConfiguration(const json& element)
31233e7eaa5SBob King {
31333e7eaa5SBob King verifyIsObject(element);
31433e7eaa5SBob King unsigned int propertyCount{0};
31533e7eaa5SBob King
31633e7eaa5SBob King // Optional comments property; value not stored
31733e7eaa5SBob King if (element.contains("comments"))
31833e7eaa5SBob King {
31933e7eaa5SBob King ++propertyCount;
32033e7eaa5SBob King }
32133e7eaa5SBob King
32233e7eaa5SBob King // Optional volts property
32333e7eaa5SBob King std::optional<double> volts{};
32433e7eaa5SBob King auto voltsIt = element.find("volts");
32533e7eaa5SBob King if (voltsIt != element.end())
32633e7eaa5SBob King {
32733e7eaa5SBob King volts = parseDouble(*voltsIt);
32833e7eaa5SBob King ++propertyCount;
32933e7eaa5SBob King }
33033e7eaa5SBob King
33133e7eaa5SBob King // Required rule_id or actions property
33233e7eaa5SBob King std::vector<std::unique_ptr<Action>> actions{};
33333e7eaa5SBob King actions = parseRuleIDOrActionsProperty(element);
33433e7eaa5SBob King ++propertyCount;
33533e7eaa5SBob King
33633e7eaa5SBob King // Verify no invalid properties exist
33733e7eaa5SBob King verifyPropertyCount(element, propertyCount);
33833e7eaa5SBob King
33933e7eaa5SBob King return std::make_unique<Configuration>(volts, std::move(actions));
34033e7eaa5SBob King }
34133e7eaa5SBob King
parseDevice(const json & element)3429c36c5fbSBob King std::unique_ptr<Device> parseDevice(const json& element)
3439c36c5fbSBob King {
3449c36c5fbSBob King verifyIsObject(element);
3459c36c5fbSBob King unsigned int propertyCount{0};
3469c36c5fbSBob King
3479c36c5fbSBob King // Optional comments property; value not stored
3489c36c5fbSBob King if (element.contains("comments"))
3499c36c5fbSBob King {
3509c36c5fbSBob King ++propertyCount;
3519c36c5fbSBob King }
3529c36c5fbSBob King
3539c36c5fbSBob King // Required id property
3549c36c5fbSBob King const json& idElement = getRequiredProperty(element, "id");
3559c36c5fbSBob King std::string id = parseString(idElement);
3569c36c5fbSBob King ++propertyCount;
3579c36c5fbSBob King
3589c36c5fbSBob King // Required is_regulator property
359f5402197SPatrick Williams const json& isRegulatorElement =
360f5402197SPatrick Williams getRequiredProperty(element, "is_regulator");
3619c36c5fbSBob King bool isRegulator = parseBoolean(isRegulatorElement);
3629c36c5fbSBob King ++propertyCount;
3639c36c5fbSBob King
3649c36c5fbSBob King // Required fru property
3659c36c5fbSBob King const json& fruElement = getRequiredProperty(element, "fru");
366a76898f1SBob King std::string fru = parseInventoryPath(fruElement);
3679c36c5fbSBob King ++propertyCount;
3689c36c5fbSBob King
3699c36c5fbSBob King // Required i2c_interface property
370f5402197SPatrick Williams const json& i2cInterfaceElement =
371f5402197SPatrick Williams getRequiredProperty(element, "i2c_interface");
3729c36c5fbSBob King std::unique_ptr<i2c::I2CInterface> i2cInterface =
3739c36c5fbSBob King parseI2CInterface(i2cInterfaceElement);
3749c36c5fbSBob King ++propertyCount;
3759c36c5fbSBob King
3769c36c5fbSBob King // Optional presence_detection property
3779c36c5fbSBob King std::unique_ptr<PresenceDetection> presenceDetection{};
3782aafb1c7SBob King auto presenceDetectionIt = element.find("presence_detection");
3792aafb1c7SBob King if (presenceDetectionIt != element.end())
3802aafb1c7SBob King {
3812aafb1c7SBob King presenceDetection = parsePresenceDetection(*presenceDetectionIt);
3822aafb1c7SBob King ++propertyCount;
3832aafb1c7SBob King }
3849c36c5fbSBob King
3859c36c5fbSBob King // Optional configuration property
3869c36c5fbSBob King std::unique_ptr<Configuration> configuration{};
38733e7eaa5SBob King auto configurationIt = element.find("configuration");
38833e7eaa5SBob King if (configurationIt != element.end())
38933e7eaa5SBob King {
39033e7eaa5SBob King configuration = parseConfiguration(*configurationIt);
39133e7eaa5SBob King ++propertyCount;
39233e7eaa5SBob King }
3939c36c5fbSBob King
39432252599SShawn McCarney // Optional phase_fault_detection property
39532252599SShawn McCarney std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
39632252599SShawn McCarney auto phaseFaultDetectionIt = element.find("phase_fault_detection");
39732252599SShawn McCarney if (phaseFaultDetectionIt != element.end())
39832252599SShawn McCarney {
39932252599SShawn McCarney if (!isRegulator)
40032252599SShawn McCarney {
40132252599SShawn McCarney throw std::invalid_argument{"Invalid phase_fault_detection "
40232252599SShawn McCarney "property when is_regulator is false"};
40332252599SShawn McCarney }
40432252599SShawn McCarney phaseFaultDetection = parsePhaseFaultDetection(*phaseFaultDetectionIt);
40532252599SShawn McCarney ++propertyCount;
40632252599SShawn McCarney }
40732252599SShawn McCarney
4089c36c5fbSBob King // Optional rails property
4099c36c5fbSBob King std::vector<std::unique_ptr<Rail>> rails{};
4109c36c5fbSBob King auto railsIt = element.find("rails");
4119c36c5fbSBob King if (railsIt != element.end())
4129c36c5fbSBob King {
4139c36c5fbSBob King if (!isRegulator)
4149c36c5fbSBob King {
4159c36c5fbSBob King throw std::invalid_argument{
4169c36c5fbSBob King "Invalid rails property when is_regulator is false"};
4179c36c5fbSBob King }
4189c36c5fbSBob King rails = parseRailArray(*railsIt);
4199c36c5fbSBob King ++propertyCount;
4209c36c5fbSBob King }
4219c36c5fbSBob King
4229c36c5fbSBob King // Verify no invalid properties exist
4239c36c5fbSBob King verifyPropertyCount(element, propertyCount);
4249c36c5fbSBob King
42532252599SShawn McCarney return std::make_unique<Device>(
42632252599SShawn McCarney id, isRegulator, fru, std::move(i2cInterface),
42732252599SShawn McCarney std::move(presenceDetection), std::move(configuration),
42832252599SShawn McCarney std::move(phaseFaultDetection), std::move(rails));
4299c36c5fbSBob King }
4309c36c5fbSBob King
parseDeviceArray(const json & element)4310e70113dSBob King std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
4320e70113dSBob King {
4330e70113dSBob King verifyIsArray(element);
4340e70113dSBob King std::vector<std::unique_ptr<Device>> devices;
4359c36c5fbSBob King for (auto& deviceElement : element)
4369c36c5fbSBob King {
4379c36c5fbSBob King devices.emplace_back(parseDevice(deviceElement));
4389c36c5fbSBob King }
4390e70113dSBob King return devices;
4400e70113dSBob King }
4410e70113dSBob King
parseHexByteArray(const json & element)442bafcb86cSBob King std::vector<uint8_t> parseHexByteArray(const json& element)
443bafcb86cSBob King {
444bafcb86cSBob King verifyIsArray(element);
445bafcb86cSBob King std::vector<uint8_t> values;
446bafcb86cSBob King for (auto& valueElement : element)
447bafcb86cSBob King {
448bafcb86cSBob King values.emplace_back(parseHexByte(valueElement));
449bafcb86cSBob King }
450bafcb86cSBob King return values;
451bafcb86cSBob King }
452bafcb86cSBob King
parseI2CCaptureBytes(const json & element)45391f87a56SShawn McCarney std::unique_ptr<I2CCaptureBytesAction> parseI2CCaptureBytes(const json& element)
45491f87a56SShawn McCarney {
45591f87a56SShawn McCarney verifyIsObject(element);
45691f87a56SShawn McCarney unsigned int propertyCount{0};
45791f87a56SShawn McCarney
45891f87a56SShawn McCarney // Required register property
45991f87a56SShawn McCarney const json& regElement = getRequiredProperty(element, "register");
46091f87a56SShawn McCarney uint8_t reg = parseHexByte(regElement);
46191f87a56SShawn McCarney ++propertyCount;
46291f87a56SShawn McCarney
46391f87a56SShawn McCarney // Required count property
46491f87a56SShawn McCarney const json& countElement = getRequiredProperty(element, "count");
46591f87a56SShawn McCarney uint8_t count = parseUint8(countElement);
46691f87a56SShawn McCarney if (count < 1)
46791f87a56SShawn McCarney {
46891f87a56SShawn McCarney throw std::invalid_argument{"Invalid byte count: Must be > 0"};
46991f87a56SShawn McCarney }
47091f87a56SShawn McCarney ++propertyCount;
47191f87a56SShawn McCarney
47291f87a56SShawn McCarney // Verify no invalid properties exist
47391f87a56SShawn McCarney verifyPropertyCount(element, propertyCount);
47491f87a56SShawn McCarney
47591f87a56SShawn McCarney return std::make_unique<I2CCaptureBytesAction>(reg, count);
47691f87a56SShawn McCarney }
47791f87a56SShawn McCarney
parseI2CCompareBit(const json & element)478f09bfe07SBob King std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
479f09bfe07SBob King {
480f09bfe07SBob King verifyIsObject(element);
481f09bfe07SBob King unsigned int propertyCount{0};
482f09bfe07SBob King
483f09bfe07SBob King // Required register property
484f09bfe07SBob King const json& regElement = getRequiredProperty(element, "register");
485f09bfe07SBob King uint8_t reg = parseHexByte(regElement);
486f09bfe07SBob King ++propertyCount;
487f09bfe07SBob King
488f09bfe07SBob King // Required position property
489f09bfe07SBob King const json& positionElement = getRequiredProperty(element, "position");
490f09bfe07SBob King uint8_t position = parseBitPosition(positionElement);
491f09bfe07SBob King ++propertyCount;
492f09bfe07SBob King
493f09bfe07SBob King // Required value property
494f09bfe07SBob King const json& valueElement = getRequiredProperty(element, "value");
495f09bfe07SBob King uint8_t value = parseBitValue(valueElement);
496f09bfe07SBob King ++propertyCount;
497f09bfe07SBob King
498f09bfe07SBob King // Verify no invalid properties exist
499f09bfe07SBob King verifyPropertyCount(element, propertyCount);
500f09bfe07SBob King
501f09bfe07SBob King return std::make_unique<I2CCompareBitAction>(reg, position, value);
502f09bfe07SBob King }
503f09bfe07SBob King
parseI2CCompareByte(const json & element)504f09bfe07SBob King std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
505f09bfe07SBob King {
506f09bfe07SBob King verifyIsObject(element);
507f09bfe07SBob King unsigned int propertyCount{0};
508f09bfe07SBob King
509f09bfe07SBob King // Required register property
510f09bfe07SBob King const json& regElement = getRequiredProperty(element, "register");
511f09bfe07SBob King uint8_t reg = parseHexByte(regElement);
512f09bfe07SBob King ++propertyCount;
513f09bfe07SBob King
514f09bfe07SBob King // Required value property
515f09bfe07SBob King const json& valueElement = getRequiredProperty(element, "value");
516f09bfe07SBob King uint8_t value = parseHexByte(valueElement);
517f09bfe07SBob King ++propertyCount;
518f09bfe07SBob King
519f09bfe07SBob King // Optional mask property
520f09bfe07SBob King uint8_t mask = 0xff;
521f09bfe07SBob King auto maskIt = element.find("mask");
522f09bfe07SBob King if (maskIt != element.end())
523f09bfe07SBob King {
524f09bfe07SBob King mask = parseHexByte(*maskIt);
525f09bfe07SBob King ++propertyCount;
526f09bfe07SBob King }
527f09bfe07SBob King
528f09bfe07SBob King // Verify no invalid properties exist
529f09bfe07SBob King verifyPropertyCount(element, propertyCount);
530f09bfe07SBob King
531f09bfe07SBob King return std::make_unique<I2CCompareByteAction>(reg, value, mask);
532f09bfe07SBob King }
533f09bfe07SBob King
parseI2CCompareBytes(const json & element)534f09bfe07SBob King std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
535f09bfe07SBob King {
536f09bfe07SBob King verifyIsObject(element);
537f09bfe07SBob King unsigned int propertyCount{0};
538f09bfe07SBob King
539f09bfe07SBob King // Required register property
540f09bfe07SBob King const json& regElement = getRequiredProperty(element, "register");
541f09bfe07SBob King uint8_t reg = parseHexByte(regElement);
542f09bfe07SBob King ++propertyCount;
543f09bfe07SBob King
544f09bfe07SBob King // Required values property
545f09bfe07SBob King const json& valueElement = getRequiredProperty(element, "values");
546f09bfe07SBob King std::vector<uint8_t> values = parseHexByteArray(valueElement);
547f09bfe07SBob King ++propertyCount;
548f09bfe07SBob King
549f09bfe07SBob King // Optional masks property
550f09bfe07SBob King std::vector<uint8_t> masks{};
551f09bfe07SBob King auto masksIt = element.find("masks");
552f09bfe07SBob King if (masksIt != element.end())
553f09bfe07SBob King {
554f09bfe07SBob King masks = parseHexByteArray(*masksIt);
555f09bfe07SBob King ++propertyCount;
556f09bfe07SBob King }
557f09bfe07SBob King
558f09bfe07SBob King // Verify masks array (if specified) was same size as values array
559f09bfe07SBob King if ((!masks.empty()) && (masks.size() != values.size()))
560f09bfe07SBob King {
561f09bfe07SBob King throw std::invalid_argument{"Invalid number of elements in masks"};
562f09bfe07SBob King }
563f09bfe07SBob King
564f09bfe07SBob King // Verify no invalid properties exist
565f09bfe07SBob King verifyPropertyCount(element, propertyCount);
566f09bfe07SBob King
567f09bfe07SBob King if (masks.empty())
568f09bfe07SBob King {
569f09bfe07SBob King return std::make_unique<I2CCompareBytesAction>(reg, values);
570f09bfe07SBob King }
571f09bfe07SBob King return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
572f09bfe07SBob King }
573f09bfe07SBob King
parseI2CInterface(const json & element)5749c36c5fbSBob King std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
5759c36c5fbSBob King {
5769c36c5fbSBob King verifyIsObject(element);
5779c36c5fbSBob King unsigned int propertyCount{0};
5789c36c5fbSBob King
5799c36c5fbSBob King // Required bus property
5809c36c5fbSBob King const json& busElement = getRequiredProperty(element, "bus");
5819c36c5fbSBob King uint8_t bus = parseUint8(busElement);
5829c36c5fbSBob King ++propertyCount;
5839c36c5fbSBob King
5849c36c5fbSBob King // Required address property
5859c36c5fbSBob King const json& addressElement = getRequiredProperty(element, "address");
5869c36c5fbSBob King uint8_t address = parseHexByte(addressElement);
5879c36c5fbSBob King ++propertyCount;
5889c36c5fbSBob King
5895d23d9d6SShawn McCarney // Verify no invalid properties exist
5909c36c5fbSBob King verifyPropertyCount(element, propertyCount);
5915d23d9d6SShawn McCarney
5925d23d9d6SShawn McCarney // Create I2CInterface object; retry failed I2C operations a max of 3 times.
5935d23d9d6SShawn McCarney int maxRetries{3};
5945d23d9d6SShawn McCarney return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED,
5955d23d9d6SShawn McCarney maxRetries);
5969c36c5fbSBob King }
5979c36c5fbSBob King
parseI2CWriteBit(const json & element)598f617f893SBob King std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
599f617f893SBob King {
600f617f893SBob King verifyIsObject(element);
601f617f893SBob King unsigned int propertyCount{0};
602f617f893SBob King
603f617f893SBob King // Required register property
604f617f893SBob King const json& regElement = getRequiredProperty(element, "register");
605bafcb86cSBob King uint8_t reg = parseHexByte(regElement);
606f617f893SBob King ++propertyCount;
607f617f893SBob King
608f617f893SBob King // Required position property
609f617f893SBob King const json& positionElement = getRequiredProperty(element, "position");
610f617f893SBob King uint8_t position = parseBitPosition(positionElement);
611f617f893SBob King ++propertyCount;
612f617f893SBob King
613f617f893SBob King // Required value property
614f617f893SBob King const json& valueElement = getRequiredProperty(element, "value");
615f617f893SBob King uint8_t value = parseBitValue(valueElement);
616f617f893SBob King ++propertyCount;
617f617f893SBob King
618f617f893SBob King // Verify no invalid properties exist
619f617f893SBob King verifyPropertyCount(element, propertyCount);
620f617f893SBob King
621f617f893SBob King return std::make_unique<I2CWriteBitAction>(reg, position, value);
622f617f893SBob King }
623f617f893SBob King
parseI2CWriteByte(const json & element)62487ff9d7dSBob King std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
62587ff9d7dSBob King {
62687ff9d7dSBob King verifyIsObject(element);
62787ff9d7dSBob King unsigned int propertyCount{0};
62887ff9d7dSBob King
62987ff9d7dSBob King // Required register property
63087ff9d7dSBob King const json& regElement = getRequiredProperty(element, "register");
631bafcb86cSBob King uint8_t reg = parseHexByte(regElement);
63287ff9d7dSBob King ++propertyCount;
63387ff9d7dSBob King
63487ff9d7dSBob King // Required value property
63587ff9d7dSBob King const json& valueElement = getRequiredProperty(element, "value");
636bafcb86cSBob King uint8_t value = parseHexByte(valueElement);
63787ff9d7dSBob King ++propertyCount;
63887ff9d7dSBob King
63987ff9d7dSBob King // Optional mask property
64087ff9d7dSBob King uint8_t mask = 0xff;
64187ff9d7dSBob King auto maskIt = element.find("mask");
64287ff9d7dSBob King if (maskIt != element.end())
64387ff9d7dSBob King {
644bafcb86cSBob King mask = parseHexByte(*maskIt);
64587ff9d7dSBob King ++propertyCount;
64687ff9d7dSBob King }
64787ff9d7dSBob King
64887ff9d7dSBob King // Verify no invalid properties exist
64987ff9d7dSBob King verifyPropertyCount(element, propertyCount);
65087ff9d7dSBob King
65187ff9d7dSBob King return std::make_unique<I2CWriteByteAction>(reg, value, mask);
65287ff9d7dSBob King }
65387ff9d7dSBob King
parseI2CWriteBytes(const json & element)654bafcb86cSBob King std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
655bafcb86cSBob King {
656bafcb86cSBob King verifyIsObject(element);
657bafcb86cSBob King unsigned int propertyCount{0};
658bafcb86cSBob King
659bafcb86cSBob King // Required register property
660bafcb86cSBob King const json& regElement = getRequiredProperty(element, "register");
661bafcb86cSBob King uint8_t reg = parseHexByte(regElement);
662bafcb86cSBob King ++propertyCount;
663bafcb86cSBob King
664bafcb86cSBob King // Required values property
665bafcb86cSBob King const json& valueElement = getRequiredProperty(element, "values");
666bafcb86cSBob King std::vector<uint8_t> values = parseHexByteArray(valueElement);
667bafcb86cSBob King ++propertyCount;
668bafcb86cSBob King
669bafcb86cSBob King // Optional masks property
670bafcb86cSBob King std::vector<uint8_t> masks{};
671bafcb86cSBob King auto masksIt = element.find("masks");
672bafcb86cSBob King if (masksIt != element.end())
673bafcb86cSBob King {
674bafcb86cSBob King masks = parseHexByteArray(*masksIt);
675bafcb86cSBob King ++propertyCount;
676bafcb86cSBob King }
677bafcb86cSBob King
678bafcb86cSBob King // Verify masks array (if specified) was same size as values array
679bafcb86cSBob King if ((!masks.empty()) && (masks.size() != values.size()))
680bafcb86cSBob King {
681bafcb86cSBob King throw std::invalid_argument{"Invalid number of elements in masks"};
682bafcb86cSBob King }
683bafcb86cSBob King
684bafcb86cSBob King // Verify no invalid properties exist
685bafcb86cSBob King verifyPropertyCount(element, propertyCount);
686bafcb86cSBob King
687bafcb86cSBob King if (masks.empty())
688bafcb86cSBob King {
689bafcb86cSBob King return std::make_unique<I2CWriteBytesAction>(reg, values);
690bafcb86cSBob King }
691bafcb86cSBob King return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
692bafcb86cSBob King }
693bafcb86cSBob King
parseIf(const json & element)69493a89d72SBob King std::unique_ptr<IfAction> parseIf(const json& element)
69593a89d72SBob King {
69693a89d72SBob King verifyIsObject(element);
69793a89d72SBob King unsigned int propertyCount{0};
69893a89d72SBob King
69993a89d72SBob King // Required condition property
70093a89d72SBob King const json& conditionElement = getRequiredProperty(element, "condition");
70193a89d72SBob King std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
70293a89d72SBob King ++propertyCount;
70393a89d72SBob King
70493a89d72SBob King // Required then property
70593a89d72SBob King const json& thenElement = getRequiredProperty(element, "then");
70693a89d72SBob King std::vector<std::unique_ptr<Action>> thenActions =
70793a89d72SBob King parseActionArray(thenElement);
70893a89d72SBob King ++propertyCount;
70993a89d72SBob King
71093a89d72SBob King // Optional else property
71193a89d72SBob King std::vector<std::unique_ptr<Action>> elseActions{};
71293a89d72SBob King auto elseIt = element.find("else");
71393a89d72SBob King if (elseIt != element.end())
71493a89d72SBob King {
71593a89d72SBob King elseActions = parseActionArray(*elseIt);
71693a89d72SBob King ++propertyCount;
71793a89d72SBob King }
71893a89d72SBob King
71993a89d72SBob King // Verify no invalid properties exist
72093a89d72SBob King verifyPropertyCount(element, propertyCount);
72193a89d72SBob King
72293a89d72SBob King return std::make_unique<IfAction>(std::move(conditionAction),
72393a89d72SBob King std::move(thenActions),
72493a89d72SBob King std::move(elseActions));
72593a89d72SBob King }
72693a89d72SBob King
parseInventoryPath(const json & element)727a76898f1SBob King std::string parseInventoryPath(const json& element)
728a76898f1SBob King {
729a76898f1SBob King std::string inventoryPath = parseString(element);
730a76898f1SBob King std::string absPath = "/xyz/openbmc_project/inventory";
731a76898f1SBob King if (inventoryPath.front() != '/')
732a76898f1SBob King {
733a76898f1SBob King absPath += '/';
734a76898f1SBob King }
735a76898f1SBob King absPath += inventoryPath;
736a76898f1SBob King return absPath;
737a76898f1SBob King }
738a76898f1SBob King
parseLogPhaseFault(const json & element)7391115785fSShawn McCarney std::unique_ptr<LogPhaseFaultAction> parseLogPhaseFault(const json& element)
7401115785fSShawn McCarney {
7411115785fSShawn McCarney verifyIsObject(element);
7421115785fSShawn McCarney unsigned int propertyCount{0};
7431115785fSShawn McCarney
7441115785fSShawn McCarney // Required type property
7451115785fSShawn McCarney const json& typeElement = getRequiredProperty(element, "type");
7461115785fSShawn McCarney PhaseFaultType type = parsePhaseFaultType(typeElement);
7471115785fSShawn McCarney ++propertyCount;
7481115785fSShawn McCarney
7491115785fSShawn McCarney // Verify no invalid properties exist
7501115785fSShawn McCarney verifyPropertyCount(element, propertyCount);
7511115785fSShawn McCarney
7521115785fSShawn McCarney return std::make_unique<LogPhaseFaultAction>(type);
7531115785fSShawn McCarney }
7541115785fSShawn McCarney
parseNot(const json & element)755f1b58dc4SBob King std::unique_ptr<NotAction> parseNot(const json& element)
756f1b58dc4SBob King {
757f1b58dc4SBob King // Required action to execute
758f1b58dc4SBob King std::unique_ptr<Action> action = parseAction(element);
759f1b58dc4SBob King
760f1b58dc4SBob King return std::make_unique<NotAction>(std::move(action));
761f1b58dc4SBob King }
762f1b58dc4SBob King
parseOr(const json & element)7630b51a9b2SBob King std::unique_ptr<OrAction> parseOr(const json& element)
7640b51a9b2SBob King {
7650b51a9b2SBob King verifyIsArray(element);
7660b51a9b2SBob King
7670b51a9b2SBob King // Verify if array size less than 2
7680b51a9b2SBob King if (element.size() < 2)
7690b51a9b2SBob King {
7700b51a9b2SBob King throw std::invalid_argument{"Array must contain two or more actions"};
7710b51a9b2SBob King }
7720b51a9b2SBob King // Array of two or more actions
7730b51a9b2SBob King std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
7740b51a9b2SBob King
7750b51a9b2SBob King return std::make_unique<OrAction>(std::move(actions));
7760b51a9b2SBob King }
7770b51a9b2SBob King
parsePhaseFaultDetection(const json & element)778*92261f88SPatrick Williams std::unique_ptr<PhaseFaultDetection> parsePhaseFaultDetection(
779*92261f88SPatrick Williams const json& element)
78039eb08a9SShawn McCarney {
78139eb08a9SShawn McCarney verifyIsObject(element);
78239eb08a9SShawn McCarney unsigned int propertyCount{0};
78339eb08a9SShawn McCarney
78439eb08a9SShawn McCarney // Optional comments property; value not stored
78539eb08a9SShawn McCarney if (element.contains("comments"))
78639eb08a9SShawn McCarney {
78739eb08a9SShawn McCarney ++propertyCount;
78839eb08a9SShawn McCarney }
78939eb08a9SShawn McCarney
79039eb08a9SShawn McCarney // Optional device_id property
79139eb08a9SShawn McCarney std::string deviceID{};
79239eb08a9SShawn McCarney auto deviceIDIt = element.find("device_id");
79339eb08a9SShawn McCarney if (deviceIDIt != element.end())
79439eb08a9SShawn McCarney {
79539eb08a9SShawn McCarney deviceID = parseString(*deviceIDIt);
79639eb08a9SShawn McCarney ++propertyCount;
79739eb08a9SShawn McCarney }
79839eb08a9SShawn McCarney
79939eb08a9SShawn McCarney // Required rule_id or actions property
80039eb08a9SShawn McCarney std::vector<std::unique_ptr<Action>> actions{};
80139eb08a9SShawn McCarney actions = parseRuleIDOrActionsProperty(element);
80239eb08a9SShawn McCarney ++propertyCount;
80339eb08a9SShawn McCarney
80439eb08a9SShawn McCarney // Verify no invalid properties exist
80539eb08a9SShawn McCarney verifyPropertyCount(element, propertyCount);
80639eb08a9SShawn McCarney
80739eb08a9SShawn McCarney return std::make_unique<PhaseFaultDetection>(std::move(actions), deviceID);
80839eb08a9SShawn McCarney }
80939eb08a9SShawn McCarney
parsePhaseFaultType(const json & element)810b70370b7SShawn McCarney PhaseFaultType parsePhaseFaultType(const json& element)
811b70370b7SShawn McCarney {
812b70370b7SShawn McCarney std::string value = parseString(element);
813b70370b7SShawn McCarney PhaseFaultType type{};
814b70370b7SShawn McCarney
815b70370b7SShawn McCarney if (value == "n")
816b70370b7SShawn McCarney {
817b70370b7SShawn McCarney type = PhaseFaultType::n;
818b70370b7SShawn McCarney }
819b70370b7SShawn McCarney else if (value == "n+1")
820b70370b7SShawn McCarney {
821b70370b7SShawn McCarney type = PhaseFaultType::n_plus_1;
822b70370b7SShawn McCarney }
823b70370b7SShawn McCarney else
824b70370b7SShawn McCarney {
825b70370b7SShawn McCarney throw std::invalid_argument{"Element is not a phase fault type"};
826b70370b7SShawn McCarney }
827b70370b7SShawn McCarney
828b70370b7SShawn McCarney return type;
829b70370b7SShawn McCarney }
830b70370b7SShawn McCarney
parsePMBusReadSensor(const json & element)83184614882SBob King std::unique_ptr<PMBusReadSensorAction> parsePMBusReadSensor(const json& element)
83284614882SBob King {
83384614882SBob King verifyIsObject(element);
83484614882SBob King unsigned int propertyCount{0};
83584614882SBob King
83684614882SBob King // Required type property
83784614882SBob King const json& typeElement = getRequiredProperty(element, "type");
8382f9e14f6SShawn McCarney SensorType type = parseSensorType(typeElement);
83984614882SBob King ++propertyCount;
84084614882SBob King
84184614882SBob King // Required command property
84284614882SBob King const json& commandElement = getRequiredProperty(element, "command");
84384614882SBob King uint8_t command = parseHexByte(commandElement);
84484614882SBob King ++propertyCount;
84584614882SBob King
84684614882SBob King // Required format property
84784614882SBob King const json& formatElement = getRequiredProperty(element, "format");
84884614882SBob King pmbus_utils::SensorDataFormat format = parseSensorDataFormat(formatElement);
84984614882SBob King ++propertyCount;
85084614882SBob King
85184614882SBob King // Optional exponent property
85284614882SBob King std::optional<int8_t> exponent{};
85384614882SBob King auto exponentIt = element.find("exponent");
85484614882SBob King if (exponentIt != element.end())
85584614882SBob King {
85684614882SBob King exponent = parseInt8(*exponentIt);
85784614882SBob King ++propertyCount;
85884614882SBob King }
85984614882SBob King
86084614882SBob King // Verify no invalid properties exist
86184614882SBob King verifyPropertyCount(element, propertyCount);
86284614882SBob King
86384614882SBob King return std::make_unique<PMBusReadSensorAction>(type, command, format,
86484614882SBob King exponent);
86584614882SBob King }
86684614882SBob King
parsePMBusWriteVoutCommand(const json & element)867*92261f88SPatrick Williams std::unique_ptr<PMBusWriteVoutCommandAction> parsePMBusWriteVoutCommand(
868*92261f88SPatrick Williams const json& element)
8690e8c68abSShawn McCarney {
8700e8c68abSShawn McCarney verifyIsObject(element);
8710e8c68abSShawn McCarney unsigned int propertyCount{0};
8720e8c68abSShawn McCarney
8730e8c68abSShawn McCarney // Optional volts property
8740e8c68abSShawn McCarney std::optional<double> volts{};
8750e8c68abSShawn McCarney auto voltsIt = element.find("volts");
8760e8c68abSShawn McCarney if (voltsIt != element.end())
8770e8c68abSShawn McCarney {
8780e8c68abSShawn McCarney volts = parseDouble(*voltsIt);
8790e8c68abSShawn McCarney ++propertyCount;
8800e8c68abSShawn McCarney }
8810e8c68abSShawn McCarney
8820e8c68abSShawn McCarney // Required format property
8830e8c68abSShawn McCarney const json& formatElement = getRequiredProperty(element, "format");
8840e8c68abSShawn McCarney std::string formatString = parseString(formatElement);
8850e8c68abSShawn McCarney if (formatString != "linear")
8860e8c68abSShawn McCarney {
8870e8c68abSShawn McCarney throw std::invalid_argument{"Invalid format value: " + formatString};
8880e8c68abSShawn McCarney }
8890e8c68abSShawn McCarney pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
8900e8c68abSShawn McCarney ++propertyCount;
8910e8c68abSShawn McCarney
8920e8c68abSShawn McCarney // Optional exponent property
8930e8c68abSShawn McCarney std::optional<int8_t> exponent{};
8940e8c68abSShawn McCarney auto exponentIt = element.find("exponent");
8950e8c68abSShawn McCarney if (exponentIt != element.end())
8960e8c68abSShawn McCarney {
8970e8c68abSShawn McCarney exponent = parseInt8(*exponentIt);
8980e8c68abSShawn McCarney ++propertyCount;
8990e8c68abSShawn McCarney }
9000e8c68abSShawn McCarney
9010e8c68abSShawn McCarney // Optional is_verified property
9020e8c68abSShawn McCarney bool isVerified = false;
9030e8c68abSShawn McCarney auto isVerifiedIt = element.find("is_verified");
9040e8c68abSShawn McCarney if (isVerifiedIt != element.end())
9050e8c68abSShawn McCarney {
9060e8c68abSShawn McCarney isVerified = parseBoolean(*isVerifiedIt);
9070e8c68abSShawn McCarney ++propertyCount;
9080e8c68abSShawn McCarney }
9090e8c68abSShawn McCarney
9100e8c68abSShawn McCarney // Verify no invalid properties exist
9110e8c68abSShawn McCarney verifyPropertyCount(element, propertyCount);
9120e8c68abSShawn McCarney
9130e8c68abSShawn McCarney return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
9140e8c68abSShawn McCarney exponent, isVerified);
9150e8c68abSShawn McCarney }
9160e8c68abSShawn McCarney
parsePresenceDetection(const json & element)9172aafb1c7SBob King std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
9182aafb1c7SBob King {
9192aafb1c7SBob King verifyIsObject(element);
9202aafb1c7SBob King unsigned int propertyCount{0};
9212aafb1c7SBob King
9222aafb1c7SBob King // Optional comments property; value not stored
9232aafb1c7SBob King if (element.contains("comments"))
9242aafb1c7SBob King {
9252aafb1c7SBob King ++propertyCount;
9262aafb1c7SBob King }
9272aafb1c7SBob King
9282aafb1c7SBob King // Required rule_id or actions property
9292aafb1c7SBob King std::vector<std::unique_ptr<Action>> actions{};
9302aafb1c7SBob King actions = parseRuleIDOrActionsProperty(element);
9312aafb1c7SBob King ++propertyCount;
9322aafb1c7SBob King
9332aafb1c7SBob King // Verify no invalid properties exist
9342aafb1c7SBob King verifyPropertyCount(element, propertyCount);
9352aafb1c7SBob King
9362aafb1c7SBob King return std::make_unique<PresenceDetection>(std::move(actions));
9372aafb1c7SBob King }
9382aafb1c7SBob King
parseRail(const json & element)939a2f2a0dcSBob King std::unique_ptr<Rail> parseRail(const json& element)
940a2f2a0dcSBob King {
941a2f2a0dcSBob King verifyIsObject(element);
942a2f2a0dcSBob King unsigned int propertyCount{0};
943a2f2a0dcSBob King
944a2f2a0dcSBob King // Optional comments property; value not stored
945a2f2a0dcSBob King if (element.contains("comments"))
946a2f2a0dcSBob King {
947a2f2a0dcSBob King ++propertyCount;
948a2f2a0dcSBob King }
949a2f2a0dcSBob King
950a2f2a0dcSBob King // Required id property
951a2f2a0dcSBob King const json& idElement = getRequiredProperty(element, "id");
952a2f2a0dcSBob King std::string id = parseString(idElement);
953a2f2a0dcSBob King ++propertyCount;
954a2f2a0dcSBob King
955a2f2a0dcSBob King // Optional configuration property
956a2f2a0dcSBob King std::unique_ptr<Configuration> configuration{};
957a2f2a0dcSBob King auto configurationIt = element.find("configuration");
958a2f2a0dcSBob King if (configurationIt != element.end())
959a2f2a0dcSBob King {
960a2f2a0dcSBob King configuration = parseConfiguration(*configurationIt);
961a2f2a0dcSBob King ++propertyCount;
962a2f2a0dcSBob King }
963a2f2a0dcSBob King
964a2f2a0dcSBob King // Optional sensor_monitoring property
965a2f2a0dcSBob King std::unique_ptr<SensorMonitoring> sensorMonitoring{};
966a2f2a0dcSBob King auto sensorMonitoringIt = element.find("sensor_monitoring");
967a2f2a0dcSBob King if (sensorMonitoringIt != element.end())
968a2f2a0dcSBob King {
969a2f2a0dcSBob King sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
970a2f2a0dcSBob King ++propertyCount;
971a2f2a0dcSBob King }
972a2f2a0dcSBob King
973a2f2a0dcSBob King // Verify no invalid properties exist
974a2f2a0dcSBob King verifyPropertyCount(element, propertyCount);
975a2f2a0dcSBob King
976a2f2a0dcSBob King return std::make_unique<Rail>(id, std::move(configuration),
977a2f2a0dcSBob King std::move(sensorMonitoring));
978a2f2a0dcSBob King }
979a2f2a0dcSBob King
parseRailArray(const json & element)9809c36c5fbSBob King std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
9819c36c5fbSBob King {
9829c36c5fbSBob King verifyIsArray(element);
9839c36c5fbSBob King std::vector<std::unique_ptr<Rail>> rails;
984a2f2a0dcSBob King for (auto& railElement : element)
985a2f2a0dcSBob King {
986a2f2a0dcSBob King rails.emplace_back(parseRail(railElement));
987a2f2a0dcSBob King }
9889c36c5fbSBob King return rails;
9899c36c5fbSBob King }
9909c36c5fbSBob King
9910e8c68abSShawn McCarney std::tuple<std::vector<std::unique_ptr<Rule>>,
9920e8c68abSShawn McCarney std::vector<std::unique_ptr<Chassis>>>
parseRoot(const json & element)9930e8c68abSShawn McCarney parseRoot(const json& element)
9940e8c68abSShawn McCarney {
9950e8c68abSShawn McCarney verifyIsObject(element);
9960e8c68abSShawn McCarney unsigned int propertyCount{0};
9970e8c68abSShawn McCarney
9980e8c68abSShawn McCarney // Optional comments property; value not stored
9990e8c68abSShawn McCarney if (element.contains("comments"))
10000e8c68abSShawn McCarney {
10010e8c68abSShawn McCarney ++propertyCount;
10020e8c68abSShawn McCarney }
10030e8c68abSShawn McCarney
10040e8c68abSShawn McCarney // Optional rules property
10050e8c68abSShawn McCarney std::vector<std::unique_ptr<Rule>> rules{};
10060e8c68abSShawn McCarney auto rulesIt = element.find("rules");
10070e8c68abSShawn McCarney if (rulesIt != element.end())
10080e8c68abSShawn McCarney {
10090e8c68abSShawn McCarney rules = parseRuleArray(*rulesIt);
10100e8c68abSShawn McCarney ++propertyCount;
10110e8c68abSShawn McCarney }
10120e8c68abSShawn McCarney
10130e8c68abSShawn McCarney // Required chassis property
10140e8c68abSShawn McCarney const json& chassisElement = getRequiredProperty(element, "chassis");
10150e8c68abSShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis =
10160e8c68abSShawn McCarney parseChassisArray(chassisElement);
10170e8c68abSShawn McCarney ++propertyCount;
10180e8c68abSShawn McCarney
10190e8c68abSShawn McCarney // Verify no invalid properties exist
10200e8c68abSShawn McCarney verifyPropertyCount(element, propertyCount);
10210e8c68abSShawn McCarney
10220e8c68abSShawn McCarney return std::make_tuple(std::move(rules), std::move(chassis));
10230e8c68abSShawn McCarney }
10240e8c68abSShawn McCarney
parseRule(const json & element)10250e8c68abSShawn McCarney std::unique_ptr<Rule> parseRule(const json& element)
10260e8c68abSShawn McCarney {
10270e8c68abSShawn McCarney verifyIsObject(element);
10280e8c68abSShawn McCarney unsigned int propertyCount{0};
10290e8c68abSShawn McCarney
10300e8c68abSShawn McCarney // Optional comments property; value not stored
10310e8c68abSShawn McCarney if (element.contains("comments"))
10320e8c68abSShawn McCarney {
10330e8c68abSShawn McCarney ++propertyCount;
10340e8c68abSShawn McCarney }
10350e8c68abSShawn McCarney
10360e8c68abSShawn McCarney // Required id property
10370e8c68abSShawn McCarney const json& idElement = getRequiredProperty(element, "id");
10380e8c68abSShawn McCarney std::string id = parseString(idElement);
10390e8c68abSShawn McCarney ++propertyCount;
10400e8c68abSShawn McCarney
10410e8c68abSShawn McCarney // Required actions property
10420e8c68abSShawn McCarney const json& actionsElement = getRequiredProperty(element, "actions");
10430e8c68abSShawn McCarney std::vector<std::unique_ptr<Action>> actions =
10440e8c68abSShawn McCarney parseActionArray(actionsElement);
10450e8c68abSShawn McCarney ++propertyCount;
10460e8c68abSShawn McCarney
10470e8c68abSShawn McCarney // Verify no invalid properties exist
10480e8c68abSShawn McCarney verifyPropertyCount(element, propertyCount);
10490e8c68abSShawn McCarney
10500e8c68abSShawn McCarney return std::make_unique<Rule>(id, std::move(actions));
10510e8c68abSShawn McCarney }
10520e8c68abSShawn McCarney
parseRuleArray(const json & element)10530e8c68abSShawn McCarney std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
10540e8c68abSShawn McCarney {
10550e8c68abSShawn McCarney verifyIsArray(element);
10560e8c68abSShawn McCarney std::vector<std::unique_ptr<Rule>> rules;
10570e8c68abSShawn McCarney for (auto& ruleElement : element)
10580e8c68abSShawn McCarney {
10590e8c68abSShawn McCarney rules.emplace_back(parseRule(ruleElement));
10600e8c68abSShawn McCarney }
10610e8c68abSShawn McCarney return rules;
10620e8c68abSShawn McCarney }
10630e8c68abSShawn McCarney
parseRuleIDOrActionsProperty(const json & element)1064*92261f88SPatrick Williams std::vector<std::unique_ptr<Action>> parseRuleIDOrActionsProperty(
1065*92261f88SPatrick Williams const json& element)
106633e7eaa5SBob King {
106733e7eaa5SBob King verifyIsObject(element);
106833e7eaa5SBob King // Required rule_id or actions property
106933e7eaa5SBob King std::vector<std::unique_ptr<Action>> actions{};
107033e7eaa5SBob King auto ruleIDIt = element.find("rule_id");
107133e7eaa5SBob King auto actionsIt = element.find("actions");
107233e7eaa5SBob King if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
107333e7eaa5SBob King {
107433e7eaa5SBob King std::string ruleID = parseString(*ruleIDIt);
107533e7eaa5SBob King actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
107633e7eaa5SBob King }
107733e7eaa5SBob King else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
107833e7eaa5SBob King {
107933e7eaa5SBob King actions = parseActionArray(*actionsIt);
108033e7eaa5SBob King }
108133e7eaa5SBob King else
108233e7eaa5SBob King {
108333e7eaa5SBob King throw std::invalid_argument{"Invalid property combination: Must "
108433e7eaa5SBob King "contain either rule_id or actions"};
108533e7eaa5SBob King }
108633e7eaa5SBob King
108733e7eaa5SBob King return actions;
108833e7eaa5SBob King }
108933e7eaa5SBob King
parseRunRule(const json & element)1090315b0b62SBob King std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
1091315b0b62SBob King {
1092315b0b62SBob King // String ruleID
1093315b0b62SBob King std::string ruleID = parseString(element);
1094315b0b62SBob King
1095315b0b62SBob King return std::make_unique<RunRuleAction>(ruleID);
1096315b0b62SBob King }
1097315b0b62SBob King
parseSensorDataFormat(const json & element)109884614882SBob King pmbus_utils::SensorDataFormat parseSensorDataFormat(const json& element)
109984614882SBob King {
110084614882SBob King if (!element.is_string())
110184614882SBob King {
110284614882SBob King throw std::invalid_argument{"Element is not a string"};
110384614882SBob King }
110484614882SBob King std::string value = element.get<std::string>();
110584614882SBob King pmbus_utils::SensorDataFormat format{};
110684614882SBob King
110784614882SBob King if (value == "linear_11")
110884614882SBob King {
110984614882SBob King format = pmbus_utils::SensorDataFormat::linear_11;
111084614882SBob King }
111184614882SBob King else if (value == "linear_16")
111284614882SBob King {
111384614882SBob King format = pmbus_utils::SensorDataFormat::linear_16;
111484614882SBob King }
111584614882SBob King else
111684614882SBob King {
111784614882SBob King throw std::invalid_argument{"Element is not a sensor data format"};
111884614882SBob King }
111984614882SBob King
112084614882SBob King return format;
112184614882SBob King }
112284614882SBob King
parseSensorMonitoring(const json & element)1123a2f2a0dcSBob King std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
1124a2f2a0dcSBob King {
1125a2f2a0dcSBob King verifyIsObject(element);
1126a2f2a0dcSBob King unsigned int propertyCount{0};
1127a2f2a0dcSBob King
1128a2f2a0dcSBob King // Optional comments property; value not stored
1129a2f2a0dcSBob King if (element.contains("comments"))
1130a2f2a0dcSBob King {
1131a2f2a0dcSBob King ++propertyCount;
1132a2f2a0dcSBob King }
1133a2f2a0dcSBob King
1134a2f2a0dcSBob King // Required rule_id or actions property
1135a2f2a0dcSBob King std::vector<std::unique_ptr<Action>> actions{};
1136a2f2a0dcSBob King actions = parseRuleIDOrActionsProperty(element);
1137a2f2a0dcSBob King ++propertyCount;
1138a2f2a0dcSBob King
1139a2f2a0dcSBob King // Verify no invalid properties exist
1140a2f2a0dcSBob King verifyPropertyCount(element, propertyCount);
1141a2f2a0dcSBob King
1142a2f2a0dcSBob King return std::make_unique<SensorMonitoring>(std::move(actions));
1143a2f2a0dcSBob King }
1144a2f2a0dcSBob King
parseSensorType(const json & element)11452f9e14f6SShawn McCarney SensorType parseSensorType(const json& element)
114684614882SBob King {
1147b70370b7SShawn McCarney std::string value = parseString(element);
11482f9e14f6SShawn McCarney SensorType type{};
114984614882SBob King
115084614882SBob King if (value == "iout")
115184614882SBob King {
11522f9e14f6SShawn McCarney type = SensorType::iout;
115384614882SBob King }
115484614882SBob King else if (value == "iout_peak")
115584614882SBob King {
11562f9e14f6SShawn McCarney type = SensorType::iout_peak;
115784614882SBob King }
115884614882SBob King else if (value == "iout_valley")
115984614882SBob King {
11602f9e14f6SShawn McCarney type = SensorType::iout_valley;
116184614882SBob King }
116284614882SBob King else if (value == "pout")
116384614882SBob King {
11642f9e14f6SShawn McCarney type = SensorType::pout;
116584614882SBob King }
116684614882SBob King else if (value == "temperature")
116784614882SBob King {
11682f9e14f6SShawn McCarney type = SensorType::temperature;
116984614882SBob King }
117084614882SBob King else if (value == "temperature_peak")
117184614882SBob King {
11722f9e14f6SShawn McCarney type = SensorType::temperature_peak;
117384614882SBob King }
117484614882SBob King else if (value == "vout")
117584614882SBob King {
11762f9e14f6SShawn McCarney type = SensorType::vout;
117784614882SBob King }
117884614882SBob King else if (value == "vout_peak")
117984614882SBob King {
11802f9e14f6SShawn McCarney type = SensorType::vout_peak;
118184614882SBob King }
118284614882SBob King else if (value == "vout_valley")
118384614882SBob King {
11842f9e14f6SShawn McCarney type = SensorType::vout_valley;
118584614882SBob King }
118684614882SBob King else
118784614882SBob King {
11882f9e14f6SShawn McCarney throw std::invalid_argument{"Element is not a sensor type"};
118984614882SBob King }
119084614882SBob King
119184614882SBob King return type;
119284614882SBob King }
119384614882SBob King
parseSetDevice(const json & element)119418a68505SBob King std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
119518a68505SBob King {
119618a68505SBob King // String deviceID
119718a68505SBob King std::string deviceID = parseString(element);
119818a68505SBob King
119918a68505SBob King return std::make_unique<SetDeviceAction>(deviceID);
120018a68505SBob King }
120118a68505SBob King
parseVoutDataFormat(const json & element)120284614882SBob King pmbus_utils::VoutDataFormat parseVoutDataFormat(const json& element)
120384614882SBob King {
120484614882SBob King if (!element.is_string())
120584614882SBob King {
120684614882SBob King throw std::invalid_argument{"Element is not a string"};
120784614882SBob King }
120884614882SBob King std::string value = element.get<std::string>();
120984614882SBob King pmbus_utils::VoutDataFormat format{};
121084614882SBob King
121184614882SBob King if (value == "linear")
121284614882SBob King {
121384614882SBob King format = pmbus_utils::VoutDataFormat::linear;
121484614882SBob King }
121584614882SBob King else if (value == "vid")
121684614882SBob King {
121784614882SBob King format = pmbus_utils::VoutDataFormat::vid;
121884614882SBob King }
121984614882SBob King else if (value == "direct")
122084614882SBob King {
122184614882SBob King format = pmbus_utils::VoutDataFormat::direct;
122284614882SBob King }
122384614882SBob King else if (value == "ieee")
122484614882SBob King {
122584614882SBob King format = pmbus_utils::VoutDataFormat::ieee;
122684614882SBob King }
122784614882SBob King else
122884614882SBob King {
122984614882SBob King throw std::invalid_argument{"Element is not a vout data format"};
123084614882SBob King }
123184614882SBob King
123284614882SBob King return format;
123384614882SBob King }
123484614882SBob King
12350e8c68abSShawn McCarney } // namespace internal
12360e8c68abSShawn McCarney
12370e8c68abSShawn McCarney } // namespace phosphor::power::regulators::config_file_parser
1238