blob: 82b3dfeedd568a5a313a4518d5147ccfa82b8dba [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);
Archana Kakani62dd8ff2024-02-12 10:00:40 -060095 return;
96 }
John Wangd9659342020-02-27 16:46:05 +080097 constructAttributes();
Archana Kakani62dd8ff2024-02-12 10:00:40 -060098 buildTables();
Archana Kakani46f352e2024-03-17 08:21:08 -050099 if (registerService)
100 {
101 requestPLDMServiceName();
102 }
John Wangd9659342020-02-27 16:46:05 +0800103}
104
105void BIOSConfig::buildTables()
106{
John Wangd9659342020-02-27 16:46:05 +0800107 auto stringTable = buildAndStoreStringTable();
108 if (stringTable)
109 {
110 buildAndStoreAttrTables(*stringTable);
111 }
112}
113
114std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
115{
116 fs::path tablePath;
117 switch (tableType)
118 {
119 case PLDM_BIOS_STRING_TABLE:
120 tablePath = tableDir / stringTableFile;
121 break;
122 case PLDM_BIOS_ATTR_TABLE:
123 tablePath = tableDir / attrTableFile;
124 break;
125 case PLDM_BIOS_ATTR_VAL_TABLE:
126 tablePath = tableDir / attrValueTableFile;
127 break;
128 }
129 return loadTable(tablePath);
130}
131
Tom Joseph7f839f92020-09-21 10:20:44 +0530132int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table,
133 bool updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800134{
135 fs::path stringTablePath(tableDir / stringTableFile);
136 fs::path attrTablePath(tableDir / attrTableFile);
137 fs::path attrValueTablePath(tableDir / attrValueTableFile);
138
139 if (!pldm_bios_table_checksum(table.data(), table.size()))
140 {
141 return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
142 }
143
144 if (tableType == PLDM_BIOS_STRING_TABLE)
145 {
146 storeTable(stringTablePath, table);
147 }
148 else if (tableType == PLDM_BIOS_ATTR_TABLE)
149 {
150 BIOSTable biosStringTable(stringTablePath.c_str());
151 if (biosStringTable.isEmpty())
152 {
153 return PLDM_INVALID_BIOS_TABLE_TYPE;
154 }
155
156 auto rc = checkAttributeTable(table);
157 if (rc != PLDM_SUCCESS)
158 {
159 return rc;
160 }
161
162 storeTable(attrTablePath, table);
163 }
164 else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
165 {
166 BIOSTable biosStringTable(stringTablePath.c_str());
167 BIOSTable biosStringValueTable(attrTablePath.c_str());
168 if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
169 {
170 return PLDM_INVALID_BIOS_TABLE_TYPE;
171 }
172
173 auto rc = checkAttributeValueTable(table);
174 if (rc != PLDM_SUCCESS)
175 {
176 return rc;
177 }
178
179 storeTable(attrValueTablePath, table);
George Liu1b180d82020-07-23 14:01:58 +0800180 }
181 else
182 {
183 return PLDM_INVALID_BIOS_TABLE_TYPE;
184 }
185
Tom Joseph7f839f92020-09-21 10:20:44 +0530186 if ((tableType == PLDM_BIOS_ATTR_VAL_TABLE) && updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800187 {
George Liu1b180d82020-07-23 14:01:58 +0800188 updateBaseBIOSTableProperty();
189 }
190
191 return PLDM_SUCCESS;
192}
193
194int BIOSConfig::checkAttributeTable(const Table& table)
195{
196 using namespace pldm::bios::utils;
197 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
198 for (auto entry :
199 BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
200 {
201 auto attrNameHandle =
202 pldm_bios_table_attr_entry_decode_string_handle(entry);
203
204 auto stringEnty = pldm_bios_table_string_find_by_handle(
205 stringTable->data(), stringTable->size(), attrNameHandle);
206 if (stringEnty == nullptr)
207 {
208 return PLDM_INVALID_BIOS_ATTR_HANDLE;
209 }
210
211 auto attrType = static_cast<pldm_bios_attribute_type>(
212 pldm_bios_table_attr_entry_decode_attribute_type(entry));
213
214 switch (attrType)
215 {
216 case PLDM_BIOS_ENUMERATION:
217 case PLDM_BIOS_ENUMERATION_READ_ONLY:
218 {
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930219 uint8_t pvNum;
220 // Preconditions are upheld therefore no error check necessary
221 pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry,
222 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800223 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930224 // Preconditions are upheld therefore no error check necessary
225 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800226 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930227 uint8_t defNum;
228 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry,
229 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800230 std::vector<uint8_t> defIndices(defNum);
231 pldm_bios_table_attr_entry_enum_decode_def_indices(
232 entry, defIndices.data(), defIndices.size());
233
234 for (size_t i = 0; i < pvHandls.size(); i++)
235 {
236 auto stringEntry = pldm_bios_table_string_find_by_handle(
237 stringTable->data(), stringTable->size(), pvHandls[i]);
238 if (stringEntry == nullptr)
239 {
240 return PLDM_INVALID_BIOS_ATTR_HANDLE;
241 }
242 }
243
244 for (size_t i = 0; i < defIndices.size(); i++)
245 {
246 auto stringEntry = pldm_bios_table_string_find_by_handle(
247 stringTable->data(), stringTable->size(),
248 pvHandls[defIndices[i]]);
249 if (stringEntry == nullptr)
250 {
251 return PLDM_INVALID_BIOS_ATTR_HANDLE;
252 }
253 }
254 break;
255 }
256 case PLDM_BIOS_INTEGER:
257 case PLDM_BIOS_INTEGER_READ_ONLY:
258 case PLDM_BIOS_STRING:
259 case PLDM_BIOS_STRING_READ_ONLY:
260 case PLDM_BIOS_PASSWORD:
261 case PLDM_BIOS_PASSWORD_READ_ONLY:
262 break;
263 default:
264 return PLDM_INVALID_BIOS_ATTR_HANDLE;
265 }
266 }
267
268 return PLDM_SUCCESS;
269}
270
271int BIOSConfig::checkAttributeValueTable(const Table& table)
272{
273 using namespace pldm::bios::utils;
274 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
275 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
276
277 baseBIOSTableMaps.clear();
278
279 for (auto tableEntry :
280 BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
281 {
282 AttributeName attributeName{};
283 AttributeType attributeType{};
284 ReadonlyStatus readonlyStatus{};
285 DisplayName displayName{};
286 Description description{};
287 MenuPath menuPath{};
288 CurrentValue currentValue{};
289 DefaultValue defaultValue{};
Sagar Srinivas7927f902023-10-09 07:53:00 -0500290 std::vector<ValueDisplayName> valueDisplayNames;
291 std::map<uint16_t, std::vector<std::string>> valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800292 Option options{};
293
294 auto attrValueHandle =
295 pldm_bios_table_attr_value_entry_decode_attribute_handle(
296 tableEntry);
297 auto attrType = static_cast<pldm_bios_attribute_type>(
298 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
299
300 auto attrEntry = pldm_bios_table_attr_find_by_handle(
301 attrTable->data(), attrTable->size(), attrValueHandle);
302 if (attrEntry == nullptr)
303 {
304 return PLDM_INVALID_BIOS_ATTR_HANDLE;
305 }
306 auto attrHandle =
307 pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
308 auto attrNameHandle =
309 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
310
311 auto stringEntry = pldm_bios_table_string_find_by_handle(
312 stringTable->data(), stringTable->size(), attrNameHandle);
313 if (stringEntry == nullptr)
314 {
315 return PLDM_INVALID_BIOS_ATTR_HANDLE;
316 }
317 auto strLength =
318 pldm_bios_table_string_entry_decode_string_length(stringEntry);
319 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930320 // Preconditions are upheld therefore no error check necessary
321 pldm_bios_table_string_entry_decode_string_check(
322 stringEntry, buffer.data(), buffer.size());
323
George Liu1b180d82020-07-23 14:01:58 +0800324 attributeName = std::string(buffer.data(), buffer.data() + strLength);
325
326 if (!biosAttributes.empty())
327 {
328 readonlyStatus =
George Liub1fbeec2020-09-04 09:59:46 +0800329 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800330 description =
331 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
332 displayName =
333 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
Sagar Srinivas7927f902023-10-09 07:53:00 -0500334 valueDisplayNamesMap =
335 biosAttributes[attrHandle % biosAttributes.size()]
336 ->valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800337 }
338
339 switch (attrType)
340 {
341 case PLDM_BIOS_ENUMERATION:
342 case PLDM_BIOS_ENUMERATION_READ_ONLY:
343 {
Sagar Srinivas7927f902023-10-09 07:53:00 -0500344 if (valueDisplayNamesMap.contains(attrHandle))
345 {
346 const std::vector<ValueDisplayName>& vdn =
347 valueDisplayNamesMap[attrHandle];
348 valueDisplayNames.insert(valueDisplayNames.end(),
349 vdn.begin(), vdn.end());
350 }
George Liu1b180d82020-07-23 14:01:58 +0800351 auto getValue = [](uint16_t handle,
352 const Table& table) -> std::string {
353 auto stringEntry = pldm_bios_table_string_find_by_handle(
354 table.data(), table.size(), handle);
355
356 auto strLength =
357 pldm_bios_table_string_entry_decode_string_length(
358 stringEntry);
359 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930360 // Preconditions are upheld therefore no error check
361 // necessary
362 pldm_bios_table_string_entry_decode_string_check(
George Liu1b180d82020-07-23 14:01:58 +0800363 stringEntry, buffer.data(), buffer.size());
364
365 return std::string(buffer.data(),
366 buffer.data() + strLength);
367 };
368
369 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
370 "AttributeType.Enumeration";
371
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930372 uint8_t pvNum;
373 // Preconditions are upheld therefore no error check necessary
374 pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
375 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800376 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930377 // Preconditions are upheld therefore no error check necessary
378 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800379 attrEntry, pvHandls.data(), pvHandls.size());
380
381 // get possible_value
382 for (size_t i = 0; i < pvHandls.size(); i++)
383 {
384 options.push_back(
385 std::make_tuple("xyz.openbmc_project.BIOSConfig."
386 "Manager.BoundType.OneOf",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500387 getValue(pvHandls[i], *stringTable),
388 valueDisplayNames[i]));
George Liu1b180d82020-07-23 14:01:58 +0800389 }
390
391 auto count =
392 pldm_bios_table_attr_value_entry_enum_decode_number(
393 tableEntry);
394 std::vector<uint8_t> handles(count);
395 pldm_bios_table_attr_value_entry_enum_decode_handles(
396 tableEntry, handles.data(), handles.size());
397
398 // get current_value
399 for (size_t i = 0; i < handles.size(); i++)
400 {
401 currentValue = getValue(pvHandls[handles[i]], *stringTable);
402 }
403
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930404 uint8_t defNum;
405 // Preconditions are upheld therefore no error check necessary
406 pldm_bios_table_attr_entry_enum_decode_def_num_check(attrEntry,
407 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800408 std::vector<uint8_t> defIndices(defNum);
409 pldm_bios_table_attr_entry_enum_decode_def_indices(
410 attrEntry, defIndices.data(), defIndices.size());
411
412 // get default_value
413 for (size_t i = 0; i < defIndices.size(); i++)
414 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500415 defaultValue = getValue(pvHandls[defIndices[i]],
416 *stringTable);
George Liu1b180d82020-07-23 14:01:58 +0800417 }
418
419 break;
420 }
421 case PLDM_BIOS_INTEGER:
422 case PLDM_BIOS_INTEGER_READ_ONLY:
423 {
424 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
425 "AttributeType.Integer";
426 currentValue = static_cast<int64_t>(
427 pldm_bios_table_attr_value_entry_integer_decode_cv(
428 tableEntry));
429
430 uint64_t lower, upper, def;
431 uint32_t scalar;
432 pldm_bios_table_attr_entry_integer_decode(
433 attrEntry, &lower, &upper, &scalar, &def);
Sagar Srinivas7927f902023-10-09 07:53:00 -0500434 options.push_back(std::make_tuple(
435 "xyz.openbmc_project.BIOSConfig.Manager."
436 "BoundType.LowerBound",
437 static_cast<int64_t>(lower), attributeName));
438 options.push_back(std::make_tuple(
439 "xyz.openbmc_project.BIOSConfig.Manager."
440 "BoundType.UpperBound",
441 static_cast<int64_t>(upper), attributeName));
442 options.push_back(std::make_tuple(
443 "xyz.openbmc_project.BIOSConfig.Manager."
444 "BoundType.ScalarIncrement",
445 static_cast<int64_t>(scalar), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800446 defaultValue = static_cast<int64_t>(def);
447 break;
448 }
449 case PLDM_BIOS_STRING:
450 case PLDM_BIOS_STRING_READ_ONLY:
451 {
452 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
453 "AttributeType.String";
454 variable_field currentString;
455 pldm_bios_table_attr_value_entry_string_decode_string(
456 tableEntry, &currentString);
457 currentValue = std::string(
458 reinterpret_cast<const char*>(currentString.ptr),
459 currentString.length);
460 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
461 attrEntry);
462 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
463 attrEntry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930464 uint16_t def;
465 // Preconditions are upheld therefore no error check necessary
466 pldm_bios_table_attr_entry_string_decode_def_string_length_check(
467 attrEntry, &def);
George Liu1b180d82020-07-23 14:01:58 +0800468 std::vector<char> defString(def + 1);
469 pldm_bios_table_attr_entry_string_decode_def_string(
470 attrEntry, defString.data(), defString.size());
471 options.push_back(
472 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
473 "BoundType.MinStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500474 static_cast<int64_t>(min), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800475 options.push_back(
476 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
477 "BoundType.MaxStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500478 static_cast<int64_t>(max), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800479 defaultValue = defString.data();
480 break;
481 }
482 case PLDM_BIOS_PASSWORD:
483 case PLDM_BIOS_PASSWORD_READ_ONLY:
484 {
485 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
486 "AttributeType.Password";
487 break;
488 }
489 default:
490 return PLDM_INVALID_BIOS_ATTR_HANDLE;
491 }
492 baseBIOSTableMaps.emplace(
493 std::move(attributeName),
494 std::make_tuple(attributeType, readonlyStatus, displayName,
495 description, menuPath, currentValue, defaultValue,
496 std::move(options)));
497 }
498
499 return PLDM_SUCCESS;
500}
501
502void BIOSConfig::updateBaseBIOSTableProperty()
503{
504 constexpr static auto biosConfigPath =
505 "/xyz/openbmc_project/bios_config/manager";
506 constexpr static auto biosConfigInterface =
507 "xyz.openbmc_project.BIOSConfig.Manager";
508 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
509 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
510
511 if (baseBIOSTableMaps.empty())
512 {
513 return;
514 }
515
516 try
517 {
518 auto& bus = dbusHandler->getBus();
Patrick Williams6da4f912023-05-10 07:50:53 -0500519 auto service = dbusHandler->getService(biosConfigPath,
520 biosConfigInterface);
George Liu1b180d82020-07-23 14:01:58 +0800521 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
522 dbusProperties, "Set");
523 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
524 method.append(biosConfigInterface, biosConfigPropertyName, value);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000525 bus.call_noreply(method, dbusTimeout);
George Liu1b180d82020-07-23 14:01:58 +0800526 }
527 catch (const std::exception& e)
528 {
Riya Dixit89644442024-03-31 05:39:59 -0500529 error("Failed to update BaseBIOSTable property, error - {ERROR}",
530 "ERROR", e);
George Liu1b180d82020-07-23 14:01:58 +0800531 }
532}
533
John Wangd9659342020-02-27 16:46:05 +0800534void BIOSConfig::constructAttributes()
535{
Archana Kakaniac713ee2024-05-20 01:27:53 -0500536 info("Bios Attribute file path: {PATH}", "PATH",
537 (jsonDir / sysType / attributesJsonFile));
538 load(jsonDir / sysType / attributesJsonFile, [this](const Json& entry) {
539 std::string attrType = entry.at("attribute_type");
540 if (attrType == "string")
541 {
542 constructAttribute<BIOSStringAttribute>(entry);
543 }
544 else if (attrType == "integer")
545 {
546 constructAttribute<BIOSIntegerAttribute>(entry);
547 }
548 else if (attrType == "enum")
549 {
550 constructAttribute<BIOSEnumAttribute>(entry);
551 }
John Wang3be70852020-02-13 15:59:04 +0800552 });
John Wangd9659342020-02-27 16:46:05 +0800553}
554
555void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
556{
557 BIOSStringTable biosStringTable(stringTable);
558
559 if (biosAttributes.empty())
560 {
561 return;
562 }
563
Tom Josephca7b2522020-11-18 12:27:11 +0530564 BaseBIOSTable biosTable{};
565 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
566 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
567
568 try
569 {
570 auto& bus = dbusHandler->getBus();
571 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams6da4f912023-05-10 07:50:53 -0500572 auto method = bus.new_method_call(service.c_str(), biosObjPath,
573 "org.freedesktop.DBus.Properties",
574 "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530575 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500576 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530577 std::variant<BaseBIOSTable> varBiosTable{};
578 reply.read(varBiosTable);
579 biosTable = std::get<BaseBIOSTable>(varBiosTable);
580 }
581 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
582 // default values populated from the BIOS JSONs to keep PLDM and
583 // bios-settings-manager in sync
584 catch (const std::exception& e)
585 {
Riya Dixit89644442024-03-31 05:39:59 -0500586 error("Failed to read BaseBIOSTable property, error - {ERROR}", "ERROR",
587 e);
Tom Josephca7b2522020-11-18 12:27:11 +0530588 }
589
John Wangd9659342020-02-27 16:46:05 +0800590 Table attrTable, attrValueTable;
591
592 for (auto& attr : biosAttributes)
593 {
594 try
595 {
Tom Josephca7b2522020-11-18 12:27:11 +0530596 auto iter = biosTable.find(attr->name);
597 if (iter == biosTable.end())
598 {
599 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
600 std::nullopt);
601 }
602 else
603 {
604 attr->constructEntry(
605 biosStringTable, attrTable, attrValueTable,
606 std::get<static_cast<uint8_t>(Index::currentValue)>(
607 iter->second));
608 }
John Wangd9659342020-02-27 16:46:05 +0800609 }
610 catch (const std::exception& e)
611 {
Riya Dixit89644442024-03-31 05:39:59 -0500612 error(
613 "Failed to construct table entry for attribute '{ATTRIBUTE}', error - {ERROR}",
614 "ATTRIBUTE", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800615 }
616 }
617
618 table::appendPadAndChecksum(attrTable);
619 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800620 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
621 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800622}
623
624std::optional<Table> BIOSConfig::buildAndStoreStringTable()
625{
626 std::set<std::string> strings;
Archana Kakaniac713ee2024-05-20 01:27:53 -0500627 load(jsonDir / sysType / attributesJsonFile, [&strings](const Json& entry) {
628 if (entry.at("attribute_type") == "enum")
John Wangd9659342020-02-27 16:46:05 +0800629 {
Archana Kakaniac713ee2024-05-20 01:27:53 -0500630 strings.emplace(entry.at("attribute_name"));
631 auto possibleValues = entry.at("possible_values");
632 for (auto& pv : possibleValues)
633 {
634 strings.emplace(pv);
635 }
636 }
637 else
638 {
639 strings.emplace(entry.at("attribute_name"));
John Wangd9659342020-02-27 16:46:05 +0800640 }
641 });
642
643 if (strings.empty())
644 {
645 return std::nullopt;
646 }
647
648 Table table;
649 for (const auto& elem : strings)
650 {
651 table::string::constructEntry(table, elem);
652 }
653
654 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800655 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800656 return table;
657}
658
659void BIOSConfig::storeTable(const fs::path& path, const Table& table)
660{
661 BIOSTable biosTable(path.c_str());
662 biosTable.store(table);
663}
664
665std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
666{
667 BIOSTable biosTable(path.c_str());
668 if (biosTable.isEmpty())
669 {
670 return std::nullopt;
671 }
672
673 Table table;
674 biosTable.load(table);
675 return table;
676}
677
678void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
679{
680 std::ifstream file;
681 Json jsonConf;
682 if (fs::exists(filePath))
683 {
684 try
685 {
686 file.open(filePath);
687 jsonConf = Json::parse(file);
688 auto entries = jsonConf.at("entries");
689 for (auto& entry : entries)
690 {
691 try
692 {
693 handler(entry);
694 }
695 catch (const std::exception& e)
696 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600697 error(
Riya Dixit89644442024-03-31 05:39:59 -0500698 "Failed to parse JSON config file at path '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500699 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800700 }
701 }
702 }
703 catch (const std::exception& e)
704 {
Riya Dixit89644442024-03-31 05:39:59 -0500705 error("Failed to parse JSON config file '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500706 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800707 }
708 }
709}
710
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600711std::string BIOSConfig::decodeStringFromStringEntry(
712 const pldm_bios_string_table_entry* stringEntry)
713{
714 auto strLength =
715 pldm_bios_table_string_entry_decode_string_length(stringEntry);
716 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930717 // Preconditions are upheld therefore no error check necessary
718 pldm_bios_table_string_entry_decode_string_check(stringEntry, buffer.data(),
719 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600720 return std::string(buffer.data(), buffer.data() + strLength);
721}
722
723std::string
724 BIOSConfig::displayStringHandle(uint16_t handle, uint8_t index,
725 const std::optional<Table>& attrTable,
726 const std::optional<Table>& stringTable)
727{
728 auto attrEntry = pldm_bios_table_attr_find_by_handle(
729 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930730 uint8_t pvNum;
731 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
732 &pvNum);
733 if (rc != PLDM_SUCCESS)
734 {
735 error(
Riya Dixit89644442024-03-31 05:39:59 -0500736 "Failed to decode BIOS table possible values for attribute entry, response code '{RC}'",
737 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930738 throw std::runtime_error(
739 "Failed to decode BIOS table possible values for attribute entry");
740 }
741
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600742 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930743 // Preconditions are upheld therefore no error check necessary
744 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
745 attrEntry, pvHandls.data(), pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600746
747 std::string displayString = std::to_string(pvHandls[index]);
748
749 auto stringEntry = pldm_bios_table_string_find_by_handle(
750 stringTable->data(), stringTable->size(), pvHandls[index]);
751
752 auto decodedStr = decodeStringFromStringEntry(stringEntry);
753
754 return decodedStr + "(" + displayString + ")";
755}
756
757void BIOSConfig::traceBIOSUpdate(
758 const pldm_bios_attr_val_table_entry* attrValueEntry,
759 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
760{
761 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
762 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
763
Patrick Williams6da4f912023-05-10 07:50:53 -0500764 auto [attrHandle,
765 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600766
767 auto attrHeader = table::attribute::decodeHeader(attrEntry);
768 BIOSStringTable biosStringTable(*stringTable);
769 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
770
771 switch (attrType)
772 {
773 case PLDM_BIOS_ENUMERATION:
774 case PLDM_BIOS_ENUMERATION_READ_ONLY:
775 {
776 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
777 attrValueEntry);
778 std::vector<uint8_t> handles(count);
779 pldm_bios_table_attr_value_entry_enum_decode_handles(
780 attrValueEntry, handles.data(), handles.size());
781
782 for (uint8_t handle : handles)
783 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600784 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
785 stringTable);
786 auto chkBMC = isBMC ? "true" : "false";
787 info(
Riya Dixit89644442024-03-31 05:39:59 -0500788 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
789 "ATTRIBUTE", attrName, "VALUE", nwVal, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600790 }
791 break;
792 }
793 case PLDM_BIOS_INTEGER:
794 case PLDM_BIOS_INTEGER_READ_ONLY:
795 {
796 auto value =
797 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600798 auto chkBMC = isBMC ? "true" : "false";
799 info(
Riya Dixit89644442024-03-31 05:39:59 -0500800 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
801 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600802 break;
803 }
804 case PLDM_BIOS_STRING:
805 case PLDM_BIOS_STRING_READ_ONLY:
806 {
807 auto value =
808 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600809 auto chkBMC = isBMC ? "true" : "false";
810 info(
Riya Dixit89644442024-03-31 05:39:59 -0500811 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
812 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600813 break;
814 }
815 default:
816 break;
817 };
818}
819
John Wang8241b342020-06-05 10:49:17 +0800820int BIOSConfig::checkAttrValueToUpdate(
821 const pldm_bios_attr_val_table_entry* attrValueEntry,
822 const pldm_bios_attr_table_entry* attrEntry, Table&)
823
824{
Patrick Williams6da4f912023-05-10 07:50:53 -0500825 auto [attrHandle,
826 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800827
828 switch (attrType)
829 {
830 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800831 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800832 {
833 auto value =
834 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500835 auto [pvHdls,
836 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600837 if (!(value.size() == 1))
838 {
839 return PLDM_ERROR_INVALID_LENGTH;
840 }
John Wang8241b342020-06-05 10:49:17 +0800841 if (value[0] >= pvHdls.size())
842 {
Riya Dixit89644442024-03-31 05:39:59 -0500843 error(
844 "Invalid index '{INDEX}' encountered for Enum type BIOS attribute",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500845 "INDEX", value[0]);
John Wang8241b342020-06-05 10:49:17 +0800846 return PLDM_ERROR_INVALID_DATA;
847 }
John Wang8241b342020-06-05 10:49:17 +0800848 return PLDM_SUCCESS;
849 }
850 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800851 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800852 {
853 auto value =
854 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500855 auto [lower, upper, scalar,
856 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800857
858 if (value < lower || value > upper)
859 {
Riya Dixit89644442024-03-31 05:39:59 -0500860 error(
861 "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}'.",
862 "ATTRIBUTE_VALUE", value, "LOWER", lower, "UPPER", upper,
863 "SCALAR", scalar);
John Wang8241b342020-06-05 10:49:17 +0800864 return PLDM_ERROR_INVALID_DATA;
865 }
866 return PLDM_SUCCESS;
867 }
868 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800869 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800870 {
871 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
872 auto value =
873 table::attribute_value::decodeStringEntry(attrValueEntry);
874 if (value.size() < stringConf.minLength ||
875 value.size() > stringConf.maxLength)
876 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600877 error(
Riya Dixit89644442024-03-31 05:39:59 -0500878 "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}'",
879 "ATTRIBUTE_VALUE", value, "LENGTH", value.size(), "MIN_LEN",
880 stringConf.minLength, "MAX_LEN", stringConf.maxLength);
John Wang8241b342020-06-05 10:49:17 +0800881 return PLDM_ERROR_INVALID_LENGTH;
882 }
883 return PLDM_SUCCESS;
884 }
885 default:
Riya Dixit89644442024-03-31 05:39:59 -0500886 error("ReadOnly or Unsupported type '{TYPE}'", "TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800887 return PLDM_ERROR;
888 };
889}
890
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600891int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
892 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800893{
894 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
895 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
896 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
897 if (!attrValueTable || !attrTable || !stringTable)
898 {
899 return PLDM_BIOS_TABLE_UNAVAILABLE;
900 }
901
John Wangd9659342020-02-27 16:46:05 +0800902 auto attrValueEntry =
903 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
904
905 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
906
Patrick Williams6da4f912023-05-10 07:50:53 -0500907 auto attrEntry = table::attribute::findByHandle(*attrTable,
908 attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800909 if (!attrEntry)
910 {
911 return PLDM_ERROR;
912 }
913
John Wang8241b342020-06-05 10:49:17 +0800914 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
915 if (rc != PLDM_SUCCESS)
916 {
917 return rc;
918 }
919
Patrick Williams6da4f912023-05-10 07:50:53 -0500920 auto destTable = table::attribute_value::updateTable(*attrValueTable, entry,
921 size);
John Wang8241b342020-06-05 10:49:17 +0800922
923 if (!destTable)
924 {
925 return PLDM_ERROR;
926 }
927
John Wangd9659342020-02-27 16:46:05 +0800928 try
929 {
930 auto attrHeader = table::attribute::decodeHeader(attrEntry);
931
932 BIOSStringTable biosStringTable(*stringTable);
933 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500934 auto iter = std::find_if(
935 biosAttributes.begin(), biosAttributes.end(),
936 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800937
938 if (iter == biosAttributes.end())
939 {
940 return PLDM_ERROR;
941 }
George Liu6d6d1e82021-02-16 11:08:55 +0800942 if (updateDBus)
943 {
944 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
945 biosStringTable);
946 }
John Wangd9659342020-02-27 16:46:05 +0800947 }
948 catch (const std::exception& e)
949 {
Riya Dixit89644442024-03-31 05:39:59 -0500950 error("Set attribute value error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800951 return PLDM_ERROR;
952 }
953
Tom Joseph7f839f92020-09-21 10:20:44 +0530954 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800955
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600956 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
957
John Wangd9659342020-02-27 16:46:05 +0800958 return PLDM_SUCCESS;
959}
960
961void BIOSConfig::removeTables()
962{
963 try
964 {
965 fs::remove(tableDir / stringTableFile);
966 fs::remove(tableDir / attrTableFile);
967 fs::remove(tableDir / attrValueTableFile);
968 }
969 catch (const std::exception& e)
970 {
Riya Dixit89644442024-03-31 05:39:59 -0500971 error("Remove the tables error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800972 }
973}
974
Sampa Misra46ece062020-03-18 07:17:44 -0500975void BIOSConfig::processBiosAttrChangeNotification(
976 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
977{
978 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
979 const auto& propertyName = dBusMap->propertyName;
980 const auto& attrName = biosAttributes[biosAttrIndex]->name;
981
982 const auto it = chProperties.find(propertyName);
983 if (it == chProperties.end())
984 {
985 return;
986 }
987
988 PropertyValue newPropVal = it->second;
989 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
990 if (!stringTable.has_value())
991 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600992 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500993 return;
994 }
995 BIOSStringTable biosStringTable(*stringTable);
996 uint16_t attrNameHdl{};
997 try
998 {
999 attrNameHdl = biosStringTable.findHandle(attrName);
1000 }
Patrick Williams51330582021-10-06 12:48:56 -05001001 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -05001002 {
Riya Dixit89644442024-03-31 05:39:59 -05001003 error(
1004 "Missing handle for attribute '{ATTRIBUTE}' in BIOS String Table, error - '{ERROR}'",
1005 "ATTRIBUTE", attrName, "ERROR", e);
Sampa Misra46ece062020-03-18 07:17:44 -05001006 return;
1007 }
1008
1009 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1010 if (!attrTable.has_value())
1011 {
Riya Dixit89644442024-03-31 05:39:59 -05001012 error("BIOS Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001013 return;
1014 }
1015 const struct pldm_bios_attr_table_entry* tableEntry =
1016 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
1017 if (tableEntry == nullptr)
1018 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001019 error(
Riya Dixit89644442024-03-31 05:39:59 -05001020 "Failed to find attribute {ATTRIBUTE} in BIOS Attribute table with attribute handle '{ATTR_HANDLE}'",
1021 "ATTRIBUTE", attrName, "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -05001022 return;
1023 }
1024
Patrick Williams6da4f912023-05-10 07:50:53 -05001025 auto [attrHdl, attrType,
1026 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -05001027
1028 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
1029
1030 if (!attrValueSrcTable.has_value())
1031 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001032 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001033 return;
1034 }
1035
1036 Table newValue;
1037 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
1038 newValue, attrHdl, attrType, newPropVal);
1039 if (rc != PLDM_SUCCESS)
1040 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001041 error(
Riya Dixit89644442024-03-31 05:39:59 -05001042 "Failed to update the attribute value table for attribute handle '{ATTR_HANDLE}' and attribute type '{TYPE}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -05001043 "ATTR_HANDLE", attrHdl, "TYPE", attrType);
Sampa Misra46ece062020-03-18 07:17:44 -05001044 return;
1045 }
1046 auto destTable = table::attribute_value::updateTable(
1047 *attrValueSrcTable, newValue.data(), newValue.size());
1048 if (destTable.has_value())
1049 {
1050 storeTable(tableDir / attrValueTableFile, *destTable);
1051 }
Sampa Misra0f262332021-02-15 00:13:51 -06001052
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001053 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001054 if (rc != PLDM_SUCCESS)
1055 {
Riya Dixit89644442024-03-31 05:39:59 -05001056 error(
1057 "Failed to setAttrValue on base bios table and dbus, response code '{RC}'",
1058 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001059 }
Sampa Misra46ece062020-03-18 07:17:44 -05001060}
1061
George Liu1244acf2020-08-14 09:11:11 +08001062uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1063{
1064 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1065 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1066
1067 BIOSStringTable biosStringTable(*stringTable);
1068 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1069 attrTable->data(), attrTable->size());
1070 auto stringHandle = biosStringTable.findHandle(attrName);
1071
1072 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1073 attrTable->data(), attrTable->size()))
1074 {
1075 auto header = table::attribute::decodeHeader(entry);
1076 if (header.stringHandle == stringHandle)
1077 {
1078 return header.attrHandle;
1079 }
1080 }
1081
1082 throw std::invalid_argument("Unknow attribute Name");
1083}
1084
1085void BIOSConfig::constructPendingAttribute(
1086 const PendingAttributes& pendingAttributes)
1087{
Tom Joseph7f839f92020-09-21 10:20:44 +05301088 std::vector<uint16_t> listOfHandles{};
1089
George Liu1244acf2020-08-14 09:11:11 +08001090 for (auto& attribute : pendingAttributes)
1091 {
1092 std::string attributeName = attribute.first;
1093 auto& [attributeType, attributevalue] = attribute.second;
1094
1095 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1096 [&attributeName](const auto& attr) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001097 return attr->name == attributeName;
1098 });
George Liu1244acf2020-08-14 09:11:11 +08001099
1100 if (iter == biosAttributes.end())
1101 {
Riya Dixit89644442024-03-31 05:39:59 -05001102 error("Wrong attribute name {NAME}", "NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001103 continue;
1104 }
1105
1106 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
1107 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
1108 attrValueEntry.data());
1109
1110 auto handler = findAttrHandle(attributeName);
1111 auto type =
1112 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1113
1114 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1115 type != BIOSConfigManager::AttributeType::String &&
1116 type != BIOSConfigManager::AttributeType::Integer)
1117 {
Riya Dixit89644442024-03-31 05:39:59 -05001118 error("Attribute type '{TYPE}' not supported", "TYPE",
1119 attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001120 continue;
1121 }
1122
George Liu4876c542022-06-08 15:59:54 +08001123 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001124 menuPath, currentValue, defaultValue,
1125 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001126
George Liu1244acf2020-08-14 09:11:11 +08001127 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001128
1129 // Need to verify that the current value has really changed
1130 if (attributeType == attrType && attributevalue != currentValue)
1131 {
1132 listOfHandles.emplace_back(htole16(handler));
1133 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301134
George Liu1244acf2020-08-14 09:11:11 +08001135 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1136
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001137 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301138 }
1139
1140 if (listOfHandles.size())
1141 {
1142#ifdef OEM_IBM
1143 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301144 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301145 if (rc != PLDM_SUCCESS)
1146 {
1147 return;
1148 }
1149#endif
George Liu1244acf2020-08-14 09:11:11 +08001150 }
1151}
1152
1153void BIOSConfig::listenPendingAttributes()
1154{
1155 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1156 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1157
1158 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001159 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001160 pldm::utils::DBusHandler::getBus(),
1161 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001162 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001163 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001164
Patrick Williams6da4f912023-05-10 07:50:53 -05001165 using Value =
1166 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1167 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001168
Patrick Williams6da4f912023-05-10 07:50:53 -05001169 Properties props{};
1170 std::string intf;
1171 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001172
Patrick Williams6da4f912023-05-10 07:50:53 -05001173 auto valPropMap = props.find(propertyName);
1174 if (valPropMap == props.end())
1175 {
1176 return;
1177 }
George Liu1244acf2020-08-14 09:11:11 +08001178
Patrick Williams6da4f912023-05-10 07:50:53 -05001179 PendingAttributes pendingAttributes =
1180 std::get<PendingAttributes>(valPropMap->second);
1181 this->constructPendingAttribute(pendingAttributes);
Patrick Williamsa6756622023-10-20 11:19:15 -05001182 });
George Liu1244acf2020-08-14 09:11:11 +08001183
1184 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1185}
1186
John Wangd9659342020-02-27 16:46:05 +08001187} // namespace bios
1188} // namespace responder
1189} // namespace pldm