xref: /openbmc/openpower-vpd-parser/impl.hpp (revision 45d54976)
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      */
Impl(const Binary & vpdBuffer,const std::string & path,const std::string & vpdFilePath,uint32_t vpdStartOffset)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