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