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