blob: ff3a97f556a7987a2434b5ec758bda2b4afc449b [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
Archana Kakani62dd8ff2024-02-12 10:00:40 -060012#include <filesystem>
John Wangd9659342020-02-27 16:46:05 +080013#include <fstream>
John Wangd9659342020-02-27 16:46:05 +080014
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
Archana Kakaniac713ee2024-05-20 01:27:53 -050034constexpr auto attributesJsonFile = "bios_attrs.json";
John Wangd9659342020-02-27 16:46:05 +080035
36constexpr auto stringTableFile = "stringTable";
37constexpr auto attrTableFile = "attributeTable";
38constexpr auto attrValueTableFile = "attributeValueTable";
39
40} // namespace
41
Sampa Misrac0c79482021-06-02 08:01:54 -050042BIOSConfig::BIOSConfig(
43 const char* jsonDir, const char* tableDir, DBusHandler* const dbusHandler,
Andrew Jeffery197033b2024-07-25 20:53:07 +093044 int /* fd */, uint8_t eid, pldm::InstanceIdDb* instanceIdDb,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050045 pldm::requester::Handler<pldm::requester::Request>* handler,
Archana Kakani62dd8ff2024-02-12 10:00:40 -060046 pldm::responder::platform_config::Handler* platformConfigHandler,
47 pldm::responder::bios::Callback requestPLDMServiceName) :
John Wangd9659342020-02-27 16:46:05 +080048 jsonDir(jsonDir),
Andrew Jeffery197033b2024-07-25 20:53:07 +093049 tableDir(tableDir), dbusHandler(dbusHandler), eid(eid),
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060050 instanceIdDb(instanceIdDb), handler(handler),
Archana Kakani62dd8ff2024-02-12 10:00:40 -060051 platformConfigHandler(platformConfigHandler),
52 requestPLDMServiceName(requestPLDMServiceName)
53{
54 fs::create_directories(tableDir);
55 removeTables();
Archana Kakani46f352e2024-03-17 08:21:08 -050056
57#ifdef SYSTEM_SPECIFIC_BIOS_JSON
58 checkSystemTypeAvailability();
59#else
60 initBIOSAttributes(sysType, false);
61#endif
62
Archana Kakani62dd8ff2024-02-12 10:00:40 -060063 listenPendingAttributes();
64}
Tom Joseph7f839f92020-09-21 10:20:44 +053065
Archana Kakani46f352e2024-03-17 08:21:08 -050066void BIOSConfig::checkSystemTypeAvailability()
John Wangd9659342020-02-27 16:46:05 +080067{
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060068 if (platformConfigHandler)
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050069 {
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060070 auto systemType = platformConfigHandler->getPlatformName();
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050071 if (systemType.has_value())
72 {
Archana Kakani46f352e2024-03-17 08:21:08 -050073 // Received System Type from Entity Manager
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050074 sysType = systemType.value();
Archana Kakani46f352e2024-03-17 08:21:08 -050075 initBIOSAttributes(sysType, true);
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050076 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060077 else
78 {
Archana Kakani46f352e2024-03-17 08:21:08 -050079 platformConfigHandler->registerSystemTypeCallback(
80 std::bind(&BIOSConfig::initBIOSAttributes, this,
81 std::placeholders::_1, std::placeholders::_2));
Archana Kakani62dd8ff2024-02-12 10:00:40 -060082 }
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050083 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060084}
85
Archana Kakani46f352e2024-03-17 08:21:08 -050086void BIOSConfig::initBIOSAttributes(const std::string& systemType,
87 bool registerService)
Archana Kakani62dd8ff2024-02-12 10:00:40 -060088{
89 sysType = systemType;
90 fs::path dir{jsonDir / sysType};
91 if (!fs::exists(dir))
92 {
93 error("System specific bios attribute directory {DIR} does not exit",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050094 "DIR", dir);
Thu Nguyen3f5a9692024-07-16 13:16:54 +000095 if (registerService)
96 {
97 requestPLDMServiceName();
98 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060099 return;
100 }
John Wangd9659342020-02-27 16:46:05 +0800101 constructAttributes();
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600102 buildTables();
Archana Kakani46f352e2024-03-17 08:21:08 -0500103 if (registerService)
104 {
105 requestPLDMServiceName();
106 }
John Wangd9659342020-02-27 16:46:05 +0800107}
108
109void BIOSConfig::buildTables()
110{
John Wangd9659342020-02-27 16:46:05 +0800111 auto stringTable = buildAndStoreStringTable();
112 if (stringTable)
113 {
114 buildAndStoreAttrTables(*stringTable);
115 }
116}
117
118std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
119{
120 fs::path tablePath;
121 switch (tableType)
122 {
123 case PLDM_BIOS_STRING_TABLE:
124 tablePath = tableDir / stringTableFile;
125 break;
126 case PLDM_BIOS_ATTR_TABLE:
127 tablePath = tableDir / attrTableFile;
128 break;
129 case PLDM_BIOS_ATTR_VAL_TABLE:
130 tablePath = tableDir / attrValueTableFile;
131 break;
132 }
133 return loadTable(tablePath);
134}
135
Tom Joseph7f839f92020-09-21 10:20:44 +0530136int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table,
137 bool updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800138{
139 fs::path stringTablePath(tableDir / stringTableFile);
140 fs::path attrTablePath(tableDir / attrTableFile);
141 fs::path attrValueTablePath(tableDir / attrValueTableFile);
142
143 if (!pldm_bios_table_checksum(table.data(), table.size()))
144 {
145 return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
146 }
147
148 if (tableType == PLDM_BIOS_STRING_TABLE)
149 {
150 storeTable(stringTablePath, table);
151 }
152 else if (tableType == PLDM_BIOS_ATTR_TABLE)
153 {
154 BIOSTable biosStringTable(stringTablePath.c_str());
155 if (biosStringTable.isEmpty())
156 {
157 return PLDM_INVALID_BIOS_TABLE_TYPE;
158 }
159
160 auto rc = checkAttributeTable(table);
161 if (rc != PLDM_SUCCESS)
162 {
163 return rc;
164 }
165
166 storeTable(attrTablePath, table);
167 }
168 else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
169 {
170 BIOSTable biosStringTable(stringTablePath.c_str());
171 BIOSTable biosStringValueTable(attrTablePath.c_str());
172 if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
173 {
174 return PLDM_INVALID_BIOS_TABLE_TYPE;
175 }
176
177 auto rc = checkAttributeValueTable(table);
178 if (rc != PLDM_SUCCESS)
179 {
180 return rc;
181 }
182
183 storeTable(attrValueTablePath, table);
George Liu1b180d82020-07-23 14:01:58 +0800184 }
185 else
186 {
187 return PLDM_INVALID_BIOS_TABLE_TYPE;
188 }
189
Tom Joseph7f839f92020-09-21 10:20:44 +0530190 if ((tableType == PLDM_BIOS_ATTR_VAL_TABLE) && updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800191 {
George Liu1b180d82020-07-23 14:01:58 +0800192 updateBaseBIOSTableProperty();
193 }
194
195 return PLDM_SUCCESS;
196}
197
198int BIOSConfig::checkAttributeTable(const Table& table)
199{
200 using namespace pldm::bios::utils;
201 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
202 for (auto entry :
203 BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
204 {
205 auto attrNameHandle =
206 pldm_bios_table_attr_entry_decode_string_handle(entry);
207
208 auto stringEnty = pldm_bios_table_string_find_by_handle(
209 stringTable->data(), stringTable->size(), attrNameHandle);
210 if (stringEnty == nullptr)
211 {
212 return PLDM_INVALID_BIOS_ATTR_HANDLE;
213 }
214
215 auto attrType = static_cast<pldm_bios_attribute_type>(
216 pldm_bios_table_attr_entry_decode_attribute_type(entry));
217
218 switch (attrType)
219 {
220 case PLDM_BIOS_ENUMERATION:
221 case PLDM_BIOS_ENUMERATION_READ_ONLY:
222 {
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930223 uint8_t pvNum;
224 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000225 pldm_bios_table_attr_entry_enum_decode_pv_num(entry, &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800226 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930227 // Preconditions are upheld therefore no error check necessary
228 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800229 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930230 uint8_t defNum;
231 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry,
232 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800233 std::vector<uint8_t> defIndices(defNum);
234 pldm_bios_table_attr_entry_enum_decode_def_indices(
235 entry, defIndices.data(), defIndices.size());
236
237 for (size_t i = 0; i < pvHandls.size(); i++)
238 {
239 auto stringEntry = pldm_bios_table_string_find_by_handle(
240 stringTable->data(), stringTable->size(), pvHandls[i]);
241 if (stringEntry == nullptr)
242 {
243 return PLDM_INVALID_BIOS_ATTR_HANDLE;
244 }
245 }
246
247 for (size_t i = 0; i < defIndices.size(); i++)
248 {
249 auto stringEntry = pldm_bios_table_string_find_by_handle(
250 stringTable->data(), stringTable->size(),
251 pvHandls[defIndices[i]]);
252 if (stringEntry == nullptr)
253 {
254 return PLDM_INVALID_BIOS_ATTR_HANDLE;
255 }
256 }
257 break;
258 }
259 case PLDM_BIOS_INTEGER:
260 case PLDM_BIOS_INTEGER_READ_ONLY:
261 case PLDM_BIOS_STRING:
262 case PLDM_BIOS_STRING_READ_ONLY:
263 case PLDM_BIOS_PASSWORD:
264 case PLDM_BIOS_PASSWORD_READ_ONLY:
265 break;
266 default:
267 return PLDM_INVALID_BIOS_ATTR_HANDLE;
268 }
269 }
270
271 return PLDM_SUCCESS;
272}
273
274int BIOSConfig::checkAttributeValueTable(const Table& table)
275{
276 using namespace pldm::bios::utils;
277 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
278 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
279
280 baseBIOSTableMaps.clear();
281
282 for (auto tableEntry :
283 BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
284 {
285 AttributeName attributeName{};
286 AttributeType attributeType{};
287 ReadonlyStatus readonlyStatus{};
288 DisplayName displayName{};
289 Description description{};
290 MenuPath menuPath{};
291 CurrentValue currentValue{};
292 DefaultValue defaultValue{};
Sagar Srinivas7927f902023-10-09 07:53:00 -0500293 std::vector<ValueDisplayName> valueDisplayNames;
294 std::map<uint16_t, std::vector<std::string>> valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800295 Option options{};
296
297 auto attrValueHandle =
298 pldm_bios_table_attr_value_entry_decode_attribute_handle(
299 tableEntry);
300 auto attrType = static_cast<pldm_bios_attribute_type>(
301 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
302
303 auto attrEntry = pldm_bios_table_attr_find_by_handle(
304 attrTable->data(), attrTable->size(), attrValueHandle);
305 if (attrEntry == nullptr)
306 {
307 return PLDM_INVALID_BIOS_ATTR_HANDLE;
308 }
309 auto attrHandle =
310 pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
311 auto attrNameHandle =
312 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
313
314 auto stringEntry = pldm_bios_table_string_find_by_handle(
315 stringTable->data(), stringTable->size(), attrNameHandle);
316 if (stringEntry == nullptr)
317 {
318 return PLDM_INVALID_BIOS_ATTR_HANDLE;
319 }
320 auto strLength =
321 pldm_bios_table_string_entry_decode_string_length(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 necessary
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000324 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
325 buffer.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930326
George Liu1b180d82020-07-23 14:01:58 +0800327 attributeName = std::string(buffer.data(), buffer.data() + strLength);
328
329 if (!biosAttributes.empty())
330 {
331 readonlyStatus =
George Liub1fbeec2020-09-04 09:59:46 +0800332 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800333 description =
334 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
335 displayName =
336 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
Sagar Srinivas7927f902023-10-09 07:53:00 -0500337 valueDisplayNamesMap =
338 biosAttributes[attrHandle % biosAttributes.size()]
339 ->valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800340 }
341
342 switch (attrType)
343 {
344 case PLDM_BIOS_ENUMERATION:
345 case PLDM_BIOS_ENUMERATION_READ_ONLY:
346 {
Sagar Srinivas7927f902023-10-09 07:53:00 -0500347 if (valueDisplayNamesMap.contains(attrHandle))
348 {
349 const std::vector<ValueDisplayName>& vdn =
350 valueDisplayNamesMap[attrHandle];
351 valueDisplayNames.insert(valueDisplayNames.end(),
352 vdn.begin(), vdn.end());
353 }
George Liu1b180d82020-07-23 14:01:58 +0800354 auto getValue = [](uint16_t handle,
355 const Table& table) -> std::string {
356 auto stringEntry = pldm_bios_table_string_find_by_handle(
357 table.data(), table.size(), handle);
358
359 auto strLength =
360 pldm_bios_table_string_entry_decode_string_length(
361 stringEntry);
362 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930363 // Preconditions are upheld therefore no error check
364 // necessary
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000365 pldm_bios_table_string_entry_decode_string(
George Liu1b180d82020-07-23 14:01:58 +0800366 stringEntry, buffer.data(), buffer.size());
367
368 return std::string(buffer.data(),
369 buffer.data() + strLength);
370 };
371
372 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
373 "AttributeType.Enumeration";
374
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930375 uint8_t pvNum;
376 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000377 pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry,
378 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800379 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930380 // Preconditions are upheld therefore no error check necessary
381 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800382 attrEntry, pvHandls.data(), pvHandls.size());
383
384 // get possible_value
385 for (size_t i = 0; i < pvHandls.size(); i++)
386 {
387 options.push_back(
388 std::make_tuple("xyz.openbmc_project.BIOSConfig."
389 "Manager.BoundType.OneOf",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500390 getValue(pvHandls[i], *stringTable),
391 valueDisplayNames[i]));
George Liu1b180d82020-07-23 14:01:58 +0800392 }
393
394 auto count =
395 pldm_bios_table_attr_value_entry_enum_decode_number(
396 tableEntry);
397 std::vector<uint8_t> handles(count);
398 pldm_bios_table_attr_value_entry_enum_decode_handles(
399 tableEntry, handles.data(), handles.size());
400
401 // get current_value
402 for (size_t i = 0; i < handles.size(); i++)
403 {
404 currentValue = getValue(pvHandls[handles[i]], *stringTable);
405 }
406
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930407 uint8_t defNum;
408 // Preconditions are upheld therefore no error check necessary
409 pldm_bios_table_attr_entry_enum_decode_def_num_check(attrEntry,
410 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800411 std::vector<uint8_t> defIndices(defNum);
412 pldm_bios_table_attr_entry_enum_decode_def_indices(
413 attrEntry, defIndices.data(), defIndices.size());
414
415 // get default_value
416 for (size_t i = 0; i < defIndices.size(); i++)
417 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500418 defaultValue = getValue(pvHandls[defIndices[i]],
419 *stringTable);
George Liu1b180d82020-07-23 14:01:58 +0800420 }
421
422 break;
423 }
424 case PLDM_BIOS_INTEGER:
425 case PLDM_BIOS_INTEGER_READ_ONLY:
426 {
427 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
428 "AttributeType.Integer";
429 currentValue = static_cast<int64_t>(
430 pldm_bios_table_attr_value_entry_integer_decode_cv(
431 tableEntry));
432
433 uint64_t lower, upper, def;
434 uint32_t scalar;
435 pldm_bios_table_attr_entry_integer_decode(
436 attrEntry, &lower, &upper, &scalar, &def);
Sagar Srinivas7927f902023-10-09 07:53:00 -0500437 options.push_back(std::make_tuple(
438 "xyz.openbmc_project.BIOSConfig.Manager."
439 "BoundType.LowerBound",
440 static_cast<int64_t>(lower), attributeName));
441 options.push_back(std::make_tuple(
442 "xyz.openbmc_project.BIOSConfig.Manager."
443 "BoundType.UpperBound",
444 static_cast<int64_t>(upper), attributeName));
445 options.push_back(std::make_tuple(
446 "xyz.openbmc_project.BIOSConfig.Manager."
447 "BoundType.ScalarIncrement",
448 static_cast<int64_t>(scalar), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800449 defaultValue = static_cast<int64_t>(def);
450 break;
451 }
452 case PLDM_BIOS_STRING:
453 case PLDM_BIOS_STRING_READ_ONLY:
454 {
455 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
456 "AttributeType.String";
457 variable_field currentString;
458 pldm_bios_table_attr_value_entry_string_decode_string(
459 tableEntry, &currentString);
460 currentValue = std::string(
461 reinterpret_cast<const char*>(currentString.ptr),
462 currentString.length);
463 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
464 attrEntry);
465 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
466 attrEntry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930467 uint16_t def;
468 // Preconditions are upheld therefore no error check necessary
469 pldm_bios_table_attr_entry_string_decode_def_string_length_check(
470 attrEntry, &def);
George Liu1b180d82020-07-23 14:01:58 +0800471 std::vector<char> defString(def + 1);
472 pldm_bios_table_attr_entry_string_decode_def_string(
473 attrEntry, defString.data(), defString.size());
474 options.push_back(
475 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
476 "BoundType.MinStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500477 static_cast<int64_t>(min), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800478 options.push_back(
479 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
480 "BoundType.MaxStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500481 static_cast<int64_t>(max), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800482 defaultValue = defString.data();
483 break;
484 }
485 case PLDM_BIOS_PASSWORD:
486 case PLDM_BIOS_PASSWORD_READ_ONLY:
487 {
488 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
489 "AttributeType.Password";
490 break;
491 }
492 default:
493 return PLDM_INVALID_BIOS_ATTR_HANDLE;
494 }
495 baseBIOSTableMaps.emplace(
496 std::move(attributeName),
497 std::make_tuple(attributeType, readonlyStatus, displayName,
498 description, menuPath, currentValue, defaultValue,
499 std::move(options)));
500 }
501
502 return PLDM_SUCCESS;
503}
504
505void BIOSConfig::updateBaseBIOSTableProperty()
506{
507 constexpr static auto biosConfigPath =
508 "/xyz/openbmc_project/bios_config/manager";
509 constexpr static auto biosConfigInterface =
510 "xyz.openbmc_project.BIOSConfig.Manager";
511 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
512 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
513
514 if (baseBIOSTableMaps.empty())
515 {
516 return;
517 }
518
519 try
520 {
521 auto& bus = dbusHandler->getBus();
Patrick Williams6da4f912023-05-10 07:50:53 -0500522 auto service = dbusHandler->getService(biosConfigPath,
523 biosConfigInterface);
George Liu1b180d82020-07-23 14:01:58 +0800524 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
525 dbusProperties, "Set");
526 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
527 method.append(biosConfigInterface, biosConfigPropertyName, value);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000528 bus.call_noreply(method, dbusTimeout);
George Liu1b180d82020-07-23 14:01:58 +0800529 }
530 catch (const std::exception& e)
531 {
Riya Dixit89644442024-03-31 05:39:59 -0500532 error("Failed to update BaseBIOSTable property, error - {ERROR}",
533 "ERROR", e);
George Liu1b180d82020-07-23 14:01:58 +0800534 }
535}
536
John Wangd9659342020-02-27 16:46:05 +0800537void BIOSConfig::constructAttributes()
538{
Archana Kakaniac713ee2024-05-20 01:27:53 -0500539 info("Bios Attribute file path: {PATH}", "PATH",
540 (jsonDir / sysType / attributesJsonFile));
541 load(jsonDir / sysType / attributesJsonFile, [this](const Json& entry) {
542 std::string attrType = entry.at("attribute_type");
543 if (attrType == "string")
544 {
545 constructAttribute<BIOSStringAttribute>(entry);
546 }
547 else if (attrType == "integer")
548 {
549 constructAttribute<BIOSIntegerAttribute>(entry);
550 }
551 else if (attrType == "enum")
552 {
553 constructAttribute<BIOSEnumAttribute>(entry);
554 }
John Wang3be70852020-02-13 15:59:04 +0800555 });
John Wangd9659342020-02-27 16:46:05 +0800556}
557
558void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
559{
560 BIOSStringTable biosStringTable(stringTable);
561
562 if (biosAttributes.empty())
563 {
564 return;
565 }
566
Tom Josephca7b2522020-11-18 12:27:11 +0530567 BaseBIOSTable biosTable{};
568 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
569 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
570
571 try
572 {
573 auto& bus = dbusHandler->getBus();
574 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams6da4f912023-05-10 07:50:53 -0500575 auto method = bus.new_method_call(service.c_str(), biosObjPath,
576 "org.freedesktop.DBus.Properties",
577 "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530578 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500579 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530580 std::variant<BaseBIOSTable> varBiosTable{};
581 reply.read(varBiosTable);
582 biosTable = std::get<BaseBIOSTable>(varBiosTable);
583 }
584 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
585 // default values populated from the BIOS JSONs to keep PLDM and
586 // bios-settings-manager in sync
587 catch (const std::exception& e)
588 {
Riya Dixit89644442024-03-31 05:39:59 -0500589 error("Failed to read BaseBIOSTable property, error - {ERROR}", "ERROR",
590 e);
Tom Josephca7b2522020-11-18 12:27:11 +0530591 }
592
John Wangd9659342020-02-27 16:46:05 +0800593 Table attrTable, attrValueTable;
594
595 for (auto& attr : biosAttributes)
596 {
597 try
598 {
Tom Josephca7b2522020-11-18 12:27:11 +0530599 auto iter = biosTable.find(attr->name);
600 if (iter == biosTable.end())
601 {
602 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
603 std::nullopt);
604 }
605 else
606 {
607 attr->constructEntry(
608 biosStringTable, attrTable, attrValueTable,
609 std::get<static_cast<uint8_t>(Index::currentValue)>(
610 iter->second));
611 }
John Wangd9659342020-02-27 16:46:05 +0800612 }
613 catch (const std::exception& e)
614 {
Riya Dixit89644442024-03-31 05:39:59 -0500615 error(
616 "Failed to construct table entry for attribute '{ATTRIBUTE}', error - {ERROR}",
617 "ATTRIBUTE", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800618 }
619 }
620
621 table::appendPadAndChecksum(attrTable);
622 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800623 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
624 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800625}
626
627std::optional<Table> BIOSConfig::buildAndStoreStringTable()
628{
629 std::set<std::string> strings;
Archana Kakaniac713ee2024-05-20 01:27:53 -0500630 load(jsonDir / sysType / attributesJsonFile, [&strings](const Json& entry) {
631 if (entry.at("attribute_type") == "enum")
John Wangd9659342020-02-27 16:46:05 +0800632 {
Archana Kakaniac713ee2024-05-20 01:27:53 -0500633 strings.emplace(entry.at("attribute_name"));
634 auto possibleValues = entry.at("possible_values");
635 for (auto& pv : possibleValues)
636 {
637 strings.emplace(pv);
638 }
639 }
640 else
641 {
642 strings.emplace(entry.at("attribute_name"));
John Wangd9659342020-02-27 16:46:05 +0800643 }
644 });
645
646 if (strings.empty())
647 {
648 return std::nullopt;
649 }
650
651 Table table;
652 for (const auto& elem : strings)
653 {
654 table::string::constructEntry(table, elem);
655 }
656
657 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800658 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800659 return table;
660}
661
662void BIOSConfig::storeTable(const fs::path& path, const Table& table)
663{
664 BIOSTable biosTable(path.c_str());
665 biosTable.store(table);
666}
667
668std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
669{
670 BIOSTable biosTable(path.c_str());
671 if (biosTable.isEmpty())
672 {
673 return std::nullopt;
674 }
675
676 Table table;
677 biosTable.load(table);
678 return table;
679}
680
681void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
682{
683 std::ifstream file;
684 Json jsonConf;
685 if (fs::exists(filePath))
686 {
687 try
688 {
689 file.open(filePath);
690 jsonConf = Json::parse(file);
691 auto entries = jsonConf.at("entries");
692 for (auto& entry : entries)
693 {
694 try
695 {
696 handler(entry);
697 }
698 catch (const std::exception& e)
699 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600700 error(
Riya Dixit89644442024-03-31 05:39:59 -0500701 "Failed to parse JSON config file at path '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500702 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800703 }
704 }
705 }
706 catch (const std::exception& e)
707 {
Riya Dixit89644442024-03-31 05:39:59 -0500708 error("Failed to parse JSON config file '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500709 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800710 }
711 }
712}
713
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600714std::string BIOSConfig::decodeStringFromStringEntry(
715 const pldm_bios_string_table_entry* stringEntry)
716{
717 auto strLength =
718 pldm_bios_table_string_entry_decode_string_length(stringEntry);
719 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930720 // Preconditions are upheld therefore no error check necessary
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000721 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
722 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600723 return std::string(buffer.data(), buffer.data() + strLength);
724}
725
726std::string
727 BIOSConfig::displayStringHandle(uint16_t handle, uint8_t index,
728 const std::optional<Table>& attrTable,
729 const std::optional<Table>& stringTable)
730{
731 auto attrEntry = pldm_bios_table_attr_find_by_handle(
732 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930733 uint8_t pvNum;
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000734 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry, &pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930735 if (rc != PLDM_SUCCESS)
736 {
737 error(
Riya Dixit89644442024-03-31 05:39:59 -0500738 "Failed to decode BIOS table possible values for attribute entry, response code '{RC}'",
739 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930740 throw std::runtime_error(
741 "Failed to decode BIOS table possible values for attribute entry");
742 }
743
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600744 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930745 // Preconditions are upheld therefore no error check necessary
746 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
747 attrEntry, pvHandls.data(), pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600748
749 std::string displayString = std::to_string(pvHandls[index]);
750
751 auto stringEntry = pldm_bios_table_string_find_by_handle(
752 stringTable->data(), stringTable->size(), pvHandls[index]);
753
754 auto decodedStr = decodeStringFromStringEntry(stringEntry);
755
756 return decodedStr + "(" + displayString + ")";
757}
758
759void BIOSConfig::traceBIOSUpdate(
760 const pldm_bios_attr_val_table_entry* attrValueEntry,
761 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
762{
763 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
764 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
765
Patrick Williams6da4f912023-05-10 07:50:53 -0500766 auto [attrHandle,
767 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600768
769 auto attrHeader = table::attribute::decodeHeader(attrEntry);
770 BIOSStringTable biosStringTable(*stringTable);
771 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
772
773 switch (attrType)
774 {
775 case PLDM_BIOS_ENUMERATION:
776 case PLDM_BIOS_ENUMERATION_READ_ONLY:
777 {
778 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
779 attrValueEntry);
780 std::vector<uint8_t> handles(count);
781 pldm_bios_table_attr_value_entry_enum_decode_handles(
782 attrValueEntry, handles.data(), handles.size());
783
784 for (uint8_t handle : handles)
785 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600786 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
787 stringTable);
788 auto chkBMC = isBMC ? "true" : "false";
789 info(
Riya Dixit89644442024-03-31 05:39:59 -0500790 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
791 "ATTRIBUTE", attrName, "VALUE", nwVal, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600792 }
793 break;
794 }
795 case PLDM_BIOS_INTEGER:
796 case PLDM_BIOS_INTEGER_READ_ONLY:
797 {
798 auto value =
799 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600800 auto chkBMC = isBMC ? "true" : "false";
801 info(
Riya Dixit89644442024-03-31 05:39:59 -0500802 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
803 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600804 break;
805 }
806 case PLDM_BIOS_STRING:
807 case PLDM_BIOS_STRING_READ_ONLY:
808 {
809 auto value =
810 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600811 auto chkBMC = isBMC ? "true" : "false";
812 info(
Riya Dixit89644442024-03-31 05:39:59 -0500813 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
814 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600815 break;
816 }
817 default:
818 break;
819 };
820}
821
John Wang8241b342020-06-05 10:49:17 +0800822int BIOSConfig::checkAttrValueToUpdate(
823 const pldm_bios_attr_val_table_entry* attrValueEntry,
824 const pldm_bios_attr_table_entry* attrEntry, Table&)
825
826{
Patrick Williams6da4f912023-05-10 07:50:53 -0500827 auto [attrHandle,
828 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800829
830 switch (attrType)
831 {
832 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800833 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800834 {
835 auto value =
836 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500837 auto [pvHdls,
838 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600839 if (!(value.size() == 1))
840 {
841 return PLDM_ERROR_INVALID_LENGTH;
842 }
John Wang8241b342020-06-05 10:49:17 +0800843 if (value[0] >= pvHdls.size())
844 {
Riya Dixit89644442024-03-31 05:39:59 -0500845 error(
846 "Invalid index '{INDEX}' encountered for Enum type BIOS attribute",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500847 "INDEX", value[0]);
John Wang8241b342020-06-05 10:49:17 +0800848 return PLDM_ERROR_INVALID_DATA;
849 }
John Wang8241b342020-06-05 10:49:17 +0800850 return PLDM_SUCCESS;
851 }
852 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800853 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800854 {
855 auto value =
856 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500857 auto [lower, upper, scalar,
858 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800859
860 if (value < lower || value > upper)
861 {
Riya Dixit89644442024-03-31 05:39:59 -0500862 error(
863 "Out of range index '{ATTRIBUTE_VALUE}' encountered for Integer type BIOS attribute for the lower bound '{LOWER}', the upper bound '{UPPER}' and the scalar value '{SCALAR}'.",
864 "ATTRIBUTE_VALUE", value, "LOWER", lower, "UPPER", upper,
865 "SCALAR", scalar);
John Wang8241b342020-06-05 10:49:17 +0800866 return PLDM_ERROR_INVALID_DATA;
867 }
868 return PLDM_SUCCESS;
869 }
870 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800871 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800872 {
873 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
874 auto value =
875 table::attribute_value::decodeStringEntry(attrValueEntry);
876 if (value.size() < stringConf.minLength ||
877 value.size() > stringConf.maxLength)
878 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600879 error(
Riya Dixit89644442024-03-31 05:39:59 -0500880 "Invalid length '{LENGTH}' encountered for string type BIOS attribute value '{ATTRIBUTE_VALUE}' when minimum string entry length '{MIN_LEN}' and maximum string entry length '{MAX_LEN}'",
881 "ATTRIBUTE_VALUE", value, "LENGTH", value.size(), "MIN_LEN",
882 stringConf.minLength, "MAX_LEN", stringConf.maxLength);
John Wang8241b342020-06-05 10:49:17 +0800883 return PLDM_ERROR_INVALID_LENGTH;
884 }
885 return PLDM_SUCCESS;
886 }
887 default:
Riya Dixit89644442024-03-31 05:39:59 -0500888 error("ReadOnly or Unsupported type '{TYPE}'", "TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800889 return PLDM_ERROR;
890 };
891}
892
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600893int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
894 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800895{
896 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
897 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
898 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
899 if (!attrValueTable || !attrTable || !stringTable)
900 {
901 return PLDM_BIOS_TABLE_UNAVAILABLE;
902 }
903
John Wangd9659342020-02-27 16:46:05 +0800904 auto attrValueEntry =
905 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
906
907 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
908
Patrick Williams6da4f912023-05-10 07:50:53 -0500909 auto attrEntry = table::attribute::findByHandle(*attrTable,
910 attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800911 if (!attrEntry)
912 {
913 return PLDM_ERROR;
914 }
915
John Wang8241b342020-06-05 10:49:17 +0800916 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
917 if (rc != PLDM_SUCCESS)
918 {
919 return rc;
920 }
921
Patrick Williams6da4f912023-05-10 07:50:53 -0500922 auto destTable = table::attribute_value::updateTable(*attrValueTable, entry,
923 size);
John Wang8241b342020-06-05 10:49:17 +0800924
925 if (!destTable)
926 {
927 return PLDM_ERROR;
928 }
929
John Wangd9659342020-02-27 16:46:05 +0800930 try
931 {
932 auto attrHeader = table::attribute::decodeHeader(attrEntry);
933
934 BIOSStringTable biosStringTable(*stringTable);
935 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500936 auto iter = std::find_if(
937 biosAttributes.begin(), biosAttributes.end(),
938 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800939
940 if (iter == biosAttributes.end())
941 {
942 return PLDM_ERROR;
943 }
George Liu6d6d1e82021-02-16 11:08:55 +0800944 if (updateDBus)
945 {
946 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
947 biosStringTable);
948 }
John Wangd9659342020-02-27 16:46:05 +0800949 }
950 catch (const std::exception& e)
951 {
Riya Dixit89644442024-03-31 05:39:59 -0500952 error("Set attribute value error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800953 return PLDM_ERROR;
954 }
955
Tom Joseph7f839f92020-09-21 10:20:44 +0530956 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800957
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600958 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
959
John Wangd9659342020-02-27 16:46:05 +0800960 return PLDM_SUCCESS;
961}
962
963void BIOSConfig::removeTables()
964{
965 try
966 {
967 fs::remove(tableDir / stringTableFile);
968 fs::remove(tableDir / attrTableFile);
969 fs::remove(tableDir / attrValueTableFile);
970 }
971 catch (const std::exception& e)
972 {
Riya Dixit89644442024-03-31 05:39:59 -0500973 error("Remove the tables error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800974 }
975}
976
Sampa Misra46ece062020-03-18 07:17:44 -0500977void BIOSConfig::processBiosAttrChangeNotification(
978 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
979{
980 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
981 const auto& propertyName = dBusMap->propertyName;
982 const auto& attrName = biosAttributes[biosAttrIndex]->name;
983
984 const auto it = chProperties.find(propertyName);
985 if (it == chProperties.end())
986 {
987 return;
988 }
989
990 PropertyValue newPropVal = it->second;
991 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
992 if (!stringTable.has_value())
993 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600994 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500995 return;
996 }
997 BIOSStringTable biosStringTable(*stringTable);
998 uint16_t attrNameHdl{};
999 try
1000 {
1001 attrNameHdl = biosStringTable.findHandle(attrName);
1002 }
Patrick Williams51330582021-10-06 12:48:56 -05001003 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -05001004 {
Riya Dixit89644442024-03-31 05:39:59 -05001005 error(
1006 "Missing handle for attribute '{ATTRIBUTE}' in BIOS String Table, error - '{ERROR}'",
1007 "ATTRIBUTE", attrName, "ERROR", e);
Sampa Misra46ece062020-03-18 07:17:44 -05001008 return;
1009 }
1010
1011 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1012 if (!attrTable.has_value())
1013 {
Riya Dixit89644442024-03-31 05:39:59 -05001014 error("BIOS Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001015 return;
1016 }
1017 const struct pldm_bios_attr_table_entry* tableEntry =
1018 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
1019 if (tableEntry == nullptr)
1020 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001021 error(
Riya Dixit89644442024-03-31 05:39:59 -05001022 "Failed to find attribute {ATTRIBUTE} in BIOS Attribute table with attribute handle '{ATTR_HANDLE}'",
1023 "ATTRIBUTE", attrName, "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -05001024 return;
1025 }
1026
Patrick Williams6da4f912023-05-10 07:50:53 -05001027 auto [attrHdl, attrType,
1028 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -05001029
1030 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
1031
1032 if (!attrValueSrcTable.has_value())
1033 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001034 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001035 return;
1036 }
1037
1038 Table newValue;
1039 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
1040 newValue, attrHdl, attrType, newPropVal);
1041 if (rc != PLDM_SUCCESS)
1042 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001043 error(
Riya Dixit89644442024-03-31 05:39:59 -05001044 "Failed to update the attribute value table for attribute handle '{ATTR_HANDLE}' and attribute type '{TYPE}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -05001045 "ATTR_HANDLE", attrHdl, "TYPE", attrType);
Sampa Misra46ece062020-03-18 07:17:44 -05001046 return;
1047 }
1048 auto destTable = table::attribute_value::updateTable(
1049 *attrValueSrcTable, newValue.data(), newValue.size());
1050 if (destTable.has_value())
1051 {
1052 storeTable(tableDir / attrValueTableFile, *destTable);
1053 }
Sampa Misra0f262332021-02-15 00:13:51 -06001054
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001055 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001056 if (rc != PLDM_SUCCESS)
1057 {
Riya Dixit89644442024-03-31 05:39:59 -05001058 error(
1059 "Failed to setAttrValue on base bios table and dbus, response code '{RC}'",
1060 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001061 }
Sampa Misra46ece062020-03-18 07:17:44 -05001062}
1063
George Liu1244acf2020-08-14 09:11:11 +08001064uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1065{
1066 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1067 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1068
1069 BIOSStringTable biosStringTable(*stringTable);
1070 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1071 attrTable->data(), attrTable->size());
1072 auto stringHandle = biosStringTable.findHandle(attrName);
1073
1074 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1075 attrTable->data(), attrTable->size()))
1076 {
1077 auto header = table::attribute::decodeHeader(entry);
1078 if (header.stringHandle == stringHandle)
1079 {
1080 return header.attrHandle;
1081 }
1082 }
1083
Manojkiran Eda2576aec2024-06-17 12:05:17 +05301084 throw std::invalid_argument("Unknown attribute Name");
George Liu1244acf2020-08-14 09:11:11 +08001085}
1086
1087void BIOSConfig::constructPendingAttribute(
1088 const PendingAttributes& pendingAttributes)
1089{
Tom Joseph7f839f92020-09-21 10:20:44 +05301090 std::vector<uint16_t> listOfHandles{};
1091
George Liu1244acf2020-08-14 09:11:11 +08001092 for (auto& attribute : pendingAttributes)
1093 {
1094 std::string attributeName = attribute.first;
1095 auto& [attributeType, attributevalue] = attribute.second;
1096
1097 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1098 [&attributeName](const auto& attr) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001099 return attr->name == attributeName;
1100 });
George Liu1244acf2020-08-14 09:11:11 +08001101
1102 if (iter == biosAttributes.end())
1103 {
Riya Dixit89644442024-03-31 05:39:59 -05001104 error("Wrong attribute name {NAME}", "NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001105 continue;
1106 }
1107
1108 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
1109 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
1110 attrValueEntry.data());
1111
1112 auto handler = findAttrHandle(attributeName);
1113 auto type =
1114 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1115
1116 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1117 type != BIOSConfigManager::AttributeType::String &&
1118 type != BIOSConfigManager::AttributeType::Integer)
1119 {
Riya Dixit89644442024-03-31 05:39:59 -05001120 error("Attribute type '{TYPE}' not supported", "TYPE",
1121 attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001122 continue;
1123 }
1124
George Liu4876c542022-06-08 15:59:54 +08001125 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001126 menuPath, currentValue, defaultValue,
1127 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001128
George Liu1244acf2020-08-14 09:11:11 +08001129 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001130
1131 // Need to verify that the current value has really changed
1132 if (attributeType == attrType && attributevalue != currentValue)
1133 {
1134 listOfHandles.emplace_back(htole16(handler));
1135 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301136
George Liu1244acf2020-08-14 09:11:11 +08001137 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1138
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001139 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301140 }
1141
1142 if (listOfHandles.size())
1143 {
1144#ifdef OEM_IBM
1145 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301146 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301147 if (rc != PLDM_SUCCESS)
1148 {
1149 return;
1150 }
1151#endif
George Liu1244acf2020-08-14 09:11:11 +08001152 }
1153}
1154
1155void BIOSConfig::listenPendingAttributes()
1156{
1157 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1158 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1159
1160 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001161 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001162 pldm::utils::DBusHandler::getBus(),
1163 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001164 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001165 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001166
Patrick Williams6da4f912023-05-10 07:50:53 -05001167 using Value =
1168 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1169 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001170
Patrick Williams6da4f912023-05-10 07:50:53 -05001171 Properties props{};
1172 std::string intf;
1173 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001174
Patrick Williams6da4f912023-05-10 07:50:53 -05001175 auto valPropMap = props.find(propertyName);
1176 if (valPropMap == props.end())
1177 {
1178 return;
1179 }
George Liu1244acf2020-08-14 09:11:11 +08001180
Patrick Williams6da4f912023-05-10 07:50:53 -05001181 PendingAttributes pendingAttributes =
1182 std::get<PendingAttributes>(valPropMap->second);
1183 this->constructPendingAttribute(pendingAttributes);
Patrick Williamsa6756622023-10-20 11:19:15 -05001184 });
George Liu1244acf2020-08-14 09:11:11 +08001185
1186 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1187}
1188
John Wangd9659342020-02-27 16:46:05 +08001189} // namespace bios
1190} // namespace responder
1191} // namespace pldm