bmc: add preparation step before data is received

Add a preparation systemd trigger event before data is received.  On
systems under memory pressure, this'll trigger a service that can do
things like flush caches.

Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: I175177f4a91b58d9f163098572a9d2614002b718
diff --git a/firmware_handler.cpp b/firmware_handler.cpp
index 4967536..aaabe83 100644
--- a/firmware_handler.cpp
+++ b/firmware_handler.cpp
@@ -39,6 +39,7 @@
     FirmwareBlobHandler::CreateFirmwareBlobHandler(
         const std::vector<HandlerPack>& firmwares,
         const std::vector<DataHandlerPack>& transports,
+        std::unique_ptr<TriggerableActionInterface> preparation,
         std::unique_ptr<TriggerableActionInterface> verification,
         std::unique_ptr<TriggerableActionInterface> update)
 {
@@ -72,8 +73,8 @@
     }
 
     return std::make_unique<FirmwareBlobHandler>(
-        firmwares, blobs, transports, bitmask, std::move(verification),
-        std::move(update));
+        firmwares, blobs, transports, bitmask, std::move(preparation),
+        std::move(verification), std::move(update));
 }
 
 /* Check if the path is in our supported list (or active list). */
@@ -712,6 +713,21 @@
 void FirmwareBlobHandler::changeState(UpdateState next)
 {
     state = next;
+
+    if (state == UpdateState::notYetStarted)
+    {
+        /* Going back to notyetstarted, let them trigger preparation again. */
+        preparationTriggered = false;
+    }
+    else if (state == UpdateState::uploadInProgress)
+    {
+        /* Store this transition logic here instead of ::open() */
+        if (!preparationTriggered)
+        {
+            preparation->trigger();
+            preparationTriggered = true;
+        }
+    }
 }
 
 bool FirmwareBlobHandler::expire(uint16_t session)