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(const BIOSStringTable& stringTable,
102                                           Table& attrTable,
103                                           Table& attrValueTable)
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     auto currentValue = getAttrValue();
119     table::attribute_value::constructIntegerEntry(attrValueTable, attrHandle,
120                                                   attrType, currentValue);
121 }
122 
123 uint64_t BIOSIntegerAttribute::getAttrValue(const PropertyValue& propertyValue)
124 {
125     uint64_t value;
126     if (dBusMap->propertyType == "uint8_t")
127     {
128         value = std::get<uint8_t>(propertyValue);
129     }
130     else if (dBusMap->propertyType == "uint16_t")
131     {
132         value = std::get<uint16_t>(propertyValue);
133     }
134     else if (dBusMap->propertyType == "int16_t")
135     {
136         value = std::get<int16_t>(propertyValue);
137     }
138     else if (dBusMap->propertyType == "uint32_t")
139     {
140         value = std::get<uint32_t>(propertyValue);
141     }
142     else if (dBusMap->propertyType == "int32_t")
143     {
144         value = std::get<int32_t>(propertyValue);
145     }
146     else if (dBusMap->propertyType == "uint64_t")
147     {
148         value = std::get<uint64_t>(propertyValue);
149     }
150     else if (dBusMap->propertyType == "int64_t")
151     {
152         value = std::get<int64_t>(propertyValue);
153     }
154     else if (dBusMap->propertyType == "double")
155     {
156         value = std::get<double>(propertyValue);
157     }
158     return value;
159 }
160 
161 uint64_t BIOSIntegerAttribute::getAttrValue()
162 {
163     if (readOnly || !dBusMap.has_value())
164     {
165         return integerInfo.defaultValue;
166     }
167 
168     try
169     {
170         auto propertyValue = dbusHandler->getDbusPropertyVariant(
171             dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
172             dBusMap->interface.c_str());
173 
174         return getAttrValue(propertyValue);
175     }
176     catch (const std::exception& e)
177     {
178         std::cerr << "Get Integer Attribute Value Error: AttributeName = "
179                   << name << std::endl;
180         return integerInfo.defaultValue;
181     }
182 }
183 
184 int BIOSIntegerAttribute::updateAttrVal(Table& newValue, uint16_t attrHdl,
185                                         uint8_t attrType,
186                                         const PropertyValue& newPropVal)
187 {
188     auto newVal = getAttrValue(newPropVal);
189     table::attribute_value::constructIntegerEntry(newValue, attrHdl, attrType,
190                                                   newVal);
191     return PLDM_SUCCESS;
192 }
193 
194 void BIOSIntegerAttribute::generateAttributeEntry(
195     const std::variant<int64_t, std::string>& attributevalue,
196     Table& attrValueEntry)
197 {
198     attrValueEntry.resize(sizeof(pldm_bios_attr_val_table_entry) +
199                           sizeof(int64_t) - 1);
200 
201     auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
202         attrValueEntry.data());
203 
204     int64_t value = std::get<int64_t>(attributevalue);
205     entry->attr_type = 3;
206     memcpy(entry->value, &value, sizeof(int64_t));
207 }
208 
209 } // namespace bios
210 } // namespace responder
211 } // namespace pldm
212