xref: /openbmc/openpower-vpd-parser/vpd-manager/include/ipz_parser.hpp (revision 612bce854fc0d212bc79e35aba1058450c04fdc3)
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 Pair of list of record's offset and a list of invalid
156      * records found during parsing
157      */
158     std::pair<types::RecordOffsetList, types::InvalidRecordList> readPT(
159         types::BinaryVector::const_iterator& itrToPT, auto ptLength);
160 
161     /**
162      * @brief API to read keyword data based on its encoding type.
163      *
164      * @param[in] kwdName - Name of the keyword.
165      * @param[in] kwdDataLength - Length of keyword data.
166      * @param[in] itrToKwdData - Iterator to start of keyword data.
167      * @return keyword data, empty otherwise.
168      */
169     std::string readKwData(std::string_view kwdName, std::size_t kwdDataLength,
170                            types::BinaryVector::const_iterator itrToKwdData);
171 
172     /**
173      * @brief API to read keyword and its value under a record.
174      *
175      * @param[in] iterator - pointer to the start of keywords under the record.
176      * @return keyword-value map of keywords under that record.
177      */
178     types::IPZVpdMap::mapped_type readKeywords(
179         types::BinaryVector::const_iterator& itrToKwds);
180 
181     /**
182      * @brief API to process a record.
183      *
184      * @param[in] recordOffset - Offset of the record in VPD.
185      */
186     void processRecord(auto recordOffset);
187 
188     /**
189      * @brief Get keyword's value from record
190      *
191      * @param[in] i_record - Record's name
192      * @param[in] i_keyword - Keyword's name
193      * @param[in] i_recordDataOffset - Record's offset value
194      *
195      * @throw std::runtime_error
196      *
197      * @return On success return bytes read, on failure throws error.
198      */
199     types::BinaryVector getKeywordValueFromRecord(
200         const types::Record& i_recordName, const types::Keyword& i_keywordName,
201         const types::RecordOffset& i_recordDataOffset);
202 
203     /**
204      * @brief Get record's details from VTOC's PT keyword value
205      *
206      * This API parses through VTOC's PT keyword value and returns the given
207      * record's offset, record's length, ECC offset and ECC length.
208      *
209      * @param[in] i_record - Record's name.
210      * @param[in] i_vtocOffset - Offset to VTOC record
211      *
212      * @return On success return record's details, on failure return empty
213      * buffer.
214      */
215     types::RecordData getRecordDetailsFromVTOC(
216         const types::Record& l_recordName,
217         const types::RecordOffset& i_vtocOffset);
218 
219     /**
220      * @brief API to update record's ECC
221      *
222      * This API is required to update the record's ECC based on the record's
223      * current data.
224      *
225      * @param[in] i_recordDataOffset - Record's data offset
226      * @param[in] i_recordDataLength - Record's data length
227      * @param[in] i_recordECCOffset - Record's ECC offset
228      * @param[in] i_recordECCLength - Record's ECC length
229      * @param[in,out] io_vpdVector - FRU VPD in vector to update record's ECC.
230      *
231      * @throw EccException
232      */
233     void updateRecordECC(const auto& i_recordDataOffset,
234                          const auto& i_recordDataLength,
235                          const auto& i_recordECCOffset,
236                          size_t i_recordECCLength,
237                          types::BinaryVector& io_vpdVector);
238 
239     /**
240      * @brief API to set record's keyword's value on hardware.
241      *
242      * @param[in] i_recordName - Record name.
243      * @param[in] i_keywordName - Keyword name.
244      * @param[in] i_keywordData - Keyword data.
245      * @param[in] i_recordDataOffset - Offset to record's data.
246      * @param[in,out] io_vpdVector - FRU VPD in vector to read and write
247      * keyword's value.
248      *
249      * @throw DataException
250      *
251      * @return On success returns number of bytes set. On failure returns -1.
252      */
253     int setKeywordValueInRecord(const types::Record& i_recordName,
254                                 const types::Keyword& i_keywordName,
255                                 const types::BinaryVector& i_keywordData,
256                                 const types::RecordOffset& i_recordDataOffset,
257                                 types::BinaryVector& io_vpdVector);
258 
259     /**
260      * @brief API to process list of invalid records found during parsing
261      *
262      * This API takes a list of invalid records found while parsing a given
263      * EEPROM, logs a predictive PEL with details about the invalid records and
264      * then dumps the EEPROM data to filesystem.
265      *
266      * @param[in] i_invalidRecordList - a list of invalid records
267      *
268      * @return On success returns true, false otherwise.
269      */
270     bool processInvalidRecords(
271         const types::InvalidRecordList& i_invalidRecordList) const noexcept;
272 
273     // Holds VPD data.
274     const types::BinaryVector& m_vpdVector;
275 
276     // stores parsed VPD data.
277     types::IPZVpdMap m_parsedVPDMap{};
278 
279     // Holds the VPD file path
280     const std::string& m_vpdFilePath;
281 
282     // Stream to the VPD file. Required to correct ECC
283     std::fstream m_vpdFileStream;
284 
285     // VPD start offset. Required for ECC correction.
286     size_t m_vpdStartOffset = 0;
287 };
288 } // namespace vpd
289