| #include "config.h" |
| |
| #include "bios_handler.hpp" |
| |
| #include "constants.hpp" |
| #include "logger.hpp" |
| |
| #include <sdbusplus/bus/match.hpp> |
| #include <utility/common_utility.hpp> |
| #include <utility/dbus_utility.hpp> |
| |
| #include <string> |
| |
| namespace vpd |
| { |
| // Template declaration to define APIs. |
| template class BiosHandler<IbmBiosHandler>; |
| |
| template <typename T> |
| void BiosHandler<T>::checkAndListenPldmService() |
| { |
| // Setup a call back match on NameOwnerChanged to determine when PLDM is up. |
| static std::shared_ptr<sdbusplus::bus::match_t> l_nameOwnerMatch = |
| std::make_shared<sdbusplus::bus::match_t>( |
| *m_asioConn, |
| sdbusplus::bus::match::rules::nameOwnerChanged( |
| constants::pldmServiceName), |
| [this](sdbusplus::message_t& l_msg) { |
| if (l_msg.is_method_error()) |
| { |
| logging::logMessage( |
| "Error in reading PLDM name owner changed signal."); |
| return; |
| } |
| |
| std::string l_name; |
| std::string l_newOwner; |
| std::string l_oldOwner; |
| |
| l_msg.read(l_name, l_oldOwner, l_newOwner); |
| |
| if (!l_newOwner.empty() && |
| (l_name.compare(constants::pldmServiceName) == |
| constants::STR_CMP_SUCCESS)) |
| { |
| m_specificBiosHandler->backUpOrRestoreBiosAttributes(); |
| |
| // Start listener now that we have done the restore. |
| listenBiosAttributes(); |
| |
| // We don't need the match anymore |
| l_nameOwnerMatch.reset(); |
| } |
| }); |
| |
| // Based on PLDM service status reset owner match registered above and |
| // trigger BIOS attribute sync. |
| if (dbusUtility::isServiceRunning(constants::pldmServiceName)) |
| { |
| l_nameOwnerMatch.reset(); |
| m_specificBiosHandler->backUpOrRestoreBiosAttributes(); |
| |
| // Start listener now that we have done the restore. |
| listenBiosAttributes(); |
| } |
| } |
| |
| template <typename T> |
| void BiosHandler<T>::listenBiosAttributes() |
| { |
| static std::shared_ptr<sdbusplus::bus::match_t> l_biosMatch = |
| std::make_shared<sdbusplus::bus::match_t>( |
| *m_asioConn, |
| sdbusplus::bus::match::rules::propertiesChanged( |
| constants::biosConfigMgrObjPath, |
| constants::biosConfigMgrInterface), |
| [this](sdbusplus::message_t& l_msg) { |
| m_specificBiosHandler->biosAttributesCallback(l_msg); |
| }); |
| } |
| |
| void IbmBiosHandler::biosAttributesCallback(sdbusplus::message_t& i_msg) |
| { |
| if (i_msg.is_method_error()) |
| { |
| logging::logMessage("Error in reading BIOS attribute signal. "); |
| return; |
| } |
| |
| std::string l_objPath; |
| types::BiosBaseTableType l_propMap; |
| i_msg.read(l_objPath, l_propMap); |
| |
| for (auto l_property : l_propMap) |
| { |
| if (l_property.first != "BaseBIOSTable") |
| { |
| // Looking for change in Base BIOS table only. |
| continue; |
| } |
| |
| if (auto l_attributeList = |
| std::get_if<std::map<std::string, types::BiosProperty>>( |
| &(l_property.second))) |
| { |
| for (const auto& l_attribute : *l_attributeList) |
| { |
| if (auto l_val = std::get_if<std::string>( |
| &(std::get<5>(std::get<1>(l_attribute))))) |
| { |
| std::string l_attributeName = std::get<0>(l_attribute); |
| if (l_attributeName == "hb_memory_mirror_mode") |
| { |
| saveAmmToVpd(*l_val); |
| } |
| |
| if (l_attributeName == "pvm_keep_and_clear") |
| { |
| saveKeepAndClearToVpd(*l_val); |
| } |
| |
| if (l_attributeName == "pvm_create_default_lpar") |
| { |
| saveCreateDefaultLparToVpd(*l_val); |
| } |
| |
| if (l_attributeName == "pvm_clear_nvram") |
| { |
| saveClearNvramToVpd(*l_val); |
| } |
| |
| continue; |
| } |
| |
| if (auto l_val = std::get_if<int64_t>( |
| &(std::get<5>(std::get<1>(l_attribute))))) |
| { |
| std::string l_attributeName = std::get<0>(l_attribute); |
| if (l_attributeName == "hb_field_core_override") |
| { |
| saveFcoToVpd(*l_val); |
| } |
| } |
| } |
| } |
| else |
| { |
| logging::logMessage("Invalid type received for BIOS table."); |
| EventLogger::createSyncPel( |
| types::ErrorType::FirmwareError, types::SeverityType::Warning, |
| __FILE__, __FUNCTION__, 0, |
| std::string("Invalid type received for BIOS table."), |
| std::nullopt, std::nullopt, std::nullopt, std::nullopt); |
| break; |
| } |
| } |
| } |
| |
| void IbmBiosHandler::backUpOrRestoreBiosAttributes() |
| { |
| // process FCO |
| processFieldCoreOverride(); |
| |
| // process AMM |
| processActiveMemoryMirror(); |
| |
| // process LPAR |
| processCreateDefaultLpar(); |
| |
| // process clear NVRAM |
| processClearNvram(); |
| |
| // process keep and clear |
| processKeepAndClear(); |
| } |
| |
| types::BiosAttributeCurrentValue IbmBiosHandler::readBiosAttribute( |
| const std::string& i_attributeName) |
| { |
| types::BiosAttributeCurrentValue l_attrValueVariant = |
| dbusUtility::biosGetAttributeMethodCall(i_attributeName); |
| |
| return l_attrValueVariant; |
| } |
| |
| void IbmBiosHandler::processFieldCoreOverride() |
| { |
| // TODO: Should we avoid doing this at runtime? |
| |
| // Read required keyword from Dbus. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::vsysInf, constants::kwdRG); |
| |
| if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| // default length of the keyword is 4 bytes. |
| if (l_fcoInVpd->size() != constants::VALUE_4) |
| { |
| logging::logMessage( |
| "Invalid value read for FCO from D-Bus. Skipping."); |
| } |
| |
| // If FCO in VPD contains anything other that ASCII Space, restore to |
| // BIOS |
| if (std::any_of(l_fcoInVpd->cbegin(), l_fcoInVpd->cend(), |
| [](uint8_t l_val) { |
| return l_val != constants::ASCII_OF_SPACE; |
| })) |
| { |
| // Restore the data to BIOS. |
| saveFcoToBios(*l_fcoInVpd); |
| } |
| else |
| { |
| types::BiosAttributeCurrentValue l_attrValueVariant = |
| readBiosAttribute("hb_field_core_override"); |
| |
| if (auto l_fcoInBios = std::get_if<int64_t>(&l_attrValueVariant)) |
| { |
| // save the BIOS data to VPD |
| saveFcoToVpd(*l_fcoInBios); |
| |
| return; |
| } |
| logging::logMessage("Invalid type recieved for FCO from BIOS."); |
| } |
| return; |
| } |
| logging::logMessage("Invalid type recieved for FCO from VPD."); |
| } |
| |
| void IbmBiosHandler::saveFcoToVpd(int64_t i_fcoInBios) |
| { |
| if (i_fcoInBios < 0) |
| { |
| logging::logMessage("Invalid FCO value in BIOS. Skip updating to VPD"); |
| return; |
| } |
| |
| // Read required keyword from Dbus. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::vsysInf, constants::kwdRG); |
| |
| if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| // default length of the keyword is 4 bytes. |
| if (l_fcoInVpd->size() != constants::VALUE_4) |
| { |
| logging::logMessage( |
| "Invalid value read for FCO from D-Bus. Skipping."); |
| return; |
| } |
| |
| // convert to VPD value type |
| types::BinaryVector l_biosValInVpdFormat = { |
| 0, 0, 0, static_cast<uint8_t>(i_fcoInBios)}; |
| |
| // Update only when the data are different. |
| if (std::memcmp(l_biosValInVpdFormat.data(), l_fcoInVpd->data(), |
| constants::VALUE_4) != constants::SUCCESS) |
| { |
| if (constants::FAILURE == |
| m_manager->updateKeyword( |
| SYSTEM_VPD_FILE_PATH, |
| types::IpzData("VSYS", constants::kwdRG, |
| l_biosValInVpdFormat))) |
| { |
| logging::logMessage( |
| "Failed to update " + std::string(constants::kwdRG) + |
| " keyword to VPD."); |
| } |
| } |
| } |
| else |
| { |
| logging::logMessage("Invalid type read for FCO from DBus."); |
| } |
| } |
| |
| void IbmBiosHandler::saveFcoToBios(const types::BinaryVector& i_fcoVal) |
| { |
| if (i_fcoVal.size() != constants::VALUE_4) |
| { |
| logging::logMessage("Bad size for FCO received. Skip writing to BIOS"); |
| return; |
| } |
| |
| types::PendingBIOSAttrs l_pendingBiosAttribute; |
| l_pendingBiosAttribute.push_back(std::make_pair( |
| "hb_field_core_override", |
| std::make_tuple( |
| "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer", |
| i_fcoVal.at(constants::VALUE_3)))); |
| |
| if (!dbusUtility::writeDbusProperty( |
| constants::biosConfigMgrService, constants::biosConfigMgrObjPath, |
| constants::biosConfigMgrInterface, "PendingAttributes", |
| l_pendingBiosAttribute)) |
| { |
| // TODO: Should we log informational PEL here as well? |
| logging::logMessage( |
| "DBus call to update FCO value in pending attribute failed. "); |
| } |
| } |
| |
| void IbmBiosHandler::saveAmmToVpd(const std::string& i_memoryMirrorMode) |
| { |
| if (i_memoryMirrorMode.empty()) |
| { |
| logging::logMessage( |
| "Empty memory mirror mode value from BIOS. Skip writing to VPD"); |
| return; |
| } |
| |
| // Read existing value. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::utilInf, constants::kwdAMM); |
| |
| if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| auto l_ammValInVpd = *l_pVal; |
| |
| types::BinaryVector l_valToUpdateInVpd{ |
| (i_memoryMirrorMode == "Enabled" ? constants::AMM_ENABLED_IN_VPD |
| : constants::AMM_DISABLED_IN_VPD)}; |
| |
| // Check if value is already updated on VPD. |
| if (l_ammValInVpd.at(0) == l_valToUpdateInVpd.at(0)) |
| { |
| return; |
| } |
| |
| if (constants::FAILURE == |
| m_manager->updateKeyword( |
| SYSTEM_VPD_FILE_PATH, |
| types::IpzData("UTIL", constants::kwdAMM, l_valToUpdateInVpd))) |
| { |
| logging::logMessage( |
| "Failed to update " + std::string(constants::kwdAMM) + |
| " keyword to VPD"); |
| } |
| } |
| else |
| { |
| // TODO: Add PEL |
| logging::logMessage( |
| "Invalid type read for memory mirror mode value from DBus. Skip writing to VPD"); |
| } |
| } |
| |
| void IbmBiosHandler::saveAmmToBios(const uint8_t& i_ammVal) |
| { |
| const std::string l_valtoUpdate = |
| (i_ammVal == constants::VALUE_2) ? "Enabled" : "Disabled"; |
| |
| types::PendingBIOSAttrs l_pendingBiosAttribute; |
| l_pendingBiosAttribute.push_back(std::make_pair( |
| "hb_memory_mirror_mode", |
| std::make_tuple( |
| "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", |
| l_valtoUpdate))); |
| |
| if (!dbusUtility::writeDbusProperty( |
| constants::biosConfigMgrService, constants::biosConfigMgrObjPath, |
| constants::biosConfigMgrInterface, "PendingAttributes", |
| l_pendingBiosAttribute)) |
| { |
| // TODO: Should we log informational PEL here as well? |
| logging::logMessage( |
| "DBus call to update AMM value in pending attribute failed."); |
| } |
| } |
| |
| void IbmBiosHandler::processActiveMemoryMirror() |
| { |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::utilInf, constants::kwdAMM); |
| |
| if (auto pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| auto l_ammValInVpd = *pVal; |
| |
| // Check if active memory mirror value is default in VPD. |
| if (l_ammValInVpd.at(0) == constants::VALUE_0) |
| { |
| types::BiosAttributeCurrentValue l_attrValueVariant = |
| readBiosAttribute("hb_memory_mirror_mode"); |
| |
| if (auto pVal = std::get_if<std::string>(&l_attrValueVariant)) |
| { |
| saveAmmToVpd(*pVal); |
| return; |
| } |
| logging::logMessage( |
| "Invalid type recieved for auto memory mirror mode from BIOS."); |
| return; |
| } |
| else |
| { |
| saveAmmToBios(l_ammValInVpd.at(0)); |
| } |
| return; |
| } |
| logging::logMessage( |
| "Invalid type recieved for auto memory mirror mode from VPD."); |
| } |
| |
| void IbmBiosHandler::saveCreateDefaultLparToVpd( |
| const std::string& i_createDefaultLparVal) |
| { |
| if (i_createDefaultLparVal.empty()) |
| { |
| logging::logMessage( |
| "Empty value received for Lpar from BIOS. Skip writing in VPD."); |
| return; |
| } |
| |
| // Read required keyword from DBus as we need to set only a Bit. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); |
| |
| if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| commonUtility::toLower( |
| const_cast<std::string&>(i_createDefaultLparVal)); |
| |
| // Check for second bit. Bit set for enabled else disabled. |
| if (((((*l_pVal).at(0) & 0x02) == 0x02) && |
| (i_createDefaultLparVal.compare("enabled") == |
| constants::STR_CMP_SUCCESS)) || |
| ((((*l_pVal).at(0) & 0x02) == 0x00) && |
| (i_createDefaultLparVal.compare("disabled") == |
| constants::STR_CMP_SUCCESS))) |
| { |
| // Values are same, Don;t update. |
| return; |
| } |
| |
| types::BinaryVector l_valToUpdateInVpd; |
| if (i_createDefaultLparVal.compare("enabled") == |
| constants::STR_CMP_SUCCESS) |
| { |
| // 2nd Bit is used to store the value. |
| l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) | 0x02); |
| } |
| else |
| { |
| // 2nd Bit is used to store the value. |
| l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) & ~(0x02)); |
| } |
| |
| if (-1 == |
| m_manager->updateKeyword( |
| SYSTEM_VPD_FILE_PATH, |
| types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR, |
| l_valToUpdateInVpd))) |
| { |
| logging::logMessage( |
| "Failed to update " + |
| std::string(constants::kwdClearNVRAM_CreateLPAR) + |
| " keyword to VPD"); |
| } |
| |
| return; |
| } |
| logging::logMessage( |
| "Invalid type recieved for create default Lpar from VPD."); |
| } |
| |
| void IbmBiosHandler::saveCreateDefaultLparToBios( |
| const std::string& i_createDefaultLparVal) |
| { |
| // checking for exact length as it is a string and can have garbage value. |
| if (i_createDefaultLparVal.size() != constants::VALUE_1) |
| { |
| logging::logMessage( |
| "Bad size for Create default LPAR in VPD. Skip writing to BIOS."); |
| return; |
| } |
| |
| std::string l_valtoUpdate = |
| (i_createDefaultLparVal.at(0) & 0x02) ? "Enabled" : "Disabled"; |
| |
| types::PendingBIOSAttrs l_pendingBiosAttribute; |
| l_pendingBiosAttribute.push_back(std::make_pair( |
| "pvm_create_default_lpar", |
| std::make_tuple( |
| "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", |
| l_valtoUpdate))); |
| |
| if (!dbusUtility::writeDbusProperty( |
| constants::biosConfigMgrService, constants::biosConfigMgrObjPath, |
| constants::biosConfigMgrInterface, "PendingAttributes", |
| l_pendingBiosAttribute)) |
| { |
| logging::logMessage( |
| "DBus call to update lpar value in pending attribute failed."); |
| } |
| |
| return; |
| } |
| |
| void IbmBiosHandler::processCreateDefaultLpar() |
| { |
| // Read required keyword from DBus. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); |
| |
| if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| saveCreateDefaultLparToBios(std::to_string(l_pVal->at(0))); |
| return; |
| } |
| logging::logMessage( |
| "Invalid type recieved for create default Lpar from VPD."); |
| } |
| |
| void IbmBiosHandler::saveClearNvramToVpd(const std::string& i_clearNvramVal) |
| { |
| if (i_clearNvramVal.empty()) |
| { |
| logging::logMessage( |
| "Empty value received for clear NVRAM from BIOS. Skip updating to VPD."); |
| return; |
| } |
| |
| // Read required keyword from DBus as we need to set only a Bit. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); |
| |
| if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| commonUtility::toLower(const_cast<std::string&>(i_clearNvramVal)); |
| |
| // Check for third bit. Bit set for enabled else disabled. |
| if (((((*l_pVal).at(0) & 0x04) == 0x04) && |
| (i_clearNvramVal.compare("enabled") == |
| constants::STR_CMP_SUCCESS)) || |
| ((((*l_pVal).at(0) & 0x04) == 0x00) && |
| (i_clearNvramVal.compare("disabled") == |
| constants::STR_CMP_SUCCESS))) |
| { |
| // Don't update, values are same. |
| return; |
| } |
| |
| types::BinaryVector l_valToUpdateInVpd; |
| if (i_clearNvramVal.compare("enabled") == constants::STR_CMP_SUCCESS) |
| { |
| // 3rd bit is used to store the value. |
| l_valToUpdateInVpd.emplace_back( |
| (*l_pVal).at(0) | constants::VALUE_4); |
| } |
| else |
| { |
| // 3rd bit is used to store the value. |
| l_valToUpdateInVpd.emplace_back( |
| (*l_pVal).at(0) & ~(constants::VALUE_4)); |
| } |
| |
| if (-1 == |
| m_manager->updateKeyword( |
| SYSTEM_VPD_FILE_PATH, |
| types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR, |
| l_valToUpdateInVpd))) |
| { |
| logging::logMessage( |
| "Failed to update " + |
| std::string(constants::kwdClearNVRAM_CreateLPAR) + |
| " keyword to VPD"); |
| } |
| |
| return; |
| } |
| logging::logMessage("Invalid type recieved for clear NVRAM from VPD."); |
| } |
| |
| void IbmBiosHandler::saveClearNvramToBios(const std::string& i_clearNvramVal) |
| { |
| // Check for the exact length as it is a string and it can have a garbage |
| // value. |
| if (i_clearNvramVal.size() != constants::VALUE_1) |
| { |
| logging::logMessage( |
| "Bad size for clear NVRAM in VPD. Skip writing to BIOS."); |
| return; |
| } |
| |
| // 3rd bit is used to store clear NVRAM value. |
| std::string l_valtoUpdate = |
| (i_clearNvramVal.at(0) & constants::VALUE_4) ? "Enabled" : "Disabled"; |
| |
| types::PendingBIOSAttrs l_pendingBiosAttribute; |
| l_pendingBiosAttribute.push_back(std::make_pair( |
| "pvm_clear_nvram", |
| std::make_tuple( |
| "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", |
| l_valtoUpdate))); |
| |
| if (!dbusUtility::writeDbusProperty( |
| constants::biosConfigMgrService, constants::biosConfigMgrObjPath, |
| constants::biosConfigMgrInterface, "PendingAttributes", |
| l_pendingBiosAttribute)) |
| { |
| logging::logMessage( |
| "DBus call to update NVRAM value in pending attribute failed."); |
| } |
| } |
| |
| void IbmBiosHandler::processClearNvram() |
| { |
| // Read required keyword from VPD. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::utilInf, constants::kwdClearNVRAM_CreateLPAR); |
| |
| if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| saveClearNvramToBios(std::to_string(l_pVal->at(0))); |
| return; |
| } |
| logging::logMessage("Invalid type recieved for clear NVRAM from VPD."); |
| } |
| |
| void IbmBiosHandler::saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal) |
| { |
| if (i_KeepAndClearVal.empty()) |
| { |
| logging::logMessage( |
| "Empty value received for keep and clear from BIOS. Skip updating to VPD."); |
| return; |
| } |
| |
| // Read required keyword from DBus as we need to set only a Bit. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::utilInf, constants::kwdKeepAndClear); |
| |
| if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| commonUtility::toLower(const_cast<std::string&>(i_KeepAndClearVal)); |
| |
| // Check for first bit. Bit set for enabled else disabled. |
| if (((((*l_pVal).at(0) & 0x01) == 0x01) && |
| (i_KeepAndClearVal.compare("enabled") == |
| constants::STR_CMP_SUCCESS)) || |
| ((((*l_pVal).at(0) & 0x01) == 0x00) && |
| (i_KeepAndClearVal.compare("disabled") == |
| constants::STR_CMP_SUCCESS))) |
| { |
| // Don't update, values are same. |
| return; |
| } |
| |
| types::BinaryVector l_valToUpdateInVpd; |
| if (i_KeepAndClearVal.compare("enabled") == constants::STR_CMP_SUCCESS) |
| { |
| // 1st bit is used to store the value. |
| l_valToUpdateInVpd.emplace_back( |
| (*l_pVal).at(0) | constants::VALUE_1); |
| } |
| else |
| { |
| // 1st bit is used to store the value. |
| l_valToUpdateInVpd.emplace_back( |
| (*l_pVal).at(0) & ~(constants::VALUE_1)); |
| } |
| |
| if (-1 == m_manager->updateKeyword( |
| SYSTEM_VPD_FILE_PATH, |
| types::IpzData("UTIL", constants::kwdKeepAndClear, |
| l_valToUpdateInVpd))) |
| { |
| logging::logMessage( |
| "Failed to update " + std::string(constants::kwdKeepAndClear) + |
| " keyword to VPD"); |
| } |
| |
| return; |
| } |
| logging::logMessage("Invalid type recieved for keep and clear from VPD."); |
| } |
| |
| void IbmBiosHandler::saveKeepAndClearToBios( |
| const std::string& i_KeepAndClearVal) |
| { |
| // checking for exact length as it is a string and can have garbage value. |
| if (i_KeepAndClearVal.size() != constants::VALUE_1) |
| { |
| logging::logMessage( |
| "Bad size for keep and clear in VPD. Skip writing to BIOS."); |
| return; |
| } |
| |
| // 1st bit is used to store keep and clear value. |
| std::string l_valtoUpdate = |
| (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled"; |
| |
| types::PendingBIOSAttrs l_pendingBiosAttribute; |
| l_pendingBiosAttribute.push_back(std::make_pair( |
| "pvm_keep_and_clear", |
| std::make_tuple( |
| "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration", |
| l_valtoUpdate))); |
| |
| if (!dbusUtility::writeDbusProperty( |
| constants::biosConfigMgrService, constants::biosConfigMgrObjPath, |
| constants::biosConfigMgrInterface, "PendingAttributes", |
| l_pendingBiosAttribute)) |
| { |
| logging::logMessage( |
| "DBus call to update keep and clear value in pending attribute failed."); |
| } |
| } |
| |
| void IbmBiosHandler::processKeepAndClear() |
| { |
| // Read required keyword from VPD. |
| auto l_kwdValueVariant = dbusUtility::readDbusProperty( |
| constants::pimServiceName, constants::systemVpdInvPath, |
| constants::utilInf, constants::kwdKeepAndClear); |
| |
| if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant)) |
| { |
| saveKeepAndClearToBios(std::to_string(l_pVal->at(0))); |
| return; |
| } |
| logging::logMessage("Invalid type recieved for keep and clear from VPD."); |
| } |
| } // namespace vpd |