1 #include "config.h" 2 3 #include "bios_enum_attribute.hpp" 4 5 #include "common/utils.hpp" 6 7 #include <iostream> 8 9 using namespace pldm::utils; 10 11 namespace pldm 12 { 13 namespace responder 14 { 15 namespace bios 16 { 17 BIOSEnumAttribute::BIOSEnumAttribute(const Json& entry, 18 DBusHandler* const dbusHandler) : 19 BIOSAttribute(entry, dbusHandler) 20 { 21 std::string attrName = entry.at("attribute_name"); 22 Json pv = entry.at("possible_values"); 23 for (auto& val : pv) 24 { 25 possibleValues.emplace_back(val); 26 } 27 28 std::vector<std::string> defaultValues; 29 Json dv = entry.at("default_values"); 30 for (auto& val : dv) 31 { 32 defaultValues.emplace_back(val); 33 } 34 assert(defaultValues.size() == 1); 35 defaultValue = defaultValues[0]; 36 if (dBusMap.has_value()) 37 { 38 auto dbusValues = entry.at("dbus").at("property_values"); 39 buildValMap(dbusValues); 40 } 41 } 42 43 uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value, 44 const std::vector<std::string>& pVs) 45 { 46 auto iter = std::find_if(pVs.begin(), pVs.end(), 47 [&value](const auto& v) { return v == value; }); 48 if (iter == pVs.end()) 49 { 50 throw std::invalid_argument("value must be one of possible value"); 51 } 52 return iter - pVs.begin(); 53 } 54 55 std::vector<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle( 56 const BIOSStringTable& stringTable, const std::vector<std::string>& pVs) 57 { 58 std::vector<uint16_t> possibleValuesHandle; 59 for (const auto& pv : pVs) 60 { 61 auto handle = stringTable.findHandle(pv); 62 possibleValuesHandle.push_back(handle); 63 } 64 65 return possibleValuesHandle; 66 } 67 68 void BIOSEnumAttribute::buildValMap(const Json& dbusVals) 69 { 70 PropertyValue value; 71 size_t pos = 0; 72 for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos) 73 { 74 if (dBusMap->propertyType == "uint8_t") 75 { 76 value = static_cast<uint8_t>(it.value()); 77 } 78 else if (dBusMap->propertyType == "uint16_t") 79 { 80 value = static_cast<uint16_t>(it.value()); 81 } 82 else if (dBusMap->propertyType == "uint32_t") 83 { 84 value = static_cast<uint32_t>(it.value()); 85 } 86 else if (dBusMap->propertyType == "uint64_t") 87 { 88 value = static_cast<uint64_t>(it.value()); 89 } 90 else if (dBusMap->propertyType == "int16_t") 91 { 92 value = static_cast<int16_t>(it.value()); 93 } 94 else if (dBusMap->propertyType == "int32_t") 95 { 96 value = static_cast<int32_t>(it.value()); 97 } 98 else if (dBusMap->propertyType == "int64_t") 99 { 100 value = static_cast<int64_t>(it.value()); 101 } 102 else if (dBusMap->propertyType == "bool") 103 { 104 value = static_cast<bool>(it.value()); 105 } 106 else if (dBusMap->propertyType == "double") 107 { 108 value = static_cast<double>(it.value()); 109 } 110 else if (dBusMap->propertyType == "string") 111 { 112 value = static_cast<std::string>(it.value()); 113 } 114 else 115 { 116 std::cerr << "Unknown D-Bus property type, TYPE=" 117 << dBusMap->propertyType << "\n"; 118 throw std::invalid_argument("Unknown D-BUS property type"); 119 } 120 valMap.emplace(value, possibleValues[pos]); 121 } 122 } 123 124 uint8_t BIOSEnumAttribute::getAttrValueIndex() 125 { 126 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues); 127 if (!dBusMap.has_value()) 128 { 129 return defaultValueIndex; 130 } 131 132 try 133 { 134 auto propValue = dbusHandler->getDbusPropertyVariant( 135 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(), 136 dBusMap->interface.c_str()); 137 auto iter = valMap.find(propValue); 138 if (iter == valMap.end()) 139 { 140 return defaultValueIndex; 141 } 142 auto currentValue = iter->second; 143 return getValueIndex(currentValue, possibleValues); 144 } 145 catch (const std::exception& e) 146 { 147 return defaultValueIndex; 148 } 149 } 150 151 uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue) 152 { 153 try 154 { 155 return getValueIndex(std::get<std::string>(propValue), possibleValues); 156 } 157 catch (const std::exception& e) 158 { 159 return getValueIndex(defaultValue, possibleValues); 160 } 161 } 162 163 void BIOSEnumAttribute::setAttrValueOnDbus( 164 const pldm_bios_attr_val_table_entry* attrValueEntry, 165 const pldm_bios_attr_table_entry* attrEntry, 166 const BIOSStringTable& stringTable) 167 { 168 if (!dBusMap.has_value()) 169 { 170 return; 171 } 172 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry); 173 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry); 174 175 assert(currHdls.size() == 1); 176 auto valueString = stringTable.findString(pvHdls[currHdls[0]]); 177 178 auto it = std::find_if(valMap.begin(), valMap.end(), 179 [&valueString](const auto& typePair) { 180 return typePair.second == valueString; 181 }); 182 if (it == valMap.end()) 183 { 184 return; 185 } 186 187 dbusHandler->setDbusProperty(*dBusMap, it->first); 188 } 189 190 void BIOSEnumAttribute::constructEntry( 191 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable, 192 std::optional<std::variant<int64_t, std::string>> optAttributeValue) 193 { 194 auto possibleValuesHandle = 195 getPossibleValuesHandle(stringTable, possibleValues); 196 std::vector<uint8_t> defaultIndices(1, 0); 197 defaultIndices[0] = getValueIndex(defaultValue, possibleValues); 198 199 pldm_bios_table_attr_entry_enum_info info = { 200 stringTable.findHandle(name), readOnly, 201 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(), 202 (uint8_t)defaultIndices.size(), defaultIndices.data(), 203 }; 204 205 auto attrTableEntry = 206 table::attribute::constructEnumEntry(attrTable, &info); 207 auto [attrHandle, attrType, _] = 208 table::attribute::decodeHeader(attrTableEntry); 209 210 std::vector<uint8_t> currValueIndices(1, 0); 211 212 if (optAttributeValue.has_value()) 213 { 214 auto attributeValue = optAttributeValue.value(); 215 if (attributeValue.index() == 1) 216 { 217 auto currValue = std::get<std::string>(attributeValue); 218 currValueIndices[0] = getValueIndex(currValue, possibleValues); 219 } 220 else 221 { 222 currValueIndices[0] = getAttrValueIndex(); 223 } 224 } 225 else 226 { 227 currValueIndices[0] = getAttrValueIndex(); 228 } 229 230 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle, 231 attrType, currValueIndices); 232 } 233 234 int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl, 235 uint8_t attrType, 236 const PropertyValue& newPropVal) 237 { 238 auto iter = valMap.find(newPropVal); 239 if (iter == valMap.end()) 240 { 241 std::cerr << "Could not find index for new BIOS enum, value=" 242 << std::get<std::string>(newPropVal) << "\n"; 243 return PLDM_ERROR; 244 } 245 auto currentValue = iter->second; 246 std::vector<uint8_t> handleIndices{ 247 getValueIndex(currentValue, possibleValues)}; 248 table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType, 249 handleIndices); 250 return PLDM_SUCCESS; 251 } 252 253 void BIOSEnumAttribute::generateAttributeEntry( 254 const std::variant<int64_t, std::string>& attributevalue, 255 Table& attrValueEntry) 256 { 257 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1); 258 259 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>( 260 attrValueEntry.data()); 261 262 std::string value = std::get<std::string>(attributevalue); 263 entry->attr_type = 0; 264 entry->value[0] = 1; // number of current values, default 1 265 entry->value[1] = getAttrValueIndex(value); 266 } 267 268 } // namespace bios 269 } // namespace responder 270 } // namespace pldm 271