blob: 1b28a5363f50a37d0d1725fd63e59b86944ee87d [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 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -050026 catch (const fs::filesystem_error&)
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{
Andrew Jefferyc43f2112023-06-30 13:00:26 +093084 size_t payloadSize = table.size();
85 table.resize(payloadSize + pldm_bios_table_pad_checksum_size(payloadSize));
86 // No validation of return value as preconditions are satisfied
87 pldm_bios_table_append_pad_checksum_check(table.data(), table.size(),
88 &payloadSize);
John Wangd9659342020-02-27 16:46:05 +080089}
90
John Wang29683b52020-02-27 16:41:44 +080091namespace string
92{
John Wang29683b52020-02-27 16:41:44 +080093uint16_t decodeHandle(const pldm_bios_string_table_entry* entry)
John Wange2efdcc2020-02-12 17:02:06 +080094{
95 return pldm_bios_table_string_entry_decode_handle(entry);
96}
97
John Wang29683b52020-02-27 16:41:44 +080098std::string decodeString(const pldm_bios_string_table_entry* entry)
John Wange2efdcc2020-02-12 17:02:06 +080099{
100 auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
101 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930102 // Preconditions are upheld therefore no error check necessary
103 pldm_bios_table_string_entry_decode_string_check(entry, buffer.data(),
104 buffer.size());
John Wange2efdcc2020-02-12 17:02:06 +0800105 return std::string(buffer.data(), buffer.data() + strLength);
John Wange297b9f2020-02-03 10:18:13 +0800106}
John Wangd9659342020-02-27 16:46:05 +0800107const pldm_bios_string_table_entry* constructEntry(Table& table,
108 const std::string& str)
109{
110 auto tableSize = table.size();
111 auto entryLength = pldm_bios_table_string_entry_encode_length(str.length());
112 table.resize(tableSize + entryLength);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930113 // Preconditions are upheld therefore no error check necessary
114 pldm_bios_table_string_entry_encode_check(
115 table.data() + tableSize, entryLength, str.c_str(), str.length());
John Wangd9659342020-02-27 16:46:05 +0800116 return reinterpret_cast<pldm_bios_string_table_entry*>(table.data() +
117 tableSize);
118}
John Wange297b9f2020-02-03 10:18:13 +0800119
John Wang29683b52020-02-27 16:41:44 +0800120} // namespace string
121
122namespace attribute
123{
John Wang29683b52020-02-27 16:41:44 +0800124TableHeader decodeHeader(const pldm_bios_attr_table_entry* entry)
125{
126 auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry);
127 auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry);
128 auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry);
129 return {attrHandle, attrType, stringHandle};
130}
131
John Wangd9659342020-02-27 16:46:05 +0800132const pldm_bios_attr_table_entry* findByHandle(const Table& table,
133 uint16_t handle)
134{
135 return pldm_bios_table_attr_find_by_handle(table.data(), table.size(),
136 handle);
137}
138
John Wang45fed202020-04-01 16:42:26 +0800139const pldm_bios_attr_table_entry* findByStringHandle(const Table& table,
140 uint16_t handle)
141{
142 return pldm_bios_table_attr_find_by_string_handle(table.data(),
143 table.size(), handle);
144}
145
John Wang29683b52020-02-27 16:41:44 +0800146const pldm_bios_attr_table_entry*
147 constructStringEntry(Table& table,
148 pldm_bios_table_attr_entry_string_info* info)
149{
150 auto entryLength =
151 pldm_bios_table_attr_entry_string_encode_length(info->def_length);
152
153 auto tableSize = table.size();
154 table.resize(tableSize + entryLength, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930155 int rc = pldm_bios_table_attr_entry_string_encode_check(
156 table.data() + tableSize, entryLength, info);
157 if (rc != PLDM_SUCCESS)
158 {
159 lg2::error("Failed to encode BIOS table string entry: {LIBPLDM_ERROR}",
160 "LIBPLDM_ERROR", rc);
161 throw std::runtime_error("Failed to encode BIOS table string entry");
162 }
John Wang29683b52020-02-27 16:41:44 +0800163 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
164 tableSize);
165}
166
John Wang95e6b3c2020-02-13 09:43:24 +0800167const pldm_bios_attr_table_entry*
168 constructIntegerEntry(Table& table,
169 pldm_bios_table_attr_entry_integer_info* info)
170{
171 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
172 auto tableSize = table.size();
173 table.resize(tableSize + entryLength, 0);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930174 int rc = pldm_bios_table_attr_entry_integer_encode_check(
175 table.data() + tableSize, entryLength, info);
176 if (rc != PLDM_SUCCESS)
177 {
178 lg2::error(
179 "Failed to encode BIOS attribute table integer entry: {LIBPLDM_ERROR}",
180 "LIBPLDM_ERROR", rc);
181 throw std::runtime_error(
182 "Failed to encode BIOS attribute table integer entry");
183 }
John Wang95e6b3c2020-02-13 09:43:24 +0800184 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
185 tableSize);
186}
187
John Wang29683b52020-02-27 16:41:44 +0800188StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry)
189{
190 auto strType = pldm_bios_table_attr_entry_string_decode_string_type(entry);
191 auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
192 auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930193 uint16_t defLength;
194 int rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
195 entry, &defLength);
196 if (rc != PLDM_SUCCESS)
197 {
198 lg2::error(
199 "Failed to decode BIOS table string definition length: {LIBPLDM_ERROR}",
200 "LIBPLDM_ERROR", rc);
201 throw std::runtime_error(
202 "Failed to decode BIOS table string definitionlength");
203 }
John Wang29683b52020-02-27 16:41:44 +0800204
205 std::vector<char> buffer(defLength + 1);
206 pldm_bios_table_attr_entry_string_decode_def_string(entry, buffer.data(),
207 buffer.size());
208 return {strType, minLength, maxLength, defLength,
209 std::string(buffer.data(), buffer.data() + defLength)};
210}
211
John Wang95e6b3c2020-02-13 09:43:24 +0800212IntegerField decodeIntegerEntry(const pldm_bios_attr_table_entry* entry)
213{
214 uint64_t lower, upper, def;
215 uint32_t scalar;
216
217 pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar,
218 &def);
219 return {lower, upper, scalar, def};
220}
221
John Wang3be70852020-02-13 15:59:04 +0800222const pldm_bios_attr_table_entry*
223 constructEnumEntry(Table& table, pldm_bios_table_attr_entry_enum_info* info)
224{
225 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
226 info->pv_num, info->def_num);
227
228 auto tableSize = table.size();
229 table.resize(tableSize + entryLength, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930230 // Preconditions are upheld therefore no error check necessary
231 pldm_bios_table_attr_entry_enum_encode_check(table.data() + tableSize,
232 entryLength, info);
John Wang3be70852020-02-13 15:59:04 +0800233
234 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
235 tableSize);
236}
237
238EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry)
239{
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930240 uint8_t pvNum;
241 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNum);
242 if (rc != PLDM_SUCCESS)
243 {
244 lg2::error(
245 "Failed to decode the number of possible values for BIOS table enum entry: {LIBPLDM_ERROR}",
246 "LIBPLDM_ERROR", rc);
247 throw std::runtime_error(
248 "Failed to decode the number of possible values for BIOS table enum entry");
249 }
John Wang3be70852020-02-13 15:59:04 +0800250 std::vector<uint16_t> pvHdls(pvNum, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930251 // Preconditions are upheld therefore no error check necessary
252 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(entry, pvHdls.data(),
253 pvNum);
254 // Preconditions are upheld therefore no error check necessary
255 uint8_t defNum;
256 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNum);
John Wang3be70852020-02-13 15:59:04 +0800257 std::vector<uint8_t> defIndices(defNum, 0);
258 pldm_bios_table_attr_entry_enum_decode_def_indices(entry, defIndices.data(),
259 defIndices.size());
260 return {pvHdls, defIndices};
261}
262
John Wang29683b52020-02-27 16:41:44 +0800263} // namespace attribute
264
265namespace attribute_value
266{
John Wang29683b52020-02-27 16:41:44 +0800267TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry)
268{
269 auto handle =
270 pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
271 auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
272 return {handle, type};
273}
274
275std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry)
276{
277 variable_field currentString{};
278 pldm_bios_table_attr_value_entry_string_decode_string(entry,
279 &currentString);
280 return std::string(currentString.ptr,
281 currentString.ptr + currentString.length);
282}
283
John Wang95e6b3c2020-02-13 09:43:24 +0800284uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry)
285{
286 return pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
287}
288
John Wang3be70852020-02-13 15:59:04 +0800289std::vector<uint8_t>
290 decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry)
291{
292 auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
293 std::vector<uint8_t> currHdls(number, 0);
294 pldm_bios_table_attr_value_entry_enum_decode_handles(entry, currHdls.data(),
295 currHdls.size());
296 return currHdls;
297}
298
John Wang29683b52020-02-27 16:41:44 +0800299const pldm_bios_attr_val_table_entry*
300 constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
301 const std::string& str)
302{
303 auto strLen = str.size();
304 auto entryLength =
305 pldm_bios_table_attr_value_entry_encode_string_length(strLen);
306 auto tableSize = table.size();
307 table.resize(tableSize + entryLength);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930308 int rc = pldm_bios_table_attr_value_entry_encode_string_check(
John Wang29683b52020-02-27 16:41:44 +0800309 table.data() + tableSize, entryLength, attrHandle, attrType, strLen,
310 str.c_str());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930311 if (rc != PLDM_SUCCESS)
312 {
313 lg2::error(
314 "Failed to encode BIOS attribute table string entry: {LIBPLDM_ERROR}",
315 "LIBPLDM_ERROR", rc);
316 throw std::runtime_error(
317 "Failed to encode BIOS attribute table string entry");
318 }
John Wang29683b52020-02-27 16:41:44 +0800319 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
320 tableSize);
321}
John Wang95e6b3c2020-02-13 09:43:24 +0800322
323const pldm_bios_attr_val_table_entry* constructIntegerEntry(Table& table,
324 uint16_t attrHandle,
325 uint8_t attrType,
326 uint64_t value)
327{
328 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
329
330 auto tableSize = table.size();
331 table.resize(tableSize + entryLength);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930332 int rc = pldm_bios_table_attr_value_entry_encode_integer_check(
John Wang95e6b3c2020-02-13 09:43:24 +0800333 table.data() + tableSize, entryLength, attrHandle, attrType, value);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930334 if (rc != PLDM_SUCCESS)
335 {
336 lg2::error(
337 "Failed to encode BIOS attribute table integer entry: {LIBPLDM_ERROR}",
338 "LIBPLDM_ERROR", rc);
339 throw std::runtime_error(
340 "Failed to encode BIOS attribute table integery entry");
341 }
John Wang95e6b3c2020-02-13 09:43:24 +0800342 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
343 tableSize);
344}
345
John Wang3be70852020-02-13 15:59:04 +0800346const pldm_bios_attr_val_table_entry*
347 constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
348 const std::vector<uint8_t>& handleIndices)
349{
350 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
351 handleIndices.size());
352 auto tableSize = table.size();
353 table.resize(tableSize + entryLength);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930354 int rc = pldm_bios_table_attr_value_entry_encode_enum_check(
John Wang3be70852020-02-13 15:59:04 +0800355 table.data() + tableSize, entryLength, attrHandle, attrType,
356 handleIndices.size(), handleIndices.data());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930357 if (rc != PLDM_SUCCESS)
358 {
359 lg2::error(
360 "Failed to encode BIOS attribute table enum entry: {LIBPLDM_ERROR}",
361 "LIBPLDM_ERROR", rc);
362 throw std::runtime_error(
363 "Failed to encode BIOS attribute table enum entry");
364 }
John Wang3be70852020-02-13 15:59:04 +0800365 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
366 tableSize);
367}
368
John Wangd9659342020-02-27 16:46:05 +0800369std::optional<Table> updateTable(const Table& table, const void* entry,
370 size_t size)
371{
372 // Replace the old attribute with the new attribute, the size of table will
373 // change:
374 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
375 // sizeof(oldAttribute) + pad(4-byte alignment, max =
376 // 3)
377 // For simplicity, we use
378 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
379 size_t destBufferLength = table.size() + size + 3;
380 Table destTable(destBufferLength);
381
382 auto rc = pldm_bios_table_attr_value_copy_and_update(
383 table.data(), table.size(), destTable.data(), &destBufferLength, entry,
384 size);
385 if (rc != PLDM_SUCCESS)
386 {
387 return std::nullopt;
388 }
389 destTable.resize(destBufferLength);
390
391 return destTable;
392}
John Wang29683b52020-02-27 16:41:44 +0800393
394} // namespace attribute_value
395
396} // namespace table
397
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +0530398} // namespace bios
399} // namespace responder
400} // namespace pldm