diff mbox series

[2/2] handler: bootloader: postpone setiing the environment

Message ID 20181121164144.8487-2-sbabic@denx.de
State Accepted
Headers show
Series None | expand

Commit Message

Stefano Babic Nov. 21, 2018, 4:41 p.m. UTC
The bootloader handler sets the environment using an image (ASCII file)
with the list of variables to be set and their values. This can under
some circunstances brick the target because the environment is set in
the middle of un update and not at the end, as it happens when the
variables are listed in the "bootenv" section of sw-description. The
environment is in fact set for the new release and in case of a power
cut or if simply the update is cancelled, the device after a reboot will
try to start with the new environment. In most cases, the new
environment points to the new version of the software that is at least
corrupted orabsent.

This patch changes the behavior and chekcs the values read from the
ASCII file, but not set the environment. It puts the variables in the
global list exactly as the parser does, and the environment will be set
just at the end of the installation.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 handlers/boot_handler.c | 49 +++++++++++++++++++++++++++++++++++------
 1 file changed, 42 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/handlers/boot_handler.c b/handlers/boot_handler.c
index ac6e4e0..29fd190 100644
--- a/handlers/boot_handler.c
+++ b/handlers/boot_handler.c
@@ -7,12 +7,15 @@ 
 
 #include <sys/types.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <errno.h>
 
 #include "generated/autoconf.h"
 #include "swupdate.h"
+#include "swupdate_dict.h"
 #include "handler.h"
 #include "util.h"
 #include "bootloader.h"
@@ -25,7 +28,8 @@  static int install_boot_environment(struct img_type *img,
 {
 	int ret;
 	int fdout;
-
+	FILE *fp;
+	char *buf;
 	char filename[64];
 	struct stat statbuf;
 
@@ -35,6 +39,11 @@  static int install_boot_environment(struct img_type *img,
 			 img->fname);
 		return -1;
 	}
+
+	if (!img->bootloader) {
+		ERROR("Internal fault, please report !");
+		return -EFAULT;
+	}
 	ret = stat(filename, &statbuf);
 	if (ret) {
 		fdout = openfileoutput(filename);
@@ -42,14 +51,40 @@  static int install_boot_environment(struct img_type *img,
 		close(fdout);
 	}
 
-	ret = bootloader_apply_list(filename);
-	if (ret != 0) {
-		ERROR("Error setting bootloader environment");
-	} else {
-		TRACE("Bootloader environment from %s updated", img->fname);
+	/*
+	 * Do not set now the bootloader environment
+	 * because this can cause a corrupted environment
+	 * if a successive handler fails.
+	 * Just put the environment in a the global list
+	 * and let that the core will update it at the end
+	 * of install
+	 */
+	fp = fopen(filename, "r");
+	if (!fp)
+		return -EACCES;
+
+	buf = (char *)malloc(MAX_BOOT_SCRIPT_LINE_LENGTH);
+	if (!buf) {
+		ERROR("Out of memory, exiting !");
+		fclose(fp);
+		return -ENOMEM;
+	}
+
+	while (fgets(buf, MAX_BOOT_SCRIPT_LINE_LENGTH, fp)) {
+		char **pair = NULL;
+		unsigned int cnt;
+
+		pair = string_split(buf, '=');
+		cnt = count_string_array((const char **)pair);
+
+		if (cnt > 0 && strlen(pair[0]))
+			dict_set_value(img->bootloader, pair[0], pair[1]);
+		free(pair);
 	}
+	fclose(fp);
+	free(buf);
 
-	return ret;
+	return 0;
 }
 
 __attribute__((constructor))