bmc: enable configuration of all verification

Enable verification configuration beyond the result file check.  This
patchset allows a developer to provide their own verification mechanisms
by implementing an interface and adding configuration to enable using
their custom version.

Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: Iba5d4be75bb49d9c4ab84be8578f0306c15b5be9
diff --git a/Makefile.am b/Makefile.am
index 872b61c..ca14c0a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,7 +42,8 @@
 	util.cpp \
 	firmware_handler.cpp \
 	file_handler.cpp \
-	internal/sys.cpp
+	internal/sys.cpp \
+	verify.cpp
 
 if ENABLE_LPC_BRIDGE
 libfirmwareblob_common_la_SOURCES += lpc_handler.cpp
diff --git a/README.md b/README.md
index 5a00d7c..25686fe 100644
--- a/README.md
+++ b/README.md
@@ -103,3 +103,4 @@
 `TARBALL_STAGED_NAME`        | `/tmp/image-update.tar`    | The filename where to write the UBI update tarball.
 `HASH_FILENAME`              | `/tmp/bmc.sig`             | The file to use for the hash provided.
 `VERIFY_STATUS_FILENAME`     | `/tmp/bmc.verify`          | The file checked for the verification status.
+`VERIFY_DBUS_SERVICE`        | `verify_image.service`     | The systemd service started for verification.
diff --git a/configure.ac b/configure.ac
index 3ec030d..02e6447 100644
--- a/configure.ac
+++ b/configure.ac
@@ -175,6 +175,11 @@
 AS_IF([test "xVERIFY_STATUS_FILENAME" == "x"], [VERIFY_STATUS_FILENAME="/tmp/bmc.verify"])
 AC_DEFINE_UNQUOTED([VERIFY_STATUS_FILENAME], ["$VERIFY_STATUS_FILENAME"], [The file checked for the verification status.])
 
+# VERIFY_DBUS_SERVICE
+AC_ARG_VAR(VERIFY_DBUS_SERVICE, [The systemd service started for verification.])
+AS_IF([test "xVERIFY_DBUS_SERVICE" == "x"], [VERIFY_DBUS_SERVICE="verify_image.service"])
+AC_DEFINE_UNQUOTED([VERIFY_DBUS_SERVICE], ["$VERIFY_DBUS_SERVICE"], [The systemd service started for verification.])
+
 AC_CHECK_HEADER(linux/ipmi.h, [HAVE_LINUX_IPMI_H=""], [HAVE_LINUX_IPMI_H="-I linux/ipmi.h"])
 AS_IF([test "$HAVE_LINUX_IPMI_H" != ""],
     AC_MSG_WARN([Could not find linux/ipmi.h: Attempting to download locally for building from openbmc/linux/+/dev-4.18])
diff --git a/firmware_handler.cpp b/firmware_handler.cpp
index 6e02024..c2e935a 100644
--- a/firmware_handler.cpp
+++ b/firmware_handler.cpp
@@ -32,55 +32,12 @@
 
 namespace blobs
 {
-// systemd service to kick start a target.
-static constexpr auto systemdService = "org.freedesktop.systemd1";
-static constexpr auto systemdRoot = "/org/freedesktop/systemd1";
-static constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
-static constexpr auto verifyTarget = "verify_image.service";
-
-namespace
-{
-
-FirmwareBlobHandler::VerifyCheckResponses
-    checkVerificationState(const std::string& path)
-{
-    FirmwareBlobHandler::VerifyCheckResponses result =
-        FirmwareBlobHandler::VerifyCheckResponses::other;
-
-    std::ifstream ifs;
-    ifs.open(path);
-    if (ifs.good())
-    {
-        /*
-         * Check for the contents of the file, accepting:
-         * running, success, or failed.
-         */
-        std::string status;
-        ifs >> status;
-        if (status == "running")
-        {
-            result = FirmwareBlobHandler::VerifyCheckResponses::running;
-        }
-        else if (status == "success")
-        {
-            result = FirmwareBlobHandler::VerifyCheckResponses::success;
-        }
-        else if (status == "failed")
-        {
-            result = FirmwareBlobHandler::VerifyCheckResponses::failed;
-        }
-    }
-
-    return result;
-}
-
-} // namespace
 
 std::unique_ptr<GenericBlobInterface>
     FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        sdbusplus::bus::bus&& bus, const std::vector<HandlerPack>& firmwares,
+        const std::vector<HandlerPack>& firmwares,
         const std::vector<DataHandlerPack>& transports,
-        const std::string& verificationPath)
+        std::unique_ptr<VerificationInterface> verification)
 {
     /* There must be at least one. */
     if (!firmwares.size())
@@ -112,9 +69,8 @@
         bitmask |= item.bitmask;
     }
 
