blob: 8b52a8c412e54c056f4f358448f17ca6b856af2e [file] [log] [blame]
John Wangd9659342020-02-27 16:46:05 +08001#include "bios_config.hpp"
2
John Wang3be70852020-02-13 15:59:04 +08003#include "bios_enum_attribute.hpp"
John Wang95e6b3c2020-02-13 09:43:24 +08004#include "bios_integer_attribute.hpp"
John Wangd9659342020-02-27 16:46:05 +08005#include "bios_string_attribute.hpp"
Sampa Misra46ece062020-03-18 07:17:44 -05006#include "bios_table.hpp"
George Liu1b180d82020-07-23 14:01:58 +08007#include "common/bios_utils.hpp"
John Wangd9659342020-02-27 16:46:05 +08008
Riya Dixit49cfb132023-03-02 04:26:53 -06009#include <phosphor-logging/lg2.hpp>
George Liu1244acf2020-08-14 09:11:11 +080010#include <xyz/openbmc_project/BIOSConfig/Manager/server.hpp>
11
John Wangd9659342020-02-27 16:46:05 +080012#include <fstream>
13#include <iostream>
14
Tom Joseph7f839f92020-09-21 10:20:44 +053015#ifdef OEM_IBM
16#include "oem/ibm/libpldmresponder/platform_oem_ibm.hpp"
17#endif
18
Riya Dixit49cfb132023-03-02 04:26:53 -060019PHOSPHOR_LOG2_USING;
20
Brad Bishop5079ac42021-08-19 18:35:06 -040021using namespace pldm::utils;
22
John Wangd9659342020-02-27 16:46:05 +080023namespace pldm
24{
25namespace responder
26{
27namespace bios
28{
29namespace
30{
George Liu1244acf2020-08-14 09:11:11 +080031using BIOSConfigManager =
32 sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager;
33
John Wangd9659342020-02-27 16:46:05 +080034constexpr auto enumJsonFile = "enum_attrs.json";
35constexpr auto stringJsonFile = "string_attrs.json";
36constexpr auto integerJsonFile = "integer_attrs.json";
37
38constexpr auto stringTableFile = "stringTable";
39constexpr auto attrTableFile = "attributeTable";
40constexpr auto attrValueTableFile = "attributeValueTable";
41
42} // namespace
43
Sampa Misrac0c79482021-06-02 08:01:54 -050044BIOSConfig::BIOSConfig(
45 const char* jsonDir, const char* tableDir, DBusHandler* const dbusHandler,
Andrew Jefferya330b2f2023-05-04 14:55:37 +093046 int fd, uint8_t eid, pldm::InstanceIdDb* instanceIdDb,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050047 pldm::requester::Handler<pldm::requester::Request>* handler,
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060048 pldm::responder::platform_config::Handler* platformConfigHandler) :
John Wangd9659342020-02-27 16:46:05 +080049 jsonDir(jsonDir),
Tom Joseph7f839f92020-09-21 10:20:44 +053050 tableDir(tableDir), dbusHandler(dbusHandler), fd(fd), eid(eid),
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060051 instanceIdDb(instanceIdDb), handler(handler),
52 platformConfigHandler(platformConfigHandler)
Tom Joseph7f839f92020-09-21 10:20:44 +053053
John Wangd9659342020-02-27 16:46:05 +080054{
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060055 if (platformConfigHandler)
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050056 {
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060057 auto systemType = platformConfigHandler->getPlatformName();
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050058 if (systemType.has_value())
59 {
60 sysType = systemType.value();
61 }
62 }
George Liu9d8921e2020-05-14 15:41:50 +080063 fs::create_directories(tableDir);
John Wangd9659342020-02-27 16:46:05 +080064 constructAttributes();
George Liu1244acf2020-08-14 09:11:11 +080065 listenPendingAttributes();
John Wangd9659342020-02-27 16:46:05 +080066}
67
68void BIOSConfig::buildTables()
69{
John Wangd9659342020-02-27 16:46:05 +080070 auto stringTable = buildAndStoreStringTable();
71 if (stringTable)
72 {
73 buildAndStoreAttrTables(*stringTable);
74 }
75}
76
77std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
78{
79 fs::path tablePath;
80 switch (tableType)
81 {
82 case PLDM_BIOS_STRING_TABLE:
83 tablePath = tableDir / stringTableFile;
84 break;
85 case PLDM_BIOS_ATTR_TABLE:
86 tablePath = tableDir / attrTableFile;
87 break;
88 case PLDM_BIOS_ATTR_VAL_TABLE:
89 tablePath = tableDir / attrValueTableFile;
90 break;
91 }
92 return loadTable(tablePath);
93}
94
Tom Joseph7f839f92020-09-21 10:20:44 +053095int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table,
96 bool updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +080097{
98 fs::path stringTablePath(tableDir / stringTableFile);
99 fs::path attrTablePath(tableDir / attrTableFile);
100 fs::path attrValueTablePath(tableDir / attrValueTableFile);
101
102 if (!pldm_bios_table_checksum(table.data(), table.size()))
103 {
104 return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
105 }
106
107 if (tableType == PLDM_BIOS_STRING_TABLE)
108 {
109 storeTable(stringTablePath, table);
110 }
111 else if (tableType == PLDM_BIOS_ATTR_TABLE)
112 {
113 BIOSTable biosStringTable(stringTablePath.c_str());
114 if (biosStringTable.isEmpty())
115 {
116 return PLDM_INVALID_BIOS_TABLE_TYPE;
117 }
118
119 auto rc = checkAttributeTable(table);
120 if (rc != PLDM_SUCCESS)
121 {
122 return rc;
123 }
124
125 storeTable(attrTablePath, table);
126 }
127 else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
128 {
129 BIOSTable biosStringTable(stringTablePath.c_str());
130 BIOSTable biosStringValueTable(attrTablePath.c_str());
131 if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
132 {
133 return PLDM_INVALID_BIOS_TABLE_TYPE;
134 }
135
136 auto rc = checkAttributeValueTable(table);
137 if (rc != PLDM_SUCCESS)
138 {
139 return rc;
140 }
141
142 storeTable(attrValueTablePath, table);
George Liu1b180d82020-07-23 14:01:58 +0800143 }
144 else
145 {
146 return PLDM_INVALID_BIOS_TABLE_TYPE;
147 }
148
Tom Joseph7f839f92020-09-21 10:20:44 +0530149 if ((tableType == PLDM_BIOS_ATTR_VAL_TABLE) && updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800150 {
George Liu1b180d82020-07-23 14:01:58 +0800151 updateBaseBIOSTableProperty();
152 }
153
154 return PLDM_SUCCESS;
155}
156
157int BIOSConfig::checkAttributeTable(const Table& table)
158{
159 using namespace pldm::bios::utils;
160 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
161 for (auto entry :
162 BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
163 {
164 auto attrNameHandle =
165 pldm_bios_table_attr_entry_decode_string_handle(entry);
166
167 auto stringEnty = pldm_bios_table_string_find_by_handle(
168 stringTable->data(), stringTable->size(), attrNameHandle);
169 if (stringEnty == nullptr)
170 {
171 return PLDM_INVALID_BIOS_ATTR_HANDLE;
172 }
173
174 auto attrType = static_cast<pldm_bios_attribute_type>(
175 pldm_bios_table_attr_entry_decode_attribute_type(entry));
176
177 switch (attrType)
178 {
179 case PLDM_BIOS_ENUMERATION:
180 case PLDM_BIOS_ENUMERATION_READ_ONLY:
181 {
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930182 uint8_t pvNum;
183 // Preconditions are upheld therefore no error check necessary
184 pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry,
185 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800186 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930187 // Preconditions are upheld therefore no error check necessary
188 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800189 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930190 uint8_t defNum;
191 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry,
192 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800193 std::vector<uint8_t> defIndices(defNum);
194 pldm_bios_table_attr_entry_enum_decode_def_indices(
195 entry, defIndices.data(), defIndices.size());
196
197 for (size_t i = 0; i < pvHandls.size(); i++)
198 {
199 auto stringEntry = pldm_bios_table_string_find_by_handle(
200 stringTable->data(), stringTable->size(), pvHandls[i]);
201 if (stringEntry == nullptr)
202 {
203 return PLDM_INVALID_BIOS_ATTR_HANDLE;
204 }
205 }
206
207 for (size_t i = 0; i < defIndices.size(); i++)
208 {
209 auto stringEntry = pldm_bios_table_string_find_by_handle(
210 stringTable->data(), stringTable->size(),
211 pvHandls[defIndices[i]]);
212 if (stringEntry == nullptr)
213 {
214 return PLDM_INVALID_BIOS_ATTR_HANDLE;
215 }
216 }
217 break;
218 }
219 case PLDM_BIOS_INTEGER:
220 case PLDM_BIOS_INTEGER_READ_ONLY:
221 case PLDM_BIOS_STRING:
222 case PLDM_BIOS_STRING_READ_ONLY:
223 case PLDM_BIOS_PASSWORD:
224 case PLDM_BIOS_PASSWORD_READ_ONLY:
225 break;
226 default:
227 return PLDM_INVALID_BIOS_ATTR_HANDLE;
228 }
229 }
230
231 return PLDM_SUCCESS;
232}
233
234int BIOSConfig::checkAttributeValueTable(const Table& table)
235{
236 using namespace pldm::bios::utils;
237 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
238 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
239
240 baseBIOSTableMaps.clear();
241
242 for (auto tableEntry :
243 BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
244 {
245 AttributeName attributeName{};
246 AttributeType attributeType{};
247 ReadonlyStatus readonlyStatus{};
248 DisplayName displayName{};
249 Description description{};
250 MenuPath menuPath{};
251 CurrentValue currentValue{};
252 DefaultValue defaultValue{};
Sagar Srinivas7927f902023-10-09 07:53:00 -0500253 std::vector<ValueDisplayName> valueDisplayNames;
254 std::map<uint16_t, std::vector<std::string>> valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800255 Option options{};
256
257 auto attrValueHandle =
258 pldm_bios_table_attr_value_entry_decode_attribute_handle(
259 tableEntry);
260 auto attrType = static_cast<pldm_bios_attribute_type>(
261 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
262
263 auto attrEntry = pldm_bios_table_attr_find_by_handle(
264 attrTable->data(), attrTable->size(), attrValueHandle);
265 if (attrEntry == nullptr)
266 {
267 return PLDM_INVALID_BIOS_ATTR_HANDLE;
268 }
269 auto attrHandle =
270 pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
271 auto attrNameHandle =
272 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
273
274 auto stringEntry = pldm_bios_table_string_find_by_handle(
275 stringTable->data(), stringTable->size(), attrNameHandle);
276 if (stringEntry == nullptr)
277 {
278 return PLDM_INVALID_BIOS_ATTR_HANDLE;
279 }
280 auto strLength =
281 pldm_bios_table_string_entry_decode_string_length(stringEntry);
282 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930283 // Preconditions are upheld therefore no error check necessary
284 pldm_bios_table_string_entry_decode_string_check(
285 stringEntry, buffer.data(), buffer.size());
286
George Liu1b180d82020-07-23 14:01:58 +0800287 attributeName = std::string(buffer.data(), buffer.data() + strLength);
288
289 if (!biosAttributes.empty())
290 {
291 readonlyStatus =
George Liub1fbeec2020-09-04 09:59:46 +0800292 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800293 description =
294 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
295 displayName =
296 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
Sagar Srinivas7927f902023-10-09 07:53:00 -0500297 valueDisplayNamesMap =
298 biosAttributes[attrHandle % biosAttributes.size()]
299 ->valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800300 }
301
302 switch (attrType)
303 {
304 case PLDM_BIOS_ENUMERATION:
305 case PLDM_BIOS_ENUMERATION_READ_ONLY:
306 {
Sagar Srinivas7927f902023-10-09 07:53:00 -0500307 if (valueDisplayNamesMap.contains(attrHandle))
308 {
309 const std::vector<ValueDisplayName>& vdn =
310 valueDisplayNamesMap[attrHandle];
311 valueDisplayNames.insert(valueDisplayNames.end(),
312 vdn.begin(), vdn.end());
313 }
George Liu1b180d82020-07-23 14:01:58 +0800314 auto getValue = [](uint16_t handle,
315 const Table& table) -> std::string {
316 auto stringEntry = pldm_bios_table_string_find_by_handle(
317 table.data(), table.size(), handle);
318
319 auto strLength =
320 pldm_bios_table_string_entry_decode_string_length(
321 stringEntry);
322 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930323 // Preconditions are upheld therefore no error check
324 // necessary
325 pldm_bios_table_string_entry_decode_string_check(
George Liu1b180d82020-07-23 14:01:58 +0800326 stringEntry, buffer.data(), buffer.size());
327
328 return std::string(buffer.data(),
329 buffer.data() + strLength);
330 };
331
332 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
333 "AttributeType.Enumeration";
334
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930335 uint8_t pvNum;
336 // Preconditions are upheld therefore no error check necessary
337 pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
338 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800339 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930340 // Preconditions are upheld therefore no error check necessary
341 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800342 attrEntry, pvHandls.data(), pvHandls.size());
343
344 // get possible_value
345 for (size_t i = 0; i < pvHandls.size(); i++)
346 {
347 options.push_back(
348 std::make_tuple("xyz.openbmc_project.BIOSConfig."
349 "Manager.BoundType.OneOf",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500350 getValue(pvHandls[i], *stringTable),
351 valueDisplayNames[i]));
George Liu1b180d82020-07-23 14:01:58 +0800352 }
353
354 auto count =
355 pldm_bios_table_attr_value_entry_enum_decode_number(
356 tableEntry);
357 std::vector<uint8_t> handles(count);
358 pldm_bios_table_attr_value_entry_enum_decode_handles(
359 tableEntry, handles.data(), handles.size());
360
361 // get current_value
362 for (size_t i = 0; i < handles.size(); i++)
363 {
364 currentValue = getValue(pvHandls[handles[i]], *stringTable);
365 }
366
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930367 uint8_t defNum;
368 // Preconditions are upheld therefore no error check necessary
369 pldm_bios_table_attr_entry_enum_decode_def_num_check(attrEntry,
370 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800371 std::vector<uint8_t> defIndices(defNum);
372 pldm_bios_table_attr_entry_enum_decode_def_indices(
373 attrEntry, defIndices.data(), defIndices.size());
374
375 // get default_value
376 for (size_t i = 0; i < defIndices.size(); i++)
377 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500378 defaultValue = getValue(pvHandls[defIndices[i]],
379 *stringTable);
George Liu1b180d82020-07-23 14:01:58 +0800380 }
381
382 break;
383 }
384 case PLDM_BIOS_INTEGER:
385 case PLDM_BIOS_INTEGER_READ_ONLY:
386 {
387 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
388 "AttributeType.Integer";
389 currentValue = static_cast<int64_t>(
390 pldm_bios_table_attr_value_entry_integer_decode_cv(
391 tableEntry));
392
393 uint64_t lower, upper, def;
394 uint32_t scalar;
395 pldm_bios_table_attr_entry_integer_decode(
396 attrEntry, &lower, &upper, &scalar, &def);
Sagar Srinivas7927f902023-10-09 07:53:00 -0500397 options.push_back(std::make_tuple(
398 "xyz.openbmc_project.BIOSConfig.Manager."
399 "BoundType.LowerBound",
400 static_cast<int64_t>(lower), attributeName));
401 options.push_back(std::make_tuple(
402 "xyz.openbmc_project.BIOSConfig.Manager."
403 "BoundType.UpperBound",
404 static_cast<int64_t>(upper), attributeName));
405 options.push_back(std::make_tuple(
406 "xyz.openbmc_project.BIOSConfig.Manager."
407 "BoundType.ScalarIncrement",
408 static_cast<int64_t>(scalar), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800409 defaultValue = static_cast<int64_t>(def);
410 break;
411 }
412 case PLDM_BIOS_STRING:
413 case PLDM_BIOS_STRING_READ_ONLY:
414 {
415 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
416 "AttributeType.String";
417 variable_field currentString;
418 pldm_bios_table_attr_value_entry_string_decode_string(
419 tableEntry, &currentString);
420 currentValue = std::string(
421 reinterpret_cast<const char*>(currentString.ptr),
422 currentString.length);
423 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
424 attrEntry);
425 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
426 attrEntry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930427 uint16_t def;
428 // Preconditions are upheld therefore no error check necessary
429 pldm_bios_table_attr_entry_string_decode_def_string_length_check(
430 attrEntry, &def);
George Liu1b180d82020-07-23 14:01:58 +0800431 std::vector<char> defString(def + 1);
432 pldm_bios_table_attr_entry_string_decode_def_string(
433 attrEntry, defString.data(), defString.size());
434 options.push_back(
435 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
436 "BoundType.MinStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500437 static_cast<int64_t>(min), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800438 options.push_back(
439 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
440 "BoundType.MaxStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500441 static_cast<int64_t>(max), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800442 defaultValue = defString.data();
443 break;
444 }
445 case PLDM_BIOS_PASSWORD:
446 case PLDM_BIOS_PASSWORD_READ_ONLY:
447 {
448 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
449 "AttributeType.Password";
450 break;
451 }
452 default:
453 return PLDM_INVALID_BIOS_ATTR_HANDLE;
454 }
455 baseBIOSTableMaps.emplace(
456 std::move(attributeName),
457 std::make_tuple(attributeType, readonlyStatus, displayName,
458 description, menuPath, currentValue, defaultValue,
459 std::move(options)));
460 }
461
462 return PLDM_SUCCESS;
463}
464
465void BIOSConfig::updateBaseBIOSTableProperty()
466{
467 constexpr static auto biosConfigPath =
468 "/xyz/openbmc_project/bios_config/manager";
469 constexpr static auto biosConfigInterface =
470 "xyz.openbmc_project.BIOSConfig.Manager";
471 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
472 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
473
474 if (baseBIOSTableMaps.empty())
475 {
476 return;
477 }
478
479 try
480 {
481 auto& bus = dbusHandler->getBus();
Patrick Williams6da4f912023-05-10 07:50:53 -0500482 auto service = dbusHandler->getService(biosConfigPath,
483 biosConfigInterface);
George Liu1b180d82020-07-23 14:01:58 +0800484 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
485 dbusProperties, "Set");
486 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
487 method.append(biosConfigInterface, biosConfigPropertyName, value);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000488 bus.call_noreply(method, dbusTimeout);
George Liu1b180d82020-07-23 14:01:58 +0800489 }
490 catch (const std::exception& e)
491 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600492 error("failed to update BaseBIOSTable property, ERROR={ERR_EXCEP}",
493 "ERR_EXCEP", e.what());
George Liu1b180d82020-07-23 14:01:58 +0800494 }
495}
496
John Wangd9659342020-02-27 16:46:05 +0800497void BIOSConfig::constructAttributes()
498{
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500499 load(jsonDir / sysType / stringJsonFile, [this](const Json& entry) {
John Wangd9659342020-02-27 16:46:05 +0800500 constructAttribute<BIOSStringAttribute>(entry);
501 });
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500502 load(jsonDir / sysType / integerJsonFile, [this](const Json& entry) {
John Wang95e6b3c2020-02-13 09:43:24 +0800503 constructAttribute<BIOSIntegerAttribute>(entry);
504 });
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500505 load(jsonDir / sysType / enumJsonFile, [this](const Json& entry) {
John Wang3be70852020-02-13 15:59:04 +0800506 constructAttribute<BIOSEnumAttribute>(entry);
507 });
John Wangd9659342020-02-27 16:46:05 +0800508}
509
510void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
511{
512 BIOSStringTable biosStringTable(stringTable);
513
514 if (biosAttributes.empty())
515 {
516 return;
517 }
518
Tom Josephca7b2522020-11-18 12:27:11 +0530519 BaseBIOSTable biosTable{};
520 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
521 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
522
523 try
524 {
525 auto& bus = dbusHandler->getBus();
526 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams6da4f912023-05-10 07:50:53 -0500527 auto method = bus.new_method_call(service.c_str(), biosObjPath,
528 "org.freedesktop.DBus.Properties",
529 "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530530 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500531 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530532 std::variant<BaseBIOSTable> varBiosTable{};
533 reply.read(varBiosTable);
534 biosTable = std::get<BaseBIOSTable>(varBiosTable);
535 }
536 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
537 // default values populated from the BIOS JSONs to keep PLDM and
538 // bios-settings-manager in sync
539 catch (const std::exception& e)
540 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600541 error("Failed to read BaseBIOSTable property, ERROR={ERR_EXCEP}",
542 "ERR_EXCEP", e.what());
Tom Josephca7b2522020-11-18 12:27:11 +0530543 }
544
John Wangd9659342020-02-27 16:46:05 +0800545 Table attrTable, attrValueTable;
546
547 for (auto& attr : biosAttributes)
548 {
549 try
550 {
Tom Josephca7b2522020-11-18 12:27:11 +0530551 auto iter = biosTable.find(attr->name);
552 if (iter == biosTable.end())
553 {
554 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
555 std::nullopt);
556 }
557 else
558 {
559 attr->constructEntry(
560 biosStringTable, attrTable, attrValueTable,
561 std::get<static_cast<uint8_t>(Index::currentValue)>(
562 iter->second));
563 }
John Wangd9659342020-02-27 16:46:05 +0800564 }
565 catch (const std::exception& e)
566 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500567 error("Error constructing table entry for '{ATTR}': {ERROR}",
568 "ATTR", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800569 }
570 }
571
572 table::appendPadAndChecksum(attrTable);
573 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800574 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
575 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800576}
577
578std::optional<Table> BIOSConfig::buildAndStoreStringTable()
579{
580 std::set<std::string> strings;
581 auto handler = [&strings](const Json& entry) {
582 strings.emplace(entry.at("attribute_name"));
583 };
584
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500585 load(jsonDir / sysType / stringJsonFile, handler);
586 load(jsonDir / sysType / integerJsonFile, handler);
587 load(jsonDir / sysType / enumJsonFile, [&strings](const Json& entry) {
John Wangd9659342020-02-27 16:46:05 +0800588 strings.emplace(entry.at("attribute_name"));
589 auto possibleValues = entry.at("possible_values");
590 for (auto& pv : possibleValues)
591 {
592 strings.emplace(pv);
593 }
594 });
595
596 if (strings.empty())
597 {
598 return std::nullopt;
599 }
600
601 Table table;
602 for (const auto& elem : strings)
603 {
604 table::string::constructEntry(table, elem);
605 }
606
607 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800608 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800609 return table;
610}
611
612void BIOSConfig::storeTable(const fs::path& path, const Table& table)
613{
614 BIOSTable biosTable(path.c_str());
615 biosTable.store(table);
616}
617
618std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
619{
620 BIOSTable biosTable(path.c_str());
621 if (biosTable.isEmpty())
622 {
623 return std::nullopt;
624 }
625
626 Table table;
627 biosTable.load(table);
628 return table;
629}
630
631void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
632{
633 std::ifstream file;
634 Json jsonConf;
635 if (fs::exists(filePath))
636 {
637 try
638 {
639 file.open(filePath);
640 jsonConf = Json::parse(file);
641 auto entries = jsonConf.at("entries");
642 for (auto& entry : entries)
643 {
644 try
645 {
646 handler(entry);
647 }
648 catch (const std::exception& e)
649 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600650 error(
651 "Failed to parse JSON config file(entry handler) : {JSON_PATH}, {ERR_EXCEP}",
652 "JSON_PATH", filePath.c_str(), "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800653 }
654 }
655 }
656 catch (const std::exception& e)
657 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500658 error("Failed to parse JSON config at '{PATH}': {ERROR}", "PATH",
659 filePath.c_str(), "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800660 }
661 }
662}
663
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600664std::string BIOSConfig::decodeStringFromStringEntry(
665 const pldm_bios_string_table_entry* stringEntry)
666{
667 auto strLength =
668 pldm_bios_table_string_entry_decode_string_length(stringEntry);
669 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930670 // Preconditions are upheld therefore no error check necessary
671 pldm_bios_table_string_entry_decode_string_check(stringEntry, buffer.data(),
672 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600673 return std::string(buffer.data(), buffer.data() + strLength);
674}
675
676std::string
677 BIOSConfig::displayStringHandle(uint16_t handle, uint8_t index,
678 const std::optional<Table>& attrTable,
679 const std::optional<Table>& stringTable)
680{
681 auto attrEntry = pldm_bios_table_attr_find_by_handle(
682 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930683 uint8_t pvNum;
684 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
685 &pvNum);
686 if (rc != PLDM_SUCCESS)
687 {
688 error(
689 "Failed to decode BIOS table possible values for attribute entry: {LIPBLDM_ERROR}",
690 "LIBPLDM_ERROR", rc);
691 throw std::runtime_error(
692 "Failed to decode BIOS table possible values for attribute entry");
693 }
694
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600695 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930696 // Preconditions are upheld therefore no error check necessary
697 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
698 attrEntry, pvHandls.data(), pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600699
700 std::string displayString = std::to_string(pvHandls[index]);
701
702 auto stringEntry = pldm_bios_table_string_find_by_handle(
703 stringTable->data(), stringTable->size(), pvHandls[index]);
704
705 auto decodedStr = decodeStringFromStringEntry(stringEntry);
706
707 return decodedStr + "(" + displayString + ")";
708}
709
710void BIOSConfig::traceBIOSUpdate(
711 const pldm_bios_attr_val_table_entry* attrValueEntry,
712 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
713{
714 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
715 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
716
Patrick Williams6da4f912023-05-10 07:50:53 -0500717 auto [attrHandle,
718 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600719
720 auto attrHeader = table::attribute::decodeHeader(attrEntry);
721 BIOSStringTable biosStringTable(*stringTable);
722 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
723
724 switch (attrType)
725 {
726 case PLDM_BIOS_ENUMERATION:
727 case PLDM_BIOS_ENUMERATION_READ_ONLY:
728 {
729 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
730 attrValueEntry);
731 std::vector<uint8_t> handles(count);
732 pldm_bios_table_attr_value_entry_enum_decode_handles(
733 attrValueEntry, handles.data(), handles.size());
734
735 for (uint8_t handle : handles)
736 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600737 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
738 stringTable);
739 auto chkBMC = isBMC ? "true" : "false";
740 info(
741 "BIOS:{ATTR_NAME}, updated to value: {NEW_VAL}, by BMC: {CHK_BMC} ",
742 "ATTR_NAME", attrName, "NEW_VAL", nwVal, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600743 }
744 break;
745 }
746 case PLDM_BIOS_INTEGER:
747 case PLDM_BIOS_INTEGER_READ_ONLY:
748 {
749 auto value =
750 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600751 auto chkBMC = isBMC ? "true" : "false";
752 info(
753 "BIOS: {ATTR_NAME}, updated to value: {UPDATED_VAL}, by BMC: {CHK_BMC}",
754 "ATTR_NAME", attrName, "UPDATED_VAL", value, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600755 break;
756 }
757 case PLDM_BIOS_STRING:
758 case PLDM_BIOS_STRING_READ_ONLY:
759 {
760 auto value =
761 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600762 auto chkBMC = isBMC ? "true" : "false";
763 info(
764 "BIOS: {ATTR_NAME}, updated to value: {UPDATED_VAL}, by BMC: {CHK_BMC}",
765 "ATTR_NAME", attrName, "UPDATED_VAL", value, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600766 break;
767 }
768 default:
769 break;
770 };
771}
772
John Wang8241b342020-06-05 10:49:17 +0800773int BIOSConfig::checkAttrValueToUpdate(
774 const pldm_bios_attr_val_table_entry* attrValueEntry,
775 const pldm_bios_attr_table_entry* attrEntry, Table&)
776
777{
Patrick Williams6da4f912023-05-10 07:50:53 -0500778 auto [attrHandle,
779 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800780
781 switch (attrType)
782 {
783 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800784 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800785 {
786 auto value =
787 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500788 auto [pvHdls,
789 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600790 if (!(value.size() == 1))
791 {
792 return PLDM_ERROR_INVALID_LENGTH;
793 }
John Wang8241b342020-06-05 10:49:17 +0800794 if (value[0] >= pvHdls.size())
795 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600796 error("Enum: Illgeal index, Index = {ATTR_INDEX}", "ATTR_INDEX",
797 (int)value[0]);
John Wang8241b342020-06-05 10:49:17 +0800798 return PLDM_ERROR_INVALID_DATA;
799 }
John Wang8241b342020-06-05 10:49:17 +0800800 return PLDM_SUCCESS;
801 }
802 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800803 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800804 {
805 auto value =
806 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500807 auto [lower, upper, scalar,
808 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800809
810 if (value < lower || value > upper)
811 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600812 error("Integer: out of bound, value = {ATTR_VALUE}",
813 "ATTR_VALUE", value);
John Wang8241b342020-06-05 10:49:17 +0800814 return PLDM_ERROR_INVALID_DATA;
815 }
816 return PLDM_SUCCESS;
817 }
818 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800819 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800820 {
821 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
822 auto value =
823 table::attribute_value::decodeStringEntry(attrValueEntry);
824 if (value.size() < stringConf.minLength ||
825 value.size() > stringConf.maxLength)
826 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600827 error(
828 "String: Length error, string = {ATTR_VALUE} length {LEN}",
829 "ATTR_VALUE", value, "LEN", value.size());
John Wang8241b342020-06-05 10:49:17 +0800830 return PLDM_ERROR_INVALID_LENGTH;
831 }
832 return PLDM_SUCCESS;
833 }
834 default:
Riya Dixit49cfb132023-03-02 04:26:53 -0600835 error("ReadOnly or Unspported type, type = {ATTR_TYPE}",
836 "ATTR_TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800837 return PLDM_ERROR;
838 };
839}
840
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600841int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
842 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800843{
844 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
845 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
846 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
847 if (!attrValueTable || !attrTable || !stringTable)
848 {
849 return PLDM_BIOS_TABLE_UNAVAILABLE;
850 }
851
John Wangd9659342020-02-27 16:46:05 +0800852 auto attrValueEntry =
853 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
854
855 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
856
Patrick Williams6da4f912023-05-10 07:50:53 -0500857 auto attrEntry = table::attribute::findByHandle(*attrTable,
858 attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800859 if (!attrEntry)
860 {
861 return PLDM_ERROR;
862 }
863
John Wang8241b342020-06-05 10:49:17 +0800864 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
865 if (rc != PLDM_SUCCESS)
866 {
867 return rc;
868 }
869
Patrick Williams6da4f912023-05-10 07:50:53 -0500870 auto destTable = table::attribute_value::updateTable(*attrValueTable, entry,
871 size);
John Wang8241b342020-06-05 10:49:17 +0800872
873 if (!destTable)
874 {
875 return PLDM_ERROR;
876 }
877
John Wangd9659342020-02-27 16:46:05 +0800878 try
879 {
880 auto attrHeader = table::attribute::decodeHeader(attrEntry);
881
882 BIOSStringTable biosStringTable(*stringTable);
883 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500884 auto iter = std::find_if(
885 biosAttributes.begin(), biosAttributes.end(),
886 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800887
888 if (iter == biosAttributes.end())
889 {
890 return PLDM_ERROR;
891 }
George Liu6d6d1e82021-02-16 11:08:55 +0800892 if (updateDBus)
893 {
894 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
895 biosStringTable);
896 }
John Wangd9659342020-02-27 16:46:05 +0800897 }
898 catch (const std::exception& e)
899 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600900 error("Set attribute value error: {ERR_EXCEP}", "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800901 return PLDM_ERROR;
902 }
903
Tom Joseph7f839f92020-09-21 10:20:44 +0530904 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800905
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600906 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
907
John Wangd9659342020-02-27 16:46:05 +0800908 return PLDM_SUCCESS;
909}
910
911void BIOSConfig::removeTables()
912{
913 try
914 {
915 fs::remove(tableDir / stringTableFile);
916 fs::remove(tableDir / attrTableFile);
917 fs::remove(tableDir / attrValueTableFile);
918 }
919 catch (const std::exception& e)
920 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600921 error("Remove the tables error: {ERR_EXCEP}", "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800922 }
923}
924
Sampa Misra46ece062020-03-18 07:17:44 -0500925void BIOSConfig::processBiosAttrChangeNotification(
926 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
927{
928 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
929 const auto& propertyName = dBusMap->propertyName;
930 const auto& attrName = biosAttributes[biosAttrIndex]->name;
931
932 const auto it = chProperties.find(propertyName);
933 if (it == chProperties.end())
934 {
935 return;
936 }
937
938 PropertyValue newPropVal = it->second;
939 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
940 if (!stringTable.has_value())
941 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600942 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500943 return;
944 }
945 BIOSStringTable biosStringTable(*stringTable);
946 uint16_t attrNameHdl{};
947 try
948 {
949 attrNameHdl = biosStringTable.findHandle(attrName);
950 }
Patrick Williams51330582021-10-06 12:48:56 -0500951 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -0500952 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500953 error("Missing handle for '{ATTR}': {ERROR}", "ATTR", attrName, "ERROR",
954 e);
Sampa Misra46ece062020-03-18 07:17:44 -0500955 return;
956 }
957
958 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
959 if (!attrTable.has_value())
960 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600961 error("Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -0500962 return;
963 }
964 const struct pldm_bios_attr_table_entry* tableEntry =
965 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
966 if (tableEntry == nullptr)
967 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600968 error(
969 "Attribute not found in attribute table, name= {ATTR_NAME} name handle={ATTR_HANDLE}",
970 "ATTR_NAME", attrName.c_str(), "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -0500971 return;
972 }
973
Patrick Williams6da4f912023-05-10 07:50:53 -0500974 auto [attrHdl, attrType,
975 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -0500976
977 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
978
979 if (!attrValueSrcTable.has_value())
980 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600981 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -0500982 return;
983 }
984
985 Table newValue;
986 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
987 newValue, attrHdl, attrType, newPropVal);
988 if (rc != PLDM_SUCCESS)
989 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600990 error(
991 "Could not update the attribute value table for attribute handle={ATTR_HANDLE} and type={ATTR_TYPE}",
992 "ATTR_HANDLE", attrHdl, "ATTR_TYPE", (uint32_t)attrType);
Sampa Misra46ece062020-03-18 07:17:44 -0500993 return;
994 }
995 auto destTable = table::attribute_value::updateTable(
996 *attrValueSrcTable, newValue.data(), newValue.size());
997 if (destTable.has_value())
998 {
999 storeTable(tableDir / attrValueTableFile, *destTable);
1000 }
Sampa Misra0f262332021-02-15 00:13:51 -06001001
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001002 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001003 if (rc != PLDM_SUCCESS)
1004 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001005 error("could not setAttrValue on base bios table and dbus, rc = {RC}",
1006 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001007 }
Sampa Misra46ece062020-03-18 07:17:44 -05001008}
1009
George Liu1244acf2020-08-14 09:11:11 +08001010uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1011{
1012 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1013 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1014
1015 BIOSStringTable biosStringTable(*stringTable);
1016 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1017 attrTable->data(), attrTable->size());
1018 auto stringHandle = biosStringTable.findHandle(attrName);
1019
1020 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1021 attrTable->data(), attrTable->size()))
1022 {
1023 auto header = table::attribute::decodeHeader(entry);
1024 if (header.stringHandle == stringHandle)
1025 {
1026 return header.attrHandle;
1027 }
1028 }
1029
1030 throw std::invalid_argument("Unknow attribute Name");
1031}
1032
1033void BIOSConfig::constructPendingAttribute(
1034 const PendingAttributes& pendingAttributes)
1035{
Tom Joseph7f839f92020-09-21 10:20:44 +05301036 std::vector<uint16_t> listOfHandles{};
1037
George Liu1244acf2020-08-14 09:11:11 +08001038 for (auto& attribute : pendingAttributes)
1039 {
1040 std::string attributeName = attribute.first;
1041 auto& [attributeType, attributevalue] = attribute.second;
1042
1043 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1044 [&attributeName](const auto& attr) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001045 return attr->name == attributeName;
1046 });
George Liu1244acf2020-08-14 09:11:11 +08001047
1048 if (iter == biosAttributes.end())
1049 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001050 error("Wrong attribute name, attributeName = {ATTR_NAME}",
1051 "ATTR_NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001052 continue;
1053 }
1054
1055 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
1056 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
1057 attrValueEntry.data());
1058
1059 auto handler = findAttrHandle(attributeName);
1060 auto type =
1061 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1062
1063 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1064 type != BIOSConfigManager::AttributeType::String &&
1065 type != BIOSConfigManager::AttributeType::Integer)
1066 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001067 error("Attribute type not supported, attributeType = {ATTR_TYPE}",
1068 "ATTR_TYPE", attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001069 continue;
1070 }
1071
George Liu4876c542022-06-08 15:59:54 +08001072 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001073 menuPath, currentValue, defaultValue,
1074 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001075
George Liu1244acf2020-08-14 09:11:11 +08001076 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001077
1078 // Need to verify that the current value has really changed
1079 if (attributeType == attrType && attributevalue != currentValue)
1080 {
1081 listOfHandles.emplace_back(htole16(handler));
1082 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301083
George Liu1244acf2020-08-14 09:11:11 +08001084 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1085
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001086 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301087 }
1088
1089 if (listOfHandles.size())
1090 {
1091#ifdef OEM_IBM
1092 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301093 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301094 if (rc != PLDM_SUCCESS)
1095 {
1096 return;
1097 }
1098#endif
George Liu1244acf2020-08-14 09:11:11 +08001099 }
1100}
1101
1102void BIOSConfig::listenPendingAttributes()
1103{
1104 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1105 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1106
1107 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001108 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001109 pldm::utils::DBusHandler::getBus(),
1110 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001111 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001112 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001113
Patrick Williams6da4f912023-05-10 07:50:53 -05001114 using Value =
1115 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1116 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001117
Patrick Williams6da4f912023-05-10 07:50:53 -05001118 Properties props{};
1119 std::string intf;
1120 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001121
Patrick Williams6da4f912023-05-10 07:50:53 -05001122 auto valPropMap = props.find(propertyName);
1123 if (valPropMap == props.end())
1124 {
1125 return;
1126 }
George Liu1244acf2020-08-14 09:11:11 +08001127
Patrick Williams6da4f912023-05-10 07:50:53 -05001128 PendingAttributes pendingAttributes =
1129 std::get<PendingAttributes>(valPropMap->second);
1130 this->constructPendingAttribute(pendingAttributes);
Patrick Williamsa6756622023-10-20 11:19:15 -05001131 });
George Liu1244acf2020-08-14 09:11:11 +08001132
1133 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1134}
1135
John Wangd9659342020-02-27 16:46:05 +08001136} // namespace bios
1137} // namespace responder
1138} // namespace pldm