1 #pragma once 2 3 #include "const.hpp" 4 #include "store.hpp" 5 6 #include <cstddef> 7 #include <fstream> 8 9 namespace openpower 10 { 11 namespace vpd 12 { 13 namespace parser 14 { 15 namespace keyword 16 { 17 /** @brief Encoding scheme of a VPD keyword's data */ 18 enum class Encoding 19 { 20 ASCII, /**< data encoded in ascii */ 21 RAW, /**< raw data */ 22 // Keywords needing custom decoding 23 B1, /**< The keyword B1 needs to be decoded specially */ 24 MB, /**< Special decoding of MB meant for Build Date */ 25 UD /**< Special decoding of UD meant for UUID */ 26 }; 27 28 } // namespace keyword 29 30 namespace internal 31 { 32 33 using KeywordInfo = std::tuple<record::Keyword, keyword::Encoding>; 34 using OffsetList = std::vector<uint32_t>; 35 using KeywordMap = Parsed::mapped_type; 36 37 } // namespace internal 38 39 /** @class Impl 40 * @brief Implements parser for VPD 41 * 42 * An Impl object must be constructed by passing in VPD in 43 * binary format. To parse the VPD, call the run() method. The run() 44 * method returns an openpower::vpd::Store object, which contains 45 * parsed VPD, and provides access methods for the VPD. 46 * 47 * Following is the algorithm used to parse IPZ/OpenPower VPD: 48 * 1) Validate that the first record is VHDR, the header record. 49 * 2) From the VHDR record, get the offset of the VTOC record, 50 * which is the table of contents record. 51 * 3) Process the VTOC record - note offsets of supported records. 52 * 4) For each supported record : 53 * 4.1) Jump to record via offset. Add record name to parser output. 54 * 4.2) Process record - for each contained and supported keyword: 55 * 4.2.1) Note keyword name and value, associate this information to 56 * to the record noted in step 4.1). 57 */ 58 class Impl 59 { 60 public: 61 Impl() = delete; 62 Impl(const Impl&) = delete; 63 Impl& operator=(const Impl&) = delete; 64 Impl(Impl&&) = delete; 65 Impl& operator=(Impl&&) = delete; 66 ~Impl() = default; 67 68 /** @brief Construct an Impl 69 * 70 * @param[in] vpdBuffer - Binary VPD 71 * @param[in] path - To call out FRU in case of any PEL. 72 * @param[in] vpdFilePath - VPD File Path 73 * @param[in] vpdStartOffset - Start offset of VPD. 74 */ 75 Impl(const Binary& vpdBuffer, const std::string& path, 76 const std::string& vpdFilePath, uint32_t vpdStartOffset) : 77 vpd(vpdBuffer), 78 inventoryPath(path), vpdFilePath(vpdFilePath), 79 vpdStartOffset(vpdStartOffset), out{} 80 { 81 #ifndef ManagerTest 82 vpdFileStream.exceptions(std::ifstream::badbit | 83 std::ifstream::failbit); 84 #endif 85 try 86 { 87 vpdFileStream.open(vpdFilePath, 88 std::ios::in | std::ios::out | std::ios::binary); 89 } 90 catch (const std::fstream::failure& fail) 91 { 92 std::cerr << "Exception in file handling [" << vpdFilePath 93 << "] error : " << fail.what(); 94 throw; 95 } 96 } 97 98 /** @brief Run the parser on binary VPD 99 * 100 * @returns openpower::vpd::Store object 101 */ 102 Store run(); 103 104 /** @brief check if VPD header is valid 105 */ 106 void checkVPDHeader(); 107 108 /** @brief Read a specific VPD keyword from hardware. 109 * This api is to read a specific VPD keyword directly from hardware. 110 * @param[in] record - record name. 111 * @param[in] keyword - keyword name. 112 * @return keyword value. 113 */ 114 std::string readKwFromHw(const std::string& record, 115 const std::string& keyword); 116 117 private: 118 /** @brief Process the table of contents record 119 * 120 * @param[in] iterator - iterator to buffer containing VPD 121 * @returns Size of the PT keyword in VTOC 122 */ 123 std::size_t readTOC(Binary::const_iterator& iterator); 124 125 /** @brief Read the PT keyword contained in the VHDR record, 126 * to obtain offsets to other records in the VPD. 127 * 128 * @param[in] iterator - iterator to buffer containing VPD 129 * @param[in] ptLength - Length of PT keyword data 130 * 131 * @returns List of offsets to records in VPD 132 */ 133 internal::OffsetList readPT(Binary::const_iterator iterator, 134 std::size_t ptLen); 135 136 /** @brief Read VPD information contained within a record 137 * 138 * @param[in] recordOffset - offset to a record location 139 * within the binary VPD 140 */ 141 void processRecord(std::size_t recordOffset); 142 143 /** @brief Read keyword data 144 * 145 * @param[in] keyword - VPD keyword 146 * @param[in] dataLength - Length of data to be read 147 * @param[in] iterator - iterator pointing to a Keyword's data in 148 * the VPD 149 * 150 * @returns keyword data as a string 151 */ 152 std::string readKwData(const internal::KeywordInfo& keyword, 153 std::size_t dataLength, 154 Binary::const_iterator iterator); 155 156 /** @brief While we're pointing at the keyword section of 157 * a record in the VPD, this will read all contained 158 * keywords and their values. 159 * 160 * @param[in] iterator - iterator pointing to a Keyword in the VPD 161 * 162 * @returns map of keyword:data 163 */ 164 internal::KeywordMap readKeywords(Binary::const_iterator iterator); 165 166 /** @brief Checks if the VHDR record is present in the VPD */ 167 void checkHeader(); 168 169 /** @brief Checks the ECC for VHDR Record. 170 * @returns Success(0) OR corrupted data(-1) 171 */ 172 int vhdrEccCheck(); 173 174 /** @brief Checks the ECC for VTOC Record. 175 * @returns Success(0) OR corrupted data(-1) 176 */ 177 int vtocEccCheck(); 178 179 /** @brief Checks the ECC for the given record. 180 * 181 * @param[in] iterator - iterator pointing to a record in the VPD 182 * @returns Success(0) OR corrupted data(-1) 183 */ 184 int recordEccCheck(Binary::const_iterator iterator); 185 186 /** @brief This interface collects Offset of VTOC 187 * @returns VTOC Offset 188 */ 189 openpower::vpd::constants::RecordOffset getVtocOffset() const; 190 191 /** @brief VPD in binary format */ 192 const Binary& vpd; 193 194 /** Inventory path to call out FRU if required */ 195 const std::string inventoryPath; 196 197 /** Eeprom hardware path */ 198 inventory::Path vpdFilePath; 199 200 /** VPD Offset **/ 201 uint32_t vpdStartOffset; 202 203 /** File stream for VPD */ 204 std::fstream vpdFileStream; 205 206 /** @brief parser output */ 207 Parsed out; 208 }; 209 210 } // namespace parser 211 } // namespace vpd 212 } // namespace openpower 213