presence: detect and report GPIO exceptions on startup

To address issue ibm2982, we will now catch exceptions when creating the
GPIO presence sensor and substitute it with a nullary sensor that always
reports non-present. This will give proper error logging for the basic
failure scenario of disconnected hardware. Currently this scenario
causes a core dump and subsequent investigation.

Additionally, an OpenBMC event log has been created using the label
xyz.openbmc_project.Fan.Presence.Error.GPIODeviceUnavailable

Signed-off-by: Mike Capps <mikepcapps@gmail.com>
Change-Id: Ib25fb27ed4a0a23aae667beb1e7708ada7ea7d65
diff --git a/presence/json_parser.cpp b/presence/json_parser.cpp
index 4c4a55c..bfaedaf 100644
--- a/presence/json_parser.cpp
+++ b/presence/json_parser.cpp
@@ -25,6 +25,8 @@
 #include <nlohmann/json.hpp>
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/bus.hpp>
+#include <xyz/openbmc_project/Logging/Create/server.hpp>
+#include <xyz/openbmc_project/Logging/Entry/server.hpp>
 
 #include <filesystem>
 #include <fstream>
@@ -47,6 +49,9 @@
 const std::map<std::string, rpolicyHandler> JsonConfig::_rpolicies = {
     {"anyof", rpolicy::getAnyof}, {"fallback", rpolicy::getFallback}};
 
+const auto loggingPath = "/xyz/openbmc_project/logging";
+const auto loggingCreateIface = "xyz.openbmc_project.Logging.Create";
+
 JsonConfig::JsonConfig(sdbusplus::bus::bus& bus) : _bus(bus)
 {}
 
@@ -266,8 +271,47 @@
     auto devpath = method["devpath"].get<std::string>();
     auto key = method["key"].get<unsigned int>();
 
-    return std::make_unique<PolicyAccess<Gpio, JsonConfig>>(fanIndex, physpath,
-                                                            devpath, key);
+    try
+    {
+        return std::make_unique<PolicyAccess<Gpio, JsonConfig>>(
+            fanIndex, physpath, devpath, key);
+    }
+    catch (const sdbusplus::exception_t& e)
+    {
+        namespace sdlogging = sdbusplus::xyz::openbmc_project::Logging::server;
+
+        log<level::ERR>(
+            fmt::format(
+                "Error creating Gpio device bridge, hardware not detected: {}",
+                e.what())
+                .c_str());
+
+        auto severity =
+            sdlogging::convertForMessage(sdlogging::Entry::Level::Error);
+
+        std::map<std::string, std::string> additionalData{
+            {"PHYSPATH", physpath},
+            {"DEVPATH", devpath},
+            {"FANINDEX", std::to_string(fanIndex)}};
+
+        try
+        {
+
+            util::SDBusPlus::lookupAndCallMethod(
+                loggingPath, loggingCreateIface, "Create",
+                "xyz.openbmc_project.Fan.Presence.Error.GPIODeviceUnavailable",
+                severity, additionalData);
+        }
+        catch (const util::DBusError& e)
+        {
+            log<level::ERR>(fmt::format("Call to create an error log for "
+                                        "presence-sensor failure failed: {}",
+                                        e.what())
+                                .c_str());
+        }
+
+        return std::make_unique<PolicyAccess<NullGpio, JsonConfig>>();
+    }
 }
 
 } // namespace method