openpower-pels: use libpldm directly for IID allocation

libpldm provides APIs for allocating instance IDs directly, which
eliminates the need for remote dbus calls to the pldm daemon.  Refactor
the code to use these APIs and eliminate all the dbus operations.

Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: Ia1214fe6d68cb49dc1c91af07b7046ac652fb9c4
diff --git a/extensions/openpower-pels/pldm_interface.cpp b/extensions/openpower-pels/pldm_interface.cpp
index a784e55..aab7a54 100644
--- a/extensions/openpower-pels/pldm_interface.cpp
+++ b/extensions/openpower-pels/pldm_interface.cpp
@@ -17,7 +17,6 @@
 
 #include <libpldm/base.h>
 #include <libpldm/oem/ibm/file_io.h>
-#include <systemd/sd-bus.h>
 #include <unistd.h>
 
 #include <phosphor-logging/lg2.hpp>
@@ -27,21 +26,6 @@
 namespace openpower::pels
 {
 
-namespace service
-{
-constexpr auto pldm = "xyz.openbmc_project.PLDM";
-}
-
-namespace object_path
-{
-constexpr auto pldm = "/xyz/openbmc_project/pldm";
-}
-
-namespace interface
-{
-constexpr auto pldm_requester = "xyz.openbmc_project.PLDM.Requester";
-}
-
 using namespace sdeventplus;
 using namespace sdeventplus::source;
 
@@ -52,7 +36,8 @@
 
 PLDMInterface::~PLDMInterface()
 {
-    sd_bus_unref(_bus);
+    freeIID();
+    pldm_instance_db_destroy(_pldm_idb);
     closeFD();
 }
 
@@ -101,63 +86,6 @@
     }
 }
 
-void PLDMInterface::instanceIDCallback(sd_bus_message* msg)
-{
-    if (!_inProgress)
-    {
-        lg2::info("A command was canceled while waiting for the instance ID");
-        return;
-    }
-
-    bool failed = false;
-
-    auto rc = sd_bus_message_get_errno(msg);
-    if (rc)
-    {
-        lg2::error("GetInstanceId D-Bus method failed, rc = {RC}", "RC", rc);
-        failed = true;
-    }
-    else
-    {
-        uint8_t id;
-        rc = sd_bus_message_read_basic(msg, 'y', &id);
-        if (rc < 0)
-        {
-            lg2::error("Could not read instance ID out of message, rc = {RC}",
-                       "RC", rc);
-            failed = true;
-        }
-        else
-        {
-            _instanceID = id;
-        }
-    }
-
-    if (failed)
-    {
-        _inProgress = false;
-        callResponseFunc(ResponseStatus::failure);
-    }
-    else
-    {
-        try
-        {
-            startCommand();
-        }
-        catch (const std::exception& e)
-        {
-            callResponseFunc(ResponseStatus::failure);
-        }
-    }
-}
-
-int iidCallback(sd_bus_message* msg, void* data, sd_bus_error* /*err*/)
-{
-    auto* interface = static_cast<PLDMInterface*>(data);
-    interface->instanceIDCallback(msg);
-    return 0;
-}
-
 void PLDMInterface::startCommand()
 {
     try
@@ -182,19 +110,49 @@
     }
 }
 
-void PLDMInterface::startReadInstanceID()
+void PLDMInterface::allocIID()
 {
-    auto rc = sd_bus_call_method_async(
-        _bus, NULL, service::pldm, object_path::pldm, interface::pldm_requester,
-        "GetInstanceId", iidCallback, this, "y", _eid);
-
-    if (rc < 0)
+    if (_instanceID)
     {
-        lg2::error(
-            "Error calling sd_bus_call_method_async, rc = {RC}, msg = {MSG}",
-            "RC", rc, "MSG", strerror(-rc));
-        throw std::runtime_error{"sd_bus_call_method_async failed"};
+        return;
     }
+
+    pldm_instance_id_t iid = 0;
+    auto rc = pldm_instance_id_alloc(_pldm_idb, _eid, &iid);
+
+    if (rc == -EAGAIN)
+    {
+        throw std::runtime_error("No free instance ids");
+    }
+    else if (rc)
+    {
+        throw std::system_category().default_error_condition(rc);
+    }
+
+    _instanceID = iid;
+}
+
+void PLDMInterface::freeIID()
+{
+    if (!_instanceID)
+    {
+        return;
+    }
+
+    auto rc = pldm_instance_id_free(_pldm_idb, _eid, *_instanceID);
+
+    if (rc == -EINVAL)
+    {
+        throw std::runtime_error("Instance ID " + std::to_string(*_instanceID) +
+                                 " for TID " + std::to_string(_eid) +
+                                 " was not previously allocated");
+    }
+    else if (rc)
+    {
+        throw std::system_category().default_error_condition(rc);
+    }
+
+    _instanceID = std::nullopt;
 }
 
 CmdStatus PLDMInterface::sendNewLogCmd(uint32_t id, uint32_t size)
