1 #include "bios_config.hpp"
2 
3 #include "bios_enum_attribute.hpp"
4 #include "bios_integer_attribute.hpp"
5 #include "bios_string_attribute.hpp"
6 #include "bios_table.hpp"
7 #include "common/bios_utils.hpp"
8 
9 #include <fstream>
10 #include <iostream>
11 
12 namespace pldm
13 {
14 namespace responder
15 {
16 namespace bios
17 {
18 namespace
19 {
20 
21 constexpr auto enumJsonFile = "enum_attrs.json";
22 constexpr auto stringJsonFile = "string_attrs.json";
23 constexpr auto integerJsonFile = "integer_attrs.json";
24 
25 constexpr auto stringTableFile = "stringTable";
26 constexpr auto attrTableFile = "attributeTable";
27 constexpr auto attrValueTableFile = "attributeValueTable";
28 
29 } // namespace
30 
31 BIOSConfig::BIOSConfig(const char* jsonDir, const char* tableDir,
32                        DBusHandler* const dbusHandler) :
33     jsonDir(jsonDir),
34     tableDir(tableDir), dbusHandler(dbusHandler), isUpdateProperty(false)
35 {
36     fs::create_directories(tableDir);
37     constructAttributes();
38 }
39 
40 void BIOSConfig::buildTables()
41 {
42     auto stringTable = buildAndStoreStringTable();
43     if (stringTable)
44     {
45         buildAndStoreAttrTables(*stringTable);
46     }
47 }
48 
49 std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
50 {
51     fs::path tablePath;
52     switch (tableType)
53     {
54         case PLDM_BIOS_STRING_TABLE:
55             tablePath = tableDir / stringTableFile;
56             break;
57         case PLDM_BIOS_ATTR_TABLE:
58             tablePath = tableDir / attrTableFile;
59             break;
60         case PLDM_BIOS_ATTR_VAL_TABLE:
61             tablePath = tableDir / attrValueTableFile;
62             break;
63     }
64     return loadTable(tablePath);
65 }
66 
67 int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table)
68 {
69     fs::path stringTablePath(tableDir / stringTableFile);
70     fs::path attrTablePath(tableDir / attrTableFile);
71     fs::path attrValueTablePath(tableDir / attrValueTableFile);
72 
73     if (!pldm_bios_table_checksum(table.data(), table.size()))
74     {
75         return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
76     }
77 
78     if (tableType == PLDM_BIOS_STRING_TABLE)
79     {
80         storeTable(stringTablePath, table);
81     }
82     else if (tableType == PLDM_BIOS_ATTR_TABLE)
83     {
84         BIOSTable biosStringTable(stringTablePath.c_str());
85         if (biosStringTable.isEmpty())
86         {
87             return PLDM_INVALID_BIOS_TABLE_TYPE;
88         }
89 
90         auto rc = checkAttributeTable(table);
91         if (rc != PLDM_SUCCESS)
92         {
93             return rc;
94         }
95 
96         storeTable(attrTablePath, table);
97     }
98     else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
99     {
100         BIOSTable biosStringTable(stringTablePath.c_str());
101         BIOSTable biosStringValueTable(attrTablePath.c_str());
102         if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
103         {
104             return PLDM_INVALID_BIOS_TABLE_TYPE;
105         }
106 
107         auto rc = checkAttributeValueTable(table);
108         if (rc != PLDM_SUCCESS)
109         {
110             return rc;
111         }
112 
113         storeTable(attrValueTablePath, table);
114         isUpdateProperty = true;
115     }
116     else
117     {
118         return PLDM_INVALID_BIOS_TABLE_TYPE;
119     }
120 
121     if (isUpdateProperty)
122     {
123         isUpdateProperty = false;
124         updateBaseBIOSTableProperty();
125     }
126 
127     return PLDM_SUCCESS;
128 }
129 
130 int BIOSConfig::checkAttributeTable(const Table& table)
131 {
132     using namespace pldm::bios::utils;
133     auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
134     for (auto entry :
135          BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
136     {
137         auto attrNameHandle =
138             pldm_bios_table_attr_entry_decode_string_handle(entry);
139 
140         auto stringEnty = pldm_bios_table_string_find_by_handle(
141             stringTable->data(), stringTable->size(), attrNameHandle);
142         if (stringEnty == nullptr)
143         {
144             return PLDM_INVALID_BIOS_ATTR_HANDLE;
145         }
146 
147         auto attrType = static_cast<pldm_bios_attribute_type>(
148             pldm_bios_table_attr_entry_decode_attribute_type(entry));
149 
150         switch (attrType)
151         {
152             case PLDM_BIOS_ENUMERATION:
153             case PLDM_BIOS_ENUMERATION_READ_ONLY:
154             {
155                 auto pvNum =
156                     pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
157                 std::vector<uint16_t> pvHandls(pvNum);
158                 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
159                     entry, pvHandls.data(), pvHandls.size());
160                 auto defNum =
161                     pldm_bios_table_attr_entry_enum_decode_def_num(entry);
162                 std::vector<uint8_t> defIndices(defNum);
163                 pldm_bios_table_attr_entry_enum_decode_def_indices(
164                     entry, defIndices.data(), defIndices.size());
165 
166                 for (size_t i = 0; i < pvHandls.size(); i++)
167                 {
168                     auto stringEntry = pldm_bios_table_string_find_by_handle(
169                         stringTable->data(), stringTable->size(), pvHandls[i]);
170                     if (stringEntry == nullptr)
171                     {
172                         return PLDM_INVALID_BIOS_ATTR_HANDLE;
173                     }
174                 }
175 
176                 for (size_t i = 0; i < defIndices.size(); i++)
177                 {
178                     auto stringEntry = pldm_bios_table_string_find_by_handle(
179                         stringTable->data(), stringTable->size(),
180                         pvHandls[defIndices[i]]);
181                     if (stringEntry == nullptr)
182                     {
183                         return PLDM_INVALID_BIOS_ATTR_HANDLE;
184                     }
185                 }
186                 break;
187             }
188             case PLDM_BIOS_INTEGER:
189             case PLDM_BIOS_INTEGER_READ_ONLY:
190             case PLDM_BIOS_STRING:
191             case PLDM_BIOS_STRING_READ_ONLY:
192             case PLDM_BIOS_PASSWORD:
193             case PLDM_BIOS_PASSWORD_READ_ONLY:
194                 break;
195             default:
196                 return PLDM_INVALID_BIOS_ATTR_HANDLE;
197         }
198     }
199 
200     return PLDM_SUCCESS;
201 }
202 
203 int BIOSConfig::checkAttributeValueTable(const Table& table)
204 {
205     using namespace pldm::bios::utils;
206     auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
207     auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
208 
209     baseBIOSTableMaps.clear();
210 
211     for (auto tableEntry :
212          BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
213     {
214         AttributeName attributeName{};
215         AttributeType attributeType{};
216         ReadonlyStatus readonlyStatus{};
217         DisplayName displayName{};
218         Description description{};
219         MenuPath menuPath{};
220         CurrentValue currentValue{};
221         DefaultValue defaultValue{};
222         Option options{};
223 
224         auto attrValueHandle =
225             pldm_bios_table_attr_value_entry_decode_attribute_handle(
226                 tableEntry);
227         auto attrType = static_cast<pldm_bios_attribute_type>(
228             pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
229 
230         auto attrEntry = pldm_bios_table_attr_find_by_handle(
231             attrTable->data(), attrTable->size(), attrValueHandle);
232         if (attrEntry == nullptr)
233         {
234             return PLDM_INVALID_BIOS_ATTR_HANDLE;
235         }
236         auto attrHandle =
237             pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
238         auto attrNameHandle =
239             pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
240 
241         auto stringEntry = pldm_bios_table_string_find_by_handle(
242             stringTable->data(), stringTable->size(), attrNameHandle);
243         if (stringEntry == nullptr)
244         {
245             return PLDM_INVALID_BIOS_ATTR_HANDLE;
246         }
247         auto strLength =
248             pldm_bios_table_string_entry_decode_string_length(stringEntry);
249         std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
250         pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
251                                                    buffer.size());
252         attributeName = std::string(buffer.data(), buffer.data() + strLength);
253 
254         if (!biosAttributes.empty())
255         {
256             readonlyStatus =
257                 biosAttributes[attrHandle / biosAttributes.size()]->readOnly;
258         }
259 
260         switch (attrType)
261         {
262             case PLDM_BIOS_ENUMERATION:
263             case PLDM_BIOS_ENUMERATION_READ_ONLY:
264             {
265                 auto getValue = [](uint16_t handle,
266                                    const Table& table) -> std::string {
267                     auto stringEntry = pldm_bios_table_string_find_by_handle(
268                         table.data(), table.size(), handle);
269 
270                     auto strLength =
271                         pldm_bios_table_string_entry_decode_string_length(
272                             stringEntry);
273                     std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
274                     pldm_bios_table_string_entry_decode_string(
275                         stringEntry, buffer.data(), buffer.size());
276 
277                     return std::string(buffer.data(),
278                                        buffer.data() + strLength);
279                 };
280 
281                 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
282                                 "AttributeType.Enumeration";
283 
284                 auto pvNum =
285                     pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry);
286                 std::vector<uint16_t> pvHandls(pvNum);
287                 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
288                     attrEntry, pvHandls.data(), pvHandls.size());
289 
290                 // get possible_value
291                 for (size_t i = 0; i < pvHandls.size(); i++)
292                 {
293                     options.push_back(
294                         std::make_tuple("xyz.openbmc_project.BIOSConfig."
295                                         "Manager.BoundType.OneOf",
296                                         getValue(pvHandls[i], *stringTable)));
297                 }
298 
299                 auto count =
300                     pldm_bios_table_attr_value_entry_enum_decode_number(
301                         tableEntry);
302                 std::vector<uint8_t> handles(count);
303                 pldm_bios_table_attr_value_entry_enum_decode_handles(
304                     tableEntry, handles.data(), handles.size());
305 
306                 // get current_value
307                 for (size_t i = 0; i < handles.size(); i++)
308                 {
309                     currentValue = getValue(pvHandls[handles[i]], *stringTable);
310                 }
311 
312                 auto defNum =
313                     pldm_bios_table_attr_entry_enum_decode_def_num(attrEntry);
314                 std::vector<uint8_t> defIndices(defNum);
315                 pldm_bios_table_attr_entry_enum_decode_def_indices(
316                     attrEntry, defIndices.data(), defIndices.size());
317 
318                 // get default_value
319                 for (size_t i = 0; i < defIndices.size(); i++)
320                 {
321                     defaultValue =
322                         getValue(pvHandls[defIndices[i]], *stringTable);
323                 }
324 
325                 break;
326             }
327             case PLDM_BIOS_INTEGER:
328             case PLDM_BIOS_INTEGER_READ_ONLY:
329             {
330                 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
331                                 "AttributeType.Integer";
332                 currentValue = static_cast<int64_t>(
333                     pldm_bios_table_attr_value_entry_integer_decode_cv(
334                         tableEntry));
335 
336                 uint64_t lower, upper, def;
337                 uint32_t scalar;
338                 pldm_bios_table_attr_entry_integer_decode(
339                     attrEntry, &lower, &upper, &scalar, &def);
340                 options.push_back(
341                     std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
342                                     "BoundType.LowerBound",
343                                     static_cast<int64_t>(lower)));
344                 options.push_back(
345                     std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
346                                     "BoundType.UpperBound",
347                                     static_cast<int64_t>(upper)));
348                 options.push_back(
349                     std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
350                                     "BoundType.ScalarIncrement",
351                                     static_cast<int64_t>(scalar)));
352                 defaultValue = static_cast<int64_t>(def);
353                 break;
354             }
355             case PLDM_BIOS_STRING:
356             case PLDM_BIOS_STRING_READ_ONLY:
357             {
358                 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
359                                 "AttributeType.String";
360                 variable_field currentString;
361                 pldm_bios_table_attr_value_entry_string_decode_string(
362                     tableEntry, &currentString);
363                 currentValue = std::string(
364                     reinterpret_cast<const char*>(currentString.ptr),
365                     currentString.length);
366                 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
367                     attrEntry);
368                 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
369                     attrEntry);
370                 auto def =
371                     pldm_bios_table_attr_entry_string_decode_def_string_length(
372                         attrEntry);
373                 std::vector<char> defString(def + 1);
374                 pldm_bios_table_attr_entry_string_decode_def_string(
375                     attrEntry, defString.data(), defString.size());
376                 options.push_back(
377                     std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
378                                     "BoundType.MinStringLength",
379                                     static_cast<int64_t>(min)));
380                 options.push_back(
381                     std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
382                                     "BoundType.MaxStringLength",
383                                     static_cast<int64_t>(max)));
384                 defaultValue = defString.data();
385                 break;
386             }
387             case PLDM_BIOS_PASSWORD:
388             case PLDM_BIOS_PASSWORD_READ_ONLY:
389             {
390                 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
391                                 "AttributeType.Password";
392                 break;
393             }
394             default:
395                 return PLDM_INVALID_BIOS_ATTR_HANDLE;
396         }
397         baseBIOSTableMaps.emplace(
398             std::move(attributeName),
399             std::make_tuple(attributeType, readonlyStatus, displayName,
400                             description, menuPath, currentValue, defaultValue,
401                             std::move(options)));
402     }
403 
404     return PLDM_SUCCESS;
405 }
406 
407 void BIOSConfig::updateBaseBIOSTableProperty()
408 {
409     constexpr static auto biosConfigPath =
410         "/xyz/openbmc_project/bios_config/manager";
411     constexpr static auto biosConfigInterface =
412         "xyz.openbmc_project.BIOSConfig.Manager";
413     constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
414     constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
415 
416     if (baseBIOSTableMaps.empty())
417     {
418         return;
419     }
420 
421     try
422     {
423         auto& bus = dbusHandler->getBus();
424         auto service =
425             dbusHandler->getService(biosConfigPath, biosConfigInterface);
426         auto method = bus.new_method_call(service.c_str(), biosConfigPath,
427                                           dbusProperties, "Set");
428         std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
429         method.append(biosConfigInterface, biosConfigPropertyName, value);
430         bus.call_noreply(method);
431     }
432     catch (const std::exception& e)
433     {
434         std::cerr << "failed to update BaseBIOSTable property, ERROR="
435                   << e.what() << "\n";
436     }
437 }
438 
439 void BIOSConfig::constructAttributes()
440 {
441     load(jsonDir / stringJsonFile, [this](const Json& entry) {
442         constructAttribute<BIOSStringAttribute>(entry);
443     });
444     load(jsonDir / integerJsonFile, [this](const Json& entry) {
445         constructAttribute<BIOSIntegerAttribute>(entry);
446     });
447     load(jsonDir / enumJsonFile, [this](const Json& entry) {
448         constructAttribute<BIOSEnumAttribute>(entry);
449     });
450 }
451 
452 void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
453 {
454     BIOSStringTable biosStringTable(stringTable);
455 
456     if (biosAttributes.empty())
457     {
458         return;
459     }
460 
461     Table attrTable, attrValueTable;
462 
463     for (auto& attr : biosAttributes)
464     {
465         try
466         {
467             attr->constructEntry(biosStringTable, attrTable, attrValueTable);
468         }
469         catch (const std::exception& e)
470         {
471             std::cerr << "Construct Table Entry Error, AttributeName = "
472                       << attr->name << std::endl;
473         }
474     }
475 
476     table::appendPadAndChecksum(attrTable);
477     table::appendPadAndChecksum(attrValueTable);
478     setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
479     setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
480 }
481 
482 std::optional<Table> BIOSConfig::buildAndStoreStringTable()
483 {
484     std::set<std::string> strings;
485     auto handler = [&strings](const Json& entry) {
486         strings.emplace(entry.at("attribute_name"));
487     };
488 
489     load(jsonDir / stringJsonFile, handler);
490     load(jsonDir / integerJsonFile, handler);
491     load(jsonDir / enumJsonFile, [&strings](const Json& entry) {
492         strings.emplace(entry.at("attribute_name"));
493         auto possibleValues = entry.at("possible_values");
494         for (auto& pv : possibleValues)
495         {
496             strings.emplace(pv);
497         }
498     });
499 
500     if (strings.empty())
501     {
502         return std::nullopt;
503     }
504 
505     Table table;
506     for (const auto& elem : strings)
507     {
508         table::string::constructEntry(table, elem);
509     }
510 
511     table::appendPadAndChecksum(table);
512     setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
513     return table;
514 }
515 
516 void BIOSConfig::storeTable(const fs::path& path, const Table& table)
517 {
518     BIOSTable biosTable(path.c_str());
519     biosTable.store(table);
520 }
521 
522 std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
523 {
524     BIOSTable biosTable(path.c_str());
525     if (biosTable.isEmpty())
526     {
527         return std::nullopt;
528     }
529 
530     Table table;
531     biosTable.load(table);
532     return table;
533 }
534 
535 void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
536 {
537     std::ifstream file;
538     Json jsonConf;
539     if (fs::exists(filePath))
540     {
541         try
542         {
543             file.open(filePath);
544             jsonConf = Json::parse(file);
545             auto entries = jsonConf.at("entries");
546             for (auto& entry : entries)
547             {
548                 try
549                 {
550                     handler(entry);
551                 }
552                 catch (const std::exception& e)
553                 {
554                     std::cerr
555                         << "Failed to parse JSON config file(entry handler) : "
556                         << filePath.c_str() << ", " << e.what() << std::endl;
557                 }
558             }
559         }
560         catch (const std::exception& e)
561         {
562             std::cerr << "Failed to parse JSON config file : "
563                       << filePath.c_str() << std::endl;
564         }
565     }
566 }
567 
568 int BIOSConfig::checkAttrValueToUpdate(
569     const pldm_bios_attr_val_table_entry* attrValueEntry,
570     const pldm_bios_attr_table_entry* attrEntry, Table&)
571 
572 {
573     auto [attrHandle, attrType] =
574         table::attribute_value::decodeHeader(attrValueEntry);
575 
576     switch (attrType)
577     {
578         case PLDM_BIOS_ENUMERATION:
579         {
580             auto value =
581                 table::attribute_value::decodeEnumEntry(attrValueEntry);
582             auto [pvHdls, defIndex] =
583                 table::attribute::decodeEnumEntry(attrEntry);
584             assert(value.size() == 1);
585             if (value[0] >= pvHdls.size())
586             {
587                 std::cerr << "Enum: Illgeal index, Index = " << (int)value[0]
588                           << std::endl;
589                 return PLDM_ERROR_INVALID_DATA;
590             }
591 
592             return PLDM_SUCCESS;
593         }
594         case PLDM_BIOS_INTEGER:
595         {
596             auto value =
597                 table::attribute_value::decodeIntegerEntry(attrValueEntry);
598             auto [lower, upper, scalar, def] =
599                 table::attribute::decodeIntegerEntry(attrEntry);
600 
601             if (value < lower || value > upper)
602             {
603                 std::cerr << "Integer: out of bound, value = " << value
604                           << std::endl;
605                 return PLDM_ERROR_INVALID_DATA;
606             }
607             return PLDM_SUCCESS;
608         }
609         case PLDM_BIOS_STRING:
610         {
611             auto stringConf = table::attribute::decodeStringEntry(attrEntry);
612             auto value =
613                 table::attribute_value::decodeStringEntry(attrValueEntry);
614             if (value.size() < stringConf.minLength ||
615                 value.size() > stringConf.maxLength)
616             {
617                 std::cerr << "String: Length error, string = " << value
618                           << " length = " << value.size() << std::endl;
619                 return PLDM_ERROR_INVALID_LENGTH;
620             }
621             return PLDM_SUCCESS;
622         }
623         default:
624             std::cerr << "ReadOnly or Unspported type, type = " << attrType
625                       << std::endl;
626             return PLDM_ERROR;
627     };
628 }
629 
630 int BIOSConfig::setAttrValue(const void* entry, size_t size)
631 {
632     auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
633     auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
634     auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
635     if (!attrValueTable || !attrTable || !stringTable)
636     {
637         return PLDM_BIOS_TABLE_UNAVAILABLE;
638     }
639 
640     auto attrValueEntry =
641         reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
642 
643     auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
644 
645     auto attrEntry =
646         table::attribute::findByHandle(*attrTable, attrValHeader.attrHandle);
647     if (!attrEntry)
648     {
649         return PLDM_ERROR;
650     }
651 
652     auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
653     if (rc != PLDM_SUCCESS)
654     {
655         return rc;
656     }
657 
658     auto destTable =
659         table::attribute_value::updateTable(*attrValueTable, entry, size);
660 
661     if (!destTable)
662     {
663         return PLDM_ERROR;
664     }
665 
666     try
667     {
668         auto attrHeader = table::attribute::decodeHeader(attrEntry);
669 
670         BIOSStringTable biosStringTable(*stringTable);
671         auto attrName = biosStringTable.findString(attrHeader.stringHandle);
672 
673         auto iter = std::find_if(
674             biosAttributes.begin(), biosAttributes.end(),
675             [&attrName](const auto& attr) { return attr->name == attrName; });
676 
677         if (iter == biosAttributes.end())
678         {
679             return PLDM_ERROR;
680         }
681         (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry, biosStringTable);
682     }
683     catch (const std::exception& e)
684     {
685         std::cerr << "Set attribute value error: " << e.what() << std::endl;
686         return PLDM_ERROR;
687     }
688 
689     BIOSTable biosAttrValueTable((tableDir / attrValueTableFile).c_str());
690     biosAttrValueTable.store(*destTable);
691     return PLDM_SUCCESS;
692 }
693 
694 void BIOSConfig::removeTables()
695 {
696     try
697     {
698         fs::remove(tableDir / stringTableFile);
699         fs::remove(tableDir / attrTableFile);
700         fs::remove(tableDir / attrValueTableFile);
701     }
702     catch (const std::exception& e)
703     {
704         std::cerr << "Remove the tables error: " << e.what() << std::endl;
705     }
706 }
707 
708 void BIOSConfig::processBiosAttrChangeNotification(
709     const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
710 {
711     const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
712     const auto& propertyName = dBusMap->propertyName;
713     const auto& attrName = biosAttributes[biosAttrIndex]->name;
714 
715     const auto it = chProperties.find(propertyName);
716     if (it == chProperties.end())
717     {
718         return;
719     }
720 
721     PropertyValue newPropVal = it->second;
722     auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
723     if (!stringTable.has_value())
724     {
725         std::cerr << "BIOS string table unavailable\n";
726         return;
727     }
728     BIOSStringTable biosStringTable(*stringTable);
729     uint16_t attrNameHdl{};
730     try
731     {
732         attrNameHdl = biosStringTable.findHandle(attrName);
733     }
734     catch (std::invalid_argument& e)
735     {
736         std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
737                   << attrName.c_str() << "\n";
738         return;
739     }
740 
741     auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
742     if (!attrTable.has_value())
743     {
744         std::cerr << "Attribute table not present\n";
745         return;
746     }
747     const struct pldm_bios_attr_table_entry* tableEntry =
748         table::attribute::findByStringHandle(*attrTable, attrNameHdl);
749     if (tableEntry == nullptr)
750     {
751         std::cerr << "Attribute not found in attribute table, name= "
752                   << attrName.c_str() << "name handle=" << attrNameHdl << "\n";
753         return;
754     }
755 
756     auto [attrHdl, attrType, stringHdl] =
757         table::attribute::decodeHeader(tableEntry);
758 
759     auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
760 
761     if (!attrValueSrcTable.has_value())
762     {
763         std::cerr << "Attribute value table not present\n";
764         return;
765     }
766 
767     Table newValue;
768     auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
769         newValue, attrHdl, attrType, newPropVal);
770     if (rc != PLDM_SUCCESS)
771     {
772         std::cerr << "Could not update the attribute value table for attribute "
773                      "handle="
774                   << attrHdl << " and type=" << (uint32_t)attrType << "\n";
775         return;
776     }
777     auto destTable = table::attribute_value::updateTable(
778         *attrValueSrcTable, newValue.data(), newValue.size());
779     if (destTable.has_value())
780     {
781         storeTable(tableDir / attrValueTableFile, *destTable);
782     }
783 }
784 
785 } // namespace bios
786 } // namespace responder
787 } // namespace pldm
788