flash-ipmi: implement flashStartHash
Change-Id: Ia134b1faef99510bbed5eb4e36dada164c010305
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/configure.ac b/configure.ac
index dd05a59..12763e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,6 +72,10 @@
AS_IF([test "x$STAGING_PATH" == "x"], [STAGING_PATH="/run/initramfs/bmc-image"])
AC_DEFINE_UNQUOTED([STAGING_PATH], ["$STAGING_PATH"], [The staging path for the flash image.])
+AC_ARG_VAR(HASH_PATH, [The path for the hash file.])
+AS_IF([test "x$HASH_PATH" == "x"], [HASH_PATH="/tmp/bmc.sig"])
+AC_DEFINE_UNQUOTED([HASH_PATH], ["$HASH_PATH"], [The path for the hash file.])
+
# Create configured output
AC_CONFIG_FILES([Makefile test/Makefile])
AC_OUTPUT
diff --git a/flash-ipmi.cpp b/flash-ipmi.cpp
index 42333dd..f58363b 100644
--- a/flash-ipmi.cpp
+++ b/flash-ipmi.cpp
@@ -47,6 +47,7 @@
void FlashUpdate::closeEverything()
{
closeFile(&flashFd);
+ closeFile(&hashFd);
}
FlashUpdate::~FlashUpdate()
@@ -76,6 +77,19 @@
return false;
}
+ /* hash path is basically optional. */
+ if (!hashPath.empty())
+ {
+ hashFd = std::fopen(hashPath.c_str(), "wb");
+ if (hashFd == nullptr)
+ {
+ log<level::INFO>("Unable to open hash storage path",
+ entry("PATH=%s", hashPath.c_str()));
+ closeFile(&flashFd);
+ return false;
+ }
+ }
+
return true;
}
@@ -141,8 +155,13 @@
bool FlashUpdate::startHash(uint32_t length)
{
- /* TODO: implement. */
- return false;
+ if (!hashFd)
+ {
+ return false;
+ }
+
+ hashLength = length;
+ return true;
}
bool FlashUpdate::hashData(uint32_t offset, const std::vector<uint8_t>& bytes)
diff --git a/flash-ipmi.hpp b/flash-ipmi.hpp
index 2e6f6f0..2d7dcaa 100644
--- a/flash-ipmi.hpp
+++ b/flash-ipmi.hpp
@@ -150,8 +150,9 @@
class FlashUpdate : public UpdateInterface
{
public:
- FlashUpdate(const std::string& stagingPath) :
- flashLength(0), flashFd(nullptr), tmpPath(stagingPath){};
+ FlashUpdate(const std::string& stagingPath, const std::string& hash = "") :
+ flashLength(0), flashFd(nullptr), tmpPath(stagingPath), hashLength(0),
+ hashFd(nullptr), hashPath(hash){};
~FlashUpdate();
FlashUpdate(const FlashUpdate&) = default;
@@ -207,4 +208,15 @@
/* Where the bytes are written before verification. */
const std::string tmpPath;
+
+ /* The length of the hash in bytes. */
+ uint32_t hashLength;
+
+ /* The file handle to the hash file. */
+ std::FILE* hashFd;
+
+ /* Where we write the hash bytes. Only required if your verification
+ * process uses a separate signature.
+ */
+ const std::string hashPath;
};
diff --git a/main.cpp b/main.cpp
index 3cc3fb7..791cb22 100644
--- a/main.cpp
+++ b/main.cpp
@@ -24,6 +24,7 @@
#include "ipmi.hpp"
static constexpr auto stagingPath = STAGING_PATH;
+static constexpr auto hashPath = HASH_PATH;
/* TODO: Once OEM IPMI number placement is settled, point to that. */
namespace oem
@@ -84,7 +85,7 @@
void setupGlobalOemFlashControl()
{
- flashUpdateSingleton = std::make_unique<FlashUpdate>(stagingPath);
+ flashUpdateSingleton = std::make_unique<FlashUpdate>(stagingPath, hashPath);
#ifdef ENABLE_GOOGLE
oem::Router* router = oem::mutableRouter();
diff --git a/test/Makefile.am b/test/Makefile.am
index d0b8b2a..9540688 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -22,7 +22,8 @@
ipmi_command_unittest \
flash_start_unittest \
flash_flashdata_unittest \
- flash_flashfinish_unittest
+ flash_flashfinish_unittest \
+ flash_hashstart_unittest
TESTS = $(check_PROGRAMS)
@@ -64,3 +65,6 @@
flash_flashfinish_unittest_SOURCES = flash_flashfinish_unittest.cpp
flash_flashfinish_unittest_LDADD = $(top_builddir)/flash-ipmi.o $(SDBUSPLUS_LIBS)
+
+flash_hashstart_unittest_SOURCES = flash_hashstart_unittest.cpp
+flash_hashstart_unittest_LDADD = $(top_builddir)/flash-ipmi.o $(SDBUSPLUS_LIBS)
diff --git a/test/flash_hashstart_unittest.cpp b/test/flash_hashstart_unittest.cpp
new file mode 100644
index 0000000..a3a1d9f
--- /dev/null
+++ b/test/flash_hashstart_unittest.cpp
@@ -0,0 +1,36 @@
+#include "flash-ipmi.hpp"
+
+#include <cstdio>
+#include <gtest/gtest.h>
+#include <string>
+
+#define THIRTYTWO_MIB 33554432
+
+TEST(FlashIpmiHashStartTest, OutofSequenceFails)
+{
+ // Verify that the image must be started first. (can change).
+
+ std::string name = std::tmpnam(nullptr);
+ std::string name2 = std::tmpnam(nullptr);
+
+ FlashUpdate updater(name, name2);
+ EXPECT_FALSE(updater.startHash(THIRTYTWO_MIB));
+
+ (void)std::remove(name.c_str());
+ (void)std::remove(name2.c_str());
+}
+
+TEST(FlashIpmiHashStartTest, VerifyHashFileCreated)
+{
+ // Verify that it's happy.
+
+ std::string name = std::tmpnam(nullptr);
+ std::string name2 = std::tmpnam(nullptr);
+
+ FlashUpdate updater(name, name2);
+ EXPECT_TRUE(updater.start(THIRTYTWO_MIB));
+ EXPECT_TRUE(updater.startHash(THIRTYTWO_MIB));
+
+ (void)std::remove(name.c_str());
+ (void)std::remove(name2.c_str());
+}