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