| #include "config.h" |
| |
| #include "vpd_tool.hpp" |
| |
| #include "tool_constants.hpp" |
| #include "tool_types.hpp" |
| #include "tool_utils.hpp" |
| |
| #include <cstdlib> |
| #include <iostream> |
| #include <regex> |
| #include <tuple> |
| namespace vpd |
| { |
| // {Record, Keyword} -> {attribute name, number of bits in keyword, starting bit |
| // position, enabled value, disabled value} |
| // Note: we do not care about min/max value for the BIOS attribute here. |
| const types::BiosAttributeKeywordMap VpdTool::m_biosAttributeVpdKeywordMap = { |
| {{"UTIL", "D0"}, |
| {{"hb_memory_mirror_mode", constants::VALUE_8, std::nullopt, |
| constants::VALUE_2, constants::VALUE_1}}}, |
| {{"UTIL", "D1"}, |
| {{"pvm_keep_and_clear", constants::VALUE_1, constants::VALUE_0, |
| constants::VALUE_1, constants::VALUE_0}, |
| {"pvm_create_default_lpar", constants::VALUE_1, constants::VALUE_1, |
| constants::VALUE_1, constants::VALUE_0}, |
| {"pvm_clear_nvram", constants::VALUE_1, constants::VALUE_2, |
| constants::VALUE_1, constants::VALUE_0}}}, |
| {{"VSYS", "RG"}, |
| {{"hb_field_core_override", constants::VALUE_32, std::nullopt, |
| std::nullopt, std::nullopt}}}}; |
| |
| int VpdTool::readKeyword( |
| const std::string& i_vpdPath, const std::string& i_recordName, |
| const std::string& i_keywordName, const bool i_onHardware, |
| const std::string& i_fileToSave) |
| { |
| int l_rc = constants::FAILURE; |
| try |
| { |
| types::DbusVariantType l_keywordValue; |
| if (i_onHardware) |
| { |
| l_keywordValue = utils::readKeywordFromHardware( |
| i_vpdPath, std::make_tuple(i_recordName, i_keywordName)); |
| } |
| else |
| { |
| std::string l_inventoryObjectPath( |
| constants::baseInventoryPath + i_vpdPath); |
| |
| l_keywordValue = utils::readDbusProperty( |
| constants::inventoryManagerService, l_inventoryObjectPath, |
| constants::ipzVpdInfPrefix + i_recordName, i_keywordName); |
| } |
| |
| if (const auto l_value = |
| std::get_if<types::BinaryVector>(&l_keywordValue); |
| l_value && !l_value->empty()) |
| { |
| // ToDo: Print value in both ASCII and hex formats |
| const std::string& l_keywordStrValue = |
| utils::getPrintableValue(*l_value); |
| |
| if (i_fileToSave.empty()) |
| { |
| utils::displayOnConsole(i_vpdPath, i_keywordName, |
| l_keywordStrValue); |
| l_rc = constants::SUCCESS; |
| } |
| else |
| { |
| if (utils::saveToFile(i_fileToSave, l_keywordStrValue)) |
| { |
| std::cout |
| << "Value read is saved on the file: " << i_fileToSave |
| << std::endl; |
| l_rc = constants::SUCCESS; |
| } |
| else |
| { |
| std::cerr |
| << "Error while saving the read value on the file: " |
| << i_fileToSave |
| << "\nDisplaying the read value on console" |
| << std::endl; |
| utils::displayOnConsole(i_vpdPath, i_keywordName, |
| l_keywordStrValue); |
| } |
| } |
| } |
| else |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cout << "Invalid data type or empty data received." |
| << std::endl; |
| } |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "Read keyword's value failed for path: " << i_vpdPath |
| << ", Record: " << i_recordName << ", Keyword: " |
| << i_keywordName << ", error: " << l_ex.what() << std::endl; |
| } |
| return l_rc; |
| } |
| |
| int VpdTool::dumpObject(std::string i_fruPath) const noexcept |
| { |
| int l_rc{constants::FAILURE}; |
| try |
| { |
| // ToDo: For PFuture system take only full path from the user. |
| i_fruPath = constants::baseInventoryPath + i_fruPath; |
| |
| nlohmann::json l_resultJsonArray = nlohmann::json::array({}); |
| const nlohmann::json l_fruJson = getFruProperties(i_fruPath); |
| if (!l_fruJson.empty()) |
| { |
| l_resultJsonArray += l_fruJson; |
| |
| utils::printJson(l_resultJsonArray); |
| } |
| else |
| { |
| std::cout << "FRU [" << i_fruPath |
| << "] is not present in the system" << std::endl; |
| } |
| l_rc = constants::SUCCESS; |
| } |
| catch (std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "Dump Object failed for FRU [" << i_fruPath |
| << "], Error: " << l_ex.what() << std::endl; |
| } |
| return l_rc; |
| } |
| |
| template <typename PropertyType> |
| void VpdTool::populateInterfaceJson(const std::string& i_inventoryObjPath, |
| const std::string& i_infName, |
| const std::vector<std::string>& i_propList, |
| nlohmann::json& io_fruJsonObject) const |
| { |
| nlohmann::json l_interfaceJsonObj = nlohmann::json::object({}); |
| |
| auto l_readProperties = [i_inventoryObjPath, &l_interfaceJsonObj, i_infName, |
| this](const std::string& i_property) { |
| const nlohmann::json l_propertyJsonObj = |
| getInventoryPropertyJson<PropertyType>(i_inventoryObjPath, |
| i_infName, i_property); |
| l_interfaceJsonObj.insert(l_propertyJsonObj.cbegin(), |
| l_propertyJsonObj.cend()); |
| }; |
| |
| std::for_each(i_propList.cbegin(), i_propList.cend(), l_readProperties); |
| |
| if (!l_interfaceJsonObj.empty()) |
| { |
| io_fruJsonObject.insert(l_interfaceJsonObj.cbegin(), |
| l_interfaceJsonObj.cend()); |
| } |
| } |
| |
| void VpdTool::populateFruJson( |
| const std::string& i_inventoryObjPath, nlohmann::json& io_fruJsonObject, |
| const std::vector<std::string>& i_interfaceList) const |
| { |
| for (const auto& l_interface : i_interfaceList) |
| { |
| if (l_interface == constants::inventoryItemInf) |
| { |
| const std::vector<std::string> l_properties = {"PrettyName"}; |
| populateInterfaceJson<std::string>(i_inventoryObjPath, |
| constants::inventoryItemInf, |
| l_properties, io_fruJsonObject); |
| continue; |
| } |
| |
| if (l_interface == constants::locationCodeInf) |
| { |
| const std::vector<std::string> l_properties = {"LocationCode"}; |
| populateInterfaceJson<std::string>(i_inventoryObjPath, |
| constants::locationCodeInf, |
| l_properties, io_fruJsonObject); |
| continue; |
| } |
| |
| if (l_interface == constants::viniInf) |
| { |
| const std::vector<std::string> l_properties = {"SN", "PN", "CC", |
| "FN", "DR"}; |
| populateInterfaceJson<vpd::types::BinaryVector>( |
| i_inventoryObjPath, constants::viniInf, l_properties, |
| io_fruJsonObject); |
| continue; |
| } |
| |
| if (l_interface == constants::assetInf) |
| { |
| if (std::find(i_interfaceList.begin(), i_interfaceList.end(), |
| constants::viniInf) != i_interfaceList.end()) |
| { |
| // The value will be filled from VINI interface. Don't |
| // process asset interface. |
| continue; |
| } |
| |
| const std::vector<std::string> l_properties = { |
| "Model", "SerialNumber", "SubModel"}; |
| |
| populateInterfaceJson<std::string>(i_inventoryObjPath, |
| constants::assetInf, |
| l_properties, io_fruJsonObject); |
| continue; |
| } |
| |
| if (l_interface == constants::networkInf) |
| { |
| const std::vector<std::string> l_properties = {"MACAddress"}; |
| populateInterfaceJson<std::string>(i_inventoryObjPath, |
| constants::networkInf, |
| l_properties, io_fruJsonObject); |
| continue; |
| } |
| |
| if (l_interface == constants::pcieSlotInf) |
| { |
| const std::vector<std::string> l_properties = {"SlotType"}; |
| populateInterfaceJson<std::string>(i_inventoryObjPath, |
| constants::pcieSlotInf, |
| l_properties, io_fruJsonObject); |
| continue; |
| } |
| |
| if (l_interface == constants::slotNumInf) |
| { |
| const std::vector<std::string> l_properties = {"SlotNumber"}; |
| populateInterfaceJson<uint32_t>(i_inventoryObjPath, |
| constants::slotNumInf, l_properties, |
| io_fruJsonObject); |
| continue; |
| } |
| |
| if (l_interface == constants::i2cDeviceInf) |
| { |
| const std::vector<std::string> l_properties = {"Address", "Bus"}; |
| populateInterfaceJson<uint32_t>(i_inventoryObjPath, |
| constants::i2cDeviceInf, |
| l_properties, io_fruJsonObject); |
| continue; |
| } |
| } |
| } |
| |
| nlohmann::json VpdTool::getFruProperties(const std::string& i_objectPath) const |
| { |
| // check if FRU is present in the system |
| if (!isFruPresent(i_objectPath)) |
| { |
| return nlohmann::json::object_t(); |
| } |
| |
| nlohmann::json l_fruJson = nlohmann::json::object_t({}); |
| |
| // need to trim out the base inventory path in the FRU JSON. |
| const std::string l_displayObjectPath = |
| (i_objectPath.find(constants::baseInventoryPath) == std::string::npos) |
| ? i_objectPath |
| : i_objectPath.substr(strlen(constants::baseInventoryPath)); |
| |
| l_fruJson.emplace(l_displayObjectPath, nlohmann::json::object_t({})); |
| |
| auto& l_fruObject = l_fruJson[l_displayObjectPath]; |
| |
| types::MapperGetObject l_mapperResp = utils::GetServiceInterfacesForObject( |
| i_objectPath, std::vector<std::string>{}); |
| |
| for (const auto& [l_service, l_interfaceList] : l_mapperResp) |
| { |
| if (l_service != constants::inventoryManagerService) |
| { |
| continue; |
| } |
| populateFruJson(i_objectPath, l_fruObject, l_interfaceList); |
| } |
| |
| const auto l_typePropertyJson = getFruTypeProperty(i_objectPath); |
| if (!l_typePropertyJson.empty()) |
| { |
| l_fruObject.insert(l_typePropertyJson.cbegin(), |
| l_typePropertyJson.cend()); |
| } |
| |
| // insert FRU "TYPE" |
| l_fruObject.emplace("TYPE", "FRU"); |
| |
| return l_fruJson; |
| } |
| |
| template <typename PropertyType> |
| nlohmann::json VpdTool::getInventoryPropertyJson( |
| const std::string& i_objectPath, const std::string& i_interface, |
| const std::string& i_propertyName) const noexcept |
| { |
| nlohmann::json l_resultInJson = nlohmann::json::object({}); |
| try |
| { |
| types::DbusVariantType l_keyWordValue; |
| |
| l_keyWordValue = |
| utils::readDbusProperty(constants::inventoryManagerService, |
| i_objectPath, i_interface, i_propertyName); |
| |
| if (const auto l_value = std::get_if<PropertyType>(&l_keyWordValue)) |
| { |
| if constexpr (std::is_same<PropertyType, std::string>::value) |
| { |
| l_resultInJson.emplace(i_propertyName, *l_value); |
| } |
| else if constexpr (std::is_same<PropertyType, bool>::value) |
| { |
| l_resultInJson.emplace(i_propertyName, |
| *l_value ? "true" : "false"); |
| } |
| else if constexpr (std::is_same<PropertyType, |
| types::BinaryVector>::value) |
| { |
| const std::string& l_keywordStrValue = |
| vpd::utils::getPrintableValue(*l_value); |
| |
| l_resultInJson.emplace(i_propertyName, l_keywordStrValue); |
| } |
| else if constexpr (std::is_same<PropertyType, uint32_t>::value) |
| { |
| l_resultInJson.emplace(i_propertyName, |
| std::to_string(*l_value)); |
| } |
| } |
| else |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cout << "Invalid data type received." << std::endl; |
| } |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "Read " << i_propertyName |
| << " value for FRU path: " << i_objectPath |
| << ", failed with exception: " << l_ex.what() << std::endl; |
| } |
| return l_resultInJson; |
| } |
| |
| int VpdTool::fixSystemVpd() const noexcept |
| { |
| int l_rc = constants::FAILURE; |
| |
| nlohmann::json l_backupRestoreCfgJsonObj = getBackupRestoreCfgJsonObj(); |
| if (!fetchKeywordInfo(l_backupRestoreCfgJsonObj)) |
| { |
| return l_rc; |
| } |
| |
| printSystemVpd(l_backupRestoreCfgJsonObj); |
| |
| do |
| { |
| printFixSystemVpdOption(types::UserOption::UseBackupDataForAll); |
| printFixSystemVpdOption( |
| types::UserOption::UseSystemBackplaneDataForAll); |
| printFixSystemVpdOption(types::UserOption::MoreOptions); |
| printFixSystemVpdOption(types::UserOption::Exit); |
| |
| int l_userSelectedOption = types::UserOption::Exit; |
| std::cin >> l_userSelectedOption; |
| |
| std::cout << std::endl << std::string(191, '=') << std::endl; |
| |
| if (types::UserOption::UseBackupDataForAll == l_userSelectedOption) |
| { |
| l_rc = updateAllKeywords(l_backupRestoreCfgJsonObj, true); |
| break; |
| } |
| else if (types::UserOption::UseSystemBackplaneDataForAll == |
| l_userSelectedOption) |
| { |
| l_rc = updateAllKeywords(l_backupRestoreCfgJsonObj, false); |
| break; |
| } |
| else if (types::UserOption::MoreOptions == l_userSelectedOption) |
| { |
| l_rc = handleMoreOption(l_backupRestoreCfgJsonObj); |
| break; |
| } |
| else if (types::UserOption::Exit == l_userSelectedOption) |
| { |
| std::cout << "Exit successfully" << std::endl; |
| break; |
| } |
| else |
| { |
| std::cout << "Provide a valid option. Retry." << std::endl; |
| } |
| } while (true); |
| |
| return l_rc; |
| } |
| |
| int VpdTool::writeKeyword( |
| std::string i_vpdPath, const std::string& i_recordName, |
| const std::string& i_keywordName, const std::string& i_keywordValue, |
| const bool i_onHardware) noexcept |
| { |
| int l_rc = constants::FAILURE; |
| try |
| { |
| if (i_vpdPath.empty() || i_recordName.empty() || |
| i_keywordName.empty() || i_keywordValue.empty()) |
| { |
| throw std::runtime_error("Received input is empty."); |
| } |
| |
| auto l_paramsToWrite = |
| std::make_tuple(i_recordName, i_keywordName, |
| utils::convertToBinary(i_keywordValue)); |
| |
| if (i_onHardware) |
| { |
| l_rc = utils::writeKeywordOnHardware(i_vpdPath, l_paramsToWrite); |
| } |
| else |
| { |
| i_vpdPath = constants::baseInventoryPath + i_vpdPath; |
| l_rc = utils::writeKeyword(i_vpdPath, l_paramsToWrite); |
| } |
| |
| if (l_rc > 0) |
| { |
| std::cout << "Data updated successfully " << std::endl; |
| l_rc = constants::SUCCESS; |
| } |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable log when verbose is enabled. |
| std::cerr << "Write keyword's value for path: " << i_vpdPath |
| << ", Record: " << i_recordName |
| << ", Keyword: " << i_keywordName |
| << " is failed. Exception: " << l_ex.what() << std::endl; |
| } |
| return l_rc; |
| } |
| |
| nlohmann::json VpdTool::getBackupRestoreCfgJsonObj() const noexcept |
| { |
| nlohmann::json l_parsedBackupRestoreJson{}; |
| try |
| { |
| nlohmann::json l_parsedSystemJson = |
| utils::getParsedJson(INVENTORY_JSON_SYM_LINK); |
| |
| // check for mandatory fields at this point itself. |
| if (!l_parsedSystemJson.contains("backupRestoreConfigPath")) |
| { |
| throw std::runtime_error( |
| "backupRestoreConfigPath tag is missing from system config JSON : " + |
| std::string(INVENTORY_JSON_SYM_LINK)); |
| } |
| |
| l_parsedBackupRestoreJson = |
| utils::getParsedJson(l_parsedSystemJson["backupRestoreConfigPath"]); |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << l_ex.what() << std::endl; |
| } |
| |
| return l_parsedBackupRestoreJson; |
| } |
| |
| int VpdTool::cleanSystemVpd(bool i_syncBiosAttributesRequired) const noexcept |
| { |
| try |
| { |
| // In order to do syncBiosAttributes, we need BIOS Config Manager |
| // service up and running |
| if (i_syncBiosAttributesRequired && |
| !utils::isServiceRunning(constants::biosConfigMgrService)) |
| { |
| std::cerr |
| << "Cannot sync BIOS attributes as BIOS Config Manager service is not running." |
| << std::endl; |
| return constants::FAILURE; |
| } |
| |
| // get the keyword map from backup_restore json |
| // iterate through the keyword map get default value of |
| // l_keywordName. |
| // use writeKeyword API to update default value on hardware, |
| // backup and D - Bus. |
| const nlohmann::json l_parsedBackupRestoreJson = |
| getBackupRestoreCfgJsonObj(); |
| |
| // check for mandatory tags |
| if (l_parsedBackupRestoreJson.contains("source") && |
| l_parsedBackupRestoreJson.contains("backupMap") && |
| l_parsedBackupRestoreJson["source"].contains("hardwarePath") && |
| l_parsedBackupRestoreJson["backupMap"].is_array()) |
| { |
| // get the source hardware path |
| const auto& l_hardwarePath = |
| l_parsedBackupRestoreJson["source"]["hardwarePath"]; |
| |
| // iterate through the backup map |
| for (const auto& l_aRecordKwInfo : |
| l_parsedBackupRestoreJson["backupMap"]) |
| { |
| // check if Manufacturing Reset is required for this entry |
| const bool l_isMfgCleanRequired = |
| l_aRecordKwInfo.value("isManufactureResetRequired", false); |
| |
| if (l_isMfgCleanRequired) |
| { |
| // get the Record name and Keyword name |
| const std::string& l_srcRecordName = |
| l_aRecordKwInfo.value("sourceRecord", ""); |
| const std::string& l_srcKeywordName = |
| l_aRecordKwInfo.value("sourceKeyword", ""); |
| |
| // validate the Record name, Keyword name and the |
| // defaultValue |
| if (!l_srcRecordName.empty() && !l_srcKeywordName.empty() && |
| l_aRecordKwInfo.contains("defaultValue") && |
| l_aRecordKwInfo["defaultValue"].is_array()) |
| { |
| // check if this keyword is used for backing up BIOS |
| // attribute |
| const bool l_isUsedForBiosAttributeBackup = |
| l_aRecordKwInfo.value("isBiosSyncRequired", false); |
| |
| const types::BinaryVector l_keywordValueToUpdate = |
| (i_syncBiosAttributesRequired && |
| l_isUsedForBiosAttributeBackup) |
| ? getVpdValueInBiosConfigManager( |
| l_srcRecordName, l_srcKeywordName) |
| : l_aRecordKwInfo["defaultValue"] |
| .get<types::BinaryVector>(); |
| |
| if (l_keywordValueToUpdate.empty()) |
| { |
| std::cerr << "Failed to update " << l_srcRecordName |
| << ":" << l_srcKeywordName |
| << " . Keyword value to update is empty" |
| << std::endl; |
| continue; |
| } |
| |
| // update the Keyword with default value, use D-Bus |
| // method UpdateKeyword exposed by vpd-manager. |
| // Note: writing to all paths (Primary EEPROM path, |
| // Secondary EEPROM path, D-Bus cache and Backup path) |
| // is the responsibility of vpd-manager's UpdateKeyword |
| // API |
| if (constants::FAILURE == |
| utils::writeKeyword( |
| l_hardwarePath, |
| std::make_tuple(l_srcRecordName, |
| l_srcKeywordName, |
| l_keywordValueToUpdate))) |
| { |
| // TODO: Enable logging when verbose |
| // is enabled. |
| std::cerr << "Failed to update " << l_srcRecordName |
| << ":" << l_srcKeywordName << std::endl; |
| } |
| } |
| else |
| { |
| std::cerr |
| << "Unrecognized Entry Record [" << l_srcRecordName |
| << "] Keyword [" << l_srcKeywordName |
| << "] in Backup Restore JSON backup map" |
| << std::endl; |
| } |
| } // mfgClean required check |
| } // keyword list loop |
| } |
| else // backupRestoreJson is not valid |
| { |
| std::cerr << "Backup Restore JSON is not valid" << std::endl; |
| } |
| |
| // success/failure message |
| std::cout << "The critical keywords from system backplane VPD has " |
| "been reset successfully." |
| << std::endl; |
| |
| } // try block end |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr |
| << "Manufacturing reset on system vpd keywords is unsuccessful. Error : " |
| << l_ex.what() << std::endl; |
| } |
| return constants::SUCCESS; |
| } |
| |
| bool VpdTool::fetchKeywordInfo(nlohmann::json& io_parsedJsonObj) const noexcept |
| { |
| bool l_returnValue = false; |
| try |
| { |
| if (io_parsedJsonObj.empty() || !io_parsedJsonObj.contains("source") || |
| !io_parsedJsonObj.contains("destination") || |
| !io_parsedJsonObj.contains("backupMap")) |
| { |
| throw std::runtime_error("Invalid JSON"); |
| } |
| |
| std::string l_srcVpdPath; |
| std::string l_dstVpdPath; |
| |
| bool l_isSourceOnHardware = false; |
| if (l_srcVpdPath = io_parsedJsonObj["source"].value("hardwarePath", ""); |
| !l_srcVpdPath.empty()) |
| { |
| l_isSourceOnHardware = true; |
| } |
| else if (l_srcVpdPath = |
| io_parsedJsonObj["source"].value("inventoryPath", ""); |
| l_srcVpdPath.empty()) |
| { |
| throw std::runtime_error("Source path is empty in JSON"); |
| } |
| |
| bool l_isDestinationOnHardware = false; |
| if (l_dstVpdPath = |
| io_parsedJsonObj["destination"].value("hardwarePath", ""); |
| !l_dstVpdPath.empty()) |
| { |
| l_isDestinationOnHardware = true; |
| } |
| else if (l_dstVpdPath = |
| io_parsedJsonObj["destination"].value("inventoryPath", ""); |
| l_dstVpdPath.empty()) |
| { |
| throw std::runtime_error("Destination path is empty in JSON"); |
| } |
| |
| for (auto& l_aRecordKwInfo : io_parsedJsonObj["backupMap"]) |
| { |
| const std::string& l_srcRecordName = |
| l_aRecordKwInfo.value("sourceRecord", ""); |
| const std::string& l_srcKeywordName = |
| l_aRecordKwInfo.value("sourceKeyword", ""); |
| const std::string& l_dstRecordName = |
| l_aRecordKwInfo.value("destinationRecord", ""); |
| const std::string& l_dstKeywordName = |
| l_aRecordKwInfo.value("destinationKeyword", ""); |
| |
| if (l_srcRecordName.empty() || l_dstRecordName.empty() || |
| l_srcKeywordName.empty() || l_dstKeywordName.empty()) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cout << "Record or keyword not found in the JSON." |
| << std::endl; |
| continue; |
| } |
| |
| types::DbusVariantType l_srcKeywordVariant; |
| if (l_isSourceOnHardware) |
| { |
| l_srcKeywordVariant = utils::readKeywordFromHardware( |
| l_srcVpdPath, |
| std::make_tuple(l_srcRecordName, l_srcKeywordName)); |
| } |
| else |
| { |
| l_srcKeywordVariant = utils::readDbusProperty( |
| constants::inventoryManagerService, l_srcVpdPath, |
| constants::ipzVpdInfPrefix + l_srcRecordName, |
| l_srcKeywordName); |
| } |
| |
| if (auto l_srcKeywordValue = |
| std::get_if<types::BinaryVector>(&l_srcKeywordVariant); |
| l_srcKeywordValue && !l_srcKeywordValue->empty()) |
| { |
| l_aRecordKwInfo["sourcekeywordValue"] = *l_srcKeywordValue; |
| } |
| else |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cout |
| << "Invalid data type or empty data received, for source record: " |
| << l_srcRecordName << ", keyword: " << l_srcKeywordName |
| << std::endl; |
| continue; |
| } |
| |
| types::DbusVariantType l_dstKeywordVariant; |
| if (l_isDestinationOnHardware) |
| { |
| l_dstKeywordVariant = utils::readKeywordFromHardware( |
| l_dstVpdPath, |
| std::make_tuple(l_dstRecordName, l_dstKeywordName)); |
| } |
| else |
| { |
| l_dstKeywordVariant = utils::readDbusProperty( |
| constants::inventoryManagerService, l_dstVpdPath, |
| constants::ipzVpdInfPrefix + l_dstRecordName, |
| l_dstKeywordName); |
| } |
| |
| if (auto l_dstKeywordValue = |
| std::get_if<types::BinaryVector>(&l_dstKeywordVariant); |
| l_dstKeywordValue && !l_dstKeywordValue->empty()) |
| { |
| l_aRecordKwInfo["destinationkeywordValue"] = *l_dstKeywordValue; |
| } |
| else |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cout |
| << "Invalid data type or empty data received, for destination record: " |
| << l_dstRecordName << ", keyword: " << l_dstKeywordName |
| << std::endl; |
| continue; |
| } |
| } |
| |
| l_returnValue = true; |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << l_ex.what() << std::endl; |
| } |
| |
| return l_returnValue; |
| } |
| |
| nlohmann::json VpdTool::getFruTypeProperty( |
| const std::string& i_objectPath) const noexcept |
| { |
| nlohmann::json l_resultInJson = nlohmann::json::object({}); |
| std::vector<std::string> l_pimInfList; |
| |
| auto l_serviceInfMap = utils::GetServiceInterfacesForObject( |
| i_objectPath, std::vector<std::string>{constants::inventoryItemInf}); |
| if (l_serviceInfMap.contains(constants::inventoryManagerService)) |
| { |
| l_pimInfList = l_serviceInfMap[constants::inventoryManagerService]; |
| |
| // iterate through the list and find |
| // "xyz.openbmc_project.Inventory.Item.*" |
| for (const auto& l_interface : l_pimInfList) |
| { |
| if (l_interface.find(constants::inventoryItemInf) != |
| std::string::npos && |
| l_interface.length() > |
| std::string(constants::inventoryItemInf).length()) |
| { |
| l_resultInJson.emplace("type", l_interface); |
| } |
| } |
| } |
| return l_resultInJson; |
| } |
| |
| bool VpdTool::isFruPresent(const std::string& i_objectPath) const noexcept |
| { |
| bool l_returnValue{false}; |
| try |
| { |
| types::DbusVariantType l_keyWordValue; |
| |
| l_keyWordValue = utils::readDbusProperty( |
| constants::inventoryManagerService, i_objectPath, |
| constants::inventoryItemInf, "Present"); |
| |
| if (const auto l_value = std::get_if<bool>(&l_keyWordValue)) |
| { |
| l_returnValue = *l_value; |
| } |
| } |
| catch (const std::runtime_error& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| // std::cerr << "Failed to check \"Present\" property for FRU " |
| // << i_objectPath << " Error: " << l_ex.what() << |
| // std::endl; |
| } |
| return l_returnValue; |
| } |
| |
| void VpdTool::printFixSystemVpdOption( |
| const types::UserOption& i_option) const noexcept |
| { |
| switch (i_option) |
| { |
| case types::UserOption::Exit: |
| std::cout << "Enter 0 => To exit successfully : "; |
| break; |
| case types::UserOption::UseBackupDataForAll: |
| std::cout << "Enter 1 => If you choose the data on backup for all " |
| "mismatching record-keyword pairs" |
| << std::endl; |
| break; |
| case types::UserOption::UseSystemBackplaneDataForAll: |
| std::cout << "Enter 2 => If you choose the data on primary for all " |
| "mismatching record-keyword pairs" |
| << std::endl; |
| break; |
| case types::UserOption::MoreOptions: |
| std::cout << "Enter 3 => If you wish to explore more options" |
| << std::endl; |
| break; |
| case types::UserOption::UseBackupDataForCurrent: |
| std::cout << "Enter 4 => If you choose the data on backup as the " |
| "right value" |
| << std::endl; |
| break; |
| case types::UserOption::UseSystemBackplaneDataForCurrent: |
| std::cout << "Enter 5 => If you choose the data on primary as the " |
| "right value" |
| << std::endl; |
| break; |
| case types::UserOption::NewValueOnBoth: |
| std::cout |
| << "Enter 6 => If you wish to enter a new value to update " |
| "both on backup and primary" |
| << std::endl; |
| break; |
| case types::UserOption::SkipCurrent: |
| std::cout << "Enter 7 => If you wish to skip the above " |
| "record-keyword pair" |
| << std::endl; |
| break; |
| } |
| } |
| |
| int VpdTool::dumpInventory(bool i_dumpTable) const noexcept |
| { |
| int l_rc{constants::FAILURE}; |
| |
| try |
| { |
| // get all object paths under PIM |
| const auto l_objectPaths = utils::GetSubTreePaths( |
| constants::baseInventoryPath, 0, |
| std::vector<std::string>{constants::inventoryItemInf}); |
| |
| if (!l_objectPaths.empty()) |
| { |
| nlohmann::json l_resultInJson = nlohmann::json::array({}); |
| |
| std::for_each(l_objectPaths.begin(), l_objectPaths.end(), |
| [&](const auto& l_objectPath) { |
| const auto l_fruJson = |
| getFruProperties(l_objectPath); |
| if (!l_fruJson.empty()) |
| { |
| if (l_resultInJson.empty()) |
| { |
| l_resultInJson += l_fruJson; |
| } |
| else |
| { |
| l_resultInJson.at(0).insert( |
| l_fruJson.cbegin(), l_fruJson.cend()); |
| } |
| } |
| }); |
| |
| if (i_dumpTable) |
| { |
| // create Table object |
| utils::Table l_inventoryTable{}; |
| |
| // columns to be populated in the Inventory table |
| const std::vector<types::TableColumnNameSizePair> |
| l_tableColumns = { |
| {"FRU", 100}, {"CC", 6}, {"DR", 20}, |
| {"LocationCode", 32}, {"PN", 8}, {"PrettyName", 80}, |
| {"SubModel", 10}, {"SN", 15}, {"type", 60}}; |
| |
| types::TableInputData l_tableData; |
| |
| // First prepare the Table Columns |
| for (const auto& l_column : l_tableColumns) |
| { |
| if (constants::FAILURE == |
| l_inventoryTable.AddColumn(l_column.first, |
| l_column.second)) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "Failed to add column " << l_column.first |
| << " in Inventory Table." << std::endl; |
| } |
| } |
| |
| // iterate through the json array |
| for (const auto& l_fruEntry : l_resultInJson[0].items()) |
| { |
| // if object path ends in "unit([0-9][0-9]?)", skip adding |
| // the object path in the table |
| if (std::regex_search(l_fruEntry.key(), |
| std::regex("unit([0-9][0-9]?)"))) |
| { |
| continue; |
| } |
| |
| std::vector<std::string> l_row; |
| for (const auto& l_column : l_tableColumns) |
| { |
| const auto& l_fruJson = l_fruEntry.value(); |
| |
| if (l_column.first == "FRU") |
| { |
| l_row.push_back(l_fruEntry.key()); |
| } |
| else |
| { |
| if (l_fruJson.contains(l_column.first)) |
| { |
| l_row.push_back(l_fruJson[l_column.first]); |
| } |
| else |
| { |
| l_row.push_back(""); |
| } |
| } |
| } |
| |
| l_tableData.push_back(l_row); |
| } |
| |
| l_rc = l_inventoryTable.Print(l_tableData); |
| } |
| else |
| { |
| // print JSON to console |
| utils::printJson(l_resultInJson); |
| l_rc = constants::SUCCESS; |
| } |
| } |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "Dump inventory failed. Error: " << l_ex.what() |
| << std::endl; |
| } |
| return l_rc; |
| } |
| |
| void VpdTool::printSystemVpd( |
| const nlohmann::json& i_parsedJsonObj) const noexcept |
| { |
| if (i_parsedJsonObj.empty() || !i_parsedJsonObj.contains("backupMap")) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "Invalid JSON to print system VPD" << std::endl; |
| } |
| |
| std::string l_outline(191, '='); |
| std::cout << "\nRestorable record-keyword pairs and their data on backup & " |
| "primary.\n\n" |
| << l_outline << std::endl; |
| |
| std::cout << std::left << std::setw(6) << "S.No" << std::left |
| << std::setw(8) << "Record" << std::left << std::setw(9) |
| << "Keyword" << std::left << std::setw(75) << "Data On Backup" |
| << std::left << std::setw(75) << "Data On Primary" << std::left |
| << std::setw(14) << "Data Mismatch\n" |
| << l_outline << std::endl; |
| |
| uint8_t l_slNum = 0; |
| |
| for (const auto& l_aRecordKwInfo : i_parsedJsonObj["backupMap"]) |
| { |
| if (l_aRecordKwInfo.contains("sourceRecord") || |
| l_aRecordKwInfo.contains("sourceKeyword") || |
| l_aRecordKwInfo.contains("destinationkeywordValue") || |
| l_aRecordKwInfo.contains("sourcekeywordValue")) |
| { |
| std::string l_mismatchFound{ |
| (l_aRecordKwInfo["destinationkeywordValue"] != |
| l_aRecordKwInfo["sourcekeywordValue"]) |
| ? "YES" |
| : "NO"}; |
| |
| std::string l_splitLine(191, '-'); |
| |
| try |
| { |
| std::cout << std::left << std::setw(6) |
| << static_cast<int>(++l_slNum) << std::left |
| << std::setw(8) |
| << l_aRecordKwInfo.value("sourceRecord", "") |
| << std::left << std::setw(9) |
| << l_aRecordKwInfo.value("sourceKeyword", "") |
| << std::left << std::setw(75) << std::setfill(' ') |
| << utils::getPrintableValue( |
| l_aRecordKwInfo["destinationkeywordValue"]) |
| << std::left << std::setw(75) << std::setfill(' ') |
| << utils::getPrintableValue( |
| l_aRecordKwInfo["sourcekeywordValue"]) |
| << std::left << std::setw(14) << l_mismatchFound |
| << '\n' |
| << l_splitLine << std::endl; |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << l_ex.what() << std::endl; |
| } |
| } |
| } |
| } |
| |
| int VpdTool::updateAllKeywords(const nlohmann::json& i_parsedJsonObj, |
| bool i_useBackupData) const noexcept |
| { |
| int l_rc = constants::FAILURE; |
| |
| if (i_parsedJsonObj.empty() || !i_parsedJsonObj.contains("source") || |
| !i_parsedJsonObj.contains("backupMap")) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "Invalid JSON" << std::endl; |
| return l_rc; |
| } |
| |
| std::string l_srcVpdPath; |
| if (auto l_vpdPath = i_parsedJsonObj["source"].value("hardwarePath", ""); |
| !l_vpdPath.empty()) |
| { |
| l_srcVpdPath = l_vpdPath; |
| } |
| else if (auto l_vpdPath = |
| i_parsedJsonObj["source"].value("inventoryPath", ""); |
| !l_vpdPath.empty()) |
| { |
| l_srcVpdPath = l_vpdPath; |
| } |
| else |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "source path information is missing in JSON" << std::endl; |
| return l_rc; |
| } |
| |
| bool l_anyMismatchFound = false; |
| for (const auto& l_aRecordKwInfo : i_parsedJsonObj["backupMap"]) |
| { |
| if (!l_aRecordKwInfo.contains("sourceRecord") || |
| !l_aRecordKwInfo.contains("sourceKeyword") || |
| !l_aRecordKwInfo.contains("destinationkeywordValue") || |
| !l_aRecordKwInfo.contains("sourcekeywordValue")) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "Missing required information in the JSON" |
| << std::endl; |
| continue; |
| } |
| |
| if (l_aRecordKwInfo["sourcekeywordValue"] != |
| l_aRecordKwInfo["destinationkeywordValue"]) |
| { |
| l_anyMismatchFound = true; |
| |
| auto l_keywordValue = |
| i_useBackupData ? l_aRecordKwInfo["destinationkeywordValue"] |
| : l_aRecordKwInfo["sourcekeywordValue"]; |
| |
| auto l_paramsToWrite = std::make_tuple( |
| l_aRecordKwInfo["sourceRecord"], |
| l_aRecordKwInfo["sourceKeyword"], l_keywordValue); |
| |
| try |
| { |
| l_rc = utils::writeKeyword(l_srcVpdPath, l_paramsToWrite); |
| if (l_rc > 0) |
| { |
| l_rc = constants::SUCCESS; |
| } |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << "write keyword failed for record: " |
| << l_aRecordKwInfo["sourceRecord"] |
| << ", keyword: " << l_aRecordKwInfo["sourceKeyword"] |
| << ", error: " << l_ex.what() << std::ends; |
| } |
| } |
| } |
| |
| std::string l_dataUsed = |
| (i_useBackupData ? "data from backup" : "data from primary VPD"); |
| if (l_anyMismatchFound) |
| { |
| std::cout << "Data updated successfully for all mismatching " |
| "record-keyword pairs by choosing their corresponding " |
| << l_dataUsed << ". Exit successfully." << std::endl; |
| } |
| else |
| { |
| std::cout << "No mismatch found for any of the above mentioned " |
| "record-keyword pair. Exit successfully." |
| << std::endl; |
| } |
| |
| return l_rc; |
| } |
| |
| int VpdTool::handleMoreOption( |
| const nlohmann::json& i_parsedJsonObj) const noexcept |
| { |
| int l_rc = constants::FAILURE; |
| |
| try |
| { |
| if (i_parsedJsonObj.empty() || !i_parsedJsonObj.contains("backupMap")) |
| { |
| throw std::runtime_error("Invalid JSON"); |
| } |
| |
| std::string l_srcVpdPath; |
| |
| if (auto l_vpdPath = |
| i_parsedJsonObj["source"].value("hardwarePath", ""); |
| !l_vpdPath.empty()) |
| { |
| l_srcVpdPath = l_vpdPath; |
| } |
| else if (auto l_vpdPath = |
| i_parsedJsonObj["source"].value("inventoryPath", ""); |
| !l_vpdPath.empty()) |
| { |
| l_srcVpdPath = l_vpdPath; |
| } |
| else |
| { |
| throw std::runtime_error( |
| "source path information is missing in JSON"); |
| } |
| |
| auto updateKeywordValue = |
| [](std::string io_vpdPath, const std::string& i_recordName, |
| const std::string& i_keywordName, |
| const types::BinaryVector& i_keywordValue) -> int { |
| int l_rc = constants::FAILURE; |
| |
| try |
| { |
| auto l_paramsToWrite = std::make_tuple( |
| i_recordName, i_keywordName, i_keywordValue); |
| l_rc = utils::writeKeyword(io_vpdPath, l_paramsToWrite); |
| |
| if (l_rc > 0) |
| { |
| std::cout << std::endl |
| << "Data updated successfully." << std::endl; |
| } |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable log when verbose is enabled. |
| std::cerr << l_ex.what() << std::endl; |
| } |
| return l_rc; |
| }; |
| |
| do |
| { |
| int l_slNum = 0; |
| bool l_exit = false; |
| |
| for (const auto& l_aRecordKwInfo : i_parsedJsonObj["backupMap"]) |
| { |
| if (!l_aRecordKwInfo.contains("sourceRecord") || |
| !l_aRecordKwInfo.contains("sourceKeyword") || |
| !l_aRecordKwInfo.contains("destinationkeywordValue") || |
| !l_aRecordKwInfo.contains("sourcekeywordValue")) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr |
| << "Source or destination information is missing in the JSON." |
| << std::endl; |
| continue; |
| } |
| |
| const std::string l_mismatchFound{ |
| (l_aRecordKwInfo["sourcekeywordValue"] != |
| l_aRecordKwInfo["destinationkeywordValue"]) |
| ? "YES" |
| : "NO"}; |
| |
| std::cout << std::endl |
| << std::left << std::setw(6) << "S.No" << std::left |
| << std::setw(8) << "Record" << std::left |
| << std::setw(9) << "Keyword" << std::left |
| << std::setw(75) << std::setfill(' ') << "Backup Data" |
| << std::left << std::setw(75) << std::setfill(' ') |
| << "Primary Data" << std::left << std::setw(14) |
| << "Data Mismatch" << std::endl; |
| |
| std::cout << std::left << std::setw(6) |
| << static_cast<int>(++l_slNum) << std::left |
| << std::setw(8) |
| << l_aRecordKwInfo.value("sourceRecord", "") |
| << std::left << std::setw(9) |
| << l_aRecordKwInfo.value("sourceKeyword", "") |
| << std::left << std::setw(75) << std::setfill(' ') |
| << utils::getPrintableValue( |
| l_aRecordKwInfo["destinationkeywordValue"]) |
| << std::left << std::setw(75) << std::setfill(' ') |
| << utils::getPrintableValue( |
| l_aRecordKwInfo["sourcekeywordValue"]) |
| << std::left << std::setw(14) << l_mismatchFound |
| << std::endl; |
| |
| std::cout << std::string(191, '=') << std::endl; |
| |
| if (constants::STR_CMP_SUCCESS == |
| l_mismatchFound.compare("YES")) |
| { |
| printFixSystemVpdOption( |
| types::UserOption::UseBackupDataForCurrent); |
| printFixSystemVpdOption( |
| types::UserOption::UseSystemBackplaneDataForCurrent); |
| printFixSystemVpdOption(types::UserOption::NewValueOnBoth); |
| printFixSystemVpdOption(types::UserOption::SkipCurrent); |
| printFixSystemVpdOption(types::UserOption::Exit); |
| } |
| else |
| { |
| std::cout << "No mismatch found." << std::endl << std::endl; |
| printFixSystemVpdOption(types::UserOption::NewValueOnBoth); |
| printFixSystemVpdOption(types::UserOption::SkipCurrent); |
| printFixSystemVpdOption(types::UserOption::Exit); |
| } |
| |
| int l_userSelectedOption = types::UserOption::Exit; |
| std::cin >> l_userSelectedOption; |
| |
| if (types::UserOption::UseBackupDataForCurrent == |
| l_userSelectedOption) |
| { |
| l_rc = updateKeywordValue( |
| l_srcVpdPath, l_aRecordKwInfo["sourceRecord"], |
| l_aRecordKwInfo["sourceKeyword"], |
| l_aRecordKwInfo["destinationkeywordValue"]); |
| } |
| else if (types::UserOption::UseSystemBackplaneDataForCurrent == |
| l_userSelectedOption) |
| { |
| l_rc = updateKeywordValue( |
| l_srcVpdPath, l_aRecordKwInfo["sourceRecord"], |
| l_aRecordKwInfo["sourceKeyword"], |
| l_aRecordKwInfo["sourcekeywordValue"]); |
| } |
| else if (types::UserOption::NewValueOnBoth == |
| l_userSelectedOption) |
| { |
| std::string l_newValue; |
| std::cout |
| << std::endl |
| << "Enter the new value to update on both " |
| "primary & backup. Value should be in ASCII or " |
| "in HEX(prefixed with 0x) : "; |
| std::cin >> l_newValue; |
| std::cout << std::endl |
| << std::string(191, '=') << std::endl; |
| |
| try |
| { |
| l_rc = updateKeywordValue( |
| l_srcVpdPath, l_aRecordKwInfo["sourceRecord"], |
| l_aRecordKwInfo["sourceKeyword"], |
| utils::convertToBinary(l_newValue)); |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << l_ex.what() << std::endl; |
| } |
| } |
| else if (types::UserOption::SkipCurrent == l_userSelectedOption) |
| { |
| std::cout << std::endl |
| << "Skipped the above record-keyword pair. " |
| "Continue to the next available pair." |
| << std::endl; |
| } |
| else if (types::UserOption::Exit == l_userSelectedOption) |
| { |
| std::cout << "Exit successfully" << std::endl; |
| l_exit = true; |
| break; |
| } |
| else |
| { |
| std::cout << "Provide a valid option. Retrying for the " |
| "current record-keyword pair" |
| << std::endl; |
| } |
| } |
| if (l_exit) |
| { |
| l_rc = constants::SUCCESS; |
| break; |
| } |
| } while (true); |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << l_ex.what() << std::endl; |
| } |
| |
| return l_rc; |
| } |
| |
| int VpdTool::resetVpdOnDbus() |
| { |
| // ToDo: Limit this function to lab mode only. |
| |
| int l_rc = constants::FAILURE; |
| try |
| { |
| std::string l_vpdManagerStopCmd( |
| "systemctl stop " + std::string(constants::vpdManagerProcessName)); |
| |
| std::cout << std::flush; |
| if (auto l_rc = std::system(l_vpdManagerStopCmd.c_str()); l_rc != 0) |
| { |
| std::cerr << "Failed to stop " << constants::vpdManagerProcessName |
| << " service. Return code [" << l_rc << "]. Exiting." |
| << std::endl; |
| return l_rc; |
| } |
| |
| std::string l_vpdServiceIsActiveCmd( |
| "systemctl is-active --quiet " + |
| std::string(constants::vpdManagerProcessName)); |
| |
| std::cout << std::flush; |
| if (auto l_rc = std::system(l_vpdServiceIsActiveCmd.c_str()); l_rc == 0) |
| { |
| std::cerr |
| << constants::vpdManagerProcessName |
| << " service is still active, can't proceed further. Return code [" |
| << l_rc << "]. Exiting." << std::endl; |
| return l_rc; |
| } |
| |
| std::error_code l_ec; |
| if (static_cast<std::uintmax_t>(-1) == |
| std::filesystem::remove_all(constants::pimPersistPath, l_ec)) |
| { |
| std::cerr |
| << "Error occured while removing the persisted VPD under path [" |
| << constants::pimPersistPath << "]." << std::endl; |
| |
| if (l_ec) |
| { |
| std::cerr << "Reason: " << l_ec.message() << std::endl; |
| } |
| |
| std::cerr << "Reboot BMC to recover the system." << std::endl; |
| return l_rc; |
| } |
| |
| std::string l_pimServiceRestartCmd( |
| "systemctl restart " + |
| std::string(constants::inventoryManagerService)); |
| |
| std::cout << std::flush; |
| if (auto l_rc = std::system(l_pimServiceRestartCmd.c_str()); l_rc != 0) |
| { |
| std::cerr << "Failed to restart " |
| << constants::inventoryManagerService |
| << " service. Return code [" << l_rc << "]. Exiting." |
| << std::endl |
| << "Reboot BMC to recover the system." << std::endl; |
| return l_rc; |
| } |
| |
| std::string l_pimServiceIsActiveCmd( |
| "systemctl is-active --quiet " + |
| std::string(constants::inventoryManagerService)); |
| |
| std::cout << std::flush; |
| if (auto l_rc = std::system(l_pimServiceIsActiveCmd.c_str()); l_rc != 0) |
| { |
| std::cerr << constants::inventoryManagerService |
| << " service is not active. Return code [" << l_rc |
| << "]. Exiting." << std::endl |
| << "Reboot BMC to recover the system." << std::endl; |
| return l_rc; |
| } |
| |
| std::string l_vpdManagerStartCmd( |
| "systemctl start " + std::string(constants::vpdManagerProcessName)); |
| |
| std::cout << std::flush; |
| if (auto l_rc = std::system(l_vpdManagerStartCmd.c_str()); l_rc != 0) |
| { |
| std::cerr << "Failed to start " << constants::vpdManagerProcessName |
| << " service. Return code [" << l_rc << "]. Exiting." |
| << std::endl |
| << "Reboot BMC to recover the system." << std::endl; |
| return l_rc; |
| } |
| |
| std::cout << std::flush; |
| if (auto l_rc = std::system(l_vpdServiceIsActiveCmd.c_str()); l_rc != 0) |
| { |
| std::cerr << constants::vpdManagerProcessName |
| << " service is not active. Return code [" << l_rc |
| << "]. Exiting." << std::endl |
| << "Reboot BMC to recover the system." << std::endl; |
| return l_rc; |
| } |
| |
| l_rc = constants::SUCCESS; |
| } |
| catch (const std::exception& l_ex) |
| { |
| // TODO: Enable logging when verbose is enabled. |
| std::cerr << l_ex.what() << std::endl; |
| } |
| |
| return l_rc; |
| } |
| |
| types::BinaryVector VpdTool::getVpdValueInBiosConfigManager( |
| const std::string& i_recordName, const std::string& i_keywordName) const |
| { |
| types::BinaryVector l_result; |
| const auto l_itrToBiosAttributeKeywordMap = |
| m_biosAttributeVpdKeywordMap.find( |
| types::IpzType(i_recordName, i_keywordName)); |
| |
| if (l_itrToBiosAttributeKeywordMap != m_biosAttributeVpdKeywordMap.end()) |
| { |
| const auto& l_biosAttributeList = |
| l_itrToBiosAttributeKeywordMap->second; |
| for (const auto& l_biosAttributeEntry : l_biosAttributeList) |
| { |
| // get the attribute name |
| const std::string l_attributeName = |
| std::get<0>(l_biosAttributeEntry); |
| |
| // get the number of bits used to store the value in VPD |
| const size_t l_numBitsKeyword = std::get<1>(l_biosAttributeEntry); |
| |
| auto l_attrValueVariant = |
| utils::biosGetAttributeMethodCall(l_attributeName); |
| |
| if (auto l_attrVal = std::get_if<int64_t>(&l_attrValueVariant)) |
| { |
| // multiple bytes update |
| |
| size_t l_numBytesKeyword = |
| l_numBitsKeyword / constants::VALUE_8; |
| |
| // convert to VPD format |
| l_result = utils::convertIntegralTypeToBytes(*l_attrVal, |
| l_numBytesKeyword); |
| } |
| else if (auto l_attrVal = |
| std::get_if<std::string>(&l_attrValueVariant)) |
| { |
| utils::toLower(*l_attrVal); |
| |
| // Since we are doing mfgClean, we do not |
| // care about reading the current VPD keyword value before |
| // writing to it. |
| if (l_numBitsKeyword == constants::VALUE_1) |
| { |
| // single bit update. |
| |
| // get the bit position |
| const uint8_t l_bitPosition = |
| std::get<2>(l_biosAttributeEntry).has_value() |
| ? std::get<2>(l_biosAttributeEntry).value() |
| : constants::VALUE_0; |
| |
| l_result.resize(constants::VALUE_1, constants::VALUE_0); |
| |
| if (l_attrVal->compare("enabled") == |
| constants::STR_CMP_SUCCESS) |
| { |
| l_result.at(constants::VALUE_0) |= |
| (constants::VALUE_1 << l_bitPosition); |
| } |
| else |
| { |
| l_result.at(constants::VALUE_0) &= |
| ~(constants::VALUE_1 << l_bitPosition); |
| } |
| } |
| else |
| { |
| // single byte update |
| const auto l_enabledValue = |
| std::get<3>(l_biosAttributeEntry).has_value() |
| ? std::get<3>(l_biosAttributeEntry).value() |
| : constants::VALUE_1; |
| |
| const auto l_disabledValue = |
| std::get<4>(l_biosAttributeEntry).has_value() |
| ? std::get<4>(l_biosAttributeEntry).value() |
| : constants::VALUE_0; |
| |
| l_result.emplace_back((l_attrVal->compare("enabled") == |
| constants::STR_CMP_SUCCESS) |
| ? l_enabledValue |
| : l_disabledValue); |
| } |
| } |
| } // BIOS attribute loop end |
| } |
| return l_result; |
| } |
| } // namespace vpd |