@@ -205,16 +163,12 @@
 
     try
     {
-        // Kick off the async call to get the instance ID if
-        // necessary, otherwise start the command itself.
+        // Allocate the instance ID, as needed.
         if (!_instanceID)
         {
-            startReadInstanceID();
+            allocIID();
         }
-        else
-        {
-            startCommand();
-        }
+        startCommand();
     }
     catch (const std::exception& e)
     {
@@ -298,7 +252,7 @@
     cleanupCmd();
 
     // Can't use this instance ID anymore.
-    _instanceID = std::nullopt;
+    freeIID();
 
     if (status == ResponseStatus::success)
     {
@@ -345,7 +299,7 @@
 
 void PLDMInterface::cancelCmd()
 {
-    _instanceID = std::nullopt;
+    freeIID();
     cleanupCmd();
 }
 
diff --git a/extensions/openpower-pels/pldm_interface.hpp b/extensions/openpower-pels/pldm_interface.hpp
index b6dae3c..51ab5c1 100644
--- a/extensions/openpower-pels/pldm_interface.hpp
+++ b/extensions/openpower-pels/pldm_interface.hpp
@@ -2,6 +2,7 @@
 
 #include "host_interface.hpp"
 
+#include <libpldm/instance-id.h>
 #include <libpldm/pldm.h>
 
 #include <sdeventplus/clock.hpp>
@@ -43,7 +44,7 @@
             event,
             std::bind(std::mem_fn(&PLDMInterface::receiveTimerExpired), this))
     {
-        sd_bus_default(&_bus);
+        pldm_instance_db_init_default(&_pldm_idb);
 
         readEID();
     }
@@ -82,17 +83,6 @@
      */
     void cleanupCmd();
 
-    /**
-     * @brief Gets called on the async D-Bus method response to
-     *        getting the PLDM instance ID.
-     *
-     * It will read the instance ID out of the message and then
-     * continue on with sending the new log command to the host.
-     *
-     * @param[in] msg - The message containing the instance ID.
-     */
-    void instanceIDCallback(sd_bus_message* msg);
-
   private:
     /**
      * @brief The asynchronous callback for getting the response
@@ -134,12 +124,6 @@
     void open();
 
     /**
-     * @brief Makes the async D-Bus method call to read the PLDM instance
-     *        ID needed to send PLDM commands.
-     */
-    void startReadInstanceID();
-
-    /**
      * @brief Encodes and sends the PLDM 'new file available' cmd
      */
     void doSend();
@@ -157,6 +141,16 @@
     void startCommand();
 
     /**
+     * @brief Allocates the instance id.
+     */
+    void allocIID();
+
+    /**
+     * @brief Frees the instance id.
+     */
+    void freeIID();
+
+    /**
      * @brief The MCTP endpoint ID
      */
     mctp_eid_t _eid;
@@ -169,7 +163,7 @@
      * If there are command failures, the same instance ID can be
      * used on retries only if the host didn't respond.
      */
-    std::optional<uint8_t> _instanceID;
+    std::optional<pldm_instance_id_t> _instanceID;
 
     /**
      * @brief The PLDM command file descriptor for the current command
@@ -193,9 +187,9 @@
     const std::chrono::milliseconds _receiveTimeout{10000};
 
     /**
-     * @brief The D-Bus connection needed for the async method call.
+     * @brief The libpldm instance ID database.
      */
-    sd_bus* _bus = nullptr;
+    pldm_instance_db* _pldm_idb = nullptr;
 
     /**
      * @brief The ID of the PEL to notify the host of.