blob: 5d436c1b3d2a4311e88862ee89fea556c223e639 [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
Riya Dixit49cfb132023-03-02 04:26:53 -06007PHOSPHOR_LOG2_USING;
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{
John Wang3be70852020-02-13 15:59:04 +080017BIOSEnumAttribute::BIOSEnumAttribute(const Json& entry,
18 DBusHandler* const dbusHandler) :
19 BIOSAttribute(entry, dbusHandler)
20{
21 std::string attrName = entry.at("attribute_name");
22 Json pv = entry.at("possible_values");
23 for (auto& val : pv)
24 {
25 possibleValues.emplace_back(val);
26 }
27
28 std::vector<std::string> defaultValues;
29 Json dv = entry.at("default_values");
30 for (auto& val : dv)
31 {
32 defaultValues.emplace_back(val);
33 }
Sagar Srinivas7927f902023-10-09 07:53:00 -050034
35 Json vdn = entry.at("value_names");
36 for (auto& val : vdn)
37 {
38 valueDisplayNames.emplace_back(val);
39 }
John Wang3be70852020-02-13 15:59:04 +080040 assert(defaultValues.size() == 1);
41 defaultValue = defaultValues[0];
George Liudaa69232020-09-02 17:22:09 +080042 if (dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +080043 {
44 auto dbusValues = entry.at("dbus").at("property_values");
45 buildValMap(dbusValues);
46 }
47}
48
49uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value,
50 const std::vector<std::string>& pVs)
51{
52 auto iter = std::find_if(pVs.begin(), pVs.end(),
53 [&value](const auto& v) { return v == value; });
54 if (iter == pVs.end())
55 {
56 throw std::invalid_argument("value must be one of possible value");
57 }
58 return iter - pVs.begin();
59}
60
61std::vector<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle(
62 const BIOSStringTable& stringTable, const std::vector<std::string>& pVs)
63{
64 std::vector<uint16_t> possibleValuesHandle;
65 for (const auto& pv : pVs)
66 {
67 auto handle = stringTable.findHandle(pv);
68 possibleValuesHandle.push_back(handle);
69 }
70
71 return possibleValuesHandle;
72}
73
74void BIOSEnumAttribute::buildValMap(const Json& dbusVals)
75{
76 PropertyValue value;
77 size_t pos = 0;
78 for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos)
79 {
80 if (dBusMap->propertyType == "uint8_t")
81 {
82 value = static_cast<uint8_t>(it.value());
83 }
84 else if (dBusMap->propertyType == "uint16_t")
85 {
86 value = static_cast<uint16_t>(it.value());
87 }
88 else if (dBusMap->propertyType == "uint32_t")
89 {
90 value = static_cast<uint32_t>(it.value());
91 }
92 else if (dBusMap->propertyType == "uint64_t")
93 {
94 value = static_cast<uint64_t>(it.value());
95 }
96 else if (dBusMap->propertyType == "int16_t")
97 {
98 value = static_cast<int16_t>(it.value());
99 }
100 else if (dBusMap->propertyType == "int32_t")
101 {
102 value = static_cast<int32_t>(it.value());
103 }
104 else if (dBusMap->propertyType == "int64_t")
105 {
106 value = static_cast<int64_t>(it.value());
107 }
108 else if (dBusMap->propertyType == "bool")
109 {
110 value = static_cast<bool>(it.value());
111 }
112 else if (dBusMap->propertyType == "double")
113 {
114 value = static_cast<double>(it.value());
115 }
116 else if (dBusMap->propertyType == "string")
117 {
118 value = static_cast<std::string>(it.value());
119 }
120 else
121 {
Riya Dixit89644442024-03-31 05:39:59 -0500122 error("Unknown D-Bus property type '{TYPE}'", "TYPE",
Riya Dixit49cfb132023-03-02 04:26:53 -0600123 dBusMap->propertyType);
John Wang3be70852020-02-13 15:59:04 +0800124 throw std::invalid_argument("Unknown D-BUS property type");
125 }
126 valMap.emplace(value, possibleValues[pos]);
127 }
128}
129
130uint8_t BIOSEnumAttribute::getAttrValueIndex()
131{
132 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
George Liu5bb9edb2021-08-05 20:10:32 +0800133 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800134 {
135 return defaultValueIndex;
136 }
137
138 try
139 {
140 auto propValue = dbusHandler->getDbusPropertyVariant(
141 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
142 dBusMap->interface.c_str());
143 auto iter = valMap.find(propValue);
144 if (iter == valMap.end())
145 {
146 return defaultValueIndex;
147 }
148 auto currentValue = iter->second;
149 return getValueIndex(currentValue, possibleValues);
150 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500151 catch (const std::exception&)
John Wang3be70852020-02-13 15:59:04 +0800152 {
153 return defaultValueIndex;
154 }
155}
156
George Liu1244acf2020-08-14 09:11:11 +0800157uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue)
158{
George Liu1244acf2020-08-14 09:11:11 +0800159 try
160 {
George Liu6d6d1e82021-02-16 11:08:55 +0800161 return getValueIndex(std::get<std::string>(propValue), possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800162 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500163 catch (const std::exception&)
George Liu1244acf2020-08-14 09:11:11 +0800164 {
George Liu6d6d1e82021-02-16 11:08:55 +0800165 return getValueIndex(defaultValue, possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800166 }
167}
168
John Wang3be70852020-02-13 15:59:04 +0800169void BIOSEnumAttribute::setAttrValueOnDbus(
170 const pldm_bios_attr_val_table_entry* attrValueEntry,
171 const pldm_bios_attr_table_entry* attrEntry,
172 const BIOSStringTable& stringTable)
173{
George Liu5bb9edb2021-08-05 20:10:32 +0800174 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800175 {
176 return;
177 }
178 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
179 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
180
181 assert(currHdls.size() == 1);
John Wang3be70852020-02-13 15:59:04 +0800182 auto valueString = stringTable.findString(pvHdls[currHdls[0]]);
183
184 auto it = std::find_if(valMap.begin(), valMap.end(),
185 [&valueString](const auto& typePair) {
Patrick Williams6da4f912023-05-10 07:50:53 -0500186 return typePair.second == valueString;
187 });
John Wang3be70852020-02-13 15:59:04 +0800188 if (it == valMap.end())
189 {
190 return;
191 }
192
193 dbusHandler->setDbusProperty(*dBusMap, it->first);
194}
195
Sagar Srinivas7927f902023-10-09 07:53:00 -0500196void BIOSEnumAttribute::populateValueDisplayNamesMap(uint16_t attrHandle)
197{
198 for (auto& vdn : valueDisplayNames)
199 {
200 valueDisplayNamesMap[attrHandle].push_back(vdn);
201 }
202}
203
Tom Josephca7b2522020-11-18 12:27:11 +0530204void BIOSEnumAttribute::constructEntry(
205 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
206 std::optional<std::variant<int64_t, std::string>> optAttributeValue)
John Wang3be70852020-02-13 15:59:04 +0800207{
Patrick Williams6da4f912023-05-10 07:50:53 -0500208 auto possibleValuesHandle = getPossibleValuesHandle(stringTable,
209 possibleValues);
John Wang3be70852020-02-13 15:59:04 +0800210 std::vector<uint8_t> defaultIndices(1, 0);
211 defaultIndices[0] = getValueIndex(defaultValue, possibleValues);
212
213 pldm_bios_table_attr_entry_enum_info info = {
214 stringTable.findHandle(name), readOnly,
215 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(),
Sagar Srinivas7927f902023-10-09 07:53:00 -0500216 (uint8_t)defaultIndices.size(), defaultIndices.data()};
John Wang3be70852020-02-13 15:59:04 +0800217
Patrick Williams6da4f912023-05-10 07:50:53 -0500218 auto attrTableEntry = table::attribute::constructEnumEntry(attrTable,
219 &info);
220 auto [attrHandle, attrType,
221 _] = table::attribute::decodeHeader(attrTableEntry);
John Wang3be70852020-02-13 15:59:04 +0800222
Sagar Srinivas7927f902023-10-09 07:53:00 -0500223 populateValueDisplayNamesMap(attrHandle);
224
John Wang3be70852020-02-13 15:59:04 +0800225 std::vector<uint8_t> currValueIndices(1, 0);
Tom Josephca7b2522020-11-18 12:27:11 +0530226
227 if (optAttributeValue.has_value())
228 {
229 auto attributeValue = optAttributeValue.value();
230 if (attributeValue.index() == 1)
231 {
232 auto currValue = std::get<std::string>(attributeValue);
233 currValueIndices[0] = getValueIndex(currValue, possibleValues);
234 }
235 else
236 {
237 currValueIndices[0] = getAttrValueIndex();
238 }
239 }
240 else
241 {
242 currValueIndices[0] = getAttrValueIndex();
243 }
John Wang3be70852020-02-13 15:59:04 +0800244
245 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
246 attrType, currValueIndices);
247}
248
Sampa Misra46ece062020-03-18 07:17:44 -0500249int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
250 uint8_t attrType,
251 const PropertyValue& newPropVal)
252{
253 auto iter = valMap.find(newPropVal);
254 if (iter == valMap.end())
255 {
Riya Dixit89644442024-03-31 05:39:59 -0500256 error("Failed to find index for new BIOS enum value '{VALUE}'", "VALUE",
257 std::get<std::string>(newPropVal));
Sampa Misra46ece062020-03-18 07:17:44 -0500258 return PLDM_ERROR;
259 }
260 auto currentValue = iter->second;
261 std::vector<uint8_t> handleIndices{
262 getValueIndex(currentValue, possibleValues)};
263 table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType,
264 handleIndices);
265 return PLDM_SUCCESS;
266}
267
George Liu1244acf2020-08-14 09:11:11 +0800268void BIOSEnumAttribute::generateAttributeEntry(
269 const std::variant<int64_t, std::string>& attributevalue,
270 Table& attrValueEntry)
271{
272 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1);
273
274 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
275 attrValueEntry.data());
276
277 std::string value = std::get<std::string>(attributevalue);
278 entry->attr_type = 0;
279 entry->value[0] = 1; // number of current values, default 1
George Liu5bb9edb2021-08-05 20:10:32 +0800280 entry->value[1] = getAttrValueIndex(value);
George Liu1244acf2020-08-14 09:11:11 +0800281}
282
John Wang3be70852020-02-13 15:59:04 +0800283} // namespace bios
284} // namespace responder
Sampa Misra46ece062020-03-18 07:17:44 -0500285} // namespace pldm