blob: 6cc9c244b518827329e302c62e3e5195916f1823 [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
John Wangd9659342020-02-27 16:46:05 +080034constexpr auto enumJsonFile = "enum_attrs.json";
35constexpr auto stringJsonFile = "string_attrs.json";
36constexpr auto integerJsonFile = "integer_attrs.json";
37
38constexpr auto stringTableFile = "stringTable";
39constexpr auto attrTableFile = "attributeTable";
40constexpr auto attrValueTableFile = "attributeValueTable";
41
42} // namespace
43
Sampa Misrac0c79482021-06-02 08:01:54 -050044BIOSConfig::BIOSConfig(
45 const char* jsonDir, const char* tableDir, DBusHandler* const dbusHandler,
Andrew Jefferya330b2f2023-05-04 14:55:37 +093046 int fd, uint8_t eid, pldm::InstanceIdDb* instanceIdDb,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050047 pldm::requester::Handler<pldm::requester::Request>* handler,
Archana Kakani62dd8ff2024-02-12 10:00:40 -060048 pldm::responder::platform_config::Handler* platformConfigHandler,
49 pldm::responder::bios::Callback requestPLDMServiceName) :
John Wangd9659342020-02-27 16:46:05 +080050 jsonDir(jsonDir),
Tom Joseph7f839f92020-09-21 10:20:44 +053051 tableDir(tableDir), dbusHandler(dbusHandler), fd(fd), eid(eid),
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060052 instanceIdDb(instanceIdDb), handler(handler),
Archana Kakani62dd8ff2024-02-12 10:00:40 -060053 platformConfigHandler(platformConfigHandler),
54 requestPLDMServiceName(requestPLDMServiceName)
55{
56 fs::create_directories(tableDir);
57 removeTables();
58 if (isSystemTypeAvailable())
59 {
60 initBIOSAttributes(sysType);
61 }
62 listenPendingAttributes();
63}
Tom Joseph7f839f92020-09-21 10:20:44 +053064
Archana Kakani62dd8ff2024-02-12 10:00:40 -060065bool BIOSConfig::isSystemTypeAvailable()
John Wangd9659342020-02-27 16:46:05 +080066{
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060067 if (platformConfigHandler)
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050068 {
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060069 auto systemType = platformConfigHandler->getPlatformName();
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050070 if (systemType.has_value())
71 {
72 sysType = systemType.value();
73 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060074 else
75 {
76 platformConfigHandler->registerSystemTypeCallback(std::bind(
77 &BIOSConfig::initBIOSAttributes, this, std::placeholders::_1));
78 return false;
79 }
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050080 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060081 return true;
82}
83
84void BIOSConfig::initBIOSAttributes(const std::string& systemType)
85{
86 sysType = systemType;
87 fs::path dir{jsonDir / sysType};
88 if (!fs::exists(dir))
89 {
90 error("System specific bios attribute directory {DIR} does not exit",
91 "DIR", dir.string());
92 return;
93 }
John Wangd9659342020-02-27 16:46:05 +080094 constructAttributes();
Archana Kakani62dd8ff2024-02-12 10:00:40 -060095 buildTables();
96 requestPLDMServiceName();
John Wangd9659342020-02-27 16:46:05 +080097}
98
99void BIOSConfig::buildTables()
100{
John Wangd9659342020-02-27 16:46:05 +0800101 auto stringTable = buildAndStoreStringTable();
102 if (stringTable)
103 {
104 buildAndStoreAttrTables(*stringTable);
105 }
106}
107
108std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
109{
110 fs::path tablePath;
111 switch (tableType)
112 {
113 case PLDM_BIOS_STRING_TABLE:
114 tablePath = tableDir / stringTableFile;
115 break;
116 case PLDM_BIOS_ATTR_TABLE:
117 tablePath = tableDir / attrTableFile;
118 break;
119 case PLDM_BIOS_ATTR_VAL_TABLE:
120 tablePath = tableDir / attrValueTableFile;
121 break;
122 }
123 return loadTable(tablePath);
124}
125
Tom Joseph7f839f92020-09-21 10:20:44 +0530126int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table,
127 bool updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800128{
129 fs::path stringTablePath(tableDir / stringTableFile);
130 fs::path attrTablePath(tableDir / attrTableFile);
131 fs::path attrValueTablePath(tableDir / attrValueTableFile);
132
133 if (!pldm_bios_table_checksum(table.data(), table.size()))
134 {
135 return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
136 }
137
138 if (tableType == PLDM_BIOS_STRING_TABLE)
139 {
140 storeTable(stringTablePath, table);
141 }
142 else if (tableType == PLDM_BIOS_ATTR_TABLE)
143 {
144 BIOSTable biosStringTable(stringTablePath.c_str());
145 if (biosStringTable.isEmpty())
146 {
147 return PLDM_INVALID_BIOS_TABLE_TYPE;
148 }
149
150 auto rc = checkAttributeTable(table);
151 if (rc != PLDM_SUCCESS)
152 {
153 return rc;
154 }
155
156 storeTable(attrTablePath, table);
157 }
158 else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
159 {
160 BIOSTable biosStringTable(stringTablePath.c_str());
161 BIOSTable biosStringValueTable(attrTablePath.c_str());
162 if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
163 {
164 return PLDM_INVALID_BIOS_TABLE_TYPE;
165 }
166
167 auto rc = checkAttributeValueTable(table);
168 if (rc != PLDM_SUCCESS)
169 {
170 return rc;
171 }
172
173 storeTable(attrValueTablePath, table);
George Liu1b180d82020-07-23 14:01:58 +0800174 }
175 else
176 {
177 return PLDM_INVALID_BIOS_TABLE_TYPE;
178 }
179
Tom Joseph7f839f92020-09-21 10:20:44 +0530180 if ((tableType == PLDM_BIOS_ATTR_VAL_TABLE) && updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800181 {
George Liu1b180d82020-07-23 14:01:58 +0800182 updateBaseBIOSTableProperty();
183 }
184
185 return PLDM_SUCCESS;
186}
187
188int BIOSConfig::checkAttributeTable(const Table& table)
189{
190 using namespace pldm::bios::utils;
191 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
192 for (auto entry :
193 BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
194 {
195 auto attrNameHandle =
196 pldm_bios_table_attr_entry_decode_string_handle(entry);
197
198 auto stringEnty = pldm_bios_table_string_find_by_handle(
199 stringTable->data(), stringTable->size(), attrNameHandle);
200 if (stringEnty == nullptr)
201 {
202 return PLDM_INVALID_BIOS_ATTR_HANDLE;
203 }
204
205 auto attrType = static_cast<pldm_bios_attribute_type>(
206 pldm_bios_table_attr_entry_decode_attribute_type(entry));
207
208 switch (attrType)
209 {
210 case PLDM_BIOS_ENUMERATION:
211 case PLDM_BIOS_ENUMERATION_READ_ONLY:
212 {
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930213 uint8_t pvNum;
214 // Preconditions are upheld therefore no error check necessary
215 pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry,
216 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800217 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930218 // Preconditions are upheld therefore no error check necessary
219 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800220 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930221 uint8_t defNum;
222 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry,
223 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800224 std::vector<uint8_t> defIndices(defNum);
225 pldm_bios_table_attr_entry_enum_decode_def_indices(
226 entry, defIndices.data(), defIndices.size());
227
228 for (size_t i = 0; i < pvHandls.size(); i++)
229 {
230 auto stringEntry = pldm_bios_table_string_find_by_handle(
231 stringTable->data(), stringTable->size(), pvHandls[i]);
232 if (stringEntry == nullptr)
233 {
234 return PLDM_INVALID_BIOS_ATTR_HANDLE;
235 }
236 }
237
238 for (size_t i = 0; i < defIndices.size(); i++)
239 {
240 auto stringEntry = pldm_bios_table_string_find_by_handle(
241 stringTable->data(), stringTable->size(),
242 pvHandls[defIndices[i]]);
243 if (stringEntry == nullptr)
244 {
245 return PLDM_INVALID_BIOS_ATTR_HANDLE;
246 }
247 }
248 break;
249 }
250 case PLDM_BIOS_INTEGER:
251 case PLDM_BIOS_INTEGER_READ_ONLY:
252 case PLDM_BIOS_STRING:
253 case PLDM_BIOS_STRING_READ_ONLY:
254 case PLDM_BIOS_PASSWORD:
255 case PLDM_BIOS_PASSWORD_READ_ONLY:
256 break;
257 default:
258 return PLDM_INVALID_BIOS_ATTR_HANDLE;
259 }
260 }
261
262 return PLDM_SUCCESS;
263}
264
265int BIOSConfig::checkAttributeValueTable(const Table& table)
266{
267 using namespace pldm::bios::utils;
268 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
269 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
270
271 baseBIOSTableMaps.clear();
272
273 for (auto tableEntry :
274 BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
275 {
276 AttributeName attributeName{};
277 AttributeType attributeType{};
278 ReadonlyStatus readonlyStatus{};
279 DisplayName displayName{};
280 Description description{};
281 MenuPath menuPath{};
282 CurrentValue currentValue{};
283 DefaultValue defaultValue{};
Sagar Srinivas7927f902023-10-09 07:53:00 -0500284 std::vector<ValueDisplayName> valueDisplayNames;
285 std::map<uint16_t, std::vector<std::string>> valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800286 Option options{};
287
288 auto attrValueHandle =
289 pldm_bios_table_attr_value_entry_decode_attribute_handle(
290 tableEntry);
291 auto attrType = static_cast<pldm_bios_attribute_type>(
292 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
293
294 auto attrEntry = pldm_bios_table_attr_find_by_handle(
295 attrTable->data(), attrTable->size(), attrValueHandle);
296 if (attrEntry == nullptr)
297 {
298 return PLDM_INVALID_BIOS_ATTR_HANDLE;
299 }
300 auto attrHandle =
301 pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
302 auto attrNameHandle =
303 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
304
305 auto stringEntry = pldm_bios_table_string_find_by_handle(
306 stringTable->data(), stringTable->size(), attrNameHandle);
307 if (stringEntry == nullptr)
308 {
309 return PLDM_INVALID_BIOS_ATTR_HANDLE;
310 }
311 auto strLength =
312 pldm_bios_table_string_entry_decode_string_length(stringEntry);
313 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930314 // Preconditions are upheld therefore no error check necessary
315 pldm_bios_table_string_entry_decode_string_check(
316 stringEntry, buffer.data(), buffer.size());
317
George Liu1b180d82020-07-23 14:01:58 +0800318 attributeName = std::string(buffer.data(), buffer.data() + strLength);
319
320 if (!biosAttributes.empty())
321 {
322 readonlyStatus =
George Liub1fbeec2020-09-04 09:59:46 +0800323 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800324 description =
325 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
326 displayName =
327 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
Sagar Srinivas7927f902023-10-09 07:53:00 -0500328 valueDisplayNamesMap =
329 biosAttributes[attrHandle % biosAttributes.size()]
330 ->valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800331 }
332
333 switch (attrType)
334 {
335 case PLDM_BIOS_ENUMERATION:
336 case PLDM_BIOS_ENUMERATION_READ_ONLY:
337 {
Sagar Srinivas7927f902023-10-09 07:53:00 -0500338 if (valueDisplayNamesMap.contains(attrHandle))
339 {
340 const std::vector<ValueDisplayName>& vdn =
341 valueDisplayNamesMap[attrHandle];
342 valueDisplayNames.insert(valueDisplayNames.end(),
343 vdn.begin(), vdn.end());
344 }
George Liu1b180d82020-07-23 14:01:58 +0800345 auto getValue = [](uint16_t handle,
346 const Table& table) -> std::string {
347 auto stringEntry = pldm_bios_table_string_find_by_handle(
348 table.data(), table.size(), handle);
349
350 auto strLength =
351 pldm_bios_table_string_entry_decode_string_length(
352 stringEntry);
353 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930354 // Preconditions are upheld therefore no error check
355 // necessary
356 pldm_bios_table_string_entry_decode_string_check(
George Liu1b180d82020-07-23 14:01:58 +0800357 stringEntry, buffer.data(), buffer.size());
358
359 return std::string(buffer.data(),
360 buffer.data() + strLength);
361 };
362
363 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
364 "AttributeType.Enumeration";
365
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930366 uint8_t pvNum;
367 // Preconditions are upheld therefore no error check necessary
368 pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
369 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800370 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930371 // Preconditions are upheld therefore no error check necessary
372 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800373 attrEntry, pvHandls.data(), pvHandls.size());
374
375 // get possible_value
376 for (size_t i = 0; i < pvHandls.size(); i++)
377 {
378 options.push_back(
379 std::make_tuple("xyz.openbmc_project.BIOSConfig."
380 "Manager.BoundType.OneOf",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500381 getValue(pvHandls[i], *stringTable),
382 valueDisplayNames[i]));
George Liu1b180d82020-07-23 14:01:58 +0800383 }
384
385 auto count =
386 pldm_bios_table_attr_value_entry_enum_decode_number(
387 tableEntry);
388 std::vector<uint8_t> handles(count);
389 pldm_bios_table_attr_value_entry_enum_decode_handles(
390 tableEntry, handles.data(), handles.size());
391
392 // get current_value
393 for (size_t i = 0; i < handles.size(); i++)
394 {
395 currentValue = getValue(pvHandls[handles[i]], *stringTable);
396 }
397
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930398 uint8_t defNum;
399 // Preconditions are upheld therefore no error check necessary
400 pldm_bios_table_attr_entry_enum_decode_def_num_check(attrEntry,
401 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800402 std::vector<uint8_t> defIndices(defNum);
403 pldm_bios_table_attr_entry_enum_decode_def_indices(
404 attrEntry, defIndices.data(), defIndices.size());
405
406 // get default_value
407 for (size_t i = 0; i < defIndices.size(); i++)
408 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500409 defaultValue = getValue(pvHandls[defIndices[i]],
410 *stringTable);
George Liu1b180d82020-07-23 14:01:58 +0800411 }
412
413 break;
414 }
415 case PLDM_BIOS_INTEGER:
416 case PLDM_BIOS_INTEGER_READ_ONLY:
417 {
418 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
419 "AttributeType.Integer";
420 currentValue = static_cast<int64_t>(
421 pldm_bios_table_attr_value_entry_integer_decode_cv(
422 tableEntry));
423
424 uint64_t lower, upper, def;
425 uint32_t scalar;
426 pldm_bios_table_attr_entry_integer_decode(
427 attrEntry, &lower, &upper, &scalar, &def);
Sagar Srinivas7927f902023-10-09 07:53:00 -0500428 options.push_back(std::make_tuple(
429 "xyz.openbmc_project.BIOSConfig.Manager."
430 "BoundType.LowerBound",
431 static_cast<int64_t>(lower), attributeName));
432 options.push_back(std::make_tuple(
433 "xyz.openbmc_project.BIOSConfig.Manager."
434 "BoundType.UpperBound",
435 static_cast<int64_t>(upper), attributeName));
436 options.push_back(std::make_tuple(
437 "xyz.openbmc_project.BIOSConfig.Manager."
438 "BoundType.ScalarIncrement",
439 static_cast<int64_t>(scalar), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800440 defaultValue = static_cast<int64_t>(def);
441 break;
442 }
443 case PLDM_BIOS_STRING:
444 case PLDM_BIOS_STRING_READ_ONLY:
445 {
446 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
447 "AttributeType.String";
448 variable_field currentString;
449 pldm_bios_table_attr_value_entry_string_decode_string(
450 tableEntry, &currentString);
451 currentValue = std::string(
452 reinterpret_cast<const char*>(currentString.ptr),
453 currentString.length);
454 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
455 attrEntry);
456 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
457 attrEntry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930458 uint16_t def;
459 // Preconditions are upheld therefore no error check necessary
460 pldm_bios_table_attr_entry_string_decode_def_string_length_check(
461 attrEntry, &def);
George Liu1b180d82020-07-23 14:01:58 +0800462 std::vector<char> defString(def + 1);
463 pldm_bios_table_attr_entry_string_decode_def_string(
464 attrEntry, defString.data(), defString.size());
465 options.push_back(
466 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
467 "BoundType.MinStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500468 static_cast<int64_t>(min), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800469 options.push_back(
470 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
471 "BoundType.MaxStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500472 static_cast<int64_t>(max), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800473 defaultValue = defString.data();
474 break;
475 }
476 case PLDM_BIOS_PASSWORD:
477 case PLDM_BIOS_PASSWORD_READ_ONLY:
478 {
479 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
480 "AttributeType.Password";
481 break;
482 }
483 default:
484 return PLDM_INVALID_BIOS_ATTR_HANDLE;
485 }
486 baseBIOSTableMaps.emplace(
487 std::move(attributeName),
488 std::make_tuple(attributeType, readonlyStatus, displayName,
489 description, menuPath, currentValue, defaultValue,
490 std::move(options)));
491 }
492
493 return PLDM_SUCCESS;
494}
495
496void BIOSConfig::updateBaseBIOSTableProperty()
497{
498 constexpr static auto biosConfigPath =
499 "/xyz/openbmc_project/bios_config/manager";
500 constexpr static auto biosConfigInterface =
501 "xyz.openbmc_project.BIOSConfig.Manager";
502 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
503 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
504
505 if (baseBIOSTableMaps.empty())
506 {
507 return;
508 }
509
510 try
511 {
512 auto& bus = dbusHandler->getBus();
Patrick Williams6da4f912023-05-10 07:50:53 -0500513 auto service = dbusHandler->getService(biosConfigPath,
514 biosConfigInterface);
George Liu1b180d82020-07-23 14:01:58 +0800515 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
516 dbusProperties, "Set");
517 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
518 method.append(biosConfigInterface, biosConfigPropertyName, value);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000519 bus.call_noreply(method, dbusTimeout);
George Liu1b180d82020-07-23 14:01:58 +0800520 }
521 catch (const std::exception& e)
522 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600523 error("failed to update BaseBIOSTable property, ERROR={ERR_EXCEP}",
524 "ERR_EXCEP", e.what());
George Liu1b180d82020-07-23 14:01:58 +0800525 }
526}
527
John Wangd9659342020-02-27 16:46:05 +0800528void BIOSConfig::constructAttributes()
529{
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600530 info("Bios Attribute file path: {PATH}", "PATH", (jsonDir / sysType));
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500531 load(jsonDir / sysType / stringJsonFile, [this](const Json& entry) {
John Wangd9659342020-02-27 16:46:05 +0800532 constructAttribute<BIOSStringAttribute>(entry);
533 });
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500534 load(jsonDir / sysType / integerJsonFile, [this](const Json& entry) {
John Wang95e6b3c2020-02-13 09:43:24 +0800535 constructAttribute<BIOSIntegerAttribute>(entry);
536 });
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500537 load(jsonDir / sysType / enumJsonFile, [this](const Json& entry) {
John Wang3be70852020-02-13 15:59:04 +0800538 constructAttribute<BIOSEnumAttribute>(entry);
539 });
John Wangd9659342020-02-27 16:46:05 +0800540}
541
542void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
543{
544 BIOSStringTable biosStringTable(stringTable);
545
546 if (biosAttributes.empty())
547 {
548 return;
549 }
550
Tom Josephca7b2522020-11-18 12:27:11 +0530551 BaseBIOSTable biosTable{};
552 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
553 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
554
555 try
556 {
557 auto& bus = dbusHandler->getBus();
558 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams6da4f912023-05-10 07:50:53 -0500559 auto method = bus.new_method_call(service.c_str(), biosObjPath,
560 "org.freedesktop.DBus.Properties",
561 "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530562 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500563 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530564 std::variant<BaseBIOSTable> varBiosTable{};
565 reply.read(varBiosTable);
566 biosTable = std::get<BaseBIOSTable>(varBiosTable);
567 }
568 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
569 // default values populated from the BIOS JSONs to keep PLDM and
570 // bios-settings-manager in sync
571 catch (const std::exception& e)
572 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600573 error("Failed to read BaseBIOSTable property, ERROR={ERR_EXCEP}",
574 "ERR_EXCEP", e.what());
Tom Josephca7b2522020-11-18 12:27:11 +0530575 }
576
John Wangd9659342020-02-27 16:46:05 +0800577 Table attrTable, attrValueTable;
578
579 for (auto& attr : biosAttributes)
580 {
581 try
582 {
Tom Josephca7b2522020-11-18 12:27:11 +0530583 auto iter = biosTable.find(attr->name);
584 if (iter == biosTable.end())
585 {
586 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
587 std::nullopt);
588 }
589 else
590 {
591 attr->constructEntry(
592 biosStringTable, attrTable, attrValueTable,
593 std::get<static_cast<uint8_t>(Index::currentValue)>(
594 iter->second));
595 }
John Wangd9659342020-02-27 16:46:05 +0800596 }
597 catch (const std::exception& e)
598 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500599 error("Error constructing table entry for '{ATTR}': {ERROR}",
600 "ATTR", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800601 }
602 }
603
604 table::appendPadAndChecksum(attrTable);
605 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800606 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
607 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800608}
609
610std::optional<Table> BIOSConfig::buildAndStoreStringTable()
611{
612 std::set<std::string> strings;
613 auto handler = [&strings](const Json& entry) {
614 strings.emplace(entry.at("attribute_name"));
615 };
616
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500617 load(jsonDir / sysType / stringJsonFile, handler);
618 load(jsonDir / sysType / integerJsonFile, handler);
619 load(jsonDir / sysType / enumJsonFile, [&strings](const Json& entry) {
John Wangd9659342020-02-27 16:46:05 +0800620 strings.emplace(entry.at("attribute_name"));
621 auto possibleValues = entry.at("possible_values");
622 for (auto& pv : possibleValues)
623 {
624 strings.emplace(pv);
625 }
626 });
627
628 if (strings.empty())
629 {
630 return std::nullopt;
631 }
632
633 Table table;
634 for (const auto& elem : strings)
635 {
636 table::string::constructEntry(table, elem);
637 }
638
639 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800640 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800641 return table;
642}
643
644void BIOSConfig::storeTable(const fs::path& path, const Table& table)
645{
646 BIOSTable biosTable(path.c_str());
647 biosTable.store(table);
648}
649
650std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
651{
652 BIOSTable biosTable(path.c_str());
653 if (biosTable.isEmpty())
654 {
655 return std::nullopt;
656 }
657
658 Table table;
659 biosTable.load(table);
660 return table;
661}
662
663void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
664{
665 std::ifstream file;
666 Json jsonConf;
667 if (fs::exists(filePath))
668 {
669 try
670 {
671 file.open(filePath);
672 jsonConf = Json::parse(file);
673 auto entries = jsonConf.at("entries");
674 for (auto& entry : entries)
675 {
676 try
677 {
678 handler(entry);
679 }
680 catch (const std::exception& e)
681 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600682 error(
683 "Failed to parse JSON config file(entry handler) : {JSON_PATH}, {ERR_EXCEP}",
684 "JSON_PATH", filePath.c_str(), "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800685 }
686 }
687 }
688 catch (const std::exception& e)
689 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500690 error("Failed to parse JSON config at '{PATH}': {ERROR}", "PATH",
691 filePath.c_str(), "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800692 }
693 }
694}
695
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600696std::string BIOSConfig::decodeStringFromStringEntry(
697 const pldm_bios_string_table_entry* stringEntry)
698{
699 auto strLength =
700 pldm_bios_table_string_entry_decode_string_length(stringEntry);
701 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930702 // Preconditions are upheld therefore no error check necessary
703 pldm_bios_table_string_entry_decode_string_check(stringEntry, buffer.data(),
704 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600705 return std::string(buffer.data(), buffer.data() + strLength);
706}
707
708std::string
709 BIOSConfig::displayStringHandle(uint16_t handle, uint8_t index,
710 const std::optional<Table>& attrTable,
711 const std::optional<Table>& stringTable)
712{
713 auto attrEntry = pldm_bios_table_attr_find_by_handle(
714 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930715 uint8_t pvNum;
716 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
717 &pvNum);
718 if (rc != PLDM_SUCCESS)
719 {
720 error(
721 "Failed to decode BIOS table possible values for attribute entry: {LIPBLDM_ERROR}",
722 "LIBPLDM_ERROR", rc);
723 throw std::runtime_error(
724 "Failed to decode BIOS table possible values for attribute entry");
725 }
726
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600727 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930728 // Preconditions are upheld therefore no error check necessary
729 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
730 attrEntry, pvHandls.data(), pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600731
732 std::string displayString = std::to_string(pvHandls[index]);
733
734 auto stringEntry = pldm_bios_table_string_find_by_handle(
735 stringTable->data(), stringTable->size(), pvHandls[index]);
736
737 auto decodedStr = decodeStringFromStringEntry(stringEntry);
738
739 return decodedStr + "(" + displayString + ")";
740}
741
742void BIOSConfig::traceBIOSUpdate(
743 const pldm_bios_attr_val_table_entry* attrValueEntry,
744 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
745{
746 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
747 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
748
Patrick Williams6da4f912023-05-10 07:50:53 -0500749 auto [attrHandle,
750 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600751
752 auto attrHeader = table::attribute::decodeHeader(attrEntry);
753 BIOSStringTable biosStringTable(*stringTable);
754 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
755
756 switch (attrType)
757 {
758 case PLDM_BIOS_ENUMERATION:
759 case PLDM_BIOS_ENUMERATION_READ_ONLY:
760 {
761 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
762 attrValueEntry);
763 std::vector<uint8_t> handles(count);
764 pldm_bios_table_attr_value_entry_enum_decode_handles(
765 attrValueEntry, handles.data(), handles.size());
766
767 for (uint8_t handle : handles)
768 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600769 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
770 stringTable);
771 auto chkBMC = isBMC ? "true" : "false";
772 info(
773 "BIOS:{ATTR_NAME}, updated to value: {NEW_VAL}, by BMC: {CHK_BMC} ",
774 "ATTR_NAME", attrName, "NEW_VAL", nwVal, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600775 }
776 break;
777 }
778 case PLDM_BIOS_INTEGER:
779 case PLDM_BIOS_INTEGER_READ_ONLY:
780 {
781 auto value =
782 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600783 auto chkBMC = isBMC ? "true" : "false";
784 info(
785 "BIOS: {ATTR_NAME}, updated to value: {UPDATED_VAL}, by BMC: {CHK_BMC}",
786 "ATTR_NAME", attrName, "UPDATED_VAL", value, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600787 break;
788 }
789 case PLDM_BIOS_STRING:
790 case PLDM_BIOS_STRING_READ_ONLY:
791 {
792 auto value =
793 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600794 auto chkBMC = isBMC ? "true" : "false";
795 info(
796 "BIOS: {ATTR_NAME}, updated to value: {UPDATED_VAL}, by BMC: {CHK_BMC}",
797 "ATTR_NAME", attrName, "UPDATED_VAL", value, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600798 break;
799 }
800 default:
801 break;
802 };
803}
804
John Wang8241b342020-06-05 10:49:17 +0800805int BIOSConfig::checkAttrValueToUpdate(
806 const pldm_bios_attr_val_table_entry* attrValueEntry,
807 const pldm_bios_attr_table_entry* attrEntry, Table&)
808
809{
Patrick Williams6da4f912023-05-10 07:50:53 -0500810 auto [attrHandle,
811 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800812
813 switch (attrType)
814 {
815 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800816 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800817 {
818 auto value =
819 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500820 auto [pvHdls,
821 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600822 if (!(value.size() == 1))
823 {
824 return PLDM_ERROR_INVALID_LENGTH;
825 }
John Wang8241b342020-06-05 10:49:17 +0800826 if (value[0] >= pvHdls.size())
827 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600828 error("Enum: Illgeal index, Index = {ATTR_INDEX}", "ATTR_INDEX",
829 (int)value[0]);
John Wang8241b342020-06-05 10:49:17 +0800830 return PLDM_ERROR_INVALID_DATA;
831 }
John Wang8241b342020-06-05 10:49:17 +0800832 return PLDM_SUCCESS;
833 }
834 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800835 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800836 {
837 auto value =
838 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500839 auto [lower, upper, scalar,
840 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800841
842 if (value < lower || value > upper)
843 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600844 error("Integer: out of bound, value = {ATTR_VALUE}",
845 "ATTR_VALUE", value);
John Wang8241b342020-06-05 10:49:17 +0800846 return PLDM_ERROR_INVALID_DATA;
847 }
848 return PLDM_SUCCESS;
849 }
850 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800851 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800852 {
853 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
854 auto value =
855 table::attribute_value::decodeStringEntry(attrValueEntry);
856 if (value.size() < stringConf.minLength ||
857 value.size() > stringConf.maxLength)
858 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600859 error(
860 "String: Length error, string = {ATTR_VALUE} length {LEN}",
861 "ATTR_VALUE", value, "LEN", value.size());
John Wang8241b342020-06-05 10:49:17 +0800862 return PLDM_ERROR_INVALID_LENGTH;
863 }
864 return PLDM_SUCCESS;
865 }
866 default:
Riya Dixit49cfb132023-03-02 04:26:53 -0600867 error("ReadOnly or Unspported type, type = {ATTR_TYPE}",
868 "ATTR_TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800869 return PLDM_ERROR;
870 };
871}
872
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600873int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
874 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800875{
876 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
877 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
878 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
879 if (!attrValueTable || !attrTable || !stringTable)
880 {
881 return PLDM_BIOS_TABLE_UNAVAILABLE;
882 }
883
John Wangd9659342020-02-27 16:46:05 +0800884 auto attrValueEntry =
885 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
886
887 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
888
Patrick Williams6da4f912023-05-10 07:50:53 -0500889 auto attrEntry = table::attribute::findByHandle(*attrTable,
890 attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800891 if (!attrEntry)
892 {
893 return PLDM_ERROR;
894 }
895
John Wang8241b342020-06-05 10:49:17 +0800896 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
897 if (rc != PLDM_SUCCESS)
898 {
899 return rc;
900 }
901
Patrick Williams6da4f912023-05-10 07:50:53 -0500902 auto destTable = table::attribute_value::updateTable(*attrValueTable, entry,
903 size);
John Wang8241b342020-06-05 10:49:17 +0800904
905 if (!destTable)
906 {
907 return PLDM_ERROR;
908 }
909
John Wangd9659342020-02-27 16:46:05 +0800910 try
911 {
912 auto attrHeader = table::attribute::decodeHeader(attrEntry);
913
914 BIOSStringTable biosStringTable(*stringTable);
915 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500916 auto iter = std::find_if(
917 biosAttributes.begin(), biosAttributes.end(),
918 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800919
920 if (iter == biosAttributes.end())
921 {
922 return PLDM_ERROR;
923 }
George Liu6d6d1e82021-02-16 11:08:55 +0800924 if (updateDBus)
925 {
926 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
927 biosStringTable);
928 }
John Wangd9659342020-02-27 16:46:05 +0800929 }
930 catch (const std::exception& e)
931 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600932 error("Set attribute value error: {ERR_EXCEP}", "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800933 return PLDM_ERROR;
934 }
935
Tom Joseph7f839f92020-09-21 10:20:44 +0530936 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800937
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600938 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
939
John Wangd9659342020-02-27 16:46:05 +0800940 return PLDM_SUCCESS;
941}
942
943void BIOSConfig::removeTables()
944{
945 try
946 {
947 fs::remove(tableDir / stringTableFile);
948 fs::remove(tableDir / attrTableFile);
949 fs::remove(tableDir / attrValueTableFile);
950 }
951 catch (const std::exception& e)
952 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600953 error("Remove the tables error: {ERR_EXCEP}", "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800954 }
955}
956
Sampa Misra46ece062020-03-18 07:17:44 -0500957void BIOSConfig::processBiosAttrChangeNotification(
958 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
959{
960 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
961 const auto& propertyName = dBusMap->propertyName;
962 const auto& attrName = biosAttributes[biosAttrIndex]->name;
963
964 const auto it = chProperties.find(propertyName);
965 if (it == chProperties.end())
966 {
967 return;
968 }
969
970 PropertyValue newPropVal = it->second;
971 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
972 if (!stringTable.has_value())
973 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600974 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500975 return;
976 }
977 BIOSStringTable biosStringTable(*stringTable);
978 uint16_t attrNameHdl{};
979 try
980 {
981 attrNameHdl = biosStringTable.findHandle(attrName);
982 }
Patrick Williams51330582021-10-06 12:48:56 -0500983 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -0500984 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500985 error("Missing handle for '{ATTR}': {ERROR}", "ATTR", attrName, "ERROR",
986 e);
Sampa Misra46ece062020-03-18 07:17:44 -0500987 return;
988 }
989
990 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
991 if (!attrTable.has_value())
992 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600993 error("Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -0500994 return;
995 }
996 const struct pldm_bios_attr_table_entry* tableEntry =
997 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
998 if (tableEntry == nullptr)
999 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001000 error(
1001 "Attribute not found in attribute table, name= {ATTR_NAME} name handle={ATTR_HANDLE}",
1002 "ATTR_NAME", attrName.c_str(), "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -05001003 return;
1004 }
1005
Patrick Williams6da4f912023-05-10 07:50:53 -05001006 auto [attrHdl, attrType,
1007 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -05001008
1009 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
1010
1011 if (!attrValueSrcTable.has_value())
1012 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001013 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001014 return;
1015 }
1016
1017 Table newValue;
1018 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
1019 newValue, attrHdl, attrType, newPropVal);
1020 if (rc != PLDM_SUCCESS)
1021 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001022 error(
1023 "Could not update the attribute value table for attribute handle={ATTR_HANDLE} and type={ATTR_TYPE}",
1024 "ATTR_HANDLE", attrHdl, "ATTR_TYPE", (uint32_t)attrType);
Sampa Misra46ece062020-03-18 07:17:44 -05001025 return;
1026 }
1027 auto destTable = table::attribute_value::updateTable(
1028 *attrValueSrcTable, newValue.data(), newValue.size());
1029 if (destTable.has_value())
1030 {
1031 storeTable(tableDir / attrValueTableFile, *destTable);
1032 }
Sampa Misra0f262332021-02-15 00:13:51 -06001033
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001034 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001035 if (rc != PLDM_SUCCESS)
1036 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001037 error("could not setAttrValue on base bios table and dbus, rc = {RC}",
1038 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001039 }
Sampa Misra46ece062020-03-18 07:17:44 -05001040}
1041
George Liu1244acf2020-08-14 09:11:11 +08001042uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1043{
1044 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1045 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1046
1047 BIOSStringTable biosStringTable(*stringTable);
1048 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1049 attrTable->data(), attrTable->size());
1050 auto stringHandle = biosStringTable.findHandle(attrName);
1051
1052 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1053 attrTable->data(), attrTable->size()))
1054 {
1055 auto header = table::attribute::decodeHeader(entry);
1056 if (header.stringHandle == stringHandle)
1057 {
1058 return header.attrHandle;
1059 }
1060 }
1061
1062 throw std::invalid_argument("Unknow attribute Name");
1063}
1064
1065void BIOSConfig::constructPendingAttribute(
1066 const PendingAttributes& pendingAttributes)
1067{
Tom Joseph7f839f92020-09-21 10:20:44 +05301068 std::vector<uint16_t> listOfHandles{};
1069
George Liu1244acf2020-08-14 09:11:11 +08001070 for (auto& attribute : pendingAttributes)
1071 {
1072 std::string attributeName = attribute.first;
1073 auto& [attributeType, attributevalue] = attribute.second;
1074
1075 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1076 [&attributeName](const auto& attr) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001077 return attr->name == attributeName;
1078 });
George Liu1244acf2020-08-14 09:11:11 +08001079
1080 if (iter == biosAttributes.end())
1081 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001082 error("Wrong attribute name, attributeName = {ATTR_NAME}",
1083 "ATTR_NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001084 continue;
1085 }
1086
1087 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
1088 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
1089 attrValueEntry.data());
1090
1091 auto handler = findAttrHandle(attributeName);
1092 auto type =
1093 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1094
1095 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1096 type != BIOSConfigManager::AttributeType::String &&
1097 type != BIOSConfigManager::AttributeType::Integer)
1098 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001099 error("Attribute type not supported, attributeType = {ATTR_TYPE}",
1100 "ATTR_TYPE", attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001101 continue;
1102 }
1103
George Liu4876c542022-06-08 15:59:54 +08001104 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001105 menuPath, currentValue, defaultValue,
1106 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001107
George Liu1244acf2020-08-14 09:11:11 +08001108 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001109
1110 // Need to verify that the current value has really changed
1111 if (attributeType == attrType && attributevalue != currentValue)
1112 {
1113 listOfHandles.emplace_back(htole16(handler));
1114 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301115
George Liu1244acf2020-08-14 09:11:11 +08001116 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1117
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001118 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301119 }
1120
1121 if (listOfHandles.size())
1122 {
1123#ifdef OEM_IBM
1124 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301125 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301126 if (rc != PLDM_SUCCESS)
1127 {
1128 return;
1129 }
1130#endif
George Liu1244acf2020-08-14 09:11:11 +08001131 }
1132}
1133
1134void BIOSConfig::listenPendingAttributes()
1135{
1136 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1137 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1138
1139 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001140 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001141 pldm::utils::DBusHandler::getBus(),
1142 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001143 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001144 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001145
Patrick Williams6da4f912023-05-10 07:50:53 -05001146 using Value =
1147 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1148 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001149
Patrick Williams6da4f912023-05-10 07:50:53 -05001150 Properties props{};
1151 std::string intf;
1152 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001153
Patrick Williams6da4f912023-05-10 07:50:53 -05001154 auto valPropMap = props.find(propertyName);
1155 if (valPropMap == props.end())
1156 {
1157 return;
1158 }
George Liu1244acf2020-08-14 09:11:11 +08001159
Patrick Williams6da4f912023-05-10 07:50:53 -05001160 PendingAttributes pendingAttributes =
1161 std::get<PendingAttributes>(valPropMap->second);
1162 this->constructPendingAttribute(pendingAttributes);
Patrick Williamsa6756622023-10-20 11:19:15 -05001163 });
George Liu1244acf2020-08-14 09:11:11 +08001164
1165 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1166}
1167
John Wangd9659342020-02-27 16:46:05 +08001168} // namespace bios
1169} // namespace responder
1170} // namespace pldm