blob: 712555dfaf2ebdb0c260a3419c46ac798b9ff724 [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) :
John Wangd9659342020-02-27 16:46:05 +080048 jsonDir(jsonDir),
Andrew Jeffery197033b2024-07-25 20:53:07 +093049 tableDir(tableDir), dbusHandler(dbusHandler), eid(eid),
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060050 instanceIdDb(instanceIdDb), handler(handler),
Archana Kakani62dd8ff2024-02-12 10:00:40 -060051 platformConfigHandler(platformConfigHandler),
52 requestPLDMServiceName(requestPLDMServiceName)
53{
54 fs::create_directories(tableDir);
55 removeTables();
Archana Kakani46f352e2024-03-17 08:21:08 -050056
57#ifdef SYSTEM_SPECIFIC_BIOS_JSON
58 checkSystemTypeAvailability();
59#else
60 initBIOSAttributes(sysType, false);
61#endif
62
Archana Kakani62dd8ff2024-02-12 10:00:40 -060063 listenPendingAttributes();
64}
Tom Joseph7f839f92020-09-21 10:20:44 +053065
Archana Kakani46f352e2024-03-17 08:21:08 -050066void BIOSConfig::checkSystemTypeAvailability()
John Wangd9659342020-02-27 16:46:05 +080067{
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060068 if (platformConfigHandler)
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050069 {
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060070 auto systemType = platformConfigHandler->getPlatformName();
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050071 if (systemType.has_value())
72 {
Archana Kakani46f352e2024-03-17 08:21:08 -050073 // Received System Type from Entity Manager
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050074 sysType = systemType.value();
Archana Kakani46f352e2024-03-17 08:21:08 -050075 initBIOSAttributes(sysType, true);
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050076 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060077 else
78 {
Archana Kakani46f352e2024-03-17 08:21:08 -050079 platformConfigHandler->registerSystemTypeCallback(
80 std::bind(&BIOSConfig::initBIOSAttributes, this,
81 std::placeholders::_1, std::placeholders::_2));
Archana Kakani62dd8ff2024-02-12 10:00:40 -060082 }
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050083 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060084}
85
Archana Kakani46f352e2024-03-17 08:21:08 -050086void BIOSConfig::initBIOSAttributes(const std::string& systemType,
87 bool registerService)
Archana Kakani62dd8ff2024-02-12 10:00:40 -060088{
89 sysType = systemType;
90 fs::path dir{jsonDir / sysType};
91 if (!fs::exists(dir))
92 {
93 error("System specific bios attribute directory {DIR} does not exit",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050094 "DIR", dir);
Thu Nguyen3f5a9692024-07-16 13:16:54 +000095 if (registerService)
96 {
97 requestPLDMServiceName();
98 }
Archana Kakani62dd8ff2024-02-12 10:00:40 -060099 return;
100 }
John Wangd9659342020-02-27 16:46:05 +0800101 constructAttributes();
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600102 buildTables();
Archana Kakani46f352e2024-03-17 08:21:08 -0500103 if (registerService)
104 {
105 requestPLDMServiceName();
106 }
John Wangd9659342020-02-27 16:46:05 +0800107}
108
109void BIOSConfig::buildTables()
110{
John Wangd9659342020-02-27 16:46:05 +0800111 auto stringTable = buildAndStoreStringTable();
112 if (stringTable)
113 {
114 buildAndStoreAttrTables(*stringTable);
115 }
116}
117
118std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType)
119{
120 fs::path tablePath;
121 switch (tableType)
122 {
123 case PLDM_BIOS_STRING_TABLE:
124 tablePath = tableDir / stringTableFile;
125 break;
126 case PLDM_BIOS_ATTR_TABLE:
127 tablePath = tableDir / attrTableFile;
128 break;
129 case PLDM_BIOS_ATTR_VAL_TABLE:
130 tablePath = tableDir / attrValueTableFile;
131 break;
132 }
133 return loadTable(tablePath);
134}
135
Tom Joseph7f839f92020-09-21 10:20:44 +0530136int BIOSConfig::setBIOSTable(uint8_t tableType, const Table& table,
137 bool updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800138{
139 fs::path stringTablePath(tableDir / stringTableFile);
140 fs::path attrTablePath(tableDir / attrTableFile);
141 fs::path attrValueTablePath(tableDir / attrValueTableFile);
142
143 if (!pldm_bios_table_checksum(table.data(), table.size()))
144 {
145 return PLDM_INVALID_BIOS_TABLE_DATA_INTEGRITY_CHECK;
146 }
147
148 if (tableType == PLDM_BIOS_STRING_TABLE)
149 {
150 storeTable(stringTablePath, table);
151 }
152 else if (tableType == PLDM_BIOS_ATTR_TABLE)
153 {
154 BIOSTable biosStringTable(stringTablePath.c_str());
155 if (biosStringTable.isEmpty())
156 {
157 return PLDM_INVALID_BIOS_TABLE_TYPE;
158 }
159
160 auto rc = checkAttributeTable(table);
161 if (rc != PLDM_SUCCESS)
162 {
163 return rc;
164 }
165
166 storeTable(attrTablePath, table);
167 }
168 else if (tableType == PLDM_BIOS_ATTR_VAL_TABLE)
169 {
170 BIOSTable biosStringTable(stringTablePath.c_str());
171 BIOSTable biosStringValueTable(attrTablePath.c_str());
172 if (biosStringTable.isEmpty() || biosStringValueTable.isEmpty())
173 {
174 return PLDM_INVALID_BIOS_TABLE_TYPE;
175 }
176
177 auto rc = checkAttributeValueTable(table);
178 if (rc != PLDM_SUCCESS)
179 {
180 return rc;
181 }
182
183 storeTable(attrValueTablePath, table);
George Liu1b180d82020-07-23 14:01:58 +0800184 }
185 else
186 {
187 return PLDM_INVALID_BIOS_TABLE_TYPE;
188 }
189
Tom Joseph7f839f92020-09-21 10:20:44 +0530190 if ((tableType == PLDM_BIOS_ATTR_VAL_TABLE) && updateBaseBIOSTable)
George Liu1b180d82020-07-23 14:01:58 +0800191 {
George Liu1b180d82020-07-23 14:01:58 +0800192 updateBaseBIOSTableProperty();
193 }
194
195 return PLDM_SUCCESS;
196}
197
198int BIOSConfig::checkAttributeTable(const Table& table)
199{
200 using namespace pldm::bios::utils;
201 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
202 for (auto entry :
203 BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(table.data(), table.size()))
204 {
205 auto attrNameHandle =
206 pldm_bios_table_attr_entry_decode_string_handle(entry);
207
208 auto stringEnty = pldm_bios_table_string_find_by_handle(
209 stringTable->data(), stringTable->size(), attrNameHandle);
210 if (stringEnty == nullptr)
211 {
212 return PLDM_INVALID_BIOS_ATTR_HANDLE;
213 }
214
215 auto attrType = static_cast<pldm_bios_attribute_type>(
216 pldm_bios_table_attr_entry_decode_attribute_type(entry));
217
218 switch (attrType)
219 {
220 case PLDM_BIOS_ENUMERATION:
221 case PLDM_BIOS_ENUMERATION_READ_ONLY:
222 {
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930223 uint8_t pvNum;
224 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000225 pldm_bios_table_attr_entry_enum_decode_pv_num(entry, &pvNum);
George Liu1b180d82020-07-23 14:01:58 +0800226 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930227 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery24611052024-08-01 13:15:36 +0000228 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
George Liu1b180d82020-07-23 14:01:58 +0800229 entry, pvHandls.data(), pvHandls.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930230 uint8_t defNum;
Andrew Jefferyff3fb9e2024-08-01 13:15:36 +0000231 pldm_bios_table_attr_entry_enum_decode_def_num(entry, &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
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000323 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
324 buffer.size());
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930325
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
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000364 pldm_bios_table_string_entry_decode_string(
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
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000376 pldm_bios_table_attr_entry_enum_decode_pv_num(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
Andrew Jeffery24611052024-08-01 13:15:36 +0000380 pldm_bios_table_attr_entry_enum_decode_pv_hdls(
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
Andrew Jefferyff3fb9e2024-08-01 13:15:36 +0000408 pldm_bios_table_attr_entry_enum_decode_def_num(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
Andrew Jeffery53e342a2024-08-01 13:15:36 +0000468 pldm_bios_table_attr_entry_string_decode_def_string_length(
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930469 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 Dixit89644442024-03-31 05:39:59 -0500531 error("Failed to update BaseBIOSTable property, error - {ERROR}",
532 "ERROR", e);
George Liu1b180d82020-07-23 14:01:58 +0800533 }
534}
535
John Wangd9659342020-02-27 16:46:05 +0800536void BIOSConfig::constructAttributes()
537{
Archana Kakaniac713ee2024-05-20 01:27:53 -0500538 info("Bios Attribute file path: {PATH}", "PATH",
539 (jsonDir / sysType / attributesJsonFile));
540 load(jsonDir / sysType / attributesJsonFile, [this](const Json& entry) {
541 std::string attrType = entry.at("attribute_type");
542 if (attrType == "string")
543 {
544 constructAttribute<BIOSStringAttribute>(entry);
545 }
546 else if (attrType == "integer")
547 {
548 constructAttribute<BIOSIntegerAttribute>(entry);
549 }
550 else if (attrType == "enum")
551 {
552 constructAttribute<BIOSEnumAttribute>(entry);
553 }
John Wang3be70852020-02-13 15:59:04 +0800554 });
John Wangd9659342020-02-27 16:46:05 +0800555}
556
557void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable)
558{
559 BIOSStringTable biosStringTable(stringTable);
560
561 if (biosAttributes.empty())
562 {
563 return;
564 }
565
Tom Josephca7b2522020-11-18 12:27:11 +0530566 BaseBIOSTable biosTable{};
567 constexpr auto biosObjPath = "/xyz/openbmc_project/bios_config/manager";
568 constexpr auto biosInterface = "xyz.openbmc_project.BIOSConfig.Manager";
569
570 try
571 {
572 auto& bus = dbusHandler->getBus();
573 auto service = dbusHandler->getService(biosObjPath, biosInterface);
Patrick Williams6da4f912023-05-10 07:50:53 -0500574 auto method = bus.new_method_call(service.c_str(), biosObjPath,
575 "org.freedesktop.DBus.Properties",
576 "Get");
Tom Josephca7b2522020-11-18 12:27:11 +0530577 method.append(biosInterface, "BaseBIOSTable");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500578 auto reply = bus.call(method, dbusTimeout);
Tom Josephca7b2522020-11-18 12:27:11 +0530579 std::variant<BaseBIOSTable> varBiosTable{};
580 reply.read(varBiosTable);
581 biosTable = std::get<BaseBIOSTable>(varBiosTable);
582 }
583 // Failed to read the BaseBIOSTable, so update the BaseBIOSTable with the
584 // default values populated from the BIOS JSONs to keep PLDM and
585 // bios-settings-manager in sync
586 catch (const std::exception& e)
587 {
Riya Dixit89644442024-03-31 05:39:59 -0500588 error("Failed to read BaseBIOSTable property, error - {ERROR}", "ERROR",
589 e);
Tom Josephca7b2522020-11-18 12:27:11 +0530590 }
591
John Wangd9659342020-02-27 16:46:05 +0800592 Table attrTable, attrValueTable;
593
594 for (auto& attr : biosAttributes)
595 {
596 try
597 {
Tom Josephca7b2522020-11-18 12:27:11 +0530598 auto iter = biosTable.find(attr->name);
599 if (iter == biosTable.end())
600 {
601 attr->constructEntry(biosStringTable, attrTable, attrValueTable,
602 std::nullopt);
603 }
604 else
605 {
606 attr->constructEntry(
607 biosStringTable, attrTable, attrValueTable,
608 std::get<static_cast<uint8_t>(Index::currentValue)>(
609 iter->second));
610 }
John Wangd9659342020-02-27 16:46:05 +0800611 }
612 catch (const std::exception& e)
613 {
Riya Dixit89644442024-03-31 05:39:59 -0500614 error(
615 "Failed to construct table entry for attribute '{ATTRIBUTE}', error - {ERROR}",
616 "ATTRIBUTE", attr->name, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800617 }
618 }
619
620 table::appendPadAndChecksum(attrTable);
621 table::appendPadAndChecksum(attrValueTable);
George Liu1b180d82020-07-23 14:01:58 +0800622 setBIOSTable(PLDM_BIOS_ATTR_TABLE, attrTable);
623 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, attrValueTable);
John Wangd9659342020-02-27 16:46:05 +0800624}
625
626std::optional<Table> BIOSConfig::buildAndStoreStringTable()
627{
628 std::set<std::string> strings;
Archana Kakaniac713ee2024-05-20 01:27:53 -0500629 load(jsonDir / sysType / attributesJsonFile, [&strings](const Json& entry) {
630 if (entry.at("attribute_type") == "enum")
John Wangd9659342020-02-27 16:46:05 +0800631 {
Archana Kakaniac713ee2024-05-20 01:27:53 -0500632 strings.emplace(entry.at("attribute_name"));
633 auto possibleValues = entry.at("possible_values");
634 for (auto& pv : possibleValues)
635 {
636 strings.emplace(pv);
637 }
638 }
639 else
640 {
641 strings.emplace(entry.at("attribute_name"));
John Wangd9659342020-02-27 16:46:05 +0800642 }
643 });
644
645 if (strings.empty())
646 {
647 return std::nullopt;
648 }
649
650 Table table;
651 for (const auto& elem : strings)
652 {
653 table::string::constructEntry(table, elem);
654 }
655
656 table::appendPadAndChecksum(table);
George Liu1b180d82020-07-23 14:01:58 +0800657 setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
John Wangd9659342020-02-27 16:46:05 +0800658 return table;
659}
660
661void BIOSConfig::storeTable(const fs::path& path, const Table& table)
662{
663 BIOSTable biosTable(path.c_str());
664 biosTable.store(table);
665}
666
667std::optional<Table> BIOSConfig::loadTable(const fs::path& path)
668{
669 BIOSTable biosTable(path.c_str());
670 if (biosTable.isEmpty())
671 {
672 return std::nullopt;
673 }
674
675 Table table;
676 biosTable.load(table);
677 return table;
678}
679
680void BIOSConfig::load(const fs::path& filePath, ParseHandler handler)
681{
682 std::ifstream file;
683 Json jsonConf;
684 if (fs::exists(filePath))
685 {
686 try
687 {
688 file.open(filePath);
689 jsonConf = Json::parse(file);
690 auto entries = jsonConf.at("entries");
691 for (auto& entry : entries)
692 {
693 try
694 {
695 handler(entry);
696 }
697 catch (const std::exception& e)
698 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600699 error(
Riya Dixit89644442024-03-31 05:39:59 -0500700 "Failed to parse JSON config file at path '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500701 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800702 }
703 }
704 }
705 catch (const std::exception& e)
706 {
Riya Dixit89644442024-03-31 05:39:59 -0500707 error("Failed to parse JSON config file '{PATH}', error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500708 "PATH", filePath, "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800709 }
710 }
711}
712
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600713std::string BIOSConfig::decodeStringFromStringEntry(
714 const pldm_bios_string_table_entry* stringEntry)
715{
716 auto strLength =
717 pldm_bios_table_string_entry_decode_string_length(stringEntry);
718 std::vector<char> buffer(strLength + 1 /* sizeof '\0' */);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930719 // Preconditions are upheld therefore no error check necessary
Andrew Jefferyfe1189c2024-08-01 13:15:36 +0000720 pldm_bios_table_string_entry_decode_string(stringEntry, buffer.data(),
721 buffer.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600722 return std::string(buffer.data(), buffer.data() + strLength);
723}
724
725std::string
726 BIOSConfig::displayStringHandle(uint16_t handle, uint8_t index,
727 const std::optional<Table>& attrTable,
728 const std::optional<Table>& stringTable)
729{
730 auto attrEntry = pldm_bios_table_attr_find_by_handle(
731 attrTable->data(), attrTable->size(), handle);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930732 uint8_t pvNum;
Andrew Jeffery8c05ca22024-08-01 13:15:36 +0000733 int rc = pldm_bios_table_attr_entry_enum_decode_pv_num(attrEntry, &pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930734 if (rc != PLDM_SUCCESS)
735 {
736 error(
Riya Dixit89644442024-03-31 05:39:59 -0500737 "Failed to decode BIOS table possible values for attribute entry, response code '{RC}'",
738 "RC", rc);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930739 throw std::runtime_error(
740 "Failed to decode BIOS table possible values for attribute entry");
741 }
742
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600743 std::vector<uint16_t> pvHandls(pvNum);
Andrew Jeffery488f19d2023-06-13 20:43:39 +0930744 // Preconditions are upheld therefore no error check necessary
Andrew Jeffery24611052024-08-01 13:15:36 +0000745 pldm_bios_table_attr_entry_enum_decode_pv_hdls(attrEntry, pvHandls.data(),
746 pvHandls.size());
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600747
748 std::string displayString = std::to_string(pvHandls[index]);
749
750 auto stringEntry = pldm_bios_table_string_find_by_handle(
751 stringTable->data(), stringTable->size(), pvHandls[index]);
752
753 auto decodedStr = decodeStringFromStringEntry(stringEntry);
754
755 return decodedStr + "(" + displayString + ")";
756}
757
758void BIOSConfig::traceBIOSUpdate(
759 const pldm_bios_attr_val_table_entry* attrValueEntry,
760 const pldm_bios_attr_table_entry* attrEntry, bool isBMC)
761{
762 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
763 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
764
Patrick Williams6da4f912023-05-10 07:50:53 -0500765 auto [attrHandle,
766 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600767
768 auto attrHeader = table::attribute::decodeHeader(attrEntry);
769 BIOSStringTable biosStringTable(*stringTable);
770 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
771
772 switch (attrType)
773 {
774 case PLDM_BIOS_ENUMERATION:
775 case PLDM_BIOS_ENUMERATION_READ_ONLY:
776 {
777 auto count = pldm_bios_table_attr_value_entry_enum_decode_number(
778 attrValueEntry);
779 std::vector<uint8_t> handles(count);
780 pldm_bios_table_attr_value_entry_enum_decode_handles(
781 attrValueEntry, handles.data(), handles.size());
782
783 for (uint8_t handle : handles)
784 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600785 auto nwVal = displayStringHandle(attrHandle, handle, attrTable,
786 stringTable);
787 auto chkBMC = isBMC ? "true" : "false";
788 info(
Riya Dixit89644442024-03-31 05:39:59 -0500789 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
790 "ATTRIBUTE", attrName, "VALUE", nwVal, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600791 }
792 break;
793 }
794 case PLDM_BIOS_INTEGER:
795 case PLDM_BIOS_INTEGER_READ_ONLY:
796 {
797 auto value =
798 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600799 auto chkBMC = isBMC ? "true" : "false";
800 info(
Riya Dixit89644442024-03-31 05:39:59 -0500801 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
802 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600803 break;
804 }
805 case PLDM_BIOS_STRING:
806 case PLDM_BIOS_STRING_READ_ONLY:
807 {
808 auto value =
809 table::attribute_value::decodeStringEntry(attrValueEntry);
Riya Dixit49cfb132023-03-02 04:26:53 -0600810 auto chkBMC = isBMC ? "true" : "false";
811 info(
Riya Dixit89644442024-03-31 05:39:59 -0500812 "BIOS attribute '{ATTRIBUTE}' updated to value '{VALUE}' by BMC '{CHECK_BMC}'",
813 "ATTRIBUTE", attrName, "VALUE", value, "CHECK_BMC", chkBMC);
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600814 break;
815 }
816 default:
817 break;
818 };
819}
820
John Wang8241b342020-06-05 10:49:17 +0800821int BIOSConfig::checkAttrValueToUpdate(
822 const pldm_bios_attr_val_table_entry* attrValueEntry,
823 const pldm_bios_attr_table_entry* attrEntry, Table&)
824
825{
Patrick Williams6da4f912023-05-10 07:50:53 -0500826 auto [attrHandle,
827 attrType] = table::attribute_value::decodeHeader(attrValueEntry);
John Wang8241b342020-06-05 10:49:17 +0800828
829 switch (attrType)
830 {
831 case PLDM_BIOS_ENUMERATION:
George Liu5bb9edb2021-08-05 20:10:32 +0800832 case PLDM_BIOS_ENUMERATION_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800833 {
834 auto value =
835 table::attribute_value::decodeEnumEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500836 auto [pvHdls,
837 defIndex] = table::attribute::decodeEnumEntry(attrEntry);
Varsha Kaverappa6a4d1cf2021-11-24 21:15:42 -0600838 if (!(value.size() == 1))
839 {
840 return PLDM_ERROR_INVALID_LENGTH;
841 }
John Wang8241b342020-06-05 10:49:17 +0800842 if (value[0] >= pvHdls.size())
843 {
Riya Dixit89644442024-03-31 05:39:59 -0500844 error(
845 "Invalid index '{INDEX}' encountered for Enum type BIOS attribute",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500846 "INDEX", value[0]);
John Wang8241b342020-06-05 10:49:17 +0800847 return PLDM_ERROR_INVALID_DATA;
848 }
John Wang8241b342020-06-05 10:49:17 +0800849 return PLDM_SUCCESS;
850 }
851 case PLDM_BIOS_INTEGER:
George Liu5bb9edb2021-08-05 20:10:32 +0800852 case PLDM_BIOS_INTEGER_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800853 {
854 auto value =
855 table::attribute_value::decodeIntegerEntry(attrValueEntry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500856 auto [lower, upper, scalar,
857 def] = table::attribute::decodeIntegerEntry(attrEntry);
John Wang8241b342020-06-05 10:49:17 +0800858
859 if (value < lower || value > upper)
860 {
Riya Dixit89644442024-03-31 05:39:59 -0500861 error(
862 "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}'.",
863 "ATTRIBUTE_VALUE", value, "LOWER", lower, "UPPER", upper,
864 "SCALAR", scalar);
John Wang8241b342020-06-05 10:49:17 +0800865 return PLDM_ERROR_INVALID_DATA;
866 }
867 return PLDM_SUCCESS;
868 }
869 case PLDM_BIOS_STRING:
George Liu5bb9edb2021-08-05 20:10:32 +0800870 case PLDM_BIOS_STRING_READ_ONLY:
John Wang8241b342020-06-05 10:49:17 +0800871 {
872 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
873 auto value =
874 table::attribute_value::decodeStringEntry(attrValueEntry);
875 if (value.size() < stringConf.minLength ||
876 value.size() > stringConf.maxLength)
877 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600878 error(
Riya Dixit89644442024-03-31 05:39:59 -0500879 "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}'",
880 "ATTRIBUTE_VALUE", value, "LENGTH", value.size(), "MIN_LEN",
881 stringConf.minLength, "MAX_LEN", stringConf.maxLength);
John Wang8241b342020-06-05 10:49:17 +0800882 return PLDM_ERROR_INVALID_LENGTH;
883 }
884 return PLDM_SUCCESS;
885 }
886 default:
Riya Dixit89644442024-03-31 05:39:59 -0500887 error("ReadOnly or Unsupported type '{TYPE}'", "TYPE", attrType);
John Wang8241b342020-06-05 10:49:17 +0800888 return PLDM_ERROR;
889 };
890}
891
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600892int BIOSConfig::setAttrValue(const void* entry, size_t size, bool isBMC,
893 bool updateDBus, bool updateBaseBIOSTable)
John Wangd9659342020-02-27 16:46:05 +0800894{
895 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
896 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
897 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
898 if (!attrValueTable || !attrTable || !stringTable)
899 {
900 return PLDM_BIOS_TABLE_UNAVAILABLE;
901 }
902
John Wangd9659342020-02-27 16:46:05 +0800903 auto attrValueEntry =
904 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
905
906 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
907
Patrick Williams6da4f912023-05-10 07:50:53 -0500908 auto attrEntry = table::attribute::findByHandle(*attrTable,
909 attrValHeader.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800910 if (!attrEntry)
911 {
912 return PLDM_ERROR;
913 }
914
John Wang8241b342020-06-05 10:49:17 +0800915 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
916 if (rc != PLDM_SUCCESS)
917 {
918 return rc;
919 }
920
Patrick Williams6da4f912023-05-10 07:50:53 -0500921 auto destTable = table::attribute_value::updateTable(*attrValueTable, entry,
922 size);
John Wang8241b342020-06-05 10:49:17 +0800923
924 if (!destTable)
925 {
926 return PLDM_ERROR;
927 }
928
John Wangd9659342020-02-27 16:46:05 +0800929 try
930 {
931 auto attrHeader = table::attribute::decodeHeader(attrEntry);
932
933 BIOSStringTable biosStringTable(*stringTable);
934 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
Patrick Williamsa6756622023-10-20 11:19:15 -0500935 auto iter = std::find_if(
936 biosAttributes.begin(), biosAttributes.end(),
937 [&attrName](const auto& attr) { return attr->name == attrName; });
John Wangd9659342020-02-27 16:46:05 +0800938
939 if (iter == biosAttributes.end())
940 {
941 return PLDM_ERROR;
942 }
George Liu6d6d1e82021-02-16 11:08:55 +0800943 if (updateDBus)
944 {
945 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry,
946 biosStringTable);
947 }
John Wangd9659342020-02-27 16:46:05 +0800948 }
949 catch (const std::exception& e)
950 {
Riya Dixit89644442024-03-31 05:39:59 -0500951 error("Set attribute value error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800952 return PLDM_ERROR;
953 }
954
Tom Joseph7f839f92020-09-21 10:20:44 +0530955 setBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE, *destTable, updateBaseBIOSTable);
George Liu5c3192b2020-08-13 17:35:43 +0800956
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600957 traceBIOSUpdate(attrValueEntry, attrEntry, isBMC);
958
John Wangd9659342020-02-27 16:46:05 +0800959 return PLDM_SUCCESS;
960}
961
962void BIOSConfig::removeTables()
963{
964 try
965 {
966 fs::remove(tableDir / stringTableFile);
967 fs::remove(tableDir / attrTableFile);
968 fs::remove(tableDir / attrValueTableFile);
969 }
970 catch (const std::exception& e)
971 {
Riya Dixit89644442024-03-31 05:39:59 -0500972 error("Remove the tables error - {ERROR}", "ERROR", e);
John Wangd9659342020-02-27 16:46:05 +0800973 }
974}
975
Sampa Misra46ece062020-03-18 07:17:44 -0500976void BIOSConfig::processBiosAttrChangeNotification(
977 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
978{
979 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
980 const auto& propertyName = dBusMap->propertyName;
981 const auto& attrName = biosAttributes[biosAttrIndex]->name;
982
983 const auto it = chProperties.find(propertyName);
984 if (it == chProperties.end())
985 {
986 return;
987 }
988
989 PropertyValue newPropVal = it->second;
990 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
991 if (!stringTable.has_value())
992 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600993 error("BIOS string table unavailable");
Sampa Misra46ece062020-03-18 07:17:44 -0500994 return;
995 }
996 BIOSStringTable biosStringTable(*stringTable);
997 uint16_t attrNameHdl{};
998 try
999 {
1000 attrNameHdl = biosStringTable.findHandle(attrName);
1001 }
Patrick Williams51330582021-10-06 12:48:56 -05001002 catch (const std::invalid_argument& e)
Sampa Misra46ece062020-03-18 07:17:44 -05001003 {
Riya Dixit89644442024-03-31 05:39:59 -05001004 error(
1005 "Missing handle for attribute '{ATTRIBUTE}' in BIOS String Table, error - '{ERROR}'",
1006 "ATTRIBUTE", attrName, "ERROR", e);
Sampa Misra46ece062020-03-18 07:17:44 -05001007 return;
1008 }
1009
1010 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1011 if (!attrTable.has_value())
1012 {
Riya Dixit89644442024-03-31 05:39:59 -05001013 error("BIOS Attribute table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001014 return;
1015 }
1016 const struct pldm_bios_attr_table_entry* tableEntry =
1017 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
1018 if (tableEntry == nullptr)
1019 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001020 error(
Riya Dixit89644442024-03-31 05:39:59 -05001021 "Failed to find attribute {ATTRIBUTE} in BIOS Attribute table with attribute handle '{ATTR_HANDLE}'",
1022 "ATTRIBUTE", attrName, "ATTR_HANDLE", attrNameHdl);
Sampa Misra46ece062020-03-18 07:17:44 -05001023 return;
1024 }
1025
Patrick Williams6da4f912023-05-10 07:50:53 -05001026 auto [attrHdl, attrType,
1027 stringHdl] = table::attribute::decodeHeader(tableEntry);
Sampa Misra46ece062020-03-18 07:17:44 -05001028
1029 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
1030
1031 if (!attrValueSrcTable.has_value())
1032 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001033 error("Attribute value table not present");
Sampa Misra46ece062020-03-18 07:17:44 -05001034 return;
1035 }
1036
1037 Table newValue;
1038 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
1039 newValue, attrHdl, attrType, newPropVal);
1040 if (rc != PLDM_SUCCESS)
1041 {
Riya Dixit49cfb132023-03-02 04:26:53 -06001042 error(
Riya Dixit89644442024-03-31 05:39:59 -05001043 "Failed to update the attribute value table for attribute handle '{ATTR_HANDLE}' and attribute type '{TYPE}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -05001044 "ATTR_HANDLE", attrHdl, "TYPE", attrType);
Sampa Misra46ece062020-03-18 07:17:44 -05001045 return;
1046 }
1047 auto destTable = table::attribute_value::updateTable(
1048 *attrValueSrcTable, newValue.data(), newValue.size());
1049 if (destTable.has_value())
1050 {
1051 storeTable(tableDir / attrValueTableFile, *destTable);
1052 }
Sampa Misra0f262332021-02-15 00:13:51 -06001053
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001054 rc = setAttrValue(newValue.data(), newValue.size(), true, false);
Sampa Misra0f262332021-02-15 00:13:51 -06001055 if (rc != PLDM_SUCCESS)
1056 {
Riya Dixit89644442024-03-31 05:39:59 -05001057 error(
1058 "Failed to setAttrValue on base bios table and dbus, response code '{RC}'",
1059 "RC", rc);
Sampa Misra0f262332021-02-15 00:13:51 -06001060 }
Sampa Misra46ece062020-03-18 07:17:44 -05001061}
1062
George Liu1244acf2020-08-14 09:11:11 +08001063uint16_t BIOSConfig::findAttrHandle(const std::string& attrName)
1064{
1065 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
1066 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
1067
1068 BIOSStringTable biosStringTable(*stringTable);
1069 pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(
1070 attrTable->data(), attrTable->size());
1071 auto stringHandle = biosStringTable.findHandle(attrName);
1072
1073 for (auto entry : pldm::bios::utils::BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(
1074 attrTable->data(), attrTable->size()))
1075 {
1076 auto header = table::attribute::decodeHeader(entry);
1077 if (header.stringHandle == stringHandle)
1078 {
1079 return header.attrHandle;
1080 }
1081 }
1082
Manojkiran Eda2576aec2024-06-17 12:05:17 +05301083 throw std::invalid_argument("Unknown attribute Name");
George Liu1244acf2020-08-14 09:11:11 +08001084}
1085
1086void BIOSConfig::constructPendingAttribute(
1087 const PendingAttributes& pendingAttributes)
1088{
Tom Joseph7f839f92020-09-21 10:20:44 +05301089 std::vector<uint16_t> listOfHandles{};
1090
George Liu1244acf2020-08-14 09:11:11 +08001091 for (auto& attribute : pendingAttributes)
1092 {
1093 std::string attributeName = attribute.first;
1094 auto& [attributeType, attributevalue] = attribute.second;
1095
1096 auto iter = std::find_if(biosAttributes.begin(), biosAttributes.end(),
1097 [&attributeName](const auto& attr) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001098 return attr->name == attributeName;
1099 });
George Liu1244acf2020-08-14 09:11:11 +08001100
1101 if (iter == biosAttributes.end())
1102 {
Riya Dixit89644442024-03-31 05:39:59 -05001103 error("Wrong attribute name {NAME}", "NAME", attributeName);
George Liu1244acf2020-08-14 09:11:11 +08001104 continue;
1105 }
1106
1107 Table attrValueEntry(sizeof(pldm_bios_attr_val_table_entry), 0);
1108 auto entry = reinterpret_cast<pldm_bios_attr_val_table_entry*>(
1109 attrValueEntry.data());
1110
1111 auto handler = findAttrHandle(attributeName);
1112 auto type =
1113 BIOSConfigManager::convertAttributeTypeFromString(attributeType);
1114
1115 if (type != BIOSConfigManager::AttributeType::Enumeration &&
1116 type != BIOSConfigManager::AttributeType::String &&
1117 type != BIOSConfigManager::AttributeType::Integer)
1118 {
Riya Dixit89644442024-03-31 05:39:59 -05001119 error("Attribute type '{TYPE}' not supported", "TYPE",
1120 attributeType);
George Liu1244acf2020-08-14 09:11:11 +08001121 continue;
1122 }
1123
George Liu4876c542022-06-08 15:59:54 +08001124 const auto [attrType, readonlyStatus, displayName, description,
Patrick Williams6da4f912023-05-10 07:50:53 -05001125 menuPath, currentValue, defaultValue,
1126 option] = baseBIOSTableMaps.at(attributeName);
George Liu4876c542022-06-08 15:59:54 +08001127
George Liu1244acf2020-08-14 09:11:11 +08001128 entry->attr_handle = htole16(handler);
George Liu4876c542022-06-08 15:59:54 +08001129
1130 // Need to verify that the current value has really changed
1131 if (attributeType == attrType && attributevalue != currentValue)
1132 {
1133 listOfHandles.emplace_back(htole16(handler));
1134 }
Tom Joseph7f839f92020-09-21 10:20:44 +05301135
George Liu1244acf2020-08-14 09:11:11 +08001136 (*iter)->generateAttributeEntry(attributevalue, attrValueEntry);
1137
Sagar Srinivascac0ebb2021-11-23 07:50:28 -06001138 setAttrValue(attrValueEntry.data(), attrValueEntry.size(), true);
Tom Joseph7f839f92020-09-21 10:20:44 +05301139 }
1140
1141 if (listOfHandles.size())
1142 {
1143#ifdef OEM_IBM
1144 auto rc = pldm::responder::platform::sendBiosAttributeUpdateEvent(
Andrew Jefferya330b2f2023-05-04 14:55:37 +09301145 eid, instanceIdDb, listOfHandles, handler);
Tom Joseph7f839f92020-09-21 10:20:44 +05301146 if (rc != PLDM_SUCCESS)
1147 {
1148 return;
1149 }
1150#endif
George Liu1244acf2020-08-14 09:11:11 +08001151 }
1152}
1153
1154void BIOSConfig::listenPendingAttributes()
1155{
1156 constexpr auto objPath = "/xyz/openbmc_project/bios_config/manager";
1157 constexpr auto objInterface = "xyz.openbmc_project.BIOSConfig.Manager";
1158
1159 using namespace sdbusplus::bus::match::rules;
Patrick Williams84b790c2022-07-22 19:26:56 -05001160 auto updateBIOSMatch = std::make_unique<sdbusplus::bus::match_t>(
George Liu1244acf2020-08-14 09:11:11 +08001161 pldm::utils::DBusHandler::getBus(),
1162 propertiesChanged(objPath, objInterface),
Patrick Williams84b790c2022-07-22 19:26:56 -05001163 [this](sdbusplus::message_t& msg) {
Patrick Williams6da4f912023-05-10 07:50:53 -05001164 constexpr auto propertyName = "PendingAttributes";
George Liu1244acf2020-08-14 09:11:11 +08001165
Patrick Williams6da4f912023-05-10 07:50:53 -05001166 using Value =
1167 std::variant<std::string, PendingAttributes, BaseBIOSTable>;
1168 using Properties = std::map<DbusProp, Value>;
George Liu1244acf2020-08-14 09:11:11 +08001169
Patrick Williams6da4f912023-05-10 07:50:53 -05001170 Properties props{};
1171 std::string intf;
1172 msg.read(intf, props);
George Liu1244acf2020-08-14 09:11:11 +08001173
Patrick Williams6da4f912023-05-10 07:50:53 -05001174 auto valPropMap = props.find(propertyName);
1175 if (valPropMap == props.end())
1176 {
1177 return;
1178 }
George Liu1244acf2020-08-14 09:11:11 +08001179
Patrick Williams6da4f912023-05-10 07:50:53 -05001180 PendingAttributes pendingAttributes =
1181 std::get<PendingAttributes>(valPropMap->second);
1182 this->constructPendingAttribute(pendingAttributes);
Patrick Williamsa6756622023-10-20 11:19:15 -05001183 });
George Liu1244acf2020-08-14 09:11:11 +08001184
1185 biosAttrMatch.emplace_back(std::move(updateBIOSMatch));
1186}
1187
John Wangd9659342020-02-27 16:46:05 +08001188} // namespace bios
1189} // namespace responder
1190} // namespace pldm