1 #pragma once
2 
3 #include "const.hpp"
4 #include "types.hpp"
5 
6 #include <nlohmann/json.hpp>
7 
8 #include <cstddef>
9 #include <fstream>
10 #include <tuple>
11 
12 namespace openpower
13 {
14 namespace vpd
15 {
16 namespace manager
17 {
18 namespace editor
19 {
20 
21 /** @class EditorImpl */
22 class EditorImpl
23 {
24   public:
25     EditorImpl() = delete;
26     EditorImpl(const EditorImpl&) = delete;
27     EditorImpl& operator=(const EditorImpl&) = delete;
28     EditorImpl(EditorImpl&&) = delete;
29     EditorImpl& operator=(EditorImpl&&) = delete;
~EditorImpl()30     ~EditorImpl() {}
31 
32     /** @brief Construct EditorImpl class
33      *
34      *  @param[in] record - Record Name
35      *  @param[in] kwd - Keyword
36      *  @param[in] vpd - Vpd Vector
37      */
EditorImpl(const std::string & record,const std::string & kwd,Binary && vpd)38     EditorImpl(const std::string& record, const std::string& kwd,
39                Binary&& vpd) :
40         startOffset(0),
41         thisRecord(record, kwd), vpdFile(std::move(vpd))
42     {}
43 
44     /** @brief Construct EditorImpl class
45      *
46      *  @param[in] path - Path to the vpd file
47      *  @param[in] json - Parsed inventory json
48      *  @param[in] record - Record name
49      *  @param[in] kwd - Keyword
50      *  @param[in] inventoryPath - Inventory path of the vpd
51      */
EditorImpl(const inventory::Path & path,const nlohmann::json & json,const std::string & record,const std::string & kwd,const sdbusplus::message::object_path & inventoryPath)52     EditorImpl(const inventory::Path& path, const nlohmann::json& json,
53                const std::string& record, const std::string& kwd,
54                const sdbusplus::message::object_path& inventoryPath) :
55         vpdFilePath(path),
56         objPath(inventoryPath), startOffset(0), jsonFile(json),
57         thisRecord(record, kwd)
58     {}
59 
60     /** @brief Construct EditorImpl class
61      *
62      * @param[in] path - EEPROM path
63      * @param[in] json - Parsed inventory json object
64      * @param[in] record - Record name
65      * @param[in] kwd - Keyword name
66      */
EditorImpl(const inventory::Path & path,const nlohmann::json & json,const std::string & record,const std::string & kwd)67     EditorImpl(const inventory::Path& path, const nlohmann::json& json,
68                const std::string& record, const std::string& kwd) :
69         vpdFilePath(path),
70         jsonFile(json), thisRecord(record, kwd)
71     {}
72 
73     /**
74      * @brief Update data for keyword
75      * The method looks for the record name to update in VTOC and then
76      * looks for the keyword name in that record. when found it updates the data
77      * of keyword with the given data. It does not block keyword data update in
78      * case the length of new data is greater than or less than the current data
79      * length. If the new data length is more than the length allotted to that
80      * keyword the new data will be truncated to update only the allotted
81      * length. Similarly if the new data length is less then only that much data
82      * will be updated for the keyword and remaining bits will be left
83      * unchanged.
84      *
85      * Following is the algorithm used to update keyword:
86      * 1) Look for the record name in the given VPD file
87      * 2) Look for the keyword name for which data needs to be updated
88      *    which is the table of contents record.
89      * 3) update the data for that keyword with the new data
90      *
91      * @param[in] kwdData - data to update
92      * @param[in] offset - offset at which the VPD starts
93      * @param[in] updCache - Flag which tells whether to update Cache or not.
94      */
95     void updateKeyword(const Binary& kwdData, uint32_t offset,
96                        const bool& updCache);
97 
98     /** @brief Expands location code on DBUS
99      *  @param[in] locationCodeType - "fcs" or "mts"
100      */
101     void expandLocationCode(const std::string& locationCodeType);
102 
103   private:
104     /** @brief read VTOC record from the vpd file
105      */
106     void readVTOC();
107 
108     /** @brief validate ecc data for the VTOC record
109      *  @param[in] itrToRecData -iterator to the record data
110      *  @param[in] itrToECCData - iterator to the ECC data
111      *  @param[in] recLength - Length of the record
112      *  @param[in] eccLength - Length of the record's ECC
113      */
114     void checkECC(Binary::const_iterator& itrToRecData,
115                   Binary::const_iterator& itrToECCData,
116                   openpower::vpd::constants::RecordLength recLength,
117                   openpower::vpd::constants::ECCLength eccLength);
118 
119     /** @brief reads value at the given offset
120      *  @param[in] offset - offset value
121      *  @return  value at that offset in bigendian
122      */
123     auto getValue(openpower::vpd::constants::offsets::Offsets offset);
124 
125     /** @brief Checks if required record name exist in the VPD file
126      *  @param[in] iterator - pointing to start of PT kwd
127      *  @param[in] ptLength - length of the PT kwd
128      */
129     void checkPTForRecord(Binary::const_iterator& iterator, Byte ptLength);
130 
131     /** @brief Checks for required keyword in the record */
132     void checkRecordForKwd();
133 
134     /** @brief update data for given keyword
135      *  @param[in] kwdData- data to be updated
136      */
137     void updateData(const Binary& kwdData);
138 
139     /** @brief update record ECC */
140     void updateRecordECC();
141 
142     /** @brief method to update cache once the data for keyword has been updated
143      */
144     void updateCache();
145 
146     /** @brief method to process and update CI in case required
147      *  @param[in] - objectPath - path of the object to introspect
148      */
149     void processAndUpdateCI(const std::string& objectPath);
150 
151     /** @brief method to process and update extra interface
152      *  @param[in] Inventory - single inventory json subpart
153      *  @param[in] objPath - path of the object to introspect
154      */
155     void processAndUpdateEI(const nlohmann::json& Inventory,
156                             const inventory::Path& objPath);
157 
158     /** @brief method to make busctl call
159      *
160      *  @param[in] object - bus object path
161      *  @param[in] interface - bus interface
162      *  @param[in] property - property to update on BUS
163      *  @param[in] data - data to be updated on Bus
164      *
165      */
166     template <typename T>
167     void makeDbusCall(const std::string& object, const std::string& interface,
168                       const std::string& property, const std::variant<T>& data);
169 
170     /** @brief Method to check the record's Data using ECC */
171     void checkRecordData();
172 
173     // path to the VPD file to edit
174     inventory::Path vpdFilePath;
175 
176     // inventory path of the vpd fru to update keyword
177     inventory::Path objPath{};
178 
179     // stream to perform operation on file
180     std::fstream vpdFileStream;
181 
182     // stream to operate on VPD data
183     std::fstream vpdDataFileStream;
184 
185     // offset to get vpd data from EEPROM
186     uint32_t startOffset;
187 
188     // file to store parsed json
189     const nlohmann::json jsonFile;
190 
191     // structure to hold info about record to edit
192     struct RecInfo
193     {
194         Binary kwdUpdatedData; // need access to it in case encoding is needed
195         const std::string recName;
196         const std::string recKWd;
197         openpower::vpd::constants::RecordOffset recOffset;
198         openpower::vpd::constants::ECCOffset recECCoffset;
199         std::size_t recECCLength;
200         std::size_t kwdDataLength;
201         openpower::vpd::constants::RecordSize recSize;
202         openpower::vpd::constants::DataOffset kwDataOffset;
203         // constructor
RecInfoopenpower::vpd::manager::editor::EditorImpl::RecInfo204         RecInfo(const std::string& rec, const std::string& kwd) :
205             recName(rec), recKWd(kwd), recOffset(0), recECCoffset(0),
206             recECCLength(0), kwdDataLength(0), recSize(0), kwDataOffset(0)
207         {}
208     } thisRecord;
209 
210     Binary vpdFile;
211 
212     // If requested Interface is common Interface
213     bool isCI;
214 }; // class EditorImpl
215 
216 } // namespace editor
217 } // namespace manager
218 } // namespace vpd
219 } // namespace openpower
220