set up data handler mechanism
Data that comes from outside of the IPMI packet will leverage a data
interface implementation. Only the IPMI blocktransfer (or really KCS)
will not use this external interface.
Change-Id: I7806da04c070dc3d6a79070ea563aeec63221dca
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/Makefile.am b/Makefile.am
index f990788..60b8e42 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,7 +4,9 @@
libfirmwareblob_LTLIBRARIES = libfirmwareblob.la
libfirmwareblob_la_SOURCES = main.cpp \
firmware_handler.cpp \
- static_handler.cpp
+ static_handler.cpp \
+ lpc_handler.cpp \
+ pci_handler.cpp
libfirmwareblob_la_LDFLAGS = $(PHOSPHOR_LOGGING_LIBS) \
-version-info 0:0:0 -shared
libfirmwareblob_la_CXXFLAGS = $(PHOSPHOR_LOGGING_CFLAGS) \
diff --git a/data_handler.hpp b/data_handler.hpp
index 07101f7..79e228f 100644
--- a/data_handler.hpp
+++ b/data_handler.hpp
@@ -1,5 +1,8 @@
#pragma once
+#include <cstdint>
+#include <vector>
+
namespace blobs
{
@@ -10,6 +13,20 @@
{
public:
virtual ~DataInterface() = default;
+
+ /**
+ * Copy bytes from external interface (blocking call).
+ *
+ * @param[in] length - number of bytes to copy
+ * @return the bytes read
+ */
+ virtual std::vector<std::uint8_t> copyFrom(std::uint32_t length) = 0;
+};
+
+struct DataHandlerPack
+{
+ std::uint16_t bitmask;
+ DataInterface* handler;
};
} // namespace blobs
diff --git a/firmware_handler.cpp b/firmware_handler.cpp
index 21556e1..f6c5472 100644
--- a/firmware_handler.cpp
+++ b/firmware_handler.cpp
@@ -18,13 +18,18 @@
std::unique_ptr<GenericBlobInterface>
FirmwareBlobHandler::CreateFirmwareBlobHandler(
- const std::vector<HandlerPack>& firmwares, std::uint16_t transports)
+ const std::vector<HandlerPack>& firmwares,
+ const std::vector<DataHandlerPack>& transports)
{
/* There must be at least one. */
if (!firmwares.size())
{
return nullptr;
}
+ if (!transports.size())
+ {
+ return nullptr;
+ }
std::vector<std::string> blobs;
for (const auto& item : firmwares)
@@ -33,7 +38,15 @@
}
blobs.push_back(hashBlobID);
- return std::make_unique<FirmwareBlobHandler>(firmwares, blobs, transports);
+ std::uint16_t bitmask = 0;
+ for (const auto& item : transports)
+ {
+ /* TODO: can use std::accumulate() unless I'm mistaken. :D */
+ bitmask |= item.bitmask;
+ }
+
+ return std::make_unique<FirmwareBlobHandler>(firmwares, blobs, transports,
+ bitmask);
}
bool FirmwareBlobHandler::canHandleBlob(const std::string& path)
@@ -92,7 +105,7 @@
else
{
/* They are requesting information about the generic blob_id. */
- meta->blobState = transports;
+ meta->blobState = bitmask;
meta->size = 0;
/* The generic blob_ids state is only the bits related to the transport
@@ -148,7 +161,7 @@
/* Check the flags for the transport mechanism: if none match we don't
* support what they request. */
- if ((flags & transports) == 0)
+ if ((flags & bitmask) == 0)
{
return false;
}
@@ -170,6 +183,16 @@
}
else
{
+ /* How are they expecting to copy this data? */
+ auto d = std::find_if(
+ transports.begin(), transports.end(),
+ [&flags](const auto& iter) { return (iter.bitmask & flags); });
+ if (d != transports.end())
+ {
+ /* We found the transport handler they requested, no surprise since
+ * above we verify they selected at least one we wanted. */
+ }
+
/* 2d) are they opening the /flash/tarball ? (to start the UBI process)
*/
/* 2e) are they opening the /flash/image ? (to start the process) */
diff --git a/firmware_handler.hpp b/firmware_handler.hpp
index 8f54d7d..786b2d1 100644
--- a/firmware_handler.hpp
+++ b/firmware_handler.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "data_handler.hpp"
#include "image_handler.hpp"
#include <blobs-ipmid/blobs.hpp>
@@ -28,23 +29,26 @@
* Create a FirmwareBlobHandler.
*
* @param[in] firmwares - list of firmware blob_ids to support.
- * @param[in] transports - bitmask of transports to support.
+ * @param[in] transports - list of transports to support.
*/
- static std::unique_ptr<GenericBlobInterface>
- CreateFirmwareBlobHandler(const std::vector<HandlerPack>& firmwares,
- std::uint16_t transports);
+ static std::unique_ptr<GenericBlobInterface> CreateFirmwareBlobHandler(
+ const std::vector<HandlerPack>& firmwares,
+ const std::vector<DataHandlerPack>& transports);
/**
* Create a FirmwareBlobHandler.
*
- * @param[in] blobs - list of blobs_ids to support and their image handlers.
- * @param[in] transports - bitmask of transports to support.
+ * @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
*/
FirmwareBlobHandler(const std::vector<HandlerPack>& firmwares,
const std::vector<std::string>& blobs,
- std::uint16_t transports) :
+ const std::vector<DataHandlerPack>& transports,
+ std::uint16_t bitmask) :
handlers(firmwares),
- blobIDs(blobs), transports(transports)
+ blobIDs(blobs), transports(transports), bitmask(bitmask)
{
}
~FirmwareBlobHandler() = default;
@@ -81,8 +85,11 @@
/** Active list of blobIDs. */
std::vector<std::string> blobIDs;
+ /** List of handlers by transport type. */
+ std::vector<DataHandlerPack> transports;
+
/** The bits set indicate what transport mechanisms are supported. */
- std::uint16_t transports;
+ std::uint16_t bitmask;
/** Temporary variable to track whether a blob is open. */
bool fileOpen = false;
diff --git a/lpc_handler.cpp b/lpc_handler.cpp
new file mode 100644
index 0000000..acd58c8
--- /dev/null
+++ b/lpc_handler.cpp
@@ -0,0 +1,15 @@
+#include "lpc_handler.hpp"
+
+#include <cstdint>
+#include <vector>
+
+namespace blobs
+{
+
+std::vector<std::uint8_t> LpcDataHandler::copyFrom(std::uint32_t length)
+{
+ /* TODO: implement this. */
+ return {};
+}
+
+} // namespace blobs
diff --git a/lpc_handler.hpp b/lpc_handler.hpp
new file mode 100644
index 0000000..903cf26
--- /dev/null
+++ b/lpc_handler.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "data_handler.hpp"
+
+#include <cstdint>
+#include <vector>
+
+namespace blobs
+{
+
+class LpcDataHandler : public DataInterface
+{
+
+ public:
+ LpcDataHandler() = default;
+
+ std::vector<std::uint8_t> copyFrom(std::uint32_t length) override;
+};
+
+} // namespace blobs
diff --git a/main.cpp b/main.cpp
index 28bb943..93d3770 100644
--- a/main.cpp
+++ b/main.cpp
@@ -2,6 +2,8 @@
#include "firmware_handler.hpp"
#include "image_handler.hpp"
+#include "lpc_handler.hpp"
+#include "pci_handler.hpp"
#include "static_handler.hpp"
#include <blobs-ipmid/manager.hpp>
@@ -16,6 +18,8 @@
namespace
{
StaticLayoutHandler staticLayoutHandler;
+LpcDataHandler lpcDataHandler;
+PciDataHandler pciDataHandler;
std::vector<HandlerPack> supportedFirmware = {
#ifdef ENABLE_STATIC_LAYOUT
@@ -23,21 +27,22 @@
#endif
};
-std::uint16_t supportedTransports =
- FirmwareBlobHandler::FirmwareUpdateFlags::bt;
+std::vector<DataHandlerPack> supportedTransports = {
+ {FirmwareBlobHandler::FirmwareUpdateFlags::bt, nullptr},
+#ifdef ENABLE_PCI_BRIDGE
+ {FirmwareBlobHandler::FirmwareUpdateFlags::p2a, &pciDataHandler},
+#endif
+#ifdef ENABLE_LPC_BRIDGE
+ {FirmwareBlobHandler::FirmwareUpdateFlags::lpc, &lpcDataHandler},
+#endif
+};
+
} // namespace
void setupFirmwareHandler() __attribute__((constructor));
void setupFirmwareHandler()
{
-#ifdef ENABLE_PCI_BRIDGE
- supportedTransports |= FirmwareBlobHandler::FirmwareUpdateFlags::p2a;
-#endif
-#ifdef ENABLE_LPC_BRIDGE
- supportedTransports |= FirmwareBlobHandler::FirmwareUpdateFlags::lpc;
-#endif
-
auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
supportedFirmware, supportedTransports);
diff --git a/pci_handler.cpp b/pci_handler.cpp
new file mode 100644
index 0000000..91edf63
--- /dev/null
+++ b/pci_handler.cpp
@@ -0,0 +1,15 @@
+#include "pci_handler.hpp"
+
+#include <cstdint>
+#include <vector>
+
+namespace blobs
+{
+
+std::vector<std::uint8_t> PciDataHandler::copyFrom(std::uint32_t length)
+{
+ /* TODO: implement this. */
+ return {};
+}
+
+} // namespace blobs
diff --git a/pci_handler.hpp b/pci_handler.hpp
new file mode 100644
index 0000000..df936e4
--- /dev/null
+++ b/pci_handler.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "data_handler.hpp"
+
+#include <cstdint>
+#include <vector>
+
+namespace blobs
+{
+
+class PciDataHandler : public DataInterface
+{
+
+ public:
+ PciDataHandler() = default;
+
+ std::vector<std::uint8_t> copyFrom(std::uint32_t length) override;
+};
+
+} // namespace blobs
diff --git a/test/data_mock.hpp b/test/data_mock.hpp
new file mode 100644
index 0000000..1fd1fae
--- /dev/null
+++ b/test/data_mock.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "data_handler.hpp"
+
+#include <gmock/gmock.h>
+
+namespace blobs
+{
+
+class DataHandlerMock : public DataInterface
+{
+ public:
+ virtual ~DataHandlerMock() = default;
+
+ MOCK_METHOD1(copyFrom, std::vector<std::uint8_t>(std::uint32_t));
+};
+
+} // namespace blobs
diff --git a/test/firmware_canhandle_unittest.cpp b/test/firmware_canhandle_unittest.cpp
index 028d472..4f00d50 100644
--- a/test/firmware_canhandle_unittest.cpp
+++ b/test/firmware_canhandle_unittest.cpp
@@ -1,3 +1,4 @@
+#include "data_mock.hpp"
#include "firmware_handler.hpp"
#include "image_mock.hpp"
@@ -25,9 +26,11 @@
{"asdf", &imageMock},
{"bcdf", &imageMock},
};
+ std::vector<DataHandlerPack> data = {
+ {FirmwareBlobHandler::FirmwareUpdateFlags::bt, nullptr},
+ };
- auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
- blobs, FirmwareBlobHandler::FirmwareUpdateFlags::bt);
+ auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(blobs, data);
for (const auto& item : items)
{
diff --git a/test/firmware_handler_unittest.cpp b/test/firmware_handler_unittest.cpp
index 16395df..bae6cab 100644
--- a/test/firmware_handler_unittest.cpp
+++ b/test/firmware_handler_unittest.cpp
@@ -12,7 +12,22 @@
TEST(FirmwareHandlerTest, CreateEmptyListVerifyFails)
{
- auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler({}, 0);
+ std::vector<DataHandlerPack> data = {
+ {FirmwareBlobHandler::FirmwareUpdateFlags::bt, nullptr},
+ };
+
+ auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler({}, data);
+ EXPECT_EQ(handler, nullptr);
+}
+TEST(FirmwareHandlerTest, CreateEmptyDataHandlerListFails)
+{
+ ImageHandlerMock imageMock;
+
+ std::vector<HandlerPack> blobs = {
+ {"asdf", &imageMock},
+ };
+
+ auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(blobs, {});
EXPECT_EQ(handler, nullptr);
}
TEST(FirmwareHandlerTest, CreateEmptyListVerifyHasHash)
@@ -22,8 +37,11 @@
std::vector<HandlerPack> blobs = {
{"asdf", &imageMock},
};
+ std::vector<DataHandlerPack> data = {
+ {FirmwareBlobHandler::FirmwareUpdateFlags::bt, nullptr},
+ };
- auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(blobs, 0);
+ auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(blobs, data);
auto result = handler->getBlobIds();
EXPECT_EQ(2, result.size());
EXPECT_EQ(2, std::count(result.begin(), result.end(), "asdf") +
diff --git a/test/firmware_stat_unittest.cpp b/test/firmware_stat_unittest.cpp
index a00adf5..e52ce86 100644
--- a/test/firmware_stat_unittest.cpp
+++ b/test/firmware_stat_unittest.cpp
@@ -22,9 +22,11 @@
std::vector<HandlerPack> blobs = {
{"asdf", &imageMock},
};
+ std::vector<DataHandlerPack> data = {
+ {FirmwareBlobHandler::FirmwareUpdateFlags::bt, nullptr},
+ };
- auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
- blobs, FirmwareBlobHandler::FirmwareUpdateFlags::bt);
+ auto handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(blobs, data);
struct BlobMeta meta;
EXPECT_TRUE(handler->stat("asdf", &meta));
EXPECT_EQ(FirmwareBlobHandler::FirmwareUpdateFlags::bt, meta.blobState);