blob: 4bb8bd881b7c9eabf92bb3e5bb61e93a84c15165 [file] [log] [blame]
/**
* Copyright © 2020 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config_file_parser.hpp"
#include "config_file_parser_error.hpp"
#include "i2c_interface.hpp"
#include "pmbus_utils.hpp"
#include <exception>
#include <fstream>
#include <optional>
#include <utility>
using json = nlohmann::json;
namespace phosphor::power::regulators::config_file_parser
{
std::tuple<std::vector<std::unique_ptr<Rule>>,
std::vector<std::unique_ptr<Chassis>>>
parse(const std::filesystem::path& pathName)
{
try
{
// Use standard JSON parser to create tree of JSON elements
std::ifstream file{pathName};
json rootElement = json::parse(file);
// Parse tree of JSON elements and return corresponding C++ objects
return internal::parseRoot(rootElement);
}
catch (const std::exception& e)
{
throw ConfigFileParserError{pathName, e.what()};
}
}
namespace internal
{
std::unique_ptr<Action> parseAction(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Required action type property; there must be exactly one specified
std::unique_ptr<Action> action{};
if (element.contains("and"))
{
action = parseAnd(element["and"]);
++propertyCount;
}
else if (element.contains("compare_presence"))
{
action = parseComparePresence(element["compare_presence"]);
++propertyCount;
}
else if (element.contains("compare_vpd"))
{
action = parseCompareVPD(element["compare_vpd"]);
++propertyCount;
}
else if (element.contains("i2c_capture_bytes"))
{
action = parseI2CCaptureBytes(element["i2c_capture_bytes"]);
++propertyCount;
}
else if (element.contains("i2c_compare_bit"))
{
action = parseI2CCompareBit(element["i2c_compare_bit"]);
++propertyCount;
}
else if (element.contains("i2c_compare_byte"))
{
action = parseI2CCompareByte(element["i2c_compare_byte"]);
++propertyCount;
}
else if (element.contains("i2c_compare_bytes"))
{
action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
++propertyCount;
}
else if (element.contains("i2c_write_bit"))
{
action = parseI2CWriteBit(element["i2c_write_bit"]);
++propertyCount;
}
else if (element.contains("i2c_write_byte"))
{
action = parseI2CWriteByte(element["i2c_write_byte"]);
++propertyCount;
}
else if (element.contains("i2c_write_bytes"))
{
action = parseI2CWriteBytes(element["i2c_write_bytes"]);
++propertyCount;
}
else if (element.contains("if"))
{
action = parseIf(element["if"]);
++propertyCount;
}
else if (element.contains("log_phase_fault"))
{
action = parseLogPhaseFault(element["log_phase_fault"]);
++propertyCount;
}
else if (element.contains("not"))
{
action = parseNot(element["not"]);
++propertyCount;
}
else if (element.contains("or"))
{
action = parseOr(element["or"]);
++propertyCount;
}
else if (element.contains("pmbus_read_sensor"))
{
action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
++propertyCount;
}
else if (element.contains("pmbus_write_vout_command"))
{
action =
parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
++propertyCount;
}
else if (element.contains("run_rule"))
{
action = parseRunRule(element["run_rule"]);
++propertyCount;
}
else if (element.contains("set_device"))
{
action = parseSetDevice(element["set_device"]);
++propertyCount;
}
else
{
throw std::invalid_argument{"Required action type property missing"};
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return action;
}
std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
{
verifyIsArray(element);
std::vector<std::unique_ptr<Action>> actions;
for (auto& actionElement : element)
{
actions.emplace_back(parseAction(actionElement));
}
return actions;
}
std::unique_ptr<AndAction> parseAnd(const json& element)
{
verifyIsArray(element);
// Verify if array size less than 2
if (element.size() < 2)
{
throw std::invalid_argument{"Array must contain two or more actions"};
}
// Array of two or more actions
std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
return std::make_unique<AndAction>(std::move(actions));
}
std::unique_ptr<Chassis> parseChassis(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Required number property
const json& numberElement = getRequiredProperty(element, "number");
unsigned int number = parseUnsignedInteger(numberElement);
if (number < 1)
{
throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
}
++propertyCount;
// Required inventory_path property
const json& inventoryPathElement =
getRequiredProperty(element, "inventory_path");
std::string inventoryPath = parseInventoryPath(inventoryPathElement);
++propertyCount;
// Optional devices property
std::vector<std::unique_ptr<Device>> devices{};
auto devicesIt = element.find("devices");
if (devicesIt != element.end())
{
devices = parseDeviceArray(*devicesIt);
++propertyCount;
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<Chassis>(number, inventoryPath, std::move(devices));
}
std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
{
verifyIsArray(element);
std::vector<std::unique_ptr<Chassis>> chassis;
for (auto& chassisElement : element)
{
chassis.emplace_back(parseChassis(chassisElement));
}
return chassis;
}
std::unique_ptr<ComparePresenceAction> parseComparePresence(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required fru property
const json& fruElement = getRequiredProperty(element, "fru");
std::string fru = parseInventoryPath(fruElement);
++propertyCount;
// Required value property
const json& valueElement = getRequiredProperty(element, "value");
bool value = parseBoolean(valueElement);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<ComparePresenceAction>(fru, value);
}
std::unique_ptr<CompareVPDAction> parseCompareVPD(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required fru property
const json& fruElement = getRequiredProperty(element, "fru");
std::string fru = parseInventoryPath(fruElement);
++propertyCount;
// Required keyword property
const json& keywordElement = getRequiredProperty(element, "keyword");
std::string keyword = parseString(keywordElement);
++propertyCount;
// Either value or byte_values required property
auto valueIt = element.find("value");
std::vector<uint8_t> value{};
auto byteValuesIt = element.find("byte_values");
if ((valueIt != element.end()) && (byteValuesIt == element.end()))
{
std::string stringValue = parseString(*valueIt, true);
value.insert(value.begin(), stringValue.begin(), stringValue.end());
++propertyCount;
}
else if ((valueIt == element.end()) && (byteValuesIt != element.end()))
{
value = parseHexByteArray(*byteValuesIt);
++propertyCount;
}
else
{
throw std::invalid_argument{
"Invalid property: Must contain either value or byte_values"};
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<CompareVPDAction>(fru, keyword, value);
}
std::unique_ptr<Configuration> parseConfiguration(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Optional volts property
std::optional<double> volts{};
auto voltsIt = element.find("volts");
if (voltsIt != element.end())
{
volts = parseDouble(*voltsIt);
++propertyCount;
}
// Required rule_id or actions property
std::vector<std::unique_ptr<Action>> actions{};
actions = parseRuleIDOrActionsProperty(element);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<Configuration>(volts, std::move(actions));
}
std::unique_ptr<Device> parseDevice(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Required id property
const json& idElement = getRequiredProperty(element, "id");
std::string id = parseString(idElement);
++propertyCount;
// Required is_regulator property
const json& isRegulatorElement =
getRequiredProperty(element, "is_regulator");
bool isRegulator = parseBoolean(isRegulatorElement);
++propertyCount;
// Required fru property
const json& fruElement = getRequiredProperty(element, "fru");
std::string fru = parseInventoryPath(fruElement);
++propertyCount;
// Required i2c_interface property
const json& i2cInterfaceElement =
getRequiredProperty(element, "i2c_interface");
std::unique_ptr<i2c::I2CInterface> i2cInterface =
parseI2CInterface(i2cInterfaceElement);
++propertyCount;
// Optional presence_detection property
std::unique_ptr<PresenceDetection> presenceDetection{};
auto presenceDetectionIt = element.find("presence_detection");
if (presenceDetectionIt != element.end())
{
presenceDetection = parsePresenceDetection(*presenceDetectionIt);
++propertyCount;
}
// Optional configuration property
std::unique_ptr<Configuration> configuration{};
auto configurationIt = element.find("configuration");
if (configurationIt != element.end())
{
configuration = parseConfiguration(*configurationIt);
++propertyCount;
}
// Optional phase_fault_detection property
std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
auto phaseFaultDetectionIt = element.find("phase_fault_detection");
if (phaseFaultDetectionIt != element.end())
{
if (!isRegulator)
{
throw std::invalid_argument{"Invalid phase_fault_detection "
"property when is_regulator is false"};
}
phaseFaultDetection = parsePhaseFaultDetection(*phaseFaultDetectionIt);
++propertyCount;
}
// Optional rails property
std::vector<std::unique_ptr<Rail>> rails{};
auto railsIt = element.find("rails");
if (railsIt != element.end())
{
if (!isRegulator)
{
throw std::invalid_argument{
"Invalid rails property when is_regulator is false"};
}
rails = parseRailArray(*railsIt);
++propertyCount;
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<Device>(
id, isRegulator, fru, std::move(i2cInterface),
std::move(presenceDetection), std::move(configuration),
std::move(phaseFaultDetection), std::move(rails));
}
std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
{
verifyIsArray(element);
std::vector<std::unique_ptr<Device>> devices;
for (auto& deviceElement : element)
{
devices.emplace_back(parseDevice(deviceElement));
}
return devices;
}
std::vector<uint8_t> parseHexByteArray(const json& element)
{
verifyIsArray(element);
std::vector<uint8_t> values;
for (auto& valueElement : element)
{
values.emplace_back(parseHexByte(valueElement));
}
return values;
}
std::unique_ptr<I2CCaptureBytesAction> parseI2CCaptureBytes(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required register property
const json& regElement = getRequiredProperty(element, "register");
uint8_t reg = parseHexByte(regElement);
++propertyCount;
// Required count property
const json& countElement = getRequiredProperty(element, "count");
uint8_t count = parseUint8(countElement);
if (count < 1)
{
throw std::invalid_argument{"Invalid byte count: Must be > 0"};
}
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<I2CCaptureBytesAction>(reg, count);
}
std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required register property
const json& regElement = getRequiredProperty(element, "register");
uint8_t reg = parseHexByte(regElement);
++propertyCount;
// Required position property
const json& positionElement = getRequiredProperty(element, "position");
uint8_t position = parseBitPosition(positionElement);
++propertyCount;
// Required value property
const json& valueElement = getRequiredProperty(element, "value");
uint8_t value = parseBitValue(valueElement);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<I2CCompareBitAction>(reg, position, value);
}
std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required register property
const json& regElement = getRequiredProperty(element, "register");
uint8_t reg = parseHexByte(regElement);
++propertyCount;
// Required value property
const json& valueElement = getRequiredProperty(element, "value");
uint8_t value = parseHexByte(valueElement);
++propertyCount;
// Optional mask property
uint8_t mask = 0xff;
auto maskIt = element.find("mask");
if (maskIt != element.end())
{
mask = parseHexByte(*maskIt);
++propertyCount;
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<I2CCompareByteAction>(reg, value, mask);
}
std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required register property
const json& regElement = getRequiredProperty(element, "register");
uint8_t reg = parseHexByte(regElement);
++propertyCount;
// Required values property
const json& valueElement = getRequiredProperty(element, "values");
std::vector<uint8_t> values = parseHexByteArray(valueElement);
++propertyCount;
// Optional masks property
std::vector<uint8_t> masks{};
auto masksIt = element.find("masks");
if (masksIt != element.end())
{
masks = parseHexByteArray(*masksIt);
++propertyCount;
}
// Verify masks array (if specified) was same size as values array
if ((!masks.empty()) && (masks.size() != values.size()))
{
throw std::invalid_argument{"Invalid number of elements in masks"};
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
if (masks.empty())
{
return std::make_unique<I2CCompareBytesAction>(reg, values);
}
return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
}
std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required bus property
const json& busElement = getRequiredProperty(element, "bus");
uint8_t bus = parseUint8(busElement);
++propertyCount;
// Required address property
const json& addressElement = getRequiredProperty(element, "address");
uint8_t address = parseHexByte(addressElement);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
// Create I2CInterface object; retry failed I2C operations a max of 3 times.
int maxRetries{3};
return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED,
maxRetries);
}
std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required register property
const json& regElement = getRequiredProperty(element, "register");
uint8_t reg = parseHexByte(regElement);
++propertyCount;
// Required position property
const json& positionElement = getRequiredProperty(element, "position");
uint8_t position = parseBitPosition(positionElement);
++propertyCount;
// Required value property
const json& valueElement = getRequiredProperty(element, "value");
uint8_t value = parseBitValue(valueElement);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<I2CWriteBitAction>(reg, position, value);
}
std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required register property
const json& regElement = getRequiredProperty(element, "register");
uint8_t reg = parseHexByte(regElement);
++propertyCount;
// Required value property
const json& valueElement = getRequiredProperty(element, "value");
uint8_t value = parseHexByte(valueElement);
++propertyCount;
// Optional mask property
uint8_t mask = 0xff;
auto maskIt = element.find("mask");
if (maskIt != element.end())
{
mask = parseHexByte(*maskIt);
++propertyCount;
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<I2CWriteByteAction>(reg, value, mask);
}
std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required register property
const json& regElement = getRequiredProperty(element, "register");
uint8_t reg = parseHexByte(regElement);
++propertyCount;
// Required values property
const json& valueElement = getRequiredProperty(element, "values");
std::vector<uint8_t> values = parseHexByteArray(valueElement);
++propertyCount;
// Optional masks property
std::vector<uint8_t> masks{};
auto masksIt = element.find("masks");
if (masksIt != element.end())
{
masks = parseHexByteArray(*masksIt);
++propertyCount;
}
// Verify masks array (if specified) was same size as values array
if ((!masks.empty()) && (masks.size() != values.size()))
{
throw std::invalid_argument{"Invalid number of elements in masks"};
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
if (masks.empty())
{
return std::make_unique<I2CWriteBytesAction>(reg, values);
}
return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
}
std::unique_ptr<IfAction> parseIf(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required condition property
const json& conditionElement = getRequiredProperty(element, "condition");
std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
++propertyCount;
// Required then property
const json& thenElement = getRequiredProperty(element, "then");
std::vector<std::unique_ptr<Action>> thenActions =
parseActionArray(thenElement);
++propertyCount;
// Optional else property
std::vector<std::unique_ptr<Action>> elseActions{};
auto elseIt = element.find("else");
if (elseIt != element.end())
{
elseActions = parseActionArray(*elseIt);
++propertyCount;
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<IfAction>(std::move(conditionAction),
std::move(thenActions),
std::move(elseActions));
}
std::string parseInventoryPath(const json& element)
{
std::string inventoryPath = parseString(element);
std::string absPath = "/xyz/openbmc_project/inventory";
if (inventoryPath.front() != '/')
{
absPath += '/';
}
absPath += inventoryPath;
return absPath;
}
std::unique_ptr<LogPhaseFaultAction> parseLogPhaseFault(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required type property
const json& typeElement = getRequiredProperty(element, "type");
PhaseFaultType type = parsePhaseFaultType(typeElement);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<LogPhaseFaultAction>(type);
}
std::unique_ptr<NotAction> parseNot(const json& element)
{
// Required action to execute
std::unique_ptr<Action> action = parseAction(element);
return std::make_unique<NotAction>(std::move(action));
}
std::unique_ptr<OrAction> parseOr(const json& element)
{
verifyIsArray(element);
// Verify if array size less than 2
if (element.size() < 2)
{
throw std::invalid_argument{"Array must contain two or more actions"};
}
// Array of two or more actions
std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
return std::make_unique<OrAction>(std::move(actions));
}
std::unique_ptr<PhaseFaultDetection>
parsePhaseFaultDetection(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Optional device_id property
std::string deviceID{};
auto deviceIDIt = element.find("device_id");
if (deviceIDIt != element.end())
{
deviceID = parseString(*deviceIDIt);
++propertyCount;
}
// Required rule_id or actions property
std::vector<std::unique_ptr<Action>> actions{};
actions = parseRuleIDOrActionsProperty(element);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<PhaseFaultDetection>(std::move(actions), deviceID);
}
PhaseFaultType parsePhaseFaultType(const json& element)
{
std::string value = parseString(element);
PhaseFaultType type{};
if (value == "n")
{
type = PhaseFaultType::n;
}
else if (value == "n+1")
{
type = PhaseFaultType::n_plus_1;
}
else
{
throw std::invalid_argument{"Element is not a phase fault type"};
}
return type;
}
std::unique_ptr<PMBusReadSensorAction> parsePMBusReadSensor(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Required type property
const json& typeElement = getRequiredProperty(element, "type");
SensorType type = parseSensorType(typeElement);
++propertyCount;
// Required command property
const json& commandElement = getRequiredProperty(element, "command");
uint8_t command = parseHexByte(commandElement);
++propertyCount;
// Required format property
const json& formatElement = getRequiredProperty(element, "format");
pmbus_utils::SensorDataFormat format = parseSensorDataFormat(formatElement);
++propertyCount;
// Optional exponent property
std::optional<int8_t> exponent{};
auto exponentIt = element.find("exponent");
if (exponentIt != element.end())
{
exponent = parseInt8(*exponentIt);
++propertyCount;
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<PMBusReadSensorAction>(type, command, format,
exponent);
}
std::unique_ptr<PMBusWriteVoutCommandAction>
parsePMBusWriteVoutCommand(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional volts property
std::optional<double> volts{};
auto voltsIt = element.find("volts");
if (voltsIt != element.end())
{
volts = parseDouble(*voltsIt);
++propertyCount;
}
// Required format property
const json& formatElement = getRequiredProperty(element, "format");
std::string formatString = parseString(formatElement);
if (formatString != "linear")
{
throw std::invalid_argument{"Invalid format value: " + formatString};
}
pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
++propertyCount;
// Optional exponent property
std::optional<int8_t> exponent{};
auto exponentIt = element.find("exponent");
if (exponentIt != element.end())
{
exponent = parseInt8(*exponentIt);
++propertyCount;
}
// Optional is_verified property
bool isVerified = false;
auto isVerifiedIt = element.find("is_verified");
if (isVerifiedIt != element.end())
{
isVerified = parseBoolean(*isVerifiedIt);
++propertyCount;
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
exponent, isVerified);
}
std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Required rule_id or actions property
std::vector<std::unique_ptr<Action>> actions{};
actions = parseRuleIDOrActionsProperty(element);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<PresenceDetection>(std::move(actions));
}
std::unique_ptr<Rail> parseRail(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Required id property
const json& idElement = getRequiredProperty(element, "id");
std::string id = parseString(idElement);
++propertyCount;
// Optional configuration property
std::unique_ptr<Configuration> configuration{};
auto configurationIt = element.find("configuration");
if (configurationIt != element.end())
{
configuration = parseConfiguration(*configurationIt);
++propertyCount;
}
// Optional sensor_monitoring property
std::unique_ptr<SensorMonitoring> sensorMonitoring{};
auto sensorMonitoringIt = element.find("sensor_monitoring");
if (sensorMonitoringIt != element.end())
{
sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
++propertyCount;
}
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<Rail>(id, std::move(configuration),
std::move(sensorMonitoring));
}
std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
{
verifyIsArray(element);
std::vector<std::unique_ptr<Rail>> rails;
for (auto& railElement : element)
{
rails.emplace_back(parseRail(railElement));
}
return rails;
}
std::tuple<std::vector<std::unique_ptr<Rule>>,
std::vector<std::unique_ptr<Chassis>>>
parseRoot(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Optional rules property
std::vector<std::unique_ptr<Rule>> rules{};
auto rulesIt = element.find("rules");
if (rulesIt != element.end())
{
rules = parseRuleArray(*rulesIt);
++propertyCount;
}
// Required chassis property
const json& chassisElement = getRequiredProperty(element, "chassis");
std::vector<std::unique_ptr<Chassis>> chassis =
parseChassisArray(chassisElement);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_tuple(std::move(rules), std::move(chassis));
}
std::unique_ptr<Rule> parseRule(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Required id property
const json& idElement = getRequiredProperty(element, "id");
std::string id = parseString(idElement);
++propertyCount;
// Required actions property
const json& actionsElement = getRequiredProperty(element, "actions");
std::vector<std::unique_ptr<Action>> actions =
parseActionArray(actionsElement);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<Rule>(id, std::move(actions));
}
std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
{
verifyIsArray(element);
std::vector<std::unique_ptr<Rule>> rules;
for (auto& ruleElement : element)
{
rules.emplace_back(parseRule(ruleElement));
}
return rules;
}
std::vector<std::unique_ptr<Action>>
parseRuleIDOrActionsProperty(const json& element)
{
verifyIsObject(element);
// Required rule_id or actions property
std::vector<std::unique_ptr<Action>> actions{};
auto ruleIDIt = element.find("rule_id");
auto actionsIt = element.find("actions");
if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
{
std::string ruleID = parseString(*ruleIDIt);
actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
}
else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
{
actions = parseActionArray(*actionsIt);
}
else
{
throw std::invalid_argument{"Invalid property combination: Must "
"contain either rule_id or actions"};
}
return actions;
}
std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
{
// String ruleID
std::string ruleID = parseString(element);
return std::make_unique<RunRuleAction>(ruleID);
}
pmbus_utils::SensorDataFormat parseSensorDataFormat(const json& element)
{
if (!element.is_string())
{
throw std::invalid_argument{"Element is not a string"};
}
std::string value = element.get<std::string>();
pmbus_utils::SensorDataFormat format{};
if (value == "linear_11")
{
format = pmbus_utils::SensorDataFormat::linear_11;
}
else if (value == "linear_16")
{
format = pmbus_utils::SensorDataFormat::linear_16;
}
else
{
throw std::invalid_argument{"Element is not a sensor data format"};
}
return format;
}
std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
{
verifyIsObject(element);
unsigned int propertyCount{0};
// Optional comments property; value not stored
if (element.contains("comments"))
{
++propertyCount;
}
// Required rule_id or actions property
std::vector<std::unique_ptr<Action>> actions{};
actions = parseRuleIDOrActionsProperty(element);
++propertyCount;
// Verify no invalid properties exist
verifyPropertyCount(element, propertyCount);
return std::make_unique<SensorMonitoring>(std::move(actions));
}
SensorType parseSensorType(const json& element)
{
std::string value = parseString(element);
SensorType type{};
if (value == "iout")
{
type = SensorType::iout;
}
else if (value == "iout_peak")
{
type = SensorType::iout_peak;
}
else if (value == "iout_valley")
{
type = SensorType::iout_valley;
}
else if (value == "pout")
{
type = SensorType::pout;
}
else if (value == "temperature")
{
type = SensorType::temperature;
}
else if (value == "temperature_peak")
{
type = SensorType::temperature_peak;
}
else if (value == "vout")
{
type = SensorType::vout;
}
else if (value == "vout_peak")
{
type = SensorType::vout_peak;
}
else if (value == "vout_valley")
{
type = SensorType::vout_valley;
}
else
{
throw std::invalid_argument{"Element is not a sensor type"};
}
return type;
}
std::unique_ptr<SetDeviceAction> parseSetDevice(const json& element)
{
// String deviceID
std::string deviceID = parseString(element);
return std::make_unique<SetDeviceAction>(deviceID);
}
pmbus_utils::VoutDataFormat parseVoutDataFormat(const json& element)
{
if (!element.is_string())
{
throw std::invalid_argument{"Element is not a string"};
}
std::string value = element.get<std::string>();
pmbus_utils::VoutDataFormat format{};
if (value == "linear")
{
format = pmbus_utils::VoutDataFormat::linear;
}
else if (value == "vid")
{
format = pmbus_utils::VoutDataFormat::vid;
}
else if (value == "direct")
{
format = pmbus_utils::VoutDataFormat::direct;
}
else if (value == "ieee")
{
format = pmbus_utils::VoutDataFormat::ieee;
}
else
{
throw std::invalid_argument{"Element is not a vout data format"};
}
return format;
}
} // namespace internal
} // namespace phosphor::power::regulators::config_file_parser