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 try 153 { 154 return getValueIndex(std::get<std::string>(propValue), possibleValues); 155 } 156 catch (const std::exception& e) 157 { 158 return getValueIndex(defaultValue, possibleValues); 159 } 160 } 161 162 void BIOSEnumAttribute::setAttrValueOnDbus( 163 const pldm_bios_attr_val_table_entry* attrValueEntry, 164 const pldm_bios_attr_table_entry* attrEntry, 165 const BIOSStringTable& stringTable) 166 { 167 if (readOnly || !dBusMap.has_value()) 168 { 169 return; 170 } 171 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry); 172 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry); 173 174 assert(currHdls.size() == 1); 175 auto valueString = stringTable.findString(pvHdls[currHdls[0]]); 176 177 auto it = std::find_if(valMap.begin(), valMap.end(), 178 [&valueString](const auto& typePair) { 179 return typePair.second == valueString; 180 }); 181 if (it == valMap.end()) 182 { 183 return; 184 } 185 186 dbusHandler->setDbusProperty(*dBusMap, it->first); 187 } 188 189 void BIOSEnumAttribute::constructEntry( 190 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable, 191 std::optional<std::variant<int64_t, std::string>> optAttributeValue) 192 { 193 auto possibleValuesHandle = 194 getPossibleValuesHandle(stringTable, possibleValues); 195 std::vector<uint8_t> defaultIndices(1, 0); 196 defaultIndices[0] = getValueIndex(defaultValue, possibleValues); 197 198 pldm_bios_table_attr_entry_enum_info info = { 199 stringTable.findHandle(name), readOnly, 200 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(), 201 (uint8_t)defaultIndices.size(), defaultIndices.data(), 202 }; 203 204 auto attrTableEntry = 205 table::attribute::constructEnumEntry(attrTable, &info); 206 auto [attrHandle, attrType, _] = 207 table::attribute::decodeHeader(attrTableEntry); 208 209 std::vector<uint8_t> currValueIndices(1, 0); 210 211 if (optAttributeValue.has_value()) 212 { 213 auto attributeValue = optAttributeValue.value(); 214 if (attributeValue.index() == 1) 215 { 216 auto currValue = std::get<std::string>(attributeValue); 217 currValueIndices[0] = getValueIndex(currValue, possibleValues); 218 } 219 else 220 { 221 currValueIndices[0] = getAttrValueIndex(); 222 } 223 } 224 else 225 { 226 currValueIndices[0] = getAttrValueIndex(); 227 } 228 229 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle, 230 attrType, currValueIndices); 231 } 232 233 int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl, 234 uint8_t attrType, 235 const PropertyValue& newPropVal) 236 { 237 auto iter = valMap.find(newPropVal); 238 if (iter == valMap.end()) 239 { 240 std::cerr << "Could not find index for new BIOS enum, value=" 241 << std::get<std::string>(newPropVal) << "\n"; 242 return PLDM_ERROR; 243 } 244 auto currentValue = iter->second; 245 std::vector<uint8_t> handleIndices{ 246 getValueIndex(currentValue, possibleValues)}; 247 table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType, 248 handleIndices); 249 return PLDM_SUCCESS; 250 } 251 252 void BIOSEnumAttribute::generateAttributeEntry( 253 const std::variant<int64_t, std::string>& attributevalue, 254 Table& attrValueEntry) 255 { 256 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1); 257 258 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>( 259 attrValueEntry.data()); 260 261 std::string value = std::get<std::string>(attributevalue); 262 entry->attr_type = 0; 263 entry->value[0] = 1; // number of current values, default 1 264 265 if (readOnly) 266 { 267 entry->value[1] = getValueIndex(defaultValue, possibleValues); 268 } 269 else 270 { 271 entry->value[1] = getAttrValueIndex(value); 272 } 273 } 274 275 } // namespace bios 276 } // namespace responder 277 } // namespace pldm 278