blob: 65e0c47c7c64e83d8a05743136e9698f5364def9 [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
Patrick Williams43fedab2025-02-03 14:28:05 -0500173types::BiosAttributeCurrentValue IbmBiosHandler::readBiosAttribute(
174 const std::string& i_attributeName)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500175{
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
RekhaAparna01c532b182025-02-19 19:56:49 -0600293 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500294 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
295 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600296 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500297 {
298 // TODO: Should we log informational PEL here as well?
299 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600300 "DBus call to update FCO value in pending attribute failed. ");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500301 }
302}
303
304void 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
350void IbmBiosHandler::saveAmmToBios(const std::string& i_ammVal)
351{
352 if (i_ammVal.size() != constants::VALUE_1)
353 {
354 logging::logMessage("Bad size for AMM received, Skip writing to BIOS");
355 return;
356 }
357
358 const std::string l_valtoUpdate =
359 (i_ammVal.at(0) == constants::VALUE_2) ? "Enabled" : "Disabled";
360
361 types::PendingBIOSAttrs l_pendingBiosAttribute;
362 l_pendingBiosAttribute.push_back(std::make_pair(
363 "hb_memory_mirror_mode",
364 std::make_tuple(
365 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
366 l_valtoUpdate)));
367
RekhaAparna01c532b182025-02-19 19:56:49 -0600368 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500369 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
370 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600371 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500372 {
373 // TODO: Should we log informational PEL here as well?
374 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600375 "DBus call to update AMM value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500376 }
377}
378
379void IbmBiosHandler::processActiveMemoryMirror()
380{
381 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
382 constants::pimServiceName, constants::systemVpdInvPath,
383 constants::utilInf, constants::kwdAMM);
384
385 if (auto pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
386 {
387 auto l_ammValInVpd = *pVal;
388
389 // Check if active memory mirror value is default in VPD.
390 if (l_ammValInVpd.at(0) == constants::VALUE_0)
391 {
392 types::BiosAttributeCurrentValue l_attrValueVariant =
393 readBiosAttribute("hb_memory_mirror_mode");
394
395 if (auto pVal = std::get_if<std::string>(&l_attrValueVariant))
396 {
397 saveAmmToVpd(*pVal);
398 return;
399 }
400 logging::logMessage(
401 "Invalid type recieved for auto memory mirror mode from BIOS.");
402 return;
403 }
404 else
405 {
406 saveAmmToBios(std::to_string(l_ammValInVpd.at(0)));
407 }
408 return;
409 }
410 logging::logMessage(
411 "Invalid type recieved for auto memory mirror mode from VPD.");
412}
413
414void IbmBiosHandler::saveCreateDefaultLparToVpd(
415 const std::string& i_createDefaultLparVal)
416{
417 if (i_createDefaultLparVal.empty())
418 {
419 logging::logMessage(
420 "Empty value received for Lpar from BIOS. Skip writing in VPD.");
421 return;
422 }
423
424 // Read required keyword from DBus as we need to set only a Bit.
425 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
426 constants::pimServiceName, constants::systemVpdInvPath,
427 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
428
429 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
430 {
431 commonUtility::toLower(
432 const_cast<std::string&>(i_createDefaultLparVal));
433
434 // Check for second bit. Bit set for enabled else disabled.
435 if (((((*l_pVal).at(0) & 0x02) == 0x02) &&
436 (i_createDefaultLparVal.compare("enabled") ==
437 constants::STR_CMP_SUCCESS)) ||
438 ((((*l_pVal).at(0) & 0x02) == 0x00) &&
439 (i_createDefaultLparVal.compare("disabled") ==
440 constants::STR_CMP_SUCCESS)))
441 {
442 // Values are same, Don;t update.
443 return;
444 }
445
446 types::BinaryVector l_valToUpdateInVpd;
447 if (i_createDefaultLparVal.compare("enabled") ==
448 constants::STR_CMP_SUCCESS)
449 {
450 // 2nd Bit is used to store the value.
451 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) | 0x02);
452 }
453 else
454 {
455 // 2nd Bit is used to store the value.
456 l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) & ~(0x02));
457 }
458
459 if (-1 ==
460 m_manager->updateKeyword(
461 SYSTEM_VPD_FILE_PATH,
462 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
463 l_valToUpdateInVpd)))
464 {
465 logging::logMessage(
466 "Failed to update " +
467 std::string(constants::kwdClearNVRAM_CreateLPAR) +
468 " keyword to VPD");
469 }
470
471 return;
472 }
473 logging::logMessage(
474 "Invalid type recieved for create default Lpar from VPD.");
475}
476
477void IbmBiosHandler::saveCreateDefaultLparToBios(
478 const std::string& i_createDefaultLparVal)
479{
480 // checking for exact length as it is a string and can have garbage value.
481 if (i_createDefaultLparVal.size() != constants::VALUE_1)
482 {
483 logging::logMessage(
484 "Bad size for Create default LPAR in VPD. Skip writing to BIOS.");
485 return;
486 }
487
488 std::string l_valtoUpdate =
489 (i_createDefaultLparVal.at(0) & 0x02) ? "Enabled" : "Disabled";
490
491 types::PendingBIOSAttrs l_pendingBiosAttribute;
492 l_pendingBiosAttribute.push_back(std::make_pair(
493 "pvm_create_default_lpar",
494 std::make_tuple(
495 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
496 l_valtoUpdate)));
497
RekhaAparna01c532b182025-02-19 19:56:49 -0600498 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500499 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
500 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600501 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500502 {
503 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600504 "DBus call to update lpar value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500505 }
506
507 return;
508}
509
510void IbmBiosHandler::processCreateDefaultLpar()
511{
512 // Read required keyword from DBus.
513 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
514 constants::pimServiceName, constants::systemVpdInvPath,
515 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
516
517 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
518 {
519 saveCreateDefaultLparToBios(std::to_string(l_pVal->at(0)));
520 return;
521 }
522 logging::logMessage(
523 "Invalid type recieved for create default Lpar from VPD.");
524}
525
526void IbmBiosHandler::saveClearNvramToVpd(const std::string& i_clearNvramVal)
527{
528 if (i_clearNvramVal.empty())
529 {
530 logging::logMessage(
531 "Empty value received for clear NVRAM from BIOS. Skip updating to VPD.");
532 return;
533 }
534
535 // Read required keyword from DBus as we need to set only a Bit.
536 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
537 constants::pimServiceName, constants::systemVpdInvPath,
538 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
539
540 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
541 {
542 commonUtility::toLower(const_cast<std::string&>(i_clearNvramVal));
543
544 // Check for third bit. Bit set for enabled else disabled.
545 if (((((*l_pVal).at(0) & 0x04) == 0x04) &&
546 (i_clearNvramVal.compare("enabled") ==
547 constants::STR_CMP_SUCCESS)) ||
548 ((((*l_pVal).at(0) & 0x04) == 0x00) &&
549 (i_clearNvramVal.compare("disabled") ==
550 constants::STR_CMP_SUCCESS)))
551 {
552 // Don't update, values are same.
553 return;
554 }
555
556 types::BinaryVector l_valToUpdateInVpd;
557 if (i_clearNvramVal.compare("enabled") == constants::STR_CMP_SUCCESS)
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 else
564 {
565 // 3rd bit is used to store the value.
566 l_valToUpdateInVpd.emplace_back(
567 (*l_pVal).at(0) & ~(constants::VALUE_4));
568 }
569
570 if (-1 ==
571 m_manager->updateKeyword(
572 SYSTEM_VPD_FILE_PATH,
573 types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
574 l_valToUpdateInVpd)))
575 {
576 logging::logMessage(
577 "Failed to update " +
578 std::string(constants::kwdClearNVRAM_CreateLPAR) +
579 " keyword to VPD");
580 }
581
582 return;
583 }
584 logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
585}
586
587void IbmBiosHandler::saveClearNvramToBios(const std::string& i_clearNvramVal)
588{
589 // Check for the exact length as it is a string and it can have a garbage
590 // value.
591 if (i_clearNvramVal.size() != constants::VALUE_1)
592 {
593 logging::logMessage(
594 "Bad size for clear NVRAM in VPD. Skip writing to BIOS.");
595 return;
596 }
597
598 // 3rd bit is used to store clear NVRAM value.
599 std::string l_valtoUpdate =
600 (i_clearNvramVal.at(0) & constants::VALUE_4) ? "Enabled" : "Disabled";
601
602 types::PendingBIOSAttrs l_pendingBiosAttribute;
603 l_pendingBiosAttribute.push_back(std::make_pair(
604 "pvm_clear_nvram",
605 std::make_tuple(
606 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
607 l_valtoUpdate)));
608
RekhaAparna01c532b182025-02-19 19:56:49 -0600609 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500610 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
611 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600612 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500613 {
614 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600615 "DBus call to update NVRAM value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500616 }
617}
618
619void IbmBiosHandler::processClearNvram()
620{
621 // Read required keyword from VPD.
622 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
623 constants::pimServiceName, constants::systemVpdInvPath,
624 constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
625
626 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
627 {
628 saveClearNvramToBios(std::to_string(l_pVal->at(0)));
629 return;
630 }
631 logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
632}
633
634void IbmBiosHandler::saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal)
635{
636 if (i_KeepAndClearVal.empty())
637 {
638 logging::logMessage(
639 "Empty value received for keep and clear from BIOS. Skip updating to VPD.");
640 return;
641 }
642
643 // Read required keyword from DBus as we need to set only a Bit.
644 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
645 constants::pimServiceName, constants::systemVpdInvPath,
646 constants::utilInf, constants::kwdKeepAndClear);
647
648 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
649 {
650 commonUtility::toLower(const_cast<std::string&>(i_KeepAndClearVal));
651
652 // Check for first bit. Bit set for enabled else disabled.
653 if (((((*l_pVal).at(0) & 0x01) == 0x01) &&
654 (i_KeepAndClearVal.compare("enabled") ==
655 constants::STR_CMP_SUCCESS)) ||
656 ((((*l_pVal).at(0) & 0x01) == 0x00) &&
657 (i_KeepAndClearVal.compare("disabled") ==
658 constants::STR_CMP_SUCCESS)))
659 {
660 // Don't update, values are same.
661 return;
662 }
663
664 types::BinaryVector l_valToUpdateInVpd;
665 if (i_KeepAndClearVal.compare("enabled") == constants::STR_CMP_SUCCESS)
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 else
672 {
673 // 1st bit is used to store the value.
674 l_valToUpdateInVpd.emplace_back(
675 (*l_pVal).at(0) & ~(constants::VALUE_1));
676 }
677
678 if (-1 == m_manager->updateKeyword(
679 SYSTEM_VPD_FILE_PATH,
680 types::IpzData("UTIL", constants::kwdKeepAndClear,
681 l_valToUpdateInVpd)))
682 {
683 logging::logMessage(
684 "Failed to update " + std::string(constants::kwdKeepAndClear) +
685 " keyword to VPD");
686 }
687
688 return;
689 }
690 logging::logMessage("Invalid type recieved for keep and clear from VPD.");
691}
692
Patrick Williams43fedab2025-02-03 14:28:05 -0500693void IbmBiosHandler::saveKeepAndClearToBios(
694 const std::string& i_KeepAndClearVal)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500695{
696 // checking for exact length as it is a string and can have garbage value.
697 if (i_KeepAndClearVal.size() != constants::VALUE_1)
698 {
699 logging::logMessage(
700 "Bad size for keep and clear in VPD. Skip writing to BIOS.");
701 return;
702 }
703
704 // 1st bit is used to store keep and clear value.
705 std::string l_valtoUpdate =
706 (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled";
707
708 types::PendingBIOSAttrs l_pendingBiosAttribute;
709 l_pendingBiosAttribute.push_back(std::make_pair(
710 "pvm_keep_and_clear",
711 std::make_tuple(
712 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
713 l_valtoUpdate)));
714
RekhaAparna01c532b182025-02-19 19:56:49 -0600715 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500716 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
717 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600718 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500719 {
720 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600721 "DBus call to update keep and clear value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500722 }
723}
724
725void IbmBiosHandler::processKeepAndClear()
726{
727 // Read required keyword from VPD.
728 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
729 constants::pimServiceName, constants::systemVpdInvPath,
730 constants::utilInf, constants::kwdKeepAndClear);
731
732 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
733 {
734 saveKeepAndClearToBios(std::to_string(l_pVal->at(0)));
735 return;
736 }
737 logging::logMessage("Invalid type recieved for keep and clear from VPD.");
738}
739} // namespace vpd