blob: 2dc2e57a0f3d6c1b35b680ed6017be4158d345e8 [file] [log] [blame]
Tom Joseph52552ef2019-06-20 09:50:15 +05301#include "bios_parser.hpp"
2
John Wang0df0e042020-01-16 10:01:36 +08003#include "bios_table.hpp"
George Liu83409572019-12-24 18:42:54 +08004#include "utils.hpp"
Tom Joseph52552ef2019-06-20 09:50:15 +05305
John Wang0df0e042020-01-16 10:01:36 +08006#include <cassert>
Tom Joseph52552ef2019-06-20 09:50:15 +05307#include <filesystem>
8#include <fstream>
Sampa Misraaa8ae722019-12-12 03:20:40 -06009#include <iostream>
Tom Joseph52552ef2019-06-20 09:50:15 +053010#include <nlohmann/json.hpp>
11#include <optional>
John Wang0df0e042020-01-16 10:01:36 +080012#include <set>
Tom Joseph52552ef2019-06-20 09:50:15 +053013
John Wang0df0e042020-01-16 10:01:36 +080014#include "libpldm/bios.h"
John Wangecb7d572019-10-17 13:38:53 +080015#include "libpldm/bios_table.h"
16
Tom Joseph52552ef2019-06-20 09:50:15 +053017namespace bios_parser
18{
19
20using Json = nlohmann::json;
21namespace fs = std::filesystem;
John Wang0df0e042020-01-16 10:01:36 +080022using namespace pldm::responder::bios;
Tom Joseph52552ef2019-06-20 09:50:15 +053023
Carol Wang612f35b2019-08-26 17:14:26 +080024const std::vector<Json> emptyJsonList{};
25const Json emptyJson{};
26
John Wange96e7e52019-10-05 17:47:30 +080027struct DBusMapping
28{
29 std::string objectPath; //!< D-Bus object path
30 std::string interface; //!< D-Bus interface
31 std::string propertyName; //!< D-Bus property name
John Wang0df0e042020-01-16 10:01:36 +080032 std::string propertyType; //!< D-Bus property type
John Wange96e7e52019-10-05 17:47:30 +080033};
Carol Wang612f35b2019-08-26 17:14:26 +080034
John Wang0df0e042020-01-16 10:01:36 +080035using AttrType = uint8_t;
36using Table = std::vector<uint8_t>;
John Wange96e7e52019-10-05 17:47:30 +080037using BIOSJsonName = std::string;
38using AttrLookup = std::map<AttrName, std::optional<DBusMapping>>;
John Wang0df0e042020-01-16 10:01:36 +080039using PropertyValue =
40 std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
41 uint64_t, double, std::string>;
42const std::set<std::string> SupportedDbusPropertyTypes = {
43 "bool", "uint8_t", "int16_t", "uint16_t", "int32_t",
44 "uint32_t", "int64_t", "uint64_t", "double", "string"};
45
John Wange96e7e52019-10-05 17:47:30 +080046using BIOSStringHandler =
47 std::function<int(const Json& entry, Strings& strings)>;
48using AttrLookupHandler = std::function<int(const Json& entry, AttrLookup)>;
49using typeHandler = std::function<int(const Json& entry)>;
50
51Strings BIOSStrings;
52AttrLookup BIOSAttrLookup;
53
54const Strings& getStrings()
55{
56 return BIOSStrings;
57}
58
John Wang0df0e042020-01-16 10:01:36 +080059int parseBIOSJsonFile(const fs::path& dirPath, const std::string& fileName,
Carol Wang612f35b2019-08-26 17:14:26 +080060 Json& fileData)
61{
62 int rc = 0;
63
John Wange96e7e52019-10-05 17:47:30 +080064 fs::path filePath = dirPath / fileName;
Carol Wang612f35b2019-08-26 17:14:26 +080065
66 std::ifstream jsonFile(filePath);
67 if (!jsonFile.is_open())
68 {
Sampa Misraaa8ae722019-12-12 03:20:40 -060069 std::cerr << "BIOS config file does not exist, FILE="
70 << filePath.c_str() << "\n";
Carol Wang612f35b2019-08-26 17:14:26 +080071 rc = -1;
72 }
73 else
74 {
75 fileData = Json::parse(jsonFile, nullptr, false);
76 if (fileData.is_discarded())
77 {
Sampa Misraaa8ae722019-12-12 03:20:40 -060078 std::cerr << "Parsing config file failed, FILE=" << filePath.c_str()
79 << "\n";
Carol Wang612f35b2019-08-26 17:14:26 +080080 rc = -1;
81 }
82 }
83
84 return rc;
85}
86
Tom Joseph52552ef2019-06-20 09:50:15 +053087namespace bios_enum
88{
89
90namespace internal
91{
92
Tom Joseph52552ef2019-06-20 09:50:15 +053093using Value = std::string;
94
John Wange96e7e52019-10-05 17:47:30 +080095/** @brief Map of DBus property value to attribute value
Tom Joseph52552ef2019-06-20 09:50:15 +053096 */
John Wange96e7e52019-10-05 17:47:30 +080097using DbusValToValMap = std::map<PropertyValue, Value>;
98
99/** @brief Map containing the DBus property value to attribute value map for the
100 * BIOS enumeration type attributes
101 */
102std::map<AttrName, DbusValToValMap> dbusValToValMaps;
Tom Joseph52552ef2019-06-20 09:50:15 +0530103
104/** @brief Map containing the possible and the default values for the BIOS
105 * enumeration type attributes.
106 */
107AttrValuesMap valueMap;
108
Tom Joseph52552ef2019-06-20 09:50:15 +0530109/** @brief Populate the mapping between D-Bus property value and attribute value
110 * for the BIOS enumeration attribute.
111 *
112 * @param[in] type - type of the D-Bus property
113 * @param[in] dBusValues - json array of D-Bus property values
114 * @param[in] pv - Possible values for the BIOS enumeration attribute
Tom Joseph52552ef2019-06-20 09:50:15 +0530115 *
116 */
John Wange96e7e52019-10-05 17:47:30 +0800117DbusValToValMap populateMapping(const std::string& type, const Json& dBusValues,
118 const PossibleValues& pv)
Tom Joseph52552ef2019-06-20 09:50:15 +0530119{
120 size_t pos = 0;
121 PropertyValue value;
John Wange96e7e52019-10-05 17:47:30 +0800122 DbusValToValMap valueMap;
Tom Joseph52552ef2019-06-20 09:50:15 +0530123 for (auto it = dBusValues.begin(); it != dBusValues.end(); ++it, ++pos)
124 {
125 if (type == "uint8_t")
126 {
127 value = static_cast<uint8_t>(it.value());
128 }
129 else if (type == "uint16_t")
130 {
131 value = static_cast<uint16_t>(it.value());
132 }
133 else if (type == "uint32_t")
134 {
135 value = static_cast<uint32_t>(it.value());
136 }
137 else if (type == "uint64_t")
138 {
139 value = static_cast<uint64_t>(it.value());
140 }
141 else if (type == "int16_t")
142 {
143 value = static_cast<int16_t>(it.value());
144 }
145 else if (type == "int32_t")
146 {
147 value = static_cast<int32_t>(it.value());
148 }
149 else if (type == "int64_t")
150 {
151 value = static_cast<int64_t>(it.value());
152 }
153 else if (type == "bool")
154 {
155 value = static_cast<bool>(it.value());
156 }
157 else if (type == "double")
158 {
159 value = static_cast<double>(it.value());
160 }
161 else if (type == "string")
162 {
163 value = static_cast<std::string>(it.value());
164 }
165 else
166 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600167 std::cerr << "Unknown D-Bus property type, TYPE=" << type.c_str()
168 << "\n";
Tom Joseph52552ef2019-06-20 09:50:15 +0530169 }
170
John Wange96e7e52019-10-05 17:47:30 +0800171 valueMap.emplace(value, pv[pos]);
Tom Joseph52552ef2019-06-20 09:50:15 +0530172 }
173
John Wange96e7e52019-10-05 17:47:30 +0800174 return valueMap;
Tom Joseph52552ef2019-06-20 09:50:15 +0530175}
176
John Wang0df0e042020-01-16 10:01:36 +0800177void updateDbusProperty(const DBusMapping& dBusMap, const PropertyValue& value)
178{
179 auto setDbusProperty = [&dBusMap](const auto& variant) {
180 pldm::utils::DBusHandler().setDbusProperty(
181 dBusMap.objectPath.c_str(), dBusMap.propertyName.c_str(),
182 dBusMap.interface.c_str(), variant);
183 };
184
185 if (dBusMap.propertyType == "uint8_t")
186 {
187 std::variant<uint8_t> v = std::get<uint8_t>(value);
188 setDbusProperty(v);
189 }
190 else if (dBusMap.propertyType == "int16_t")
191 {
192 std::variant<int16_t> v = std::get<int16_t>(value);
193 setDbusProperty(v);
194 }
195 else if (dBusMap.propertyType == "uint16_t")
196 {
197 std::variant<uint16_t> v = std::get<uint16_t>(value);
198 setDbusProperty(v);
199 }
200 else if (dBusMap.propertyType == "int32_t")
201 {
202 std::variant<int32_t> v = std::get<int32_t>(value);
203 setDbusProperty(v);
204 }
205 else if (dBusMap.propertyType == "uint32_t")
206 {
207 std::variant<uint32_t> v = std::get<uint32_t>(value);
208 setDbusProperty(v);
209 }
210 else if (dBusMap.propertyType == "int64_t")
211 {
212 std::variant<int64_t> v = std::get<int64_t>(value);
213 setDbusProperty(v);
214 }
215 else if (dBusMap.propertyType == "uint64_t")
216 {
217 std::variant<uint64_t> v = std::get<uint64_t>(value);
218 setDbusProperty(v);
219 }
220 else if (dBusMap.propertyType == "double")
221 {
222 std::variant<double> v = std::get<double>(value);
223 setDbusProperty(v);
224 }
225 else if (dBusMap.propertyType == "string")
226 {
227 std::variant<std::string> v = std::get<std::string>(value);
228 setDbusProperty(v);
229 }
230 else
231 {
232 assert(false && "UnSpported Dbus Type");
233 }
234}
235
Tom Joseph52552ef2019-06-20 09:50:15 +0530236} // namespace internal
237
John Wange96e7e52019-10-05 17:47:30 +0800238int setupBIOSStrings(const Json& entry, Strings& strings)
Tom Joseph52552ef2019-06-20 09:50:15 +0530239{
John Wange96e7e52019-10-05 17:47:30 +0800240 Json pvs = entry.value("possible_values", emptyJsonList);
Tom Joseph52552ef2019-06-20 09:50:15 +0530241
John Wange96e7e52019-10-05 17:47:30 +0800242 for (auto& pv : pvs)
Tom Joseph52552ef2019-06-20 09:50:15 +0530243 {
John Wange96e7e52019-10-05 17:47:30 +0800244 strings.emplace_back(std::move(pv.get<std::string>()));
Tom Joseph52552ef2019-06-20 09:50:15 +0530245 }
246
John Wange96e7e52019-10-05 17:47:30 +0800247 return 0;
248}
Tom Joseph52552ef2019-06-20 09:50:15 +0530249
John Wange96e7e52019-10-05 17:47:30 +0800250int setup(const Json& entry)
251{
252 PossibleValues possibleValues;
253 DefaultValues defaultValues;
254
255 std::string attrName = entry.value("attribute_name", "");
256 Json pv = entry["possible_values"];
257 for (auto& val : pv)
Tom Joseph52552ef2019-06-20 09:50:15 +0530258 {
John Wange96e7e52019-10-05 17:47:30 +0800259 possibleValues.emplace_back(std::move(val));
Tom Joseph52552ef2019-06-20 09:50:15 +0530260 }
John Wange96e7e52019-10-05 17:47:30 +0800261 Json dv = entry["default_values"];
262 for (auto& val : dv)
Tom Joseph52552ef2019-06-20 09:50:15 +0530263 {
John Wange96e7e52019-10-05 17:47:30 +0800264 defaultValues.emplace_back(std::move(val));
Tom Joseph52552ef2019-06-20 09:50:15 +0530265 }
John Wange96e7e52019-10-05 17:47:30 +0800266 if (entry.count("dbus") != 0)
Tom Joseph52552ef2019-06-20 09:50:15 +0530267 {
John Wange96e7e52019-10-05 17:47:30 +0800268 auto dbusEntry = entry.value("dbus", emptyJson);
269 std::string propertyType = dbusEntry.value("property_type", "");
270 Json propValues = dbusEntry["property_values"];
271 internal::dbusValToValMaps.emplace(
272 attrName, internal::populateMapping(propertyType, propValues,
273 possibleValues));
Tom Joseph52552ef2019-06-20 09:50:15 +0530274 }
John Wange96e7e52019-10-05 17:47:30 +0800275 // Defaulting all the types of attributes to BIOSEnumeration
276 internal::valueMap.emplace(std::move(attrName),
277 std::make_tuple(entry.count("dbus") == 0,
278 std::move(possibleValues),
279 std::move(defaultValues)));
280 return 0;
Tom Joseph52552ef2019-06-20 09:50:15 +0530281}
282
283const AttrValuesMap& getValues()
284{
285 return internal::valueMap;
286}
287
288CurrentValues getAttrValue(const AttrName& attrName)
289{
John Wange96e7e52019-10-05 17:47:30 +0800290 const auto& dBusMap = BIOSAttrLookup.at(attrName);
Tom Joseph52552ef2019-06-20 09:50:15 +0530291 CurrentValues currentValues;
John Wang0df0e042020-01-16 10:01:36 +0800292 PropertyValue propValue;
Tom Joseph52552ef2019-06-20 09:50:15 +0530293
294 if (dBusMap == std::nullopt)
295 {
296 const auto& valueEntry = internal::valueMap.at(attrName);
297 const auto& [readOnly, possibleValues, currentValues] = valueEntry;
298 return currentValues;
299 }
300
John Wange96e7e52019-10-05 17:47:30 +0800301 const auto& dbusValToValMap = internal::dbusValToValMaps.at(attrName);
John Wang8b85f522019-10-17 19:28:19 +0800302 propValue =
John Wang0df0e042020-01-16 10:01:36 +0800303 pldm::utils::DBusHandler().getDbusPropertyVariant<PropertyValue>(
304 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
305 dBusMap->interface.c_str());
306
John Wange96e7e52019-10-05 17:47:30 +0800307 auto iter = dbusValToValMap.find(propValue);
308 if (iter != dbusValToValMap.end())
Tom Joseph52552ef2019-06-20 09:50:15 +0530309 {
310 currentValues.push_back(iter->second);
311 }
312
313 return currentValues;
314}
315
John Wang0df0e042020-01-16 10:01:36 +0800316int setAttrValue(const AttrName& attrName,
317 const pldm_bios_attr_val_table_entry* attrValueEntry,
318 const pldm_bios_attr_table_entry* attrEntry,
319 const BIOSStringTable& stringTable)
320{
321 const auto& dBusMap = BIOSAttrLookup.at(attrName);
322 if (dBusMap == std::nullopt)
323 {
324 return PLDM_SUCCESS;
325 }
326
327 uint8_t pvNum = pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry);
328 std::vector<uint16_t> pvHdls(pvNum, 0);
329 pldm_bios_table_attr_entry_enum_decode_pv_hdls(attrEntry, pvHdls.data(),
330 pvNum);
331
332 uint8_t defNum =
333 pldm_bios_table_attr_value_entry_enum_decode_number(attrValueEntry);
334
335 assert(defNum == 1);
336
337 std::vector<uint8_t> currHdls(1, 0);
338 pldm_bios_table_attr_value_entry_enum_decode_handles(
339 attrValueEntry, currHdls.data(), currHdls.size());
340
341 auto valueString = stringTable.findString(pvHdls[currHdls[0]]);
342
343 const auto& dbusValToValMap = internal::dbusValToValMaps.at(attrName);
344
345 auto it = std::find_if(dbusValToValMap.begin(), dbusValToValMap.end(),
346 [&valueString](const auto& typePair) {
347 return typePair.second == valueString;
348 });
349 if (it == dbusValToValMap.end())
350 {
351 std::cerr << "Invalid Enum Value\n";
352 return PLDM_ERROR;
353 }
354
355 internal::updateDbusProperty(dBusMap.value(), it->first);
356
357 return PLDM_SUCCESS;
358}
359
Tom Joseph52552ef2019-06-20 09:50:15 +0530360} // namespace bios_enum
361
Carol Wang612f35b2019-08-26 17:14:26 +0800362namespace bios_string
363{
364
365/** @brief BIOS string types
366 */
John Wang0df0e042020-01-16 10:01:36 +0800367enum BIOSStringEncoding
Carol Wang612f35b2019-08-26 17:14:26 +0800368{
369 UNKNOWN = 0x00,
370 ASCII = 0x01,
371 HEX = 0x02,
372 UTF_8 = 0x03,
373 UTF_16LE = 0x04,
374 UTF_16BE = 0x05,
375 VENDOR_SPECIFIC = 0xFF
376};
377
378const std::map<std::string, uint8_t> strTypeMap{
379 {"Unknown", UNKNOWN},
380 {"ASCII", ASCII},
381 {"Hex", HEX},
382 {"UTF-8", UTF_8},
383 {"UTF-16LE", UTF_16LE},
384 {"UTF-16LE", UTF_16LE},
385 {"Vendor Specific", VENDOR_SPECIFIC}};
386
387namespace internal
388{
389
Carol Wang612f35b2019-08-26 17:14:26 +0800390/** @brief Map containing the possible and the default values for the BIOS
391 * string type attributes.
392 */
393AttrValuesMap valueMap;
394
Carol Wang612f35b2019-08-26 17:14:26 +0800395} // namespace internal
396
John Wangecb7d572019-10-17 13:38:53 +0800397int setup(const Json& jsonEntry)
Carol Wang612f35b2019-08-26 17:14:26 +0800398{
Carol Wang612f35b2019-08-26 17:14:26 +0800399
John Wangecb7d572019-10-17 13:38:53 +0800400 std::string attr = jsonEntry.value("attribute_name", "");
John Wange96e7e52019-10-05 17:47:30 +0800401 // Transfer string type from string to enum
John Wangecb7d572019-10-17 13:38:53 +0800402 std::string strTypeTmp = jsonEntry.value("string_type", "Unknown");
John Wange96e7e52019-10-05 17:47:30 +0800403 auto iter = strTypeMap.find(strTypeTmp);
404 if (iter == strTypeMap.end())
Carol Wang612f35b2019-08-26 17:14:26 +0800405 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600406 std::cerr << "Wrong string type, STRING_TYPE=" << strTypeTmp.c_str()
407 << " ATTRIBUTE_NAME=" << attr.c_str() << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800408 return -1;
409 }
410 uint8_t strType = iter->second;
411
John Wangecb7d572019-10-17 13:38:53 +0800412 uint16_t minStrLen = jsonEntry.value("minimum_string_length", 0);
413 uint16_t maxStrLen = jsonEntry.value("maximum_string_length", 0);
414 uint16_t defaultStrLen = jsonEntry.value("default_string_length", 0);
415 std::string defaultStr = jsonEntry.value("default_string", "");
416
417 pldm_bios_table_attr_entry_string_info info = {
418 0, /* name handle */
419 false, /* read only */
420 strType, minStrLen, maxStrLen, defaultStrLen, defaultStr.data(),
421 };
422
423 const char* errmsg;
424 auto rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg);
425 if (rc != PLDM_SUCCESS)
John Wange96e7e52019-10-05 17:47:30 +0800426 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600427 std::cerr << "Wrong filed for string attribute, ATTRIBUTE_NAME="
428 << attr.c_str() << " ERRMSG=" << errmsg
429 << " MINIMUM_STRING_LENGTH=" << minStrLen
430 << " MAXIMUM_STRING_LENGTH=" << maxStrLen
431 << " DEFAULT_STRING_LENGTH=" << defaultStrLen
432 << " DEFAULT_STRING=" << defaultStr.data() << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800433 return -1;
Carol Wang612f35b2019-08-26 17:14:26 +0800434 }
435
John Wange96e7e52019-10-05 17:47:30 +0800436 // Defaulting all the types of attributes to BIOSString
437 internal::valueMap.emplace(
438 std::move(attr),
John Wangecb7d572019-10-17 13:38:53 +0800439 std::make_tuple(jsonEntry.count("dbus") == 0, strType, minStrLen,
440 maxStrLen, defaultStrLen, std::move(defaultStr)));
Carol Wang612f35b2019-08-26 17:14:26 +0800441
John Wange96e7e52019-10-05 17:47:30 +0800442 return 0;
Carol Wang612f35b2019-08-26 17:14:26 +0800443}
444
445const AttrValuesMap& getValues()
446{
447 return internal::valueMap;
448}
Carol Wangb503f9e2019-09-02 16:34:10 +0800449
450std::string getAttrValue(const AttrName& attrName)
451{
John Wange96e7e52019-10-05 17:47:30 +0800452 const auto& dBusMap = BIOSAttrLookup.at(attrName);
Carol Wangb503f9e2019-09-02 16:34:10 +0800453 std::variant<std::string> propValue;
454
455 if (dBusMap == std::nullopt)
456 { // return default string
457 const auto& valueEntry = internal::valueMap.at(attrName);
458 return std::get<DefaultStr>(valueEntry);
459 }
460
George Liu83409572019-12-24 18:42:54 +0800461 return pldm::utils::DBusHandler().getDbusProperty<std::string>(
John Wang8b85f522019-10-17 19:28:19 +0800462 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
463 dBusMap->interface.c_str());
Carol Wangb503f9e2019-09-02 16:34:10 +0800464}
465
John Wang0df0e042020-01-16 10:01:36 +0800466std::string stringToUtf8(BIOSStringEncoding stringType,
467 const std::vector<uint8_t>& data)
468{
469 switch (stringType)
470 {
471 case ASCII:
472 case UTF_8:
473 case HEX:
474 return std::string(data.begin(), data.end());
475 case UTF_16BE:
476 case UTF_16LE: // TODO
477 return std::string(data.begin(), data.end());
478 case VENDOR_SPECIFIC:
479 throw std::invalid_argument("Vendor Specific is unsupported");
480 case UNKNOWN:
481 throw std::invalid_argument("Unknown String Type");
482 }
483 throw std::invalid_argument("String Type Error");
484}
485
486int setAttrValue(const AttrName& attrName,
487 const pldm_bios_attr_val_table_entry* attrValueEntry,
488 const pldm_bios_attr_table_entry* attrEntry,
489 const BIOSStringTable&)
490{
491 const auto& dBusMap = BIOSAttrLookup.at(attrName);
492 if (dBusMap == std::nullopt)
493 {
494 return PLDM_SUCCESS;
495 }
496
497 auto stringType =
498 pldm_bios_table_attr_entry_string_decode_string_type(attrEntry);
499
500 variable_field currentString{};
501 pldm_bios_table_attr_value_entry_string_decode_string(attrValueEntry,
502 &currentString);
503 std::vector<uint8_t> data(currentString.ptr,
504 currentString.ptr + currentString.length);
505
506 std::variant<std::string> value =
507 stringToUtf8(static_cast<BIOSStringEncoding>(stringType), data);
508
509 pldm::utils::DBusHandler().setDbusProperty(
510 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
511 dBusMap->interface.c_str(), value);
512
513 return PLDM_SUCCESS;
514}
515
Carol Wang612f35b2019-08-26 17:14:26 +0800516} // namespace bios_string
517
John Wangecb7d572019-10-17 13:38:53 +0800518namespace bios_integer
519{
520
521AttrValuesMap valueMap;
522
523int setup(const Json& jsonEntry)
524{
525
526 std::string attr = jsonEntry.value("attribute_name", "");
527 // Transfer string type from string to enum
528
529 uint64_t lowerBound = jsonEntry.value("lower_bound", 0);
530 uint64_t upperBound = jsonEntry.value("upper_bound", 0);
531 uint32_t scalarIncrement = jsonEntry.value("scalar_increment", 1);
532 uint64_t defaultValue = jsonEntry.value("default_value", 0);
533 pldm_bios_table_attr_entry_integer_info info = {
534 0, /* name handle*/
535 false, /* read only */
536 lowerBound, upperBound, scalarIncrement, defaultValue,
537 };
538 const char* errmsg = nullptr;
539 auto rc = pldm_bios_table_attr_entry_integer_info_check(&info, &errmsg);
540 if (rc != PLDM_SUCCESS)
541 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600542 std::cerr << "Wrong filed for integer attribute, ATTRIBUTE_NAME="
543 << attr.c_str() << " ERRMSG=" << errmsg
544 << " LOWER_BOUND=" << lowerBound
545 << " UPPER_BOUND=" << upperBound
546 << " DEFAULT_VALUE=" << defaultValue
547 << " SCALAR_INCREMENT=" << scalarIncrement << "\n";
John Wangecb7d572019-10-17 13:38:53 +0800548 return -1;
549 }
550
551 valueMap.emplace(std::move(attr),
552 std::make_tuple(jsonEntry.count("dbus") == 0, lowerBound,
553 upperBound, scalarIncrement,
554 defaultValue));
555
556 return 0;
557}
558
John Wang0df0e042020-01-16 10:01:36 +0800559void updateDbusProperty(const DBusMapping& dBusMap, uint64_t value)
560{
561 auto setDbusProperty = [&dBusMap](const auto& variant) {
562 pldm::utils::DBusHandler().setDbusProperty(
563 dBusMap.objectPath.c_str(), dBusMap.propertyName.c_str(),
564 dBusMap.interface.c_str(), variant);
565 };
566
567 if (dBusMap.propertyType == "uint8_t")
568 {
569 std::variant<uint8_t> v = value;
570 setDbusProperty(v);
571 }
572 else if (dBusMap.propertyType == "int16_t")
573 {
574 std::variant<int16_t> v = value;
575 setDbusProperty(v);
576 }
577 else if (dBusMap.propertyType == "uint16_t")
578 {
579 std::variant<uint16_t> v = value;
580 setDbusProperty(v);
581 }
582 else if (dBusMap.propertyType == "int32_t")
583 {
584 std::variant<int32_t> v = value;
585 setDbusProperty(v);
586 }
587 else if (dBusMap.propertyType == "uint32_t")
588 {
589 std::variant<uint32_t> v = value;
590 setDbusProperty(v);
591 }
592 else if (dBusMap.propertyType == "int64_t")
593 {
594 std::variant<int64_t> v = value;
595 setDbusProperty(v);
596 }
597 else if (dBusMap.propertyType == "uint64_t")
598 {
599 std::variant<uint64_t> v = value;
600 setDbusProperty(v);
601 }
602 else
603 {
604 assert(false && "Unsupported Dbus Type");
605 }
606}
607
John Wangecb7d572019-10-17 13:38:53 +0800608const AttrValuesMap& getValues()
609{
610 return valueMap;
611}
612
613uint64_t getAttrValue(const AttrName& attrName)
614{
615 const auto& dBusMap = BIOSAttrLookup.at(attrName);
616 std::variant<std::string> propValue;
617
618 if (dBusMap == std::nullopt)
619 { // return default string
620 const auto& valueEntry = valueMap.at(attrName);
621 return std::get<AttrDefaultValue>(valueEntry);
622 }
623
George Liu83409572019-12-24 18:42:54 +0800624 return pldm::utils::DBusHandler().getDbusProperty<uint64_t>(
John Wangecb7d572019-10-17 13:38:53 +0800625 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
626 dBusMap->interface.c_str());
627}
628
John Wang0df0e042020-01-16 10:01:36 +0800629int setAttrValue(const AttrName& attrName,
630 const pldm_bios_attr_val_table_entry* attrValueEntry,
631 const pldm_bios_attr_table_entry*, const BIOSStringTable&)
632{
633 const auto& dBusMap = BIOSAttrLookup.at(attrName);
634 if (dBusMap == std::nullopt)
635 {
636 return PLDM_SUCCESS;
637 }
638
639 uint64_t currentValue =
640 pldm_bios_table_attr_value_entry_integer_decode_cv(attrValueEntry);
641
642 updateDbusProperty(dBusMap.value(), currentValue);
643
644 return PLDM_SUCCESS;
645}
646
John Wangecb7d572019-10-17 13:38:53 +0800647} // namespace bios_integer
648
John Wange96e7e52019-10-05 17:47:30 +0800649const std::map<BIOSJsonName, BIOSStringHandler> BIOSStringHandlers = {
650 {bIOSEnumJson, bios_enum::setupBIOSStrings},
651};
Tom Joseph52552ef2019-06-20 09:50:15 +0530652
John Wange96e7e52019-10-05 17:47:30 +0800653const std::map<BIOSJsonName, typeHandler> BIOSTypeHandlers = {
654 {bIOSEnumJson, bios_enum::setup},
655 {bIOSStrJson, bios_string::setup},
John Wangecb7d572019-10-17 13:38:53 +0800656 {bIOSIntegerJson, bios_integer::setup},
John Wange96e7e52019-10-05 17:47:30 +0800657};
658
659void setupBIOSStrings(const BIOSJsonName& jsonName, const Json& entry,
660 Strings& strings)
661{
662 strings.emplace_back(entry.value("attribute_name", ""));
663 auto iter = BIOSStringHandlers.find(jsonName);
664 if (iter != BIOSStringHandlers.end())
665 {
666 iter->second(entry, strings);
667 }
668}
669
John Wangecb7d572019-10-17 13:38:53 +0800670void setupBIOSAttrLookup(const Json& jsonEntry, AttrLookup& lookup)
John Wange96e7e52019-10-05 17:47:30 +0800671{
672 std::optional<DBusMapping> dBusMap;
John Wangecb7d572019-10-17 13:38:53 +0800673 std::string attrName = jsonEntry.value("attribute_name", "");
John Wange96e7e52019-10-05 17:47:30 +0800674
John Wangecb7d572019-10-17 13:38:53 +0800675 if (jsonEntry.count("dbus") != 0)
John Wange96e7e52019-10-05 17:47:30 +0800676 {
John Wangecb7d572019-10-17 13:38:53 +0800677 auto dBusEntry = jsonEntry.value("dbus", emptyJson);
John Wange96e7e52019-10-05 17:47:30 +0800678 std::string objectPath = dBusEntry.value("object_path", "");
679 std::string interface = dBusEntry.value("interface", "");
680 std::string propertyName = dBusEntry.value("property_name", "");
John Wang0df0e042020-01-16 10:01:36 +0800681 std::string propertyType = dBusEntry.value("property_type", "");
682 if (!objectPath.empty() && !interface.empty() &&
683 !propertyName.empty() &&
684 (SupportedDbusPropertyTypes.find(propertyType) !=
685 SupportedDbusPropertyTypes.end()))
John Wange96e7e52019-10-05 17:47:30 +0800686 {
687 dBusMap = std::optional<DBusMapping>(
John Wang0df0e042020-01-16 10:01:36 +0800688 {objectPath, interface, propertyName, propertyType});
John Wange96e7e52019-10-05 17:47:30 +0800689 }
690 else
691 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600692 std::cerr << "Invalid dbus config, OBJPATH="
693 << dBusMap->objectPath.c_str()
694 << " INTERFACE=" << dBusMap->interface.c_str()
695 << " PROPERTY_NAME=" << dBusMap->propertyName.c_str()
John Wang0df0e042020-01-16 10:01:36 +0800696 << " PROPERTY_TYPE=" << dBusMap->propertyType.c_str()
Sampa Misraaa8ae722019-12-12 03:20:40 -0600697 << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800698 }
699 }
700 lookup.emplace(attrName, dBusMap);
701}
702
703int setupBIOSType(const BIOSJsonName& jsonName, const Json& entry)
704{
705 auto iter = BIOSTypeHandlers.find(jsonName);
706 if (iter != BIOSTypeHandlers.end())
707 {
708 iter->second(entry);
709 }
710 return 0;
711}
712
John Wangecb7d572019-10-17 13:38:53 +0800713const std::vector<BIOSJsonName> BIOSConfigFiles = {bIOSEnumJson, bIOSStrJson,
714 bIOSIntegerJson};
John Wange96e7e52019-10-05 17:47:30 +0800715
716int setupConfig(const char* dirPath)
717{
718 if (!BIOSStrings.empty() && !BIOSAttrLookup.empty())
719 {
720 return 0;
721 }
722
723 fs::path dir(dirPath);
Tom Joseph52552ef2019-06-20 09:50:15 +0530724 if (!fs::exists(dir) || fs::is_empty(dir))
725 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600726 std::cerr << "BIOS config directory does not exist or empty, DIR="
727 << dirPath << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800728 return -1;
Tom Joseph52552ef2019-06-20 09:50:15 +0530729 }
John Wange96e7e52019-10-05 17:47:30 +0800730 for (auto jsonName : BIOSConfigFiles)
Tom Joseph52552ef2019-06-20 09:50:15 +0530731 {
John Wange96e7e52019-10-05 17:47:30 +0800732 Json json;
John Wang0df0e042020-01-16 10:01:36 +0800733 if (parseBIOSJsonFile(dir, jsonName, json) < 0)
Tom Joseph52552ef2019-06-20 09:50:15 +0530734 {
Tom Joseph52552ef2019-06-20 09:50:15 +0530735 continue;
736 }
John Wange96e7e52019-10-05 17:47:30 +0800737 auto entries = json.value("entries", emptyJsonList);
Tom Joseph52552ef2019-06-20 09:50:15 +0530738 for (auto& entry : entries)
739 {
John Wange96e7e52019-10-05 17:47:30 +0800740 setupBIOSStrings(jsonName, entry, BIOSStrings);
741 setupBIOSAttrLookup(entry, BIOSAttrLookup);
742 setupBIOSType(jsonName, entry);
Tom Joseph52552ef2019-06-20 09:50:15 +0530743 }
744 }
John Wange96e7e52019-10-05 17:47:30 +0800745 if (BIOSStrings.empty())
746 { // means there is no attribute
Sampa Misraaa8ae722019-12-12 03:20:40 -0600747 std::cerr << "No attribute is found in the config directory, DIR="
748 << dirPath << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800749 return -1;
750 }
751 return 0;
Tom Joseph52552ef2019-06-20 09:50:15 +0530752}
753
John Wang0df0e042020-01-16 10:01:36 +0800754using setAttrValueHandler = std::function<int(
755 const AttrName&, const pldm_bios_attr_val_table_entry*,
756 const pldm_bios_attr_table_entry*, const BIOSStringTable&)>;
757
758const std::map<AttrType, setAttrValueHandler> SetAttrValueMap{{
759 {PLDM_BIOS_STRING, bios_string::setAttrValue},
760 {PLDM_BIOS_STRING_READ_ONLY, bios_string::setAttrValue},
761 {PLDM_BIOS_ENUMERATION, bios_enum::setAttrValue},
762 {PLDM_BIOS_ENUMERATION_READ_ONLY, bios_enum::setAttrValue},
763 {PLDM_BIOS_INTEGER, bios_integer::setAttrValue},
764 {PLDM_BIOS_INTEGER_READ_ONLY, bios_integer::setAttrValue},
765
766}};
767
768int setAttributeValueOnDbus(const variable_field* attributeData,
769 const BIOSTable& biosAttributeTable,
770 const BIOSStringTable& stringTable)
771{
772 Table attributeTable;
773 biosAttributeTable.load(attributeTable);
774 auto attrValueEntry =
775 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(
776 attributeData->ptr);
777
778 auto attrType =
779 pldm_bios_table_attr_value_entry_decode_attribute_type(attrValueEntry);
780 auto attrHandle = pldm_bios_table_attr_value_entry_decode_attribute_handle(
781 attrValueEntry);
782
783 auto attrEntry = pldm_bios_table_attr_find_by_handle(
784 attributeTable.data(), attributeTable.size(), attrHandle);
785
786 assert(attrEntry != nullptr);
787
788 auto attrNameHandle =
789 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
790
791 auto attrName = stringTable.findString(attrNameHandle);
792
793 try
794 {
795 auto rc = SetAttrValueMap.at(attrType)(attrName, attrValueEntry,
796 attrEntry, stringTable);
797 return rc;
798 }
799 catch (const std::exception& e)
800 {
801 std::cerr << "setAttributeValueOnDbus Error: " << e.what() << std::endl;
802 return PLDM_ERROR;
803 }
804}
805
Tom Joseph52552ef2019-06-20 09:50:15 +0530806} // namespace bios_parser