Combine attn handler and openpower hwdiags

The main binary is now openpower-hw-diags. This application will take a
command line option --daemon to load it as a daemon. As a daemon it will
register the attention handler portion of application as the attention
gpio event handler. If the application is not loaded as a daemon it will
operate as a stand alone application which accepts command line options
for requesting hardware analyses and diagnostics operations.

Change-Id: I6210b744cb320873d74a0757928f904ca6296846
Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
diff --git a/.gitignore b/.gitignore
index 547b6ed..471453d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 *.sw*
 /build
+/subprojects/libhei
diff --git a/analyzer/analyzer_main.cpp b/analyzer/analyzer_main.cpp
new file mode 100644
index 0000000..73e8f51
--- /dev/null
+++ b/analyzer/analyzer_main.cpp
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+#include <hei_main.hpp>
+
+namespace analyzer
+{
+
+/** @brief Analyze and isolate hardware errors */
+void analyzeHardware()
+{
+    printf("analyzeHardware()\n");
+}
+
+} // namespace analyzer
diff --git a/analyzer/analyzer_main.hpp b/analyzer/analyzer_main.hpp
new file mode 100644
index 0000000..d7199b5
--- /dev/null
+++ b/analyzer/analyzer_main.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+namespace analyzer
+{
+
+/**
+ * @brief Analyze and isolate hardware errors
+ *
+ * If any error conditions are found on the host isolate the hardware
+ * component that caused the error(s).
+ */
+void analyzeHardware();
+
+} // namespace analyzer
diff --git a/src/hei_user_defines.hpp b/analyzer/hei_user_defines.hpp
similarity index 85%
rename from src/hei_user_defines.hpp
rename to analyzer/hei_user_defines.hpp
index 797f22e..e45e18d 100644
--- a/src/hei_user_defines.hpp
+++ b/analyzer/hei_user_defines.hpp
@@ -2,8 +2,8 @@
 
 /**
  * @file hei_user_defines.hpp
- * @brief The purpose of this file is to create common defines that
- *        will be used throughout this library.
+ * @brief The purpose of this file is to provide defines that are required by
+ *        the hardware error isolator library (libhei)
  */
 
 #include <assert.h>
diff --git a/analyzer/meson.build b/analyzer/meson.build
new file mode 100644
index 0000000..fd0f7da
--- /dev/null
+++ b/analyzer/meson.build
@@ -0,0 +1,10 @@
+# Get opennpower-libhei dependencies. If not available via package manager
+# "fallback" to using the local libhei subproject.
+libhei_dep = dependency('libhei', fallback : ['libhei', 'libhei_dep'])
+
+# Create hardware error analyzer library
+analyzer = static_library('analyzer',
+                          'analyzer_main.cpp',
+                          'user_interface.cpp',
+                          dependencies : libhei_dep,
+                          install : true)
diff --git a/src/user_interface.cpp b/analyzer/user_interface.cpp
similarity index 100%
rename from src/user_interface.cpp
rename to analyzer/user_interface.cpp
diff --git a/attn/attn_handler.cpp b/attn/attn_handler.cpp
index 0463837..ec600e5 100644
--- a/attn/attn_handler.cpp
+++ b/attn/attn_handler.cpp
@@ -1,5 +1,6 @@
 #include <libpdbg.h>
 
+#include <analyzer/analyzer_main.hpp>
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/bus.hpp>
 
@@ -157,12 +158,7 @@
     ss << "[ATTN] checkstop" << std::endl;
     log<level::INFO>(ss.str().c_str());
 
-    if (0 != rc)
-    {
-        std::stringstream ss; // log message stream
-        ss << "[ATTN] checkstop NOT handled" << std::endl;
-        log<level::INFO>(ss.str().c_str());
-    }
+    analyzer::analyzeHardware();
 
     // TODO recoverable errors?
 
diff --git a/attn/attn_handler.service b/attn/attn_handler.service
index 42bbf34..43d3db7 100644
--- a/attn/attn_handler.service
+++ b/attn/attn_handler.service
@@ -5,7 +5,7 @@
 After=mapper-wait@-xyz-openbmc_project-logging.service
 
 [Service]
