PLDM: Implement host-condition interface

This commit implements the PDI interface defined at
https://gerrit.openbmc-project.xyz/c/openbmc
/phosphor-dbus-interfaces/+/42435

pldmd hosts the new xyz.openbmc_project.Condition.HostFirmware interface
so it's difficult for it to have other code within pldmd to also set
this during startup.

The solution proposed in this commit is to provide the hostPDRHandler
object to the HostFirmware interface implementation. This then allows
reads of the HostFirmware property to just ask the hostPDRHandler for
the current state of the host.

Signed-off-by: Pavithra Barithaya <pavithra.b@ibm.com>
Change-Id: I3f7d4f573332e96fcd3ae594dc25750070cd6e62
diff --git a/host-bmc/host_condition.cpp b/host-bmc/host_condition.cpp
new file mode 100644
index 0000000..2bdcb36
--- /dev/null
+++ b/host-bmc/host_condition.cpp
@@ -0,0 +1,24 @@
+#include "host_condition.hpp"
+
+namespace pldm
+{
+namespace dbus_api
+{
+
+Host::FirmwareCondition Host::currentFirmwareCondition() const
+{
+    bool hostRunning = false;
+
+    if (hostPdrObj != nullptr)
+    {
+        hostRunning = hostPdrObj.get()->isHostUp();
+    }
+
+    auto value = hostRunning ? Host::FirmwareCondition::Running
+                             : Host::FirmwareCondition::Off;
+
+    return value;
+}
+
+} // namespace dbus_api
+} // namespace pldm
diff --git a/host-bmc/host_condition.hpp b/host-bmc/host_condition.hpp
new file mode 100644
index 0000000..6ea9978
--- /dev/null
+++ b/host-bmc/host_condition.hpp
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "host-bmc/host_pdr_handler.hpp"
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+#include <xyz/openbmc_project/Condition/HostFirmware/server.hpp>
+
+namespace pldm
+{
+namespace dbus_api
+{
+
+using HostIntf = sdbusplus::server::object::object<
+    sdbusplus::xyz::openbmc_project::Condition::server::HostFirmware>;
+
+class Host : public HostIntf
+{
+  public:
+    Host() = delete;
+    Host(const Host&) = delete;
+    Host& operator=(const Host&) = delete;
+    Host(Host&&) = delete;
+    Host& operator=(Host&&) = delete;
+    virtual ~Host() = default;
+
+    Host(sdbusplus::bus::bus& bus, const std::string& path) :
+        HostIntf(bus, path.c_str()){};
+
+    /** @brief Override reads to CurrentFirmwareCondition */
+    FirmwareCondition currentFirmwareCondition() const override;
+
+    /** @brief Store shared pointer to host PDR instance */
+    void setHostPdrObj(std::shared_ptr<HostPDRHandler> obj)
+    {
+        hostPdrObj = obj;
+    }
+
+  private:
+    std::shared_ptr<HostPDRHandler> hostPdrObj;
+};
+} // namespace dbus_api
+} // namespace pldm
diff --git a/meson.build b/meson.build
index 949d889..e674da3 100644
--- a/meson.build
+++ b/meson.build
@@ -186,6 +186,7 @@
   'pldmd/dbus_impl_requester.cpp',
   'pldmd/instance_id.cpp',
   'pldmd/dbus_impl_pdr.cpp',
+  'host-bmc/host_condition.cpp',
   implicit_include_directories: false,
   dependencies: deps,
   install: true,
diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp
index 00019f1..b1f1c95 100644
--- a/pldmd/pldmd.cpp
+++ b/pldmd/pldmd.cpp
@@ -5,6 +5,7 @@
 
 #include "common/utils.hpp"
 #include "dbus_impl_requester.hpp"
+#include "host-bmc/host_condition.hpp"
 #include "invoker.hpp"
 #include "requester/handler.hpp"
 #include "requester/request.hpp"
@@ -167,6 +168,9 @@
     auto event = Event::get_default();
     auto& bus = pldm::utils::DBusHandler::getBus();
     dbus_api::Requester dbusImplReq(bus, "/xyz/openbmc_project/pldm");
+
+    dbus_api::Host dbusImplHost(bus, "/xyz/openbmc_project/pldm");
+
     Invoker invoker{};
     requester::Handler<requester::Request> reqHandler(sockfd, event,
                                                       dbusImplReq);
@@ -183,7 +187,7 @@
                     decltype(&pldm_entity_association_tree_destroy)>
         bmcEntityTree(pldm_entity_association_tree_init(),
                       pldm_entity_association_tree_destroy);
-    std::unique_ptr<HostPDRHandler> hostPDRHandler;
+    std::shared_ptr<HostPDRHandler> hostPDRHandler;
     std::unique_ptr<pldm::host_effecters::HostEffecterParser>
         hostEffecterParser;
     std::unique_ptr<DbusToPLDMEvent> dbusToPLDMEventHandler;
@@ -191,10 +195,14 @@
     auto hostEID = pldm::utils::readHostEID();
     if (hostEID)
     {
-        hostPDRHandler = std::make_unique<HostPDRHandler>(
+        hostPDRHandler = std::make_shared<HostPDRHandler>(
             sockfd, hostEID, event, pdrRepo.get(), EVENTS_JSONS_DIR,
             entityTree.get(), bmcEntityTree.get(), dbusImplReq, &reqHandler,
             verbose);
+        // HostFirmware interface needs access to hostPDR to know if host
+        // is running
+        dbusImplHost.setHostPdrObj(hostPDRHandler);
+
         hostEffecterParser =
             std::make_unique<pldm::host_effecters::HostEffecterParser>(
                 &dbusImplReq, sockfd, pdrRepo.get(), dbusHandler.get(),