blob: 6b1b91823135836269c82f28717eb4fdfce1fb52 [file] [log] [blame]
John Wangd9659342020-02-27 16:46:05 +08001#include "bios_config.hpp"
2
John Wang3be70852020-02-13 15:59:04 +08003#include "bios_enum_attribute.hpp"
John Wang95e6b3c2020-02-13 09:43:24 +08004#include "bios_integer_attribute.hpp"
John Wangd9659342020-02-27 16:46:05 +08005#include "bios_string_attribute.hpp"
Sampa Misra46ece062020-03-18 07:17:44 -05006#include "bios_table.hpp"
George Liu1b180d82020-07-23 14:01:58 +08007#include "common/bios_utils.hpp"
John Wangd9659342020-02-27 16:46:05 +08008
Riya Dixit49cfb132023-03-02 04:26:53 -06009#include <phosphor-logging/lg2.hpp>
George Liu1244acf2020-08-14 09:11:11 +080010#include <xyz/openbmc_project/BIOSConfig/Manager/server.hpp>
11
Archana Kakani62dd8ff2024-02-12 10:00:40 -060012#include <filesystem>
John Wangd9659342020-02-27 16:46:05 +080013#include <fstream>
John Wangd9659342020-02-27 16:46:05 +080014
Tom Joseph7f839f92020-09-21 10:20:44 +053015#ifdef OEM_IBM
16#include "oem/ibm/libpldmresponder/platform_oem_ibm.hpp"
17#endif
18
Riya Dixit49cfb132023-03-02 04:26:53 -060019PHOSPHOR_LOG2_USING;
20
Brad Bishop5079ac42021-08-19 18:35:06 -040021using namespace pldm::utils;
22
John Wangd9659342020-02-27 16:46:05 +080023namespace pldm
24{
25namespace responder
26{
27namespace bios
28{
29namespace
30{
George Liu1244acf2020-08-14 09:11:11 +080031using BIOSConfigManager =
32 sdbusplus::xyz::openbmc_project::BIOSConfig::server::Manager;
33
Archana Kakaniac713ee2024-05-20 01:27:53 -050034constexpr auto attributesJsonFile = "bios_attrs.json";
John Wangd9659342020-02-27 16:46:05 +080035
36constexpr auto stringTableFile = "stringTable";
37constexpr auto attrTableFile = "attributeTable";
38constexpr auto attrValueTableFile = "attributeValueTable";
39
40} // namespace
41
Sampa Misrac0c79482021-06-02 08:01:54 -050042BIOSConfig::BIOSConfig(
43 const char* jsonDir, const char* tableDir, DBusHandler* const dbusHandler,
Andrew Jeffery197033b2024-07-25 20:53:07 +093044 int /* fd */, uint8_t eid, pldm::InstanceIdDb* instanceIdDb,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050045 pldm::requester::Handler<pldm::requester::Request>* handler,
Archana Kakani62dd8ff2024-02-12 10:00:40 -060046 pldm::responder::platform_config::Handler* platformConfigHandler,
47 pldm::responder::bios::Callback requestPLDMServiceName) :
Patrick Williams16c2a0a2024-08-16 15:20:59 -040048 jsonDir(jsonDir), tableDir(tableDir), dbusHandler(dbusHandler), eid(eid),
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060049 instanceIdDb(instanceIdDb), handler(handler),
Archana Kakani62dd8ff2024-02-12 10:00:40 -060050 platformConfigHandler(platformConfigHandler),
51 requestPLDMServiceName(requestPLDMServiceName)
52{
53 fs::create_directories(tableDir);
54 removeTables();
Archana Kakani46f352e2024-03-17 08:21:08 -050055
56#ifdef SYSTEM_SPECIFIC_BIOS_JSON
57 checkSystemTypeAvailability();
58#else
59 initBIOSAttributes(sysType, false);
60#endif
61
Archana Kakani62dd8ff2024-02-12 10:00:40 -060062 listenPendingAttributes();
63}
Tom Joseph7f839f92020-09-21 10:20:44 +053064
Archana Kakani46f352e2024-03-17 08:21:08 -050065void BIOSConfig::checkSystemTypeAvailability()
John Wangd9659342020-02-27 16:46:05 +080066{
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060067 if (platformConfigHandler)
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050068 {
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060069 auto systemType = platformConfigHandler->getPlatformName();
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050070 if (systemType.has_value())
71 {
Archana Kakani46f352e2024-03-17 08:21:08 -050072 // Received System Type from Entity Manager
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050073 sysType = systemType.value();
Archana Kakani46f352e2024-03-17 08:21:08 -050074 initBIOSAttributes(sysType, true);
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050075 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060076 else
77 {
Archana Kakani46f352e2024-03-17 08:21:08 -050078 platformConfigHandler->registerSystemTypeCallback(
79 std::bind(&BIOSConfig::initBIOSAttributes, this,
80 std::placeholders::_1, std::placeholders::_2));
Archana Kakani62dd8ff2024-02-12 10:00:40 -060081 }
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050082 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060083}
84
Archana Kakani46f352e2024-03-17 08:21:08 -050085void BIOSConfig::initBIOSAttributes(const std::string& systemType,
86 bool registerService)
Archana Kakani62dd8ff2024-02-12 10:00:40 -060087{
88 sysType = systemType;
89 fs::path dir{jsonDir / sysType};
90 if (!fs::exists(dir))
91 {
92 error("System specific bios attribute directory {DIR} does not exit",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050093 "DIR", dir);
Thu Nguyen3f5a9692024-07-16 13:16:54 +000094 if (registerService)
95 {
96 requestPLDMServiceName();
97 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060098 return;
99 }
John Wangd9659342020-02-27 16:46:05 +0800100 constructAttributes();
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600101 buildTables();
Archana Kakani46f352e2024-03-17 08:21:08 -0500102 if (registerService)
103 {
104 requestPLDMServiceName();
105 }
John Wangd9659342020-02-27 16:46:05 +0800106}
107
108void BIOSConfig::buildTables()
109{
John Wangd9659342020-02-27 16:46:05 +0800110 auto stringTable = buildAndStoreStringTable();
111 if (stringTable)
112 {
113 buildAndStoreAttrTables(*stringTable);
114 }
115}
116
117std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
118{
119 fs::path tablePath;
120 switch (tableType)
121 {
122 case PLDM_BIOS_STRING_TABLE:
123 tablePath = tableDir / stringTableFile;
124 break;
125 case PLDM_BIOS_ATTR_TABLE:
126 tablePath = tableDir / attrTableFile;
127 break;
128 case PLDM_BIOS_ATTR_VAL_TABLE:
129 tablePath = tableDir / attrValueTableFile;
130 break;
131 }
132 return loadTable(tablePath);
133}
134
Tom Joseph7f839f92020-09-21 10:20:44 +0530135int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table,
136 bool updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800137{
138 fs::path stringTablePath(tableDir / stringTableFile);
139 fs::path attrTablePath(tableDir / attrTableFile);
140 fs::path attrValueTablePath(tableDir / attrValueTableFile);
141
142 if (!pldm_bios_table_checksum(table.data(), table.size()))
143 {
144 return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
145 }
146
147 if (tableType == PLDM_BIOS_STRING_TABLE)
148 {
149 storeTable(stringTablePath, table);
150 }
151 else if (tableType == PLDM_BIOS_ATTR_TABLE)
152 {
153 BIOSTable biosStringTable(stringTablePath.c_str());
154 if (biosStringTable.isEmpty())
155 {
156 return PLDM_INVALID_BIOS_TABLE_TYPE;
157 }
158
159 auto rc = checkAttributeTable(table);
160 if (rc != PLDM_SUCCESS)
161 {
162 return rc;
163 }
164
165 storeTable(attrTablePath, table);
166 }
167 else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
168 {
169 BIOSTable biosStringTable(stringTablePath.c_str());
170 BIOSTable biosStringValueTable(attrTablePath.c_str());
171 if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
172 {
173 return PLDM_INVALID_BIOS_TABLE_TYPE;
174 }
175
176 auto rc = checkAttributeValueTable(table);
177 if (rc != PLDM_SUCCESS)
178 {
179 return rc;
180 }
181
182 storeTable(attrValueTablePath, table);
George Liu1b180d82020-07-23 14:01:58 +0800183 }
184 else
185 {
186 return PLDM_INVALID_BIOS_TABLE_TYPE;
187 }
188
Tom Joseph7f839f92020-09-21 10:20:44 +0530189 if ((tableType == PLDM_BIOS_ATTR_VAL_TABLE) && updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800190 {
George Liu1b180d82020-07-23 14:01:58 +0800191 updateBaseBIOSTableProperty();
192 }
193
194 return PLDM_SUCCESS;
195}
196
197int BIOSConfig::checkAttributeTable(const Table& table)
198{
199 using namespace pldm::bios::utils;
200 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
201 for (auto entry :
202 BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
203 {
204 auto attrNameHandle =
205 pldm_bios_table_attr_entry_decode_string_handle(entry);
206
207 auto stringEnty = pldm_bios_table_string_find_by_handle(
208 stringTable->data(), stringTable->size(), attrNameHandle);
209 if (stringEnty == nullptr)
210 {
211 return PLDM_INVALID_BIOS_ATTR_HANDLE;
212 }
213
214 auto attrType = static_cast<pldm_bios_attribute_type>(
215 pldm_bios_table_attr_entry_decode_attribute_type(entry));
216
217 switch (attrType)
218 {
219 case PLDM_BIOS_ENUMERATION:
220 case PLDM_BIOS_ENUMERATION_READ_ONLY:
221 {
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930222 uint8_t pvNum;
223 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000224 pldm_bios_table_attr_entry_enum_decode_pv_num(entry, &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
Andrew Jeffery24611052024-08-01 13:15:36 +0000227 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
George Liu1b180d82020-07-23 14:01:58 +0800228 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930229 uint8_t defNum;
Andrew Jefferyff3fb9e2024-08-01 13:15:36 +0000230 pldm_bios_table_attr_entry_enum_decode_def_num(entry, &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800231 std::vector<uint8_t> defIndices(defNum);
232 pldm_bios_table_attr_entry_enum_decode_def_indices(
233 entry, defIndices.data(), defIndices.size());
234
235 for (size_t i = 0; i < pvHandls.size(); i++)
236 {
237 auto stringEntry = pldm_bios_table_string_find_by_handle(
238 stringTable->data(), stringTable->size(), pvHandls[i]);
239 if (stringEntry == nullptr)
240 {
241 return PLDM_INVALID_BIOS_ATTR_HANDLE;
242 }
243 }
244
245 for (size_t i = 0; i < defIndices.size(); i++)
246 {
247 auto stringEntry = pldm_bios_table_string_find_by_handle(
248 stringTable->data(), stringTable->size(),
249 pvHandls[defIndices[i]]);
250 if (stringEntry == nullptr)
251 {
252 return PLDM_INVALID_BIOS_ATTR_HANDLE;
253 }
254 }
255 break;
256 }
257 case PLDM_BIOS_INTEGER:
258 case PLDM_BIOS_INTEGER_READ_ONLY:
259 case PLDM_BIOS_STRING:
260 case PLDM_BIOS_STRING_READ_ONLY:
261 case PLDM_BIOS_PASSWORD:
262 case PLDM_BIOS_PASSWORD_READ_ONLY:
263 break;
264 default:
265 return PLDM_INVALID_BIOS_ATTR_HANDLE;
266 }
267 }
268
269 return PLDM_SUCCESS;
270}
271
272int BIOSConfig::checkAttributeValueTable(const Table& table)
273{
274 using namespace pldm::bios::utils;
275 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
276 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
277
278 baseBIOSTableMaps.clear();
279
280 for (auto tableEntry :
281 BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(table.data(), table.size()))
282 {
283 AttributeName attributeName{};
284 AttributeType attributeType{};
285 ReadonlyStatus readonlyStatus{};
286 DisplayName displayName{};
287 Description description{};
288 MenuPath menuPath{};
289 CurrentValue currentValue{};
290 DefaultValue defaultValue{};
Sagar Srinivas7927f902023-10-09 07:53:00 -0500291 std::vector<ValueDisplayName> valueDisplayNames;
292 std::map<uint16_t, std::vector<std::string>> valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800293 Option options{};
294
295 auto attrValueHandle =
296 pldm_bios_table_attr_value_entry_decode_attribute_handle(
297 tableEntry);
298 auto attrType = static_cast<pldm_bios_attribute_type>(
299 pldm_bios_table_attr_value_entry_decode_attribute_type(tableEntry));
300
301 auto attrEntry = pldm_bios_table_attr_find_by_handle(
302 attrTable->data(), attrTable->size(), attrValueHandle);
303 if (attrEntry == nullptr)
304 {
305 return PLDM_INVALID_BIOS_ATTR_HANDLE;
306 }
307 auto attrHandle =
308 pldm_bios_table_attr_entry_decode_attribute_handle(attrEntry);
309 auto attrNameHandle =
310 pldm_bios_table_attr_entry_decode_string_handle(attrEntry);
311
312 auto stringEntry = pldm_bios_table_string_find_by_handle(
313 stringTable->data(), stringTable->size(), attrNameHandle);
314 if (stringEntry == nullptr)
315 {
316 return PLDM_INVALID_BIOS_ATTR_HANDLE;
317 }
318 auto strLength =
319 pldm_bios_table_string_entry_decode_string_length(stringEntry);
320 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930321 // Preconditions are upheld therefore no error check necessary
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000322 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
323 buffer.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930324
George Liu1b180d82020-07-23 14:01:58 +0800325 attributeName = std::string(buffer.data(), buffer.data() + strLength);
326
327 if (!biosAttributes.empty())
328 {
329 readonlyStatus =
George Liub1fbeec2020-09-04 09:59:46 +0800330 biosAttributes[attrHandle % biosAttributes.size()]->readOnly;
George Liu92bb4022020-09-03 14:58:24 +0800331 description =
332 biosAttributes[attrHandle % biosAttributes.size()]->helpText;
333 displayName =
334 biosAttributes[attrHandle % biosAttributes.size()]->displayName;
Sagar Srinivas7927f902023-10-09 07:53:00 -0500335 valueDisplayNamesMap =
336 biosAttributes[attrHandle % biosAttributes.size()]
337 ->valueDisplayNamesMap;
George Liu1b180d82020-07-23 14:01:58 +0800338 }
339
340 switch (attrType)
341 {
342 case PLDM_BIOS_ENUMERATION:
343 case PLDM_BIOS_ENUMERATION_READ_ONLY:
344 {
Sagar Srinivas7927f902023-10-09 07:53:00 -0500345 if (valueDisplayNamesMap.contains(attrHandle))
346 {
347 const std::vector<ValueDisplayName>& vdn =
348 valueDisplayNamesMap[attrHandle];
349 valueDisplayNames.insert(valueDisplayNames.end(),
350 vdn.begin(), vdn.end());
351 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400352 auto getValue =
353 [](uint16_t handle, const Table& table) -> std::string {
George Liu1b180d82020-07-23 14:01:58 +0800354 auto stringEntry = pldm_bios_table_string_find_by_handle(
355 table.data(), table.size(), handle);
356
357 auto strLength =
358 pldm_bios_table_string_entry_decode_string_length(
359 stringEntry);
360 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930361 // Preconditions are upheld therefore no error check
362 // necessary
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000363 pldm_bios_table_string_entry_decode_string(
George Liu1b180d82020-07-23 14:01:58 +0800364 stringEntry, buffer.data(), buffer.size());
365
366 return std::string(buffer.data(),
367 buffer.data() + strLength);
368 };
369
370 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
371 "AttributeType.Enumeration";
372
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930373 uint8_t pvNum;
374 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000375 pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry,
376 &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800377 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930378 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery24611052024-08-01 13:15:36 +0000379 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
George Liu1b180d82020-07-23 14:01:58 +0800380 attrEntry, pvHandls.data(), pvHandls.size());
381
382 // get possible_value
383 for (size_t i = 0; i < pvHandls.size(); i++)
384 {
385 options.push_back(
386 std::make_tuple("xyz.openbmc_project.BIOSConfig."
387 "Manager.BoundType.OneOf",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500388 getValue(pvHandls[i], *stringTable),
389 valueDisplayNames[i]));
George Liu1b180d82020-07-23 14:01:58 +0800390 }
391
392 auto count =
393 pldm_bios_table_attr_value_entry_enum_decode_number(
394 tableEntry);
395 std::vector<uint8_t> handles(count);
396 pldm_bios_table_attr_value_entry_enum_decode_handles(
397 tableEntry, handles.data(), handles.size());
398
399 // get current_value
400 for (size_t i = 0; i < handles.size(); i++)
401 {
402 currentValue = getValue(pvHandls[handles[i]], *stringTable);
403 }
404
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930405 uint8_t defNum;
406 // Preconditions are upheld therefore no error check necessary
Andrew Jefferyff3fb9e2024-08-01 13:15:36 +0000407 pldm_bios_table_attr_entry_enum_decode_def_num(attrEntry,
408 &defNum);
George Liu1b180d82020-07-23 14:01:58 +0800409 std::vector<uint8_t> defIndices(defNum);
410 pldm_bios_table_attr_entry_enum_decode_def_indices(
411 attrEntry, defIndices.data(), defIndices.size());
412
413 // get default_value
414 for (size_t i = 0; i < defIndices.size(); i++)
415 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400416 defaultValue =
417 getValue(pvHandls[defIndices[i]], *stringTable);
George Liu1b180d82020-07-23 14:01:58 +0800418 }
419
420 break;
421 }
422 case PLDM_BIOS_INTEGER:
423 case PLDM_BIOS_INTEGER_READ_ONLY:
424 {
425 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
426 "AttributeType.Integer";
427 currentValue = static_cast<int64_t>(
428 pldm_bios_table_attr_value_entry_integer_decode_cv(
429 tableEntry));
430
431 uint64_t lower, upper, def;
432 uint32_t scalar;
433 pldm_bios_table_attr_entry_integer_decode(
434 attrEntry, &lower, &upper, &scalar, &def);
Sagar Srinivas7927f902023-10-09 07:53:00 -0500435 options.push_back(std::make_tuple(
436 "xyz.openbmc_project.BIOSConfig.Manager."
437 "BoundType.LowerBound",
438 static_cast<int64_t>(lower), attributeName));
439 options.push_back(std::make_tuple(
440 "xyz.openbmc_project.BIOSConfig.Manager."
441 "BoundType.UpperBound",
442 static_cast<int64_t>(upper), attributeName));
443 options.push_back(std::make_tuple(
444 "xyz.openbmc_project.BIOSConfig.Manager."
445 "BoundType.ScalarIncrement",
446 static_cast<int64_t>(scalar), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800447 defaultValue = static_cast<int64_t>(def);
448 break;
449 }
450 case PLDM_BIOS_STRING:
451 case PLDM_BIOS_STRING_READ_ONLY:
452 {
453 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
454 "AttributeType.String";
455 variable_field currentString;
456 pldm_bios_table_attr_value_entry_string_decode_string(
457 tableEntry, &currentString);
458 currentValue = std::string(
459 reinterpret_cast<const char*>(currentString.ptr),
460 currentString.length);
461 auto min = pldm_bios_table_attr_entry_string_decode_min_length(
462 attrEntry);
463 auto max = pldm_bios_table_attr_entry_string_decode_max_length(
464 attrEntry);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930465 uint16_t def;
466 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery53e342a2024-08-01 13:15:36 +0000467 pldm_bios_table_attr_entry_string_decode_def_string_length(
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930468 attrEntry, &def);
George Liu1b180d82020-07-23 14:01:58 +0800469 std::vector<char> defString(def + 1);
470 pldm_bios_table_attr_entry_string_decode_def_string(
471 attrEntry, defString.data(), defString.size());
472 options.push_back(
473 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
474 "BoundType.MinStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500475 static_cast<int64_t>(min), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800476 options.push_back(
477 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
478 "BoundType.MaxStringLength",
Sagar Srinivas7927f902023-10-09 07:53:00 -0500479 static_cast<int64_t>(max), attributeName));
George Liu1b180d82020-07-23 14:01:58 +0800480 defaultValue = defString.data();
481 break;
482 }
483 case PLDM_BIOS_PASSWORD:
484 case PLDM_BIOS_PASSWORD_READ_ONLY:
485 {
486 attributeType = "xyz.openbmc_project.BIOSConfig.Manager."
487 "AttributeType.Password";
488 break;
489 }
490 default:
491 return PLDM_INVALID_BIOS_ATTR_HANDLE;
492 }
493 baseBIOSTableMaps.emplace(
494 std::move(attributeName),
495 std::make_tuple(attributeType, readonlyStatus, displayName,
496 description, menuPath, currentValue, defaultValue,
497 std::move(options)));
498 }
499
500 return PLDM_SUCCESS;
501}
502
503void BIOSConfig::updateBaseBIOSTableProperty()
504{
505 constexpr static auto biosConfigPath =
506 "/xyz/openbmc_project/bios_config/manager";
507 constexpr static auto biosConfigInterface =
508 "xyz.openbmc_project.BIOSConfig.Manager";
509 constexpr static auto biosConfigPropertyName = "BaseBIOSTable";
510 constexpr static auto dbusProperties = "org.freedesktop.DBus.Properties";
511
512 if (baseBIOSTableMaps.empty())
513 {
514 return;
515 }
516
517 try
518 {
519 auto& bus = dbusHandler->getBus();
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400520 auto service =
521 dbusHandler->getService(biosConfigPath, biosConfigInterface);
George Liu1b180d82020-07-23 14:01:58 +0800522 auto method = bus.new_method_call(service.c_str(), biosConfigPath,
523 dbusProperties, "Set");
524 std::variant<BaseBIOSTable> value = baseBIOSTableMaps;
Archana Kakani97a0f482025-03-10 05:39:38 -0500525 if (oemBiosHandler)
526 {
527 oemBiosHandler->processOEMBaseBiosTable(baseBIOSTableMaps);
528 }
George Liu1b180d82020-07-23 14:01:58 +0800529 method.append(biosConfigInterface, biosConfigPropertyName, value);
vkaverap@in.ibm.com5b71b862023-08-21 05:19:04 +0000530 bus.call_noreply(method, dbusTimeout);
George Liu1b180d82020-07-23 14:01:58 +0800531 }
532 catch (const std::exception& e)
533 {
Riya Dixit89644442024-03-31 05:39:59 -0500534 error("Failed to update BaseBIOSTable property, error - {ERROR}",
535 "ERROR", e);
George Liu1b180d82020-07-23 14:01:58 +0800536 }
537}
538
John Wangd9659342020-02-27 16:46:05 +0800539void BIOSConfig::constructAttributes()
540{
Archana Kakaniac713ee2024-05-20 01:27:53 -0500541 info("Bios Attribute file path: {PATH}", "PATH",
542 (jsonDir / sysType / attributesJsonFile));
543 load(jsonDir / sysType / attributesJsonFile, [this](const Json& entry) {
544 std::string attrType = entry.at("attribute_type");
545 if (attrType == "string")
546 {
547 constructAttribute<BIOSStringAttribute>(entry);
548 }
549 else if (attrType == "integer")
550 {
551 constructAttribute<BIOSIntegerAttribute>(entry);
552 }
553 else if (attrType == "enum")
554 {
555 constructAttribute<BIOSEnumAttribute>(entry);
556 }
John Wang3be70852020-02-13 15:59:04 +0800557 });
John Wangd9659342020-02-27 16:46:05 +0800558}
559
560void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
561{
562 BIOSStringTable biosStringTable(stringTable);
563
564 if (biosAttributes.empty())
565 {
566 return;
567 }
568
Tom Josephca7b2522020-11-18 12:27:11 +0530569 BaseBIOSTable biosTable{};
570 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
571 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
572
573 try
574 {
575 auto& bus = dbusHandler->getBus();
576 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400577 auto method =
578 bus.new_method_call(service.c_str(), biosObjPath,
579 "org.freedesktop.DBus.Properties", "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530580 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500581 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530582 std::variant<BaseBIOSTable> varBiosTable{};
583 reply.read(varBiosTable);
584 biosTable = std::get<BaseBIOSTable>(varBiosTable);
585 }
586 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
587 // default values populated from the BIOS JSONs to keep PLDM and
588 // bios-settings-manager in sync
589 catch (const std::exception& e)
590 {
Riya Dixit89644442024-03-31 05:39:59 -0500591 error("Failed to read BaseBIOSTable property, error - {ERROR}", "ERROR",
592 e);
Tom Josephca7b2522020-11-18 12:27:11 +0530593 }
594
John Wangd9659342020-02-27 16:46:05 +0800595 Table attrTable, attrValueTable;
596
597 for (auto& attr : biosAttributes)
598 {
599 try
600 {
Tom Josephca7b2522020-11-18 12:27:11 +0530601 auto iter = biosTable.find(attr->name);
602 if (iter == biosTable.end())
603 {
604 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
605 std::nullopt);
606 }
607 else
608 {
609 attr->constructEntry(
610 biosStringTable, attrTable, attrValueTable,
611 std::get<static_cast<uint8_t>(Index::currentValue)>(
612 iter->second));
613 }
John Wangd9659342020-02-27 16:46:05 +0800614 }
615 catch (const std::exception& e)
616 {
Riya Dixit89644442024-03-31 05:39:59 -0500617 error(
618 "Failed to construct table entry for attribute '{ATTRIBUTE}', error - {ERROR}",
619 "ATTRIBUTE", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800620 }
621 }
622
623 table::appendPadAndChecksum(attrTable);
624 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800625 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
626 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800627}
628
629std::optional<Table> BIOSConfig::buildAndStoreStringTable()
630{
631 std::set<std::string> strings;
Archana Kakaniac713ee2024-05-20 01:27:53 -0500632 load(jsonDir / sysType / attributesJsonFile, [&strings](const Json& entry) {
633 if (entry.at("attribute_type") == "enum")
John Wangd9659342020-02-27 16:46:05 +0800634 {
Archana Kakaniac713ee2024-05-20 01:27:53 -0500635 strings.emplace(entry.at("attribute_name"));
636 auto possibleValues = entry.at("possible_values");
637 for (auto& pv : possibleValues)
638 {
639 strings.emplace(pv);
640 }
641 }
642 else
643 {
644 strings.emplace(entry.at("attribute_name"));
John Wangd9659342020-02-27 16:46:05 +0800645 }
646 });
647
648 if (strings.empty())
649 {
650 return std::nullopt;
651 }
652
653 Table table;
654 for (const auto& elem : strings)
655 {
656 table::string::constructEntry(table, elem);
657 }
658
659 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800660 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800661 return table;
662}
663
664void BIOSConfig::storeTable(const fs::path& path, const Table& table)
665{
666 BIOSTable biosTable(path.c_str());
667 biosTable.store(table);
668}
669
670std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
671{
672 BIOSTable biosTable(path.c_str());
673 if (biosTable.isEmpty())
674 {
675 return std::nullopt;
676 }
677
678 Table table;
679 biosTable.load(table);
680 return table;
681}
682
683void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
684{
685 std::ifstream file;
686 Json jsonConf;
687 if (fs::exists(filePath))
688 {
689 try
690 {
691 file.open(filePath);
692 jsonConf = Json::parse(file);
693 auto entries = jsonConf.at("entries");
694 for (auto& entry : entries)
695 {
696 try
697 {
698 handler(entry);
699 }
700 catch (const std::exception& e)
701 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600702 error(
Riya Dixit89644442024-03-31 05:39:59 -0500703 "Failed to parse JSON config file at path '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500704 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800705 }
706 }
707 }
708 catch (const std::exception& e)
709 {
Riya Dixit89644442024-03-31 05:39:59 -0500710 error("Failed to parse JSON config file '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500711 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800712 }
713 }
714}
715
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600716std::string BIOSConfig::decodeStringFromStringEntry(
717 const pldm_bios_string_table_entry* stringEntry)
718{
719 auto strLength =
720 pldm_bios_table_string_entry_decode_string_length(stringEntry);
721 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930722 // Preconditions are upheld therefore no error check necessary
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000723 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
724 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600725 return std::string(buffer.data(), buffer.data() + strLength);
726}
727
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400728std::string BIOSConfig::displayStringHandle(
729 uint16_t handle, uint8_t index, const std::optional<Table>& attrTable,
730 const std::optional<Table>& stringTable)
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600731{
732 auto attrEntry = pldm_bios_table_attr_find_by_handle(
733 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930734 uint8_t pvNum;
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000735 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry, &pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930736 if (rc != PLDM_SUCCESS)
737 {
738 error(
Riya Dixit89644442024-03-31 05:39:59 -0500739 "Failed to decode BIOS table possible values for attribute entry, response code '{RC}'",
740 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930741 throw std::runtime_error(
742 "Failed to decode BIOS table possible values for attribute entry");
743 }
744
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600745 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930746 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery24611052024-08-01 13:15:36 +0000747 pldm_bios_table_attr_entry_enum_decode_pv_hdls(attrEntry, pvHandls.data(),
748 pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600749
750 std::string displayString = std::to_string(pvHandls[index]);
751
752 auto stringEntry = pldm_bios_table_string_find_by_handle(
753 stringTable->data(), stringTable->size(), pvHandls[index]);
754
755 auto decodedStr = decodeStringFromStringEntry(stringEntry);
756
757 return decodedStr + "(" + displayString + ")";
758}
759
760void BIOSConfig::traceBIOSUpdate(
761 const pldm_bios_attr_val_table_entry* attrValueEntry,
762 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
763{
764 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
765 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
766
Patrick Williams6da4f912023-05-10 07:50:53 -0500767 auto [attrHandle,
768 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600769
770 auto attrHeader = table::attribute::decodeHeader(attrEntry);
771 BIOSStringTable biosStringTable(*stringTable);
772 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
773
774 switch (attrType)
775 {
776 case PLDM_BIOS_ENUMERATION:
777 case PLDM_BIOS_ENUMERATION_READ_ONLY:
778 {
779 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
780 attrValueEntry);
781 std::vector<uint8_t> handles(count);
782 pldm_bios_table_attr_value_entry_enum_decode_handles(
783 attrValueEntry, handles.data(), handles.size());
784
785 for (uint8_t handle : handles)
786 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600787 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
788 stringTable);
789 auto chkBMC = isBMC ? "true" : "false";
790 info(
Riya Dixit89644442024-03-31 05:39:59 -0500791 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
792 "ATTRIBUTE", attrName, "VALUE", nwVal, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600793 }
794 break;
795 }
796 case PLDM_BIOS_INTEGER:
797 case PLDM_BIOS_INTEGER_READ_ONLY:
798 {
799 auto value =
800 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600801 auto chkBMC = isBMC ? "true" : "false";
802 info(
Riya Dixit89644442024-03-31 05:39:59 -0500803 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
804 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600805 break;
806 }
807 case PLDM_BIOS_STRING:
808 case PLDM_BIOS_STRING_READ_ONLY:
809 {
810 auto value =
811 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600812 auto chkBMC = isBMC ? "true" : "false";
813 info(
Riya Dixit89644442024-03-31 05:39:59 -0500814 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
815 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600816 break;
817 }
818 default:
819 break;
820 };
821}
822
John Wang8241b342020-06-05 10:49:17 +0800823int BIOSConfig::checkAttrValueToUpdate(
824 const pldm_bios_attr_val_table_entry* attrValueEntry,
825 const pldm_bios_attr_table_entry* attrEntry, Table&)
826
827{
Patrick Williams6da4f912023-05-10 07:50:53 -0500828 auto [attrHandle,
829 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800830
831 switch (attrType)
832 {
833 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800834 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800835 {
836 auto value =
837 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500838 auto [pvHdls,
839 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600840 if (!(value.size() == 1))
841 {
842 return PLDM_ERROR_INVALID_LENGTH;
843 }
John Wang8241b342020-06-05 10:49:17 +0800844 if (value[0] >= pvHdls.size())
845 {
Riya Dixit89644442024-03-31 05:39:59 -0500846 error(
847 "Invalid index '{INDEX}' encountered for Enum type BIOS attribute",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500848 "INDEX", value[0]);
John Wang8241b342020-06-05 10:49:17 +0800849 return PLDM_ERROR_INVALID_DATA;
850 }
John Wang8241b342020-06-05 10:49:17 +0800851 return PLDM_SUCCESS;
852 }
853 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800854 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800855 {
856 auto value =
857 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500858 auto [lower, upper, scalar,
859 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800860
861 if (value < lower || value > upper)
862 {
Riya Dixit89644442024-03-31 05:39:59 -0500863 error(
864 "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}'.",
865 "ATTRIBUTE_VALUE", value, "LOWER", lower, "UPPER", upper,
866 "SCALAR", scalar);
John Wang8241b342020-06-05 10:49:17 +0800867 return PLDM_ERROR_INVALID_DATA;
868 }
869 return PLDM_SUCCESS;
870 }
871 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800872 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800873 {
874 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
875 auto value =
876 table::attribute_value::decodeStringEntry(attrValueEntry);
877 if (value.size() < stringConf.minLength ||
878 value.size() > stringConf.maxLength)
879 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600880 error(
Riya Dixit89644442024-03-31 05:39:59 -0500881 "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}'",
882 "ATTRIBUTE_VALUE", value, "LENGTH", value.size(), "MIN_LEN",
883 stringConf.minLength, "MAX_LEN", stringConf.maxLength);
John Wang8241b342020-06-05 10:49:17 +0800884 return PLDM_ERROR_INVALID_LENGTH;
885 }
886 return PLDM_SUCCESS;
887 }
888 default:
Riya Dixit89644442024-03-31 05:39:59 -0500889 error("ReadOnly or Unsupported type '{TYPE}'", "TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800890 return PLDM_ERROR;
891 };
892}
893
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600894int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
895 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800896{
897 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
898 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
899 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
900 if (!attrValueTable || !attrTable || !stringTable)
901 {
902 return PLDM_BIOS_TABLE_UNAVAILABLE;
903 }
904
John Wangd9659342020-02-27 16:46:05 +0800905 auto attrValueEntry =
906 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
907
908 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
909
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400910 auto attrEntry =
911 table::attribute::findByHandle(*attrTable, attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800912 if (!attrEntry)
913 {
914 return PLDM_ERROR;
915 }
916
John Wang8241b342020-06-05 10:49:17 +0800917 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
918 if (rc != PLDM_SUCCESS)
919 {
920 return rc;
921 }
922
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400923 auto destTable =
924 table::attribute_value::updateTable(*attrValueTable, entry, size);
John Wang8241b342020-06-05 10:49:17 +0800925
926 if (!destTable)
927 {
928 return PLDM_ERROR;
929 }
930
John Wangd9659342020-02-27 16:46:05 +0800931 try
932 {
933 auto attrHeader = table::attribute::decodeHeader(attrEntry);
934
935 BIOSStringTable biosStringTable(*stringTable);
936 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500937 auto iter = std::find_if(
938 biosAttributes.begin(), biosAttributes.end(),
939 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800940
941 if (iter == biosAttributes.end())
942 {
943 return PLDM_ERROR;
944 }
George Liu6d6d1e82021-02-16 11:08:55 +0800945 if (updateDBus)
946 {
947 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
948 biosStringTable);
949 }
John Wangd9659342020-02-27 16:46:05 +0800950 }
951 catch (const std::exception& e)
952 {
Riya Dixit89644442024-03-31 05:39:59 -0500953 error("Set attribute value error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800954 return PLDM_ERROR;
955 }
956
Tom Joseph7f839f92020-09-21 10:20:44 +0530957 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800958
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600959 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
960
John Wangd9659342020-02-27 16:46:05 +0800961 return PLDM_SUCCESS;
962}
963
964void BIOSConfig::removeTables()
965{
966 try
967 {
968 fs::remove(tableDir / stringTableFile);
969 fs::remove(tableDir / attrTableFile);
970 fs::remove(tableDir / attrValueTableFile);
971 }
972 catch (const std::exception& e)
973 {
Riya Dixit89644442024-03-31 05:39:59 -0500974 error("Remove the tables error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800975 }
976}
977
Sampa Misra46ece062020-03-18 07:17:44 -0500978void BIOSConfig::processBiosAttrChangeNotification(
979 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
980{
981 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
982 const auto& propertyName = dBusMap->propertyName;
983 const auto& attrName = biosAttributes[biosAttrIndex]->name;
984
985 const auto it = chProperties.find(propertyName);
986 if (it == chProperties.end())
987 {
988 return;
989 }
990
991 PropertyValue newPropVal = it->second;
992 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
993 if (!stringTable.has_value())
994 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600995 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500996 return;
997 }
998 BIOSStringTable biosStringTable(*stringTable);
999 uint16_t attrNameHdl{};
1000 try
1001 {
1002 attrNameHdl = biosStringTable.findHandle(attrName);
1003 }
Patrick Williams51330582021-10-06 12:48:56 -05001004 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -05001005 {
Riya Dixit89644442024-03-31 05:39:59 -05001006 error(
1007 "Missing handle for attribute '{ATTRIBUTE}' in BIOS String Table, error - '{ERROR}'",
1008 "ATTRIBUTE", attrName, "ERROR", e);
Sampa Misra46ece062020-03-18 07:17:44 -05001009 return;
1010 }
1011
1012 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1013 if (!attrTable.has_value())
1014 {
Riya Dixit89644442024-03-31 05:39:59 -05001015 error("BIOS Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001016 return;
1017 }
1018 const struct pldm_bios_attr_table_entry* tableEntry =
1019 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
1020 if (tableEntry == nullptr)
1021 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001022 error(
Riya Dixit89644442024-03-31 05:39:59 -05001023 "Failed to find attribute {ATTRIBUTE} in BIOS Attribute table with attribute handle '{ATTR_HANDLE}'",
1024 "ATTRIBUTE", attrName, "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -05001025 return;
1026 }
1027
Patrick Williams6da4f912023-05-10 07:50:53 -05001028 auto [attrHdl, attrType,
1029 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -05001030
1031 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
1032
1033 if (!attrValueSrcTable.has_value())
1034 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001035 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001036 return;
1037 }
1038
1039 Table newValue;
1040 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
1041 newValue, attrHdl, attrType, newPropVal);
1042 if (rc != PLDM_SUCCESS)
1043 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001044 error(
Riya Dixit89644442024-03-31 05:39:59 -05001045 "Failed to update the attribute value table for attribute handle '{ATTR_HANDLE}' and attribute type '{TYPE}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -05001046 "ATTR_HANDLE", attrHdl, "TYPE", attrType);
Sampa Misra46ece062020-03-18 07:17:44 -05001047 return;
1048 }
1049 auto destTable = table::attribute_value::updateTable(
1050 *attrValueSrcTable, newValue.data(), newValue.size());
1051 if (destTable.has_value())
1052 {
1053 storeTable(tableDir / attrValueTableFile, *destTable);
1054 }
Sampa Misra0f262332021-02-15 00:13:51 -06001055
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001056 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001057 if (rc != PLDM_SUCCESS)
1058 {
Riya Dixit89644442024-03-31 05:39:59 -05001059 error(
1060 "Failed to setAttrValue on base bios table and dbus, response code '{RC}'",
1061 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001062 }
Sampa Misra46ece062020-03-18 07:17:44 -05001063}
1064
George Liu1244acf2020-08-14 09:11:11 +08001065uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1066{
1067 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1068 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1069
1070 BIOSStringTable biosStringTable(*stringTable);
1071 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1072 attrTable->data(), attrTable->size());
1073 auto stringHandle = biosStringTable.findHandle(attrName);
1074
1075 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1076 attrTable->data(), attrTable->size()))
1077 {
1078 auto header = table::attribute::decodeHeader(entry);
1079 if (header.stringHandle == stringHandle)
1080 {
1081 return header.attrHandle;
1082 }
1083 }
1084
Manojkiran Eda2576aec2024-06-17 12:05:17 +05301085 throw std::invalid_argument("Unknown attribute Name");
George Liu1244acf2020-08-14 09:11:11 +08001086}
1087
1088void BIOSConfig::constructPendingAttribute(
1089 const PendingAttributes& pendingAttributes)
1090{
Tom Joseph7f839f92020-09-21 10:20:44 +05301091 std::vector<uint16_t> listOfHandles{};
1092
George Liu1244acf2020-08-14 09:11:11 +08001093 for (auto& attribute : pendingAttributes)
1094 {
1095 std::string attributeName = attribute.first;
1096 auto& [attributeType, attributevalue] = attribute.second;
1097
1098 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1099 [&attributeName](const auto& attr) {
Patrick Williams16c2a0a2024-08-16 15:20:59 -04001100 return attr->name == attributeName;
1101 });
George Liu1244acf2020-08-14 09:11:11 +08001102
1103 if (iter == biosAttributes.end())
1104 {
Riya Dixit89644442024-03-31 05:39:59 -05001105 error("Wrong attribute name {NAME}", "NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001106 continue;
1107 }
1108
1109 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
Pavithra Barithaya677a4552025-01-31 10:33:39 +05301110 auto entry = new (attrValueEntry.data()) pldm_bios_attr_val_table_entry;
George Liu1244acf2020-08-14 09:11:11 +08001111
1112 auto handler = findAttrHandle(attributeName);
1113 auto type =
1114 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1115
1116 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1117 type != BIOSConfigManager::AttributeType::String &&
1118 type != BIOSConfigManager::AttributeType::Integer)
1119 {
Riya Dixit89644442024-03-31 05:39:59 -05001120 error("Attribute type '{TYPE}' not supported", "TYPE",
1121 attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001122 continue;
1123 }
1124
George Liu4876c542022-06-08 15:59:54 +08001125 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001126 menuPath, currentValue, defaultValue,
1127 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001128
George Liu1244acf2020-08-14 09:11:11 +08001129 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001130
1131 // Need to verify that the current value has really changed
1132 if (attributeType == attrType && attributevalue != currentValue)
1133 {
1134 listOfHandles.emplace_back(htole16(handler));
1135 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301136
George Liu1244acf2020-08-14 09:11:11 +08001137 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1138
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001139 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301140 }
1141
1142 if (listOfHandles.size())
1143 {
1144#ifdef OEM_IBM
1145 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301146 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301147 if (rc != PLDM_SUCCESS)
1148 {
1149 return;
1150 }
1151#endif
George Liu1244acf2020-08-14 09:11:11 +08001152 }
1153}
1154
1155void BIOSConfig::listenPendingAttributes()
1156{
1157 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1158 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1159
1160 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001161 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001162 pldm::utils::DBusHandler::getBus(),
1163 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001164 [this](sdbusplus::message_t& msg) {
Patrick Williams16c2a0a2024-08-16 15:20:59 -04001165 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001166
Patrick Williams16c2a0a2024-08-16 15:20:59 -04001167 using Value =
1168 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1169 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001170
Patrick Williams16c2a0a2024-08-16 15:20:59 -04001171 Properties props{};
1172 std::string intf;
1173 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001174
Patrick Williams16c2a0a2024-08-16 15:20:59 -04001175 auto valPropMap = props.find(propertyName);
1176 if (valPropMap == props.end())
1177 {
1178 return;
1179 }
George Liu1244acf2020-08-14 09:11:11 +08001180
Patrick Williams16c2a0a2024-08-16 15:20:59 -04001181 PendingAttributes pendingAttributes =
1182 std::get<PendingAttributes>(valPropMap->second);
1183 this->constructPendingAttribute(pendingAttributes);
1184 });
George Liu1244acf2020-08-14 09:11:11 +08001185
1186 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1187}
1188
John Wangd9659342020-02-27 16:46:05 +08001189} // namespace bios
1190} // namespace responder
1191} // namespace pldm