bmc: add ActionPack notion to bundle actions
Each firmware type will provide its own set of action implementations
for each step, preparation, verification, and update.
Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: Id6409ac356a74e9094272b37709861e2a33d9862
diff --git a/bmc/firmware_handler.cpp b/bmc/firmware_handler.cpp
index 855c3fa..d193a4d 100644
--- a/bmc/firmware_handler.cpp
+++ b/bmc/firmware_handler.cpp
@@ -40,10 +40,7 @@
std::unique_ptr<blobs::GenericBlobInterface>
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)
+ const std::vector<DataHandlerPack>& transports, ActionMap&& actionPacks)
{
/* There must be at least one. */
if (!firmwares.size())
@@ -75,8 +72,7 @@
}
return std::make_unique<FirmwareBlobHandler>(
- firmwares, blobs, transports, bitmask, std::move(preparation),
- std::move(verification), std::move(update));
+ firmwares, blobs, transports, bitmask, std::move(actionPacks));
}
/* Check if the path is in our supported list (or active list). */
@@ -172,6 +168,7 @@
ActionStatus FirmwareBlobHandler::getActionStatus()
{
ActionStatus value = ActionStatus::unknown;
+ auto* pack = getActionPack();
switch (state)
{
@@ -179,7 +176,13 @@
value = ActionStatus::unknown;
break;
case UpdateState::verificationStarted:
- value = verification->status();
+ /* If we got here, there must be data AND a hash, not just a hash,
+ * therefore pack will be known. */
+ if (!pack)
+ {
+ break;
+ }
+ value = pack->verification->status();
lastVerificationStatus = value;
break;
case UpdateState::verificationCompleted:
@@ -189,7 +192,11 @@
value = ActionStatus::unknown;
break;
case UpdateState::updateStarted:
- value = update->status();
+ if (!pack)
+ {
+ break;
+ }
+ value = pack->update->status();
lastUpdateStatus = value;
break;
case UpdateState::updateCompleted:
@@ -340,6 +347,9 @@
switch (state)
{
+ case UpdateState::notYetStarted:
+ /* Only hashBlobId and firmware BlobIds present. */
+ break;
case UpdateState::uploadInProgress:
/* Unreachable code because if it's started a file is open. */
break;
@@ -391,6 +401,35 @@
break;
}
+ /* To support multiple firmware options, we need to make sure they're
+ * opening the one they already opened during this update sequence, or it's
+ * the first time they're opening it.
+ */
+ if (path != hashBlobId)
+ {
+ /* If they're not opening the hashBlobId they must be opening a firmware
+ * handler.
+ */
+ if (openedFirmwareType.empty())
+ {
+ /* First time for this sequence. */
+ openedFirmwareType = path;
+ }
+ else
+ {
+ if (openedFirmwareType != path)
+ {
+ /* Previously, in this sequence they opened /flash/image, and
+ * now they're opening /flash/bios without finishing out
+ * /flash/image (for example).
+ */
+ std::fprintf(stderr, "Trying to open alternate firmware while "
+ "unfinished with other firmware.\n");
+ return false;
+ }
+ }
+ }
+
/* There are two abstractions at play, how you get the data and how you
* handle that data. such that, whether the data comes from the PCI bridge
* or LPC bridge is not connected to whether the data goes into a static
@@ -731,8 +770,12 @@
/* Store this transition logic here instead of ::open() */
if (!preparationTriggered)
{
- preparation->trigger();
- preparationTriggered = true;
+ auto* pack = getActionPack();
+ if (pack)
+ {
+ pack->preparation->trigger();
+ preparationTriggered = true;
+ }
}
}
}
@@ -763,17 +806,28 @@
removeBlobId(activeImageBlobId);
removeBlobId(activeHashBlobId);
+ openedFirmwareType = "";
changeState(UpdateState::notYetStarted);
}
void FirmwareBlobHandler::abortVerification()
{
- verification->abort();
+ auto* pack = getActionPack();
+ if (pack)
+ {
+ pack->verification->abort();
+ }
}
bool FirmwareBlobHandler::triggerVerification()
{
- bool result = verification->trigger();
+ auto* pack = getActionPack();
+ if (!pack)
+ {
+ return false;
+ }
+
+ bool result = pack->verification->trigger();
if (result)
{
changeState(UpdateState::verificationStarted);
@@ -784,12 +838,22 @@
void FirmwareBlobHandler::abortUpdate()
{
- update->abort();
+ auto* pack = getActionPack();
+ if (pack)
+ {
+ pack->update->abort();
+ }
}
bool FirmwareBlobHandler::triggerUpdate()
{
- bool result = update->trigger();
+ auto* pack = getActionPack();
+ if (!pack)
+ {
+ return false;
+ }
+
+ bool result = pack->update->trigger();
if (result)
{
changeState(UpdateState::updateStarted);