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/gpio.hpp b/presence/gpio.hpp
index ae4bc7f..317e264 100644
--- a/presence/gpio.hpp
+++ b/presence/gpio.hpp
@@ -112,6 +112,64 @@
     std::optional<sdeventplus::source::IO> source;
 };
 
+/**
+ * @class NullGpio
+ * @brief a phony presence sensor implementation that always
+ *        reports not-present. Used to keep fan-presence service
+ *        running when hardware is offline.
+ *
+ */
+class NullGpio : public PresenceSensor
+{
+  public:
+    NullGpio() = default;
+
+    /**
+     * @brief start
+     *
+     * Required to conform to interface
+     *
+     * @return false [dummy implementation]
+     */
+    bool start() override
+    {
+        return false;
+    }
+
+    /**
+     * @brief stop
+     *
+     * Required to conform to interface
+     */
+    void stop() override
+    {}
+
+    /**
+     * @brief Check the sensor.
+     *
+     * @return false [dummy implementation]
+     */
+    bool present() override
+    {
+        return false;
+    }
+
+    /**
+     * @brief Called when this presence sensor doesn't agree with other ones.
+     *
+     * @param[in] fanInventoryPath - The fan inventory D-Bus object path.
+     */
+    void logConflict(const std::string& fanInventoryPath) const override
+    {}
+
+  private:
+    /**
+     * @brief Required to conform to interface
+     *
+     */
+    virtual RedundancyPolicy& getPolicy() = 0;
+};
+
 } // namespace presence
 } // namespace fan
 } // namespace phosphor