eSEL : Handle logging of eSEL in OpenPower OEM library

The eSEL sent from host is logged as D-Bus error object only when
Add SEL command is from the host. Since the eSEL is an OpenPower
error representation, this should not be handled in the phosphor
implementation of the Add SEL command. The eSEL is logged as D-Bus
error object when the progress indicator in the Partial Add eSEL data
indicates last portion of the eSEL data.

Change-Id: I85c91e3c4819fb610ccf5ef27c2878e836c0f70e
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/elog-errors.hpp b/elog-errors.hpp
index 7cf7a37..5e6f204 100644
--- a/elog-errors.hpp
+++ b/elog-errors.hpp
@@ -11,6 +11,86 @@
 
 namespace sdbusplus
 {
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct GPIO;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace org
+{
+namespace open_power
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct Procedure;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace open_power
+} // namespace org
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct Inventory;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct IIC;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
 namespace org
 {
 namespace open_power
@@ -29,6 +109,80 @@
 } // namespace org
 } // namespace sdbusplus
 
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct Device;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace org
+{
+namespace open_power
+{
+namespace Host
+{
+namespace Error
+{
+struct MaintenanceProcedure;
+} // namespace Error
+} // namespace Host
+} // namespace open_power
+} // namespace org
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace org
+{
+namespace open_power
+{
+namespace Host
+{
+namespace Error
+{
+struct Event;
+} // namespace Error
+} // namespace Host
+} // namespace open_power
+} // namespace org
+} // namespace sdbusplus
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace Error
+{
+struct IPMISensor;
+} // namespace Error
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
 namespace phosphor
 {
 
@@ -39,6 +193,57 @@
 {
 namespace open_power
 {
+namespace Common
+{
+namespace Callout
+{
+namespace _Procedure
+{
+
+struct PROCEDURE
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "PROCEDURE";
+    using type = std::tuple<std::decay_t<decltype("PROCEDURE=%u")>, uint32_t>;
+    explicit constexpr PROCEDURE(uint32_t a) :
+        _entry(entry("PROCEDURE=%u", a)){};
+    type _entry;
+};
+
+} // namespace _Procedure
+
+struct Procedure
+{
+    static constexpr auto L = level::ERR;
+    using PROCEDURE = _Procedure::PROCEDURE;
+    using metadata_types = std::tuple<PROCEDURE>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace open_power
+} // namespace org
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::org::open_power::Common::Callout::Error::Procedure>
+{
+    using type = org::open_power::Common::Callout::Procedure;
+};
+
+} // namespace details
+
+namespace org
+{
+namespace open_power
+{
 namespace OCC
 {
 namespace Metrics
@@ -48,10 +253,14 @@
 
 struct ESEL
 {
-    static constexpr auto str = "ESEL=%s";
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
     static constexpr auto str_short = "ESEL";
-    using type = std::tuple<std::decay_t<decltype(str)>, const char*>;
-    explicit constexpr ESEL(const char* a) : _entry(entry(str, a)){};
+    using type = std::tuple<std::decay_t<decltype("ESEL=%s")>, const char*>;
+    explicit constexpr ESEL(const char* a) : _entry(entry("ESEL=%s", a)){};
     type _entry;
 };
 
@@ -81,6 +290,403 @@
 
 } // namespace details
 
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _Device
+{
+
+struct CALLOUT_ERRNO
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "CALLOUT_ERRNO";
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_ERRNO=%d")>, int32_t>;
+    explicit constexpr CALLOUT_ERRNO(int32_t a) :
+        _entry(entry("CALLOUT_ERRNO=%d", a)){};
+    type _entry;
+};
+struct CALLOUT_DEVICE_PATH
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "CALLOUT_DEVICE_PATH";
+    using type = std::tuple<std::decay_t<decltype("CALLOUT_DEVICE_PATH=%s")>,
+                            const char*>;
+    explicit constexpr CALLOUT_DEVICE_PATH(const char* a) :
+        _entry(entry("CALLOUT_DEVICE_PATH=%s", a)){};
+    type _entry;
+};
+
+} // namespace _Device
+
+struct Device
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_ERRNO = _Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH = _Device::CALLOUT_DEVICE_PATH;
+    using metadata_types = std::tuple<CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::Device>
+{
+    using type = xyz::openbmc_project::Common::Callout::Device;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _GPIO
+{
+
+struct CALLOUT_GPIO_NUM
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "CALLOUT_GPIO_NUM";
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_GPIO_NUM=%u")>, uint32_t>;
+    explicit constexpr CALLOUT_GPIO_NUM(uint32_t a) :
+        _entry(entry("CALLOUT_GPIO_NUM=%u", a)){};
+    type _entry;
+};
+
+} // namespace _GPIO
+
+struct GPIO
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_GPIO_NUM = _GPIO::CALLOUT_GPIO_NUM;
+    using CALLOUT_ERRNO =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH;
+    using metadata_types =
+        std::tuple<CALLOUT_GPIO_NUM, CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::GPIO>
+{
+    using type = xyz::openbmc_project::Common::Callout::GPIO;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _IIC
+{
+
+struct CALLOUT_IIC_BUS
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "CALLOUT_IIC_BUS";
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_IIC_BUS=%s")>, const char*>;
+    explicit constexpr CALLOUT_IIC_BUS(const char* a) :
+        _entry(entry("CALLOUT_IIC_BUS=%s", a)){};
+    type _entry;
+};
+struct CALLOUT_IIC_ADDR
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "CALLOUT_IIC_ADDR";
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_IIC_ADDR=0x%hx")>, uint16_t>;
+    explicit constexpr CALLOUT_IIC_ADDR(uint16_t a) :
+        _entry(entry("CALLOUT_IIC_ADDR=0x%hx", a)){};
+    type _entry;
+};
+
+} // namespace _IIC
+
+struct IIC
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_IIC_BUS = _IIC::CALLOUT_IIC_BUS;
+    using CALLOUT_IIC_ADDR = _IIC::CALLOUT_IIC_ADDR;
+    using CALLOUT_ERRNO =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_ERRNO;
+    using CALLOUT_DEVICE_PATH =
+        xyz::openbmc_project::Common::Callout::Device::CALLOUT_DEVICE_PATH;
+    using metadata_types = std::tuple<CALLOUT_IIC_BUS, CALLOUT_IIC_ADDR,
+                                      CALLOUT_ERRNO, CALLOUT_DEVICE_PATH>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::IIC>
+{
+    using type = xyz::openbmc_project::Common::Callout::IIC;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _Inventory
+{
+
+struct CALLOUT_INVENTORY_PATH
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "CALLOUT_INVENTORY_PATH";
+    using type = std::tuple<std::decay_t<decltype("CALLOUT_INVENTORY_PATH=%s")>,
+                            const char*>;
+    explicit constexpr CALLOUT_INVENTORY_PATH(const char* a) :
+        _entry(entry("CALLOUT_INVENTORY_PATH=%s", a)){};
+    type _entry;
+};
+
+} // namespace _Inventory
+
+struct Inventory
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_INVENTORY_PATH = _Inventory::CALLOUT_INVENTORY_PATH;
+    using metadata_types = std::tuple<CALLOUT_INVENTORY_PATH>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::Inventory>
+{
+    using type = xyz::openbmc_project::Common::Callout::Inventory;
+};
+
+} // namespace details
+
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace Common
+{
+namespace Callout
+{
+namespace _IPMISensor
+{
+
+struct CALLOUT_IPMI_SENSOR_NUM
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "CALLOUT_IPMI_SENSOR_NUM";
+    using type =
+        std::tuple<std::decay_t<decltype("CALLOUT_IPMI_SENSOR_NUM=%u")>,
+                   uint32_t>;
+    explicit constexpr CALLOUT_IPMI_SENSOR_NUM(uint32_t a) :
+        _entry(entry("CALLOUT_IPMI_SENSOR_NUM=%u", a)){};
+    type _entry;
+};
+
+} // namespace _IPMISensor
+
+struct IPMISensor
+{
+    static constexpr auto L = level::ERR;
+    using CALLOUT_IPMI_SENSOR_NUM = _IPMISensor::CALLOUT_IPMI_SENSOR_NUM;
+    using metadata_types = std::tuple<CALLOUT_IPMI_SENSOR_NUM>;
+};
+
+} // namespace Callout
+} // namespace Common
+} // namespace openbmc_project
+} // namespace xyz
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::xyz::openbmc_project::Common::Callout::Error::IPMISensor>
+{
+    using type = xyz::openbmc_project::Common::Callout::IPMISensor;
+};
+
+} // namespace details
+
+namespace org
+{
+namespace open_power
+{
+namespace Host
+{
+namespace _Event
+{
+
+struct ESEL
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "ESEL";
+    using type = std::tuple<std::decay_t<decltype("ESEL=%s")>, const char*>;
+    explicit constexpr ESEL(const char* a) : _entry(entry("ESEL=%s", a)){};
+    type _entry;
+};
+
+} // namespace _Event
+
+struct Event
+{
+    static constexpr auto L = level::ERR;
+    using ESEL = _Event::ESEL;
+    using CALLOUT_INVENTORY_PATH = xyz::openbmc_project::Common::Callout::
+        Inventory::CALLOUT_INVENTORY_PATH;
+    using metadata_types = std::tuple<ESEL, CALLOUT_INVENTORY_PATH>;
+};
+
+} // namespace Host
+} // namespace open_power
+} // namespace org
+
+namespace details
+{
+
+template <>
+struct map_exception_type<sdbusplus::org::open_power::Host::Error::Event>
+{
+    using type = org::open_power::Host::Event;
+};
+
+} // namespace details
+
+namespace org
+{
+namespace open_power
+{
+namespace Host
+{
+namespace _MaintenanceProcedure
+{
+
+struct ESEL
+{
+    /*
+     * We can't use -fsanitize=undefined if we declare a
+     * 'static constexpr auto str' member, so don't. Instead, open-code the
+     * mako template lookups.
+     */
+    static constexpr auto str_short = "ESEL";
+    using type = std::tuple<std::decay_t<decltype("ESEL=%s")>, const char*>;
+    explicit constexpr ESEL(const char* a) : _entry(entry("ESEL=%s", a)){};
+    type _entry;
+};
+
+} // namespace _MaintenanceProcedure
+
+struct MaintenanceProcedure
+{
+    static constexpr auto L = level::ERR;
+    using ESEL = _MaintenanceProcedure::ESEL;
+    using PROCEDURE = org::open_power::Common::Callout::Procedure::PROCEDURE;
+    using metadata_types = std::tuple<ESEL, PROCEDURE>;
+};
+
+} // namespace Host
+} // namespace open_power
+} // namespace org
+
+namespace details
+{
+
+template <>
+struct map_exception_type<
+    sdbusplus::org::open_power::Host::Error::MaintenanceProcedure>
+{
+    using type = org::open_power::Host::MaintenanceProcedure;
+};
+
+} // namespace details
+
 } // namespace logging
 
 } // namespace phosphor
