blob: 898a34ad8843661ba36a622083ebaf6f23fe34c7 [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 }
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);
176 pldm_bios_table_attr_entry_integer_encode(table.data() + tableSize,
177 entryLength, info);
178 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
179 tableSize);
180}
181
John Wang29683b52020-02-27 16:41:44 +0800182StringField decodeStringEntry(const pldm_bios_attr_table_entry* entry)
183{
184 auto strType = pldm_bios_table_attr_entry_string_decode_string_type(entry);
185 auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
186 auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930187 uint16_t defLength;
188 int rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
189 entry, &defLength);
190 if (rc != PLDM_SUCCESS)
191 {
192 lg2::error(
193 "Failed to decode BIOS table string definition length: {LIBPLDM_ERROR}",
194 "LIBPLDM_ERROR", rc);
195 throw std::runtime_error(
196 "Failed to decode BIOS table string definitionlength");
197 }
John Wang29683b52020-02-27 16:41:44 +0800198
199 std::vector<char> buffer(defLength + 1);
200 pldm_bios_table_attr_entry_string_decode_def_string(entry, buffer.data(),
201 buffer.size());
202 return {strType, minLength, maxLength, defLength,
203 std::string(buffer.data(), buffer.data() + defLength)};
204}
205
John Wang95e6b3c2020-02-13 09:43:24 +0800206IntegerField decodeIntegerEntry(const pldm_bios_attr_table_entry* entry)
207{
208 uint64_t lower, upper, def;
209 uint32_t scalar;
210
211 pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar,
212 &def);
213 return {lower, upper, scalar, def};
214}
215
John Wang3be70852020-02-13 15:59:04 +0800216const pldm_bios_attr_table_entry*
217 constructEnumEntry(Table& table, pldm_bios_table_attr_entry_enum_info* info)
218{
219 auto entryLength = pldm_bios_table_attr_entry_enum_encode_length(
220 info->pv_num, info->def_num);
221
222 auto tableSize = table.size();
223 table.resize(tableSize + entryLength, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930224 // Preconditions are upheld therefore no error check necessary
225 pldm_bios_table_attr_entry_enum_encode_check(table.data() + tableSize,
226 entryLength, info);
John Wang3be70852020-02-13 15:59:04 +0800227
228 return reinterpret_cast<pldm_bios_attr_table_entry*>(table.data() +
229 tableSize);
230}
231
232EnumField decodeEnumEntry(const pldm_bios_attr_table_entry* entry)
233{
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930234 uint8_t pvNum;
235 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNum);
236 if (rc != PLDM_SUCCESS)
237 {
238 lg2::error(
239 "Failed to decode the number of possible values for BIOS table enum entry: {LIBPLDM_ERROR}",
240 "LIBPLDM_ERROR", rc);
241 throw std::runtime_error(
242 "Failed to decode the number of possible values for BIOS table enum entry");
243 }
John Wang3be70852020-02-13 15:59:04 +0800244 std::vector<uint16_t> pvHdls(pvNum, 0);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930245 // Preconditions are upheld therefore no error check necessary
246 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(entry, pvHdls.data(),
247 pvNum);
248 // Preconditions are upheld therefore no error check necessary
249 uint8_t defNum;
250 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNum);
John Wang3be70852020-02-13 15:59:04 +0800251 std::vector<uint8_t> defIndices(defNum, 0);
252 pldm_bios_table_attr_entry_enum_decode_def_indices(entry, defIndices.data(),
253 defIndices.size());
254 return {pvHdls, defIndices};
255}
256
John Wang29683b52020-02-27 16:41:44 +0800257} // namespace attribute
258
259namespace attribute_value
260{
John Wang29683b52020-02-27 16:41:44 +0800261TableHeader decodeHeader(const pldm_bios_attr_val_table_entry* entry)
262{
263 auto handle =
264 pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
265 auto type = pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
266 return {handle, type};
267}
268
269std::string decodeStringEntry(const pldm_bios_attr_val_table_entry* entry)
270{
271 variable_field currentString{};
272 pldm_bios_table_attr_value_entry_string_decode_string(entry,
273 &currentString);
274 return std::string(currentString.ptr,
275 currentString.ptr + currentString.length);
276}
277
John Wang95e6b3c2020-02-13 09:43:24 +0800278uint64_t decodeIntegerEntry(const pldm_bios_attr_val_table_entry* entry)
279{
280 return pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
281}
282
John Wang3be70852020-02-13 15:59:04 +0800283std::vector<uint8_t>
284 decodeEnumEntry(const pldm_bios_attr_val_table_entry* entry)
285{
286 auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
287 std::vector<uint8_t> currHdls(number, 0);
288 pldm_bios_table_attr_value_entry_enum_decode_handles(entry, currHdls.data(),
289 currHdls.size());
290 return currHdls;
291}
292
John Wang29683b52020-02-27 16:41:44 +0800293const pldm_bios_attr_val_table_entry*
294 constructStringEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
295 const std::string& str)
296{
297 auto strLen = str.size();
298 auto entryLength =
299 pldm_bios_table_attr_value_entry_encode_string_length(strLen);
300 auto tableSize = table.size();
301 table.resize(tableSize + entryLength);
302 pldm_bios_table_attr_value_entry_encode_string(
303 table.data() + tableSize, entryLength, attrHandle, attrType, strLen,
304 str.c_str());
305 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
306 tableSize);
307}
John Wang95e6b3c2020-02-13 09:43:24 +0800308
309const pldm_bios_attr_val_table_entry* constructIntegerEntry(Table& table,
310 uint16_t attrHandle,
311 uint8_t attrType,
312 uint64_t value)
313{
314 auto entryLength = pldm_bios_table_attr_value_entry_encode_integer_length();
315
316 auto tableSize = table.size();
317 table.resize(tableSize + entryLength);
318 pldm_bios_table_attr_value_entry_encode_integer(
319 table.data() + tableSize, entryLength, attrHandle, attrType, value);
320 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
321 tableSize);
322}
323
John Wang3be70852020-02-13 15:59:04 +0800324const pldm_bios_attr_val_table_entry*
325 constructEnumEntry(Table& table, uint16_t attrHandle, uint8_t attrType,
326 const std::vector<uint8_t>& handleIndices)
327{
328 auto entryLength = pldm_bios_table_attr_value_entry_encode_enum_length(
329 handleIndices.size());
330 auto tableSize = table.size();
331 table.resize(tableSize + entryLength);
332 pldm_bios_table_attr_value_entry_encode_enum(
333 table.data() + tableSize, entryLength, attrHandle, attrType,
334 handleIndices.size(), handleIndices.data());
335 return reinterpret_cast<pldm_bios_attr_val_table_entry*>(table.data() +
336 tableSize);
337}
338
John Wangd9659342020-02-27 16:46:05 +0800339std::optional<Table> updateTable(const Table& table, const void* entry,
340 size_t size)
341{
342 // Replace the old attribute with the new attribute, the size of table will
343 // change:
344 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) -
345 // sizeof(oldAttribute) + pad(4-byte alignment, max =
346 // 3)
347 // For simplicity, we use
348 // sizeof(newTableBuffer) = srcTableSize + sizeof(newAttribute) + 3
349 size_t destBufferLength = table.size() + size + 3;
350 Table destTable(destBufferLength);
351
352 auto rc = pldm_bios_table_attr_value_copy_and_update(
353 table.data(), table.size(), destTable.data(), &destBufferLength, entry,
354 size);
355 if (rc != PLDM_SUCCESS)
356 {
357 return std::nullopt;
358 }
359 destTable.resize(destBufferLength);
360
361 return destTable;
362}
John Wang29683b52020-02-27 16:41:44 +0800363
364} // namespace attribute_value
365
366} // namespace table
367
Deepak Kodihallicb7f2d42019-06-19 13:25:31 +0530368} // namespace bios
369} // namespace responder
370} // namespace pldm