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