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