1 #include "bios_table.hpp"
2 
3 #include "bios_table.h"
4 
5 #include <fstream>
6 
7 namespace pldm
8 {
9 
10 namespace responder
11 {
12 
13 namespace bios
14 {
15 
16 BIOSTable::BIOSTable(const char* filePath) : filePath(filePath)
17 {}
18 
19 bool BIOSTable::isEmpty() const noexcept
20 {
21     bool empty = false;
22     try
23     {
24         empty = fs::is_empty(filePath);
25     }
26     catch (const fs::filesystem_error& e)
27     {
28         return true;
29     }
30     return empty;
31 }
32 
33 void BIOSTable::store(const Table& table)
34 {
35     std::ofstream stream(filePath.string(), std::ios::out | std::ios::binary);
36     stream.write(reinterpret_cast<const char*>(table.data()), table.size());
37 }
38 
39 void BIOSTable::load(Response& response) const
40 {
41     auto currSize = response.size();
42     auto fileSize = fs::file_size(filePath);
43     response.resize(currSize + fileSize);
44     std::ifstream stream(filePath.string(), std::ios::in | std::ios::binary);
45     stream.read(reinterpret_cast<char*>(response.data() + currSize), fileSize);
46 }
47 
48 BIOSStringTable::BIOSStringTable(const Table& stringTable) :
49     stringTable(stringTable)
50 {}
51 
52 BIOSStringTable::BIOSStringTable(const BIOSTable& biosTable)
53 {
54     biosTable.load(stringTable);
55 }
56 
57 std::string BIOSStringTable::findString(uint16_t handle) const
58 {
59     auto stringEntry = pldm_bios_table_string_find_by_handle(
60         stringTable.data(), stringTable.size(), handle);
61     if (stringEntry == nullptr)
62     {
63         throw std::invalid_argument("Invalid String Handle");
64     }
65     return table::string::decodeString(stringEntry);
66 }
67 
68 uint16_t BIOSStringTable::findHandle(const std::string& name) const
69 {
70     auto stringEntry = pldm_bios_table_string_find_by_string(
71         stringTable.data(), stringTable.size(), name.c_str());
72     if (stringEntry == nullptr)
73     {
74         throw std::invalid_argument("Invalid String Name");
75     }
76 
77     return table::string::decodeHandle(stringEntry);
78 }
79 
80 namespace table
81 {
82 
83 void appendPadAndChecksum(Table& table)
84 {
85     auto sizeWithoutPad = table.size();
86     auto padAndChecksumSize = pldm_bios_table_pad_checksum_size(sizeWithoutPad);
87     table.resize(table.size() + padAndChecksumSize);
88 
89     pldm_bios_table_append_pad_checksum(table.data(), table.size(),
90                                         sizeWithoutPad);
91 }
92 
93 namespace string
94 {
95 
96 uint16_t decodeHandle(const pldm_bios_string_table_entry* entry)
97 {
98     return pldm_bios_table_string_entry_decode_handle(entry);
99 }
100 
101 std::string decodeString(const pldm_bios_string_table_entry* entry)
102 {
103     auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
104     std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
105     pldm_bios_table_string_entry_decode_string(entry, buffer.data(),
106                                                buffer.size());
107     return std::string(buffer.data(), buffer.data() + strLength);
108 }
109 const pldm_bios_string_table_entry* constructEntry(Table& table,
110                                                    const std::string& str)
111 {
112     auto tableSize = table.size();
113     auto entryLength = pldm_bios_table_string_entry_encode_length(str.length());
114     table.resize(tableSize + entryLength);
115     pldm_bios_table_string_entry_encode(table.data() + tableSize, entryLength,
116                                         str.c_str(), str.length());
117     return reinterpret_cast<pldm_bios_string_table_entry*>(table.data() +
118                                                            tableSize);
119 }
120 
121 } // namespace string
122 
123 namespace attribute
124 {
125 
126 TableHeader decodeHeader(const pldm_bios_attr_table_entry* entry)
127 {
128     auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry);
129     auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry);
130     auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry);
131     return {attrHandle, attrType, stringHandle};
132 }
133 
134 const pldm_bios_attr_table_entry* findByHandle(const Table& table,
135                                                uint16_t handle)
136 {
137     return pldm_bios_table_attr_find_by_handle(table.data(), table.size(),
138                                                handle);
139 }
140 
141 const pldm_bios_attr_table_entry* findByStringHandle(const Table& table,
142                                                      uint16_t handle)
143 {
144     return pldm_bios_table_attr_find_by_string_handle(table.data(),
145                                                       table.size(), handle);
146 }
147 
148 const pldm_bios_attr_table_entry*
149     constructStringEntry(Table& table,
150                          pldm_bios_table_attr_entry_string_info* info)
151 {
152     auto entryLength =
153         pldm_bios_table_attr_entry_string_encode_length(info->def_length);
154 
155     auto tableSize = table.size();
156     table.resize(tableSize + entryLength, 0);
157     pldm_bios_table_attr_entry_string_encode(table.data() + tableSize,
158                                              entryLength, info);
159     return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
160                                                          tableSize);
161 }
162 
163 const pldm_bios_attr_table_entry*
164     constructIntegerEntry(Table& table,
165                           pldm_bios_table_attr_entry_integer_info* info)
166 {
167     auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
168     auto tableSize = table.size();
169     table.resize(tableSize + entryLength, 0);
170     pldm_bios_table_attr_entry_integer_encode(table.data() + tableSize,
171                                               entryLength, info);
172     return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
173                                                          tableSize);
174 }
175 
176 StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry)
177 {
178     auto strType = pldm_bios_table_attr_entry_string_decode_string_type(entry);
179     auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
180     auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
181     auto defLength =
182         pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
183 
184     std::vector<char> buffer(defLength + 1);
185     pldm_bios_table_attr_entry_string_decode_def_string(entry, buffer.data(),
186                                                         buffer.size());
187     return {strType, minLength, maxLength, defLength,
188             std::string(buffer.data(), buffer.data() + defLength)};
189 }
190 
191 IntegerField decodeIntegerEntry(const pldm_bios_attr_table_entry* entry)
192 {
193     uint64_t lower, upper, def;
194     uint32_t scalar;
195 
196     pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar,
197                                               &def);
198     return {lower, upper, scalar, def};
199 }
200 
201 const pldm_bios_attr_table_entry*
202     constructEnumEntry(Table& table, pldm_bios_table_attr_entry_enum_info* info)
203 {
204     auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
205         info->pv_num, info->def_num);
206 
207     auto tableSize = table.size();
208     table.resize(tableSize + entryLength, 0);
209     pldm_bios_table_attr_entry_enum_encode(table.data() + tableSize,
210                                            entryLength, info);
211 
212     return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
213                                                          tableSize);
214 }
215 
216 EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry)
217 {
218     uint8_t pvNum = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
219     std::vector<uint16_t> pvHdls(pvNum, 0);
220     pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pvHdls.data(), pvNum);
221     auto defNum = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
222     std::vector<uint8_t> defIndices(defNum, 0);
223     pldm_bios_table_attr_entry_enum_decode_def_indices(entry, defIndices.data(),
224                                                        defIndices.size());
225     return {pvHdls, defIndices};
226 }
227 
228 } // namespace attribute
229 
230 namespace attribute_value
231 {
232 
233 TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry)
234 {
235     auto handle =
236         pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
237     auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
238     return {handle, type};
239 }
240 
241 std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry)
242 {
243     variable_field currentString{};
244     pldm_bios_table_attr_value_entry_string_decode_string(entry,
245                                                           &currentString);
246     return std::string(currentString.ptr,
247                        currentString.ptr + currentString.length);
248 }
249 
250 uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry)
251 {
252     return pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
253 }
254 
255 std::vector<uint8_t>
256     decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry)
257 {
258     auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
259     std::vector<uint8_t> currHdls(number, 0);
260     pldm_bios_table_attr_value_entry_enum_decode_handles(entry, currHdls.data(),
261                                                          currHdls.size());
262     return currHdls;
263 }
264 
265 const pldm_bios_attr_val_table_entry*
266     constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
267                          const std::string& str)
268 {
269     auto strLen = str.size();
270     auto entryLength =
271         pldm_bios_table_attr_value_entry_encode_string_length(strLen);
272     auto tableSize = table.size();
273     table.resize(tableSize + entryLength);
274     pldm_bios_table_attr_value_entry_encode_string(
275         table.data() + tableSize, entryLength, attrHandle, attrType, strLen,
276         str.c_str());
277     return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
278                                                              tableSize);
279 }
280 
281 const pldm_bios_attr_val_table_entry* constructIntegerEntry(Table& table,
282                                                             uint16_t attrHandle,
283                                                             uint8_t attrType,
284                                                             uint64_t value)
285 {
286     auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
287 
288     auto tableSize = table.size();
289     table.resize(tableSize + entryLength);
290     pldm_bios_table_attr_value_entry_encode_integer(
291         table.data() + tableSize, entryLength, attrHandle, attrType, value);
292     return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
293                                                              tableSize);
294 }
295 
296 const pldm_bios_attr_val_table_entry*
297     constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
298                        const std::vector<uint8_t>& handleIndices)
299 {
300     auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
301         handleIndices.size());
302     auto tableSize = table.size();
303     table.resize(tableSize + entryLength);
304     pldm_bios_table_attr_value_entry_encode_enum(
305         table.data() + tableSize, entryLength, attrHandle, attrType,
306         handleIndices.size(), handleIndices.data());
307     return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
308                                                              tableSize);
309 }
310 
311 std::optional<Table> updateTable(const Table& table, const void* entry,
312                                  size_t size)
313 {
314     // Replace the old attribute with the new attribute, the size of table will
315     // change:
316     //   sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
317     //                      sizeof(oldAttribute) + pad(4-byte alignment, max =
318     //                      3)
319     // For simplicity, we use
320     //   sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
321     size_t destBufferLength = table.size() + size + 3;
322     Table destTable(destBufferLength);
323 
324     auto rc = pldm_bios_table_attr_value_copy_and_update(
325         table.data(), table.size(), destTable.data(), &destBufferLength, entry,
326         size);
327     if (rc != PLDM_SUCCESS)
328     {
329         return std::nullopt;
330     }
331     destTable.resize(destBufferLength);
332 
333     return destTable;
334 }
335 
336 } // namespace attribute_value
337 
338 } // namespace table
339 
340 } // namespace bios
341 } // namespace responder
342 } // namespace pldm
343