Find OCC objects

For now, map OCC object per POWER processor.

Add a method that returns a list of OCC objects that need to be on the
bus, based on the processor inventory.

Change-Id: I1dd36b96f71684a1d5866876e4ca9aa0283ef8b0
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index 3b01dfa..2ee9f0f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,10 @@
+# Build these headers, don't install them
+noinst_HEADERS = \
+	occ_finder.hpp
+
 sbin_PROGRAMS = openpower-occ-control
 openpower_occ_control_SOURCES = \
+	occ_finder.cpp \
 	app.cpp
 
 openpower_occ_control_LDFLAGS = \
diff --git a/occ_finder.cpp b/occ_finder.cpp
new file mode 100644
index 0000000..8d6391d
--- /dev/null
+++ b/occ_finder.cpp
@@ -0,0 +1,71 @@
+#include <algorithm>
+#include <sdbusplus/server.hpp>
+#include "occ_finder.hpp"
+#include "config.h"
+
+namespace open_power
+{
+namespace occ
+{
+namespace finder
+{
+
+constexpr auto toChar(size_t c)
+{
+    constexpr auto map = "0123";
+    return map[c];
+}
+
+std::vector<std::string> get()
+{
+    auto bus = sdbusplus::bus::new_default();
+    auto mapper =
+        bus.new_method_call(
+            "xyz.openbmc_project.ObjectMapper",
+            "/xyz/openbmc_project/object_mapper",
+            "xyz.openbmc_project.ObjectMapper",
+            "GetSubTreePaths");
+
+    auto depth = 0;
+    mapper.append(std::string(INVENTORY_ROOT));
+    mapper.append(depth);
+    mapper.append(std::vector<std::string>(
+        {std::string(INVENTORY_ITEM_INTERFACE)}));
+
+    auto result = bus.call(mapper);
+    if (result.is_method_error())
+    {
+        throw std::runtime_error("ObjectMapper GetSubTreePaths failed");
+    }
+
+    std::vector<std::string> response;
+    result.read(response);
+    if (response.empty())
+    {
+        throw std::runtime_error("ObjectMapper GetSubTreePaths : bad response");
+    }
+
+    std::vector<std::string> occs;
+    size_t count = 0;
+    std::string cpu = std::string(CPU_NAME) + toChar(count);
+    auto constexpr MAX_PROCS = 4; // Revisit for multi-node systems
+    for (const auto& path: response)
+    {
+        if (std::equal(cpu.crbegin(), cpu.crend(), path.crbegin()))
+        {
+            if(count == MAX_PROCS)
+            {
+                break;
+            }
+            occs.emplace_back(std::string(OCC_NAME) +
+                              toChar(count++));
+        }
+        cpu.back() = toChar(count);
+    }
+
+    return occs;
+}
+
+} // namespace finder
+} // namespace occ
+} // namespace open_power
diff --git a/occ_finder.hpp b/occ_finder.hpp
new file mode 100644
index 0000000..2a31b71
--- /dev/null
+++ b/occ_finder.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <vector>
+#include <string>
+
+namespace open_power
+{
+namespace occ
+{
+namespace finder
+{
+
+/** @brief Get OCC objects on the system by mapping them to processor inventory
+ *  @returns list of occ objects, such as occ0, occ1, and so on.
+ */
+std::vector<std::string> get();
+
+} // namespace finder
+} // namespace occ
+} // namespace open_power