blob: f9ddf463467cae1b2cdcc3880aba0383d186c203 [file] [log] [blame]
Tom Joseph52552ef2019-06-20 09:50:15 +05301#include "bios_parser.hpp"
2
George Liu83409572019-12-24 18:42:54 +08003#include "utils.hpp"
Tom Joseph52552ef2019-06-20 09:50:15 +05304
5#include <filesystem>
6#include <fstream>
Sampa Misraaa8ae722019-12-12 03:20:40 -06007#include <iostream>
Tom Joseph52552ef2019-06-20 09:50:15 +05308#include <nlohmann/json.hpp>
9#include <optional>
Tom Joseph52552ef2019-06-20 09:50:15 +053010
John Wangecb7d572019-10-17 13:38:53 +080011#include "libpldm/bios_table.h"
12
Tom Joseph52552ef2019-06-20 09:50:15 +053013namespace bios_parser
14{
15
16using Json = nlohmann::json;
17namespace fs = std::filesystem;
Tom Joseph52552ef2019-06-20 09:50:15 +053018
Carol Wang612f35b2019-08-26 17:14:26 +080019const std::vector<Json> emptyJsonList{};
20const Json emptyJson{};
21
John Wange96e7e52019-10-05 17:47:30 +080022struct DBusMapping
23{
24 std::string objectPath; //!< D-Bus object path
25 std::string interface; //!< D-Bus interface
26 std::string propertyName; //!< D-Bus property name
27};
Carol Wang612f35b2019-08-26 17:14:26 +080028
John Wange96e7e52019-10-05 17:47:30 +080029using AttrName = std::string;
30using BIOSJsonName = std::string;
31using AttrLookup = std::map<AttrName, std::optional<DBusMapping>>;
32using BIOSStringHandler =
33 std::function<int(const Json& entry, Strings& strings)>;
34using AttrLookupHandler = std::function<int(const Json& entry, AttrLookup)>;
35using typeHandler = std::function<int(const Json& entry)>;
36
37Strings BIOSStrings;
38AttrLookup BIOSAttrLookup;
39
40const Strings& getStrings()
41{
42 return BIOSStrings;
43}
44
45int parseBiosJsonFile(const fs::path& dirPath, const std::string& fileName,
Carol Wang612f35b2019-08-26 17:14:26 +080046 Json& fileData)
47{
48 int rc = 0;
49
John Wange96e7e52019-10-05 17:47:30 +080050 fs::path filePath = dirPath / fileName;
Carol Wang612f35b2019-08-26 17:14:26 +080051
52 std::ifstream jsonFile(filePath);
53 if (!jsonFile.is_open())
54 {
Sampa Misraaa8ae722019-12-12 03:20:40 -060055 std::cerr << "BIOS config file does not exist, FILE="
56 << filePath.c_str() << "\n";
Carol Wang612f35b2019-08-26 17:14:26 +080057 rc = -1;
58 }
59 else
60 {
61 fileData = Json::parse(jsonFile, nullptr, false);
62 if (fileData.is_discarded())
63 {
Sampa Misraaa8ae722019-12-12 03:20:40 -060064 std::cerr << "Parsing config file failed, FILE=" << filePath.c_str()
65 << "\n";
Carol Wang612f35b2019-08-26 17:14:26 +080066 rc = -1;
67 }
68 }
69
70 return rc;
71}
72
Tom Joseph52552ef2019-06-20 09:50:15 +053073namespace bios_enum
74{
75
76namespace internal
77{
78
79using PropertyValue =
80 std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
81 uint64_t, double, std::string>;
82using Value = std::string;
83
John Wange96e7e52019-10-05 17:47:30 +080084/** @brief Map of DBus property value to attribute value
Tom Joseph52552ef2019-06-20 09:50:15 +053085 */
John Wange96e7e52019-10-05 17:47:30 +080086using DbusValToValMap = std::map<PropertyValue, Value>;
87
88/** @brief Map containing the DBus property value to attribute value map for the
89 * BIOS enumeration type attributes
90 */
91std::map<AttrName, DbusValToValMap> dbusValToValMaps;
Tom Joseph52552ef2019-06-20 09:50:15 +053092
93/** @brief Map containing the possible and the default values for the BIOS
94 * enumeration type attributes.
95 */
96AttrValuesMap valueMap;
97
Tom Joseph52552ef2019-06-20 09:50:15 +053098/** @brief Populate the mapping between D-Bus property value and attribute value
99 * for the BIOS enumeration attribute.
100 *
101 * @param[in] type - type of the D-Bus property
102 * @param[in] dBusValues - json array of D-Bus property values
103 * @param[in] pv - Possible values for the BIOS enumeration attribute
Tom Joseph52552ef2019-06-20 09:50:15 +0530104 *
105 */
John Wange96e7e52019-10-05 17:47:30 +0800106DbusValToValMap populateMapping(const std::string& type, const Json& dBusValues,
107 const PossibleValues& pv)
Tom Joseph52552ef2019-06-20 09:50:15 +0530108{
109 size_t pos = 0;
110 PropertyValue value;
John Wange96e7e52019-10-05 17:47:30 +0800111 DbusValToValMap valueMap;
Tom Joseph52552ef2019-06-20 09:50:15 +0530112 for (auto it = dBusValues.begin(); it != dBusValues.end(); ++it, ++pos)
113 {
114 if (type == "uint8_t")
115 {
116 value = static_cast<uint8_t>(it.value());
117 }
118 else if (type == "uint16_t")
119 {
120 value = static_cast<uint16_t>(it.value());
121 }
122 else if (type == "uint32_t")
123 {
124 value = static_cast<uint32_t>(it.value());
125 }
126 else if (type == "uint64_t")
127 {
128 value = static_cast<uint64_t>(it.value());
129 }
130 else if (type == "int16_t")
131 {
132 value = static_cast<int16_t>(it.value());
133 }
134 else if (type == "int32_t")
135 {
136 value = static_cast<int32_t>(it.value());
137 }
138 else if (type == "int64_t")
139 {
140 value = static_cast<int64_t>(it.value());
141 }
142 else if (type == "bool")
143 {
144 value = static_cast<bool>(it.value());
145 }
146 else if (type == "double")
147 {
148 value = static_cast<double>(it.value());
149 }
150 else if (type == "string")
151 {
152 value = static_cast<std::string>(it.value());
153 }
154 else
155 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600156 std::cerr << "Unknown D-Bus property type, TYPE=" << type.c_str()
157 << "\n";
Tom Joseph52552ef2019-06-20 09:50:15 +0530158 }
159
John Wange96e7e52019-10-05 17:47:30 +0800160 valueMap.emplace(value, pv[pos]);
Tom Joseph52552ef2019-06-20 09:50:15 +0530161 }
162
John Wange96e7e52019-10-05 17:47:30 +0800163 return valueMap;
Tom Joseph52552ef2019-06-20 09:50:15 +0530164}
165
166} // namespace internal
167
John Wange96e7e52019-10-05 17:47:30 +0800168int setupBIOSStrings(const Json& entry, Strings& strings)
Tom Joseph52552ef2019-06-20 09:50:15 +0530169{
John Wange96e7e52019-10-05 17:47:30 +0800170 Json pvs = entry.value("possible_values", emptyJsonList);
Tom Joseph52552ef2019-06-20 09:50:15 +0530171
John Wange96e7e52019-10-05 17:47:30 +0800172 for (auto& pv : pvs)
Tom Joseph52552ef2019-06-20 09:50:15 +0530173 {
John Wange96e7e52019-10-05 17:47:30 +0800174 strings.emplace_back(std::move(pv.get<std::string>()));
Tom Joseph52552ef2019-06-20 09:50:15 +0530175 }
176
John Wange96e7e52019-10-05 17:47:30 +0800177 return 0;
178}
Tom Joseph52552ef2019-06-20 09:50:15 +0530179
John Wange96e7e52019-10-05 17:47:30 +0800180int setup(const Json& entry)
181{
182 PossibleValues possibleValues;
183 DefaultValues defaultValues;
184
185 std::string attrName = entry.value("attribute_name", "");
186 Json pv = entry["possible_values"];
187 for (auto& val : pv)
Tom Joseph52552ef2019-06-20 09:50:15 +0530188 {
John Wange96e7e52019-10-05 17:47:30 +0800189 possibleValues.emplace_back(std::move(val));
Tom Joseph52552ef2019-06-20 09:50:15 +0530190 }
John Wange96e7e52019-10-05 17:47:30 +0800191 Json dv = entry["default_values"];
192 for (auto& val : dv)
Tom Joseph52552ef2019-06-20 09:50:15 +0530193 {
John Wange96e7e52019-10-05 17:47:30 +0800194 defaultValues.emplace_back(std::move(val));
Tom Joseph52552ef2019-06-20 09:50:15 +0530195 }
John Wange96e7e52019-10-05 17:47:30 +0800196 if (entry.count("dbus") != 0)
Tom Joseph52552ef2019-06-20 09:50:15 +0530197 {
John Wange96e7e52019-10-05 17:47:30 +0800198 auto dbusEntry = entry.value("dbus", emptyJson);
199 std::string propertyType = dbusEntry.value("property_type", "");
200 Json propValues = dbusEntry["property_values"];
201 internal::dbusValToValMaps.emplace(
202 attrName, internal::populateMapping(propertyType, propValues,
203 possibleValues));
Tom Joseph52552ef2019-06-20 09:50:15 +0530204 }
John Wange96e7e52019-10-05 17:47:30 +0800205 // Defaulting all the types of attributes to BIOSEnumeration
206 internal::valueMap.emplace(std::move(attrName),
207 std::make_tuple(entry.count("dbus") == 0,
208 std::move(possibleValues),
209 std::move(defaultValues)));
210 return 0;
Tom Joseph52552ef2019-06-20 09:50:15 +0530211}
212
213const AttrValuesMap& getValues()
214{
215 return internal::valueMap;
216}
217
218CurrentValues getAttrValue(const AttrName& attrName)
219{
John Wange96e7e52019-10-05 17:47:30 +0800220 const auto& dBusMap = BIOSAttrLookup.at(attrName);
Tom Joseph52552ef2019-06-20 09:50:15 +0530221 CurrentValues currentValues;
222 internal::PropertyValue propValue;
223
224 if (dBusMap == std::nullopt)
225 {
226 const auto& valueEntry = internal::valueMap.at(attrName);
227 const auto& [readOnly, possibleValues, currentValues] = valueEntry;
228 return currentValues;
229 }
230
John Wange96e7e52019-10-05 17:47:30 +0800231 const auto& dbusValToValMap = internal::dbusValToValMaps.at(attrName);
John Wang8b85f522019-10-17 19:28:19 +0800232 propValue =
George Liu83409572019-12-24 18:42:54 +0800233 pldm::utils::DBusHandler()
John Wang8b85f522019-10-17 19:28:19 +0800234 .getDbusPropertyVariant<internal::PropertyValue>(
235 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
236 dBusMap->interface.c_str());
John Wange96e7e52019-10-05 17:47:30 +0800237 auto iter = dbusValToValMap.find(propValue);
238 if (iter != dbusValToValMap.end())
Tom Joseph52552ef2019-06-20 09:50:15 +0530239 {
240 currentValues.push_back(iter->second);
241 }
242
243 return currentValues;
244}
245
246} // namespace bios_enum
247
Carol Wang612f35b2019-08-26 17:14:26 +0800248namespace bios_string
249{
250
251/** @brief BIOS string types
252 */
253enum BiosStringEncoding
254{
255 UNKNOWN = 0x00,
256 ASCII = 0x01,
257 HEX = 0x02,
258 UTF_8 = 0x03,
259 UTF_16LE = 0x04,
260 UTF_16BE = 0x05,
261 VENDOR_SPECIFIC = 0xFF
262};
263
264const std::map<std::string, uint8_t> strTypeMap{
265 {"Unknown", UNKNOWN},
266 {"ASCII", ASCII},
267 {"Hex", HEX},
268 {"UTF-8", UTF_8},
269 {"UTF-16LE", UTF_16LE},
270 {"UTF-16LE", UTF_16LE},
271 {"Vendor Specific", VENDOR_SPECIFIC}};
272
273namespace internal
274{
275
Carol Wang612f35b2019-08-26 17:14:26 +0800276/** @brief Map containing the possible and the default values for the BIOS
277 * string type attributes.
278 */
279AttrValuesMap valueMap;
280
Carol Wang612f35b2019-08-26 17:14:26 +0800281} // namespace internal
282
John Wangecb7d572019-10-17 13:38:53 +0800283int setup(const Json& jsonEntry)
Carol Wang612f35b2019-08-26 17:14:26 +0800284{
Carol Wang612f35b2019-08-26 17:14:26 +0800285
John Wangecb7d572019-10-17 13:38:53 +0800286 std::string attr = jsonEntry.value("attribute_name", "");
John Wange96e7e52019-10-05 17:47:30 +0800287 // Transfer string type from string to enum
John Wangecb7d572019-10-17 13:38:53 +0800288 std::string strTypeTmp = jsonEntry.value("string_type", "Unknown");
John Wange96e7e52019-10-05 17:47:30 +0800289 auto iter = strTypeMap.find(strTypeTmp);
290 if (iter == strTypeMap.end())
Carol Wang612f35b2019-08-26 17:14:26 +0800291 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600292 std::cerr << "Wrong string type, STRING_TYPE=" << strTypeTmp.c_str()
293 << " ATTRIBUTE_NAME=" << attr.c_str() << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800294 return -1;
295 }
296 uint8_t strType = iter->second;
297
John Wangecb7d572019-10-17 13:38:53 +0800298 uint16_t minStrLen = jsonEntry.value("minimum_string_length", 0);
299 uint16_t maxStrLen = jsonEntry.value("maximum_string_length", 0);
300 uint16_t defaultStrLen = jsonEntry.value("default_string_length", 0);
301 std::string defaultStr = jsonEntry.value("default_string", "");
302
303 pldm_bios_table_attr_entry_string_info info = {
304 0, /* name handle */
305 false, /* read only */
306 strType, minStrLen, maxStrLen, defaultStrLen, defaultStr.data(),
307 };
308
309 const char* errmsg;
310 auto rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg);
311 if (rc != PLDM_SUCCESS)
John Wange96e7e52019-10-05 17:47:30 +0800312 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600313 std::cerr << "Wrong filed for string attribute, ATTRIBUTE_NAME="
314 << attr.c_str() << " ERRMSG=" << errmsg
315 << " MINIMUM_STRING_LENGTH=" << minStrLen
316 << " MAXIMUM_STRING_LENGTH=" << maxStrLen
317 << " DEFAULT_STRING_LENGTH=" << defaultStrLen
318 << " DEFAULT_STRING=" << defaultStr.data() << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800319 return -1;
Carol Wang612f35b2019-08-26 17:14:26 +0800320 }
321
John Wange96e7e52019-10-05 17:47:30 +0800322 // Defaulting all the types of attributes to BIOSString
323 internal::valueMap.emplace(
324 std::move(attr),
John Wangecb7d572019-10-17 13:38:53 +0800325 std::make_tuple(jsonEntry.count("dbus") == 0, strType, minStrLen,
326 maxStrLen, defaultStrLen, std::move(defaultStr)));
Carol Wang612f35b2019-08-26 17:14:26 +0800327
John Wange96e7e52019-10-05 17:47:30 +0800328 return 0;
Carol Wang612f35b2019-08-26 17:14:26 +0800329}
330
331const AttrValuesMap& getValues()
332{
333 return internal::valueMap;
334}
Carol Wangb503f9e2019-09-02 16:34:10 +0800335
336std::string getAttrValue(const AttrName& attrName)
337{
John Wange96e7e52019-10-05 17:47:30 +0800338 const auto& dBusMap = BIOSAttrLookup.at(attrName);
Carol Wangb503f9e2019-09-02 16:34:10 +0800339 std::variant<std::string> propValue;
340
341 if (dBusMap == std::nullopt)
342 { // return default string
343 const auto& valueEntry = internal::valueMap.at(attrName);
344 return std::get<DefaultStr>(valueEntry);
345 }
346
George Liu83409572019-12-24 18:42:54 +0800347 return pldm::utils::DBusHandler().getDbusProperty<std::string>(
John Wang8b85f522019-10-17 19:28:19 +0800348 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
349 dBusMap->interface.c_str());
Carol Wangb503f9e2019-09-02 16:34:10 +0800350}
351
Carol Wang612f35b2019-08-26 17:14:26 +0800352} // namespace bios_string
353
John Wangecb7d572019-10-17 13:38:53 +0800354namespace bios_integer
355{
356
357AttrValuesMap valueMap;
358
359int setup(const Json& jsonEntry)
360{
361
362 std::string attr = jsonEntry.value("attribute_name", "");
363 // Transfer string type from string to enum
364
365 uint64_t lowerBound = jsonEntry.value("lower_bound", 0);
366 uint64_t upperBound = jsonEntry.value("upper_bound", 0);
367 uint32_t scalarIncrement = jsonEntry.value("scalar_increment", 1);
368 uint64_t defaultValue = jsonEntry.value("default_value", 0);
369 pldm_bios_table_attr_entry_integer_info info = {
370 0, /* name handle*/
371 false, /* read only */
372 lowerBound, upperBound, scalarIncrement, defaultValue,
373 };
374 const char* errmsg = nullptr;
375 auto rc = pldm_bios_table_attr_entry_integer_info_check(&info, &errmsg);
376 if (rc != PLDM_SUCCESS)
377 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600378 std::cerr << "Wrong filed for integer attribute, ATTRIBUTE_NAME="
379 << attr.c_str() << " ERRMSG=" << errmsg
380 << " LOWER_BOUND=" << lowerBound
381 << " UPPER_BOUND=" << upperBound
382 << " DEFAULT_VALUE=" << defaultValue
383 << " SCALAR_INCREMENT=" << scalarIncrement << "\n";
John Wangecb7d572019-10-17 13:38:53 +0800384 return -1;
385 }
386
387 valueMap.emplace(std::move(attr),
388 std::make_tuple(jsonEntry.count("dbus") == 0, lowerBound,
389 upperBound, scalarIncrement,
390 defaultValue));
391
392 return 0;
393}
394
395const AttrValuesMap& getValues()
396{
397 return valueMap;
398}
399
400uint64_t getAttrValue(const AttrName& attrName)
401{
402 const auto& dBusMap = BIOSAttrLookup.at(attrName);
403 std::variant<std::string> propValue;
404
405 if (dBusMap == std::nullopt)
406 { // return default string
407 const auto& valueEntry = valueMap.at(attrName);
408 return std::get<AttrDefaultValue>(valueEntry);
409 }
410
George Liu83409572019-12-24 18:42:54 +0800411 return pldm::utils::DBusHandler().getDbusProperty<uint64_t>(
John Wangecb7d572019-10-17 13:38:53 +0800412 dBusMap->objectPath.c_str(), dBusMap->propertyName.c_str(),
413 dBusMap->interface.c_str());
414}
415
416} // namespace bios_integer
417
John Wange96e7e52019-10-05 17:47:30 +0800418const std::map<BIOSJsonName, BIOSStringHandler> BIOSStringHandlers = {
419 {bIOSEnumJson, bios_enum::setupBIOSStrings},
420};
Tom Joseph52552ef2019-06-20 09:50:15 +0530421
John Wange96e7e52019-10-05 17:47:30 +0800422const std::map<BIOSJsonName, typeHandler> BIOSTypeHandlers = {
423 {bIOSEnumJson, bios_enum::setup},
424 {bIOSStrJson, bios_string::setup},
John Wangecb7d572019-10-17 13:38:53 +0800425 {bIOSIntegerJson, bios_integer::setup},
John Wange96e7e52019-10-05 17:47:30 +0800426};
427
428void setupBIOSStrings(const BIOSJsonName& jsonName, const Json& entry,
429 Strings& strings)
430{
431 strings.emplace_back(entry.value("attribute_name", ""));
432 auto iter = BIOSStringHandlers.find(jsonName);
433 if (iter != BIOSStringHandlers.end())
434 {
435 iter->second(entry, strings);
436 }
437}
438
John Wangecb7d572019-10-17 13:38:53 +0800439void setupBIOSAttrLookup(const Json& jsonEntry, AttrLookup& lookup)
John Wange96e7e52019-10-05 17:47:30 +0800440{
441 std::optional<DBusMapping> dBusMap;
John Wangecb7d572019-10-17 13:38:53 +0800442 std::string attrName = jsonEntry.value("attribute_name", "");
John Wange96e7e52019-10-05 17:47:30 +0800443
John Wangecb7d572019-10-17 13:38:53 +0800444 if (jsonEntry.count("dbus") != 0)
John Wange96e7e52019-10-05 17:47:30 +0800445 {
John Wangecb7d572019-10-17 13:38:53 +0800446 auto dBusEntry = jsonEntry.value("dbus", emptyJson);
John Wange96e7e52019-10-05 17:47:30 +0800447 std::string objectPath = dBusEntry.value("object_path", "");
448 std::string interface = dBusEntry.value("interface", "");
449 std::string propertyName = dBusEntry.value("property_name", "");
450 if (!objectPath.empty() && !interface.empty() && !propertyName.empty())
451 {
452 dBusMap = std::optional<DBusMapping>(
453 {objectPath, interface, propertyName});
454 }
455 else
456 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600457 std::cerr << "Invalid dbus config, OBJPATH="
458 << dBusMap->objectPath.c_str()
459 << " INTERFACE=" << dBusMap->interface.c_str()
460 << " PROPERTY_NAME=" << dBusMap->propertyName.c_str()
461 << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800462 }
463 }
464 lookup.emplace(attrName, dBusMap);
465}
466
467int setupBIOSType(const BIOSJsonName& jsonName, const Json& entry)
468{
469 auto iter = BIOSTypeHandlers.find(jsonName);
470 if (iter != BIOSTypeHandlers.end())
471 {
472 iter->second(entry);
473 }
474 return 0;
475}
476
John Wangecb7d572019-10-17 13:38:53 +0800477const std::vector<BIOSJsonName> BIOSConfigFiles = {bIOSEnumJson, bIOSStrJson,
478 bIOSIntegerJson};
John Wange96e7e52019-10-05 17:47:30 +0800479
480int setupConfig(const char* dirPath)
481{
482 if (!BIOSStrings.empty() && !BIOSAttrLookup.empty())
483 {
484 return 0;
485 }
486
487 fs::path dir(dirPath);
Tom Joseph52552ef2019-06-20 09:50:15 +0530488 if (!fs::exists(dir) || fs::is_empty(dir))
489 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600490 std::cerr << "BIOS config directory does not exist or empty, DIR="
491 << dirPath << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800492 return -1;
Tom Joseph52552ef2019-06-20 09:50:15 +0530493 }
John Wange96e7e52019-10-05 17:47:30 +0800494 for (auto jsonName : BIOSConfigFiles)
Tom Joseph52552ef2019-06-20 09:50:15 +0530495 {
John Wange96e7e52019-10-05 17:47:30 +0800496 Json json;
497 if (parseBiosJsonFile(dir, jsonName, json) < 0)
Tom Joseph52552ef2019-06-20 09:50:15 +0530498 {
Tom Joseph52552ef2019-06-20 09:50:15 +0530499 continue;
500 }
John Wange96e7e52019-10-05 17:47:30 +0800501 auto entries = json.value("entries", emptyJsonList);
Tom Joseph52552ef2019-06-20 09:50:15 +0530502 for (auto& entry : entries)
503 {
John Wange96e7e52019-10-05 17:47:30 +0800504 setupBIOSStrings(jsonName, entry, BIOSStrings);
505 setupBIOSAttrLookup(entry, BIOSAttrLookup);
506 setupBIOSType(jsonName, entry);
Tom Joseph52552ef2019-06-20 09:50:15 +0530507 }
508 }
John Wange96e7e52019-10-05 17:47:30 +0800509 if (BIOSStrings.empty())
510 { // means there is no attribute
Sampa Misraaa8ae722019-12-12 03:20:40 -0600511 std::cerr << "No attribute is found in the config directory, DIR="
512 << dirPath << "\n";
John Wange96e7e52019-10-05 17:47:30 +0800513 return -1;
514 }
515 return 0;
Tom Joseph52552ef2019-06-20 09:50:15 +0530516}
517
518} // namespace bios_parser