blob: 0a4386bfbe545dc737da588ccb4b32d7ae120088 [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,
Jinu Joy Thomas2bbe7f32025-09-26 00:05:53 -0500268 types::IpzData(constants::vsysInf, constants::kwdRG,
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500269 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,
Jinu Joy Thomas2bbe7f32025-09-26 00:05:53 -0500321 constants::vsysInf, constants::kwdAMM);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500322
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,
Jinu Joy Thomas2bbe7f32025-09-26 00:05:53 -0500340 types::IpzData(constants::vsysInf, constants::kwdAMM,
341 l_valToUpdateInVpd)))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500342 {
343 logging::logMessage(
344 "Failed to update " + std::string(constants::kwdAMM) +
345 " keyword to VPD");
346 }
347 }
348 else
349 {
350 // TODO: Add PEL
351 logging::logMessage(
352 "Invalid type read for memory mirror mode value from DBus. Skip writing to VPD");
353 }
354}
355
Anupama B R3aca2932025-03-05 22:37:15 -0600356void IbmBiosHandler::saveAmmToBios(const uint8_t& i_ammVal)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500357{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500358 const std::string l_valtoUpdate =
Anupama B R3aca2932025-03-05 22:37:15 -0600359 (i_ammVal == constants::VALUE_2) ? "Enabled" : "Disabled";
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500360
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,
Jinu Joy Thomas2bbe7f32025-09-26 00:05:53 -0500383 constants::vsysInf, constants::kwdAMM);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500384
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 {
Anupama B R3aca2932025-03-05 22:37:15 -0600406 saveAmmToBios(l_ammValInVpd.at(0));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500407 }
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,
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500427 constants::vsysInf, constants::kwdClearNVRAM_CreateLPAR);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500428
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
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500459 if (-1 == m_manager->updateKeyword(
460 SYSTEM_VPD_FILE_PATH,
461 types::IpzData(constants::vsysInf,
462 constants::kwdClearNVRAM_CreateLPAR,
463 l_valToUpdateInVpd)))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500464 {
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,
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500515 constants::vsysInf, constants::kwdClearNVRAM_CreateLPAR);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500516
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,
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500538 constants::vsysInf, constants::kwdClearNVRAM_CreateLPAR);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500539
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
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500570 if (-1 == m_manager->updateKeyword(
571 SYSTEM_VPD_FILE_PATH,
572 types::IpzData(constants::vsysInf,
573 constants::kwdClearNVRAM_CreateLPAR,
574 l_valToUpdateInVpd)))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500575 {
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,
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500624 constants::vsysInf, constants::kwdClearNVRAM_CreateLPAR);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500625
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,
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500646 constants::vsysInf, constants::kwdKeepAndClear);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500647
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
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500678 if (-1 ==
679 m_manager->updateKeyword(
680 SYSTEM_VPD_FILE_PATH,
681 types::IpzData(constants::vsysInf, constants::kwdKeepAndClear,
682 l_valToUpdateInVpd)))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500683 {
684 logging::logMessage(
685 "Failed to update " + std::string(constants::kwdKeepAndClear) +
686 " keyword to VPD");
687 }
688
689 return;
690 }
691 logging::logMessage("Invalid type recieved for keep and clear from VPD.");
692}
693
Patrick Williams43fedab2025-02-03 14:28:05 -0500694void IbmBiosHandler::saveKeepAndClearToBios(
695 const std::string& i_KeepAndClearVal)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500696{
697 // checking for exact length as it is a string and can have garbage value.
698 if (i_KeepAndClearVal.size() != constants::VALUE_1)
699 {
700 logging::logMessage(
701 "Bad size for keep and clear in VPD. Skip writing to BIOS.");
702 return;
703 }
704
705 // 1st bit is used to store keep and clear value.
706 std::string l_valtoUpdate =
707 (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled";
708
709 types::PendingBIOSAttrs l_pendingBiosAttribute;
710 l_pendingBiosAttribute.push_back(std::make_pair(
711 "pvm_keep_and_clear",
712 std::make_tuple(
713 "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
714 l_valtoUpdate)));
715
RekhaAparna01c532b182025-02-19 19:56:49 -0600716 if (!dbusUtility::writeDbusProperty(
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500717 constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
718 constants::biosConfigMgrInterface, "PendingAttributes",
RekhaAparna01c532b182025-02-19 19:56:49 -0600719 l_pendingBiosAttribute))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500720 {
721 logging::logMessage(
RekhaAparna01c532b182025-02-19 19:56:49 -0600722 "DBus call to update keep and clear value in pending attribute failed.");
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500723 }
724}
725
726void IbmBiosHandler::processKeepAndClear()
727{
728 // Read required keyword from VPD.
729 auto l_kwdValueVariant = dbusUtility::readDbusProperty(
730 constants::pimServiceName, constants::systemVpdInvPath,
Jinu Joy Thomas71fd2792025-09-25 03:49:42 -0500731 constants::vsysInf, constants::kwdKeepAndClear);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500732
733 if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
734 {
735 saveKeepAndClearToBios(std::to_string(l_pVal->at(0)));
736 return;
737 }
738 logging::logMessage("Invalid type recieved for keep and clear from VPD.");
739}
740} // namespace vpd