1 #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
14 namespace vpd
15 {
16 // Template declaration to define APIs.
17 template class BiosHandler<IbmBiosHandler>;
18
19 template <typename T>
checkAndListenPldmService()20 void 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
68 template <typename T>
listenBiosAttributes()69 void 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
biosAttributesCallback(sdbusplus::message_t & i_msg)82 void 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
backUpOrRestoreBiosAttributes()155 void 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
readBiosAttribute(const std::string & i_attributeName)173 types::BiosAttributeCurrentValue IbmBiosHandler::readBiosAttribute(
174 const std::string& i_attributeName)
175 {
176 types::BiosAttributeCurrentValue l_attrValueVariant =
177 dbusUtility::biosGetAttributeMethodCall(i_attributeName);
178
179 return l_attrValueVariant;
180 }
181
processFieldCoreOverride()182 void 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
saveFcoToVpd(int64_t i_fcoInBios)229 void 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
saveFcoToBios(const types::BinaryVector & i_fcoVal)278 void 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 if (!dbusUtility::writeDbusProperty(
294 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
295 constants::biosConfigMgrInterface, "PendingAttributes",
296 l_pendingBiosAttribute))
297 {
298 // TODO: Should we log informational PEL here as well?
299 logging::logMessage(
300 "DBus call to update FCO value in pending attribute failed. ");
301 }
302 }
303
saveAmmToVpd(const std::string & i_memoryMirrorMode)304 void IbmBiosHandler::saveAmmToVpd(const std::string& i_memoryMirrorMode)
305 {
306 if (i_memoryMirrorMode.empty())
307 {
308 logging::logMessage(
309 "Empty memory mirror mode value from BIOS. Skip writing to VPD");
310 return;
311 }
312
313 // Read existing value.
314 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
315 constants::pimServiceName, constants::systemVpdInvPath,
316 constants::utilInf, constants::kwdAMM);
317
318 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
319 {
320 auto l_ammValInVpd = *l_pVal;
321
322 types::BinaryVector l_valToUpdateInVpd{
323 (i_memoryMirrorMode == "Enabled" ? constants::AMM_ENABLED_IN_VPD
324 : constants::AMM_DISABLED_IN_VPD)};
325
326 // Check if value is already updated on VPD.
327 if (l_ammValInVpd.at(0) == l_valToUpdateInVpd.at(0))
328 {
329 return;
330 }
331
332 if (constants::FAILURE ==
333 m_manager->updateKeyword(
334 SYSTEM_VPD_FILE_PATH,
335 types::IpzData("UTIL", constants::kwdAMM, l_valToUpdateInVpd)))
336 {
337 logging::logMessage(
338 "Failed to update " + std::string(constants::kwdAMM) +
339 " keyword to VPD");
340 }
341 }
342 else
343 {
344 // TODO: Add PEL
345 logging::logMessage(
346 "Invalid type read for memory mirror mode value from DBus. Skip writing to VPD");
347 }
348 }
349
saveAmmToBios(const uint8_t & i_ammVal)350 void IbmBiosHandler::saveAmmToBios(const uint8_t& i_ammVal)
351 {
352 const std::string l_valtoUpdate =
353 (i_ammVal == constants::VALUE_2) ? "Enabled" : "Disabled";
354
355 types::PendingBIOSAttrs l_pendingBiosAttribute;
356 l_pendingBiosAttribute.push_back(std::make_pair(
357 "hb_memory_mirror_mode",
358 std::make_tuple(
359 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
360 l_valtoUpdate)));
361
362 if (!dbusUtility::writeDbusProperty(
363 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
364 constants::biosConfigMgrInterface, "PendingAttributes",
365 l_pendingBiosAttribute))
366 {
367 // TODO: Should we log informational PEL here as well?
368 logging::logMessage(
369 "DBus call to update AMM value in pending attribute failed.");
370 }
371 }
372
processActiveMemoryMirror()373 void IbmBiosHandler::processActiveMemoryMirror()
374 {
375 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
376 constants::pimServiceName, constants::systemVpdInvPath,
377 constants::utilInf, constants::kwdAMM);
378
379 if (auto pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
380 {
381 auto l_ammValInVpd = *pVal;
382
383 // Check if active memory mirror value is default in VPD.
384 if (l_ammValInVpd.at(0) == constants::VALUE_0)
385 {
386 types::BiosAttributeCurrentValue l_attrValueVariant =
387 readBiosAttribute("hb_memory_mirror_mode");
388
389 if (auto pVal = std::get_if<std::string>(&l_attrValueVariant))
390 {
391 saveAmmToVpd(*pVal);
392 return;
393 }
394 logging::logMessage(
395 "Invalid type recieved for auto memory mirror mode from BIOS.");
396 return;
397 }
398 else
399 {
400 saveAmmToBios(l_ammValInVpd.at(0));
401 }
402 return;
403 }
404 logging::logMessage(
405 "Invalid type recieved for auto memory mirror mode from VPD.");
406 }
407
saveCreateDefaultLparToVpd(const std::string & i_createDefaultLparVal)408 void IbmBiosHandler::saveCreateDefaultLparToVpd(
409 const std::string& i_createDefaultLparVal)
410 {
411 if (i_createDefaultLparVal.empty())
412 {
413 logging::logMessage(
414 "Empty value received for Lpar from BIOS. Skip writing in VPD.");
415 return;
416 }
417
418 // Read required keyword from DBus as we need to set only a Bit.
419 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
420 constants::pimServiceName, constants::systemVpdInvPath,
421 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
422
423 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
424 {
425 commonUtility::toLower(
426 const_cast<std::string&>(i_createDefaultLparVal));
427
428 // Check for second bit. Bit set for enabled else disabled.
429 if (((((*l_pVal).at(0) & 0x02) == 0x02) &&
430 (i_createDefaultLparVal.compare("enabled") ==
431 constants::STR_CMP_SUCCESS)) ||
432 ((((*l_pVal).at(0) & 0x02) == 0x00) &&
433 (i_createDefaultLparVal.compare("disabled") ==
434 constants::STR_CMP_SUCCESS)))
435 {
436 // Values are same, Don;t update.
437 return;
438 }
439
440 types::BinaryVector l_valToUpdateInVpd;
441 if (i_createDefaultLparVal.compare("enabled") ==
442 constants::STR_CMP_SUCCESS)
443 {
444 // 2nd Bit is used to store the value.
445 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) | 0x02);
446 }
447 else
448 {
449 // 2nd Bit is used to store the value.
450 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) & ~(0x02));
451 }
452
453 if (-1 ==
454 m_manager->updateKeyword(
455 SYSTEM_VPD_FILE_PATH,
456 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
457 l_valToUpdateInVpd)))
458 {
459 logging::logMessage(
460 "Failed to update " +
461 std::string(constants::kwdClearNVRAM_CreateLPAR) +
462 " keyword to VPD");
463 }
464
465 return;
466 }
467 logging::logMessage(
468 "Invalid type recieved for create default Lpar from VPD.");
469 }
470
saveCreateDefaultLparToBios(const std::string & i_createDefaultLparVal)471 void IbmBiosHandler::saveCreateDefaultLparToBios(
472 const std::string& i_createDefaultLparVal)
473 {
474 // checking for exact length as it is a string and can have garbage value.
475 if (i_createDefaultLparVal.size() != constants::VALUE_1)
476 {
477 logging::logMessage(
478 "Bad size for Create default LPAR in VPD. Skip writing to BIOS.");
479 return;
480 }
481
482 std::string l_valtoUpdate =
483 (i_createDefaultLparVal.at(0) & 0x02) ? "Enabled" : "Disabled";
484
485 types::PendingBIOSAttrs l_pendingBiosAttribute;
486 l_pendingBiosAttribute.push_back(std::make_pair(
487 "pvm_create_default_lpar",
488 std::make_tuple(
489 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
490 l_valtoUpdate)));
491
492 if (!dbusUtility::writeDbusProperty(
493 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
494 constants::biosConfigMgrInterface, "PendingAttributes",
495 l_pendingBiosAttribute))
496 {
497 logging::logMessage(
498 "DBus call to update lpar value in pending attribute failed.");
499 }
500
501 return;
502 }
503
processCreateDefaultLpar()504 void IbmBiosHandler::processCreateDefaultLpar()
505 {
506 // Read required keyword from DBus.
507 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
508 constants::pimServiceName, constants::systemVpdInvPath,
509 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
510
511 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
512 {
513 saveCreateDefaultLparToBios(std::to_string(l_pVal->at(0)));
514 return;
515 }
516 logging::logMessage(
517 "Invalid type recieved for create default Lpar from VPD.");
518 }
519
saveClearNvramToVpd(const std::string & i_clearNvramVal)520 void IbmBiosHandler::saveClearNvramToVpd(const std::string& i_clearNvramVal)
521 {
522 if (i_clearNvramVal.empty())
523 {
524 logging::logMessage(
525 "Empty value received for clear NVRAM from BIOS. Skip updating to VPD.");
526 return;
527 }
528
529 // Read required keyword from DBus as we need to set only a Bit.
530 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
531 constants::pimServiceName, constants::systemVpdInvPath,
532 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
533
534 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
535 {
536 commonUtility::toLower(const_cast<std::string&>(i_clearNvramVal));
537
538 // Check for third bit. Bit set for enabled else disabled.
539 if (((((*l_pVal).at(0) & 0x04) == 0x04) &&
540 (i_clearNvramVal.compare("enabled") ==
541 constants::STR_CMP_SUCCESS)) ||
542 ((((*l_pVal).at(0) & 0x04) == 0x00) &&
543 (i_clearNvramVal.compare("disabled") ==
544 constants::STR_CMP_SUCCESS)))
545 {
546 // Don't update, values are same.
547 return;
548 }
549
550 types::BinaryVector l_valToUpdateInVpd;
551 if (i_clearNvramVal.compare("enabled") == constants::STR_CMP_SUCCESS)
552 {
553 // 3rd bit is used to store the value.
554 l_valToUpdateInVpd.emplace_back(
555 (*l_pVal).at(0) | constants::VALUE_4);
556 }
557 else
558 {
559 // 3rd bit is used to store the value.
560 l_valToUpdateInVpd.emplace_back(
561 (*l_pVal).at(0) & ~(constants::VALUE_4));
562 }
563
564 if (-1 ==
565 m_manager->updateKeyword(
566 SYSTEM_VPD_FILE_PATH,
567 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
568 l_valToUpdateInVpd)))
569 {
570 logging::logMessage(
571 "Failed to update " +
572 std::string(constants::kwdClearNVRAM_CreateLPAR) +
573 " keyword to VPD");
574 }
575
576 return;
577 }
578 logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
579 }
580
saveClearNvramToBios(const std::string & i_clearNvramVal)581 void IbmBiosHandler::saveClearNvramToBios(const std::string& i_clearNvramVal)
582 {
583 // Check for the exact length as it is a string and it can have a garbage
584 // value.
585 if (i_clearNvramVal.size() != constants::VALUE_1)
586 {
587 logging::logMessage(
588 "Bad size for clear NVRAM in VPD. Skip writing to BIOS.");
589 return;
590 }
591
592 // 3rd bit is used to store clear NVRAM value.
593 std::string l_valtoUpdate =
594 (i_clearNvramVal.at(0) & constants::VALUE_4) ? "Enabled" : "Disabled";
595
596 types::PendingBIOSAttrs l_pendingBiosAttribute;
597 l_pendingBiosAttribute.push_back(std::make_pair(
598 "pvm_clear_nvram",
599 std::make_tuple(
600 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
601 l_valtoUpdate)));
602
603 if (!dbusUtility::writeDbusProperty(
604 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
605 constants::biosConfigMgrInterface, "PendingAttributes",
606 l_pendingBiosAttribute))
607 {
608 logging::logMessage(
609 "DBus call to update NVRAM value in pending attribute failed.");
610 }
611 }
612
processClearNvram()613 void IbmBiosHandler::processClearNvram()
614 {
615 // Read required keyword from VPD.
616 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
617 constants::pimServiceName, constants::systemVpdInvPath,
618 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
619
620 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
621 {
622 saveClearNvramToBios(std::to_string(l_pVal->at(0)));
623 return;
624 }
625 logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
626 }
627
saveKeepAndClearToVpd(const std::string & i_KeepAndClearVal)628 void IbmBiosHandler::saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal)
629 {
630 if (i_KeepAndClearVal.empty())
631 {
632 logging::logMessage(
633 "Empty value received for keep and clear from BIOS. Skip updating to VPD.");
634 return;
635 }
636
637 // Read required keyword from DBus as we need to set only a Bit.
638 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
639 constants::pimServiceName, constants::systemVpdInvPath,
640 constants::utilInf, constants::kwdKeepAndClear);
641
642 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
643 {
644 commonUtility::toLower(const_cast<std::string&>(i_KeepAndClearVal));
645
646 // Check for first bit. Bit set for enabled else disabled.
647 if (((((*l_pVal).at(0) & 0x01) == 0x01) &&
648 (i_KeepAndClearVal.compare("enabled") ==
649 constants::STR_CMP_SUCCESS)) ||
650 ((((*l_pVal).at(0) & 0x01) == 0x00) &&
651 (i_KeepAndClearVal.compare("disabled") ==
652 constants::STR_CMP_SUCCESS)))
653 {
654 // Don't update, values are same.
655 return;
656 }
657
658 types::BinaryVector l_valToUpdateInVpd;
659 if (i_KeepAndClearVal.compare("enabled") == constants::STR_CMP_SUCCESS)
660 {
661 // 1st bit is used to store the value.
662 l_valToUpdateInVpd.emplace_back(
663 (*l_pVal).at(0) | constants::VALUE_1);
664 }
665 else
666 {
667 // 1st bit is used to store the value.
668 l_valToUpdateInVpd.emplace_back(
669 (*l_pVal).at(0) & ~(constants::VALUE_1));
670 }
671
672 if (-1 == m_manager->updateKeyword(
673 SYSTEM_VPD_FILE_PATH,
674 types::IpzData("UTIL", constants::kwdKeepAndClear,
675 l_valToUpdateInVpd)))
676 {
677 logging::logMessage(
678 "Failed to update " + std::string(constants::kwdKeepAndClear) +
679 " keyword to VPD");
680 }
681
682 return;
683 }
684 logging::logMessage("Invalid type recieved for keep and clear from VPD.");
685 }
686
saveKeepAndClearToBios(const std::string & i_KeepAndClearVal)687 void IbmBiosHandler::saveKeepAndClearToBios(
688 const std::string& i_KeepAndClearVal)
689 {
690 // checking for exact length as it is a string and can have garbage value.
691 if (i_KeepAndClearVal.size() != constants::VALUE_1)
692 {
693 logging::logMessage(
694 "Bad size for keep and clear in VPD. Skip writing to BIOS.");
695 return;
696 }
697
698 // 1st bit is used to store keep and clear value.
699 std::string l_valtoUpdate =
700 (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled";
701
702 types::PendingBIOSAttrs l_pendingBiosAttribute;
703 l_pendingBiosAttribute.push_back(std::make_pair(
704 "pvm_keep_and_clear",
705 std::make_tuple(
706 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
707 l_valtoUpdate)));
708
709 if (!dbusUtility::writeDbusProperty(
710 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
711 constants::biosConfigMgrInterface, "PendingAttributes",
712 l_pendingBiosAttribute))
713 {
714 logging::logMessage(
715 "DBus call to update keep and clear value in pending attribute failed.");
716 }
717 }
718
processKeepAndClear()719 void IbmBiosHandler::processKeepAndClear()
720 {
721 // Read required keyword from VPD.
722 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
723 constants::pimServiceName, constants::systemVpdInvPath,
724 constants::utilInf, constants::kwdKeepAndClear);
725
726 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
727 {
728 saveKeepAndClearToBios(std::to_string(l_pVal->at(0)));
729 return;
730 }
731 logging::logMessage("Invalid type recieved for keep and clear from VPD.");
732 }
733 } // namespace vpd
734