Skip to content

Commit

Permalink
Keyword VPD: Update keyword on Dbus
Browse files Browse the repository at this point in the history
Keyword's value gets updated on D-bus irrespective of verifying the keyword size.

For example, For a 4 byte keyword, if user gives more than 4 bytes of data to
update, hardware update will accept only 4 bytes but D-bus update will accept
every extra byte given by the user. This will create a mismatch between hardware
and D-bus.

So to avoid such mismatches we came up with the design of updating the keyword's
value in hardware first ( which takes care of size checks) and copy the same
in other sources. With this approach we maintain the reliability of keyword
updates across all other sources.

This commit implements the portion where we read the keyword's value from hardware
(assuming the hardware write is already done from Manager class) and write the same
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 <priyanga24@in.ibm.com>
  • Loading branch information
PriyangaRamasamy committed Nov 18, 2024
1 parent d4d8f48 commit 4b744f2
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 4b744f2

Please sign in to comment.