-ExecStart=/usr/bin/attn_handler
+ExecStart=/usr/bin/openpower-hw-diags --daemon
 Restart=on-failure
 
 [Install]
diff --git a/attn/attn_main.cpp b/attn/attn_main.cpp
index c0e2451..492531b 100644
--- a/attn/attn_main.cpp
+++ b/attn/attn_main.cpp
@@ -1,66 +1,19 @@
-#include <libpdbg.h>
+#include <../attn/attn_monitor.hpp>
 
-#include <attn_handler.hpp>
-#include <attn_monitor.hpp>
-
-#include <algorithm>
-
-/*
- * @brief Search the command line arguments for an option
- *
- * @param i_begin   command line args vector begin
- * @param i_end     command line args vector end
- * @param i_option  configuration option to look for
- *
- * @return true = option found on command line
- */
-bool getCliOption(char** i_begin, char** i_end, const std::string& i_option)
+namespace attn
 {
-    return (i_end != std::find(i_begin, i_end, i_option));
-}
-
-/*
- * @brief Search the command line arguments for a setting value
- *
- * @param i_begin   command line args vector begin
- * @param i_end     command line args vectory end
- * @param i_setting configuration setting to look for
- *
- * @return value of the setting or 0 if setting not found or value not given
- */
-char* getCliSetting(char** i_begin, char** i_end, const std::string& i_setting)
-{
-    char** value = std::find(i_begin, i_end, i_setting);
-    if (value != i_end && ++value != i_end)
-    {
-        return *value;
-    }
-    return 0; // nullptr
-}
 
 /**
  * @brief Attention handler application main()
- *
- * This is the main interface to the Attention handler application, it will
- * initialize the libgpd targets and start a gpio mointor.
- *
- * Command line arguments:
- *
- *  breakpoints - enables breakpoint special attn handling
- *
- * @return 0 = success
  */
-int main(int argc, char* argv[])
+int attnDaemon(bool i_breakpoints)
 {
-    int rc = 0; // return code
+    int rc = 0; // assume success
 
     gpiod_line* line; // gpio line to monitor
 
     boost::asio::io_service io; // async io monitoring service
 
-    // initialize pdbg targets
-    pdbg_targets_init(nullptr);
-
     // GPIO line configuration (falling edge, active low)
     struct gpiod_line_request_config config
     {
@@ -76,16 +29,15 @@
     }
     else
     {
-        // Check command line args for breakpoint handling enable option
-        bool bp_enable = getCliOption(argv, argv + argc, "-breakpoints");
-
         // Creating a vector of one gpio to monitor
         std::vector<std::unique_ptr<attn::AttnMonitor>> gpios;
-        gpios.push_back(
-            std::make_unique<attn::AttnMonitor>(line, config, io, bp_enable));
+        gpios.push_back(std::make_unique<attn::AttnMonitor>(line, config, io,
+                                                            i_breakpoints));
 
         io.run(); // start GPIO monitor
     }
 
     return rc;
 }
+
+} // namespace attn
diff --git a/attn/attn_main.hpp b/attn/attn_main.hpp
new file mode 100644
index 0000000..4403b45
--- /dev/null
+++ b/attn/attn_main.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+namespace attn
+{
+
+/**
+ * @brief Load the attention handler as a gpio monitor
+ *
+ * Request the attention gpio for monitoring and attach the attention handler
+ * as the gpio event handler.
+ *
+ * @param i_breakpoints     enables breakpoint special attn handling
+ *
+ * @return 0 == success
+ */
+int attnDaemon(bool i_breakpoints);
+
+} // namespace attn
diff --git a/attn/meson.build b/attn/meson.build
index c715dce..dfa1ce9 100644
--- a/attn/meson.build
+++ b/attn/meson.build
@@ -28,8 +28,10 @@
         dependency('systemd').get_pkgconfig_variable(
             'systemdsystemunitdir')
 )
