blob: f1f22c550e682dc5fc78f3b73f71c40fedab7622 [file] [log] [blame]
Sampa Misra46ece062020-03-18 07:17:44 -05001#include "config.h"
2
John Wang3be70852020-02-13 15:59:04 +08003#include "bios_enum_attribute.hpp"
4
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05005#include "common/utils.hpp"
John Wang3be70852020-02-13 15:59:04 +08006
7#include <iostream>
8
9namespace pldm
10{
11namespace responder
12{
13namespace bios
14{
15
16BIOSEnumAttribute::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];
George Liudaa69232020-09-02 17:22:09 +080035 if (dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +080036 {
37 auto dbusValues = entry.at("dbus").at("property_values");
38 buildValMap(dbusValues);
39 }
40}
41
42uint8_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
54std::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
67void 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
123uint8_t BIOSEnumAttribute::getAttrValueIndex()
124{
125 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
George Liudaa69232020-09-02 17:22:09 +0800126 if (readOnly || !dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800127 {
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
George Liu1244acf2020-08-14 09:11:11 +0800150uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue)
151{
George Liu1244acf2020-08-14 09:11:11 +0800152 try
153 {
George Liu6d6d1e82021-02-16 11:08:55 +0800154 return getValueIndex(std::get<std::string>(propValue), possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800155 }
156 catch (const std::exception& e)
157 {
George Liu6d6d1e82021-02-16 11:08:55 +0800158 return getValueIndex(defaultValue, possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800159 }
160}
161
John Wang3be70852020-02-13 15:59:04 +0800162void BIOSEnumAttribute::setAttrValueOnDbus(
163 const pldm_bios_attr_val_table_entry* attrValueEntry,
164 const pldm_bios_attr_table_entry* attrEntry,
165 const BIOSStringTable& stringTable)
166{
George Liudaa69232020-09-02 17:22:09 +0800167 if (readOnly || !dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800168 {
169 return;
170 }
171 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
172 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
173
174 assert(currHdls.size() == 1);
John Wang3be70852020-02-13 15:59:04 +0800175 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
Tom Josephca7b2522020-11-18 12:27:11 +0530189void BIOSEnumAttribute::constructEntry(
190 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
191 std::optional<std::variant<int64_t, std::string>> optAttributeValue)
John Wang3be70852020-02-13 15:59:04 +0800192{
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);
Tom Josephca7b2522020-11-18 12:27:11 +0530210
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 }
John Wang3be70852020-02-13 15:59:04 +0800228
229 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
230 attrType, currValueIndices);
231}
232
Sampa Misra46ece062020-03-18 07:17:44 -0500233int 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
George Liu1244acf2020-08-14 09:11:11 +0800252void 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
George Liudaa69232020-09-02 17:22:09 +0800264
George Liubcabada2021-03-12 15:07:39 +0800265 if (readOnly)
George Liudaa69232020-09-02 17:22:09 +0800266 {
267 entry->value[1] = getValueIndex(defaultValue, possibleValues);
268 }
George Liudaa69232020-09-02 17:22:09 +0800269 else
270 {
271 entry->value[1] = getAttrValueIndex(value);
272 }
George Liu1244acf2020-08-14 09:11:11 +0800273}
274
John Wang3be70852020-02-13 15:59:04 +0800275} // namespace bios
276} // namespace responder
Sampa Misra46ece062020-03-18 07:17:44 -0500277} // namespace pldm