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