-executable('attn_handler',
+
+attn = static_library('attn_handler',
            'attn_main.cpp', 'attn_handler.cpp', 'attn_monitor.cpp',
+           include_directories : incdir,
            dependencies : [whole_archive, libpdbg,
                            no_whole_archive, sdbusplus, libgpiod],
            cpp_args : boost_args,
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..96c0fa9
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,87 @@
+#include <libpdbg.h>
+
+#include <analyzer/analyzer_main.hpp>
+#include <attn/attn_main.hpp>
+
+#include <algorithm>
+
+/*
+ * @brief Search the command line arguments for an option
+ *
+ * @param i_begin   command line args vector begin
+ * @param i_end     command line args vector end
+ * @param i_option  configuration option to look for
+ *
+ * @return true = option found on command line
+ */
+bool getCliOption(char** i_begin, char** i_end, const std::string& i_option)
+{
+    return (i_end != std::find(i_begin, i_end, i_option));
+}
+
+/*
+ * @brief Search the command line arguments for a setting value
+ *
+ * @param i_begin   command line args vector begin
+ * @param i_end     command line args vectory end
+ * @param i_setting configuration setting to look for
+ *
+ * @return value of the setting or 0 if setting not found or value not given
+ */
+char* getCliSetting(char** i_begin, char** i_end, const std::string& i_setting)
+{
+    char** value = std::find(i_begin, i_end, i_setting);
+    if (value != i_end && ++value != i_end)
+    {
+        return *value;
+    }
+    return 0; // nullptr
+}
+
+/**
+ * @brief Attention handler application main()
+ *
+ * This is the main interface to the hardware diagnostics application. This
+ * application will either be loaded as a daemon for monitoring the attention
+ * gpio or it will be loaded as an application to analyze hardware and
+ * diagnose hadrware error conditions.
+ *
+ * Command line arguments:
+ *
+ *  analyze         analyze hardware
+ *  --daemon        load application as a daemon
+ *  --breakpoints   enable breakpoint special attn handling (in daemon mode)
+ *
+ * @return 0 = success
+ */
+int main(int argc, char* argv[])
+{
+    int rc = 0; // return code
+
+    // initialize pdbg targets
+    pdbg_targets_init(nullptr);
+
+    // TODO Handle target init fail
+
+    // check if we are being loaded as a daemon
+    if (true == getCliOption(argv, argv + argc, "--daemon"))
+    {
+        // Check command line args for breakpoint handling enable option
+        bool bp_enable = getCliOption(argv, argv + argc, "--breakpoints");
+
+        // Configure and start attention monitor
+        attn::attnDaemon(bp_enable);
+    }
+    // We are being loaded as an application, so parse the command line
+    // arguments to determine what operation is being requested.
+    else
+    {
+        // Request to analyze the hardware for error conditions
+        if (true == getCliOption(argv, argv + argc, "analyze"))
+        {
+            analyzer::analyzeHardware();
+        }
+    }
+
+    return rc;
+}
diff --git a/meson.build b/meson.build
index 139d66f..e6d411f 100644
--- a/meson.build
+++ b/meson.build
@@ -10,9 +10,15 @@
 # libhei is available as a subproject
 subproject('libhei')
 
-subdir('src')
+incdir = include_directories('.')
+
+subdir('analyzer')
 subdir('attn')
 
+executable('openpower-hw-diags', 'main.cpp',
+            link_with : [analyzer, attn],
+            install : true)
+
 build_tests = get_option('tests')
 
 if not build_tests.disabled()
diff --git a/src/main.cpp b/src/main.cpp
deleted file mode 100644
index 0de89fa..0000000
--- a/src/main.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <stdio.h>
-
-#include <hei_main.hpp>
-
-int main()
-{
-    printf("Hello, World!\n");
-}
diff --git a/src/meson.build b/src/meson.build
deleted file mode 100644
index 407f66f..0000000
--- a/src/meson.build
+++ /dev/null
@@ -1,9 +0,0 @@
-# If libhei is not provided by the system then build using the subproject
-libhei_dep = dependency('libhei', fallback : ['libhei', 'libhei_dep'])
-
-# create openpower-hw-diags application
-executable('openpower-hw-diags',
-           'main.cpp',
-           'user_interface.cpp',
-           dependencies : libhei_dep,
-           install : true)