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