diff mbox series

Fix setting recovery_status flag in rescue mode

Message ID 20190117145926.19252-1-sbabic@denx.de
State Accepted
Headers show
Series Fix setting recovery_status flag in rescue mode | expand

Commit Message

Stefano Babic Jan. 17, 2019, 2:59 p.m. UTC
The "recovery_status" flag (bootloader variable) is set when SWUpdate
starts to install images on the target. This works if streaming mode is
not set. When it is set, some images are already installed before
SWUpdate sets the flag. In case of power-on when a single image is used
or in case pf rescue system, the bootloader cannot recognize that an update
was interrupted and tries to start the production software, that can be
corrupted. The rescue is started again just as fallback after failing to
start the production software, but there are cases where this does not
work.

Check if an image is streamed to the target and sets the
"recoverz?status" flag before writing to the storage.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 core/swupdate.c            |  6 +++---
 corelib/stream_interface.c | 18 +++++++++++++++---
 include/swupdate.h         |  2 ++
 3 files changed, 20 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/core/swupdate.c b/core/swupdate.c
index c59a258..61e6dc0 100644
--- a/core/swupdate.c
+++ b/core/swupdate.c
@@ -366,7 +366,7 @@  static int install_from_file(char *fname, int check)
 	/*
 	 * Set "recovery_status" as begin of the transaction"
 	 */
-	bootloader_env_set("recovery_status", "in_progress");
+	bootloader_env_set(BOOTVAR_TRANSACTION, "in_progress");
 
 	ret = install_images(&swcfg, fdsw, 1);
 
@@ -379,7 +379,7 @@  static int install_from_file(char *fname, int check)
 		return EXIT_FAILURE;
 	}
 
-	bootloader_env_unset("recovery_status");
+	bootloader_env_unset(BOOTVAR_TRANSACTION);
 	fprintf(stdout, "Software updated successfully\n");
 	fprintf(stdout, "Please reboot the device to start the new software\n");
 
@@ -955,7 +955,7 @@  int main(int argc, char **argv)
 		result = install_from_file(fname, opt_c);
 		switch (result) {
 		case EXIT_FAILURE:
-			bootloader_env_set("recovery_status", "failed");
+			bootloader_env_set(BOOTVAR_TRANSACTION, "failed");
 			break;
 		case EXIT_SUCCESS:
 			notify(SUCCESS, 0, INFOLEVEL, NULL);
diff --git a/corelib/stream_interface.c b/corelib/stream_interface.c
index a386837..8a07761 100644
--- a/corelib/stream_interface.c
+++ b/corelib/stream_interface.c
@@ -125,6 +125,7 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 	struct img_type *img, *part;
 	char output_file[MAX_IMAGE_FNAME];
 	const char* TMPDIR = get_tmpdir();
+	bool installed_directly = false;
 
 	/* preset the info about the install parts */
 
@@ -229,6 +230,17 @@  static int extract_files(int fd, struct swupdate_cfg *software)
 				break;
 			case INSTALL_FROM_STREAM:
 				TRACE("Installing STREAM %s, %lld bytes", img->fname, img->size);
+
+				/*
+				 * If this is the first image to be directly installed, set transaction flag
+				 * to on to be checked if a power-off happens. Be sure to set the flag
+				 * just once
+				 */
+				if (!installed_directly) {
+					bootloader_env_set(BOOTVAR_TRANSACTION, "in_progress");
+					installed_directly = true;
+				}
+
 				/*
 				 * If we are streaming data to store in a UBI volume, make
 				 * sure that the UBI partitions are adjusted beforehand
@@ -379,12 +391,12 @@  void *network_initializer(void *data)
 			 * must be successful. Set we have
 			 * initiated an update
 			 */
-			bootloader_env_set("recovery_status", "in_progress");
+			bootloader_env_set(BOOTVAR_TRANSACTION, "in_progress");
 
 			notify(RUN, RECOVERY_NO_ERROR, INFOLEVEL, "Installation in progress");
 			ret = install_images(software, 0, 0);
 			if (ret != 0) {
-				bootloader_env_set("recovery_status", "failed");
+				bootloader_env_set(BOOTVAR_TRANSACTION, "failed");
 				notify(FAILURE, RECOVERY_ERROR, ERRORLEVEL, "Installation failed !");
 				inst.last_install = FAILURE;
 
@@ -393,7 +405,7 @@  void *network_initializer(void *data)
 				 * Clear the recovery variable to indicate to bootloader
 				 * that it is not required to start recovery again
 				 */
-				bootloader_env_unset("recovery_status");
+				bootloader_env_unset(BOOTVAR_TRANSACTION);
 				notify(SUCCESS, RECOVERY_NO_ERROR, INFOLEVEL, "SWUPDATE successful !");
 				inst.last_install = SUCCESS;
 			}
diff --git a/include/swupdate.h b/include/swupdate.h
index 088d782..b54b904 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -14,6 +14,8 @@ 
 #include "mongoose_interface.h"
 #include "swupdate_dict.h"
 
+#define BOOTVAR_TRANSACTION "recovery_status"
+
 /*
  * swupdate uses SHA256 hashes
  */