diff options
author | Deepak Kodihalli <dkodihal@in.ibm.com> | 2016-11-22 22:02:14 -0600 |
---|---|---|
committer | Deepak Kodihalli <dkodihal@in.ibm.com> | 2016-12-08 06:14:37 -0600 |
commit | 023112f485be11b6c4d93dee32e195f143335130 (patch) | |
tree | 6441449d262f462c97077464ee907519d36ea08a | |
parent | 810c9defd7cd473d3eef14f177c6a24d6500fae1 (diff) | |
download | openpower-vpd-parser-023112f485be11b6c4d93dee32e195f143335130.tar.gz openpower-vpd-parser-023112f485be11b6c4d93dee32e195f143335130.zip |
parser : read table of contents record
This change implements logic to read the OpenPOWER VPD VTOC record,
which contains information about offsets to other records in the VPD.
Change-Id: Id40dee0f940815766bf2e956c6ab08c875e6f79b
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
-rw-r--r-- | impl.cpp | 93 | ||||
-rw-r--r-- | impl.hpp | 25 |
2 files changed, 117 insertions, 1 deletions
@@ -10,12 +10,28 @@ namespace vpd namespace parser { +namespace +{ + +using RecordId = uint8_t; +using RecordOffset = uint16_t; +using RecordSize = uint16_t; +using RecordType = uint16_t; +using RecordLength = uint16_t; +using KwSize = uint8_t; +using ECCOffset = uint16_t; +using ECCLength = uint16_t; + +} + namespace offsets { enum Offsets { - VHDR = 17 + VHDR = 17, + VHDR_TOC_ENTRY = 29, + VTOC_PTR = 35, }; } @@ -26,6 +42,7 @@ namespace lengths enum Lengths { RECORD_NAME = 4, + KW_NAME = 2, RECORD_MIN = 44, }; @@ -50,6 +67,80 @@ void Impl::checkHeader() const } } +internal::OffsetList Impl::readTOC() const +{ + internal::OffsetList offsets {}; + + // The offset to VTOC could be 1 or 2 bytes long + RecordOffset vtocOffset = vpd.at(offsets::VTOC_PTR); + RecordOffset highByte = vpd.at(offsets::VTOC_PTR + 1); + vtocOffset |= (highByte << 8); + + // Got the offset to VTOC, skip past record header and keyword header + // to get to the record name. + auto iterator = vpd.cbegin(); + std::advance(iterator, + vtocOffset + + sizeof(RecordId) + + sizeof(RecordSize) + + // Skip past the RT keyword, which contains + // the record name. + lengths::KW_NAME + + sizeof(KwSize)); + + auto stop = std::next(iterator, lengths::RECORD_NAME); + std::string record(iterator, stop); + if ("VTOC" != record) + { + throw std::runtime_error("VTOC record not found"); + } + + // VTOC record name is good, now read through the TOC, stored in the PT + // PT keyword; vpdBuffer is now pointing at the first character of the + // name 'VTOC', jump to PT data. + // Skip past record name and KW name, 'PT' + std::advance(iterator, lengths::RECORD_NAME + lengths::KW_NAME); + // Note size of PT + std::size_t ptLen = *iterator; + // Skip past PT size + std::advance(iterator, sizeof(KwSize)); + + // vpdBuffer is now pointing to PT data + return readPT(iterator, ptLen); +} + +internal::OffsetList Impl::readPT(Binary::const_iterator iterator, + std::size_t ptLength) const +{ + internal::OffsetList offsets{}; + + auto end = iterator; + std::advance(end, ptLength); + + // Look at each entry in the PT keyword. In the entry, + // we care only about the record offset information. + while (iterator < end) + { + // Skip record name and record type + std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType)); + + // Get record offset + RecordOffset offset = *iterator; + RecordOffset highByte = *(iterator + 1); + offset |= (highByte << 8); + offsets.push_back(offset); + + // Jump record size, record length, ECC offset and ECC length + std::advance(iterator, + sizeof(RecordSize) + + sizeof(RecordLength) + + sizeof(ECCOffset) + + sizeof(ECCLength)); + } + + return offsets; +} + } // namespace parser } // namespace vpd } // namespace openpower @@ -1,5 +1,6 @@ #pragma once +#include <cstddef> #include "store.hpp" namespace openpower @@ -9,6 +10,13 @@ namespace vpd namespace parser { +namespace internal +{ + +using OffsetList = std::vector<uint32_t>; + +} + /** @class Impl * @brief Implements parser for OpenPOWER VPD * @@ -54,6 +62,23 @@ class Impl Store run(); private: + /** @brief Process the table of contents record, VHDR + * + * @returns List of offsets to records in VPD + */ + internal::OffsetList readTOC() const; + + /** @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) const; + /** @brief Checks if the VHDR record is present in the VPD */ void checkHeader() const; |