eSEL: Add severity and callout to the error metadata

The sensor number in the eSEL data is mapped to the inventory
object path and the callout association is added to the error
metadata. The mappings are generated from the MRW. The severity
of the eSEL is inferred from the eSEL data and the corresponding
error level is updated in the metadata. This implementation is
moved from phosphor-ipmi-host to this repository, since this is
OpenPower specific.

Change-Id: I0bf0fe3776b593c6d38a958a23a140aeae71e754
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/.gitignore b/.gitignore
index 56b89b5..6ef6990 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,3 +49,4 @@
 *.lo
 *.la
 org/open_power/OCC/Metrics/*
+/inventory-sensor.cpp
diff --git a/Makefile.am b/Makefile.am
index 3d369a0..ede9703 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,10 +4,14 @@
 liboemhandler_la_SOURCES = oemhandler.cpp \
                            host-interface.cpp \
                            local_users.cpp \
-                           org/open_power/OCC/Metrics/error.cpp
+                           org/open_power/OCC/Metrics/error.cpp \
+                           inventory-sensor.cpp
 
 BUILT_SOURCES = org/open_power/OCC/Metrics/error.hpp \
-                org/open_power/OCC/Metrics/error.cpp
+                org/open_power/OCC/Metrics/error.cpp \
+                inventory-sensor.cpp
+
+CLEANFILES = $(BUILT_SOURCES)
 
 liboemhandler_la_LDFLAGS = $(SYSTEMD_LIBS)\
                            $(SDBUSPLUS_LIBS) \
@@ -28,3 +32,6 @@
 org/open_power/OCC/Metrics/error.cpp: ${top_srcdir}/org/open_power/OCC/Metrics.errors.yaml
 	@mkdir -p `dirname $@`
 	$(SDBUSPLUSPLUS) -r $(top_srcdir) error exception-cpp org.open_power.OCC.Metrics > $@
+
+inventory-sensor.cpp:
+	$(AM_V_GEN)@INVSENSORGEN@ -o $(top_builddir) generate-cpp
diff --git a/configure.ac b/configure.ac
index 4683d40..b002e0a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,6 +70,10 @@
       [CONTROL_HOST_OBJ_MGR="/org/open_power/control"])
 AC_DEFINE_UNQUOTED([CONTROL_HOST_OBJ_MGR], ["$CONTROL_HOST_OBJ_MGR"], [The Control Host D-Bus Object Manager])
 
+AS_IF([test "x$INVSENSOR_YAML_GEN" == "x"], [INVSENSOR_YAML_GEN="inventory-sensor-example.yaml"])
+INVSENSORGEN="$PYTHON ${srcdir}/scripts/inventory-sensor.py -i $INVSENSOR_YAML_GEN"
+AC_SUBST(INVSENSORGEN)
+
 AC_DEFINE(MAPPER_BUS_NAME, "xyz.openbmc_project.ObjectMapper",
           [The object mapper bus name])
 
diff --git a/oemhandler.cpp b/oemhandler.cpp
index e215e39..bf40275 100644
--- a/oemhandler.cpp
+++ b/oemhandler.cpp
@@ -27,6 +27,58 @@
 using namespace phosphor::logging;
 constexpr auto occMetricsType = 0xDD;
 
+extern const ObjectIDMap invSensors;
+const std::map<uint8_t, Entry::Level> severityMap{
+    {0x10, Entry::Level::Warning}, // Recoverable error
+    {0x20, Entry::Level::Warning}, // Predictive error
+    {0x40, Entry::Level::Error},   // Unrecoverable error
+    {0x50, Entry::Level::Error},   // Critical error
+    {0x60, Entry::Level::Error},   // Error from a diagnostic test
+    {0x70, Entry::Level::Warning}, // Recoverable symptom
+    {0xFF, Entry::Level::Error},   // Unknown error
+};
+
+Entry::Level mapSeverity(const std::string& eSELData)
+{
+    constexpr size_t severityOffset = 0x4A;
+
+    if (eSELData.size() > severityOffset)
+    {
+        // Dive in to the IBM log to find the severity
+        uint8_t sev = 0xF0 & eSELData[severityOffset];
+
+        auto find = severityMap.find(sev);
+        if (find != severityMap.end())
+        {
+            return find->second;
+        }
+    }
+
+    // Default to Entry::Level::Error if a matching is not found.
+    return Entry::Level::Error;
+}
+
+std::string mapCalloutAssociation(const std::string& eSELData)
+{
+    auto rec = reinterpret_cast<const SELEventRecord*>(&eSELData[0]);
+    uint8_t sensor = rec->sensorNum;
+
+    /*
+     * Search the sensor number to inventory path mapping to figure out the
+     * inventory associated with the ESEL.
+     */
+    auto found = std::find_if(invSensors.begin(), invSensors.end(),
+                              [&sensor](const auto& iter) {
+                                  return (iter.second.sensorID == sensor);
+                              });
+    if (found != invSensors.end())
+    {
+        return found->first;
+    }
+
+    return {};
+}
+
 std::string readESEL(const char* fileName)
 {
     std::string content{};
@@ -73,24 +125,29 @@
 {
     // 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]());
+    auto sev = mapSeverity(eSELData);
+    auto inventoryPath = mapCalloutAssociation(eSELData);
 
-    for (size_t i = 0; i < eSELData.size(); i++)
+    if (!inventoryPath.empty())
     {
-        sprintf(&data[i * byteSeperator], "%02x ", eSELData[i]);
+        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>(
+            sev, hostmetadata::ESEL(data.get()),
+            hostmetadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));
     }
-    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()));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/oemhandler.hpp b/oemhandler.hpp
index a98ae95..01d5046 100644
--- a/oemhandler.hpp
+++ b/oemhandler.hpp
@@ -1,9 +1,9 @@
-#ifndef __HOST_IPMI_OPENPOWEROEM_HANDLER_H__
-#define __HOST_IPMI_OPENPOWEROEM_HANDLER_H__
+#pragma once
 
 #include <host-ipmid/ipmid-api.h>
 #include <stdint.h>
 
