Add phosphor-msl-verify

phosphor-msl-verify is a oneshot application for basic
minimum ship level (MSL) verification.

https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Control/README.msl.md

Change-Id: Ifa036bb0a45255af7c7773bd910e83c64842d868
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/mslverify/util.hpp b/mslverify/util.hpp
new file mode 100644
index 0000000..2c26fc2
--- /dev/null
+++ b/mslverify/util.hpp
@@ -0,0 +1,225 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/message.hpp>
+#include <phosphor-logging/log.hpp>
+#include <phosphor-logging/elog.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+namespace util
+{
+namespace detail
+{
+namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
+} // namespace detail
+
+/** @brief Alias for PropertiesChanged signal callbacks. */
+template <typename ...T>
+using Properties = std::map<std::string, sdbusplus::message::variant<T...>>;
+
+namespace sdbusplus
+{
+
+/** @brief Get the bus connection. */
+static auto& getBus() __attribute__((pure));
+static auto& getBus()
+{
+    static auto bus = ::sdbusplus::bus::new_default();
+    return bus;
+}
+
+/** @brief Invoke a method. */
+template <typename ...Args>
+static auto callMethod(
+        ::sdbusplus::bus::bus& bus,
+        const std::string& busName,
+        const std::string& path,
+        const std::string& interface,
+        const std::string& method,
+        Args&& ... args)
+{
+    auto reqMsg = bus.new_method_call(
+            busName.c_str(),
+            path.c_str(),
+            interface.c_str(),
+            method.c_str());
+    reqMsg.append(std::forward<Args>(args)...);
+    auto respMsg = bus.call(reqMsg);
+
+    if (respMsg.is_method_error())
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+                "Failed to invoke DBus method.",
+                phosphor::logging::entry("PATH=%s", path.c_str()),
+                phosphor::logging::entry(
+                    "INTERFACE=%s", interface.c_str()),
+                phosphor::logging::entry("METHOD=%s", method.c_str()));
+        phosphor::logging::elog<detail::errors::InternalFailure>();
+    }
+
+    return respMsg;
+}
+
+/** @brief Invoke a method. */
+template <typename ...Args>
+static auto callMethod(
+        const std::string& busName,
+        const std::string& path,
+        const std::string& interface,
+        const std::string& method,
+        Args&& ... args)
+{
+    return callMethod(
+            getBus(),
+            busName,
+            path,
+            interface,
+            method,
+            std::forward<Args>(args)...);
+}
+
+/** @brief Invoke a method and read the response. */
+template <typename Ret, typename ...Args>
+static auto callMethodAndRead(
+        ::sdbusplus::bus::bus& bus,
+        const std::string& busName,
+        const std::string& path,
+        const std::string& interface,
+        const std::string& method,
+        Args&& ... args)
+{
+    ::sdbusplus::message::message respMsg =
+        callMethod<Args...>(
+                bus,
+                busName,
+                path,
+                interface,
+                method,
+                std::forward<Args>(args)...);
+    Ret resp;
+    respMsg.read(resp);
+    return resp;
+}
+
+/** @brief Invoke a method and read the response. */
+ template <typename Ret, typename ...Args>
+static auto callMethodAndRead(
+        const std::string& busName,
+        const std::string& path,
+        const std::string& interface,
+        const std::string& method,
+        Args&& ... args)
+{
+    return callMethodAndRead<Ret>(
+            getBus(),
+            busName,
+            path,
+            interface,
+            method,
+            std::forward<Args>(args)...);
+}
+
+
+/** @brief Get service from the mapper. */
+static auto getService(
+        ::sdbusplus::bus::bus& bus,
+        const std::string& path,
+        const std::string& interface)
+{
+    using namespace std::literals::string_literals;
+    using GetObject = std::map<std::string, std::vector<std::string>>;
+
+    auto mapperResp = callMethodAndRead<GetObject>(
+            bus,
+            "xyz.openbmc_project.ObjectMapper"s,
+            "/xyz/openbmc_project/object_mapper"s,
+            "xyz.openbmc_project.ObjectMapper"s,
+            "GetObject"s,
+            path,
+            GetObject::mapped_type{interface});
+
+    if (mapperResp.empty())
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+                "Object not found.",
+                phosphor::logging::entry("PATH=%s", path.c_str()),
+                phosphor::logging::entry(
+                    "INTERFACE=%s", interface.c_str()));
+        phosphor::logging::elog<detail::errors::InternalFailure>();
+    }
+    return mapperResp.begin()->first;
+}
+
+/** @brief Get a property without mapper lookup. */
+template <typename Property>
+static auto getProperty(
+        ::sdbusplus::bus::bus& bus,
+        const std::string& busName,
+        const std::string& path,
+        const std::string& interface,
+        const std::string& property)
+{
+    using namespace std::literals::string_literals;
+
+    auto msg = callMethod(
+            bus,
+            busName,
+            path,
+            "org.freedesktop.DBus.Properties"s,
+            "Get"s,
+            interface,
+            property);
+    ::sdbusplus::message::variant<Property> value;
+    msg.read(value);
+    return value.template get<Property>();
+}
+
+/** @brief Get a property without mapper lookup. */
+template <typename Property>
+static auto getProperty(
+        const std::string& busName,
+        const std::string& path,
+        const std::string& interface,
+        const std::string& property)
+{
+    return getProperty<Property>(
+            getBus(),
+            busName,
+            path,
+            interface,
+            property);
+}
+
+/** @brief Get a property with mapper lookup. */
+template <typename Property>
+static auto getProperty(
+        ::sdbusplus::bus::bus& bus,
+        const std::string& path,
+        const std::string& interface,
+        const std::string& property)
+{
+    return getProperty<Property>(
+            bus,
+            getService(bus, path, interface),
+            path,
+            interface,
+            property);
+}
+
+/** @brief Get a property with mapper lookup. */
+template <typename Property>
+static auto getProperty(
+        const std::string& path,
+        const std::string& interface,
+        const std::string& property)
+{
+    return getProperty<Property>(
+            getBus(),
+            path,
+            interface,
+            property);
+}
+
+} // namespace sdbusplus
+} // namespace util