| #include "bios_enum_attribute.hpp" |
| |
| #include "common/utils.hpp" |
| |
| #include <phosphor-logging/lg2.hpp> |
| |
| PHOSPHOR_LOG2_USING; |
| |
| 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<std::string> defaultValues; |
| Json dv = entry.at("default_values"); |
| for (auto& val : dv) |
| { |
| defaultValues.emplace_back(val); |
| } |
| |
| Json vdn = entry.at("value_names"); |
| for (auto& val : vdn) |
| { |
| valueDisplayNames.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<std::string>& 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<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle( |
| const BIOSStringTable& stringTable, const std::vector<std::string>& pVs) |
| { |
| std::vector<uint16_t> 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<uint8_t>(it.value()); |
| } |
| else if (dBusMap->propertyType == "uint16_t") |
| { |
| value = static_cast<uint16_t>(it.value()); |
| } |
| else if (dBusMap->propertyType == "uint32_t") |
| { |
| value = static_cast<uint32_t>(it.value()); |
| } |
| else if (dBusMap->propertyType == "uint64_t") |
| { |
| value = static_cast<uint64_t>(it.value()); |
| } |
| else if (dBusMap->propertyType == "int16_t") |
| { |
| value = static_cast<int16_t>(it.value()); |
| } |
| else if (dBusMap->propertyType == "int32_t") |
| { |
| value = static_cast<int32_t>(it.value()); |
| } |
| else if (dBusMap->propertyType == "int64_t") |
| { |
| value = static_cast<int64_t>(it.value()); |
| } |
| else if (dBusMap->propertyType == "bool") |
| { |
| value = static_cast<bool>(it.value()); |
| } |
| else if (dBusMap->propertyType == "double") |
| { |
| value = static_cast<double>(it.value()); |
| } |
| else if (dBusMap->propertyType == "string") |
| { |
| value = static_cast<std::string>(it.value()); |
| } |
| else |
| { |
| error("Unknown D-Bus property type '{TYPE}'", "TYPE", |
| dBusMap->propertyType); |
| 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&) |
| { |
| return defaultValueIndex; |
| } |
| } |
| |
| uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue) |
| { |
| try |
| { |
| return getValueIndex(std::get<std::string>(propValue), possibleValues); |
| } |
| catch (const std::exception&) |
| { |
| 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::populateValueDisplayNamesMap(uint16_t attrHandle) |
| { |
| for (auto& vdn : valueDisplayNames) |
| { |
| valueDisplayNamesMap[attrHandle].push_back(vdn); |
| } |
| } |
| |
| void BIOSEnumAttribute::constructEntry( |
| const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable, |
| std::optional<std::variant<int64_t, std::string>> optAttributeValue) |
| { |
| auto possibleValuesHandle = |
| getPossibleValuesHandle(stringTable, possibleValues); |
| std::vector<uint8_t> 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); |
| |
| populateValueDisplayNamesMap(attrHandle); |
| |
| std::vector<uint8_t> currValueIndices(1, 0); |
| |
| if (optAttributeValue.has_value()) |
| { |
| auto attributeValue = optAttributeValue.value(); |
| if (attributeValue.index() == 1) |
| { |
| auto currValue = std::get<std::string>(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()) |
| { |
| error("Failed to find index for new BIOS enum value '{VALUE}'", "VALUE", |
| std::get<std::string>(newPropVal)); |
| return PLDM_ERROR; |
| } |
| auto currentValue = iter->second; |
| std::vector<uint8_t> handleIndices{ |
| getValueIndex(currentValue, possibleValues)}; |
| table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType, |
| handleIndices); |
| return PLDM_SUCCESS; |
| } |
| |
| void BIOSEnumAttribute::generateAttributeEntry( |
| const std::variant<int64_t, std::string>& attributevalue, |
| Table& attrValueEntry) |
| { |
| attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1); |
| |
| auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>( |
| attrValueEntry.data()); |
| |
| std::string value = std::get<std::string>(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 |