manager: Sync pvm_clear_nvram BIOS Attribute
This commit adds support to synchronize the pvm_clear_nvram BIOS
attribute to bit 2 in the UTIL/D1 keyword of the motherboard VPD.
The attribute will be used by PHYP to determine when to clear their
NVRAM content.
A value of "Disabled" in the BIOS attribute maps to the D1:2 bit being 0
and a value of "Enabled: maps to the D1:2 bit being 1.
Signed-off-by: Santosh Puranik <santosh.puranik@in.ibm.com>
Change-Id: Ia0f3cfa92a98a2a1a95dd67ca598770459b9b7f2
diff --git a/vpd-manager/bios_handler.cpp b/vpd-manager/bios_handler.cpp
index 1f0306c..ff8ad37 100644
--- a/vpd-manager/bios_handler.cpp
+++ b/vpd-manager/bios_handler.cpp
@@ -155,6 +155,15 @@
saveCreateDefaultLparToVPD(*val);
}
}
+ else if (attributeName == "pvm_clear_nvram")
+ {
+ auto attrValue = std::get<5>(std::get<1>(item));
+ auto val = std::get_if<std::string>(&attrValue);
+ if (val)
+ {
+ saveClearNVRAMToVPD(*val);
+ }
+ }
}
}
}
@@ -200,7 +209,7 @@
if (mirrorMode != "Enabled" && mirrorMode != "Disabled")
{
- std::cerr << "Bad value for Mirror mode BIOS arttribute: " << mirrorMode
+ std::cerr << "Bad value for Mirror mode BIOS attribute: " << mirrorMode
<< std::endl;
return;
}
@@ -238,7 +247,7 @@
if (keepAndClear != "Enabled" && keepAndClear != "Disabled")
{
- std::cerr << "Bad value for keep and clear BIOS arttribute: "
+ std::cerr << "Bad value for keep and clear BIOS attribute: "
<< keepAndClear << std::endl;
return;
}
@@ -277,7 +286,7 @@
if (createDefaultLpar != "Enabled" && createDefaultLpar != "Disabled")
{
- std::cerr << "Bad value for create default lpar BIOS arttribute: "
+ std::cerr << "Bad value for create default lpar BIOS attribute: "
<< createDefaultLpar << std::endl;
return;
}
@@ -301,6 +310,44 @@
}
}
+void BiosHandler::saveClearNVRAMToVPD(const std::string& clearNVRAM)
+{
+ 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 (clearNVRAM != "Enabled" && clearNVRAM != "Disabled")
+ {
+ std::cerr << "Bad value for clear NVRAM BIOS attribute: " << clearNVRAM
+ << std::endl;
+ return;
+ }
+
+ // Write to VPD only if the value is not already what we want to write.
+ if (clearNVRAM == "Enabled" && ((valInVPD.at(0) & 0x04) != 0x04))
+ {
+ vpdVal.emplace_back(valInVPD.at(0) | 0x04);
+ }
+ else if (clearNVRAM == "Disabled" && ((valInVPD.at(0) & 0x04) != 0))
+ {
+ vpdVal.emplace_back(valInVPD.at(0) & ~(0x04));
+ }
+
+ if (!vpdVal.empty())
+ {
+ std::cout << "Writing clear NVRAM 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;
@@ -365,6 +412,22 @@
return createDefaultLpar;
}
+std::string BiosHandler::readBIOSClearNVRAM()
+{
+ std::string clearNVRAM{};
+ auto val = readBIOSAttribute("pvm_clear_nvram");
+
+ if (auto pVal = std::get_if<std::string>(&val))
+ {
+ clearNVRAM = *pVal;
+ }
+ else
+ {
+ std::cerr << "Clear NVRAM is not a string" << std::endl;
+ }
+ return clearNVRAM;
+}
+
void BiosHandler::saveFCOToBIOS(const std::string& fcoVal, int64_t fcoInBIOS)
{
if (fcoVal.size() != 4)
@@ -512,17 +575,52 @@
biosAttrs);
}
+void BiosHandler::saveClearNVRAMToBIOS(const std::string& clearNVRAM,
+ const std::string& clearNVRAMInBIOS)
+{
+ if (clearNVRAM.size() != 1)
+ {
+ std::cerr << "Bad size for Clear NVRAM in VPD: " << clearNVRAM.size()
+ << std::endl;
+ return;
+ }
+
+ // Need to write?
+ std::string toWrite = (clearNVRAM.at(0) & 0x04) ? "Enabled" : "Disabled";
+ if (clearNVRAMInBIOS == toWrite)
+ {
+ std::cout << "Skip Clear NVRAM BIOS write, value is already: "
+ << toWrite << std::endl;
+ return;
+ }
+
+ PendingBIOSAttrsType biosAttrs;
+ biosAttrs.push_back(
+ std::make_pair("pvm_clear_nvram",
+ std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
+ "AttributeType.Enumeration",
+ toWrite)));
+
+ std::cout << "Set pvm_clear_nvram 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, 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.
+ // Check if the VPD contains valid data for FCO, AMM, Keep and Clear,
+ // Create default LPAR and Clear NVRAM *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 =
@@ -531,6 +629,7 @@
auto ammInBIOS = readBIOSAMM();
auto keepAndClearInBIOS = readBIOSKeepAndClear();
auto createDefaultLparInBIOS = readBIOSCreateDefaultLpar();
+ auto clearNVRAMInBIOS = readBIOSClearNVRAM();
if (fcoInVPD == " ")
{
@@ -550,8 +649,9 @@
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.
+ // No uninitialized handling needed for keep and clear, create default
+ // lpar and clear nvram 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.
@@ -560,6 +660,10 @@
saveCreateDefaultLparToBIOS(createDefaultLparInVPD,
createDefaultLparInBIOS);
+ auto clearNVRAMInVPD =
+ readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
+ saveClearNVRAMToBIOS(clearNVRAMInVPD, clearNVRAMInBIOS);
+
// 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 86e3318..985daa7 100644
--- a/vpd-manager/bios_handler.hpp
+++ b/vpd-manager/bios_handler.hpp
@@ -135,13 +135,24 @@
void saveCreateDefaultLparToVPD(const std::string& createDefaultLpar);
/**
+ * @brief Persistently saves the Clear NVRAM setting
+ *
+ * Create default LPAR setting is saved to the UTIL/D1 keyword's 2nd bit in
+ * the motherboard VPD. If the clear NVRAM in BIOS is "Disabled",
+ * set D1:2 to 0, if "Enabled" set D1:2 to 1
+ *
+ * @param[in] createDefaultLpar - The mirror mode BIOS attribute.
+ */
+ void saveClearNVRAMToVPD(const std::string& clearNVRAM);
+
+ /**
* @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.
*
* @param[in] ammVal - The mirror mode as read from VPD.
- * @param[in] ammInBIOS - The mirror more in the BIOS table.
+ * @param[in] ammInBIOS - The mirror mode in the BIOS table.
*/
void saveAMMToBIOS(const std::string& ammVal, const std::string& ammInBIOS);
@@ -162,8 +173,8 @@
* 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.
+ * @param[in] keepAndClear - The keep and clear as read from VPD.
+ * @param[in] keepAndClearInBIOS - The keep and clear in the BIOS table.
*/
void saveKeepAndClearToBIOS(const std::string& keepAndClear,
const std::string& keepAndClearInBIOS);
@@ -174,14 +185,27 @@
* 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.
+ * @param[in] createDefaultLpar - The create default LPAR as read from VPD.
+ * @param[in] createDefaultLparInBIOS - The create default LPAR in the BIOS
+ * table.
*/
void
saveCreateDefaultLparToBIOS(const std::string& createDefaultLpar,
const std::string& createDefaultLparInBIOS);
/**
+ * @brief Writes Clear NVRAM setting to BIOS
+ *
+ * Writes to the pvm_clear_nvram BIOS attribute, if the value is
+ * not already the same as we are trying to write.
+ *
+ * @param[in] clearNVRAM - The clear NVRAM as read from VPD.
+ * @param[in] clearNVRAMInBIOS - The clear NVRAM in the BIOS table.
+ */
+ void saveClearNVRAMToBIOS(const std::string& clearNVRAM,
+ const std::string& clearNVRAMInBIOS);
+
+ /**
* @brief Reads the hb_memory_mirror_mode attribute
*
* @return std::string - The AMM BIOS attribute. Empty string on failure.
@@ -212,10 +236,18 @@
std::string readBIOSCreateDefaultLpar();
/**
+ * @brief Reads the pvm_clear_nvram attribute
+ *
+ * @return std::string - The Clear NVRAM BIOS attribute. Empty
+ * string on failure.
+ */
+ std::string readBIOSClearNVRAM();
+
+ /**
* @brief Restore BIOS attributes
*
* This function checks if we are coming out of a factory reset. If yes,
- * it checks the VPD cache for valid backed up copy of the FCO and AMM
+ * it checks the VPD cache for valid backed up copy of the applicable
* BIOS attributes. If valid values are found in the VPD, it will apply
* those to the BIOS attributes.
*/