blob: 3b2a42bcf2ea5c13c8e8ef1d0ca69e0a5c264c6a [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 Jefferybc28b912024-08-01 13:15:36 +0000157 int rc = pldm_bios_table_attr_entry_string_encode(table.data() + tableSize,
158 entryLength, info);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930159 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 Jeffery228dae32024-08-01 13:15:36 +0000176 int rc = pldm_bios_table_attr_entry_integer_encode(table.data() + tableSize,
177 entryLength, info);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930178 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;
Andrew Jeffery53e342a2024-08-01 13:15:36 +0000196 int rc = pldm_bios_table_attr_entry_string_decode_def_string_length(
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930197 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
Andrew Jeffery24611052024-08-01 13:15:36 +0000254 pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pvHdls.data(), pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930255 // Preconditions are upheld therefore no error check necessary
256 uint8_t defNum;
Andrew Jefferyff3fb9e2024-08-01 13:15:36 +0000257 pldm_bios_table_attr_entry_enum_decode_def_num(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 {
Riya Dixit89644442024-03-31 05:39:59 -0500314 error(
315 "Failed to encode BIOS attribute table string entry, response code '{RC}'",
316 "RC", rc);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930317 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);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930333 int rc = pldm_bios_table_attr_value_entry_encode_integer_check(
John Wang95e6b3c2020-02-13 09:43:24 +0800334 table.data() + tableSize, entryLength, attrHandle, attrType, value);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930335 if (rc != PLDM_SUCCESS)
336 {
Riya Dixit89644442024-03-31 05:39:59 -0500337 error(
338 "Failed to encode BIOS attribute table integer entry, response code '{RC}'",
339 "RC", rc);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930340 throw std::runtime_error(
341 "Failed to encode BIOS attribute table integery entry");
342 }
John Wang95e6b3c2020-02-13 09:43:24 +0800343 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
344 tableSize);
345}
346
John Wang3be70852020-02-13 15:59:04 +0800347const pldm_bios_attr_val_table_entry*
348 constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
349 const std::vector<uint8_t>& handleIndices)
350{
351 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
352 handleIndices.size());
353 auto tableSize = table.size();
354 table.resize(tableSize + entryLength);
Andrew Jeffery4663aae2024-08-01 13:15:36 +0000355 int rc = pldm_bios_table_attr_value_entry_encode_enum(
John Wang3be70852020-02-13 15:59:04 +0800356 table.data() + tableSize, entryLength, attrHandle, attrType,
357 handleIndices.size(), handleIndices.data());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930358 if (rc != PLDM_SUCCESS)
359 {
Riya Dixit89644442024-03-31 05:39:59 -0500360 error(
361 "Failed to encode BIOS attribute table enum entry, response code '{RC}'",
362 "RC", rc);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930363 throw std::runtime_error(
364 "Failed to encode BIOS attribute table enum entry");
365 }
John Wang3be70852020-02-13 15:59:04 +0800366 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
367 tableSize);
368}
369
John Wangd9659342020-02-27 16:46:05 +0800370std::optional<Table> updateTable(const Table& table, const void* entry,
371 size_t size)
372{
373 // Replace the old attribute with the new attribute, the size of table will
374 // change:
375 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
376 // sizeof(oldAttribute) + pad(4-byte alignment, max =
377 // 3)
378 // For simplicity, we use
379 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
380 size_t destBufferLength = table.size() + size + 3;
381 Table destTable(destBufferLength);
382
383 auto rc = pldm_bios_table_attr_value_copy_and_update(
384 table.data(), table.size(), destTable.data(), &destBufferLength, entry,
385 size);
386 if (rc != PLDM_SUCCESS)
387 {
388 return std::nullopt;
389 }
390 destTable.resize(destBufferLength);
391
392 return destTable;
393}
John Wang29683b52020-02-27 16:41:44 +0800394
395} // namespace attribute_value
396
397} // namespace table
398
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +0530399} // namespace bios
400} // namespace responder
401} // namespace pldm