manager: Add some attributes to BIOS restore
This commit adds support to synchronize the pvm_keep_and_clear
and pvm_create_default_lpar BIOS attributes to the UTIL/D1
keyword in the motherboard VPD.
The use-case for doing this is the same as the other attributes we
already handle - that to restore them post a factory reset.
pvm_keep_and_clear - Backed up to UTIL/D1, bit 0
pvm_create_default_lpar - Backed up to UTIL/D1, bit 1
Signed-off-by: Santosh Puranik <santosh.puranik@in.ibm.com>
Change-Id: I8a2c08a06a17d15ed9a607a482a2c8a88173fddd
Signed-off-by: Santosh Puranik <santosh.puranik@in.ibm.com>
diff --git a/vpd-manager/bios_handler.cpp b/vpd-manager/bios_handler.cpp
index 417852e..1f0306c 100644
--- a/vpd-manager/bios_handler.cpp
+++ b/vpd-manager/bios_handler.cpp
@@ -137,6 +137,24 @@
saveFCOToVPD(*val);
}
}
+ else if (attributeName == "pvm_keep_and_clear")
+ {
+ auto attrValue = std::get<5>(std::get<1>(item));
+ auto val = std::get_if<std::string>(&attrValue);
+ if (val)
+ {
+ saveKeepAndClearToVPD(*val);
+ }
+ }
+ else if (attributeName == "pvm_create_default_lpar")
+ {
+ auto attrValue = std::get<5>(std::get<1>(item));
+ auto val = std::get_if<std::string>(&attrValue);
+ if (val)
+ {
+ saveCreateDefaultLparToVPD(*val);
+ }
+ }
}
}
}
@@ -206,6 +224,83 @@
}
}
+void BiosHandler::saveKeepAndClearToVPD(const std::string& keepAndClear)
+{
+ Binary vpdVal;
+ auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
+
+ if (valInVPD.size() != 1)
+ {
+ std::cerr << "Read bad size for UTIL/D1: " << valInVPD.size()
+ << std::endl;
+ return;
+ }
+
+ if (keepAndClear != "Enabled" && keepAndClear != "Disabled")
+ {
+ std::cerr << "Bad value for keep and clear BIOS arttribute: "
+ << keepAndClear << std::endl;
+ return;
+ }
+
+ // Write to VPD only if the value is not already what we want to write.
+ if (keepAndClear == "Enabled" && ((valInVPD.at(0) & 0x01) != 0x01))
+ {
+ vpdVal.emplace_back(valInVPD.at(0) | 0x01);
+ }
+ else if (keepAndClear == "Disabled" && ((valInVPD.at(0) & 0x01) != 0))
+ {
+ vpdVal.emplace_back(valInVPD.at(0) & ~(0x01));
+ }
+
+ if (!vpdVal.empty())
+ {
+ std::cout << "Writing Keep and Clear to VPD: "
+ << static_cast<int>(vpdVal.at(0)) << std::endl;
+ manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
+ "UTIL", "D1", vpdVal);
+ }
+}
+
+void BiosHandler::saveCreateDefaultLparToVPD(
+ const std::string& createDefaultLpar)
+{
+ Binary vpdVal;
+ auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
+
+ if (valInVPD.size() != 1)
+ {
+ std::cerr << "Read bad size for UTIL/D1: " << valInVPD.size()
+ << std::endl;
+ return;
+ }
+
+ if (createDefaultLpar != "Enabled" && createDefaultLpar != "Disabled")
+ {
+ std::cerr << "Bad value for create default lpar BIOS arttribute: "
+ << createDefaultLpar << std::endl;
+ return;
+ }
+
+ // Write to VPD only if the value is not already what we want to write.
+ if (createDefaultLpar == "Enabled" && ((valInVPD.at(0) & 0x02) != 0x02))
+ {
+ vpdVal.emplace_back(valInVPD.at(0) | 0x02);
+ }
+ else if (createDefaultLpar == "Disabled" && ((valInVPD.at(0) & 0x02) != 0))
+ {
+ vpdVal.emplace_back(valInVPD.at(0) & ~(0x02));
+ }
+
+ if (!vpdVal.empty())
+ {
+ std::cout << "Writing create default lpar to VPD: "
+ << static_cast<int>(vpdVal.at(0)) << std::endl;
+ manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
+ "UTIL", "D1", vpdVal);
+ }
+}
+
int64_t BiosHandler::readBIOSFCO()
{
int64_t fcoVal = -1;
@@ -238,6 +333,38 @@
return ammVal;
}
+std::string BiosHandler::readBIOSKeepAndClear()
+{
+ std::string keepAndClear{};
+ auto val = readBIOSAttribute("pvm_keep_and_clear");
+
+ if (auto pVal = std::get_if<std::string>(&val))
+ {
+ keepAndClear = *pVal;
+ }
+ else
+ {
+ std::cerr << "Keep and clear is not a string" << std::endl;
+ }
+ return keepAndClear;
+}
+
+std::string BiosHandler::readBIOSCreateDefaultLpar()
+{
+ std::string createDefaultLpar{};
+ auto val = readBIOSAttribute("pvm_create_default_lpar");
+
+ if (auto pVal = std::get_if<std::string>(&val))
+ {
+ createDefaultLpar = *pVal;
+ }
+ else
+ {
+ std::cerr << "Create default LPAR is not a string" << std::endl;
+ }
+ return createDefaultLpar;
+}
+
void BiosHandler::saveFCOToBIOS(const std::string& fcoVal, int64_t fcoInBIOS)
{
if (fcoVal.size() != 4)
@@ -313,21 +440,97 @@
biosAttrs);
}
+void BiosHandler::saveKeepAndClearToBIOS(const std::string& keepAndClear,
+ const std::string& keepAndClearInBIOS)
+{
+ if (keepAndClear.size() != 1)
+ {
+ std::cerr << "Bad size for Keep and Clear in VPD: "
+ << keepAndClear.size() << std::endl;
+ return;
+ }
+
+ // Need to write?
+ std::string toWrite = (keepAndClear.at(0) & 0x01) ? "Enabled" : "Disabled";
+ if (keepAndClearInBIOS == toWrite)
+ {
+ std::cout << "Skip Keep and Clear BIOS write, value is already: "
+ << toWrite << std::endl;
+ return;
+ }
+
+ PendingBIOSAttrsType biosAttrs;
+ biosAttrs.push_back(
+ std::make_pair("pvm_keep_and_clear",
+ std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
+ "AttributeType.Enumeration",
+ toWrite)));
+
+ std::cout << "Set pvm_keep_and_clear to: " << toWrite << std::endl;
+
+ setBusProperty<PendingBIOSAttrsType>(
+ "xyz.openbmc_project.BIOSConfigManager",
+ "/xyz/openbmc_project/bios_config/manager",
+ "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
+ biosAttrs);
+}
+
+void BiosHandler::saveCreateDefaultLparToBIOS(
+ const std::string& createDefaultLpar,
+ const std::string& createDefaultLparInBIOS)
+{
+ if (createDefaultLpar.size() != 1)
+ {
+ std::cerr << "Bad size for Create default LPAR in VPD: "
+ << createDefaultLpar.size() << std::endl;
+ return;
+ }
+
+ // Need to write?
+ std::string toWrite =
+ (createDefaultLpar.at(0) & 0x02) ? "Enabled" : "Disabled";
+ if (createDefaultLparInBIOS == toWrite)
+ {
+ std::cout << "Skip Create default LPAR BIOS write, value is already: "
+ << toWrite << std::endl;
+ return;
+ }
+
+ PendingBIOSAttrsType biosAttrs;
+ biosAttrs.push_back(
+ std::make_pair("pvm_create_default_lpar",
+ std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
+ "AttributeType.Enumeration",
+ toWrite)));
+
+ std::cout << "Set pvm_create_default_lpar to: " << toWrite << std::endl;
+
+ setBusProperty<PendingBIOSAttrsType>(
+ "xyz.openbmc_project.BIOSConfigManager",
+ "/xyz/openbmc_project/bios_config/manager",
+ "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
+ biosAttrs);
+}
+
void BiosHandler::restoreBIOSAttribs()
{
// TODO: We could make this slightly more scalable by defining a table of
// attributes and their corresponding VPD keywords. However, that needs much
// more thought.
std::cout << "Attempting BIOS attribute reset" << std::endl;
- // Check if the VPD contains valid data for FCO and AMM *and* that it
- // differs from the data already in the attributes. If so, set the BIOS
- // attributes as per the value in the VPD.
+ // Check if the VPD contains valid data for FCO, AMM, Keep and Clear and
+ // Create default LPAR *and* that it differs from the data already in the
+ // attributes. If so, set the BIOS attributes as per the value in the VPD.
// If the VPD contains default data, then initialize the VPD keywords with
// data taken from the BIOS.
auto fcoInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "RG");
auto ammInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D0");
+ auto keepAndClearInVPD =
+ readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
auto fcoInBIOS = readBIOSFCO();
auto ammInBIOS = readBIOSAMM();
+ auto keepAndClearInBIOS = readBIOSKeepAndClear();
+ auto createDefaultLparInBIOS = readBIOSCreateDefaultLpar();
if (fcoInVPD == " ")
{
@@ -347,6 +550,16 @@
saveAMMToBIOS(ammInVPD, ammInBIOS);
}
+ // No uninitialized handling needed for keep and clear and create default
+ // lpar attributes. Their defaults in VPD are 0's which is what we want.
+ saveKeepAndClearToBIOS(keepAndClearInVPD, keepAndClearInBIOS);
+ // Have to read D1 again because two attributes are stored in the same
+ // keyword.
+ auto createDefaultLparInVPD =
+ readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
+ saveCreateDefaultLparToBIOS(createDefaultLparInVPD,
+ createDefaultLparInBIOS);
+
// Start listener now that we have done the restore
listenBiosAttribs();
}
diff --git a/vpd-manager/bios_handler.hpp b/vpd-manager/bios_handler.hpp
index 0bc381a..86e3318 100644
--- a/vpd-manager/bios_handler.hpp
+++ b/vpd-manager/bios_handler.hpp
@@ -113,10 +113,32 @@
void saveFCOToVPD(int64_t fcoVal);
/**
+ * @brief Persistently saves the Keep and Clear setting
+ *
+ * Keep and clear setting is saved to the UTIL/D1 keyword's 0th bit in the
+ * motherboard VPD. If the keep and clear in BIOS is "Disabled", set D1:0 to
+ * 0, if "Enabled" set D1:0 to 1
+ *
+ * @param[in] keepAndClear - The keep and clear BIOS attribute.
+ */
+ void saveKeepAndClearToVPD(const std::string& keepAndClear);
+
+ /**
+ * @brief Persistently saves the Create default LPAR setting
+ *
+ * Create default LPAR setting is saved to the UTIL/D1 keyword's 1st bit in
+ * the motherboard VPD. If the create default LPAR in BIOS is "Disabled",
+ * set D1:1 to 0, if "Enabled" set D1:1 to 1
+ *
+ * @param[in] createDefaultLpar - The mirror mode BIOS attribute.
+ */
+ void saveCreateDefaultLparToVPD(const std::string& createDefaultLpar);
+
+ /**
* @brief Writes Memory mirror mode to BIOS
*
- * Writes to the hb_memory_mirror_mode BIOS attribute, if the value is not
- * already the same as we are trying to write.
+ * Writes to the hb_memory_mirror_mode BIOS attribute, if the value is
+ * not already the same as we are trying to write.
*
* @param[in] ammVal - The mirror mode as read from VPD.
* @param[in] ammInBIOS - The mirror more in the BIOS table.
@@ -135,20 +157,61 @@
void saveFCOToBIOS(const std::string& fcoVal, int64_t fcoInBIOS);
/**
+ * @brief Writes Keep and clear setting to BIOS
+ *
+ * Writes to the pvm_keep_and_clear BIOS attribute, if the value is
+ * not already the same as we are trying to write.
+ *
+ * @param[in] keepAndClear - The mirror mode as read from VPD.
+ * @param[in] keepAndClearInBIOS - The mirror more in the BIOS table.
+ */
+ void saveKeepAndClearToBIOS(const std::string& keepAndClear,
+ const std::string& keepAndClearInBIOS);
+
+ /**
+ * @brief Writes Create default LPAR setting to BIOS
+ *
+ * Writes to the pvm_create_default_lpar BIOS attribute, if the value is
+ * not already the same as we are trying to write.
+ *
+ * @param[in] createDefaultLpar - The mirror mode as read from VPD.
+ * @param[in] createDefaultLparInBIOS - The mirror more in the BIOS table.
+ */
+ void
+ saveCreateDefaultLparToBIOS(const std::string& createDefaultLpar,
+ const std::string& createDefaultLparInBIOS);
+
+ /**
* @brief Reads the hb_memory_mirror_mode attribute
*
- * @return int64_t - The AMM BIOS attribute. -1 on failure.
+ * @return std::string - The AMM BIOS attribute. Empty string on failure.
*/
std::string readBIOSAMM();
/**
* @brief Reads the hb_field_core_override attribute
*
- * @return std::string - The FCO BIOS attribute. Empty string on failure.
+ * @return int64_t - The FCO BIOS attribute. -1 on failure.
*/
int64_t readBIOSFCO();
/**
+ * @brief Reads the pvm_keep_and_clear attribute
+ *
+ * @return std::string - The Keep and clear BIOS attribute. Empty string on
+ * failure.
+ */
+ std::string readBIOSKeepAndClear();
+
+ /**
+ * @brief Reads the pvm_create_default_lpar attribute
+ *
+ * @return std::string - The Create default LPAR BIOS attribute. Empty
+ * string on failure.
+ */
+ std::string readBIOSCreateDefaultLpar();
+
+ /**
* @brief Restore BIOS attributes
*
* This function checks if we are coming out of a factory reset. If yes,