Skip to content

Commit

Permalink
vpd-tool: writeKeyword API implementation
Browse files Browse the repository at this point in the history
This commit implements VpdTool class writeKeyword API, which send Dbus
request to vpd-manager Dbus service, who hosts the writeKeyword
interface to update keyword's value.

Whether the user gives Dbus object path or hardware path internally
both primary and backup paths gets updated.

Testing:
Tested for both DBus object path and EEPROM path’s, observed that
keyword’s values get updated in both primary and secondary paths.

Signed-off-by: Anupama B R <[email protected]>
  • Loading branch information
branupama committed Dec 9, 2024
1 parent 1e2faf8 commit 4792c1c
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 3 deletions.
8 changes: 8 additions & 0 deletions vpd-tool/include/tool_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,13 @@ using IpzType = std::tuple<std::string, std::string>;
//ReadVpdParams either of IPZ or keyword format
using ReadVpdParams = std::variant<IpzType, std::string>;

//KwData contains tuple of <keywordName, KeywordValue>
using KwData = std::tuple<std::string, BinaryVector>;

//IpzData contains tuple of <RecordName, KeywordName, KeywordValue>
using IpzData = std::tuple<std::string, std::string, BinaryVector>;

//WriteVpdParams either of IPZ or keyword format
using WriteVpdParams = std::variant<IpzData, KwData>;
} // namespace types
} // namespace vpd
89 changes: 89 additions & 0 deletions vpd-tool/include/tool_utils.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "tool_constants.hpp"
#include "tool_types.hpp"

#include <nlohmann/json.hpp>
Expand Down Expand Up @@ -170,5 +171,93 @@ inline types::DbusVariantType
throw;
}
}

/**
* @brief API to write keyword's value.
*
* This API writes keyword's value by requesting DBus service(vpd-manager) who
* hosts the 'WriteKeyword' interface to update keyword's value.
*
* @param[in] i_vpdPath - EEPROM or object path, where keyword is present.
* @param[in] i_paramsToWriteData - Data required to update keyword's value.
*
* @return - Number of bytes written on success, -1 on failure.
*
* @throw - std::runtime_error, sdbusplus::exception::SdBusError
*/
inline int writeKeyword(const std::string& i_vpdPath,
const types::WriteVpdParams i_paramsToWriteData)
{
if (i_vpdPath.empty())
{
throw std::runtime_error("Empty path");
}

try
{
int l_rc = constants::FAILURE;
auto l_bus = sdbusplus::bus::new_default();

auto l_method = l_bus.new_method_call(
constants::vpdManagerService, constants::vpdManagerObjectPath,
constants::vpdManagerInfName, "WriteKeyword");

l_method.append(i_vpdPath, i_paramsToWriteData);
auto l_result = l_bus.call(l_method);

l_result.read(l_rc);

if (l_rc > 0)
{
std::cout << "Data updated successfully " << std::endl;
}
return l_rc;
}
catch (const sdbusplus::exception::SdBusError& l_error)
{
throw;
}
}

inline types::BinaryVector convertToBinary(const std::string& i_value)
{
std::vector<uint8_t> l_binaryValue{};

if (i_value.substr(0, 2).compare("0x") == 0)
{
auto l_value = i_value.substr(2);

if (l_value.empty())
{
throw std::runtime_error(
"Provide a valid hexadecimal input. (Ex. 0x30313233)");
}

if (l_value.length() % 2 != 0)
{
throw std::runtime_error(
"Write option accepts 2 digit hex numbers. (Ex. 0x1 "
"should be given as 0x01).");
}

if (l_value.find_first_not_of("0123456789abcdefABCDEF") !=
std::string::npos)
{
throw std::runtime_error("Provide a valid hexadecimal input.");
}

for (size_t l_pos = 0; l_pos < l_value.length(); l_pos += 2)
{
uint8_t l_byte = static_cast<uint8_t>(
std::stoi(l_value.substr(l_pos, 2), nullptr, 16));
l_binaryValue.push_back(l_byte);
}
}
else
{
l_binaryValue.assign(i_value.begin(), i_value.end());
}
return l_binaryValue;
}
} // namespace utils
} // namespace vpd
26 changes: 26 additions & 0 deletions vpd-tool/include/vpd_tool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,31 @@ class VpdTool
const std::string& i_recordName,
const std::string& i_keywordName, const bool i_onHardware,
const std::string& i_fileToSave = {});

/**
* @brief Write keyword's value.
*
* API to update VPD keyword's value to the given input path.
* If i_onHardware value in true, i_fruPath is considered has hardware path
* otherwise it will be considered as DBus object path.
*
* Regardless of given input path is primary path or secondary path,
* internally both paths will get updated with new keyword's value.
*
* @param[in] i_vpdPath - DBus object path or EEPROM path.
* @param[in] i_recordName - Record name.
* @param[in] i_keywordName - Keyword name.
* @param[in] i_keywordValue - Keyword value.
* @param[in] i_onHardware - True if i_vpdPath is EEPROM path, false
* otherwise.
* @param[in] i_filePath - File path to take keyword's value.
*
* @return On success return 0, otherwise return -1.
*/
int writeKeyword(const std::string& i_vpdPath,
const std::string& i_recordName,
const std::string& i_keywordName,
const std::string& i_keywordValue, const bool i_onHardware,
const std::string& i_filePath = {});
};
} // namespace vpd
44 changes: 44 additions & 0 deletions vpd-tool/src/vpd_tool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "tool_utils.hpp"

#include <iostream>
#include <tuple>

namespace vpd
{
Expand Down Expand Up @@ -74,4 +75,47 @@ int VpdTool::readKeyword(const std::string& i_vpdPath,
}
return l_rc;
}

int VpdTool::writeKeyword(const std::string& i_vpdPath,
const std::string& i_recordName,
const std::string& i_keywordName,
const std::string& i_keywordValue,
const bool i_onHardware,
const std::string& i_filePath)
{
int l_rc = constants::FAILURE;
try
{
if (i_vpdPath.empty() || i_recordName.empty() || i_keywordName.empty())
{
throw std::runtime_error("Received input is empty.");
}

if (!i_filePath.empty())
{
// ToDo: Take keyword value from the file
}

std::string l_vpdPath{i_vpdPath};
if (!i_onHardware)
{
l_vpdPath = constants::baseInventoryPath + i_vpdPath;
}

auto l_paramsToWrite =
std::make_tuple(i_recordName, i_keywordName,
utils::convertToBinary(i_keywordValue));

l_rc = utils::writeKeyword(l_vpdPath, l_paramsToWrite);
}
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;
}
} // namespace vpd
9 changes: 6 additions & 3 deletions vpd-tool/src/vpd_tool_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ int main(int argc, char** argv)
->needs(l_recordOption)
->needs(l_keywordOption);

// ToDo: Take offset value from user for hardware path.

CLI11_PARSE(l_app, argc, argv);

if (!l_objectOption->empty() && l_vpdPath.empty())
Expand Down Expand Up @@ -176,7 +174,12 @@ int main(int argc, char** argv)
return l_rc;
}

// ToDo: implementation of write keyword
bool l_isHardwareOperation = (l_hardwareFlag->empty() ? false : true);

vpd::VpdTool l_vpdToolObj;
l_vpdToolObj.writeKeyword(l_vpdPath, l_recordName, l_keywordName,
l_keywordValue, l_isHardwareOperation,
l_filePath);
}
else
{
Expand Down

0 comments on commit 4792c1c

Please sign in to comment.