blob: 7d7cba4fdafd58e3444531c8a427d61f9d4d0ed3 [file] [log] [blame]
John Wang3be70852020-02-13 15:59:04 +08001#include "bios_enum_attribute.hpp"
2
3#include "utils.hpp"
4
5#include <iostream>
6
7namespace pldm
8{
9namespace responder
10{
11namespace bios
12{
13
14BIOSEnumAttribute::BIOSEnumAttribute(const Json& entry,
15 DBusHandler* const dbusHandler) :
16 BIOSAttribute(entry, dbusHandler)
17{
18 std::string attrName = entry.at("attribute_name");
19 Json pv = entry.at("possible_values");
20 for (auto& val : pv)
21 {
22 possibleValues.emplace_back(val);
23 }
24
25 std::vector<std::string> defaultValues;
26 Json dv = entry.at("default_values");
27 for (auto& val : dv)
28 {
29 defaultValues.emplace_back(val);
30 }
31 assert(defaultValues.size() == 1);
32 defaultValue = defaultValues[0];
33 if (!readOnly)
34 {
35 auto dbusValues = entry.at("dbus").at("property_values");
36 buildValMap(dbusValues);
37 }
38}
39
40uint8_t BIOSEnumAttribute::getValueIndex(const std::string& value,
41 const std::vector<std::string>& pVs)
42{
43 auto iter = std::find_if(pVs.begin(), pVs.end(),
44 [&value](const auto& v) { return v == value; });
45 if (iter == pVs.end())
46 {
47 throw std::invalid_argument("value must be one of possible value");
48 }
49 return iter - pVs.begin();
50}
51
52std::vector<uint16_t> BIOSEnumAttribute::getPossibleValuesHandle(
53 const BIOSStringTable& stringTable, const std::vector<std::string>& pVs)
54{
55 std::vector<uint16_t> possibleValuesHandle;
56 for (const auto& pv : pVs)
57 {
58 auto handle = stringTable.findHandle(pv);
59 possibleValuesHandle.push_back(handle);
60 }
61
62 return possibleValuesHandle;
63}
64
65void BIOSEnumAttribute::buildValMap(const Json& dbusVals)
66{
67 PropertyValue value;
68 size_t pos = 0;
69 for (auto it = dbusVals.begin(); it != dbusVals.end(); ++it, ++pos)
70 {
71 if (dBusMap->propertyType == "uint8_t")
72 {
73 value = static_cast<uint8_t>(it.value());
74 }
75 else if (dBusMap->propertyType == "uint16_t")
76 {
77 value = static_cast<uint16_t>(it.value());
78 }
79 else if (dBusMap->propertyType == "uint32_t")
80 {
81 value = static_cast<uint32_t>(it.value());
82 }
83 else if (dBusMap->propertyType == "uint64_t")
84 {
85 value = static_cast<uint64_t>(it.value());
86 }
87 else if (dBusMap->propertyType == "int16_t")
88 {
89 value = static_cast<int16_t>(it.value());
90 }
91 else if (dBusMap->propertyType == "int32_t")
92 {
93 value = static_cast<int32_t>(it.value());
94 }
95 else if (dBusMap->propertyType == "int64_t")
96 {
97 value = static_cast<int64_t>(it.value());
98 }
99 else if (dBusMap->propertyType == "bool")
100 {
101 value = static_cast<bool>(it.value());
102 }
103 else if (dBusMap->propertyType == "double")
104 {
105 value = static_cast<double>(it.value());
106 }
107 else if (dBusMap->propertyType == "string")
108 {
109 value = static_cast<std::string>(it.value());
110 }
111 else
112 {
113 std::cerr << "Unknown D-Bus property type, TYPE="
114 << dBusMap->propertyType << "\n";
115 throw std::invalid_argument("Unknown D-BUS property type");
116 }
117 valMap.emplace(value, possibleValues[pos]);
118 }
119}
120
121uint8_t BIOSEnumAttribute::getAttrValueIndex()
122{
123 auto defaultValueIndex = getValueIndex(defaultValue, possibleValues);
124 if (readOnly)
125 {
126 return defaultValueIndex;
127 }
128
129 try
130 {
131 auto propValue = dbusHandler->getDbusPropertyVariant(
132 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
133 dBusMap->interface.c_str());
134 auto iter = valMap.find(propValue);
135 if (iter == valMap.end())
136 {
137 return defaultValueIndex;
138 }
139 auto currentValue = iter->second;
140 return getValueIndex(currentValue, possibleValues);
141 }
142 catch (const std::exception& e)
143 {
144 return defaultValueIndex;
145 }
146}
147
148void BIOSEnumAttribute::setAttrValueOnDbus(
149 const pldm_bios_attr_val_table_entry* attrValueEntry,
150 const pldm_bios_attr_table_entry* attrEntry,
151 const BIOSStringTable& stringTable)
152{
153 if (readOnly)
154 {
155 return;
156 }
157 auto [pvHdls, _] = table::attribute::decodeEnumEntry(attrEntry);
158 auto currHdls = table::attribute_value::decodeEnumEntry(attrValueEntry);
159
160 assert(currHdls.size() == 1);
161
162 auto valueString = stringTable.findString(pvHdls[currHdls[0]]);
163
164 auto it = std::find_if(valMap.begin(), valMap.end(),
165 [&valueString](const auto& typePair) {
166 return typePair.second == valueString;
167 });
168 if (it == valMap.end())
169 {
170 return;
171 }
172
173 dbusHandler->setDbusProperty(*dBusMap, it->first);
174}
175
176void BIOSEnumAttribute::constructEntry(const BIOSStringTable& stringTable,
177 Table& attrTable, Table& attrValueTable)
178{
179 auto possibleValuesHandle =
180 getPossibleValuesHandle(stringTable, possibleValues);
181 std::vector<uint8_t> defaultIndices(1, 0);
182 defaultIndices[0] = getValueIndex(defaultValue, possibleValues);
183
184 pldm_bios_table_attr_entry_enum_info info = {
185 stringTable.findHandle(name), readOnly,
186 (uint8_t)possibleValuesHandle.size(), possibleValuesHandle.data(),
187 (uint8_t)defaultIndices.size(), defaultIndices.data(),
188 };
189
190 auto attrTableEntry =
191 table::attribute::constructEnumEntry(attrTable, &info);
192 auto [attrHandle, attrType, _] =
193 table::attribute::decodeHeader(attrTableEntry);
194
195 std::vector<uint8_t> currValueIndices(1, 0);
196 currValueIndices[0] = getAttrValueIndex();
197
198 table::attribute_value::constructEnumEntry(attrValueTable, attrHandle,
199 attrType, currValueIndices);
200}
201
202} // namespace bios
203} // namespace responder
204} // namespace pldm