blob: 3f5272f226bf42118e284c4424bd82a25c3152e2 [file] [log] [blame]
John Wang3be70852020-02-13 15:59:04 +08001#include "bios_enum_attribute.hpp"
2
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05003#include "common/utils.hpp"
John Wang3be70852020-02-13 15:59:04 +08004
Riya Dixit49cfb132023-03-02 04:26:53 -06005#include <phosphor-logging/lg2.hpp>
6
John Wang3be70852020-02-13 15:59:04 +08007#include <iostream>
8
Riya Dixit49cfb132023-03-02 04:26:53 -06009PHOSPHOR_LOG2_USING;
10
Brad Bishop5079ac42021-08-19 18:35:06 -040011using namespace pldm::utils;
12
John Wang3be70852020-02-13 15:59:04 +080013namespace pldm
14{
15namespace responder
16{
17namespace bios
18{
John Wang3be70852020-02-13 15:59:04 +080019BIOSEnumAttribute::BIOSEnumAttribute(const Json& entry,
20 DBusHandler* const dbusHandler) :
21 BIOSAttribute(entry, dbusHandler)
22{
23 std::string attrName = entry.at("attribute_name");
24 Json pv = entry.at("possible_values");
25 for (auto& val : pv)
26 {
27 possibleValues.emplace_back(val);
28 }
29
30 std::vector<std::string> defaultValues;
31 Json dv = entry.at("default_values");
32 for (auto& val : dv)
33 {
34 defaultValues.emplace_back(val);
35 }
Sagar Srinivas7927f902023-10-09 07:53:00 -050036
37 Json vdn = entry.at("value_names");
38 for (auto& val : vdn)
39 {
40 valueDisplayNames.emplace_back(val);
41 }
John Wang3be70852020-02-13 15:59:04 +080042 assert(defaultValues.size() == 1);
43 defaultValue = defaultValues[0];
George Liudaa69232020-09-02 17:22:09 +080044 if (dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +080045 {
46 auto dbusValues = entry.at("dbus").at("property_values");
47 buildValMap(dbusValues);
48 }
49}
50
51uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value,
52 const std::vector<std::string>& pVs)
53{
54 auto iter = std::find_if(pVs.begin(), pVs.end(),
55 [&value](const auto& v) { return v == value; });
56 if (iter == pVs.end())
57 {
58 throw std::invalid_argument("value must be one of possible value");
59 }
60 return iter - pVs.begin();
61}
62
63std::vector<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle(
64 const BIOSStringTable& stringTable, const std::vector<std::string>& pVs)
65{
66 std::vector<uint16_t> possibleValuesHandle;
67 for (const auto& pv : pVs)
68 {
69 auto handle = stringTable.findHandle(pv);
70 possibleValuesHandle.push_back(handle);
71 }
72
73 return possibleValuesHandle;
74}
75
76void BIOSEnumAttribute::buildValMap(const Json& dbusVals)
77{
78 PropertyValue value;
79 size_t pos = 0;
80 for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos)
81 {
82 if (dBusMap->propertyType == "uint8_t")
83 {
84 value = static_cast<uint8_t>(it.value());
85 }
86 else if (dBusMap->propertyType == "uint16_t")
87 {
88 value = static_cast<uint16_t>(it.value());
89 }
90 else if (dBusMap->propertyType == "uint32_t")
91 {
92 value = static_cast<uint32_t>(it.value());
93 }
94 else if (dBusMap->propertyType == "uint64_t")
95 {
96 value = static_cast<uint64_t>(it.value());
97 }
98 else if (dBusMap->propertyType == "int16_t")
99 {
100 value = static_cast<int16_t>(it.value());
101 }
102 else if (dBusMap->propertyType == "int32_t")
103 {
104 value = static_cast<int32_t>(it.value());
105 }
106 else if (dBusMap->propertyType == "int64_t")
107 {
108 value = static_cast<int64_t>(it.value());
109 }
110 else if (dBusMap->propertyType == "bool")
111 {
112 value = static_cast<bool>(it.value());
113 }
114 else if (dBusMap->propertyType == "double")
115 {
116 value = static_cast<double>(it.value());
117 }
118 else if (dBusMap->propertyType == "string")
119 {
120 value = static_cast<std::string>(it.value());
121 }
122 else
123 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600124 error("Unknown D-Bus property type, TYPE={PROP_TYPE}", "PROP_TYPE",
125 dBusMap->propertyType);
John Wang3be70852020-02-13 15:59:04 +0800126 throw std::invalid_argument("Unknown D-BUS property type");
127 }
128 valMap.emplace(value, possibleValues[pos]);
129 }
130}
131
132uint8_t BIOSEnumAttribute::getAttrValueIndex()
133{
134 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
George Liu5bb9edb2021-08-05 20:10:32 +0800135 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800136 {
137 return defaultValueIndex;
138 }
139
140 try
141 {
142 auto propValue = dbusHandler->getDbusPropertyVariant(
143 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
144 dBusMap->interface.c_str());
145 auto iter = valMap.find(propValue);
146 if (iter == valMap.end())
147 {
148 return defaultValueIndex;
149 }
150 auto currentValue = iter->second;
151 return getValueIndex(currentValue, possibleValues);
152 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500153 catch (const std::exception&)
John Wang3be70852020-02-13 15:59:04 +0800154 {
155 return defaultValueIndex;
156 }
157}
158
George Liu1244acf2020-08-14 09:11:11 +0800159uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue)
160{
George Liu1244acf2020-08-14 09:11:11 +0800161 try
162 {
George Liu6d6d1e82021-02-16 11:08:55 +0800163 return getValueIndex(std::get<std::string>(propValue), possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800164 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500165 catch (const std::exception&)
George Liu1244acf2020-08-14 09:11:11 +0800166 {
George Liu6d6d1e82021-02-16 11:08:55 +0800167 return getValueIndex(defaultValue, possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800168 }
169}
170
John Wang3be70852020-02-13 15:59:04 +0800171void BIOSEnumAttribute::setAttrValueOnDbus(
172 const pldm_bios_attr_val_table_entry* attrValueEntry,
173 const pldm_bios_attr_table_entry* attrEntry,
174 const BIOSStringTable& stringTable)
175{
George Liu5bb9edb2021-08-05 20:10:32 +0800176 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800177 {
178 return;
179 }
180 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
181 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
182
183 assert(currHdls.size() == 1);
John Wang3be70852020-02-13 15:59:04 +0800184 auto valueString = stringTable.findString(pvHdls[currHdls[0]]);
185
186 auto it = std::find_if(valMap.begin(), valMap.end(),
187 [&valueString](const auto& typePair) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500188 return typePair.second == valueString;
189 });
John Wang3be70852020-02-13 15:59:04 +0800190 if (it == valMap.end())
191 {
192 return;
193 }
194
195 dbusHandler->setDbusProperty(*dBusMap, it->first);
196}
197
Sagar Srinivas7927f902023-10-09 07:53:00 -0500198void BIOSEnumAttribute::populateValueDisplayNamesMap(uint16_t attrHandle)
199{
200 for (auto& vdn : valueDisplayNames)
201 {
202 valueDisplayNamesMap[attrHandle].push_back(vdn);
203 }
204}
205
Tom Josephca7b2522020-11-18 12:27:11 +0530206void BIOSEnumAttribute::constructEntry(
207 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
208 std::optional<std::variant<int64_t, std::string>> optAttributeValue)
John Wang3be70852020-02-13 15:59:04 +0800209{
Patrick Williams6da4f912023-05-10 07:50:53 -0500210 auto possibleValuesHandle = getPossibleValuesHandle(stringTable,
211 possibleValues);
John Wang3be70852020-02-13 15:59:04 +0800212 std::vector<uint8_t> defaultIndices(1, 0);
213 defaultIndices[0] = getValueIndex(defaultValue, possibleValues);
214
215 pldm_bios_table_attr_entry_enum_info info = {
216 stringTable.findHandle(name), readOnly,
217 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(),
Sagar Srinivas7927f902023-10-09 07:53:00 -0500218 (uint8_t)defaultIndices.size(), defaultIndices.data()};
John Wang3be70852020-02-13 15:59:04 +0800219
Patrick Williams6da4f912023-05-10 07:50:53 -0500220 auto attrTableEntry = table::attribute::constructEnumEntry(attrTable,
221 &info);
222 auto [attrHandle, attrType,
223 _] = table::attribute::decodeHeader(attrTableEntry);
John Wang3be70852020-02-13 15:59:04 +0800224
Sagar Srinivas7927f902023-10-09 07:53:00 -0500225 populateValueDisplayNamesMap(attrHandle);
226
John Wang3be70852020-02-13 15:59:04 +0800227 std::vector<uint8_t> currValueIndices(1, 0);
Tom Josephca7b2522020-11-18 12:27:11 +0530228
229 if (optAttributeValue.has_value())
230 {
231 auto attributeValue = optAttributeValue.value();
232 if (attributeValue.index() == 1)
233 {
234 auto currValue = std::get<std::string>(attributeValue);
235 currValueIndices[0] = getValueIndex(currValue, possibleValues);
236 }
237 else
238 {
239 currValueIndices[0] = getAttrValueIndex();
240 }
241 }
242 else
243 {
244 currValueIndices[0] = getAttrValueIndex();
245 }
John Wang3be70852020-02-13 15:59:04 +0800246
247 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
248 attrType, currValueIndices);
249}
250
Sampa Misra46ece062020-03-18 07:17:44 -0500251int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
252 uint8_t attrType,
253 const PropertyValue& newPropVal)
254{
255 auto iter = valMap.find(newPropVal);
256 if (iter == valMap.end())
257 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600258 error("Could not find index for new BIOS enum, value={PROP_VAL}",
259 "PROP_VAL", std::get<std::string>(newPropVal));
Sampa Misra46ece062020-03-18 07:17:44 -0500260 return PLDM_ERROR;
261 }
262 auto currentValue = iter->second;
263 std::vector<uint8_t> handleIndices{
264 getValueIndex(currentValue, possibleValues)};
265 table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType,
266 handleIndices);
267 return PLDM_SUCCESS;
268}
269
George Liu1244acf2020-08-14 09:11:11 +0800270void BIOSEnumAttribute::generateAttributeEntry(
271 const std::variant<int64_t, std::string>& attributevalue,
272 Table& attrValueEntry)
273{
274 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1);
275
276 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
277 attrValueEntry.data());
278
279 std::string value = std::get<std::string>(attributevalue);
280 entry->attr_type = 0;
281 entry->value[0] = 1; // number of current values, default 1
George Liu5bb9edb2021-08-05 20:10:32 +0800282 entry->value[1] = getAttrValueIndex(value);
George Liu1244acf2020-08-14 09:11:11 +0800283}
284
John Wang3be70852020-02-13 15:59:04 +0800285} // namespace bios
286} // namespace responder
Sampa Misra46ece062020-03-18 07:17:44 -0500287} // namespace pldm