blob: 7197553d47fd86b769e5915123c0eccf7922adf9 [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
Riya Dixit49cfb132023-03-02 04:26:53 -06007#include <phosphor-logging/lg2.hpp>
8
John Wang3be70852020-02-13 15:59:04 +08009#include <iostream>
10
Riya Dixit49cfb132023-03-02 04:26:53 -060011PHOSPHOR_LOG2_USING;
12
Brad Bishop5079ac42021-08-19 18:35:06 -040013using namespace pldm::utils;
14
John Wang3be70852020-02-13 15:59:04 +080015namespace pldm
16{
17namespace responder
18{
19namespace bios
20{
John Wang3be70852020-02-13 15:59:04 +080021BIOSEnumAttribute::BIOSEnumAttribute(const Json& entry,
22 DBusHandler* const dbusHandler) :
23 BIOSAttribute(entry, dbusHandler)
24{
25 std::string attrName = entry.at("attribute_name");
26 Json pv = entry.at("possible_values");
27 for (auto& val : pv)
28 {
29 possibleValues.emplace_back(val);
30 }
31
32 std::vector<std::string> defaultValues;
33 Json dv = entry.at("default_values");
34 for (auto& val : dv)
35 {
36 defaultValues.emplace_back(val);
37 }
38 assert(defaultValues.size() == 1);
39 defaultValue = defaultValues[0];
George Liudaa69232020-09-02 17:22:09 +080040 if (dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +080041 {
42 auto dbusValues = entry.at("dbus").at("property_values");
43 buildValMap(dbusValues);
44 }
45}
46
47uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value,
48 const std::vector<std::string>& pVs)
49{
50 auto iter = std::find_if(pVs.begin(), pVs.end(),
51 [&value](const auto& v) { return v == value; });
52 if (iter == pVs.end())
53 {
54 throw std::invalid_argument("value must be one of possible value");
55 }
56 return iter - pVs.begin();
57}
58
59std::vector<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle(
60 const BIOSStringTable& stringTable, const std::vector<std::string>& pVs)
61{
62 std::vector<uint16_t> possibleValuesHandle;
63 for (const auto& pv : pVs)
64 {
65 auto handle = stringTable.findHandle(pv);
66 possibleValuesHandle.push_back(handle);
67 }
68
69 return possibleValuesHandle;
70}
71
72void BIOSEnumAttribute::buildValMap(const Json& dbusVals)
73{
74 PropertyValue value;
75 size_t pos = 0;
76 for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos)
77 {
78 if (dBusMap->propertyType == "uint8_t")
79 {
80 value = static_cast<uint8_t>(it.value());
81 }
82 else if (dBusMap->propertyType == "uint16_t")
83 {
84 value = static_cast<uint16_t>(it.value());
85 }
86 else if (dBusMap->propertyType == "uint32_t")
87 {
88 value = static_cast<uint32_t>(it.value());
89 }
90 else if (dBusMap->propertyType == "uint64_t")
91 {
92 value = static_cast<uint64_t>(it.value());
93 }
94 else if (dBusMap->propertyType == "int16_t")
95 {
96 value = static_cast<int16_t>(it.value());
97 }
98 else if (dBusMap->propertyType == "int32_t")
99 {
100 value = static_cast<int32_t>(it.value());
101 }
102 else if (dBusMap->propertyType == "int64_t")
103 {
104 value = static_cast<int64_t>(it.value());
105 }
106 else if (dBusMap->propertyType == "bool")
107 {
108 value = static_cast<bool>(it.value());
109 }
110 else if (dBusMap->propertyType == "double")
111 {
112 value = static_cast<double>(it.value());
113 }
114 else if (dBusMap->propertyType == "string")
115 {
116 value = static_cast<std::string>(it.value());
117 }
118 else
119 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600120 error("Unknown D-Bus property type, TYPE={PROP_TYPE}", "PROP_TYPE",
121 dBusMap->propertyType);
John Wang3be70852020-02-13 15:59:04 +0800122 throw std::invalid_argument("Unknown D-BUS property type");
123 }
124 valMap.emplace(value, possibleValues[pos]);
125 }
126}
127
128uint8_t BIOSEnumAttribute::getAttrValueIndex()
129{
130 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
George Liu5bb9edb2021-08-05 20:10:32 +0800131 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800132 {
133 return defaultValueIndex;
134 }
135
136 try
137 {
138 auto propValue = dbusHandler->getDbusPropertyVariant(
139 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
140 dBusMap->interface.c_str());
141 auto iter = valMap.find(propValue);
142 if (iter == valMap.end())
143 {
144 return defaultValueIndex;
145 }
146 auto currentValue = iter->second;
147 return getValueIndex(currentValue, possibleValues);
148 }
149 catch (const std::exception& e)
150 {
151 return defaultValueIndex;
152 }
153}
154
George Liu1244acf2020-08-14 09:11:11 +0800155uint8_t BIOSEnumAttribute::getAttrValueIndex(const PropertyValue& propValue)
156{
George Liu1244acf2020-08-14 09:11:11 +0800157 try
158 {
George Liu6d6d1e82021-02-16 11:08:55 +0800159 return getValueIndex(std::get<std::string>(propValue), possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800160 }
161 catch (const std::exception& e)
162 {
George Liu6d6d1e82021-02-16 11:08:55 +0800163 return getValueIndex(defaultValue, possibleValues);
George Liu1244acf2020-08-14 09:11:11 +0800164 }
165}
166
John Wang3be70852020-02-13 15:59:04 +0800167void BIOSEnumAttribute::setAttrValueOnDbus(
168 const pldm_bios_attr_val_table_entry* attrValueEntry,
169 const pldm_bios_attr_table_entry* attrEntry,
170 const BIOSStringTable& stringTable)
171{
George Liu5bb9edb2021-08-05 20:10:32 +0800172 if (!dBusMap.has_value())
John Wang3be70852020-02-13 15:59:04 +0800173 {
174 return;
175 }
176 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
177 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
178
179 assert(currHdls.size() == 1);
John Wang3be70852020-02-13 15:59:04 +0800180 auto valueString = stringTable.findString(pvHdls[currHdls[0]]);
181
182 auto it = std::find_if(valMap.begin(), valMap.end(),
183 [&valueString](const auto& typePair) {
184 return typePair.second == valueString;
185 });
186 if (it == valMap.end())
187 {
188 return;
189 }
190
191 dbusHandler->setDbusProperty(*dBusMap, it->first);
192}
193
Tom Josephca7b2522020-11-18 12:27:11 +0530194void BIOSEnumAttribute::constructEntry(
195 const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
196 std::optional<std::variant<int64_t, std::string>> optAttributeValue)
John Wang3be70852020-02-13 15:59:04 +0800197{
198 auto possibleValuesHandle =
199 getPossibleValuesHandle(stringTable, possibleValues);
200 std::vector<uint8_t> defaultIndices(1, 0);
201 defaultIndices[0] = getValueIndex(defaultValue, possibleValues);
202
203 pldm_bios_table_attr_entry_enum_info info = {
204 stringTable.findHandle(name), readOnly,
205 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(),
206 (uint8_t)defaultIndices.size(), defaultIndices.data(),
207 };
208
209 auto attrTableEntry =
210 table::attribute::constructEnumEntry(attrTable, &info);
211 auto [attrHandle, attrType, _] =
212 table::attribute::decodeHeader(attrTableEntry);
213
214 std::vector<uint8_t> currValueIndices(1, 0);
Tom Josephca7b2522020-11-18 12:27:11 +0530215
216 if (optAttributeValue.has_value())
217 {
218 auto attributeValue = optAttributeValue.value();
219 if (attributeValue.index() == 1)
220 {
221 auto currValue = std::get<std::string>(attributeValue);
222 currValueIndices[0] = getValueIndex(currValue, possibleValues);
223 }
224 else
225 {
226 currValueIndices[0] = getAttrValueIndex();
227 }
228 }
229 else
230 {
231 currValueIndices[0] = getAttrValueIndex();
232 }
John Wang3be70852020-02-13 15:59:04 +0800233
234 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
235 attrType, currValueIndices);
236}
237
Sampa Misra46ece062020-03-18 07:17:44 -0500238int BIOSEnumAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
239 uint8_t attrType,
240 const PropertyValue& newPropVal)
241{
242 auto iter = valMap.find(newPropVal);
243 if (iter == valMap.end())
244 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600245 error("Could not find index for new BIOS enum, value={PROP_VAL}",
246 "PROP_VAL", std::get<std::string>(newPropVal));
Sampa Misra46ece062020-03-18 07:17:44 -0500247 return PLDM_ERROR;
248 }
249 auto currentValue = iter->second;
250 std::vector<uint8_t> handleIndices{
251 getValueIndex(currentValue, possibleValues)};
252 table::attribute_value::constructEnumEntry(newValue, attrHdl, attrType,
253 handleIndices);
254 return PLDM_SUCCESS;
255}
256
George Liu1244acf2020-08-14 09:11:11 +0800257void BIOSEnumAttribute::generateAttributeEntry(
258 const std::variant<int64_t, std::string>& attributevalue,
259 Table& attrValueEntry)
260{
261 attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) + 1);
262
263 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
264 attrValueEntry.data());
265
266 std::string value = std::get<std::string>(attributevalue);
267 entry->attr_type = 0;
268 entry->value[0] = 1; // number of current values, default 1
George Liu5bb9edb2021-08-05 20:10:32 +0800269 entry->value[1] = getAttrValueIndex(value);
George Liu1244acf2020-08-14 09:11:11 +0800270}
271
John Wang3be70852020-02-13 15:59:04 +0800272} // namespace bios
273} // namespace responder
Sampa Misra46ece062020-03-18 07:17:44 -0500274} // namespace pldm