xref: /openbmc/openpower-vpd-parser/vpd-manager/include/ipz_parser.hpp (revision 43fedabc032ba7c209b58111b6c35c7d95a9f14e)
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