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 uint8_t& i_ammVal) 351 { 352 const std::string l_valtoUpdate = 353 (i_ammVal == constants::VALUE_2) ? "Enabled" : "Disabled"; 354 355 types::PendingBIOSAttrs l_pendingBiosAttribute; 356 l_pendingBiosAttribute.push_back(std::make_pair( 357 "hb_memory_mirror_mode", 358 std::make_tuple( 359 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", 360 l_valtoUpdate))); 361 362 if (!dbusUtility::writeDbusProperty( 363 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 364 constants::biosConfigMgrInterface, "PendingAttributes", 365 l_pendingBiosAttribute)) 366 { 367 // TODO: Should we log informational PEL here as well? 368 logging::logMessage( 369 "DBus call to update AMM value in pending attribute failed."); 370 } 371 } 372 373 void IbmBiosHandler::processActiveMemoryMirror() 374 { 375 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 376 constants::pimServiceName, constants::systemVpdInvPath, 377 constants::utilInf, constants::kwdAMM); 378 379 if (auto pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 380 { 381 auto l_ammValInVpd = *pVal; 382 383 // Check if active memory mirror value is default in VPD. 384 if (l_ammValInVpd.at(0) == constants::VALUE_0) 385 { 386 types::BiosAttributeCurrentValue l_attrValueVariant = 387 readBiosAttribute("hb_memory_mirror_mode"); 388 389 if (auto pVal = std::get_if<std::string>(&l_attrValueVariant)) 390 { 391 saveAmmToVpd(*pVal); 392 return; 393 } 394 logging::logMessage( 395 "Invalid type recieved for auto memory mirror mode from BIOS."); 396 return; 397 } 398 else 399 { 400 saveAmmToBios(l_ammValInVpd.at(0)); 401 } 402 return; 403 } 404 logging::logMessage( 405 "Invalid type recieved for auto memory mirror mode from VPD."); 406 } 407 408 void IbmBiosHandler::saveCreateDefaultLparToVpd( 409 const std::string& i_createDefaultLparVal) 410 { 411 if (i_createDefaultLparVal.empty()) 412 { 413 logging::logMessage( 414 "Empty value received for Lpar from BIOS. Skip writing in VPD."); 415 return; 416 } 417 418 // Read required keyword from DBus as we need to set only a Bit. 419 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 420 constants::pimServiceName, constants::systemVpdInvPath, 421 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); 422 423 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 424 { 425 commonUtility::toLower( 426 const_cast<std::string&>(i_createDefaultLparVal)); 427 428 // Check for second bit. Bit set for enabled else disabled. 429 if (((((*l_pVal).at(0) & 0x02) == 0x02) && 430 (i_createDefaultLparVal.compare("enabled") == 431 constants::STR_CMP_SUCCESS)) || 432 ((((*l_pVal).at(0) & 0x02) == 0x00) && 433 (i_createDefaultLparVal.compare("disabled") == 434 constants::STR_CMP_SUCCESS))) 435 { 436 // Values are same, Don;t update. 437 return; 438 } 439 440 types::BinaryVector l_valToUpdateInVpd; 441 if (i_createDefaultLparVal.compare("enabled") == 442 constants::STR_CMP_SUCCESS) 443 { 444 // 2nd Bit is used to store the value. 445 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) | 0x02); 446 } 447 else 448 { 449 // 2nd Bit is used to store the value. 450 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) & ~(0x02)); 451 } 452 453 if (-1 == 454 m_manager->updateKeyword( 455 SYSTEM_VPD_FILE_PATH, 456 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR, 457 l_valToUpdateInVpd))) 458 { 459 logging::logMessage( 460 "Failed to update " + 461 std::string(constants::kwdClearNVRAM_CreateLPAR) + 462 " keyword to VPD"); 463 } 464 465 return; 466 } 467 logging::logMessage( 468 "Invalid type recieved for create default Lpar from VPD."); 469 } 470 471 void IbmBiosHandler::saveCreateDefaultLparToBios( 472 const std::string& i_createDefaultLparVal) 473 { 474 // checking for exact length as it is a string and can have garbage value. 475 if (i_createDefaultLparVal.size() != constants::VALUE_1) 476 { 477 logging::logMessage( 478 "Bad size for Create default LPAR in VPD. Skip writing to BIOS."); 479 return; 480 } 481 482 std::string l_valtoUpdate = 483 (i_createDefaultLparVal.at(0) & 0x02) ? "Enabled" : "Disabled"; 484 485 types::PendingBIOSAttrs l_pendingBiosAttribute; 486 l_pendingBiosAttribute.push_back(std::make_pair( 487 "pvm_create_default_lpar", 488 std::make_tuple( 489 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", 490 l_valtoUpdate))); 491 492 if (!dbusUtility::writeDbusProperty( 493 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 494 constants::biosConfigMgrInterface, "PendingAttributes", 495 l_pendingBiosAttribute)) 496 { 497 logging::logMessage( 498 "DBus call to update lpar value in pending attribute failed."); 499 } 500 501 return; 502 } 503 504 void IbmBiosHandler::processCreateDefaultLpar() 505 { 506 // Read required keyword from DBus. 507 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 508 constants::pimServiceName, constants::systemVpdInvPath, 509 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); 510 511 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 512 { 513 saveCreateDefaultLparToBios(std::to_string(l_pVal->at(0))); 514 return; 515 } 516 logging::logMessage( 517 "Invalid type recieved for create default Lpar from VPD."); 518 } 519 520 void IbmBiosHandler::saveClearNvramToVpd(const std::string& i_clearNvramVal) 521 { 522 if (i_clearNvramVal.empty()) 523 { 524 logging::logMessage( 525 "Empty value received for clear NVRAM from BIOS. Skip updating to VPD."); 526 return; 527 } 528 529 // Read required keyword from DBus as we need to set only a Bit. 530 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 531 constants::pimServiceName, constants::systemVpdInvPath, 532 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); 533 534 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 535 { 536 commonUtility::toLower(const_cast<std::string&>(i_clearNvramVal)); 537 538 // Check for third bit. Bit set for enabled else disabled. 539 if (((((*l_pVal).at(0) & 0x04) == 0x04) && 540 (i_clearNvramVal.compare("enabled") == 541 constants::STR_CMP_SUCCESS)) || 542 ((((*l_pVal).at(0) & 0x04) == 0x00) && 543 (i_clearNvramVal.compare("disabled") == 544 constants::STR_CMP_SUCCESS))) 545 { 546 // Don't update, values are same. 547 return; 548 } 549 550 types::BinaryVector l_valToUpdateInVpd; 551 if (i_clearNvramVal.compare("enabled") == constants::STR_CMP_SUCCESS) 552 { 553 // 3rd bit is used to store the value. 554 l_valToUpdateInVpd.emplace_back( 555 (*l_pVal).at(0) | constants::VALUE_4); 556 } 557 else 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 564 if (-1 == 565 m_manager->updateKeyword( 566 SYSTEM_VPD_FILE_PATH, 567 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR, 568 l_valToUpdateInVpd))) 569 { 570 logging::logMessage( 571 "Failed to update " + 572 std::string(constants::kwdClearNVRAM_CreateLPAR) + 573 " keyword to VPD"); 574 } 575 576 return; 577 } 578 logging::logMessage("Invalid type recieved for clear NVRAM from VPD."); 579 } 580 581 void IbmBiosHandler::saveClearNvramToBios(const std::string& i_clearNvramVal) 582 { 583 // Check for the exact length as it is a string and it can have a garbage 584 // value. 585 if (i_clearNvramVal.size() != constants::VALUE_1) 586 { 587 logging::logMessage( 588 "Bad size for clear NVRAM in VPD. Skip writing to BIOS."); 589 return; 590 } 591 592 // 3rd bit is used to store clear NVRAM value. 593 std::string l_valtoUpdate = 594 (i_clearNvramVal.at(0) & constants::VALUE_4) ? "Enabled" : "Disabled"; 595 596 types::PendingBIOSAttrs l_pendingBiosAttribute; 597 l_pendingBiosAttribute.push_back(std::make_pair( 598 "pvm_clear_nvram", 599 std::make_tuple( 600 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", 601 l_valtoUpdate))); 602 603 if (!dbusUtility::writeDbusProperty( 604 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 605 constants::biosConfigMgrInterface, "PendingAttributes", 606 l_pendingBiosAttribute)) 607 { 608 logging::logMessage( 609 "DBus call to update NVRAM value in pending attribute failed."); 610 } 611 } 612 613 void IbmBiosHandler::processClearNvram() 614 { 615 // Read required keyword from VPD. 616 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 617 constants::pimServiceName, constants::systemVpdInvPath, 618 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); 619 620 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 621 { 622 saveClearNvramToBios(std::to_string(l_pVal->at(0))); 623 return; 624 } 625 logging::logMessage("Invalid type recieved for clear NVRAM from VPD."); 626 } 627 628 void IbmBiosHandler::saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal) 629 { 630 if (i_KeepAndClearVal.empty()) 631 { 632 logging::logMessage( 633 "Empty value received for keep and clear from BIOS. Skip updating to VPD."); 634 return; 635 } 636 637 // Read required keyword from DBus as we need to set only a Bit. 638 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 639 constants::pimServiceName, constants::systemVpdInvPath, 640 constants::utilInf, constants::kwdKeepAndClear); 641 642 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 643 { 644 commonUtility::toLower(const_cast<std::string&>(i_KeepAndClearVal)); 645 646 // Check for first bit. Bit set for enabled else disabled. 647 if (((((*l_pVal).at(0) & 0x01) == 0x01) && 648 (i_KeepAndClearVal.compare("enabled") == 649 constants::STR_CMP_SUCCESS)) || 650 ((((*l_pVal).at(0) & 0x01) == 0x00) && 651 (i_KeepAndClearVal.compare("disabled") == 652 constants::STR_CMP_SUCCESS))) 653 { 654 // Don't update, values are same. 655 return; 656 } 657 658 types::BinaryVector l_valToUpdateInVpd; 659 if (i_KeepAndClearVal.compare("enabled") == constants::STR_CMP_SUCCESS) 660 { 661 // 1st bit is used to store the value. 662 l_valToUpdateInVpd.emplace_back( 663 (*l_pVal).at(0) | constants::VALUE_1); 664 } 665 else 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 672 if (-1 == m_manager->updateKeyword( 673 SYSTEM_VPD_FILE_PATH, 674 types::IpzData("UTIL", constants::kwdKeepAndClear, 675 l_valToUpdateInVpd))) 676 { 677 logging::logMessage( 678 "Failed to update " + std::string(constants::kwdKeepAndClear) + 679 " keyword to VPD"); 680 } 681 682 return; 683 } 684 logging::logMessage("Invalid type recieved for keep and clear from VPD."); 685 } 686 687 void IbmBiosHandler::saveKeepAndClearToBios( 688 const std::string& i_KeepAndClearVal) 689 { 690 // checking for exact length as it is a string and can have garbage value. 691 if (i_KeepAndClearVal.size() != constants::VALUE_1) 692 { 693 logging::logMessage( 694 "Bad size for keep and clear in VPD. Skip writing to BIOS."); 695 return; 696 } 697 698 // 1st bit is used to store keep and clear value. 699 std::string l_valtoUpdate = 700 (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled"; 701 702 types::PendingBIOSAttrs l_pendingBiosAttribute; 703 l_pendingBiosAttribute.push_back(std::make_pair( 704 "pvm_keep_and_clear", 705 std::make_tuple( 706 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", 707 l_valtoUpdate))); 708 709 if (!dbusUtility::writeDbusProperty( 710 constants::biosConfigMgrService, constants::biosConfigMgrObjPath, 711 constants::biosConfigMgrInterface, "PendingAttributes", 712 l_pendingBiosAttribute)) 713 { 714 logging::logMessage( 715 "DBus call to update keep and clear value in pending attribute failed."); 716 } 717 } 718 719 void IbmBiosHandler::processKeepAndClear() 720 { 721 // Read required keyword from VPD. 722 auto l_kwdValueVariant = dbusUtility::readDbusProperty( 723 constants::pimServiceName, constants::systemVpdInvPath, 724 constants::utilInf, constants::kwdKeepAndClear); 725 726 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) 727 { 728 saveKeepAndClearToBios(std::to_string(l_pVal->at(0))); 729 return; 730 } 731 logging::logMessage("Invalid type recieved for keep and clear from VPD."); 732 } 733 } // namespace vpd 734