Determine the host software id

The id is determined by hashing the PNOR version.
For now, assume the pnor partitions are located at
/tmp/pnor. Part of openbmc/openbmc#1276. The PNOR
version is read from pnor.toc

Change-Id: Iddab7bb4ae5c350c60abf93057ddd997c97fa84c
Signed-off-by: Gunnar Mills <gmills@us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index d686971..9cd2046 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,11 +15,13 @@
 generic_cxxflags = \
 	$(SYSTEMD_CFLAGS) \
 	$(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
-	$(SDBUSPLUS_CFLAGS)
+	$(SDBUSPLUS_CFLAGS) \
+	$(PHOSPHOR_LOGGING_CFLAGS)
 generic_ldflags = \
 	$(SYSTEMD_LIBS) \
 	$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
-	$(SDBUSPLUS_LIBS)
+	$(SDBUSPLUS_LIBS) \
+	$(PHOSPHOR_LOGGING_LIBS)
 
 openpower_version_host_software_manager_CXXFLAGS = $(generic_cxxflags)
 openpower_version_host_software_manager_LDFLAGS = $(generic_ldflags)
diff --git a/configure.ac b/configure.ac
index d51ad37..45081db 100755
--- a/configure.ac
+++ b/configure.ac
@@ -15,6 +15,8 @@
     AC_MSG_ERROR(["Requires phosphor-dbus-interfaces package."]))
 PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],,
     AC_MSG_ERROR(["Requires sdbusplus package."]))
+PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],,
+    [AC_MSG_ERROR([The openbmc/phosphor-logging package is required])])
 
 # Checks for library functions
 LT_INIT # Required for systemd linking
@@ -35,6 +37,10 @@
 AC_DEFINE(BUSNAME_UPDATER, "org.open_power.Software.Host.Updater",
     [The item updater DBus busname to own.])
 
+AC_ARG_VAR(TOC_FILE, [The path to the pnor toc file])
+AS_IF([test "x$TOC_FILE" == "x"], [TOC_FILE="/tmp/pnor/pnor.toc"])
+AC_DEFINE_UNQUOTED([TOC_FILE], ["$TOC_FILE"], [The path to the pnor toc file])
+
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
 
diff --git a/version_host_software_manager.cpp b/version_host_software_manager.cpp
old mode 100755
new mode 100644
index 1fc562e..7719270
--- a/version_host_software_manager.cpp
+++ b/version_host_software_manager.cpp
@@ -1,3 +1,9 @@
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <stdexcept>
+#include <phosphor-logging/log.hpp>
 #include "version_host_software_manager.hpp"
 
 namespace openpower
@@ -7,6 +13,64 @@
 namespace manager
 {
 
+using namespace phosphor::logging;
+
+std::string Version::getVersion(const std::string& tocFilePath)
+{
+    constexpr auto versionKey = "version=";
+    constexpr auto versionKeySize = strlen(versionKey);
+
+    if (tocFilePath.empty())
+    {
+        log<level::ERR>("Error TocFilePath is empty");
+        throw std::runtime_error("TocFilePath is empty");
+    }
+
+    std::string version{};
+    std::ifstream efile;
+    std::string line;
+    efile.exceptions(std::ifstream::failbit
+                     | std::ifstream::badbit
+                     | std::ifstream::eofbit);
+
+    // Too many GCC bugs (53984, 66145) to do this the right way...
+    try
+    {
+        efile.open(tocFilePath);
+        while (getline(efile, line))
+        {
+            if (line.compare(0, versionKeySize, versionKey) == 0)
+            {
+                version = line.substr(versionKeySize);
+                break;
+            }
+        }
+        efile.close();
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>("Error in reading Host pnor.toc file");
+    }
+
+    return version;
+}
+
+std::string Version::getId(const std::string& version)
+{
+    std::stringstream hexId;
+
+    if (version.empty())
+    {
+        log<level::ERR>("Error Host version is empty");
+        throw std::runtime_error("Host version is empty");
+    }
+
+    // Only want 8 hex digits.
+    hexId << std::hex << ((std::hash<std::string> {}(
+                               version)) & 0xFFFFFFFF);
+    return hexId.str();
+}
+
 } // namespace manager
 } // namespace software
 } // namepsace openpower
diff --git a/version_host_software_manager.hpp b/version_host_software_manager.hpp
index d674f9c..eb970aa 100755
--- a/version_host_software_manager.hpp
+++ b/version_host_software_manager.hpp
@@ -25,10 +25,25 @@
          *
          * @param[in] bus       - The Dbus bus object
          * @param[in] objPath   - The Dbus object path
+         * @param[in] versionId - The Host version identifier
          */
         Version(sdbusplus::bus::bus& bus,
-                const char* objPath) : VersionInherit(
-                    bus, objPath) {};
+                const std::string& objPath) : VersionInherit(
+                    bus, (objPath).c_str()) {};
+
+        /**
+         * @brief Get the code version identifier.
+         *
+         * @return The version identifier.
+         **/
+        static std::string getVersion(const std::string& tocFilePath);
+
+        /**
+         * @brief Get the Host Version id.
+         *
+         * @return The id.
+         **/
+        static std::string getId(const std::string& version);
 };
 
 } // namespace manager
diff --git a/version_host_software_manager_main.cpp b/version_host_software_manager_main.cpp
old mode 100755
new mode 100644
index 5b77904..bb3283e
--- a/version_host_software_manager_main.cpp
+++ b/version_host_software_manager_main.cpp
@@ -1,4 +1,5 @@
 #include <sdbusplus/bus.hpp>
+#include <string>
 #include "config.h"
 #include "version_host_software_manager.hpp"
 
@@ -10,6 +11,12 @@
     sdbusplus::server::manager::manager objManager(bus,
             SOFTWARE_OBJPATH);
 
+    auto version = openpower::software::manager::Version::getVersion(TOC_FILE);
+    auto id = openpower::software::manager::Version::getId(version);
+
+    openpower::software::manager::Version manager(bus,
+            std::string{SOFTWARE_OBJPATH} + '/' + id);
+
     bus.request_name(VERSION_BUSNAME);
 
     while (true)