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