+#include <map>
 #include <string>
 
 // IPMI commands for net functions.
@@ -43,4 +43,37 @@
     uint8_t progress;
 } __attribute__((packed));
 
-#endif
+/** @struct SELEventRecord
+ *
+ *  IPMI SEL event record format.
+ */
+struct SELEventRecord
+{
+    uint16_t recordID;        //!< Record ID.
+    uint8_t recordType;       //!< Record Type.
+    uint32_t timeStamp;       //!< Timestamp.
+    uint16_t generatorID;     //!< Generator ID.
+    uint8_t eventMsgRevision; //!< Event Message Revision.
+    uint8_t sensorType;       //!< Sensor Type.
+    uint8_t sensorNum;        //!< Sensor Number.
+    uint8_t eventType;        //!< Event Dir | Event Type.
+    uint8_t eventData1;       //!< Event Data 1.
+    uint8_t eventData2;       //!< Event Data 2.
+    uint8_t eventData3;       //!< Event Data 3.
+} __attribute__((packed));
+
+using Id = uint8_t;
+using Type = uint8_t;
+using ReadingType = uint8_t;
+using Offset = uint8_t;
+using Path = std::string;
+
+struct Data
+{
+    Id sensorID;
+    Type sensorType;
+    ReadingType eventReadingType;
+    Offset eventOffset;
+};
+
+using ObjectIDMap = std::map<Path, Data>;
diff --git a/scripts/inventory-sensor-example.yaml b/scripts/inventory-sensor-example.yaml
new file mode 100755
index 0000000..7ff78fb
--- /dev/null
+++ b/scripts/inventory-sensor-example.yaml
@@ -0,0 +1,340 @@
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm0:
+  sensorID: 0xa6
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm1:
+  sensorID: 0xa8
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm10:
+  sensorID: 0xba
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm11:
+  sensorID: 0xbc
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm12:
+  sensorID: 0xbe
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm13:
+  sensorID: 0xc0
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm14:
+  sensorID: 0xc2
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm15:
+  sensorID: 0xc4
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm2:
+  sensorID: 0xaa
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm3:
+  sensorID: 0xac
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm4:
+  sensorID: 0xae
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm5:
+  sensorID: 0xb0
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm6:
+  sensorID: 0xb2
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm7:
+  sensorID: 0xb4
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm8:
+  sensorID: 0xb6
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm9:
+  sensorID: 0xb8
+  sensorType: 0x0C
+  eventReadingType: 0x6F
+  offset: 0x04
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0:
+  sensorID: 0x5a
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core0:
+  sensorID: 0x12
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core1:
+  sensorID: 0x15
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core2:
+  sensorID: 0x18
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core3:
+  sensorID: 0x1b
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core4:
+  sensorID: 0x1e
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core5:
+  sensorID: 0x21
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core6:
+  sensorID: 0x24
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core7:
+  sensorID: 0x27
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core8:
+  sensorID: 0x2a
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core9:
+  sensorID: 0x2d
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core10:
+  sensorID: 0x30
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core11:
+  sensorID: 0x33
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core12:
+  sensorID: 0x36
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core13:
+  sensorID: 0x39
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core14:
+  sensorID: 0x3c
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core15:
+  sensorID: 0x3f
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core16:
+  sensorID: 0x42
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core17:
+  sensorID: 0x45
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core18:
+  sensorID: 0x48
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core19:
+  sensorID: 0x4b
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core20:
+  sensorID: 0x4e
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core21:
+  sensorID: 0x51
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core22:
+  sensorID: 0x54
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core23:
+  sensorID: 0x57
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1:
+  sensorID: 0xa4
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core0:
+  sensorID: 0x5c
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core1:
+  sensorID: 0x5f
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core2:
+  sensorID: 0x62
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core3:
+  sensorID: 0x65
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core4:
+  sensorID: 0x68
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core5:
+  sensorID: 0x6b
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core6:
+  sensorID: 0x6e
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core7:
+  sensorID: 0x71
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core8:
+  sensorID: 0x74
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core9:
+  sensorID: 0x77
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core10:
+  sensorID: 0x7a
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core11:
+  sensorID: 0x7d
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core12:
+  sensorID: 0x80
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core13:
+  sensorID: 0x83
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core14:
+  sensorID: 0x86
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core15:
+  sensorID: 0x89
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core16:
+  sensorID: 0x8c
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core17:
+  sensorID: 0x8f
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core18:
+  sensorID: 0x92
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core19:
+  sensorID: 0x95
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core20:
+  sensorID: 0x98
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core21:
+  sensorID: 0x9b
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core22:
+  sensorID: 0x9e
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1/core23:
+  sensorID: 0xa1
+  sensorType: 0x07
+  eventReadingType: 0x6F
+  offset: 0x08
+/xyz/openbmc_project/inventory/system/chassis/motherboard:
+  sensorID: 0x0c
+  sensorType: 0xC7
+  eventReadingType: 0x03
+  offset: 0x00
+/xyz/openbmc_project/inventory/system:
+  sensorID: 0x01
+  sensorType: 0x12
+  eventReadingType: 0x6F
+  offset: 0x02
diff --git a/scripts/inventory-sensor.py b/scripts/inventory-sensor.py
new file mode 100755
index 0000000..1040cf0
--- /dev/null
+++ b/scripts/inventory-sensor.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import yaml
+import argparse
+from mako.template import Template
+
+
+def generate_cpp(sensor_yaml, output_dir):
+    with open(os.path.join(script_dir, sensor_yaml), 'r') as f:
+        ifile = yaml.safe_load(f)
+        if not isinstance(ifile, dict):
+            ifile = {}
+
+        # Render the mako template
+
+        t = Template(filename=os.path.join(
+                     script_dir,
+                     "inventorysensor.mako.cpp"))
+
+        output_cpp = os.path.join(output_dir, "inventory-sensor.cpp")
+        with open(output_cpp, 'w') as fd:
+            fd.write(t.render(sensorDict=ifile))
+
+
+def main():
+
+    valid_commands = {
+        'generate-cpp': generate_cpp
+    }
+    parser = argparse.ArgumentParser(
+        description="Inventory Object to IPMI SensorID code generator")
+
+    parser.add_argument(
+        '-i', '--sensor_yaml', dest='sensor_yaml',
+        default='example.yaml', help='input sensor yaml file to parse')
+
+    parser.add_argument(
+        "-o", "--output-dir", dest="outputdir",
+        default=".",
+        help="output directory")
+
+    parser.add_argument(
+        'command', metavar='COMMAND', type=str,
+        choices=valid_commands.keys(),
+        help='Command to run.')
+
+    args = parser.parse_args()
+
+    if (not (os.path.isfile(os.path.join(script_dir, args.sensor_yaml)))):
+        sys.exit("Can not find input yaml file " + args.sensor_yaml)
+
+    function = valid_commands[args.command]
+    function(args.sensor_yaml, args.outputdir)
+
+
+if __name__ == '__main__':
+    script_dir = os.path.dirname(os.path.realpath(__file__))
+    main()
diff --git a/scripts/inventorysensor.mako.cpp b/scripts/inventorysensor.mako.cpp
new file mode 100644
index 0000000..0689662
--- /dev/null
+++ b/scripts/inventorysensor.mako.cpp
@@ -0,0 +1,26 @@
+## This file is a template.  The comment below is emitted
+## into the rendered file; feel free to edit this file.
+
+// !!! WARNING: This is a GENERATED Code..Please do NOT Edit !!!
+
+#include "oemhandler.hpp"
+
+extern const ObjectIDMap invSensors = {
+% for key in sensorDict.iterkeys():
+   % if key:
+{"${key}",
+    {
+<%
+       objectPath = sensorDict[key]
+       sensorID = objectPath["sensorID"]
+       sensorType = objectPath["sensorType"]
+       eventReadingType = objectPath["eventReadingType"]
+       offset = objectPath["offset"]
+%>
+        ${sensorID},${sensorType},${eventReadingType},${offset}
+    }
+},
+   % endif
+% endfor
+};
+