1 #include "config.h" 2 3 #include "bios_handler.hpp" 4 5 #include "constants.hpp" 6 #include "logger.hpp" 7 8 #include <sdbusplus/bus/match.hpp> 9 #include <utility/common_utility.hpp> 10 #include <utility/dbus_utility.hpp> 11 12 #include <string> 13 14 namespace vpd 15 { 16 // Template declaration to define APIs. 17 template class BiosHandler<IbmBiosHandler>; 18 19 template <typename T> 20 void BiosHandler<T>::checkAndListenPldmService() 21 { 22 // Setup a call back match on NameOwnerChanged to determine when PLDM is up. 23 static std::shared_ptr<sdbusplus::bus::match_t> l_nameOwnerMatch = 24 std::make_shared<sdbusplus::bus::match_t>( 25 *m_asioConn, 26 sdbusplus::bus::match::rules::nameOwnerChanged( 27 constants::pldmServiceName), 28 [this](sdbusplus::message_t& l_msg) { 29 if (l_msg.is_method_error()) 30 { 31 logging::logMessage( 32 "Error in reading PLDM name owner changed signal."); 33 return; 34 } 35 36 std::string l_name; 37 std::string l_newOwner; 38 std::string l_oldOwner; 39 40 l_msg.read(l_name, l_oldOwner, l_newOwner); 41 42 if (!l_newOwner.empty() && 43 (l_name.compare(constants::pldmServiceName) == 44 constants::STR_CMP_SUCCESS)) 45 { 46 m_specificBiosHandler->backUpOrRestoreBiosAttributes(); 47 48 // Start listener now that we have done the restore. 49 listenBiosAttributes(); 50 51 // We don't need the match anymore 52 l_nameOwnerMatch.reset(); 53 } 54 }); 55 56 // Based on PLDM service status reset owner match registered above and 57 // trigger BIOS attribute sync. 58 if (dbusUtility::isServiceRunning(constants::pldmServiceName)) 59 { 60 l_nameOwnerMatch.reset(); 61 m_specificBiosHandler->backUpOrRestoreBiosAttributes(); 62 63 // Start listener now that we have done the restore. 64 listenBiosAttributes(); 65 } 66 } 67 68 template <typename T> 69 void BiosHandler<T>::listenBiosAttributes() 70 { 71 static std::shared_ptr<sdbusplus::bus::match_t> l_biosMatch = 72 std::make_shared<sdbusplus::bus::match_t>( 73 *m_asioConn, 74 sdbusplus::bus::match::rules::propertiesChanged( 75 constants::biosConfigMgrObjPath, 76 constants::biosConfigMgrInterface), 77 [this](sdbusplus::message_t& l_msg) { 78 m_specificBiosHandler->biosAttributesCallback(l_msg); 79 }); 80 } 81 82 void IbmBiosHandler::biosAttributesCallback(sdbusplus::message_t& i_msg) 83 { 84 if (i_msg.is_method_error()) 85 { 86 logging::logMessage("Error in reading BIOS attribute signal. "); 87 return; 88 } 89 90 std::string l_objPath; 91 types::BiosBaseTableType l_propMap; 92 i_msg.read(l_objPath, l_propMap); 93 94 for (auto l_property : l_propMap) 95 { 96 if (l_property.first != "BaseBIOSTable") 97 { 98 // Looking for change in Base BIOS table only. 99 continue; 100 } 101 102 if (auto l_attributeList = 103 std::get_if<std::map<std::string, types::BiosProperty>>( 104 &(l_property.second))) 105 { 106 for (const auto& l_attribute : *l_attributeList) 107 { 108 if (auto l_val = std::get_if<std::string>( 109 &(std::get<5>(std::get<1>(l_attribute))))) 110 { 111 std::string l_attributeName = std::get<0>(l_attribute); 112 if (l_attributeName == "hb_memory_mirror_mode") 113 { 114 saveAmmToVpd(*l_val); 115 } 116 117 if (l_attributeName == "pvm_keep_and_clear") 118 { 119 saveKeepAndClearToVpd(*l_val); 120 } 121 122 if (l_attributeName == "pvm_create_default_lpar") 123 { 124 saveCreateDefaultLparToVpd(*l_val); 125 } 126 127 if (l_attributeName == "pvm_clear_nvram") 128 { 129 saveClearNvramToVpd(*l_val); 130 } 131 132 continue; 133 } 134 135 if (auto l_val = std::get_if<int64_t>( 136 &(std::get<5>(std::get<1>(l_attribute))))) 137 { 138 std::string l_attributeName = std::get<0>(l_attribute); 139 if (l_attributeName == "hb_field_core_override") 140 { 141 saveFcoToVpd(*l_val); 142 } 143 } 144 } 145 } 146 else 147 { 148 // TODO: log a predicitive PEL. 149 logging::logMessage("Invalid typre received from BIOS table."); 150 break; 151 } 152 } 153 } 154 155 void IbmBiosHandler::backUpOrRestoreBiosAttributes() 156 { 157 // process FCO 158 processFieldCoreOverride(); 159 160 // process AMM 161 processActiveMemoryMirror(); 162 163 // process LPAR 164 processCreateDefaultLpar(); 165 166 // process clear NVRAM 167 processClearNvram(); 168 169 // process keep and clear 170 processKeepAndClear(); 171 } 172 173 types::BiosAttributeCurrentValue IbmBiosHandler::readBiosAttribute( 174 const std::string& i_attributeName) 175 { 176 types::BiosAttributeCurrentValue l_attrValueVariant = 177 dbusUtility::biosGetAttributeMethodCall(i_attributeName); 178 179 return l_attrValueVariant; 180 } 181 182 void IbmBiosHandler::processFieldCoreOverride() 183 { 184 // TODO: Should we avoid doing this at runtime? 185 186 // Read required keyword from Dbus. 187 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 188 constants::pimServiceName, constants::systemVpdInvPath, 189 constants::vsysInf, constants::kwdRG); 190 191 if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 192 { 193 // default length of the keyword is 4 bytes. 194 if (l_fcoInVpd->size() != constants::VALUE_4) 195 { 196 logging::logMessage( 197 "Invalid value read for FCO from D-Bus. Skipping."); 198 } 199 200 // If FCO in VPD contains anything other that ASCII Space, restore to 201 // BIOS 202 if (std::any_of(l_fcoInVpd->cbegin(), l_fcoInVpd->cend(), 203 [](uint8_t l_val) { 204 return l_val != constants::ASCII_OF_SPACE; 205 })) 206 { 207 // Restore the data to BIOS. 208 saveFcoToBios(*l_fcoInVpd); 209 } 210 else 211 { 212 types::BiosAttributeCurrentValue l_attrValueVariant = 213 readBiosAttribute("hb_field_core_override"); 214 215 if (auto l_fcoInBios = std::get_if<int64_t>(&l_attrValueVariant)) 216 { 217 // save the BIOS data to VPD 218 saveFcoToVpd(*l_fcoInBios); 219 220 return; 221 } 222 logging::logMessage("Invalid type recieved for FCO from BIOS."); 223 } 224 return; 225 } 226 logging::logMessage("Invalid type recieved for FCO from VPD."); 227 } 228 229 void IbmBiosHandler::saveFcoToVpd(int64_t i_fcoInBios) 230 { 231 if (i_fcoInBios < 0) 232 { 233 logging::logMessage("Invalid FCO value in BIOS. Skip updating to VPD"); 234 return; 235 } 236 237 // Read required keyword from Dbus. 238 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 239 constants::pimServiceName, constants::systemVpdInvPath, 240 constants::vsysInf, constants::kwdRG); 241 242 if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 243 { 244 // default length of the keyword is 4 bytes. 245 if (l_fcoInVpd->size() != constants::VALUE_4) 246 { 247 logging::logMessage( 248 "Invalid value read for FCO from D-Bus. Skipping."); 249 return; 250 } 251 252 // convert to VPD value type 253 types::BinaryVector l_biosValInVpdFormat = { 254 0, 0, 0, static_cast<uint8_t>(i_fcoInBios)}; 255 256 // Update only when the data are different. 257 if (std::memcmp(l_biosValInVpdFormat.data(), l_fcoInVpd->data(), 258 constants::VALUE_4) != constants::SUCCESS) 259 { 260 if (constants::FAILURE == 261 m_manager->updateKeyword( 262 SYSTEM_VPD_FILE_PATH, 263 types::IpzData("VSYS", constants::kwdRG, 264 l_biosValInVpdFormat))) 265 { 266 logging::logMessage( 267 "Failed to update " + std::string(constants::kwdRG) + 268 " keyword to VPD."); 269 } 270 } 271 } 272 else 273 { 274 logging::logMessage("Invalid type read for FCO from DBus."); 275 } 276 } 277 278 void IbmBiosHandler::saveFcoToBios(const types::BinaryVector& i_fcoVal) 279 { 280 if (i_fcoVal.size() != constants::VALUE_4) 281 { 282 logging::logMessage("Bad size for FCO received. Skip writing to BIOS"); 283 return; 284 } 285 286 types::PendingBIOSAttrs l_pendingBiosAttribute; 287 l_pendingBiosAttribute.push_back(std::make_pair( 288 "hb_field_core_override", 289 std::make_tuple( 290 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer", 291 i_fcoVal.at(constants::VALUE_3)))); 292 293 if (!dbusUtility::writeDbusProperty( 294 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 295 constants::biosConfigMgrInterface, "PendingAttributes", 296 l_pendingBiosAttribute)) 297 { 298 // TODO: Should we log informational PEL here as well? 299 logging::logMessage( 300 "DBus call to update FCO value in pending attribute failed. "); 301 } 302 } 303 304 void IbmBiosHandler::saveAmmToVpd(const std::string& i_memoryMirrorMode) 305 { 306 if (i_memoryMirrorMode.empty()) 307 { 308 logging::logMessage( 309 "Empty memory mirror mode value from BIOS. Skip writing to VPD"); 310 return; 311 } 312 313 // Read existing value. 314 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 315 constants::pimServiceName, constants::systemVpdInvPath, 316 constants::utilInf, constants::kwdAMM); 317 318 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 319 { 320 auto l_ammValInVpd = *l_pVal; 321 322 types::BinaryVector l_valToUpdateInVpd{ 323 (i_memoryMirrorMode == "Enabled" ? constants::AMM_ENABLED_IN_VPD 324 : constants::AMM_DISABLED_IN_VPD)}; 325 326 // Check if value is already updated on VPD. 327 if (l_ammValInVpd.at(0) == l_valToUpdateInVpd.at(0)) 328 { 329 return; 330 } 331 332 if (constants::FAILURE == 333 m_manager->updateKeyword( 334 SYSTEM_VPD_FILE_PATH, 335 types::IpzData("UTIL", constants::kwdAMM, l_valToUpdateInVpd))) 336 { 337 logging::logMessage( 338 "Failed to update " + std::string(constants::kwdAMM) + 339 " keyword to VPD"); 340 } 341 } 342 else 343 { 344 // TODO: Add PEL 345 logging::logMessage( 346 "Invalid type read for memory mirror mode value from DBus. Skip writing to VPD"); 347 } 348 } 349 350 void IbmBiosHandler::saveAmmToBios(const std::string& i_ammVal) 351 { 352 if (i_ammVal.size() != constants::VALUE_1) 353 { 354 logging::logMessage("Bad size for AMM received, Skip writing to BIOS"); 355 return; 356 } 357 358 const std::string l_valtoUpdate = 359 (i_ammVal.at(0) == constants::VALUE_2) ? "Enabled" : "Disabled"; 360 361 types::PendingBIOSAttrs l_pendingBiosAttribute; 362 l_pendingBiosAttribute.push_back(std::make_pair( 363 "hb_memory_mirror_mode", 364 std::make_tuple( 365 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", 366 l_valtoUpdate))); 367 368 if (!dbusUtility::writeDbusProperty( 369 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 370 constants::biosConfigMgrInterface, "PendingAttributes", 371 l_pendingBiosAttribute)) 372 { 373 // TODO: Should we log informational PEL here as well? 374 logging::logMessage( 375 "DBus call to update AMM value in pending attribute failed."); 376 } 377 } 378 379 void IbmBiosHandler::processActiveMemoryMirror() 380 { 381 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 382 constants::pimServiceName, constants::systemVpdInvPath, 383 constants::utilInf, constants::kwdAMM); 384 385 if (auto pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 386 { 387 auto l_ammValInVpd = *pVal; 388 389 // Check if active memory mirror value is default in VPD. 390 if (l_ammValInVpd.at(0) == constants::VALUE_0) 391 { 392 types::BiosAttributeCurrentValue l_attrValueVariant = 393 readBiosAttribute("hb_memory_mirror_mode"); 394 395 if (auto pVal = std::get_if<std::string>(&l_attrValueVariant)) 396 { 397 saveAmmToVpd(*pVal); 398 return; 399 } 400 logging::logMessage( 401 "Invalid type recieved for auto memory mirror mode from BIOS."); 402 return; 403 } 404 else 405 { 406 saveAmmToBios(std::to_string(l_ammValInVpd.at(0))); 407 } 408 return; 409 } 410 logging::logMessage( 411 "Invalid type recieved for auto memory mirror mode from VPD."); 412 } 413 414 void IbmBiosHandler::saveCreateDefaultLparToVpd( 415 const std::string& i_createDefaultLparVal) 416 { 417 if (i_createDefaultLparVal.empty()) 418 { 419 logging::logMessage( 420 "Empty value received for Lpar from BIOS. Skip writing in VPD."); 421 return; 422 } 423 424 // Read required keyword from DBus as we need to set only a Bit. 425 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 426 constants::pimServiceName, constants::systemVpdInvPath, 427 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); 428 429 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 430 { 431 commonUtility::toLower( 432 const_cast<std::string&>(i_createDefaultLparVal)); 433 434 // Check for second bit. Bit set for enabled else disabled. 435 if (((((*l_pVal).at(0) & 0x02) == 0x02) && 436 (i_createDefaultLparVal.compare("enabled") == 437 constants::STR_CMP_SUCCESS)) || 438 ((((*l_pVal).at(0) & 0x02) == 0x00) && 439 (i_createDefaultLparVal.compare("disabled") == 440 constants::STR_CMP_SUCCESS))) 441 { 442 // Values are same, Don;t update. 443 return; 444 } 445 446 types::BinaryVector l_valToUpdateInVpd; 447 if (i_createDefaultLparVal.compare("enabled") == 448 constants::STR_CMP_SUCCESS) 449 { 450 // 2nd Bit is used to store the value. 451 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) | 0x02); 452 } 453 else 454 { 455 // 2nd Bit is used to store the value. 456 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) & ~(0x02)); 457 } 458 459 if (-1 == 460 m_manager->updateKeyword( 461 SYSTEM_VPD_FILE_PATH, 462 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR, 463 l_valToUpdateInVpd))) 464 { 465 logging::logMessage( 466 "Failed to update " + 467 std::string(constants::kwdClearNVRAM_CreateLPAR) + 468 " keyword to VPD"); 469 } 470 471 return; 472 } 473 logging::logMessage( 474 "Invalid type recieved for create default Lpar from VPD."); 475 } 476 477 void IbmBiosHandler::saveCreateDefaultLparToBios( 478 const std::string& i_createDefaultLparVal) 479 { 480 // checking for exact length as it is a string and can have garbage value. 481 if (i_createDefaultLparVal.size() != constants::VALUE_1) 482 { 483 logging::logMessage( 484 "Bad size for Create default LPAR in VPD. Skip writing to BIOS."); 485 return; 486 } 487 488 std::string l_valtoUpdate = 489 (i_createDefaultLparVal.at(0) & 0x02) ? "Enabled" : "Disabled"; 490 491 types::PendingBIOSAttrs l_pendingBiosAttribute; 492 l_pendingBiosAttribute.push_back(std::make_pair( 493 "pvm_create_default_lpar", 494 std::make_tuple( 495 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", 496 l_valtoUpdate))); 497 498 if (!dbusUtility::writeDbusProperty( 499 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 500 constants::biosConfigMgrInterface, "PendingAttributes", 501 l_pendingBiosAttribute)) 502 { 503 logging::logMessage( 504 "DBus call to update lpar value in pending attribute failed."); 505 } 506 507 return; 508 } 509 510 void IbmBiosHandler::processCreateDefaultLpar() 511 { 512 // Read required keyword from DBus. 513 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 514 constants::pimServiceName, constants::systemVpdInvPath, 515 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); 516 517 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 518 { 519 saveCreateDefaultLparToBios(std::to_string(l_pVal->at(0))); 520 return; 521 } 522 logging::logMessage( 523 "Invalid type recieved for create default Lpar from VPD."); 524 } 525 526 void IbmBiosHandler::saveClearNvramToVpd(const std::string& i_clearNvramVal) 527 { 528 if (i_clearNvramVal.empty()) 529 { 530 logging::logMessage( 531 "Empty value received for clear NVRAM from BIOS. Skip updating to VPD."); 532 return; 533 } 534 535 // Read required keyword from DBus as we need to set only a Bit. 536 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 537 constants::pimServiceName, constants::systemVpdInvPath, 538 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); 539 540 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 541 { 542 commonUtility::toLower(const_cast<std::string&>(i_clearNvramVal)); 543 544 // Check for third bit. Bit set for enabled else disabled. 545 if (((((*l_pVal).at(0) & 0x04) == 0x04) && 546 (i_clearNvramVal.compare("enabled") == 547 constants::STR_CMP_SUCCESS)) || 548 ((((*l_pVal).at(0) & 0x04) == 0x00) && 549 (i_clearNvramVal.compare("disabled") == 550 constants::STR_CMP_SUCCESS))) 551 { 552 // Don't update, values are same. 553 return; 554 } 555 556 types::BinaryVector l_valToUpdateInVpd; 557 if (i_clearNvramVal.compare("enabled") == constants::STR_CMP_SUCCESS) 558 { 559 // 3rd bit is used to store the value. 560 l_valToUpdateInVpd.emplace_back( 561 (*l_pVal).at(0) | constants::VALUE_4); 562 } 563 else 564 { 565 // 3rd bit is used to store the value. 566 l_valToUpdateInVpd.emplace_back( 567 (*l_pVal).at(0) & ~(constants::VALUE_4)); 568 } 569 570 if (-1 == 571 m_manager->updateKeyword( 572 SYSTEM_VPD_FILE_PATH, 573 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR, 574 l_valToUpdateInVpd))) 575 { 576 logging::logMessage( 577 "Failed to update " + 578 std::string(constants::kwdClearNVRAM_CreateLPAR) + 579 " keyword to VPD"); 580 } 581 582 return; 583 } 584 logging::logMessage("Invalid type recieved for clear NVRAM from VPD."); 585 } 586 587 void IbmBiosHandler::saveClearNvramToBios(const std::string& i_clearNvramVal) 588 { 589 // Check for the exact length as it is a string and it can have a garbage 590 // value. 591 if (i_clearNvramVal.size() != constants::VALUE_1) 592 { 593 logging::logMessage( 594 "Bad size for clear NVRAM in VPD. Skip writing to BIOS."); 595 return; 596 } 597 598 // 3rd bit is used to store clear NVRAM value. 599 std::string l_valtoUpdate = 600 (i_clearNvramVal.at(0) & constants::VALUE_4) ? "Enabled" : "Disabled"; 601 602 types::PendingBIOSAttrs l_pendingBiosAttribute; 603 l_pendingBiosAttribute.push_back(std::make_pair( 604 "pvm_clear_nvram", 605 std::make_tuple( 606 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", 607 l_valtoUpdate))); 608 609 if (!dbusUtility::writeDbusProperty( 610 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 611 constants::biosConfigMgrInterface, "PendingAttributes", 612 l_pendingBiosAttribute)) 613 { 614 logging::logMessage( 615 "DBus call to update NVRAM value in pending attribute failed."); 616 } 617 } 618 619 void IbmBiosHandler::processClearNvram() 620 { 621 // Read required keyword from VPD. 622 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 623 constants::pimServiceName, constants::systemVpdInvPath, 624 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); 625 626 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 627 { 628 saveClearNvramToBios(std::to_string(l_pVal->at(0))); 629 return; 630 } 631 logging::logMessage("Invalid type recieved for clear NVRAM from VPD."); 632 } 633 634 void IbmBiosHandler::saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal) 635 { 636 if (i_KeepAndClearVal.empty()) 637 { 638 logging::logMessage( 639 "Empty value received for keep and clear from BIOS. Skip updating to VPD."); 640 return; 641 } 642 643 // Read required keyword from DBus as we need to set only a Bit. 644 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 645 constants::pimServiceName, constants::systemVpdInvPath, 646 constants::utilInf, constants::kwdKeepAndClear); 647 648 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 649 { 650 commonUtility::toLower(const_cast<std::string&>(i_KeepAndClearVal)); 651 652 // Check for first bit. Bit set for enabled else disabled. 653 if (((((*l_pVal).at(0) & 0x01) == 0x01) && 654 (i_KeepAndClearVal.compare("enabled") == 655 constants::STR_CMP_SUCCESS)) || 656 ((((*l_pVal).at(0) & 0x01) == 0x00) && 657 (i_KeepAndClearVal.compare("disabled") == 658 constants::STR_CMP_SUCCESS))) 659 { 660 // Don't update, values are same. 661 return; 662 } 663 664 types::BinaryVector l_valToUpdateInVpd; 665 if (i_KeepAndClearVal.compare("enabled") == constants::STR_CMP_SUCCESS) 666 { 667 // 1st bit is used to store the value. 668 l_valToUpdateInVpd.emplace_back( 669 (*l_pVal).at(0) | constants::VALUE_1); 670 } 671 else 672 { 673 // 1st bit is used to store the value. 674 l_valToUpdateInVpd.emplace_back( 675 (*l_pVal).at(0) & ~(constants::VALUE_1)); 676 } 677 678 if (-1 == m_manager->updateKeyword( 679 SYSTEM_VPD_FILE_PATH, 680 types::IpzData("UTIL", constants::kwdKeepAndClear, 681 l_valToUpdateInVpd))) 682 { 683 logging::logMessage( 684 "Failed to update " + std::string(constants::kwdKeepAndClear) + 685 " keyword to VPD"); 686 } 687 688 return; 689 } 690 logging::logMessage("Invalid type recieved for keep and clear from VPD."); 691 } 692 693 void IbmBiosHandler::saveKeepAndClearToBios( 694 const std::string& i_KeepAndClearVal) 695 { 696 // checking for exact length as it is a string and can have garbage value. 697 if (i_KeepAndClearVal.size() != constants::VALUE_1) 698 { 699 logging::logMessage( 700 "Bad size for keep and clear in VPD. Skip writing to BIOS."); 701 return; 702 } 703 704 // 1st bit is used to store keep and clear value. 705 std::string l_valtoUpdate = 706 (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled"; 707 708 types::PendingBIOSAttrs l_pendingBiosAttribute; 709 l_pendingBiosAttribute.push_back(std::make_pair( 710 "pvm_keep_and_clear", 711 std::make_tuple( 712 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", 713 l_valtoUpdate))); 714 715 if (!dbusUtility::writeDbusProperty( 716 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 717 constants::biosConfigMgrInterface, "PendingAttributes", 718 l_pendingBiosAttribute)) 719 { 720 logging::logMessage( 721 "DBus call to update keep and clear value in pending attribute failed."); 722 } 723 } 724 725 void IbmBiosHandler::processKeepAndClear() 726 { 727 // Read required keyword from VPD. 728 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 729 constants::pimServiceName, constants::systemVpdInvPath, 730 constants::utilInf, constants::kwdKeepAndClear); 731 732 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 733 { 734 saveKeepAndClearToBios(std::to_string(l_pVal->at(0))); 735 return; 736 } 737 logging::logMessage("Invalid type recieved for keep and clear from VPD."); 738 } 739 } // namespace vpd 740