-    return std::make_unique<FirmwareBlobHandler>(std::move(bus), firmwares,
-                                                 blobs, transports, bitmask,
-                                                 verificationPath);
+    return std::make_unique<FirmwareBlobHandler>(
+        firmwares, blobs, transports, bitmask, std::move(verification));
 }
 
 /* Check if the path is in our supported list (or active list). */
@@ -257,7 +213,7 @@
      */
     if (item->second->activePath == verifyBlobId)
     {
-        auto value = checkVerificationState(verificationPath);
+        auto value = verification->checkVerificationState();
 
         meta->metadata.push_back(static_cast<std::uint8_t>(value));
 
@@ -700,25 +656,13 @@
 
 bool FirmwareBlobHandler::triggerVerification()
 {
-    auto method = bus.new_method_call(systemdService, systemdRoot,
-                                      systemdInterface, "StartUnit");
-    method.append(verifyTarget);
-    method.append("replace");
-
-    try
+    bool result = verification->triggerVerification();
+    if (result)
     {
-        bus.call_noreply(method);
         state = UpdateState::verificationStarted;
     }
-    catch (const sdbusplus::exception::SdBusError& ex)
-    {
-        /* TODO: Once logging supports unit-tests, add a log message to test
-         * this failure.
-         */
-        return false;
-    }
 
-    return true;
+    return result;
 }
 
 } // namespace blobs
diff --git a/firmware_handler.hpp b/firmware_handler.hpp
index 3467ccd..88cb957 100644
--- a/firmware_handler.hpp
+++ b/firmware_handler.hpp
@@ -5,24 +5,12 @@
 #include "data_handler.hpp"
 #include "image_handler.hpp"
 #include "util.hpp"
+#include "verify.hpp"
 
 #include <blobs-ipmid/blobs.hpp>
 #include <cstdint>
 #include <map>
 #include <memory>
-#if HAVE_SDBUSPLUS
-#include <sdbusplus/bus.hpp>
-#else
-namespace sdbusplus
-{
-namespace bus
-{
-class bus
-{
-};
-} // namespace bus
-} // namespace sdbusplus
-#endif
 #include <string>
 #include <vector>
 
@@ -111,48 +99,37 @@
         verificationCompleted,
     };
 
-    /** The return values for verification. */
-    enum class VerifyCheckResponses : std::uint8_t
-    {
-        running = 0,
-        success = 1,
-        failed = 2,
-        other = 3,
-    };
-
     /**
      * Create a FirmwareBlobHandler.
      *
-     * @param[in] bus - an sdbusplus handler for a bus to use.
      * @param[in] firmwares - list of firmware blob_ids to support.
      * @param[in] transports - list of transports to support.
-     * @param[in[ verificationPath - path to check for verification output
+     * @param[in] verification - pointer to object for triggering verification
      */
     static std::unique_ptr<GenericBlobInterface> CreateFirmwareBlobHandler(
-        sdbusplus::bus::bus&& bus, const std::vector<HandlerPack>& firmwares,
+        const std::vector<HandlerPack>& firmwares,
         const std::vector<DataHandlerPack>& transports,
-        const std::string& verificationPath);
+        std::unique_ptr<VerificationInterface> verification);
 
     /**
      * Create a FirmwareBlobHandler.
      *
-     * @param[in] bus - an sdbusplus handler for a bus to use
      * @param[in] firmwares - list of firmware types and their handlers
      * @param[in] blobs - list of blobs_ids to support
      * @param[in] transports - list of transport types and their handlers
      * @param[in] bitmask - bitmask of transports to support
+     * @param[in] verification - pointer to object for triggering verification
      */
