mmc: Set updated version to primary
Once the update is successful, mark the version as primary so that
it boots from the updated version upon BMC reboot.
Add a sleep to wait for the service file to complete setting the
primary version. Otherwise, the BMC could mark a Delete or
Priority value change as complete and the service is not done yet,
and if the BMC is rebooted it could try to boot from a non-existent
version.
As backgroung, reference issue openbmc/openbmc#2857 that attempted
to create a 'wait for service' function but was not successful.
This could be investigated further at a later time, which would
benefit other functions like Factory Reset that are also using
sleep as a workaround to wait for systemd service files.
Tested: Verified the version was set to primary during code update
and delete, and that 3s passed (service file finished in
about 1s) before the delete/update continued.
Change-Id: I4f9afdb020d8cc7c18cfdafe468dbff2dc8046c1
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/mmc/flash.cpp b/mmc/flash.cpp
index dd12b0d..3bd67fa 100644
--- a/mmc/flash.cpp
+++ b/mmc/flash.cpp
@@ -33,6 +33,7 @@
msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
auto mmcServiceFile = "obmc-flash-mmc@" + versionId + ".service";
+ auto mmcSetPrimary = "obmc-flash-mmc-setprimary@" + versionId + ".service";
if (newStateUnit == mmcServiceFile && newStateResult == "done")
{
@@ -40,7 +41,12 @@
activationProgress->progress(activationProgress->progress() + 1);
}
- if (newStateUnit == mmcServiceFile)
+ if (newStateUnit == mmcSetPrimary && newStateResult == "done")
+ {
+ ubootEnvVarsUpdated = true;
+ }
+
+ if (newStateUnit == mmcServiceFile || newStateUnit == mmcSetPrimary)
{
if (newStateResult == "failed" || newStateResult == "dependency")
{
@@ -49,7 +55,23 @@
}
else if (roVolumeCreated)
{
- Activation::onFlashWriteSuccess();
+ if (!ubootEnvVarsUpdated)
+ {
+ activationProgress->progress(90);
+
+ // Set the priority which triggers the service that updates the
+ // environment variables.
+ if (!Activation::redundancyPriority)
+ {
+ Activation::redundancyPriority =
+ std::make_unique<RedundancyPriority>(bus, path, *this,
+ 0);
+ }
+ }
+ else // Environment variables were updated
+ {
+ Activation::onFlashWriteSuccess();
+ }
}
}
diff --git a/mmc/item_updater_helper.cpp b/mmc/item_updater_helper.cpp
index 0eb910e..29b4e58 100644
--- a/mmc/item_updater_helper.cpp
+++ b/mmc/item_updater_helper.cpp
@@ -2,6 +2,8 @@
#include "item_updater_helper.hpp"
+#include <thread>
+
namespace phosphor
{
namespace software
@@ -38,9 +40,18 @@
bus.call_noreply(method);
}
-void Helper::updateUbootVersionId(const std::string& /* versionId */)
+void Helper::updateUbootVersionId(const std::string& versionId)
{
- // Empty
+ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+ auto serviceFile = "obmc-flash-mmc-setprimary@" + versionId + ".service";
+ method.append(serviceFile, "replace");
+ bus.call_noreply(method);
+
+ // Wait a few seconds for the service file to finish, otherwise the BMC may
+ // be rebooted while pointing to a non-existent version.
+ constexpr auto setPrimaryWait = std::chrono::seconds(3);
+ std::this_thread::sleep_for(setPrimaryWait);
}
void Helper::mirrorAlt()
diff --git a/mmc/obmc-flash-mmc-setprimary@.service.in b/mmc/obmc-flash-mmc-setprimary@.service.in
new file mode 100644
index 0000000..69feafb
--- /dev/null
+++ b/mmc/obmc-flash-mmc-setprimary@.service.in
@@ -0,0 +1,7 @@
+[Unit]
+Description=Set %I as primary version
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/usr/bin/obmc-flash-bmc mmc-setprimary %i