Attn: Default special attention changed to TI

When a special attention occurs the attention handler uses the get TI
info chipop to determine whether to service either a TI or a
breakipoint. If this chipop is not available or is not functional the
attention handler will assume a TI has occurred. With this new behavior
an additional attention handler configuration option was added
(--defaultbreakpoint) which will allow breakpoints to be handled on
systems where the get TI info chipop is not available or not functional.

Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
Change-Id: I1b386b5daf06021acd6567fdad39c21903e2ac3b
diff --git a/attn/attn_config.cpp b/attn/attn_config.cpp
index e2d4a72..6ab6e19 100644
--- a/attn/attn_config.cpp
+++ b/attn/attn_config.cpp
@@ -7,6 +7,7 @@
 Config::Config()
 {
     setFlagAll();
+    iv_flags.reset(dfltBreakpoint); // default value is clear
 }
 
 /** @brief Get state of flag */
diff --git a/attn/attn_config.hpp b/attn/attn_config.hpp
index 32f885e..e8ef101 100644
--- a/attn/attn_config.hpp
+++ b/attn/attn_config.hpp
@@ -7,10 +7,11 @@
 /** @brief configuration flags */
 enum AttentionFlag
 {
-    enVital       = 0,
-    enCheckstop   = 1,
-    enTerminate   = 2,
-    enBreakpoints = 3,
+    enVital        = 0,
+    enCheckstop    = 1,
+    enTerminate    = 2,
+    enBreakpoints  = 3,
+    dfltBreakpoint = 4,
     lastFlag
 };
 
diff --git a/attn/attn_handler.cpp b/attn/attn_handler.cpp
index cf4671b..5ca4c69 100644
--- a/attn/attn_handler.cpp
+++ b/attn/attn_handler.cpp
@@ -297,17 +297,36 @@
             rc = tiHandler(tiDataArea);
         }
     }
-    // TI area not valid, assume breakpoint
+    // TI area not valid or not available
     else
     {
-        trace<level::INFO>("TI info NOT available, assume breakpoint");
+        trace<level::INFO>("TI info NOT available");
 
-        if (true == (i_attention->getConfig()->getFlag(enBreakpoints)))
+        // if configured to handle breakpoint as default special attention
+        if (i_attention->getConfig()->getFlag(dfltBreakpoint))
         {
-            trace<level::INFO>("breakpoint");
+            trace<level::INFO>("assuming breakpoint");
 
-            // Call the breakpoint special attention handler
-            bpHandler();
+            if (true == (i_attention->getConfig()->getFlag(enBreakpoints)))
+            {
+                trace<level::INFO>("breakpoint");
+
+                // Call the breakpoint special attention handler
+                bpHandler();
+            }
+        }
+        // if configured to handle TI as default special attention
+        else
+        {
+            trace<level::INFO>("assuming TI");
+
+            if (true == (i_attention->getConfig()->getFlag(enTerminate)))
+            {
+                trace<level::INFO>("TI (terminate immediately)");
+
+                // Call TI special attention handler
+                rc = tiHandler(nullptr);
+            }
         }
     }
 
diff --git a/attn/ti_handler.cpp b/attn/ti_handler.cpp
index a318e56..3d24f32 100644
--- a/attn/ti_handler.cpp
+++ b/attn/ti_handler.cpp
@@ -13,21 +13,37 @@
 /** @brief Start host diagnostic mode or quiesce host on TI */
 int tiHandler(TiDataArea* i_tiDataArea)
 {
-    int rc = RC_NOT_HANDLED; // assume TI not handled
+    int rc = RC_SUCCESS;
 
-    // PHYP TI
-    if (0xa1 == i_tiDataArea->command)
+    std::map<std::string, std::string> tiAdditionalData;
+
+    // If TI Info is available we can add it to the PEL
+    if (nullptr != i_tiDataArea)
     {
-        // Generate PEL with TI info
-        std::map<std::string, std::string> i_tiDataAreaMap;
-        parsePhypOpalTiInfo(i_tiDataAreaMap, i_tiDataArea); // human readable
-        parseRawTiInfo(i_tiDataAreaMap, i_tiDataArea);      // hex dump
-        eventTerminate(i_tiDataAreaMap);                    // generate PEL
+        if (0xa1 == i_tiDataArea->command)
+        {
+            parsePhypOpalTiInfo(tiAdditionalData, i_tiDataArea);
+        }
+        else
+        {
+            parseHbTiInfo(tiAdditionalData, i_tiDataArea);
+        }
+        parseRawTiInfo(tiAdditionalData, i_tiDataArea);
+    }
 
-        auto bus    = sdbusplus::bus::new_system();
-        auto method = bus.new_method_call(
-            "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
-            "org.freedesktop.systemd1.Manager", "StartUnit");
+    eventTerminate(tiAdditionalData); // generate PEL
+
+    // Transition host by starting appropriate dbus target
+    auto bus    = sdbusplus::bus::new_system();
+    auto method = bus.new_method_call(
+        "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+        "org.freedesktop.systemd1.Manager", "StartUnit");
+
+    // If TI info is not available we are going to assume PHYP TI for now
+    // (as opposed to HB TI - we have already decided it is not a breakpoint).
+    if ((nullptr == i_tiDataArea) || (0xa1 == i_tiDataArea->command))
+    {
+        trace<level::INFO>("PHYP TI");
 
         if (autoRebootEnabled())
         {
@@ -38,26 +54,22 @@
         }
         else
         {
-            // If autoreboot is disabled we will start the host quiesce target
+            // If autoreboot is disabled we will quiesce the host
             trace<level::INFO>("start obmc-host-quiesce target");
             method.append("obmc-host-quiesce@0.target");
         }
-
-        method.append("replace"); // mode = replace conflicting queued jobs
-        bus.call_noreply(method); // start the service
-
-        rc = RC_SUCCESS;
     }
-    // HB TI
     else
     {
-        // Generate PEL with TI info
-        std::map<std::string, std::string> i_tiDataAreaMap;
-        parseHbTiInfo(i_tiDataAreaMap, i_tiDataArea);  // human readable
-        parseRawTiInfo(i_tiDataAreaMap, i_tiDataArea); // hex dump
-        eventTerminate(i_tiDataAreaMap);               // generate PEL
+        // For now we are just going to just quiesce host on HB TI
+        trace<level::INFO>("HB TI");
+        trace<level::INFO>("start obmc-host-quiesce target");
+        method.append("obmc-host-quiesce@0.target");
     }
 
+    method.append("replace"); // mode = replace conflicting queued jobs
+    bus.call_noreply(method); // start the service
+
     return rc;
 }