-    FirmwareBlobHandler(sdbusplus::bus::bus&& bus,
-                        const std::vector<HandlerPack>& firmwares,
+    FirmwareBlobHandler(const std::vector<HandlerPack>& firmwares,
                         const std::vector<std::string>& blobs,
                         const std::vector<DataHandlerPack>& transports,
                         std::uint16_t bitmask,
-                        const std::string& verificationPath) :
-        bus(std::move(bus)),
-        handlers(firmwares), blobIDs(blobs), transports(transports),
-        bitmask(bitmask), activeImage(activeImageBlobId),
-        activeHash(activeHashBlobId), verifyImage(verifyBlobId), lookup(),
-        state(UpdateState::notYetStarted), verificationPath(verificationPath)
+                        std::unique_ptr<VerificationInterface> verification) :
+        handlers(firmwares),
+        blobIDs(blobs), transports(transports), bitmask(bitmask),
+        activeImage(activeImageBlobId), activeHash(activeHashBlobId),
+        verifyImage(verifyBlobId), lookup(), state(UpdateState::notYetStarted),
+        verification(std::move(verification))
     {
     }
     ~FirmwareBlobHandler() = default;
@@ -187,8 +164,6 @@
     };
 
   private:
-    sdbusplus::bus::bus bus;
-
     /** List of handlers by type. */
     std::vector<HandlerPack> handlers;
 
@@ -216,7 +191,7 @@
     /** The firmware update state. */
     UpdateState state;
 
-    const std::string verificationPath;
+    std::unique_ptr<VerificationInterface> verification;
 
     /** Temporary variable to track whether a blob is open. */
     bool fileOpen = false;
diff --git a/main.cpp b/main.cpp
index 6458b98..a711227 100644
--- a/main.cpp
+++ b/main.cpp
@@ -24,6 +24,7 @@
 #include "lpc_nuvoton.hpp"
 #include "pci_handler.hpp"
 #include "util.hpp"
+#include "verify.hpp"
 
 #include <cstdint>
 #include <memory>
@@ -94,8 +95,10 @@
     using namespace phosphor::logging;
 
     auto handler = blobs::FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        sdbusplus::bus::new_default(), blobs::supportedFirmware,
-        blobs::supportedTransports, VERIFY_STATUS_FILENAME);
+        blobs::supportedFirmware, blobs::supportedTransports,
+        blobs::Verification::CreateDefaultVerification(
+            sdbusplus::bus::new_default(), VERIFY_STATUS_FILENAME,
+            VERIFY_DBUS_SERVICE));
 
     if (!handler)
     {
diff --git a/status.hpp b/status.hpp
new file mode 100644
index 0000000..7ef0ce2
--- /dev/null
+++ b/status.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <cstdint>
+
+namespace blobs
+{
+
+enum class VerifyCheckResponses : std::uint8_t
+{
+    running = 0,
+    success = 1,
+    failed = 2,
+    other = 3,
+};
+}
diff --git a/test/firmware_canhandle_unittest.cpp b/test/firmware_canhandle_unittest.cpp
index f739b9e..380df45 100644
--- a/test/firmware_canhandle_unittest.cpp
+++ b/test/firmware_canhandle_unittest.cpp
@@ -2,8 +2,8 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -32,11 +32,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     for (const auto& item : items)
     {
diff --git a/test/firmware_close_unittest.cpp b/test/firmware_close_unittest.cpp
index b0d20fb..ff839af 100644
--- a/test/firmware_close_unittest.cpp
+++ b/test/firmware_close_unittest.cpp
@@ -2,8 +2,8 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gmock/gmock.h>
@@ -32,11 +32,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(dataMock, open()).WillOnce(Return(true));
     EXPECT_CALL(imageMock, open(StrEq(hashBlobId))).WillOnce(Return(true));
@@ -78,11 +75,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock, open(StrEq(hashBlobId))).WillOnce(Return(true));
 
diff --git a/test/firmware_commit_unittest.cpp b/test/firmware_commit_unittest.cpp
index 009f158..2766fd3 100644
--- a/test/firmware_commit_unittest.cpp
+++ b/test/firmware_commit_unittest.cpp
@@ -2,8 +2,8 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -32,11 +32,12 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+    /* Verify it doesn't get called by using StrictMock. */
+    std::unique_ptr<VerificationInterface> verifyMock =
+        std::make_unique<StrictMock<VerificationMock>>();
 
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, std::move(verifyMock));
 
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
 
