blob: 3334f0a06b9270a4bef82c797ea763b1e47b2d1c [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#include "config.h"
2
3#include "bios_handler.hpp"
4
5#include "constants.hpp"
6#include "logger.hpp"
7
8#include <sdbusplus/bus/match.hpp>
9#include <utility/common_utility.hpp>
10#include <utility/dbus_utility.hpp>
11
12#include <string>
13
14namespace vpd
15{
16// Template declaration to define APIs.
17template class BiosHandler<IbmBiosHandler>;
18
19template <typename T>
Sunny Srivastava5de031d2025-09-02 23:58:02 -050020void BiosHandler<T>::checkAndListenPldmService() noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050021{
Sunny Srivastava5de031d2025-09-02 23:58:02 -050022 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050023 {
Sunny Srivastava5de031d2025-09-02 23:58:02 -050024 // Setup a call back match on NameOwnerChanged to determine when PLDM is
25 // up.
26 static std::shared_ptr<sdbusplus::bus::match_t> l_nameOwnerMatch =
27 std::make_shared<sdbusplus::bus::match_t>(
28 *m_asioConn,
29 sdbusplus::bus::match::rules::nameOwnerChanged(
30 constants::pldmServiceName),
31 [this](sdbusplus::message_t& l_msg) {
32 if (l_msg.is_method_error())
33 {
34 logging::logMessage(
35 "Error in reading PLDM name owner changed signal.");
36 return;
37 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050038
Sunny Srivastava5de031d2025-09-02 23:58:02 -050039 std::string l_name;
40 std::string l_newOwner;
41 std::string l_oldOwner;
42
43 l_msg.read(l_name, l_oldOwner, l_newOwner);
44
45 if (!l_newOwner.empty() &&
46 (l_name.compare(constants::pldmServiceName) ==
47 constants::STR_CMP_SUCCESS))
48 {
49 m_specificBiosHandler->backUpOrRestoreBiosAttributes();
50
51 // Start listener now that we have done the restore.
52 listenBiosAttributes();
53
54 // We don't need the match anymore
55 l_nameOwnerMatch.reset();
56 }
57 });
58
59 // Based on PLDM service status reset owner match registered above and
60 // trigger BIOS attribute sync.
61 if (dbusUtility::isServiceRunning(constants::pldmServiceName))
62 {
63 l_nameOwnerMatch.reset();
64 m_specificBiosHandler->backUpOrRestoreBiosAttributes();
65
66 // Start listener now that we have done the restore.
67 listenBiosAttributes();
68 }
69 }
70 catch (const std::exception& l_ex)
71 {
72 logging::logMessage(
73 "Failed to register callback for PLDM servce. Error: " +
74 std::string(l_ex.what()));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050075 }
76}
77
78template <typename T>
79void BiosHandler<T>::listenBiosAttributes()
80{
81 static std::shared_ptr<sdbusplus::bus::match_t> l_biosMatch =
82 std::make_shared<sdbusplus::bus::match_t>(
83 *m_asioConn,
84 sdbusplus::bus::match::rules::propertiesChanged(
85 constants::biosConfigMgrObjPath,
86 constants::biosConfigMgrInterface),
87 [this](sdbusplus::message_t& l_msg) {
88 m_specificBiosHandler->biosAttributesCallback(l_msg);
89 });
90}
91
92void IbmBiosHandler::biosAttributesCallback(sdbusplus::message_t& i_msg)
93{
94 if (i_msg.is_method_error())
95 {
96 logging::logMessage("Error in reading BIOS attribute signal. ");
97 return;
98 }
99
100 std::string l_objPath;
101 types::BiosBaseTableType l_propMap;
102 i_msg.read(l_objPath, l_propMap);
103
104 for (auto l_property : l_propMap)
105 {
106 if (l_property.first != "BaseBIOSTable")
107 {
108 // Looking for change in Base BIOS table only.
109 continue;
110 }
111
112 if (auto l_attributeList =
113 std::get_if<std::map<std::string, types::BiosProperty>>(
114 &(l_property.second)))
115 {
116 for (const auto& l_attribute : *l_attributeList)
117 {
118 if (auto l_val = std::get_if<std::string>(
119 &(std::get<5>(std::get<1>(l_attribute)))))
120 {
121 std::string l_attributeName = std::get<0>(l_attribute);
122 if (l_attributeName == "hb_memory_mirror_mode")
123 {
124 saveAmmToVpd(*l_val);
125 }
126
127 if (l_attributeName == "pvm_keep_and_clear")
128 {
129 saveKeepAndClearToVpd(*l_val);
130 }
131
132 if (l_attributeName == "pvm_create_default_lpar")
133 {
134 saveCreateDefaultLparToVpd(*l_val);
135 }
136
137 if (l_attributeName == "pvm_clear_nvram")
138 {
139 saveClearNvramToVpd(*l_val);
140 }
141
142 continue;
143 }
144
145 if (auto l_val = std::get_if<int64_t>(
146 &(std::get<5>(std::get<1>(l_attribute)))))
147 {
148 std::string l_attributeName = std::get<0>(l_attribute);
149 if (l_attributeName == "hb_field_core_override")
150 {
151 saveFcoToVpd(*l_val);
152 }
153 }
154 }
155 }
156 else
157 {
Sunny Srivastavab7818d12025-04-13 13:21:36 +0530158 logging::logMessage("Invalid type received for BIOS table.");
159 EventLogger::createSyncPel(
160 types::ErrorType::FirmwareError, types::SeverityType::Warning,
161 __FILE__, __FUNCTION__, 0,
162 std::string("Invalid type received for BIOS table."),
163 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500164 break;
165 }
166 }
167}
168
169void IbmBiosHandler::backUpOrRestoreBiosAttributes()
170{
171 // process FCO
172 processFieldCoreOverride();
173
174 // process AMM
175 processActiveMemoryMirror();
176
177 // process LPAR
178 processCreateDefaultLpar();
179
180 // process clear NVRAM
181 processClearNvram();
182
183 // process keep and clear
184 processKeepAndClear();
185}
186
Patrick Williams43fedab2025-02-03 14:28:05 -0500187types::BiosAttributeCurrentValue IbmBiosHandler::readBiosAttribute(
188 const std::string& i_attributeName)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500189{
190 types::BiosAttributeCurrentValue l_attrValueVariant =
191 dbusUtility::biosGetAttributeMethodCall(i_attributeName);
192
193 return l_attrValueVariant;
194}
195
196void IbmBiosHandler::processFieldCoreOverride()
197{
198 // TODO: Should we avoid doing this at runtime?
199
200 // Read required keyword from Dbus.
201 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
202 constants::pimServiceName, constants::systemVpdInvPath,
203 constants::vsysInf, constants::kwdRG);
204
205 if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
206 {
207 // default length of the keyword is 4 bytes.
208 if (l_fcoInVpd->size() != constants::VALUE_4)
209 {
210 logging::logMessage(
211 "Invalid value read for FCO from D-Bus. Skipping.");
212 }
213
214 // If FCO in VPD contains anything other that ASCII Space, restore to
215 // BIOS
216 if (std::any_of(l_fcoInVpd->cbegin(), l_fcoInVpd->cend(),
217 [](uint8_t l_val) {
218 return l_val != constants::ASCII_OF_SPACE;
219 }))
220 {
221 // Restore the data to BIOS.
222 saveFcoToBios(*l_fcoInVpd);
223 }
224 else
225 {
226 types::BiosAttributeCurrentValue l_attrValueVariant =
227 readBiosAttribute("hb_field_core_override");
228
229 if (auto l_fcoInBios = std::get_if<int64_t>(&l_attrValueVariant))
230 {
231 // save the BIOS data to VPD
232 saveFcoToVpd(*l_fcoInBios);
233
234 return;
235 }
236 logging::logMessage("Invalid type recieved for FCO from BIOS.");
237 }
238 return;
239 }
240 logging::logMessage("Invalid type recieved for FCO from VPD.");
241}
242
243void IbmBiosHandler::saveFcoToVpd(int64_t i_fcoInBios)
244{
245 if (i_fcoInBios < 0)
246 {
247 logging::logMessage("Invalid FCO value in BIOS. Skip updating to VPD");
248 return;
249 }
250
251 // Read required keyword from Dbus.
252 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
253 constants::pimServiceName, constants::systemVpdInvPath,
254 constants::vsysInf, constants::kwdRG);
255
256 if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
257 {
258 // default length of the keyword is 4 bytes.
259 if (l_fcoInVpd->size() != constants::VALUE_4)
260 {
261 logging::logMessage(
262 "Invalid value read for FCO from D-Bus. Skipping.");
263 return;
264 }
265
266 // convert to VPD value type
267 types::BinaryVector l_biosValInVpdFormat = {
268 0, 0, 0, static_cast<uint8_t>(i_fcoInBios)};
269
270 // Update only when the data are different.
271 if (std::memcmp(l_biosValInVpdFormat.data(), l_fcoInVpd->data(),
272 constants::VALUE_4) != constants::SUCCESS)
273 {
274 if (constants::FAILURE ==
275 m_manager->updateKeyword(
276 SYSTEM_VPD_FILE_PATH,
277 types::IpzData("VSYS", constants::kwdRG,
278 l_biosValInVpdFormat)))
279 {
280 logging::logMessage(
281 "Failed to update " + std::string(constants::kwdRG) +
282 " keyword to VPD.");
283 }
284 }
285 }
286 else
287 {
288 logging::logMessage("Invalid type read for FCO from DBus.");
289 }
290}
291
292void IbmBiosHandler::saveFcoToBios(const types::BinaryVector& i_fcoVal)
293{
294 if (i_fcoVal.size() != constants::VALUE_4)
295 {
296 logging::logMessage("Bad size for FCO received. Skip writing to BIOS");
297 return;
298 }
299
300 types::PendingBIOSAttrs l_pendingBiosAttribute;
301 l_pendingBiosAttribute.push_back(std::make_pair(
302 "hb_field_core_override",
303 std::make_tuple(
304 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer",
305 i_fcoVal.at(constants::VALUE_3))));
306
RekhaAparna01c532b182025-02-19 19:56:49 -0600307 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500308 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
309 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600310 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500311 {
312 // TODO: Should we log informational PEL here as well?
313 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600314 "DBus call to update FCO value in pending attribute failed. ");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500315 }
316}
317
318void IbmBiosHandler::saveAmmToVpd(const std::string& i_memoryMirrorMode)
319{
320 if (i_memoryMirrorMode.empty())
321 {
322 logging::logMessage(
323 "Empty memory mirror mode value from BIOS. Skip writing to VPD");
324 return;
325 }
326
327 // Read existing value.
328 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
329 constants::pimServiceName, constants::systemVpdInvPath,
330 constants::utilInf, constants::kwdAMM);
331
332 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
333 {
334 auto l_ammValInVpd = *l_pVal;
335
336 types::BinaryVector l_valToUpdateInVpd{
337 (i_memoryMirrorMode == "Enabled" ? constants::AMM_ENABLED_IN_VPD
338 : constants::AMM_DISABLED_IN_VPD)};
339
340 // Check if value is already updated on VPD.
341 if (l_ammValInVpd.at(0) == l_valToUpdateInVpd.at(0))
342 {
343 return;
344 }
345
346 if (constants::FAILURE ==
347 m_manager->updateKeyword(
348 SYSTEM_VPD_FILE_PATH,
349 types::IpzData("UTIL", constants::kwdAMM, l_valToUpdateInVpd)))
350 {
351 logging::logMessage(
352 "Failed to update " + std::string(constants::kwdAMM) +
353 " keyword to VPD");
354 }
355 }
356 else
357 {
358 // TODO: Add PEL
359 logging::logMessage(
360 "Invalid type read for memory mirror mode value from DBus. Skip writing to VPD");
361 }
362}
363
Anupama B R3aca2932025-03-05 22:37:15 -0600364void IbmBiosHandler::saveAmmToBios(const uint8_t& i_ammVal)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500365{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500366 const std::string l_valtoUpdate =
Anupama B R3aca2932025-03-05 22:37:15 -0600367 (i_ammVal == constants::VALUE_2) ? "Enabled" : "Disabled";
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500368
369 types::PendingBIOSAttrs l_pendingBiosAttribute;
370 l_pendingBiosAttribute.push_back(std::make_pair(
371 "hb_memory_mirror_mode",
372 std::make_tuple(
373 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
374 l_valtoUpdate)));
375
RekhaAparna01c532b182025-02-19 19:56:49 -0600376 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500377 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
378 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600379 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500380 {
381 // TODO: Should we log informational PEL here as well?
382 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600383 "DBus call to update AMM value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500384 }
385}
386
387void IbmBiosHandler::processActiveMemoryMirror()
388{
389 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
390 constants::pimServiceName, constants::systemVpdInvPath,
391 constants::utilInf, constants::kwdAMM);
392
393 if (auto pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
394 {
395 auto l_ammValInVpd = *pVal;
396
397 // Check if active memory mirror value is default in VPD.
398 if (l_ammValInVpd.at(0) == constants::VALUE_0)
399 {
400 types::BiosAttributeCurrentValue l_attrValueVariant =
401 readBiosAttribute("hb_memory_mirror_mode");
402
403 if (auto pVal = std::get_if<std::string>(&l_attrValueVariant))
404 {
405 saveAmmToVpd(*pVal);
406 return;
407 }
408 logging::logMessage(
409 "Invalid type recieved for auto memory mirror mode from BIOS.");
410 return;
411 }
412 else
413 {
Anupama B R3aca2932025-03-05 22:37:15 -0600414 saveAmmToBios(l_ammValInVpd.at(0));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500415 }
416 return;
417 }
418 logging::logMessage(
419 "Invalid type recieved for auto memory mirror mode from VPD.");
420}
421
422void IbmBiosHandler::saveCreateDefaultLparToVpd(
423 const std::string& i_createDefaultLparVal)
424{
425 if (i_createDefaultLparVal.empty())
426 {
427 logging::logMessage(
428 "Empty value received for Lpar from BIOS. Skip writing in VPD.");
429 return;
430 }
431
432 // Read required keyword from DBus as we need to set only a Bit.
433 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
434 constants::pimServiceName, constants::systemVpdInvPath,
435 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
436
437 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
438 {
439 commonUtility::toLower(
440 const_cast<std::string&>(i_createDefaultLparVal));
441
442 // Check for second bit. Bit set for enabled else disabled.
443 if (((((*l_pVal).at(0) & 0x02) == 0x02) &&
444 (i_createDefaultLparVal.compare("enabled") ==
445 constants::STR_CMP_SUCCESS)) ||
446 ((((*l_pVal).at(0) & 0x02) == 0x00) &&
447 (i_createDefaultLparVal.compare("disabled") ==
448 constants::STR_CMP_SUCCESS)))
449 {
450 // Values are same, Don;t update.
451 return;
452 }
453
454 types::BinaryVector l_valToUpdateInVpd;
455 if (i_createDefaultLparVal.compare("enabled") ==
456 constants::STR_CMP_SUCCESS)
457 {
458 // 2nd Bit is used to store the value.
459 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) | 0x02);
460 }
461 else
462 {
463 // 2nd Bit is used to store the value.
464 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) & ~(0x02));
465 }
466
467 if (-1 ==
468 m_manager->updateKeyword(
469 SYSTEM_VPD_FILE_PATH,
470 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
471 l_valToUpdateInVpd)))
472 {
473 logging::logMessage(
474 "Failed to update " +
475 std::string(constants::kwdClearNVRAM_CreateLPAR) +
476 " keyword to VPD");
477 }
478
479 return;
480 }
481 logging::logMessage(
482 "Invalid type recieved for create default Lpar from VPD.");
483}
484
485void IbmBiosHandler::saveCreateDefaultLparToBios(
486 const std::string& i_createDefaultLparVal)
487{
488 // checking for exact length as it is a string and can have garbage value.
489 if (i_createDefaultLparVal.size() != constants::VALUE_1)
490 {
491 logging::logMessage(
492 "Bad size for Create default LPAR in VPD. Skip writing to BIOS.");
493 return;
494 }
495
496 std::string l_valtoUpdate =
497 (i_createDefaultLparVal.at(0) & 0x02) ? "Enabled" : "Disabled";
498
499 types::PendingBIOSAttrs l_pendingBiosAttribute;
500 l_pendingBiosAttribute.push_back(std::make_pair(
501 "pvm_create_default_lpar",
502 std::make_tuple(
503 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
504 l_valtoUpdate)));
505
RekhaAparna01c532b182025-02-19 19:56:49 -0600506 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500507 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
508 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600509 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500510 {
511 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600512 "DBus call to update lpar value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500513 }
514
515 return;
516}
517
518void IbmBiosHandler::processCreateDefaultLpar()
519{
520 // Read required keyword from DBus.
521 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
522 constants::pimServiceName, constants::systemVpdInvPath,
523 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
524
525 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
526 {
527 saveCreateDefaultLparToBios(std::to_string(l_pVal->at(0)));
528 return;
529 }
530 logging::logMessage(
531 "Invalid type recieved for create default Lpar from VPD.");
532}
533
534void IbmBiosHandler::saveClearNvramToVpd(const std::string& i_clearNvramVal)
535{
536 if (i_clearNvramVal.empty())
537 {
538 logging::logMessage(
539 "Empty value received for clear NVRAM from BIOS. Skip updating to VPD.");
540 return;
541 }
542
543 // Read required keyword from DBus as we need to set only a Bit.
544 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
545 constants::pimServiceName, constants::systemVpdInvPath,
546 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
547
548 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
549 {
550 commonUtility::toLower(const_cast<std::string&>(i_clearNvramVal));
551
552 // Check for third bit. Bit set for enabled else disabled.
553 if (((((*l_pVal).at(0) & 0x04) == 0x04) &&
554 (i_clearNvramVal.compare("enabled") ==
555 constants::STR_CMP_SUCCESS)) ||
556 ((((*l_pVal).at(0) & 0x04) == 0x00) &&
557 (i_clearNvramVal.compare("disabled") ==
558 constants::STR_CMP_SUCCESS)))
559 {
560 // Don't update, values are same.
561 return;
562 }
563
564 types::BinaryVector l_valToUpdateInVpd;
565 if (i_clearNvramVal.compare("enabled") == constants::STR_CMP_SUCCESS)
566 {
567 // 3rd bit is used to store the value.
568 l_valToUpdateInVpd.emplace_back(
569 (*l_pVal).at(0) | constants::VALUE_4);
570 }
571 else
572 {
573 // 3rd bit is used to store the value.
574 l_valToUpdateInVpd.emplace_back(
575 (*l_pVal).at(0) & ~(constants::VALUE_4));
576 }
577
578 if (-1 ==
579 m_manager->updateKeyword(
580 SYSTEM_VPD_FILE_PATH,
581 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
582 l_valToUpdateInVpd)))
583 {
584 logging::logMessage(
585 "Failed to update " +
586 std::string(constants::kwdClearNVRAM_CreateLPAR) +
587 " keyword to VPD");
588 }
589
590 return;
591 }
592 logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
593}
594
595void IbmBiosHandler::saveClearNvramToBios(const std::string& i_clearNvramVal)
596{
597 // Check for the exact length as it is a string and it can have a garbage
598 // value.
599 if (i_clearNvramVal.size() != constants::VALUE_1)
600 {
601 logging::logMessage(
602 "Bad size for clear NVRAM in VPD. Skip writing to BIOS.");
603 return;
604 }
605
606 // 3rd bit is used to store clear NVRAM value.
607 std::string l_valtoUpdate =
608 (i_clearNvramVal.at(0) & constants::VALUE_4) ? "Enabled" : "Disabled";
609
610 types::PendingBIOSAttrs l_pendingBiosAttribute;
611 l_pendingBiosAttribute.push_back(std::make_pair(
612 "pvm_clear_nvram",
613 std::make_tuple(
614 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
615 l_valtoUpdate)));
616
RekhaAparna01c532b182025-02-19 19:56:49 -0600617 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500618 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
619 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600620 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500621 {
622 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600623 "DBus call to update NVRAM value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500624 }
625}
626
627void IbmBiosHandler::processClearNvram()
628{
629 // Read required keyword from VPD.
630 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
631 constants::pimServiceName, constants::systemVpdInvPath,
632 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
633
634 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
635 {
636 saveClearNvramToBios(std::to_string(l_pVal->at(0)));
637 return;
638 }
639 logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
640}
641
642void IbmBiosHandler::saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal)
643{
644 if (i_KeepAndClearVal.empty())
645 {
646 logging::logMessage(
647 "Empty value received for keep and clear from BIOS. Skip updating to VPD.");
648 return;
649 }
650
651 // Read required keyword from DBus as we need to set only a Bit.
652 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
653 constants::pimServiceName, constants::systemVpdInvPath,
654 constants::utilInf, constants::kwdKeepAndClear);
655
656 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
657 {
658 commonUtility::toLower(const_cast<std::string&>(i_KeepAndClearVal));
659
660 // Check for first bit. Bit set for enabled else disabled.
661 if (((((*l_pVal).at(0) & 0x01) == 0x01) &&
662 (i_KeepAndClearVal.compare("enabled") ==
663 constants::STR_CMP_SUCCESS)) ||
664 ((((*l_pVal).at(0) & 0x01) == 0x00) &&
665 (i_KeepAndClearVal.compare("disabled") ==
666 constants::STR_CMP_SUCCESS)))
667 {
668 // Don't update, values are same.
669 return;
670 }
671
672 types::BinaryVector l_valToUpdateInVpd;
673 if (i_KeepAndClearVal.compare("enabled") == constants::STR_CMP_SUCCESS)
674 {
675 // 1st bit is used to store the value.
676 l_valToUpdateInVpd.emplace_back(
677 (*l_pVal).at(0) | constants::VALUE_1);
678 }
679 else
680 {
681 // 1st bit is used to store the value.
682 l_valToUpdateInVpd.emplace_back(
683 (*l_pVal).at(0) & ~(constants::VALUE_1));
684 }
685
686 if (-1 == m_manager->updateKeyword(
687 SYSTEM_VPD_FILE_PATH,
688 types::IpzData("UTIL", constants::kwdKeepAndClear,
689 l_valToUpdateInVpd)))
690 {
691 logging::logMessage(
692 "Failed to update " + std::string(constants::kwdKeepAndClear) +
693 " keyword to VPD");
694 }
695
696 return;
697 }
698 logging::logMessage("Invalid type recieved for keep and clear from VPD.");
699}
700
Patrick Williams43fedab2025-02-03 14:28:05 -0500701void IbmBiosHandler::saveKeepAndClearToBios(
702 const std::string& i_KeepAndClearVal)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500703{
704 // checking for exact length as it is a string and can have garbage value.
705 if (i_KeepAndClearVal.size() != constants::VALUE_1)
706 {
707 logging::logMessage(
708 "Bad size for keep and clear in VPD. Skip writing to BIOS.");
709 return;
710 }
711
712 // 1st bit is used to store keep and clear value.
713 std::string l_valtoUpdate =
714 (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled";
715
716 types::PendingBIOSAttrs l_pendingBiosAttribute;
717 l_pendingBiosAttribute.push_back(std::make_pair(
718 "pvm_keep_and_clear",
719 std::make_tuple(
720 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
721 l_valtoUpdate)));
722
RekhaAparna01c532b182025-02-19 19:56:49 -0600723 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500724 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
725 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600726 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500727 {
728 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600729 "DBus call to update keep and clear value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500730 }
731}
732
733void IbmBiosHandler::processKeepAndClear()
734{
735 // Read required keyword from VPD.
736 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
737 constants::pimServiceName, constants::systemVpdInvPath,
738 constants::utilInf, constants::kwdKeepAndClear);
739
740 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
741 {
742 saveKeepAndClearToBios(std::to_string(l_pVal->at(0)));
743 return;
744 }
745 logging::logMessage("Invalid type recieved for keep and clear from VPD.");
746}
747} // namespace vpd