diff --git a/include/keyword_vpd_parser.hpp b/include/keyword_vpd_parser.hpp index ae30a34c..038ba05f 100644 --- a/include/keyword_vpd_parser.hpp +++ b/include/keyword_vpd_parser.hpp @@ -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. @@ -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; diff --git a/src/keyword_vpd_parser.cpp b/src/keyword_vpd_parser.cpp index 0e0181f5..14f19dc6 100644 --- a/src/keyword_vpd_parser.cpp +++ b/src/keyword_vpd_parser.cpp @@ -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(&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 diff --git a/src/parser.cpp b/src/parser.cpp index ce45ef20..b146acde 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -116,6 +116,34 @@ int Parser::updateVpdKeyword(const types::WriteVpdParams& i_paramsToWriteData) return -1; } } + else if (const types::KwData* l_kwData = + std::get_if(&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 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.