@@ -61,11 +62,12 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+    /* Verify it doesn't get called by using StrictMock. */
+    std::unique_ptr<VerificationInterface> verifyMock =
+        std::make_unique<StrictMock<VerificationMock>>();
 
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, std::move(verifyMock));
 
     EXPECT_CALL(imageMock1, open(StrEq(hashBlobId))).WillOnce(Return(true));
 
@@ -91,14 +93,17 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+    auto verifyMock = CreateVerifyMock();
+    auto verifyMockPtr = reinterpret_cast<VerificationMock*>(verifyMock.get());
 
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, std::move(verifyMock));
 
     EXPECT_TRUE(handler->open(0, OpenFlags::write, verifyBlobId));
 
+    EXPECT_CALL(*verifyMockPtr, triggerVerification())
+        .WillRepeatedly(Return(true));
+
     EXPECT_TRUE(handler->commit(0, {}));
 }
 
@@ -117,29 +122,16 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    StrictMock<sdbusplus::SdBusMock> sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
+    auto verifyMock = CreateVerifyMock();
+    auto verifyMockPtr = reinterpret_cast<VerificationMock*>(verifyMock.get());
 
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, std::move(verifyMock));
 
     EXPECT_TRUE(handler->open(0, OpenFlags::write, verifyBlobId));
 
-    /* Note: I used StrictMock<> here to just catch all the calls.  However, the
-     * unit-tests pass if we don't use StrictMock and ignore the calls.
-     */
-    EXPECT_CALL(sdbus_mock,
-                sd_bus_message_new_method_call(
-                    IsNull(), NotNull(), StrEq("org.freedesktop.systemd1"),
-                    StrEq("/org/freedesktop/systemd1"),
-                    StrEq("org.freedesktop.systemd1.Manager"),
-                    StrEq("StartUnit")))
-        .WillOnce(Return(0));
-    EXPECT_CALL(sdbus_mock,
-                sd_bus_message_append_basic(IsNull(), 's', NotNull()))
-        .Times(2)
-        .WillRepeatedly(Return(0));
-    EXPECT_CALL(sdbus_mock, sd_bus_call(_, _, _, _, _)).WillOnce(Return(0));
+    EXPECT_CALL(*verifyMockPtr, triggerVerification())
+        .WillRepeatedly(Return(true));
 
     EXPECT_TRUE(handler->commit(0, {}));
     EXPECT_TRUE(handler->commit(0, {}));
diff --git a/test/firmware_createhandler_unittest.cpp b/test/firmware_createhandler_unittest.cpp
index 3bee96e..4821ffa 100644
--- a/test/firmware_createhandler_unittest.cpp
+++ b/test/firmware_createhandler_unittest.cpp
@@ -2,14 +2,10 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
-
-#include <phosphor-logging/test/sdjournal_mock.hpp>
-#include <sdbusplus/test/sdbus_mock.hpp>
+#include "verification_mock.hpp"
 
 #include <gtest/gtest.h>
 
-using namespace phosphor::logging;
-
 namespace blobs
 {
 using ::testing::Return;
@@ -34,16 +30,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
-    //    TODO: Once we can test across log<> paths again, re-enable this test
-    //    as a failure test instead of a success one. EXPECT_CALL(journalMock,
-    //    journal_send_call(StrEq("PRIORITY=%d")))
-    //        .WillOnce(Return(0));
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     //    EXPECT_EQ(handler, nullptr);
     EXPECT_FALSE(handler == nullptr);
diff --git a/test/firmware_delete_unittest.cpp b/test/firmware_delete_unittest.cpp
index 8d21e29..de67a15 100644
--- a/test/firmware_delete_unittest.cpp
+++ b/test/firmware_delete_unittest.cpp
@@ -2,8 +2,8 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gmock/gmock.h>
@@ -30,11 +30,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock, open(StrEq(hashBlobId))).WillOnce(Return(true));
 
diff --git a/test/firmware_handler_unittest.cpp b/test/firmware_handler_unittest.cpp
index 65e73bd..09cbf9e 100644
--- a/test/firmware_handler_unittest.cpp
+++ b/test/firmware_handler_unittest.cpp
@@ -1,9 +1,9 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
 #include <algorithm>
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -17,11 +17,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), {}, data, "");
+        {}, data, CreateVerifyMock());
     EXPECT_EQ(handler, nullptr);
 }
 TEST(FirmwareHandlerTest, CreateEmptyDataHandlerListFails)
