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 (readOnly || !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 
108     pldm_bios_table_attr_entry_integer_info info = {
109         stringTable.findHandle(name), readOnly,
110         integerInfo.lowerBound,       integerInfo.upperBound,
111         integerInfo.scalarIncrement,  integerInfo.defaultValue,
112     };
113 
114     auto attrTableEntry =
115         table::attribute::constructIntegerEntry(attrTable, &info);
116 
117     auto [attrHandle, attrType, _] =
118         table::attribute::decodeHeader(attrTableEntry);
119 
120     int64_t currentValue{};
121     if (optAttributeValue.has_value())
122     {
123         auto attributeValue = optAttributeValue.value();
124         if (attributeValue.index() == 0)
125         {
126             currentValue = std::get<int64_t>(attributeValue);
127         }
128         else
129         {
130             currentValue = getAttrValue();
131         }
132     }
133     else
134     {
135         currentValue = getAttrValue();
136     }
137 
138     table::attribute_value::constructIntegerEntry(attrValueTable, attrHandle,
139                                                   attrType, currentValue);
140 }
141 
142 uint64_t BIOSIntegerAttribute::getAttrValue(const PropertyValue& propertyValue)
143 {
144     uint64_t value = 0;
145     if (dBusMap->propertyType == "uint8_t")
146     {
147         value = std::get<uint8_t>(propertyValue);
148     }
149     else if (dBusMap->propertyType == "uint16_t")
150     {
151         value = std::get<uint16_t>(propertyValue);
152     }
153     else if (dBusMap->propertyType == "int16_t")
154     {
155         value = std::get<int16_t>(propertyValue);
156     }
157     else if (dBusMap->propertyType == "uint32_t")
158     {
159         value = std::get<uint32_t>(propertyValue);
160     }
161     else if (dBusMap->propertyType == "int32_t")
162     {
163         value = std::get<int32_t>(propertyValue);
164     }
165     else if (dBusMap->propertyType == "uint64_t")
166     {
167         value = std::get<uint64_t>(propertyValue);
168     }
169     else if (dBusMap->propertyType == "int64_t")
170     {
171         value = std::get<int64_t>(propertyValue);
172     }
173     else if (dBusMap->propertyType == "double")
174     {
175         value = std::get<double>(propertyValue);
176     }
177     else
178     {
179         std::cerr << "Unsupported property type for getAttrValue: "
180                   << dBusMap->propertyType << std::endl;
181         throw std::invalid_argument("dbus type error");
182     }
183     return value;
184 }
185 
186 uint64_t BIOSIntegerAttribute::getAttrValue()
187 {
188     if (readOnly || !dBusMap.has_value())
189     {
190         return integerInfo.defaultValue;
191     }
192 
193     try
194     {
195         auto propertyValue = dbusHandler->getDbusPropertyVariant(
196             dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
197             dBusMap->interface.c_str());
198 
199         return getAttrValue(propertyValue);
200     }
201     catch (const std::exception& e)
202     {
203         std::cerr << "Get Integer Attribute Value Error: AttributeName = "
204                   << name << std::endl;
205         return integerInfo.defaultValue;
206     }
207 }
208 
209 int BIOSIntegerAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
210                                         uint8_t attrType,
211                                         const PropertyValue& newPropVal)
212 {
213     auto newVal = getAttrValue(newPropVal);
214     table::attribute_value::constructIntegerEntry(newValue, attrHdl, attrType,
215                                                   newVal);
216     return PLDM_SUCCESS;
217 }
218 
219 void BIOSIntegerAttribute::generateAttributeEntry(
220     const std::variant<int64_t, std::string>& attributevalue,
221     Table& attrValueEntry)
222 {
223     attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) +
224                           sizeof(int64_t) - 1);
225 
226     auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
227         attrValueEntry.data());
228 
229     int64_t value = std::get<int64_t>(attributevalue);
230     entry->attr_type = 3;
231     memcpy(entry->value, &value, sizeof(int64_t));
232 }
233 
234 } // namespace bios
235 } // namespace responder
236 } // namespace pldm
237