Skip to content

Commit

Permalink
Keyword VPD: Update keyword on Dbus
Browse files Browse the repository at this point in the history
This commit has implementation to read keyword from hardware
and write on D-bus.

Test:
busctl call com.ibm.VPD.Manager /com/ibm/VPD/Manager com.ibm.VPD.Manager  ReadKeyword sv "/tmp/keyword.dat" s "SN"
v ay 12 89 72 51 48 66 71 55 56 66 48 49 52

Change-Id: I60d7a2b418ad5e451e46f288bde3477794145ec0
Signed-off-by: Priyanga Ramasamy <[email protected]>
  • Loading branch information
PriyangaRamasamy committed Nov 18, 2024
1 parent d4d8f48 commit 3322dd8
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 0 deletions.
26 changes: 26 additions & 0 deletions include/keyword_vpd_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ class KeywordVpdParser : public ParserInterface
*/
types::VPDMapVariant parse();

/**
* @brief API to read keyword's value from hardware
*
* @param[in] i_paramsToReadData - Data required to perform read
*
* @throw
* sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument
*
* @return On success return the value read. On failure throw exception.
*/
types::DbusVariantType
readKeywordFromHardware(const types::ReadVpdParams i_paramsToReadData);

private:
/**
* @brief Parse the VPD data and emplace them as pair into the Map.
Expand Down Expand Up @@ -88,6 +101,19 @@ class KeywordVpdParser : public ParserInterface
*/
void checkNextBytesValidity(uint8_t numberOfBytes);

/**
* @brief API to iterate through the VPD vector to find the given keyword.
*
* This API iterates through VPD vector using m_vpdIterator and finds the
* given keyword. m_vpdIterator points to the keyword name if find is
* successful.
*
* @param[in] i_keyword - Keyword name.
*
* @return 0 On successful find, -1 on failure.
*/
int findKeyword(const std::string& i_keyword);

/*Vector of keyword VPD data*/
const types::BinaryVector& m_keywordVpdVector;

Expand Down
93 changes: 93 additions & 0 deletions src/keyword_vpd_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,97 @@ void KeywordVpdParser::checkNextBytesValidity(uint8_t i_numberOfBytes)
}
}

types::DbusVariantType KeywordVpdParser::readKeywordFromHardware(
const types::ReadVpdParams i_paramsToReadData)
{
types::Keyword l_keyword;

if (const types::Keyword* l_kwData =
std::get_if<types::Keyword>(&i_paramsToReadData))
{
l_keyword = *l_kwData;
}
else
{
logging::logMessage("Given VPD type is not supported.");
throw types::DbusInvalidArgument();
}

if (l_keyword.empty())
{
logging::logMessage("Given an empty keyword name.");
throw types::DbusInvalidArgument();
}

// Iterate through VPD vector to find the keyword
if (findKeyword(l_keyword) != 0)
{
logging::logMessage("Keyword " + l_keyword + " not found.");
throw types::DbusInvalidArgument();
}

// Skip bytes representing the keyword name
std::advance(m_vpdIterator, constants::TWO_BYTES);

// Get size of the keyword
const auto l_keywordSize = *m_vpdIterator;

// Skip bytes representing the size of the keyword
std::advance(m_vpdIterator, constants::ONE_BYTE);

// Read the keyword's value and return
return types::DbusVariantType{types::BinaryVector(
m_vpdIterator, std::ranges::next(m_vpdIterator, l_keywordSize,
m_keywordVpdVector.cend()))};
}

int KeywordVpdParser::findKeyword(const std::string& i_keyword)
{
m_vpdIterator = m_keywordVpdVector.begin();

// Skip Keyword VPD's start tag
std::advance(m_vpdIterator, sizeof(constants::KW_VPD_START_TAG));

// Get size of the header
uint16_t l_dataSize = getKwDataSize();

// Skip bytes which represents the size of header + Skip header data
std::advance(m_vpdIterator, constants::TWO_BYTES + l_dataSize);

// Skip Keyword VPD pair's start tag
std::advance(m_vpdIterator, constants::ONE_BYTE);

// Get total size of keyword value pairs
auto l_totalSize = getKwDataSize();

if (l_totalSize <= 0)
{
// Keyword not found
return -1;
}

// Skip bytes which represents the total size of kw-value pairs
std::advance(m_vpdIterator, constants::TWO_BYTES);

while (l_totalSize > 0)
{
// Get keyword name
std::string l_keywordName(m_vpdIterator,
m_vpdIterator + constants::TWO_BYTES);

if (l_keywordName == i_keyword)
{
// Keyword successfully found
return 0;
}
std::advance(m_vpdIterator, constants::TWO_BYTES);
size_t l_kwSize = *m_vpdIterator;

std::advance(m_vpdIterator, constants::ONE_BYTE + l_kwSize);
l_totalSize -= constants::TWO_BYTES + constants::ONE_BYTE + l_kwSize;
}

// Keyword not found
return -1;
}
} // namespace vpd
28 changes: 28 additions & 0 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,34 @@ int Parser::updateVpdKeyword(const types::WriteVpdParams& i_paramsToWriteData)
return -1;
}
}
else if (const types::KwData* l_kwData =
std::get_if<types::KwData>(&i_paramsToWriteData))
{
l_interfaceName = constants::kwdVpdInf;
l_propertyName = std::get<0>(*l_kwData);

try
{
// Read keyword's value from hardware to write the same on
// D-bus.
std::shared_ptr<ParserInterface> l_vpdParserInstance =
getVpdParserInstance();
logging::logMessage("Performing VPD read on " + m_vpdFilePath);
l_keywordValue = l_vpdParserInstance->readKeywordFromHardware(
types::ReadVpdParams(l_propertyName));
}
catch (const std::exception& l_exception)
{
// Unable to read keyword's value from hardware.
logging::logMessage(
"Error while reading keyword's value from hadware path " +
m_vpdFilePath +
", error: " + std::string(l_exception.what()));

// TODO: Log PEL
return -1;
}
}
else
{
// Input parameter type provided isn't compatible to perform update.
Expand Down

0 comments on commit 3322dd8

Please sign in to comment.