@@ -33,11 +30,8 @@
         {"asdf", &imageMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, {}, "");
+        blobs, {}, CreateVerifyMock());
     EXPECT_EQ(handler, nullptr);
 }
 TEST(FirmwareHandlerTest, VerifyHashRequiredForHappiness)
@@ -52,17 +46,14 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
     EXPECT_EQ(handler, nullptr);
 
     blobs.push_back({hashBlobId, &imageMock});
 
     handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
     auto result = handler->getBlobIds();
     EXPECT_EQ(3, result.size());
     EXPECT_EQ(3, std::count(result.begin(), result.end(), "asdf") +
diff --git a/test/firmware_open_unittest.cpp b/test/firmware_open_unittest.cpp
index 5b6d690..5148a44 100644
--- a/test/firmware_open_unittest.cpp
+++ b/test/firmware_open_unittest.cpp
@@ -2,8 +2,8 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gmock/gmock.h>
@@ -30,11 +30,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock, open("asdf")).WillOnce(Return(true));
 
@@ -61,11 +58,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock, open(StrEq(hashBlobId))).WillOnce(Return(true));
 
@@ -97,11 +91,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(dataMock, open()).WillOnce(Return(true));
     EXPECT_CALL(imageMock, open(StrEq(hashBlobId))).WillOnce(Return(true));
@@ -132,11 +123,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(dataMock, open()).WillOnce(Return(false));
 
@@ -164,11 +152,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
 
@@ -212,11 +197,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock, open("asdf")).WillOnce(Return(true));
 
@@ -254,11 +236,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock, open("asdf")).WillOnce(Return(false));
 
@@ -284,11 +263,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_FALSE(
         handler->open(0, FirmwareBlobHandler::UpdateFlags::ipmi, "asdf"));
@@ -308,11 +284,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_FALSE(
         handler->open(0, FirmwareBlobHandler::UpdateFlags::lpc, "asdf"));
@@ -332,11 +305,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_FALSE(handler->open(
         0, OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi, "bcdf"));
diff --git a/test/firmware_sessionstat_unittest.cpp b/test/firmware_sessionstat_unittest.cpp
index 891ade2..7882141 100644
--- a/test/firmware_sessionstat_unittest.cpp
+++ b/test/firmware_sessionstat_unittest.cpp
@@ -2,8 +2,8 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -28,11 +28,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
 
@@ -69,11 +66,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(dataMock, open()).WillOnce(Return(true));
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
diff --git a/test/firmware_stat_unittest.cpp b/test/firmware_stat_unittest.cpp
index 79b8a44..becb3f1 100644
--- a/test/firmware_stat_unittest.cpp
+++ b/test/firmware_stat_unittest.cpp
@@ -1,8 +1,8 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -28,11 +28,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     struct BlobMeta meta;
     EXPECT_TRUE(handler->stat("asdf", &meta));
diff --git a/test/firmware_write_unittest.cpp b/test/firmware_write_unittest.cpp
index 75eab40..72ffcb3 100644
--- a/test/firmware_write_unittest.cpp
+++ b/test/firmware_write_unittest.cpp
@@ -2,10 +2,10 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
+#include "verification_mock.hpp"
 
 #include <cstdint>
 #include <cstring>
-#include <sdbusplus/test/sdbus_mock.hpp>
 #include <vector>
 
 #include <gtest/gtest.h>
@@ -29,11 +29,8 @@
         {FirmwareBlobHandler::UpdateFlags::ipmi, nullptr},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
 
@@ -63,11 +60,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(dataMock, open()).WillOnce(Return(true));
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
@@ -106,11 +100,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(dataMock, open()).WillOnce(Return(true));
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
diff --git a/test/firmware_writemeta_unittest.cpp b/test/firmware_writemeta_unittest.cpp
index f70495a..3441a14 100644
--- a/test/firmware_writemeta_unittest.cpp
+++ b/test/firmware_writemeta_unittest.cpp
@@ -2,8 +2,7 @@
 #include "firmware_handler.hpp"
 #include "image_mock.hpp"
 #include "util.hpp"
-
-#include <sdbusplus/test/sdbus_mock.hpp>
+#include "verification_mock.hpp"
 
 #include <gtest/gtest.h>
 
