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