#pragma once #include "const.hpp" #include "store.hpp" #include #include namespace openpower { namespace vpd { namespace parser { namespace keyword { /** @brief Encoding scheme of a VPD keyword's data */ enum class Encoding { ASCII, /**< data encoded in ascii */ RAW, /**< raw data */ // Keywords needing custom decoding B1, /**< The keyword B1 needs to be decoded specially */ MB, /**< Special decoding of MB meant for Build Date */ UD /**< Special decoding of UD meant for UUID */ }; } // namespace keyword namespace internal { using KeywordInfo = std::tuple; using OffsetList = std::vector; using KeywordMap = Parsed::mapped_type; } // namespace internal /** @class Impl * @brief Implements parser for VPD * * An Impl object must be constructed by passing in VPD in * binary format. To parse the VPD, call the run() method. The run() * method returns an openpower::vpd::Store object, which contains * parsed VPD, and provides access methods for the VPD. * * Following is the algorithm used to parse IPZ/OpenPower VPD: * 1) Validate that the first record is VHDR, the header record. * 2) From the VHDR record, get the offset of the VTOC record, * which is the table of contents record. * 3) Process the VTOC record - note offsets of supported records. * 4) For each supported record : * 4.1) Jump to record via offset. Add record name to parser output. * 4.2) Process record - for each contained and supported keyword: * 4.2.1) Note keyword name and value, associate this information to * to the record noted in step 4.1). */ class Impl { public: Impl() = delete; Impl(const Impl&) = delete; Impl& operator=(const Impl&) = delete; Impl(Impl&&) = delete; Impl& operator=(Impl&&) = delete; ~Impl() = default; /** @brief Construct an Impl * * @param[in] vpdBuffer - Binary VPD * @param[in] path - To call out FRU in case of any PEL. * @param[in] vpdFilePath - VPD File Path * @param[in] vpdStartOffset - Start offset of VPD. */ Impl(const Binary& vpdBuffer, const std::string& path, const std::string& vpdFilePath, uint32_t vpdStartOffset) : vpd(vpdBuffer), inventoryPath(path), vpdFilePath(vpdFilePath), vpdStartOffset(vpdStartOffset), out{} { #ifndef ManagerTest vpdFileStream.exceptions(std::ifstream::badbit | std::ifstream::failbit); #endif try { vpdFileStream.open(vpdFilePath, std::ios::in | std::ios::out | std::ios::binary); } catch (const std::fstream::failure& fail) { std::cerr << "Exception in file handling [" << vpdFilePath << "] error : " << fail.what(); throw; } } /** @brief Run the parser on binary VPD * * @returns openpower::vpd::Store object */ Store run(); /** @brief check if VPD header is valid */ void checkVPDHeader(); /** @brief Read a specific VPD keyword from hardware. * This api is to read a specific VPD keyword directly from hardware. * @param[in] record - record name. * @param[in] keyword - keyword name. * @return keyword value. */ std::string readKwFromHw(const std::string& record, const std::string& keyword); private: /** @brief Process the table of contents record * * @param[in] iterator - iterator to buffer containing VPD * @returns Size of the PT keyword in VTOC */ std::size_t readTOC(Binary::const_iterator& iterator); /** @brief Read the PT keyword contained in the VHDR record, * to obtain offsets to other records in the VPD. * * @param[in] iterator - iterator to buffer containing VPD * @param[in] ptLength - Length of PT keyword data * * @returns List of offsets to records in VPD */ internal::OffsetList readPT(Binary::const_iterator iterator, std::size_t ptLen); /** @brief Read VPD information contained within a record * * @param[in] recordOffset - offset to a record location * within the binary VPD */ void processRecord(std::size_t recordOffset); /** @brief Read keyword data * * @param[in] keyword - VPD keyword * @param[in] dataLength - Length of data to be read * @param[in] iterator - iterator pointing to a Keyword's data in * the VPD * * @returns keyword data as a string */ std::string readKwData(const internal::KeywordInfo& keyword, std::size_t dataLength, Binary::const_iterator iterator); /** @brief While we're pointing at the keyword section of * a record in the VPD, this will read all contained * keywords and their values. * * @param[in] iterator - iterator pointing to a Keyword in the VPD * * @returns map of keyword:data */ internal::KeywordMap readKeywords(Binary::const_iterator iterator); /** @brief Checks if the VHDR record is present in the VPD */ void checkHeader(); /** @brief Checks the ECC for VHDR Record. * @returns Success(0) OR corrupted data(-1) */ int vhdrEccCheck(); /** @brief Checks the ECC for VTOC Record. * @returns Success(0) OR corrupted data(-1) */ int vtocEccCheck(); /** @brief Checks the ECC for the given record. * * @param[in] iterator - iterator pointing to a record in the VPD * @returns Success(0) OR corrupted data(-1) */ int recordEccCheck(Binary::const_iterator iterator); /** @brief This interface collects Offset of VTOC * @returns VTOC Offset */ openpower::vpd::constants::RecordOffset getVtocOffset() const; /** @brief VPD in binary format */ const Binary& vpd; /** Inventory path to call out FRU if required */ const std::string inventoryPath; /** Eeprom hardware path */ inventory::Path vpdFilePath; /** VPD Offset **/ uint32_t vpdStartOffset; /** File stream for VPD */ std::fstream vpdFileStream; /** @brief parser output */ Parsed out; }; } // namespace parser } // namespace vpd } // namespace openpower