diff --git a/oemhandler.cpp b/oemhandler.cpp
index a66f3e6..e215e39 100644
--- a/oemhandler.cpp
+++ b/oemhandler.cpp
@@ -16,6 +16,7 @@
 #include <host-interface.hpp>
 #include <host-ipmid/ipmid-host-cmd.hpp>
 #include <memory>
+#include <org/open_power/Host/error.hpp>
 #include <org/open_power/OCC/Metrics/error.hpp>
 #include <sdbusplus/bus.hpp>
 
@@ -68,6 +69,30 @@
     report<error>(metadata::ESEL(data.get()));
 }
 
+void createHostEntry(const std::string& eSELData)
+{
+    // Each byte in eSEL is formatted as %02x with a space between bytes and
+    // insert '/0' at the end of the character array.
+    std::string inventoryPath{};
+    constexpr auto byteSeperator = 3;
+
+    std::unique_ptr<char[]> data(
+        new char[(eSELData.size() * byteSeperator) + 1]());
+
+    for (size_t i = 0; i < eSELData.size(); i++)
+    {
+        sprintf(&data[i * byteSeperator], "%02x ", eSELData[i]);
+    }
+    data[eSELData.size() * byteSeperator] = '\0';
+
+    using hosterror = sdbusplus::org::open_power::Host::Error::Event;
+    using hostmetadata = org::open_power::Host::Event;
+
+    report<hosterror>(
+        Entry::Level::Warning, hostmetadata::ESEL(data.get()),
+        hostmetadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // For the First partial add eSEL the SEL Record ID and offset
 // value should be 0x0000. The extended data needs to be in
@@ -161,6 +186,10 @@
         {
             createOCCLogEntry(eSELData);
         }
+        else
+        {
+            createHostEntry(eSELData);
+        }
     }
 
     return rc;