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