blob: 991b5c017670da9b15dc52bcc04102c00e3e8849 [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();
Archana Kakani46f352e2024-03-17 08:21:08 -050058
59#ifdef SYSTEM_SPECIFIC_BIOS_JSON
60 checkSystemTypeAvailability();
61#else
62 initBIOSAttributes(sysType, false);
63#endif
64
Archana Kakani62dd8ff2024-02-12 10:00:40 -060065 listenPendingAttributes();
66}
Tom Joseph7f839f92020-09-21 10:20:44 +053067
Archana Kakani46f352e2024-03-17 08:21:08 -050068void BIOSConfig::checkSystemTypeAvailability()
John Wangd9659342020-02-27 16:46:05 +080069{
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060070 if (platformConfigHandler)
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050071 {
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060072 auto systemType = platformConfigHandler->getPlatformName();
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050073 if (systemType.has_value())
74 {
Archana Kakani46f352e2024-03-17 08:21:08 -050075 // Received System Type from Entity Manager
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050076 sysType = systemType.value();
Archana Kakani46f352e2024-03-17 08:21:08 -050077 initBIOSAttributes(sysType, true);
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050078 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060079 else
80 {
Archana Kakani46f352e2024-03-17 08:21:08 -050081 platformConfigHandler->registerSystemTypeCallback(
82 std::bind(&BIOSConfig::initBIOSAttributes, this,
83 std::placeholders::_1, std::placeholders::_2));
Archana Kakani62dd8ff2024-02-12 10:00:40 -060084 }
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050085 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060086}
87
Archana Kakani46f352e2024-03-17 08:21:08 -050088void BIOSConfig::initBIOSAttributes(const std::string& systemType,
89 bool registerService)
Archana Kakani62dd8ff2024-02-12 10:00:40 -060090{
91 sysType = systemType;
92 fs::path dir{jsonDir / sysType};
93 if (!fs::exists(dir))
94 {
95 error("System specific bios attribute directory {DIR} does not exit",
96 "DIR", dir.string());
97 return;
98 }
John Wangd9659342020-02-27 16:46:05 +080099 constructAttributes();
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600100 buildTables();
Archana Kakani46f352e2024-03-17 08:21:08 -0500101 if (registerService)
102 {
103 requestPLDMServiceName();
104 }
John Wangd9659342020-02-27 16:46:05 +0800105}
106
107void BIOSConfig::buildTables()
108{
John Wangd9659342020-02-27 16:46:05 +0800109 auto stringTable = buildAndStoreStringTable();
110 if (stringTable)
111 {
112 buildAndStoreAttrTables(*stringTable);
113 }
114}
115
116std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
117{
118 fs::path tablePath;
119 switch (tableType)
120 {
121 case PLDM_BIOS_STRING_TABLE:
122 tablePath = tableDir / stringTableFile;
123 break;
124 case PLDM_BIOS_ATTR_TABLE:
125 tablePath = tableDir / attrTableFile;
126 break;
127 case PLDM_BIOS_ATTR_VAL_TABLE:
128 tablePath = tableDir / attrValueTableFile;
129 break;
130 }
131 return loadTable(tablePath);
132}
133
Tom Joseph7f839f92020-09-21 10:20:44 +0530134int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table,
135 bool updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800136{
137 fs::path stringTablePath(tableDir / stringTableFile);
138 fs::path attrTablePath(tableDir / attrTableFile);
139 fs::path attrValueTablePath(tableDir / attrValueTableFile);
140
141 if (!pldm_bios_table_checksum(table.data(), table.size()))
142 {
143 return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
144 }
145
146 if (tableType == PLDM_BIOS_STRING_TABLE)
147 {
148 storeTable(stringTablePath, table);
149 }
150 else if (tableType == PLDM_BIOS_ATTR_TABLE)
151 {
152 BIOSTable biosStringTable(stringTablePath.c_str());
153 if (biosStringTable.isEmpty())
154 {
155 return PLDM_INVALID_BIOS_TABLE_TYPE;
156 }
157
158 auto rc = checkAttributeTable(table);
159 if (rc != PLDM_SUCCESS)
160 {
161 return rc;
162 }
163
164 storeTable(attrTablePath, table);
165 }
166 else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
167 {
168 BIOSTable biosStringTable(stringTablePath.c_str());
169 BIOSTable biosStringValueTable(attrTablePath.c_str());
170 if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
171 {
172 return PLDM_INVALID_BIOS_TABLE_TYPE;
173 }
174
175 auto rc = checkAttributeValueTable(table);
176 if (rc != PLDM_SUCCESS)
177 {
178 return rc;
179 }
180
181 storeTable(attrValueTablePath, table);
George Liu1b180d82020-07-23 14:01:58 +0800182 }
183 else
184 {
185 return PLDM_INVALID_BIOS_TABLE_TYPE;
186 }
187
Tom Joseph7f839f92020-09-21 10:20:44 +0530188 if ((tableType == PLDM_BIOS_ATTR_VAL_TABLE) && updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800189 {
George Liu1b180d82020-07-23 14:01:58 +0800190 updateBaseBIOSTableProperty();
191 }
192
193 return PLDM_SUCCESS;
194}
195
196int BIOSConfig::checkAttributeTable(const Table& table)
197{
198 using namespace pldm::bios::utils;
199 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
200 for (auto entry :
201 BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
202 {
203 auto attrNameHandle =
204 pldm_bios_table_attr_entry_decode_string_handle(entry);
205
206 auto stringEnty = pldm_bios_table_string_find_by_handle(
207 stringTable->data(), stringTable->size(), attrNameHandle);
208 if (stringEnty == nullptr)
209 {
210 return PLDM_INVALID_BIOS_ATTR_HANDLE;
211 }
212
213 auto attrType = static_cast<pldm_bios_attribute_type>(
214 pldm_bios_table_attr_entry_decode_attribute_type(entry));
215
216 switch (attrType)
217 {
218 case PLDM_BIOS_ENUMERATION:
219 case PLDM_BIOS_ENUMERATION_READ_ONLY:
220 {
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930221 uint8_t pvNum;
222 // Preconditions are upheld therefore no error check necessary
223 pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry,
224 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800225 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930226 // Preconditions are upheld therefore no error check necessary
227 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800228 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930229 uint8_t defNum;
230 pldm_bios_table_attr_entry_enum_decode_def_num_check(entry,
231 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800232 std::vector<uint8_t> defIndices(defNum);
233 pldm_bios_table_attr_entry_enum_decode_def_indices(
234 entry, defIndices.data(), defIndices.size());
235
236 for (size_t i = 0; i < pvHandls.size(); i++)
237 {
238 auto stringEntry = pldm_bios_table_string_find_by_handle(
239 stringTable->data(), stringTable->size(), pvHandls[i]);
240 if (stringEntry == nullptr)
241 {
242 return PLDM_INVALID_BIOS_ATTR_HANDLE;
243 }
244 }
245
246 for (size_t i = 0; i < defIndices.size(); i++)
247 {
248 auto stringEntry = pldm_bios_table_string_find_by_handle(
249 stringTable->data(), stringTable->size(),
250 pvHandls[defIndices[i]]);
251 if (stringEntry == nullptr)
252 {
253 return PLDM_INVALID_BIOS_ATTR_HANDLE;
254 }
255 }
256 break;
257 }
258 case PLDM_BIOS_INTEGER:
259 case PLDM_BIOS_INTEGER_READ_ONLY:
260 case PLDM_BIOS_STRING:
261 case PLDM_BIOS_STRING_READ_ONLY:
262 case PLDM_BIOS_PASSWORD:
263 case PLDM_BIOS_PASSWORD_READ_ONLY:
264 break;
265 default:
266 return PLDM_INVALID_BIOS_ATTR_HANDLE;
267 }
268 }
269
270 return PLDM_SUCCESS;
271}
272
273int BIOSConfig::checkAttributeValueTable(const Table& table)
274{
275 using namespace pldm::bios::utils;
276 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
277 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
278
279 baseBIOSTableMaps.clear();
280
281 for (auto tableEntry :
282 BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
283 {
284 AttributeName attributeName{};
285 AttributeType attributeType{};
286 ReadonlyStatus readonlyStatus{};
287 DisplayName displayName{};
288 Description description{};
289 MenuPath menuPath{};
290 CurrentValue currentValue{};
291 DefaultValue defaultValue{};
Sagar Srinivas7927f902023-10-09 07:53:00 -0500292 std::vector<ValueDisplayName> valueDisplayNames;
293 std::map<uint16_t, std::vector<std::string>> valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800294 Option options{};
295
296 auto attrValueHandle =
297 pldm_bios_table_attr_value_entry_decode_attribute_handle(
298 tableEntry);
299 auto attrType = static_cast<pldm_bios_attribute_type>(
300 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
301
302 auto attrEntry = pldm_bios_table_attr_find_by_handle(
303 attrTable->data(), attrTable->size(), attrValueHandle);
304 if (attrEntry == nullptr)
305 {
306 return PLDM_INVALID_BIOS_ATTR_HANDLE;
307 }
308 auto attrHandle =
309 pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
310 auto attrNameHandle =
311 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
312
313 auto stringEntry = pldm_bios_table_string_find_by_handle(
314 stringTable->data(), stringTable->size(), attrNameHandle);
315 if (stringEntry == nullptr)
316 {
317 return PLDM_INVALID_BIOS_ATTR_HANDLE;
318 }
319 auto strLength =
320 pldm_bios_table_string_entry_decode_string_length(stringEntry);
321 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930322 // Preconditions are upheld therefore no error check necessary
323 pldm_bios_table_string_entry_decode_string_check(
324 stringEntry, buffer.data(), buffer.size());
325
George Liu1b180d82020-07-23 14:01:58 +0800326 attributeName = std::string(buffer.data(), buffer.data() + strLength);
327
328 if (!biosAttributes.empty())
329 {
330 readonlyStatus =
George Liub1fbeec2020-09-04 09:59:46 +0800331 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800332 description =
333 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
334 displayName =
335 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
Sagar Srinivas7927f902023-10-09 07:53:00 -0500336 valueDisplayNamesMap =
337 biosAttributes[attrHandle % biosAttributes.size()]
338 ->valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800339 }
340
341 switch (attrType)
342 {
343 case PLDM_BIOS_ENUMERATION:
344 case PLDM_BIOS_ENUMERATION_READ_ONLY:
345 {
Sagar Srinivas7927f902023-10-09 07:53:00 -0500346 if (valueDisplayNamesMap.contains(attrHandle))
347 {
348 const std::vector<ValueDisplayName>& vdn =
349 valueDisplayNamesMap[attrHandle];
350 valueDisplayNames.insert(valueDisplayNames.end(),
351 vdn.begin(), vdn.end());
352 }
George Liu1b180d82020-07-23 14:01:58 +0800353 auto getValue = [](uint16_t handle,
354 const Table& table) -> std::string {
355 auto stringEntry = pldm_bios_table_string_find_by_handle(
356 table.data(), table.size(), handle);
357
358 auto strLength =
359 pldm_bios_table_string_entry_decode_string_length(
360 stringEntry);
361 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930362 // Preconditions are upheld therefore no error check
363 // necessary
364 pldm_bios_table_string_entry_decode_string_check(
George Liu1b180d82020-07-23 14:01:58 +0800365 stringEntry, buffer.data(), buffer.size());
366
367 return std::string(buffer.data(),
368 buffer.data() + strLength);
369 };
370
371 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
372 "AttributeType.Enumeration";
373
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930374 uint8_t pvNum;
375 // Preconditions are upheld therefore no error check necessary
376 pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
377 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800378 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930379 // Preconditions are upheld therefore no error check necessary
380 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
George Liu1b180d82020-07-23 14:01:58 +0800381 attrEntry, pvHandls.data(), pvHandls.size());
382
383 // get possible_value
384 for (size_t i = 0; i < pvHandls.size(); i++)
385 {
386 options.push_back(
387 std::make_tuple("xyz.openbmc_project.BIOSConfig."
388 "Manager.BoundType.OneOf",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500389 getValue(pvHandls[i], *stringTable),
390 valueDisplayNames[i]));
George Liu1b180d82020-07-23 14:01:58 +0800391 }
392
393 auto count =
394 pldm_bios_table_attr_value_entry_enum_decode_number(
395 tableEntry);
396 std::vector<uint8_t> handles(count);
397 pldm_bios_table_attr_value_entry_enum_decode_handles(
398 tableEntry, handles.data(), handles.size());
399
400 // get current_value
401 for (size_t i = 0; i < handles.size(); i++)
402 {
403 currentValue = getValue(pvHandls[handles[i]], *stringTable);
404 }
405
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930406 uint8_t defNum;
407 // Preconditions are upheld therefore no error check necessary
408 pldm_bios_table_attr_entry_enum_decode_def_num_check(attrEntry,
409 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800410 std::vector<uint8_t> defIndices(defNum);
411 pldm_bios_table_attr_entry_enum_decode_def_indices(
412 attrEntry, defIndices.data(), defIndices.size());
413
414 // get default_value
415 for (size_t i = 0; i < defIndices.size(); i++)
416 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500417 defaultValue = getValue(pvHandls[defIndices[i]],
418 *stringTable);
George Liu1b180d82020-07-23 14:01:58 +0800419 }
420
421 break;
422 }
423 case PLDM_BIOS_INTEGER:
424 case PLDM_BIOS_INTEGER_READ_ONLY:
425 {
426 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
427 "AttributeType.Integer";
428 currentValue = static_cast<int64_t>(
429 pldm_bios_table_attr_value_entry_integer_decode_cv(
430 tableEntry));
431
432 uint64_t lower, upper, def;
433 uint32_t scalar;
434 pldm_bios_table_attr_entry_integer_decode(
435 attrEntry, &lower, &upper, &scalar, &def);
Sagar Srinivas7927f902023-10-09 07:53:00 -0500436 options.push_back(std::make_tuple(
437 "xyz.openbmc_project.BIOSConfig.Manager."
438 "BoundType.LowerBound",
439 static_cast<int64_t>(lower), attributeName));
440 options.push_back(std::make_tuple(
441 "xyz.openbmc_project.BIOSConfig.Manager."
442 "BoundType.UpperBound",
443 static_cast<int64_t>(upper), attributeName));
444 options.push_back(std::make_tuple(
445 "xyz.openbmc_project.BIOSConfig.Manager."
446 "BoundType.ScalarIncrement",
447 static_cast<int64_t>(scalar), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800448 defaultValue = static_cast<int64_t>(def);
449 break;
450 }
451 case PLDM_BIOS_STRING:
452 case PLDM_BIOS_STRING_READ_ONLY:
453 {
454 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
455 "AttributeType.String";
456 variable_field currentString;
457 pldm_bios_table_attr_value_entry_string_decode_string(
458 tableEntry, &currentString);
459 currentValue = std::string(
460 reinterpret_cast<const char*>(currentString.ptr),
461 currentString.length);
462 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
463 attrEntry);
464 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
465 attrEntry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930466 uint16_t def;
467 // Preconditions are upheld therefore no error check necessary
468 pldm_bios_table_attr_entry_string_decode_def_string_length_check(
469 attrEntry, &def);
George Liu1b180d82020-07-23 14:01:58 +0800470 std::vector<char> defString(def + 1);
471 pldm_bios_table_attr_entry_string_decode_def_string(
472 attrEntry, defString.data(), defString.size());
473 options.push_back(
474 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
475 "BoundType.MinStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500476 static_cast<int64_t>(min), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800477 options.push_back(
478 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
479 "BoundType.MaxStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500480 static_cast<int64_t>(max), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800481 defaultValue = defString.data();
482 break;
483 }
484 case PLDM_BIOS_PASSWORD:
485 case PLDM_BIOS_PASSWORD_READ_ONLY:
486 {
487 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
488 "AttributeType.Password";
489 break;
490 }
491 default:
492 return PLDM_INVALID_BIOS_ATTR_HANDLE;
493 }
494 baseBIOSTableMaps.emplace(
495 std::move(attributeName),
496 std::make_tuple(attributeType, readonlyStatus, displayName,
497 description, menuPath, currentValue, defaultValue,
498 std::move(options)));
499 }
500
501 return PLDM_SUCCESS;
502}
503
504void BIOSConfig::updateBaseBIOSTableProperty()
505{
506 constexpr static auto biosConfigPath =
507 "/xyz/openbmc_project/bios_config/manager";
508 constexpr static auto biosConfigInterface =
509 "xyz.openbmc_project.BIOSConfig.Manager";
510 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
511 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
512
513 if (baseBIOSTableMaps.empty())
514 {
515 return;
516 }
517
518 try
519 {
520 auto& bus = dbusHandler->getBus();
Patrick Williams6da4f912023-05-10 07:50:53 -0500521 auto service = dbusHandler->getService(biosConfigPath,
522 biosConfigInterface);
George Liu1b180d82020-07-23 14:01:58 +0800523 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
524 dbusProperties, "Set");
525 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
526 method.append(biosConfigInterface, biosConfigPropertyName, value);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000527 bus.call_noreply(method, dbusTimeout);
George Liu1b180d82020-07-23 14:01:58 +0800528 }
529 catch (const std::exception& e)
530 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600531 error("failed to update BaseBIOSTable property, ERROR={ERR_EXCEP}",
532 "ERR_EXCEP", e.what());
George Liu1b180d82020-07-23 14:01:58 +0800533 }
534}
535
John Wangd9659342020-02-27 16:46:05 +0800536void BIOSConfig::constructAttributes()
537{
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600538 info("Bios Attribute file path: {PATH}", "PATH", (jsonDir / sysType));
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500539 load(jsonDir / sysType / stringJsonFile, [this](const Json& entry) {
John Wangd9659342020-02-27 16:46:05 +0800540 constructAttribute<BIOSStringAttribute>(entry);
541 });
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500542 load(jsonDir / sysType / integerJsonFile, [this](const Json& entry) {
John Wang95e6b3c2020-02-13 09:43:24 +0800543 constructAttribute<BIOSIntegerAttribute>(entry);
544 });
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500545 load(jsonDir / sysType / enumJsonFile, [this](const Json& entry) {
John Wang3be70852020-02-13 15:59:04 +0800546 constructAttribute<BIOSEnumAttribute>(entry);
547 });
John Wangd9659342020-02-27 16:46:05 +0800548}
549
550void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
551{
552 BIOSStringTable biosStringTable(stringTable);
553
554 if (biosAttributes.empty())
555 {
556 return;
557 }
558
Tom Josephca7b2522020-11-18 12:27:11 +0530559 BaseBIOSTable biosTable{};
560 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
561 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
562
563 try
564 {
565 auto& bus = dbusHandler->getBus();
566 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams6da4f912023-05-10 07:50:53 -0500567 auto method = bus.new_method_call(service.c_str(), biosObjPath,
568 "org.freedesktop.DBus.Properties",
569 "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530570 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500571 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530572 std::variant<BaseBIOSTable> varBiosTable{};
573 reply.read(varBiosTable);
574 biosTable = std::get<BaseBIOSTable>(varBiosTable);
575 }
576 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
577 // default values populated from the BIOS JSONs to keep PLDM and
578 // bios-settings-manager in sync
579 catch (const std::exception& e)
580 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600581 error("Failed to read BaseBIOSTable property, ERROR={ERR_EXCEP}",
582 "ERR_EXCEP", e.what());
Tom Josephca7b2522020-11-18 12:27:11 +0530583 }
584
John Wangd9659342020-02-27 16:46:05 +0800585 Table attrTable, attrValueTable;
586
587 for (auto& attr : biosAttributes)
588 {
589 try
590 {
Tom Josephca7b2522020-11-18 12:27:11 +0530591 auto iter = biosTable.find(attr->name);
592 if (iter == biosTable.end())
593 {
594 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
595 std::nullopt);
596 }
597 else
598 {
599 attr->constructEntry(
600 biosStringTable, attrTable, attrValueTable,
601 std::get<static_cast<uint8_t>(Index::currentValue)>(
602 iter->second));
603 }
John Wangd9659342020-02-27 16:46:05 +0800604 }
605 catch (const std::exception& e)
606 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500607 error("Error constructing table entry for '{ATTR}': {ERROR}",
608 "ATTR", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800609 }
610 }
611
612 table::appendPadAndChecksum(attrTable);
613 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800614 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
615 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800616}
617
618std::optional<Table> BIOSConfig::buildAndStoreStringTable()
619{
620 std::set<std::string> strings;
621 auto handler = [&strings](const Json& entry) {
622 strings.emplace(entry.at("attribute_name"));
623 };
624
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500625 load(jsonDir / sysType / stringJsonFile, handler);
626 load(jsonDir / sysType / integerJsonFile, handler);
627 load(jsonDir / sysType / enumJsonFile, [&strings](const Json& entry) {
John Wangd9659342020-02-27 16:46:05 +0800628 strings.emplace(entry.at("attribute_name"));
629 auto possibleValues = entry.at("possible_values");
630 for (auto& pv : possibleValues)
631 {
632 strings.emplace(pv);
633 }
634 });
635
636 if (strings.empty())
637 {
638 return std::nullopt;
639 }
640
641 Table table;
642 for (const auto& elem : strings)
643 {
644 table::string::constructEntry(table, elem);
645 }
646
647 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800648 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800649 return table;
650}
651
652void BIOSConfig::storeTable(const fs::path& path, const Table& table)
653{
654 BIOSTable biosTable(path.c_str());
655 biosTable.store(table);
656}
657
658std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
659{
660 BIOSTable biosTable(path.c_str());
661 if (biosTable.isEmpty())
662 {
663 return std::nullopt;
664 }
665
666 Table table;
667 biosTable.load(table);
668 return table;
669}
670
671void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
672{
673 std::ifstream file;
674 Json jsonConf;
675 if (fs::exists(filePath))
676 {
677 try
678 {
679 file.open(filePath);
680 jsonConf = Json::parse(file);
681 auto entries = jsonConf.at("entries");
682 for (auto& entry : entries)
683 {
684 try
685 {
686 handler(entry);
687 }
688 catch (const std::exception& e)
689 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600690 error(
691 "Failed to parse JSON config file(entry handler) : {JSON_PATH}, {ERR_EXCEP}",
692 "JSON_PATH", filePath.c_str(), "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800693 }
694 }
695 }
696 catch (const std::exception& e)
697 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500698 error("Failed to parse JSON config at '{PATH}': {ERROR}", "PATH",
699 filePath.c_str(), "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800700 }
701 }
702}
703
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600704std::string BIOSConfig::decodeStringFromStringEntry(
705 const pldm_bios_string_table_entry* stringEntry)
706{
707 auto strLength =
708 pldm_bios_table_string_entry_decode_string_length(stringEntry);
709 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930710 // Preconditions are upheld therefore no error check necessary
711 pldm_bios_table_string_entry_decode_string_check(stringEntry, buffer.data(),
712 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600713 return std::string(buffer.data(), buffer.data() + strLength);
714}
715
716std::string
717 BIOSConfig::displayStringHandle(uint16_t handle, uint8_t index,
718 const std::optional<Table>& attrTable,
719 const std::optional<Table>& stringTable)
720{
721 auto attrEntry = pldm_bios_table_attr_find_by_handle(
722 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930723 uint8_t pvNum;
724 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(attrEntry,
725 &pvNum);
726 if (rc != PLDM_SUCCESS)
727 {
728 error(
729 "Failed to decode BIOS table possible values for attribute entry: {LIPBLDM_ERROR}",
730 "LIBPLDM_ERROR", rc);
731 throw std::runtime_error(
732 "Failed to decode BIOS table possible values for attribute entry");
733 }
734
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600735 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930736 // Preconditions are upheld therefore no error check necessary
737 pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
738 attrEntry, pvHandls.data(), pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600739
740 std::string displayString = std::to_string(pvHandls[index]);
741
742 auto stringEntry = pldm_bios_table_string_find_by_handle(
743 stringTable->data(), stringTable->size(), pvHandls[index]);
744
745 auto decodedStr = decodeStringFromStringEntry(stringEntry);
746
747 return decodedStr + "(" + displayString + ")";
748}
749
750void BIOSConfig::traceBIOSUpdate(
751 const pldm_bios_attr_val_table_entry* attrValueEntry,
752 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
753{
754 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
755 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
756
Patrick Williams6da4f912023-05-10 07:50:53 -0500757 auto [attrHandle,
758 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600759
760 auto attrHeader = table::attribute::decodeHeader(attrEntry);
761 BIOSStringTable biosStringTable(*stringTable);
762 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
763
764 switch (attrType)
765 {
766 case PLDM_BIOS_ENUMERATION:
767 case PLDM_BIOS_ENUMERATION_READ_ONLY:
768 {
769 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
770 attrValueEntry);
771 std::vector<uint8_t> handles(count);
772 pldm_bios_table_attr_value_entry_enum_decode_handles(
773 attrValueEntry, handles.data(), handles.size());
774
775 for (uint8_t handle : handles)
776 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600777 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
778 stringTable);
779 auto chkBMC = isBMC ? "true" : "false";
780 info(
781 "BIOS:{ATTR_NAME}, updated to value: {NEW_VAL}, by BMC: {CHK_BMC} ",
782 "ATTR_NAME", attrName, "NEW_VAL", nwVal, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600783 }
784 break;
785 }
786 case PLDM_BIOS_INTEGER:
787 case PLDM_BIOS_INTEGER_READ_ONLY:
788 {
789 auto value =
790 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600791 auto chkBMC = isBMC ? "true" : "false";
792 info(
793 "BIOS: {ATTR_NAME}, updated to value: {UPDATED_VAL}, by BMC: {CHK_BMC}",
794 "ATTR_NAME", attrName, "UPDATED_VAL", value, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600795 break;
796 }
797 case PLDM_BIOS_STRING:
798 case PLDM_BIOS_STRING_READ_ONLY:
799 {
800 auto value =
801 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600802 auto chkBMC = isBMC ? "true" : "false";
803 info(
804 "BIOS: {ATTR_NAME}, updated to value: {UPDATED_VAL}, by BMC: {CHK_BMC}",
805 "ATTR_NAME", attrName, "UPDATED_VAL", value, "CHK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600806 break;
807 }
808 default:
809 break;
810 };
811}
812
John Wang8241b342020-06-05 10:49:17 +0800813int BIOSConfig::checkAttrValueToUpdate(
814 const pldm_bios_attr_val_table_entry* attrValueEntry,
815 const pldm_bios_attr_table_entry* attrEntry, Table&)
816
817{
Patrick Williams6da4f912023-05-10 07:50:53 -0500818 auto [attrHandle,
819 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800820
821 switch (attrType)
822 {
823 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800824 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800825 {
826 auto value =
827 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500828 auto [pvHdls,
829 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600830 if (!(value.size() == 1))
831 {
832 return PLDM_ERROR_INVALID_LENGTH;
833 }
John Wang8241b342020-06-05 10:49:17 +0800834 if (value[0] >= pvHdls.size())
835 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600836 error("Enum: Illgeal index, Index = {ATTR_INDEX}", "ATTR_INDEX",
837 (int)value[0]);
John Wang8241b342020-06-05 10:49:17 +0800838 return PLDM_ERROR_INVALID_DATA;
839 }
John Wang8241b342020-06-05 10:49:17 +0800840 return PLDM_SUCCESS;
841 }
842 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800843 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800844 {
845 auto value =
846 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500847 auto [lower, upper, scalar,
848 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800849
850 if (value < lower || value > upper)
851 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600852 error("Integer: out of bound, value = {ATTR_VALUE}",
853 "ATTR_VALUE", value);
John Wang8241b342020-06-05 10:49:17 +0800854 return PLDM_ERROR_INVALID_DATA;
855 }
856 return PLDM_SUCCESS;
857 }
858 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800859 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800860 {
861 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
862 auto value =
863 table::attribute_value::decodeStringEntry(attrValueEntry);
864 if (value.size() < stringConf.minLength ||
865 value.size() > stringConf.maxLength)
866 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600867 error(
868 "String: Length error, string = {ATTR_VALUE} length {LEN}",
869 "ATTR_VALUE", value, "LEN", value.size());
John Wang8241b342020-06-05 10:49:17 +0800870 return PLDM_ERROR_INVALID_LENGTH;
871 }
872 return PLDM_SUCCESS;
873 }
874 default:
Riya Dixit49cfb132023-03-02 04:26:53 -0600875 error("ReadOnly or Unspported type, type = {ATTR_TYPE}",
876 "ATTR_TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800877 return PLDM_ERROR;
878 };
879}
880
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600881int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
882 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800883{
884 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
885 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
886 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
887 if (!attrValueTable || !attrTable || !stringTable)
888 {
889 return PLDM_BIOS_TABLE_UNAVAILABLE;
890 }
891
John Wangd9659342020-02-27 16:46:05 +0800892 auto attrValueEntry =
893 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
894
895 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
896
Patrick Williams6da4f912023-05-10 07:50:53 -0500897 auto attrEntry = table::attribute::findByHandle(*attrTable,
898 attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800899 if (!attrEntry)
900 {
901 return PLDM_ERROR;
902 }
903
John Wang8241b342020-06-05 10:49:17 +0800904 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
905 if (rc != PLDM_SUCCESS)
906 {
907 return rc;
908 }
909
Patrick Williams6da4f912023-05-10 07:50:53 -0500910 auto destTable = table::attribute_value::updateTable(*attrValueTable, entry,
911 size);
John Wang8241b342020-06-05 10:49:17 +0800912
913 if (!destTable)
914 {
915 return PLDM_ERROR;
916 }
917
John Wangd9659342020-02-27 16:46:05 +0800918 try
919 {
920 auto attrHeader = table::attribute::decodeHeader(attrEntry);
921
922 BIOSStringTable biosStringTable(*stringTable);
923 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500924 auto iter = std::find_if(
925 biosAttributes.begin(), biosAttributes.end(),
926 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800927
928 if (iter == biosAttributes.end())
929 {
930 return PLDM_ERROR;
931 }
George Liu6d6d1e82021-02-16 11:08:55 +0800932 if (updateDBus)
933 {
934 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
935 biosStringTable);
936 }
John Wangd9659342020-02-27 16:46:05 +0800937 }
938 catch (const std::exception& e)
939 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600940 error("Set attribute value error: {ERR_EXCEP}", "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800941 return PLDM_ERROR;
942 }
943
Tom Joseph7f839f92020-09-21 10:20:44 +0530944 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800945
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600946 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
947
John Wangd9659342020-02-27 16:46:05 +0800948 return PLDM_SUCCESS;
949}
950
951void BIOSConfig::removeTables()
952{
953 try
954 {
955 fs::remove(tableDir / stringTableFile);
956 fs::remove(tableDir / attrTableFile);
957 fs::remove(tableDir / attrValueTableFile);
958 }
959 catch (const std::exception& e)
960 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600961 error("Remove the tables error: {ERR_EXCEP}", "ERR_EXCEP", e.what());
John Wangd9659342020-02-27 16:46:05 +0800962 }
963}
964
Sampa Misra46ece062020-03-18 07:17:44 -0500965void BIOSConfig::processBiosAttrChangeNotification(
966 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
967{
968 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
969 const auto& propertyName = dBusMap->propertyName;
970 const auto& attrName = biosAttributes[biosAttrIndex]->name;
971
972 const auto it = chProperties.find(propertyName);
973 if (it == chProperties.end())
974 {
975 return;
976 }
977
978 PropertyValue newPropVal = it->second;
979 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
980 if (!stringTable.has_value())
981 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600982 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500983 return;
984 }
985 BIOSStringTable biosStringTable(*stringTable);
986 uint16_t attrNameHdl{};
987 try
988 {
989 attrNameHdl = biosStringTable.findHandle(attrName);
990 }
Patrick Williams51330582021-10-06 12:48:56 -0500991 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -0500992 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500993 error("Missing handle for '{ATTR}': {ERROR}", "ATTR", attrName, "ERROR",
994 e);
Sampa Misra46ece062020-03-18 07:17:44 -0500995 return;
996 }
997
998 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
999 if (!attrTable.has_value())
1000 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001001 error("Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001002 return;
1003 }
1004 const struct pldm_bios_attr_table_entry* tableEntry =
1005 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
1006 if (tableEntry == nullptr)
1007 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001008 error(
1009 "Attribute not found in attribute table, name= {ATTR_NAME} name handle={ATTR_HANDLE}",
1010 "ATTR_NAME", attrName.c_str(), "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -05001011 return;
1012 }
1013
Patrick Williams6da4f912023-05-10 07:50:53 -05001014 auto [attrHdl, attrType,
1015 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -05001016
1017 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
1018
1019 if (!attrValueSrcTable.has_value())
1020 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001021 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001022 return;
1023 }
1024
1025 Table newValue;
1026 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
1027 newValue, attrHdl, attrType, newPropVal);
1028 if (rc != PLDM_SUCCESS)
1029 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001030 error(
1031 "Could not update the attribute value table for attribute handle={ATTR_HANDLE} and type={ATTR_TYPE}",
1032 "ATTR_HANDLE", attrHdl, "ATTR_TYPE", (uint32_t)attrType);
Sampa Misra46ece062020-03-18 07:17:44 -05001033 return;
1034 }
1035 auto destTable = table::attribute_value::updateTable(
1036 *attrValueSrcTable, newValue.data(), newValue.size());
1037 if (destTable.has_value())
1038 {
1039 storeTable(tableDir / attrValueTableFile, *destTable);
1040 }
Sampa Misra0f262332021-02-15 00:13:51 -06001041
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001042 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001043 if (rc != PLDM_SUCCESS)
1044 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001045 error("could not setAttrValue on base bios table and dbus, rc = {RC}",
1046 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001047 }
Sampa Misra46ece062020-03-18 07:17:44 -05001048}
1049
George Liu1244acf2020-08-14 09:11:11 +08001050uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1051{
1052 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1053 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1054
1055 BIOSStringTable biosStringTable(*stringTable);
1056 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1057 attrTable->data(), attrTable->size());
1058 auto stringHandle = biosStringTable.findHandle(attrName);
1059
1060 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1061 attrTable->data(), attrTable->size()))
1062 {
1063 auto header = table::attribute::decodeHeader(entry);
1064 if (header.stringHandle == stringHandle)
1065 {
1066 return header.attrHandle;
1067 }
1068 }
1069
1070 throw std::invalid_argument("Unknow attribute Name");
1071}
1072
1073void BIOSConfig::constructPendingAttribute(
1074 const PendingAttributes& pendingAttributes)
1075{
Tom Joseph7f839f92020-09-21 10:20:44 +05301076 std::vector<uint16_t> listOfHandles{};
1077
George Liu1244acf2020-08-14 09:11:11 +08001078 for (auto& attribute : pendingAttributes)
1079 {
1080 std::string attributeName = attribute.first;
1081 auto& [attributeType, attributevalue] = attribute.second;
1082
1083 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1084 [&attributeName](const auto& attr) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001085 return attr->name == attributeName;
1086 });
George Liu1244acf2020-08-14 09:11:11 +08001087
1088 if (iter == biosAttributes.end())
1089 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001090 error("Wrong attribute name, attributeName = {ATTR_NAME}",
1091 "ATTR_NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001092 continue;
1093 }
1094
1095 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
1096 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
1097 attrValueEntry.data());
1098
1099 auto handler = findAttrHandle(attributeName);
1100 auto type =
1101 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1102
1103 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1104 type != BIOSConfigManager::AttributeType::String &&
1105 type != BIOSConfigManager::AttributeType::Integer)
1106 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001107 error("Attribute type not supported, attributeType = {ATTR_TYPE}",
1108 "ATTR_TYPE", attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001109 continue;
1110 }
1111
George Liu4876c542022-06-08 15:59:54 +08001112 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001113 menuPath, currentValue, defaultValue,
1114 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001115
George Liu1244acf2020-08-14 09:11:11 +08001116 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001117
1118 // Need to verify that the current value has really changed
1119 if (attributeType == attrType && attributevalue != currentValue)
1120 {
1121 listOfHandles.emplace_back(htole16(handler));
1122 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301123
George Liu1244acf2020-08-14 09:11:11 +08001124 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1125
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001126 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301127 }
1128
1129 if (listOfHandles.size())
1130 {
1131#ifdef OEM_IBM
1132 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301133 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301134 if (rc != PLDM_SUCCESS)
1135 {
1136 return;
1137 }
1138#endif
George Liu1244acf2020-08-14 09:11:11 +08001139 }
1140}
1141
1142void BIOSConfig::listenPendingAttributes()
1143{
1144 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1145 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1146
1147 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001148 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001149 pldm::utils::DBusHandler::getBus(),
1150 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001151 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001152 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001153
Patrick Williams6da4f912023-05-10 07:50:53 -05001154 using Value =
1155 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1156 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001157
Patrick Williams6da4f912023-05-10 07:50:53 -05001158 Properties props{};
1159 std::string intf;
1160 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001161
Patrick Williams6da4f912023-05-10 07:50:53 -05001162 auto valPropMap = props.find(propertyName);
1163 if (valPropMap == props.end())
1164 {
1165 return;
1166 }
George Liu1244acf2020-08-14 09:11:11 +08001167
Patrick Williams6da4f912023-05-10 07:50:53 -05001168 PendingAttributes pendingAttributes =
1169 std::get<PendingAttributes>(valPropMap->second);
1170 this->constructPendingAttribute(pendingAttributes);
Patrick Williamsa6756622023-10-20 11:19:15 -05001171 });
George Liu1244acf2020-08-14 09:11:11 +08001172
1173 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1174}
1175
John Wangd9659342020-02-27 16:46:05 +08001176} // namespace bios
1177} // namespace responder
1178} // namespace pldm