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(const BIOSStringTable& stringTable, 199 Table& attrTable, Table& attrValueTable) 200 { 201 auto possibleValuesHandle = 202 getPossibleValuesHandle(stringTable, possibleValues); 203 std::vector<uint8_t> defaultIndices(1, 0); 204 defaultIndices[0] = getValueIndex(defaultValue, possibleValues); 205 206 pldm_bios_table_attr_entry_enum_info info = { 207 stringTable.findHandle(name), readOnly, 208 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(), 209 (uint8_t)defaultIndices.size(), defaultIndices.data(), 210 }; 211 212 auto attrTableEntry = 213 table::attribute::constructEnumEntry(attrTable, &info); 214 auto [attrHandle, attrType, _] = 215 table::attribute::decodeHeader(attrTableEntry); 216 217 std::vector<uint8_t> currValueIndices(1, 0); 218 currValueIndices[0] = getAttrValueIndex(); 219 220 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle, 221 attrType, currValueIndices); 222 } 223 224 int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl, 225 uint8_t attrType, 226 const PropertyValue& newPropVal) 227 { 228 auto iter = valMap.find(newPropVal); 229 if (iter == valMap.end()) 230 { 231 std::cerr << "Could not find index for new BIOS enum, value=" 232 << std::get<std::string>(newPropVal) << "\n"; 233 return PLDM_ERROR; 234 } 235 auto currentValue = iter->second; 236 std::vector<uint8_t> handleIndices{ 237 getValueIndex(currentValue, possibleValues)}; 238 table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType, 239 handleIndices); 240 return PLDM_SUCCESS; 241 } 242 243 void BIOSEnumAttribute::generateAttributeEntry( 244 const std::variant<int64_t, std::string>& attributevalue, 245 Table& attrValueEntry) 246 { 247 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1); 248 249 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>( 250 attrValueEntry.data()); 251 252 std::string value = std::get<std::string>(attributevalue); 253 entry->attr_type = 0; 254 entry->value[0] = 1; // number of current values, default 1 255 256 if (readOnly) 257 { 258 entry->value[1] = getValueIndex(defaultValue, possibleValues); 259 } 260 else if (!dBusMap.has_value()) 261 { 262 entry->value[1] = getValueIndex(value, possibleValues); 263 } 264 else 265 { 266 entry->value[1] = getAttrValueIndex(value); 267 } 268 } 269 270 } // namespace bios 271 } // namespace responder 272 } // namespace pldm 273