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