blob: 61100e9d34ca0e28be1a8e9440bfd00101d84ed1 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#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
10namespace 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 */
18class 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 */
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 */
Patrick Williams43fedab2025-02-03 14:28:05 -050090 types::DbusVariantType readKeywordFromHardware(
91 const types::ReadVpdParams i_paramsToReadData);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050092
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.
Souvik Roy612bce82025-04-16 02:22:33 -0500155 * @return Pair of list of record's offset and a list of invalid
156 * records found during parsing
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500157 */
Souvik Roy612bce82025-04-16 02:22:33 -0500158 std::pair<types::RecordOffsetList, types::InvalidRecordList> readPT(
159 types::BinaryVector::const_iterator& itrToPT, auto ptLength);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500160
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 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500178 types::IPZVpdMap::mapped_type readKeywords(
179 types::BinaryVector::const_iterator& itrToKwds);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500180
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 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500215 types::RecordData getRecordDetailsFromVTOC(
216 const types::Record& l_recordName,
217 const types::RecordOffset& i_vtocOffset);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500218
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
Souvik Roy612bce82025-04-16 02:22:33 -0500259 /**
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
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500273 // 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