1 #pragma once
2 
3 #include <libpldm/bios.h>
4 #include <libpldm/bios_table.h>
5 #include <stdint.h>
6 
7 #include <filesystem>
8 #include <optional>
9 #include <string>
10 #include <vector>
11 
12 namespace pldm
13 {
14 
15 namespace responder
16 {
17 
18 namespace bios
19 {
20 
21 using Table = std::vector<uint8_t>;
22 using Response = std::vector<uint8_t>;
23 namespace fs = std::filesystem;
24 
25 /** @class BIOSTable
26  *
27  *  @brief Provides APIs for storing and loading BIOS tables
28  *
29  *  Typical usage is as follows:
30  *  BIOSTable table(BIOS_STRING_TABLE_FILE_PATH);
31  *  if (table.isEmpty()) { // no persisted table
32  *    // construct BIOSTable 't'
33  *    // prepare Response 'r'
34  *    // send response to GetBIOSTable
35  *    table.store(t); // persisted
36  *  }
37  *  else { // persisted table exists
38  *    // create Response 'r' which has response fields (except
39  *    // the table itself) to a GetBIOSTable command
40  *    table.load(r); // actual table will be pushed back to the vector
41  *  }
42  */
43 class BIOSTable
44 {
45   public:
46     /** @brief Ctor - set file path to persist BIOS table
47      *
48      *  @param[in] filePath - file where BIOS table should be persisted
49      */
50     BIOSTable(const char* filePath);
51 
52     /** @brief Checks if there's a persisted BIOS table
53      *
54      *  @return bool - true if table exists, false otherwise
55      */
56     bool isEmpty() const noexcept;
57 
58     /** @brief Persist a BIOS table(string/attribute/attribute value)
59      *
60      *  @param[in] table - BIOS table
61      */
62     void store(const Table& table);
63 
64     /** @brief Load BIOS table from persistent store to memory
65      *
66      *  @param[in,out] response - PLDM response message to GetBIOSTable
67      *  (excluding table), table will be pushed back to this.
68      */
69     void load(Response& response) const;
70 
71   private:
72     // file storing PLDM BIOS table
73     fs::path filePath;
74 };
75 
76 /** @class BIOSStringTableInterface
77  *  @brief Provide interfaces to the BIOS string table operations
78  */
79 class BIOSStringTableInterface
80 {
81   public:
82     virtual ~BIOSStringTableInterface() = default;
83 
84     /** @brief Find the string name from the BIOS string table for a string
85      * handle
86      *  @param[in] handle - string handle
87      *  @return name of the corresponding BIOS string
88      */
89     virtual std::string findString(uint16_t handle) const = 0;
90 
91     /** @brief Find the string handle from the BIOS string table by the given
92      *         name
93      *  @param[in] name - name of the BIOS string
94      *  @return handle of the string
95      */
96     virtual uint16_t findHandle(const std::string& name) const = 0;
97 };
98 
99 /** @class BIOSStringTable
100  *  @brief Collection of BIOS string table operations.
101  */
102 class BIOSStringTable : public BIOSStringTableInterface
103 {
104   public:
105     /** @brief Constructs BIOSStringTable
106      *
107      *  @param[in] stringTable - The stringTable in RAM
108      */
109     BIOSStringTable(const Table& stringTable);
110 
111     /** @brief Constructs BIOSStringTable
112      *
113      *  @param[in] biosTable - The BIOSTable
114      */
115     BIOSStringTable(const BIOSTable& biosTable);
116 
117     /** @brief Find the string name from the BIOS string table for a string
118      * handle
119      *  @param[in] handle - string handle
120      *  @return name of the corresponding BIOS string
121      *  @throw std::invalid_argument if the string can not be found.
122      */
123     std::string findString(uint16_t handle) const override;
124 
125     /** @brief Find the string handle from the BIOS string table by the given
126      *         name
127      *  @param[in] name - name of the BIOS string
128      *  @return handle of the string
129      *  @throw std::invalid_argument if the string can not be found
130      */
131     uint16_t findHandle(const std::string& name) const override;
132 
133   private:
134     Table stringTable;
135 };
136 
137 namespace table
138 {
139 
140 /** @brief Append Pad and Checksum
141  *
142  *  @param[in,out] table - table to be appended with pad and checksum
143  */
144 void appendPadAndChecksum(Table& table);
145 
146 namespace string
147 {
148 
149 /** @brief Get the string handle for the entry
150  *  @param[in] entry - Pointer to a bios string table entry
151  *  @return Handle to identify a string in the bios string table
152  */
153 uint16_t decodeHandle(const pldm_bios_string_table_entry* entry);
154 
155 /** @brief Get the string from the entry
156  *  @param[in] entry - Pointer to a bios string table entry
157  *  @return The String
158  */
159 std::string decodeString(const pldm_bios_string_table_entry* entry);
160 
161 /** @brief construct entry of string table at the end of the given
162  *         table
163  *  @param[in,out] table - The given table
164  *  @param[in] str - string itself
165  *  @return pointer to the constructed entry
166  */
167 const pldm_bios_string_table_entry* constructEntry(Table& table,
168                                                    const std::string& str);
169 
170 } // namespace string
171 
172 namespace attribute
173 {
174 
175 /** @struct TableHeader
176  *  @brief Header of attribute table
177  */
178 struct TableHeader
179 {
180     uint16_t attrHandle;
181     uint8_t attrType;
182     uint16_t stringHandle;
183 };
184 
185 /** @brief Decode header of attribute table entry
186  *  @param[in] entry - Pointer to an attribute table entry
187  *  @return Attribute table header
188  */
189 TableHeader decodeHeader(const pldm_bios_attr_table_entry* entry);
190 
191 /** @brief Find attribute entry by handle
192  *  @param[in] table - attribute table
193  *  @param[in] handle - attribute handle
194  *  @return Pointer to the attribute table entry
195  */
196 const pldm_bios_attr_table_entry* findByHandle(const Table& table,
197                                                uint16_t handle);
198 
199 /** @brief Find attribute entry by string handle
200  *  @param[in] table - attribute table
201  *  @param[in] handle - string handle
202  *  @return Pointer to the attribute table entry
203  */
204 const pldm_bios_attr_table_entry* findByStringHandle(const Table& table,
205                                                      uint16_t handle);
206 
207 /** @struct StringField
208  *  @brief String field of attribute table
209  */
210 struct StringField
211 {
212     uint8_t stringType;
213     uint16_t minLength;
214     uint16_t maxLength;
215     uint16_t defLength;
216     std::string defString;
217 };
218 
219 /** @brief decode string entry of attribute table
220  *  @param[in] entry - Pointer to an attribute table entry
221  *  @return String field of the entry
222  */
223 StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry);
224 
225 /** @brief construct string entry of attribute table at the end of the given
226  *         table
227  *  @param[in,out] table - The given table
228  *  @param[in] info - string info
229  *  @return pointer to the constructed entry
230  */
231 const pldm_bios_attr_table_entry*
232     constructStringEntry(Table& table,
233                          pldm_bios_table_attr_entry_string_info* info);
234 
235 /** @struct IntegerField
236  *  @brief Integer field of attribute table
237  */
238 struct IntegerField
239 {
240     uint64_t lowerBound;
241     uint64_t upperBound;
242     uint32_t scalarIncrement;
243     uint64_t defaultValue;
244 };
245 
246 /** @brief construct integer entry of attribute table at the end of the
247  *         given table
248  *  @param[in,out] table - The given table
249  *  @param[in] info - integer info
250  *  @return pointer to the constructed entry
251  */
252 const pldm_bios_attr_table_entry*
253     constructIntegerEntry(Table& table,
254                           pldm_bios_table_attr_entry_integer_info* info);
255 
256 /** @brief decode integer entry of attribute table
257  *  @param[in] entry - Pointer to an attribute table entry
258  *  @return Integer field of the entry
259  */
260 IntegerField decodeIntegerEntry(const pldm_bios_attr_table_entry* entry);
261 
262 /** @struct EnumField
263  *  @brief Enum field of attribute table
264  */
265 struct EnumField
266 {
267     std::vector<uint16_t> possibleValueStringHandle;
268     std::vector<uint8_t> defaultValueIndex;
269 };
270 
271 /** @brief decode enum entry of attribute table
272  *  @param[in] entry - Pointer to an attribute table entry
273  *  @return Enum field of the entry
274  */
275 EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry);
276 
277 /** @brief construct enum entry of attribute table at the end of the
278  *         given table
279  *  @param[in,out] table - The given table
280  *  @param[in] info - enum info
281  *  @return pointer to the constructed entry
282  */
283 const pldm_bios_attr_table_entry*
284     constructEnumEntry(Table& table,
285                        pldm_bios_table_attr_entry_enum_info* info);
286 
287 } // namespace attribute
288 
289 namespace attribute_value
290 {
291 
292 /** @struct TableHeader
293  *  @brief Header of attribute value table
294  */
295 struct TableHeader
296 {
297     uint16_t attrHandle;
298     uint8_t attrType;
299 };
300 
301 /** @brief Decode header of attribute value table
302  *  @param[in] entry - Pointer to an attribute value table entry
303  *  @return Attribute value table header
304  */
305 TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry);
306 
307 /** @brief Decode string entry of attribute value table
308  *  @param[in] entry - Pointer to an attribute value table entry
309  *  @return The decoded string
310  */
311 std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry);
312 
313 /** @brief Decode integer entry of attribute value table
314  *  @param[in] entry - Pointer to an attribute value table entry
315  *  @return The decoded integer
316  */
317 uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry);
318 
319 /** @brief Decode enum entry of attribute value table
320  *  @param[in] entry - Pointer to an attribute value table entry
321  *  @return Current value string handle indices
322  */
323 std::vector<uint8_t>
324     decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry);
325 
326 /** @brief Construct string entry of attribute value table at the end of the
327  *         given table
328  *  @param[in] table - The given table
329  *  @param[in] attrHandle - attribute handle
330  *  @param[in] attrType - attribute type
331  *  @param[in] str - The string
332  *  @return Pointer to the constructed entry
333  */
334 const pldm_bios_attr_val_table_entry*
335     constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
336                          const std::string& str);
337 
338 /** @brief Construct integer entry of attribute value table at the end of
339  *         the given table
340  *  @param[in] table - The given table
341  *  @param[in] attrHandle - attribute handle
342  *  @param[in] attrType - attribute type
343  *  @param[in] value - The integer
344  *  @return Pointer to the constructed entry
345  */
346 const pldm_bios_attr_val_table_entry* constructIntegerEntry(Table& table,
347                                                             uint16_t attrHandle,
348                                                             uint8_t attrType,
349                                                             uint64_t value);
350 
351 /** @brief Construct enum entry of attribute value table at the end of
352  *         the given table
353  *  @param[in] table - The given table
354  *  @param[in] attrHandle - attribute handle
355  *  @param[in] attrType - attribute type
356  *  @param[in] handleIndices -  handle indices
357  *  @return Pointer to the constructed entry
358  */
359 const pldm_bios_attr_val_table_entry*
360     constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
361                        const std::vector<uint8_t>& handleIndices);
362 
363 /** @brief construct a table with an new entry
364  *  @param[in] table - the table need to be updated
365  *  @param[in] entry - the new attribute value entry
366  *  @param[in] size - size of the new entry
367  *  @return newly constructed table, std::nullopt if failed
368  */
369 std::optional<Table> updateTable(const Table& table, const void* entry,
370                                  size_t size);
371 
372 } // namespace attribute_value
373 
374 } // namespace table
375 
376 } // namespace bios
377 } // namespace responder
378 } // namespace pldm
379