blob: ba8895e34a7f540ad6c4636f29a14d080ae85c30 [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 }
36 assert(defaultValues.size() == 1);
37 defaultValue = defaultValues[0];
George Liudaa69232020-09-02 17:22:09 +080038 if (dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +080039 {
40 auto dbusValues = entry.at("dbus").at("property_values");
41 buildValMap(dbusValues);
42 }
43}
44
45uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value,
46 const std::vector<std::string>& pVs)
47{
48 auto iter = std::find_if(pVs.begin(), pVs.end(),
49 [&value](const auto& v) { return v == value; });
50 if (iter == pVs.end())
51 {
52 throw std::invalid_argument("value must be one of possible value");
53 }
54 return iter - pVs.begin();
55}
56
57std::vector<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle(
58 const BIOSStringTable& stringTable, const std::vector<std::string>& pVs)
59{
60 std::vector<uint16_t> possibleValuesHandle;
61 for (const auto& pv : pVs)
62 {
63 auto handle = stringTable.findHandle(pv);
64 possibleValuesHandle.push_back(handle);
65 }
66
67 return possibleValuesHandle;
68}
69
70void BIOSEnumAttribute::buildValMap(const Json& dbusVals)
71{
72 PropertyValue value;
73 size_t pos = 0;
74 for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos)
75 {
76 if (dBusMap->propertyType == "uint8_t")
77 {
78 value = static_cast<uint8_t>(it.value());
79 }
80 else if (dBusMap->propertyType == "uint16_t")
81 {
82 value = static_cast<uint16_t>(it.value());
83 }
84 else if (dBusMap->propertyType == "uint32_t")
85 {
86 value = static_cast<uint32_t>(it.value());
87 }
88 else if (dBusMap->propertyType == "uint64_t")
89 {
90 value = static_cast<uint64_t>(it.value());
91 }
92 else if (dBusMap->propertyType == "int16_t")
93 {
94 value = static_cast<int16_t>(it.value());
95 }
96 else if (dBusMap->propertyType == "int32_t")
97 {
98 value = static_cast<int32_t>(it.value());
99 }
100 else if (dBusMap->propertyType == "int64_t")
101 {
102 value = static_cast<int64_t>(it.value());
103 }
104 else if (dBusMap->propertyType == "bool")
105 {
106 value = static_cast<bool>(it.value());
107 }
108 else if (dBusMap->propertyType == "double")
109 {
110 value = static_cast<double>(it.value());
111 }
112 else if (dBusMap->propertyType == "string")
113 {
114 value = static_cast<std::string>(it.value());
115 }
116 else
117 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600118 error("Unknown D-Bus property type, TYPE={PROP_TYPE}", "PROP_TYPE",
119 dBusMap->propertyType);
John Wang3be70852020-02-13 15:59:04 +0800120 throw std::invalid_argument("Unknown D-BUS property type");
121 }
122 valMap.emplace(value, possibleValues[pos]);
123 }
124}
125
126uint8_t BIOSEnumAttribute::getAttrValueIndex()
127{
128 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
George Liu5bb9edb2021-08-05 20:10:32 +0800129 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800130 {
131 return defaultValueIndex;
132 }
133
134 try
135 {
136 auto propValue = dbusHandler->getDbusPropertyVariant(
137 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
138 dBusMap->interface.c_str());
139 auto iter = valMap.find(propValue);
140 if (iter == valMap.end())
141 {
142 return defaultValueIndex;
143 }
144 auto currentValue = iter->second;
145 return getValueIndex(currentValue, possibleValues);
146 }
147 catch (const std::exception& e)
148 {
149 return defaultValueIndex;
150 }
151}
152
George Liu1244acf2020-08-14 09:11:11 +0800153uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue)
154{
George Liu1244acf2020-08-14 09:11:11 +0800155 try
156 {
George Liu6d6d1e82021-02-16 11:08:55 +0800157 return getValueIndex(std::get<std::string>(propValue), possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800158 }
159 catch (const std::exception& e)
160 {
George Liu6d6d1e82021-02-16 11:08:55 +0800161 return getValueIndex(defaultValue, possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800162 }
163}
164
John Wang3be70852020-02-13 15:59:04 +0800165void BIOSEnumAttribute::setAttrValueOnDbus(
166 const pldm_bios_attr_val_table_entry* attrValueEntry,
167 const pldm_bios_attr_table_entry* attrEntry,
168 const BIOSStringTable& stringTable)
169{
George Liu5bb9edb2021-08-05 20:10:32 +0800170 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800171 {
172 return;
173 }
174 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
175 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
176
177 assert(currHdls.size() == 1);
John Wang3be70852020-02-13 15:59:04 +0800178 auto valueString = stringTable.findString(pvHdls[currHdls[0]]);
179
180 auto it = std::find_if(valMap.begin(), valMap.end(),
181 [&valueString](const auto& typePair) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500182 return typePair.second == valueString;
183 });
John Wang3be70852020-02-13 15:59:04 +0800184 if (it == valMap.end())
185 {
186 return;
187 }
188
189 dbusHandler->setDbusProperty(*dBusMap, it->first);
190}
191
Tom Josephca7b2522020-11-18 12:27:11 +0530192void BIOSEnumAttribute::constructEntry(
193 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
194 std::optional<std::variant<int64_t, std::string>> optAttributeValue)
John Wang3be70852020-02-13 15:59:04 +0800195{
Patrick Williams6da4f912023-05-10 07:50:53 -0500196 auto possibleValuesHandle = getPossibleValuesHandle(stringTable,
197 possibleValues);
John Wang3be70852020-02-13 15:59:04 +0800198 std::vector<uint8_t> defaultIndices(1, 0);
199 defaultIndices[0] = getValueIndex(defaultValue, possibleValues);
200
201 pldm_bios_table_attr_entry_enum_info info = {
202 stringTable.findHandle(name), readOnly,
203 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(),
204 (uint8_t)defaultIndices.size(), defaultIndices.data(),
205 };
206
Patrick Williams6da4f912023-05-10 07:50:53 -0500207 auto attrTableEntry = table::attribute::constructEnumEntry(attrTable,
208 &info);
209 auto [attrHandle, attrType,
210 _] = table::attribute::decodeHeader(attrTableEntry);
John Wang3be70852020-02-13 15:59:04 +0800211
212 std::vector<uint8_t> currValueIndices(1, 0);
Tom Josephca7b2522020-11-18 12:27:11 +0530213
214 if (optAttributeValue.has_value())
215 {
216 auto attributeValue = optAttributeValue.value();
217 if (attributeValue.index() == 1)
218 {
219 auto currValue = std::get<std::string>(attributeValue);
220 currValueIndices[0] = getValueIndex(currValue, possibleValues);
221 }
222 else
223 {
224 currValueIndices[0] = getAttrValueIndex();
225 }
226 }
227 else
228 {
229 currValueIndices[0] = getAttrValueIndex();
230 }
John Wang3be70852020-02-13 15:59:04 +0800231
232 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
233 attrType, currValueIndices);
234}
235
Sampa Misra46ece062020-03-18 07:17:44 -0500236int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
237 uint8_t attrType,
238 const PropertyValue& newPropVal)
239{
240 auto iter = valMap.find(newPropVal);
241 if (iter == valMap.end())
242 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600243 error("Could not find index for new BIOS enum, value={PROP_VAL}",
244 "PROP_VAL", std::get<std::string>(newPropVal));
Sampa Misra46ece062020-03-18 07:17:44 -0500245 return PLDM_ERROR;
246 }
247 auto currentValue = iter->second;
248 std::vector<uint8_t> handleIndices{
249 getValueIndex(currentValue, possibleValues)};
250 table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType,
251 handleIndices);
252 return PLDM_SUCCESS;
253}
254
George Liu1244acf2020-08-14 09:11:11 +0800255void BIOSEnumAttribute::generateAttributeEntry(
256 const std::variant<int64_t, std::string>& attributevalue,
257 Table& attrValueEntry)
258{
259 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1);
260
261 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
262 attrValueEntry.data());
263
264 std::string value = std::get<std::string>(attributevalue);
265 entry->attr_type = 0;
266 entry->value[0] = 1; // number of current values, default 1
George Liu5bb9edb2021-08-05 20:10:32 +0800267 entry->value[1] = getAttrValueIndex(value);
George Liu1244acf2020-08-14 09:11:11 +0800268}
269
John Wang3be70852020-02-13 15:59:04 +0800270} // namespace bios
271} // namespace responder
Sampa Misra46ece062020-03-18 07:17:44 -0500272} // namespace pldm