blob: f29d8133d90537b51efb4dce084bd4ef1eb08eb8 [file] [log] [blame]
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +05301#include "bios_table.hpp"
2
George Liuc453e162022-12-21 17:16:23 +08003#include <libpldm/base.h>
4#include <libpldm/bios_table.h>
5#include <libpldm/utils.h>
John Wangf719f3b2020-01-17 08:46:22 +08006
Andrew Jeffery488f19d2023-06-13 20:43:39 +09307#include <phosphor-logging/lg2.hpp>
8
George Liu6492f522020-06-16 10:34:05 +08009#include <fstream>
10
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053011namespace pldm
12{
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053013namespace responder
14{
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053015namespace bios
16{
Patrick Williams6da4f912023-05-10 07:50:53 -050017BIOSTable::BIOSTable(const char* filePath) : filePath(filePath) {}
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053018
19bool BIOSTable::isEmpty() const noexcept
20{
21 bool empty = false;
22 try
23 {
24 empty = fs::is_empty(filePath);
25 }
Patrick Williams51330582021-10-06 12:48:56 -050026 catch (const fs::filesystem_error& e)
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053027 {
28 return true;
29 }
30 return empty;
31}
32
33void 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
39void 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
John Wange297b9f2020-02-03 10:18:13 +080048BIOSStringTable::BIOSStringTable(const Table& stringTable) :
49 stringTable(stringTable)
George Liu6492f522020-06-16 10:34:05 +080050{}
John Wange297b9f2020-02-03 10:18:13 +080051
52BIOSStringTable::BIOSStringTable(const BIOSTable& biosTable)
53{
54 biosTable.load(stringTable);
John Wangf719f3b2020-01-17 08:46:22 +080055}
56
57std::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 }
John Wang29683b52020-02-27 16:41:44 +080065 return table::string::decodeString(stringEntry);
John Wangf719f3b2020-01-17 08:46:22 +080066}
67
John Wange297b9f2020-02-03 10:18:13 +080068uint16_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
John Wang29683b52020-02-27 16:41:44 +080077 return table::string::decodeHandle(stringEntry);
John Wange2efdcc2020-02-12 17:02:06 +080078}
79
John Wang29683b52020-02-27 16:41:44 +080080namespace table
81{
John Wangd9659342020-02-27 16:46:05 +080082void appendPadAndChecksum(Table& table)
83{
84 auto sizeWithoutPad = table.size();
85 auto padAndChecksumSize = pldm_bios_table_pad_checksum_size(sizeWithoutPad);
86 table.resize(table.size() + padAndChecksumSize);
87
88 pldm_bios_table_append_pad_checksum(table.data(), table.size(),
89 sizeWithoutPad);
90}
91
John Wang29683b52020-02-27 16:41:44 +080092namespace string
93{
John Wang29683b52020-02-27 16:41:44 +080094uint16_t decodeHandle(const pldm_bios_string_table_entry* entry)
John Wange2efdcc2020-02-12 17:02:06 +080095{
96 return pldm_bios_table_string_entry_decode_handle(entry);
97}
98
John Wang29683b52020-02-27 16:41:44 +080099std::string decodeString(const pldm_bios_string_table_entry* entry)
John Wange2efdcc2020-02-12 17:02:06 +0800100{
101 auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
102 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930103 // Preconditions are upheld therefore no error check necessary
104 pldm_bios_table_string_entry_decode_string_check(entry, buffer.data(),
105 buffer.size());
John Wange2efdcc2020-02-12 17:02:06 +0800106 return std::string(buffer.data(), buffer.data() + strLength);
John Wange297b9f2020-02-03 10:18:13 +0800107}
John Wangd9659342020-02-27 16:46:05 +0800108const pldm_bios_string_table_entry* constructEntry(Table& table,
109 const std::string& str)
110{
111 auto tableSize = table.size();
112 auto entryLength = pldm_bios_table_string_entry_encode_length(str.length());
113 table.resize(tableSize + entryLength);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930114 // Preconditions are upheld therefore no error check necessary
115 pldm_bios_table_string_entry_encode_check(
116 table.data() + tableSize, entryLength, str.c_str(), str.length());
John Wangd9659342020-02-27 16:46:05 +0800117 return reinterpret_cast<pldm_bios_string_table_entry*>(table.data() +
118 tableSize);
119}
John Wange297b9f2020-02-03 10:18:13 +0800120
John Wang29683b52020-02-27 16:41:44 +0800121} // namespace string
122
123namespace attribute
124{
John Wang29683b52020-02-27 16:41:44 +0800125TableHeader decodeHeader(const pldm_bios_attr_table_entry* entry)
126{
127 auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry);
128 auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry);
129 auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry);
130 return {attrHandle, attrType, stringHandle};
131}
132
John Wangd9659342020-02-27 16:46:05 +0800133const pldm_bios_attr_table_entry* findByHandle(const Table& table,
134 uint16_t handle)
135{
136 return pldm_bios_table_attr_find_by_handle(table.data(), table.size(),
137 handle);
138}
139
John Wang45fed202020-04-01 16:42:26 +0800140const pldm_bios_attr_table_entry* findByStringHandle(const Table& table,
141 uint16_t handle)
142{
143 return pldm_bios_table_attr_find_by_string_handle(table.data(),
144 table.size(), handle);
145}
146
John Wang29683b52020-02-27 16:41:44 +0800147const pldm_bios_attr_table_entry*
148 constructStringEntry(Table& table,
149 pldm_bios_table_attr_entry_string_info* info)
150{
151 auto entryLength =
152 pldm_bios_table_attr_entry_string_encode_length(info->def_length);
153
154 auto tableSize = table.size();
155 table.resize(tableSize + entryLength, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930156 int rc = pldm_bios_table_attr_entry_string_encode_check(
157 table.data() + tableSize, entryLength, info);
158 if (rc != PLDM_SUCCESS)
159 {
160 lg2::error("Failed to encode BIOS table string entry: {LIBPLDM_ERROR}",
161 "LIBPLDM_ERROR", rc);
162 throw std::runtime_error("Failed to encode BIOS table string entry");
163 }
John Wang29683b52020-02-27 16:41:44 +0800164 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
165 tableSize);
166}
167
John Wang95e6b3c2020-02-13 09:43:24 +0800168const pldm_bios_attr_table_entry*
169 constructIntegerEntry(Table& table,
170 pldm_bios_table_attr_entry_integer_info* info)
171{
172 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
173 auto tableSize = table.size();
174 table.resize(tableSize + entryLength, 0);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930175 int rc = pldm_bios_table_attr_entry_integer_encode_check(
176 table.data() + tableSize, entryLength, info);
177 if (rc != PLDM_SUCCESS)
178 {
179 lg2::error(
180 "Failed to encode BIOS attribute table integer entry: {LIBPLDM_ERROR}",
181 "LIBPLDM_ERROR", rc);
182 throw std::runtime_error(
183 "Failed to encode BIOS attribute table integer entry");
184 }
John Wang95e6b3c2020-02-13 09:43:24 +0800185 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
186 tableSize);
187}
188
John Wang29683b52020-02-27 16:41:44 +0800189StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry)
190{
191 auto strType = pldm_bios_table_attr_entry_string_decode_string_type(entry);
192 auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
193 auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930194 uint16_t defLength;
195 int rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
196 entry, &defLength);
197 if (rc != PLDM_SUCCESS)
198 {
199 lg2::error(
200 "Failed to decode BIOS table string definition length: {LIBPLDM_ERROR}",
201 "LIBPLDM_ERROR", rc);
202 throw std::runtime_error(
203 "Failed to decode BIOS table string definitionlength");
204 }
John Wang29683b52020-02-27 16:41:44 +0800205
206 std::vector<char> buffer(defLength + 1);
207 pldm_bios_table_attr_entry_string_decode_def_string(entry, buffer.data(),
208 buffer.size());
209 return {strType, minLength, maxLength, defLength,
210 std::string(buffer.data(), buffer.data() + defLength)};
211}
212
John Wang95e6b3c2020-02-13 09:43:24 +0800213IntegerField decodeIntegerEntry(const pldm_bios_attr_table_entry* entry)
214{
215 uint64_t lower, upper, def;
216 uint32_t scalar;
217
218 pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar,
219 &def);
220 return {lower, upper, scalar, def};
221}
222
John Wang3be70852020-02-13 15:59:04 +0800223const pldm_bios_attr_table_entry*
224 constructEnumEntry(Table& table, pldm_bios_table_attr_entry_enum_info* info)
225{
226 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
227 info->pv_num, info->def_num);
228
229 auto tableSize = table.size();
230 table.resize(tableSize + entryLength, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930231 // Preconditions are upheld therefore no error check necessary
232 pldm_bios_table_attr_entry_enum_encode_check(table.data() + tableSize,
233 entryLength, info);
John Wang3be70852020-02-13 15:59:04 +0800234
235 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
236 tableSize);
237}
238
239EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry)
240{
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930241 uint8_t pvNum;
242 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNum);
243 if (rc != PLDM_SUCCESS)
244 {
245 lg2::error(
246 "Failed to decode the number of possible values for BIOS table enum entry: {LIBPLDM_ERROR}",
247 "LIBPLDM_ERROR", rc);
248 throw std::runtime_error(
249 "Failed to decode the number of possible values for BIOS table enum entry");
250 }
John Wang3be70852020-02-13 15:59:04 +0800251 std::vector<uint16_t> pvHdls(pvNum, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930252 // Preconditions are upheld therefore no error check necessary
253 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(entry, pvHdls.data(),
254 pvNum);
255 // Preconditions are upheld therefore no error check necessary
256 uint8_t defNum;
257 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNum);
John Wang3be70852020-02-13 15:59:04 +0800258 std::vector<uint8_t> defIndices(defNum, 0);
259 pldm_bios_table_attr_entry_enum_decode_def_indices(entry, defIndices.data(),
260 defIndices.size());
261 return {pvHdls, defIndices};
262}
263
John Wang29683b52020-02-27 16:41:44 +0800264} // namespace attribute
265
266namespace attribute_value
267{
John Wang29683b52020-02-27 16:41:44 +0800268TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry)
269{
270 auto handle =
271 pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
272 auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
273 return {handle, type};
274}
275
276std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry)
277{
278 variable_field currentString{};
279 pldm_bios_table_attr_value_entry_string_decode_string(entry,
280 &currentString);
281 return std::string(currentString.ptr,
282 currentString.ptr + currentString.length);
283}
284
John Wang95e6b3c2020-02-13 09:43:24 +0800285uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry)
286{
287 return pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
288}
289
John Wang3be70852020-02-13 15:59:04 +0800290std::vector<uint8_t>
291 decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry)
292{
293 auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
294 std::vector<uint8_t> currHdls(number, 0);
295 pldm_bios_table_attr_value_entry_enum_decode_handles(entry, currHdls.data(),
296 currHdls.size());
297 return currHdls;
298}
299
John Wang29683b52020-02-27 16:41:44 +0800300const pldm_bios_attr_val_table_entry*
301 constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
302 const std::string& str)
303{
304 auto strLen = str.size();
305 auto entryLength =
306 pldm_bios_table_attr_value_entry_encode_string_length(strLen);
307 auto tableSize = table.size();
308 table.resize(tableSize + entryLength);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930309 int rc = pldm_bios_table_attr_value_entry_encode_string_check(
John Wang29683b52020-02-27 16:41:44 +0800310 table.data() + tableSize, entryLength, attrHandle, attrType, strLen,
311 str.c_str());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930312 if (rc != PLDM_SUCCESS)
313 {
314 lg2::error(
315 "Failed to encode BIOS attribute table string entry: {LIBPLDM_ERROR}",
316 "LIBPLDM_ERROR", rc);
317 throw std::runtime_error(
318 "Failed to encode BIOS attribute table string entry");
319 }
John Wang29683b52020-02-27 16:41:44 +0800320 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
321 tableSize);
322}
John Wang95e6b3c2020-02-13 09:43:24 +0800323
324const pldm_bios_attr_val_table_entry* constructIntegerEntry(Table& table,
325 uint16_t attrHandle,
326 uint8_t attrType,
327 uint64_t value)
328{
329 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
330
331 auto tableSize = table.size();
332 table.resize(tableSize + entryLength);
333 pldm_bios_table_attr_value_entry_encode_integer(
334 table.data() + tableSize, entryLength, attrHandle, attrType, value);
335 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
336 tableSize);
337}
338
John Wang3be70852020-02-13 15:59:04 +0800339const pldm_bios_attr_val_table_entry*
340 constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
341 const std::vector<uint8_t>& handleIndices)
342{
343 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
344 handleIndices.size());
345 auto tableSize = table.size();
346 table.resize(tableSize + entryLength);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930347 int rc = pldm_bios_table_attr_value_entry_encode_enum_check(
John Wang3be70852020-02-13 15:59:04 +0800348 table.data() + tableSize, entryLength, attrHandle, attrType,
349 handleIndices.size(), handleIndices.data());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930350 if (rc != PLDM_SUCCESS)
351 {
352 lg2::error(
353 "Failed to encode BIOS attribute table enum entry: {LIBPLDM_ERROR}",
354 "LIBPLDM_ERROR", rc);
355 throw std::runtime_error(
356 "Failed to encode BIOS attribute table enum entry");
357 }
John Wang3be70852020-02-13 15:59:04 +0800358 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
359 tableSize);
360}
361
John Wangd9659342020-02-27 16:46:05 +0800362std::optional<Table> updateTable(const Table& table, const void* entry,
363 size_t size)
364{
365 // Replace the old attribute with the new attribute, the size of table will
366 // change:
367 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
368 // sizeof(oldAttribute) + pad(4-byte alignment, max =
369 // 3)
370 // For simplicity, we use
371 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
372 size_t destBufferLength = table.size() + size + 3;
373 Table destTable(destBufferLength);
374
375 auto rc = pldm_bios_table_attr_value_copy_and_update(
376 table.data(), table.size(), destTable.data(), &destBufferLength, entry,
377 size);
378 if (rc != PLDM_SUCCESS)
379 {
380 return std::nullopt;
381 }
382 destTable.resize(destBufferLength);
383
384 return destTable;
385}
John Wang29683b52020-02-27 16:41:44 +0800386
387} // namespace attribute_value
388
389} // namespace table
390
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +0530391} // namespace bios
392} // namespace responder
393} // namespace pldm