@@ -27,11 +26,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
 
@@ -58,11 +54,8 @@
         {FirmwareBlobHandler::UpdateFlags::lpc, &dataMock},
     };
 
-    sdbusplus::SdBusMock sdbus_mock;
-    auto bus_mock = sdbusplus::get_mocked_new(&sdbus_mock);
-
     auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
-        std::move(bus_mock), blobs, data, "");
+        blobs, data, CreateVerifyMock());
 
     EXPECT_CALL(dataMock, open()).WillOnce(Return(true));
     EXPECT_CALL(imageMock2, open("asdf")).WillOnce(Return(true));
diff --git a/test/verification_mock.hpp b/test/verification_mock.hpp
new file mode 100644
index 0000000..e1021c8
--- /dev/null
+++ b/test/verification_mock.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "status.hpp"
+#include "verify.hpp"
+
+#include <memory>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+namespace blobs
+{
+
+class VerificationMock : public VerificationInterface
+{
+  public:
+    MOCK_METHOD0(triggerVerification, bool());
+    MOCK_METHOD0(abortVerification, void());
+    MOCK_METHOD0(checkVerificationState, VerifyCheckResponses());
+};
+
+std::unique_ptr<VerificationInterface> CreateVerifyMock()
+{
+    return std::make_unique<VerificationMock>();
+}
+
+} // namespace blobs
diff --git a/tools/updater.cpp b/tools/updater.cpp
index f2a0264..d596483 100644
--- a/tools/updater.cpp
+++ b/tools/updater.cpp
@@ -17,6 +17,7 @@
 #include "updater.hpp"
 
 #include "firmware_handler.hpp"
+#include "status.hpp"
 #include "tool_errors.hpp"
 #include "util.hpp"
 
@@ -116,8 +117,7 @@
     static constexpr int commandAttempts = 20;
     int attempts = 0;
     bool exitLoop = false;
-    blobs::FirmwareBlobHandler::VerifyCheckResponses result =
-        blobs::FirmwareBlobHandler::VerifyCheckResponses::other;
+    blobs::VerifyCheckResponses result = blobs::VerifyCheckResponses::other;
 
     try
     {
@@ -136,23 +136,21 @@
                 std::fprintf(stderr, "Received invalid metadata response!!!\n");
             }
 
-            result =
-                static_cast<blobs::FirmwareBlobHandler::VerifyCheckResponses>(
-                    resp.metadata[0]);
+            result = static_cast<blobs::VerifyCheckResponses>(resp.metadata[0]);
 
             switch (result)
             {
-                case blobs::FirmwareBlobHandler::VerifyCheckResponses::failed:
+                case blobs::VerifyCheckResponses::failed:
                     std::fprintf(stderr, "failed\n");
                     exitLoop = true;
                     break;
-                case blobs::FirmwareBlobHandler::VerifyCheckResponses::other:
+                case blobs::VerifyCheckResponses::other:
                     std::fprintf(stderr, "other\n");
                     break;
-                case blobs::FirmwareBlobHandler::VerifyCheckResponses::running:
+                case blobs::VerifyCheckResponses::running:
                     std::fprintf(stderr, "running\n");
                     break;
-                case blobs::FirmwareBlobHandler::VerifyCheckResponses::success:
+                case blobs::VerifyCheckResponses::success:
                     std::fprintf(stderr, "success\n");
                     exitLoop = true;
                     break;
@@ -182,8 +180,7 @@
      * which exceptions from the lower layers allow one to try and delete the
      * blobs to rollback the state and progress.
      */
-    return (result ==
-            blobs::FirmwareBlobHandler::VerifyCheckResponses::success);
+    return (result == blobs::VerifyCheckResponses::success);
 }
 
 bool UpdateHandler::verifyFile(const std::string& target)
