blob: 4dde248389fbaccdac484468cd3803dd63186342 [file] [log] [blame]
#include "tool_constants.hpp"
#include "tool_utils.hpp"
#include "vpd_tool.hpp"
#include <CLI/CLI.hpp>
#include <filesystem>
#include <iostream>
/**
* @brief Resets the VPD on DBus for all the Frus.
*
* API clears the inventory persisted data and restarts the phosphor inventory
* manager(PIM) DBus service and the VPD manager service. VPD manager service
* collects the VPD for all the FRU's listed on the system config JSON and calls
* PIM to publish VPD on DBus.
*
* Note: Force reset only happens if chassis is powered off.
*
* @return On success returns 0, otherwise returns -1.
*/
int forceReset()
{
if (vpd::utils::isChassisPowerOff())
{
vpd::VpdTool l_vpdToolObj;
return l_vpdToolObj.resetVpdOnDbus();
}
std::cerr
<< "The chassis power state is not Off. Force reset operation is not allowed."
<< std::endl;
return vpd::constants::FAILURE;
}
/**
* @brief API to perform manufacturing clean.
*
* @param[in] i_mfgCleanConfirmFlag - Confirmation flag to perform manufacturing
* clean.
* @param[in] i_syncBiosAttributesFlag - Flag which specifies whether
* BIOS attribute related keywords need to be synced from BIOS Config Manager
* instead of being reset to default value.
*
* @return Status returned by cleanSystemVpd operation, success otherwise.
*/
int doMfgClean(const auto& i_mfgCleanConfirmFlag,
const auto& i_syncBiosAttributesFlag)
{
if (i_mfgCleanConfirmFlag->empty())
{
constexpr auto MAX_CONFIRMATION_STR_LENGTH{3};
std::string l_confirmation{};
std::cout
<< "This option resets some of the system VPD keywords to their default values. Do you really wish to proceed further?[yes/no]:";
std::cin >> std::setw(MAX_CONFIRMATION_STR_LENGTH) >> l_confirmation;
if (l_confirmation != "yes")
{
return vpd::constants::SUCCESS;
}
}
vpd::VpdTool l_vpdToolObj;
return l_vpdToolObj.cleanSystemVpd(!i_syncBiosAttributesFlag->empty());
}
/**
* @brief API to write keyword's value.
*
* @param[in] i_hardwareFlag - Flag to perform write on hardware.
* @param[in] i_keywordValueOption - Option to read keyword value from command.
* @param[in] i_vpdPath - DBus object path or EEPROM path.
* @param[in] i_recordName - Record to be updated.
* @param[in] i_keywordName - Keyword to be updated.
* @param[in] i_keywordValue - Value to be updated in keyword.
*
* @return Status of writeKeyword operation, failure otherwise.
*/
int writeKeyword(const auto& i_hardwareFlag, const auto& i_keywordValueOption,
const std::string& i_vpdPath, const std::string& i_recordName,
const std::string& i_keywordName,
const std::string& i_keywordValue)
{
std::error_code l_ec;
if (!i_hardwareFlag->empty() && !std::filesystem::exists(i_vpdPath, l_ec))
{
std::cerr << "Given EEPROM file path doesn't exist : " + i_vpdPath
<< std::endl;
return vpd::constants::FAILURE;
}
if (l_ec)
{
std::cerr << "filesystem call exists failed for file: " << i_vpdPath
<< ", reason: " + l_ec.message() << std::endl;
return vpd::constants::FAILURE;
}
if (!i_keywordValueOption->empty() && i_keywordValue.empty())
{
std::cerr
<< "Please provide keyword value.\nUse --value/--file to give "
"keyword value. Refer --help."
<< std::endl;
return vpd::constants::FAILURE;
}
if (i_keywordValueOption->empty())
{
std::cerr
<< "Please provide keyword value.\nUse --value/--file to give "
"keyword value. Refer --help."
<< std::endl;
return vpd::constants::FAILURE;
}
vpd::VpdTool l_vpdToolObj;
return l_vpdToolObj.writeKeyword(i_vpdPath, i_recordName, i_keywordName,
i_keywordValue, !i_hardwareFlag->empty());
}
/**
* @brief API to read keyword's value.
*
* @param[in] i_hardwareFlag - Flag to perform write on hardware.
* @param[in] i_vpdPath - DBus object path or EEPROM path.
* @param[in] i_recordName - Record to be updated.
* @param[in] i_keywordName - Keyword to be updated.
* @param[in] i_filePath - File path to save keyword's read value.
*
* @return On success return 0, otherwise return -1.
*/
int readKeyword(const auto& i_hardwareFlag, const std::string& i_vpdPath,
const std::string& i_recordName,
const std::string& i_keywordName, const std::string& i_filePath)
{
std::error_code l_ec;
if (!i_hardwareFlag->empty() && !std::filesystem::exists(i_vpdPath, l_ec))
{
std::string l_errMessage{
"Given EEPROM file path doesn't exist : " + i_vpdPath};
if (l_ec)
{
l_errMessage += ". filesystem call exists failed, reason: " +
l_ec.message();
}
std::cerr << l_errMessage << std::endl;
return vpd::constants::FAILURE;
}
bool l_isHardwareOperation = (!i_hardwareFlag->empty() ? true : false);
vpd::VpdTool l_vpdToolObj;
return l_vpdToolObj.readKeyword(i_vpdPath, i_recordName, i_keywordName,
l_isHardwareOperation, i_filePath);
}
/**
* @brief API to check option value pair in the tool command.
*
* In VPD tool command, some of the option(s) mandate values to be passed along
* with the option. This API based on option, detects those mandatory value(s).
*
* @param[in] i_objectOption - Option to pass object path.
* @param[in] i_vpdPath - Object path, DBus or EEPROM.
* @param[in] i_recordOption - Option to pass record name.
* @param[in] i_recordName - Record name.
* @param[in] i_keywordOption - Option to pass keyword name.
* @param[in] i_keywordName - Keyword name.
* @param[in] i_fileOption - Option to pass file path.
* @param[in] i_filePath - File path.
*
* @return Success if corresponding value is found against option, failure
* otherwise.
*/
int checkOptionValuePair(const auto& i_objectOption, const auto& i_vpdPath,
const auto& i_recordOption, const auto& i_recordName,
const auto& i_keywordOption, const auto& i_keywordName,
const auto& i_fileOption, const auto& i_filePath)
{
if (!i_objectOption->empty() && i_vpdPath.empty())
{
std::cout << "Given path is empty." << std::endl;
return vpd::constants::FAILURE;
}
if (!i_recordOption->empty() &&
(i_recordName.size() != vpd::constants::RECORD_SIZE))
{
std::cerr << "Record " << i_recordName << " is not supported."
<< std::endl;
return vpd::constants::FAILURE;
}
if (!i_keywordOption->empty() &&
(i_keywordName.size() != vpd::constants::KEYWORD_SIZE))
{
std::cerr << "Keyword " << i_keywordName << " is not supported."
<< std::endl;
return vpd::constants::FAILURE;
}
if (!i_fileOption->empty() && i_filePath.empty())
{
std::cout << "File path is empty." << std::endl;
return vpd::constants::FAILURE;
}
return vpd::constants::SUCCESS;
}
/**
* @brief API to create app footer.
*
* @param[in] i_app - CLI::App object.
*/
void updateFooter(CLI::App& i_app)
{
i_app.footer(
"Read:\n"
" IPZ Format:\n"
" From DBus to console: "
"vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name>\n"
" From DBus to file: "
"vpd-tool -r -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
" From hardware to console: "
"vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name>\n"
" From hardware to file: "
"vpd-tool -r -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
"Write:\n"
" IPZ Format:\n"
" On DBus: "
"vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
" On DBus, take keyword value from file:\n"
" vpd-tool -w/-u -O <DBus Object Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
" On hardware: "
"vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> -V <Keyword Value>\n"
" On hardware, take keyword value from file:\n"
" vpd-tool -w/-u -H -O <EEPROM Path> -R <Record Name> -K <Keyword Name> --file <File Path>\n"
"Dump Object:\n"
" From DBus to console: "
"vpd-tool -o -O <DBus Object Path>\n"
"Fix System VPD:\n"
" vpd-tool --fixSystemVPD\n"
"MfgClean:\n"
" Flag to clean and reset specific keywords on system VPD to its default value.\n"
" vpd-tool --mfgClean\n"
" To sync BIOS attribute related keywords with BIOS Config Manager:\n"
" vpd-tool --mfgClean --syncBiosAttributes\n"
"Dump Inventory:\n"
" From DBus to console in JSON format: "
"vpd-tool -i\n"
" From DBus to console in Table format: "
"vpd-tool -i -t\n"
"Force Reset:\n"
" vpd-tool --forceReset\n");
}
int main(int argc, char** argv)
{
CLI::App l_app{"VPD Command Line Tool"};
std::string l_vpdPath{};
std::string l_recordName{};
std::string l_keywordName{};
std::string l_filePath{};
std::string l_keywordValue{};
updateFooter(l_app);
auto l_objectOption =
l_app.add_option("--object, -O", l_vpdPath, "File path");
auto l_recordOption =
l_app.add_option("--record, -R", l_recordName, "Record name");
auto l_keywordOption =
l_app.add_option("--keyword, -K", l_keywordName, "Keyword name");
auto l_fileOption =
l_app.add_option("--file", l_filePath, "Absolute file path");
auto l_keywordValueOption =
l_app.add_option("--value, -V", l_keywordValue,
"Keyword value in ascii/hex format."
" ascii ex: 01234; hex ex: 0x30313233");
auto l_hardwareFlag =
l_app.add_flag("--Hardware, -H", "CAUTION: Developer only option.");
auto l_readFlag = l_app.add_flag("--readKeyword, -r", "Read keyword")
->needs(l_objectOption)
->needs(l_recordOption)
->needs(l_keywordOption);
auto l_writeFlag =
l_app
.add_flag(
"--writeKeyword, -w,--updateKeyword, -u",
"Write keyword, Note: Irrespective of DBus or hardware path provided, primary and backup, redundant EEPROM(if any) paths will get updated with given key value")
->needs(l_objectOption)
->needs(l_recordOption)
->needs(l_keywordOption);
// ToDo: Take offset value from user for hardware path.
auto l_dumpObjFlag =
l_app
.add_flag("--dumpObject, -o",
"Dump specific properties of an inventory object")
->needs(l_objectOption);
auto l_fixSystemVpdFlag = l_app.add_flag(
"--fixSystemVPD",
"Use this option to interactively fix critical system VPD keywords");
auto l_dumpInventoryFlag =
l_app.add_flag("--dumpInventory, -i", "Dump all the inventory objects");
auto l_mfgCleanFlag = l_app.add_flag(
"--mfgClean", "Manufacturing clean on system VPD keyword");
auto l_mfgCleanConfirmFlag = l_app.add_flag(
"--yes", "Using this flag with --mfgClean option, assumes "
"yes to proceed without confirmation.");
auto l_dumpInventoryTableFlag =
l_app.add_flag("--table, -t", "Dump inventory in table format");
auto l_mfgCleanSyncBiosAttributesFlag = l_app.add_flag(
"--syncBiosAttributes, -s",
"Using this flag with --mfgClean option, Syncs the BIOS attribute related keywords from BIOS Config Manager service instead resetting keyword's value to default value");
auto l_forceResetFlag = l_app.add_flag(
"--forceReset, -f, -F",
"Force collect for hardware. CAUTION: Developer only option.");
CLI11_PARSE(l_app, argc, argv);
if (checkOptionValuePair(l_objectOption, l_vpdPath, l_recordOption,
l_recordName, l_keywordOption, l_keywordName,
l_fileOption, l_filePath) ==
vpd::constants::FAILURE)
{
return vpd::constants::FAILURE;
}
if (!l_readFlag->empty())
{
return readKeyword(l_hardwareFlag, l_vpdPath, l_recordName,
l_keywordName, l_filePath);
}
if (!l_writeFlag->empty())
{
if ((l_keywordValueOption->empty() && l_fileOption->empty()) ||
(!l_keywordValueOption->empty() && !l_fileOption->empty()))
{
std::cerr
<< "Please provide keyword value.\nUse --value/--file to give "
"keyword value. Refer --help."
<< std::endl;
return vpd::constants::FAILURE;
}
if (!l_fileOption->empty())
{
l_keywordValue = vpd::utils::readValueFromFile(l_filePath);
if (l_keywordValue.empty())
{
return vpd::constants::FAILURE;
}
return writeKeyword(l_hardwareFlag, l_fileOption, l_vpdPath,
l_recordName, l_keywordName, l_keywordValue);
}
return writeKeyword(l_hardwareFlag, l_keywordValueOption, l_vpdPath,
l_recordName, l_keywordName, l_keywordValue);
}
if (!l_dumpObjFlag->empty())
{
vpd::VpdTool l_vpdToolObj;
return l_vpdToolObj.dumpObject(l_vpdPath);
}
if (!l_fixSystemVpdFlag->empty())
{
vpd::VpdTool l_vpdToolObj;
return l_vpdToolObj.fixSystemVpd();
}
if (!l_mfgCleanFlag->empty())
{
return doMfgClean(l_mfgCleanConfirmFlag,
l_mfgCleanSyncBiosAttributesFlag);
}
if (!l_dumpInventoryFlag->empty())
{
vpd::VpdTool l_vpdToolObj;
return l_vpdToolObj.dumpInventory(!l_dumpInventoryTableFlag->empty());
}
if (!l_forceResetFlag->empty())
{
return forceReset();
}
std::cout << l_app.help() << std::endl;
return vpd::constants::FAILURE;
}