blob: d53a5939a5edc922193e0e3ec96c62feb54715dc [file] [log] [blame]
#include "vpd_tool_impl.hpp"
#include <CLI/CLI.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
using namespace CLI;
using namespace std;
namespace fs = std::filesystem;
using namespace openpower::vpd;
using json = nlohmann::json;
int main(int argc, char** argv)
{
int rc = 0;
App app{"VPD Command line tool to dump the inventory and to read and "
"update the keywords"};
string objectPath{};
string recordName{};
string keyword{};
string val{};
uint32_t offset = 0;
auto object =
app.add_option("--object, -O", objectPath, "Enter the Object Path");
auto record =
app.add_option("--record, -R", recordName, "Enter the Record Name");
auto kw = app.add_option("--keyword, -K", keyword, "Enter the Keyword");
auto valOption = app.add_option(
"--value, -V", val,
"Enter the value. The value to be updated should be either in ascii or "
"in hex. ascii eg: 01234; hex eg: 0x30313233");
app.add_option("--seek, -s", offset,
"User can provide VPD offset using this option. Default "
"offset value is 0. Using --seek is optional and is valid "
"only while using --Hardware/-H option.");
auto dumpObjFlag =
app.add_flag("--dumpObject, -o",
"Dump the given object from the inventory. { "
"vpd-tool-exe --dumpObject/-o --object/-O object-name }")
->needs(object);
auto dumpInvFlag = app.add_flag(
"--dumpInventory, -i", "Dump all the inventory objects. { vpd-tool-exe "
"--dumpInventory/-i }");
auto readFlag =
app.add_flag("--readKeyword, -r",
"Read the data of the given keyword. { "
"vpd-tool-exe --readKeyword/-r --object/-O "
"\"object-name\" --record/-R \"record-name\" --keyword/-K "
"\"keyword-name\" }")
->needs(object)
->needs(record)
->needs(kw);
auto writeFlag =
app.add_flag(
"--writeKeyword, -w, --updateKeyword, -u",
"Update the value. { vpd-tool-exe "
"--writeKeyword/-w/--updateKeyword/-u "
"--object/-O object-name --record/-R record-name --keyword/-K "
"keyword-name --value/-V (or) --file }. Value can be given "
"directly via console using --value or via file using --file")
->needs(object)
->needs(record)
->needs(kw);
auto fileOption = app.add_option(
"--file", val,
"Enter the file name with its absolute path. This option can be used "
"in read and write operations. When used in read, the read value will "
"be saved to this file and when used in write, the value to be written "
"will be taken from this file.");
auto forceResetFlag =
app.add_flag("--forceReset, -f, -F",
"Force Collect for Hardware. CAUTION: Developer Only "
"Option. { vpd-tool-exe --forceReset/-f/-F }");
auto Hardware = app.add_flag(
"--Hardware, -H",
"This is a supplementary flag to read/write directly from/to hardware. "
"User should provide valid hardware/eeprom path (and not dbus object "
"path) in the -O/--object path. CAUTION: Developer Only Option");
auto fixSystemVPDFlag = app.add_flag(
"--fixSystemVPD", "Use this option to interactively fix critical "
"system VPD keywords {vpd-tool-exe --fixSystemVPD}");
auto mfgClean =
app.add_flag("--mfgClean", "Flag to clean and reset specific keywords "
"on system VPD to its default value.");
auto confirm =
app.add_flag("--yes", "Using this flag with --mfgClean option, assumes "
"yes to proceed without confirmation.");
CLI11_PARSE(app, argc, argv);
ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
auto jsObject = json::parse(inventoryJson);
try
{
if (*object && objectPath.empty())
{
throw runtime_error("Given path is empty.");
}
if (*record && (recordName.size() != 4))
{
throw runtime_error("Record " + recordName + " not supported.");
}
if ((*kw) && (keyword.size() != 2))
{
throw runtime_error("Keyword " + keyword + " not supported.");
}
if (*Hardware)
{
if (!fs::exists(objectPath)) // if dbus object path is given or
// invalid eeprom path is given
{
string errorMsg = "Invalid EEPROM path : ";
errorMsg += objectPath;
errorMsg +=
". The given EEPROM path doesn't exist. Provide valid "
"EEPROM path when -H flag is used. Refer help option. ";
throw runtime_error(errorMsg);
}
}
if (*writeFlag)
{
if (isReadOnlyEEPROM(objectPath, jsObject))
{
throw runtime_error("Read only EEPROM. Update not allowed.");
}
if ((!*fileOption) && (!*valOption))
{
throw runtime_error("Please provide the data that needs to be "
"updated. Use --value/--file to "
"input data. Refer --help.");
}
if ((*fileOption) && (!fs::exists(val)))
{
throw runtime_error("Please provide a valid file with absolute "
"path in --file.");
}
}
if (*dumpObjFlag)
{
VpdTool vpdToolObj(move(objectPath));
vpdToolObj.dumpObject(jsObject);
}
else if (*dumpInvFlag)
{
VpdTool vpdToolObj;
vpdToolObj.dumpInventory(jsObject);
}
else if (*readFlag && !*Hardware)
{
VpdTool vpdToolObj(move(objectPath), move(recordName),
move(keyword), move(val));
vpdToolObj.readKeyword();
}
else if (*writeFlag && !*Hardware)
{
VpdTool vpdToolObj(move(objectPath), move(recordName),
move(keyword), move(val));
rc = vpdToolObj.updateKeyword();
}
else if (*forceResetFlag)
{
// Force reset the BMC only if the CEC is powered OFF.
if (getPowerState() ==
"xyz.openbmc_project.State.Chassis.PowerState.Off")
{
VpdTool vpdToolObj;
vpdToolObj.forceReset(jsObject);
}
else
{
std::cerr << "The chassis power state is not Off. Force reset "
"operation is not allowed.";
return -1;
}
}
else if (*writeFlag && *Hardware)
{
VpdTool vpdToolObj(move(objectPath), move(recordName),
move(keyword), move(val));
rc = vpdToolObj.updateHardware(offset);
}
else if (*readFlag && *Hardware)
{
VpdTool vpdToolObj(move(objectPath), move(recordName),
move(keyword), move(val));
vpdToolObj.readKwFromHw(offset);
}
else if (*fixSystemVPDFlag)
{
std::string backupEepromPath;
std::string backupInvPath;
findBackupVPDPaths(backupEepromPath, backupInvPath, jsObject);
VpdTool vpdToolObj;
if (backupEepromPath.empty())
{
rc = vpdToolObj.fixSystemVPD();
}
else
{
rc = vpdToolObj.fixSystemBackupVPD(backupEepromPath,
backupInvPath);
}
}
else if (*mfgClean)
{
if (!*confirm)
{
std::string confirmation{};
std::cout << "\nThis option resets some of the system VPD "
"keywords to their default values. Do you really "
"wish to proceed further?[yes/no]: ";
std::cin >> confirmation;
if (confirmation != "yes")
{
return 0;
}
}
VpdTool vpdToolObj;
rc = vpdToolObj.cleanSystemVPD();
}
else
{
throw runtime_error("One of the valid options is required. Refer "
"--help for list of options.");
}
}
catch (const exception& e)
{
cerr << e.what();
rc = -1;
}
return rc;
}