blob: 280ba3bba675dd00ffbf466cbaa9759f8f12f5b4 [file] [log] [blame]
#pragma once
#include "const.hpp"
#include "store.hpp"
#include <cstddef>
#include <fstream>
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<record::Keyword, keyword::Encoding>;
using OffsetList = std::vector<uint32_t>;
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