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, ¤tString); 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