blob: 17bb79b75037dad2a414f11e152d68cbf51b686c [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
Andrew Jeffery0eb5bce2024-08-01 13:15:36 +000089 pldm_bios_table_append_pad_checksum(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}
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400109const pldm_bios_string_table_entry*
110 constructEntry(Table& table, const std::string& str)
John Wangd9659342020-02-27 16:46:05 +0800111{
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());
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400118 return reinterpret_cast<pldm_bios_string_table_entry*>(
119 table.data() + tableSize);
John Wangd9659342020-02-27 16:46:05 +0800120}
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
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400134const pldm_bios_attr_table_entry*
135 findByHandle(const Table& table, uint16_t handle)
John Wangd9659342020-02-27 16:46:05 +0800136{
137 return pldm_bios_table_attr_find_by_handle(table.data(), table.size(),
138 handle);
139}
140
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400141const pldm_bios_attr_table_entry*
142 findByStringHandle(const Table& table, uint16_t handle)
John Wang45fed202020-04-01 16:42:26 +0800143{
144 return pldm_bios_table_attr_find_by_string_handle(table.data(),
145 table.size(), handle);
146}
147
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400148const pldm_bios_attr_table_entry* constructStringEntry(
149 Table& table, pldm_bios_table_attr_entry_string_info* info)
John Wang29683b52020-02-27 16:41:44 +0800150{
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 Jefferybc28b912024-08-01 13:15:36 +0000156 int rc = pldm_bios_table_attr_entry_string_encode(table.data() + tableSize,
157 entryLength, info);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930158 if (rc != PLDM_SUCCESS)
159 {
Riya Dixit89644442024-03-31 05:39:59 -0500160 error("Failed to encode BIOS table string entry, response code '{RC}'",
161 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930162 throw std::runtime_error("Failed to encode BIOS table string entry");
163 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400164 return reinterpret_cast<pldm_bios_attr_table_entry*>(
165 table.data() + tableSize);
John Wang29683b52020-02-27 16:41:44 +0800166}
167
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400168const pldm_bios_attr_table_entry* constructIntegerEntry(
169 Table& table, pldm_bios_table_attr_entry_integer_info* info)
John Wang95e6b3c2020-02-13 09:43:24 +0800170{
171 auto entryLength = pldm_bios_table_attr_entry_integer_encode_length();
172 auto tableSize = table.size();
173 table.resize(tableSize + entryLength, 0);
Andrew Jeffery228dae32024-08-01 13:15:36 +0000174 int rc = pldm_bios_table_attr_entry_integer_encode(table.data() + tableSize,
175 entryLength, info);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930176 if (rc != PLDM_SUCCESS)
177 {
Riya Dixit89644442024-03-31 05:39:59 -0500178 error(
179 "Failed to encode BIOS attribute table integer entry, response code '{RC}'",
180 "RC", rc);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930181 throw std::runtime_error(
182 "Failed to encode BIOS attribute table integer entry");
183 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400184 return reinterpret_cast<pldm_bios_attr_table_entry*>(
185 table.data() + tableSize);
John Wang95e6b3c2020-02-13 09:43:24 +0800186}
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;
Andrew Jeffery53e342a2024-08-01 13:15:36 +0000194 int rc = pldm_bios_table_attr_entry_string_decode_def_string_length(
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930195 entry, &defLength);
196 if (rc != PLDM_SUCCESS)
197 {
Riya Dixit89644442024-03-31 05:39:59 -0500198 error(
199 "Failed to decode BIOS table string definition length, response code '{RC}'",
200 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930201 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
Andrew Jeffery04883152024-08-01 13:15:36 +0000231 pldm_bios_table_attr_entry_enum_encode(table.data() + tableSize,
232 entryLength, info);
John Wang3be70852020-02-13 15:59:04 +0800233
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400234 return reinterpret_cast<pldm_bios_attr_table_entry*>(
235 table.data() + tableSize);
John Wang3be70852020-02-13 15:59:04 +0800236}
237
238EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry)
239{
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930240 uint8_t pvNum;
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000241 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num(entry, &pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930242 if (rc != PLDM_SUCCESS)
243 {
Riya Dixit89644442024-03-31 05:39:59 -0500244 error(
245 "Failed to decode the number of possible values for BIOS table enum entry, response code '{RC}'",
246 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930247 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
Andrew Jeffery24611052024-08-01 13:15:36 +0000252 pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pvHdls.data(), pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930253 // Preconditions are upheld therefore no error check necessary
254 uint8_t defNum;
Andrew Jefferyff3fb9e2024-08-01 13:15:36 +0000255 pldm_bios_table_attr_entry_enum_decode_def_num(entry, &defNum);
John Wang3be70852020-02-13 15:59:04 +0800256 std::vector<uint8_t> defIndices(defNum, 0);
257 pldm_bios_table_attr_entry_enum_decode_def_indices(entry, defIndices.data(),
258 defIndices.size());
259 return {pvHdls, defIndices};
260}
261
John Wang29683b52020-02-27 16:41:44 +0800262} // namespace attribute
263
264namespace attribute_value
265{
John Wang29683b52020-02-27 16:41:44 +0800266TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry)
267{
268 auto handle =
269 pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
270 auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
271 return {handle, type};
272}
273
274std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry)
275{
276 variable_field currentString{};
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400277 pldm_bios_table_attr_value_entry_string_decode_string(
278 entry, &currentString);
John Wang29683b52020-02-27 16:41:44 +0800279 return std::string(currentString.ptr,
280 currentString.ptr + currentString.length);
281}
282
John Wang95e6b3c2020-02-13 09:43:24 +0800283uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry)
284{
285 return pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
286}
287
John Wang3be70852020-02-13 15:59:04 +0800288std::vector<uint8_t>
289 decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry)
290{
291 auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
292 std::vector<uint8_t> currHdls(number, 0);
293 pldm_bios_table_attr_value_entry_enum_decode_handles(entry, currHdls.data(),
294 currHdls.size());
295 return currHdls;
296}
297
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400298const pldm_bios_attr_val_table_entry* constructStringEntry(
299 Table& table, uint16_t attrHandle, uint8_t attrType, const std::string& str)
John Wang29683b52020-02-27 16:41:44 +0800300{
301 auto strLen = str.size();
302 auto entryLength =
303 pldm_bios_table_attr_value_entry_encode_string_length(strLen);
304 auto tableSize = table.size();
305 table.resize(tableSize + entryLength);
Andrew Jeffery25d38782024-08-01 13:15:36 +0000306 int rc = pldm_bios_table_attr_value_entry_encode_string(
John Wang29683b52020-02-27 16:41:44 +0800307 table.data() + tableSize, entryLength, attrHandle, attrType, strLen,
308 str.c_str());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930309 if (rc != PLDM_SUCCESS)
310 {
Riya Dixit89644442024-03-31 05:39:59 -0500311 error(
312 "Failed to encode BIOS attribute table string entry, response code '{RC}'",
313 "RC", rc);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930314 throw std::runtime_error(
315 "Failed to encode BIOS attribute table string entry");
316 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400317 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(
318 table.data() + tableSize);
John Wang29683b52020-02-27 16:41:44 +0800319}
John Wang95e6b3c2020-02-13 09:43:24 +0800320
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400321const pldm_bios_attr_val_table_entry* constructIntegerEntry(
322 Table& table, uint16_t attrHandle, uint8_t attrType, uint64_t value)
John Wang95e6b3c2020-02-13 09:43:24 +0800323{
324 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
325
326 auto tableSize = table.size();
327 table.resize(tableSize + entryLength);
Andrew Jefferya5f2fcd2024-08-01 13:15:36 +0000328 int rc = pldm_bios_table_attr_value_entry_encode_integer(
John Wang95e6b3c2020-02-13 09:43:24 +0800329 table.data() + tableSize, entryLength, attrHandle, attrType, value);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930330 if (rc != PLDM_SUCCESS)
331 {
Riya Dixit89644442024-03-31 05:39:59 -0500332 error(
333 "Failed to encode BIOS attribute table integer entry, response code '{RC}'",
334 "RC", rc);
Andrew Jefferyc727fb42023-07-12 09:19:02 +0930335 throw std::runtime_error(
336 "Failed to encode BIOS attribute table integery entry");
337 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400338 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(
339 table.data() + tableSize);
John Wang95e6b3c2020-02-13 09:43:24 +0800340}
341
John Wang3be70852020-02-13 15:59:04 +0800342const pldm_bios_attr_val_table_entry*
343 constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
344 const std::vector<uint8_t>& handleIndices)
345{
346 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
347 handleIndices.size());
348 auto tableSize = table.size();
349 table.resize(tableSize + entryLength);
Andrew Jeffery4663aae2024-08-01 13:15:36 +0000350 int rc = pldm_bios_table_attr_value_entry_encode_enum(
John Wang3be70852020-02-13 15:59:04 +0800351 table.data() + tableSize, entryLength, attrHandle, attrType,
352 handleIndices.size(), handleIndices.data());
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930353 if (rc != PLDM_SUCCESS)
354 {
Riya Dixit89644442024-03-31 05:39:59 -0500355 error(
356 "Failed to encode BIOS attribute table enum entry, response code '{RC}'",
357 "RC", rc);
Andrew Jefferyd15ecf92023-06-27 15:57:22 +0930358 throw std::runtime_error(
359 "Failed to encode BIOS attribute table enum entry");
360 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400361 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(
362 table.data() + tableSize);
John Wang3be70852020-02-13 15:59:04 +0800363}
364
John Wangd9659342020-02-27 16:46:05 +0800365std::optional<Table> updateTable(const Table& table, const void* entry,
366 size_t size)
367{
368 // Replace the old attribute with the new attribute, the size of table will
369 // change:
370 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
371 // sizeof(oldAttribute) + pad(4-byte alignment, max =
372 // 3)
373 // For simplicity, we use
374 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
375 size_t destBufferLength = table.size() + size + 3;
376 Table destTable(destBufferLength);
377
378 auto rc = pldm_bios_table_attr_value_copy_and_update(
379 table.data(), table.size(), destTable.data(), &destBufferLength, entry,
380 size);
381 if (rc != PLDM_SUCCESS)
382 {
383 return std::nullopt;
384 }
385 destTable.resize(destBufferLength);
386
387 return destTable;
388}
John Wang29683b52020-02-27 16:41:44 +0800389
390} // namespace attribute_value
391
392} // namespace table
393
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +0530394} // namespace bios
395} // namespace responder
396} // namespace pldm