1 #include "config.h"
2
3 #include "bios_handler.hpp"
4
5 #include "const.hpp"
6 #include "ibm_vpd_utils.hpp"
7 #include "manager.hpp"
8 #include "types.hpp"
9
10 #include <sdbusplus/bus.hpp>
11
12 #include <iostream>
13 #include <memory>
14 #include <string>
15 #include <tuple>
16 #include <variant>
17
18 using namespace openpower::vpd;
19 using namespace openpower::vpd::constants;
20
21 namespace openpower
22 {
23 namespace vpd
24 {
25 namespace manager
26 {
checkAndListenPLDMService()27 void BiosHandler::checkAndListenPLDMService()
28 {
29 // Setup a match on NameOwnerChanged to determine when PLDM is up. In
30 // the signal handler, call restoreBIOSAttribs
31 static std::shared_ptr<sdbusplus::bus::match_t> nameOwnerMatch =
32 std::make_shared<sdbusplus::bus::match_t>(
33 *conn,
34 sdbusplus::bus::match::rules::nameOwnerChanged(
35 "xyz.openbmc_project.PLDM"),
36 [this](sdbusplus::message_t& msg) {
37 if (msg.is_method_error())
38 {
39 std::cerr
40 << "Error in reading name owner signal " << std::endl;
41 return;
42 }
43 std::string name;
44 std::string newOwner;
45 std::string oldOwner;
46
47 msg.read(name, oldOwner, newOwner);
48 if (newOwner != "" && name == "xyz.openbmc_project.PLDM")
49 {
50 this->restoreBIOSAttribs();
51 // We don't need the match anymore
52 nameOwnerMatch.reset();
53 }
54 });
55 // Check if PLDM is already running, if it is, we can go ahead and attempt
56 // to sync BIOS attributes (since PLDM would have initialized them by the
57 // time it acquires a bus name).
58 bool isPLDMRunning = false;
59 try
60 {
61 auto bus = sdbusplus::bus::new_default();
62 auto method =
63 bus.new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
64 "org.freedesktop.DBus", "NameHasOwner");
65 method.append("xyz.openbmc_project.PLDM");
66
67 auto result = bus.call(method);
68 result.read(isPLDMRunning);
69 }
70 catch (const sdbusplus::exception::SdBusError& e)
71 {
72 std::cerr << "Failed to check if PLDM is running, assume false"
73 << std::endl;
74 std::cerr << e.what() << std::endl;
75 }
76
77 std::cout << "Is PLDM running: " << isPLDMRunning << std::endl;
78
79 if (isPLDMRunning)
80 {
81 nameOwnerMatch.reset();
82 restoreBIOSAttribs();
83 }
84 }
85
listenBiosAttribs()86 void BiosHandler::listenBiosAttribs()
87 {
88 static std::shared_ptr<sdbusplus::bus::match_t> biosMatcher =
89 std::make_shared<sdbusplus::bus::match_t>(
90 *conn,
91 sdbusplus::bus::match::rules::propertiesChanged(
92 "/xyz/openbmc_project/bios_config/manager",
93 "xyz.openbmc_project.BIOSConfig.Manager"),
94 [this](sdbusplus::message_t& msg) { biosAttribsCallback(msg); });
95 }
96
biosAttribsCallback(sdbusplus::message_t & msg)97 void BiosHandler::biosAttribsCallback(sdbusplus::message_t& msg)
98 {
99 if (msg.is_method_error())
100 {
101 std::cerr << "Error in reading BIOS attribute signal " << std::endl;
102 return;
103 }
104 using BiosProperty = std::tuple<
105 std::string, bool, std::string, std::string, std::string,
106 std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
107 std::vector<std::tuple<std::string, std::variant<int64_t, std::string>,
108 std::string>>>;
109
110 using BiosBaseTable =
111 std::variant<std::monostate, std::map<std::string, BiosProperty>>;
112 using BiosBaseTableType = std::map<std::string, BiosBaseTable>;
113
114 std::string object;
115 BiosBaseTableType propMap;
116 msg.read(object, propMap);
117 for (auto prop : propMap)
118 {
119 if (prop.first == "BaseBIOSTable")
120 {
121 if (auto list = std::get_if<std::map<std::string, BiosProperty>>(
122 &(prop.second)))
123 {
124 for (const auto& item : *list)
125 {
126 std::string attributeName = std::get<0>(item);
127 if (attributeName == "hb_memory_mirror_mode")
128 {
129 auto attrValue = std::get<5>(std::get<1>(item));
130 auto val = std::get_if<std::string>(&attrValue);
131 if (val)
132 {
133 saveAMMToVPD(*val);
134 }
135 }
136 else if (attributeName == "hb_field_core_override")
137 {
138 auto attrValue = std::get<5>(std::get<1>(item));
139 auto val = std::get_if<int64_t>(&attrValue);
140 if (val)
141 {
142 saveFCOToVPD(*val);
143 }
144 }
145 else if (attributeName == "pvm_keep_and_clear")
146 {
147 auto attrValue = std::get<5>(std::get<1>(item));
148 auto val = std::get_if<std::string>(&attrValue);
149 if (val)
150 {
151 saveKeepAndClearToVPD(*val);
152 }
153 }
154 else if (attributeName == "pvm_create_default_lpar")
155 {
156 auto attrValue = std::get<5>(std::get<1>(item));
157 auto val = std::get_if<std::string>(&attrValue);
158 if (val)
159 {
160 saveCreateDefaultLparToVPD(*val);
161 }
162 }
163 else if (attributeName == "pvm_clear_nvram")
164 {
165 auto attrValue = std::get<5>(std::get<1>(item));
166 auto val = std::get_if<std::string>(&attrValue);
167 if (val)
168 {
169 saveClearNVRAMToVPD(*val);
170 }
171 }
172 }
173 }
174 else
175 {
176 inventory::PelAdditionalData additionalData;
177 additionalData.emplace(
178 "DESCRIPTION",
179 "Invalid type received for BIOS base table property");
180
181 createPEL(additionalData, PelSeverity::ERROR,
182 errIntfForVPDDefault, nullptr);
183 std::cerr
184 << "Invalid type received for BIOS base table property"
185 << std::endl;
186 }
187 }
188 }
189 }
190
saveFCOToVPD(int64_t fcoVal)191 void BiosHandler::saveFCOToVPD(int64_t fcoVal)
192 {
193 if (fcoVal == -1)
194 {
195 std::cerr << "Invalid FCO value from BIOS: " << fcoVal << std::endl;
196 return;
197 }
198
199 Binary vpdVal = {0, 0, 0, static_cast<uint8_t>(fcoVal)};
200 auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "RG");
201
202 if (valInVPD.size() != 4)
203 {
204 std::cerr << "Read bad size for VSYS/RG: " << valInVPD.size()
205 << std::endl;
206 return;
207 }
208
209 if (std::memcmp(vpdVal.data(), valInVPD.data(), 4) != 0)
210 {
211 std::cout << "Writing FCO to VPD: " << fcoVal << std::endl;
212 manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
213 "VSYS", "RG", vpdVal);
214 }
215 }
216
saveAMMToVPD(const std::string & mirrorMode)217 void BiosHandler::saveAMMToVPD(const std::string& mirrorMode)
218 {
219 Binary vpdVal;
220 auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D0");
221
222 if (valInVPD.size() != 1)
223 {
224 std::cerr << "Read bad size for UTIL/D0: " << valInVPD.size()
225 << std::endl;
226 return;
227 }
228
229 if (mirrorMode != "Enabled" && mirrorMode != "Disabled")
230 {
231 std::cerr << "Bad value for Mirror mode BIOS attribute: " << mirrorMode
232 << std::endl;
233 return;
234 }
235
236 // Write to VPD only if the value is not already what we want to write.
237 if (mirrorMode == "Enabled" && valInVPD.at(0) != 2)
238 {
239 vpdVal.emplace_back(2);
240 }
241 else if (mirrorMode == "Disabled" && valInVPD.at(0) != 1)
242 {
243 vpdVal.emplace_back(1);
244 }
245
246 if (!vpdVal.empty())
247 {
248 std::cout << "Writing AMM to VPD: " << static_cast<int>(vpdVal.at(0))
249 << std::endl;
250 manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
251 "UTIL", "D0", vpdVal);
252 }
253 }
254
saveKeepAndClearToVPD(const std::string & keepAndClear)255 void BiosHandler::saveKeepAndClearToVPD(const std::string& keepAndClear)
256 {
257 Binary vpdVal;
258 auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
259
260 if (valInVPD.size() != 1)
261 {
262 std::cerr << "Read bad size for UTIL/D1: " << valInVPD.size()
263 << std::endl;
264 return;
265 }
266
267 if (keepAndClear != "Enabled" && keepAndClear != "Disabled")
268 {
269 std::cerr << "Bad value for keep and clear BIOS attribute: "
270 << keepAndClear << std::endl;
271 return;
272 }
273
274 // Write to VPD only if the value is not already what we want to write.
275 if (keepAndClear == "Enabled" && ((valInVPD.at(0) & 0x01) != 0x01))
276 {
277 vpdVal.emplace_back(valInVPD.at(0) | 0x01);
278 }
279 else if (keepAndClear == "Disabled" && ((valInVPD.at(0) & 0x01) != 0))
280 {
281 vpdVal.emplace_back(valInVPD.at(0) & ~(0x01));
282 }
283
284 if (!vpdVal.empty())
285 {
286 std::cout << "Writing Keep and Clear to VPD: "
287 << static_cast<int>(vpdVal.at(0)) << std::endl;
288 manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
289 "UTIL", "D1", vpdVal);
290 }
291 }
292
saveCreateDefaultLparToVPD(const std::string & createDefaultLpar)293 void BiosHandler::saveCreateDefaultLparToVPD(
294 const std::string& createDefaultLpar)
295 {
296 Binary vpdVal;
297 auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
298
299 if (valInVPD.size() != 1)
300 {
301 std::cerr << "Read bad size for UTIL/D1: " << valInVPD.size()
302 << std::endl;
303 return;
304 }
305
306 if (createDefaultLpar != "Enabled" && createDefaultLpar != "Disabled")
307 {
308 std::cerr << "Bad value for create default lpar BIOS attribute: "
309 << createDefaultLpar << std::endl;
310 return;
311 }
312
313 // Write to VPD only if the value is not already what we want to write.
314 if (createDefaultLpar == "Enabled" && ((valInVPD.at(0) & 0x02) != 0x02))
315 {
316 vpdVal.emplace_back(valInVPD.at(0) | 0x02);
317 }
318 else if (createDefaultLpar == "Disabled" && ((valInVPD.at(0) & 0x02) != 0))
319 {
320 vpdVal.emplace_back(valInVPD.at(0) & ~(0x02));
321 }
322
323 if (!vpdVal.empty())
324 {
325 std::cout << "Writing create default lpar to VPD: "
326 << static_cast<int>(vpdVal.at(0)) << std::endl;
327 manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
328 "UTIL", "D1", vpdVal);
329 }
330 }
331
saveClearNVRAMToVPD(const std::string & clearNVRAM)332 void BiosHandler::saveClearNVRAMToVPD(const std::string& clearNVRAM)
333 {
334 Binary vpdVal;
335 auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
336
337 if (valInVPD.size() != 1)
338 {
339 std::cerr << "Read bad size for UTIL/D1: " << valInVPD.size()
340 << std::endl;
341 return;
342 }
343
344 if (clearNVRAM != "Enabled" && clearNVRAM != "Disabled")
345 {
346 std::cerr << "Bad value for clear NVRAM BIOS attribute: " << clearNVRAM
347 << std::endl;
348 return;
349 }
350
351 // Write to VPD only if the value is not already what we want to write.
352 if (clearNVRAM == "Enabled" && ((valInVPD.at(0) & 0x04) != 0x04))
353 {
354 vpdVal.emplace_back(valInVPD.at(0) | 0x04);
355 }
356 else if (clearNVRAM == "Disabled" && ((valInVPD.at(0) & 0x04) != 0))
357 {
358 vpdVal.emplace_back(valInVPD.at(0) & ~(0x04));
359 }
360
361 if (!vpdVal.empty())
362 {
363 std::cout << "Writing clear NVRAM to VPD: "
364 << static_cast<int>(vpdVal.at(0)) << std::endl;
365 manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
366 "UTIL", "D1", vpdVal);
367 }
368 }
369
readBIOSFCO()370 int64_t BiosHandler::readBIOSFCO()
371 {
372 int64_t fcoVal = -1;
373 auto val = readBIOSAttribute("hb_field_core_override");
374
375 if (auto pVal = std::get_if<int64_t>(&val))
376 {
377 fcoVal = *pVal;
378 }
379 else
380 {
381 std::cerr << "FCO is not an int" << std::endl;
382 }
383 return fcoVal;
384 }
385
readBIOSAMM()386 std::string BiosHandler::readBIOSAMM()
387 {
388 std::string ammVal{};
389 auto val = readBIOSAttribute("hb_memory_mirror_mode");
390
391 if (auto pVal = std::get_if<std::string>(&val))
392 {
393 ammVal = *pVal;
394 }
395 else
396 {
397 std::cerr << "AMM is not a string" << std::endl;
398 }
399 return ammVal;
400 }
401
readBIOSKeepAndClear()402 std::string BiosHandler::readBIOSKeepAndClear()
403 {
404 std::string keepAndClear{};
405 auto val = readBIOSAttribute("pvm_keep_and_clear");
406
407 if (auto pVal = std::get_if<std::string>(&val))
408 {
409 keepAndClear = *pVal;
410 }
411 else
412 {
413 std::cerr << "Keep and clear is not a string" << std::endl;
414 }
415 return keepAndClear;
416 }
417
readBIOSCreateDefaultLpar()418 std::string BiosHandler::readBIOSCreateDefaultLpar()
419 {
420 std::string createDefaultLpar{};
421 auto val = readBIOSAttribute("pvm_create_default_lpar");
422
423 if (auto pVal = std::get_if<std::string>(&val))
424 {
425 createDefaultLpar = *pVal;
426 }
427 else
428 {
429 std::cerr << "Create default LPAR is not a string" << std::endl;
430 }
431 return createDefaultLpar;
432 }
433
readBIOSClearNVRAM()434 std::string BiosHandler::readBIOSClearNVRAM()
435 {
436 std::string clearNVRAM{};
437 auto val = readBIOSAttribute("pvm_clear_nvram");
438
439 if (auto pVal = std::get_if<std::string>(&val))
440 {
441 clearNVRAM = *pVal;
442 }
443 else
444 {
445 std::cerr << "Clear NVRAM is not a string" << std::endl;
446 }
447 return clearNVRAM;
448 }
449
saveFCOToBIOS(const std::string & fcoVal,int64_t fcoInBIOS)450 void BiosHandler::saveFCOToBIOS(const std::string& fcoVal, int64_t fcoInBIOS)
451 {
452 if (fcoVal.size() != 4)
453 {
454 std::cerr << "Bad size for FCO in VPD: " << fcoVal.size() << std::endl;
455 return;
456 }
457
458 // Need to write?
459 if (fcoInBIOS == static_cast<int64_t>(fcoVal.at(3)))
460 {
461 std::cout << "Skip FCO BIOS write, value is already: " << fcoInBIOS
462 << std::endl;
463 return;
464 }
465
466 PendingBIOSAttrsType biosAttrs;
467 biosAttrs.push_back(
468 std::make_pair("hb_field_core_override",
469 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
470 "AttributeType.Integer",
471 fcoVal.at(3))));
472
473 std::cout << "Set hb_field_core_override to: "
474 << static_cast<int>(fcoVal.at(3)) << std::endl;
475
476 setBusProperty<PendingBIOSAttrsType>(
477 "xyz.openbmc_project.BIOSConfigManager",
478 "/xyz/openbmc_project/bios_config/manager",
479 "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
480 biosAttrs);
481 }
482
saveAMMToBIOS(const std::string & ammVal,const std::string & ammInBIOS)483 void BiosHandler::saveAMMToBIOS(const std::string& ammVal,
484 const std::string& ammInBIOS)
485 {
486 if (ammVal.size() != 1)
487 {
488 std::cerr << "Bad size for AMM in VPD: " << ammVal.size() << std::endl;
489 return;
490 }
491
492 // Make sure data in VPD is sane
493 if (ammVal.at(0) != 1 && ammVal.at(0) != 2)
494 {
495 std::cerr << "Bad value for AMM read from VPD: "
496 << static_cast<int>(ammVal.at(0)) << std::endl;
497 return;
498 }
499
500 // Need to write?
501 std::string toWrite = (ammVal.at(0) == 2) ? "Enabled" : "Disabled";
502 if (ammInBIOS == toWrite)
503 {
504 std::cout << "Skip AMM BIOS write, value is already: " << toWrite
505 << std::endl;
506 return;
507 }
508
509 PendingBIOSAttrsType biosAttrs;
510 biosAttrs.push_back(
511 std::make_pair("hb_memory_mirror_mode",
512 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
513 "AttributeType.Enumeration",
514 toWrite)));
515
516 std::cout << "Set hb_memory_mirror_mode to: " << toWrite << std::endl;
517
518 setBusProperty<PendingBIOSAttrsType>(
519 "xyz.openbmc_project.BIOSConfigManager",
520 "/xyz/openbmc_project/bios_config/manager",
521 "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
522 biosAttrs);
523 }
524
saveKeepAndClearToBIOS(const std::string & keepAndClear,const std::string & keepAndClearInBIOS)525 void BiosHandler::saveKeepAndClearToBIOS(const std::string& keepAndClear,
526 const std::string& keepAndClearInBIOS)
527 {
528 if (keepAndClear.size() != 1)
529 {
530 std::cerr << "Bad size for Keep and Clear in VPD: "
531 << keepAndClear.size() << std::endl;
532 return;
533 }
534
535 // Need to write?
536 std::string toWrite = (keepAndClear.at(0) & 0x01) ? "Enabled" : "Disabled";
537 if (keepAndClearInBIOS == toWrite)
538 {
539 std::cout << "Skip Keep and Clear BIOS write, value is already: "
540 << toWrite << std::endl;
541 return;
542 }
543
544 PendingBIOSAttrsType biosAttrs;
545 biosAttrs.push_back(
546 std::make_pair("pvm_keep_and_clear",
547 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
548 "AttributeType.Enumeration",
549 toWrite)));
550
551 std::cout << "Set pvm_keep_and_clear to: " << toWrite << std::endl;
552
553 setBusProperty<PendingBIOSAttrsType>(
554 "xyz.openbmc_project.BIOSConfigManager",
555 "/xyz/openbmc_project/bios_config/manager",
556 "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
557 biosAttrs);
558 }
559
saveCreateDefaultLparToBIOS(const std::string & createDefaultLpar,const std::string & createDefaultLparInBIOS)560 void BiosHandler::saveCreateDefaultLparToBIOS(
561 const std::string& createDefaultLpar,
562 const std::string& createDefaultLparInBIOS)
563 {
564 if (createDefaultLpar.size() != 1)
565 {
566 std::cerr << "Bad size for Create default LPAR in VPD: "
567 << createDefaultLpar.size() << std::endl;
568 return;
569 }
570
571 // Need to write?
572 std::string toWrite =
573 (createDefaultLpar.at(0) & 0x02) ? "Enabled" : "Disabled";
574 if (createDefaultLparInBIOS == toWrite)
575 {
576 std::cout << "Skip Create default LPAR BIOS write, value is already: "
577 << toWrite << std::endl;
578 return;
579 }
580
581 PendingBIOSAttrsType biosAttrs;
582 biosAttrs.push_back(
583 std::make_pair("pvm_create_default_lpar",
584 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
585 "AttributeType.Enumeration",
586 toWrite)));
587
588 std::cout << "Set pvm_create_default_lpar to: " << toWrite << std::endl;
589
590 setBusProperty<PendingBIOSAttrsType>(
591 "xyz.openbmc_project.BIOSConfigManager",
592 "/xyz/openbmc_project/bios_config/manager",
593 "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
594 biosAttrs);
595 }
596
saveClearNVRAMToBIOS(const std::string & clearNVRAM,const std::string & clearNVRAMInBIOS)597 void BiosHandler::saveClearNVRAMToBIOS(const std::string& clearNVRAM,
598 const std::string& clearNVRAMInBIOS)
599 {
600 if (clearNVRAM.size() != 1)
601 {
602 std::cerr << "Bad size for Clear NVRAM in VPD: " << clearNVRAM.size()
603 << std::endl;
604 return;
605 }
606
607 // Need to write?
608 std::string toWrite = (clearNVRAM.at(0) & 0x04) ? "Enabled" : "Disabled";
609 if (clearNVRAMInBIOS == toWrite)
610 {
611 std::cout << "Skip Clear NVRAM BIOS write, value is already: "
612 << toWrite << std::endl;
613 return;
614 }
615
616 PendingBIOSAttrsType biosAttrs;
617 biosAttrs.push_back(
618 std::make_pair("pvm_clear_nvram",
619 std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
620 "AttributeType.Enumeration",
621 toWrite)));
622
623 std::cout << "Set pvm_clear_nvram to: " << toWrite << std::endl;
624
625 setBusProperty<PendingBIOSAttrsType>(
626 "xyz.openbmc_project.BIOSConfigManager",
627 "/xyz/openbmc_project/bios_config/manager",
628 "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
629 biosAttrs);
630 }
631
restoreBIOSAttribs()632 void BiosHandler::restoreBIOSAttribs()
633 {
634 // TODO: We could make this slightly more scalable by defining a table of
635 // attributes and their corresponding VPD keywords. However, that needs much
636 // more thought.
637 std::cout << "Attempting BIOS attribute reset" << std::endl;
638 // Check if the VPD contains valid data for FCO, AMM, Keep and Clear,
639 // Create default LPAR and Clear NVRAM *and* that it differs from the data
640 // already in the attributes. If so, set the BIOS attributes as per the
641 // value in the VPD. If the VPD contains default data, then initialize the
642 // VPD keywords with data taken from the BIOS.
643 auto fcoInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "RG");
644 auto ammInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D0");
645 auto keepAndClearInVPD =
646 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
647 auto fcoInBIOS = readBIOSFCO();
648 auto ammInBIOS = readBIOSAMM();
649 auto keepAndClearInBIOS = readBIOSKeepAndClear();
650 auto createDefaultLparInBIOS = readBIOSCreateDefaultLpar();
651 auto clearNVRAMInBIOS = readBIOSClearNVRAM();
652
653 if (fcoInVPD == " ")
654 {
655 saveFCOToVPD(fcoInBIOS);
656 }
657 else
658 {
659 saveFCOToBIOS(fcoInVPD, fcoInBIOS);
660 }
661
662 if (ammInVPD.at(0) == 0)
663 {
664 saveAMMToVPD(ammInBIOS);
665 }
666 else
667 {
668 saveAMMToBIOS(ammInVPD, ammInBIOS);
669 }
670
671 // No uninitialized handling needed for keep and clear, create default
672 // lpar and clear nvram attributes. Their defaults in VPD are 0's which is
673 // what we want.
674 saveKeepAndClearToBIOS(keepAndClearInVPD, keepAndClearInBIOS);
675 // Have to read D1 again because two attributes are stored in the same
676 // keyword.
677 auto createDefaultLparInVPD =
678 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
679 saveCreateDefaultLparToBIOS(createDefaultLparInVPD,
680 createDefaultLparInBIOS);
681
682 auto clearNVRAMInVPD =
683 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
684 saveClearNVRAMToBIOS(clearNVRAMInVPD, clearNVRAMInBIOS);
685
686 // Start listener now that we have done the restore
687 listenBiosAttribs();
688 }
689 } // namespace manager
690 } // namespace vpd
691 } // namespace openpower
692