firmware_handler: implement session stat w/ verification

Implement session stat to handle checking on the verification state as
well as properly reporting when there isn't an image handler.

Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: I98079a0f38976e1aa9876c8a2232481231dbc6e1
diff --git a/firmware_handler.cpp b/firmware_handler.cpp
index 8daead6..a07ddbb 100644
--- a/firmware_handler.cpp
+++ b/firmware_handler.cpp
@@ -21,6 +21,7 @@
 #include <algorithm>
 #include <cstdint>
 #include <cstring>
+#include <fstream>
 #include <memory>
 #include <phosphor-logging/log.hpp>
 #include <string>
@@ -35,6 +36,7 @@
 static constexpr auto systemdRoot = "/org/freedesktop/systemd1";
 static constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
 static constexpr auto verifyTarget = "verify_image.service";
+static constexpr auto statusPath = "/tmp/bmc.verify";
 
 const std::string FirmwareBlobHandler::verifyBlobID = "/flash/verify";
 const std::string FirmwareBlobHandler::hashBlobID = "/flash/hash";
@@ -42,6 +44,43 @@
     "/flash/active/image";
 const std::string FirmwareBlobHandler::activeHashBlobID = "/flash/active/hash";
 
+namespace
+{
+
+FirmwareBlobHandler::VerifyCheckResponses checkVerificationState()
+{
+    FirmwareBlobHandler::VerifyCheckResponses result =
+        FirmwareBlobHandler::VerifyCheckResponses::other;
+
+    std::ifstream ifs;
+    ifs.open(statusPath);
+    if (ifs.good())
+    {
+        /*
+         * Check for the contents of the file, accepting:
+         * running, success, or failed.
+         */
+        std::string status;
+        ifs >> status;
+        if (status == "running")
+        {
+            result = FirmwareBlobHandler::VerifyCheckResponses::running;
+        }
+        else if (status == "success")
+        {
+            result = FirmwareBlobHandler::VerifyCheckResponses::success;
+        }
+        else if (status == "failed")
+        {
+            result = FirmwareBlobHandler::VerifyCheckResponses::failed;
+        }
+    }
+
+    return result;
+}
+
+} // namespace
+
 std::unique_ptr<GenericBlobInterface>
     FirmwareBlobHandler::CreateFirmwareBlobHandler(
         sdbusplus::bus::bus&& bus, const std::vector<HandlerPack>& firmwares,
@@ -217,20 +256,30 @@
      */
     meta->blobState = item->second->flags;
 
+    /* The size here refers to the size of the file -- of something analagous.
+     */
+    meta->size = (item->second->imageHandler)
+                     ? item->second->imageHandler->getSize()
+                     : 0;
+
+    meta->metadata.clear();
+
     /* TODO: Implement this for the verification blob, which is what we expect.
      * Calling stat() on the verify blob without an active session should not
      * provide insight.
      */
+    if (item->second->activePath == verifyBlobID)
+    {
+        meta->metadata.push_back(
+            static_cast<std::uint8_t>(checkVerificationState()));
 
-    /* The size here refers to the size of the file -- of something analagous.
-     */
-    meta->size = item->second->imageHandler->getSize();
+        return true;
+    }
 
     /* The metadata blob returned comes from the data handler... it's used for
      * instance, in P2A bridging to get required information about the mapping,
      * and is the "opposite" of the lpc writemeta requirement.
      */
-    meta->metadata.clear();
     if (item->second->dataHandler)
     {
         auto bytes = item->second->dataHandler->readMeta();
@@ -238,10 +287,6 @@
                               bytes.end());
     }
 
-    /* TODO: During things like verification, etc, we can report the state as
-     * committed, etc, so we'll need to do that.
-     */
-
     return true;
 }
 
diff --git a/firmware_handler.hpp b/firmware_handler.hpp
index 212e570..fe410a1 100644
--- a/firmware_handler.hpp
+++ b/firmware_handler.hpp
@@ -111,7 +111,7 @@
     };
 
     /** The return values for verification. */
-    enum VerifyCheckResponses : std::uint8_t
+    enum class VerifyCheckResponses : std::uint8_t
     {
         running = 0,
         success = 1,