tools/handler: Read the running version
A host tool would read the running firmware version through polling the
version blob state.
Signed-off-by: Jie Yang <jjy@google.com>
Change-Id: I0d68fff6527cd52360abee1cb225a8f228d68392
diff --git a/tools/helper.cpp b/tools/helper.cpp
index d3790de..232f482 100644
--- a/tools/helper.cpp
+++ b/tools/helper.cpp
@@ -19,10 +19,13 @@
#include "status.hpp"
#include "tool_errors.hpp"
+#include <blobs-ipmid/blobs.hpp>
#include <ipmiblob/blob_errors.hpp>
+#include <ipmiblob/blob_interface.hpp>
#include <chrono>
#include <thread>
+#include <utility>
namespace host_tool
{
@@ -110,6 +113,67 @@
return (result == ipmi_flash::ActionStatus::success);
}
+/* Poll an open blob session for reading.
+ *
+ * The committing bit indicates that the blob is not available for reading now
+ * and the reader might come back and check the state later.
+ *
+ * Polling finishes under the following conditions:
+ * - The open_read bit set -> stat successful
+ * - The open_read and committing bits unset -> stat failed;
+ * - Blob exception was received;
+ * - Time ran out.
+ * Polling continues when the open_read bit unset and committing bit set.
+ * If the blob is not open_read and not committing, then it is an error to the
+ * reader.
+ */
+std::pair<bool, uint32_t> pollReadReady(std::uint16_t session,
+ ipmiblob::BlobInterface* blob)
+{
+ using namespace std::chrono_literals;
+ static constexpr auto pollingSleep = 5s;
+ ipmiblob::StatResponse blobStatResp;
+
+ try
+ {
+ /* Polling lasts 5 minutes. When opening a version blob, the system
+ * unit defined in the version handler will extract the running version
+ * from the image on the flash.
+ */
+ static constexpr int commandAttempts = 60;
+ int attempts = 0;
+
+ while (attempts++ < commandAttempts)
+ {
+ blobStatResp = blob->getStat(session);
+
+ if (blobStatResp.blob_state & blobs::StateFlags::open_read)
+ {
+ std::fprintf(stderr, "success\n");
+ return std::make_pair(true, blobStatResp.size);
+ }
+ else if (blobStatResp.blob_state & blobs::StateFlags::committing)
+ {
+ std::fprintf(stderr, "running\n");
+ }
+ else
+ {
+ std::fprintf(stderr, "failed\n");
+ return std::make_pair(false, 0);
+ }
+
+ std::this_thread::sleep_for(pollingSleep);
+ }
+ }
+ catch (const ipmiblob::BlobException& b)
+ {
+ throw ToolException("blob exception received: " +
+ std::string(b.what()));
+ }
+
+ return std::make_pair(false, 0);
+}
+
void* memcpyAligned(void* destination, const void* source, std::size_t size)
{
std::size_t i = 0;