blob: 2ce290909fab9c6cd44ac8fb49c2cfbffe5100b2 [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
Brad Bishop5079ac42021-08-19 18:35:06 -04009using namespace pldm::utils;
10
John Wang3be70852020-02-13 15:59:04 +080011namespace pldm
12{
13namespace responder
14{
15namespace bios
16{
17
18BIOSEnumAttribute::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];
George Liudaa69232020-09-02 17:22:09 +080037 if (dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +080038 {
39 auto dbusValues = entry.at("dbus").at("property_values");
40 buildValMap(dbusValues);
41 }
42}
43
44uint8_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
56std::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
69void 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
125uint8_t BIOSEnumAttribute::getAttrValueIndex()
126{
127 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
George Liudaa69232020-09-02 17:22:09 +0800128 if (readOnly || !dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800129 {
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
George Liu1244acf2020-08-14 09:11:11 +0800152uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue)
153{
George Liu1244acf2020-08-14 09:11:11 +0800154 try
155 {
George Liu6d6d1e82021-02-16 11:08:55 +0800156 return getValueIndex(std::get<std::string>(propValue), possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800157 }
158 catch (const std::exception& e)
159 {
George Liu6d6d1e82021-02-16 11:08:55 +0800160 return getValueIndex(defaultValue, possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800161 }
162}
163
John Wang3be70852020-02-13 15:59:04 +0800164void BIOSEnumAttribute::setAttrValueOnDbus(
165 const pldm_bios_attr_val_table_entry* attrValueEntry,
166 const pldm_bios_attr_table_entry* attrEntry,
167 const BIOSStringTable& stringTable)
168{
George Liudaa69232020-09-02 17:22:09 +0800169 if (readOnly || !dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800170 {
171 return;
172 }
173 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
174 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
175
176 assert(currHdls.size() == 1);
John Wang3be70852020-02-13 15:59:04 +0800177 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
Tom Josephca7b2522020-11-18 12:27:11 +0530191void BIOSEnumAttribute::constructEntry(
192 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
193 std::optional<std::variant<int64_t, std::string>> optAttributeValue)
John Wang3be70852020-02-13 15:59:04 +0800194{
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);
Tom Josephca7b2522020-11-18 12:27:11 +0530212
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 }
John Wang3be70852020-02-13 15:59:04 +0800230
231 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
232 attrType, currValueIndices);
233}
234
Sampa Misra46ece062020-03-18 07:17:44 -0500235int 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
George Liu1244acf2020-08-14 09:11:11 +0800254void 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
George Liudaa69232020-09-02 17:22:09 +0800266
George Liubcabada2021-03-12 15:07:39 +0800267 if (readOnly)
George Liudaa69232020-09-02 17:22:09 +0800268 {
269 entry->value[1] = getValueIndex(defaultValue, possibleValues);
270 }
George Liudaa69232020-09-02 17:22:09 +0800271 else
272 {
273 entry->value[1] = getAttrValueIndex(value);
274 }
George Liu1244acf2020-08-14 09:11:11 +0800275}
276
John Wang3be70852020-02-13 15:59:04 +0800277} // namespace bios
278} // namespace responder
Sampa Misra46ece062020-03-18 07:17:44 -0500279} // namespace pldm