Revamped code for VPD parser
The commit removes all the pre-existing code from the branch
and pushes the revamped code.
Major modification includes:
- Movement from multi exe to single daemon model.
- Multithreaded approach to parse FRU VPD.
- Better error handling.
- Refactored code for performance optimization.
Note: This code supports all the existing functionalities as it is.
Change-Id: I1ddce1f0725ac59020b72709689a1013643bda8b
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
diff --git a/vpd-manager/include/manager.hpp b/vpd-manager/include/manager.hpp
new file mode 100644
index 0000000..cb64123
--- /dev/null
+++ b/vpd-manager/include/manager.hpp
@@ -0,0 +1,300 @@
+#pragma once
+
+#include "constants.hpp"
+#include "gpio_monitor.hpp"
+#include "types.hpp"
+#include "worker.hpp"
+
+#include <sdbusplus/asio/object_server.hpp>
+
+namespace vpd
+{
+/**
+ * @brief Class to manage VPD processing.
+ *
+ * The class is responsible to implement methods to manage VPD on the system.
+ * It also implements methods to be exposed over D-Bus required to access/edit
+ * VPD data.
+ */
+class Manager
+{
+ public:
+ /**
+ * List of deleted methods.
+ */
+ Manager(const Manager&) = delete;
+ Manager& operator=(const Manager&) = delete;
+ Manager(Manager&&) = delete;
+
+ /**
+ * @brief Constructor.
+ *
+ * @param[in] ioCon - IO context.
+ * @param[in] iFace - interface to implement.
+ * @param[in] connection - Dbus Connection.
+ */
+ Manager(const std::shared_ptr<boost::asio::io_context>& ioCon,
+ const std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
+ const std::shared_ptr<sdbusplus::asio::connection>& asioConnection);
+
+ /**
+ * @brief Destructor.
+ */
+ ~Manager() = default;
+
+ /**
+ * @brief Update keyword value.
+ *
+ * This API is used to update keyword value on the given input path and its
+ * redundant path(s) if any taken from system config JSON.
+ *
+ * To update IPZ type VPD, input parameter for writing should be in the form
+ * of (Record, Keyword, Value). Eg: ("VINI", "SN", {0x01, 0x02, 0x03}).
+ *
+ * To update Keyword type VPD, input parameter for writing should be in the
+ * form of (Keyword, Value). Eg: ("PE", {0x01, 0x02, 0x03}).
+ *
+ * @param[in] i_vpdPath - Path (inventory object path/FRU EEPROM path).
+ * @param[in] i_paramsToWriteData - Input details.
+ *
+ * @return On success returns number of bytes written, on failure returns
+ * -1.
+ */
+ int updateKeyword(const types::Path i_vpdPath,
+ const types::WriteVpdParams i_paramsToWriteData);
+
+ /**
+ * @brief Update keyword value on hardware.
+ *
+ * This API is used to update keyword value on hardware. Updates only on the
+ * given input hardware path, does not look for corresponding redundant or
+ * primary path against the given path. To update corresponding paths, make
+ * separate call with respective path.
+ *
+ * To update IPZ type VPD, input parameter for writing should be in the form
+ * of (Record, Keyword, Value). Eg: ("VINI", "SN", {0x01, 0x02, 0x03}).
+ *
+ * To update Keyword type VPD, input parameter for writing should be in the
+ * form of (Keyword, Value). Eg: ("PE", {0x01, 0x02, 0x03}).
+ *
+ * @param[in] i_fruPath - EEPROM path of the FRU.
+ * @param[in] i_paramsToWriteData - Input details.
+ *
+ * @return On success returns number of bytes written, on failure returns
+ * -1.
+ */
+ int updateKeywordOnHardware(
+ const types::Path i_fruPath,
+ const types::WriteVpdParams i_paramsToWriteData) noexcept;
+
+ /**
+ * @brief Read keyword value.
+ *
+ * API can be used to read VPD keyword from the given input path.
+ *
+ * To read keyword of type IPZ, input parameter for reading should be in the
+ * form of (Record, Keyword). Eg: ("VINI", "SN").
+ *
+ * To read keyword from keyword type VPD, just keyword name has to be
+ * supplied in the input parameter. Eg: ("SN").
+ *
+ * @param[in] i_fruPath - EEPROM path.
+ * @param[in] i_paramsToReadData - Input details.
+ *
+ * @throw
+ * sdbusplus::xyz::openbmc_project::Common::Device::Error::ReadFailure.
+ *
+ * @return On success returns the read value in variant of array of bytes.
+ * On failure throws exception.
+ */
+ types::DbusVariantType
+ readKeyword(const types::Path i_fruPath,
+ const types::ReadVpdParams i_paramsToReadData);
+
+ /**
+ * @brief Collect single FRU VPD
+ * API can be used to perform VPD collection for the given FRU, only if the
+ * current state of the system matches with the state at which the FRU is
+ * allowed for VPD recollection.
+ *
+ * @param[in] i_dbusObjPath - D-bus object path
+ */
+ void collectSingleFruVpd(
+ const sdbusplus::message::object_path& i_dbusObjPath);
+
+ /**
+ * @brief Delete single FRU VPD
+ * API can be used to perform VPD deletion for the given FRU.
+ *
+ * @param[in] i_dbusObjPath - D-bus object path
+ */
+ void deleteSingleFruVpd(
+ const sdbusplus::message::object_path& i_dbusObjPath);
+
+ /**
+ * @brief Get expanded location code.
+ *
+ * API to get expanded location code from the unexpanded location code.
+ *
+ * @param[in] i_unexpandedLocationCode - Unexpanded location code.
+ * @param[in] i_nodeNumber - Denotes the node in case of a multi-node
+ * configuration, defaulted to zero incase of single node system.
+ *
+ * @throw xyz.openbmc_project.Common.Error.InvalidArgument for
+ * invalid argument.
+ *
+ * @return Location code of the FRU.
+ */
+ std::string getExpandedLocationCode(
+ const std::string& i_unexpandedLocationCode,
+ [[maybe_unused]] const uint16_t i_nodeNumber = 0);
+
+ /**
+ * @brief Get D-Bus object path of FRUs from expanded location code.
+ *
+ * An API to get list of FRU D-Bus object paths for a given expanded
+ * location code.
+ *
+ * @param[in] i_expandedLocationCode - Expanded location code.
+ *
+ * @throw xyz.openbmc_project.Common.Error.InvalidArgument for
+ * invalid argument.
+ *
+ * @return List of FRUs D-Bus object paths for the given location code.
+ */
+ types::ListOfPaths getFrusByExpandedLocationCode(
+ const std::string& i_expandedLocationCode);
+
+ /**
+ * @brief Get D-Bus object path of FRUs from unexpanded location code.
+ *
+ * An API to get list of FRU D-Bus object paths for a given unexpanded
+ * location code.
+ *
+ * @param[in] i_unexpandedLocationCode - Unexpanded location code.
+ * @param[in] i_nodeNumber - Denotes the node in case of a multi-node
+ * configuration, defaulted to zero incase of single node system.
+ *
+ * @throw xyz.openbmc_project.Common.Error.InvalidArgument for
+ * invalid argument.
+ *
+ * @return List of FRUs D-Bus object paths for the given location code.
+ */
+ types::ListOfPaths getFrusByUnexpandedLocationCode(
+ const std::string& i_unexpandedLocationCode,
+ [[maybe_unused]] const uint16_t i_nodeNumber = 0);
+
+ /**
+ * @brief Get Hardware path
+ * API can be used to get EEPROM path for the given inventory path.
+ *
+ * @param[in] i_dbusObjPath - D-bus object path
+ *
+ * @return Corresponding EEPROM path.
+ */
+ std::string getHwPath(const sdbusplus::message::object_path& i_dbusObjPath);
+
+ /**
+ * @brief Perform VPD recollection
+ * This api will trigger parser to perform VPD recollection for FRUs that
+ * can be replaced at standby.
+ */
+ void performVpdRecollection();
+
+ /**
+ * @brief Get unexpanded location code.
+ *
+ * An API to get unexpanded location code and node number from expanded
+ * location code.
+ *
+ * @param[in] i_expandedLocationCode - Expanded location code.
+ *
+ * @throw xyz.openbmc_project.Common.Error.InvalidArgument for
+ * invalid argument.
+ *
+ * @return Location code in unexpanded format and its node number.
+ */
+ std::tuple<std::string, uint16_t>
+ getUnexpandedLocationCode(const std::string& i_expandedLocationCode);
+
+ private:
+#ifdef IBM_SYSTEM
+ /**
+ * @brief API to set timer to detect system VPD over D-Bus.
+ *
+ * System VPD is required before bus name for VPD-Manager is claimed. Once
+ * system VPD is published, VPD for other FRUs should be collected. This API
+ * detects id system VPD is already published on D-Bus and based on that
+ * triggers VPD collection for rest of the FRUs.
+ *
+ * Note: Throws exception in case of any failure. Needs to be handled by the
+ * caller.
+ */
+ void SetTimerToDetectSVPDOnDbus();
+
+ /**
+ * @brief Set timer to detect and set VPD collection status for the system.
+ *
+ * Collection of FRU VPD is triggered in a separate thread. Resulting in
+ * multiple threads at a given time. The API creates a timer which on
+ * regular interval will check if all the threads were collected back and
+ * sets the status of the VPD collection for the system accordingly.
+ *
+ * @throw std::runtime_error
+ */
+ void SetTimerToDetectVpdCollectionStatus();
+
+ /**
+ * @brief API to register callback for "AssetTag" property change.
+ */
+ void registerAssetTagChangeCallback();
+
+ /**
+ * @brief Callback API to be triggered on "AssetTag" property change.
+ *
+ * @param[in] i_msg - The callback message.
+ */
+ void processAssetTagChangeCallback(sdbusplus::message_t& i_msg);
+#endif
+
+ /**
+ * @brief An api to check validity of unexpanded location code.
+ *
+ * @param[in] i_locationCode - Unexpanded location code.
+ *
+ * @return True/False based on validity check.
+ */
+ bool isValidUnexpandedLocationCode(const std::string& i_locationCode);
+
+ /**
+ * @brief API to register callback for Host state change.
+ */
+ void registerHostStateChangeCallback();
+
+ /**
+ * @brief API to process host state change callback.
+ *
+ * @param[in] i_msg - Callback message.
+ */
+ void hostStateChangeCallBack(sdbusplus::message_t& i_msg);
+
+ // Shared pointer to asio context object.
+ const std::shared_ptr<boost::asio::io_context>& m_ioContext;
+
+ // Shared pointer to Dbus interface class.
+ const std::shared_ptr<sdbusplus::asio::dbus_interface>& m_interface;
+
+ // Shared pointer to bus connection.
+ const std::shared_ptr<sdbusplus::asio::connection>& m_asioConnection;
+
+ // Shared pointer to worker class
+ std::shared_ptr<Worker> m_worker;
+
+ // Shared pointer to GpioMonitor class
+ std::shared_ptr<GpioMonitor> m_gpioMonitor;
+
+ // Variable to hold current collection status
+ std::string m_vpdCollectionStatus = "NotStarted";
+};
+
+} // namespace vpd