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