blob: c5c549cacec72f67d65990e21da1c8240586b156 [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>
John Wangd9659342020-02-27 16:46:05 +080013
Tom Joseph7f839f92020-09-21 10:20:44 +053014#ifdef OEM_IBM
15#include "oem/ibm/libpldmresponder/platform_oem_ibm.hpp"
16#endif
17
Riya Dixit49cfb132023-03-02 04:26:53 -060018PHOSPHOR_LOG2_USING;
19
Brad Bishop5079ac42021-08-19 18:35:06 -040020using namespace pldm::utils;
21
John Wangd9659342020-02-27 16:46:05 +080022namespace pldm
23{
24namespace responder
25{
26namespace bios
27{
28namespace
29{
George Liu1244acf2020-08-14 09:11:11 +080030using BIOSConfigManager =
31 sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager;
32
John Wangd9659342020-02-27 16:46:05 +080033constexpr auto enumJsonFile = "enum_attrs.json";
34constexpr auto stringJsonFile = "string_attrs.json";
35constexpr auto integerJsonFile = "integer_attrs.json";
36
37constexpr auto stringTableFile = "stringTable";
38constexpr auto attrTableFile = "attributeTable";
39constexpr auto attrValueTableFile = "attributeValueTable";
40
41} // namespace
42
Sampa Misrac0c79482021-06-02 08:01:54 -050043BIOSConfig::BIOSConfig(
44 const char* jsonDir, const char* tableDir, DBusHandler* const dbusHandler,
Andrew Jefferya330b2f2023-05-04 14:55:37 +093045 int fd, uint8_t eid, pldm::InstanceIdDb* instanceIdDb,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050046 pldm::requester::Handler<pldm::requester::Request>* handler,
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060047 pldm::responder::platform_config::Handler* platformConfigHandler) :
John Wangd9659342020-02-27 16:46:05 +080048 jsonDir(jsonDir),
Tom Joseph7f839f92020-09-21 10:20:44 +053049 tableDir(tableDir), dbusHandler(dbusHandler), fd(fd), eid(eid),
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060050 instanceIdDb(instanceIdDb), handler(handler),
51 platformConfigHandler(platformConfigHandler)
Tom Joseph7f839f92020-09-21 10:20:44 +053052
John Wangd9659342020-02-27 16:46:05 +080053{
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060054 if (platformConfigHandler)
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050055 {
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060056 auto systemType = platformConfigHandler->getPlatformName();
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050057 if (systemType.has_value())
58 {
59 sysType = systemType.value();
60 }
61 }
George Liu9d8921e2020-05-14 15:41:50 +080062 fs::create_directories(tableDir);
John Wangd9659342020-02-27 16:46:05 +080063 constructAttributes();
George Liu1244acf2020-08-14 09:11:11 +080064 listenPendingAttributes();
John Wangd9659342020-02-27 16:46:05 +080065}
66
67void BIOSConfig::buildTables()
68{
John Wangd9659342020-02-27 16:46:05 +080069 auto stringTable = buildAndStoreStringTable();
70 if (stringTable)
71 {
72 buildAndStoreAttrTables(*stringTable);
73 }
74}
75
76std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
77{
78 fs::path tablePath;
79 switch (tableType)
80 {
81 case PLDM_BIOS_STRING_TABLE:
82 tablePath = tableDir / stringTableFile;
83 break;
84 case PLDM_BIOS_ATTR_TABLE:
85 tablePath = tableDir / attrTableFile;
86 break;
87 case PLDM_BIOS_ATTR_VAL_TABLE:
88 tablePath = tableDir / attrValueTableFile;
89 break;
90 }
91 return loadTable(tablePath);
92}
93
Tom Joseph7f839f92020-09-21 10:20:44 +053094int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table,
95 bool updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +080096{
97 fs::path stringTablePath(tableDir / stringTableFile);
98 fs::path attrTablePath(tableDir / attrTableFile);
99 fs::path attrValueTablePath(tableDir / attrValueTableFile);
100
101 if (!pldm_bios_table_checksum(table.data(), table.size()))
102 {
103 return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
104 }
105
106 if (tableType == PLDM_BIOS_STRING_TABLE)
107 {
108 storeTable(stringTablePath, table);
109 }
110 else if (tableType == PLDM_BIOS_ATTR_TABLE)
111 {
112 BIOSTable biosStringTable(stringTablePath.c_str());
113 if (biosStringTable.isEmpty())
114 {
115 return PLDM_INVALID_BIOS_TABLE_TYPE;
116 }
117
118 auto rc = checkAttributeTable(table);
119 if (rc != PLDM_SUCCESS)
120 {
121 return rc;
122 }
123
124 storeTable(attrTablePath, table);
125 }
126 else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
127 {
128 BIOSTable biosStringTable(stringTablePath.c_str());
129 BIOSTable biosStringValueTable(attrTablePath.c_str());
130 if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
131 {
132 return PLDM_INVALID_BIOS_TABLE_TYPE;
133 }
134
135 auto rc = checkAttributeValueTable(table);
136 if (rc != PLDM_SUCCESS)
137 {
138 return rc;
139 }
140
141 storeTable(attrValueTablePath, table);
George Liu1b180d82020-07-23 14:01:58 +0800142 }
143 else
144 {
145 return PLDM_INVALID_BIOS_TABLE_TYPE;
146 }
147
Tom Joseph7f839f92020-09-21 10:20:44 +0530148 if ((tableType == PLDM_BIOS_ATTR_VAL_TABLE) && updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800149 {
George Liu1b180d82020-07-23 14:01:58 +0800150 updateBaseBIOSTableProperty();
151 }
152
153 return PLDM_SUCCESS;
154}
155
156int BIOSConfig::checkAttributeTable(const Table& table)
157{
158 using namespace pldm::bios::utils;
159 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
160 for (auto entry :
161 BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
162 {
163 auto attrNameHandle =
164 pldm_bios_table_attr_entry_decode_string_handle(entry);
165
166 auto stringEnty = pldm_bios_table_string_find_by_handle(
167 stringTable->data(), stringTable->size(), attrNameHandle);
168 if (stringEnty == nullptr)
169 {
170 return PLDM_INVALID_BIOS_ATTR_HANDLE;
171 }
172
173 auto attrType = static_cast<pldm_bios_attribute_type>(
174 pldm_bios_table_attr_entry_decode_attribute_type(entry));
175
176 switch (attrType)
177 {
178 case PLDM_BIOS_ENUMERATION:
179 case PLDM_BIOS_ENUMERATION_READ_ONLY:
180 {
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930181 uint8_t pvNum;
182 // Preconditions are upheld therefore no error check necessary
183 pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry,
184 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800185 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930186 // Preconditions are upheld therefore no error check necessary
187 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800188 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930189 uint8_t defNum;
190 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry,
191 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800192 std::vector<uint8_t> defIndices(defNum);
193 pldm_bios_table_attr_entry_enum_decode_def_indices(
194 entry, defIndices.data(), defIndices.size());
195
196 for (size_t i = 0; i < pvHandls.size(); i++)
197 {
198 auto stringEntry = pldm_bios_table_string_find_by_handle(
199 stringTable->data(), stringTable->size(), pvHandls[i]);
200 if (stringEntry == nullptr)
201 {
202 return PLDM_INVALID_BIOS_ATTR_HANDLE;
203 }
204 }
205
206 for (size_t i = 0; i < defIndices.size(); i++)
207 {
208 auto stringEntry = pldm_bios_table_string_find_by_handle(
209 stringTable->data(), stringTable->size(),
210 pvHandls[defIndices[i]]);
211 if (stringEntry == nullptr)
212 {
213 return PLDM_INVALID_BIOS_ATTR_HANDLE;
214 }
215 }
216 break;
217 }
218 case PLDM_BIOS_INTEGER:
219 case PLDM_BIOS_INTEGER_READ_ONLY:
220 case PLDM_BIOS_STRING:
221 case PLDM_BIOS_STRING_READ_ONLY:
222 case PLDM_BIOS_PASSWORD:
223 case PLDM_BIOS_PASSWORD_READ_ONLY:
224 break;
225 default:
226 return PLDM_INVALID_BIOS_ATTR_HANDLE;
227 }
228 }
229
230 return PLDM_SUCCESS;
231}
232
233int BIOSConfig::checkAttributeValueTable(const Table& table)
234{
235 using namespace pldm::bios::utils;
236 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
237 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
238
239 baseBIOSTableMaps.clear();
240
241 for (auto tableEntry :
242 BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
243 {
244 AttributeName attributeName{};
245 AttributeType attributeType{};
246 ReadonlyStatus readonlyStatus{};
247 DisplayName displayName{};
248 Description description{};
249 MenuPath menuPath{};
250 CurrentValue currentValue{};
251 DefaultValue defaultValue{};
Sagar Srinivas7927f902023-10-09 07:53:00 -0500252 std::vector<ValueDisplayName> valueDisplayNames;
253 std::map<uint16_t, std::vector<std::string>> valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800254 Option options{};
255
256 auto attrValueHandle =
257 pldm_bios_table_attr_value_entry_decode_attribute_handle(
258 tableEntry);
259 auto attrType = static_cast<pldm_bios_attribute_type>(
260 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
261
262 auto attrEntry = pldm_bios_table_attr_find_by_handle(
263 attrTable->data(), attrTable->size(), attrValueHandle);
264 if (attrEntry == nullptr)
265 {
266 return PLDM_INVALID_BIOS_ATTR_HANDLE;
267 }
268 auto attrHandle =
269 pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
270 auto attrNameHandle =
271 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
272
273 auto stringEntry = pldm_bios_table_string_find_by_handle(
274 stringTable->data(), stringTable->size(), attrNameHandle);
275 if (stringEntry == nullptr)
276 {
277 return PLDM_INVALID_BIOS_ATTR_HANDLE;
278 }
279 auto strLength =
280 pldm_bios_table_string_entry_decode_string_length(stringEntry);
281 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930282 // Preconditions are upheld therefore no error check necessary
283 pldm_bios_table_string_entry_decode_string_check(
284 stringEntry, buffer.data(), buffer.size());
285
George Liu1b180d82020-07-23 14:01:58 +0800286 attributeName = std::string(buffer.data(), buffer.data() + strLength);
287
288 if (!biosAttributes.empty())
289 {
290 readonlyStatus =
George Liub1fbeec2020-09-04 09:59:46 +0800291 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800292 description =
293 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
294 displayName =
295 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
Sagar Srinivas7927f902023-10-09 07:53:00 -0500296 valueDisplayNamesMap =
297 biosAttributes[attrHandle % biosAttributes.size()]
298 ->valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800299 }
300
301 switch (attrType)
302 {
303 case PLDM_BIOS_ENUMERATION:
304 case PLDM_BIOS_ENUMERATION_READ_ONLY:
305 {
Sagar Srinivas7927f902023-10-09 07:53:00 -0500306 if (valueDisplayNamesMap.contains(attrHandle))
307 {
308 const std::vector<ValueDisplayName>& vdn =
309 valueDisplayNamesMap[attrHandle];
310 valueDisplayNames.insert(valueDisplayNames.end(),
311 vdn.begin(), vdn.end());
312 }
George Liu1b180d82020-07-23 14:01:58 +0800313 auto getValue = [](uint16_t handle,
314 const Table& table) -> std::string {
315 auto stringEntry = pldm_bios_table_string_find_by_handle(
316 table.data(), table.size(), handle);
317
318 auto strLength =
319 pldm_bios_table_string_entry_decode_string_length(
320 stringEntry);
321 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930322 // Preconditions are upheld therefore no error check
323 // necessary
324 pldm_bios_table_string_entry_decode_string_check(
George Liu1b180d82020-07-23 14:01:58 +0800325 stringEntry, buffer.data(), buffer.size());
326
327 return std::string(buffer.data(),
328 buffer.data() + strLength);
329 };
330
331 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
332 "AttributeType.Enumeration";
333
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930334 uint8_t pvNum;
335 // Preconditions are upheld therefore no error check necessary
336 pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
337 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800338 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930339 // Preconditions are upheld therefore no error check necessary
340 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800341 attrEntry, pvHandls.data(), pvHandls.size());
342
343 // get possible_value
344 for (size_t i = 0; i < pvHandls.size(); i++)
345 {
346 options.push_back(
347 std::make_tuple("xyz.openbmc_project.BIOSConfig."
348 "Manager.BoundType.OneOf",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500349 getValue(pvHandls[i], *stringTable),
350 valueDisplayNames[i]));
George Liu1b180d82020-07-23 14:01:58 +0800351 }
352
353 auto count =
354 pldm_bios_table_attr_value_entry_enum_decode_number(
355 tableEntry);
356 std::vector<uint8_t> handles(count);
357 pldm_bios_table_attr_value_entry_enum_decode_handles(
358 tableEntry, handles.data(), handles.size());
359
360 // get current_value
361 for (size_t i = 0; i < handles.size(); i++)
362 {
363 currentValue = getValue(pvHandls[handles[i]], *stringTable);
364 }
365
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930366 uint8_t defNum;
367 // Preconditions are upheld therefore no error check necessary
368 pldm_bios_table_attr_entry_enum_decode_def_num_check(attrEntry,
369 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800370 std::vector<uint8_t> defIndices(defNum);
371 pldm_bios_table_attr_entry_enum_decode_def_indices(
372 attrEntry, defIndices.data(), defIndices.size());
373
374 // get default_value
375 for (size_t i = 0; i < defIndices.size(); i++)
376 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500377 defaultValue = getValue(pvHandls[defIndices[i]],
378 *stringTable);
George Liu1b180d82020-07-23 14:01:58 +0800379 }
380
381 break;
382 }
383 case PLDM_BIOS_INTEGER:
384 case PLDM_BIOS_INTEGER_READ_ONLY:
385 {
386 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
387 "AttributeType.Integer";
388 currentValue = static_cast<int64_t>(
389 pldm_bios_table_attr_value_entry_integer_decode_cv(
390 tableEntry));
391
392 uint64_t lower, upper, def;
393 uint32_t scalar;
394 pldm_bios_table_attr_entry_integer_decode(
395 attrEntry, &lower, &upper, &scalar, &def);
Sagar Srinivas7927f902023-10-09 07:53:00 -0500396 options.push_back(std::make_tuple(
397 "xyz.openbmc_project.BIOSConfig.Manager."
398 "BoundType.LowerBound",
399 static_cast<int64_t>(lower), attributeName));
400 options.push_back(std::make_tuple(
401 "xyz.openbmc_project.BIOSConfig.Manager."
402 "BoundType.UpperBound",
403 static_cast<int64_t>(upper), attributeName));
404 options.push_back(std::make_tuple(
405 "xyz.openbmc_project.BIOSConfig.Manager."
406 "BoundType.ScalarIncrement",
407 static_cast<int64_t>(scalar), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800408 defaultValue = static_cast<int64_t>(def);
409 break;
410 }
411 case PLDM_BIOS_STRING:
412 case PLDM_BIOS_STRING_READ_ONLY:
413 {
414 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
415 "AttributeType.String";
416 variable_field currentString;
417 pldm_bios_table_attr_value_entry_string_decode_string(
418 tableEntry, &currentString);
419 currentValue = std::string(
420 reinterpret_cast<const char*>(currentString.ptr),
421 currentString.length);
422 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
423 attrEntry);
424 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
425 attrEntry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930426 uint16_t def;
427 // Preconditions are upheld therefore no error check necessary
428 pldm_bios_table_attr_entry_string_decode_def_string_length_check(
429 attrEntry, &def);
George Liu1b180d82020-07-23 14:01:58 +0800430 std::vector<char> defString(def + 1);
431 pldm_bios_table_attr_entry_string_decode_def_string(
432 attrEntry, defString.data(), defString.size());
433 options.push_back(
434 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
435 "BoundType.MinStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500436 static_cast<int64_t>(min), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800437 options.push_back(
438 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
439 "BoundType.MaxStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500440 static_cast<int64_t>(max), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800441 defaultValue = defString.data();
442 break;
443 }
444 case PLDM_BIOS_PASSWORD:
445 case PLDM_BIOS_PASSWORD_READ_ONLY:
446 {
447 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
448 "AttributeType.Password";
449 break;
450 }
451 default:
452 return PLDM_INVALID_BIOS_ATTR_HANDLE;
453 }
454 baseBIOSTableMaps.emplace(
455 std::move(attributeName),
456 std::make_tuple(attributeType, readonlyStatus, displayName,
457 description, menuPath, currentValue, defaultValue,
458 std::move(options)));
459 }
460
461 return PLDM_SUCCESS;
462}
463
464void BIOSConfig::updateBaseBIOSTableProperty()
465{
466 constexpr static auto biosConfigPath =
467 "/xyz/openbmc_project/bios_config/manager";
468 constexpr static auto biosConfigInterface =
469 "xyz.openbmc_project.BIOSConfig.Manager";
470 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
471 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
472
473 if (baseBIOSTableMaps.empty())
474 {
475 return;
476 }
477
478 try
479 {
480 auto& bus = dbusHandler->getBus();
Patrick Williams6da4f912023-05-10 07:50:53 -0500481 auto service = dbusHandler->getService(biosConfigPath,
482 biosConfigInterface);
George Liu1b180d82020-07-23 14:01:58 +0800483 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
484 dbusProperties, "Set");
485 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
486 method.append(biosConfigInterface, biosConfigPropertyName, value);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000487 bus.call_noreply(method, dbusTimeout);
George Liu1b180d82020-07-23 14:01:58 +0800488 }
489 catch (const std::exception& e)
490 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600491 error("failed to update BaseBIOSTable property, ERROR={ERR_EXCEP}",
492 "ERR_EXCEP", e.what());
George Liu1b180d82020-07-23 14:01:58 +0800493 }
494}
495
John Wangd9659342020-02-27 16:46:05 +0800496void BIOSConfig::constructAttributes()
497{
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500498 load(jsonDir / sysType / stringJsonFile, [this](const Json& entry) {
John Wangd9659342020-02-27 16:46:05 +0800499 constructAttribute<BIOSStringAttribute>(entry);
500 });
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500501 load(jsonDir / sysType / integerJsonFile, [this](const Json& entry) {
John Wang95e6b3c2020-02-13 09:43:24 +0800502 constructAttribute<BIOSIntegerAttribute>(entry);
503 });
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500504 load(jsonDir / sysType / enumJsonFile, [this](const Json& entry) {
John Wang3be70852020-02-13 15:59:04 +0800505 constructAttribute<BIOSEnumAttribute>(entry);
506 });
John Wangd9659342020-02-27 16:46:05 +0800507}
508
509void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
510{
511 BIOSStringTable biosStringTable(stringTable);
512
513 if (biosAttributes.empty())
514 {
515 return;
516 }
517
Tom Josephca7b2522020-11-18 12:27:11 +0530518 BaseBIOSTable biosTable{};
519 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
520 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
521
522 try
523 {
524 auto& bus = dbusHandler->getBus();
525 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams6da4f912023-05-10 07:50:53 -0500526 auto method = bus.new_method_call(service.c_str(), biosObjPath,
527 "org.freedesktop.DBus.Properties",
528 "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530529 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500530 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530531 std::variant<BaseBIOSTable> varBiosTable{};
532 reply.read(varBiosTable);
533 biosTable = std::get<BaseBIOSTable>(varBiosTable);
534 }
535 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
536 // default values populated from the BIOS JSONs to keep PLDM and
537 // bios-settings-manager in sync
538 catch (const std::exception& e)
539 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600540 error("Failed to read BaseBIOSTable property, ERROR={ERR_EXCEP}",
541 "ERR_EXCEP", e.what());
Tom Josephca7b2522020-11-18 12:27:11 +0530542 }
543
John Wangd9659342020-02-27 16:46:05 +0800544 Table attrTable, attrValueTable;
545
546 for (auto& attr : biosAttributes)
547 {
548 try
549 {
Tom Josephca7b2522020-11-18 12:27:11 +0530550 auto iter = biosTable.find(attr->name);
551 if (iter == biosTable.end())
552 {
553 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
554 std::nullopt);
555 }
556 else
557 {
558 attr->constructEntry(
559 biosStringTable, attrTable, attrValueTable,
560 std::get<static_cast<uint8_t>(Index::currentValue)>(
561 iter->second));
562 }
John Wangd9659342020-02-27 16:46:05 +0800563 }
564 catch (const std::exception& e)
565 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500566 error("Error constructing table entry for '{ATTR}': {ERROR}",
567 "ATTR", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800568 }
569 }
570
571 table::appendPadAndChecksum(attrTable);
572 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800573 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
574 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800575}
576
577std::optional<Table> BIOSConfig::buildAndStoreStringTable()
578{
579 std::set<std::string> strings;
580 auto handler = [&strings](const Json& entry) {
581 strings.emplace(entry.at("attribute_name"));
582 };
583
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500584 load(jsonDir / sysType / stringJsonFile, handler);
585 load(jsonDir / sysType / integerJsonFile, handler);
586 load(jsonDir / sysType / enumJsonFile, [&strings](const Json& entry) {
John Wangd9659342020-02-27 16:46:05 +0800587 strings.emplace(entry.at("attribute_name"));
588 auto possibleValues = entry.at("possible_values");
589 for (auto& pv : possibleValues)
590 {
591 strings.emplace(pv);
592 }
593 });
594
595 if (strings.empty())
596 {
597 return std::nullopt;
598 }
599
600 Table table;
601 for (const auto& elem : strings)
602 {
603 table::string::constructEntry(table, elem);
604 }
605
606 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800607 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800608 return table;
609}
610
611void BIOSConfig::storeTable(const fs::path& path, const Table& table)
612{
613 BIOSTable biosTable(path.c_str());
614 biosTable.store(table);
615}
616
617std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
618{
619 BIOSTable biosTable(path.c_str());
620 if (biosTable.isEmpty())
621 {
622 return std::nullopt;
623 }
624
625 Table table;
626 biosTable.load(table);
627 return table;
628}
629
630void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
631{
632 std::ifstream file;
633 Json jsonConf;
634 if (fs::exists(filePath))
635 {
636 try
637 {
638 file.open(filePath);
639 jsonConf = Json::parse(file);
640 auto entries = jsonConf.at("entries");
641 for (auto& entry : entries)
642 {
643 try
644 {
645 handler(entry);
646 }
647 catch (const std::exception& e)
648 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600649 error(
650 "Failed to parse JSON config file(entry handler) : {JSON_PATH}, {ERR_EXCEP}",
651 "JSON_PATH", filePath.c_str(), "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800652 }
653 }
654 }
655 catch (const std::exception& e)
656 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500657 error("Failed to parse JSON config at '{PATH}': {ERROR}", "PATH",
658 filePath.c_str(), "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800659 }
660 }
661}
662
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600663std::string BIOSConfig::decodeStringFromStringEntry(
664 const pldm_bios_string_table_entry* stringEntry)
665{
666 auto strLength =
667 pldm_bios_table_string_entry_decode_string_length(stringEntry);
668 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930669 // Preconditions are upheld therefore no error check necessary
670 pldm_bios_table_string_entry_decode_string_check(stringEntry, buffer.data(),
671 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600672 return std::string(buffer.data(), buffer.data() + strLength);
673}
674
675std::string
676 BIOSConfig::displayStringHandle(uint16_t handle, uint8_t index,
677 const std::optional<Table>& attrTable,
678 const std::optional<Table>& stringTable)
679{
680 auto attrEntry = pldm_bios_table_attr_find_by_handle(
681 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930682 uint8_t pvNum;
683 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
684 &pvNum);
685 if (rc != PLDM_SUCCESS)
686 {
687 error(
688 "Failed to decode BIOS table possible values for attribute entry: {LIPBLDM_ERROR}",
689 "LIBPLDM_ERROR", rc);
690 throw std::runtime_error(
691 "Failed to decode BIOS table possible values for attribute entry");
692 }
693
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600694 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930695 // Preconditions are upheld therefore no error check necessary
696 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
697 attrEntry, pvHandls.data(), pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600698
699 std::string displayString = std::to_string(pvHandls[index]);
700
701 auto stringEntry = pldm_bios_table_string_find_by_handle(
702 stringTable->data(), stringTable->size(), pvHandls[index]);
703
704 auto decodedStr = decodeStringFromStringEntry(stringEntry);
705
706 return decodedStr + "(" + displayString + ")";
707}
708
709void BIOSConfig::traceBIOSUpdate(
710 const pldm_bios_attr_val_table_entry* attrValueEntry,
711 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
712{
713 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
714 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
715
Patrick Williams6da4f912023-05-10 07:50:53 -0500716 auto [attrHandle,
717 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600718
719 auto attrHeader = table::attribute::decodeHeader(attrEntry);
720 BIOSStringTable biosStringTable(*stringTable);
721 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
722
723 switch (attrType)
724 {
725 case PLDM_BIOS_ENUMERATION:
726 case PLDM_BIOS_ENUMERATION_READ_ONLY:
727 {
728 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
729 attrValueEntry);
730 std::vector<uint8_t> handles(count);
731 pldm_bios_table_attr_value_entry_enum_decode_handles(
732 attrValueEntry, handles.data(), handles.size());
733
734 for (uint8_t handle : handles)
735 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600736 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
737 stringTable);
738 auto chkBMC = isBMC ? "true" : "false";
739 info(
740 "BIOS:{ATTR_NAME}, updated to value: {NEW_VAL}, by BMC: {CHK_BMC} ",
741 "ATTR_NAME", attrName, "NEW_VAL", nwVal, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600742 }
743 break;
744 }
745 case PLDM_BIOS_INTEGER:
746 case PLDM_BIOS_INTEGER_READ_ONLY:
747 {
748 auto value =
749 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600750 auto chkBMC = isBMC ? "true" : "false";
751 info(
752 "BIOS: {ATTR_NAME}, updated to value: {UPDATED_VAL}, by BMC: {CHK_BMC}",
753 "ATTR_NAME", attrName, "UPDATED_VAL", value, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600754 break;
755 }
756 case PLDM_BIOS_STRING:
757 case PLDM_BIOS_STRING_READ_ONLY:
758 {
759 auto value =
760 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600761 auto chkBMC = isBMC ? "true" : "false";
762 info(
763 "BIOS: {ATTR_NAME}, updated to value: {UPDATED_VAL}, by BMC: {CHK_BMC}",
764 "ATTR_NAME", attrName, "UPDATED_VAL", value, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600765 break;
766 }
767 default:
768 break;
769 };
770}
771
John Wang8241b342020-06-05 10:49:17 +0800772int BIOSConfig::checkAttrValueToUpdate(
773 const pldm_bios_attr_val_table_entry* attrValueEntry,
774 const pldm_bios_attr_table_entry* attrEntry, Table&)
775
776{
Patrick Williams6da4f912023-05-10 07:50:53 -0500777 auto [attrHandle,
778 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800779
780 switch (attrType)
781 {
782 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800783 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800784 {
785 auto value =
786 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500787 auto [pvHdls,
788 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600789 if (!(value.size() == 1))
790 {
791 return PLDM_ERROR_INVALID_LENGTH;
792 }
John Wang8241b342020-06-05 10:49:17 +0800793 if (value[0] >= pvHdls.size())
794 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600795 error("Enum: Illgeal index, Index = {ATTR_INDEX}", "ATTR_INDEX",
796 (int)value[0]);
John Wang8241b342020-06-05 10:49:17 +0800797 return PLDM_ERROR_INVALID_DATA;
798 }
John Wang8241b342020-06-05 10:49:17 +0800799 return PLDM_SUCCESS;
800 }
801 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800802 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800803 {
804 auto value =
805 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500806 auto [lower, upper, scalar,
807 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800808
809 if (value < lower || value > upper)
810 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600811 error("Integer: out of bound, value = {ATTR_VALUE}",
812 "ATTR_VALUE", value);
John Wang8241b342020-06-05 10:49:17 +0800813 return PLDM_ERROR_INVALID_DATA;
814 }
815 return PLDM_SUCCESS;
816 }
817 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800818 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800819 {
820 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
821 auto value =
822 table::attribute_value::decodeStringEntry(attrValueEntry);
823 if (value.size() < stringConf.minLength ||
824 value.size() > stringConf.maxLength)
825 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600826 error(
827 "String: Length error, string = {ATTR_VALUE} length {LEN}",
828 "ATTR_VALUE", value, "LEN", value.size());
John Wang8241b342020-06-05 10:49:17 +0800829 return PLDM_ERROR_INVALID_LENGTH;
830 }
831 return PLDM_SUCCESS;
832 }
833 default:
Riya Dixit49cfb132023-03-02 04:26:53 -0600834 error("ReadOnly or Unspported type, type = {ATTR_TYPE}",
835 "ATTR_TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800836 return PLDM_ERROR;
837 };
838}
839
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600840int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
841 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800842{
843 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
844 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
845 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
846 if (!attrValueTable || !attrTable || !stringTable)
847 {
848 return PLDM_BIOS_TABLE_UNAVAILABLE;
849 }
850
John Wangd9659342020-02-27 16:46:05 +0800851 auto attrValueEntry =
852 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
853
854 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
855
Patrick Williams6da4f912023-05-10 07:50:53 -0500856 auto attrEntry = table::attribute::findByHandle(*attrTable,
857 attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800858 if (!attrEntry)
859 {
860 return PLDM_ERROR;
861 }
862
John Wang8241b342020-06-05 10:49:17 +0800863 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
864 if (rc != PLDM_SUCCESS)
865 {
866 return rc;
867 }
868
Patrick Williams6da4f912023-05-10 07:50:53 -0500869 auto destTable = table::attribute_value::updateTable(*attrValueTable, entry,
870 size);
John Wang8241b342020-06-05 10:49:17 +0800871
872 if (!destTable)
873 {
874 return PLDM_ERROR;
875 }
876
John Wangd9659342020-02-27 16:46:05 +0800877 try
878 {
879 auto attrHeader = table::attribute::decodeHeader(attrEntry);
880
881 BIOSStringTable biosStringTable(*stringTable);
882 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500883 auto iter = std::find_if(
884 biosAttributes.begin(), biosAttributes.end(),
885 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800886
887 if (iter == biosAttributes.end())
888 {
889 return PLDM_ERROR;
890 }
George Liu6d6d1e82021-02-16 11:08:55 +0800891 if (updateDBus)
892 {
893 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
894 biosStringTable);
895 }
John Wangd9659342020-02-27 16:46:05 +0800896 }
897 catch (const std::exception& e)
898 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600899 error("Set attribute value error: {ERR_EXCEP}", "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800900 return PLDM_ERROR;
901 }
902
Tom Joseph7f839f92020-09-21 10:20:44 +0530903 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800904
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600905 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
906
John Wangd9659342020-02-27 16:46:05 +0800907 return PLDM_SUCCESS;
908}
909
910void BIOSConfig::removeTables()
911{
912 try
913 {
914 fs::remove(tableDir / stringTableFile);
915 fs::remove(tableDir / attrTableFile);
916 fs::remove(tableDir / attrValueTableFile);
917 }
918 catch (const std::exception& e)
919 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600920 error("Remove the tables error: {ERR_EXCEP}", "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800921 }
922}
923
Sampa Misra46ece062020-03-18 07:17:44 -0500924void BIOSConfig::processBiosAttrChangeNotification(
925 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
926{
927 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
928 const auto& propertyName = dBusMap->propertyName;
929 const auto& attrName = biosAttributes[biosAttrIndex]->name;
930
931 const auto it = chProperties.find(propertyName);
932 if (it == chProperties.end())
933 {
934 return;
935 }
936
937 PropertyValue newPropVal = it->second;
938 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
939 if (!stringTable.has_value())
940 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600941 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500942 return;
943 }
944 BIOSStringTable biosStringTable(*stringTable);
945 uint16_t attrNameHdl{};
946 try
947 {
948 attrNameHdl = biosStringTable.findHandle(attrName);
949 }
Patrick Williams51330582021-10-06 12:48:56 -0500950 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -0500951 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500952 error("Missing handle for '{ATTR}': {ERROR}", "ATTR", attrName, "ERROR",
953 e);
Sampa Misra46ece062020-03-18 07:17:44 -0500954 return;
955 }
956
957 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
958 if (!attrTable.has_value())
959 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600960 error("Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -0500961 return;
962 }
963 const struct pldm_bios_attr_table_entry* tableEntry =
964 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
965 if (tableEntry == nullptr)
966 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600967 error(
968 "Attribute not found in attribute table, name= {ATTR_NAME} name handle={ATTR_HANDLE}",
969 "ATTR_NAME", attrName.c_str(), "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -0500970 return;
971 }
972
Patrick Williams6da4f912023-05-10 07:50:53 -0500973 auto [attrHdl, attrType,
974 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -0500975
976 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
977
978 if (!attrValueSrcTable.has_value())
979 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600980 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -0500981 return;
982 }
983
984 Table newValue;
985 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
986 newValue, attrHdl, attrType, newPropVal);
987 if (rc != PLDM_SUCCESS)
988 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600989 error(
990 "Could not update the attribute value table for attribute handle={ATTR_HANDLE} and type={ATTR_TYPE}",
991 "ATTR_HANDLE", attrHdl, "ATTR_TYPE", (uint32_t)attrType);
Sampa Misra46ece062020-03-18 07:17:44 -0500992 return;
993 }
994 auto destTable = table::attribute_value::updateTable(
995 *attrValueSrcTable, newValue.data(), newValue.size());
996 if (destTable.has_value())
997 {
998 storeTable(tableDir / attrValueTableFile, *destTable);
999 }
Sampa Misra0f262332021-02-15 00:13:51 -06001000
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001001 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001002 if (rc != PLDM_SUCCESS)
1003 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001004 error("could not setAttrValue on base bios table and dbus, rc = {RC}",
1005 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001006 }
Sampa Misra46ece062020-03-18 07:17:44 -05001007}
1008
George Liu1244acf2020-08-14 09:11:11 +08001009uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1010{
1011 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1012 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1013
1014 BIOSStringTable biosStringTable(*stringTable);
1015 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1016 attrTable->data(), attrTable->size());
1017 auto stringHandle = biosStringTable.findHandle(attrName);
1018
1019 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1020 attrTable->data(), attrTable->size()))
1021 {
1022 auto header = table::attribute::decodeHeader(entry);
1023 if (header.stringHandle == stringHandle)
1024 {
1025 return header.attrHandle;
1026 }
1027 }
1028
1029 throw std::invalid_argument("Unknow attribute Name");
1030}
1031
1032void BIOSConfig::constructPendingAttribute(
1033 const PendingAttributes& pendingAttributes)
1034{
Tom Joseph7f839f92020-09-21 10:20:44 +05301035 std::vector<uint16_t> listOfHandles{};
1036
George Liu1244acf2020-08-14 09:11:11 +08001037 for (auto& attribute : pendingAttributes)
1038 {
1039 std::string attributeName = attribute.first;
1040 auto& [attributeType, attributevalue] = attribute.second;
1041
1042 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1043 [&attributeName](const auto& attr) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001044 return attr->name == attributeName;
1045 });
George Liu1244acf2020-08-14 09:11:11 +08001046
1047 if (iter == biosAttributes.end())
1048 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001049 error("Wrong attribute name, attributeName = {ATTR_NAME}",
1050 "ATTR_NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001051 continue;
1052 }
1053
1054 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
1055 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
1056 attrValueEntry.data());
1057
1058 auto handler = findAttrHandle(attributeName);
1059 auto type =
1060 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1061
1062 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1063 type != BIOSConfigManager::AttributeType::String &&
1064 type != BIOSConfigManager::AttributeType::Integer)
1065 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001066 error("Attribute type not supported, attributeType = {ATTR_TYPE}",
1067 "ATTR_TYPE", attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001068 continue;
1069 }
1070
George Liu4876c542022-06-08 15:59:54 +08001071 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001072 menuPath, currentValue, defaultValue,
1073 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001074
George Liu1244acf2020-08-14 09:11:11 +08001075 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001076
1077 // Need to verify that the current value has really changed
1078 if (attributeType == attrType && attributevalue != currentValue)
1079 {
1080 listOfHandles.emplace_back(htole16(handler));
1081 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301082
George Liu1244acf2020-08-14 09:11:11 +08001083 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1084
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001085 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301086 }
1087
1088 if (listOfHandles.size())
1089 {
1090#ifdef OEM_IBM
1091 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301092 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301093 if (rc != PLDM_SUCCESS)
1094 {
1095 return;
1096 }
1097#endif
George Liu1244acf2020-08-14 09:11:11 +08001098 }
1099}
1100
1101void BIOSConfig::listenPendingAttributes()
1102{
1103 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1104 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1105
1106 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001107 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001108 pldm::utils::DBusHandler::getBus(),
1109 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001110 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001111 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001112
Patrick Williams6da4f912023-05-10 07:50:53 -05001113 using Value =
1114 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1115 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001116
Patrick Williams6da4f912023-05-10 07:50:53 -05001117 Properties props{};
1118 std::string intf;
1119 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001120
Patrick Williams6da4f912023-05-10 07:50:53 -05001121 auto valPropMap = props.find(propertyName);
1122 if (valPropMap == props.end())
1123 {
1124 return;
1125 }
George Liu1244acf2020-08-14 09:11:11 +08001126
Patrick Williams6da4f912023-05-10 07:50:53 -05001127 PendingAttributes pendingAttributes =
1128 std::get<PendingAttributes>(valPropMap->second);
1129 this->constructPendingAttribute(pendingAttributes);
Patrick Williamsa6756622023-10-20 11:19:15 -05001130 });
George Liu1244acf2020-08-14 09:11:11 +08001131
1132 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1133}
1134
John Wangd9659342020-02-27 16:46:05 +08001135} // namespace bios
1136} // namespace responder
1137} // namespace pldm