chassiskill: Add chassiskill tool

This tool is meant to circumvent the d-bus method of
powering down the chassis and directly pull the power
from it. Meant for use by the 'obmcutil' tool.

Turns off the 'power_up_outs' GPIOs

Change-Id: If8e51acbb3b192097fa9efa504d6cfa48d2bee9d
Signed-off-by: Anthony Wilson <wilsonan@us.ibm.com>
diff --git a/chassiskill.cpp b/chassiskill.cpp
new file mode 100644
index 0000000..a051f90
--- /dev/null
+++ b/chassiskill.cpp
@@ -0,0 +1,78 @@
+#include "utility.hpp"
+
+#include <algorithm>
+#include <cstring>
+#include <experimental/filesystem>
+#include <fstream>
+#include <nlohmann/json.hpp>
+#include <phosphor-logging/log.hpp>
+
+using json = nlohmann::json;
+using namespace phosphor::logging;
+using namespace utility;
+
+constexpr auto gpioDefsFile = "/etc/default/obmc/gpio/gpio_defs.json";
+
+int main(void)
+{
+    std::ifstream gpioDefsStream(gpioDefsFile);
+
+    if (!gpioDefsStream.is_open())
+    {
+        log<level::ERR>("Error opening gpio definitions file",
+                        entry("FILE=%s", gpioDefsFile));
+        return 1;
+    }
+
+    auto data = json::parse(gpioDefsStream, nullptr, false);
+
+    if (data.is_discarded())
+    {
+        log<level::ERR>("Error parsing gpio definitions file",
+                        entry("FILE=%s", gpioDefsFile));
+        return 1;
+    }
+
+    // To determine what pins are needed to deassert, look in the
+    // gpioDefsFile for the defined "power_up_outs" under
+    // gpio_configs->power_config. Then match the name up with
+    // its definition in "gpio_definitions" to determine the pin id's.
+    auto gpios = data["gpio_configs"]["power_config"]["power_up_outs"];
+
+    if (gpios.size() <= 0)
+    {
+        log<level::ERR>("Could not find power_up_outs defs",
+                        entry("FILE=%s", gpioDefsFile));
+        return 1;
+    }
+
+    auto defs = data["gpio_definitions"];
+
+    for (const auto& gpio : gpios)
+    {
+        auto gpioEntry = std::find_if(defs.begin(), defs.end(),
+                            [&gpio](const auto& g) {
+                                return g["name"] == gpio["name"];
+                            });
+
+        if (gpioEntry != defs.end())
+        {
+            std::string pin = (*gpioEntry)["pin"];
+            bool activeLow = gpio["polarity"];
+
+            if (!gpioSetValue(pin, !activeLow, false))
+            {
+                log<level::ERR>("chassiskill::gpioSetValue() failed",
+                                entry("PIN=%s", pin.c_str()));
+                return 1;
+            }
+            else
+            {
+                log<level::INFO>("'chassiskill' operation complete",
+                                 entry("PIN=%s", pin.c_str()));
+            }
+        }
+    }
+
+    return 0;
+}