1 #include "bios_integer_attribute.hpp"
2 
3 #include "common/utils.hpp"
4 
5 namespace pldm
6 {
7 namespace responder
8 {
9 namespace bios
10 {
11 
12 BIOSIntegerAttribute::BIOSIntegerAttribute(const Json& entry,
13                                            DBusHandler* const dbusHandler) :
14     BIOSAttribute(entry, dbusHandler)
15 {
16     std::string attr = entry.at("attribute_name");
17 
18     integerInfo.lowerBound = entry.at("lower_bound");
19     integerInfo.upperBound = entry.at("upper_bound");
20     integerInfo.scalarIncrement = entry.at("scalar_increment");
21     integerInfo.defaultValue = entry.at("default_value");
22     pldm_bios_table_attr_entry_integer_info info = {
23         0,
24         readOnly,
25         integerInfo.lowerBound,
26         integerInfo.upperBound,
27         integerInfo.scalarIncrement,
28         integerInfo.defaultValue,
29     };
30     const char* errmsg = nullptr;
31     auto rc = pldm_bios_table_attr_entry_integer_info_check(&info, &errmsg);
32     if (rc != PLDM_SUCCESS)
33     {
34         std::cerr << "Wrong filed for integer attribute, ATTRIBUTE_NAME="
35                   << attr.c_str() << " ERRMSG=" << errmsg
36                   << " LOWER_BOUND=" << integerInfo.lowerBound
37                   << " UPPER_BOUND=" << integerInfo.upperBound
38                   << " DEFAULT_VALUE=" << integerInfo.defaultValue
39                   << " SCALAR_INCREMENT=" << integerInfo.scalarIncrement
40                   << "\n";
41         throw std::invalid_argument("Wrong field for integer attribute");
42     }
43 }
44 
45 void BIOSIntegerAttribute::setAttrValueOnDbus(
46     const pldm_bios_attr_val_table_entry* attrValueEntry,
47     const pldm_bios_attr_table_entry*, const BIOSStringTable&)
48 {
49     if (readOnly || !dBusMap.has_value())
50     {
51         return;
52     }
53     auto currentValue =
54         table::attribute_value::decodeIntegerEntry(attrValueEntry);
55 
56     if (dBusMap->propertyType == "uint8_t")
57     {
58         return dbusHandler->setDbusProperty(*dBusMap,
59                                             static_cast<uint8_t>(currentValue));
60     }
61     else if (dBusMap->propertyType == "uint16_t")
62     {
63         return dbusHandler->setDbusProperty(
64             *dBusMap, static_cast<uint16_t>(currentValue));
65     }
66     else if (dBusMap->propertyType == "int16_t")
67     {
68         return dbusHandler->setDbusProperty(*dBusMap,
69                                             static_cast<int16_t>(currentValue));
70     }
71     else if (dBusMap->propertyType == "uint32_t")
72     {
73         return dbusHandler->setDbusProperty(
74             *dBusMap, static_cast<uint32_t>(currentValue));
75     }
76     else if (dBusMap->propertyType == "int32_t")
77     {
78         return dbusHandler->setDbusProperty(*dBusMap,
79                                             static_cast<int32_t>(currentValue));
80     }
81     else if (dBusMap->propertyType == "uint64_t")
82     {
83         return dbusHandler->setDbusProperty(*dBusMap, currentValue);
84     }
85     else if (dBusMap->propertyType == "int64_t")
86     {
87         return dbusHandler->setDbusProperty(*dBusMap,
88                                             static_cast<int64_t>(currentValue));
89     }
90     else if (dBusMap->propertyType == "double")
91     {
92         return dbusHandler->setDbusProperty(*dBusMap,
93                                             static_cast<double>(currentValue));
94     }
95 
96     std::cerr << "Unsupported property type on dbus: " << dBusMap->propertyType
97               << std::endl;
98     throw std::invalid_argument("dbus type error");
99 }
100 
101 void BIOSIntegerAttribute::constructEntry(
102     const BIOSStringTable& stringTable, Table& attrTable, Table& attrValueTable,
103     std::optional<std::variant<int64_t, std::string>> optAttributeValue)
104 {
105 
106     pldm_bios_table_attr_entry_integer_info info = {
107         stringTable.findHandle(name), readOnly,
108         integerInfo.lowerBound,       integerInfo.upperBound,
109         integerInfo.scalarIncrement,  integerInfo.defaultValue,
110     };
111 
112     auto attrTableEntry =
113         table::attribute::constructIntegerEntry(attrTable, &info);
114 
115     auto [attrHandle, attrType, _] =
116         table::attribute::decodeHeader(attrTableEntry);
117 
118     int64_t currentValue{};
119     if (optAttributeValue.has_value())
120     {
121         auto attributeValue = optAttributeValue.value();
122         if (attributeValue.index() == 0)
123         {
124             currentValue = std::get<int64_t>(attributeValue);
125         }
126         else
127         {
128             currentValue = getAttrValue();
129         }
130     }
131     else
132     {
133         currentValue = getAttrValue();
134     }
135 
136     table::attribute_value::constructIntegerEntry(attrValueTable, attrHandle,
137                                                   attrType, currentValue);
138 }
139 
140 uint64_t BIOSIntegerAttribute::getAttrValue(const PropertyValue& propertyValue)
141 {
142     uint64_t value = 0;
143     if (dBusMap->propertyType == "uint8_t")
144     {
145         value = std::get<uint8_t>(propertyValue);
146     }
147     else if (dBusMap->propertyType == "uint16_t")
148     {
149         value = std::get<uint16_t>(propertyValue);
150     }
151     else if (dBusMap->propertyType == "int16_t")
152     {
153         value = std::get<int16_t>(propertyValue);
154     }
155     else if (dBusMap->propertyType == "uint32_t")
156     {
157         value = std::get<uint32_t>(propertyValue);
158     }
159     else if (dBusMap->propertyType == "int32_t")
160     {
161         value = std::get<int32_t>(propertyValue);
162     }
163     else if (dBusMap->propertyType == "uint64_t")
164     {
165         value = std::get<uint64_t>(propertyValue);
166     }
167     else if (dBusMap->propertyType == "int64_t")
168     {
169         value = std::get<int64_t>(propertyValue);
170     }
171     else if (dBusMap->propertyType == "double")
172     {
173         value = std::get<double>(propertyValue);
174     }
175     else
176     {
177         std::cerr << "Unsupported property type for getAttrValue: "
178                   << dBusMap->propertyType << std::endl;
179         throw std::invalid_argument("dbus type error");
180     }
181     return value;
182 }
183 
184 uint64_t BIOSIntegerAttribute::getAttrValue()
185 {
186     if (readOnly || !dBusMap.has_value())
187     {
188         return integerInfo.defaultValue;
189     }
190 
191     try
192     {
193         auto propertyValue = dbusHandler->getDbusPropertyVariant(
194             dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
195             dBusMap->interface.c_str());
196 
197         return getAttrValue(propertyValue);
198     }
199     catch (const std::exception& e)
200     {
201         std::cerr << "Get Integer Attribute Value Error: AttributeName = "
202                   << name << std::endl;
203         return integerInfo.defaultValue;
204     }
205 }
206 
207 int BIOSIntegerAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
208                                         uint8_t attrType,
209                                         const PropertyValue& newPropVal)
210 {
211     auto newVal = getAttrValue(newPropVal);
212     table::attribute_value::constructIntegerEntry(newValue, attrHdl, attrType,
213                                                   newVal);
214     return PLDM_SUCCESS;
215 }
216 
217 void BIOSIntegerAttribute::generateAttributeEntry(
218     const std::variant<int64_t, std::string>& attributevalue,
219     Table& attrValueEntry)
220 {
221     attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) +
222                           sizeof(int64_t) - 1);
223 
224     auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
225         attrValueEntry.data());
226 
227     int64_t value = std::get<int64_t>(attributevalue);
228     entry->attr_type = 3;
229     memcpy(entry->value, &value, sizeof(int64_t));
230 }
231 
232 } // namespace bios
233 } // namespace responder
234 } // namespace pldm
235