blob: b41b7b607296c001272b82e5055ca12224a21307 [file] [log] [blame]
#pragma once
#include "logger.hpp"
#include "parser_interface.hpp"
#include "types.hpp"
#include <fstream>
#include <string_view>
namespace vpd
{
/**
* @brief Concrete class to implement IPZ VPD parsing.
*
* The class inherits ParserInterface interface class and overrides the parser
* functionality to implement parsing logic for IPZ VPD format.
*/
class IpzVpdParser : public ParserInterface
{
public:
// Deleted APIs
IpzVpdParser() = delete;
IpzVpdParser(const IpzVpdParser&) = delete;
IpzVpdParser& operator=(const IpzVpdParser&) = delete;
IpzVpdParser(IpzVpdParser&&) = delete;
IpzVpdParser& operator=(IpzVpdParser&&) = delete;
/**
* @brief Constructor.
*
* @param[in] vpdVector - VPD data.
* @param[in] vpdFilePath - Path to VPD EEPROM.
* @param[in] vpdStartOffset - Offset from where VPD starts in the file.
* Defaulted to 0.
*/
IpzVpdParser(const types::BinaryVector& vpdVector,
const std::string& vpdFilePath, size_t vpdStartOffset = 0) :
m_vpdVector(vpdVector), m_vpdFilePath(vpdFilePath),
m_vpdStartOffset(vpdStartOffset)
{
try
{
m_vpdFileStream.exceptions(
std::ifstream::badbit | std::ifstream::failbit);
m_vpdFileStream.open(vpdFilePath, std::ios::in | std::ios::out |
std::ios::binary);
}
catch (const std::fstream::failure& e)
{
logging::logMessage(e.what());
}
}
/**
* @brief Defaul destructor.
*/
~IpzVpdParser() = default;
/**
* @brief API to parse IPZ VPD file.
*
* Note: Caller needs to check validity of the map returned. Throws
* exception in certain situation, needs to be handled accordingly.
*
* @return parsed VPD data.
*/
virtual types::VPDMapVariant parse() override;
/**
* @brief API to check validity of VPD header.
*
* Note: The API throws exception in case of any failure or malformed VDP.
*
* @param[in] itrToVPD - Iterator to the beginning of VPD file.
* Don't change the parameter to reference as movement of passsed iterator
* to an offset is not required after header check.
*/
void checkHeader(types::BinaryVector::const_iterator itrToVPD);
/**
* @brief API to read keyword's value from hardware
*
* @param[in] i_paramsToReadData - Data required to perform read
*
* @throw
* sdbusplus::xyz::openbmc_project::Common::Device::Error::ReadFailure.
*
* @return On success return the value read. On failure throw exception.
*/
types::DbusVariantType readKeywordFromHardware(
const types::ReadVpdParams i_paramsToReadData);
/**
* @brief API to write keyword's value on hardware.
*
* @param[in] i_paramsToWriteData - Data required to perform write.
*
* @throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument.
* @throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed.
* @throw DataException
* @throw EccException
*
*
* @return On success returns number of bytes written on hardware, On
* failure throws exception.
*/
int writeKeywordOnHardware(const types::WriteVpdParams i_paramsToWriteData);
private:
/**
* @brief Check ECC of VPD header.
*
* @return true/false based on check result.
*/
bool vhdrEccCheck();
/**
* @brief Check ECC of VTOC.
*
* @return true/false based on check result.
*/
bool vtocEccCheck();
/**
* @brief Check ECC of a record.
*
* Note: Throws exception in case of failure. Caller need to handle as
* required.
*
* @param[in] iterator - Iterator to the record.
* @return success/failre
*/
bool recordEccCheck(types::BinaryVector::const_iterator iterator);
/**
* @brief API to read VTOC record.
*
* The API reads VTOC record and returns the length of PT keyword.
*
* Note: Throws exception in case of any error. Caller need to handle as
* required.
*
* @param[in] itrToVPD - Iterator to begining of VPD data.
* @return Length of PT keyword.
*/
auto readTOC(types::BinaryVector::const_iterator& itrToVPD);
/**
* @brief API to read PT record.
*
* Note: Throws exception in case ECC check fails.
*
* @param[in] itrToPT - Iterator to PT record in VPD vector.
* @param[in] ptLength - length of the PT record.
* @return List of record's offset.
*/
types::RecordOffsetList readPT(types::BinaryVector::const_iterator& itrToPT,
auto ptLength);
/**
* @brief API to read keyword data based on its encoding type.
*
* @param[in] kwdName - Name of the keyword.
* @param[in] kwdDataLength - Length of keyword data.
* @param[in] itrToKwdData - Iterator to start of keyword data.
* @return keyword data, empty otherwise.
*/
std::string readKwData(std::string_view kwdName, std::size_t kwdDataLength,
types::BinaryVector::const_iterator itrToKwdData);
/**
* @brief API to read keyword and its value under a record.
*
* @param[in] iterator - pointer to the start of keywords under the record.
* @return keyword-value map of keywords under that record.
*/
types::IPZVpdMap::mapped_type readKeywords(
types::BinaryVector::const_iterator& itrToKwds);
/**
* @brief API to process a record.
*
* @param[in] recordOffset - Offset of the record in VPD.
*/
void processRecord(auto recordOffset);
/**
* @brief Get keyword's value from record
*
* @param[in] i_record - Record's name
* @param[in] i_keyword - Keyword's name
* @param[in] i_recordDataOffset - Record's offset value
*
* @throw std::runtime_error
*
* @return On success return bytes read, on failure throws error.
*/
types::BinaryVector getKeywordValueFromRecord(
const types::Record& i_recordName, const types::Keyword& i_keywordName,
const types::RecordOffset& i_recordDataOffset);
/**
* @brief Get record's details from VTOC's PT keyword value
*
* This API parses through VTOC's PT keyword value and returns the given
* record's offset, record's length, ECC offset and ECC length.
*
* @param[in] i_record - Record's name.
* @param[in] i_vtocOffset - Offset to VTOC record
*
* @return On success return record's details, on failure return empty
* buffer.
*/
types::RecordData getRecordDetailsFromVTOC(
const types::Record& l_recordName,
const types::RecordOffset& i_vtocOffset);
/**
* @brief API to update record's ECC
*
* This API is required to update the record's ECC based on the record's
* current data.
*
* @param[in] i_recordDataOffset - Record's data offset
* @param[in] i_recordDataLength - Record's data length
* @param[in] i_recordECCOffset - Record's ECC offset
* @param[in] i_recordECCLength - Record's ECC length
* @param[in,out] io_vpdVector - FRU VPD in vector to update record's ECC.
*
* @throw EccException
*/
void updateRecordECC(const auto& i_recordDataOffset,
const auto& i_recordDataLength,
const auto& i_recordECCOffset,
size_t i_recordECCLength,
types::BinaryVector& io_vpdVector);
/**
* @brief API to set record's keyword's value on hardware.
*
* @param[in] i_recordName - Record name.
* @param[in] i_keywordName - Keyword name.
* @param[in] i_keywordData - Keyword data.
* @param[in] i_recordDataOffset - Offset to record's data.
* @param[in,out] io_vpdVector - FRU VPD in vector to read and write
* keyword's value.
*
* @throw DataException
*
* @return On success returns number of bytes set. On failure returns -1.
*/
int setKeywordValueInRecord(const types::Record& i_recordName,
const types::Keyword& i_keywordName,
const types::BinaryVector& i_keywordData,
const types::RecordOffset& i_recordDataOffset,
types::BinaryVector& io_vpdVector);
// Holds VPD data.
const types::BinaryVector& m_vpdVector;
// stores parsed VPD data.
types::IPZVpdMap m_parsedVPDMap{};
// Holds the VPD file path
const std::string& m_vpdFilePath;
// Stream to the VPD file. Required to correct ECC
std::fstream m_vpdFileStream;
// VPD start offset. Required for ECC correction.
size_t m_vpdStartOffset = 0;
};
} // namespace vpd