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