blob: 158905cffc4e3145f967696902a672a360e27a81 [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
Riya Dixit89644442024-03-31 05:39:59 -050011PHOSPHOR_LOG2_USING;
12
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053013namespace pldm
14{
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053015namespace responder
16{
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053017namespace bios
18{
Patrick Williams6da4f912023-05-10 07:50:53 -050019BIOSTable::BIOSTable(const char* filePath) : filePath(filePath) {}
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053020
21bool BIOSTable::isEmpty() const noexcept
22{
23 bool empty = false;
24 try
25 {
26 empty = fs::is_empty(filePath);
27 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -050028 catch (const fs::filesystem_error&)
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +053029 {
30 return true;
31 }
32 return empty;
33}
34
35void BIOSTable::store(const Table& table)
36{
37 std::ofstream stream(filePath.string(), std::ios::out | std::ios::binary);
38 stream.write(reinterpret_cast<const char*>(table.data()), table.size());
39}
40
41void BIOSTable::load(Response& response) const
42{
43 auto currSize = response.size();
44 auto fileSize = fs::file_size(filePath);
45 response.resize(currSize + fileSize);
46 std::ifstream stream(filePath.string(), std::ios::in | std::ios::binary);
47 stream.read(reinterpret_cast<char*>(response.data() + currSize), fileSize);
48}
49
John Wange297b9f2020-02-03 10:18:13 +080050BIOSStringTable::BIOSStringTable(const Table& stringTable) :
51 stringTable(stringTable)
George Liu6492f522020-06-16 10:34:05 +080052{}
John Wange297b9f2020-02-03 10:18:13 +080053
54BIOSStringTable::BIOSStringTable(const BIOSTable& biosTable)
55{
56 biosTable.load(stringTable);
John Wangf719f3b2020-01-17 08:46:22 +080057}
58
59std::string BIOSStringTable::findString(uint16_t handle) const
60{
61 auto stringEntry = pldm_bios_table_string_find_by_handle(
62 stringTable.data(), stringTable.size(), handle);
63 if (stringEntry == nullptr)
64 {
65 throw std::invalid_argument("Invalid String Handle");
66 }
John Wang29683b52020-02-27 16:41:44 +080067 return table::string::decodeString(stringEntry);
John Wangf719f3b2020-01-17 08:46:22 +080068}
69
John Wange297b9f2020-02-03 10:18:13 +080070uint16_t BIOSStringTable::findHandle(const std::string& name) const
71{
72 auto stringEntry = pldm_bios_table_string_find_by_string(
73 stringTable.data(), stringTable.size(), name.c_str());
74 if (stringEntry == nullptr)
75 {
76 throw std::invalid_argument("Invalid String Name");
77 }
78
John Wang29683b52020-02-27 16:41:44 +080079 return table::string::decodeHandle(stringEntry);
John Wange2efdcc2020-02-12 17:02:06 +080080}
81
John Wang29683b52020-02-27 16:41:44 +080082namespace table
83{
John Wangd9659342020-02-27 16:46:05 +080084void appendPadAndChecksum(Table& table)
85{
Andrew Jefferyc43f2112023-06-30 13:00:26 +093086 size_t payloadSize = table.size();
87 table.resize(payloadSize + pldm_bios_table_pad_checksum_size(payloadSize));
88 // No validation of return value as preconditions are satisfied
89 pldm_bios_table_append_pad_checksum_check(table.data(), table.size(),
90 &payloadSize);
John Wangd9659342020-02-27 16:46:05 +080091}
92
John Wang29683b52020-02-27 16:41:44 +080093namespace string
94{
John Wang29683b52020-02-27 16:41:44 +080095uint16_t decodeHandle(const pldm_bios_string_table_entry* entry)
John Wange2efdcc2020-02-12 17:02:06 +080096{
97 return pldm_bios_table_string_entry_decode_handle(entry);
98}
99
John Wang29683b52020-02-27 16:41:44 +0800100std::string decodeString(const pldm_bios_string_table_entry* entry)
John Wange2efdcc2020-02-12 17:02:06 +0800101{
102 auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
103 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930104 // Preconditions are upheld therefore no error check necessary
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000105 pldm_bios_table_string_entry_decode_string(entry, buffer.data(),
106 buffer.size());
John Wange2efdcc2020-02-12 17:02:06 +0800107 return std::string(buffer.data(), buffer.data() + strLength);
John Wange297b9f2020-02-03 10:18:13 +0800108}
John Wangd9659342020-02-27 16:46:05 +0800109const 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);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930115 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery51d2ef22024-08-01 13:15:36 +0000116 pldm_bios_table_string_entry_encode(table.data() + tableSize, entryLength,
117 str.c_str(), str.length());
John Wangd9659342020-02-27 16:46:05 +0800118 return reinterpret_cast<pldm_bios_string_table_entry*>(table.data() +
119 tableSize);
120}
John Wange297b9f2020-02-03 10:18:13 +0800121
John Wang29683b52020-02-27 16:41:44 +0800122} // namespace string
123
124namespace attribute
125{
John Wang29683b52020-02-27 16:41:44 +0800126TableHeader 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
John Wangd9659342020-02-27 16:46:05 +0800134const 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
John Wang45fed202020-04-01 16:42:26 +0800141const 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
John Wang29683b52020-02-27 16:41:44 +0800148const 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);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930157 int rc = pldm_bios_table_attr_entry_string_encode_check(
158 table.data() + tableSize, entryLength, info);
159 if (rc != PLDM_SUCCESS)
160 {
Riya Dixit89644442024-03-31 05:39:59 -0500161 error("Failed to encode BIOS table string entry, response code '{RC}'",
162 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930163 throw std::runtime_error("Failed to encode BIOS table string entry");
164 }
John Wang29683b52020-02-27 16:41:44 +0800165 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
166 tableSize);
167}
168
John Wang95e6b3c2020-02-13 09:43:24 +0800169const pldm_bios_attr_table_entry*
170 constructIntegerEntry(Table& table,
171 pldm_bios_table_attr_entry_integer_info* info)
172{
173 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
174 auto tableSize = table.size();
175 table.resize(tableSize + entryLength, 0);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930176 int rc = pldm_bios_table_attr_entry_integer_encode_check(
177 table.data() + tableSize, entryLength, info);
178 if (rc != PLDM_SUCCESS)
179 {
Riya Dixit89644442024-03-31 05:39:59 -0500180 error(
181 "Failed to encode BIOS attribute table integer entry, response code '{RC}'",
182 "RC", rc);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930183 throw std::runtime_error(
184 "Failed to encode BIOS attribute table integer entry");
185 }
John Wang95e6b3c2020-02-13 09:43:24 +0800186 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
187 tableSize);
188}
189
John Wang29683b52020-02-27 16:41:44 +0800190StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry)
191{
192 auto strType = pldm_bios_table_attr_entry_string_decode_string_type(entry);
193 auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
194 auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930195 uint16_t defLength;
196 int rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
197 entry, &defLength);
198 if (rc != PLDM_SUCCESS)
199 {
Riya Dixit89644442024-03-31 05:39:59 -0500200 error(
201 "Failed to decode BIOS table string definition length, response code '{RC}'",
202 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930203 throw std::runtime_error(
204 "Failed to decode BIOS table string definitionlength");
205 }
John Wang29683b52020-02-27 16:41:44 +0800206
207 std::vector<char> buffer(defLength + 1);
208 pldm_bios_table_attr_entry_string_decode_def_string(entry, buffer.data(),
209 buffer.size());
210 return {strType, minLength, maxLength, defLength,
211 std::string(buffer.data(), buffer.data() + defLength)};
212}
213
John Wang95e6b3c2020-02-13 09:43:24 +0800214IntegerField decodeIntegerEntry(const pldm_bios_attr_table_entry* entry)
215{
216 uint64_t lower, upper, def;
217 uint32_t scalar;
218
219 pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar,
220 &def);
221 return {lower, upper, scalar, def};
222}
223
John Wang3be70852020-02-13 15:59:04 +0800224const pldm_bios_attr_table_entry*
225 constructEnumEntry(Table& table, pldm_bios_table_attr_entry_enum_info* info)
226{
227 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
228 info->pv_num, info->def_num);
229
230 auto tableSize = table.size();
231 table.resize(tableSize + entryLength, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930232 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery04883152024-08-01 13:15:36 +0000233 pldm_bios_table_attr_entry_enum_encode(table.data() + tableSize,
234 entryLength, info);
John Wang3be70852020-02-13 15:59:04 +0800235
236 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
237 tableSize);
238}
239
240EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry)
241{
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930242 uint8_t pvNum;
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000243 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num(entry, &pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930244 if (rc != PLDM_SUCCESS)
245 {
Riya Dixit89644442024-03-31 05:39:59 -0500246 error(
247 "Failed to decode the number of possible values for BIOS table enum entry, response code '{RC}'",
248 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930249 throw std::runtime_error(
250 "Failed to decode the number of possible values for BIOS table enum entry");
251 }
John Wang3be70852020-02-13 15:59:04 +0800252 std::vector<uint16_t> pvHdls(pvNum, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930253 // Preconditions are upheld therefore no error check necessary
254 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(entry, pvHdls.data(),
255 pvNum);
256 // Preconditions are upheld therefore no error check necessary
257 uint8_t defNum;
258 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNum);
John Wang3be70852020-02-13 15:59:04 +0800259 std::vector<uint8_t> defIndices(defNum, 0);
260 pldm_bios_table_attr_entry_enum_decode_def_indices(entry, defIndices.data(),
261 defIndices.size());
262 return {pvHdls, defIndices};
263}
264
John Wang29683b52020-02-27 16:41:44 +0800265} // namespace attribute
266
267namespace attribute_value
268{
John Wang29683b52020-02-27 16:41:44 +0800269TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry)
270{
271 auto handle =
272 pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
273 auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
274 return {handle, type};
275}
276
277std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry)
278{
279 variable_field currentString{};
280 pldm_bios_table_attr_value_entry_string_decode_string(entry,
281 &currentString);
282 return std::string(currentString.ptr,
283 currentString.ptr + currentString.length);
284}
285
John Wang95e6b3c2020-02-13 09:43:24 +0800286uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry)
287{
288 return pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
289}
290
John Wang3be70852020-02-13 15:59:04 +0800291std::vector<uint8_t>
292 decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry)
293{
294 auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
295 std::vector<uint8_t> currHdls(number, 0);
296 pldm_bios_table_attr_value_entry_enum_decode_handles(entry, currHdls.data(),
297 currHdls.size());
298 return currHdls;
299}
300
John Wang29683b52020-02-27 16:41:44 +0800301const pldm_bios_attr_val_table_entry*
302 constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
303 const std::string& str)
304{
305 auto strLen = str.size();
306 auto entryLength =
307 pldm_bios_table_attr_value_entry_encode_string_length(strLen);
308 auto tableSize = table.size();
309 table.resize(tableSize + entryLength);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930310 int rc = pldm_bios_table_attr_value_entry_encode_string_check(
John Wang29683b52020-02-27 16:41:44 +0800311 table.data() + tableSize, entryLength, attrHandle, attrType, strLen,
312 str.c_str());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930313 if (rc != PLDM_SUCCESS)
314 {
Riya Dixit89644442024-03-31 05:39:59 -0500315 error(
316 "Failed to encode BIOS attribute table string entry, response code '{RC}'",
317 "RC", rc);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930318 throw std::runtime_error(
319 "Failed to encode BIOS attribute table string entry");
320 }
John Wang29683b52020-02-27 16:41:44 +0800321 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
322 tableSize);
323}
John Wang95e6b3c2020-02-13 09:43:24 +0800324
325const pldm_bios_attr_val_table_entry* constructIntegerEntry(Table& table,
326 uint16_t attrHandle,
327 uint8_t attrType,
328 uint64_t value)
329{
330 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
331
332 auto tableSize = table.size();
333 table.resize(tableSize + entryLength);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930334 int rc = pldm_bios_table_attr_value_entry_encode_integer_check(
John Wang95e6b3c2020-02-13 09:43:24 +0800335 table.data() + tableSize, entryLength, attrHandle, attrType, value);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930336 if (rc != PLDM_SUCCESS)
337 {
Riya Dixit89644442024-03-31 05:39:59 -0500338 error(
339 "Failed to encode BIOS attribute table integer entry, response code '{RC}'",
340 "RC", rc);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930341 throw std::runtime_error(
342 "Failed to encode BIOS attribute table integery entry");
343 }
John Wang95e6b3c2020-02-13 09:43:24 +0800344 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
345 tableSize);
346}
347
John Wang3be70852020-02-13 15:59:04 +0800348const pldm_bios_attr_val_table_entry*
349 constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
350 const std::vector<uint8_t>& handleIndices)
351{
352 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
353 handleIndices.size());
354 auto tableSize = table.size();
355 table.resize(tableSize + entryLength);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930356 int rc = pldm_bios_table_attr_value_entry_encode_enum_check(
John Wang3be70852020-02-13 15:59:04 +0800357 table.data() + tableSize, entryLength, attrHandle, attrType,
358 handleIndices.size(), handleIndices.data());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930359 if (rc != PLDM_SUCCESS)
360 {
Riya Dixit89644442024-03-31 05:39:59 -0500361 error(
362 "Failed to encode BIOS attribute table enum entry, response code '{RC}'",
363 "RC", rc);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930364 throw std::runtime_error(
365 "Failed to encode BIOS attribute table enum entry");
366 }
John Wang3be70852020-02-13 15:59:04 +0800367 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
368 tableSize);
369}
370
John Wangd9659342020-02-27 16:46:05 +0800371std::optional<Table> updateTable(const Table& table, const void* entry,
372 size_t size)
373{
374 // Replace the old attribute with the new attribute, the size of table will
375 // change:
376 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
377 // sizeof(oldAttribute) + pad(4-byte alignment, max =
378 // 3)
379 // For simplicity, we use
380 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
381 size_t destBufferLength = table.size() + size + 3;
382 Table destTable(destBufferLength);
383
384 auto rc = pldm_bios_table_attr_value_copy_and_update(
385 table.data(), table.size(), destTable.data(), &destBufferLength, entry,
386 size);
387 if (rc != PLDM_SUCCESS)
388 {
389 return std::nullopt;
390 }
391 destTable.resize(destBufferLength);
392
393 return destTable;
394}
John Wang29683b52020-02-27 16:41:44 +0800395
396} // namespace attribute_value
397
398} // namespace table
399
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +0530400} // namespace bios
401} // namespace responder
402} // namespace pldm