tools: ipmi handler must open ipmi device
The ipmi handler must open the ipmi device on the host.
Note: The initial implementation will only support ipmi system devices
that are listed as device 0. This can be improved later or swapped
out to link against another ipmi command implementation.
Change-Id: I262039fdf3554ba144be1943875fd088766f3b57
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/test/Makefile.am b/test/Makefile.am
index a85285a..3d51fa4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -28,7 +28,8 @@
firmware_commit_unittest \
file_handler_unittest \
tools_blob_unittest \
- tools_updater_unittest
+ tools_updater_unittest \
+ tools_ipmi_unittest
TESTS = $(check_PROGRAMS)
@@ -73,3 +74,6 @@
tools_updater_unittest_SOURCES = tools_updater_unittest.cpp
tools_updater_unittest_LDADD = $(top_builddir)/tools/updater.o
+
+tools_ipmi_unittest_SOURCES = tools_ipmi_unittest.cpp
+tools_ipmi_unittest_LDADD = $(top_builddir)/tools/ipmi_handler.o
diff --git a/test/tools_ipmi_unittest.cpp b/test/tools_ipmi_unittest.cpp
new file mode 100644
index 0000000..8a72489
--- /dev/null
+++ b/test/tools_ipmi_unittest.cpp
@@ -0,0 +1,20 @@
+#include "internal_sys_mock.hpp"
+#include "ipmi_handler.hpp"
+
+namespace host_tool
+{
+
+using ::testing::_;
+using ::testing::Return;
+
+TEST(IpmiHandlerTest, OpenAllFails)
+{
+ /* Open against all device files fail. */
+ internal::InternalSysMock sysMock;
+ IpmiHandler ipmi(&sysMock);
+
+ EXPECT_CALL(sysMock, open(_, _)).WillRepeatedly(Return(-1));
+ EXPECT_EQ(false, ipmi.open());
+}
+
+} // namespace host_tool
diff --git a/tools/ipmi_handler.cpp b/tools/ipmi_handler.cpp
index a0c1198..e1e0529 100644
--- a/tools/ipmi_handler.cpp
+++ b/tools/ipmi_handler.cpp
@@ -16,9 +16,40 @@
#include "ipmi_handler.hpp"
+#include <fcntl.h>
+
+#include <sstream>
+#include <string>
+#include <vector>
+
namespace host_tool
{
+bool IpmiHandler::open()
+{
+ const int device = 0;
+ const std::vector<std::string> formats = {"/dev/ipmi", "/dev/ipmi/",
+ "/dev/ipmidev/"};
+
+ for (const auto& format : formats)
+ {
+ std::ostringstream path;
+ path << format << device;
+
+ fd = sys->open(path.str().c_str(), O_RDWR);
+ if (fd < 0)
+ {
+ continue;
+ }
+ break;
+ }
+
+ /* Should we throw an exception here, since we exhausted these options?
+ * Maybe. :D
+ */
+ return !(fd < 0);
+}
+
std::vector<std::uint8_t>
IpmiHandler::sendPacket(const std::vector<std::uint8_t>& data)
{
diff --git a/tools/ipmi_handler.hpp b/tools/ipmi_handler.hpp
index eec0c87..48e6def 100644
--- a/tools/ipmi_handler.hpp
+++ b/tools/ipmi_handler.hpp
@@ -12,11 +12,28 @@
explicit IpmiHandler(const internal::Sys* sys = &internal::sys_impl) :
sys(sys){};
+ ~IpmiHandler() = default;
+ IpmiHandler(const IpmiHandler&) = delete;
+ IpmiHandler& operator=(const IpmiHandler&) = delete;
+ IpmiHandler(IpmiHandler&&) = default;
+ IpmiHandler& operator=(IpmiHandler&&) = default;
+
+ /**
+ * Attempt to open the device node.
+ *
+ * @return true on success, failure otherwise.
+ */
+ bool open();
+
std::vector<std::uint8_t>
sendPacket(const std::vector<std::uint8_t>& data) override;
private:
const internal::Sys* sys;
+ /** TODO: Use a smart file descriptor when it's ready. Until then only
+ * allow moving this object.
+ */
+ int fd = -1;
};
} // namespace host_tool