blob: e878827c6bcc8f7d7d042e81f2da3e584290d10b [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{
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 }
34 assert(defaultValues.size() == 1);
35 defaultValue = defaultValues[0];
George Liudaa69232020-09-02 17:22:09 +080036 if (dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +080037 {
38 auto dbusValues = entry.at("dbus").at("property_values");
39 buildValMap(dbusValues);
40 }
41}
42
43uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value,
44 const std::vector<std::string>& pVs)
45{
46 auto iter = std::find_if(pVs.begin(), pVs.end(),
47 [&value](const auto& v) { return v == value; });
48 if (iter == pVs.end())
49 {
50 throw std::invalid_argument("value must be one of possible value");
51 }
52 return iter - pVs.begin();
53}
54
55std::vector<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle(
56 const BIOSStringTable& stringTable, const std::vector<std::string>& pVs)
57{
58 std::vector<uint16_t> possibleValuesHandle;
59 for (const auto& pv : pVs)
60 {
61 auto handle = stringTable.findHandle(pv);
62 possibleValuesHandle.push_back(handle);
63 }
64
65 return possibleValuesHandle;
66}
67
68void BIOSEnumAttribute::buildValMap(const Json& dbusVals)
69{
70 PropertyValue value;
71 size_t pos = 0;
72 for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos)
73 {
74 if (dBusMap->propertyType == "uint8_t")
75 {
76 value = static_cast<uint8_t>(it.value());
77 }
78 else if (dBusMap->propertyType == "uint16_t")
79 {
80 value = static_cast<uint16_t>(it.value());
81 }
82 else if (dBusMap->propertyType == "uint32_t")
83 {
84 value = static_cast<uint32_t>(it.value());
85 }
86 else if (dBusMap->propertyType == "uint64_t")
87 {
88 value = static_cast<uint64_t>(it.value());
89 }
90 else if (dBusMap->propertyType == "int16_t")
91 {
92 value = static_cast<int16_t>(it.value());
93 }
94 else if (dBusMap->propertyType == "int32_t")
95 {
96 value = static_cast<int32_t>(it.value());
97 }
98 else if (dBusMap->propertyType == "int64_t")
99 {
100 value = static_cast<int64_t>(it.value());
101 }
102 else if (dBusMap->propertyType == "bool")
103 {
104 value = static_cast<bool>(it.value());
105 }
106 else if (dBusMap->propertyType == "double")
107 {
108 value = static_cast<double>(it.value());
109 }
110 else if (dBusMap->propertyType == "string")
111 {
112 value = static_cast<std::string>(it.value());
113 }
114 else
115 {
116 std::cerr << "Unknown D-Bus property type, TYPE="
117 << dBusMap->propertyType << "\n";
118 throw std::invalid_argument("Unknown D-BUS property type");
119 }
120 valMap.emplace(value, possibleValues[pos]);
121 }
122}
123
124uint8_t BIOSEnumAttribute::getAttrValueIndex()
125{
126 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
George Liu5bb9edb2021-08-05 20:10:32 +0800127 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800128 {
129 return defaultValueIndex;
130 }
131
132 try
133 {
134 auto propValue = dbusHandler->getDbusPropertyVariant(
135 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
136 dBusMap->interface.c_str());
137 auto iter = valMap.find(propValue);
138 if (iter == valMap.end())
139 {
140 return defaultValueIndex;
141 }
142 auto currentValue = iter->second;
143 return getValueIndex(currentValue, possibleValues);
144 }
145 catch (const std::exception& e)
146 {
147 return defaultValueIndex;
148 }
149}
150
George Liu1244acf2020-08-14 09:11:11 +0800151uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue)
152{
George Liu1244acf2020-08-14 09:11:11 +0800153 try
154 {
George Liu6d6d1e82021-02-16 11:08:55 +0800155 return getValueIndex(std::get<std::string>(propValue), possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800156 }
157 catch (const std::exception& e)
158 {
George Liu6d6d1e82021-02-16 11:08:55 +0800159 return getValueIndex(defaultValue, possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800160 }
161}
162
John Wang3be70852020-02-13 15:59:04 +0800163void BIOSEnumAttribute::setAttrValueOnDbus(
164 const pldm_bios_attr_val_table_entry* attrValueEntry,
165 const pldm_bios_attr_table_entry* attrEntry,
166 const BIOSStringTable& stringTable)
167{
George Liu5bb9edb2021-08-05 20:10:32 +0800168 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800169 {
170 return;
171 }
172 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
173 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
174
175 assert(currHdls.size() == 1);
John Wang3be70852020-02-13 15:59:04 +0800176 auto valueString = stringTable.findString(pvHdls[currHdls[0]]);
177
178 auto it = std::find_if(valMap.begin(), valMap.end(),
179 [&valueString](const auto& typePair) {
180 return typePair.second == valueString;
181 });
182 if (it == valMap.end())
183 {
184 return;
185 }
186
187 dbusHandler->setDbusProperty(*dBusMap, it->first);
188}
189
Tom Josephca7b2522020-11-18 12:27:11 +0530190void BIOSEnumAttribute::constructEntry(
191 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
192 std::optional<std::variant<int64_t, std::string>> optAttributeValue)
John Wang3be70852020-02-13 15:59:04 +0800193{
194 auto possibleValuesHandle =
195 getPossibleValuesHandle(stringTable, possibleValues);
196 std::vector<uint8_t> defaultIndices(1, 0);
197 defaultIndices[0] = getValueIndex(defaultValue, possibleValues);
198
199 pldm_bios_table_attr_entry_enum_info info = {
200 stringTable.findHandle(name), readOnly,
201 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(),
202 (uint8_t)defaultIndices.size(), defaultIndices.data(),
203 };
204
205 auto attrTableEntry =
206 table::attribute::constructEnumEntry(attrTable, &info);
207 auto [attrHandle, attrType, _] =
208 table::attribute::decodeHeader(attrTableEntry);
209
210 std::vector<uint8_t> currValueIndices(1, 0);
Tom Josephca7b2522020-11-18 12:27:11 +0530211
212 if (optAttributeValue.has_value())
213 {
214 auto attributeValue = optAttributeValue.value();
215 if (attributeValue.index() == 1)
216 {
217 auto currValue = std::get<std::string>(attributeValue);
218 currValueIndices[0] = getValueIndex(currValue, possibleValues);
219 }
220 else
221 {
222 currValueIndices[0] = getAttrValueIndex();
223 }
224 }
225 else
226 {
227 currValueIndices[0] = getAttrValueIndex();
228 }
John Wang3be70852020-02-13 15:59:04 +0800229
230 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
231 attrType, currValueIndices);
232}
233
Sampa Misra46ece062020-03-18 07:17:44 -0500234int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
235 uint8_t attrType,
236 const PropertyValue& newPropVal)
237{
238 auto iter = valMap.find(newPropVal);
239 if (iter == valMap.end())
240 {
241 std::cerr << "Could not find index for new BIOS enum, value="
242 << std::get<std::string>(newPropVal) << "\n";
243 return PLDM_ERROR;
244 }
245 auto currentValue = iter->second;
246 std::vector<uint8_t> handleIndices{
247 getValueIndex(currentValue, possibleValues)};
248 table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType,
249 handleIndices);
250 return PLDM_SUCCESS;
251}
252
George Liu1244acf2020-08-14 09:11:11 +0800253void BIOSEnumAttribute::generateAttributeEntry(
254 const std::variant<int64_t, std::string>& attributevalue,
255 Table& attrValueEntry)
256{
257 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1);
258
259 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
260 attrValueEntry.data());
261
262 std::string value = std::get<std::string>(attributevalue);
263 entry->attr_type = 0;
264 entry->value[0] = 1; // number of current values, default 1
George Liu5bb9edb2021-08-05 20:10:32 +0800265 entry->value[1] = getAttrValueIndex(value);
George Liu1244acf2020-08-14 09:11:11 +0800266}
267
John Wang3be70852020-02-13 15:59:04 +0800268} // namespace bios
269} // namespace responder
Sampa Misra46ece062020-03-18 07:17:44 -0500270} // namespace pldm