#include "config.h" #include "bios_enum_attribute.hpp" #include "common/utils.hpp" #include using namespace pldm::utils; namespace pldm { namespace responder { namespace bios { BIOSEnumAttribute::BIOSEnumAttribute(const Json& entry, DBusHandler* const dbusHandler) : BIOSAttribute(entry, dbusHandler) { std::string attrName = entry.at("attribute_name"); Json pv = entry.at("possible_values"); for (auto& val : pv) { possibleValues.emplace_back(val); } std::vector defaultValues; Json dv = entry.at("default_values"); for (auto& val : dv) { defaultValues.emplace_back(val); } assert(defaultValues.size() == 1); defaultValue = defaultValues[0]; if (dBusMap.has_value()) { auto dbusValues = entry.at("dbus").at("property_values"); buildValMap(dbusValues); } } uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value, const std::vector& pVs) { auto iter = std::find_if(pVs.begin(), pVs.end(), [&value](const auto& v) { return v == value; }); if (iter == pVs.end()) { throw std::invalid_argument("value must be one of possible value"); } return iter - pVs.begin(); } std::vector BIOSEnumAttribute::getPossibleValuesHandle( const BIOSStringTable& stringTable, const std::vector& pVs) { std::vector possibleValuesHandle; for (const auto& pv : pVs) { auto handle = stringTable.findHandle(pv); possibleValuesHandle.push_back(handle); } return possibleValuesHandle; } void BIOSEnumAttribute::buildValMap(const Json& dbusVals) { PropertyValue value; size_t pos = 0; for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos) { if (dBusMap->propertyType == "uint8_t") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "uint16_t") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "uint32_t") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "uint64_t") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "int16_t") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "int32_t") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "int64_t") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "bool") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "double") { value = static_cast(it.value()); } else if (dBusMap->propertyType == "string") { value = static_cast(it.value()); } else { std::cerr << "Unknown D-Bus property type, TYPE=" << dBusMap->propertyType << "\n"; throw std::invalid_argument("Unknown D-BUS property type"); } valMap.emplace(value, possibleValues[pos]); } } uint8_t BIOSEnumAttribute::getAttrValueIndex() { auto defaultValueIndex = getValueIndex(defaultValue, possibleValues); if (!dBusMap.has_value()) { return defaultValueIndex; } try { auto propValue = dbusHandler->getDbusPropertyVariant( dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(), dBusMap->interface.c_str()); auto iter = valMap.find(propValue); if (iter == valMap.end()) { return defaultValueIndex; } auto currentValue = iter->second; return getValueIndex(currentValue, possibleValues); } catch (const std::exception& e) { return defaultValueIndex; } } uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue) { try { return getValueIndex(std::get(propValue), possibleValues); } catch (const std::exception& e) { return getValueIndex(defaultValue, possibleValues); } } void BIOSEnumAttribute::setAttrValueOnDbus( const pldm_bios_attr_val_table_entry* attrValueEntry, const pldm_bios_attr_table_entry* attrEntry, const BIOSStringTable& stringTable) { if (!dBusMap.has_value()) { return; } auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry); auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry); assert(currHdls.size() == 1); auto valueString = stringTable.findString(pvHdls[currHdls[0]]); auto it = std::find_if(valMap.begin(), valMap.end(), [&valueString](const auto& typePair) { return typePair.second == valueString; }); if (it == valMap.end()) { return; } dbusHandler->setDbusProperty(*dBusMap, it->first); } void BIOSEnumAttribute::constructEntry( const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable, std::optional> optAttributeValue) { auto possibleValuesHandle = getPossibleValuesHandle(stringTable, possibleValues); std::vector defaultIndices(1, 0); defaultIndices[0] = getValueIndex(defaultValue, possibleValues); pldm_bios_table_attr_entry_enum_info info = { stringTable.findHandle(name), readOnly, (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(), (uint8_t)defaultIndices.size(), defaultIndices.data(), }; auto attrTableEntry = table::attribute::constructEnumEntry(attrTable, &info); auto [attrHandle, attrType, _] = table::attribute::decodeHeader(attrTableEntry); std::vector currValueIndices(1, 0); if (optAttributeValue.has_value()) { auto attributeValue = optAttributeValue.value(); if (attributeValue.index() == 1) { auto currValue = std::get(attributeValue); currValueIndices[0] = getValueIndex(currValue, possibleValues); } else { currValueIndices[0] = getAttrValueIndex(); } } else { currValueIndices[0] = getAttrValueIndex(); } table::attribute_value::constructEnumEntry(attrValueTable, attrHandle, attrType, currValueIndices); } int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl, uint8_t attrType, const PropertyValue& newPropVal) { auto iter = valMap.find(newPropVal); if (iter == valMap.end()) { std::cerr << "Could not find index for new BIOS enum, value=" << std::get(newPropVal) << "\n"; return PLDM_ERROR; } auto currentValue = iter->second; std::vector handleIndices{ getValueIndex(currentValue, possibleValues)}; table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType, handleIndices); return PLDM_SUCCESS; } void BIOSEnumAttribute::generateAttributeEntry( const std::variant& attributevalue, Table& attrValueEntry) { attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1); auto entry = reinterpret_cast( attrValueEntry.data()); std::string value = std::get(attributevalue); entry->attr_type = 0; entry->value[0] = 1; // number of current values, default 1 entry->value[1] = getAttrValueIndex(value); } } // namespace bios } // namespace responder } // namespace pldm