tools: implement blob close

Implement blob close call.

Change-Id: If7c845e1e3b542e6f0253136eb8b6fd40bc96f3d
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/test/blob_interface_mock.hpp b/test/blob_interface_mock.hpp
index c3b4f4c..eff241f 100644
--- a/test/blob_interface_mock.hpp
+++ b/test/blob_interface_mock.hpp
@@ -14,6 +14,7 @@
     MOCK_METHOD2(openBlob,
                  std::uint16_t(const std::string&,
                                blobs::FirmwareBlobHandler::UpdateFlags));
+    MOCK_METHOD1(closeBlob, void(std::uint16_t));
 };
 
 } // namespace host_tool
diff --git a/tools/blob_handler.cpp b/tools/blob_handler.cpp
index 486f133..06d11e5 100644
--- a/tools/blob_handler.cpp
+++ b/tools/blob_handler.cpp
@@ -238,4 +238,23 @@
     return session;
 }
 
+void BlobHandler::closeBlob(std::uint16_t session)
+{
+    std::vector<std::uint8_t> request, resp;
+    auto addrSession = reinterpret_cast<std::uint8_t*>(&session);
+    std::copy(addrSession, addrSession + sizeof(session),
+              std::back_inserter(request));
+
+    try
+    {
+        resp = sendIpmiPayload(BlobOEMCommands::bmcBlobClose, request);
+    }
+    catch (const BlobException& b)
+    {
+        std::fprintf(stderr, "Received failure on close: %s\n", b.what());
+    }
+
+    return;
+}
+
 } // namespace host_tool
diff --git a/tools/blob_handler.hpp b/tools/blob_handler.hpp
index c22d326..6c176e4 100644
--- a/tools/blob_handler.hpp
+++ b/tools/blob_handler.hpp
@@ -68,6 +68,8 @@
         openBlob(const std::string& id,
                  blobs::FirmwareBlobHandler::UpdateFlags handlerFlags) override;
 
+    void closeBlob(std::uint16_t session) override;
+
   private:
     IpmiInterface* ipmi;
 };
diff --git a/tools/blob_interface.hpp b/tools/blob_interface.hpp
index 7e22849..b79121b 100644
--- a/tools/blob_interface.hpp
+++ b/tools/blob_interface.hpp
@@ -47,6 +47,13 @@
     virtual std::uint16_t
         openBlob(const std::string& id,
                  blobs::FirmwareBlobHandler::UpdateFlags handlerFlags) = 0;
+
+    /**
+     * Attempt to close the open session.
+     *
+     * @param[in] session - the session to close.
+     */
+    virtual void closeBlob(std::uint16_t session) = 0;
 };
 
 } // namespace host_tool
diff --git a/tools/updater.cpp b/tools/updater.cpp
index 6fed1d6..27414c1 100644
--- a/tools/updater.cpp
+++ b/tools/updater.cpp
@@ -92,6 +92,8 @@
         throw ToolException("Failed to send contents of " + imagePath);
     }
 
+    blob->closeBlob(session);
+
     /* Send over the hash contents. */
     /* Trigger the verification. */
     /* Check the verification. */