blob: 51fad71fdd51ccc31b1667751bd972e32c11ef26 [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 Jefferya330b2f2023-05-04 14:55:37 +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),
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),
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
225 pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry,
226 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800227 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930228 // Preconditions are upheld therefore no error check necessary
229 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800230 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930231 uint8_t defNum;
232 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry,
233 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800234 std::vector<uint8_t> defIndices(defNum);
235 pldm_bios_table_attr_entry_enum_decode_def_indices(
236 entry, defIndices.data(), defIndices.size());
237
238 for (size_t i = 0; i < pvHandls.size(); i++)
239 {
240 auto stringEntry = pldm_bios_table_string_find_by_handle(
241 stringTable->data(), stringTable->size(), pvHandls[i]);
242 if (stringEntry == nullptr)
243 {
244 return PLDM_INVALID_BIOS_ATTR_HANDLE;
245 }
246 }
247
248 for (size_t i = 0; i < defIndices.size(); i++)
249 {
250 auto stringEntry = pldm_bios_table_string_find_by_handle(
251 stringTable->data(), stringTable->size(),
252 pvHandls[defIndices[i]]);
253 if (stringEntry == nullptr)
254 {
255 return PLDM_INVALID_BIOS_ATTR_HANDLE;
256 }
257 }
258 break;
259 }
260 case PLDM_BIOS_INTEGER:
261 case PLDM_BIOS_INTEGER_READ_ONLY:
262 case PLDM_BIOS_STRING:
263 case PLDM_BIOS_STRING_READ_ONLY:
264 case PLDM_BIOS_PASSWORD:
265 case PLDM_BIOS_PASSWORD_READ_ONLY:
266 break;
267 default:
268 return PLDM_INVALID_BIOS_ATTR_HANDLE;
269 }
270 }
271
272 return PLDM_SUCCESS;
273}
274
275int BIOSConfig::checkAttributeValueTable(const Table& table)
276{
277 using namespace pldm::bios::utils;
278 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
279 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
280
281 baseBIOSTableMaps.clear();
282
283 for (auto tableEntry :
284 BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
285 {
286 AttributeName attributeName{};
287 AttributeType attributeType{};
288 ReadonlyStatus readonlyStatus{};
289 DisplayName displayName{};
290 Description description{};
291 MenuPath menuPath{};
292 CurrentValue currentValue{};
293 DefaultValue defaultValue{};
Sagar Srinivas7927f902023-10-09 07:53:00 -0500294 std::vector<ValueDisplayName> valueDisplayNames;
295 std::map<uint16_t, std::vector<std::string>> valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800296 Option options{};
297
298 auto attrValueHandle =
299 pldm_bios_table_attr_value_entry_decode_attribute_handle(
300 tableEntry);
301 auto attrType = static_cast<pldm_bios_attribute_type>(
302 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
303
304 auto attrEntry = pldm_bios_table_attr_find_by_handle(
305 attrTable->data(), attrTable->size(), attrValueHandle);
306 if (attrEntry == nullptr)
307 {
308 return PLDM_INVALID_BIOS_ATTR_HANDLE;
309 }
310 auto attrHandle =
311 pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
312 auto attrNameHandle =
313 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
314
315 auto stringEntry = pldm_bios_table_string_find_by_handle(
316 stringTable->data(), stringTable->size(), attrNameHandle);
317 if (stringEntry == nullptr)
318 {
319 return PLDM_INVALID_BIOS_ATTR_HANDLE;
320 }
321 auto strLength =
322 pldm_bios_table_string_entry_decode_string_length(stringEntry);
323 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930324 // Preconditions are upheld therefore no error check necessary
325 pldm_bios_table_string_entry_decode_string_check(
326 stringEntry, buffer.data(), buffer.size());
327
George Liu1b180d82020-07-23 14:01:58 +0800328 attributeName = std::string(buffer.data(), buffer.data() + strLength);
329
330 if (!biosAttributes.empty())
331 {
332 readonlyStatus =
George Liub1fbeec2020-09-04 09:59:46 +0800333 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800334 description =
335 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
336 displayName =
337 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
Sagar Srinivas7927f902023-10-09 07:53:00 -0500338 valueDisplayNamesMap =
339 biosAttributes[attrHandle % biosAttributes.size()]
340 ->valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800341 }
342
343 switch (attrType)
344 {
345 case PLDM_BIOS_ENUMERATION:
346 case PLDM_BIOS_ENUMERATION_READ_ONLY:
347 {
Sagar Srinivas7927f902023-10-09 07:53:00 -0500348 if (valueDisplayNamesMap.contains(attrHandle))
349 {
350 const std::vector<ValueDisplayName>& vdn =
351 valueDisplayNamesMap[attrHandle];
352 valueDisplayNames.insert(valueDisplayNames.end(),
353 vdn.begin(), vdn.end());
354 }
George Liu1b180d82020-07-23 14:01:58 +0800355 auto getValue = [](uint16_t handle,
356 const Table& table) -> std::string {
357 auto stringEntry = pldm_bios_table_string_find_by_handle(
358 table.data(), table.size(), handle);
359
360 auto strLength =
361 pldm_bios_table_string_entry_decode_string_length(
362 stringEntry);
363 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930364 // Preconditions are upheld therefore no error check
365 // necessary
366 pldm_bios_table_string_entry_decode_string_check(
George Liu1b180d82020-07-23 14:01:58 +0800367 stringEntry, buffer.data(), buffer.size());
368
369 return std::string(buffer.data(),
370 buffer.data() + strLength);
371 };
372
373 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
374 "AttributeType.Enumeration";
375
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930376 uint8_t pvNum;
377 // Preconditions are upheld therefore no error check necessary
378 pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
379 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800380 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930381 // Preconditions are upheld therefore no error check necessary
382 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800383 attrEntry, pvHandls.data(), pvHandls.size());
384
385 // get possible_value
386 for (size_t i = 0; i < pvHandls.size(); i++)
387 {
388 options.push_back(
389 std::make_tuple("xyz.openbmc_project.BIOSConfig."
390 "Manager.BoundType.OneOf",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500391 getValue(pvHandls[i], *stringTable),
392 valueDisplayNames[i]));
George Liu1b180d82020-07-23 14:01:58 +0800393 }
394
395 auto count =
396 pldm_bios_table_attr_value_entry_enum_decode_number(
397 tableEntry);
398 std::vector<uint8_t> handles(count);
399 pldm_bios_table_attr_value_entry_enum_decode_handles(
400 tableEntry, handles.data(), handles.size());
401
402 // get current_value
403 for (size_t i = 0; i < handles.size(); i++)
404 {
405 currentValue = getValue(pvHandls[handles[i]], *stringTable);
406 }
407
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930408 uint8_t defNum;
409 // Preconditions are upheld therefore no error check necessary
410 pldm_bios_table_attr_entry_enum_decode_def_num_check(attrEntry,
411 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800412 std::vector<uint8_t> defIndices(defNum);
413 pldm_bios_table_attr_entry_enum_decode_def_indices(
414 attrEntry, defIndices.data(), defIndices.size());
415
416 // get default_value
417 for (size_t i = 0; i < defIndices.size(); i++)
418 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500419 defaultValue = getValue(pvHandls[defIndices[i]],
420 *stringTable);
George Liu1b180d82020-07-23 14:01:58 +0800421 }
422
423 break;
424 }
425 case PLDM_BIOS_INTEGER:
426 case PLDM_BIOS_INTEGER_READ_ONLY:
427 {
428 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
429 "AttributeType.Integer";
430 currentValue = static_cast<int64_t>(
431 pldm_bios_table_attr_value_entry_integer_decode_cv(
432 tableEntry));
433
434 uint64_t lower, upper, def;
435 uint32_t scalar;
436 pldm_bios_table_attr_entry_integer_decode(
437 attrEntry, &lower, &upper, &scalar, &def);
Sagar Srinivas7927f902023-10-09 07:53:00 -0500438 options.push_back(std::make_tuple(
439 "xyz.openbmc_project.BIOSConfig.Manager."
440 "BoundType.LowerBound",
441 static_cast<int64_t>(lower), attributeName));
442 options.push_back(std::make_tuple(
443 "xyz.openbmc_project.BIOSConfig.Manager."
444 "BoundType.UpperBound",
445 static_cast<int64_t>(upper), attributeName));
446 options.push_back(std::make_tuple(
447 "xyz.openbmc_project.BIOSConfig.Manager."
448 "BoundType.ScalarIncrement",
449 static_cast<int64_t>(scalar), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800450 defaultValue = static_cast<int64_t>(def);
451 break;
452 }
453 case PLDM_BIOS_STRING:
454 case PLDM_BIOS_STRING_READ_ONLY:
455 {
456 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
457 "AttributeType.String";
458 variable_field currentString;
459 pldm_bios_table_attr_value_entry_string_decode_string(
460 tableEntry, &currentString);
461 currentValue = std::string(
462 reinterpret_cast<const char*>(currentString.ptr),
463 currentString.length);
464 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
465 attrEntry);
466 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
467 attrEntry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930468 uint16_t def;
469 // Preconditions are upheld therefore no error check necessary
470 pldm_bios_table_attr_entry_string_decode_def_string_length_check(
471 attrEntry, &def);
George Liu1b180d82020-07-23 14:01:58 +0800472 std::vector<char> defString(def + 1);
473 pldm_bios_table_attr_entry_string_decode_def_string(
474 attrEntry, defString.data(), defString.size());
475 options.push_back(
476 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
477 "BoundType.MinStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500478 static_cast<int64_t>(min), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800479 options.push_back(
480 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
481 "BoundType.MaxStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500482 static_cast<int64_t>(max), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800483 defaultValue = defString.data();
484 break;
485 }
486 case PLDM_BIOS_PASSWORD:
487 case PLDM_BIOS_PASSWORD_READ_ONLY:
488 {
489 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
490 "AttributeType.Password";
491 break;
492 }
493 default:
494 return PLDM_INVALID_BIOS_ATTR_HANDLE;
495 }
496 baseBIOSTableMaps.emplace(
497 std::move(attributeName),
498 std::make_tuple(attributeType, readonlyStatus, displayName,
499 description, menuPath, currentValue, defaultValue,
500 std::move(options)));
501 }
502
503 return PLDM_SUCCESS;
504}
505
506void BIOSConfig::updateBaseBIOSTableProperty()
507{
508 constexpr static auto biosConfigPath =
509 "/xyz/openbmc_project/bios_config/manager";
510 constexpr static auto biosConfigInterface =
511 "xyz.openbmc_project.BIOSConfig.Manager";
512 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
513 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
514
515 if (baseBIOSTableMaps.empty())
516 {
517 return;
518 }
519
520 try
521 {
522 auto& bus = dbusHandler->getBus();
Patrick Williams6da4f912023-05-10 07:50:53 -0500523 auto service = dbusHandler->getService(biosConfigPath,
524 biosConfigInterface);
George Liu1b180d82020-07-23 14:01:58 +0800525 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
526 dbusProperties, "Set");
527 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
528 method.append(biosConfigInterface, biosConfigPropertyName, value);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000529 bus.call_noreply(method, dbusTimeout);
George Liu1b180d82020-07-23 14:01:58 +0800530 }
531 catch (const std::exception& e)
532 {
Riya Dixit89644442024-03-31 05:39:59 -0500533 error("Failed to update BaseBIOSTable property, error - {ERROR}",
534 "ERROR", e);
George Liu1b180d82020-07-23 14:01:58 +0800535 }
536}
537
John Wangd9659342020-02-27 16:46:05 +0800538void BIOSConfig::constructAttributes()
539{
Archana Kakaniac713ee2024-05-20 01:27:53 -0500540 info("Bios Attribute file path: {PATH}", "PATH",
541 (jsonDir / sysType / attributesJsonFile));
542 load(jsonDir / sysType / attributesJsonFile, [this](const Json& entry) {
543 std::string attrType = entry.at("attribute_type");
544 if (attrType == "string")
545 {
546 constructAttribute<BIOSStringAttribute>(entry);
547 }
548 else if (attrType == "integer")
549 {
550 constructAttribute<BIOSIntegerAttribute>(entry);
551 }
552 else if (attrType == "enum")
553 {
554 constructAttribute<BIOSEnumAttribute>(entry);
555 }
John Wang3be70852020-02-13 15:59:04 +0800556 });
John Wangd9659342020-02-27 16:46:05 +0800557}
558
559void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
560{
561 BIOSStringTable biosStringTable(stringTable);
562
563 if (biosAttributes.empty())
564 {
565 return;
566 }
567
Tom Josephca7b2522020-11-18 12:27:11 +0530568 BaseBIOSTable biosTable{};
569 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
570 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
571
572 try
573 {
574 auto& bus = dbusHandler->getBus();
575 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams6da4f912023-05-10 07:50:53 -0500576 auto method = bus.new_method_call(service.c_str(), biosObjPath,
577 "org.freedesktop.DBus.Properties",
578 "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530579 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500580 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530581 std::variant<BaseBIOSTable> varBiosTable{};
582 reply.read(varBiosTable);
583 biosTable = std::get<BaseBIOSTable>(varBiosTable);
584 }
585 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
586 // default values populated from the BIOS JSONs to keep PLDM and
587 // bios-settings-manager in sync
588 catch (const std::exception& e)
589 {
Riya Dixit89644442024-03-31 05:39:59 -0500590 error("Failed to read BaseBIOSTable property, error - {ERROR}", "ERROR",
591 e);
Tom Josephca7b2522020-11-18 12:27:11 +0530592 }
593
John Wangd9659342020-02-27 16:46:05 +0800594 Table attrTable, attrValueTable;
595
596 for (auto& attr : biosAttributes)
597 {
598 try
599 {
Tom Josephca7b2522020-11-18 12:27:11 +0530600 auto iter = biosTable.find(attr->name);
601 if (iter == biosTable.end())
602 {
603 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
604 std::nullopt);
605 }
606 else
607 {
608 attr->constructEntry(
609 biosStringTable, attrTable, attrValueTable,
610 std::get<static_cast<uint8_t>(Index::currentValue)>(
611 iter->second));
612 }
John Wangd9659342020-02-27 16:46:05 +0800613 }
614 catch (const std::exception& e)
615 {
Riya Dixit89644442024-03-31 05:39:59 -0500616 error(
617 "Failed to construct table entry for attribute '{ATTRIBUTE}', error - {ERROR}",
618 "ATTRIBUTE", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800619 }
620 }
621
622 table::appendPadAndChecksum(attrTable);
623 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800624 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
625 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800626}
627
628std::optional<Table> BIOSConfig::buildAndStoreStringTable()
629{
630 std::set<std::string> strings;
Archana Kakaniac713ee2024-05-20 01:27:53 -0500631 load(jsonDir / sysType / attributesJsonFile, [&strings](const Json& entry) {
632 if (entry.at("attribute_type") == "enum")
John Wangd9659342020-02-27 16:46:05 +0800633 {
Archana Kakaniac713ee2024-05-20 01:27:53 -0500634 strings.emplace(entry.at("attribute_name"));
635 auto possibleValues = entry.at("possible_values");
636 for (auto& pv : possibleValues)
637 {
638 strings.emplace(pv);
639 }
640 }
641 else
642 {
643 strings.emplace(entry.at("attribute_name"));
John Wangd9659342020-02-27 16:46:05 +0800644 }
645 });
646
647 if (strings.empty())
648 {
649 return std::nullopt;
650 }
651
652 Table table;
653 for (const auto& elem : strings)
654 {
655 table::string::constructEntry(table, elem);
656 }
657
658 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800659 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800660 return table;
661}
662
663void BIOSConfig::storeTable(const fs::path& path, const Table& table)
664{
665 BIOSTable biosTable(path.c_str());
666 biosTable.store(table);
667}
668
669std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
670{
671 BIOSTable biosTable(path.c_str());
672 if (biosTable.isEmpty())
673 {
674 return std::nullopt;
675 }
676
677 Table table;
678 biosTable.load(table);
679 return table;
680}
681
682void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
683{
684 std::ifstream file;
685 Json jsonConf;
686 if (fs::exists(filePath))
687 {
688 try
689 {
690 file.open(filePath);
691 jsonConf = Json::parse(file);
692 auto entries = jsonConf.at("entries");
693 for (auto& entry : entries)
694 {
695 try
696 {
697 handler(entry);
698 }
699 catch (const std::exception& e)
700 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600701 error(
Riya Dixit89644442024-03-31 05:39:59 -0500702 "Failed to parse JSON config file at path '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500703 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800704 }
705 }
706 }
707 catch (const std::exception& e)
708 {
Riya Dixit89644442024-03-31 05:39:59 -0500709 error("Failed to parse JSON config file '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500710 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800711 }
712 }
713}
714
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600715std::string BIOSConfig::decodeStringFromStringEntry(
716 const pldm_bios_string_table_entry* stringEntry)
717{
718 auto strLength =
719 pldm_bios_table_string_entry_decode_string_length(stringEntry);
720 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930721 // Preconditions are upheld therefore no error check necessary
722 pldm_bios_table_string_entry_decode_string_check(stringEntry, buffer.data(),
723 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600724 return std::string(buffer.data(), buffer.data() + strLength);
725}
726
727std::string
728 BIOSConfig::displayStringHandle(uint16_t handle, uint8_t index,
729 const std::optional<Table>& attrTable,
730 const std::optional<Table>& stringTable)
731{
732 auto attrEntry = pldm_bios_table_attr_find_by_handle(
733 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930734 uint8_t pvNum;
735 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
736 &pvNum);
737 if (rc != PLDM_SUCCESS)
738 {
739 error(
Riya Dixit89644442024-03-31 05:39:59 -0500740 "Failed to decode BIOS table possible values for attribute entry, response code '{RC}'",
741 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930742 throw std::runtime_error(
743 "Failed to decode BIOS table possible values for attribute entry");
744 }
745
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600746 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930747 // Preconditions are upheld therefore no error check necessary
748 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
749 attrEntry, pvHandls.data(), pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600750
751 std::string displayString = std::to_string(pvHandls[index]);
752
753 auto stringEntry = pldm_bios_table_string_find_by_handle(
754 stringTable->data(), stringTable->size(), pvHandls[index]);
755
756 auto decodedStr = decodeStringFromStringEntry(stringEntry);
757
758 return decodedStr + "(" + displayString + ")";
759}
760
761void BIOSConfig::traceBIOSUpdate(
762 const pldm_bios_attr_val_table_entry* attrValueEntry,
763 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
764{
765 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
766 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
767
Patrick Williams6da4f912023-05-10 07:50:53 -0500768 auto [attrHandle,
769 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600770
771 auto attrHeader = table::attribute::decodeHeader(attrEntry);
772 BIOSStringTable biosStringTable(*stringTable);
773 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
774
775 switch (attrType)
776 {
777 case PLDM_BIOS_ENUMERATION:
778 case PLDM_BIOS_ENUMERATION_READ_ONLY:
779 {
780 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
781 attrValueEntry);
782 std::vector<uint8_t> handles(count);
783 pldm_bios_table_attr_value_entry_enum_decode_handles(
784 attrValueEntry, handles.data(), handles.size());
785
786 for (uint8_t handle : handles)
787 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600788 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
789 stringTable);
790 auto chkBMC = isBMC ? "true" : "false";
791 info(
Riya Dixit89644442024-03-31 05:39:59 -0500792 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
793 "ATTRIBUTE", attrName, "VALUE", nwVal, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600794 }
795 break;
796 }
797 case PLDM_BIOS_INTEGER:
798 case PLDM_BIOS_INTEGER_READ_ONLY:
799 {
800 auto value =
801 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600802 auto chkBMC = isBMC ? "true" : "false";
803 info(
Riya Dixit89644442024-03-31 05:39:59 -0500804 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
805 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600806 break;
807 }
808 case PLDM_BIOS_STRING:
809 case PLDM_BIOS_STRING_READ_ONLY:
810 {
811 auto value =
812 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600813 auto chkBMC = isBMC ? "true" : "false";
814 info(
Riya Dixit89644442024-03-31 05:39:59 -0500815 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
816 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600817 break;
818 }
819 default:
820 break;
821 };
822}
823
John Wang8241b342020-06-05 10:49:17 +0800824int BIOSConfig::checkAttrValueToUpdate(
825 const pldm_bios_attr_val_table_entry* attrValueEntry,
826 const pldm_bios_attr_table_entry* attrEntry, Table&)
827
828{
Patrick Williams6da4f912023-05-10 07:50:53 -0500829 auto [attrHandle,
830 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800831
832 switch (attrType)
833 {
834 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800835 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800836 {
837 auto value =
838 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500839 auto [pvHdls,
840 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600841 if (!(value.size() == 1))
842 {
843 return PLDM_ERROR_INVALID_LENGTH;
844 }
John Wang8241b342020-06-05 10:49:17 +0800845 if (value[0] >= pvHdls.size())
846 {
Riya Dixit89644442024-03-31 05:39:59 -0500847 error(
848 "Invalid index '{INDEX}' encountered for Enum type BIOS attribute",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500849 "INDEX", value[0]);
John Wang8241b342020-06-05 10:49:17 +0800850 return PLDM_ERROR_INVALID_DATA;
851 }
John Wang8241b342020-06-05 10:49:17 +0800852 return PLDM_SUCCESS;
853 }
854 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800855 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800856 {
857 auto value =
858 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500859 auto [lower, upper, scalar,
860 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800861
862 if (value < lower || value > upper)
863 {
Riya Dixit89644442024-03-31 05:39:59 -0500864 error(
865 "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}'.",
866 "ATTRIBUTE_VALUE", value, "LOWER", lower, "UPPER", upper,
867 "SCALAR", scalar);
John Wang8241b342020-06-05 10:49:17 +0800868 return PLDM_ERROR_INVALID_DATA;
869 }
870 return PLDM_SUCCESS;
871 }
872 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800873 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800874 {
875 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
876 auto value =
877 table::attribute_value::decodeStringEntry(attrValueEntry);
878 if (value.size() < stringConf.minLength ||
879 value.size() > stringConf.maxLength)
880 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600881 error(
Riya Dixit89644442024-03-31 05:39:59 -0500882 "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}'",
883 "ATTRIBUTE_VALUE", value, "LENGTH", value.size(), "MIN_LEN",
884 stringConf.minLength, "MAX_LEN", stringConf.maxLength);
John Wang8241b342020-06-05 10:49:17 +0800885 return PLDM_ERROR_INVALID_LENGTH;
886 }
887 return PLDM_SUCCESS;
888 }
889 default:
Riya Dixit89644442024-03-31 05:39:59 -0500890 error("ReadOnly or Unsupported type '{TYPE}'", "TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800891 return PLDM_ERROR;
892 };
893}
894
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600895int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
896 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800897{
898 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
899 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
900 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
901 if (!attrValueTable || !attrTable || !stringTable)
902 {
903 return PLDM_BIOS_TABLE_UNAVAILABLE;
904 }
905
John Wangd9659342020-02-27 16:46:05 +0800906 auto attrValueEntry =
907 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
908
909 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
910
Patrick Williams6da4f912023-05-10 07:50:53 -0500911 auto attrEntry = table::attribute::findByHandle(*attrTable,
912 attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800913 if (!attrEntry)
914 {
915 return PLDM_ERROR;
916 }
917
John Wang8241b342020-06-05 10:49:17 +0800918 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
919 if (rc != PLDM_SUCCESS)
920 {
921 return rc;
922 }
923
Patrick Williams6da4f912023-05-10 07:50:53 -0500924 auto destTable = table::attribute_value::updateTable(*attrValueTable, entry,
925 size);
John Wang8241b342020-06-05 10:49:17 +0800926
927 if (!destTable)
928 {
929 return PLDM_ERROR;
930 }
931
John Wangd9659342020-02-27 16:46:05 +0800932 try
933 {
934 auto attrHeader = table::attribute::decodeHeader(attrEntry);
935
936 BIOSStringTable biosStringTable(*stringTable);
937 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500938 auto iter = std::find_if(
939 biosAttributes.begin(), biosAttributes.end(),
940 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800941
942 if (iter == biosAttributes.end())
943 {
944 return PLDM_ERROR;
945 }
George Liu6d6d1e82021-02-16 11:08:55 +0800946 if (updateDBus)
947 {
948 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
949 biosStringTable);
950 }
John Wangd9659342020-02-27 16:46:05 +0800951 }
952 catch (const std::exception& e)
953 {
Riya Dixit89644442024-03-31 05:39:59 -0500954 error("Set attribute value error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800955 return PLDM_ERROR;
956 }
957
Tom Joseph7f839f92020-09-21 10:20:44 +0530958 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800959
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600960 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
961
John Wangd9659342020-02-27 16:46:05 +0800962 return PLDM_SUCCESS;
963}
964
965void BIOSConfig::removeTables()
966{
967 try
968 {
969 fs::remove(tableDir / stringTableFile);
970 fs::remove(tableDir / attrTableFile);
971 fs::remove(tableDir / attrValueTableFile);
972 }
973 catch (const std::exception& e)
974 {
Riya Dixit89644442024-03-31 05:39:59 -0500975 error("Remove the tables error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800976 }
977}
978
Sampa Misra46ece062020-03-18 07:17:44 -0500979void BIOSConfig::processBiosAttrChangeNotification(
980 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
981{
982 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
983 const auto& propertyName = dBusMap->propertyName;
984 const auto& attrName = biosAttributes[biosAttrIndex]->name;
985
986 const auto it = chProperties.find(propertyName);
987 if (it == chProperties.end())
988 {
989 return;
990 }
991
992 PropertyValue newPropVal = it->second;
993 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
994 if (!stringTable.has_value())
995 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600996 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500997 return;
998 }
999 BIOSStringTable biosStringTable(*stringTable);
1000 uint16_t attrNameHdl{};
1001 try
1002 {
1003 attrNameHdl = biosStringTable.findHandle(attrName);
1004 }
Patrick Williams51330582021-10-06 12:48:56 -05001005 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -05001006 {
Riya Dixit89644442024-03-31 05:39:59 -05001007 error(
1008 "Missing handle for attribute '{ATTRIBUTE}' in BIOS String Table, error - '{ERROR}'",
1009 "ATTRIBUTE", attrName, "ERROR", e);
Sampa Misra46ece062020-03-18 07:17:44 -05001010 return;
1011 }
1012
1013 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1014 if (!attrTable.has_value())
1015 {
Riya Dixit89644442024-03-31 05:39:59 -05001016 error("BIOS Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001017 return;
1018 }
1019 const struct pldm_bios_attr_table_entry* tableEntry =
1020 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
1021 if (tableEntry == nullptr)
1022 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001023 error(
Riya Dixit89644442024-03-31 05:39:59 -05001024 "Failed to find attribute {ATTRIBUTE} in BIOS Attribute table with attribute handle '{ATTR_HANDLE}'",
1025 "ATTRIBUTE", attrName, "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -05001026 return;
1027 }
1028
Patrick Williams6da4f912023-05-10 07:50:53 -05001029 auto [attrHdl, attrType,
1030 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -05001031
1032 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
1033
1034 if (!attrValueSrcTable.has_value())
1035 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001036 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001037 return;
1038 }
1039
1040 Table newValue;
1041 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
1042 newValue, attrHdl, attrType, newPropVal);
1043 if (rc != PLDM_SUCCESS)
1044 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001045 error(
Riya Dixit89644442024-03-31 05:39:59 -05001046 "Failed to update the attribute value table for attribute handle '{ATTR_HANDLE}' and attribute type '{TYPE}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -05001047 "ATTR_HANDLE", attrHdl, "TYPE", attrType);
Sampa Misra46ece062020-03-18 07:17:44 -05001048 return;
1049 }
1050 auto destTable = table::attribute_value::updateTable(
1051 *attrValueSrcTable, newValue.data(), newValue.size());
1052 if (destTable.has_value())
1053 {
1054 storeTable(tableDir / attrValueTableFile, *destTable);
1055 }
Sampa Misra0f262332021-02-15 00:13:51 -06001056
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001057 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001058 if (rc != PLDM_SUCCESS)
1059 {
Riya Dixit89644442024-03-31 05:39:59 -05001060 error(
1061 "Failed to setAttrValue on base bios table and dbus, response code '{RC}'",
1062 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001063 }
Sampa Misra46ece062020-03-18 07:17:44 -05001064}
1065
George Liu1244acf2020-08-14 09:11:11 +08001066uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1067{
1068 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1069 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1070
1071 BIOSStringTable biosStringTable(*stringTable);
1072 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1073 attrTable->data(), attrTable->size());
1074 auto stringHandle = biosStringTable.findHandle(attrName);
1075
1076 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1077 attrTable->data(), attrTable->size()))
1078 {
1079 auto header = table::attribute::decodeHeader(entry);
1080 if (header.stringHandle == stringHandle)
1081 {
1082 return header.attrHandle;
1083 }
1084 }
1085
Manojkiran Eda2576aec2024-06-17 12:05:17 +05301086 throw std::invalid_argument("Unknown attribute Name");
George Liu1244acf2020-08-14 09:11:11 +08001087}
1088
1089void BIOSConfig::constructPendingAttribute(
1090 const PendingAttributes& pendingAttributes)
1091{
Tom Joseph7f839f92020-09-21 10:20:44 +05301092 std::vector<uint16_t> listOfHandles{};
1093
George Liu1244acf2020-08-14 09:11:11 +08001094 for (auto& attribute : pendingAttributes)
1095 {
1096 std::string attributeName = attribute.first;
1097 auto& [attributeType, attributevalue] = attribute.second;
1098
1099 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1100 [&attributeName](const auto& attr) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001101 return attr->name == attributeName;
1102 });
George Liu1244acf2020-08-14 09:11:11 +08001103
1104 if (iter == biosAttributes.end())
1105 {
Riya Dixit89644442024-03-31 05:39:59 -05001106 error("Wrong attribute name {NAME}", "NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001107 continue;
1108 }
1109
1110 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
1111 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
1112 attrValueEntry.data());
1113
1114 auto handler = findAttrHandle(attributeName);
1115 auto type =
1116 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1117
1118 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1119 type != BIOSConfigManager::AttributeType::String &&
1120 type != BIOSConfigManager::AttributeType::Integer)
1121 {
Riya Dixit89644442024-03-31 05:39:59 -05001122 error("Attribute type '{TYPE}' not supported", "TYPE",
1123 attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001124 continue;
1125 }
1126
George Liu4876c542022-06-08 15:59:54 +08001127 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001128 menuPath, currentValue, defaultValue,
1129 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001130
George Liu1244acf2020-08-14 09:11:11 +08001131 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001132
1133 // Need to verify that the current value has really changed
1134 if (attributeType == attrType && attributevalue != currentValue)
1135 {
1136 listOfHandles.emplace_back(htole16(handler));
1137 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301138
George Liu1244acf2020-08-14 09:11:11 +08001139 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1140
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001141 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301142 }
1143
1144 if (listOfHandles.size())
1145 {
1146#ifdef OEM_IBM
1147 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301148 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301149 if (rc != PLDM_SUCCESS)
1150 {
1151 return;
1152 }
1153#endif
George Liu1244acf2020-08-14 09:11:11 +08001154 }
1155}
1156
1157void BIOSConfig::listenPendingAttributes()
1158{
1159 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1160 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1161
1162 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001163 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001164 pldm::utils::DBusHandler::getBus(),
1165 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001166 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001167 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001168
Patrick Williams6da4f912023-05-10 07:50:53 -05001169 using Value =
1170 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1171 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001172
Patrick Williams6da4f912023-05-10 07:50:53 -05001173 Properties props{};
1174 std::string intf;
1175 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001176
Patrick Williams6da4f912023-05-10 07:50:53 -05001177 auto valPropMap = props.find(propertyName);
1178 if (valPropMap == props.end())
1179 {
1180 return;
1181 }
George Liu1244acf2020-08-14 09:11:11 +08001182
Patrick Williams6da4f912023-05-10 07:50:53 -05001183 PendingAttributes pendingAttributes =
1184 std::get<PendingAttributes>(valPropMap->second);
1185 this->constructPendingAttribute(pendingAttributes);
Patrick Williamsa6756622023-10-20 11:19:15 -05001186 });
George Liu1244acf2020-08-14 09:11:11 +08001187
1188 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1189}
1190
John Wangd9659342020-02-27 16:46:05 +08001191} // namespace bios
1192} // namespace responder
1193} // namespace pldm