1 #pragma once 2 3 #include "store.hpp" 4 5 #include <cstddef> 6 7 namespace openpower 8 { 9 namespace vpd 10 { 11 namespace parser 12 { 13 namespace keyword 14 { 15 16 /** @brief Encoding scheme of a VPD keyword's data */ 17 enum class Encoding 18 { 19 ASCII, /**< data encoded in ascii */ 20 RAW, /**< raw data */ 21 // Keywords needing custom decoding 22 B1, /**< The keyword B1 needs to be decoded specially */ 23 MB, /**< Special decoding of MB meant for Build Date */ 24 UD /**< Special decoding of UD meant for UUID */ 25 }; 26 27 } // namespace keyword 28 29 namespace internal 30 { 31 32 using KeywordInfo = std::tuple<record::Keyword, keyword::Encoding>; 33 using OffsetList = std::vector<uint32_t>; 34 using KeywordMap = Parsed::mapped_type; 35 36 } // namespace internal 37 38 /** @class Impl 39 * @brief Implements parser for VPD 40 * 41 * An Impl object must be constructed by passing in VPD in 42 * binary format. To parse the VPD, call the run() method. The run() 43 * method returns an openpower::vpd::Store object, which contains 44 * parsed VPD, and provides access methods for the VPD. 45 * 46 * Following is the algorithm used to parse IPZ/OpenPower VPD: 47 * 1) Validate that the first record is VHDR, the header record. 48 * 2) From the VHDR record, get the offset of the VTOC record, 49 * which is the table of contents record. 50 * 3) Process the VTOC record - note offsets of supported records. 51 * 4) For each supported record : 52 * 4.1) Jump to record via offset. Add record name to parser output. 53 * 4.2) Process record - for each contained and supported keyword: 54 * 4.2.1) Note keyword name and value, associate this information to 55 * to the record noted in step 4.1). 56 */ 57 class Impl 58 { 59 public: 60 Impl() = delete; 61 Impl(const Impl&) = delete; 62 Impl& operator=(const Impl&) = delete; 63 Impl(Impl&&) = delete; 64 Impl& operator=(Impl&&) = delete; 65 ~Impl() = default; 66 67 /** @brief Construct an Impl 68 * 69 * @param[in] vpdBuffer - Binary VPD 70 */ 71 explicit Impl(Binary&& vpdBuffer) : vpd(std::move(vpdBuffer)), out{} 72 { 73 } 74 75 /** @brief Run the parser on binary VPD 76 * 77 * @returns openpower::vpd::Store object 78 */ 79 Store run(); 80 81 private: 82 /** @brief Process the table of contents record, VHDR 83 * 84 * @returns List of offsets to records in VPD 85 */ 86 internal::OffsetList readTOC() const; 87 88 /** @brief Read the PT keyword contained in the VHDR record, 89 * to obtain offsets to other records in the VPD. 90 * 91 * @param[in] iterator - iterator to buffer containing VPD 92 * @param[in] ptLength - Length of PT keyword data 93 * 94 * @returns List of offsets to records in VPD 95 */ 96 internal::OffsetList readPT(Binary::const_iterator iterator, 97 std::size_t ptLen) const; 98 99 /** @brief Read VPD information contained within a record 100 * 101 * @param[in] recordOffset - offset to a record location 102 * within the binary VPD 103 */ 104 void processRecord(std::size_t recordOffset); 105 106 /** @brief Read keyword data 107 * 108 * @param[in] keyword - VPD keyword 109 * @param[in] dataLength - Length of data to be read 110 * @param[in] iterator - iterator pointing to a Keyword's data in 111 * the VPD 112 * 113 * @returns keyword data as a string 114 */ 115 std::string readKwData(const internal::KeywordInfo& keyword, 116 std::size_t dataLength, 117 Binary::const_iterator iterator); 118 119 /** @brief While we're pointing at the keyword section of 120 * a record in the VPD, this will read all contained 121 * keywords and their values. 122 * 123 * @param[in] iterator - iterator pointing to a Keyword in the VPD 124 * 125 * @returns map of keyword:data 126 */ 127 internal::KeywordMap readKeywords(Binary::const_iterator iterator); 128 129 /** @brief Checks if the VHDR record is present in the VPD */ 130 void checkHeader() const; 131 132 /** @brief VPD in binary format */ 133 Binary vpd; 134 135 /** @brief parser output */ 136 Parsed out; 137 }; 138 139 } // namespace parser 140 } // namespace vpd 141 } // namespace openpower 142