diff --git a/verify.cpp b/verify.cpp
new file mode 100644
index 0000000..5023bf8
--- /dev/null
+++ b/verify.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2019 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 "verify.hpp"
+
+#include "status.hpp"
+
+#include <fstream>
+#include <memory>
+#include <sdbusplus/bus.hpp>
+#include <string>
+#include <vector>
+
+namespace blobs
+{
+
+std::unique_ptr<VerificationInterface>
+    Verification::CreateDefaultVerification(sdbusplus::bus::bus&& bus,
+                                            const std::string& path,
+                                            const std::string& service)
+{
+    return std::make_unique<Verification>(std::move(bus), path, service);
+}
+
+bool Verification::triggerVerification()
+{
+    static constexpr auto systemdService = "org.freedesktop.systemd1";
+    static constexpr auto systemdRoot = "/org/freedesktop/systemd1";
+    static constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
+
+    auto method = bus.new_method_call(systemdService, systemdRoot,
+                                      systemdInterface, "StartUnit");
+    method.append(triggerService);
+    method.append("replace");
+
+    try
+    {
+        bus.call_noreply(method);
+    }
+    catch (const sdbusplus::exception::SdBusError& ex)
+    {
+        /* TODO: Once logging supports unit-tests, add a log message to test
+         * this failure.
+         */
+        return false;
+    }
+
+    return true;
+}
+
+void Verification::abortVerification()
+{
+    /* TODO: Implement this. */
+}
+
+VerifyCheckResponses Verification::checkVerificationState()
+{
+    VerifyCheckResponses result = VerifyCheckResponses::other;
+
+    std::ifstream ifs;
+    ifs.open(checkPath);
+    if (ifs.good())
+    {
+        /*
+         * Check for the contents of the file, accepting:
+         * running, success, or failed.
+         */
+        std::string status;
+        ifs >> status;
+        if (status == "running")
+        {
+            result = VerifyCheckResponses::running;
+        }
+        else if (status == "success")
+        {
+            result = VerifyCheckResponses::success;
+        }
+        else if (status == "failed")
+        {
+            result = VerifyCheckResponses::failed;
+        }
+    }
+
+    return result;
+}
+
+} // namespace blobs
diff --git a/verify.hpp b/verify.hpp
new file mode 100644
index 0000000..0f67a20
--- /dev/null
+++ b/verify.hpp
@@ -0,0 +1,92 @@
+#pragma once
+
+#include "config.h"
+
+#include "status.hpp"
+
+#include <memory>
+#include <string>
+
+#if HAVE_SDBUSPLUS
+#include <sdbusplus/bus.hpp>
+#else
+namespace sdbusplus
+{
+namespace bus
+{
+class bus
+{
+};
+} // namespace bus
+} // namespace sdbusplus
+#endif
+
+namespace blobs
+{
+
+class VerificationInterface
+{
+  public:
+    virtual ~VerificationInterface() = default;
+
+    /**
+     * Trigger verification service.
+     *
+     * @return true if successfully started, false otherwise.
+     */
+    virtual bool triggerVerification() = 0;
+
+    /** Abort the verification process. */
+    virtual void abortVerification() = 0;
+
+    /** Check the current state of the verification process. */
+    virtual VerifyCheckResponses checkVerificationState() = 0;
+};
+
+/**
+ * Representation of what is used for verification.  Currently, this reduces the
+ * chance of error by using an object instead of two strings to control the
+ * verification step, however, it leaves room for a future possibility out
+ * something wholly configurable.
+ */
+class Verification : public VerificationInterface
+{
+  public:
+    /**
+     * Create a default Verification object that uses systemd to trigger the
+     * process.
+     *
+     * @param[in] bus - an sdbusplus handler for a bus to use.
+     * @param[in] path - the path to check for verification status.
+     * @param[in[ service - the systemd service to start to trigger
+     * verification.
+     */
+    static std::unique_ptr<VerificationInterface>
+        CreateDefaultVerification(sdbusplus::bus::bus&& bus,
+                                  const std::string& path,
+                                  const std::string& service);
+
+    Verification(sdbusplus::bus::bus&& bus, const std::string& path,
+                 const std::string& service) :
+        bus(std::move(bus)),
+        checkPath(path), triggerService(service)
+    {
+    }
+
+    ~Verification() = default;
+    Verification(const Verification&) = delete;
+    Verification& operator=(const Verification&) = delete;
+    Verification(Verification&&) = default;
+    Verification& operator=(Verification&&) = default;
+
+    bool triggerVerification() override;
+    void abortVerification() override;
+    VerifyCheckResponses checkVerificationState() override;
+
+  private:
+    sdbusplus::bus::bus bus;
+    const std::string checkPath;
+    const std::string triggerService;
+};
+
+} // namespace blobs