Sync keyword update to inherited FRUs
This commit syncs keyword update to all inherited FRUs.
When a keyword value is updated either from vpd-tool or from vpd-manager
WriteKeyword API, the keyword update should also be synced to all
inherited FRUs on PIM to prevent mismatch.
Test:
```
Tested on a rainier 2s2u simics setup.
1. Ensure BMC is in Ready state
2. Read VINI PN of /system/chassis/motherboard using vpd-tool
3. Update VINI PN of /system/chassis/motherboard using vpd-tool
4. Once vpd-tool returns success, read VINI PN of inherited FRUs
/system/chassis and /system/chassis/motherboard/tod_battery
5. VINI PN value should be same on the inherited FRUs.
```
Change-Id: Iff7340a111722f9e5336c0c846a79ffec8bbb8db
Signed-off-by: Souvik Roy <souvikroyofficial10@gmail.com>
diff --git a/vpd-manager/include/utility/vpd_specific_utility.hpp b/vpd-manager/include/utility/vpd_specific_utility.hpp
index bcdce9d..0228e74 100644
--- a/vpd-manager/include/utility/vpd_specific_utility.hpp
+++ b/vpd-manager/include/utility/vpd_specific_utility.hpp
@@ -804,5 +804,88 @@
}
return false;
}
+
+/**
+ * @brief API to sync keyword update to inherited FRUs.
+ *
+ * For a given keyword update on a EEPROM path, this API syncs the keyword
+ * update to all inherited FRUs' respective interface, property on PIM.
+ *
+ * @param[in] i_fruPath - EEPROM path of FRU.
+ * @param[in] i_paramsToWriteData - Input details.
+ * @param[in] i_sysCfgJsonObj - System config JSON.
+ *
+ */
+inline void updateKwdOnInheritedFrus(
+ const std::string& i_fruPath,
+ const types::WriteVpdParams& i_paramsToWriteData,
+ const nlohmann::json& i_sysCfgJsonObj) noexcept
+{
+ try
+ {
+ if (!i_sysCfgJsonObj.contains("frus"))
+ {
+ throw std::runtime_error("Mandatory tag(s) missing from JSON");
+ }
+
+ if (!i_sysCfgJsonObj["frus"].contains(i_fruPath))
+ {
+ throw std::runtime_error(
+ "VPD path [" + i_fruPath + "] not found in system config JSON");
+ }
+
+ const types::IpzData* l_ipzData =
+ std::get_if<types::IpzData>(&i_paramsToWriteData);
+
+ if (!l_ipzData)
+ {
+ throw std::runtime_error("Unsupported VPD type");
+ }
+ // iterate through all inventory paths for given EEPROM path,
+ // except the base FRU.
+ // if for an inventory path, "inherit" tag is true,
+ // update the inventory path's com.ibm.ipzvpd.<record>,keyword
+ // property
+
+ types::ObjectMap l_objectInterfaceMap;
+
+ auto l_populateInterfaceMap =
+ [&l_objectInterfaceMap,
+ &l_ipzData = std::as_const(l_ipzData)](const auto& l_Fru) {
+ // update inherited FRUs only
+ if (l_Fru.value("inherit", true))
+ {
+ l_objectInterfaceMap.emplace(
+ sdbusplus::message::object_path{l_Fru["inventoryPath"]},
+ types::InterfaceMap{
+ {std::string{constants::ipzVpdInf +
+ std::get<0>(*l_ipzData)},
+ types::PropertyMap{{std::get<1>(*l_ipzData),
+ std::get<2>(*l_ipzData)}}}});
+ }
+ };
+
+ // iterate through all FRUs except the base FRU
+ std::for_each(
+ i_sysCfgJsonObj["frus"][i_fruPath].begin() + constants::VALUE_1,
+ i_sysCfgJsonObj["frus"][i_fruPath].end(), l_populateInterfaceMap);
+
+ if (!l_objectInterfaceMap.empty())
+ {
+ // notify PIM
+ if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
+ {
+ throw std::runtime_error(
+ "Call to PIM failed for VPD file " + i_fruPath);
+ }
+ }
+ }
+ catch (const std::exception& l_ex)
+ {
+ logging::logMessage(
+ "Failed to sync keyword update to inherited FRUs of FRU [" +
+ i_fruPath + "]. Error: " + std::string(l_ex.what()));
+ }
+}
} // namespace vpdSpecificUtility
} // namespace vpd
diff --git a/vpd-manager/src/manager.cpp b/vpd-manager/src/manager.cpp
index ade45b7..fadd965 100644
--- a/vpd-manager/src/manager.cpp
+++ b/vpd-manager/src/manager.cpp
@@ -197,6 +197,14 @@
l_fruPath + "]");
}
}
+
+ // update keyword in inherited FRUs
+ if (l_rc != constants::FAILURE)
+ {
+ vpdSpecificUtility::updateKwdOnInheritedFrus(
+ l_fruPath, i_paramsToWriteData, l_sysCfgJsonObj);
+ }
+
return l_rc;
}
catch (const std::exception& l_exception)