blob: 5497ac679634443f032845b3b468c1bf3de72648 [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 =
George Liub1fbeec2020-09-04 09:59:46 +0800271 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800272 description =
273 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
274 displayName =
275 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
George Liu1b180d82020-07-23 14:01:58 +0800276 }
277
278 switch (attrType)
279 {
280 case PLDM_BIOS_ENUMERATION:
281 case PLDM_BIOS_ENUMERATION_READ_ONLY:
282 {
283 auto getValue = [](uint16_t handle,
284 const Table& table) -> std::string {
285 auto stringEntry = pldm_bios_table_string_find_by_handle(
286 table.data(), table.size(), handle);
287
288 auto strLength =
289 pldm_bios_table_string_entry_decode_string_length(
290 stringEntry);
291 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
292 pldm_bios_table_string_entry_decode_string(
293 stringEntry, buffer.data(), buffer.size());
294
295 return std::string(buffer.data(),
296 buffer.data() + strLength);
297 };
298
299 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
300 "AttributeType.Enumeration";
301
302 auto pvNum =
303 pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry);
304 std::vector<uint16_t> pvHandls(pvNum);
305 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
306 attrEntry, pvHandls.data(), pvHandls.size());
307
308 // get possible_value
309 for (size_t i = 0; i < pvHandls.size(); i++)
310 {
311 options.push_back(
312 std::make_tuple("xyz.openbmc_project.BIOSConfig."
313 "Manager.BoundType.OneOf",
314 getValue(pvHandls[i], *stringTable)));
315 }
316
317 auto count =
318 pldm_bios_table_attr_value_entry_enum_decode_number(
319 tableEntry);
320 std::vector<uint8_t> handles(count);
321 pldm_bios_table_attr_value_entry_enum_decode_handles(
322 tableEntry, handles.data(), handles.size());
323
324 // get current_value
325 for (size_t i = 0; i < handles.size(); i++)
326 {
327 currentValue = getValue(pvHandls[handles[i]], *stringTable);
328 }
329
330 auto defNum =
331 pldm_bios_table_attr_entry_enum_decode_def_num(attrEntry);
332 std::vector<uint8_t> defIndices(defNum);
333 pldm_bios_table_attr_entry_enum_decode_def_indices(
334 attrEntry, defIndices.data(), defIndices.size());
335
336 // get default_value
337 for (size_t i = 0; i < defIndices.size(); i++)
338 {
339 defaultValue =
340 getValue(pvHandls[defIndices[i]], *stringTable);
341 }
342
343 break;
344 }
345 case PLDM_BIOS_INTEGER:
346 case PLDM_BIOS_INTEGER_READ_ONLY:
347 {
348 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
349 "AttributeType.Integer";
350 currentValue = static_cast<int64_t>(
351 pldm_bios_table_attr_value_entry_integer_decode_cv(
352 tableEntry));
353
354 uint64_t lower, upper, def;
355 uint32_t scalar;
356 pldm_bios_table_attr_entry_integer_decode(
357 attrEntry, &lower, &upper, &scalar, &def);
358 options.push_back(
359 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
360 "BoundType.LowerBound",
361 static_cast<int64_t>(lower)));
362 options.push_back(
363 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
364 "BoundType.UpperBound",
365 static_cast<int64_t>(upper)));
366 options.push_back(
367 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
368 "BoundType.ScalarIncrement",
369 static_cast<int64_t>(scalar)));
370 defaultValue = static_cast<int64_t>(def);
371 break;
372 }
373 case PLDM_BIOS_STRING:
374 case PLDM_BIOS_STRING_READ_ONLY:
375 {
376 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
377 "AttributeType.String";
378 variable_field currentString;
379 pldm_bios_table_attr_value_entry_string_decode_string(
380 tableEntry, &currentString);
381 currentValue = std::string(
382 reinterpret_cast<const char*>(currentString.ptr),
383 currentString.length);
384 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
385 attrEntry);
386 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
387 attrEntry);
388 auto def =
389 pldm_bios_table_attr_entry_string_decode_def_string_length(
390 attrEntry);
391 std::vector<char> defString(def + 1);
392 pldm_bios_table_attr_entry_string_decode_def_string(
393 attrEntry, defString.data(), defString.size());
394 options.push_back(
395 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
396 "BoundType.MinStringLength",
397 static_cast<int64_t>(min)));
398 options.push_back(
399 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
400 "BoundType.MaxStringLength",
401 static_cast<int64_t>(max)));
402 defaultValue = defString.data();
403 break;
404 }
405 case PLDM_BIOS_PASSWORD:
406 case PLDM_BIOS_PASSWORD_READ_ONLY:
407 {
408 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
409 "AttributeType.Password";
410 break;
411 }
412 default:
413 return PLDM_INVALID_BIOS_ATTR_HANDLE;
414 }
415 baseBIOSTableMaps.emplace(
416 std::move(attributeName),
417 std::make_tuple(attributeType, readonlyStatus, displayName,
418 description, menuPath, currentValue, defaultValue,
419 std::move(options)));
420 }
421
422 return PLDM_SUCCESS;
423}
424
425void BIOSConfig::updateBaseBIOSTableProperty()
426{
427 constexpr static auto biosConfigPath =
428 "/xyz/openbmc_project/bios_config/manager";
429 constexpr static auto biosConfigInterface =
430 "xyz.openbmc_project.BIOSConfig.Manager";
431 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
432 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
433
434 if (baseBIOSTableMaps.empty())
435 {
436 return;
437 }
438
439 try
440 {
441 auto& bus = dbusHandler->getBus();
442 auto service =
443 dbusHandler->getService(biosConfigPath, biosConfigInterface);
444 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
445 dbusProperties, "Set");
446 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
447 method.append(biosConfigInterface, biosConfigPropertyName, value);
448 bus.call_noreply(method);
449 }
450 catch (const std::exception& e)
451 {
452 std::cerr << "failed to update BaseBIOSTable property, ERROR="
453 << e.what() << "\n";
454 }
455}
456
John Wangd9659342020-02-27 16:46:05 +0800457void BIOSConfig::constructAttributes()
458{
459 load(jsonDir / stringJsonFile, [this](const Json& entry) {
460 constructAttribute<BIOSStringAttribute>(entry);
461 });
John Wang3be70852020-02-13 15:59:04 +0800462 load(jsonDir / integerJsonFile, [this](const Json& entry) {
John Wang95e6b3c2020-02-13 09:43:24 +0800463 constructAttribute<BIOSIntegerAttribute>(entry);
464 });
John Wang3be70852020-02-13 15:59:04 +0800465 load(jsonDir / enumJsonFile, [this](const Json& entry) {
466 constructAttribute<BIOSEnumAttribute>(entry);
467 });
John Wangd9659342020-02-27 16:46:05 +0800468}
469
470void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
471{
472 BIOSStringTable biosStringTable(stringTable);
473
474 if (biosAttributes.empty())
475 {
476 return;
477 }
478
479 Table attrTable, attrValueTable;
480
481 for (auto& attr : biosAttributes)
482 {
483 try
484 {
485 attr->constructEntry(biosStringTable, attrTable, attrValueTable);
486 }
487 catch (const std::exception& e)
488 {
489 std::cerr << "Construct Table Entry Error, AttributeName = "
490 << attr->name << std::endl;
491 }
492 }
493
494 table::appendPadAndChecksum(attrTable);
495 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800496 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
497 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800498}
499
500std::optional<Table> BIOSConfig::buildAndStoreStringTable()
501{
502 std::set<std::string> strings;
503 auto handler = [&strings](const Json& entry) {
504 strings.emplace(entry.at("attribute_name"));
505 };
506
507 load(jsonDir / stringJsonFile, handler);
508 load(jsonDir / integerJsonFile, handler);
509 load(jsonDir / enumJsonFile, [&strings](const Json& entry) {
510 strings.emplace(entry.at("attribute_name"));
511 auto possibleValues = entry.at("possible_values");
512 for (auto& pv : possibleValues)
513 {
514 strings.emplace(pv);
515 }
516 });
517
518 if (strings.empty())
519 {
520 return std::nullopt;
521 }
522
523 Table table;
524 for (const auto& elem : strings)
525 {
526 table::string::constructEntry(table, elem);
527 }
528
529 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800530 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800531 return table;
532}
533
534void BIOSConfig::storeTable(const fs::path& path, const Table& table)
535{
536 BIOSTable biosTable(path.c_str());
537 biosTable.store(table);
538}
539
540std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
541{
542 BIOSTable biosTable(path.c_str());
543 if (biosTable.isEmpty())
544 {
545 return std::nullopt;
546 }
547
548 Table table;
549 biosTable.load(table);
550 return table;
551}
552
553void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
554{
555 std::ifstream file;
556 Json jsonConf;
557 if (fs::exists(filePath))
558 {
559 try
560 {
561 file.open(filePath);
562 jsonConf = Json::parse(file);
563 auto entries = jsonConf.at("entries");
564 for (auto& entry : entries)
565 {
566 try
567 {
568 handler(entry);
569 }
570 catch (const std::exception& e)
571 {
572 std::cerr
573 << "Failed to parse JSON config file(entry handler) : "
574 << filePath.c_str() << ", " << e.what() << std::endl;
575 }
576 }
577 }
578 catch (const std::exception& e)
579 {
580 std::cerr << "Failed to parse JSON config file : "
581 << filePath.c_str() << std::endl;
582 }
583 }
584}
585
John Wang8241b342020-06-05 10:49:17 +0800586int BIOSConfig::checkAttrValueToUpdate(
587 const pldm_bios_attr_val_table_entry* attrValueEntry,
588 const pldm_bios_attr_table_entry* attrEntry, Table&)
589
590{
591 auto [attrHandle, attrType] =
592 table::attribute_value::decodeHeader(attrValueEntry);
593
594 switch (attrType)
595 {
596 case PLDM_BIOS_ENUMERATION:
597 {
598 auto value =
599 table::attribute_value::decodeEnumEntry(attrValueEntry);
600 auto [pvHdls, defIndex] =
601 table::attribute::decodeEnumEntry(attrEntry);
602 assert(value.size() == 1);
603 if (value[0] >= pvHdls.size())
604 {
605 std::cerr << "Enum: Illgeal index, Index = " << (int)value[0]
606 << std::endl;
607 return PLDM_ERROR_INVALID_DATA;
608 }
609
610 return PLDM_SUCCESS;
611 }
612 case PLDM_BIOS_INTEGER:
613 {
614 auto value =
615 table::attribute_value::decodeIntegerEntry(attrValueEntry);
616 auto [lower, upper, scalar, def] =
617 table::attribute::decodeIntegerEntry(attrEntry);
618
619 if (value < lower || value > upper)
620 {
621 std::cerr << "Integer: out of bound, value = " << value
622 << std::endl;
623 return PLDM_ERROR_INVALID_DATA;
624 }
625 return PLDM_SUCCESS;
626 }
627 case PLDM_BIOS_STRING:
628 {
629 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
630 auto value =
631 table::attribute_value::decodeStringEntry(attrValueEntry);
632 if (value.size() < stringConf.minLength ||
633 value.size() > stringConf.maxLength)
634 {
635 std::cerr << "String: Length error, string = " << value
636 << " length = " << value.size() << std::endl;
637 return PLDM_ERROR_INVALID_LENGTH;
638 }
639 return PLDM_SUCCESS;
640 }
641 default:
642 std::cerr << "ReadOnly or Unspported type, type = " << attrType
643 << std::endl;
644 return PLDM_ERROR;
645 };
646}
647
Tom Joseph7f839f92020-09-21 10:20:44 +0530648int BIOSConfig::setAttrValue(const void* entry, size_t size,
649 bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800650{
651 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
652 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
653 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
654 if (!attrValueTable || !attrTable || !stringTable)
655 {
656 return PLDM_BIOS_TABLE_UNAVAILABLE;
657 }
658
John Wangd9659342020-02-27 16:46:05 +0800659 auto attrValueEntry =
660 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
661
662 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
663
664 auto attrEntry =
665 table::attribute::findByHandle(*attrTable, attrValHeader.attrHandle);
666 if (!attrEntry)
667 {
668 return PLDM_ERROR;
669 }
670
John Wang8241b342020-06-05 10:49:17 +0800671 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
672 if (rc != PLDM_SUCCESS)
673 {
674 return rc;
675 }
676
677 auto destTable =
678 table::attribute_value::updateTable(*attrValueTable, entry, size);
679
680 if (!destTable)
681 {
682 return PLDM_ERROR;
683 }
684
John Wangd9659342020-02-27 16:46:05 +0800685 try
686 {
687 auto attrHeader = table::attribute::decodeHeader(attrEntry);
688
689 BIOSStringTable biosStringTable(*stringTable);
690 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
691
692 auto iter = std::find_if(
693 biosAttributes.begin(), biosAttributes.end(),
694 [&attrName](const auto& attr) { return attr->name == attrName; });
695
696 if (iter == biosAttributes.end())
697 {
698 return PLDM_ERROR;
699 }
700 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry, biosStringTable);
701 }
702 catch (const std::exception& e)
703 {
704 std::cerr << "Set attribute value error: " << e.what() << std::endl;
705 return PLDM_ERROR;
706 }
707
Tom Joseph7f839f92020-09-21 10:20:44 +0530708 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800709
John Wangd9659342020-02-27 16:46:05 +0800710 return PLDM_SUCCESS;
711}
712
713void BIOSConfig::removeTables()
714{
715 try
716 {
717 fs::remove(tableDir / stringTableFile);
718 fs::remove(tableDir / attrTableFile);
719 fs::remove(tableDir / attrValueTableFile);
720 }
721 catch (const std::exception& e)
722 {
723 std::cerr << "Remove the tables error: " << e.what() << std::endl;
724 }
725}
726
Sampa Misra46ece062020-03-18 07:17:44 -0500727void BIOSConfig::processBiosAttrChangeNotification(
728 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
729{
730 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
731 const auto& propertyName = dBusMap->propertyName;
732 const auto& attrName = biosAttributes[biosAttrIndex]->name;
733
734 const auto it = chProperties.find(propertyName);
735 if (it == chProperties.end())
736 {
737 return;
738 }
739
740 PropertyValue newPropVal = it->second;
741 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
742 if (!stringTable.has_value())
743 {
744 std::cerr << "BIOS string table unavailable\n";
745 return;
746 }
747 BIOSStringTable biosStringTable(*stringTable);
748 uint16_t attrNameHdl{};
749 try
750 {
751 attrNameHdl = biosStringTable.findHandle(attrName);
752 }
753 catch (std::invalid_argument& e)
754 {
755 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
756 << attrName.c_str() << "\n";
757 return;
758 }
759
760 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
761 if (!attrTable.has_value())
762 {
763 std::cerr << "Attribute table not present\n";
764 return;
765 }
766 const struct pldm_bios_attr_table_entry* tableEntry =
767 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
768 if (tableEntry == nullptr)
769 {
770 std::cerr << "Attribute not found in attribute table, name= "
771 << attrName.c_str() << "name handle=" << attrNameHdl << "\n";
772 return;
773 }
774
775 auto [attrHdl, attrType, stringHdl] =
776 table::attribute::decodeHeader(tableEntry);
777
778 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
779
780 if (!attrValueSrcTable.has_value())
781 {
782 std::cerr << "Attribute value table not present\n";
783 return;
784 }
785
786 Table newValue;
787 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
788 newValue, attrHdl, attrType, newPropVal);
789 if (rc != PLDM_SUCCESS)
790 {
791 std::cerr << "Could not update the attribute value table for attribute "
792 "handle="
793 << attrHdl << " and type=" << (uint32_t)attrType << "\n";
794 return;
795 }
796 auto destTable = table::attribute_value::updateTable(
797 *attrValueSrcTable, newValue.data(), newValue.size());
798 if (destTable.has_value())
799 {
800 storeTable(tableDir / attrValueTableFile, *destTable);
801 }
802}
803
George Liu1244acf2020-08-14 09:11:11 +0800804uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
805{
806 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
807 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
808
809 BIOSStringTable biosStringTable(*stringTable);
810 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
811 attrTable->data(), attrTable->size());
812 auto stringHandle = biosStringTable.findHandle(attrName);
813
814 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
815 attrTable->data(), attrTable->size()))
816 {
817 auto header = table::attribute::decodeHeader(entry);
818 if (header.stringHandle == stringHandle)
819 {
820 return header.attrHandle;
821 }
822 }
823
824 throw std::invalid_argument("Unknow attribute Name");
825}
826
827void BIOSConfig::constructPendingAttribute(
828 const PendingAttributes& pendingAttributes)
829{
Tom Joseph7f839f92020-09-21 10:20:44 +0530830 std::vector<uint16_t> listOfHandles{};
831
George Liu1244acf2020-08-14 09:11:11 +0800832 for (auto& attribute : pendingAttributes)
833 {
834 std::string attributeName = attribute.first;
835 auto& [attributeType, attributevalue] = attribute.second;
836
837 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
838 [&attributeName](const auto& attr) {
839 return attr->name == attributeName;
840 });
841
842 if (iter == biosAttributes.end())
843 {
844 std::cerr << "Wrong attribute name, attributeName = "
845 << attributeName << std::endl;
846 continue;
847 }
848
849 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
850 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
851 attrValueEntry.data());
852
853 auto handler = findAttrHandle(attributeName);
854 auto type =
855 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
856
857 if (type != BIOSConfigManager::AttributeType::Enumeration &&
858 type != BIOSConfigManager::AttributeType::String &&
859 type != BIOSConfigManager::AttributeType::Integer)
860 {
861 std::cerr << "Attribute type not supported, attributeType = "
862 << attributeType << std::endl;
863 continue;
864 }
865
866 entry->attr_handle = htole16(handler);
Tom Joseph7f839f92020-09-21 10:20:44 +0530867 listOfHandles.emplace_back(htole16(handler));
868
George Liu1244acf2020-08-14 09:11:11 +0800869 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
870
Tom Joseph7f839f92020-09-21 10:20:44 +0530871 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), false);
872 }
873
874 if (listOfHandles.size())
875 {
876#ifdef OEM_IBM
877 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
878 fd, eid, requester, listOfHandles);
879 if (rc != PLDM_SUCCESS)
880 {
881 return;
882 }
883#endif
884 updateBaseBIOSTableProperty();
George Liu1244acf2020-08-14 09:11:11 +0800885 }
886}
887
888void BIOSConfig::listenPendingAttributes()
889{
890 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
891 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
892
893 using namespace sdbusplus::bus::match::rules;
894 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match::match>(
895 pldm::utils::DBusHandler::getBus(),
896 propertiesChanged(objPath, objInterface),
897 [this](sdbusplus::message::message& msg) {
898 constexpr auto propertyName = "PendingAttributes";
899
900 using Value =
901 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
902 using Properties = std::map<DbusProp, Value>;
903
904 Properties props{};
905 std::string intf;
906 msg.read(intf, props);
907
908 auto valPropMap = props.find(propertyName);
909 if (valPropMap == props.end())
910 {
911 return;
912 }
913
914 PendingAttributes pendingAttributes =
915 std::get<PendingAttributes>(valPropMap->second);
916 this->constructPendingAttribute(pendingAttributes);
917 });
918
919 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
920}
921
John Wangd9659342020-02-27 16:46:05 +0800922} // namespace bios
923} // namespace responder
924} // namespace pldm