1 #pragma once 2 3 #include "logger.hpp" 4 #include "parser_interface.hpp" 5 #include "types.hpp" 6 7 #include <fstream> 8 #include <string_view> 9 10 namespace vpd 11 { 12 /** 13 * @brief Concrete class to implement IPZ VPD parsing. 14 * 15 * The class inherits ParserInterface interface class and overrides the parser 16 * functionality to implement parsing logic for IPZ VPD format. 17 */ 18 class IpzVpdParser : public ParserInterface 19 { 20 public: 21 // Deleted APIs 22 IpzVpdParser() = delete; 23 IpzVpdParser(const IpzVpdParser&) = delete; 24 IpzVpdParser& operator=(const IpzVpdParser&) = delete; 25 IpzVpdParser(IpzVpdParser&&) = delete; 26 IpzVpdParser& operator=(IpzVpdParser&&) = delete; 27 28 /** 29 * @brief Constructor. 30 * 31 * @param[in] vpdVector - VPD data. 32 * @param[in] vpdFilePath - Path to VPD EEPROM. 33 * @param[in] vpdStartOffset - Offset from where VPD starts in the file. 34 * Defaulted to 0. 35 */ IpzVpdParser(const types::BinaryVector & vpdVector,const std::string & vpdFilePath,size_t vpdStartOffset=0)36 IpzVpdParser(const types::BinaryVector& vpdVector, 37 const std::string& vpdFilePath, size_t vpdStartOffset = 0) : 38 m_vpdVector(vpdVector), m_vpdFilePath(vpdFilePath), 39 m_vpdStartOffset(vpdStartOffset) 40 { 41 try 42 { 43 m_vpdFileStream.exceptions( 44 std::ifstream::badbit | std::ifstream::failbit); 45 m_vpdFileStream.open(vpdFilePath, std::ios::in | std::ios::out | 46 std::ios::binary); 47 } 48 catch (const std::fstream::failure& e) 49 { 50 logging::logMessage(e.what()); 51 } 52 } 53 54 /** 55 * @brief Defaul destructor. 56 */ 57 ~IpzVpdParser() = default; 58 59 /** 60 * @brief API to parse IPZ VPD file. 61 * 62 * Note: Caller needs to check validity of the map returned. Throws 63 * exception in certain situation, needs to be handled accordingly. 64 * 65 * @return parsed VPD data. 66 */ 67 virtual types::VPDMapVariant parse() override; 68 69 /** 70 * @brief API to check validity of VPD header. 71 * 72 * Note: The API throws exception in case of any failure or malformed VDP. 73 * 74 * @param[in] itrToVPD - Iterator to the beginning of VPD file. 75 * Don't change the parameter to reference as movement of passsed iterator 76 * to an offset is not required after header check. 77 */ 78 void checkHeader(types::BinaryVector::const_iterator itrToVPD); 79 80 /** 81 * @brief API to read keyword's value from hardware 82 * 83 * @param[in] i_paramsToReadData - Data required to perform read 84 * 85 * @throw 86 * sdbusplus::xyz::openbmc_project::Common::Device::Error::ReadFailure. 87 * 88 * @return On success return the value read. On failure throw exception. 89 */ 90 types::DbusVariantType readKeywordFromHardware( 91 const types::ReadVpdParams i_paramsToReadData); 92 93 /** 94 * @brief API to write keyword's value on hardware. 95 * 96 * @param[in] i_paramsToWriteData - Data required to perform write. 97 * 98 * @throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument. 99 * @throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed. 100 * @throw DataException 101 * @throw EccException 102 * 103 * 104 * @return On success returns number of bytes written on hardware, On 105 * failure throws exception. 106 */ 107 int writeKeywordOnHardware(const types::WriteVpdParams i_paramsToWriteData); 108 109 private: 110 /** 111 * @brief Check ECC of VPD header. 112 * 113 * @return true/false based on check result. 114 */ 115 bool vhdrEccCheck(); 116 117 /** 118 * @brief Check ECC of VTOC. 119 * 120 * @return true/false based on check result. 121 */ 122 bool vtocEccCheck(); 123 124 /** 125 * @brief Check ECC of a record. 126 * 127 * Note: Throws exception in case of failure. Caller need to handle as 128 * required. 129 * 130 * @param[in] iterator - Iterator to the record. 131 * @return success/failre 132 */ 133 bool recordEccCheck(types::BinaryVector::const_iterator iterator); 134 135 /** 136 * @brief API to read VTOC record. 137 * 138 * The API reads VTOC record and returns the length of PT keyword. 139 * 140 * Note: Throws exception in case of any error. Caller need to handle as 141 * required. 142 * 143 * @param[in] itrToVPD - Iterator to begining of VPD data. 144 * @return Length of PT keyword. 145 */ 146 auto readTOC(types::BinaryVector::const_iterator& itrToVPD); 147 148 /** 149 * @brief API to read PT record. 150 * 151 * Note: Throws exception in case ECC check fails. 152 * 153 * @param[in] itrToPT - Iterator to PT record in VPD vector. 154 * @param[in] ptLength - length of the PT record. 155 * @return List of record's offset. 156 */ 157 types::RecordOffsetList readPT(types::BinaryVector::const_iterator& itrToPT, 158 auto ptLength); 159 160 /** 161 * @brief API to read keyword data based on its encoding type. 162 * 163 * @param[in] kwdName - Name of the keyword. 164 * @param[in] kwdDataLength - Length of keyword data. 165 * @param[in] itrToKwdData - Iterator to start of keyword data. 166 * @return keyword data, empty otherwise. 167 */ 168 std::string readKwData(std::string_view kwdName, std::size_t kwdDataLength, 169 types::BinaryVector::const_iterator itrToKwdData); 170 171 /** 172 * @brief API to read keyword and its value under a record. 173 * 174 * @param[in] iterator - pointer to the start of keywords under the record. 175 * @return keyword-value map of keywords under that record. 176 */ 177 types::IPZVpdMap::mapped_type readKeywords( 178 types::BinaryVector::const_iterator& itrToKwds); 179 180 /** 181 * @brief API to process a record. 182 * 183 * @param[in] recordOffset - Offset of the record in VPD. 184 */ 185 void processRecord(auto recordOffset); 186 187 /** 188 * @brief Get keyword's value from record 189 * 190 * @param[in] i_record - Record's name 191 * @param[in] i_keyword - Keyword's name 192 * @param[in] i_recordDataOffset - Record's offset value 193 * 194 * @throw std::runtime_error 195 * 196 * @return On success return bytes read, on failure throws error. 197 */ 198 types::BinaryVector getKeywordValueFromRecord( 199 const types::Record& i_recordName, const types::Keyword& i_keywordName, 200 const types::RecordOffset& i_recordDataOffset); 201 202 /** 203 * @brief Get record's details from VTOC's PT keyword value 204 * 205 * This API parses through VTOC's PT keyword value and returns the given 206 * record's offset, record's length, ECC offset and ECC length. 207 * 208 * @param[in] i_record - Record's name. 209 * @param[in] i_vtocOffset - Offset to VTOC record 210 * 211 * @return On success return record's details, on failure return empty 212 * buffer. 213 */ 214 types::RecordData getRecordDetailsFromVTOC( 215 const types::Record& l_recordName, 216 const types::RecordOffset& i_vtocOffset); 217 218 /** 219 * @brief API to update record's ECC 220 * 221 * This API is required to update the record's ECC based on the record's 222 * current data. 223 * 224 * @param[in] i_recordDataOffset - Record's data offset 225 * @param[in] i_recordDataLength - Record's data length 226 * @param[in] i_recordECCOffset - Record's ECC offset 227 * @param[in] i_recordECCLength - Record's ECC length 228 * @param[in,out] io_vpdVector - FRU VPD in vector to update record's ECC. 229 * 230 * @throw EccException 231 */ 232 void updateRecordECC(const auto& i_recordDataOffset, 233 const auto& i_recordDataLength, 234 const auto& i_recordECCOffset, 235 size_t i_recordECCLength, 236 types::BinaryVector& io_vpdVector); 237 238 /** 239 * @brief API to set record's keyword's value on hardware. 240 * 241 * @param[in] i_recordName - Record name. 242 * @param[in] i_keywordName - Keyword name. 243 * @param[in] i_keywordData - Keyword data. 244 * @param[in] i_recordDataOffset - Offset to record's data. 245 * @param[in,out] io_vpdVector - FRU VPD in vector to read and write 246 * keyword's value. 247 * 248 * @throw DataException 249 * 250 * @return On success returns number of bytes set. On failure returns -1. 251 */ 252 int setKeywordValueInRecord(const types::Record& i_recordName, 253 const types::Keyword& i_keywordName, 254 const types::BinaryVector& i_keywordData, 255 const types::RecordOffset& i_recordDataOffset, 256 types::BinaryVector& io_vpdVector); 257 258 // Holds VPD data. 259 const types::BinaryVector& m_vpdVector; 260 261 // stores parsed VPD data. 262 types::IPZVpdMap m_parsedVPDMap{}; 263 264 // Holds the VPD file path 265 const std::string& m_vpdFilePath; 266 267 // Stream to the VPD file. Required to correct ECC 268 std::fstream m_vpdFileStream; 269 270 // VPD start offset. Required for ECC correction. 271 size_t m_vpdStartOffset = 0; 272 }; 273 } // namespace vpd 274