tools: start burn_my_bmc tool

Start implementation of burn_my_bmc host tool, the purpose of which is
to upload the firmware image and trigger the verification process.

The utility will accept four parameters:
1) command - the command to run, initially only "update"
2) interface - the data interface to use, e.g. lpc or pci
3) image - the path to the image file
4) sig - the path to the image's signature file

Change-Id: Ifbab7df947f37dd3a6fddddcf523c0fa724c9551
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/.gitignore b/.gitignore
index c13c7cc..ae38b8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,3 +48,4 @@
 # Custom generated files
 
 # Output binaries
+burn_my_bmc
diff --git a/Makefile.am b/Makefile.am
index d2dc190..75c84cd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,4 +21,4 @@
 	$(PHOSPHOR_LOGGING_CFLAGS) \
 	-flto
 
-SUBDIRS = . test
+SUBDIRS = . test tools
diff --git a/configure.ac b/configure.ac
index c50fa18..db229b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -129,5 +129,5 @@
 )
 
 # Create configured output
-AC_CONFIG_FILES([Makefile test/Makefile])
+AC_CONFIG_FILES([Makefile test/Makefile tools/Makefile])
 AC_OUTPUT
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..88c72e2
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,11 @@
+noinst_PROGRAMS = burn_my_bmc
+
+burn_my_bmc_SOURCES = main.cpp
+burn_my_bmc_LDADD = libupdater.la
+burn_my_bmc_CXXFLAGS =
+
+noinst_LTLIBRARIES = libupdater.la
+libupdater_la_LDFLAGS = -static
+libupdater_la_CXXFLAGS =
+libupdater_la_SOURCES = \
+	updater.cpp
diff --git a/tools/main.cpp b/tools/main.cpp
new file mode 100644
index 0000000..7bbf380
--- /dev/null
+++ b/tools/main.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "updater.hpp"
+
+/* Use CLI11 argument parser once in openbmc/meta-oe or whatever. */
+#include <getopt.h>
+
+#include <cstdio>
+#include <string>
+
+void usage(const char* program)
+{
+    std::fprintf(stderr,
+                 "Usage: %s -command <command> -interface <interface> -image "
+                 "<image file> -sig <signature file>",
+                 program);
+}
+
+bool checkCommand(const std::string& command)
+{
+    return (command == "update");
+}
+
+bool checkInterface(const std::string& interface)
+{
+    return (interface == "ipmibt" || interface == "ipmilpc");
+}
+
+int main(int argc, char* argv[])
+{
+    std::string command, interface, imagePath, signaturePath;
+
+    while (1)
+    {
+        // clang-format off
+        static struct option long_options[] = {
+            {"command", required_argument, 0, 'c'},
+            {"interface", required_argument, 0, 'i'},
+            {"image", required_argument, 0, 'm'},
+            {"sig", required_argument, 0, 's'},
+            {0, 0, 0, 0}
+        };
+        // clang-format on
+
+        int option_index = 0;
+        int c =
+            getopt_long(argc, argv, "c:i:m:s:", long_options, &option_index);
+        if (c == -1)
+        {
+            break;
+        }
+
+        switch (c)
+        {
+            case 'c':
+                command = std::string{optarg};
+                if (!checkCommand(command))
+                {
+                    usage(argv[0]);
+                    exit(EXIT_FAILURE);
+                }
+
+                break;
+            case 'i':
+                interface = std::string{optarg};
+                if (!checkInterface(interface))
+                {
+                    usage(argv[0]);
+                    exit(EXIT_FAILURE);
+                }
+                break;
+            case 'm':
+                imagePath = std::string{optarg};
+                break;
+            case 's':
+                signaturePath = std::string{optarg};
+                break;
+            default:
+                usage(argv[0]);
+                exit(EXIT_FAILURE);
+        }
+    }
+
+    /* They want to update the firmware. */
+    if (command == "update")
+    {
+        if (interface.empty() || imagePath.empty() || signaturePath.empty())
+        {
+            usage(argv[0]);
+            exit(EXIT_FAILURE);
+        }
+
+        /* The parameters are all filled out. */
+        return updaterMain(interface, imagePath, signaturePath);
+    }
+
+    return 0;
+}
diff --git a/tools/updater.cpp b/tools/updater.cpp
new file mode 100644
index 0000000..4771180
--- /dev/null
+++ b/tools/updater.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "updater.hpp"
+
+int updaterMain(const std::string& interface, const std::string& imagePath,
+                const std::string& signaturePath)
+{
+    return 0;
+}
diff --git a/tools/updater.hpp b/tools/updater.hpp
new file mode 100644
index 0000000..c17025e
--- /dev/null
+++ b/tools/updater.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <string>
+
+/**
+ * Attempt to update the BMC's firmware using the interface provided.
+ *
+ * @param[in] interface - the interface to use.
+ * @param[in] imagePath - the path to the image file.
+ * @param[in] signaturePath - the path to the signature file.
+ * @return non-zero on failure.
+ */
+int updaterMain(const std::string& interface, const std::string& imagePath,
+                const std::string& signaturePath);